1 // SPDX-License-Identifier: GPL-2.0+ 2 /* Copyright (C) 2021 Maxlinear Corporation 3 * Copyright (C) 2020 Intel Corporation 4 * 5 * Drivers for Maxlinear Ethernet GPY 6 * 7 */ 8 9 #include <linux/module.h> 10 #include <linux/bitfield.h> 11 #include <linux/hwmon.h> 12 #include <linux/phy.h> 13 #include <linux/polynomial.h> 14 #include <linux/netdevice.h> 15 16 /* PHY ID */ 17 #define PHY_ID_GPYx15B_MASK 0xFFFFFFFC 18 #define PHY_ID_GPY21xB_MASK 0xFFFFFFF9 19 #define PHY_ID_GPY2xx 0x67C9DC00 20 #define PHY_ID_GPY115B 0x67C9DF00 21 #define PHY_ID_GPY115C 0x67C9DF10 22 #define PHY_ID_GPY211B 0x67C9DE08 23 #define PHY_ID_GPY211C 0x67C9DE10 24 #define PHY_ID_GPY212B 0x67C9DE09 25 #define PHY_ID_GPY212C 0x67C9DE20 26 #define PHY_ID_GPY215B 0x67C9DF04 27 #define PHY_ID_GPY215C 0x67C9DF20 28 #define PHY_ID_GPY241B 0x67C9DE40 29 #define PHY_ID_GPY241BM 0x67C9DE80 30 #define PHY_ID_GPY245B 0x67C9DEC0 31 32 #define PHY_MIISTAT 0x18 /* MII state */ 33 #define PHY_IMASK 0x19 /* interrupt mask */ 34 #define PHY_ISTAT 0x1A /* interrupt status */ 35 #define PHY_FWV 0x1E /* firmware version */ 36 37 #define PHY_MIISTAT_SPD_MASK GENMASK(2, 0) 38 #define PHY_MIISTAT_DPX BIT(3) 39 #define PHY_MIISTAT_LS BIT(10) 40 41 #define PHY_MIISTAT_SPD_10 0 42 #define PHY_MIISTAT_SPD_100 1 43 #define PHY_MIISTAT_SPD_1000 2 44 #define PHY_MIISTAT_SPD_2500 4 45 46 #define PHY_IMASK_WOL BIT(15) /* Wake-on-LAN */ 47 #define PHY_IMASK_ANC BIT(10) /* Auto-Neg complete */ 48 #define PHY_IMASK_ADSC BIT(5) /* Link auto-downspeed detect */ 49 #define PHY_IMASK_DXMC BIT(2) /* Duplex mode change */ 50 #define PHY_IMASK_LSPC BIT(1) /* Link speed change */ 51 #define PHY_IMASK_LSTC BIT(0) /* Link state change */ 52 #define PHY_IMASK_MASK (PHY_IMASK_LSTC | \ 53 PHY_IMASK_LSPC | \ 54 PHY_IMASK_DXMC | \ 55 PHY_IMASK_ADSC | \ 56 PHY_IMASK_ANC) 57 58 #define PHY_FWV_REL_MASK BIT(15) 59 #define PHY_FWV_TYPE_MASK GENMASK(11, 8) 60 #define PHY_FWV_MINOR_MASK GENMASK(7, 0) 61 62 /* SGMII */ 63 #define VSPEC1_SGMII_CTRL 0x08 64 #define VSPEC1_SGMII_CTRL_ANEN BIT(12) /* Aneg enable */ 65 #define VSPEC1_SGMII_CTRL_ANRS BIT(9) /* Restart Aneg */ 66 #define VSPEC1_SGMII_ANEN_ANRS (VSPEC1_SGMII_CTRL_ANEN | \ 67 VSPEC1_SGMII_CTRL_ANRS) 68 69 /* Temperature sensor */ 70 #define VPSPEC1_TEMP_STA 0x0E 71 #define VPSPEC1_TEMP_STA_DATA GENMASK(9, 0) 72 73 /* WoL */ 74 #define VPSPEC2_WOL_CTL 0x0E06 75 #define VPSPEC2_WOL_AD01 0x0E08 76 #define VPSPEC2_WOL_AD23 0x0E09 77 #define VPSPEC2_WOL_AD45 0x0E0A 78 #define WOL_EN BIT(0) 79 80 static const struct { 81 int type; 82 int minor; 83 } ver_need_sgmii_reaneg[] = { 84 {7, 0x6D}, 85 {8, 0x6D}, 86 {9, 0x73}, 87 }; 88 89 #if IS_ENABLED(CONFIG_HWMON) 90 /* The original translation formulae of the temperature (in degrees of Celsius) 91 * are as follows: 92 * 93 * T = -2.5761e-11*(N^4) + 9.7332e-8*(N^3) + -1.9165e-4*(N^2) + 94 * 3.0762e-1*(N^1) + -5.2156e1 95 * 96 * where [-52.156, 137.961]C and N = [0, 1023]. 97 * 98 * They must be accordingly altered to be suitable for the integer arithmetics. 99 * The technique is called 'factor redistribution', which just makes sure the 100 * multiplications and divisions are made so to have a result of the operations 101 * within the integer numbers limit. In addition we need to translate the 102 * formulae to accept millidegrees of Celsius. Here what it looks like after 103 * the alterations: 104 * 105 * T = -25761e-12*(N^4) + 97332e-9*(N^3) + -191650e-6*(N^2) + 106 * 307620e-3*(N^1) + -52156 107 * 108 * where T = [-52156, 137961]mC and N = [0, 1023]. 109 */ 110 static const struct polynomial poly_N_to_temp = { 111 .terms = { 112 {4, -25761, 1000, 1}, 113 {3, 97332, 1000, 1}, 114 {2, -191650, 1000, 1}, 115 {1, 307620, 1000, 1}, 116 {0, -52156, 1, 1} 117 } 118 }; 119 120 static int gpy_hwmon_read(struct device *dev, 121 enum hwmon_sensor_types type, 122 u32 attr, int channel, long *value) 123 { 124 struct phy_device *phydev = dev_get_drvdata(dev); 125 int ret; 126 127 ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VPSPEC1_TEMP_STA); 128 if (ret < 0) 129 return ret; 130 if (!ret) 131 return -ENODATA; 132 133 *value = polynomial_calc(&poly_N_to_temp, 134 FIELD_GET(VPSPEC1_TEMP_STA_DATA, ret)); 135 136 return 0; 137 } 138 139 static umode_t gpy_hwmon_is_visible(const void *data, 140 enum hwmon_sensor_types type, 141 u32 attr, int channel) 142 { 143 return 0444; 144 } 145 146 static const struct hwmon_channel_info *gpy_hwmon_info[] = { 147 HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT), 148 NULL 149 }; 150 151 static const struct hwmon_ops gpy_hwmon_hwmon_ops = { 152 .is_visible = gpy_hwmon_is_visible, 153 .read = gpy_hwmon_read, 154 }; 155 156 static const struct hwmon_chip_info gpy_hwmon_chip_info = { 157 .ops = &gpy_hwmon_hwmon_ops, 158 .info = gpy_hwmon_info, 159 }; 160 161 static int gpy_hwmon_register(struct phy_device *phydev) 162 { 163 struct device *dev = &phydev->mdio.dev; 164 struct device *hwmon_dev; 165 char *hwmon_name; 166 167 hwmon_name = devm_hwmon_sanitize_name(dev, dev_name(dev)); 168 if (IS_ERR(hwmon_name)) 169 return PTR_ERR(hwmon_name); 170 171 hwmon_dev = devm_hwmon_device_register_with_info(dev, hwmon_name, 172 phydev, 173 &gpy_hwmon_chip_info, 174 NULL); 175 176 return PTR_ERR_OR_ZERO(hwmon_dev); 177 } 178 #else 179 static int gpy_hwmon_register(struct phy_device *phydev) 180 { 181 return 0; 182 } 183 #endif 184 185 static int gpy_config_init(struct phy_device *phydev) 186 { 187 int ret; 188 189 /* Mask all interrupts */ 190 ret = phy_write(phydev, PHY_IMASK, 0); 191 if (ret) 192 return ret; 193 194 /* Clear all pending interrupts */ 195 ret = phy_read(phydev, PHY_ISTAT); 196 return ret < 0 ? ret : 0; 197 } 198 199 static int gpy_probe(struct phy_device *phydev) 200 { 201 int ret; 202 203 if (!phydev->is_c45) { 204 ret = phy_get_c45_ids(phydev); 205 if (ret < 0) 206 return ret; 207 } 208 209 /* Show GPY PHY FW version in dmesg */ 210 ret = phy_read(phydev, PHY_FWV); 211 if (ret < 0) 212 return ret; 213 214 ret = gpy_hwmon_register(phydev); 215 if (ret) 216 return ret; 217 218 phydev_info(phydev, "Firmware Version: 0x%04X (%s)\n", ret, 219 (ret & PHY_FWV_REL_MASK) ? "release" : "test"); 220 221 return 0; 222 } 223 224 static bool gpy_sgmii_need_reaneg(struct phy_device *phydev) 225 { 226 int fw_ver, fw_type, fw_minor; 227 size_t i; 228 229 fw_ver = phy_read(phydev, PHY_FWV); 230 if (fw_ver < 0) 231 return true; 232 233 fw_type = FIELD_GET(PHY_FWV_TYPE_MASK, fw_ver); 234 fw_minor = FIELD_GET(PHY_FWV_MINOR_MASK, fw_ver); 235 236 for (i = 0; i < ARRAY_SIZE(ver_need_sgmii_reaneg); i++) { 237 if (fw_type != ver_need_sgmii_reaneg[i].type) 238 continue; 239 if (fw_minor < ver_need_sgmii_reaneg[i].minor) 240 return true; 241 break; 242 } 243 244 return false; 245 } 246 247 static bool gpy_2500basex_chk(struct phy_device *phydev) 248 { 249 int ret; 250 251 ret = phy_read(phydev, PHY_MIISTAT); 252 if (ret < 0) { 253 phydev_err(phydev, "Error: MDIO register access failed: %d\n", 254 ret); 255 return false; 256 } 257 258 if (!(ret & PHY_MIISTAT_LS) || 259 FIELD_GET(PHY_MIISTAT_SPD_MASK, ret) != PHY_MIISTAT_SPD_2500) 260 return false; 261 262 phydev->speed = SPEED_2500; 263 phydev->interface = PHY_INTERFACE_MODE_2500BASEX; 264 phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, 265 VSPEC1_SGMII_CTRL_ANEN, 0); 266 return true; 267 } 268 269 static bool gpy_sgmii_aneg_en(struct phy_device *phydev) 270 { 271 int ret; 272 273 ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL); 274 if (ret < 0) { 275 phydev_err(phydev, "Error: MMD register access failed: %d\n", 276 ret); 277 return true; 278 } 279 280 return (ret & VSPEC1_SGMII_CTRL_ANEN) ? true : false; 281 } 282 283 static int gpy_config_aneg(struct phy_device *phydev) 284 { 285 bool changed = false; 286 u32 adv; 287 int ret; 288 289 if (phydev->autoneg == AUTONEG_DISABLE) { 290 /* Configure half duplex with genphy_setup_forced, 291 * because genphy_c45_pma_setup_forced does not support. 292 */ 293 return phydev->duplex != DUPLEX_FULL 294 ? genphy_setup_forced(phydev) 295 : genphy_c45_pma_setup_forced(phydev); 296 } 297 298 ret = genphy_c45_an_config_aneg(phydev); 299 if (ret < 0) 300 return ret; 301 if (ret > 0) 302 changed = true; 303 304 adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising); 305 ret = phy_modify_changed(phydev, MII_CTRL1000, 306 ADVERTISE_1000FULL | ADVERTISE_1000HALF, 307 adv); 308 if (ret < 0) 309 return ret; 310 if (ret > 0) 311 changed = true; 312 313 ret = genphy_c45_check_and_restart_aneg(phydev, changed); 314 if (ret < 0) 315 return ret; 316 317 if (phydev->interface == PHY_INTERFACE_MODE_USXGMII || 318 phydev->interface == PHY_INTERFACE_MODE_INTERNAL) 319 return 0; 320 321 /* No need to trigger re-ANEG if link speed is 2.5G or SGMII ANEG is 322 * disabled. 323 */ 324 if (!gpy_sgmii_need_reaneg(phydev) || gpy_2500basex_chk(phydev) || 325 !gpy_sgmii_aneg_en(phydev)) 326 return 0; 327 328 /* There is a design constraint in GPY2xx device where SGMII AN is 329 * only triggered when there is change of speed. If, PHY link 330 * partner`s speed is still same even after PHY TPI is down and up 331 * again, SGMII AN is not triggered and hence no new in-band message 332 * from GPY to MAC side SGMII. 333 * This could cause an issue during power up, when PHY is up prior to 334 * MAC. At this condition, once MAC side SGMII is up, MAC side SGMII 335 * wouldn`t receive new in-band message from GPY with correct link 336 * status, speed and duplex info. 337 * 338 * 1) If PHY is already up and TPI link status is still down (such as 339 * hard reboot), TPI link status is polled for 4 seconds before 340 * retriggerring SGMII AN. 341 * 2) If PHY is already up and TPI link status is also up (such as soft 342 * reboot), polling of TPI link status is not needed and SGMII AN is 343 * immediately retriggered. 344 * 3) Other conditions such as PHY is down, speed change etc, skip 345 * retriggering SGMII AN. Note: in case of speed change, GPY FW will 346 * initiate SGMII AN. 347 */ 348 349 if (phydev->state != PHY_UP) 350 return 0; 351 352 ret = phy_read_poll_timeout(phydev, MII_BMSR, ret, ret & BMSR_LSTATUS, 353 20000, 4000000, false); 354 if (ret == -ETIMEDOUT) 355 return 0; 356 else if (ret < 0) 357 return ret; 358 359 /* Trigger SGMII AN. */ 360 return phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, 361 VSPEC1_SGMII_CTRL_ANRS, VSPEC1_SGMII_CTRL_ANRS); 362 } 363 364 static void gpy_update_interface(struct phy_device *phydev) 365 { 366 int ret; 367 368 /* Interface mode is fixed for USXGMII and integrated PHY */ 369 if (phydev->interface == PHY_INTERFACE_MODE_USXGMII || 370 phydev->interface == PHY_INTERFACE_MODE_INTERNAL) 371 return; 372 373 /* Automatically switch SERDES interface between SGMII and 2500-BaseX 374 * according to speed. Disable ANEG in 2500-BaseX mode. 375 */ 376 switch (phydev->speed) { 377 case SPEED_2500: 378 phydev->interface = PHY_INTERFACE_MODE_2500BASEX; 379 ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, 380 VSPEC1_SGMII_CTRL_ANEN, 0); 381 if (ret < 0) 382 phydev_err(phydev, 383 "Error: Disable of SGMII ANEG failed: %d\n", 384 ret); 385 break; 386 case SPEED_1000: 387 case SPEED_100: 388 case SPEED_10: 389 phydev->interface = PHY_INTERFACE_MODE_SGMII; 390 if (gpy_sgmii_aneg_en(phydev)) 391 break; 392 /* Enable and restart SGMII ANEG for 10/100/1000Mbps link speed 393 * if ANEG is disabled (in 2500-BaseX mode). 394 */ 395 ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL, 396 VSPEC1_SGMII_ANEN_ANRS, 397 VSPEC1_SGMII_ANEN_ANRS); 398 if (ret < 0) 399 phydev_err(phydev, 400 "Error: Enable of SGMII ANEG failed: %d\n", 401 ret); 402 break; 403 } 404 405 if (phydev->speed == SPEED_2500 || phydev->speed == SPEED_1000) 406 genphy_read_master_slave(phydev); 407 } 408 409 static int gpy_read_status(struct phy_device *phydev) 410 { 411 int ret; 412 413 ret = genphy_update_link(phydev); 414 if (ret) 415 return ret; 416 417 phydev->speed = SPEED_UNKNOWN; 418 phydev->duplex = DUPLEX_UNKNOWN; 419 phydev->pause = 0; 420 phydev->asym_pause = 0; 421 422 if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) { 423 ret = genphy_c45_read_lpa(phydev); 424 if (ret < 0) 425 return ret; 426 427 /* Read the link partner's 1G advertisement */ 428 ret = phy_read(phydev, MII_STAT1000); 429 if (ret < 0) 430 return ret; 431 mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, ret); 432 } else if (phydev->autoneg == AUTONEG_DISABLE) { 433 linkmode_zero(phydev->lp_advertising); 434 } 435 436 ret = phy_read(phydev, PHY_MIISTAT); 437 if (ret < 0) 438 return ret; 439 440 phydev->link = (ret & PHY_MIISTAT_LS) ? 1 : 0; 441 phydev->duplex = (ret & PHY_MIISTAT_DPX) ? DUPLEX_FULL : DUPLEX_HALF; 442 switch (FIELD_GET(PHY_MIISTAT_SPD_MASK, ret)) { 443 case PHY_MIISTAT_SPD_10: 444 phydev->speed = SPEED_10; 445 break; 446 case PHY_MIISTAT_SPD_100: 447 phydev->speed = SPEED_100; 448 break; 449 case PHY_MIISTAT_SPD_1000: 450 phydev->speed = SPEED_1000; 451 break; 452 case PHY_MIISTAT_SPD_2500: 453 phydev->speed = SPEED_2500; 454 break; 455 } 456 457 if (phydev->link) 458 gpy_update_interface(phydev); 459 460 return 0; 461 } 462 463 static int gpy_config_intr(struct phy_device *phydev) 464 { 465 u16 mask = 0; 466 467 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 468 mask = PHY_IMASK_MASK; 469 470 return phy_write(phydev, PHY_IMASK, mask); 471 } 472 473 static irqreturn_t gpy_handle_interrupt(struct phy_device *phydev) 474 { 475 int reg; 476 477 reg = phy_read(phydev, PHY_ISTAT); 478 if (reg < 0) { 479 phy_error(phydev); 480 return IRQ_NONE; 481 } 482 483 if (!(reg & PHY_IMASK_MASK)) 484 return IRQ_NONE; 485 486 phy_trigger_machine(phydev); 487 488 return IRQ_HANDLED; 489 } 490 491 static int gpy_set_wol(struct phy_device *phydev, 492 struct ethtool_wolinfo *wol) 493 { 494 struct net_device *attach_dev = phydev->attached_dev; 495 int ret; 496 497 if (wol->wolopts & WAKE_MAGIC) { 498 /* MAC address - Byte0:Byte1:Byte2:Byte3:Byte4:Byte5 499 * VPSPEC2_WOL_AD45 = Byte0:Byte1 500 * VPSPEC2_WOL_AD23 = Byte2:Byte3 501 * VPSPEC2_WOL_AD01 = Byte4:Byte5 502 */ 503 ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, 504 VPSPEC2_WOL_AD45, 505 ((attach_dev->dev_addr[0] << 8) | 506 attach_dev->dev_addr[1])); 507 if (ret < 0) 508 return ret; 509 510 ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, 511 VPSPEC2_WOL_AD23, 512 ((attach_dev->dev_addr[2] << 8) | 513 attach_dev->dev_addr[3])); 514 if (ret < 0) 515 return ret; 516 517 ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, 518 VPSPEC2_WOL_AD01, 519 ((attach_dev->dev_addr[4] << 8) | 520 attach_dev->dev_addr[5])); 521 if (ret < 0) 522 return ret; 523 524 /* Enable the WOL interrupt */ 525 ret = phy_write(phydev, PHY_IMASK, PHY_IMASK_WOL); 526 if (ret < 0) 527 return ret; 528 529 /* Enable magic packet matching */ 530 ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, 531 VPSPEC2_WOL_CTL, 532 WOL_EN); 533 if (ret < 0) 534 return ret; 535 536 /* Clear the interrupt status register. 537 * Only WoL is enabled so clear all. 538 */ 539 ret = phy_read(phydev, PHY_ISTAT); 540 if (ret < 0) 541 return ret; 542 } else { 543 /* Disable magic packet matching */ 544 ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, 545 VPSPEC2_WOL_CTL, 546 WOL_EN); 547 if (ret < 0) 548 return ret; 549 } 550 551 if (wol->wolopts & WAKE_PHY) { 552 /* Enable the link state change interrupt */ 553 ret = phy_set_bits(phydev, PHY_IMASK, PHY_IMASK_LSTC); 554 if (ret < 0) 555 return ret; 556 557 /* Clear the interrupt status register */ 558 ret = phy_read(phydev, PHY_ISTAT); 559 if (ret < 0) 560 return ret; 561 562 if (ret & (PHY_IMASK_MASK & ~PHY_IMASK_LSTC)) 563 phy_trigger_machine(phydev); 564 565 return 0; 566 } 567 568 /* Disable the link state change interrupt */ 569 return phy_clear_bits(phydev, PHY_IMASK, PHY_IMASK_LSTC); 570 } 571 572 static void gpy_get_wol(struct phy_device *phydev, 573 struct ethtool_wolinfo *wol) 574 { 575 int ret; 576 577 wol->supported = WAKE_MAGIC | WAKE_PHY; 578 wol->wolopts = 0; 579 580 ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, VPSPEC2_WOL_CTL); 581 if (ret & WOL_EN) 582 wol->wolopts |= WAKE_MAGIC; 583 584 ret = phy_read(phydev, PHY_IMASK); 585 if (ret & PHY_IMASK_LSTC) 586 wol->wolopts |= WAKE_PHY; 587 } 588 589 static int gpy_loopback(struct phy_device *phydev, bool enable) 590 { 591 int ret; 592 593 ret = phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK, 594 enable ? BMCR_LOOPBACK : 0); 595 if (!ret) { 596 /* It takes some time for PHY device to switch 597 * into/out-of loopback mode. 598 */ 599 msleep(100); 600 } 601 602 return ret; 603 } 604 605 static int gpy115_loopback(struct phy_device *phydev, bool enable) 606 { 607 int ret; 608 int fw_minor; 609 610 if (enable) 611 return gpy_loopback(phydev, enable); 612 613 ret = phy_read(phydev, PHY_FWV); 614 if (ret < 0) 615 return ret; 616 617 fw_minor = FIELD_GET(PHY_FWV_MINOR_MASK, ret); 618 if (fw_minor > 0x0076) 619 return gpy_loopback(phydev, 0); 620 621 return genphy_soft_reset(phydev); 622 } 623 624 static struct phy_driver gpy_drivers[] = { 625 { 626 PHY_ID_MATCH_MODEL(PHY_ID_GPY2xx), 627 .name = "Maxlinear Ethernet GPY2xx", 628 .get_features = genphy_c45_pma_read_abilities, 629 .config_init = gpy_config_init, 630 .probe = gpy_probe, 631 .suspend = genphy_suspend, 632 .resume = genphy_resume, 633 .config_aneg = gpy_config_aneg, 634 .aneg_done = genphy_c45_aneg_done, 635 .read_status = gpy_read_status, 636 .config_intr = gpy_config_intr, 637 .handle_interrupt = gpy_handle_interrupt, 638 .set_wol = gpy_set_wol, 639 .get_wol = gpy_get_wol, 640 .set_loopback = gpy_loopback, 641 }, 642 { 643 .phy_id = PHY_ID_GPY115B, 644 .phy_id_mask = PHY_ID_GPYx15B_MASK, 645 .name = "Maxlinear Ethernet GPY115B", 646 .get_features = genphy_c45_pma_read_abilities, 647 .config_init = gpy_config_init, 648 .probe = gpy_probe, 649 .suspend = genphy_suspend, 650 .resume = genphy_resume, 651 .config_aneg = gpy_config_aneg, 652 .aneg_done = genphy_c45_aneg_done, 653 .read_status = gpy_read_status, 654 .config_intr = gpy_config_intr, 655 .handle_interrupt = gpy_handle_interrupt, 656 .set_wol = gpy_set_wol, 657 .get_wol = gpy_get_wol, 658 .set_loopback = gpy115_loopback, 659 }, 660 { 661 PHY_ID_MATCH_MODEL(PHY_ID_GPY115C), 662 .name = "Maxlinear Ethernet GPY115C", 663 .get_features = genphy_c45_pma_read_abilities, 664 .config_init = gpy_config_init, 665 .probe = gpy_probe, 666 .suspend = genphy_suspend, 667 .resume = genphy_resume, 668 .config_aneg = gpy_config_aneg, 669 .aneg_done = genphy_c45_aneg_done, 670 .read_status = gpy_read_status, 671 .config_intr = gpy_config_intr, 672 .handle_interrupt = gpy_handle_interrupt, 673 .set_wol = gpy_set_wol, 674 .get_wol = gpy_get_wol, 675 .set_loopback = gpy115_loopback, 676 }, 677 { 678 .phy_id = PHY_ID_GPY211B, 679 .phy_id_mask = PHY_ID_GPY21xB_MASK, 680 .name = "Maxlinear Ethernet GPY211B", 681 .get_features = genphy_c45_pma_read_abilities, 682 .config_init = gpy_config_init, 683 .probe = gpy_probe, 684 .suspend = genphy_suspend, 685 .resume = genphy_resume, 686 .config_aneg = gpy_config_aneg, 687 .aneg_done = genphy_c45_aneg_done, 688 .read_status = gpy_read_status, 689 .config_intr = gpy_config_intr, 690 .handle_interrupt = gpy_handle_interrupt, 691 .set_wol = gpy_set_wol, 692 .get_wol = gpy_get_wol, 693 .set_loopback = gpy_loopback, 694 }, 695 { 696 PHY_ID_MATCH_MODEL(PHY_ID_GPY211C), 697 .name = "Maxlinear Ethernet GPY211C", 698 .get_features = genphy_c45_pma_read_abilities, 699 .config_init = gpy_config_init, 700 .probe = gpy_probe, 701 .suspend = genphy_suspend, 702 .resume = genphy_resume, 703 .config_aneg = gpy_config_aneg, 704 .aneg_done = genphy_c45_aneg_done, 705 .read_status = gpy_read_status, 706 .config_intr = gpy_config_intr, 707 .handle_interrupt = gpy_handle_interrupt, 708 .set_wol = gpy_set_wol, 709 .get_wol = gpy_get_wol, 710 .set_loopback = gpy_loopback, 711 }, 712 { 713 .phy_id = PHY_ID_GPY212B, 714 .phy_id_mask = PHY_ID_GPY21xB_MASK, 715 .name = "Maxlinear Ethernet GPY212B", 716 .get_features = genphy_c45_pma_read_abilities, 717 .config_init = gpy_config_init, 718 .probe = gpy_probe, 719 .suspend = genphy_suspend, 720 .resume = genphy_resume, 721 .config_aneg = gpy_config_aneg, 722 .aneg_done = genphy_c45_aneg_done, 723 .read_status = gpy_read_status, 724 .config_intr = gpy_config_intr, 725 .handle_interrupt = gpy_handle_interrupt, 726 .set_wol = gpy_set_wol, 727 .get_wol = gpy_get_wol, 728 .set_loopback = gpy_loopback, 729 }, 730 { 731 PHY_ID_MATCH_MODEL(PHY_ID_GPY212C), 732 .name = "Maxlinear Ethernet GPY212C", 733 .get_features = genphy_c45_pma_read_abilities, 734 .config_init = gpy_config_init, 735 .probe = gpy_probe, 736 .suspend = genphy_suspend, 737 .resume = genphy_resume, 738 .config_aneg = gpy_config_aneg, 739 .aneg_done = genphy_c45_aneg_done, 740 .read_status = gpy_read_status, 741 .config_intr = gpy_config_intr, 742 .handle_interrupt = gpy_handle_interrupt, 743 .set_wol = gpy_set_wol, 744 .get_wol = gpy_get_wol, 745 .set_loopback = gpy_loopback, 746 }, 747 { 748 .phy_id = PHY_ID_GPY215B, 749 .phy_id_mask = PHY_ID_GPYx15B_MASK, 750 .name = "Maxlinear Ethernet GPY215B", 751 .get_features = genphy_c45_pma_read_abilities, 752 .config_init = gpy_config_init, 753 .probe = gpy_probe, 754 .suspend = genphy_suspend, 755 .resume = genphy_resume, 756 .config_aneg = gpy_config_aneg, 757 .aneg_done = genphy_c45_aneg_done, 758 .read_status = gpy_read_status, 759 .config_intr = gpy_config_intr, 760 .handle_interrupt = gpy_handle_interrupt, 761 .set_wol = gpy_set_wol, 762 .get_wol = gpy_get_wol, 763 .set_loopback = gpy_loopback, 764 }, 765 { 766 PHY_ID_MATCH_MODEL(PHY_ID_GPY215C), 767 .name = "Maxlinear Ethernet GPY215C", 768 .get_features = genphy_c45_pma_read_abilities, 769 .config_init = gpy_config_init, 770 .probe = gpy_probe, 771 .suspend = genphy_suspend, 772 .resume = genphy_resume, 773 .config_aneg = gpy_config_aneg, 774 .aneg_done = genphy_c45_aneg_done, 775 .read_status = gpy_read_status, 776 .config_intr = gpy_config_intr, 777 .handle_interrupt = gpy_handle_interrupt, 778 .set_wol = gpy_set_wol, 779 .get_wol = gpy_get_wol, 780 .set_loopback = gpy_loopback, 781 }, 782 { 783 PHY_ID_MATCH_MODEL(PHY_ID_GPY241B), 784 .name = "Maxlinear Ethernet GPY241B", 785 .get_features = genphy_c45_pma_read_abilities, 786 .config_init = gpy_config_init, 787 .probe = gpy_probe, 788 .suspend = genphy_suspend, 789 .resume = genphy_resume, 790 .config_aneg = gpy_config_aneg, 791 .aneg_done = genphy_c45_aneg_done, 792 .read_status = gpy_read_status, 793 .config_intr = gpy_config_intr, 794 .handle_interrupt = gpy_handle_interrupt, 795 .set_wol = gpy_set_wol, 796 .get_wol = gpy_get_wol, 797 .set_loopback = gpy_loopback, 798 }, 799 { 800 PHY_ID_MATCH_MODEL(PHY_ID_GPY241BM), 801 .name = "Maxlinear Ethernet GPY241BM", 802 .get_features = genphy_c45_pma_read_abilities, 803 .config_init = gpy_config_init, 804 .probe = gpy_probe, 805 .suspend = genphy_suspend, 806 .resume = genphy_resume, 807 .config_aneg = gpy_config_aneg, 808 .aneg_done = genphy_c45_aneg_done, 809 .read_status = gpy_read_status, 810 .config_intr = gpy_config_intr, 811 .handle_interrupt = gpy_handle_interrupt, 812 .set_wol = gpy_set_wol, 813 .get_wol = gpy_get_wol, 814 .set_loopback = gpy_loopback, 815 }, 816 { 817 PHY_ID_MATCH_MODEL(PHY_ID_GPY245B), 818 .name = "Maxlinear Ethernet GPY245B", 819 .get_features = genphy_c45_pma_read_abilities, 820 .config_init = gpy_config_init, 821 .probe = gpy_probe, 822 .suspend = genphy_suspend, 823 .resume = genphy_resume, 824 .config_aneg = gpy_config_aneg, 825 .aneg_done = genphy_c45_aneg_done, 826 .read_status = gpy_read_status, 827 .config_intr = gpy_config_intr, 828 .handle_interrupt = gpy_handle_interrupt, 829 .set_wol = gpy_set_wol, 830 .get_wol = gpy_get_wol, 831 .set_loopback = gpy_loopback, 832 }, 833 }; 834 module_phy_driver(gpy_drivers); 835 836 static struct mdio_device_id __maybe_unused gpy_tbl[] = { 837 {PHY_ID_MATCH_MODEL(PHY_ID_GPY2xx)}, 838 {PHY_ID_GPY115B, PHY_ID_GPYx15B_MASK}, 839 {PHY_ID_MATCH_MODEL(PHY_ID_GPY115C)}, 840 {PHY_ID_GPY211B, PHY_ID_GPY21xB_MASK}, 841 {PHY_ID_MATCH_MODEL(PHY_ID_GPY211C)}, 842 {PHY_ID_GPY212B, PHY_ID_GPY21xB_MASK}, 843 {PHY_ID_MATCH_MODEL(PHY_ID_GPY212C)}, 844 {PHY_ID_GPY215B, PHY_ID_GPYx15B_MASK}, 845 {PHY_ID_MATCH_MODEL(PHY_ID_GPY215C)}, 846 {PHY_ID_MATCH_MODEL(PHY_ID_GPY241B)}, 847 {PHY_ID_MATCH_MODEL(PHY_ID_GPY241BM)}, 848 {PHY_ID_MATCH_MODEL(PHY_ID_GPY245B)}, 849 { } 850 }; 851 MODULE_DEVICE_TABLE(mdio, gpy_tbl); 852 853 MODULE_DESCRIPTION("Maxlinear Ethernet GPY Driver"); 854 MODULE_AUTHOR("Xu Liang"); 855 MODULE_LICENSE("GPL"); 856