1 /************************************************************************** 2 3 Copyright (c) 2007-2009, Chelsio Inc. 4 All rights reserved. 5 6 Redistribution and use in source and binary forms, with or without 7 modification, are permitted provided that the following conditions are met: 8 9 1. Redistributions of source code must retain the above copyright notice, 10 this list of conditions and the following disclaimer. 11 12 2. Neither the name of the Chelsio Corporation nor the names of its 13 contributors may be used to endorse or promote products derived from 14 this software without specific prior written permission. 15 16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 POSSIBILITY OF SUCH DAMAGE. 27 28 ***************************************************************************/ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <cxgb_include.h> 34 35 #undef msleep 36 #define msleep t3_os_sleep 37 38 enum { 39 PMD_RSD = 10, /* PMA/PMD receive signal detect register */ 40 PCS_STAT1_X = 24, /* 10GBASE-X PCS status 1 register */ 41 PCS_STAT1_R = 32, /* 10GBASE-R PCS status 1 register */ 42 XS_LN_STAT = 24 /* XS lane status register */ 43 }; 44 45 enum { 46 AEL100X_TX_DISABLE = 9, 47 AEL100X_TX_CONFIG1 = 0xc002, 48 49 AEL1002_PWR_DOWN_HI = 0xc011, 50 AEL1002_PWR_DOWN_LO = 0xc012, 51 AEL1002_XFI_EQL = 0xc015, 52 AEL1002_LB_EN = 0xc017, 53 54 AEL_OPT_SETTINGS = 0xc017, 55 AEL_I2C_CTRL = 0xc30a, 56 AEL_I2C_DATA = 0xc30b, 57 AEL_I2C_STAT = 0xc30c, 58 59 AEL2005_GPIO_CTRL = 0xc214, 60 AEL2005_GPIO_STAT = 0xc215, 61 62 AEL2020_GPIO_INTR = 0xc103, 63 AEL2020_GPIO_CTRL = 0xc108, 64 AEL2020_GPIO_STAT = 0xc10c, 65 AEL2020_GPIO_CFG = 0xc110, 66 67 AEL2020_GPIO_SDA = 0, 68 AEL2020_GPIO_MODDET = 1, 69 AEL2020_GPIO_0 = 3, 70 AEL2020_GPIO_1 = 2, 71 AEL2020_GPIO_LSTAT = AEL2020_GPIO_1, 72 }; 73 74 enum { edc_none, edc_sr, edc_twinax }; 75 76 /* PHY module I2C device address */ 77 enum { 78 MODULE_DEV_ADDR = 0xa0, 79 SFF_DEV_ADDR = 0xa2, 80 }; 81 82 /* PHY transceiver type */ 83 enum { 84 phy_transtype_unknown = 0, 85 phy_transtype_sfp = 3, 86 phy_transtype_xfp = 6, 87 }; 88 89 #define AEL2005_MODDET_IRQ 4 90 91 struct reg_val { 92 unsigned short mmd_addr; 93 unsigned short reg_addr; 94 unsigned short clear_bits; 95 unsigned short set_bits; 96 }; 97 98 static int ael2xxx_get_module_type(struct cphy *phy, int delay_ms); 99 100 static int set_phy_regs(struct cphy *phy, const struct reg_val *rv) 101 { 102 int err; 103 104 for (err = 0; rv->mmd_addr && !err; rv++) { 105 if (rv->clear_bits == 0xffff) 106 err = mdio_write(phy, rv->mmd_addr, rv->reg_addr, 107 rv->set_bits); 108 else 109 err = t3_mdio_change_bits(phy, rv->mmd_addr, 110 rv->reg_addr, rv->clear_bits, 111 rv->set_bits); 112 } 113 return err; 114 } 115 116 static void ael100x_txon(struct cphy *phy) 117 { 118 int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL; 119 120 msleep(100); 121 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio); 122 msleep(30); 123 } 124 125 /* 126 * Read an 8-bit word from a device attached to the PHY's i2c bus. 127 */ 128 static int ael_i2c_rd(struct cphy *phy, int dev_addr, int word_addr) 129 { 130 int i, err; 131 unsigned int stat, data; 132 133 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL, 134 (dev_addr << 8) | (1 << 8) | word_addr); 135 if (err) 136 return err; 137 138 for (i = 0; i < 200; i++) { 139 msleep(1); 140 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat); 141 if (err) 142 return err; 143 if ((stat & 3) == 1) { 144 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA, 145 &data); 146 if (err) 147 return err; 148 return data >> 8; 149 } 150 } 151 CH_WARN(phy->adapter, "PHY %u i2c read of dev.addr %x.%x timed out\n", 152 phy->addr, dev_addr, word_addr); 153 return -ETIMEDOUT; 154 } 155 156 /* 157 * Write an 8-bit word to a device attached to the PHY's i2c bus. 158 */ 159 static int ael_i2c_wr(struct cphy *phy, int dev_addr, int word_addr, int data) 160 { 161 int i, err; 162 unsigned int stat; 163 164 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA, data); 165 if (err) 166 return err; 167 168 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL, 169 (dev_addr << 8) | word_addr); 170 if (err) 171 return err; 172 173 for (i = 0; i < 200; i++) { 174 msleep(1); 175 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat); 176 if (err) 177 return err; 178 if ((stat & 3) == 1) 179 return 0; 180 } 181 CH_WARN(phy->adapter, "PHY %u i2c Write of dev.addr %x.%x = %#x timed out\n", 182 phy->addr, dev_addr, word_addr, data); 183 return -ETIMEDOUT; 184 } 185 186 static int get_phytrans_type(struct cphy *phy) 187 { 188 int v; 189 190 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0); 191 if (v < 0) 192 return phy_transtype_unknown; 193 194 return v; 195 } 196 197 static int ael_laser_down(struct cphy *phy, int enable) 198 { 199 int v, dev_addr; 200 201 v = get_phytrans_type(phy); 202 if (v < 0) 203 return v; 204 205 if (v == phy_transtype_sfp) { 206 /* Check SFF Soft TX disable is supported */ 207 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 93); 208 if (v < 0) 209 return v; 210 211 v &= 0x40; 212 if (!v) 213 return v; 214 215 dev_addr = SFF_DEV_ADDR; 216 } else if (v == phy_transtype_xfp) 217 dev_addr = MODULE_DEV_ADDR; 218 else 219 return v; 220 221 v = ael_i2c_rd(phy, dev_addr, 110); 222 if (v < 0) 223 return v; 224 225 if (enable) 226 v |= 0x40; 227 else 228 v &= ~0x40; 229 230 v = ael_i2c_wr(phy, dev_addr, 110, v); 231 232 return v; 233 } 234 235 static int ael1002_power_down(struct cphy *phy, int enable) 236 { 237 int err; 238 239 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable); 240 if (!err) 241 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 242 BMCR_PDOWN, enable ? BMCR_PDOWN : 0); 243 return err; 244 } 245 246 static int ael1002_get_module_type(struct cphy *phy, int delay_ms) 247 { 248 int v; 249 250 if (delay_ms) 251 msleep(delay_ms); 252 253 v = ael2xxx_get_module_type(phy, delay_ms); 254 255 return (v == -ETIMEDOUT ? phy_modtype_none : v); 256 } 257 258 static int ael1002_reset(struct cphy *phy, int wait) 259 { 260 int err; 261 262 if ((err = ael1002_power_down(phy, 0)) || 263 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) || 264 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) || 265 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) || 266 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) || 267 (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN, 268 0, 1 << 5))) 269 return err; 270 271 err = ael1002_get_module_type(phy, 300); 272 if (err >= 0) 273 phy->modtype = err; 274 275 return 0; 276 } 277 278 static int ael1002_intr_noop(struct cphy *phy) 279 { 280 return 0; 281 } 282 283 /* 284 * Get link status for a 10GBASE-R device. 285 */ 286 static int get_link_status_r(struct cphy *phy, int *link_ok, int *speed, 287 int *duplex, int *fc) 288 { 289 if (link_ok) { 290 unsigned int stat0, stat1, stat2; 291 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0); 292 293 if (!err) 294 err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_R, &stat1); 295 if (!err) 296 err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2); 297 if (err) 298 return err; 299 *link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1; 300 } 301 if (speed) 302 *speed = SPEED_10000; 303 if (duplex) 304 *duplex = DUPLEX_FULL; 305 return 0; 306 } 307 308 #ifdef C99_NOT_SUPPORTED 309 static struct cphy_ops ael1002_ops = { 310 ael1002_reset, 311 ael1002_intr_noop, 312 ael1002_intr_noop, 313 ael1002_intr_noop, 314 ael1002_intr_noop, 315 NULL, 316 NULL, 317 NULL, 318 NULL, 319 NULL, 320 get_link_status_r, 321 ael1002_power_down, 322 }; 323 #else 324 static struct cphy_ops ael1002_ops = { 325 .reset = ael1002_reset, 326 .intr_enable = ael1002_intr_noop, 327 .intr_disable = ael1002_intr_noop, 328 .intr_clear = ael1002_intr_noop, 329 .intr_handler = ael1002_intr_noop, 330 .get_link_status = get_link_status_r, 331 .power_down = ael1002_power_down, 332 }; 333 #endif 334 335 int t3_ael1002_phy_prep(pinfo_t *pinfo, int phy_addr, 336 const struct mdio_ops *mdio_ops) 337 { 338 int err; 339 struct cphy *phy = &pinfo->phy; 340 341 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael1002_ops, mdio_ops, 342 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE, 343 "10GBASE-R"); 344 ael100x_txon(phy); 345 ael_laser_down(phy, 0); 346 347 err = ael1002_get_module_type(phy, 0); 348 if (err >= 0) 349 phy->modtype = err; 350 351 return 0; 352 } 353 354 static int ael1006_reset(struct cphy *phy, int wait) 355 { 356 int err; 357 358 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait); 359 if (err) 360 return err; 361 362 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 363 F_GPIO6_OUT_VAL, 0); 364 365 msleep(125); 366 367 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 368 F_GPIO6_OUT_VAL, F_GPIO6_OUT_VAL); 369 370 msleep(125); 371 372 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait); 373 if (err) 374 return err; 375 376 msleep(125); 377 378 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 1); 379 if (err) 380 return err; 381 382 msleep(125); 383 384 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 0); 385 386 return err; 387 388 } 389 390 #ifdef C99_NOT_SUPPORTED 391 static struct cphy_ops ael1006_ops = { 392 ael1006_reset, 393 t3_phy_lasi_intr_enable, 394 t3_phy_lasi_intr_disable, 395 t3_phy_lasi_intr_clear, 396 t3_phy_lasi_intr_handler, 397 NULL, 398 NULL, 399 NULL, 400 NULL, 401 NULL, 402 get_link_status_r, 403 ael1002_power_down, 404 }; 405 #else 406 static struct cphy_ops ael1006_ops = { 407 .reset = ael1006_reset, 408 .intr_enable = t3_phy_lasi_intr_enable, 409 .intr_disable = t3_phy_lasi_intr_disable, 410 .intr_clear = t3_phy_lasi_intr_clear, 411 .intr_handler = t3_phy_lasi_intr_handler, 412 .get_link_status = get_link_status_r, 413 .power_down = ael1002_power_down, 414 }; 415 #endif 416 417 int t3_ael1006_phy_prep(pinfo_t *pinfo, int phy_addr, 418 const struct mdio_ops *mdio_ops) 419 { 420 struct cphy *phy = &pinfo->phy; 421 422 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael1006_ops, mdio_ops, 423 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE, 424 "10GBASE-SR"); 425 phy->modtype = phy_modtype_sr; 426 ael100x_txon(phy); 427 return 0; 428 } 429 430 /* 431 * Decode our module type. 432 */ 433 static int ael2xxx_get_module_type(struct cphy *phy, int delay_ms) 434 { 435 int v; 436 437 if (delay_ms) 438 msleep(delay_ms); 439 440 v = get_phytrans_type(phy); 441 if (v == phy_transtype_sfp) { 442 /* SFP: see SFF-8472 for below */ 443 444 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 3); 445 if (v < 0) 446 return v; 447 448 if (v == 0x1) 449 return phy_modtype_twinax; 450 if (v == 0x10) 451 return phy_modtype_sr; 452 if (v == 0x20) 453 return phy_modtype_lr; 454 if (v == 0x40) 455 return phy_modtype_lrm; 456 457 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 6); 458 if (v < 0) 459 return v; 460 if (v != 4) 461 return phy_modtype_unknown; 462 463 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 10); 464 if (v < 0) 465 return v; 466 467 if (v & 0x80) { 468 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0x12); 469 if (v < 0) 470 return v; 471 return v > 10 ? phy_modtype_twinax_long : 472 phy_modtype_twinax; 473 } 474 } else if (v == phy_transtype_xfp) { 475 /* XFP: See INF-8077i for details. */ 476 477 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 127); 478 if (v < 0) 479 return v; 480 481 if (v != 1) { 482 /* XXX: set page select to table 1 yourself */ 483 return phy_modtype_unknown; 484 } 485 486 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 131); 487 if (v < 0) 488 return v; 489 v &= 0xf0; 490 if (v == 0x10) 491 return phy_modtype_lrm; 492 if (v == 0x40) 493 return phy_modtype_lr; 494 if (v == 0x80) 495 return phy_modtype_sr; 496 } 497 498 return phy_modtype_unknown; 499 } 500 501 /* 502 * Code to support the Aeluros/NetLogic 2005 10Gb PHY. 503 */ 504 static int ael2005_setup_sr_edc(struct cphy *phy) 505 { 506 static struct reg_val regs[] = { 507 { MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x181 }, 508 { MDIO_DEV_PMA_PMD, 0xc010, 0xffff, 0x448a }, 509 { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5200 }, 510 { 0, 0, 0, 0 } 511 }; 512 static u16 sr_edc[] = { 513 0xcc00, 0x2ff4, 514 0xcc01, 0x3cd4, 515 0xcc02, 0x2015, 516 0xcc03, 0x3105, 517 0xcc04, 0x6524, 518 0xcc05, 0x27ff, 519 0xcc06, 0x300f, 520 0xcc07, 0x2c8b, 521 0xcc08, 0x300b, 522 0xcc09, 0x4009, 523 0xcc0a, 0x400e, 524 0xcc0b, 0x2f72, 525 0xcc0c, 0x3002, 526 0xcc0d, 0x1002, 527 0xcc0e, 0x2172, 528 0xcc0f, 0x3012, 529 0xcc10, 0x1002, 530 0xcc11, 0x25d2, 531 0xcc12, 0x3012, 532 0xcc13, 0x1002, 533 0xcc14, 0xd01e, 534 0xcc15, 0x27d2, 535 0xcc16, 0x3012, 536 0xcc17, 0x1002, 537 0xcc18, 0x2004, 538 0xcc19, 0x3c84, 539 0xcc1a, 0x6436, 540 0xcc1b, 0x2007, 541 0xcc1c, 0x3f87, 542 0xcc1d, 0x8676, 543 0xcc1e, 0x40b7, 544 0xcc1f, 0xa746, 545 0xcc20, 0x4047, 546 0xcc21, 0x5673, 547 0xcc22, 0x2982, 548 0xcc23, 0x3002, 549 0xcc24, 0x13d2, 550 0xcc25, 0x8bbd, 551 0xcc26, 0x2862, 552 0xcc27, 0x3012, 553 0xcc28, 0x1002, 554 0xcc29, 0x2092, 555 0xcc2a, 0x3012, 556 0xcc2b, 0x1002, 557 0xcc2c, 0x5cc3, 558 0xcc2d, 0x314, 559 0xcc2e, 0x2942, 560 0xcc2f, 0x3002, 561 0xcc30, 0x1002, 562 0xcc31, 0xd019, 563 0xcc32, 0x2032, 564 0xcc33, 0x3012, 565 0xcc34, 0x1002, 566 0xcc35, 0x2a04, 567 0xcc36, 0x3c74, 568 0xcc37, 0x6435, 569 0xcc38, 0x2fa4, 570 0xcc39, 0x3cd4, 571 0xcc3a, 0x6624, 572 0xcc3b, 0x5563, 573 0xcc3c, 0x2d42, 574 0xcc3d, 0x3002, 575 0xcc3e, 0x13d2, 576 0xcc3f, 0x464d, 577 0xcc40, 0x2862, 578 0xcc41, 0x3012, 579 0xcc42, 0x1002, 580 0xcc43, 0x2032, 581 0xcc44, 0x3012, 582 0xcc45, 0x1002, 583 0xcc46, 0x2fb4, 584 0xcc47, 0x3cd4, 585 0xcc48, 0x6624, 586 0xcc49, 0x5563, 587 0xcc4a, 0x2d42, 588 0xcc4b, 0x3002, 589 0xcc4c, 0x13d2, 590 0xcc4d, 0x2ed2, 591 0xcc4e, 0x3002, 592 0xcc4f, 0x1002, 593 0xcc50, 0x2fd2, 594 0xcc51, 0x3002, 595 0xcc52, 0x1002, 596 0xcc53, 0x004, 597 0xcc54, 0x2942, 598 0xcc55, 0x3002, 599 0xcc56, 0x1002, 600 0xcc57, 0x2092, 601 0xcc58, 0x3012, 602 0xcc59, 0x1002, 603 0xcc5a, 0x5cc3, 604 0xcc5b, 0x317, 605 0xcc5c, 0x2f72, 606 0xcc5d, 0x3002, 607 0xcc5e, 0x1002, 608 0xcc5f, 0x2942, 609 0xcc60, 0x3002, 610 0xcc61, 0x1002, 611 0xcc62, 0x22cd, 612 0xcc63, 0x301d, 613 0xcc64, 0x2862, 614 0xcc65, 0x3012, 615 0xcc66, 0x1002, 616 0xcc67, 0x2ed2, 617 0xcc68, 0x3002, 618 0xcc69, 0x1002, 619 0xcc6a, 0x2d72, 620 0xcc6b, 0x3002, 621 0xcc6c, 0x1002, 622 0xcc6d, 0x628f, 623 0xcc6e, 0x2112, 624 0xcc6f, 0x3012, 625 0xcc70, 0x1002, 626 0xcc71, 0x5aa3, 627 0xcc72, 0x2dc2, 628 0xcc73, 0x3002, 629 0xcc74, 0x1312, 630 0xcc75, 0x6f72, 631 0xcc76, 0x1002, 632 0xcc77, 0x2807, 633 0xcc78, 0x31a7, 634 0xcc79, 0x20c4, 635 0xcc7a, 0x3c24, 636 0xcc7b, 0x6724, 637 0xcc7c, 0x1002, 638 0xcc7d, 0x2807, 639 0xcc7e, 0x3187, 640 0xcc7f, 0x20c4, 641 0xcc80, 0x3c24, 642 0xcc81, 0x6724, 643 0xcc82, 0x1002, 644 0xcc83, 0x2514, 645 0xcc84, 0x3c64, 646 0xcc85, 0x6436, 647 0xcc86, 0xdff4, 648 0xcc87, 0x6436, 649 0xcc88, 0x1002, 650 0xcc89, 0x40a4, 651 0xcc8a, 0x643c, 652 0xcc8b, 0x4016, 653 0xcc8c, 0x8c6c, 654 0xcc8d, 0x2b24, 655 0xcc8e, 0x3c24, 656 0xcc8f, 0x6435, 657 0xcc90, 0x1002, 658 0xcc91, 0x2b24, 659 0xcc92, 0x3c24, 660 0xcc93, 0x643a, 661 0xcc94, 0x4025, 662 0xcc95, 0x8a5a, 663 0xcc96, 0x1002, 664 0xcc97, 0x2731, 665 0xcc98, 0x3011, 666 0xcc99, 0x1001, 667 0xcc9a, 0xc7a0, 668 0xcc9b, 0x100, 669 0xcc9c, 0xc502, 670 0xcc9d, 0x53ac, 671 0xcc9e, 0xc503, 672 0xcc9f, 0xd5d5, 673 0xcca0, 0xc600, 674 0xcca1, 0x2a6d, 675 0xcca2, 0xc601, 676 0xcca3, 0x2a4c, 677 0xcca4, 0xc602, 678 0xcca5, 0x111, 679 0xcca6, 0xc60c, 680 0xcca7, 0x5900, 681 0xcca8, 0xc710, 682 0xcca9, 0x700, 683 0xccaa, 0xc718, 684 0xccab, 0x700, 685 0xccac, 0xc720, 686 0xccad, 0x4700, 687 0xccae, 0xc801, 688 0xccaf, 0x7f50, 689 0xccb0, 0xc802, 690 0xccb1, 0x7760, 691 0xccb2, 0xc803, 692 0xccb3, 0x7fce, 693 0xccb4, 0xc804, 694 0xccb5, 0x5700, 695 0xccb6, 0xc805, 696 0xccb7, 0x5f11, 697 0xccb8, 0xc806, 698 0xccb9, 0x4751, 699 0xccba, 0xc807, 700 0xccbb, 0x57e1, 701 0xccbc, 0xc808, 702 0xccbd, 0x2700, 703 0xccbe, 0xc809, 704 0xccbf, 0x000, 705 0xccc0, 0xc821, 706 0xccc1, 0x002, 707 0xccc2, 0xc822, 708 0xccc3, 0x014, 709 0xccc4, 0xc832, 710 0xccc5, 0x1186, 711 0xccc6, 0xc847, 712 0xccc7, 0x1e02, 713 0xccc8, 0xc013, 714 0xccc9, 0xf341, 715 0xccca, 0xc01a, 716 0xcccb, 0x446, 717 0xcccc, 0xc024, 718 0xcccd, 0x1000, 719 0xccce, 0xc025, 720 0xcccf, 0xa00, 721 0xccd0, 0xc026, 722 0xccd1, 0xc0c, 723 0xccd2, 0xc027, 724 0xccd3, 0xc0c, 725 0xccd4, 0xc029, 726 0xccd5, 0x0a0, 727 0xccd6, 0xc030, 728 0xccd7, 0xa00, 729 0xccd8, 0xc03c, 730 0xccd9, 0x01c, 731 0xccda, 0xc005, 732 0xccdb, 0x7a06, 733 0xccdc, 0x000, 734 0xccdd, 0x2731, 735 0xccde, 0x3011, 736 0xccdf, 0x1001, 737 0xcce0, 0xc620, 738 0xcce1, 0x000, 739 0xcce2, 0xc621, 740 0xcce3, 0x03f, 741 0xcce4, 0xc622, 742 0xcce5, 0x000, 743 0xcce6, 0xc623, 744 0xcce7, 0x000, 745 0xcce8, 0xc624, 746 0xcce9, 0x000, 747 0xccea, 0xc625, 748 0xcceb, 0x000, 749 0xccec, 0xc627, 750 0xcced, 0x000, 751 0xccee, 0xc628, 752 0xccef, 0x000, 753 0xccf0, 0xc62c, 754 0xccf1, 0x000, 755 0xccf2, 0x000, 756 0xccf3, 0x2806, 757 0xccf4, 0x3cb6, 758 0xccf5, 0xc161, 759 0xccf6, 0x6134, 760 0xccf7, 0x6135, 761 0xccf8, 0x5443, 762 0xccf9, 0x303, 763 0xccfa, 0x6524, 764 0xccfb, 0x00b, 765 0xccfc, 0x1002, 766 0xccfd, 0x2104, 767 0xccfe, 0x3c24, 768 0xccff, 0x2105, 769 0xcd00, 0x3805, 770 0xcd01, 0x6524, 771 0xcd02, 0xdff4, 772 0xcd03, 0x4005, 773 0xcd04, 0x6524, 774 0xcd05, 0x1002, 775 0xcd06, 0x5dd3, 776 0xcd07, 0x306, 777 0xcd08, 0x2ff7, 778 0xcd09, 0x38f7, 779 0xcd0a, 0x60b7, 780 0xcd0b, 0xdffd, 781 0xcd0c, 0x00a, 782 0xcd0d, 0x1002, 783 0xcd0e, 0 784 }; 785 int i, err; 786 787 err = set_phy_regs(phy, regs); 788 if (err) 789 return err; 790 791 msleep(50); 792 793 for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2) 794 err = mdio_write(phy, MDIO_DEV_PMA_PMD, sr_edc[i], 795 sr_edc[i + 1]); 796 if (!err) 797 phy->priv = edc_sr; 798 return err; 799 } 800 801 static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype) 802 { 803 static struct reg_val regs[] = { 804 { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5a00 }, 805 { 0, 0, 0, 0 } 806 }; 807 static struct reg_val preemphasis[] = { 808 { MDIO_DEV_PMA_PMD, 0xc014, 0xffff, 0xfe16 }, 809 { MDIO_DEV_PMA_PMD, 0xc015, 0xffff, 0xa000 }, 810 { 0, 0, 0, 0 } 811 }; 812 static u16 twinax_edc[] = { 813 0xcc00, 0x4009, 814 0xcc01, 0x27ff, 815 0xcc02, 0x300f, 816 0xcc03, 0x40aa, 817 0xcc04, 0x401c, 818 0xcc05, 0x401e, 819 0xcc06, 0x2ff4, 820 0xcc07, 0x3cd4, 821 0xcc08, 0x2035, 822 0xcc09, 0x3145, 823 0xcc0a, 0x6524, 824 0xcc0b, 0x26a2, 825 0xcc0c, 0x3012, 826 0xcc0d, 0x1002, 827 0xcc0e, 0x29c2, 828 0xcc0f, 0x3002, 829 0xcc10, 0x1002, 830 0xcc11, 0x2072, 831 0xcc12, 0x3012, 832 0xcc13, 0x1002, 833 0xcc14, 0x22cd, 834 0xcc15, 0x301d, 835 0xcc16, 0x2e52, 836 0xcc17, 0x3012, 837 0xcc18, 0x1002, 838 0xcc19, 0x28e2, 839 0xcc1a, 0x3002, 840 0xcc1b, 0x1002, 841 0xcc1c, 0x628f, 842 0xcc1d, 0x2ac2, 843 0xcc1e, 0x3012, 844 0xcc1f, 0x1002, 845 0xcc20, 0x5553, 846 0xcc21, 0x2ae2, 847 0xcc22, 0x3002, 848 0xcc23, 0x1302, 849 0xcc24, 0x401e, 850 0xcc25, 0x2be2, 851 0xcc26, 0x3012, 852 0xcc27, 0x1002, 853 0xcc28, 0x2da2, 854 0xcc29, 0x3012, 855 0xcc2a, 0x1002, 856 0xcc2b, 0x2ba2, 857 0xcc2c, 0x3002, 858 0xcc2d, 0x1002, 859 0xcc2e, 0x5ee3, 860 0xcc2f, 0x305, 861 0xcc30, 0x400e, 862 0xcc31, 0x2bc2, 863 0xcc32, 0x3002, 864 0xcc33, 0x1002, 865 0xcc34, 0x2b82, 866 0xcc35, 0x3012, 867 0xcc36, 0x1002, 868 0xcc37, 0x5663, 869 0xcc38, 0x302, 870 0xcc39, 0x401e, 871 0xcc3a, 0x6f72, 872 0xcc3b, 0x1002, 873 0xcc3c, 0x628f, 874 0xcc3d, 0x2be2, 875 0xcc3e, 0x3012, 876 0xcc3f, 0x1002, 877 0xcc40, 0x22cd, 878 0xcc41, 0x301d, 879 0xcc42, 0x2e52, 880 0xcc43, 0x3012, 881 0xcc44, 0x1002, 882 0xcc45, 0x2522, 883 0xcc46, 0x3012, 884 0xcc47, 0x1002, 885 0xcc48, 0x2da2, 886 0xcc49, 0x3012, 887 0xcc4a, 0x1002, 888 0xcc4b, 0x2ca2, 889 0xcc4c, 0x3012, 890 0xcc4d, 0x1002, 891 0xcc4e, 0x2fa4, 892 0xcc4f, 0x3cd4, 893 0xcc50, 0x6624, 894 0xcc51, 0x410b, 895 0xcc52, 0x56b3, 896 0xcc53, 0x3c4, 897 0xcc54, 0x2fb2, 898 0xcc55, 0x3002, 899 0xcc56, 0x1002, 900 0xcc57, 0x220b, 901 0xcc58, 0x303b, 902 0xcc59, 0x56b3, 903 0xcc5a, 0x3c3, 904 0xcc5b, 0x866b, 905 0xcc5c, 0x400c, 906 0xcc5d, 0x23a2, 907 0xcc5e, 0x3012, 908 0xcc5f, 0x1002, 909 0xcc60, 0x2da2, 910 0xcc61, 0x3012, 911 0xcc62, 0x1002, 912 0xcc63, 0x2ca2, 913 0xcc64, 0x3012, 914 0xcc65, 0x1002, 915 0xcc66, 0x2fb4, 916 0xcc67, 0x3cd4, 917 0xcc68, 0x6624, 918 0xcc69, 0x56b3, 919 0xcc6a, 0x3c3, 920 0xcc6b, 0x866b, 921 0xcc6c, 0x401c, 922 0xcc6d, 0x2205, 923 0xcc6e, 0x3035, 924 0xcc6f, 0x5b53, 925 0xcc70, 0x2c52, 926 0xcc71, 0x3002, 927 0xcc72, 0x13c2, 928 0xcc73, 0x5cc3, 929 0xcc74, 0x317, 930 0xcc75, 0x2522, 931 0xcc76, 0x3012, 932 0xcc77, 0x1002, 933 0xcc78, 0x2da2, 934 0xcc79, 0x3012, 935 0xcc7a, 0x1002, 936 0xcc7b, 0x2b82, 937 0xcc7c, 0x3012, 938 0xcc7d, 0x1002, 939 0xcc7e, 0x5663, 940 0xcc7f, 0x303, 941 0xcc80, 0x401e, 942 0xcc81, 0x004, 943 0xcc82, 0x2c42, 944 0xcc83, 0x3012, 945 0xcc84, 0x1002, 946 0xcc85, 0x6f72, 947 0xcc86, 0x1002, 948 0xcc87, 0x628f, 949 0xcc88, 0x2304, 950 0xcc89, 0x3c84, 951 0xcc8a, 0x6436, 952 0xcc8b, 0xdff4, 953 0xcc8c, 0x6436, 954 0xcc8d, 0x2ff5, 955 0xcc8e, 0x3005, 956 0xcc8f, 0x8656, 957 0xcc90, 0xdfba, 958 0xcc91, 0x56a3, 959 0xcc92, 0xd05a, 960 0xcc93, 0x21c2, 961 0xcc94, 0x3012, 962 0xcc95, 0x1392, 963 0xcc96, 0xd05a, 964 0xcc97, 0x56a3, 965 0xcc98, 0xdfba, 966 0xcc99, 0x383, 967 0xcc9a, 0x6f72, 968 0xcc9b, 0x1002, 969 0xcc9c, 0x28c5, 970 0xcc9d, 0x3005, 971 0xcc9e, 0x4178, 972 0xcc9f, 0x5653, 973 0xcca0, 0x384, 974 0xcca1, 0x22b2, 975 0xcca2, 0x3012, 976 0xcca3, 0x1002, 977 0xcca4, 0x2be5, 978 0xcca5, 0x3005, 979 0xcca6, 0x41e8, 980 0xcca7, 0x5653, 981 0xcca8, 0x382, 982 0xcca9, 0x002, 983 0xccaa, 0x4258, 984 0xccab, 0x2474, 985 0xccac, 0x3c84, 986 0xccad, 0x6437, 987 0xccae, 0xdff4, 988 0xccaf, 0x6437, 989 0xccb0, 0x2ff5, 990 0xccb1, 0x3c05, 991 0xccb2, 0x8757, 992 0xccb3, 0xb888, 993 0xccb4, 0x9787, 994 0xccb5, 0xdff4, 995 0xccb6, 0x6724, 996 0xccb7, 0x866a, 997 0xccb8, 0x6f72, 998 0xccb9, 0x1002, 999 0xccba, 0x2d01, 1000 0xccbb, 0x3011, 1001 0xccbc, 0x1001, 1002 0xccbd, 0xc620, 1003 0xccbe, 0x14e5, 1004 0xccbf, 0xc621, 1005 0xccc0, 0xc53d, 1006 0xccc1, 0xc622, 1007 0xccc2, 0x3cbe, 1008 0xccc3, 0xc623, 1009 0xccc4, 0x4452, 1010 0xccc5, 0xc624, 1011 0xccc6, 0xc5c5, 1012 0xccc7, 0xc625, 1013 0xccc8, 0xe01e, 1014 0xccc9, 0xc627, 1015 0xccca, 0x000, 1016 0xcccb, 0xc628, 1017 0xcccc, 0x000, 1018 0xcccd, 0xc62b, 1019 0xccce, 0x000, 1020 0xcccf, 0xc62c, 1021 0xccd0, 0x000, 1022 0xccd1, 0x000, 1023 0xccd2, 0x2d01, 1024 0xccd3, 0x3011, 1025 0xccd4, 0x1001, 1026 0xccd5, 0xc620, 1027 0xccd6, 0x000, 1028 0xccd7, 0xc621, 1029 0xccd8, 0x000, 1030 0xccd9, 0xc622, 1031 0xccda, 0x0ce, 1032 0xccdb, 0xc623, 1033 0xccdc, 0x07f, 1034 0xccdd, 0xc624, 1035 0xccde, 0x032, 1036 0xccdf, 0xc625, 1037 0xcce0, 0x000, 1038 0xcce1, 0xc627, 1039 0xcce2, 0x000, 1040 0xcce3, 0xc628, 1041 0xcce4, 0x000, 1042 0xcce5, 0xc62b, 1043 0xcce6, 0x000, 1044 0xcce7, 0xc62c, 1045 0xcce8, 0x000, 1046 0xcce9, 0x000, 1047 0xccea, 0x2d01, 1048 0xcceb, 0x3011, 1049 0xccec, 0x1001, 1050 0xcced, 0xc502, 1051 0xccee, 0x609f, 1052 0xccef, 0xc600, 1053 0xccf0, 0x2a6e, 1054 0xccf1, 0xc601, 1055 0xccf2, 0x2a2c, 1056 0xccf3, 0xc60c, 1057 0xccf4, 0x5400, 1058 0xccf5, 0xc710, 1059 0xccf6, 0x700, 1060 0xccf7, 0xc718, 1061 0xccf8, 0x700, 1062 0xccf9, 0xc720, 1063 0xccfa, 0x4700, 1064 0xccfb, 0xc728, 1065 0xccfc, 0x700, 1066 0xccfd, 0xc729, 1067 0xccfe, 0x1207, 1068 0xccff, 0xc801, 1069 0xcd00, 0x7f50, 1070 0xcd01, 0xc802, 1071 0xcd02, 0x7760, 1072 0xcd03, 0xc803, 1073 0xcd04, 0x7fce, 1074 0xcd05, 0xc804, 1075 0xcd06, 0x520e, 1076 0xcd07, 0xc805, 1077 0xcd08, 0x5c11, 1078 0xcd09, 0xc806, 1079 0xcd0a, 0x3c51, 1080 0xcd0b, 0xc807, 1081 0xcd0c, 0x4061, 1082 0xcd0d, 0xc808, 1083 0xcd0e, 0x49c1, 1084 0xcd0f, 0xc809, 1085 0xcd10, 0x3840, 1086 0xcd11, 0xc80a, 1087 0xcd12, 0x000, 1088 0xcd13, 0xc821, 1089 0xcd14, 0x002, 1090 0xcd15, 0xc822, 1091 0xcd16, 0x046, 1092 0xcd17, 0xc844, 1093 0xcd18, 0x182f, 1094 0xcd19, 0xc013, 1095 0xcd1a, 0xf341, 1096 0xcd1b, 0xc01a, 1097 0xcd1c, 0x446, 1098 0xcd1d, 0xc024, 1099 0xcd1e, 0x1000, 1100 0xcd1f, 0xc025, 1101 0xcd20, 0xa00, 1102 0xcd21, 0xc026, 1103 0xcd22, 0xc0c, 1104 0xcd23, 0xc027, 1105 0xcd24, 0xc0c, 1106 0xcd25, 0xc029, 1107 0xcd26, 0x0a0, 1108 0xcd27, 0xc030, 1109 0xcd28, 0xa00, 1110 0xcd29, 0xc03c, 1111 0xcd2a, 0x01c, 1112 0xcd2b, 0x000, 1113 0xcd2c, 0x2b84, 1114 0xcd2d, 0x3c74, 1115 0xcd2e, 0x6435, 1116 0xcd2f, 0xdff4, 1117 0xcd30, 0x6435, 1118 0xcd31, 0x2806, 1119 0xcd32, 0x3006, 1120 0xcd33, 0x8565, 1121 0xcd34, 0x2b24, 1122 0xcd35, 0x3c24, 1123 0xcd36, 0x6436, 1124 0xcd37, 0x1002, 1125 0xcd38, 0x2b24, 1126 0xcd39, 0x3c24, 1127 0xcd3a, 0x6436, 1128 0xcd3b, 0x4045, 1129 0xcd3c, 0x8656, 1130 0xcd3d, 0x1002, 1131 0xcd3e, 0x2807, 1132 0xcd3f, 0x31a7, 1133 0xcd40, 0x20c4, 1134 0xcd41, 0x3c24, 1135 0xcd42, 0x6724, 1136 0xcd43, 0x1002, 1137 0xcd44, 0x2807, 1138 0xcd45, 0x3187, 1139 0xcd46, 0x20c4, 1140 0xcd47, 0x3c24, 1141 0xcd48, 0x6724, 1142 0xcd49, 0x1002, 1143 0xcd4a, 0x2514, 1144 0xcd4b, 0x3c64, 1145 0xcd4c, 0x6436, 1146 0xcd4d, 0xdff4, 1147 0xcd4e, 0x6436, 1148 0xcd4f, 0x1002, 1149 0xcd50, 0x2806, 1150 0xcd51, 0x3cb6, 1151 0xcd52, 0xc161, 1152 0xcd53, 0x6134, 1153 0xcd54, 0x6135, 1154 0xcd55, 0x5443, 1155 0xcd56, 0x303, 1156 0xcd57, 0x6524, 1157 0xcd58, 0x00b, 1158 0xcd59, 0x1002, 1159 0xcd5a, 0xd019, 1160 0xcd5b, 0x2104, 1161 0xcd5c, 0x3c24, 1162 0xcd5d, 0x2105, 1163 0xcd5e, 0x3805, 1164 0xcd5f, 0x6524, 1165 0xcd60, 0xdff4, 1166 0xcd61, 0x4005, 1167 0xcd62, 0x6524, 1168 0xcd63, 0x2e8d, 1169 0xcd64, 0x303d, 1170 0xcd65, 0x5dd3, 1171 0xcd66, 0x306, 1172 0xcd67, 0x2ff7, 1173 0xcd68, 0x38f7, 1174 0xcd69, 0x60b7, 1175 0xcd6a, 0xdffd, 1176 0xcd6b, 0x00a, 1177 0xcd6c, 0x1002, 1178 0xcd6d, 0 1179 }; 1180 int i, err; 1181 1182 err = set_phy_regs(phy, regs); 1183 if (!err && modtype == phy_modtype_twinax_long) 1184 err = set_phy_regs(phy, preemphasis); 1185 if (err) 1186 return err; 1187 1188 msleep(50); 1189 1190 for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2) 1191 err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i], 1192 twinax_edc[i + 1]); 1193 if (!err) 1194 phy->priv = edc_twinax; 1195 return err; 1196 } 1197 1198 static int ael2005_get_module_type(struct cphy *phy, int delay_ms) 1199 { 1200 int v; 1201 unsigned int stat; 1202 1203 v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, &stat); 1204 if (v) 1205 return v; 1206 1207 if (stat & (1 << 8)) /* module absent */ 1208 return phy_modtype_none; 1209 1210 return ael2xxx_get_module_type(phy, delay_ms); 1211 } 1212 1213 static int ael2005_intr_enable(struct cphy *phy) 1214 { 1215 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x200); 1216 return err ? err : t3_phy_lasi_intr_enable(phy); 1217 } 1218 1219 static int ael2005_intr_disable(struct cphy *phy) 1220 { 1221 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x100); 1222 return err ? err : t3_phy_lasi_intr_disable(phy); 1223 } 1224 1225 static int ael2005_intr_clear(struct cphy *phy) 1226 { 1227 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0xd00); 1228 return err ? err : t3_phy_lasi_intr_clear(phy); 1229 } 1230 1231 static int ael2005_reset(struct cphy *phy, int wait) 1232 { 1233 static struct reg_val regs0[] = { 1234 { MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 }, 1235 { MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 }, 1236 { MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 }, 1237 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 }, 1238 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 }, 1239 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 }, 1240 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 }, 1241 { 0, 0, 0, 0 } 1242 }; 1243 static struct reg_val regs1[] = { 1244 { MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 }, 1245 { MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 }, 1246 { 0, 0, 0, 0 } 1247 }; 1248 1249 int err; 1250 unsigned int lasi_ctrl; 1251 1252 err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl); 1253 if (err) 1254 return err; 1255 1256 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0); 1257 if (err) 1258 return err; 1259 1260 msleep(125); 1261 phy->priv = edc_none; 1262 err = set_phy_regs(phy, regs0); 1263 if (err) 1264 return err; 1265 1266 msleep(50); 1267 1268 err = ael2005_get_module_type(phy, 0); 1269 if (err < 0) 1270 return err; 1271 phy->modtype = (u8)err; 1272 1273 if (err == phy_modtype_none) 1274 err = 0; 1275 else if (err == phy_modtype_twinax || err == phy_modtype_twinax_long) 1276 err = ael2005_setup_twinax_edc(phy, err); 1277 else 1278 err = ael2005_setup_sr_edc(phy); 1279 if (err) 1280 return err; 1281 1282 err = set_phy_regs(phy, regs1); 1283 if (err) 1284 return err; 1285 1286 /* reset wipes out interrupts, reenable them if they were on */ 1287 if (lasi_ctrl & 1) 1288 err = ael2005_intr_enable(phy); 1289 return err; 1290 } 1291 1292 static int ael2005_intr_handler(struct cphy *phy) 1293 { 1294 unsigned int stat; 1295 int ret, edc_needed, cause = 0; 1296 1297 ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_STAT, &stat); 1298 if (ret) 1299 return ret; 1300 1301 if (stat & AEL2005_MODDET_IRQ) { 1302 ret = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 1303 0xd00); 1304 if (ret) 1305 return ret; 1306 1307 /* modules have max 300 ms init time after hot plug */ 1308 ret = ael2005_get_module_type(phy, 300); 1309 if (ret < 0) 1310 return ret; 1311 1312 phy->modtype = (u8)ret; 1313 if (ret == phy_modtype_none) 1314 edc_needed = phy->priv; /* on unplug retain EDC */ 1315 else if (ret == phy_modtype_twinax || 1316 ret == phy_modtype_twinax_long) 1317 edc_needed = edc_twinax; 1318 else 1319 edc_needed = edc_sr; 1320 1321 if (edc_needed != phy->priv) { 1322 ret = ael2005_reset(phy, 0); 1323 return ret ? ret : cphy_cause_module_change; 1324 } 1325 cause = cphy_cause_module_change; 1326 } 1327 1328 ret = t3_phy_lasi_intr_handler(phy); 1329 if (ret < 0) 1330 return ret; 1331 1332 ret |= cause; 1333 if (!ret) 1334 ret |= cphy_cause_link_change; 1335 return ret; 1336 } 1337 1338 static struct cphy_ops ael2005_ops = { 1339 #ifdef C99_NOT_SUPPORTED 1340 ael2005_reset, 1341 ael2005_intr_enable, 1342 ael2005_intr_disable, 1343 ael2005_intr_clear, 1344 ael2005_intr_handler, 1345 NULL, 1346 NULL, 1347 NULL, 1348 NULL, 1349 NULL, 1350 get_link_status_r, 1351 ael1002_power_down, 1352 #else 1353 .reset = ael2005_reset, 1354 .intr_enable = ael2005_intr_enable, 1355 .intr_disable = ael2005_intr_disable, 1356 .intr_clear = ael2005_intr_clear, 1357 .intr_handler = ael2005_intr_handler, 1358 .get_link_status = get_link_status_r, 1359 .power_down = ael1002_power_down, 1360 #endif 1361 }; 1362 1363 int t3_ael2005_phy_prep(pinfo_t *pinfo, int phy_addr, 1364 const struct mdio_ops *mdio_ops) 1365 { 1366 int err; 1367 struct cphy *phy = &pinfo->phy; 1368 1369 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael2005_ops, mdio_ops, 1370 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE | 1371 SUPPORTED_IRQ, "10GBASE-R"); 1372 msleep(125); 1373 ael_laser_down(phy, 0); 1374 1375 err = ael2005_get_module_type(phy, 0); 1376 if (err >= 0) 1377 phy->modtype = err; 1378 1379 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0, 1380 1 << 5); 1381 } 1382 1383 /* 1384 * Setup EDC and other parameters for operation with an optical module. 1385 */ 1386 static int ael2020_setup_sr_edc(struct cphy *phy) 1387 { 1388 static struct reg_val regs[] = { 1389 { MDIO_DEV_PMA_PMD, 0xcc01, 0xffff, 0x488a }, 1390 1391 { MDIO_DEV_PMA_PMD, 0xcb1b, 0xffff, 0x0200 }, 1392 { MDIO_DEV_PMA_PMD, 0xcb1c, 0xffff, 0x00f0 }, 1393 { MDIO_DEV_PMA_PMD, 0xcc06, 0xffff, 0x00e0 }, 1394 1395 /* end */ 1396 { 0, 0, 0, 0 } 1397 }; 1398 int err; 1399 1400 err = set_phy_regs(phy, regs); 1401 msleep(50); 1402 if (err) 1403 return err; 1404 1405 phy->priv = edc_sr; 1406 return 0; 1407 } 1408 1409 /* 1410 * Setup EDC and other parameters for operation with an TWINAX module. 1411 */ 1412 static int ael2020_setup_twinax_edc(struct cphy *phy, int modtype) 1413 { 1414 static struct reg_val uCclock40MHz[] = { 1415 { MDIO_DEV_PMA_PMD, 0xff28, 0xffff, 0x4001 }, 1416 { MDIO_DEV_PMA_PMD, 0xff2a, 0xffff, 0x0002 }, 1417 { 0, 0, 0, 0 } 1418 }; 1419 1420 static struct reg_val uCclockActivate[] = { 1421 { MDIO_DEV_PMA_PMD, 0xd000, 0xffff, 0x5200 }, 1422 { 0, 0, 0, 0 } 1423 }; 1424 1425 static struct reg_val uCactivate[] = { 1426 { MDIO_DEV_PMA_PMD, 0xd080, 0xffff, 0x0100 }, 1427 { MDIO_DEV_PMA_PMD, 0xd092, 0xffff, 0x0000 }, 1428 { 0, 0, 0, 0 } 1429 }; 1430 1431 static u16 twinax_edc[] = { 1432 0xd800, 0x4009, 1433 0xd801, 0x2fff, 1434 0xd802, 0x300f, 1435 0xd803, 0x40aa, 1436 0xd804, 0x401c, 1437 0xd805, 0x401e, 1438 0xd806, 0x2ff4, 1439 0xd807, 0x3dc4, 1440 0xd808, 0x2035, 1441 0xd809, 0x3035, 1442 0xd80a, 0x6524, 1443 0xd80b, 0x2cb2, 1444 0xd80c, 0x3012, 1445 0xd80d, 0x1002, 1446 0xd80e, 0x26e2, 1447 0xd80f, 0x3022, 1448 0xd810, 0x1002, 1449 0xd811, 0x27d2, 1450 0xd812, 0x3022, 1451 0xd813, 0x1002, 1452 0xd814, 0x2822, 1453 0xd815, 0x3012, 1454 0xd816, 0x1002, 1455 0xd817, 0x2492, 1456 0xd818, 0x3022, 1457 0xd819, 0x1002, 1458 0xd81a, 0x2772, 1459 0xd81b, 0x3012, 1460 0xd81c, 0x1002, 1461 0xd81d, 0x23d2, 1462 0xd81e, 0x3022, 1463 0xd81f, 0x1002, 1464 0xd820, 0x22cd, 1465 0xd821, 0x301d, 1466 0xd822, 0x27f2, 1467 0xd823, 0x3022, 1468 0xd824, 0x1002, 1469 0xd825, 0x5553, 1470 0xd826, 0x0307, 1471 0xd827, 0x2522, 1472 0xd828, 0x3022, 1473 0xd829, 0x1002, 1474 0xd82a, 0x2142, 1475 0xd82b, 0x3012, 1476 0xd82c, 0x1002, 1477 0xd82d, 0x4016, 1478 0xd82e, 0x5e63, 1479 0xd82f, 0x0344, 1480 0xd830, 0x2142, 1481 0xd831, 0x3012, 1482 0xd832, 0x1002, 1483 0xd833, 0x400e, 1484 0xd834, 0x2522, 1485 0xd835, 0x3022, 1486 0xd836, 0x1002, 1487 0xd837, 0x2b52, 1488 0xd838, 0x3012, 1489 0xd839, 0x1002, 1490 0xd83a, 0x2742, 1491 0xd83b, 0x3022, 1492 0xd83c, 0x1002, 1493 0xd83d, 0x25e2, 1494 0xd83e, 0x3022, 1495 0xd83f, 0x1002, 1496 0xd840, 0x2fa4, 1497 0xd841, 0x3dc4, 1498 0xd842, 0x6624, 1499 0xd843, 0x414b, 1500 0xd844, 0x56b3, 1501 0xd845, 0x03c6, 1502 0xd846, 0x866b, 1503 0xd847, 0x400c, 1504 0xd848, 0x2712, 1505 0xd849, 0x3012, 1506 0xd84a, 0x1002, 1507 0xd84b, 0x2c4b, 1508 0xd84c, 0x309b, 1509 0xd84d, 0x56b3, 1510 0xd84e, 0x03c3, 1511 0xd84f, 0x866b, 1512 0xd850, 0x400c, 1513 0xd851, 0x2272, 1514 0xd852, 0x3022, 1515 0xd853, 0x1002, 1516 0xd854, 0x2742, 1517 0xd855, 0x3022, 1518 0xd856, 0x1002, 1519 0xd857, 0x25e2, 1520 0xd858, 0x3022, 1521 0xd859, 0x1002, 1522 0xd85a, 0x2fb4, 1523 0xd85b, 0x3dc4, 1524 0xd85c, 0x6624, 1525 0xd85d, 0x56b3, 1526 0xd85e, 0x03c3, 1527 0xd85f, 0x866b, 1528 0xd860, 0x401c, 1529 0xd861, 0x2c45, 1530 0xd862, 0x3095, 1531 0xd863, 0x5b53, 1532 0xd864, 0x2372, 1533 0xd865, 0x3012, 1534 0xd866, 0x13c2, 1535 0xd867, 0x5cc3, 1536 0xd868, 0x2712, 1537 0xd869, 0x3012, 1538 0xd86a, 0x1312, 1539 0xd86b, 0x2b52, 1540 0xd86c, 0x3012, 1541 0xd86d, 0x1002, 1542 0xd86e, 0x2742, 1543 0xd86f, 0x3022, 1544 0xd870, 0x1002, 1545 0xd871, 0x2582, 1546 0xd872, 0x3022, 1547 0xd873, 0x1002, 1548 0xd874, 0x2142, 1549 0xd875, 0x3012, 1550 0xd876, 0x1002, 1551 0xd877, 0x628f, 1552 0xd878, 0x2985, 1553 0xd879, 0x33a5, 1554 0xd87a, 0x25e2, 1555 0xd87b, 0x3022, 1556 0xd87c, 0x1002, 1557 0xd87d, 0x5653, 1558 0xd87e, 0x03d2, 1559 0xd87f, 0x401e, 1560 0xd880, 0x6f72, 1561 0xd881, 0x1002, 1562 0xd882, 0x628f, 1563 0xd883, 0x2304, 1564 0xd884, 0x3c84, 1565 0xd885, 0x6436, 1566 0xd886, 0xdff4, 1567 0xd887, 0x6436, 1568 0xd888, 0x2ff5, 1569 0xd889, 0x3005, 1570 0xd88a, 0x8656, 1571 0xd88b, 0xdfba, 1572 0xd88c, 0x56a3, 1573 0xd88d, 0xd05a, 1574 0xd88e, 0x2972, 1575 0xd88f, 0x3012, 1576 0xd890, 0x1392, 1577 0xd891, 0xd05a, 1578 0xd892, 0x56a3, 1579 0xd893, 0xdfba, 1580 0xd894, 0x0383, 1581 0xd895, 0x6f72, 1582 0xd896, 0x1002, 1583 0xd897, 0x2b45, 1584 0xd898, 0x3005, 1585 0xd899, 0x4178, 1586 0xd89a, 0x5653, 1587 0xd89b, 0x0384, 1588 0xd89c, 0x2a62, 1589 0xd89d, 0x3012, 1590 0xd89e, 0x1002, 1591 0xd89f, 0x2f05, 1592 0xd8a0, 0x3005, 1593 0xd8a1, 0x41c8, 1594 0xd8a2, 0x5653, 1595 0xd8a3, 0x0382, 1596 0xd8a4, 0x0002, 1597 0xd8a5, 0x4218, 1598 0xd8a6, 0x2474, 1599 0xd8a7, 0x3c84, 1600 0xd8a8, 0x6437, 1601 0xd8a9, 0xdff4, 1602 0xd8aa, 0x6437, 1603 0xd8ab, 0x2ff5, 1604 0xd8ac, 0x3c05, 1605 0xd8ad, 0x8757, 1606 0xd8ae, 0xb888, 1607 0xd8af, 0x9787, 1608 0xd8b0, 0xdff4, 1609 0xd8b1, 0x6724, 1610 0xd8b2, 0x866a, 1611 0xd8b3, 0x6f72, 1612 0xd8b4, 0x1002, 1613 0xd8b5, 0x2641, 1614 0xd8b6, 0x3021, 1615 0xd8b7, 0x1001, 1616 0xd8b8, 0xc620, 1617 0xd8b9, 0x0000, 1618 0xd8ba, 0xc621, 1619 0xd8bb, 0x0000, 1620 0xd8bc, 0xc622, 1621 0xd8bd, 0x00ce, 1622 0xd8be, 0xc623, 1623 0xd8bf, 0x007f, 1624 0xd8c0, 0xc624, 1625 0xd8c1, 0x0032, 1626 0xd8c2, 0xc625, 1627 0xd8c3, 0x0000, 1628 0xd8c4, 0xc627, 1629 0xd8c5, 0x0000, 1630 0xd8c6, 0xc628, 1631 0xd8c7, 0x0000, 1632 0xd8c8, 0xc62c, 1633 0xd8c9, 0x0000, 1634 0xd8ca, 0x0000, 1635 0xd8cb, 0x2641, 1636 0xd8cc, 0x3021, 1637 0xd8cd, 0x1001, 1638 0xd8ce, 0xc502, 1639 0xd8cf, 0x53ac, 1640 0xd8d0, 0xc503, 1641 0xd8d1, 0x2cd3, 1642 0xd8d2, 0xc600, 1643 0xd8d3, 0x2a6e, 1644 0xd8d4, 0xc601, 1645 0xd8d5, 0x2a2c, 1646 0xd8d6, 0xc605, 1647 0xd8d7, 0x5557, 1648 0xd8d8, 0xc60c, 1649 0xd8d9, 0x5400, 1650 0xd8da, 0xc710, 1651 0xd8db, 0x0700, 1652 0xd8dc, 0xc711, 1653 0xd8dd, 0x0f06, 1654 0xd8de, 0xc718, 1655 0xd8df, 0x0700, 1656 0xd8e0, 0xc719, 1657 0xd8e1, 0x0f06, 1658 0xd8e2, 0xc720, 1659 0xd8e3, 0x4700, 1660 0xd8e4, 0xc721, 1661 0xd8e5, 0x0f06, 1662 0xd8e6, 0xc728, 1663 0xd8e7, 0x0700, 1664 0xd8e8, 0xc729, 1665 0xd8e9, 0x1207, 1666 0xd8ea, 0xc801, 1667 0xd8eb, 0x7f50, 1668 0xd8ec, 0xc802, 1669 0xd8ed, 0x7760, 1670 0xd8ee, 0xc803, 1671 0xd8ef, 0x7fce, 1672 0xd8f0, 0xc804, 1673 0xd8f1, 0x520e, 1674 0xd8f2, 0xc805, 1675 0xd8f3, 0x5c11, 1676 0xd8f4, 0xc806, 1677 0xd8f5, 0x3c51, 1678 0xd8f6, 0xc807, 1679 0xd8f7, 0x4061, 1680 0xd8f8, 0xc808, 1681 0xd8f9, 0x49c1, 1682 0xd8fa, 0xc809, 1683 0xd8fb, 0x3840, 1684 0xd8fc, 0xc80a, 1685 0xd8fd, 0x0000, 1686 0xd8fe, 0xc821, 1687 0xd8ff, 0x0002, 1688 0xd900, 0xc822, 1689 0xd901, 0x0046, 1690 0xd902, 0xc844, 1691 0xd903, 0x182f, 1692 0xd904, 0xc013, 1693 0xd905, 0xf341, 1694 0xd906, 0xc084, 1695 0xd907, 0x0030, 1696 0xd908, 0xc904, 1697 0xd909, 0x1401, 1698 0xd90a, 0xcb0c, 1699 0xd90b, 0x0004, 1700 0xd90c, 0xcb0e, 1701 0xd90d, 0xa00a, 1702 0xd90e, 0xcb0f, 1703 0xd90f, 0xc0c0, 1704 0xd910, 0xcb10, 1705 0xd911, 0xc0c0, 1706 0xd912, 0xcb11, 1707 0xd913, 0x00a0, 1708 0xd914, 0xcb12, 1709 0xd915, 0x0007, 1710 0xd916, 0xc241, 1711 0xd917, 0xa000, 1712 0xd918, 0xc243, 1713 0xd919, 0x7fe0, 1714 0xd91a, 0xc604, 1715 0xd91b, 0x000e, 1716 0xd91c, 0xc609, 1717 0xd91d, 0x00f5, 1718 0xd91e, 0xc611, 1719 0xd91f, 0x000e, 1720 0xd920, 0xc660, 1721 0xd921, 0x9600, 1722 0xd922, 0xc687, 1723 0xd923, 0x0004, 1724 0xd924, 0xc60a, 1725 0xd925, 0x04f5, 1726 0xd926, 0x0000, 1727 0xd927, 0x2641, 1728 0xd928, 0x3021, 1729 0xd929, 0x1001, 1730 0xd92a, 0xc620, 1731 0xd92b, 0x14e5, 1732 0xd92c, 0xc621, 1733 0xd92d, 0xc53d, 1734 0xd92e, 0xc622, 1735 0xd92f, 0x3cbe, 1736 0xd930, 0xc623, 1737 0xd931, 0x4452, 1738 0xd932, 0xc624, 1739 0xd933, 0xc5c5, 1740 0xd934, 0xc625, 1741 0xd935, 0xe01e, 1742 0xd936, 0xc627, 1743 0xd937, 0x0000, 1744 0xd938, 0xc628, 1745 0xd939, 0x0000, 1746 0xd93a, 0xc62c, 1747 0xd93b, 0x0000, 1748 0xd93c, 0x0000, 1749 0xd93d, 0x2b84, 1750 0xd93e, 0x3c74, 1751 0xd93f, 0x6435, 1752 0xd940, 0xdff4, 1753 0xd941, 0x6435, 1754 0xd942, 0x2806, 1755 0xd943, 0x3006, 1756 0xd944, 0x8565, 1757 0xd945, 0x2b24, 1758 0xd946, 0x3c24, 1759 0xd947, 0x6436, 1760 0xd948, 0x1002, 1761 0xd949, 0x2b24, 1762 0xd94a, 0x3c24, 1763 0xd94b, 0x6436, 1764 0xd94c, 0x4045, 1765 0xd94d, 0x8656, 1766 0xd94e, 0x5663, 1767 0xd94f, 0x0302, 1768 0xd950, 0x401e, 1769 0xd951, 0x1002, 1770 0xd952, 0x2807, 1771 0xd953, 0x31a7, 1772 0xd954, 0x20c4, 1773 0xd955, 0x3c24, 1774 0xd956, 0x6724, 1775 0xd957, 0x1002, 1776 0xd958, 0x2807, 1777 0xd959, 0x3187, 1778 0xd95a, 0x20c4, 1779 0xd95b, 0x3c24, 1780 0xd95c, 0x6724, 1781 0xd95d, 0x1002, 1782 0xd95e, 0x24f4, 1783 0xd95f, 0x3c64, 1784 0xd960, 0x6436, 1785 0xd961, 0xdff4, 1786 0xd962, 0x6436, 1787 0xd963, 0x1002, 1788 0xd964, 0x2006, 1789 0xd965, 0x3d76, 1790 0xd966, 0xc161, 1791 0xd967, 0x6134, 1792 0xd968, 0x6135, 1793 0xd969, 0x5443, 1794 0xd96a, 0x0303, 1795 0xd96b, 0x6524, 1796 0xd96c, 0x00fb, 1797 0xd96d, 0x1002, 1798 0xd96e, 0x20d4, 1799 0xd96f, 0x3c24, 1800 0xd970, 0x2025, 1801 0xd971, 0x3005, 1802 0xd972, 0x6524, 1803 0xd973, 0x1002, 1804 0xd974, 0xd019, 1805 0xd975, 0x2104, 1806 0xd976, 0x3c24, 1807 0xd977, 0x2105, 1808 0xd978, 0x3805, 1809 0xd979, 0x6524, 1810 0xd97a, 0xdff4, 1811 0xd97b, 0x4005, 1812 0xd97c, 0x6524, 1813 0xd97d, 0x2e8d, 1814 0xd97e, 0x303d, 1815 0xd97f, 0x2408, 1816 0xd980, 0x35d8, 1817 0xd981, 0x5dd3, 1818 0xd982, 0x0307, 1819 0xd983, 0x8887, 1820 0xd984, 0x63a7, 1821 0xd985, 0x8887, 1822 0xd986, 0x63a7, 1823 0xd987, 0xdffd, 1824 0xd988, 0x00f9, 1825 0xd989, 0x1002, 1826 0xd98a, 0x0000, 1827 }; 1828 int i, err; 1829 1830 /* set uC clock and activate it */ 1831 err = set_phy_regs(phy, uCclock40MHz); 1832 msleep(500); 1833 if (err) 1834 return err; 1835 err = set_phy_regs(phy, uCclockActivate); 1836 msleep(500); 1837 if (err) 1838 return err; 1839 1840 for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2) 1841 err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i], 1842 twinax_edc[i + 1]); 1843 /* activate uC */ 1844 err = set_phy_regs(phy, uCactivate); 1845 if (!err) 1846 phy->priv = edc_twinax; 1847 return err; 1848 } 1849 1850 /* 1851 * Return Module Type. 1852 */ 1853 static int ael2020_get_module_type(struct cphy *phy, int delay_ms) 1854 { 1855 int v; 1856 unsigned int stat; 1857 1858 v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2020_GPIO_STAT, &stat); 1859 if (v) 1860 return v; 1861 1862 if (stat & (0x1 << (AEL2020_GPIO_MODDET*4))) { 1863 /* module absent */ 1864 return phy_modtype_none; 1865 } 1866 1867 return ael2xxx_get_module_type(phy, delay_ms); 1868 } 1869 1870 /* 1871 * Enable PHY interrupts. We enable "Module Detection" interrupts (on any 1872 * state transition) and then generic Link Alarm Status Interrupt (LASI). 1873 */ 1874 static int ael2020_intr_enable(struct cphy *phy) 1875 { 1876 struct reg_val regs[] = { 1877 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CFG+AEL2020_GPIO_LSTAT, 1878 0xffff, 0x4 }, 1879 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL, 1880 0xffff, 0x8 << (AEL2020_GPIO_LSTAT*4) }, 1881 1882 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL, 1883 0xffff, 0x2 << (AEL2020_GPIO_MODDET*4) }, 1884 1885 /* end */ 1886 { 0, 0, 0, 0 } 1887 }; 1888 int err; 1889 1890 err = set_phy_regs(phy, regs); 1891 if (err) 1892 return err; 1893 1894 phy->caps |= POLL_LINK_1ST_TIME; 1895 1896 /* enable standard Link Alarm Status Interrupts */ 1897 err = t3_phy_lasi_intr_enable(phy); 1898 if (err) 1899 return err; 1900 1901 return 0; 1902 } 1903 1904 /* 1905 * Disable PHY interrupts. The mirror of the above ... 1906 */ 1907 static int ael2020_intr_disable(struct cphy *phy) 1908 { 1909 struct reg_val regs[] = { 1910 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL, 1911 0xffff, 0xb << (AEL2020_GPIO_LSTAT*4) }, 1912 1913 { MDIO_DEV_PMA_PMD, AEL2020_GPIO_CTRL, 1914 0xffff, 0x1 << (AEL2020_GPIO_MODDET*4) }, 1915 1916 /* end */ 1917 { 0, 0, 0, 0 } 1918 }; 1919 int err; 1920 1921 err = set_phy_regs(phy, regs); 1922 if (err) 1923 return err; 1924 1925 /* disable standard Link Alarm Status Interrupts */ 1926 return t3_phy_lasi_intr_disable(phy); 1927 } 1928 1929 /* 1930 * Clear PHY interrupt state. 1931 */ 1932 static int ael2020_intr_clear(struct cphy *phy) 1933 { 1934 unsigned int stat; 1935 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2020_GPIO_INTR, &stat); 1936 return err ? err : t3_phy_lasi_intr_clear(phy); 1937 } 1938 1939 /* 1940 * Common register settings for the AEL2020 when it comes out of reset. 1941 */ 1942 static struct reg_val ael2020_reset_regs[] = { 1943 { MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x3101 }, 1944 1945 { MDIO_DEV_PMA_PMD, 0xcd40, 0xffff, 0x0001 }, 1946 1947 { MDIO_DEV_PMA_PMD, 0xff02, 0xffff, 0x0023 }, 1948 { MDIO_DEV_PMA_PMD, 0xff03, 0xffff, 0x0000 }, 1949 { MDIO_DEV_PMA_PMD, 0xff04, 0xffff, 0x0000 }, 1950 1951 /* end */ 1952 { 0, 0, 0, 0 } 1953 }; 1954 1955 /* 1956 * Reset the PHY and put it into a canonical operating state. 1957 */ 1958 static int ael2020_reset(struct cphy *phy, int wait) 1959 { 1960 int err; 1961 unsigned int lasi_ctrl; 1962 1963 /* grab current interrupt state */ 1964 err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl); 1965 if (err) 1966 return err; 1967 1968 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 125); 1969 if (err) 1970 return err; 1971 msleep(100); 1972 1973 /* basic initialization for all module types */ 1974 phy->priv = edc_none; 1975 err = set_phy_regs(phy, ael2020_reset_regs); 1976 if (err) 1977 return err; 1978 1979 /* determine module type and perform appropriate initialization */ 1980 err = ael2020_get_module_type(phy, 0); 1981 if (err < 0) 1982 return err; 1983 phy->modtype = (u8)err; 1984 if (err == phy_modtype_none) 1985 err = 0; 1986 else if (err == phy_modtype_twinax || err == phy_modtype_twinax_long) 1987 err = ael2020_setup_twinax_edc(phy, err); 1988 else 1989 err = ael2020_setup_sr_edc(phy); 1990 if (err) 1991 return err; 1992 1993 /* reset wipes out interrupts, reenable them if they were on */ 1994 if (lasi_ctrl & 1) 1995 err = ael2020_intr_enable(phy); 1996 return err; 1997 } 1998 1999 /* 2000 * Handle a PHY interrupt. 2001 */ 2002 static int ael2020_intr_handler(struct cphy *phy) 2003 { 2004 unsigned int stat; 2005 int ret, edc_needed, cause = 0; 2006 2007 ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2020_GPIO_INTR, &stat); 2008 if (ret) 2009 return ret; 2010 2011 if (stat & (0x1 << AEL2020_GPIO_MODDET)) { 2012 /* modules have max 300 ms init time after hot plug */ 2013 ret = ael2020_get_module_type(phy, 300); 2014 if (ret < 0) 2015 return ret; 2016 2017 phy->modtype = (u8)ret; 2018 if (ret == phy_modtype_none) 2019 edc_needed = phy->priv; /* on unplug retain EDC */ 2020 else if (ret == phy_modtype_twinax || 2021 ret == phy_modtype_twinax_long) 2022 edc_needed = edc_twinax; 2023 else 2024 edc_needed = edc_sr; 2025 2026 if (edc_needed != phy->priv) { 2027 ret = ael2020_reset(phy, 0); 2028 return ret ? ret : cphy_cause_module_change; 2029 } 2030 cause = cphy_cause_module_change; 2031 } 2032 2033 ret = t3_phy_lasi_intr_handler(phy); 2034 if (ret < 0) 2035 return ret; 2036 2037 ret |= cause; 2038 if (!ret) 2039 ret |= cphy_cause_link_change; 2040 return ret; 2041 } 2042 2043 static struct cphy_ops ael2020_ops = { 2044 #ifdef C99_NOT_SUPPORTED 2045 ael2020_reset, 2046 ael2020_intr_enable, 2047 ael2020_intr_disable, 2048 ael2020_intr_clear, 2049 ael2020_intr_handler, 2050 NULL, 2051 NULL, 2052 NULL, 2053 NULL, 2054 NULL, 2055 get_link_status_r, 2056 ael1002_power_down, 2057 #else 2058 .reset = ael2020_reset, 2059 .intr_enable = ael2020_intr_enable, 2060 .intr_disable = ael2020_intr_disable, 2061 .intr_clear = ael2020_intr_clear, 2062 .intr_handler = ael2020_intr_handler, 2063 .get_link_status = get_link_status_r, 2064 .power_down = ael1002_power_down, 2065 #endif 2066 }; 2067 2068 int t3_ael2020_phy_prep(pinfo_t *pinfo, int phy_addr, 2069 const struct mdio_ops *mdio_ops) 2070 { 2071 int err; 2072 struct cphy *phy = &pinfo->phy; 2073 2074 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &ael2020_ops, mdio_ops, 2075 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE | 2076 SUPPORTED_IRQ, "10GBASE-R"); 2077 msleep(125); 2078 2079 err = set_phy_regs(phy, ael2020_reset_regs); 2080 if (err) 2081 return err; 2082 err = ael2020_get_module_type(phy, 0); 2083 if (err >= 0) 2084 phy->modtype = err; 2085 2086 ael_laser_down(phy, 0); 2087 return 0; 2088 } 2089 2090 /* 2091 * Get link status for a 10GBASE-X device. 2092 */ 2093 static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed, 2094 int *duplex, int *fc) 2095 { 2096 if (link_ok) { 2097 unsigned int stat0, stat1, stat2; 2098 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0); 2099 2100 if (!err) 2101 err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_X, &stat1); 2102 if (!err) 2103 err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2); 2104 if (err) 2105 return err; 2106 *link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1; 2107 } 2108 if (speed) 2109 *speed = SPEED_10000; 2110 if (duplex) 2111 *duplex = DUPLEX_FULL; 2112 return 0; 2113 } 2114 2115 #ifdef C99_NOT_SUPPORTED 2116 static struct cphy_ops qt2045_ops = { 2117 ael1006_reset, 2118 t3_phy_lasi_intr_enable, 2119 t3_phy_lasi_intr_disable, 2120 t3_phy_lasi_intr_clear, 2121 t3_phy_lasi_intr_handler, 2122 NULL, 2123 NULL, 2124 NULL, 2125 NULL, 2126 NULL, 2127 get_link_status_x, 2128 ael1002_power_down, 2129 }; 2130 #else 2131 static struct cphy_ops qt2045_ops = { 2132 .reset = ael1006_reset, 2133 .intr_enable = t3_phy_lasi_intr_enable, 2134 .intr_disable = t3_phy_lasi_intr_disable, 2135 .intr_clear = t3_phy_lasi_intr_clear, 2136 .intr_handler = t3_phy_lasi_intr_handler, 2137 .get_link_status = get_link_status_x, 2138 .power_down = ael1002_power_down, 2139 }; 2140 #endif 2141 2142 int t3_qt2045_phy_prep(pinfo_t *pinfo, int phy_addr, 2143 const struct mdio_ops *mdio_ops) 2144 { 2145 unsigned int stat; 2146 struct cphy *phy = &pinfo->phy; 2147 2148 cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &qt2045_ops, mdio_ops, 2149 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP, 2150 "10GBASE-CX4"); 2151 2152 /* 2153 * Some cards where the PHY is supposed to be at address 0 actually 2154 * have it at 1. 2155 */ 2156 if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) && 2157 stat == 0xffff) 2158 phy->addr = 1; 2159 return 0; 2160 } 2161 2162 static int xaui_direct_reset(struct cphy *phy, int wait) 2163 { 2164 return 0; 2165 } 2166 2167 static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok, 2168 int *speed, int *duplex, int *fc) 2169 { 2170 if (link_ok) { 2171 unsigned int status; 2172 adapter_t *adapter = phy->adapter; 2173 2174 status = t3_read_reg(adapter, 2175 XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) | 2176 t3_read_reg(adapter, 2177 XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) | 2178 t3_read_reg(adapter, 2179 XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) | 2180 t3_read_reg(adapter, 2181 XGM_REG(A_XGM_SERDES_STAT3, phy->addr)); 2182 *link_ok = !(status & F_LOWSIG0); 2183 } 2184 if (speed) 2185 *speed = SPEED_10000; 2186 if (duplex) 2187 *duplex = DUPLEX_FULL; 2188 return 0; 2189 } 2190 2191 static int xaui_direct_power_down(struct cphy *phy, int enable) 2192 { 2193 return 0; 2194 } 2195 2196 #ifdef C99_NOT_SUPPORTED 2197 static struct cphy_ops xaui_direct_ops = { 2198 xaui_direct_reset, 2199 ael1002_intr_noop, 2200 ael1002_intr_noop, 2201 ael1002_intr_noop, 2202 ael1002_intr_noop, 2203 NULL, 2204 NULL, 2205 NULL, 2206 NULL, 2207 NULL, 2208 xaui_direct_get_link_status, 2209 xaui_direct_power_down, 2210 }; 2211 #else 2212 static struct cphy_ops xaui_direct_ops = { 2213 .reset = xaui_direct_reset, 2214 .intr_enable = ael1002_intr_noop, 2215 .intr_disable = ael1002_intr_noop, 2216 .intr_clear = ael1002_intr_noop, 2217 .intr_handler = ael1002_intr_noop, 2218 .get_link_status = xaui_direct_get_link_status, 2219 .power_down = xaui_direct_power_down, 2220 }; 2221 #endif 2222 2223 int t3_xaui_direct_phy_prep(pinfo_t *pinfo, int phy_addr, 2224 const struct mdio_ops *mdio_ops) 2225 { 2226 cphy_init(&pinfo->phy, pinfo->adapter, pinfo, phy_addr, &xaui_direct_ops, mdio_ops, 2227 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP, 2228 "10GBASE-CX4"); 2229 return 0; 2230 } 2231