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