1a2443fd1SAndrew Lunn // SPDX-License-Identifier: GPL-2.0+ 20cefeebaSMichael Barkowski /* 30cefeebaSMichael Barkowski * Driver for ICPlus PHYs 40cefeebaSMichael Barkowski * 50cefeebaSMichael Barkowski * Copyright (c) 2007 Freescale Semiconductor, Inc. 60cefeebaSMichael Barkowski */ 70cefeebaSMichael Barkowski #include <linux/kernel.h> 80cefeebaSMichael Barkowski #include <linux/string.h> 90cefeebaSMichael Barkowski #include <linux/errno.h> 100cefeebaSMichael Barkowski #include <linux/unistd.h> 110cefeebaSMichael Barkowski #include <linux/interrupt.h> 120cefeebaSMichael Barkowski #include <linux/init.h> 130cefeebaSMichael Barkowski #include <linux/delay.h> 140cefeebaSMichael Barkowski #include <linux/netdevice.h> 150cefeebaSMichael Barkowski #include <linux/etherdevice.h> 160cefeebaSMichael Barkowski #include <linux/skbuff.h> 170cefeebaSMichael Barkowski #include <linux/spinlock.h> 180cefeebaSMichael Barkowski #include <linux/mm.h> 190cefeebaSMichael Barkowski #include <linux/module.h> 200cefeebaSMichael Barkowski #include <linux/mii.h> 210cefeebaSMichael Barkowski #include <linux/ethtool.h> 220cefeebaSMichael Barkowski #include <linux/phy.h> 23f2f1a847SMartin Blumenstingl #include <linux/property.h> 240cefeebaSMichael Barkowski 250cefeebaSMichael Barkowski #include <asm/io.h> 260cefeebaSMichael Barkowski #include <asm/irq.h> 277c0f6ba6SLinus Torvalds #include <linux/uaccess.h> 280cefeebaSMichael Barkowski 29e3e09f26SGiuseppe CAVALLARO MODULE_DESCRIPTION("ICPlus IP175C/IP101A/IP101G/IC1001 PHY drivers"); 300cefeebaSMichael Barkowski MODULE_AUTHOR("Michael Barkowski"); 310cefeebaSMichael Barkowski MODULE_LICENSE("GPL"); 320cefeebaSMichael Barkowski 33e3e09f26SGiuseppe CAVALLARO /* IP101A/G - IP1001 */ 349c9b1f24SGiuseppe CAVALLARO #define IP10XX_SPEC_CTRL_STATUS 16 /* Spec. Control Register */ 35ee336140SMartin Blumenstingl #define IP1001_RXPHASE_SEL BIT(0) /* Add delay on RX_CLK */ 36ee336140SMartin Blumenstingl #define IP1001_TXPHASE_SEL BIT(1) /* Add delay on TX_CLK */ 379c9b1f24SGiuseppe CAVALLARO #define IP1001_SPEC_CTRL_STATUS_2 20 /* IP1001 Spec. Control Reg 2 */ 389c9b1f24SGiuseppe CAVALLARO #define IP1001_APS_ON 11 /* IP1001 APS Mode bit */ 39ee336140SMartin Blumenstingl #define IP101A_G_APS_ON BIT(1) /* IP101A/G APS Mode bit */ 40996f7393SGiuseppe CAVALLARO #define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */ 41ba2f55b0SHeiner Kallweit #define IP101A_G_IRQ_PIN_USED BIT(15) /* INTR pin used */ 42a872c388SMartin Blumenstingl #define IP101A_G_IRQ_ALL_MASK BIT(11) /* IRQ's inactive */ 43f7e290fbSMartin Blumenstingl #define IP101A_G_IRQ_SPEED_CHANGE BIT(2) 44f7e290fbSMartin Blumenstingl #define IP101A_G_IRQ_DUPLEX_CHANGE BIT(1) 45f7e290fbSMartin Blumenstingl #define IP101A_G_IRQ_LINK_CHANGE BIT(0) 469c9b1f24SGiuseppe CAVALLARO 47f2f1a847SMartin Blumenstingl #define IP101G_DIGITAL_IO_SPEC_CTRL 0x1d 48f2f1a847SMartin Blumenstingl #define IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32 BIT(2) 49f2f1a847SMartin Blumenstingl 502ad4758cSMichael Walle #define IP175C_PHY_ID 0x02430d80 512ad4758cSMichael Walle #define IP1001_PHY_ID 0x02430d90 522ad4758cSMichael Walle #define IP101A_PHY_ID 0x02430c54 532ad4758cSMichael Walle 54f2f1a847SMartin Blumenstingl /* The 32-pin IP101GR package can re-configure the mode of the RXER/INTR_32 pin 55f2f1a847SMartin Blumenstingl * (pin number 21). The hardware default is RXER (receive error) mode. But it 56f2f1a847SMartin Blumenstingl * can be configured to interrupt mode manually. 57f2f1a847SMartin Blumenstingl */ 58f2f1a847SMartin Blumenstingl enum ip101gr_sel_intr32 { 59f2f1a847SMartin Blumenstingl IP101GR_SEL_INTR32_KEEP, 60f2f1a847SMartin Blumenstingl IP101GR_SEL_INTR32_INTR, 61f2f1a847SMartin Blumenstingl IP101GR_SEL_INTR32_RXER, 62f2f1a847SMartin Blumenstingl }; 63f2f1a847SMartin Blumenstingl 64f2f1a847SMartin Blumenstingl struct ip101a_g_phy_priv { 65f2f1a847SMartin Blumenstingl enum ip101gr_sel_intr32 sel_intr32; 66f2f1a847SMartin Blumenstingl }; 67f2f1a847SMartin Blumenstingl 680cefeebaSMichael Barkowski static int ip175c_config_init(struct phy_device *phydev) 690cefeebaSMichael Barkowski { 700cefeebaSMichael Barkowski int err, i; 719ed66cb5SFlorian Fainelli static int full_reset_performed; 720cefeebaSMichael Barkowski 730cefeebaSMichael Barkowski if (full_reset_performed == 0) { 740cefeebaSMichael Barkowski 750cefeebaSMichael Barkowski /* master reset */ 76e5a03bfdSAndrew Lunn err = mdiobus_write(phydev->mdio.bus, 30, 0, 0x175c); 770cefeebaSMichael Barkowski if (err < 0) 780cefeebaSMichael Barkowski return err; 790cefeebaSMichael Barkowski 800cefeebaSMichael Barkowski /* ensure no bus delays overlap reset period */ 81e5a03bfdSAndrew Lunn err = mdiobus_read(phydev->mdio.bus, 30, 0); 820cefeebaSMichael Barkowski 830cefeebaSMichael Barkowski /* data sheet specifies reset period is 2 msec */ 840cefeebaSMichael Barkowski mdelay(2); 850cefeebaSMichael Barkowski 860cefeebaSMichael Barkowski /* enable IP175C mode */ 87e5a03bfdSAndrew Lunn err = mdiobus_write(phydev->mdio.bus, 29, 31, 0x175c); 880cefeebaSMichael Barkowski if (err < 0) 890cefeebaSMichael Barkowski return err; 900cefeebaSMichael Barkowski 910cefeebaSMichael Barkowski /* Set MII0 speed and duplex (in PHY mode) */ 92e5a03bfdSAndrew Lunn err = mdiobus_write(phydev->mdio.bus, 29, 22, 0x420); 930cefeebaSMichael Barkowski if (err < 0) 940cefeebaSMichael Barkowski return err; 950cefeebaSMichael Barkowski 960cefeebaSMichael Barkowski /* reset switch ports */ 970cefeebaSMichael Barkowski for (i = 0; i < 5; i++) { 98e5a03bfdSAndrew Lunn err = mdiobus_write(phydev->mdio.bus, i, 990cefeebaSMichael Barkowski MII_BMCR, BMCR_RESET); 1000cefeebaSMichael Barkowski if (err < 0) 1010cefeebaSMichael Barkowski return err; 1020cefeebaSMichael Barkowski } 1030cefeebaSMichael Barkowski 1040cefeebaSMichael Barkowski for (i = 0; i < 5; i++) 105e5a03bfdSAndrew Lunn err = mdiobus_read(phydev->mdio.bus, i, MII_BMCR); 1060cefeebaSMichael Barkowski 1070cefeebaSMichael Barkowski mdelay(2); 1080cefeebaSMichael Barkowski 1090cefeebaSMichael Barkowski full_reset_performed = 1; 1100cefeebaSMichael Barkowski } 1110cefeebaSMichael Barkowski 112e5a03bfdSAndrew Lunn if (phydev->mdio.addr != 4) { 1130cefeebaSMichael Barkowski phydev->state = PHY_RUNNING; 1140cefeebaSMichael Barkowski phydev->speed = SPEED_100; 1150cefeebaSMichael Barkowski phydev->duplex = DUPLEX_FULL; 1160cefeebaSMichael Barkowski phydev->link = 1; 1170cefeebaSMichael Barkowski netif_carrier_on(phydev->attached_dev); 1180cefeebaSMichael Barkowski } 1190cefeebaSMichael Barkowski 1200cefeebaSMichael Barkowski return 0; 1210cefeebaSMichael Barkowski } 1220cefeebaSMichael Barkowski 1239c9b1f24SGiuseppe CAVALLARO static int ip1001_config_init(struct phy_device *phydev) 1249c9b1f24SGiuseppe CAVALLARO { 1259c9b1f24SGiuseppe CAVALLARO int c; 1269c9b1f24SGiuseppe CAVALLARO 1279c9b1f24SGiuseppe CAVALLARO /* Enable Auto Power Saving mode */ 1289c9b1f24SGiuseppe CAVALLARO c = phy_read(phydev, IP1001_SPEC_CTRL_STATUS_2); 129b8e3995aSDavid McKay if (c < 0) 130b8e3995aSDavid McKay return c; 1319c9b1f24SGiuseppe CAVALLARO c |= IP1001_APS_ON; 132b8e3995aSDavid McKay c = phy_write(phydev, IP1001_SPEC_CTRL_STATUS_2, c); 1339c9b1f24SGiuseppe CAVALLARO if (c < 0) 1349c9b1f24SGiuseppe CAVALLARO return c; 135377ecca9SGiuseppe CAVALLARO 13632a64161SFlorian Fainelli if (phy_interface_is_rgmii(phydev)) { 137b4a49631SStuart Menefy 1389c9b1f24SGiuseppe CAVALLARO c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS); 139b8e3995aSDavid McKay if (c < 0) 140b8e3995aSDavid McKay return c; 141b8e3995aSDavid McKay 142b4a49631SStuart Menefy c &= ~(IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL); 143b4a49631SStuart Menefy 144b4a49631SStuart Menefy if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) 145b4a49631SStuart Menefy c |= (IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL); 146b4a49631SStuart Menefy else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) 147b4a49631SStuart Menefy c |= IP1001_RXPHASE_SEL; 148b4a49631SStuart Menefy else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) 149b4a49631SStuart Menefy c |= IP1001_TXPHASE_SEL; 150b4a49631SStuart Menefy 151a4886d52SGiuseppe CAVALLARO c = phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c); 152b8e3995aSDavid McKay if (c < 0) 153b8e3995aSDavid McKay return c; 154a4886d52SGiuseppe CAVALLARO } 155377ecca9SGiuseppe CAVALLARO 156b8e3995aSDavid McKay return 0; 1579c9b1f24SGiuseppe CAVALLARO } 1589c9b1f24SGiuseppe CAVALLARO 1590cefeebaSMichael Barkowski static int ip175c_read_status(struct phy_device *phydev) 1600cefeebaSMichael Barkowski { 161e5a03bfdSAndrew Lunn if (phydev->mdio.addr == 4) /* WAN port */ 1620cefeebaSMichael Barkowski genphy_read_status(phydev); 1630cefeebaSMichael Barkowski else 1640cefeebaSMichael Barkowski /* Don't need to read status for switch ports */ 1650cefeebaSMichael Barkowski phydev->irq = PHY_IGNORE_INTERRUPT; 1660cefeebaSMichael Barkowski 1670cefeebaSMichael Barkowski return 0; 1680cefeebaSMichael Barkowski } 1690cefeebaSMichael Barkowski 1700cefeebaSMichael Barkowski static int ip175c_config_aneg(struct phy_device *phydev) 1710cefeebaSMichael Barkowski { 172e5a03bfdSAndrew Lunn if (phydev->mdio.addr == 4) /* WAN port */ 1730cefeebaSMichael Barkowski genphy_config_aneg(phydev); 1740cefeebaSMichael Barkowski 1750cefeebaSMichael Barkowski return 0; 1760cefeebaSMichael Barkowski } 1770cefeebaSMichael Barkowski 178f2f1a847SMartin Blumenstingl static int ip101a_g_probe(struct phy_device *phydev) 179f2f1a847SMartin Blumenstingl { 180f2f1a847SMartin Blumenstingl struct device *dev = &phydev->mdio.dev; 181f2f1a847SMartin Blumenstingl struct ip101a_g_phy_priv *priv; 182f2f1a847SMartin Blumenstingl 183f2f1a847SMartin Blumenstingl priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 184f2f1a847SMartin Blumenstingl if (!priv) 185f2f1a847SMartin Blumenstingl return -ENOMEM; 186f2f1a847SMartin Blumenstingl 187f2f1a847SMartin Blumenstingl /* Both functions (RX error and interrupt status) are sharing the same 188f2f1a847SMartin Blumenstingl * pin on the 32-pin IP101GR, so this is an exclusive choice. 189f2f1a847SMartin Blumenstingl */ 190f2f1a847SMartin Blumenstingl if (device_property_read_bool(dev, "icplus,select-rx-error") && 191f2f1a847SMartin Blumenstingl device_property_read_bool(dev, "icplus,select-interrupt")) { 192f2f1a847SMartin Blumenstingl dev_err(dev, 193f2f1a847SMartin Blumenstingl "RXER and INTR mode cannot be selected together\n"); 194f2f1a847SMartin Blumenstingl return -EINVAL; 195f2f1a847SMartin Blumenstingl } 196f2f1a847SMartin Blumenstingl 197f2f1a847SMartin Blumenstingl if (device_property_read_bool(dev, "icplus,select-rx-error")) 198f2f1a847SMartin Blumenstingl priv->sel_intr32 = IP101GR_SEL_INTR32_RXER; 199f2f1a847SMartin Blumenstingl else if (device_property_read_bool(dev, "icplus,select-interrupt")) 200f2f1a847SMartin Blumenstingl priv->sel_intr32 = IP101GR_SEL_INTR32_INTR; 201f2f1a847SMartin Blumenstingl else 202f2f1a847SMartin Blumenstingl priv->sel_intr32 = IP101GR_SEL_INTR32_KEEP; 203f2f1a847SMartin Blumenstingl 204f2f1a847SMartin Blumenstingl phydev->priv = priv; 205f2f1a847SMartin Blumenstingl 206f2f1a847SMartin Blumenstingl return 0; 207f2f1a847SMartin Blumenstingl } 208f2f1a847SMartin Blumenstingl 209034289b2SMartin Blumenstingl static int ip101a_g_config_init(struct phy_device *phydev) 210034289b2SMartin Blumenstingl { 211f2f1a847SMartin Blumenstingl struct ip101a_g_phy_priv *priv = phydev->priv; 212f2f1a847SMartin Blumenstingl int err, c; 213034289b2SMartin Blumenstingl 214f2f1a847SMartin Blumenstingl /* configure the RXER/INTR_32 pin of the 32-pin IP101GR if needed: */ 215f2f1a847SMartin Blumenstingl switch (priv->sel_intr32) { 216f2f1a847SMartin Blumenstingl case IP101GR_SEL_INTR32_RXER: 217f2f1a847SMartin Blumenstingl err = phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL, 218f2f1a847SMartin Blumenstingl IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32, 0); 219f2f1a847SMartin Blumenstingl if (err < 0) 220f2f1a847SMartin Blumenstingl return err; 221f2f1a847SMartin Blumenstingl break; 222f2f1a847SMartin Blumenstingl 223f2f1a847SMartin Blumenstingl case IP101GR_SEL_INTR32_INTR: 224f2f1a847SMartin Blumenstingl err = phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL, 225f2f1a847SMartin Blumenstingl IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32, 226f2f1a847SMartin Blumenstingl IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32); 227f2f1a847SMartin Blumenstingl if (err < 0) 228f2f1a847SMartin Blumenstingl return err; 229f2f1a847SMartin Blumenstingl break; 230f2f1a847SMartin Blumenstingl 231f2f1a847SMartin Blumenstingl default: 232f2f1a847SMartin Blumenstingl /* Don't touch IP101G_DIGITAL_IO_SPEC_CTRL because it's not 233f2f1a847SMartin Blumenstingl * documented on IP101A and it's not clear whether this would 234f2f1a847SMartin Blumenstingl * cause problems. 235f2f1a847SMartin Blumenstingl * For the 32-pin IP101GR we simply keep the SEL_INTR32 236f2f1a847SMartin Blumenstingl * configuration as set by the bootloader when not configured 237f2f1a847SMartin Blumenstingl * to one of the special functions. 238f2f1a847SMartin Blumenstingl */ 239f2f1a847SMartin Blumenstingl break; 240f2f1a847SMartin Blumenstingl } 241f2f1a847SMartin Blumenstingl 242034289b2SMartin Blumenstingl /* Enable Auto Power Saving mode */ 243034289b2SMartin Blumenstingl c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS); 244034289b2SMartin Blumenstingl c |= IP101A_G_APS_ON; 245034289b2SMartin Blumenstingl 246034289b2SMartin Blumenstingl return phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c); 247034289b2SMartin Blumenstingl } 248034289b2SMartin Blumenstingl 24912ae7ba3SIoana Ciornei static int ip101a_g_ack_interrupt(struct phy_device *phydev) 25012ae7ba3SIoana Ciornei { 25112ae7ba3SIoana Ciornei int err = phy_read(phydev, IP101A_G_IRQ_CONF_STATUS); 25212ae7ba3SIoana Ciornei 25312ae7ba3SIoana Ciornei if (err < 0) 25412ae7ba3SIoana Ciornei return err; 25512ae7ba3SIoana Ciornei 25612ae7ba3SIoana Ciornei return 0; 25712ae7ba3SIoana Ciornei } 25812ae7ba3SIoana Ciornei 259ba2f55b0SHeiner Kallweit static int ip101a_g_config_intr(struct phy_device *phydev) 260ba2f55b0SHeiner Kallweit { 261ba2f55b0SHeiner Kallweit u16 val; 26212ae7ba3SIoana Ciornei int err; 263ba2f55b0SHeiner Kallweit 26412ae7ba3SIoana Ciornei if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 26512ae7ba3SIoana Ciornei err = ip101a_g_ack_interrupt(phydev); 26612ae7ba3SIoana Ciornei if (err) 26712ae7ba3SIoana Ciornei return err; 26812ae7ba3SIoana Ciornei 269ba2f55b0SHeiner Kallweit /* INTR pin used: Speed/link/duplex will cause an interrupt */ 270ba2f55b0SHeiner Kallweit val = IP101A_G_IRQ_PIN_USED; 27112ae7ba3SIoana Ciornei err = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, val); 27212ae7ba3SIoana Ciornei } else { 273a872c388SMartin Blumenstingl val = IP101A_G_IRQ_ALL_MASK; 27412ae7ba3SIoana Ciornei err = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, val); 27512ae7ba3SIoana Ciornei if (err) 27612ae7ba3SIoana Ciornei return err; 277ba2f55b0SHeiner Kallweit 27812ae7ba3SIoana Ciornei err = ip101a_g_ack_interrupt(phydev); 27912ae7ba3SIoana Ciornei } 28012ae7ba3SIoana Ciornei 28112ae7ba3SIoana Ciornei return err; 282ba2f55b0SHeiner Kallweit } 283ba2f55b0SHeiner Kallweit 28425497b7fSIoana Ciornei static irqreturn_t ip101a_g_handle_interrupt(struct phy_device *phydev) 285f7e290fbSMartin Blumenstingl { 28625497b7fSIoana Ciornei int irq_status; 287f7e290fbSMartin Blumenstingl 28825497b7fSIoana Ciornei irq_status = phy_read(phydev, IP101A_G_IRQ_CONF_STATUS); 28925497b7fSIoana Ciornei if (irq_status < 0) { 29025497b7fSIoana Ciornei phy_error(phydev); 29125497b7fSIoana Ciornei return IRQ_NONE; 29225497b7fSIoana Ciornei } 293f7e290fbSMartin Blumenstingl 29425497b7fSIoana Ciornei if (!(irq_status & (IP101A_G_IRQ_SPEED_CHANGE | 295f7e290fbSMartin Blumenstingl IP101A_G_IRQ_DUPLEX_CHANGE | 29625497b7fSIoana Ciornei IP101A_G_IRQ_LINK_CHANGE))) 29725497b7fSIoana Ciornei return IRQ_NONE; 29825497b7fSIoana Ciornei 29925497b7fSIoana Ciornei phy_trigger_machine(phydev); 30025497b7fSIoana Ciornei 30125497b7fSIoana Ciornei return IRQ_HANDLED; 302f7e290fbSMartin Blumenstingl } 303f7e290fbSMartin Blumenstingl 304d5bf9071SChristian Hohnstaedt static struct phy_driver icplus_driver[] = { 305d5bf9071SChristian Hohnstaedt { 3062ad4758cSMichael Walle PHY_ID_MATCH_MODEL(IP175C_PHY_ID), 3070cefeebaSMichael Barkowski .name = "ICPlus IP175C", 308dcdecdcfSHeiner Kallweit /* PHY_BASIC_FEATURES */ 3098edf206cSMichael Walle .config_init = ip175c_config_init, 3108edf206cSMichael Walle .config_aneg = ip175c_config_aneg, 3118edf206cSMichael Walle .read_status = ip175c_read_status, 312dab10863SGiuseppe Cavallaro .suspend = genphy_suspend, 313dab10863SGiuseppe Cavallaro .resume = genphy_resume, 314d5bf9071SChristian Hohnstaedt }, { 3152ad4758cSMichael Walle PHY_ID_MATCH_MODEL(IP1001_PHY_ID), 316377ecca9SGiuseppe CAVALLARO .name = "ICPlus IP1001", 317dcdecdcfSHeiner Kallweit /* PHY_GBIT_FEATURES */ 3188edf206cSMichael Walle .config_init = ip1001_config_init, 319*df22de9aSMichael Walle .soft_reset = genphy_soft_reset, 320377ecca9SGiuseppe CAVALLARO .suspend = genphy_suspend, 321377ecca9SGiuseppe CAVALLARO .resume = genphy_resume, 322d5bf9071SChristian Hohnstaedt }, { 3237360a4deSMichael Walle PHY_ID_MATCH_EXACT(IP101A_PHY_ID), 324e3e09f26SGiuseppe CAVALLARO .name = "ICPlus IP101A/G", 325dcdecdcfSHeiner Kallweit /* PHY_BASIC_FEATURES */ 326f2f1a847SMartin Blumenstingl .probe = ip101a_g_probe, 327ba2f55b0SHeiner Kallweit .config_intr = ip101a_g_config_intr, 32825497b7fSIoana Ciornei .handle_interrupt = ip101a_g_handle_interrupt, 3298edf206cSMichael Walle .config_init = ip101a_g_config_init, 330*df22de9aSMichael Walle .soft_reset = genphy_soft_reset, 3319c9b1f24SGiuseppe CAVALLARO .suspend = genphy_suspend, 3329c9b1f24SGiuseppe CAVALLARO .resume = genphy_resume, 333d5bf9071SChristian Hohnstaedt } }; 3349c9b1f24SGiuseppe CAVALLARO 33550fd7150SJohan Hovold module_phy_driver(icplus_driver); 3364e4f10f6SDavid Woodhouse 337cf93c945SUwe Kleine-König static struct mdio_device_id __maybe_unused icplus_tbl[] = { 3382ad4758cSMichael Walle { PHY_ID_MATCH_MODEL(IP175C_PHY_ID) }, 3392ad4758cSMichael Walle { PHY_ID_MATCH_MODEL(IP1001_PHY_ID) }, 3407360a4deSMichael Walle { PHY_ID_MATCH_EXACT(IP101A_PHY_ID) }, 3414e4f10f6SDavid Woodhouse { } 3424e4f10f6SDavid Woodhouse }; 3434e4f10f6SDavid Woodhouse 3444e4f10f6SDavid Woodhouse MODULE_DEVICE_TABLE(mdio, icplus_tbl); 345