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 AEL1002_PWR_DOWN_HI = 0xc011, 49 AEL1002_PWR_DOWN_LO = 0xc012, 50 AEL1002_XFI_EQL = 0xc015, 51 AEL1002_LB_EN = 0xc017, 52 AEL_OPT_SETTINGS = 0xc017, 53 AEL_I2C_CTRL = 0xc30a, 54 AEL_I2C_DATA = 0xc30b, 55 AEL_I2C_STAT = 0xc30c, 56 AEL2005_GPIO_CTRL = 0xc214, 57 AEL2005_GPIO_STAT = 0xc215, 58 }; 59 60 enum { edc_none, edc_sr, edc_twinax }; 61 62 /* PHY module I2C device address */ 63 enum { 64 MODULE_DEV_ADDR = 0xa0, 65 SFF_DEV_ADDR = 0xa2, 66 }; 67 68 /* PHY transceiver type */ 69 enum { 70 phy_transtype_unknown = 0, 71 phy_transtype_sfp = 3, 72 phy_transtype_xfp = 6, 73 }; 74 75 #define AEL2005_MODDET_IRQ 4 76 77 struct reg_val { 78 unsigned short mmd_addr; 79 unsigned short reg_addr; 80 unsigned short clear_bits; 81 unsigned short set_bits; 82 }; 83 84 static int get_module_type(struct cphy *phy); 85 86 static int set_phy_regs(struct cphy *phy, const struct reg_val *rv) 87 { 88 int err; 89 90 for (err = 0; rv->mmd_addr && !err; rv++) { 91 if (rv->clear_bits == 0xffff) 92 err = mdio_write(phy, rv->mmd_addr, rv->reg_addr, 93 rv->set_bits); 94 else 95 err = t3_mdio_change_bits(phy, rv->mmd_addr, 96 rv->reg_addr, rv->clear_bits, 97 rv->set_bits); 98 } 99 return err; 100 } 101 102 static void ael100x_txon(struct cphy *phy) 103 { 104 int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL; 105 106 msleep(100); 107 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio); 108 msleep(30); 109 } 110 111 static int ael_i2c_rd(struct cphy *phy, int dev_addr, int word_addr) 112 { 113 int i, err; 114 unsigned int stat, data; 115 116 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL, 117 (dev_addr << 8) | (1 << 8) | word_addr); 118 if (err) 119 return err; 120 121 for (i = 0; i < 200; i++) { 122 msleep(1); 123 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat); 124 if (err) 125 return err; 126 if ((stat & 3) == 1) { 127 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA, 128 &data); 129 if (err) 130 return err; 131 return data >> 8; 132 } 133 } 134 CH_WARN(phy->adapter, "PHY %u I2C read of addr %u timed out\n", 135 phy->addr, word_addr); 136 return -ETIMEDOUT; 137 } 138 139 static int ael_i2c_wr(struct cphy *phy, int dev_addr, int word_addr, int data) 140 { 141 int i, err; 142 unsigned int stat; 143 144 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_DATA, data); 145 if (err) 146 return err; 147 148 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL_I2C_CTRL, 149 (dev_addr << 8) | word_addr); 150 if (err) 151 return err; 152 153 for (i = 0; i < 200; i++) { 154 msleep(1); 155 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL_I2C_STAT, &stat); 156 if (err) 157 return err; 158 if ((stat & 3) == 1) 159 return 0; 160 } 161 CH_WARN(phy->adapter, "PHY %u I2C Write of addr %u timed out\n", 162 phy->addr, word_addr); 163 return -ETIMEDOUT; 164 } 165 166 static int get_phytrans_type(struct cphy *phy) 167 { 168 int v; 169 170 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0); 171 if (v < 0) 172 return phy_transtype_unknown; 173 174 return v; 175 } 176 177 static int ael_laser_down(struct cphy *phy, int enable) 178 { 179 int v, dev_addr; 180 181 v = get_phytrans_type(phy); 182 if (v < 0) 183 return v; 184 185 if (v == phy_transtype_sfp) { 186 /* Check SFF Soft TX disable is supported */ 187 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 93); 188 if (v < 0) 189 return v; 190 191 v &= 0x40; 192 if (!v) 193 return v; 194 195 dev_addr = SFF_DEV_ADDR; 196 } else if (v == phy_transtype_xfp) 197 dev_addr = MODULE_DEV_ADDR; 198 else 199 return v; 200 201 v = ael_i2c_rd(phy, dev_addr, 110); 202 if (v < 0) 203 return v; 204 205 if (enable) 206 v |= 0x40; 207 else 208 v &= ~0x40; 209 210 v = ael_i2c_wr(phy, dev_addr, 110, v); 211 212 return v; 213 } 214 215 static int ael1002_power_down(struct cphy *phy, int enable) 216 { 217 int err; 218 219 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable); 220 if (!err) 221 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 222 BMCR_PDOWN, enable ? BMCR_PDOWN : 0); 223 return err; 224 } 225 226 static int ael1002_get_module_type(struct cphy *phy, int delay_ms) 227 { 228 int v; 229 230 if (delay_ms) 231 msleep(delay_ms); 232 233 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0); 234 235 return v == -ETIMEDOUT ? phy_modtype_none : get_module_type(phy); 236 } 237 238 static int ael1002_reset(struct cphy *phy, int wait) 239 { 240 int err; 241 242 if ((err = ael1002_power_down(phy, 0)) || 243 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) || 244 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) || 245 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) || 246 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) || 247 (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN, 248 0, 1 << 5))) 249 return err; 250 251 err = ael1002_get_module_type(phy, 300); 252 if (err >= 0) 253 phy->modtype = err; 254 255 return 0; 256 } 257 258 static int ael1002_intr_noop(struct cphy *phy) 259 { 260 return 0; 261 } 262 263 /* 264 * Get link status for a 10GBASE-R device. 265 */ 266 static int get_link_status_r(struct cphy *phy, int *link_ok, int *speed, 267 int *duplex, int *fc) 268 { 269 if (link_ok) { 270 unsigned int stat0, stat1, stat2; 271 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0); 272 273 if (!err) 274 err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_R, &stat1); 275 if (!err) 276 err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2); 277 if (err) 278 return err; 279 *link_ok = (stat0 & stat1 & (stat2 >> 12)) & 1; 280 } 281 if (speed) 282 *speed = SPEED_10000; 283 if (duplex) 284 *duplex = DUPLEX_FULL; 285 return 0; 286 } 287 288 #ifdef C99_NOT_SUPPORTED 289 static struct cphy_ops ael1002_ops = { 290 ael1002_reset, 291 ael1002_intr_noop, 292 ael1002_intr_noop, 293 ael1002_intr_noop, 294 ael1002_intr_noop, 295 NULL, 296 NULL, 297 NULL, 298 NULL, 299 NULL, 300 get_link_status_r, 301 ael1002_power_down, 302 }; 303 #else 304 static struct cphy_ops ael1002_ops = { 305 .reset = ael1002_reset, 306 .intr_enable = ael1002_intr_noop, 307 .intr_disable = ael1002_intr_noop, 308 .intr_clear = ael1002_intr_noop, 309 .intr_handler = ael1002_intr_noop, 310 .get_link_status = get_link_status_r, 311 .power_down = ael1002_power_down, 312 }; 313 #endif 314 315 int t3_ael1002_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 316 const struct mdio_ops *mdio_ops) 317 { 318 int err; 319 320 cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops, 321 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE, 322 "10GBASE-R"); 323 ael100x_txon(phy); 324 ael_laser_down(phy, 0); 325 326 err = ael1002_get_module_type(phy, 0); 327 if (err >= 0) 328 phy->modtype = err; 329 330 return 0; 331 } 332 333 static int ael1006_reset(struct cphy *phy, int wait) 334 { 335 int err; 336 337 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait); 338 if (err) 339 return err; 340 341 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 342 F_GPIO6_OUT_VAL, 0); 343 344 msleep(125); 345 346 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 347 F_GPIO6_OUT_VAL, F_GPIO6_OUT_VAL); 348 349 msleep(125); 350 351 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait); 352 if (err) 353 return err; 354 355 msleep(125); 356 357 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 1); 358 if (err) 359 return err; 360 361 msleep(125); 362 363 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 1, 0); 364 365 return err; 366 367 } 368 369 static int ael1006_power_down(struct cphy *phy, int enable) 370 { 371 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 372 BMCR_PDOWN, enable ? BMCR_PDOWN : 0); 373 } 374 375 #ifdef C99_NOT_SUPPORTED 376 static struct cphy_ops ael1006_ops = { 377 ael1006_reset, 378 t3_phy_lasi_intr_enable, 379 t3_phy_lasi_intr_disable, 380 t3_phy_lasi_intr_clear, 381 t3_phy_lasi_intr_handler, 382 NULL, 383 NULL, 384 NULL, 385 NULL, 386 NULL, 387 get_link_status_r, 388 ael1006_power_down, 389 }; 390 #else 391 static struct cphy_ops ael1006_ops = { 392 .reset = ael1006_reset, 393 .intr_enable = t3_phy_lasi_intr_enable, 394 .intr_disable = t3_phy_lasi_intr_disable, 395 .intr_clear = t3_phy_lasi_intr_clear, 396 .intr_handler = t3_phy_lasi_intr_handler, 397 .get_link_status = get_link_status_r, 398 .power_down = ael1006_power_down, 399 }; 400 #endif 401 402 int t3_ael1006_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 403 const struct mdio_ops *mdio_ops) 404 { 405 cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops, 406 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE, 407 "10GBASE-SR"); 408 ael100x_txon(phy); 409 return 0; 410 } 411 412 static int ael2005_setup_sr_edc(struct cphy *phy) 413 { 414 static struct reg_val regs[] = { 415 { MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x181 }, 416 { MDIO_DEV_PMA_PMD, 0xc010, 0xffff, 0x448a }, 417 { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5200 }, 418 { 0, 0, 0, 0 } 419 }; 420 static u16 sr_edc[] = { 421 0xcc00, 0x2ff4, 422 0xcc01, 0x3cd4, 423 0xcc02, 0x2015, 424 0xcc03, 0x3105, 425 0xcc04, 0x6524, 426 0xcc05, 0x27ff, 427 0xcc06, 0x300f, 428 0xcc07, 0x2c8b, 429 0xcc08, 0x300b, 430 0xcc09, 0x4009, 431 0xcc0a, 0x400e, 432 0xcc0b, 0x2f72, 433 0xcc0c, 0x3002, 434 0xcc0d, 0x1002, 435 0xcc0e, 0x2172, 436 0xcc0f, 0x3012, 437 0xcc10, 0x1002, 438 0xcc11, 0x25d2, 439 0xcc12, 0x3012, 440 0xcc13, 0x1002, 441 0xcc14, 0xd01e, 442 0xcc15, 0x27d2, 443 0xcc16, 0x3012, 444 0xcc17, 0x1002, 445 0xcc18, 0x2004, 446 0xcc19, 0x3c84, 447 0xcc1a, 0x6436, 448 0xcc1b, 0x2007, 449 0xcc1c, 0x3f87, 450 0xcc1d, 0x8676, 451 0xcc1e, 0x40b7, 452 0xcc1f, 0xa746, 453 0xcc20, 0x4047, 454 0xcc21, 0x5673, 455 0xcc22, 0x2982, 456 0xcc23, 0x3002, 457 0xcc24, 0x13d2, 458 0xcc25, 0x8bbd, 459 0xcc26, 0x2862, 460 0xcc27, 0x3012, 461 0xcc28, 0x1002, 462 0xcc29, 0x2092, 463 0xcc2a, 0x3012, 464 0xcc2b, 0x1002, 465 0xcc2c, 0x5cc3, 466 0xcc2d, 0x314, 467 0xcc2e, 0x2942, 468 0xcc2f, 0x3002, 469 0xcc30, 0x1002, 470 0xcc31, 0xd019, 471 0xcc32, 0x2032, 472 0xcc33, 0x3012, 473 0xcc34, 0x1002, 474 0xcc35, 0x2a04, 475 0xcc36, 0x3c74, 476 0xcc37, 0x6435, 477 0xcc38, 0x2fa4, 478 0xcc39, 0x3cd4, 479 0xcc3a, 0x6624, 480 0xcc3b, 0x5563, 481 0xcc3c, 0x2d42, 482 0xcc3d, 0x3002, 483 0xcc3e, 0x13d2, 484 0xcc3f, 0x464d, 485 0xcc40, 0x2862, 486 0xcc41, 0x3012, 487 0xcc42, 0x1002, 488 0xcc43, 0x2032, 489 0xcc44, 0x3012, 490 0xcc45, 0x1002, 491 0xcc46, 0x2fb4, 492 0xcc47, 0x3cd4, 493 0xcc48, 0x6624, 494 0xcc49, 0x5563, 495 0xcc4a, 0x2d42, 496 0xcc4b, 0x3002, 497 0xcc4c, 0x13d2, 498 0xcc4d, 0x2ed2, 499 0xcc4e, 0x3002, 500 0xcc4f, 0x1002, 501 0xcc50, 0x2fd2, 502 0xcc51, 0x3002, 503 0xcc52, 0x1002, 504 0xcc53, 0x004, 505 0xcc54, 0x2942, 506 0xcc55, 0x3002, 507 0xcc56, 0x1002, 508 0xcc57, 0x2092, 509 0xcc58, 0x3012, 510 0xcc59, 0x1002, 511 0xcc5a, 0x5cc3, 512 0xcc5b, 0x317, 513 0xcc5c, 0x2f72, 514 0xcc5d, 0x3002, 515 0xcc5e, 0x1002, 516 0xcc5f, 0x2942, 517 0xcc60, 0x3002, 518 0xcc61, 0x1002, 519 0xcc62, 0x22cd, 520 0xcc63, 0x301d, 521 0xcc64, 0x2862, 522 0xcc65, 0x3012, 523 0xcc66, 0x1002, 524 0xcc67, 0x2ed2, 525 0xcc68, 0x3002, 526 0xcc69, 0x1002, 527 0xcc6a, 0x2d72, 528 0xcc6b, 0x3002, 529 0xcc6c, 0x1002, 530 0xcc6d, 0x628f, 531 0xcc6e, 0x2112, 532 0xcc6f, 0x3012, 533 0xcc70, 0x1002, 534 0xcc71, 0x5aa3, 535 0xcc72, 0x2dc2, 536 0xcc73, 0x3002, 537 0xcc74, 0x1312, 538 0xcc75, 0x6f72, 539 0xcc76, 0x1002, 540 0xcc77, 0x2807, 541 0xcc78, 0x31a7, 542 0xcc79, 0x20c4, 543 0xcc7a, 0x3c24, 544 0xcc7b, 0x6724, 545 0xcc7c, 0x1002, 546 0xcc7d, 0x2807, 547 0xcc7e, 0x3187, 548 0xcc7f, 0x20c4, 549 0xcc80, 0x3c24, 550 0xcc81, 0x6724, 551 0xcc82, 0x1002, 552 0xcc83, 0x2514, 553 0xcc84, 0x3c64, 554 0xcc85, 0x6436, 555 0xcc86, 0xdff4, 556 0xcc87, 0x6436, 557 0xcc88, 0x1002, 558 0xcc89, 0x40a4, 559 0xcc8a, 0x643c, 560 0xcc8b, 0x4016, 561 0xcc8c, 0x8c6c, 562 0xcc8d, 0x2b24, 563 0xcc8e, 0x3c24, 564 0xcc8f, 0x6435, 565 0xcc90, 0x1002, 566 0xcc91, 0x2b24, 567 0xcc92, 0x3c24, 568 0xcc93, 0x643a, 569 0xcc94, 0x4025, 570 0xcc95, 0x8a5a, 571 0xcc96, 0x1002, 572 0xcc97, 0x2731, 573 0xcc98, 0x3011, 574 0xcc99, 0x1001, 575 0xcc9a, 0xc7a0, 576 0xcc9b, 0x100, 577 0xcc9c, 0xc502, 578 0xcc9d, 0x53ac, 579 0xcc9e, 0xc503, 580 0xcc9f, 0xd5d5, 581 0xcca0, 0xc600, 582 0xcca1, 0x2a6d, 583 0xcca2, 0xc601, 584 0xcca3, 0x2a4c, 585 0xcca4, 0xc602, 586 0xcca5, 0x111, 587 0xcca6, 0xc60c, 588 0xcca7, 0x5900, 589 0xcca8, 0xc710, 590 0xcca9, 0x700, 591 0xccaa, 0xc718, 592 0xccab, 0x700, 593 0xccac, 0xc720, 594 0xccad, 0x4700, 595 0xccae, 0xc801, 596 0xccaf, 0x7f50, 597 0xccb0, 0xc802, 598 0xccb1, 0x7760, 599 0xccb2, 0xc803, 600 0xccb3, 0x7fce, 601 0xccb4, 0xc804, 602 0xccb5, 0x5700, 603 0xccb6, 0xc805, 604 0xccb7, 0x5f11, 605 0xccb8, 0xc806, 606 0xccb9, 0x4751, 607 0xccba, 0xc807, 608 0xccbb, 0x57e1, 609 0xccbc, 0xc808, 610 0xccbd, 0x2700, 611 0xccbe, 0xc809, 612 0xccbf, 0x000, 613 0xccc0, 0xc821, 614 0xccc1, 0x002, 615 0xccc2, 0xc822, 616 0xccc3, 0x014, 617 0xccc4, 0xc832, 618 0xccc5, 0x1186, 619 0xccc6, 0xc847, 620 0xccc7, 0x1e02, 621 0xccc8, 0xc013, 622 0xccc9, 0xf341, 623 0xccca, 0xc01a, 624 0xcccb, 0x446, 625 0xcccc, 0xc024, 626 0xcccd, 0x1000, 627 0xccce, 0xc025, 628 0xcccf, 0xa00, 629 0xccd0, 0xc026, 630 0xccd1, 0xc0c, 631 0xccd2, 0xc027, 632 0xccd3, 0xc0c, 633 0xccd4, 0xc029, 634 0xccd5, 0x0a0, 635 0xccd6, 0xc030, 636 0xccd7, 0xa00, 637 0xccd8, 0xc03c, 638 0xccd9, 0x01c, 639 0xccda, 0xc005, 640 0xccdb, 0x7a06, 641 0xccdc, 0x000, 642 0xccdd, 0x2731, 643 0xccde, 0x3011, 644 0xccdf, 0x1001, 645 0xcce0, 0xc620, 646 0xcce1, 0x000, 647 0xcce2, 0xc621, 648 0xcce3, 0x03f, 649 0xcce4, 0xc622, 650 0xcce5, 0x000, 651 0xcce6, 0xc623, 652 0xcce7, 0x000, 653 0xcce8, 0xc624, 654 0xcce9, 0x000, 655 0xccea, 0xc625, 656 0xcceb, 0x000, 657 0xccec, 0xc627, 658 0xcced, 0x000, 659 0xccee, 0xc628, 660 0xccef, 0x000, 661 0xccf0, 0xc62c, 662 0xccf1, 0x000, 663 0xccf2, 0x000, 664 0xccf3, 0x2806, 665 0xccf4, 0x3cb6, 666 0xccf5, 0xc161, 667 0xccf6, 0x6134, 668 0xccf7, 0x6135, 669 0xccf8, 0x5443, 670 0xccf9, 0x303, 671 0xccfa, 0x6524, 672 0xccfb, 0x00b, 673 0xccfc, 0x1002, 674 0xccfd, 0x2104, 675 0xccfe, 0x3c24, 676 0xccff, 0x2105, 677 0xcd00, 0x3805, 678 0xcd01, 0x6524, 679 0xcd02, 0xdff4, 680 0xcd03, 0x4005, 681 0xcd04, 0x6524, 682 0xcd05, 0x1002, 683 0xcd06, 0x5dd3, 684 0xcd07, 0x306, 685 0xcd08, 0x2ff7, 686 0xcd09, 0x38f7, 687 0xcd0a, 0x60b7, 688 0xcd0b, 0xdffd, 689 0xcd0c, 0x00a, 690 0xcd0d, 0x1002, 691 0xcd0e, 0 692 }; 693 int i, err; 694 695 err = set_phy_regs(phy, regs); 696 if (err) 697 return err; 698 699 msleep(50); 700 701 for (i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2) 702 err = mdio_write(phy, MDIO_DEV_PMA_PMD, sr_edc[i], 703 sr_edc[i + 1]); 704 if (!err) 705 phy->priv = edc_sr; 706 return err; 707 } 708 709 static int ael2005_setup_twinax_edc(struct cphy *phy, int modtype) 710 { 711 static struct reg_val regs[] = { 712 { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5a00 }, 713 { 0, 0, 0, 0 } 714 }; 715 static struct reg_val preemphasis[] = { 716 { MDIO_DEV_PMA_PMD, 0xc014, 0xffff, 0xfe16 }, 717 { MDIO_DEV_PMA_PMD, 0xc015, 0xffff, 0xa000 }, 718 { 0, 0, 0, 0 } 719 }; 720 static u16 twinax_edc[] = { 721 0xcc00, 0x4009, 722 0xcc01, 0x27ff, 723 0xcc02, 0x300f, 724 0xcc03, 0x40aa, 725 0xcc04, 0x401c, 726 0xcc05, 0x401e, 727 0xcc06, 0x2ff4, 728 0xcc07, 0x3cd4, 729 0xcc08, 0x2035, 730 0xcc09, 0x3145, 731 0xcc0a, 0x6524, 732 0xcc0b, 0x26a2, 733 0xcc0c, 0x3012, 734 0xcc0d, 0x1002, 735 0xcc0e, 0x29c2, 736 0xcc0f, 0x3002, 737 0xcc10, 0x1002, 738 0xcc11, 0x2072, 739 0xcc12, 0x3012, 740 0xcc13, 0x1002, 741 0xcc14, 0x22cd, 742 0xcc15, 0x301d, 743 0xcc16, 0x2e52, 744 0xcc17, 0x3012, 745 0xcc18, 0x1002, 746 0xcc19, 0x28e2, 747 0xcc1a, 0x3002, 748 0xcc1b, 0x1002, 749 0xcc1c, 0x628f, 750 0xcc1d, 0x2ac2, 751 0xcc1e, 0x3012, 752 0xcc1f, 0x1002, 753 0xcc20, 0x5553, 754 0xcc21, 0x2ae2, 755 0xcc22, 0x3002, 756 0xcc23, 0x1302, 757 0xcc24, 0x401e, 758 0xcc25, 0x2be2, 759 0xcc26, 0x3012, 760 0xcc27, 0x1002, 761 0xcc28, 0x2da2, 762 0xcc29, 0x3012, 763 0xcc2a, 0x1002, 764 0xcc2b, 0x2ba2, 765 0xcc2c, 0x3002, 766 0xcc2d, 0x1002, 767 0xcc2e, 0x5ee3, 768 0xcc2f, 0x305, 769 0xcc30, 0x400e, 770 0xcc31, 0x2bc2, 771 0xcc32, 0x3002, 772 0xcc33, 0x1002, 773 0xcc34, 0x2b82, 774 0xcc35, 0x3012, 775 0xcc36, 0x1002, 776 0xcc37, 0x5663, 777 0xcc38, 0x302, 778 0xcc39, 0x401e, 779 0xcc3a, 0x6f72, 780 0xcc3b, 0x1002, 781 0xcc3c, 0x628f, 782 0xcc3d, 0x2be2, 783 0xcc3e, 0x3012, 784 0xcc3f, 0x1002, 785 0xcc40, 0x22cd, 786 0xcc41, 0x301d, 787 0xcc42, 0x2e52, 788 0xcc43, 0x3012, 789 0xcc44, 0x1002, 790 0xcc45, 0x2522, 791 0xcc46, 0x3012, 792 0xcc47, 0x1002, 793 0xcc48, 0x2da2, 794 0xcc49, 0x3012, 795 0xcc4a, 0x1002, 796 0xcc4b, 0x2ca2, 797 0xcc4c, 0x3012, 798 0xcc4d, 0x1002, 799 0xcc4e, 0x2fa4, 800 0xcc4f, 0x3cd4, 801 0xcc50, 0x6624, 802 0xcc51, 0x410b, 803 0xcc52, 0x56b3, 804 0xcc53, 0x3c4, 805 0xcc54, 0x2fb2, 806 0xcc55, 0x3002, 807 0xcc56, 0x1002, 808 0xcc57, 0x220b, 809 0xcc58, 0x303b, 810 0xcc59, 0x56b3, 811 0xcc5a, 0x3c3, 812 0xcc5b, 0x866b, 813 0xcc5c, 0x400c, 814 0xcc5d, 0x23a2, 815 0xcc5e, 0x3012, 816 0xcc5f, 0x1002, 817 0xcc60, 0x2da2, 818 0xcc61, 0x3012, 819 0xcc62, 0x1002, 820 0xcc63, 0x2ca2, 821 0xcc64, 0x3012, 822 0xcc65, 0x1002, 823 0xcc66, 0x2fb4, 824 0xcc67, 0x3cd4, 825 0xcc68, 0x6624, 826 0xcc69, 0x56b3, 827 0xcc6a, 0x3c3, 828 0xcc6b, 0x866b, 829 0xcc6c, 0x401c, 830 0xcc6d, 0x2205, 831 0xcc6e, 0x3035, 832 0xcc6f, 0x5b53, 833 0xcc70, 0x2c52, 834 0xcc71, 0x3002, 835 0xcc72, 0x13c2, 836 0xcc73, 0x5cc3, 837 0xcc74, 0x317, 838 0xcc75, 0x2522, 839 0xcc76, 0x3012, 840 0xcc77, 0x1002, 841 0xcc78, 0x2da2, 842 0xcc79, 0x3012, 843 0xcc7a, 0x1002, 844 0xcc7b, 0x2b82, 845 0xcc7c, 0x3012, 846 0xcc7d, 0x1002, 847 0xcc7e, 0x5663, 848 0xcc7f, 0x303, 849 0xcc80, 0x401e, 850 0xcc81, 0x004, 851 0xcc82, 0x2c42, 852 0xcc83, 0x3012, 853 0xcc84, 0x1002, 854 0xcc85, 0x6f72, 855 0xcc86, 0x1002, 856 0xcc87, 0x628f, 857 0xcc88, 0x2304, 858 0xcc89, 0x3c84, 859 0xcc8a, 0x6436, 860 0xcc8b, 0xdff4, 861 0xcc8c, 0x6436, 862 0xcc8d, 0x2ff5, 863 0xcc8e, 0x3005, 864 0xcc8f, 0x8656, 865 0xcc90, 0xdfba, 866 0xcc91, 0x56a3, 867 0xcc92, 0xd05a, 868 0xcc93, 0x21c2, 869 0xcc94, 0x3012, 870 0xcc95, 0x1392, 871 0xcc96, 0xd05a, 872 0xcc97, 0x56a3, 873 0xcc98, 0xdfba, 874 0xcc99, 0x383, 875 0xcc9a, 0x6f72, 876 0xcc9b, 0x1002, 877 0xcc9c, 0x28c5, 878 0xcc9d, 0x3005, 879 0xcc9e, 0x4178, 880 0xcc9f, 0x5653, 881 0xcca0, 0x384, 882 0xcca1, 0x22b2, 883 0xcca2, 0x3012, 884 0xcca3, 0x1002, 885 0xcca4, 0x2be5, 886 0xcca5, 0x3005, 887 0xcca6, 0x41e8, 888 0xcca7, 0x5653, 889 0xcca8, 0x382, 890 0xcca9, 0x002, 891 0xccaa, 0x4258, 892 0xccab, 0x2474, 893 0xccac, 0x3c84, 894 0xccad, 0x6437, 895 0xccae, 0xdff4, 896 0xccaf, 0x6437, 897 0xccb0, 0x2ff5, 898 0xccb1, 0x3c05, 899 0xccb2, 0x8757, 900 0xccb3, 0xb888, 901 0xccb4, 0x9787, 902 0xccb5, 0xdff4, 903 0xccb6, 0x6724, 904 0xccb7, 0x866a, 905 0xccb8, 0x6f72, 906 0xccb9, 0x1002, 907 0xccba, 0x2d01, 908 0xccbb, 0x3011, 909 0xccbc, 0x1001, 910 0xccbd, 0xc620, 911 0xccbe, 0x14e5, 912 0xccbf, 0xc621, 913 0xccc0, 0xc53d, 914 0xccc1, 0xc622, 915 0xccc2, 0x3cbe, 916 0xccc3, 0xc623, 917 0xccc4, 0x4452, 918 0xccc5, 0xc624, 919 0xccc6, 0xc5c5, 920 0xccc7, 0xc625, 921 0xccc8, 0xe01e, 922 0xccc9, 0xc627, 923 0xccca, 0x000, 924 0xcccb, 0xc628, 925 0xcccc, 0x000, 926 0xcccd, 0xc62b, 927 0xccce, 0x000, 928 0xcccf, 0xc62c, 929 0xccd0, 0x000, 930 0xccd1, 0x000, 931 0xccd2, 0x2d01, 932 0xccd3, 0x3011, 933 0xccd4, 0x1001, 934 0xccd5, 0xc620, 935 0xccd6, 0x000, 936 0xccd7, 0xc621, 937 0xccd8, 0x000, 938 0xccd9, 0xc622, 939 0xccda, 0x0ce, 940 0xccdb, 0xc623, 941 0xccdc, 0x07f, 942 0xccdd, 0xc624, 943 0xccde, 0x032, 944 0xccdf, 0xc625, 945 0xcce0, 0x000, 946 0xcce1, 0xc627, 947 0xcce2, 0x000, 948 0xcce3, 0xc628, 949 0xcce4, 0x000, 950 0xcce5, 0xc62b, 951 0xcce6, 0x000, 952 0xcce7, 0xc62c, 953 0xcce8, 0x000, 954 0xcce9, 0x000, 955 0xccea, 0x2d01, 956 0xcceb, 0x3011, 957 0xccec, 0x1001, 958 0xcced, 0xc502, 959 0xccee, 0x609f, 960 0xccef, 0xc600, 961 0xccf0, 0x2a6e, 962 0xccf1, 0xc601, 963 0xccf2, 0x2a2c, 964 0xccf3, 0xc60c, 965 0xccf4, 0x5400, 966 0xccf5, 0xc710, 967 0xccf6, 0x700, 968 0xccf7, 0xc718, 969 0xccf8, 0x700, 970 0xccf9, 0xc720, 971 0xccfa, 0x4700, 972 0xccfb, 0xc728, 973 0xccfc, 0x700, 974 0xccfd, 0xc729, 975 0xccfe, 0x1207, 976 0xccff, 0xc801, 977 0xcd00, 0x7f50, 978 0xcd01, 0xc802, 979 0xcd02, 0x7760, 980 0xcd03, 0xc803, 981 0xcd04, 0x7fce, 982 0xcd05, 0xc804, 983 0xcd06, 0x520e, 984 0xcd07, 0xc805, 985 0xcd08, 0x5c11, 986 0xcd09, 0xc806, 987 0xcd0a, 0x3c51, 988 0xcd0b, 0xc807, 989 0xcd0c, 0x4061, 990 0xcd0d, 0xc808, 991 0xcd0e, 0x49c1, 992 0xcd0f, 0xc809, 993 0xcd10, 0x3840, 994 0xcd11, 0xc80a, 995 0xcd12, 0x000, 996 0xcd13, 0xc821, 997 0xcd14, 0x002, 998 0xcd15, 0xc822, 999 0xcd16, 0x046, 1000 0xcd17, 0xc844, 1001 0xcd18, 0x182f, 1002 0xcd19, 0xc013, 1003 0xcd1a, 0xf341, 1004 0xcd1b, 0xc01a, 1005 0xcd1c, 0x446, 1006 0xcd1d, 0xc024, 1007 0xcd1e, 0x1000, 1008 0xcd1f, 0xc025, 1009 0xcd20, 0xa00, 1010 0xcd21, 0xc026, 1011 0xcd22, 0xc0c, 1012 0xcd23, 0xc027, 1013 0xcd24, 0xc0c, 1014 0xcd25, 0xc029, 1015 0xcd26, 0x0a0, 1016 0xcd27, 0xc030, 1017 0xcd28, 0xa00, 1018 0xcd29, 0xc03c, 1019 0xcd2a, 0x01c, 1020 0xcd2b, 0x000, 1021 0xcd2c, 0x2b84, 1022 0xcd2d, 0x3c74, 1023 0xcd2e, 0x6435, 1024 0xcd2f, 0xdff4, 1025 0xcd30, 0x6435, 1026 0xcd31, 0x2806, 1027 0xcd32, 0x3006, 1028 0xcd33, 0x8565, 1029 0xcd34, 0x2b24, 1030 0xcd35, 0x3c24, 1031 0xcd36, 0x6436, 1032 0xcd37, 0x1002, 1033 0xcd38, 0x2b24, 1034 0xcd39, 0x3c24, 1035 0xcd3a, 0x6436, 1036 0xcd3b, 0x4045, 1037 0xcd3c, 0x8656, 1038 0xcd3d, 0x1002, 1039 0xcd3e, 0x2807, 1040 0xcd3f, 0x31a7, 1041 0xcd40, 0x20c4, 1042 0xcd41, 0x3c24, 1043 0xcd42, 0x6724, 1044 0xcd43, 0x1002, 1045 0xcd44, 0x2807, 1046 0xcd45, 0x3187, 1047 0xcd46, 0x20c4, 1048 0xcd47, 0x3c24, 1049 0xcd48, 0x6724, 1050 0xcd49, 0x1002, 1051 0xcd4a, 0x2514, 1052 0xcd4b, 0x3c64, 1053 0xcd4c, 0x6436, 1054 0xcd4d, 0xdff4, 1055 0xcd4e, 0x6436, 1056 0xcd4f, 0x1002, 1057 0xcd50, 0x2806, 1058 0xcd51, 0x3cb6, 1059 0xcd52, 0xc161, 1060 0xcd53, 0x6134, 1061 0xcd54, 0x6135, 1062 0xcd55, 0x5443, 1063 0xcd56, 0x303, 1064 0xcd57, 0x6524, 1065 0xcd58, 0x00b, 1066 0xcd59, 0x1002, 1067 0xcd5a, 0xd019, 1068 0xcd5b, 0x2104, 1069 0xcd5c, 0x3c24, 1070 0xcd5d, 0x2105, 1071 0xcd5e, 0x3805, 1072 0xcd5f, 0x6524, 1073 0xcd60, 0xdff4, 1074 0xcd61, 0x4005, 1075 0xcd62, 0x6524, 1076 0xcd63, 0x2e8d, 1077 0xcd64, 0x303d, 1078 0xcd65, 0x5dd3, 1079 0xcd66, 0x306, 1080 0xcd67, 0x2ff7, 1081 0xcd68, 0x38f7, 1082 0xcd69, 0x60b7, 1083 0xcd6a, 0xdffd, 1084 0xcd6b, 0x00a, 1085 0xcd6c, 0x1002, 1086 0xcd6d, 0 1087 }; 1088 int i, err; 1089 1090 err = set_phy_regs(phy, regs); 1091 if (!err && modtype == phy_modtype_twinax_long) 1092 err = set_phy_regs(phy, preemphasis); 1093 if (err) 1094 return err; 1095 1096 msleep(50); 1097 1098 for (i = 0; i < ARRAY_SIZE(twinax_edc) && !err; i += 2) 1099 err = mdio_write(phy, MDIO_DEV_PMA_PMD, twinax_edc[i], 1100 twinax_edc[i + 1]); 1101 if (!err) 1102 phy->priv = edc_twinax; 1103 return err; 1104 } 1105 1106 static int get_module_type(struct cphy *phy) 1107 { 1108 int v; 1109 1110 v = get_phytrans_type(phy); 1111 if (v == phy_transtype_sfp) { 1112 /* SFP: see SFF-8472 for below */ 1113 1114 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 3); 1115 if (v < 0) 1116 return v; 1117 1118 if (v == 0x1) 1119 return phy_modtype_twinax; 1120 if (v == 0x10) 1121 return phy_modtype_sr; 1122 if (v == 0x20) 1123 return phy_modtype_lr; 1124 if (v == 0x40) 1125 return phy_modtype_lrm; 1126 1127 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 6); 1128 if (v < 0) 1129 return v; 1130 if (v != 4) 1131 return phy_modtype_unknown; 1132 1133 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 10); 1134 if (v < 0) 1135 return v; 1136 1137 if (v & 0x80) { 1138 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 0x12); 1139 if (v < 0) 1140 return v; 1141 return v > 10 ? phy_modtype_twinax_long : 1142 phy_modtype_twinax; 1143 } 1144 } else if (v == phy_transtype_xfp) { 1145 /* XFP: See INF-8077i for details. */ 1146 1147 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 127); 1148 if (v < 0) 1149 return v; 1150 1151 if (v != 1) { 1152 /* XXX: set page select to table 1 yourself */ 1153 return phy_modtype_unknown; 1154 } 1155 1156 v = ael_i2c_rd(phy, MODULE_DEV_ADDR, 131); 1157 if (v < 0) 1158 return v; 1159 v &= 0xf0; 1160 if (v == 0x10) 1161 return phy_modtype_lrm; 1162 if (v == 0x40) 1163 return phy_modtype_lr; 1164 if (v == 0x80) 1165 return phy_modtype_sr; 1166 } 1167 1168 return phy_modtype_unknown; 1169 } 1170 1171 1172 static int ael2005_intr_enable(struct cphy *phy) 1173 { 1174 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x200); 1175 return err ? err : t3_phy_lasi_intr_enable(phy); 1176 } 1177 1178 static int ael2005_intr_disable(struct cphy *phy) 1179 { 1180 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0x100); 1181 return err ? err : t3_phy_lasi_intr_disable(phy); 1182 } 1183 1184 static int ael2005_intr_clear(struct cphy *phy) 1185 { 1186 int err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 0xd00); 1187 return err ? err : t3_phy_lasi_intr_clear(phy); 1188 } 1189 1190 static int ael2005_get_module_type(struct cphy *phy, int delay_ms) 1191 { 1192 int v; 1193 unsigned int stat; 1194 1195 v = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, &stat); 1196 if (v) 1197 return v; 1198 1199 if (stat & (1 << 8)) /* module absent */ 1200 return phy_modtype_none; 1201 1202 if (delay_ms) 1203 msleep(delay_ms); 1204 1205 return get_module_type(phy); 1206 } 1207 1208 static int ael2005_reset(struct cphy *phy, int wait) 1209 { 1210 static struct reg_val regs0[] = { 1211 { MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 }, 1212 { MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 }, 1213 { MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 }, 1214 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 }, 1215 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 }, 1216 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 }, 1217 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 }, 1218 { 0, 0, 0, 0 } 1219 }; 1220 static struct reg_val regs1[] = { 1221 { MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 }, 1222 { MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 }, 1223 { 0, 0, 0, 0 } 1224 }; 1225 1226 int err, lasi_ctrl; 1227 1228 err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, &lasi_ctrl); 1229 if (err) 1230 return err; 1231 1232 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0); 1233 if (err) 1234 return err; 1235 1236 msleep(125); 1237 phy->priv = edc_none; 1238 err = set_phy_regs(phy, regs0); 1239 if (err) 1240 return err; 1241 1242 msleep(50); 1243 1244 err = ael2005_get_module_type(phy, 0); 1245 if (err < 0) 1246 return err; 1247 phy->modtype = (u8)err; 1248 1249 if (err == phy_modtype_none || err == phy_modtype_unknown) 1250 err = 0; 1251 else if (err == phy_modtype_twinax || err == phy_modtype_twinax_long) 1252 err = ael2005_setup_twinax_edc(phy, err); 1253 else 1254 err = ael2005_setup_sr_edc(phy); 1255 if (err) 1256 return err; 1257 1258 err = set_phy_regs(phy, regs1); 1259 if (err) 1260 return err; 1261 1262 /* reset wipes out interrupts, reenable them if they were on */ 1263 if (lasi_ctrl & 1) 1264 err = ael2005_intr_enable(phy); 1265 return err; 1266 } 1267 1268 static int ael2005_intr_handler(struct cphy *phy) 1269 { 1270 unsigned int stat; 1271 int ret, edc_needed, cause = 0; 1272 1273 ret = mdio_read(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_STAT, &stat); 1274 if (ret) 1275 return ret; 1276 1277 if (stat & AEL2005_MODDET_IRQ) { 1278 ret = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL2005_GPIO_CTRL, 1279 0xd00); 1280 if (ret) 1281 return ret; 1282 1283 /* modules have max 300 ms init time after hot plug */ 1284 ret = ael2005_get_module_type(phy, 300); 1285 if (ret < 0) 1286 return ret; 1287 1288 phy->modtype = (u8)ret; 1289 if (ret == phy_modtype_none) 1290 edc_needed = phy->priv; /* on unplug retain EDC */ 1291 else if (ret == phy_modtype_twinax || 1292 ret == phy_modtype_twinax_long) 1293 edc_needed = edc_twinax; 1294 else 1295 edc_needed = edc_sr; 1296 1297 if (edc_needed != phy->priv) { 1298 ret = ael2005_reset(phy, 0); 1299 return ret ? ret : cphy_cause_module_change; 1300 } 1301 cause = cphy_cause_module_change; 1302 } 1303 1304 ret = t3_phy_lasi_intr_handler(phy); 1305 if (ret < 0) 1306 return ret; 1307 1308 ret |= cause; 1309 if (!ret) 1310 ret |= cphy_cause_link_change; 1311 return ret; 1312 } 1313 1314 #ifdef C99_NOT_SUPPORTED 1315 static struct cphy_ops ael2005_ops = { 1316 ael2005_reset, 1317 ael2005_intr_enable, 1318 ael2005_intr_disable, 1319 ael2005_intr_clear, 1320 ael2005_intr_handler, 1321 NULL, 1322 NULL, 1323 NULL, 1324 NULL, 1325 NULL, 1326 get_link_status_r, 1327 ael1002_power_down, 1328 }; 1329 #else 1330 static struct cphy_ops ael2005_ops = { 1331 .reset = ael2005_reset, 1332 .intr_enable = ael2005_intr_enable, 1333 .intr_disable = ael2005_intr_disable, 1334 .intr_clear = ael2005_intr_clear, 1335 .intr_handler = ael2005_intr_handler, 1336 .get_link_status = get_link_status_r, 1337 .power_down = ael1002_power_down, 1338 }; 1339 #endif 1340 1341 int t3_ael2005_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 1342 const struct mdio_ops *mdio_ops) 1343 { 1344 int err; 1345 cphy_init(phy, adapter, phy_addr, &ael2005_ops, mdio_ops, 1346 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE | 1347 SUPPORTED_IRQ, "10GBASE-R"); 1348 msleep(125); 1349 ael_laser_down(phy, 0); 1350 1351 err = ael2005_get_module_type(phy, 0); 1352 if (err >= 0) 1353 phy->modtype = err; 1354 1355 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0, 1356 1 << 5); 1357 } 1358 1359 /* 1360 * Get link status for a 10GBASE-X device. 1361 */ 1362 static int get_link_status_x(struct cphy *phy, int *link_ok, int *speed, 1363 int *duplex, int *fc) 1364 { 1365 if (link_ok) { 1366 unsigned int stat0, stat1, stat2; 1367 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, PMD_RSD, &stat0); 1368 1369 if (!err) 1370 err = mdio_read(phy, MDIO_DEV_PCS, PCS_STAT1_X, &stat1); 1371 if (!err) 1372 err = mdio_read(phy, MDIO_DEV_XGXS, XS_LN_STAT, &stat2); 1373 if (err) 1374 return err; 1375 *link_ok = (stat0 & (stat1 >> 12) & (stat2 >> 12)) & 1; 1376 } 1377 if (speed) 1378 *speed = SPEED_10000; 1379 if (duplex) 1380 *duplex = DUPLEX_FULL; 1381 return 0; 1382 } 1383 1384 #ifdef C99_NOT_SUPPORTED 1385 static struct cphy_ops qt2045_ops = { 1386 ael1006_reset, 1387 t3_phy_lasi_intr_enable, 1388 t3_phy_lasi_intr_disable, 1389 t3_phy_lasi_intr_clear, 1390 t3_phy_lasi_intr_handler, 1391 NULL, 1392 NULL, 1393 NULL, 1394 NULL, 1395 NULL, 1396 get_link_status_x, 1397 ael1006_power_down, 1398 }; 1399 #else 1400 static struct cphy_ops qt2045_ops = { 1401 .reset = ael1006_reset, 1402 .intr_enable = t3_phy_lasi_intr_enable, 1403 .intr_disable = t3_phy_lasi_intr_disable, 1404 .intr_clear = t3_phy_lasi_intr_clear, 1405 .intr_handler = t3_phy_lasi_intr_handler, 1406 .get_link_status = get_link_status_x, 1407 .power_down = ael1006_power_down, 1408 }; 1409 #endif 1410 1411 int t3_qt2045_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 1412 const struct mdio_ops *mdio_ops) 1413 { 1414 unsigned int stat; 1415 1416 cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops, 1417 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP, 1418 "10GBASE-CX4"); 1419 1420 /* 1421 * Some cards where the PHY is supposed to be at address 0 actually 1422 * have it at 1. 1423 */ 1424 if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) && 1425 stat == 0xffff) 1426 phy->addr = 1; 1427 return 0; 1428 } 1429 1430 static int xaui_direct_reset(struct cphy *phy, int wait) 1431 { 1432 return 0; 1433 } 1434 1435 static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok, 1436 int *speed, int *duplex, int *fc) 1437 { 1438 if (link_ok) { 1439 unsigned int status; 1440 1441 status = t3_read_reg(phy->adapter, 1442 XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) | 1443 t3_read_reg(phy->adapter, 1444 XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) | 1445 t3_read_reg(phy->adapter, 1446 XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) | 1447 t3_read_reg(phy->adapter, 1448 XGM_REG(A_XGM_SERDES_STAT3, phy->addr)); 1449 *link_ok = !(status & F_LOWSIG0); 1450 } 1451 if (speed) 1452 *speed = SPEED_10000; 1453 if (duplex) 1454 *duplex = DUPLEX_FULL; 1455 return 0; 1456 } 1457 1458 static int xaui_direct_power_down(struct cphy *phy, int enable) 1459 { 1460 return 0; 1461 } 1462 1463 #ifdef C99_NOT_SUPPORTED 1464 static struct cphy_ops xaui_direct_ops = { 1465 xaui_direct_reset, 1466 ael1002_intr_noop, 1467 ael1002_intr_noop, 1468 ael1002_intr_noop, 1469 ael1002_intr_noop, 1470 NULL, 1471 NULL, 1472 NULL, 1473 NULL, 1474 NULL, 1475 xaui_direct_get_link_status, 1476 xaui_direct_power_down, 1477 }; 1478 #else 1479 static struct cphy_ops xaui_direct_ops = { 1480 .reset = xaui_direct_reset, 1481 .intr_enable = ael1002_intr_noop, 1482 .intr_disable = ael1002_intr_noop, 1483 .intr_clear = ael1002_intr_noop, 1484 .intr_handler = ael1002_intr_noop, 1485 .get_link_status = xaui_direct_get_link_status, 1486 .power_down = xaui_direct_power_down, 1487 }; 1488 #endif 1489 1490 int t3_xaui_direct_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 1491 const struct mdio_ops *mdio_ops) 1492 { 1493 cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops, 1494 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP, 1495 "10GBASE-CX4"); 1496 return 0; 1497 } 1498