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