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