1 /************************************************************************** 2 3 Copyright (c) 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 /* MDIO_DEV_PMA_PMD registers */ 40 AQ_LINK_STAT = 0xe800, 41 42 /* MDIO_DEV_XGXS registers */ 43 AQ_XAUI_RX_CFG = 0xc400, 44 AQ_XAUI_KX_CFG = 0xc440, 45 AQ_XAUI_TX_CFG = 0xe400, 46 47 /* MDIO_DEV_ANEG registers */ 48 AQ_100M_CTRL = 0x0010, 49 AQ_10G_CTRL = 0x0020, 50 AQ_1G_CTRL = 0xc400, 51 AQ_ANEG_STAT = 0xc800, 52 53 /* MDIO_DEV_VEND1 registers */ 54 AQ_FW_VERSION = 0x0020, 55 AQ_THERMAL_THR = 0xc421, 56 AQ_THERMAL1 = 0xc820, 57 AQ_THERMAL2 = 0xc821, 58 AQ_IFLAG_GLOBAL = 0xfc00, 59 AQ_IMASK_GLOBAL = 0xff00, 60 }; 61 62 #define AQBIT(x) (1 << (0x##x)) 63 #define ADV_1G_FULL AQBIT(f) 64 #define ADV_1G_HALF AQBIT(e) 65 #define ADV_10G_FULL AQBIT(c) 66 67 #define AQ_WRITE_REGS(phy, regs) do { \ 68 int i; \ 69 for (i = 0; i < ARRAY_SIZE(regs); i++) { \ 70 (void) mdio_write(phy, regs[i].mmd, regs[i].reg, regs[i].val); \ 71 } \ 72 } while (0) 73 #define AQ_READ_REGS(phy, regs) do { \ 74 unsigned i, v; \ 75 for (i = 0; i < ARRAY_SIZE(regs); i++) { \ 76 (void) mdio_read(phy, regs[i].mmd, regs[i].reg, &v); \ 77 } \ 78 } while (0) 79 80 /* 81 * Return value is temperature in celcius, 0xffff for error or don't know. 82 */ 83 static int 84 aq100x_temperature(struct cphy *phy) 85 { 86 unsigned int v; 87 88 if (mdio_read(phy, MDIO_DEV_VEND1, AQ_THERMAL2, &v) || 89 v == 0xffff || (v & 1) != 1) 90 return (0xffff); 91 92 if (mdio_read(phy, MDIO_DEV_VEND1, AQ_THERMAL1, &v)) 93 return (0xffff); 94 95 return ((int)((signed char)(v >> 8))); 96 } 97 98 static int 99 aq100x_set_defaults(struct cphy *phy) 100 { 101 return mdio_write(phy, MDIO_DEV_VEND1, AQ_THERMAL_THR, 0x6c00); 102 } 103 104 static int 105 aq100x_reset(struct cphy *phy, int wait) 106 { 107 int err; 108 err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait); 109 if (!err) 110 err = aq100x_set_defaults(phy); 111 return (err); 112 } 113 114 static int 115 aq100x_intr_enable(struct cphy *phy) 116 { 117 struct { 118 int mmd; 119 int reg; 120 int val; 121 } imasks[] = { 122 {MDIO_DEV_VEND1, 0xd400, AQBIT(e)}, 123 {MDIO_DEV_VEND1, 0xff01, AQBIT(2)}, 124 {MDIO_DEV_VEND1, AQ_IMASK_GLOBAL, AQBIT(0)} 125 }; 126 127 AQ_WRITE_REGS(phy, imasks); 128 129 return (0); 130 } 131 132 static int 133 aq100x_intr_disable(struct cphy *phy) 134 { 135 struct { 136 int mmd; 137 int reg; 138 int val; 139 } imasks[] = { 140 {MDIO_DEV_VEND1, 0xd400, 0}, 141 {MDIO_DEV_VEND1, 0xff01, 0}, 142 {MDIO_DEV_VEND1, AQ_IMASK_GLOBAL, 0} 143 }; 144 145 AQ_WRITE_REGS(phy, imasks); 146 147 return (0); 148 } 149 150 static int 151 aq100x_intr_clear(struct cphy *phy) 152 { 153 struct { 154 int mmd; 155 int reg; 156 } iclr[] = { 157 {MDIO_DEV_VEND1, 0xcc00}, 158 {MDIO_DEV_VEND1, AQ_IMASK_GLOBAL} /* needed? */ 159 }; 160 161 AQ_READ_REGS(phy, iclr); 162 163 return (0); 164 } 165 166 static int 167 aq100x_vendor_intr(struct cphy *phy, int *rc) 168 { 169 int err; 170 unsigned int cause, v; 171 172 err = mdio_read(phy, MDIO_DEV_VEND1, 0xfc01, &cause); 173 if (err) 174 return (err); 175 176 if (cause & AQBIT(2)) { 177 err = mdio_read(phy, MDIO_DEV_VEND1, 0xcc00, &v); 178 if (err) 179 return (err); 180 181 if (v & AQBIT(e)) { 182 CH_WARN(phy->adapter, "PHY%d: temperature is now %dC\n", 183 phy->addr, aq100x_temperature(phy)); 184 185 t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 186 phy->addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL, 0); 187 188 *rc |= cphy_cause_alarm; 189 } 190 191 cause &= ~4; 192 } 193 194 if (cause) 195 CH_WARN(phy->adapter, "PHY%d: unhandled vendor interrupt" 196 " (0x%x)\n", phy->addr, cause); 197 198 return (0); 199 200 } 201 202 static int 203 aq100x_intr_handler(struct cphy *phy) 204 { 205 int err, rc = 0; 206 unsigned int cause; 207 208 err = mdio_read(phy, MDIO_DEV_VEND1, AQ_IFLAG_GLOBAL, &cause); 209 if (err) 210 return (err); 211 212 if (cause & AQBIT(0)) { 213 err = aq100x_vendor_intr(phy, &rc); 214 if (err) 215 return (err); 216 cause &= ~AQBIT(0); 217 } 218 219 if (cause) 220 CH_WARN(phy->adapter, "PHY%d: unhandled interrupt (0x%x)\n", 221 phy->addr, cause); 222 223 return (rc); 224 } 225 226 static int 227 aq100x_power_down(struct cphy *phy, int off) 228 { 229 int err, wait = 500; 230 unsigned int v; 231 232 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, BMCR_PDOWN, 233 off ? BMCR_PDOWN : 0); 234 if (err || off) 235 return (err); 236 237 msleep(300); 238 do { 239 err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v); 240 if (err) 241 return (err); 242 v &= BMCR_RESET; 243 if (v) 244 msleep(10); 245 } while (v && --wait); 246 if (v) { 247 CH_WARN(phy->adapter, "PHY%d: power-up timed out (0x%x).\n", 248 phy->addr, v); 249 return (ETIMEDOUT); 250 } 251 252 return (0); 253 } 254 255 static int 256 aq100x_autoneg_enable(struct cphy *phy) 257 { 258 int err; 259 260 err = aq100x_power_down(phy, 0); 261 if (!err) 262 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, MII_BMCR, 263 BMCR_RESET, BMCR_ANENABLE | BMCR_ANRESTART); 264 265 return (err); 266 } 267 268 static int 269 aq100x_autoneg_restart(struct cphy *phy) 270 { 271 return aq100x_autoneg_enable(phy); 272 } 273 274 static int 275 aq100x_advertise(struct cphy *phy, unsigned int advertise_map) 276 { 277 unsigned int adv; 278 int err; 279 280 /* 10G advertisement */ 281 adv = 0; 282 if (advertise_map & ADVERTISED_10000baseT_Full) 283 adv |= ADV_10G_FULL; 284 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, AQ_10G_CTRL, 285 ADV_10G_FULL, adv); 286 if (err) 287 return (err); 288 289 /* 1G advertisement */ 290 adv = 0; 291 if (advertise_map & ADVERTISED_1000baseT_Full) 292 adv |= ADV_1G_FULL; 293 if (advertise_map & ADVERTISED_1000baseT_Half) 294 adv |= ADV_1G_HALF; 295 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, AQ_1G_CTRL, 296 ADV_1G_FULL | ADV_1G_HALF, adv); 297 if (err) 298 return (err); 299 300 /* 100M, pause advertisement */ 301 adv = 0; 302 if (advertise_map & ADVERTISED_100baseT_Half) 303 adv |= ADVERTISE_100HALF; 304 if (advertise_map & ADVERTISED_100baseT_Full) 305 adv |= ADVERTISE_100FULL; 306 if (advertise_map & ADVERTISED_Pause) 307 adv |= ADVERTISE_PAUSE_CAP; 308 if (advertise_map & ADVERTISED_Asym_Pause) 309 adv |= ADVERTISE_PAUSE_ASYM; 310 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, AQ_100M_CTRL, 0xfe0, adv); 311 312 return (err); 313 } 314 315 static int 316 aq100x_set_loopback(struct cphy *phy, int mmd, int dir, int enable) 317 { 318 return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 319 BMCR_LOOPBACK, enable ? BMCR_LOOPBACK : 0); 320 } 321 322 static int 323 aq100x_set_speed_duplex(struct cphy *phy, int speed, int duplex) 324 { 325 int err, set; 326 327 if (speed == SPEED_100) 328 set = BMCR_SPEED100; 329 else if (speed == SPEED_1000) 330 set = BMCR_SPEED1000; 331 else if (speed == SPEED_10000) 332 set = BMCR_SPEED1000 | BMCR_SPEED100; 333 else 334 return (EINVAL); 335 336 if (duplex != DUPLEX_FULL) 337 return (EINVAL); 338 339 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, MII_BMCR, 340 BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART, 0); 341 if (err) 342 return (err); 343 344 err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 345 BMCR_SPEED1000 | BMCR_SPEED100, set); 346 if (err) 347 return (err); 348 349 return (0); 350 } 351 352 static int 353 aq100x_get_link_status(struct cphy *phy, int *link_ok, int *speed, int *duplex, 354 int *fc) 355 { 356 int err; 357 unsigned int v, link = 0; 358 359 err = mdio_read(phy, MDIO_DEV_PMA_PMD, AQ_LINK_STAT, &v); 360 if (err) 361 return (err); 362 if (v == 0xffff || !(v & 1)) 363 goto done; 364 365 err = mdio_read(phy, MDIO_DEV_ANEG, MII_BMCR, &v); 366 if (err) 367 return (err); 368 if (v & 0x8000) 369 goto done; 370 if (v & BMCR_ANENABLE) { 371 372 err = mdio_read(phy, MDIO_DEV_ANEG, 1, &v); 373 if (err) 374 return (err); 375 if ((v & 0x20) == 0) 376 goto done; 377 378 err = mdio_read(phy, MDIO_DEV_ANEG, AQ_ANEG_STAT, &v); 379 if (err) 380 return (err); 381 382 if (speed) { 383 switch (v & 0x6) { 384 case 0x6: *speed = SPEED_10000; 385 break; 386 case 0x4: *speed = SPEED_1000; 387 break; 388 case 0x2: *speed = SPEED_100; 389 break; 390 case 0x0: *speed = SPEED_10; 391 break; 392 } 393 } 394 395 if (duplex) 396 *duplex = v & 1 ? DUPLEX_FULL : DUPLEX_HALF; 397 398 if (fc) { 399 unsigned int lpa, adv; 400 err = mdio_read(phy, MDIO_DEV_ANEG, 0x13, &lpa); 401 if (!err) 402 err = mdio_read(phy, MDIO_DEV_ANEG, 403 AQ_100M_CTRL, &adv); 404 if (err) 405 return err; 406 407 if (lpa & adv & ADVERTISE_PAUSE_CAP) 408 *fc = PAUSE_RX | PAUSE_TX; 409 else if (lpa & ADVERTISE_PAUSE_CAP && 410 lpa & ADVERTISE_PAUSE_ASYM && 411 adv & ADVERTISE_PAUSE_ASYM) 412 *fc = PAUSE_TX; 413 else if (lpa & ADVERTISE_PAUSE_ASYM && 414 adv & ADVERTISE_PAUSE_CAP) 415 *fc = PAUSE_RX; 416 else 417 *fc = 0; 418 } 419 420 } else { 421 err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v); 422 if (err) 423 return (err); 424 425 v &= BMCR_SPEED1000 | BMCR_SPEED100; 426 if (speed) { 427 if (v == (BMCR_SPEED1000 | BMCR_SPEED100)) 428 *speed = SPEED_10000; 429 else if (v == BMCR_SPEED1000) 430 *speed = SPEED_1000; 431 else if (v == BMCR_SPEED100) 432 *speed = SPEED_100; 433 else 434 *speed = SPEED_10; 435 } 436 437 if (duplex) 438 *duplex = DUPLEX_FULL; 439 } 440 441 link = 1; 442 done: 443 if (link_ok) 444 *link_ok = link; 445 return (0); 446 } 447 448 static struct cphy_ops aq100x_ops = { 449 .reset = aq100x_reset, 450 .intr_enable = aq100x_intr_enable, 451 .intr_disable = aq100x_intr_disable, 452 .intr_clear = aq100x_intr_clear, 453 .intr_handler = aq100x_intr_handler, 454 .autoneg_enable = aq100x_autoneg_enable, 455 .autoneg_restart = aq100x_autoneg_restart, 456 .advertise = aq100x_advertise, 457 .set_loopback = aq100x_set_loopback, 458 .set_speed_duplex = aq100x_set_speed_duplex, 459 .get_link_status = aq100x_get_link_status, 460 .power_down = aq100x_power_down, 461 }; 462 463 int 464 t3_aq100x_phy_prep(pinfo_t *pinfo, int phy_addr, 465 const struct mdio_ops *mdio_ops) 466 { 467 struct cphy *phy = &pinfo->phy; 468 unsigned int v, v2, gpio, wait; 469 int err; 470 adapter_t *adapter = pinfo->adapter; 471 472 cphy_init(&pinfo->phy, adapter, pinfo, phy_addr, &aq100x_ops, mdio_ops, 473 SUPPORTED_1000baseT_Full | SUPPORTED_10000baseT_Full | 474 SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_AUI | 475 SUPPORTED_MISC_IRQ, "1000/10GBASE-T"); 476 477 /* 478 * Hard reset the PHY. 479 */ 480 gpio = phy_addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL; 481 t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, 0); 482 msleep(1); 483 t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, gpio); 484 485 /* 486 * Give it enough time to load the firmware and get ready for mdio. 487 */ 488 msleep(1000); 489 wait = 500; /* in 10ms increments */ 490 do { 491 err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v); 492 if (err || v == 0xffff) { 493 494 /* Allow prep_adapter to succeed when ffff is read */ 495 496 CH_WARN(adapter, "PHY%d: reset failed (0x%x, 0x%x).\n", 497 phy_addr, err, v); 498 goto done; 499 } 500 501 v &= BMCR_RESET; 502 if (v) 503 msleep(10); 504 } while (v && --wait); 505 if (v) { 506 CH_WARN(adapter, "PHY%d: reset timed out (0x%x).\n", 507 phy_addr, v); 508 509 goto done; /* let prep_adapter succeed */ 510 } 511 512 /* Firmware version check. */ 513 (void) mdio_read(phy, MDIO_DEV_VEND1, AQ_FW_VERSION, &v); 514 if (v < 0x115) 515 CH_WARN(adapter, "PHY%d: unknown firmware %d.%d\n", phy_addr, 516 v >> 8, v & 0xff); 517 518 /* The PHY should start in really-low-power mode. */ 519 (void) mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v); 520 if ((v & BMCR_PDOWN) == 0) 521 CH_WARN(adapter, "PHY%d does not start in low power mode.\n", 522 phy_addr); 523 524 /* 525 * Verify XAUI and 1000-X settings, but let prep succeed no matter what. 526 */ 527 v = v2 = 0; 528 (void) mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_RX_CFG, &v); 529 (void) mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_TX_CFG, &v2); 530 if (v != 0x1b || v2 != 0x1b) 531 CH_WARN(adapter, "PHY%d: incorrect XAUI settings " 532 "(0x%x, 0x%x).\n", phy_addr, v, v2); 533 v = 0; 534 (void) mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_KX_CFG, &v); 535 if ((v & 0xf) != 0xf) 536 CH_WARN(adapter, "PHY%d: incorrect 1000-X settings " 537 "(0x%x).\n", phy_addr, v); 538 539 (void) aq100x_set_defaults(phy); 540 done: 541 return (err); 542 } 543