xref: /onnv-gate/usr/src/uts/common/io/chxge/com/ch_subr.c (revision 3833:45d8d0ee8613)
1*3833Sxw161283 /*
2*3833Sxw161283  * CDDL HEADER START
3*3833Sxw161283  *
4*3833Sxw161283  * The contents of this file are subject to the terms of the
5*3833Sxw161283  * Common Development and Distribution License (the "License").
6*3833Sxw161283  * You may not use this file except in compliance with the License.
7*3833Sxw161283  *
8*3833Sxw161283  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*3833Sxw161283  * or http://www.opensolaris.org/os/licensing.
10*3833Sxw161283  * See the License for the specific language governing permissions
11*3833Sxw161283  * and limitations under the License.
12*3833Sxw161283  *
13*3833Sxw161283  * When distributing Covered Code, include this CDDL HEADER in each
14*3833Sxw161283  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*3833Sxw161283  * If applicable, add the following below this CDDL HEADER, with the
16*3833Sxw161283  * fields enclosed by brackets "[]" replaced with your own identifying
17*3833Sxw161283  * information: Portions Copyright [yyyy] [name of copyright owner]
18*3833Sxw161283  *
19*3833Sxw161283  * CDDL HEADER END
20*3833Sxw161283  */
21*3833Sxw161283 
22*3833Sxw161283 /*
23*3833Sxw161283  * Copyright (C) 2003-2005 Chelsio Communications.  All rights reserved.
24*3833Sxw161283  */
25*3833Sxw161283 
26*3833Sxw161283 #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* ch_subr.c */
27*3833Sxw161283 
28*3833Sxw161283 #include "common.h"
29*3833Sxw161283 #include "elmer0.h"
30*3833Sxw161283 #include "regs.h"
31*3833Sxw161283 
32*3833Sxw161283 #include "gmac.h"
33*3833Sxw161283 #include "cphy.h"
34*3833Sxw161283 #include "sge.h"
35*3833Sxw161283 #include "tp.h"
36*3833Sxw161283 #include "espi.h"
37*3833Sxw161283 
38*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
39*3833Sxw161283 #include "mc3.h"
40*3833Sxw161283 #include "mc4.h"
41*3833Sxw161283 #include "mc5.h"
42*3833Sxw161283 #include "ulp.h"
43*3833Sxw161283 #endif
44*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_COUGAR
45*3833Sxw161283 #include "cspi.h"
46*3833Sxw161283 #endif
47*3833Sxw161283 
48*3833Sxw161283 /*
49*3833Sxw161283  * t1_wait_op_done - wait until an operation is completed
50*3833Sxw161283  * @adapter: the adapter performing the operation
51*3833Sxw161283  * @reg: the register to check for completion
52*3833Sxw161283  * @mask: a single-bit field within @reg that indicates completion
53*3833Sxw161283  * @polarity: the value of the field when the operation is completed
54*3833Sxw161283  * @attempts: number of check iterations
55*3833Sxw161283  * @delay: delay in usecs between iterations
56*3833Sxw161283  * @attempts: number of check iterations
57*3833Sxw161283  * @delay: delay in usecs between iterations
58*3833Sxw161283  *
59*3833Sxw161283  * Wait until an operation is completed by checking a bit in a register
60*3833Sxw161283  * up to @attempts times.	Returns %0 if the operation completes and %1
61*3833Sxw161283  * otherwise.
62*3833Sxw161283  */
t1_wait_op_done(adapter_t * adapter,int reg,u32 mask,int polarity,int attempts,int delay)63*3833Sxw161283 int t1_wait_op_done(adapter_t *adapter, int reg, u32 mask, int polarity,
64*3833Sxw161283 		int attempts, int delay)
65*3833Sxw161283 {
66*3833Sxw161283 	while (attempts) {
67*3833Sxw161283 		u32 val = t1_read_reg_4(adapter, reg) & mask;
68*3833Sxw161283 		if (!!val == polarity)
69*3833Sxw161283 			return (0);
70*3833Sxw161283 		if (--attempts == 0)
71*3833Sxw161283 			return (1);
72*3833Sxw161283 		if (delay)
73*3833Sxw161283 			DELAY_US(delay);
74*3833Sxw161283 	}
75*3833Sxw161283 
76*3833Sxw161283 	return (1);
77*3833Sxw161283 }
78*3833Sxw161283 
79*3833Sxw161283 /* #define TPI_ATTEMPTS 50 */
80*3833Sxw161283 #define	TPI_ATTEMPTS 100
81*3833Sxw161283 
82*3833Sxw161283 /*
83*3833Sxw161283  * Write a register over the TPI interface (unlocked and locked versions).
84*3833Sxw161283  */
85*3833Sxw161283 int
__t1_tpi_write(adapter_t * adapter,u32 addr,u32 value)86*3833Sxw161283 __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value)
87*3833Sxw161283 {
88*3833Sxw161283 	int tpi_busy;
89*3833Sxw161283 
90*3833Sxw161283 	t1_write_reg_4(adapter, A_TPI_ADDR, addr);
91*3833Sxw161283 	t1_write_reg_4(adapter, A_TPI_WR_DATA, value);
92*3833Sxw161283 	t1_write_reg_4(adapter, A_TPI_CSR, F_TPIWR);
93*3833Sxw161283 
94*3833Sxw161283 	tpi_busy = t1_wait_op_done(adapter, A_TPI_CSR, F_TPIRDY, 1,
95*3833Sxw161283 		TPI_ATTEMPTS, 3);
96*3833Sxw161283 	if (tpi_busy)
97*3833Sxw161283 		CH_ALERT("%s: TPI write to 0x%x failed\n",
98*3833Sxw161283 			adapter_name(adapter), addr);
99*3833Sxw161283 	return (tpi_busy);
100*3833Sxw161283 }
101*3833Sxw161283 
102*3833Sxw161283 int
t1_tpi_write(adapter_t * adapter,u32 addr,u32 value)103*3833Sxw161283 t1_tpi_write(adapter_t *adapter, u32 addr, u32 value)
104*3833Sxw161283 {
105*3833Sxw161283 	int ret;
106*3833Sxw161283 
107*3833Sxw161283 	TPI_LOCK(adapter);
108*3833Sxw161283 	ret = __t1_tpi_write(adapter, addr, value);
109*3833Sxw161283 	TPI_UNLOCK(adapter);
110*3833Sxw161283 	return (ret);
111*3833Sxw161283 }
112*3833Sxw161283 
113*3833Sxw161283 /*
114*3833Sxw161283  * Read a register over the TPI interface (unlocked and locked versions).
115*3833Sxw161283  */
116*3833Sxw161283 int
__t1_tpi_read(adapter_t * adapter,u32 addr,u32 * valp)117*3833Sxw161283 __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp)
118*3833Sxw161283 {
119*3833Sxw161283 	int tpi_busy;
120*3833Sxw161283 
121*3833Sxw161283 	t1_write_reg_4(adapter, A_TPI_ADDR, addr);
122*3833Sxw161283 	t1_write_reg_4(adapter, A_TPI_CSR, 0);
123*3833Sxw161283 
124*3833Sxw161283 	tpi_busy = t1_wait_op_done(adapter, A_TPI_CSR, F_TPIRDY, 1,
125*3833Sxw161283 		TPI_ATTEMPTS, 3);
126*3833Sxw161283 
127*3833Sxw161283 	if (tpi_busy)
128*3833Sxw161283 		CH_ALERT("%s: TPI read from 0x%x failed\n",
129*3833Sxw161283 			adapter_name(adapter), addr);
130*3833Sxw161283 	else
131*3833Sxw161283 		*valp = t1_read_reg_4(adapter, A_TPI_RD_DATA);
132*3833Sxw161283 	return (tpi_busy);
133*3833Sxw161283 }
134*3833Sxw161283 
135*3833Sxw161283 int
t1_tpi_read(adapter_t * adapter,u32 addr,u32 * valp)136*3833Sxw161283 t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp)
137*3833Sxw161283 {
138*3833Sxw161283 	int ret;
139*3833Sxw161283 
140*3833Sxw161283 	TPI_LOCK(adapter);
141*3833Sxw161283 	ret = __t1_tpi_read(adapter, addr, valp);
142*3833Sxw161283 	TPI_UNLOCK(adapter);
143*3833Sxw161283 	return (ret);
144*3833Sxw161283 }
145*3833Sxw161283 
146*3833Sxw161283 /*
147*3833Sxw161283  * Set a TPI parameter.
148*3833Sxw161283  */
t1_tpi_par(adapter_t * adapter,u32 value)149*3833Sxw161283 static void t1_tpi_par(adapter_t *adapter, u32 value)
150*3833Sxw161283 {
151*3833Sxw161283 	t1_write_reg_4(adapter, A_TPI_PAR, V_TPIPAR(value));
152*3833Sxw161283 }
153*3833Sxw161283 
154*3833Sxw161283 /*
155*3833Sxw161283  * Called when a port's link settings change to propagate the new values to the
156*3833Sxw161283  * associated PHY and MAC.  After performing the common tasks it invokes an
157*3833Sxw161283  * OS-specific handler.
158*3833Sxw161283  */
159*3833Sxw161283 void
link_changed(adapter_t * adapter,int port_id)160*3833Sxw161283 link_changed(adapter_t *adapter, int port_id)
161*3833Sxw161283 {
162*3833Sxw161283 	int link_ok, speed, duplex, fc;
163*3833Sxw161283 	struct cphy *phy = adapter->port[port_id].phy;
164*3833Sxw161283 	struct link_config *lc = &adapter->port[port_id].link_config;
165*3833Sxw161283 
166*3833Sxw161283 	phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
167*3833Sxw161283 
168*3833Sxw161283 	lc->speed = speed < 0 ? SPEED_INVALID : speed;
169*3833Sxw161283 	lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex;
170*3833Sxw161283 	if (!(lc->requested_fc & PAUSE_AUTONEG))
171*3833Sxw161283 		fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
172*3833Sxw161283 
173*3833Sxw161283 	if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) {
174*3833Sxw161283 		/* Set MAC speed, duplex, and flow control to match PHY. */
175*3833Sxw161283 		struct cmac *mac = adapter->port[port_id].mac;
176*3833Sxw161283 
177*3833Sxw161283 		mac->ops->set_speed_duplex_fc(mac, speed, duplex, fc);
178*3833Sxw161283 		lc->fc = (unsigned char)fc;
179*3833Sxw161283 	}
180*3833Sxw161283 	t1_os_link_changed(adapter, port_id, link_ok, speed, duplex, fc);
181*3833Sxw161283 }
182*3833Sxw161283 
t1_pci_intr_handler(adapter_t * adapter)183*3833Sxw161283 static int t1_pci_intr_handler(adapter_t *adapter)
184*3833Sxw161283 {
185*3833Sxw161283 	u32 pcix_cause;
186*3833Sxw161283 
187*3833Sxw161283 	(void) t1_os_pci_read_config_4(adapter, A_PCICFG_INTR_CAUSE,
188*3833Sxw161283 		&pcix_cause);
189*3833Sxw161283 
190*3833Sxw161283 	if (pcix_cause) {
191*3833Sxw161283 		(void) t1_os_pci_write_config_4(adapter, A_PCICFG_INTR_CAUSE,
192*3833Sxw161283 			pcix_cause);
193*3833Sxw161283 		t1_fatal_err(adapter);    /* PCI errors are fatal */
194*3833Sxw161283 	}
195*3833Sxw161283 	return (0);
196*3833Sxw161283 }
197*3833Sxw161283 
198*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
199*3833Sxw161283 #include "fpga_defs.h"
200*3833Sxw161283 
201*3833Sxw161283 /*
202*3833Sxw161283  * PHY interrupt handler for FPGA boards.
203*3833Sxw161283  */
fpga_phy_intr_handler(adapter_t * adapter)204*3833Sxw161283 static int fpga_phy_intr_handler(adapter_t *adapter)
205*3833Sxw161283 {
206*3833Sxw161283 	int p;
207*3833Sxw161283 	u32 cause = t1_read_reg_4(adapter, FPGA_GMAC_ADDR_INTERRUPT_CAUSE);
208*3833Sxw161283 
209*3833Sxw161283 	for_each_port(adapter, p)
210*3833Sxw161283 		if (cause & (1 << p)) {
211*3833Sxw161283 			struct cphy *phy = adapter->port[p].phy;
212*3833Sxw161283 			int phy_cause = phy->ops->interrupt_handler(phy);
213*3833Sxw161283 
214*3833Sxw161283 			if (phy_cause & cphy_cause_link_change)
215*3833Sxw161283 				link_changed(adapter, p);
216*3833Sxw161283 		}
217*3833Sxw161283 	t1_write_reg_4(adapter, FPGA_GMAC_ADDR_INTERRUPT_CAUSE, cause);
218*3833Sxw161283 	return (0);
219*3833Sxw161283 }
220*3833Sxw161283 
221*3833Sxw161283 /*
222*3833Sxw161283  * Slow path interrupt handler for FPGAs.
223*3833Sxw161283  */
fpga_slow_intr(adapter_t * adapter)224*3833Sxw161283 static int fpga_slow_intr(adapter_t *adapter)
225*3833Sxw161283 {
226*3833Sxw161283 	u32 cause = t1_read_reg_4(adapter, A_PL_CAUSE);
227*3833Sxw161283 
228*3833Sxw161283 	cause &= ~F_PL_INTR_SGE_DATA;
229*3833Sxw161283 	if (cause & F_PL_INTR_SGE_ERR)
230*3833Sxw161283 		(void) t1_sge_intr_error_handler(adapter->sge);
231*3833Sxw161283 
232*3833Sxw161283 	if (cause & FPGA_PCIX_INTERRUPT_GMAC)
233*3833Sxw161283 		(void) fpga_phy_intr_handler(adapter);
234*3833Sxw161283 
235*3833Sxw161283 	if (cause & FPGA_PCIX_INTERRUPT_TP) {
236*3833Sxw161283 		/*
237*3833Sxw161283 		 * FPGA doesn't support MC4 interrupts and it requires
238*3833Sxw161283 		 * this odd layer of indirection for MC5.
239*3833Sxw161283 		 */
240*3833Sxw161283 		u32 tp_cause = t1_read_reg_4(adapter,
241*3833Sxw161283 			FPGA_TP_ADDR_INTERRUPT_CAUSE);
242*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
243*3833Sxw161283 		if (tp_cause & FPGA_TP_INTERRUPT_MC5)
244*3833Sxw161283 			t1_mc5_intr_handler(adapter->mc5);
245*3833Sxw161283 #endif
246*3833Sxw161283 		/* Clear TP interrupt */
247*3833Sxw161283 		t1_write_reg_4(adapter, FPGA_TP_ADDR_INTERRUPT_CAUSE,
248*3833Sxw161283 			tp_cause);
249*3833Sxw161283 	}
250*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
251*3833Sxw161283 	if (cause & FPGA_PCIX_INTERRUPT_MC3)
252*3833Sxw161283 		(void) t1_mc3_intr_handler(adapter->mc3);
253*3833Sxw161283 #endif
254*3833Sxw161283 	if (cause & FPGA_PCIX_INTERRUPT_PCIX)
255*3833Sxw161283 		(void) t1_pci_intr_handler(adapter);
256*3833Sxw161283 
257*3833Sxw161283 	/* Clear the interrupts just processed. */
258*3833Sxw161283 	if (cause)
259*3833Sxw161283 		t1_write_reg_4(adapter, A_PL_CAUSE, cause);
260*3833Sxw161283 
261*3833Sxw161283 	return (cause != 0);
262*3833Sxw161283 }
263*3833Sxw161283 
264*3833Sxw161283 /*
265*3833Sxw161283  * FPGA MDIO initialization.
266*3833Sxw161283  */
fpga_mdio_init(adapter_t * adapter,const struct board_info * bi)267*3833Sxw161283 static void fpga_mdio_init(adapter_t *adapter, const struct board_info *bi)
268*3833Sxw161283 {
269*3833Sxw161283 	(void) bi;	/* avoid warnings */
270*3833Sxw161283 	t1_write_reg_4(adapter, A_MI0_CLK, V_MI0_CLK_DIV(3));
271*3833Sxw161283 }
272*3833Sxw161283 
273*3833Sxw161283 /*
274*3833Sxw161283  * FPGA MDIO read/write operations.
275*3833Sxw161283  */
fpga_mdio_read(adapter_t * adapter,int phy_addr,int mmd_addr,int reg_addr,unsigned int * val)276*3833Sxw161283 static int fpga_mdio_read(adapter_t *adapter, int phy_addr, int mmd_addr,
277*3833Sxw161283 	int reg_addr, unsigned int *val)
278*3833Sxw161283 {
279*3833Sxw161283 	if (mmd_addr)
280*3833Sxw161283 		return (-EINVAL);
281*3833Sxw161283 
282*3833Sxw161283 	/* Check if MDI is busy; this shouldn't happen. */
283*3833Sxw161283 	if (t1_read_reg_4(adapter, A_MI0_CSR) & F_MI0_BUSY) {
284*3833Sxw161283 		CH_ALERT("%s: MDIO busy at start of read\n",
285*3833Sxw161283 			adapter_name(adapter));
286*3833Sxw161283 		return (-EBUSY);
287*3833Sxw161283 	}
288*3833Sxw161283 	t1_write_reg_4(adapter, A_MI0_ADDR,
289*3833Sxw161283 		V_MI0_PHY_REG_ADDR(reg_addr) | V_MI0_PHY_ADDR(phy_addr));
290*3833Sxw161283 	*val = t1_read_reg_4(adapter, A_MI0_DATA_EXT);
291*3833Sxw161283 
292*3833Sxw161283 	return (0);
293*3833Sxw161283 }
294*3833Sxw161283 
fpga_mdio_write(adapter_t * adapter,int phy_addr,int mmd_addr,int reg_addr,unsigned int val)295*3833Sxw161283 static int fpga_mdio_write(adapter_t *adapter, int phy_addr, int mmd_addr,
296*3833Sxw161283 	int reg_addr, unsigned int val)
297*3833Sxw161283 {
298*3833Sxw161283 	if (mmd_addr)
299*3833Sxw161283 		return (-EINVAL);
300*3833Sxw161283 
301*3833Sxw161283 	/* Check if MDI is busy; this shouldn't happen. */
302*3833Sxw161283 	if (t1_read_reg_4(adapter, A_MI0_CSR) & F_MI0_BUSY) {
303*3833Sxw161283 		CH_ALERT("%s: MDIO busy at start of write\n",
304*3833Sxw161283 			adapter_name(adapter));
305*3833Sxw161283 		return (-EBUSY);
306*3833Sxw161283 	}
307*3833Sxw161283 	t1_write_reg_4(adapter, A_MI0_ADDR,
308*3833Sxw161283 		V_MI0_PHY_REG_ADDR(reg_addr) | V_MI0_PHY_ADDR(phy_addr));
309*3833Sxw161283 	t1_write_reg_4(adapter, A_MI0_DATA_EXT, val);
310*3833Sxw161283 	return (0);
311*3833Sxw161283 }
312*3833Sxw161283 
313*3833Sxw161283 static struct mdio_ops fpga_mdio_ops = {
314*3833Sxw161283 	fpga_mdio_init,
315*3833Sxw161283 	fpga_mdio_read,
316*3833Sxw161283 	fpga_mdio_write
317*3833Sxw161283 };
318*3833Sxw161283 #endif
319*3833Sxw161283 
320*3833Sxw161283 /*
321*3833Sxw161283  * Wait until Elmer's MI1 interface is ready for new operations.
322*3833Sxw161283  */
mi1_wait_until_ready(adapter_t * adapter,int mi1_reg)323*3833Sxw161283 static int mi1_wait_until_ready(adapter_t *adapter, int mi1_reg)
324*3833Sxw161283 {
325*3833Sxw161283 	int attempts = 100, busy;
326*3833Sxw161283 
327*3833Sxw161283 	do {
328*3833Sxw161283 		u32 val;
329*3833Sxw161283 
330*3833Sxw161283 		(void) __t1_tpi_read(adapter, mi1_reg, &val);
331*3833Sxw161283 		busy = val & F_MI1_OP_BUSY;
332*3833Sxw161283 		if (busy)
333*3833Sxw161283 			DELAY_US(10);
334*3833Sxw161283 	} while (busy && --attempts);
335*3833Sxw161283 	if (busy)
336*3833Sxw161283 		CH_ALERT("%s: MDIO operation timed out\n",
337*3833Sxw161283 			adapter_name(adapter));
338*3833Sxw161283 	return (busy);
339*3833Sxw161283 }
340*3833Sxw161283 
341*3833Sxw161283 /*
342*3833Sxw161283  * MI1 MDIO initialization.
343*3833Sxw161283  */
mi1_mdio_init(adapter_t * adapter,const struct board_info * bi)344*3833Sxw161283 static void mi1_mdio_init(adapter_t *adapter, const struct board_info *bi)
345*3833Sxw161283 {
346*3833Sxw161283 	u32 clkdiv = bi->clock_elmer0 / (2 * bi->mdio_mdc) - 1;
347*3833Sxw161283 	u32 val = F_MI1_PREAMBLE_ENABLE | V_MI1_MDI_INVERT(bi->mdio_mdiinv) |
348*3833Sxw161283 		V_MI1_MDI_ENABLE(bi->mdio_mdien) | V_MI1_CLK_DIV(clkdiv);
349*3833Sxw161283 
350*3833Sxw161283 	if (!(bi->caps & SUPPORTED_10000baseT_Full))
351*3833Sxw161283 		val |= V_MI1_SOF(1);
352*3833Sxw161283 	(void) t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_CFG, val);
353*3833Sxw161283 }
354*3833Sxw161283 
355*3833Sxw161283 #if defined(CONFIG_CHELSIO_T1_1G) || defined(CONFIG_CHELSIO_T1_COUGAR)
356*3833Sxw161283 /*
357*3833Sxw161283  * Elmer MI1 MDIO read/write operations.
358*3833Sxw161283  */
mi1_mdio_read(adapter_t * adapter,int phy_addr,int mmd_addr,int reg_addr,unsigned int * valp)359*3833Sxw161283 static int mi1_mdio_read(adapter_t *adapter, int phy_addr, int mmd_addr,
360*3833Sxw161283 	int reg_addr, unsigned int *valp)
361*3833Sxw161283 {
362*3833Sxw161283 	u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr);
363*3833Sxw161283 
364*3833Sxw161283 	if (mmd_addr)
365*3833Sxw161283 		return (-EINVAL);
366*3833Sxw161283 
367*3833Sxw161283 	TPI_LOCK(adapter);
368*3833Sxw161283 	(void) __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
369*3833Sxw161283 	(void) __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
370*3833Sxw161283 		MI1_OP_DIRECT_READ);
371*3833Sxw161283 	(void) mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
372*3833Sxw161283 	(void) __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp);
373*3833Sxw161283 	TPI_UNLOCK(adapter);
374*3833Sxw161283 	return (0);
375*3833Sxw161283 }
376*3833Sxw161283 
mi1_mdio_write(adapter_t * adapter,int phy_addr,int mmd_addr,int reg_addr,unsigned int val)377*3833Sxw161283 static int mi1_mdio_write(adapter_t *adapter, int phy_addr, int mmd_addr,
378*3833Sxw161283 	int reg_addr, unsigned int val)
379*3833Sxw161283 {
380*3833Sxw161283 	u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr);
381*3833Sxw161283 
382*3833Sxw161283 	if (mmd_addr)
383*3833Sxw161283 		return (-EINVAL);
384*3833Sxw161283 
385*3833Sxw161283 	TPI_LOCK(adapter);
386*3833Sxw161283 	(void) __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
387*3833Sxw161283 	(void) __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val);
388*3833Sxw161283 	(void) __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
389*3833Sxw161283 		MI1_OP_DIRECT_WRITE);
390*3833Sxw161283 	(void) mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
391*3833Sxw161283 	TPI_UNLOCK(adapter);
392*3833Sxw161283 	return (0);
393*3833Sxw161283 }
394*3833Sxw161283 
395*3833Sxw161283 #if defined(CONFIG_CHELSIO_T1_1G) || defined(CONFIG_CHELSIO_T1_COUGAR)
396*3833Sxw161283 static struct mdio_ops mi1_mdio_ops = {
397*3833Sxw161283 	mi1_mdio_init,
398*3833Sxw161283 	mi1_mdio_read,
399*3833Sxw161283 	mi1_mdio_write
400*3833Sxw161283 };
401*3833Sxw161283 #endif
402*3833Sxw161283 
403*3833Sxw161283 #endif
404*3833Sxw161283 
405*3833Sxw161283 #if 0
406*3833Sxw161283 static int mi1_mdio_ext_readinc(adapter_t *adapter, int phy_addr, int mmd_addr,
407*3833Sxw161283 				int reg_addr, unsigned int *valp)
408*3833Sxw161283 {
409*3833Sxw161283 	u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
410*3833Sxw161283 
411*3833Sxw161283 	TPI_LOCK(adapter);
412*3833Sxw161283 
413*3833Sxw161283 	/* Write the address we want. */
414*3833Sxw161283 	(void) __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
415*3833Sxw161283 	(void) __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, reg_addr);
416*3833Sxw161283 	(void) __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
417*3833Sxw161283 		MI1_OP_INDIRECT_ADDRESS);
418*3833Sxw161283 	(void) mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
419*3833Sxw161283 
420*3833Sxw161283 	/* Write the operation we want. */
421*3833Sxw161283 	(void) __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
422*3833Sxw161283 		MI1_OP_INDIRECT_READ_INC);
423*3833Sxw161283 	(void) mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
424*3833Sxw161283 
425*3833Sxw161283 	/* Read the data. */
426*3833Sxw161283 	(void) __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp);
427*3833Sxw161283 	TPI_UNLOCK(adapter);
428*3833Sxw161283 	return (0);
429*3833Sxw161283 }
430*3833Sxw161283 #endif
431*3833Sxw161283 
mi1_mdio_ext_read(adapter_t * adapter,int phy_addr,int mmd_addr,int reg_addr,unsigned int * valp)432*3833Sxw161283 static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr,
433*3833Sxw161283 	int reg_addr, unsigned int *valp)
434*3833Sxw161283 {
435*3833Sxw161283 	u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
436*3833Sxw161283 
437*3833Sxw161283 	TPI_LOCK(adapter);
438*3833Sxw161283 
439*3833Sxw161283 	/* Write the address we want. */
440*3833Sxw161283 	(void) __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
441*3833Sxw161283 	(void) __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, reg_addr);
442*3833Sxw161283 	(void) __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
443*3833Sxw161283 		MI1_OP_INDIRECT_ADDRESS);
444*3833Sxw161283 	(void) mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
445*3833Sxw161283 
446*3833Sxw161283 	/* Write the operation we want. */
447*3833Sxw161283 	(void) __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
448*3833Sxw161283 		MI1_OP_INDIRECT_READ);
449*3833Sxw161283 	(void) mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
450*3833Sxw161283 
451*3833Sxw161283 	/* Read the data. */
452*3833Sxw161283 	(void) __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp);
453*3833Sxw161283 	TPI_UNLOCK(adapter);
454*3833Sxw161283 	return (0);
455*3833Sxw161283 }
456*3833Sxw161283 
mi1_mdio_ext_write(adapter_t * adapter,int phy_addr,int mmd_addr,int reg_addr,unsigned int val)457*3833Sxw161283 static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr,
458*3833Sxw161283 	int reg_addr, unsigned int val)
459*3833Sxw161283 {
460*3833Sxw161283 	u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
461*3833Sxw161283 
462*3833Sxw161283 	TPI_LOCK(adapter);
463*3833Sxw161283 
464*3833Sxw161283 	/* Write the address we want. */
465*3833Sxw161283 	(void) __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
466*3833Sxw161283 	(void) __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, reg_addr);
467*3833Sxw161283 	(void) __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
468*3833Sxw161283 		MI1_OP_INDIRECT_ADDRESS);
469*3833Sxw161283 	(void) mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
470*3833Sxw161283 
471*3833Sxw161283 	/* Write the data. */
472*3833Sxw161283 	(void) __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val);
473*3833Sxw161283 	(void) __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
474*3833Sxw161283 		MI1_OP_INDIRECT_WRITE);
475*3833Sxw161283 	(void) mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
476*3833Sxw161283 	TPI_UNLOCK(adapter);
477*3833Sxw161283 	return (0);
478*3833Sxw161283 }
479*3833Sxw161283 
480*3833Sxw161283 static struct mdio_ops mi1_mdio_ext_ops = {
481*3833Sxw161283 	mi1_mdio_init,
482*3833Sxw161283 	mi1_mdio_ext_read,
483*3833Sxw161283 	mi1_mdio_ext_write
484*3833Sxw161283 };
485*3833Sxw161283 
486*3833Sxw161283 enum {
487*3833Sxw161283 	CH_BRD_T110_1CU,
488*3833Sxw161283 	CH_BRD_N110_1F,
489*3833Sxw161283 	CH_BRD_N210_1F,
490*3833Sxw161283 	CH_BRD_T210_1F,
491*3833Sxw161283 	CH_BRD_T210_1CU,
492*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
493*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
494*3833Sxw161283 	CH_BRD_T204_4CU,
495*3833Sxw161283 	CH_BRD_T204V_4CU,
496*3833Sxw161283 	CH_BRD_6800_4CU,
497*3833Sxw161283 	CH_BRD_7500_4CU,
498*3833Sxw161283 	CH_BRD_7500_4F,
499*3833Sxw161283 	CH_BRD_T101_1CU_LB,
500*3833Sxw161283 	CH_BRD_T101_1F_LB,
501*3833Sxw161283 #endif
502*3833Sxw161283 	CH_BRD_8000_1F,
503*3833Sxw161283 	CH_BRD_T110_1F,
504*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_COUGAR
505*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
506*3833Sxw161283 	CH_BRD_COUGAR_4CU,
507*3833Sxw161283 #endif
508*3833Sxw161283 	CH_BRD_COUGAR_1F,
509*3833Sxw161283 #endif
510*3833Sxw161283 #ifdef CONFIG_USERMODE
511*3833Sxw161283 	CH_BRD_SIMUL,
512*3833Sxw161283 #endif
513*3833Sxw161283 #endif
514*3833Sxw161283 };
515*3833Sxw161283 
516*3833Sxw161283 static struct board_info t1_board[] = {
517*3833Sxw161283 
518*3833Sxw161283 { CHBT_BOARD_CHT110, 1/*ports#*/,
519*3833Sxw161283   SUPPORTED_10000baseT_Full /*caps*/, CHBT_TERM_T1,
520*3833Sxw161283   CHBT_MAC_PM3393, CHBT_PHY_MY3126,
521*3833Sxw161283   125000000/*clk-core*/, 150000000/*clk-mc3*/, 125000000/*clk-mc4*/,
522*3833Sxw161283   1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 1/*mdien*/,
523*3833Sxw161283   1/*mdiinv*/, 1/*mdc*/, 1/*phybaseaddr*/, &t1_pm3393_ops,
524*3833Sxw161283   &t1_my3126_ops, &mi1_mdio_ext_ops,
525*3833Sxw161283   "Chelsio T110 1x10GBase-CX4 TOE" },
526*3833Sxw161283 
527*3833Sxw161283 { CHBT_BOARD_N110, 1/*ports#*/,
528*3833Sxw161283   SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE /*caps*/, CHBT_TERM_T1,
529*3833Sxw161283   CHBT_MAC_PM3393, CHBT_PHY_88X2010,
530*3833Sxw161283   125000000/*clk-core*/, 0/*clk-mc3*/, 0/*clk-mc4*/,
531*3833Sxw161283   1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 0/*mdien*/,
532*3833Sxw161283   0/*mdiinv*/, 1/*mdc*/, 0/*phybaseaddr*/, &t1_pm3393_ops,
533*3833Sxw161283   &t1_mv88x201x_ops, &mi1_mdio_ext_ops,
534*3833Sxw161283   "Chelsio N110 1x10GBaseX NIC" },
535*3833Sxw161283 
536*3833Sxw161283 { CHBT_BOARD_N210, 1/*ports#*/,
537*3833Sxw161283   SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE /*caps*/, CHBT_TERM_T2,
538*3833Sxw161283   CHBT_MAC_PM3393, CHBT_PHY_88X2010,
539*3833Sxw161283   125000000/*clk-core*/, 0/*clk-mc3*/, 0/*clk-mc4*/,
540*3833Sxw161283   1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 0/*mdien*/,
541*3833Sxw161283   0/*mdiinv*/, 1/*mdc*/, 0/*phybaseaddr*/, &t1_pm3393_ops,
542*3833Sxw161283   &t1_mv88x201x_ops, &mi1_mdio_ext_ops,
543*3833Sxw161283   "Chelsio N210 1x10GBaseX NIC" },
544*3833Sxw161283 
545*3833Sxw161283 { CHBT_BOARD_CHT210, 1/*ports#*/,
546*3833Sxw161283   SUPPORTED_10000baseT_Full /*caps*/, CHBT_TERM_T2,
547*3833Sxw161283   CHBT_MAC_PM3393, CHBT_PHY_88X2010,
548*3833Sxw161283   125000000/*clk-core*/, 133000000/*clk-mc3*/, 125000000/*clk-mc4*/,
549*3833Sxw161283   1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 0/*mdien*/,
550*3833Sxw161283   0/*mdiinv*/, 1/*mdc*/, 0/*phybaseaddr*/, &t1_pm3393_ops,
551*3833Sxw161283   &t1_mv88x201x_ops, &mi1_mdio_ext_ops,
552*3833Sxw161283   "Chelsio T210 1x10GBaseX TOE" },
553*3833Sxw161283 
554*3833Sxw161283 { CHBT_BOARD_CHT210, 1/*ports#*/,
555*3833Sxw161283   SUPPORTED_10000baseT_Full /*caps*/, CHBT_TERM_T2,
556*3833Sxw161283   CHBT_MAC_PM3393, CHBT_PHY_MY3126,
557*3833Sxw161283   125000000/*clk-core*/, 133000000/*clk-mc3*/, 125000000/*clk-mc4*/,
558*3833Sxw161283   1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 1/*mdien*/,
559*3833Sxw161283   1/*mdiinv*/, 1/*mdc*/, 1/*phybaseaddr*/, &t1_pm3393_ops,
560*3833Sxw161283   &t1_my3126_ops, &mi1_mdio_ext_ops,
561*3833Sxw161283   "Chelsio T210 1x10GBase-CX4 TOE" },
562*3833Sxw161283 
563*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
564*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
565*3833Sxw161283 { CHBT_BOARD_CHT204, 4/*ports#*/,
566*3833Sxw161283   SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg |
567*3833Sxw161283   SUPPORTED_PAUSE | SUPPORTED_TP /*caps*/, CHBT_TERM_T2, CHBT_MAC_IXF1010, CHBT_PHY_88E1111,
568*3833Sxw161283   100000000/*clk-core*/, 133000000/*clk-mc3*/, 100000000/*clk-mc4*/,
569*3833Sxw161283   4/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 0/*mdien*/,
570*3833Sxw161283   0/*mdiinv*/, 1/*mdc*/, 4/*phybaseaddr*/, &t1_ixf1010_ops,
571*3833Sxw161283   &t1_mv88e1xxx_ops, &mi1_mdio_ops,
572*3833Sxw161283   "Chelsio T204 4x100/1000BaseT TOE" },
573*3833Sxw161283 { CHBT_BOARD_CHT204V, 4/*ports#*/,
574*3833Sxw161283   SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half |
575*3833Sxw161283   SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg |
576*3833Sxw161283   SUPPORTED_PAUSE | SUPPORTED_TP /*caps*/, CHBT_TERM_T2, CHBT_MAC_VSC7321, CHBT_PHY_88E1111,
577*3833Sxw161283   100000000/*clk-core*/, 133000000/*clk-mc3*/, 100000000/*clk-mc4*/,
578*3833Sxw161283   4/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 0/*mdien*/,
579*3833Sxw161283   0/*mdiinv*/, 1/*mdc*/, 4/*phybaseaddr*/, &t1_vsc7326_ops,
580*3833Sxw161283   &t1_mv88e1xxx_ops, &mi1_mdio_ops,
581*3833Sxw161283   "Chelsio T204V 4x100/1000BaseT TOE" },
582*3833Sxw161283 
583*3833Sxw161283 { CHBT_BOARD_6800, 1/*ports#*/,
584*3833Sxw161283   SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half |
585*3833Sxw161283   SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Half |
586*3833Sxw161283   SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_TP /*caps*/,
587*3833Sxw161283   CHBT_TERM_FPGA, CHBT_MAC_CHELSIO_A, CHBT_PHY_88E1041,
588*3833Sxw161283   16000000/*clk-core*/, 16000000/*clk-mc3*/, 16000000/*clk-mc4*/,
589*3833Sxw161283   0/*espi-ports*/, 0/*clk-cspi*/, 0/*clk-elmer0*/, 0/*mdien*/,
590*3833Sxw161283   0/*mdiinv*/, 4/*mdc*/, 0/*phybaseaddr*/, &t1_chelsio_mac_ops, &t1_mv88e1xxx_ops, &fpga_mdio_ops,
591*3833Sxw161283   "Chelsio FPGA 4x10/100/1000BaseT TOE" },
592*3833Sxw161283 
593*3833Sxw161283 { CHBT_BOARD_7500, 4/*ports#*/,
594*3833Sxw161283   SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg |
595*3833Sxw161283   SUPPORTED_TP /*caps*/, CHBT_TERM_T1, CHBT_MAC_IXF1010, CHBT_PHY_88E1041,
596*3833Sxw161283   87500000/*clk-core*/, 87500000/*clk-mc3*/, 87500000/*clk-mc4*/,
597*3833Sxw161283   4/*espi-ports*/, 0/*clk-cspi*/, 40/*clk-elmer0*/, 0/*mdien*/,
598*3833Sxw161283   0/*mdiinv*/, 4/*mdc*/, 0/*phybaseaddr*/, &t1_ixf1010_ops,
599*3833Sxw161283   &t1_mv88e1xxx_ops, &mi1_mdio_ops,
600*3833Sxw161283   "Chelsio 7500 4x100/1000BaseT TOE" },
601*3833Sxw161283 
602*3833Sxw161283 { CHBT_BOARD_7500, 4/*ports#*/,
603*3833Sxw161283   SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE /*caps*/,
604*3833Sxw161283   CHBT_TERM_T1, CHBT_MAC_IXF1010, CHBT_PHY_88E1041,
605*3833Sxw161283   87500000/*clk-core*/, 87500000/*clk-mc3*/, 87500000/*clk-mc4*/,
606*3833Sxw161283   4/*espi-ports*/, 0/*clk-cspi*/, 40/*clk-elmer0*/, 0/*mdien*/,
607*3833Sxw161283   0/*mdiinv*/, 4/*mdc*/, 0/*phybaseaddr*/, &t1_ixf1010_ops,
608*3833Sxw161283   &t1_mv88e1xxx_ops, &mi1_mdio_ops,
609*3833Sxw161283   "Chelsio 7500 4x1000BaseX TOE" },
610*3833Sxw161283 
611*3833Sxw161283 { CHBT_BOARD_CHT101, 1/*ports#*/,
612*3833Sxw161283   SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg |
613*3833Sxw161283   SUPPORTED_TP | SUPPORTED_PAUSE | SUPPORTED_LOOPBACK /*caps*/, CHBT_TERM_T1, CHBT_MAC_IXF1010, CHBT_PHY_88E1111,
614*3833Sxw161283   83300000/*clk-core*/, 83300000/*clk-mc3*/, 83300000/*clk-mc4*/,
615*3833Sxw161283   2/*espi-ports*/, 0/*clk-cspi*/, 40/*clk-elmer0*/, 0/*mdien*/,
616*3833Sxw161283   0/*mdiinv*/, 4/*mdc*/, 4/*phybaseaddr*/, &t1_ixf1010_ops,
617*3833Sxw161283   &t1_mv88e1xxx_ops, &mi1_mdio_ops,
618*3833Sxw161283   "Chelsio T101 1x100/1000BaseT TOE" },
619*3833Sxw161283 
620*3833Sxw161283 { CHBT_BOARD_CHT101, 1/*ports#*/,
621*3833Sxw161283   SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE | SUPPORTED_PAUSE | SUPPORTED_LOOPBACK /*caps*/,
622*3833Sxw161283   CHBT_TERM_T1, CHBT_MAC_IXF1010, CHBT_PHY_88E1111,
623*3833Sxw161283   83300000/*clk-core*/, 83300000/*clk-mc3*/, 83300000/*clk-mc4*/,
624*3833Sxw161283   2/*espi-ports*/, 0/*clk-cspi*/, 40/*clk-elmer0*/, 0/*mdien*/,
625*3833Sxw161283   0/*mdiinv*/, 4/*mdc*/, 4/*phybaseaddr*/, &t1_ixf1010_ops,
626*3833Sxw161283   &t1_mv88e1xxx_ops, &mi1_mdio_ops,
627*3833Sxw161283   "Chelsio T101 1x1000BaseX TOE" },
628*3833Sxw161283 #endif
629*3833Sxw161283 
630*3833Sxw161283 { CHBT_BOARD_8000, 1/*ports#*/,
631*3833Sxw161283   SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE /*caps*/, CHBT_TERM_T1,
632*3833Sxw161283   CHBT_MAC_PM3393, CHBT_PHY_XPAK,
633*3833Sxw161283   125000000/*clk-core*/, 150000000/*clk-mc3*/, 125000000/*clk-mc4*/,
634*3833Sxw161283   1/*espi-ports*/, 0/*clk-cspi*/, 40/*clk-elmer0*/, 1/*mdien*/,
635*3833Sxw161283   1/*mdiinv*/, 1/*mdc*/, 0/*phybaseaddr*/, &t1_pm3393_ops,
636*3833Sxw161283   &t1_xpak_ops, &mi1_mdio_ext_ops,
637*3833Sxw161283   "Chelsio 8000 1x10GBaseX TOE" },
638*3833Sxw161283 
639*3833Sxw161283 { CHBT_BOARD_CHT110, 1/*ports#*/,
640*3833Sxw161283   SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE /*caps*/, CHBT_TERM_T1,
641*3833Sxw161283   CHBT_MAC_PM3393, CHBT_PHY_XPAK,
642*3833Sxw161283   125000000/*clk-core*/, 150000000/*clk-mc3*/, 125000000/*clk-mc4*/,
643*3833Sxw161283   1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 1/*mdien*/,
644*3833Sxw161283   1/*mdiinv*/, 1/*mdc*/, 1/*phybaseaddr*/, &t1_pm3393_ops,
645*3833Sxw161283   &t1_xpak_ops, &mi1_mdio_ext_ops,
646*3833Sxw161283   "Chelsio T110 1x10GBaseX TOE" },
647*3833Sxw161283 
648*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_COUGAR
649*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
650*3833Sxw161283 { CHBT_BOARD_COUGAR, 4/*ports#*/,
651*3833Sxw161283   SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half |
652*3833Sxw161283   SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Half |
653*3833Sxw161283   SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_TP /*caps*/,
654*3833Sxw161283   CHBT_TERM_T1, CHBT_MAC_VSC7321, CHBT_PHY_88E1041,
655*3833Sxw161283   87500000/*clk-core*/, 87500000/*clk-mc3*/, 87500000/*clk-mc4*/,
656*3833Sxw161283   4/*espi-ports*/, 333300000/*clk-cspi*/, 40/*clk-elmer0*/, 0/*mdien*/,
657*3833Sxw161283   0/*mdiinv*/, 4/*mdc*/, 0/*phybaseaddr*/, &t1_vsc7321_ops,
658*3833Sxw161283   &t1_mv88e1xxx_ops, &mi1_mdio_ops,
659*3833Sxw161283   "Chelsio Cougar 4x100/1000BaseT TOE" },
660*3833Sxw161283 #endif
661*3833Sxw161283 
662*3833Sxw161283 { CHBT_BOARD_COUGAR, 1/*ports#*/,
663*3833Sxw161283   SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE /*caps*/, CHBT_TERM_T1,
664*3833Sxw161283   CHBT_MAC_VSC7321, CHBT_PHY_XPAK,
665*3833Sxw161283   87500000/*clk-core*/, 87500000/*clk-mc3*/, 87500000/*clk-mc4*/,
666*3833Sxw161283   1/*espi-ports*/, 333300000/*clk-cspi*/, 40/*clk-elmer0*/, 1/*mdien*/,
667*3833Sxw161283   1/*mdiinv*/, 1/*mdc*/, 0/*phybaseaddr*/, &t1_vsc7321_ops,
668*3833Sxw161283   &t1_xpak_ops, &mi1_mdio_ext_ops,
669*3833Sxw161283   "Chelsio Cougar 1x10GBaseX TOE" },
670*3833Sxw161283 #endif
671*3833Sxw161283 
672*3833Sxw161283 #ifdef CONFIG_USERMODE
673*3833Sxw161283 { CHBT_BOARD_SIMUL, 1/*ports#*/,
674*3833Sxw161283   0/*caps*/, CHBT_TERM_T1, CHBT_MAC_DUMMY, CHBT_PHY_DUMMY,
675*3833Sxw161283   125000000/*clk-core*/, 125000000/*clk-mc3*/, 125000000/*clk-mc4*/,
676*3833Sxw161283   1/*espi-ports*/, 0/*clk-cspi*/, 0/*clk-elmer0*/, 0/*mdien*/,
677*3833Sxw161283   0/*mdiinv*/, 0/*mdc*/, 0/*phybaseaddr*/, &t1_dummy_mac_ops,
678*3833Sxw161283   &t1_dummy_phy_ops, NULL, "Chelsio simulation environment TOE" },
679*3833Sxw161283 #endif
680*3833Sxw161283 #endif
681*3833Sxw161283 };
682*3833Sxw161283 
683*3833Sxw161283 struct pci_device_id t1_pci_tbl[] = {
684*3833Sxw161283 	CH_DEVICE(8, 0, CH_BRD_T110_1CU),
685*3833Sxw161283 	CH_DEVICE(8, 1, CH_BRD_T110_1CU),
686*3833Sxw161283 	CH_DEVICE(7, 0, CH_BRD_N110_1F),
687*3833Sxw161283 	CH_DEVICE(10, 1, CH_BRD_N210_1F),
688*3833Sxw161283 	CH_DEVICE(11, 1, CH_BRD_T210_1F),
689*3833Sxw161283 	CH_DEVICE(14, 1, CH_BRD_T210_1CU),
690*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
691*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
692*3833Sxw161283 	CH_DEVICE(12, 1, CH_BRD_T204_4CU),
693*3833Sxw161283 	CH_DEVICE(13, 1, CH_BRD_T204V_4CU),
694*3833Sxw161283 	CH_DEVICE(1, 0, CH_BRD_6800_4CU),
695*3833Sxw161283 	CH_DEVICE(2, 1, CH_BRD_7500_4CU),
696*3833Sxw161283 	CH_DEVICE(2, 3, CH_BRD_7500_4F),
697*3833Sxw161283 	CH_DEVICE(4, 0, CH_BRD_T101_1CU_LB),
698*3833Sxw161283 	CH_DEVICE(4, 2, CH_BRD_T101_1F_LB),
699*3833Sxw161283 #endif
700*3833Sxw161283 	CH_DEVICE(3, 0, CH_BRD_8000_1F),
701*3833Sxw161283 	CH_DEVICE(3, 1, CH_BRD_8000_1F),
702*3833Sxw161283 	CH_DEVICE(6, 0, CH_BRD_T110_1F),
703*3833Sxw161283 	CH_DEVICE(6, 1, CH_BRD_T110_1F),
704*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_COUGAR
705*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
706*3833Sxw161283 	CH_DEVICE(5, 0, CH_BRD_COUGAR_4CU),
707*3833Sxw161283 #endif
708*3833Sxw161283 	CH_DEVICE(5, 1, CH_BRD_COUGAR_1F),
709*3833Sxw161283 #endif
710*3833Sxw161283 #ifdef CONFIG_USERMODE
711*3833Sxw161283 	CH_DEVICE(0x5000, PCI_ANY_ID, CH_BRD_SIMUL),
712*3833Sxw161283 #endif
713*3833Sxw161283 #endif
714*3833Sxw161283         { 0, }
715*3833Sxw161283 };
716*3833Sxw161283 
717*3833Sxw161283 #ifndef CH_DEVICE_COMMON
718*3833Sxw161283 /*
719*3833Sxw161283  * Return the board_info structure with a given index.  Out-of-range indices
720*3833Sxw161283  * return NULL.
721*3833Sxw161283  */
722*3833Sxw161283 const struct board_info *
t1_get_board_info(unsigned int board_id)723*3833Sxw161283 t1_get_board_info(unsigned int board_id)
724*3833Sxw161283 {
725*3833Sxw161283 	return (board_id < DIMOF(t1_board) ? &t1_board[board_id] : NULL);
726*3833Sxw161283 }
727*3833Sxw161283 #else
728*3833Sxw161283 /*
729*3833Sxw161283  * Return the board_info structure that corresponds to a given PCI devid/ssid
730*3833Sxw161283  * pair.  Return NULL if the id combination is unknown.
731*3833Sxw161283  */
t1_get_board_info_from_ids(unsigned int devid,unsigned short ssid)732*3833Sxw161283 const struct board_info *t1_get_board_info_from_ids(unsigned int devid,
733*3833Sxw161283 						    unsigned short ssid)
734*3833Sxw161283 {
735*3833Sxw161283 	struct pci_device_id *p;
736*3833Sxw161283 
737*3833Sxw161283 	for (p = t1_pci_tbl; p->devid; ++p)
738*3833Sxw161283 		if (p->devid == devid && p->ssid == ssid)
739*3833Sxw161283 			return (&t1_board[p->board_info_index]);
740*3833Sxw161283 	return (NULL);
741*3833Sxw161283 }
742*3833Sxw161283 #endif
743*3833Sxw161283 
744*3833Sxw161283 typedef struct {
745*3833Sxw161283 	u32 format_version;
746*3833Sxw161283 	u8 serial_number[16];
747*3833Sxw161283 	u8 mac_base_address[6];
748*3833Sxw161283 	u8 pad[2];	/* make multiple-of-4 size requirement explicit */
749*3833Sxw161283 } chelsio_vpd_t;
750*3833Sxw161283 
751*3833Sxw161283 #define	EEPROMSIZE	(8 * 1024)
752*3833Sxw161283 #define	EEPROM_MAX_POLL	4
753*3833Sxw161283 
754*3833Sxw161283 /*
755*3833Sxw161283  * Read SEEPROM. A zero is written to the flag register when the addres is
756*3833Sxw161283  * written to the Control register. The hardware device will set the flag to a
757*3833Sxw161283  * one when 4B have been transferred to the Data register.
758*3833Sxw161283  */
759*3833Sxw161283 int
t1_seeprom_read(adapter_t * adapter,u32 addr,u32 * data)760*3833Sxw161283 t1_seeprom_read(adapter_t *adapter, u32 addr, u32 *data)
761*3833Sxw161283 {
762*3833Sxw161283 	int i = EEPROM_MAX_POLL;
763*3833Sxw161283 	u16 val;
764*3833Sxw161283 
765*3833Sxw161283 	if (addr >= EEPROMSIZE || (addr & 3))
766*3833Sxw161283 	return (-EINVAL);
767*3833Sxw161283 
768*3833Sxw161283 	(void) t1_os_pci_write_config_2(adapter, A_PCICFG_VPD_ADDR, (u16)addr);
769*3833Sxw161283 	do {
770*3833Sxw161283 		DELAY_US(50);
771*3833Sxw161283 		(void) t1_os_pci_read_config_2(adapter,
772*3833Sxw161283 			A_PCICFG_VPD_ADDR, &val);
773*3833Sxw161283 	} while (!(val & F_VPD_OP_FLAG) && --i);
774*3833Sxw161283 
775*3833Sxw161283 	if (!(val & F_VPD_OP_FLAG)) {
776*3833Sxw161283 		CH_ERR("%s: reading EEPROM address 0x%x failed\n",
777*3833Sxw161283 			adapter_name(adapter), addr);
778*3833Sxw161283 		return (-EIO);
779*3833Sxw161283 	}
780*3833Sxw161283 	(void) t1_os_pci_read_config_4(adapter, A_PCICFG_VPD_DATA, data);
781*3833Sxw161283 	*data = le32_to_cpu(*data);
782*3833Sxw161283 	return (0);
783*3833Sxw161283 }
784*3833Sxw161283 
t1_eeprom_vpd_get(adapter_t * adapter,chelsio_vpd_t * vpd)785*3833Sxw161283 static int t1_eeprom_vpd_get(adapter_t *adapter, chelsio_vpd_t *vpd)
786*3833Sxw161283 {
787*3833Sxw161283 	int addr, ret = 0;
788*3833Sxw161283 
789*3833Sxw161283 	for (addr = 0; !ret && addr < sizeof (*vpd); addr += sizeof (u32))
790*3833Sxw161283 		ret = t1_seeprom_read(adapter, addr,
791*3833Sxw161283 			(u32 *)((u8 *)vpd + addr));
792*3833Sxw161283 
793*3833Sxw161283 	return (ret);
794*3833Sxw161283 }
795*3833Sxw161283 
796*3833Sxw161283 /*
797*3833Sxw161283  * Read a port's MAC address from the VPD ROM.
798*3833Sxw161283  */
vpd_macaddress_get(adapter_t * adapter,int index,u8 mac_addr[])799*3833Sxw161283 static int vpd_macaddress_get(adapter_t *adapter, int index, u8 mac_addr[])
800*3833Sxw161283 {
801*3833Sxw161283 	chelsio_vpd_t vpd;
802*3833Sxw161283 
803*3833Sxw161283 	if (t1_eeprom_vpd_get(adapter, &vpd))
804*3833Sxw161283 	return (1);
805*3833Sxw161283 	memcpy(mac_addr, vpd.mac_base_address, 5);
806*3833Sxw161283 	mac_addr[5] = vpd.mac_base_address[5] + index;
807*3833Sxw161283 	return (0);
808*3833Sxw161283 }
809*3833Sxw161283 
810*3833Sxw161283 /*
811*3833Sxw161283  * Set up the MAC/PHY according to the requested link settings.
812*3833Sxw161283  *
813*3833Sxw161283  * If the PHY can auto-negotiate first decide what to advertise, then
814*3833Sxw161283  * enable/disable auto-negotiation as desired and reset.
815*3833Sxw161283  *
816*3833Sxw161283  * If the PHY does not auto-negotiate we just reset it.
817*3833Sxw161283  *
818*3833Sxw161283  * If auto-negotiation is off set the MAC to the proper speed/duplex/FC,
819*3833Sxw161283  * otherwise do it later based on the outcome of auto-negotiation.
820*3833Sxw161283  */
821*3833Sxw161283 int
t1_link_start(struct cphy * phy,struct cmac * mac,struct link_config * lc)822*3833Sxw161283 t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc)
823*3833Sxw161283 {
824*3833Sxw161283 	unsigned int fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
825*3833Sxw161283 
826*3833Sxw161283 	if (lc->supported & SUPPORTED_Autoneg) {
827*3833Sxw161283 		lc->advertising &= ~(ADVERTISED_ASYM_PAUSE | ADVERTISED_PAUSE);
828*3833Sxw161283 		if (fc) {
829*3833Sxw161283 			if (fc == ((PAUSE_RX | PAUSE_TX) & !is_T2(mac->adapter)))
830*3833Sxw161283 				lc->advertising |= ADVERTISED_PAUSE;
831*3833Sxw161283 			else {
832*3833Sxw161283 				lc->advertising |= ADVERTISED_ASYM_PAUSE;
833*3833Sxw161283 				if (fc == PAUSE_RX)
834*3833Sxw161283 					lc->advertising |= ADVERTISED_PAUSE;
835*3833Sxw161283 			}
836*3833Sxw161283 		}
837*3833Sxw161283 		phy->ops->advertise(phy, lc->advertising);
838*3833Sxw161283 
839*3833Sxw161283 		if (lc->autoneg == AUTONEG_DISABLE) {
840*3833Sxw161283 			lc->speed = lc->requested_speed;
841*3833Sxw161283 			lc->duplex = lc->requested_duplex;
842*3833Sxw161283 			lc->fc = (unsigned char)fc;
843*3833Sxw161283 			mac->ops->set_speed_duplex_fc(mac, lc->speed,
844*3833Sxw161283 						      lc->duplex, fc);
845*3833Sxw161283 			/* Also disables autoneg */
846*3833Sxw161283 			phy->state = PHY_AUTONEG_RDY;
847*3833Sxw161283 			phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex);
848*3833Sxw161283 			phy->ops->reset(phy, 0);
849*3833Sxw161283 		} else {
850*3833Sxw161283 			phy->state = PHY_AUTONEG_EN;
851*3833Sxw161283 			phy->ops->autoneg_enable(phy); /* also resets PHY */
852*3833Sxw161283 		}
853*3833Sxw161283 	} else {
854*3833Sxw161283 		phy->state = PHY_AUTONEG_RDY;
855*3833Sxw161283 		mac->ops->set_speed_duplex_fc(mac, -1, -1, fc);
856*3833Sxw161283 		lc->fc = (unsigned char)fc;
857*3833Sxw161283 		phy->ops->reset(phy, 0);
858*3833Sxw161283 	}
859*3833Sxw161283 	return 0;
860*3833Sxw161283 }
861*3833Sxw161283 
862*3833Sxw161283 /*
863*3833Sxw161283  * External interrupt handler for boards using elmer0.
864*3833Sxw161283  */
865*3833Sxw161283 int
elmer0_ext_intr_handler(adapter_t * adapter)866*3833Sxw161283 elmer0_ext_intr_handler(adapter_t *adapter)
867*3833Sxw161283 {
868*3833Sxw161283 	struct cphy *phy;
869*3833Sxw161283 	int phy_cause;
870*3833Sxw161283 	u32 cause;
871*3833Sxw161283 
872*3833Sxw161283 	(void) t1_tpi_read(adapter, A_ELMER0_INT_CAUSE, &cause);
873*3833Sxw161283 
874*3833Sxw161283 	switch (board_info(adapter)->board) {
875*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
876*3833Sxw161283         case CHBT_BOARD_CHT204:
877*3833Sxw161283         case CHBT_BOARD_CHT204V: {
878*3833Sxw161283                 int i, port_bit;
879*3833Sxw161283 		for_each_port(adapter, i) {
880*3833Sxw161283 			port_bit = i ? i + 1 : 0;
881*3833Sxw161283 			if (!(cause & (1 << port_bit))) continue;
882*3833Sxw161283 
883*3833Sxw161283 			phy = adapter->port[i].phy;
884*3833Sxw161283 			phy_cause = phy->ops->interrupt_handler(phy);
885*3833Sxw161283 			if (phy_cause & cphy_cause_link_change)
886*3833Sxw161283 				link_changed(adapter, i);
887*3833Sxw161283 		}
888*3833Sxw161283 		break;
889*3833Sxw161283 	}
890*3833Sxw161283 	case CHBT_BOARD_CHT101:
891*3833Sxw161283 		if (cause & ELMER0_GP_BIT1) { /* Marvell 88E1111 interrupt */
892*3833Sxw161283 			phy = adapter->port[0].phy;
893*3833Sxw161283 			phy_cause = phy->ops->interrupt_handler(phy);
894*3833Sxw161283 			if (phy_cause & cphy_cause_link_change)
895*3833Sxw161283 				link_changed(adapter, 0);
896*3833Sxw161283 		}
897*3833Sxw161283 		break;
898*3833Sxw161283 	case CHBT_BOARD_7500: {
899*3833Sxw161283 		int p;
900*3833Sxw161283 		/*
901*3833Sxw161283 		 * Elmer0's interrupt cause isn't useful here because there is
902*3833Sxw161283 		 * only one bit that can be set for all 4 ports.  This means
903*3833Sxw161283 		 * we are forced to check every PHY's interrupt status
904*3833Sxw161283 		 * register to see who initiated the interrupt.
905*3833Sxw161283 		 */
906*3833Sxw161283 		for_each_port(adapter, p) {
907*3833Sxw161283 			phy = adapter->port[p].phy;
908*3833Sxw161283 			phy_cause = phy->ops->interrupt_handler(phy);
909*3833Sxw161283 			if (phy_cause & cphy_cause_link_change)
910*3833Sxw161283 			    link_changed(adapter, p);
911*3833Sxw161283 		}
912*3833Sxw161283 		break;
913*3833Sxw161283 	}
914*3833Sxw161283 #endif
915*3833Sxw161283 	case CHBT_BOARD_CHT210:
916*3833Sxw161283 	case CHBT_BOARD_N210:
917*3833Sxw161283 	case CHBT_BOARD_N110:
918*3833Sxw161283 		if (cause & ELMER0_GP_BIT6) { /* Marvell 88x2010 interrupt */
919*3833Sxw161283 			phy = adapter->port[0].phy;
920*3833Sxw161283 			phy_cause = phy->ops->interrupt_handler(phy);
921*3833Sxw161283 			if (phy_cause & cphy_cause_link_change)
922*3833Sxw161283 				link_changed(adapter, 0);
923*3833Sxw161283 		}
924*3833Sxw161283 		break;
925*3833Sxw161283 	case CHBT_BOARD_8000:
926*3833Sxw161283 	case CHBT_BOARD_CHT110:
927*3833Sxw161283 		CH_DBG(adapter, INTR, "External interrupt cause 0x%x\n",
928*3833Sxw161283 			cause);
929*3833Sxw161283 		if (cause & ELMER0_GP_BIT1) {	/* PMC3393 INTB */
930*3833Sxw161283 			struct cmac *mac = adapter->port[0].mac;
931*3833Sxw161283 
932*3833Sxw161283 			mac->ops->interrupt_handler(mac);
933*3833Sxw161283 		}
934*3833Sxw161283 		if (cause & ELMER0_GP_BIT5) {	/* XPAK MOD_DETECT */
935*3833Sxw161283 			u32 mod_detect;
936*3833Sxw161283 
937*3833Sxw161283 			(void) t1_tpi_read(adapter, A_ELMER0_GPI_STAT,
938*3833Sxw161283 				&mod_detect);
939*3833Sxw161283 			CH_MSG(adapter, INFO, LINK, "XPAK %s\n",
940*3833Sxw161283 				mod_detect ? "removed" : "inserted");
941*3833Sxw161283 		}
942*3833Sxw161283 		break;
943*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_COUGAR
944*3833Sxw161283 	case CHBT_BOARD_COUGAR:
945*3833Sxw161283 		if (adapter->params.nports == 1) {
946*3833Sxw161283 			if (cause & ELMER0_GP_BIT1) {	/* Vitesse MAC */
947*3833Sxw161283 				struct cmac *mac = adapter->port[0].mac;
948*3833Sxw161283 				mac->ops->interrupt_handler(mac);
949*3833Sxw161283 			}
950*3833Sxw161283 			if (cause & ELMER0_GP_BIT5) {	/* XPAK MOD_DETECT */
951*3833Sxw161283 			}
952*3833Sxw161283 		} else {
953*3833Sxw161283 			int i, port_bit;
954*3833Sxw161283 
955*3833Sxw161283 			for_each_port(adapter, i) {
956*3833Sxw161283 				port_bit = i ? i + 1 : 0;
957*3833Sxw161283 				if (!(cause & (1 << port_bit))) continue;
958*3833Sxw161283 
959*3833Sxw161283 				phy = adapter->port[i].phy;
960*3833Sxw161283 				phy_cause = phy->ops->interrupt_handler(phy);
961*3833Sxw161283 				if (phy_cause & cphy_cause_link_change)
962*3833Sxw161283 					link_changed(adapter, i);
963*3833Sxw161283 			}
964*3833Sxw161283 		}
965*3833Sxw161283 		break;
966*3833Sxw161283 #endif
967*3833Sxw161283 	}
968*3833Sxw161283 	(void) t1_tpi_write(adapter, A_ELMER0_INT_CAUSE, cause);
969*3833Sxw161283 	return (0);
970*3833Sxw161283 }
971*3833Sxw161283 
972*3833Sxw161283 /* Enables all interrupts. */
973*3833Sxw161283 void
t1_interrupts_enable(adapter_t * adapter)974*3833Sxw161283 t1_interrupts_enable(adapter_t *adapter)
975*3833Sxw161283 {
976*3833Sxw161283 	unsigned int i;
977*3833Sxw161283 
978*3833Sxw161283 	adapter->slow_intr_mask = F_PL_INTR_SGE_ERR | F_PL_INTR_TP;
979*3833Sxw161283 	(void) t1_sge_intr_enable(adapter->sge);
980*3833Sxw161283 	t1_tp_intr_enable(adapter->tp);
981*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
982*3833Sxw161283 	if (adapter->mc4) {
983*3833Sxw161283 		adapter->slow_intr_mask |= F_PL_INTR_MC3 | F_PL_INTR_MC4 |
984*3833Sxw161283 			F_PL_INTR_ULP | F_PL_INTR_MC5;
985*3833Sxw161283 	/*
986*3833Sxw161283 	 * T2 -- Disable interrupts for now b/c we are not clearing
987*3833Sxw161283 	 * correctly yet.
988*3833Sxw161283 	 */
989*3833Sxw161283 		/* t1_ulp_intr_enable(adapter->ulp); */
990*3833Sxw161283 		t1_ulp_intr_disable(adapter->ulp);
991*3833Sxw161283 
992*3833Sxw161283 		t1_mc3_intr_enable(adapter->mc3);
993*3833Sxw161283 		t1_mc4_intr_enable(adapter->mc4);
994*3833Sxw161283 		t1_mc5_intr_enable(adapter->mc5);
995*3833Sxw161283 	}
996*3833Sxw161283 #endif
997*3833Sxw161283 	if (adapter->espi) {
998*3833Sxw161283 		adapter->slow_intr_mask |= F_PL_INTR_ESPI;
999*3833Sxw161283 		t1_espi_intr_enable(adapter->espi);
1000*3833Sxw161283 	}
1001*3833Sxw161283 
1002*3833Sxw161283 	/* Enable MAC/PHY interrupts for each port. */
1003*3833Sxw161283 	for_each_port(adapter, i) {
1004*3833Sxw161283 		adapter->port[i].mac->ops->interrupt_enable(adapter->
1005*3833Sxw161283 			port[i].mac);
1006*3833Sxw161283 		adapter->port[i].phy->ops->interrupt_enable(adapter->
1007*3833Sxw161283 			port[i].phy);
1008*3833Sxw161283 	}
1009*3833Sxw161283 
1010*3833Sxw161283 	/* Enable PCIX & external chip interrupts on ASIC boards. */
1011*3833Sxw161283 	if (t1_is_asic(adapter)) {
1012*3833Sxw161283 		u32 pl_intr = t1_read_reg_4(adapter, A_PL_ENABLE);
1013*3833Sxw161283 
1014*3833Sxw161283 		/* PCI-X interrupts */
1015*3833Sxw161283 		(void) t1_os_pci_write_config_4(adapter, A_PCICFG_INTR_ENABLE,
1016*3833Sxw161283 			0xffffffff);
1017*3833Sxw161283 
1018*3833Sxw161283 		adapter->slow_intr_mask |= F_PL_INTR_EXT | F_PL_INTR_PCIX;
1019*3833Sxw161283 		pl_intr |= F_PL_INTR_EXT | F_PL_INTR_PCIX;
1020*3833Sxw161283 		t1_write_reg_4(adapter, A_PL_ENABLE, pl_intr);
1021*3833Sxw161283 	}
1022*3833Sxw161283 }
1023*3833Sxw161283 
1024*3833Sxw161283 /* Disables all interrupts. */
1025*3833Sxw161283 void
t1_interrupts_disable(adapter_t * adapter)1026*3833Sxw161283 t1_interrupts_disable(adapter_t * adapter)
1027*3833Sxw161283 {
1028*3833Sxw161283 	unsigned int i;
1029*3833Sxw161283 
1030*3833Sxw161283 	(void) t1_sge_intr_disable(adapter->sge);
1031*3833Sxw161283 	t1_tp_intr_disable(adapter->tp);
1032*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
1033*3833Sxw161283 	if (adapter->mc4) {
1034*3833Sxw161283 		t1_ulp_intr_disable(adapter->ulp);
1035*3833Sxw161283 		t1_mc3_intr_disable(adapter->mc3);
1036*3833Sxw161283 		t1_mc4_intr_disable(adapter->mc4);
1037*3833Sxw161283 		t1_mc5_intr_disable(adapter->mc5);
1038*3833Sxw161283 	}
1039*3833Sxw161283 #endif
1040*3833Sxw161283 	if (adapter->espi)
1041*3833Sxw161283 		t1_espi_intr_disable(adapter->espi);
1042*3833Sxw161283 
1043*3833Sxw161283 	/* Disable MAC/PHY interrupts for each port. */
1044*3833Sxw161283 	for_each_port(adapter, i) {
1045*3833Sxw161283 		adapter->port[i].mac->ops->interrupt_disable(adapter->
1046*3833Sxw161283 			port[i].mac);
1047*3833Sxw161283 		adapter->port[i].phy->ops->interrupt_disable(adapter->
1048*3833Sxw161283 			port[i].phy);
1049*3833Sxw161283 	}
1050*3833Sxw161283 
1051*3833Sxw161283 	/* Disable PCIX & external chip interrupts. */
1052*3833Sxw161283 	if (t1_is_asic(adapter))
1053*3833Sxw161283 		t1_write_reg_4(adapter, A_PL_ENABLE, 0);
1054*3833Sxw161283 
1055*3833Sxw161283 	/* PCI-X interrupts */
1056*3833Sxw161283 	(void) t1_os_pci_write_config_4(adapter, A_PCICFG_INTR_ENABLE, 0);
1057*3833Sxw161283 
1058*3833Sxw161283 	adapter->slow_intr_mask = 0;
1059*3833Sxw161283 }
1060*3833Sxw161283 
1061*3833Sxw161283 /* Clears all interrupts */
1062*3833Sxw161283 void
t1_interrupts_clear(adapter_t * adapter)1063*3833Sxw161283 t1_interrupts_clear(adapter_t * adapter)
1064*3833Sxw161283 {
1065*3833Sxw161283 	unsigned int i;
1066*3833Sxw161283 
1067*3833Sxw161283 	(void) t1_sge_intr_clear(adapter->sge);
1068*3833Sxw161283 	t1_tp_intr_clear(adapter->tp);
1069*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
1070*3833Sxw161283 	if (adapter->mc4) {
1071*3833Sxw161283 		t1_ulp_intr_clear(adapter->ulp);
1072*3833Sxw161283 		t1_mc3_intr_clear(adapter->mc3);
1073*3833Sxw161283 		t1_mc4_intr_clear(adapter->mc4);
1074*3833Sxw161283 		t1_mc5_intr_clear(adapter->mc5);
1075*3833Sxw161283 	}
1076*3833Sxw161283 #endif
1077*3833Sxw161283 	if (adapter->espi)
1078*3833Sxw161283 		t1_espi_intr_clear(adapter->espi);
1079*3833Sxw161283 
1080*3833Sxw161283 	/* Clear MAC/PHY interrupts for each port. */
1081*3833Sxw161283 	for_each_port(adapter, i) {
1082*3833Sxw161283 		adapter->port[i].mac->ops->interrupt_clear(adapter->
1083*3833Sxw161283 			port[i].mac);
1084*3833Sxw161283 		adapter->port[i].phy->ops->interrupt_clear(adapter->
1085*3833Sxw161283 			port[i].phy);
1086*3833Sxw161283 	}
1087*3833Sxw161283 
1088*3833Sxw161283 	/* Enable interrupts for external devices. */
1089*3833Sxw161283 	if (t1_is_asic(adapter)) {
1090*3833Sxw161283 		u32 pl_intr = t1_read_reg_4(adapter, A_PL_CAUSE);
1091*3833Sxw161283 
1092*3833Sxw161283 		t1_write_reg_4(adapter, A_PL_CAUSE,
1093*3833Sxw161283 			pl_intr | F_PL_INTR_EXT | F_PL_INTR_PCIX);
1094*3833Sxw161283 	}
1095*3833Sxw161283 
1096*3833Sxw161283 	/* PCI-X interrupts */
1097*3833Sxw161283 	(void) t1_os_pci_write_config_4(adapter, A_PCICFG_INTR_CAUSE,
1098*3833Sxw161283 		0xffffffff);
1099*3833Sxw161283 }
1100*3833Sxw161283 
1101*3833Sxw161283 /*
1102*3833Sxw161283  * Slow path interrupt handler for ASICs.
1103*3833Sxw161283  */
asic_slow_intr(adapter_t * adapter)1104*3833Sxw161283 static int asic_slow_intr(adapter_t *adapter)
1105*3833Sxw161283 {
1106*3833Sxw161283 	u32 cause = t1_read_reg_4(adapter, A_PL_CAUSE);
1107*3833Sxw161283 
1108*3833Sxw161283 	cause &= adapter->slow_intr_mask;
1109*3833Sxw161283 	if (!cause)
1110*3833Sxw161283 		return (0);
1111*3833Sxw161283 	if (cause & F_PL_INTR_SGE_ERR)
1112*3833Sxw161283 		(void) t1_sge_intr_error_handler(adapter->sge);
1113*3833Sxw161283 	if (cause & F_PL_INTR_TP)
1114*3833Sxw161283 		(void) t1_tp_intr_handler(adapter->tp);
1115*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
1116*3833Sxw161283 	if (cause & F_PL_INTR_MC3)
1117*3833Sxw161283 		(void) t1_mc3_intr_handler(adapter->mc3);
1118*3833Sxw161283 	if (cause & F_PL_INTR_MC4)
1119*3833Sxw161283 		(void) t1_mc4_intr_handler(adapter->mc4);
1120*3833Sxw161283 	if (cause & F_PL_INTR_ULP)
1121*3833Sxw161283 		(void) t1_ulp_intr_handler(adapter->ulp);
1122*3833Sxw161283 	if (cause & F_PL_INTR_MC5)
1123*3833Sxw161283 		(void) t1_mc5_intr_handler(adapter->mc5);
1124*3833Sxw161283 #endif
1125*3833Sxw161283 	if (cause & F_PL_INTR_ESPI)
1126*3833Sxw161283 		(void) t1_espi_intr_handler(adapter->espi);
1127*3833Sxw161283 	if (cause & F_PL_INTR_PCIX)
1128*3833Sxw161283 		(void) t1_pci_intr_handler(adapter);
1129*3833Sxw161283 	if (cause & F_PL_INTR_EXT)
1130*3833Sxw161283 		t1_os_elmer0_ext_intr(adapter);
1131*3833Sxw161283 
1132*3833Sxw161283 	/* Clear the interrupts just processed. */
1133*3833Sxw161283 	t1_write_reg_4(adapter, A_PL_CAUSE, cause);
1134*3833Sxw161283 	(void) t1_read_reg_4(adapter, A_PL_CAUSE); /* flush writes */
1135*3833Sxw161283 	return (1);
1136*3833Sxw161283 }
1137*3833Sxw161283 
1138*3833Sxw161283 int
t1_slow_intr_handler(adapter_t * adapter)1139*3833Sxw161283 t1_slow_intr_handler(adapter_t *adapter)
1140*3833Sxw161283 {
1141*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
1142*3833Sxw161283 	if (!t1_is_asic(adapter))
1143*3833Sxw161283 		return (fpga_slow_intr(adapter));
1144*3833Sxw161283 #endif
1145*3833Sxw161283 	return (asic_slow_intr(adapter));
1146*3833Sxw161283 }
1147*3833Sxw161283 
1148*3833Sxw161283 /* Power sequencing is a work-around for Intel's XPAKs. */
1149*3833Sxw161283 static void
power_sequence_xpak(adapter_t * adapter)1150*3833Sxw161283 power_sequence_xpak(adapter_t * adapter)
1151*3833Sxw161283 {
1152*3833Sxw161283 	u32 mod_detect;
1153*3833Sxw161283 	u32 gpo;
1154*3833Sxw161283 
1155*3833Sxw161283 	/* Check for XPAK */
1156*3833Sxw161283 	(void) t1_tpi_read(adapter, A_ELMER0_GPI_STAT, &mod_detect);
1157*3833Sxw161283 	if (!(ELMER0_GP_BIT5 & mod_detect)) {
1158*3833Sxw161283 		/* XPAK is present */
1159*3833Sxw161283 		(void) t1_tpi_read(adapter, A_ELMER0_GPO, &gpo);
1160*3833Sxw161283 		gpo |= ELMER0_GP_BIT18;
1161*3833Sxw161283 		(void) t1_tpi_write(adapter, A_ELMER0_GPO, gpo);
1162*3833Sxw161283 	}
1163*3833Sxw161283 }
1164*3833Sxw161283 
t1_get_board_rev(adapter_t * adapter,const struct board_info * bi,struct adapter_params * p)1165*3833Sxw161283 int __devinit t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
1166*3833Sxw161283 	struct adapter_params *p)
1167*3833Sxw161283 {
1168*3833Sxw161283 	p->chip_version = bi->chip_term;
1169*3833Sxw161283 	p->is_asic = (p->chip_version != CHBT_TERM_FPGA);
1170*3833Sxw161283 	if (p->chip_version == CHBT_TERM_T1 ||
1171*3833Sxw161283 	    p->chip_version == CHBT_TERM_T2 ||
1172*3833Sxw161283 	    p->chip_version == CHBT_TERM_FPGA) {
1173*3833Sxw161283 		u32 val = t1_read_reg_4(adapter, A_TP_PC_CONFIG);
1174*3833Sxw161283 
1175*3833Sxw161283 		val = G_TP_PC_REV(val);
1176*3833Sxw161283 		if (val == 2)
1177*3833Sxw161283 			p->chip_revision = TERM_T1B;
1178*3833Sxw161283 		else if (val == 3)
1179*3833Sxw161283 			p->chip_revision = TERM_T2;
1180*3833Sxw161283 		else
1181*3833Sxw161283 			return (-1);
1182*3833Sxw161283 	} else
1183*3833Sxw161283 		return (-1);
1184*3833Sxw161283 	return (0);
1185*3833Sxw161283 }
1186*3833Sxw161283 
1187*3833Sxw161283 /*
1188*3833Sxw161283  * Enable board components other than the Chelsio chip, such as external MAC
1189*3833Sxw161283  * and PHY.
1190*3833Sxw161283  */
board_init(adapter_t * adapter,const struct board_info * bi)1191*3833Sxw161283 static int board_init(adapter_t *adapter, const struct board_info *bi)
1192*3833Sxw161283 {
1193*3833Sxw161283 	switch (bi->board) {
1194*3833Sxw161283 	case CHBT_BOARD_8000:
1195*3833Sxw161283 	case CHBT_BOARD_N110:
1196*3833Sxw161283 	case CHBT_BOARD_N210:
1197*3833Sxw161283 	case CHBT_BOARD_CHT210:
1198*3833Sxw161283 	case CHBT_BOARD_COUGAR:
1199*3833Sxw161283 		t1_tpi_par(adapter, 0xf);
1200*3833Sxw161283 		(void) t1_tpi_write(adapter, A_ELMER0_GPO, 0x800);
1201*3833Sxw161283 		break;
1202*3833Sxw161283 	case CHBT_BOARD_CHT110:
1203*3833Sxw161283 		t1_tpi_par(adapter, 0xf);
1204*3833Sxw161283 		(void) t1_tpi_write(adapter, A_ELMER0_GPO, 0x1800);
1205*3833Sxw161283 
1206*3833Sxw161283 		/*
1207*3833Sxw161283 		 * TBD XXX Might not need.  This fixes a problem
1208*3833Sxw161283 		 * described in the Intel SR XPAK errata.
1209*3833Sxw161283 		 */
1210*3833Sxw161283 		power_sequence_xpak(adapter);
1211*3833Sxw161283 		break;
1212*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_1G
1213*3833Sxw161283 	case CHBT_BOARD_CHT204:
1214*3833Sxw161283 	case CHBT_BOARD_CHT204V:
1215*3833Sxw161283                 t1_tpi_par(adapter, 0xf);
1216*3833Sxw161283                 (void) t1_tpi_write(adapter, A_ELMER0_GPO, 0x804);
1217*3833Sxw161283                 break;
1218*3833Sxw161283 	case CHBT_BOARD_CHT101:
1219*3833Sxw161283 	case CHBT_BOARD_7500:
1220*3833Sxw161283 		t1_tpi_par(adapter, 0xf);
1221*3833Sxw161283 		(void) t1_tpi_write(adapter, A_ELMER0_GPO, 0x1804);
1222*3833Sxw161283 		break;
1223*3833Sxw161283 #endif
1224*3833Sxw161283 	}
1225*3833Sxw161283 	return (0);
1226*3833Sxw161283 }
1227*3833Sxw161283 
1228*3833Sxw161283 /*
1229*3833Sxw161283  * Initialize and configure the Terminator HW modules.  Note that external
1230*3833Sxw161283  * MAC and PHYs are initialized separately.
1231*3833Sxw161283  */
1232*3833Sxw161283 int
t1_init_hw_modules(adapter_t * adapter)1233*3833Sxw161283 t1_init_hw_modules(adapter_t *adapter)
1234*3833Sxw161283 {
1235*3833Sxw161283 	int err = -EIO;
1236*3833Sxw161283 	const struct board_info *bi = board_info(adapter);
1237*3833Sxw161283 
1238*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
1239*3833Sxw161283 	if (adapter->mc3 && t1_mc3_init(adapter->mc3, bi->clock_mc3))
1240*3833Sxw161283 		goto out_err;
1241*3833Sxw161283 	if (adapter->mc4 && t1_mc4_init(adapter->mc4, bi->clock_mc4))
1242*3833Sxw161283 		goto out_err;
1243*3833Sxw161283 	if (adapter->mc5 && t1_mc5_init(adapter->mc5,
1244*3833Sxw161283 					adapter->params.mc5.nservers,
1245*3833Sxw161283 					adapter->params.mc5.nroutes, 1, 0))
1246*3833Sxw161283 		goto out_err;
1247*3833Sxw161283 	if (adapter->ulp && t1_ulp_init(adapter->ulp,
1248*3833Sxw161283 					adapter->params.tp.pm_tx_base))
1249*3833Sxw161283 		goto out_err;
1250*3833Sxw161283 #endif
1251*3833Sxw161283 	if (!adapter->mc4) {
1252*3833Sxw161283 		u32 val = t1_read_reg_4(adapter, A_MC4_CFG);
1253*3833Sxw161283 
1254*3833Sxw161283 		t1_write_reg_4(adapter, A_MC4_CFG, val | F_READY | F_MC4_SLOW);
1255*3833Sxw161283 		t1_write_reg_4(adapter, A_MC5_CONFIG,
1256*3833Sxw161283 			F_M_BUS_ENABLE | F_TCAM_RESET);
1257*3833Sxw161283 	}
1258*3833Sxw161283 
1259*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_COUGAR
1260*3833Sxw161283 	if (adapter->cspi && t1_cspi_init(adapter->cspi))
1261*3833Sxw161283 		goto out_err;
1262*3833Sxw161283 #endif
1263*3833Sxw161283 	if (adapter->espi && t1_espi_init(adapter->espi, bi->chip_mac,
1264*3833Sxw161283 		bi->espi_nports))
1265*3833Sxw161283 		goto out_err;
1266*3833Sxw161283 
1267*3833Sxw161283 	if (t1_tp_reset(adapter->tp, &adapter->params.tp, bi->clock_core))
1268*3833Sxw161283 		goto out_err;
1269*3833Sxw161283 
1270*3833Sxw161283 	err = t1_sge_configure(adapter->sge, &adapter->params.sge);
1271*3833Sxw161283 	if (err)
1272*3833Sxw161283 		goto out_err;
1273*3833Sxw161283 
1274*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
1275*3833Sxw161283 	(void) t1_tp_set_coalescing_size(adapter->tp,
1276*3833Sxw161283 		min(adapter->params.sge.large_buf_capacity,
1277*3833Sxw161283 			TP_MAX_RX_COALESCING_SIZE));
1278*3833Sxw161283 #endif
1279*3833Sxw161283 	err = 0;
1280*3833Sxw161283 out_err:
1281*3833Sxw161283 	return (err);
1282*3833Sxw161283 }
1283*3833Sxw161283 
1284*3833Sxw161283 /*
1285*3833Sxw161283  * Determine a card's PCI mode.
1286*3833Sxw161283  */
get_pci_mode(adapter_t * adapter,struct pci_params * p)1287*3833Sxw161283 static void __devinit get_pci_mode(adapter_t *adapter, struct pci_params *p)
1288*3833Sxw161283 {
1289*3833Sxw161283 	static unsigned short speed_map[] = { 33, 66, 100, 133 };
1290*3833Sxw161283 	u32 pci_mode;
1291*3833Sxw161283 
1292*3833Sxw161283 	(void) t1_os_pci_read_config_4(adapter, A_PCICFG_MODE, &pci_mode);
1293*3833Sxw161283 	p->speed = speed_map[G_PCI_MODE_CLK(pci_mode)];
1294*3833Sxw161283 	p->width = (pci_mode & F_PCI_MODE_64BIT) ? 64 : 32;
1295*3833Sxw161283 	p->is_pcix = (pci_mode & F_PCI_MODE_PCIX) != 0;
1296*3833Sxw161283 }
1297*3833Sxw161283 
1298*3833Sxw161283 /*
1299*3833Sxw161283  * Release the structures holding the SW per-Terminator-HW-module state.
1300*3833Sxw161283  */
1301*3833Sxw161283 void
t1_free_sw_modules(adapter_t * adapter)1302*3833Sxw161283 t1_free_sw_modules(adapter_t *adapter)
1303*3833Sxw161283 {
1304*3833Sxw161283 	unsigned int i;
1305*3833Sxw161283 
1306*3833Sxw161283 	for_each_port(adapter, i) {
1307*3833Sxw161283 		struct cmac *mac = adapter->port[i].mac;
1308*3833Sxw161283 		struct cphy *phy = adapter->port[i].phy;
1309*3833Sxw161283 
1310*3833Sxw161283 		if (mac)
1311*3833Sxw161283 			mac->ops->destroy(mac);
1312*3833Sxw161283 		if (phy)
1313*3833Sxw161283 			phy->ops->destroy(phy);
1314*3833Sxw161283 	}
1315*3833Sxw161283 
1316*3833Sxw161283 	if (adapter->sge)
1317*3833Sxw161283 		(void) t1_sge_destroy(adapter->sge);
1318*3833Sxw161283 	if (adapter->tp)
1319*3833Sxw161283 		t1_tp_destroy(adapter->tp);
1320*3833Sxw161283 	if (adapter->espi)
1321*3833Sxw161283 		t1_espi_destroy(adapter->espi);
1322*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
1323*3833Sxw161283 	if (adapter->mc5)
1324*3833Sxw161283 		t1_mc5_destroy(adapter->mc5);
1325*3833Sxw161283 	if (adapter->mc3)
1326*3833Sxw161283 		t1_mc3_destroy(adapter->mc3);
1327*3833Sxw161283 	if (adapter->mc4)
1328*3833Sxw161283 		t1_mc4_destroy(adapter->mc4);
1329*3833Sxw161283 	if (adapter->ulp)
1330*3833Sxw161283 		t1_ulp_destroy(adapter->ulp);
1331*3833Sxw161283 #endif
1332*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_COUGAR
1333*3833Sxw161283 	if (adapter->cspi)
1334*3833Sxw161283 		t1_cspi_destroy(adapter->cspi);
1335*3833Sxw161283 #endif
1336*3833Sxw161283 }
1337*3833Sxw161283 
init_link_config(struct link_config * lc,const struct board_info * bi)1338*3833Sxw161283 static void __devinit init_link_config(struct link_config *lc,
1339*3833Sxw161283 	const struct board_info *bi)
1340*3833Sxw161283 {
1341*3833Sxw161283 	lc->supported = bi->caps;
1342*3833Sxw161283 	lc->requested_speed = lc->speed = SPEED_INVALID;
1343*3833Sxw161283 	lc->requested_duplex = lc->duplex = DUPLEX_INVALID;
1344*3833Sxw161283 	lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX;
1345*3833Sxw161283 	if (lc->supported & SUPPORTED_Autoneg) {
1346*3833Sxw161283 		lc->advertising = lc->supported;
1347*3833Sxw161283 		lc->autoneg = AUTONEG_ENABLE;
1348*3833Sxw161283 		lc->requested_fc |= PAUSE_AUTONEG;
1349*3833Sxw161283 	} else {
1350*3833Sxw161283 		lc->advertising = 0;
1351*3833Sxw161283 		lc->autoneg = AUTONEG_DISABLE;
1352*3833Sxw161283 	}
1353*3833Sxw161283 }
1354*3833Sxw161283 
1355*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
init_mtus(unsigned short mtus[])1356*3833Sxw161283 void init_mtus(unsigned short mtus[])
1357*3833Sxw161283 {
1358*3833Sxw161283 	mtus[0] = 68;
1359*3833Sxw161283 	mtus[1] = 508;
1360*3833Sxw161283 	mtus[2] = 576;
1361*3833Sxw161283 	mtus[3] = 1492;
1362*3833Sxw161283 	mtus[4] = 1500;
1363*3833Sxw161283 	mtus[5] = 2000;
1364*3833Sxw161283 	mtus[6] = 4000;
1365*3833Sxw161283 	mtus[7] = 9000;
1366*3833Sxw161283 }
1367*3833Sxw161283 #endif
1368*3833Sxw161283 
1369*3833Sxw161283 /*
1370*3833Sxw161283  * Allocate and initialize the data structures that hold the SW state of
1371*3833Sxw161283  * the Terminator HW modules.
1372*3833Sxw161283  */
t1_init_sw_modules(adapter_t * adapter,const struct board_info * bi)1373*3833Sxw161283 int __devinit t1_init_sw_modules(adapter_t *adapter,
1374*3833Sxw161283 	const struct board_info *bi)
1375*3833Sxw161283 {
1376*3833Sxw161283 	unsigned int i;
1377*3833Sxw161283 
1378*3833Sxw161283 	adapter->params.brd_info = bi;
1379*3833Sxw161283 	adapter->params.nports = bi->port_number;
1380*3833Sxw161283 	adapter->params.stats_update_period = bi->gmac->stats_update_period;
1381*3833Sxw161283 
1382*3833Sxw161283 	adapter->sge = t1_sge_create(adapter, &adapter->params.sge);
1383*3833Sxw161283 	if (!adapter->sge) {
1384*3833Sxw161283 		CH_ERR("%s: SGE initialization failed\n",
1385*3833Sxw161283 			adapter_name(adapter));
1386*3833Sxw161283 		goto error;
1387*3833Sxw161283 	}
1388*3833Sxw161283 
1389*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_OFFLOAD
1390*3833Sxw161283 	if (bi->clock_mc4) {
1391*3833Sxw161283 		/*
1392*3833Sxw161283 		 * Must wait 200us after power up before touching the
1393*3833Sxw161283 		 * memory controllers.
1394*3833Sxw161283 		 */
1395*3833Sxw161283 		DELAY_US(200);
1396*3833Sxw161283 
1397*3833Sxw161283 		adapter->mc3 = t1_mc3_create(adapter);
1398*3833Sxw161283 		if (!adapter->mc3) {
1399*3833Sxw161283 			CH_ERR("%s: MC3 initialization failed\n",
1400*3833Sxw161283 				adapter_name(adapter));
1401*3833Sxw161283 			goto error;
1402*3833Sxw161283 		}
1403*3833Sxw161283 
1404*3833Sxw161283 		adapter->mc4 = t1_mc4_create(adapter);
1405*3833Sxw161283 		if (!adapter->mc4) {
1406*3833Sxw161283 			CH_ERR("%s: MC4 initialization failed\n",
1407*3833Sxw161283 				adapter_name(adapter));
1408*3833Sxw161283 			goto error;
1409*3833Sxw161283 		}
1410*3833Sxw161283 
1411*3833Sxw161283 		if (!adapter->params.mc5.mode)
1412*3833Sxw161283 			adapter->params.mc5.mode = MC5_MODE_144_BIT;
1413*3833Sxw161283 		adapter->mc5 = t1_mc5_create(adapter,
1414*3833Sxw161283 			adapter->params.mc5.mode);
1415*3833Sxw161283 		if (!adapter->mc5) {
1416*3833Sxw161283 			CH_ERR("%s: MC5 initialization failed\n",
1417*3833Sxw161283 				adapter_name(adapter));
1418*3833Sxw161283 			goto error;
1419*3833Sxw161283 		}
1420*3833Sxw161283 
1421*3833Sxw161283 		adapter->ulp = t1_ulp_create(adapter);
1422*3833Sxw161283 		if (!adapter->ulp) {
1423*3833Sxw161283 			CH_ERR("%s: ULP initialization failed\n",
1424*3833Sxw161283 				adapter_name(adapter));
1425*3833Sxw161283 			goto error;
1426*3833Sxw161283 		}
1427*3833Sxw161283 
1428*3833Sxw161283 		adapter->params.tp.pm_size = t1_mc3_get_size(adapter->mc3);
1429*3833Sxw161283 		adapter->params.tp.cm_size = t1_mc4_get_size(adapter->mc4);
1430*3833Sxw161283 
1431*3833Sxw161283 		adapter->params.mc5.nservers = DEFAULT_SERVER_REGION_LEN;
1432*3833Sxw161283 		adapter->params.mc5.nroutes = DEFAULT_RT_REGION_LEN;
1433*3833Sxw161283 
1434*3833Sxw161283 		init_mtus(adapter->params.mtus);
1435*3833Sxw161283 	}
1436*3833Sxw161283 #endif
1437*3833Sxw161283 
1438*3833Sxw161283 #ifdef CONFIG_CHELSIO_T1_COUGAR
1439*3833Sxw161283 	if (bi->clock_cspi && !(adapter->cspi = t1_cspi_create(adapter))) {
1440*3833Sxw161283 		CH_ERR("%s: CSPI initialization failed\n",
1441*3833Sxw161283 			adapter_name(adapter));
1442*3833Sxw161283 		goto error;
1443*3833Sxw161283 	}
1444*3833Sxw161283 #endif
1445*3833Sxw161283 
1446*3833Sxw161283 	if (bi->espi_nports && !(adapter->espi = t1_espi_create(adapter))) {
1447*3833Sxw161283 		CH_ERR("%s: ESPI initialization failed\n",
1448*3833Sxw161283 			adapter_name(adapter));
1449*3833Sxw161283 		goto error;
1450*3833Sxw161283 	}
1451*3833Sxw161283 
1452*3833Sxw161283 	adapter->tp = t1_tp_create(adapter, &adapter->params.tp);
1453*3833Sxw161283 	if (!adapter->tp) {
1454*3833Sxw161283 		CH_ERR("%s: TP initialization failed\n",
1455*3833Sxw161283 			adapter_name(adapter));
1456*3833Sxw161283 		goto error;
1457*3833Sxw161283 	}
1458*3833Sxw161283 
1459*3833Sxw161283 	(void) board_init(adapter, bi);
1460*3833Sxw161283 	bi->mdio_ops->init(adapter, bi);
1461*3833Sxw161283 	if (bi->gphy->reset)
1462*3833Sxw161283 		bi->gphy->reset(adapter);
1463*3833Sxw161283 	if (bi->gmac->reset)
1464*3833Sxw161283 		bi->gmac->reset(adapter);
1465*3833Sxw161283 
1466*3833Sxw161283 	for_each_port(adapter, i) {
1467*3833Sxw161283 		u8 hw_addr[6];
1468*3833Sxw161283 		struct cmac *mac;
1469*3833Sxw161283 		int phy_addr = bi->mdio_phybaseaddr + i;
1470*3833Sxw161283 
1471*3833Sxw161283 		adapter->port[i].phy = bi->gphy->create(adapter, phy_addr,
1472*3833Sxw161283 							bi->mdio_ops);
1473*3833Sxw161283 		if (!adapter->port[i].phy) {
1474*3833Sxw161283 			CH_ERR("%s: PHY %d initialization failed\n",
1475*3833Sxw161283 				adapter_name(adapter), i);
1476*3833Sxw161283 			goto error;
1477*3833Sxw161283 		}
1478*3833Sxw161283 
1479*3833Sxw161283 		adapter->port[i].mac = mac = bi->gmac->create(adapter, i);
1480*3833Sxw161283 		if (!mac) {
1481*3833Sxw161283 			CH_ERR("%s: MAC %d initialization failed\n",
1482*3833Sxw161283 				adapter_name(adapter), i);
1483*3833Sxw161283 			goto error;
1484*3833Sxw161283 		}
1485*3833Sxw161283 
1486*3833Sxw161283 		/*
1487*3833Sxw161283 		 * Get the port's MAC addresses either from the EEPROM if one
1488*3833Sxw161283 		 * exists or the one hardcoded in the MAC.
1489*3833Sxw161283 		 */
1490*3833Sxw161283 		if (!t1_is_asic(adapter) || bi->chip_mac == CHBT_MAC_DUMMY)
1491*3833Sxw161283 			mac->ops->macaddress_get(mac, hw_addr);
1492*3833Sxw161283 		else if (vpd_macaddress_get(adapter, i, hw_addr)) {
1493*3833Sxw161283 			CH_ERR("%s: could not read MAC address from VPD ROM\n",
1494*3833Sxw161283 				port_name(adapter, i));
1495*3833Sxw161283 			goto error;
1496*3833Sxw161283 		}
1497*3833Sxw161283 		t1_os_set_hw_addr(adapter, i, hw_addr);
1498*3833Sxw161283 		init_link_config(&adapter->port[i].link_config, bi);
1499*3833Sxw161283 	}
1500*3833Sxw161283 
1501*3833Sxw161283 	get_pci_mode(adapter, &adapter->params.pci);
1502*3833Sxw161283 	t1_interrupts_clear(adapter);
1503*3833Sxw161283 	return (0);
1504*3833Sxw161283 
1505*3833Sxw161283 error:
1506*3833Sxw161283 	t1_free_sw_modules(adapter);
1507*3833Sxw161283 	return (-1);
1508*3833Sxw161283 }
1509