This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / net / chelsio / subr.c
1 /*****************************************************************************
2  *                                                                           *
3  * File: subr.c                                                              *
4  * $Revision: 1.27 $                                                         *
5  * $Date: 2005/06/22 01:08:36 $                                              *
6  * Description:                                                              *
7  *  Various subroutines (intr,pio,etc.) used by Chelsio 10G Ethernet driver. *
8  *  part of the Chelsio 10Gb Ethernet Driver.                                *
9  *                                                                           *
10  * This program is free software; you can redistribute it and/or modify      *
11  * it under the terms of the GNU General Public License, version 2, as       *
12  * published by the Free Software Foundation.                                *
13  *                                                                           *
14  * You should have received a copy of the GNU General Public License along   *
15  * with this program; if not, write to the Free Software Foundation, Inc.,   *
16  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.                 *
17  *                                                                           *
18  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED    *
19  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF      *
20  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.                     *
21  *                                                                           *
22  * http://www.chelsio.com                                                    *
23  *                                                                           *
24  * Copyright (c) 2003 - 2005 Chelsio Communications, Inc.                    *
25  * All rights reserved.                                                      *
26  *                                                                           *
27  * Maintainers: maintainers@chelsio.com                                      *
28  *                                                                           *
29  * Authors: Dimitrios Michailidis   <dm@chelsio.com>                         *
30  *          Tina Yang               <tainay@chelsio.com>                     *
31  *          Felix Marti             <felix@chelsio.com>                      *
32  *          Scott Bardone           <sbardone@chelsio.com>                   *
33  *          Kurt Ottaway            <kottaway@chelsio.com>                   *
34  *          Frank DiMambro          <frank@chelsio.com>                      *
35  *                                                                           *
36  * History:                                                                  *
37  *                                                                           *
38  ****************************************************************************/
39
40 #include "common.h"
41 #include "elmer0.h"
42 #include "regs.h"
43 #include "gmac.h"
44 #include "cphy.h"
45 #include "sge.h"
46 #include "espi.h"
47
48 /**
49  *      t1_wait_op_done - wait until an operation is completed
50  *      @adapter: the adapter performing the operation
51  *      @reg: the register to check for completion
52  *      @mask: a single-bit field within @reg that indicates completion
53  *      @polarity: the value of the field when the operation is completed
54  *      @attempts: number of check iterations
55  *      @delay: delay in usecs between iterations
56  *
57  *      Wait until an operation is completed by checking a bit in a register
58  *      up to @attempts times.  Returns %0 if the operation completes and %1
59  *      otherwise.
60  */
61 static int t1_wait_op_done(adapter_t *adapter, int reg, u32 mask, int polarity,
62                     int attempts, int delay)
63 {
64         while (1) {
65                 u32 val = readl(adapter->regs + reg) & mask;
66
67                 if (!!val == polarity)
68                         return 0;
69                 if (--attempts == 0)
70                         return 1;
71                 if (delay)
72                         udelay(delay);
73         }
74 }
75
76 #define TPI_ATTEMPTS 50
77
78 /*
79  * Write a register over the TPI interface (unlocked and locked versions).
80  */
81 static int __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value)
82 {
83         int tpi_busy;
84
85         writel(addr, adapter->regs + A_TPI_ADDR);
86         writel(value, adapter->regs + A_TPI_WR_DATA);
87         writel(F_TPIWR, adapter->regs + A_TPI_CSR);
88
89         tpi_busy = t1_wait_op_done(adapter, A_TPI_CSR, F_TPIRDY, 1,
90                                    TPI_ATTEMPTS, 3);
91         if (tpi_busy)
92                 CH_ALERT("%s: TPI write to 0x%x failed\n",
93                          adapter->name, addr);
94         return tpi_busy;
95 }
96
97 int t1_tpi_write(adapter_t *adapter, u32 addr, u32 value)
98 {
99         int ret;
100
101         spin_lock(&(adapter)->tpi_lock);
102         ret = __t1_tpi_write(adapter, addr, value);
103         spin_unlock(&(adapter)->tpi_lock);
104         return ret;
105 }
106
107 /*
108  * Read a register over the TPI interface (unlocked and locked versions).
109  */
110 static int __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp)
111 {
112         int tpi_busy;
113
114         writel(addr, adapter->regs + A_TPI_ADDR);
115         writel(0, adapter->regs + A_TPI_CSR);
116
117         tpi_busy = t1_wait_op_done(adapter, A_TPI_CSR, F_TPIRDY, 1,
118                                    TPI_ATTEMPTS, 3);
119         if (tpi_busy)
120                 CH_ALERT("%s: TPI read from 0x%x failed\n",
121                          adapter->name, addr);
122         else
123                 *valp = readl(adapter->regs + A_TPI_RD_DATA);
124         return tpi_busy;
125 }
126
127 int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp)
128 {
129         int ret;
130
131         spin_lock(&(adapter)->tpi_lock);
132         ret = __t1_tpi_read(adapter, addr, valp);
133         spin_unlock(&(adapter)->tpi_lock);
134         return ret;
135 }
136
137 /*
138  * Called when a port's link settings change to propagate the new values to the
139  * associated PHY and MAC.  After performing the common tasks it invokes an
140  * OS-specific handler.
141  */
142 /* static */ void link_changed(adapter_t *adapter, int port_id)
143 {
144         int link_ok, speed, duplex, fc;
145         struct cphy *phy = adapter->port[port_id].phy;
146         struct link_config *lc = &adapter->port[port_id].link_config;
147
148         phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
149
150         lc->speed = speed < 0 ? SPEED_INVALID : speed;
151         lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex;
152         if (!(lc->requested_fc & PAUSE_AUTONEG))
153                 fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
154
155         if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE) {
156                 /* Set MAC speed, duplex, and flow control to match PHY. */
157                 struct cmac *mac = adapter->port[port_id].mac;
158
159                 mac->ops->set_speed_duplex_fc(mac, speed, duplex, fc);
160                 lc->fc = (unsigned char)fc;
161         }
162         t1_link_changed(adapter, port_id, link_ok, speed, duplex, fc);
163 }
164
165 static int t1_pci_intr_handler(adapter_t *adapter)
166 {
167         u32 pcix_cause;
168
169         pci_read_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, &pcix_cause);
170
171         if (pcix_cause) {
172                 pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE,
173                                          pcix_cause);
174                 t1_fatal_err(adapter);    /* PCI errors are fatal */
175         }
176         return 0;
177 }
178
179
180 /*
181  * Wait until Elmer's MI1 interface is ready for new operations.
182  */
183 static int mi1_wait_until_ready(adapter_t *adapter, int mi1_reg)
184 {
185         int attempts = 100, busy;
186
187         do {
188                 u32 val;
189
190                 __t1_tpi_read(adapter, mi1_reg, &val);
191                 busy = val & F_MI1_OP_BUSY;
192                 if (busy)
193                         udelay(10);
194         } while (busy && --attempts);
195         if (busy)
196                 CH_ALERT("%s: MDIO operation timed out\n",
197                          adapter->name);
198         return busy;
199 }
200
201 /*
202  * MI1 MDIO initialization.
203  */
204 static void mi1_mdio_init(adapter_t *adapter, const struct board_info *bi)
205 {
206         u32 clkdiv = bi->clock_elmer0 / (2 * bi->mdio_mdc) - 1;
207         u32 val = F_MI1_PREAMBLE_ENABLE | V_MI1_MDI_INVERT(bi->mdio_mdiinv) |
208                 V_MI1_MDI_ENABLE(bi->mdio_mdien) | V_MI1_CLK_DIV(clkdiv);
209
210         if (!(bi->caps & SUPPORTED_10000baseT_Full))
211                 val |= V_MI1_SOF(1);
212         t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_CFG, val);
213 }
214
215 static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr,
216                              int reg_addr, unsigned int *valp)
217 {
218         u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
219
220         spin_lock(&(adapter)->tpi_lock);
221
222         /* Write the address we want. */
223         __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
224         __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, reg_addr);
225         __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
226                        MI1_OP_INDIRECT_ADDRESS);
227         mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
228
229         /* Write the operation we want. */
230         __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_READ);
231         mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
232
233         /* Read the data. */
234         __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp);
235         spin_unlock(&(adapter)->tpi_lock);
236         return 0;
237 }
238
239 static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr,
240                               int reg_addr, unsigned int val)
241 {
242         u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr);
243
244         spin_lock(&(adapter)->tpi_lock);
245
246         /* Write the address we want. */
247         __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr);
248         __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, reg_addr);
249         __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP,
250                        MI1_OP_INDIRECT_ADDRESS);
251         mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
252
253         /* Write the data. */
254         __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val);
255         __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_WRITE);
256         mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP);
257         spin_unlock(&(adapter)->tpi_lock);
258         return 0;
259 }
260
261 static struct mdio_ops mi1_mdio_ext_ops = {
262         mi1_mdio_init,
263         mi1_mdio_ext_read,
264         mi1_mdio_ext_write
265 };
266
267 enum {
268         CH_BRD_N110_1F,
269         CH_BRD_N210_1F,
270 };
271
272 static struct board_info t1_board[] = {
273
274 { CHBT_BOARD_N110, 1/*ports#*/,
275   SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE /*caps*/, CHBT_TERM_T1,
276   CHBT_MAC_PM3393, CHBT_PHY_88X2010,
277   125000000/*clk-core*/, 0/*clk-mc3*/, 0/*clk-mc4*/,
278   1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 0/*mdien*/,
279   0/*mdiinv*/, 1/*mdc*/, 0/*phybaseaddr*/, &t1_pm3393_ops,
280   &t1_mv88x201x_ops, &mi1_mdio_ext_ops,
281   "Chelsio N110 1x10GBaseX NIC" },
282
283 { CHBT_BOARD_N210, 1/*ports#*/,
284   SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE /*caps*/, CHBT_TERM_T2,
285   CHBT_MAC_PM3393, CHBT_PHY_88X2010,
286   125000000/*clk-core*/, 0/*clk-mc3*/, 0/*clk-mc4*/,
287   1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 0/*mdien*/,
288   0/*mdiinv*/, 1/*mdc*/, 0/*phybaseaddr*/, &t1_pm3393_ops,
289   &t1_mv88x201x_ops, &mi1_mdio_ext_ops,
290   "Chelsio N210 1x10GBaseX NIC" },
291
292 };
293
294 struct pci_device_id t1_pci_tbl[] = {
295         CH_DEVICE(7, 0, CH_BRD_N110_1F),
296         CH_DEVICE(10, 1, CH_BRD_N210_1F),
297         { 0, }
298 };
299
300 MODULE_DEVICE_TABLE(pci, t1_pci_tbl);
301
302 /*
303  * Return the board_info structure with a given index.  Out-of-range indices
304  * return NULL.
305  */
306 const struct board_info *t1_get_board_info(unsigned int board_id)
307 {
308         return board_id < ARRAY_SIZE(t1_board) ? &t1_board[board_id] : NULL;
309 }
310
311 struct chelsio_vpd_t {
312         u32 format_version;
313         u8 serial_number[16];
314         u8 mac_base_address[6];
315         u8 pad[2];           /* make multiple-of-4 size requirement explicit */
316 };
317
318 #define EEPROMSIZE        (8 * 1024)
319 #define EEPROM_MAX_POLL   4
320
321 /*
322  * Read SEEPROM. A zero is written to the flag register when the addres is
323  * written to the Control register. The hardware device will set the flag to a
324  * one when 4B have been transferred to the Data register.
325  */
326 int t1_seeprom_read(adapter_t *adapter, u32 addr, u32 *data)
327 {
328         int i = EEPROM_MAX_POLL;
329         u16 val;
330
331         if (addr >= EEPROMSIZE || (addr & 3))
332                 return -EINVAL;
333
334         pci_write_config_word(adapter->pdev, A_PCICFG_VPD_ADDR, (u16)addr);
335         do {
336                 udelay(50);
337                 pci_read_config_word(adapter->pdev, A_PCICFG_VPD_ADDR, &val);
338         } while (!(val & F_VPD_OP_FLAG) && --i);
339
340         if (!(val & F_VPD_OP_FLAG)) {
341                 CH_ERR("%s: reading EEPROM address 0x%x failed\n",
342                        adapter->name, addr);
343                 return -EIO;
344         }
345         pci_read_config_dword(adapter->pdev, A_PCICFG_VPD_DATA, data);
346         *data = le32_to_cpu(*data);
347         return 0;
348 }
349
350 static int t1_eeprom_vpd_get(adapter_t *adapter, struct chelsio_vpd_t *vpd)
351 {
352         int addr, ret = 0;
353
354         for (addr = 0; !ret && addr < sizeof(*vpd); addr += sizeof(u32))
355                 ret = t1_seeprom_read(adapter, addr,
356                                       (u32 *)((u8 *)vpd + addr));
357
358         return ret;
359 }
360
361 /*
362  * Read a port's MAC address from the VPD ROM.
363  */
364 static int vpd_macaddress_get(adapter_t *adapter, int index, u8 mac_addr[])
365 {
366         struct chelsio_vpd_t vpd;
367
368         if (t1_eeprom_vpd_get(adapter, &vpd))
369                 return 1;
370         memcpy(mac_addr, vpd.mac_base_address, 5);
371         mac_addr[5] = vpd.mac_base_address[5] + index;
372         return 0;
373 }
374
375 /*
376  * Set up the MAC/PHY according to the requested link settings.
377  *
378  * If the PHY can auto-negotiate first decide what to advertise, then
379  * enable/disable auto-negotiation as desired and reset.
380  *
381  * If the PHY does not auto-negotiate we just reset it.
382  *
383  * If auto-negotiation is off set the MAC to the proper speed/duplex/FC,
384  * otherwise do it later based on the outcome of auto-negotiation.
385  */
386 int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc)
387 {
388         unsigned int fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
389
390         if (lc->supported & SUPPORTED_Autoneg) {
391                 lc->advertising &= ~(ADVERTISED_ASYM_PAUSE | ADVERTISED_PAUSE);
392                 if (fc) {
393                         lc->advertising |= ADVERTISED_ASYM_PAUSE;
394                         if (fc == (PAUSE_RX | PAUSE_TX))
395                                 lc->advertising |= ADVERTISED_PAUSE;
396                 }
397                 phy->ops->advertise(phy, lc->advertising);
398
399                 if (lc->autoneg == AUTONEG_DISABLE) {
400                         lc->speed = lc->requested_speed;
401                         lc->duplex = lc->requested_duplex;
402                         lc->fc = (unsigned char)fc;
403                         mac->ops->set_speed_duplex_fc(mac, lc->speed,
404                                                       lc->duplex, fc);
405                         /* Also disables autoneg */
406                         phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex);
407                         phy->ops->reset(phy, 0);
408                 } else
409                         phy->ops->autoneg_enable(phy); /* also resets PHY */
410         } else {
411                 mac->ops->set_speed_duplex_fc(mac, -1, -1, fc);
412                 lc->fc = (unsigned char)fc;
413                 phy->ops->reset(phy, 0);
414         }
415         return 0;
416 }
417
418 /*
419  * External interrupt handler for boards using elmer0.
420  */
421 int elmer0_ext_intr_handler(adapter_t *adapter)
422 {
423         struct cphy *phy;
424         int phy_cause;
425         u32 cause;
426
427         t1_tpi_read(adapter, A_ELMER0_INT_CAUSE, &cause);
428
429         switch (board_info(adapter)->board) {
430         case CHBT_BOARD_N210:
431         case CHBT_BOARD_N110:
432                 if (cause & ELMER0_GP_BIT6) { /* Marvell 88x2010 interrupt */
433                         phy = adapter->port[0].phy;
434                         phy_cause = phy->ops->interrupt_handler(phy);
435                         if (phy_cause & cphy_cause_link_change)
436                                 link_changed(adapter, 0);
437                 }
438                 break;
439         }
440         t1_tpi_write(adapter, A_ELMER0_INT_CAUSE, cause);
441         return 0;
442 }
443
444 /* Enables all interrupts. */
445 void t1_interrupts_enable(adapter_t *adapter)
446 {
447         unsigned int i;
448         u32 pl_intr;
449
450         adapter->slow_intr_mask = F_PL_INTR_SGE_ERR;
451
452         t1_sge_intr_enable(adapter->sge);
453         if (adapter->espi) {
454                 adapter->slow_intr_mask |= F_PL_INTR_ESPI;
455                 t1_espi_intr_enable(adapter->espi);
456         }
457
458         /* Enable MAC/PHY interrupts for each port. */
459         for_each_port(adapter, i) {
460                 adapter->port[i].mac->ops->interrupt_enable(adapter->port[i].mac);
461                 adapter->port[i].phy->ops->interrupt_enable(adapter->port[i].phy);
462         }
463
464         /* Enable PCIX & external chip interrupts on ASIC boards. */
465         pl_intr = readl(adapter->regs + A_PL_ENABLE);
466
467         /* PCI-X interrupts */
468         pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE,
469                                0xffffffff);
470
471         adapter->slow_intr_mask |= F_PL_INTR_EXT | F_PL_INTR_PCIX;
472         pl_intr |= F_PL_INTR_EXT | F_PL_INTR_PCIX;
473         writel(pl_intr, adapter->regs + A_PL_ENABLE);
474 }
475
476 /* Disables all interrupts. */
477 void t1_interrupts_disable(adapter_t* adapter)
478 {
479         unsigned int i;
480
481         t1_sge_intr_disable(adapter->sge);
482         if (adapter->espi)
483                 t1_espi_intr_disable(adapter->espi);
484
485         /* Disable MAC/PHY interrupts for each port. */
486         for_each_port(adapter, i) {
487                 adapter->port[i].mac->ops->interrupt_disable(adapter->port[i].mac);
488                 adapter->port[i].phy->ops->interrupt_disable(adapter->port[i].phy);
489         }
490
491         /* Disable PCIX & external chip interrupts. */
492         writel(0, adapter->regs + A_PL_ENABLE);
493
494         /* PCI-X interrupts */
495         pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE, 0);
496
497         adapter->slow_intr_mask = 0;
498 }
499
500 /* Clears all interrupts */
501 void t1_interrupts_clear(adapter_t* adapter)
502 {
503         unsigned int i;
504         u32 pl_intr;
505
506
507         t1_sge_intr_clear(adapter->sge);
508         if (adapter->espi)
509                 t1_espi_intr_clear(adapter->espi);
510
511         /* Clear MAC/PHY interrupts for each port. */
512         for_each_port(adapter, i) {
513                 adapter->port[i].mac->ops->interrupt_clear(adapter->port[i].mac);
514                 adapter->port[i].phy->ops->interrupt_clear(adapter->port[i].phy);
515         }
516
517         /* Enable interrupts for external devices. */
518         pl_intr = readl(adapter->regs + A_PL_CAUSE);
519
520         writel(pl_intr | F_PL_INTR_EXT | F_PL_INTR_PCIX,
521                adapter->regs + A_PL_CAUSE);
522
523         /* PCI-X interrupts */
524         pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, 0xffffffff);
525 }
526
527 /*
528  * Slow path interrupt handler for ASICs.
529  */
530 int t1_slow_intr_handler(adapter_t *adapter)
531 {
532         u32 cause = readl(adapter->regs + A_PL_CAUSE);
533
534         cause &= adapter->slow_intr_mask;
535         if (!cause)
536                 return 0;
537         if (cause & F_PL_INTR_SGE_ERR)
538                 t1_sge_intr_error_handler(adapter->sge);
539         if (cause & F_PL_INTR_ESPI)
540                 t1_espi_intr_handler(adapter->espi);
541         if (cause & F_PL_INTR_PCIX)
542                 t1_pci_intr_handler(adapter);
543         if (cause & F_PL_INTR_EXT)
544                 t1_elmer0_ext_intr(adapter);
545
546         /* Clear the interrupts just processed. */
547         writel(cause, adapter->regs + A_PL_CAUSE);
548         (void)readl(adapter->regs + A_PL_CAUSE); /* flush writes */
549         return 1;
550 }
551
552 /* Pause deadlock avoidance parameters */
553 #define DROP_MSEC 16
554 #define DROP_PKTS_CNT  1
555
556 static void set_csum_offload(adapter_t *adapter, u32 csum_bit, int enable)
557 {
558         u32 val = readl(adapter->regs + A_TP_GLOBAL_CONFIG);
559
560         if (enable)
561                 val |= csum_bit;
562         else
563                 val &= ~csum_bit;
564         writel(val, adapter->regs + A_TP_GLOBAL_CONFIG);
565 }
566
567 void t1_tp_set_ip_checksum_offload(adapter_t *adapter, int enable)
568 {
569         set_csum_offload(adapter, F_IP_CSUM, enable);
570 }
571
572 void t1_tp_set_udp_checksum_offload(adapter_t *adapter, int enable)
573 {
574         set_csum_offload(adapter, F_UDP_CSUM, enable);
575 }
576
577 void t1_tp_set_tcp_checksum_offload(adapter_t *adapter, int enable)
578 {
579         set_csum_offload(adapter, F_TCP_CSUM, enable);
580 }
581
582 static void t1_tp_reset(adapter_t *adapter, unsigned int tp_clk)
583 {
584         u32 val;
585
586         val = F_TP_IN_CSPI_CPL | F_TP_IN_CSPI_CHECK_IP_CSUM |
587               F_TP_IN_CSPI_CHECK_TCP_CSUM | F_TP_IN_ESPI_ETHERNET;
588         val |= F_TP_IN_ESPI_CHECK_IP_CSUM |
589                F_TP_IN_ESPI_CHECK_TCP_CSUM;
590         writel(val, adapter->regs + A_TP_IN_CONFIG);
591         writel(F_TP_OUT_CSPI_CPL |
592                F_TP_OUT_ESPI_ETHERNET |
593                F_TP_OUT_ESPI_GENERATE_IP_CSUM |
594                F_TP_OUT_ESPI_GENERATE_TCP_CSUM,
595                adapter->regs + A_TP_OUT_CONFIG);
596
597         val = readl(adapter->regs + A_TP_GLOBAL_CONFIG);
598         val &= ~(F_IP_CSUM | F_UDP_CSUM | F_TCP_CSUM);
599         writel(val, adapter->regs + A_TP_GLOBAL_CONFIG);
600
601         /*
602          * Enable pause frame deadlock prevention.
603          */
604         if (is_T2(adapter)) {
605                 u32 drop_ticks = DROP_MSEC * (tp_clk / 1000);
606
607                 writel(F_ENABLE_TX_DROP | F_ENABLE_TX_ERROR |
608                        V_DROP_TICKS_CNT(drop_ticks) |
609                        V_NUM_PKTS_DROPPED(DROP_PKTS_CNT),
610                        adapter->regs + A_TP_TX_DROP_CONFIG);
611         }
612
613         writel(F_TP_RESET, adapter->regs + A_TP_RESET);
614 }
615
616 int __devinit t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
617                                struct adapter_params *p)
618 {
619         p->chip_version = bi->chip_term;
620         if (p->chip_version == CHBT_TERM_T1 ||
621             p->chip_version == CHBT_TERM_T2) {
622                 u32 val = readl(adapter->regs + A_TP_PC_CONFIG);
623
624                 val = G_TP_PC_REV(val);
625                 if (val == 2)
626                         p->chip_revision = TERM_T1B;
627                 else if (val == 3)
628                         p->chip_revision = TERM_T2;
629                 else
630                         return -1;
631         } else
632                 return -1;
633         return 0;
634 }
635
636 /*
637  * Enable board components other than the Chelsio chip, such as external MAC
638  * and PHY.
639  */
640 static int board_init(adapter_t *adapter, const struct board_info *bi)
641 {
642         switch (bi->board) {
643         case CHBT_BOARD_N110:
644         case CHBT_BOARD_N210:
645                 writel(V_TPIPAR(0xf), adapter->regs + A_TPI_PAR);
646                 t1_tpi_write(adapter, A_ELMER0_GPO, 0x800);
647                 break;
648         }
649         return 0;
650 }
651
652 /*
653  * Initialize and configure the Terminator HW modules.  Note that external
654  * MAC and PHYs are initialized separately.
655  */
656 int t1_init_hw_modules(adapter_t *adapter)
657 {
658         int err = -EIO;
659         const struct board_info *bi = board_info(adapter);
660
661         if (!bi->clock_mc4) {
662                 u32 val = readl(adapter->regs + A_MC4_CFG);
663
664                 writel(val | F_READY | F_MC4_SLOW, adapter->regs + A_MC4_CFG);
665                 writel(F_M_BUS_ENABLE | F_TCAM_RESET,
666                        adapter->regs + A_MC5_CONFIG);
667         }
668
669         if (adapter->espi && t1_espi_init(adapter->espi, bi->chip_mac,
670                                           bi->espi_nports))
671                 goto out_err;
672
673         t1_tp_reset(adapter, bi->clock_core);
674
675         err = t1_sge_configure(adapter->sge, &adapter->params.sge);
676         if (err)
677                 goto out_err;
678
679         err = 0;
680  out_err:
681         return err;
682 }
683
684 /*
685  * Determine a card's PCI mode.
686  */
687 static void __devinit get_pci_mode(adapter_t *adapter, struct chelsio_pci_params *p)
688 {
689         static const unsigned short speed_map[] = { 33, 66, 100, 133 };
690         u32 pci_mode;
691
692         pci_read_config_dword(adapter->pdev, A_PCICFG_MODE, &pci_mode);
693         p->speed = speed_map[G_PCI_MODE_CLK(pci_mode)];
694         p->width = (pci_mode & F_PCI_MODE_64BIT) ? 64 : 32;
695         p->is_pcix = (pci_mode & F_PCI_MODE_PCIX) != 0;
696 }
697
698 /*
699  * Release the structures holding the SW per-Terminator-HW-module state.
700  */
701 void t1_free_sw_modules(adapter_t *adapter)
702 {
703         unsigned int i;
704
705         for_each_port(adapter, i) {
706                 struct cmac *mac = adapter->port[i].mac;
707                 struct cphy *phy = adapter->port[i].phy;
708
709                 if (mac)
710                         mac->ops->destroy(mac);
711                 if (phy)
712                         phy->ops->destroy(phy);
713         }
714
715         if (adapter->sge)
716                 t1_sge_destroy(adapter->sge);
717         if (adapter->espi)
718                 t1_espi_destroy(adapter->espi);
719 }
720
721 static void __devinit init_link_config(struct link_config *lc,
722                                        const struct board_info *bi)
723 {
724         lc->supported = bi->caps;
725         lc->requested_speed = lc->speed = SPEED_INVALID;
726         lc->requested_duplex = lc->duplex = DUPLEX_INVALID;
727         lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX;
728         if (lc->supported & SUPPORTED_Autoneg) {
729                 lc->advertising = lc->supported;
730                 lc->autoneg = AUTONEG_ENABLE;
731                 lc->requested_fc |= PAUSE_AUTONEG;
732         } else {
733                 lc->advertising = 0;
734                 lc->autoneg = AUTONEG_DISABLE;
735         }
736 }
737
738
739 /*
740  * Allocate and initialize the data structures that hold the SW state of
741  * the Terminator HW modules.
742  */
743 int __devinit t1_init_sw_modules(adapter_t *adapter,
744                                  const struct board_info *bi)
745 {
746         unsigned int i;
747
748         adapter->params.brd_info = bi;
749         adapter->params.nports = bi->port_number;
750         adapter->params.stats_update_period = bi->gmac->stats_update_period;
751
752         adapter->sge = t1_sge_create(adapter, &adapter->params.sge);
753         if (!adapter->sge) {
754                 CH_ERR("%s: SGE initialization failed\n",
755                        adapter->name);
756                 goto error;
757         }
758
759         if (bi->espi_nports && !(adapter->espi = t1_espi_create(adapter))) {
760                 CH_ERR("%s: ESPI initialization failed\n",
761                        adapter->name);
762                 goto error;
763         }
764
765         board_init(adapter, bi);
766         bi->mdio_ops->init(adapter, bi);
767         if (bi->gphy->reset)
768                 bi->gphy->reset(adapter);
769         if (bi->gmac->reset)
770                 bi->gmac->reset(adapter);
771
772         for_each_port(adapter, i) {
773                 u8 hw_addr[6];
774                 struct cmac *mac;
775                 int phy_addr = bi->mdio_phybaseaddr + i;
776
777                 adapter->port[i].phy = bi->gphy->create(adapter, phy_addr,
778                                                         bi->mdio_ops);
779                 if (!adapter->port[i].phy) {
780                         CH_ERR("%s: PHY %d initialization failed\n",
781                                adapter->name, i);
782                         goto error;
783                 }
784
785                 adapter->port[i].mac = mac = bi->gmac->create(adapter, i);
786                 if (!mac) {
787                         CH_ERR("%s: MAC %d initialization failed\n",
788                                adapter->name, i);
789                         goto error;
790                 }
791
792                 /*
793                  * Get the port's MAC addresses either from the EEPROM if one
794                  * exists or the one hardcoded in the MAC.
795                  */
796                 if (vpd_macaddress_get(adapter, i, hw_addr)) {
797                         CH_ERR("%s: could not read MAC address from VPD ROM\n",
798                                adapter->port[i].dev->name);
799                         goto error;
800                 }
801                 memcpy(adapter->port[i].dev->dev_addr, hw_addr, ETH_ALEN);
802                 init_link_config(&adapter->port[i].link_config, bi);
803         }
804
805         get_pci_mode(adapter, &adapter->params.pci);
806         t1_interrupts_clear(adapter);
807         return 0;
808
809  error:
810         t1_free_sw_modules(adapter);
811         return -1;
812 }