1 // SPDX-License-Identifier: GPL-2.0 2 /* Driver for the Texas Instruments DP83822, DP83825 and DP83826 PHYs. 3 * 4 * Copyright (C) 2017 Texas Instruments Inc. 5 */ 6 7 #include <linux/ethtool.h> 8 #include <linux/etherdevice.h> 9 #include <linux/kernel.h> 10 #include <linux/mii.h> 11 #include <linux/module.h> 12 #include <linux/of.h> 13 #include <linux/phy.h> 14 #include <linux/netdevice.h> 15 16 #define DP83822_PHY_ID 0x2000a240 17 #define DP83825S_PHY_ID 0x2000a140 18 #define DP83825I_PHY_ID 0x2000a150 19 #define DP83825CM_PHY_ID 0x2000a160 20 #define DP83825CS_PHY_ID 0x2000a170 21 #define DP83826C_PHY_ID 0x2000a130 22 #define DP83826NC_PHY_ID 0x2000a110 23 24 #define DP83822_DEVADDR 0x1f 25 26 #define MII_DP83822_CTRL_2 0x0a 27 #define MII_DP83822_PHYSTS 0x10 28 #define MII_DP83822_PHYSCR 0x11 29 #define MII_DP83822_MISR1 0x12 30 #define MII_DP83822_MISR2 0x13 31 #define MII_DP83822_FCSCR 0x14 32 #define MII_DP83822_RCSR 0x17 33 #define MII_DP83822_RESET_CTRL 0x1f 34 #define MII_DP83822_GENCFG 0x465 35 #define MII_DP83822_SOR1 0x467 36 37 /* GENCFG */ 38 #define DP83822_SIG_DET_LOW BIT(0) 39 40 /* Control Register 2 bits */ 41 #define DP83822_FX_ENABLE BIT(14) 42 43 #define DP83822_HW_RESET BIT(15) 44 #define DP83822_SW_RESET BIT(14) 45 46 /* PHY STS bits */ 47 #define DP83822_PHYSTS_DUPLEX BIT(2) 48 #define DP83822_PHYSTS_10 BIT(1) 49 #define DP83822_PHYSTS_LINK BIT(0) 50 51 /* PHYSCR Register Fields */ 52 #define DP83822_PHYSCR_INT_OE BIT(0) /* Interrupt Output Enable */ 53 #define DP83822_PHYSCR_INTEN BIT(1) /* Interrupt Enable */ 54 55 /* MISR1 bits */ 56 #define DP83822_RX_ERR_HF_INT_EN BIT(0) 57 #define DP83822_FALSE_CARRIER_HF_INT_EN BIT(1) 58 #define DP83822_ANEG_COMPLETE_INT_EN BIT(2) 59 #define DP83822_DUP_MODE_CHANGE_INT_EN BIT(3) 60 #define DP83822_SPEED_CHANGED_INT_EN BIT(4) 61 #define DP83822_LINK_STAT_INT_EN BIT(5) 62 #define DP83822_ENERGY_DET_INT_EN BIT(6) 63 #define DP83822_LINK_QUAL_INT_EN BIT(7) 64 65 /* MISR2 bits */ 66 #define DP83822_JABBER_DET_INT_EN BIT(0) 67 #define DP83822_WOL_PKT_INT_EN BIT(1) 68 #define DP83822_SLEEP_MODE_INT_EN BIT(2) 69 #define DP83822_MDI_XOVER_INT_EN BIT(3) 70 #define DP83822_LB_FIFO_INT_EN BIT(4) 71 #define DP83822_PAGE_RX_INT_EN BIT(5) 72 #define DP83822_ANEG_ERR_INT_EN BIT(6) 73 #define DP83822_EEE_ERROR_CHANGE_INT_EN BIT(7) 74 75 /* INT_STAT1 bits */ 76 #define DP83822_WOL_INT_EN BIT(4) 77 #define DP83822_WOL_INT_STAT BIT(12) 78 79 #define MII_DP83822_RXSOP1 0x04a5 80 #define MII_DP83822_RXSOP2 0x04a6 81 #define MII_DP83822_RXSOP3 0x04a7 82 83 /* WoL Registers */ 84 #define MII_DP83822_WOL_CFG 0x04a0 85 #define MII_DP83822_WOL_STAT 0x04a1 86 #define MII_DP83822_WOL_DA1 0x04a2 87 #define MII_DP83822_WOL_DA2 0x04a3 88 #define MII_DP83822_WOL_DA3 0x04a4 89 90 /* WoL bits */ 91 #define DP83822_WOL_MAGIC_EN BIT(0) 92 #define DP83822_WOL_SECURE_ON BIT(5) 93 #define DP83822_WOL_EN BIT(7) 94 #define DP83822_WOL_INDICATION_SEL BIT(8) 95 #define DP83822_WOL_CLR_INDICATION BIT(11) 96 97 /* RCSR bits */ 98 #define DP83822_RGMII_MODE_EN BIT(9) 99 #define DP83822_RX_CLK_SHIFT BIT(12) 100 #define DP83822_TX_CLK_SHIFT BIT(11) 101 102 /* SOR1 mode */ 103 #define DP83822_STRAP_MODE1 0 104 #define DP83822_STRAP_MODE2 BIT(0) 105 #define DP83822_STRAP_MODE3 BIT(1) 106 #define DP83822_STRAP_MODE4 GENMASK(1, 0) 107 108 #define DP83822_COL_STRAP_MASK GENMASK(11, 10) 109 #define DP83822_COL_SHIFT 10 110 #define DP83822_RX_ER_STR_MASK GENMASK(9, 8) 111 #define DP83822_RX_ER_SHIFT 8 112 113 #define MII_DP83822_FIBER_ADVERTISE (ADVERTISED_TP | ADVERTISED_MII | \ 114 ADVERTISED_FIBRE | \ 115 ADVERTISED_Pause | ADVERTISED_Asym_Pause) 116 117 struct dp83822_private { 118 bool fx_signal_det_low; 119 int fx_enabled; 120 u16 fx_sd_enable; 121 }; 122 123 static int dp83822_set_wol(struct phy_device *phydev, 124 struct ethtool_wolinfo *wol) 125 { 126 struct net_device *ndev = phydev->attached_dev; 127 u16 value; 128 const u8 *mac; 129 130 if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) { 131 mac = (const u8 *)ndev->dev_addr; 132 133 if (!is_valid_ether_addr(mac)) 134 return -EINVAL; 135 136 /* MAC addresses start with byte 5, but stored in mac[0]. 137 * 822 PHYs store bytes 4|5, 2|3, 0|1 138 */ 139 phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA1, 140 (mac[1] << 8) | mac[0]); 141 phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA2, 142 (mac[3] << 8) | mac[2]); 143 phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA3, 144 (mac[5] << 8) | mac[4]); 145 146 value = phy_read_mmd(phydev, DP83822_DEVADDR, 147 MII_DP83822_WOL_CFG); 148 if (wol->wolopts & WAKE_MAGIC) 149 value |= DP83822_WOL_MAGIC_EN; 150 else 151 value &= ~DP83822_WOL_MAGIC_EN; 152 153 if (wol->wolopts & WAKE_MAGICSECURE) { 154 phy_write_mmd(phydev, DP83822_DEVADDR, 155 MII_DP83822_RXSOP1, 156 (wol->sopass[1] << 8) | wol->sopass[0]); 157 phy_write_mmd(phydev, DP83822_DEVADDR, 158 MII_DP83822_RXSOP2, 159 (wol->sopass[3] << 8) | wol->sopass[2]); 160 phy_write_mmd(phydev, DP83822_DEVADDR, 161 MII_DP83822_RXSOP3, 162 (wol->sopass[5] << 8) | wol->sopass[4]); 163 value |= DP83822_WOL_SECURE_ON; 164 } else { 165 value &= ~DP83822_WOL_SECURE_ON; 166 } 167 168 /* Clear any pending WoL interrupt */ 169 phy_read(phydev, MII_DP83822_MISR2); 170 171 value |= DP83822_WOL_EN | DP83822_WOL_INDICATION_SEL | 172 DP83822_WOL_CLR_INDICATION; 173 174 return phy_write_mmd(phydev, DP83822_DEVADDR, 175 MII_DP83822_WOL_CFG, value); 176 } else { 177 return phy_clear_bits_mmd(phydev, DP83822_DEVADDR, 178 MII_DP83822_WOL_CFG, DP83822_WOL_EN); 179 } 180 } 181 182 static void dp83822_get_wol(struct phy_device *phydev, 183 struct ethtool_wolinfo *wol) 184 { 185 int value; 186 u16 sopass_val; 187 188 wol->supported = (WAKE_MAGIC | WAKE_MAGICSECURE); 189 wol->wolopts = 0; 190 191 value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG); 192 193 if (value & DP83822_WOL_MAGIC_EN) 194 wol->wolopts |= WAKE_MAGIC; 195 196 if (value & DP83822_WOL_SECURE_ON) { 197 sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR, 198 MII_DP83822_RXSOP1); 199 wol->sopass[0] = (sopass_val & 0xff); 200 wol->sopass[1] = (sopass_val >> 8); 201 202 sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR, 203 MII_DP83822_RXSOP2); 204 wol->sopass[2] = (sopass_val & 0xff); 205 wol->sopass[3] = (sopass_val >> 8); 206 207 sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR, 208 MII_DP83822_RXSOP3); 209 wol->sopass[4] = (sopass_val & 0xff); 210 wol->sopass[5] = (sopass_val >> 8); 211 212 wol->wolopts |= WAKE_MAGICSECURE; 213 } 214 215 /* WoL is not enabled so set wolopts to 0 */ 216 if (!(value & DP83822_WOL_EN)) 217 wol->wolopts = 0; 218 } 219 220 static int dp83822_config_intr(struct phy_device *phydev) 221 { 222 struct dp83822_private *dp83822 = phydev->priv; 223 int misr_status; 224 int physcr_status; 225 int err; 226 227 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 228 misr_status = phy_read(phydev, MII_DP83822_MISR1); 229 if (misr_status < 0) 230 return misr_status; 231 232 misr_status |= (DP83822_LINK_STAT_INT_EN | 233 DP83822_ENERGY_DET_INT_EN | 234 DP83822_LINK_QUAL_INT_EN); 235 236 if (!dp83822->fx_enabled) 237 misr_status |= DP83822_ANEG_COMPLETE_INT_EN | 238 DP83822_DUP_MODE_CHANGE_INT_EN | 239 DP83822_SPEED_CHANGED_INT_EN; 240 241 242 err = phy_write(phydev, MII_DP83822_MISR1, misr_status); 243 if (err < 0) 244 return err; 245 246 misr_status = phy_read(phydev, MII_DP83822_MISR2); 247 if (misr_status < 0) 248 return misr_status; 249 250 misr_status |= (DP83822_JABBER_DET_INT_EN | 251 DP83822_SLEEP_MODE_INT_EN | 252 DP83822_LB_FIFO_INT_EN | 253 DP83822_PAGE_RX_INT_EN | 254 DP83822_EEE_ERROR_CHANGE_INT_EN); 255 256 if (!dp83822->fx_enabled) 257 misr_status |= DP83822_ANEG_ERR_INT_EN | 258 DP83822_WOL_PKT_INT_EN; 259 260 err = phy_write(phydev, MII_DP83822_MISR2, misr_status); 261 if (err < 0) 262 return err; 263 264 physcr_status = phy_read(phydev, MII_DP83822_PHYSCR); 265 if (physcr_status < 0) 266 return physcr_status; 267 268 physcr_status |= DP83822_PHYSCR_INT_OE | DP83822_PHYSCR_INTEN; 269 270 } else { 271 err = phy_write(phydev, MII_DP83822_MISR1, 0); 272 if (err < 0) 273 return err; 274 275 err = phy_write(phydev, MII_DP83822_MISR2, 0); 276 if (err < 0) 277 return err; 278 279 physcr_status = phy_read(phydev, MII_DP83822_PHYSCR); 280 if (physcr_status < 0) 281 return physcr_status; 282 283 physcr_status &= ~DP83822_PHYSCR_INTEN; 284 } 285 286 return phy_write(phydev, MII_DP83822_PHYSCR, physcr_status); 287 } 288 289 static irqreturn_t dp83822_handle_interrupt(struct phy_device *phydev) 290 { 291 bool trigger_machine = false; 292 int irq_status; 293 294 /* The MISR1 and MISR2 registers are holding the interrupt status in 295 * the upper half (15:8), while the lower half (7:0) is used for 296 * controlling the interrupt enable state of those individual interrupt 297 * sources. To determine the possible interrupt sources, just read the 298 * MISR* register and use it directly to know which interrupts have 299 * been enabled previously or not. 300 */ 301 irq_status = phy_read(phydev, MII_DP83822_MISR1); 302 if (irq_status < 0) { 303 phy_error(phydev); 304 return IRQ_NONE; 305 } 306 if (irq_status & ((irq_status & GENMASK(7, 0)) << 8)) 307 trigger_machine = true; 308 309 irq_status = phy_read(phydev, MII_DP83822_MISR2); 310 if (irq_status < 0) { 311 phy_error(phydev); 312 return IRQ_NONE; 313 } 314 if (irq_status & ((irq_status & GENMASK(7, 0)) << 8)) 315 trigger_machine = true; 316 317 if (!trigger_machine) 318 return IRQ_NONE; 319 320 phy_trigger_machine(phydev); 321 322 return IRQ_HANDLED; 323 } 324 325 static int dp8382x_disable_wol(struct phy_device *phydev) 326 { 327 return phy_clear_bits_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG, 328 DP83822_WOL_EN | DP83822_WOL_MAGIC_EN | 329 DP83822_WOL_SECURE_ON); 330 } 331 332 static int dp83822_read_status(struct phy_device *phydev) 333 { 334 struct dp83822_private *dp83822 = phydev->priv; 335 int status = phy_read(phydev, MII_DP83822_PHYSTS); 336 int ctrl2; 337 int ret; 338 339 if (dp83822->fx_enabled) { 340 if (status & DP83822_PHYSTS_LINK) { 341 phydev->speed = SPEED_UNKNOWN; 342 phydev->duplex = DUPLEX_UNKNOWN; 343 } else { 344 ctrl2 = phy_read(phydev, MII_DP83822_CTRL_2); 345 if (ctrl2 < 0) 346 return ctrl2; 347 348 if (!(ctrl2 & DP83822_FX_ENABLE)) { 349 ret = phy_write(phydev, MII_DP83822_CTRL_2, 350 DP83822_FX_ENABLE | ctrl2); 351 if (ret < 0) 352 return ret; 353 } 354 } 355 } 356 357 ret = genphy_read_status(phydev); 358 if (ret) 359 return ret; 360 361 if (status < 0) 362 return status; 363 364 if (status & DP83822_PHYSTS_DUPLEX) 365 phydev->duplex = DUPLEX_FULL; 366 else 367 phydev->duplex = DUPLEX_HALF; 368 369 if (status & DP83822_PHYSTS_10) 370 phydev->speed = SPEED_10; 371 else 372 phydev->speed = SPEED_100; 373 374 return 0; 375 } 376 377 static int dp83822_config_init(struct phy_device *phydev) 378 { 379 struct dp83822_private *dp83822 = phydev->priv; 380 struct device *dev = &phydev->mdio.dev; 381 int rgmii_delay; 382 s32 rx_int_delay; 383 s32 tx_int_delay; 384 int err = 0; 385 int bmcr; 386 387 if (phy_interface_is_rgmii(phydev)) { 388 rx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0, 389 true); 390 391 if (rx_int_delay <= 0) 392 rgmii_delay = 0; 393 else 394 rgmii_delay = DP83822_RX_CLK_SHIFT; 395 396 tx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0, 397 false); 398 if (tx_int_delay <= 0) 399 rgmii_delay &= ~DP83822_TX_CLK_SHIFT; 400 else 401 rgmii_delay |= DP83822_TX_CLK_SHIFT; 402 403 if (rgmii_delay) { 404 err = phy_set_bits_mmd(phydev, DP83822_DEVADDR, 405 MII_DP83822_RCSR, rgmii_delay); 406 if (err) 407 return err; 408 } 409 410 phy_set_bits_mmd(phydev, DP83822_DEVADDR, 411 MII_DP83822_RCSR, DP83822_RGMII_MODE_EN); 412 } else { 413 phy_clear_bits_mmd(phydev, DP83822_DEVADDR, 414 MII_DP83822_RCSR, DP83822_RGMII_MODE_EN); 415 } 416 417 if (dp83822->fx_enabled) { 418 err = phy_modify(phydev, MII_DP83822_CTRL_2, 419 DP83822_FX_ENABLE, 1); 420 if (err < 0) 421 return err; 422 423 /* Only allow advertising what this PHY supports */ 424 linkmode_and(phydev->advertising, phydev->advertising, 425 phydev->supported); 426 427 linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, 428 phydev->supported); 429 linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, 430 phydev->advertising); 431 linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT, 432 phydev->supported); 433 linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT, 434 phydev->supported); 435 linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT, 436 phydev->advertising); 437 linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT, 438 phydev->advertising); 439 440 /* Auto neg is not supported in fiber mode */ 441 bmcr = phy_read(phydev, MII_BMCR); 442 if (bmcr < 0) 443 return bmcr; 444 445 if (bmcr & BMCR_ANENABLE) { 446 err = phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0); 447 if (err < 0) 448 return err; 449 } 450 phydev->autoneg = AUTONEG_DISABLE; 451 linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, 452 phydev->supported); 453 linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, 454 phydev->advertising); 455 456 /* Setup fiber advertisement */ 457 err = phy_modify_changed(phydev, MII_ADVERTISE, 458 MII_DP83822_FIBER_ADVERTISE, 459 MII_DP83822_FIBER_ADVERTISE); 460 461 if (err < 0) 462 return err; 463 464 if (dp83822->fx_signal_det_low) { 465 err = phy_set_bits_mmd(phydev, DP83822_DEVADDR, 466 MII_DP83822_GENCFG, 467 DP83822_SIG_DET_LOW); 468 if (err) 469 return err; 470 } 471 } 472 return dp8382x_disable_wol(phydev); 473 } 474 475 static int dp8382x_config_init(struct phy_device *phydev) 476 { 477 return dp8382x_disable_wol(phydev); 478 } 479 480 static int dp83822_phy_reset(struct phy_device *phydev) 481 { 482 int err; 483 484 err = phy_write(phydev, MII_DP83822_RESET_CTRL, DP83822_SW_RESET); 485 if (err < 0) 486 return err; 487 488 return phydev->drv->config_init(phydev); 489 } 490 491 #ifdef CONFIG_OF_MDIO 492 static int dp83822_of_init(struct phy_device *phydev) 493 { 494 struct dp83822_private *dp83822 = phydev->priv; 495 struct device *dev = &phydev->mdio.dev; 496 497 /* Signal detection for the PHY is only enabled if the FX_EN and the 498 * SD_EN pins are strapped. Signal detection can only enabled if FX_EN 499 * is strapped otherwise signal detection is disabled for the PHY. 500 */ 501 if (dp83822->fx_enabled && dp83822->fx_sd_enable) 502 dp83822->fx_signal_det_low = device_property_present(dev, 503 "ti,link-loss-low"); 504 if (!dp83822->fx_enabled) 505 dp83822->fx_enabled = device_property_present(dev, 506 "ti,fiber-mode"); 507 508 return 0; 509 } 510 #else 511 static int dp83822_of_init(struct phy_device *phydev) 512 { 513 return 0; 514 } 515 #endif /* CONFIG_OF_MDIO */ 516 517 static int dp83822_read_straps(struct phy_device *phydev) 518 { 519 struct dp83822_private *dp83822 = phydev->priv; 520 int fx_enabled, fx_sd_enable; 521 int val; 522 523 val = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_SOR1); 524 if (val < 0) 525 return val; 526 527 phydev_dbg(phydev, "SOR1 strap register: 0x%04x\n", val); 528 529 fx_enabled = (val & DP83822_COL_STRAP_MASK) >> DP83822_COL_SHIFT; 530 if (fx_enabled == DP83822_STRAP_MODE2 || 531 fx_enabled == DP83822_STRAP_MODE3) 532 dp83822->fx_enabled = 1; 533 534 if (dp83822->fx_enabled) { 535 fx_sd_enable = (val & DP83822_RX_ER_STR_MASK) >> DP83822_RX_ER_SHIFT; 536 if (fx_sd_enable == DP83822_STRAP_MODE3 || 537 fx_sd_enable == DP83822_STRAP_MODE4) 538 dp83822->fx_sd_enable = 1; 539 } 540 541 return 0; 542 } 543 544 static int dp83822_probe(struct phy_device *phydev) 545 { 546 struct dp83822_private *dp83822; 547 int ret; 548 549 dp83822 = devm_kzalloc(&phydev->mdio.dev, sizeof(*dp83822), 550 GFP_KERNEL); 551 if (!dp83822) 552 return -ENOMEM; 553 554 phydev->priv = dp83822; 555 556 ret = dp83822_read_straps(phydev); 557 if (ret) 558 return ret; 559 560 dp83822_of_init(phydev); 561 562 if (dp83822->fx_enabled) 563 phydev->port = PORT_FIBRE; 564 565 return 0; 566 } 567 568 static int dp83822_suspend(struct phy_device *phydev) 569 { 570 int value; 571 572 value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG); 573 574 if (!(value & DP83822_WOL_EN)) 575 genphy_suspend(phydev); 576 577 return 0; 578 } 579 580 static int dp83822_resume(struct phy_device *phydev) 581 { 582 int value; 583 584 genphy_resume(phydev); 585 586 value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG); 587 588 phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG, value | 589 DP83822_WOL_CLR_INDICATION); 590 591 return 0; 592 } 593 594 #define DP83822_PHY_DRIVER(_id, _name) \ 595 { \ 596 PHY_ID_MATCH_MODEL(_id), \ 597 .name = (_name), \ 598 /* PHY_BASIC_FEATURES */ \ 599 .probe = dp83822_probe, \ 600 .soft_reset = dp83822_phy_reset, \ 601 .config_init = dp83822_config_init, \ 602 .read_status = dp83822_read_status, \ 603 .get_wol = dp83822_get_wol, \ 604 .set_wol = dp83822_set_wol, \ 605 .config_intr = dp83822_config_intr, \ 606 .handle_interrupt = dp83822_handle_interrupt, \ 607 .suspend = dp83822_suspend, \ 608 .resume = dp83822_resume, \ 609 } 610 611 #define DP8382X_PHY_DRIVER(_id, _name) \ 612 { \ 613 PHY_ID_MATCH_MODEL(_id), \ 614 .name = (_name), \ 615 /* PHY_BASIC_FEATURES */ \ 616 .soft_reset = dp83822_phy_reset, \ 617 .config_init = dp8382x_config_init, \ 618 .get_wol = dp83822_get_wol, \ 619 .set_wol = dp83822_set_wol, \ 620 .config_intr = dp83822_config_intr, \ 621 .handle_interrupt = dp83822_handle_interrupt, \ 622 .suspend = dp83822_suspend, \ 623 .resume = dp83822_resume, \ 624 } 625 626 static struct phy_driver dp83822_driver[] = { 627 DP83822_PHY_DRIVER(DP83822_PHY_ID, "TI DP83822"), 628 DP8382X_PHY_DRIVER(DP83825I_PHY_ID, "TI DP83825I"), 629 DP8382X_PHY_DRIVER(DP83826C_PHY_ID, "TI DP83826C"), 630 DP8382X_PHY_DRIVER(DP83826NC_PHY_ID, "TI DP83826NC"), 631 DP8382X_PHY_DRIVER(DP83825S_PHY_ID, "TI DP83825S"), 632 DP8382X_PHY_DRIVER(DP83825CM_PHY_ID, "TI DP83825M"), 633 DP8382X_PHY_DRIVER(DP83825CS_PHY_ID, "TI DP83825CS"), 634 }; 635 module_phy_driver(dp83822_driver); 636 637 static struct mdio_device_id __maybe_unused dp83822_tbl[] = { 638 { DP83822_PHY_ID, 0xfffffff0 }, 639 { DP83825I_PHY_ID, 0xfffffff0 }, 640 { DP83826C_PHY_ID, 0xfffffff0 }, 641 { DP83826NC_PHY_ID, 0xfffffff0 }, 642 { DP83825S_PHY_ID, 0xfffffff0 }, 643 { DP83825CM_PHY_ID, 0xfffffff0 }, 644 { DP83825CS_PHY_ID, 0xfffffff0 }, 645 { }, 646 }; 647 MODULE_DEVICE_TABLE(mdio, dp83822_tbl); 648 649 MODULE_DESCRIPTION("Texas Instruments DP83822 PHY driver"); 650 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com"); 651 MODULE_LICENSE("GPL v2"); 652