diff options
Diffstat (limited to 'drivers/net/chelsio/subr.c')
-rw-r--r-- | drivers/net/chelsio/subr.c | 265 |
1 files changed, 165 insertions, 100 deletions
diff --git a/drivers/net/chelsio/subr.c b/drivers/net/chelsio/subr.c index e4473ec43d26..d41d15a71e4d 100644 --- a/drivers/net/chelsio/subr.c +++ b/drivers/net/chelsio/subr.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include "gmac.h" | 43 | #include "gmac.h" |
44 | #include "cphy.h" | 44 | #include "cphy.h" |
45 | #include "sge.h" | 45 | #include "sge.h" |
46 | #include "tp.h" | ||
46 | #include "espi.h" | 47 | #include "espi.h" |
47 | 48 | ||
48 | /** | 49 | /** |
@@ -59,7 +60,7 @@ | |||
59 | * otherwise. | 60 | * otherwise. |
60 | */ | 61 | */ |
61 | static int t1_wait_op_done(adapter_t *adapter, int reg, u32 mask, int polarity, | 62 | static int t1_wait_op_done(adapter_t *adapter, int reg, u32 mask, int polarity, |
62 | int attempts, int delay) | 63 | int attempts, int delay) |
63 | { | 64 | { |
64 | while (1) { | 65 | while (1) { |
65 | u32 val = readl(adapter->regs + reg) & mask; | 66 | u32 val = readl(adapter->regs + reg) & mask; |
@@ -78,7 +79,7 @@ static int t1_wait_op_done(adapter_t *adapter, int reg, u32 mask, int polarity, | |||
78 | /* | 79 | /* |
79 | * Write a register over the TPI interface (unlocked and locked versions). | 80 | * Write a register over the TPI interface (unlocked and locked versions). |
80 | */ | 81 | */ |
81 | static int __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value) | 82 | int __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value) |
82 | { | 83 | { |
83 | int tpi_busy; | 84 | int tpi_busy; |
84 | 85 | ||
@@ -98,16 +99,16 @@ int t1_tpi_write(adapter_t *adapter, u32 addr, u32 value) | |||
98 | { | 99 | { |
99 | int ret; | 100 | int ret; |
100 | 101 | ||
101 | spin_lock(&(adapter)->tpi_lock); | 102 | spin_lock(&adapter->tpi_lock); |
102 | ret = __t1_tpi_write(adapter, addr, value); | 103 | ret = __t1_tpi_write(adapter, addr, value); |
103 | spin_unlock(&(adapter)->tpi_lock); | 104 | spin_unlock(&adapter->tpi_lock); |
104 | return ret; | 105 | return ret; |
105 | } | 106 | } |
106 | 107 | ||
107 | /* | 108 | /* |
108 | * Read a register over the TPI interface (unlocked and locked versions). | 109 | * Read a register over the TPI interface (unlocked and locked versions). |
109 | */ | 110 | */ |
110 | static int __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp) | 111 | int __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp) |
111 | { | 112 | { |
112 | int tpi_busy; | 113 | int tpi_busy; |
113 | 114 | ||
@@ -128,18 +129,26 @@ int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp) | |||
128 | { | 129 | { |
129 | int ret; | 130 | int ret; |
130 | 131 | ||
131 | spin_lock(&(adapter)->tpi_lock); | 132 | spin_lock(&adapter->tpi_lock); |
132 | ret = __t1_tpi_read(adapter, addr, valp); | 133 | ret = __t1_tpi_read(adapter, addr, valp); |
133 | spin_unlock(&(adapter)->tpi_lock); | 134 | spin_unlock(&adapter->tpi_lock); |
134 | return ret; | 135 | return ret; |
135 | } | 136 | } |
136 | 137 | ||
137 | /* | 138 | /* |
139 | * Set a TPI parameter. | ||
140 | */ | ||
141 | static void t1_tpi_par(adapter_t *adapter, u32 value) | ||
142 | { | ||
143 | writel(V_TPIPAR(value), adapter->regs + A_TPI_PAR); | ||
144 | } | ||
145 | |||
146 | /* | ||
138 | * Called when a port's link settings change to propagate the new values to the | 147 | * 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 | 148 | * associated PHY and MAC. After performing the common tasks it invokes an |
140 | * OS-specific handler. | 149 | * OS-specific handler. |
141 | */ | 150 | */ |
142 | /* static */ void link_changed(adapter_t *adapter, int port_id) | 151 | void t1_link_changed(adapter_t *adapter, int port_id) |
143 | { | 152 | { |
144 | int link_ok, speed, duplex, fc; | 153 | int link_ok, speed, duplex, fc; |
145 | struct cphy *phy = adapter->port[port_id].phy; | 154 | struct cphy *phy = adapter->port[port_id].phy; |
@@ -159,7 +168,7 @@ int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp) | |||
159 | mac->ops->set_speed_duplex_fc(mac, speed, duplex, fc); | 168 | mac->ops->set_speed_duplex_fc(mac, speed, duplex, fc); |
160 | lc->fc = (unsigned char)fc; | 169 | lc->fc = (unsigned char)fc; |
161 | } | 170 | } |
162 | t1_link_changed(adapter, port_id, link_ok, speed, duplex, fc); | 171 | t1_link_negotiated(adapter, port_id, link_ok, speed, duplex, fc); |
163 | } | 172 | } |
164 | 173 | ||
165 | static int t1_pci_intr_handler(adapter_t *adapter) | 174 | static int t1_pci_intr_handler(adapter_t *adapter) |
@@ -217,7 +226,7 @@ static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr, | |||
217 | { | 226 | { |
218 | u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr); | 227 | u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr); |
219 | 228 | ||
220 | spin_lock(&(adapter)->tpi_lock); | 229 | spin_lock(&adapter->tpi_lock); |
221 | 230 | ||
222 | /* Write the address we want. */ | 231 | /* Write the address we want. */ |
223 | __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr); | 232 | __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr); |
@@ -227,12 +236,13 @@ static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr, | |||
227 | mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP); | 236 | mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP); |
228 | 237 | ||
229 | /* Write the operation we want. */ | 238 | /* Write the operation we want. */ |
230 | __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_READ); | 239 | __t1_tpi_write(adapter, |
240 | A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_READ); | ||
231 | mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP); | 241 | mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP); |
232 | 242 | ||
233 | /* Read the data. */ | 243 | /* Read the data. */ |
234 | __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp); | 244 | __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp); |
235 | spin_unlock(&(adapter)->tpi_lock); | 245 | spin_unlock(&adapter->tpi_lock); |
236 | return 0; | 246 | return 0; |
237 | } | 247 | } |
238 | 248 | ||
@@ -241,7 +251,7 @@ static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr, | |||
241 | { | 251 | { |
242 | u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr); | 252 | u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr); |
243 | 253 | ||
244 | spin_lock(&(adapter)->tpi_lock); | 254 | spin_lock(&adapter->tpi_lock); |
245 | 255 | ||
246 | /* Write the address we want. */ | 256 | /* Write the address we want. */ |
247 | __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr); | 257 | __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr); |
@@ -254,7 +264,7 @@ static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr, | |||
254 | __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val); | 264 | __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val); |
255 | __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_WRITE); | 265 | __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_WRITE); |
256 | mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP); | 266 | mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP); |
257 | spin_unlock(&(adapter)->tpi_lock); | 267 | spin_unlock(&adapter->tpi_lock); |
258 | return 0; | 268 | return 0; |
259 | } | 269 | } |
260 | 270 | ||
@@ -265,12 +275,25 @@ static struct mdio_ops mi1_mdio_ext_ops = { | |||
265 | }; | 275 | }; |
266 | 276 | ||
267 | enum { | 277 | enum { |
278 | CH_BRD_T110_1CU, | ||
268 | CH_BRD_N110_1F, | 279 | CH_BRD_N110_1F, |
269 | CH_BRD_N210_1F, | 280 | CH_BRD_N210_1F, |
281 | CH_BRD_T210_1F, | ||
282 | CH_BRD_T210_1CU, | ||
283 | CH_BRD_N204_4CU, | ||
270 | }; | 284 | }; |
271 | 285 | ||
272 | static struct board_info t1_board[] = { | 286 | static struct board_info t1_board[] = { |
273 | 287 | ||
288 | { CHBT_BOARD_CHT110, 1/*ports#*/, | ||
289 | SUPPORTED_10000baseT_Full /*caps*/, CHBT_TERM_T1, | ||
290 | CHBT_MAC_PM3393, CHBT_PHY_MY3126, | ||
291 | 125000000/*clk-core*/, 150000000/*clk-mc3*/, 125000000/*clk-mc4*/, | ||
292 | 1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 1/*mdien*/, | ||
293 | 1/*mdiinv*/, 1/*mdc*/, 1/*phybaseaddr*/, &t1_pm3393_ops, | ||
294 | &t1_my3126_ops, &mi1_mdio_ext_ops, | ||
295 | "Chelsio T110 1x10GBase-CX4 TOE" }, | ||
296 | |||
274 | { CHBT_BOARD_N110, 1/*ports#*/, | 297 | { CHBT_BOARD_N110, 1/*ports#*/, |
275 | SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE /*caps*/, CHBT_TERM_T1, | 298 | SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE /*caps*/, CHBT_TERM_T1, |
276 | CHBT_MAC_PM3393, CHBT_PHY_88X2010, | 299 | CHBT_MAC_PM3393, CHBT_PHY_88X2010, |
@@ -289,12 +312,36 @@ static struct board_info t1_board[] = { | |||
289 | &t1_mv88x201x_ops, &mi1_mdio_ext_ops, | 312 | &t1_mv88x201x_ops, &mi1_mdio_ext_ops, |
290 | "Chelsio N210 1x10GBaseX NIC" }, | 313 | "Chelsio N210 1x10GBaseX NIC" }, |
291 | 314 | ||
315 | { CHBT_BOARD_CHT210, 1/*ports#*/, | ||
316 | SUPPORTED_10000baseT_Full /*caps*/, CHBT_TERM_T2, | ||
317 | CHBT_MAC_PM3393, CHBT_PHY_88X2010, | ||
318 | 125000000/*clk-core*/, 133000000/*clk-mc3*/, 125000000/*clk-mc4*/, | ||
319 | 1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 0/*mdien*/, | ||
320 | 0/*mdiinv*/, 1/*mdc*/, 0/*phybaseaddr*/, &t1_pm3393_ops, | ||
321 | &t1_mv88x201x_ops, &mi1_mdio_ext_ops, | ||
322 | "Chelsio T210 1x10GBaseX TOE" }, | ||
323 | |||
324 | { CHBT_BOARD_CHT210, 1/*ports#*/, | ||
325 | SUPPORTED_10000baseT_Full /*caps*/, CHBT_TERM_T2, | ||
326 | CHBT_MAC_PM3393, CHBT_PHY_MY3126, | ||
327 | 125000000/*clk-core*/, 133000000/*clk-mc3*/, 125000000/*clk-mc4*/, | ||
328 | 1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 1/*mdien*/, | ||
329 | 1/*mdiinv*/, 1/*mdc*/, 1/*phybaseaddr*/, &t1_pm3393_ops, | ||
330 | &t1_my3126_ops, &mi1_mdio_ext_ops, | ||
331 | "Chelsio T210 1x10GBase-CX4 TOE" }, | ||
332 | |||
333 | |||
292 | }; | 334 | }; |
293 | 335 | ||
294 | struct pci_device_id t1_pci_tbl[] = { | 336 | struct pci_device_id t1_pci_tbl[] = { |
337 | CH_DEVICE(8, 0, CH_BRD_T110_1CU), | ||
338 | CH_DEVICE(8, 1, CH_BRD_T110_1CU), | ||
295 | CH_DEVICE(7, 0, CH_BRD_N110_1F), | 339 | CH_DEVICE(7, 0, CH_BRD_N110_1F), |
296 | CH_DEVICE(10, 1, CH_BRD_N210_1F), | 340 | CH_DEVICE(10, 1, CH_BRD_N210_1F), |
297 | { 0, } | 341 | CH_DEVICE(11, 1, CH_BRD_T210_1F), |
342 | CH_DEVICE(14, 1, CH_BRD_T210_1CU), | ||
343 | CH_DEVICE(16, 1, CH_BRD_N204_4CU), | ||
344 | { 0 } | ||
298 | }; | 345 | }; |
299 | 346 | ||
300 | MODULE_DEVICE_TABLE(pci, t1_pci_tbl); | 347 | MODULE_DEVICE_TABLE(pci, t1_pci_tbl); |
@@ -390,9 +437,14 @@ int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc) | |||
390 | if (lc->supported & SUPPORTED_Autoneg) { | 437 | if (lc->supported & SUPPORTED_Autoneg) { |
391 | lc->advertising &= ~(ADVERTISED_ASYM_PAUSE | ADVERTISED_PAUSE); | 438 | lc->advertising &= ~(ADVERTISED_ASYM_PAUSE | ADVERTISED_PAUSE); |
392 | if (fc) { | 439 | if (fc) { |
393 | lc->advertising |= ADVERTISED_ASYM_PAUSE; | 440 | if (fc == ((PAUSE_RX | PAUSE_TX) & |
394 | if (fc == (PAUSE_RX | PAUSE_TX)) | 441 | (mac->adapter->params.nports < 2))) |
395 | lc->advertising |= ADVERTISED_PAUSE; | 442 | lc->advertising |= ADVERTISED_PAUSE; |
443 | else { | ||
444 | lc->advertising |= ADVERTISED_ASYM_PAUSE; | ||
445 | if (fc == PAUSE_RX) | ||
446 | lc->advertising |= ADVERTISED_PAUSE; | ||
447 | } | ||
396 | } | 448 | } |
397 | phy->ops->advertise(phy, lc->advertising); | 449 | phy->ops->advertise(phy, lc->advertising); |
398 | 450 | ||
@@ -403,11 +455,15 @@ int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc) | |||
403 | mac->ops->set_speed_duplex_fc(mac, lc->speed, | 455 | mac->ops->set_speed_duplex_fc(mac, lc->speed, |
404 | lc->duplex, fc); | 456 | lc->duplex, fc); |
405 | /* Also disables autoneg */ | 457 | /* Also disables autoneg */ |
458 | phy->state = PHY_AUTONEG_RDY; | ||
406 | phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex); | 459 | phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex); |
407 | phy->ops->reset(phy, 0); | 460 | phy->ops->reset(phy, 0); |
408 | } else | 461 | } else { |
462 | phy->state = PHY_AUTONEG_EN; | ||
409 | phy->ops->autoneg_enable(phy); /* also resets PHY */ | 463 | phy->ops->autoneg_enable(phy); /* also resets PHY */ |
464 | } | ||
410 | } else { | 465 | } else { |
466 | phy->state = PHY_AUTONEG_RDY; | ||
411 | mac->ops->set_speed_duplex_fc(mac, -1, -1, fc); | 467 | mac->ops->set_speed_duplex_fc(mac, -1, -1, fc); |
412 | lc->fc = (unsigned char)fc; | 468 | lc->fc = (unsigned char)fc; |
413 | phy->ops->reset(phy, 0); | 469 | phy->ops->reset(phy, 0); |
@@ -418,7 +474,7 @@ int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc) | |||
418 | /* | 474 | /* |
419 | * External interrupt handler for boards using elmer0. | 475 | * External interrupt handler for boards using elmer0. |
420 | */ | 476 | */ |
421 | int elmer0_ext_intr_handler(adapter_t *adapter) | 477 | int t1_elmer0_ext_intr_handler(adapter_t *adapter) |
422 | { | 478 | { |
423 | struct cphy *phy; | 479 | struct cphy *phy; |
424 | int phy_cause; | 480 | int phy_cause; |
@@ -427,14 +483,33 @@ int elmer0_ext_intr_handler(adapter_t *adapter) | |||
427 | t1_tpi_read(adapter, A_ELMER0_INT_CAUSE, &cause); | 483 | t1_tpi_read(adapter, A_ELMER0_INT_CAUSE, &cause); |
428 | 484 | ||
429 | switch (board_info(adapter)->board) { | 485 | switch (board_info(adapter)->board) { |
486 | case CHBT_BOARD_CHT210: | ||
430 | case CHBT_BOARD_N210: | 487 | case CHBT_BOARD_N210: |
431 | case CHBT_BOARD_N110: | 488 | case CHBT_BOARD_N110: |
432 | if (cause & ELMER0_GP_BIT6) { /* Marvell 88x2010 interrupt */ | 489 | if (cause & ELMER0_GP_BIT6) { /* Marvell 88x2010 interrupt */ |
433 | phy = adapter->port[0].phy; | 490 | phy = adapter->port[0].phy; |
434 | phy_cause = phy->ops->interrupt_handler(phy); | 491 | phy_cause = phy->ops->interrupt_handler(phy); |
435 | if (phy_cause & cphy_cause_link_change) | 492 | if (phy_cause & cphy_cause_link_change) |
436 | link_changed(adapter, 0); | 493 | t1_link_changed(adapter, 0); |
494 | } | ||
495 | break; | ||
496 | case CHBT_BOARD_8000: | ||
497 | case CHBT_BOARD_CHT110: | ||
498 | CH_DBG(adapter, INTR, "External interrupt cause 0x%x\n", | ||
499 | cause); | ||
500 | if (cause & ELMER0_GP_BIT1) { /* PMC3393 INTB */ | ||
501 | struct cmac *mac = adapter->port[0].mac; | ||
502 | |||
503 | mac->ops->interrupt_handler(mac); | ||
437 | } | 504 | } |
505 | if (cause & ELMER0_GP_BIT5) { /* XPAK MOD_DETECT */ | ||
506 | u32 mod_detect; | ||
507 | |||
508 | t1_tpi_read(adapter, | ||
509 | A_ELMER0_GPI_STAT, &mod_detect); | ||
510 | CH_MSG(adapter, INFO, LINK, "XPAK %s\n", | ||
511 | mod_detect ? "removed" : "inserted"); | ||
512 | } | ||
438 | break; | 513 | break; |
439 | } | 514 | } |
440 | t1_tpi_write(adapter, A_ELMER0_INT_CAUSE, cause); | 515 | t1_tpi_write(adapter, A_ELMER0_INT_CAUSE, cause); |
@@ -445,11 +520,11 @@ int elmer0_ext_intr_handler(adapter_t *adapter) | |||
445 | void t1_interrupts_enable(adapter_t *adapter) | 520 | void t1_interrupts_enable(adapter_t *adapter) |
446 | { | 521 | { |
447 | unsigned int i; | 522 | unsigned int i; |
448 | u32 pl_intr; | ||
449 | 523 | ||
450 | adapter->slow_intr_mask = F_PL_INTR_SGE_ERR; | 524 | adapter->slow_intr_mask = F_PL_INTR_SGE_ERR | F_PL_INTR_TP; |
451 | 525 | ||
452 | t1_sge_intr_enable(adapter->sge); | 526 | t1_sge_intr_enable(adapter->sge); |
527 | t1_tp_intr_enable(adapter->tp); | ||
453 | if (adapter->espi) { | 528 | if (adapter->espi) { |
454 | adapter->slow_intr_mask |= F_PL_INTR_ESPI; | 529 | adapter->slow_intr_mask |= F_PL_INTR_ESPI; |
455 | t1_espi_intr_enable(adapter->espi); | 530 | t1_espi_intr_enable(adapter->espi); |
@@ -462,15 +537,17 @@ void t1_interrupts_enable(adapter_t *adapter) | |||
462 | } | 537 | } |
463 | 538 | ||
464 | /* Enable PCIX & external chip interrupts on ASIC boards. */ | 539 | /* Enable PCIX & external chip interrupts on ASIC boards. */ |
465 | pl_intr = readl(adapter->regs + A_PL_ENABLE); | 540 | if (t1_is_asic(adapter)) { |
541 | u32 pl_intr = readl(adapter->regs + A_PL_ENABLE); | ||
466 | 542 | ||
467 | /* PCI-X interrupts */ | 543 | /* PCI-X interrupts */ |
468 | pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE, | 544 | pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE, |
469 | 0xffffffff); | 545 | 0xffffffff); |
470 | 546 | ||
471 | adapter->slow_intr_mask |= F_PL_INTR_EXT | F_PL_INTR_PCIX; | 547 | adapter->slow_intr_mask |= F_PL_INTR_EXT | F_PL_INTR_PCIX; |
472 | pl_intr |= F_PL_INTR_EXT | F_PL_INTR_PCIX; | 548 | pl_intr |= F_PL_INTR_EXT | F_PL_INTR_PCIX; |
473 | writel(pl_intr, adapter->regs + A_PL_ENABLE); | 549 | writel(pl_intr, adapter->regs + A_PL_ENABLE); |
550 | } | ||
474 | } | 551 | } |
475 | 552 | ||
476 | /* Disables all interrupts. */ | 553 | /* Disables all interrupts. */ |
@@ -479,6 +556,7 @@ void t1_interrupts_disable(adapter_t* adapter) | |||
479 | unsigned int i; | 556 | unsigned int i; |
480 | 557 | ||
481 | t1_sge_intr_disable(adapter->sge); | 558 | t1_sge_intr_disable(adapter->sge); |
559 | t1_tp_intr_disable(adapter->tp); | ||
482 | if (adapter->espi) | 560 | if (adapter->espi) |
483 | t1_espi_intr_disable(adapter->espi); | 561 | t1_espi_intr_disable(adapter->espi); |
484 | 562 | ||
@@ -489,7 +567,8 @@ void t1_interrupts_disable(adapter_t* adapter) | |||
489 | } | 567 | } |
490 | 568 | ||
491 | /* Disable PCIX & external chip interrupts. */ | 569 | /* Disable PCIX & external chip interrupts. */ |
492 | writel(0, adapter->regs + A_PL_ENABLE); | 570 | if (t1_is_asic(adapter)) |
571 | writel(0, adapter->regs + A_PL_ENABLE); | ||
493 | 572 | ||
494 | /* PCI-X interrupts */ | 573 | /* PCI-X interrupts */ |
495 | pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE, 0); | 574 | pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE, 0); |
@@ -501,10 +580,9 @@ void t1_interrupts_disable(adapter_t* adapter) | |||
501 | void t1_interrupts_clear(adapter_t* adapter) | 580 | void t1_interrupts_clear(adapter_t* adapter) |
502 | { | 581 | { |
503 | unsigned int i; | 582 | unsigned int i; |
504 | u32 pl_intr; | ||
505 | |||
506 | 583 | ||
507 | t1_sge_intr_clear(adapter->sge); | 584 | t1_sge_intr_clear(adapter->sge); |
585 | t1_tp_intr_clear(adapter->tp); | ||
508 | if (adapter->espi) | 586 | if (adapter->espi) |
509 | t1_espi_intr_clear(adapter->espi); | 587 | t1_espi_intr_clear(adapter->espi); |
510 | 588 | ||
@@ -515,10 +593,12 @@ void t1_interrupts_clear(adapter_t* adapter) | |||
515 | } | 593 | } |
516 | 594 | ||
517 | /* Enable interrupts for external devices. */ | 595 | /* Enable interrupts for external devices. */ |
518 | pl_intr = readl(adapter->regs + A_PL_CAUSE); | 596 | if (t1_is_asic(adapter)) { |
597 | u32 pl_intr = readl(adapter->regs + A_PL_CAUSE); | ||
519 | 598 | ||
520 | writel(pl_intr | F_PL_INTR_EXT | F_PL_INTR_PCIX, | 599 | writel(pl_intr | F_PL_INTR_EXT | F_PL_INTR_PCIX, |
521 | adapter->regs + A_PL_CAUSE); | 600 | adapter->regs + A_PL_CAUSE); |
601 | } | ||
522 | 602 | ||
523 | /* PCI-X interrupts */ | 603 | /* PCI-X interrupts */ |
524 | pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, 0xffffffff); | 604 | pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, 0xffffffff); |
@@ -527,7 +607,7 @@ void t1_interrupts_clear(adapter_t* adapter) | |||
527 | /* | 607 | /* |
528 | * Slow path interrupt handler for ASICs. | 608 | * Slow path interrupt handler for ASICs. |
529 | */ | 609 | */ |
530 | int t1_slow_intr_handler(adapter_t *adapter) | 610 | static int asic_slow_intr(adapter_t *adapter) |
531 | { | 611 | { |
532 | u32 cause = readl(adapter->regs + A_PL_CAUSE); | 612 | u32 cause = readl(adapter->regs + A_PL_CAUSE); |
533 | 613 | ||
@@ -536,89 +616,50 @@ int t1_slow_intr_handler(adapter_t *adapter) | |||
536 | return 0; | 616 | return 0; |
537 | if (cause & F_PL_INTR_SGE_ERR) | 617 | if (cause & F_PL_INTR_SGE_ERR) |
538 | t1_sge_intr_error_handler(adapter->sge); | 618 | t1_sge_intr_error_handler(adapter->sge); |
619 | if (cause & F_PL_INTR_TP) | ||
620 | t1_tp_intr_handler(adapter->tp); | ||
539 | if (cause & F_PL_INTR_ESPI) | 621 | if (cause & F_PL_INTR_ESPI) |
540 | t1_espi_intr_handler(adapter->espi); | 622 | t1_espi_intr_handler(adapter->espi); |
541 | if (cause & F_PL_INTR_PCIX) | 623 | if (cause & F_PL_INTR_PCIX) |
542 | t1_pci_intr_handler(adapter); | 624 | t1_pci_intr_handler(adapter); |
543 | if (cause & F_PL_INTR_EXT) | 625 | if (cause & F_PL_INTR_EXT) |
544 | t1_elmer0_ext_intr(adapter); | 626 | t1_elmer0_ext_intr_handler(adapter); |
545 | 627 | ||
546 | /* Clear the interrupts just processed. */ | 628 | /* Clear the interrupts just processed. */ |
547 | writel(cause, adapter->regs + A_PL_CAUSE); | 629 | writel(cause, adapter->regs + A_PL_CAUSE); |
548 | (void)readl(adapter->regs + A_PL_CAUSE); /* flush writes */ | 630 | readl(adapter->regs + A_PL_CAUSE); /* flush writes */ |
549 | return 1; | 631 | return 1; |
550 | } | 632 | } |
551 | 633 | ||
552 | /* Pause deadlock avoidance parameters */ | 634 | int t1_slow_intr_handler(adapter_t *adapter) |
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 | { | 635 | { |
574 | set_csum_offload(adapter, F_UDP_CSUM, enable); | 636 | return asic_slow_intr(adapter); |
575 | } | 637 | } |
576 | 638 | ||
577 | void t1_tp_set_tcp_checksum_offload(adapter_t *adapter, int enable) | 639 | /* Power sequencing is a work-around for Intel's XPAKs. */ |
640 | static void power_sequence_xpak(adapter_t* adapter) | ||
578 | { | 641 | { |
579 | set_csum_offload(adapter, F_TCP_CSUM, enable); | 642 | u32 mod_detect; |
580 | } | 643 | u32 gpo; |
581 | 644 | ||
582 | static void t1_tp_reset(adapter_t *adapter, unsigned int tp_clk) | 645 | /* Check for XPAK */ |
583 | { | 646 | t1_tpi_read(adapter, A_ELMER0_GPI_STAT, &mod_detect); |
584 | u32 val; | 647 | if (!(ELMER0_GP_BIT5 & mod_detect)) { |
585 | 648 | /* XPAK is present */ | |
586 | val = F_TP_IN_CSPI_CPL | F_TP_IN_CSPI_CHECK_IP_CSUM | | 649 | t1_tpi_read(adapter, A_ELMER0_GPO, &gpo); |
587 | F_TP_IN_CSPI_CHECK_TCP_CSUM | F_TP_IN_ESPI_ETHERNET; | 650 | gpo |= ELMER0_GP_BIT18; |
588 | val |= F_TP_IN_ESPI_CHECK_IP_CSUM | | 651 | t1_tpi_write(adapter, A_ELMER0_GPO, gpo); |
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 | } | 652 | } |
612 | |||
613 | writel(F_TP_RESET, adapter->regs + A_TP_RESET); | ||
614 | } | 653 | } |
615 | 654 | ||
616 | int __devinit t1_get_board_rev(adapter_t *adapter, const struct board_info *bi, | 655 | int __devinit t1_get_board_rev(adapter_t *adapter, const struct board_info *bi, |
617 | struct adapter_params *p) | 656 | struct adapter_params *p) |
618 | { | 657 | { |
619 | p->chip_version = bi->chip_term; | 658 | p->chip_version = bi->chip_term; |
659 | p->is_asic = (p->chip_version != CHBT_TERM_FPGA); | ||
620 | if (p->chip_version == CHBT_TERM_T1 || | 660 | if (p->chip_version == CHBT_TERM_T1 || |
621 | p->chip_version == CHBT_TERM_T2) { | 661 | p->chip_version == CHBT_TERM_T2 || |
662 | p->chip_version == CHBT_TERM_FPGA) { | ||
622 | u32 val = readl(adapter->regs + A_TP_PC_CONFIG); | 663 | u32 val = readl(adapter->regs + A_TP_PC_CONFIG); |
623 | 664 | ||
624 | val = G_TP_PC_REV(val); | 665 | val = G_TP_PC_REV(val); |
@@ -640,10 +681,22 @@ int __devinit t1_get_board_rev(adapter_t *adapter, const struct board_info *bi, | |||
640 | static int board_init(adapter_t *adapter, const struct board_info *bi) | 681 | static int board_init(adapter_t *adapter, const struct board_info *bi) |
641 | { | 682 | { |
642 | switch (bi->board) { | 683 | switch (bi->board) { |
684 | case CHBT_BOARD_8000: | ||
643 | case CHBT_BOARD_N110: | 685 | case CHBT_BOARD_N110: |
644 | case CHBT_BOARD_N210: | 686 | case CHBT_BOARD_N210: |
645 | writel(V_TPIPAR(0xf), adapter->regs + A_TPI_PAR); | 687 | case CHBT_BOARD_CHT210: |
646 | t1_tpi_write(adapter, A_ELMER0_GPO, 0x800); | 688 | case CHBT_BOARD_COUGAR: |
689 | t1_tpi_par(adapter, 0xf); | ||
690 | t1_tpi_write(adapter, A_ELMER0_GPO, 0x800); | ||
691 | break; | ||
692 | case CHBT_BOARD_CHT110: | ||
693 | t1_tpi_par(adapter, 0xf); | ||
694 | t1_tpi_write(adapter, A_ELMER0_GPO, 0x1800); | ||
695 | |||
696 | /* TBD XXX Might not need. This fixes a problem | ||
697 | * described in the Intel SR XPAK errata. | ||
698 | */ | ||
699 | power_sequence_xpak(adapter); | ||
647 | break; | 700 | break; |
648 | } | 701 | } |
649 | return 0; | 702 | return 0; |
@@ -670,7 +723,8 @@ int t1_init_hw_modules(adapter_t *adapter) | |||
670 | bi->espi_nports)) | 723 | bi->espi_nports)) |
671 | goto out_err; | 724 | goto out_err; |
672 | 725 | ||
673 | t1_tp_reset(adapter, bi->clock_core); | 726 | if (t1_tp_reset(adapter->tp, &adapter->params.tp, bi->clock_core)) |
727 | goto out_err; | ||
674 | 728 | ||
675 | err = t1_sge_configure(adapter->sge, &adapter->params.sge); | 729 | err = t1_sge_configure(adapter->sge, &adapter->params.sge); |
676 | if (err) | 730 | if (err) |
@@ -714,6 +768,8 @@ void t1_free_sw_modules(adapter_t *adapter) | |||
714 | 768 | ||
715 | if (adapter->sge) | 769 | if (adapter->sge) |
716 | t1_sge_destroy(adapter->sge); | 770 | t1_sge_destroy(adapter->sge); |
771 | if (adapter->tp) | ||
772 | t1_tp_destroy(adapter->tp); | ||
717 | if (adapter->espi) | 773 | if (adapter->espi) |
718 | t1_espi_destroy(adapter->espi); | 774 | t1_espi_destroy(adapter->espi); |
719 | } | 775 | } |
@@ -762,6 +818,13 @@ int __devinit t1_init_sw_modules(adapter_t *adapter, | |||
762 | goto error; | 818 | goto error; |
763 | } | 819 | } |
764 | 820 | ||
821 | adapter->tp = t1_tp_create(adapter, &adapter->params.tp); | ||
822 | if (!adapter->tp) { | ||
823 | CH_ERR("%s: TP initialization failed\n", | ||
824 | adapter->name); | ||
825 | goto error; | ||
826 | } | ||
827 | |||
765 | board_init(adapter, bi); | 828 | board_init(adapter, bi); |
766 | bi->mdio_ops->init(adapter, bi); | 829 | bi->mdio_ops->init(adapter, bi); |
767 | if (bi->gphy->reset) | 830 | if (bi->gphy->reset) |
@@ -793,7 +856,9 @@ int __devinit t1_init_sw_modules(adapter_t *adapter, | |||
793 | * Get the port's MAC addresses either from the EEPROM if one | 856 | * Get the port's MAC addresses either from the EEPROM if one |
794 | * exists or the one hardcoded in the MAC. | 857 | * exists or the one hardcoded in the MAC. |
795 | */ | 858 | */ |
796 | if (vpd_macaddress_get(adapter, i, hw_addr)) { | 859 | if (!t1_is_asic(adapter) || bi->chip_mac == CHBT_MAC_DUMMY) |
860 | mac->ops->macaddress_get(mac, hw_addr); | ||
861 | else if (vpd_macaddress_get(adapter, i, hw_addr)) { | ||
797 | CH_ERR("%s: could not read MAC address from VPD ROM\n", | 862 | CH_ERR("%s: could not read MAC address from VPD ROM\n", |
798 | adapter->port[i].dev->name); | 863 | adapter->port[i].dev->name); |
799 | goto error; | 864 | goto error; |
@@ -806,7 +871,7 @@ int __devinit t1_init_sw_modules(adapter_t *adapter, | |||
806 | t1_interrupts_clear(adapter); | 871 | t1_interrupts_clear(adapter); |
807 | return 0; | 872 | return 0; |
808 | 873 | ||
809 | error: | 874 | error: |
810 | t1_free_sw_modules(adapter); | 875 | t1_free_sw_modules(adapter); |
811 | return -1; | 876 | return -1; |
812 | } | 877 | } |