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