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 50f2f1a847SMartin Blumenstingl /* The 32-pin IP101GR package can re-configure the mode of the RXER/INTR_32 pin 51f2f1a847SMartin Blumenstingl * (pin number 21). The hardware default is RXER (receive error) mode. But it 52f2f1a847SMartin Blumenstingl * can be configured to interrupt mode manually. 53f2f1a847SMartin Blumenstingl */ 54f2f1a847SMartin Blumenstingl enum ip101gr_sel_intr32 { 55f2f1a847SMartin Blumenstingl IP101GR_SEL_INTR32_KEEP, 56f2f1a847SMartin Blumenstingl IP101GR_SEL_INTR32_INTR, 57f2f1a847SMartin Blumenstingl IP101GR_SEL_INTR32_RXER, 58f2f1a847SMartin Blumenstingl }; 59f2f1a847SMartin Blumenstingl 60f2f1a847SMartin Blumenstingl struct ip101a_g_phy_priv { 61f2f1a847SMartin Blumenstingl enum ip101gr_sel_intr32 sel_intr32; 62f2f1a847SMartin Blumenstingl }; 63f2f1a847SMartin Blumenstingl 640cefeebaSMichael Barkowski static int ip175c_config_init(struct phy_device *phydev) 650cefeebaSMichael Barkowski { 660cefeebaSMichael Barkowski int err, i; 679ed66cb5SFlorian Fainelli static int full_reset_performed; 680cefeebaSMichael Barkowski 690cefeebaSMichael Barkowski if (full_reset_performed == 0) { 700cefeebaSMichael Barkowski 710cefeebaSMichael Barkowski /* master reset */ 72e5a03bfdSAndrew Lunn err = mdiobus_write(phydev->mdio.bus, 30, 0, 0x175c); 730cefeebaSMichael Barkowski if (err < 0) 740cefeebaSMichael Barkowski return err; 750cefeebaSMichael Barkowski 760cefeebaSMichael Barkowski /* ensure no bus delays overlap reset period */ 77e5a03bfdSAndrew Lunn err = mdiobus_read(phydev->mdio.bus, 30, 0); 780cefeebaSMichael Barkowski 790cefeebaSMichael Barkowski /* data sheet specifies reset period is 2 msec */ 800cefeebaSMichael Barkowski mdelay(2); 810cefeebaSMichael Barkowski 820cefeebaSMichael Barkowski /* enable IP175C mode */ 83e5a03bfdSAndrew Lunn err = mdiobus_write(phydev->mdio.bus, 29, 31, 0x175c); 840cefeebaSMichael Barkowski if (err < 0) 850cefeebaSMichael Barkowski return err; 860cefeebaSMichael Barkowski 870cefeebaSMichael Barkowski /* Set MII0 speed and duplex (in PHY mode) */ 88e5a03bfdSAndrew Lunn err = mdiobus_write(phydev->mdio.bus, 29, 22, 0x420); 890cefeebaSMichael Barkowski if (err < 0) 900cefeebaSMichael Barkowski return err; 910cefeebaSMichael Barkowski 920cefeebaSMichael Barkowski /* reset switch ports */ 930cefeebaSMichael Barkowski for (i = 0; i < 5; i++) { 94e5a03bfdSAndrew Lunn err = mdiobus_write(phydev->mdio.bus, i, 950cefeebaSMichael Barkowski MII_BMCR, BMCR_RESET); 960cefeebaSMichael Barkowski if (err < 0) 970cefeebaSMichael Barkowski return err; 980cefeebaSMichael Barkowski } 990cefeebaSMichael Barkowski 1000cefeebaSMichael Barkowski for (i = 0; i < 5; i++) 101e5a03bfdSAndrew Lunn err = mdiobus_read(phydev->mdio.bus, i, MII_BMCR); 1020cefeebaSMichael Barkowski 1030cefeebaSMichael Barkowski mdelay(2); 1040cefeebaSMichael Barkowski 1050cefeebaSMichael Barkowski full_reset_performed = 1; 1060cefeebaSMichael Barkowski } 1070cefeebaSMichael Barkowski 108e5a03bfdSAndrew Lunn if (phydev->mdio.addr != 4) { 1090cefeebaSMichael Barkowski phydev->state = PHY_RUNNING; 1100cefeebaSMichael Barkowski phydev->speed = SPEED_100; 1110cefeebaSMichael Barkowski phydev->duplex = DUPLEX_FULL; 1120cefeebaSMichael Barkowski phydev->link = 1; 1130cefeebaSMichael Barkowski netif_carrier_on(phydev->attached_dev); 1140cefeebaSMichael Barkowski } 1150cefeebaSMichael Barkowski 1160cefeebaSMichael Barkowski return 0; 1170cefeebaSMichael Barkowski } 1180cefeebaSMichael Barkowski 1199c9b1f24SGiuseppe CAVALLARO static int ip1xx_reset(struct phy_device *phydev) 120377ecca9SGiuseppe CAVALLARO { 121b8e3995aSDavid McKay int bmcr; 122377ecca9SGiuseppe CAVALLARO 123377ecca9SGiuseppe CAVALLARO /* Software Reset PHY */ 1249c9b1f24SGiuseppe CAVALLARO bmcr = phy_read(phydev, MII_BMCR); 125b8e3995aSDavid McKay if (bmcr < 0) 126b8e3995aSDavid McKay return bmcr; 1279c9b1f24SGiuseppe CAVALLARO bmcr |= BMCR_RESET; 128b8e3995aSDavid McKay bmcr = phy_write(phydev, MII_BMCR, bmcr); 129b8e3995aSDavid McKay if (bmcr < 0) 130b8e3995aSDavid McKay return bmcr; 131377ecca9SGiuseppe CAVALLARO 132377ecca9SGiuseppe CAVALLARO do { 1339c9b1f24SGiuseppe CAVALLARO bmcr = phy_read(phydev, MII_BMCR); 134b8e3995aSDavid McKay if (bmcr < 0) 135b8e3995aSDavid McKay return bmcr; 1369c9b1f24SGiuseppe CAVALLARO } while (bmcr & BMCR_RESET); 1379c9b1f24SGiuseppe CAVALLARO 138b8e3995aSDavid McKay return 0; 1399c9b1f24SGiuseppe CAVALLARO } 1409c9b1f24SGiuseppe CAVALLARO 1419c9b1f24SGiuseppe CAVALLARO static int ip1001_config_init(struct phy_device *phydev) 1429c9b1f24SGiuseppe CAVALLARO { 1439c9b1f24SGiuseppe CAVALLARO int c; 1449c9b1f24SGiuseppe CAVALLARO 1459c9b1f24SGiuseppe CAVALLARO c = ip1xx_reset(phydev); 1469c9b1f24SGiuseppe CAVALLARO if (c < 0) 1479c9b1f24SGiuseppe CAVALLARO return c; 1489c9b1f24SGiuseppe CAVALLARO 1499c9b1f24SGiuseppe CAVALLARO /* Enable Auto Power Saving mode */ 1509c9b1f24SGiuseppe CAVALLARO c = phy_read(phydev, IP1001_SPEC_CTRL_STATUS_2); 151b8e3995aSDavid McKay if (c < 0) 152b8e3995aSDavid McKay return c; 1539c9b1f24SGiuseppe CAVALLARO c |= IP1001_APS_ON; 154b8e3995aSDavid McKay c = phy_write(phydev, IP1001_SPEC_CTRL_STATUS_2, c); 1559c9b1f24SGiuseppe CAVALLARO if (c < 0) 1569c9b1f24SGiuseppe CAVALLARO return c; 157377ecca9SGiuseppe CAVALLARO 15832a64161SFlorian Fainelli if (phy_interface_is_rgmii(phydev)) { 159b4a49631SStuart Menefy 1609c9b1f24SGiuseppe CAVALLARO c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS); 161b8e3995aSDavid McKay if (c < 0) 162b8e3995aSDavid McKay return c; 163b8e3995aSDavid McKay 164b4a49631SStuart Menefy c &= ~(IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL); 165b4a49631SStuart Menefy 166b4a49631SStuart Menefy if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) 167b4a49631SStuart Menefy c |= (IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL); 168b4a49631SStuart Menefy else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) 169b4a49631SStuart Menefy c |= IP1001_RXPHASE_SEL; 170b4a49631SStuart Menefy else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) 171b4a49631SStuart Menefy c |= IP1001_TXPHASE_SEL; 172b4a49631SStuart Menefy 173a4886d52SGiuseppe CAVALLARO c = phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c); 174b8e3995aSDavid McKay if (c < 0) 175b8e3995aSDavid McKay return c; 176a4886d52SGiuseppe CAVALLARO } 177377ecca9SGiuseppe CAVALLARO 178b8e3995aSDavid McKay return 0; 1799c9b1f24SGiuseppe CAVALLARO } 1809c9b1f24SGiuseppe CAVALLARO 1810cefeebaSMichael Barkowski static int ip175c_read_status(struct phy_device *phydev) 1820cefeebaSMichael Barkowski { 183e5a03bfdSAndrew Lunn if (phydev->mdio.addr == 4) /* WAN port */ 1840cefeebaSMichael Barkowski genphy_read_status(phydev); 1850cefeebaSMichael Barkowski else 1860cefeebaSMichael Barkowski /* Don't need to read status for switch ports */ 1870cefeebaSMichael Barkowski phydev->irq = PHY_IGNORE_INTERRUPT; 1880cefeebaSMichael Barkowski 1890cefeebaSMichael Barkowski return 0; 1900cefeebaSMichael Barkowski } 1910cefeebaSMichael Barkowski 1920cefeebaSMichael Barkowski static int ip175c_config_aneg(struct phy_device *phydev) 1930cefeebaSMichael Barkowski { 194e5a03bfdSAndrew Lunn if (phydev->mdio.addr == 4) /* WAN port */ 1950cefeebaSMichael Barkowski genphy_config_aneg(phydev); 1960cefeebaSMichael Barkowski 1970cefeebaSMichael Barkowski return 0; 1980cefeebaSMichael Barkowski } 1990cefeebaSMichael Barkowski 200f2f1a847SMartin Blumenstingl static int ip101a_g_probe(struct phy_device *phydev) 201f2f1a847SMartin Blumenstingl { 202f2f1a847SMartin Blumenstingl struct device *dev = &phydev->mdio.dev; 203f2f1a847SMartin Blumenstingl struct ip101a_g_phy_priv *priv; 204f2f1a847SMartin Blumenstingl 205f2f1a847SMartin Blumenstingl priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 206f2f1a847SMartin Blumenstingl if (!priv) 207f2f1a847SMartin Blumenstingl return -ENOMEM; 208f2f1a847SMartin Blumenstingl 209f2f1a847SMartin Blumenstingl /* Both functions (RX error and interrupt status) are sharing the same 210f2f1a847SMartin Blumenstingl * pin on the 32-pin IP101GR, so this is an exclusive choice. 211f2f1a847SMartin Blumenstingl */ 212f2f1a847SMartin Blumenstingl if (device_property_read_bool(dev, "icplus,select-rx-error") && 213f2f1a847SMartin Blumenstingl device_property_read_bool(dev, "icplus,select-interrupt")) { 214f2f1a847SMartin Blumenstingl dev_err(dev, 215f2f1a847SMartin Blumenstingl "RXER and INTR mode cannot be selected together\n"); 216f2f1a847SMartin Blumenstingl return -EINVAL; 217f2f1a847SMartin Blumenstingl } 218f2f1a847SMartin Blumenstingl 219f2f1a847SMartin Blumenstingl if (device_property_read_bool(dev, "icplus,select-rx-error")) 220f2f1a847SMartin Blumenstingl priv->sel_intr32 = IP101GR_SEL_INTR32_RXER; 221f2f1a847SMartin Blumenstingl else if (device_property_read_bool(dev, "icplus,select-interrupt")) 222f2f1a847SMartin Blumenstingl priv->sel_intr32 = IP101GR_SEL_INTR32_INTR; 223f2f1a847SMartin Blumenstingl else 224f2f1a847SMartin Blumenstingl priv->sel_intr32 = IP101GR_SEL_INTR32_KEEP; 225f2f1a847SMartin Blumenstingl 226f2f1a847SMartin Blumenstingl phydev->priv = priv; 227f2f1a847SMartin Blumenstingl 228f2f1a847SMartin Blumenstingl return 0; 229f2f1a847SMartin Blumenstingl } 230f2f1a847SMartin Blumenstingl 231034289b2SMartin Blumenstingl static int ip101a_g_config_init(struct phy_device *phydev) 232034289b2SMartin Blumenstingl { 233f2f1a847SMartin Blumenstingl struct ip101a_g_phy_priv *priv = phydev->priv; 234f2f1a847SMartin Blumenstingl int err, c; 235034289b2SMartin Blumenstingl 236034289b2SMartin Blumenstingl c = ip1xx_reset(phydev); 237034289b2SMartin Blumenstingl if (c < 0) 238034289b2SMartin Blumenstingl return c; 239034289b2SMartin Blumenstingl 240f2f1a847SMartin Blumenstingl /* configure the RXER/INTR_32 pin of the 32-pin IP101GR if needed: */ 241f2f1a847SMartin Blumenstingl switch (priv->sel_intr32) { 242f2f1a847SMartin Blumenstingl case IP101GR_SEL_INTR32_RXER: 243f2f1a847SMartin Blumenstingl err = phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL, 244f2f1a847SMartin Blumenstingl IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32, 0); 245f2f1a847SMartin Blumenstingl if (err < 0) 246f2f1a847SMartin Blumenstingl return err; 247f2f1a847SMartin Blumenstingl break; 248f2f1a847SMartin Blumenstingl 249f2f1a847SMartin Blumenstingl case IP101GR_SEL_INTR32_INTR: 250f2f1a847SMartin Blumenstingl err = phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL, 251f2f1a847SMartin Blumenstingl IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32, 252f2f1a847SMartin Blumenstingl IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32); 253f2f1a847SMartin Blumenstingl if (err < 0) 254f2f1a847SMartin Blumenstingl return err; 255f2f1a847SMartin Blumenstingl break; 256f2f1a847SMartin Blumenstingl 257f2f1a847SMartin Blumenstingl default: 258f2f1a847SMartin Blumenstingl /* Don't touch IP101G_DIGITAL_IO_SPEC_CTRL because it's not 259f2f1a847SMartin Blumenstingl * documented on IP101A and it's not clear whether this would 260f2f1a847SMartin Blumenstingl * cause problems. 261f2f1a847SMartin Blumenstingl * For the 32-pin IP101GR we simply keep the SEL_INTR32 262f2f1a847SMartin Blumenstingl * configuration as set by the bootloader when not configured 263f2f1a847SMartin Blumenstingl * to one of the special functions. 264f2f1a847SMartin Blumenstingl */ 265f2f1a847SMartin Blumenstingl break; 266f2f1a847SMartin Blumenstingl } 267f2f1a847SMartin Blumenstingl 268034289b2SMartin Blumenstingl /* Enable Auto Power Saving mode */ 269034289b2SMartin Blumenstingl c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS); 270034289b2SMartin Blumenstingl c |= IP101A_G_APS_ON; 271034289b2SMartin Blumenstingl 272034289b2SMartin Blumenstingl return phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c); 273034289b2SMartin Blumenstingl } 274034289b2SMartin Blumenstingl 275ba2f55b0SHeiner Kallweit static int ip101a_g_config_intr(struct phy_device *phydev) 276ba2f55b0SHeiner Kallweit { 277ba2f55b0SHeiner Kallweit u16 val; 278ba2f55b0SHeiner Kallweit 279ba2f55b0SHeiner Kallweit if (phydev->interrupts == PHY_INTERRUPT_ENABLED) 280ba2f55b0SHeiner Kallweit /* INTR pin used: Speed/link/duplex will cause an interrupt */ 281ba2f55b0SHeiner Kallweit val = IP101A_G_IRQ_PIN_USED; 282ba2f55b0SHeiner Kallweit else 283a872c388SMartin Blumenstingl val = IP101A_G_IRQ_ALL_MASK; 284ba2f55b0SHeiner Kallweit 285ba2f55b0SHeiner Kallweit return phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, val); 286ba2f55b0SHeiner Kallweit } 287ba2f55b0SHeiner Kallweit 288f7e290fbSMartin Blumenstingl static int ip101a_g_did_interrupt(struct phy_device *phydev) 289f7e290fbSMartin Blumenstingl { 290f7e290fbSMartin Blumenstingl int val = phy_read(phydev, IP101A_G_IRQ_CONF_STATUS); 291f7e290fbSMartin Blumenstingl 292f7e290fbSMartin Blumenstingl if (val < 0) 293f7e290fbSMartin Blumenstingl return 0; 294f7e290fbSMartin Blumenstingl 295f7e290fbSMartin Blumenstingl return val & (IP101A_G_IRQ_SPEED_CHANGE | 296f7e290fbSMartin Blumenstingl IP101A_G_IRQ_DUPLEX_CHANGE | 297f7e290fbSMartin Blumenstingl IP101A_G_IRQ_LINK_CHANGE); 298f7e290fbSMartin Blumenstingl } 299f7e290fbSMartin Blumenstingl 300996f7393SGiuseppe CAVALLARO static int ip101a_g_ack_interrupt(struct phy_device *phydev) 301996f7393SGiuseppe CAVALLARO { 302996f7393SGiuseppe CAVALLARO int err = phy_read(phydev, IP101A_G_IRQ_CONF_STATUS); 303996f7393SGiuseppe CAVALLARO if (err < 0) 304996f7393SGiuseppe CAVALLARO return err; 305996f7393SGiuseppe CAVALLARO 306996f7393SGiuseppe CAVALLARO return 0; 307996f7393SGiuseppe CAVALLARO } 308996f7393SGiuseppe CAVALLARO 309d5bf9071SChristian Hohnstaedt static struct phy_driver icplus_driver[] = { 310d5bf9071SChristian Hohnstaedt { 3110cefeebaSMichael Barkowski .phy_id = 0x02430d80, 3120cefeebaSMichael Barkowski .name = "ICPlus IP175C", 3130cefeebaSMichael Barkowski .phy_id_mask = 0x0ffffff0, 314*dcdecdcfSHeiner Kallweit /* PHY_BASIC_FEATURES */ 3150cefeebaSMichael Barkowski .config_init = &ip175c_config_init, 3160cefeebaSMichael Barkowski .config_aneg = &ip175c_config_aneg, 3170cefeebaSMichael Barkowski .read_status = &ip175c_read_status, 318dab10863SGiuseppe Cavallaro .suspend = genphy_suspend, 319dab10863SGiuseppe Cavallaro .resume = genphy_resume, 320d5bf9071SChristian Hohnstaedt }, { 321377ecca9SGiuseppe CAVALLARO .phy_id = 0x02430d90, 322377ecca9SGiuseppe CAVALLARO .name = "ICPlus IP1001", 323377ecca9SGiuseppe CAVALLARO .phy_id_mask = 0x0ffffff0, 324*dcdecdcfSHeiner Kallweit /* PHY_GBIT_FEATURES */ 325377ecca9SGiuseppe CAVALLARO .config_init = &ip1001_config_init, 326377ecca9SGiuseppe CAVALLARO .suspend = genphy_suspend, 327377ecca9SGiuseppe CAVALLARO .resume = genphy_resume, 328d5bf9071SChristian Hohnstaedt }, { 3299c9b1f24SGiuseppe CAVALLARO .phy_id = 0x02430c54, 330e3e09f26SGiuseppe CAVALLARO .name = "ICPlus IP101A/G", 3319c9b1f24SGiuseppe CAVALLARO .phy_id_mask = 0x0ffffff0, 332*dcdecdcfSHeiner Kallweit /* PHY_BASIC_FEATURES */ 333f2f1a847SMartin Blumenstingl .probe = ip101a_g_probe, 334ba2f55b0SHeiner Kallweit .config_intr = ip101a_g_config_intr, 335f7e290fbSMartin Blumenstingl .did_interrupt = ip101a_g_did_interrupt, 336996f7393SGiuseppe CAVALLARO .ack_interrupt = ip101a_g_ack_interrupt, 337e3e09f26SGiuseppe CAVALLARO .config_init = &ip101a_g_config_init, 3389c9b1f24SGiuseppe CAVALLARO .suspend = genphy_suspend, 3399c9b1f24SGiuseppe CAVALLARO .resume = genphy_resume, 340d5bf9071SChristian Hohnstaedt } }; 3419c9b1f24SGiuseppe CAVALLARO 34250fd7150SJohan Hovold module_phy_driver(icplus_driver); 3434e4f10f6SDavid Woodhouse 344cf93c945SUwe Kleine-König static struct mdio_device_id __maybe_unused icplus_tbl[] = { 3454e4f10f6SDavid Woodhouse { 0x02430d80, 0x0ffffff0 }, 346377ecca9SGiuseppe CAVALLARO { 0x02430d90, 0x0ffffff0 }, 347e3e09f26SGiuseppe CAVALLARO { 0x02430c54, 0x0ffffff0 }, 3484e4f10f6SDavid Woodhouse { } 3494e4f10f6SDavid Woodhouse }; 3504e4f10f6SDavid Woodhouse 3514e4f10f6SDavid Woodhouse MODULE_DEVICE_TABLE(mdio, icplus_tbl); 352