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 #ifdef CONFIG_DEFINED 34 #include <cxgb_include.h> 35 #else 36 #include <dev/cxgb/cxgb_include.h> 37 #endif 38 39 #undef msleep 40 #define msleep t3_os_sleep 41 42 enum { 43 AEL100X_TX_DISABLE = 9, 44 AEL100X_TX_CONFIG1 = 0xc002, 45 AEL1002_PWR_DOWN_HI = 0xc011, 46 AEL1002_PWR_DOWN_LO = 0xc012, 47 AEL1002_XFI_EQL = 0xc015, 48 AEL1002_LB_EN = 0xc017, 49 AEL_OPT_SETTINGS = 0xc017, 50 }; 51 52 struct reg_val { 53 unsigned short mmd_addr; 54 unsigned short reg_addr; 55 unsigned short clear_bits; 56 unsigned short set_bits; 57 }; 58 59 static int set_phy_regs(struct cphy *phy, const struct reg_val *rv) 60 { 61 int err; 62 63 for (err = 0; rv->mmd_addr && !err; rv++) { 64 if (rv->clear_bits == 0xffff) 65 err = mdio_write(phy, rv->mmd_addr, rv->reg_addr, 66 rv->set_bits); 67 else 68 err = t3_mdio_change_bits(phy, rv->mmd_addr, 69 rv->reg_addr, rv->clear_bits, 70 rv->set_bits); 71 } 72 return err; 73 } 74 75 static void ael100x_txon(struct cphy *phy) 76 { 77 int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL; 78 79 msleep(100); 80 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio); 81 msleep(30); 82 } 83 84 static int ael1002_power_down(struct cphy *phy, int enable) 85 { 86 int err; 87 88 err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable); 89 if (!err) 90 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 91 BMCR_PDOWN, enable ? BMCR_PDOWN : 0); 92 return err; 93 } 94 95 static int ael1002_reset(struct cphy *phy, int wait) 96 { 97 int err; 98 99 if ((err = ael1002_power_down(phy, 0)) || 100 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) || 101 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) || 102 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) || 103 (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) || 104 (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN, 105 0, 1 << 5))) 106 return err; 107 return 0; 108 } 109 110 static int ael1002_intr_noop(struct cphy *phy) 111 { 112 return 0; 113 } 114 115 static int ael100x_get_link_status(struct cphy *phy, int *link_ok, 116 int *speed, int *duplex, int *fc) 117 { 118 if (link_ok) { 119 unsigned int status; 120 int err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &status); 121 122 /* 123 * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it 124 * once more to get the current link state. 125 */ 126 if (!err && !(status & BMSR_LSTATUS)) 127 err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, 128 &status); 129 if (err) 130 return err; 131 *link_ok = !!(status & BMSR_LSTATUS); 132 } 133 if (speed) 134 *speed = SPEED_10000; 135 if (duplex) 136 *duplex = DUPLEX_FULL; 137 return 0; 138 } 139 140 #ifdef C99_NOT_SUPPORTED 141 static struct cphy_ops ael1002_ops = { 142 ael1002_reset, 143 ael1002_intr_noop, 144 ael1002_intr_noop, 145 ael1002_intr_noop, 146 ael1002_intr_noop, 147 NULL, 148 NULL, 149 NULL, 150 NULL, 151 NULL, 152 ael100x_get_link_status, 153 ael1002_power_down, 154 }; 155 #else 156 static struct cphy_ops ael1002_ops = { 157 .reset = ael1002_reset, 158 .intr_enable = ael1002_intr_noop, 159 .intr_disable = ael1002_intr_noop, 160 .intr_clear = ael1002_intr_noop, 161 .intr_handler = ael1002_intr_noop, 162 .get_link_status = ael100x_get_link_status, 163 .power_down = ael1002_power_down, 164 }; 165 #endif 166 167 int t3_ael1002_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 168 const struct mdio_ops *mdio_ops) 169 { 170 cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops, 171 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE, 172 "10GBASE-R"); 173 ael100x_txon(phy); 174 return 0; 175 } 176 177 static int ael1006_reset(struct cphy *phy, int wait) 178 { 179 return t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait); 180 } 181 182 static int ael1006_power_down(struct cphy *phy, int enable) 183 { 184 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 185 BMCR_PDOWN, enable ? BMCR_PDOWN : 0); 186 } 187 188 #ifdef C99_NOT_SUPPORTED 189 static struct cphy_ops ael1006_ops = { 190 ael1006_reset, 191 t3_phy_lasi_intr_enable, 192 t3_phy_lasi_intr_disable, 193 t3_phy_lasi_intr_clear, 194 t3_phy_lasi_intr_handler, 195 NULL, 196 NULL, 197 NULL, 198 NULL, 199 NULL, 200 ael100x_get_link_status, 201 ael1006_power_down, 202 }; 203 #else 204 static struct cphy_ops ael1006_ops = { 205 .reset = ael1006_reset, 206 .intr_enable = t3_phy_lasi_intr_enable, 207 .intr_disable = t3_phy_lasi_intr_disable, 208 .intr_clear = t3_phy_lasi_intr_clear, 209 .intr_handler = t3_phy_lasi_intr_handler, 210 .get_link_status = ael100x_get_link_status, 211 .power_down = ael1006_power_down, 212 }; 213 #endif 214 215 int t3_ael1006_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 216 const struct mdio_ops *mdio_ops) 217 { 218 cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops, 219 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE, 220 "10GBASE-SR"); 221 ael100x_txon(phy); 222 return 0; 223 } 224 225 static int ael2005_setup_sr_edc(struct cphy *phy) 226 { 227 static u16 sr_edc[] = { 228 0xcc00, 0x2ff4, 229 0xcc01, 0x3cd4, 230 0xcc02, 0x2015, 231 0xcc03, 0x3105, 232 0xcc04, 0x6524, 233 0xcc05, 0x27ff, 234 0xcc06, 0x300f, 235 0xcc07, 0x2c8b, 236 0xcc08, 0x300b, 237 0xcc09, 0x4009, 238 0xcc0a, 0x400e, 239 0xcc0b, 0x2f72, 240 0xcc0c, 0x3002, 241 0xcc0d, 0x1002, 242 0xcc0e, 0x2172, 243 0xcc0f, 0x3012, 244 0xcc10, 0x1002, 245 0xcc11, 0x25d2, 246 0xcc12, 0x3012, 247 0xcc13, 0x1002, 248 0xcc14, 0xd01e, 249 0xcc15, 0x27d2, 250 0xcc16, 0x3012, 251 0xcc17, 0x1002, 252 0xcc18, 0x2004, 253 0xcc19, 0x3c84, 254 0xcc1a, 0x6436, 255 0xcc1b, 0x2007, 256 0xcc1c, 0x3f87, 257 0xcc1d, 0x8676, 258 0xcc1e, 0x40b7, 259 0xcc1f, 0xa746, 260 0xcc20, 0x4047, 261 0xcc21, 0x5673, 262 0xcc22, 0x2982, 263 0xcc23, 0x3002, 264 0xcc24, 0x13d2, 265 0xcc25, 0x8bbd, 266 0xcc26, 0x2862, 267 0xcc27, 0x3012, 268 0xcc28, 0x1002, 269 0xcc29, 0x2092, 270 0xcc2a, 0x3012, 271 0xcc2b, 0x1002, 272 0xcc2c, 0x5cc3, 273 0xcc2d, 0x314, 274 0xcc2e, 0x2942, 275 0xcc2f, 0x3002, 276 0xcc30, 0x1002, 277 0xcc31, 0xd019, 278 0xcc32, 0x2032, 279 0xcc33, 0x3012, 280 0xcc34, 0x1002, 281 0xcc35, 0x2a04, 282 0xcc36, 0x3c74, 283 0xcc37, 0x6435, 284 0xcc38, 0x2fa4, 285 0xcc39, 0x3cd4, 286 0xcc3a, 0x6624, 287 0xcc3b, 0x5563, 288 0xcc3c, 0x2d42, 289 0xcc3d, 0x3002, 290 0xcc3e, 0x13d2, 291 0xcc3f, 0x464d, 292 0xcc40, 0x2862, 293 0xcc41, 0x3012, 294 0xcc42, 0x1002, 295 0xcc43, 0x2032, 296 0xcc44, 0x3012, 297 0xcc45, 0x1002, 298 0xcc46, 0x2fb4, 299 0xcc47, 0x3cd4, 300 0xcc48, 0x6624, 301 0xcc49, 0x5563, 302 0xcc4a, 0x2d42, 303 0xcc4b, 0x3002, 304 0xcc4c, 0x13d2, 305 0xcc4d, 0x2ed2, 306 0xcc4e, 0x3002, 307 0xcc4f, 0x1002, 308 0xcc50, 0x2fd2, 309 0xcc51, 0x3002, 310 0xcc52, 0x1002, 311 0xcc53, 0x004, 312 0xcc54, 0x2942, 313 0xcc55, 0x3002, 314 0xcc56, 0x1002, 315 0xcc57, 0x2092, 316 0xcc58, 0x3012, 317 0xcc59, 0x1002, 318 0xcc5a, 0x5cc3, 319 0xcc5b, 0x317, 320 0xcc5c, 0x2f72, 321 0xcc5d, 0x3002, 322 0xcc5e, 0x1002, 323 0xcc5f, 0x2942, 324 0xcc60, 0x3002, 325 0xcc61, 0x1002, 326 0xcc62, 0x22cd, 327 0xcc63, 0x301d, 328 0xcc64, 0x2862, 329 0xcc65, 0x3012, 330 0xcc66, 0x1002, 331 0xcc67, 0x2ed2, 332 0xcc68, 0x3002, 333 0xcc69, 0x1002, 334 0xcc6a, 0x2d72, 335 0xcc6b, 0x3002, 336 0xcc6c, 0x1002, 337 0xcc6d, 0x628f, 338 0xcc6e, 0x2112, 339 0xcc6f, 0x3012, 340 0xcc70, 0x1002, 341 0xcc71, 0x5aa3, 342 0xcc72, 0x2dc2, 343 0xcc73, 0x3002, 344 0xcc74, 0x1312, 345 0xcc75, 0x6f72, 346 0xcc76, 0x1002, 347 0xcc77, 0x2807, 348 0xcc78, 0x31a7, 349 0xcc79, 0x20c4, 350 0xcc7a, 0x3c24, 351 0xcc7b, 0x6724, 352 0xcc7c, 0x1002, 353 0xcc7d, 0x2807, 354 0xcc7e, 0x3187, 355 0xcc7f, 0x20c4, 356 0xcc80, 0x3c24, 357 0xcc81, 0x6724, 358 0xcc82, 0x1002, 359 0xcc83, 0x2514, 360 0xcc84, 0x3c64, 361 0xcc85, 0x6436, 362 0xcc86, 0xdff4, 363 0xcc87, 0x6436, 364 0xcc88, 0x1002, 365 0xcc89, 0x40a4, 366 0xcc8a, 0x643c, 367 0xcc8b, 0x4016, 368 0xcc8c, 0x8c6c, 369 0xcc8d, 0x2b24, 370 0xcc8e, 0x3c24, 371 0xcc8f, 0x6435, 372 0xcc90, 0x1002, 373 0xcc91, 0x2b24, 374 0xcc92, 0x3c24, 375 0xcc93, 0x643a, 376 0xcc94, 0x4025, 377 0xcc95, 0x8a5a, 378 0xcc96, 0x1002, 379 0xcc97, 0x2731, 380 0xcc98, 0x3011, 381 0xcc99, 0x1001, 382 0xcc9a, 0xc7a0, 383 0xcc9b, 0x100, 384 0xcc9c, 0xc502, 385 0xcc9d, 0x53ac, 386 0xcc9e, 0xc503, 387 0xcc9f, 0xd5d5, 388 0xcca0, 0xc600, 389 0xcca1, 0x2a6d, 390 0xcca2, 0xc601, 391 0xcca3, 0x2a4c, 392 0xcca4, 0xc602, 393 0xcca5, 0x111, 394 0xcca6, 0xc60c, 395 0xcca7, 0x5900, 396 0xcca8, 0xc710, 397 0xcca9, 0x700, 398 0xccaa, 0xc718, 399 0xccab, 0x700, 400 0xccac, 0xc720, 401 0xccad, 0x4700, 402 0xccae, 0xc801, 403 0xccaf, 0x7f50, 404 0xccb0, 0xc802, 405 0xccb1, 0x7760, 406 0xccb2, 0xc803, 407 0xccb3, 0x7fce, 408 0xccb4, 0xc804, 409 0xccb5, 0x5700, 410 0xccb6, 0xc805, 411 0xccb7, 0x5f11, 412 0xccb8, 0xc806, 413 0xccb9, 0x4751, 414 0xccba, 0xc807, 415 0xccbb, 0x57e1, 416 0xccbc, 0xc808, 417 0xccbd, 0x2700, 418 0xccbe, 0xc809, 419 0xccbf, 0x000, 420 0xccc0, 0xc821, 421 0xccc1, 0x002, 422 0xccc2, 0xc822, 423 0xccc3, 0x014, 424 0xccc4, 0xc832, 425 0xccc5, 0x1186, 426 0xccc6, 0xc847, 427 0xccc7, 0x1e02, 428 0xccc8, 0xc013, 429 0xccc9, 0xf341, 430 0xccca, 0xc01a, 431 0xcccb, 0x446, 432 0xcccc, 0xc024, 433 0xcccd, 0x1000, 434 0xccce, 0xc025, 435 0xcccf, 0xa00, 436 0xccd0, 0xc026, 437 0xccd1, 0xc0c, 438 0xccd2, 0xc027, 439 0xccd3, 0xc0c, 440 0xccd4, 0xc029, 441 0xccd5, 0x0a0, 442 0xccd6, 0xc030, 443 0xccd7, 0xa00, 444 0xccd8, 0xc03c, 445 0xccd9, 0x01c, 446 0xccda, 0xc005, 447 0xccdb, 0x7a06, 448 0xccdc, 0x000, 449 0xccdd, 0x2731, 450 0xccde, 0x3011, 451 0xccdf, 0x1001, 452 0xcce0, 0xc620, 453 0xcce1, 0x000, 454 0xcce2, 0xc621, 455 0xcce3, 0x03f, 456 0xcce4, 0xc622, 457 0xcce5, 0x000, 458 0xcce6, 0xc623, 459 0xcce7, 0x000, 460 0xcce8, 0xc624, 461 0xcce9, 0x000, 462 0xccea, 0xc625, 463 0xcceb, 0x000, 464 0xccec, 0xc627, 465 0xcced, 0x000, 466 0xccee, 0xc628, 467 0xccef, 0x000, 468 0xccf0, 0xc62c, 469 0xccf1, 0x000, 470 0xccf2, 0x000, 471 0xccf3, 0x2806, 472 0xccf4, 0x3cb6, 473 0xccf5, 0xc161, 474 0xccf6, 0x6134, 475 0xccf7, 0x6135, 476 0xccf8, 0x5443, 477 0xccf9, 0x303, 478 0xccfa, 0x6524, 479 0xccfb, 0x00b, 480 0xccfc, 0x1002, 481 0xccfd, 0x2104, 482 0xccfe, 0x3c24, 483 0xccff, 0x2105, 484 0xcd00, 0x3805, 485 0xcd01, 0x6524, 486 0xcd02, 0xdff4, 487 0xcd03, 0x4005, 488 0xcd04, 0x6524, 489 0xcd05, 0x1002, 490 0xcd06, 0x5dd3, 491 0xcd07, 0x306, 492 0xcd08, 0x2ff7, 493 0xcd09, 0x38f7, 494 0xcd0a, 0x60b7, 495 0xcd0b, 0xdffd, 496 0xcd0c, 0x00a, 497 0xcd0d, 0x1002, 498 0xcd0e, 0 499 }; 500 int i, err; 501 502 for (err = i = 0; i < ARRAY_SIZE(sr_edc) && !err; i += 2) 503 err = mdio_write(phy, MDIO_DEV_PMA_PMD, sr_edc[i], 504 sr_edc[i + 1]); 505 return err; 506 } 507 508 static int ael2005_reset(struct cphy *phy, int wait) 509 { 510 static struct reg_val regs0[] = { 511 { MDIO_DEV_PMA_PMD, 0xc001, 0, 1 << 5 }, 512 { MDIO_DEV_PMA_PMD, 0xc017, 0, 1 << 5 }, 513 { MDIO_DEV_PMA_PMD, 0xc013, 0xffff, 0xf341 }, 514 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 }, 515 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8100 }, 516 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0x8000 }, 517 { MDIO_DEV_PMA_PMD, 0xc210, 0xffff, 0 }, 518 { 0, 0, 0, 0 } 519 }; 520 static struct reg_val regs1[] = { 521 { MDIO_DEV_PMA_PMD, 0xc003, 0xffff, 0x181 }, 522 { MDIO_DEV_PMA_PMD, 0xc010, 0xffff, 0x448a }, 523 { MDIO_DEV_PMA_PMD, 0xc04a, 0xffff, 0x5200 }, 524 { 0, 0, 0, 0 } 525 }; 526 static struct reg_val regs2[] = { 527 { MDIO_DEV_PMA_PMD, 0xca00, 0xffff, 0x0080 }, 528 { MDIO_DEV_PMA_PMD, 0xca12, 0xffff, 0 }, 529 { 0, 0, 0, 0 } 530 }; 531 532 int err; 533 534 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, 0); 535 if (err) 536 return err; 537 538 msleep(125); 539 err = set_phy_regs(phy, regs0); 540 if (err) 541 return err; 542 543 msleep(50); 544 err = set_phy_regs(phy, regs1); 545 if (err) 546 return err; 547 548 msleep(50); 549 err = ael2005_setup_sr_edc(phy); 550 if (err) 551 return err; 552 553 return set_phy_regs(phy, regs2); 554 } 555 556 #ifdef C99_NOT_SUPPORTED 557 static struct cphy_ops ael2005_ops = { 558 ael2005_reset, 559 t3_phy_lasi_intr_enable, 560 t3_phy_lasi_intr_disable, 561 t3_phy_lasi_intr_clear, 562 t3_phy_lasi_intr_handler, 563 NULL, 564 NULL, 565 NULL, 566 NULL, 567 NULL, 568 ael100x_get_link_status, 569 ael1002_power_down, 570 }; 571 #else 572 static struct cphy_ops ael2005_ops = { 573 .reset = ael2005_reset, 574 .intr_enable = t3_phy_lasi_intr_enable, 575 .intr_disable = t3_phy_lasi_intr_disable, 576 .intr_clear = t3_phy_lasi_intr_clear, 577 .intr_handler = t3_phy_lasi_intr_handler, 578 .get_link_status = ael100x_get_link_status, 579 .power_down = ael1002_power_down, 580 }; 581 #endif 582 583 int t3_ael2005_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 584 const struct mdio_ops *mdio_ops) 585 { 586 cphy_init(phy, adapter, phy_addr, &ael2005_ops, mdio_ops, 587 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE, 588 "10GBASE-R"); 589 msleep(125); 590 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0, 591 1 << 5); 592 } 593 594 #ifdef C99_NOT_SUPPORTED 595 static struct cphy_ops qt2045_ops = { 596 ael1006_reset, 597 t3_phy_lasi_intr_enable, 598 t3_phy_lasi_intr_disable, 599 t3_phy_lasi_intr_clear, 600 t3_phy_lasi_intr_handler, 601 NULL, 602 NULL, 603 NULL, 604 NULL, 605 NULL, 606 ael100x_get_link_status, 607 ael1006_power_down, 608 }; 609 #else 610 static struct cphy_ops qt2045_ops = { 611 .reset = ael1006_reset, 612 .intr_enable = t3_phy_lasi_intr_enable, 613 .intr_disable = t3_phy_lasi_intr_disable, 614 .intr_clear = t3_phy_lasi_intr_clear, 615 .intr_handler = t3_phy_lasi_intr_handler, 616 .get_link_status = ael100x_get_link_status, 617 .power_down = ael1006_power_down, 618 }; 619 #endif 620 621 int t3_qt2045_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 622 const struct mdio_ops *mdio_ops) 623 { 624 unsigned int stat; 625 626 cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops, 627 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP, 628 "10GBASE-CX4"); 629 630 /* 631 * Some cards where the PHY is supposed to be at address 0 actually 632 * have it at 1. 633 */ 634 if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) && 635 stat == 0xffff) 636 phy->addr = 1; 637 return 0; 638 } 639 640 static int xaui_direct_reset(struct cphy *phy, int wait) 641 { 642 return 0; 643 } 644 645 static int xaui_direct_get_link_status(struct cphy *phy, int *link_ok, 646 int *speed, int *duplex, int *fc) 647 { 648 if (link_ok) { 649 unsigned int status; 650 651 status = t3_read_reg(phy->adapter, 652 XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) | 653 t3_read_reg(phy->adapter, 654 XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) | 655 t3_read_reg(phy->adapter, 656 XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) | 657 t3_read_reg(phy->adapter, 658 XGM_REG(A_XGM_SERDES_STAT3, phy->addr)); 659 *link_ok = !(status & F_LOWSIG0); 660 } 661 if (speed) 662 *speed = SPEED_10000; 663 if (duplex) 664 *duplex = DUPLEX_FULL; 665 return 0; 666 } 667 668 static int xaui_direct_power_down(struct cphy *phy, int enable) 669 { 670 return 0; 671 } 672 673 #ifdef C99_NOT_SUPPORTED 674 static struct cphy_ops xaui_direct_ops = { 675 xaui_direct_reset, 676 ael1002_intr_noop, 677 ael1002_intr_noop, 678 ael1002_intr_noop, 679 ael1002_intr_noop, 680 NULL, 681 NULL, 682 NULL, 683 NULL, 684 NULL, 685 xaui_direct_get_link_status, 686 xaui_direct_power_down, 687 }; 688 #else 689 static struct cphy_ops xaui_direct_ops = { 690 .reset = xaui_direct_reset, 691 .intr_enable = ael1002_intr_noop, 692 .intr_disable = ael1002_intr_noop, 693 .intr_clear = ael1002_intr_noop, 694 .intr_handler = ael1002_intr_noop, 695 .get_link_status = xaui_direct_get_link_status, 696 .power_down = xaui_direct_power_down, 697 }; 698 #endif 699 700 int t3_xaui_direct_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 701 const struct mdio_ops *mdio_ops) 702 { 703 cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops, 704 SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP, 705 "10GBASE-CX4"); 706 return 0; 707 } 708