Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Driver for ICPlus PHYs
0004  *
0005  * Copyright (c) 2007 Freescale Semiconductor, Inc.
0006  */
0007 #include <linux/kernel.h>
0008 #include <linux/string.h>
0009 #include <linux/errno.h>
0010 #include <linux/unistd.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/init.h>
0013 #include <linux/delay.h>
0014 #include <linux/netdevice.h>
0015 #include <linux/etherdevice.h>
0016 #include <linux/skbuff.h>
0017 #include <linux/spinlock.h>
0018 #include <linux/mm.h>
0019 #include <linux/module.h>
0020 #include <linux/mii.h>
0021 #include <linux/ethtool.h>
0022 #include <linux/phy.h>
0023 #include <linux/property.h>
0024 
0025 #include <asm/io.h>
0026 #include <asm/irq.h>
0027 #include <linux/uaccess.h>
0028 
0029 MODULE_DESCRIPTION("ICPlus IP175C/IP101A/IP101G/IC1001 PHY drivers");
0030 MODULE_AUTHOR("Michael Barkowski");
0031 MODULE_LICENSE("GPL");
0032 
0033 /* IP101A/G - IP1001 */
0034 #define IP10XX_SPEC_CTRL_STATUS     16  /* Spec. Control Register */
0035 #define IP1001_RXPHASE_SEL      BIT(0)  /* Add delay on RX_CLK */
0036 #define IP1001_TXPHASE_SEL      BIT(1)  /* Add delay on TX_CLK */
0037 #define IP1001_SPEC_CTRL_STATUS_2   20  /* IP1001 Spec. Control Reg 2 */
0038 #define IP1001_APS_ON           11  /* IP1001 APS Mode  bit */
0039 #define IP101A_G_APS_ON         BIT(1)  /* IP101A/G APS Mode bit */
0040 #define IP101A_G_AUTO_MDIX_DIS      BIT(11)
0041 #define IP101A_G_IRQ_CONF_STATUS    0x11    /* Conf Info IRQ & Status Reg */
0042 #define IP101A_G_IRQ_PIN_USED       BIT(15) /* INTR pin used */
0043 #define IP101A_G_IRQ_ALL_MASK       BIT(11) /* IRQ's inactive */
0044 #define IP101A_G_IRQ_SPEED_CHANGE   BIT(2)
0045 #define IP101A_G_IRQ_DUPLEX_CHANGE  BIT(1)
0046 #define IP101A_G_IRQ_LINK_CHANGE    BIT(0)
0047 #define IP101A_G_PHY_STATUS     18
0048 #define IP101A_G_MDIX           BIT(9)
0049 #define IP101A_G_PHY_SPEC_CTRL      30
0050 #define IP101A_G_FORCE_MDIX     BIT(3)
0051 
0052 #define IP101G_PAGE_CONTROL             0x14
0053 #define IP101G_PAGE_CONTROL_MASK            GENMASK(4, 0)
0054 #define IP101G_DIGITAL_IO_SPEC_CTRL         0x1d
0055 #define IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32      BIT(2)
0056 
0057 #define IP101G_DEFAULT_PAGE         16
0058 
0059 #define IP101G_P1_CNT_CTRL      17
0060 #define CNT_CTRL_RX_EN          BIT(13)
0061 #define IP101G_P8_CNT_CTRL      17
0062 #define CNT_CTRL_RDCLR_EN       BIT(15)
0063 #define IP101G_CNT_REG          18
0064 
0065 #define IP175C_PHY_ID 0x02430d80
0066 #define IP1001_PHY_ID 0x02430d90
0067 #define IP101A_PHY_ID 0x02430c54
0068 
0069 /* The 32-pin IP101GR package can re-configure the mode of the RXER/INTR_32 pin
0070  * (pin number 21). The hardware default is RXER (receive error) mode. But it
0071  * can be configured to interrupt mode manually.
0072  */
0073 enum ip101gr_sel_intr32 {
0074     IP101GR_SEL_INTR32_KEEP,
0075     IP101GR_SEL_INTR32_INTR,
0076     IP101GR_SEL_INTR32_RXER,
0077 };
0078 
0079 struct ip101g_hw_stat {
0080     const char *name;
0081     int page;
0082 };
0083 
0084 static struct ip101g_hw_stat ip101g_hw_stats[] = {
0085     { "phy_crc_errors", 1 },
0086     { "phy_symbol_errors", 11, },
0087 };
0088 
0089 struct ip101a_g_phy_priv {
0090     enum ip101gr_sel_intr32 sel_intr32;
0091     u64 stats[ARRAY_SIZE(ip101g_hw_stats)];
0092 };
0093 
0094 static int ip175c_config_init(struct phy_device *phydev)
0095 {
0096     int err, i;
0097     static int full_reset_performed;
0098 
0099     if (full_reset_performed == 0) {
0100 
0101         /* master reset */
0102         err = mdiobus_write(phydev->mdio.bus, 30, 0, 0x175c);
0103         if (err < 0)
0104             return err;
0105 
0106         /* ensure no bus delays overlap reset period */
0107         err = mdiobus_read(phydev->mdio.bus, 30, 0);
0108 
0109         /* data sheet specifies reset period is 2 msec */
0110         mdelay(2);
0111 
0112         /* enable IP175C mode */
0113         err = mdiobus_write(phydev->mdio.bus, 29, 31, 0x175c);
0114         if (err < 0)
0115             return err;
0116 
0117         /* Set MII0 speed and duplex (in PHY mode) */
0118         err = mdiobus_write(phydev->mdio.bus, 29, 22, 0x420);
0119         if (err < 0)
0120             return err;
0121 
0122         /* reset switch ports */
0123         for (i = 0; i < 5; i++) {
0124             err = mdiobus_write(phydev->mdio.bus, i,
0125                         MII_BMCR, BMCR_RESET);
0126             if (err < 0)
0127                 return err;
0128         }
0129 
0130         for (i = 0; i < 5; i++)
0131             err = mdiobus_read(phydev->mdio.bus, i, MII_BMCR);
0132 
0133         mdelay(2);
0134 
0135         full_reset_performed = 1;
0136     }
0137 
0138     if (phydev->mdio.addr != 4) {
0139         phydev->state = PHY_RUNNING;
0140         phydev->speed = SPEED_100;
0141         phydev->duplex = DUPLEX_FULL;
0142         phydev->link = 1;
0143         netif_carrier_on(phydev->attached_dev);
0144     }
0145 
0146     return 0;
0147 }
0148 
0149 static int ip1001_config_init(struct phy_device *phydev)
0150 {
0151     int c;
0152 
0153     /* Enable Auto Power Saving mode */
0154     c = phy_read(phydev, IP1001_SPEC_CTRL_STATUS_2);
0155     if (c < 0)
0156         return c;
0157     c |= IP1001_APS_ON;
0158     c = phy_write(phydev, IP1001_SPEC_CTRL_STATUS_2, c);
0159     if (c < 0)
0160         return c;
0161 
0162     if (phy_interface_is_rgmii(phydev)) {
0163 
0164         c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
0165         if (c < 0)
0166             return c;
0167 
0168         c &= ~(IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL);
0169 
0170         if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
0171             c |= (IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL);
0172         else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
0173             c |= IP1001_RXPHASE_SEL;
0174         else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
0175             c |= IP1001_TXPHASE_SEL;
0176 
0177         c = phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c);
0178         if (c < 0)
0179             return c;
0180     }
0181 
0182     return 0;
0183 }
0184 
0185 static int ip175c_read_status(struct phy_device *phydev)
0186 {
0187     if (phydev->mdio.addr == 4) /* WAN port */
0188         genphy_read_status(phydev);
0189     else
0190         /* Don't need to read status for switch ports */
0191         phydev->irq = PHY_MAC_INTERRUPT;
0192 
0193     return 0;
0194 }
0195 
0196 static int ip175c_config_aneg(struct phy_device *phydev)
0197 {
0198     if (phydev->mdio.addr == 4) /* WAN port */
0199         genphy_config_aneg(phydev);
0200 
0201     return 0;
0202 }
0203 
0204 static int ip101a_g_probe(struct phy_device *phydev)
0205 {
0206     struct device *dev = &phydev->mdio.dev;
0207     struct ip101a_g_phy_priv *priv;
0208 
0209     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0210     if (!priv)
0211         return -ENOMEM;
0212 
0213     /* Both functions (RX error and interrupt status) are sharing the same
0214      * pin on the 32-pin IP101GR, so this is an exclusive choice.
0215      */
0216     if (device_property_read_bool(dev, "icplus,select-rx-error") &&
0217         device_property_read_bool(dev, "icplus,select-interrupt")) {
0218         dev_err(dev,
0219             "RXER and INTR mode cannot be selected together\n");
0220         return -EINVAL;
0221     }
0222 
0223     if (device_property_read_bool(dev, "icplus,select-rx-error"))
0224         priv->sel_intr32 = IP101GR_SEL_INTR32_RXER;
0225     else if (device_property_read_bool(dev, "icplus,select-interrupt"))
0226         priv->sel_intr32 = IP101GR_SEL_INTR32_INTR;
0227     else
0228         priv->sel_intr32 = IP101GR_SEL_INTR32_KEEP;
0229 
0230     phydev->priv = priv;
0231 
0232     return 0;
0233 }
0234 
0235 static int ip101a_g_config_intr_pin(struct phy_device *phydev)
0236 {
0237     struct ip101a_g_phy_priv *priv = phydev->priv;
0238     int oldpage, err = 0;
0239 
0240     oldpage = phy_select_page(phydev, IP101G_DEFAULT_PAGE);
0241     if (oldpage < 0)
0242         goto out;
0243 
0244     /* configure the RXER/INTR_32 pin of the 32-pin IP101GR if needed: */
0245     switch (priv->sel_intr32) {
0246     case IP101GR_SEL_INTR32_RXER:
0247         err = __phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL,
0248                    IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32, 0);
0249         if (err < 0)
0250             goto out;
0251         break;
0252 
0253     case IP101GR_SEL_INTR32_INTR:
0254         err = __phy_modify(phydev, IP101G_DIGITAL_IO_SPEC_CTRL,
0255                    IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32,
0256                    IP101G_DIGITAL_IO_SPEC_CTRL_SEL_INTR32);
0257         if (err < 0)
0258             goto out;
0259         break;
0260 
0261     default:
0262         /* Don't touch IP101G_DIGITAL_IO_SPEC_CTRL because it's not
0263          * documented on IP101A and it's not clear whether this would
0264          * cause problems.
0265          * For the 32-pin IP101GR we simply keep the SEL_INTR32
0266          * configuration as set by the bootloader when not configured
0267          * to one of the special functions.
0268          */
0269         break;
0270     }
0271 
0272 out:
0273     return phy_restore_page(phydev, oldpage, err);
0274 }
0275 
0276 static int ip101a_config_init(struct phy_device *phydev)
0277 {
0278     int ret;
0279 
0280     /* Enable Auto Power Saving mode */
0281     ret = phy_set_bits(phydev, IP10XX_SPEC_CTRL_STATUS, IP101A_G_APS_ON);
0282     if (ret)
0283         return ret;
0284 
0285     return ip101a_g_config_intr_pin(phydev);
0286 }
0287 
0288 static int ip101g_config_init(struct phy_device *phydev)
0289 {
0290     int ret;
0291 
0292     /* Enable the PHY counters */
0293     ret = phy_modify_paged(phydev, 1, IP101G_P1_CNT_CTRL,
0294                    CNT_CTRL_RX_EN, CNT_CTRL_RX_EN);
0295     if (ret)
0296         return ret;
0297 
0298     /* Clear error counters on read */
0299     ret = phy_modify_paged(phydev, 8, IP101G_P8_CNT_CTRL,
0300                    CNT_CTRL_RDCLR_EN, CNT_CTRL_RDCLR_EN);
0301     if (ret)
0302         return ret;
0303 
0304     return ip101a_g_config_intr_pin(phydev);
0305 }
0306 
0307 static int ip101a_g_read_status(struct phy_device *phydev)
0308 {
0309     int oldpage, ret, stat1, stat2;
0310 
0311     ret = genphy_read_status(phydev);
0312     if (ret)
0313         return ret;
0314 
0315     oldpage = phy_select_page(phydev, IP101G_DEFAULT_PAGE);
0316     if (oldpage < 0)
0317         goto out;
0318 
0319     ret = __phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
0320     if (ret < 0)
0321         goto out;
0322     stat1 = ret;
0323 
0324     ret = __phy_read(phydev, IP101A_G_PHY_SPEC_CTRL);
0325     if (ret < 0)
0326         goto out;
0327     stat2 = ret;
0328 
0329     if (stat1 & IP101A_G_AUTO_MDIX_DIS) {
0330         if (stat2 & IP101A_G_FORCE_MDIX)
0331             phydev->mdix_ctrl = ETH_TP_MDI_X;
0332         else
0333             phydev->mdix_ctrl = ETH_TP_MDI;
0334     } else {
0335         phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
0336     }
0337 
0338     if (stat2 & IP101A_G_MDIX)
0339         phydev->mdix = ETH_TP_MDI_X;
0340     else
0341         phydev->mdix = ETH_TP_MDI;
0342 
0343     ret = 0;
0344 
0345 out:
0346     return phy_restore_page(phydev, oldpage, ret);
0347 }
0348 
0349 static int ip101a_g_config_mdix(struct phy_device *phydev)
0350 {
0351     u16 ctrl = 0, ctrl2 = 0;
0352     int oldpage;
0353     int ret = 0;
0354 
0355     switch (phydev->mdix_ctrl) {
0356     case ETH_TP_MDI:
0357         ctrl = IP101A_G_AUTO_MDIX_DIS;
0358         break;
0359     case ETH_TP_MDI_X:
0360         ctrl = IP101A_G_AUTO_MDIX_DIS;
0361         ctrl2 = IP101A_G_FORCE_MDIX;
0362         break;
0363     case ETH_TP_MDI_AUTO:
0364         break;
0365     default:
0366         return 0;
0367     }
0368 
0369     oldpage = phy_select_page(phydev, IP101G_DEFAULT_PAGE);
0370     if (oldpage < 0)
0371         goto out;
0372 
0373     ret = __phy_modify(phydev, IP10XX_SPEC_CTRL_STATUS,
0374                IP101A_G_AUTO_MDIX_DIS, ctrl);
0375     if (ret)
0376         goto out;
0377 
0378     ret = __phy_modify(phydev, IP101A_G_PHY_SPEC_CTRL,
0379                IP101A_G_FORCE_MDIX, ctrl2);
0380 
0381 out:
0382     return phy_restore_page(phydev, oldpage, ret);
0383 }
0384 
0385 static int ip101a_g_config_aneg(struct phy_device *phydev)
0386 {
0387     int ret;
0388 
0389     ret = ip101a_g_config_mdix(phydev);
0390     if (ret)
0391         return ret;
0392 
0393     return genphy_config_aneg(phydev);
0394 }
0395 
0396 static int ip101a_g_ack_interrupt(struct phy_device *phydev)
0397 {
0398     int err;
0399 
0400     err = phy_read_paged(phydev, IP101G_DEFAULT_PAGE,
0401                  IP101A_G_IRQ_CONF_STATUS);
0402     if (err < 0)
0403         return err;
0404 
0405     return 0;
0406 }
0407 
0408 static int ip101a_g_config_intr(struct phy_device *phydev)
0409 {
0410     u16 val;
0411     int err;
0412 
0413     if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
0414         err = ip101a_g_ack_interrupt(phydev);
0415         if (err)
0416             return err;
0417 
0418         /* INTR pin used: Speed/link/duplex will cause an interrupt */
0419         val = IP101A_G_IRQ_PIN_USED;
0420         err = phy_write_paged(phydev, IP101G_DEFAULT_PAGE,
0421                       IP101A_G_IRQ_CONF_STATUS, val);
0422     } else {
0423         val = IP101A_G_IRQ_ALL_MASK;
0424         err = phy_write_paged(phydev, IP101G_DEFAULT_PAGE,
0425                       IP101A_G_IRQ_CONF_STATUS, val);
0426         if (err)
0427             return err;
0428 
0429         err = ip101a_g_ack_interrupt(phydev);
0430     }
0431 
0432     return err;
0433 }
0434 
0435 static irqreturn_t ip101a_g_handle_interrupt(struct phy_device *phydev)
0436 {
0437     int irq_status;
0438 
0439     irq_status = phy_read_paged(phydev, IP101G_DEFAULT_PAGE,
0440                     IP101A_G_IRQ_CONF_STATUS);
0441     if (irq_status < 0) {
0442         phy_error(phydev);
0443         return IRQ_NONE;
0444     }
0445 
0446     if (!(irq_status & (IP101A_G_IRQ_SPEED_CHANGE |
0447                 IP101A_G_IRQ_DUPLEX_CHANGE |
0448                 IP101A_G_IRQ_LINK_CHANGE)))
0449         return IRQ_NONE;
0450 
0451     phy_trigger_machine(phydev);
0452 
0453     return IRQ_HANDLED;
0454 }
0455 
0456 /* The IP101A doesn't really have a page register. We just pretend to have one
0457  * so we can use the paged versions of the callbacks of the IP101G.
0458  */
0459 static int ip101a_read_page(struct phy_device *phydev)
0460 {
0461     return IP101G_DEFAULT_PAGE;
0462 }
0463 
0464 static int ip101a_write_page(struct phy_device *phydev, int page)
0465 {
0466     WARN_ONCE(page != IP101G_DEFAULT_PAGE, "wrong page selected\n");
0467 
0468     return 0;
0469 }
0470 
0471 static int ip101g_read_page(struct phy_device *phydev)
0472 {
0473     return __phy_read(phydev, IP101G_PAGE_CONTROL);
0474 }
0475 
0476 static int ip101g_write_page(struct phy_device *phydev, int page)
0477 {
0478     return __phy_write(phydev, IP101G_PAGE_CONTROL, page);
0479 }
0480 
0481 static int ip101a_g_has_page_register(struct phy_device *phydev)
0482 {
0483     int oldval, val, ret;
0484 
0485     oldval = phy_read(phydev, IP101G_PAGE_CONTROL);
0486     if (oldval < 0)
0487         return oldval;
0488 
0489     ret = phy_write(phydev, IP101G_PAGE_CONTROL, 0xffff);
0490     if (ret)
0491         return ret;
0492 
0493     val = phy_read(phydev, IP101G_PAGE_CONTROL);
0494     if (val < 0)
0495         return val;
0496 
0497     ret = phy_write(phydev, IP101G_PAGE_CONTROL, oldval);
0498     if (ret)
0499         return ret;
0500 
0501     return val == IP101G_PAGE_CONTROL_MASK;
0502 }
0503 
0504 static int ip101a_g_match_phy_device(struct phy_device *phydev, bool ip101a)
0505 {
0506     int ret;
0507 
0508     if (phydev->phy_id != IP101A_PHY_ID)
0509         return 0;
0510 
0511     /* The IP101A and the IP101G share the same PHY identifier.The IP101G
0512      * seems to be a successor of the IP101A and implements more functions.
0513      * Amongst other things there is a page select register, which is not
0514      * available on the IP101A. Use this to distinguish these two.
0515      */
0516     ret = ip101a_g_has_page_register(phydev);
0517     if (ret < 0)
0518         return ret;
0519 
0520     return ip101a == !ret;
0521 }
0522 
0523 static int ip101a_match_phy_device(struct phy_device *phydev)
0524 {
0525     return ip101a_g_match_phy_device(phydev, true);
0526 }
0527 
0528 static int ip101g_match_phy_device(struct phy_device *phydev)
0529 {
0530     return ip101a_g_match_phy_device(phydev, false);
0531 }
0532 
0533 static int ip101g_get_sset_count(struct phy_device *phydev)
0534 {
0535     return ARRAY_SIZE(ip101g_hw_stats);
0536 }
0537 
0538 static void ip101g_get_strings(struct phy_device *phydev, u8 *data)
0539 {
0540     int i;
0541 
0542     for (i = 0; i < ARRAY_SIZE(ip101g_hw_stats); i++)
0543         strscpy(data + i * ETH_GSTRING_LEN,
0544             ip101g_hw_stats[i].name, ETH_GSTRING_LEN);
0545 }
0546 
0547 static u64 ip101g_get_stat(struct phy_device *phydev, int i)
0548 {
0549     struct ip101g_hw_stat stat = ip101g_hw_stats[i];
0550     struct ip101a_g_phy_priv *priv = phydev->priv;
0551     int val;
0552     u64 ret;
0553 
0554     val = phy_read_paged(phydev, stat.page, IP101G_CNT_REG);
0555     if (val < 0) {
0556         ret = U64_MAX;
0557     } else {
0558         priv->stats[i] += val;
0559         ret = priv->stats[i];
0560     }
0561 
0562     return ret;
0563 }
0564 
0565 static void ip101g_get_stats(struct phy_device *phydev,
0566                  struct ethtool_stats *stats, u64 *data)
0567 {
0568     int i;
0569 
0570     for (i = 0; i < ARRAY_SIZE(ip101g_hw_stats); i++)
0571         data[i] = ip101g_get_stat(phydev, i);
0572 }
0573 
0574 static struct phy_driver icplus_driver[] = {
0575 {
0576     PHY_ID_MATCH_MODEL(IP175C_PHY_ID),
0577     .name       = "ICPlus IP175C",
0578     /* PHY_BASIC_FEATURES */
0579     .config_init    = ip175c_config_init,
0580     .config_aneg    = ip175c_config_aneg,
0581     .read_status    = ip175c_read_status,
0582     .suspend    = genphy_suspend,
0583     .resume     = genphy_resume,
0584 }, {
0585     PHY_ID_MATCH_MODEL(IP1001_PHY_ID),
0586     .name       = "ICPlus IP1001",
0587     /* PHY_GBIT_FEATURES */
0588     .config_init    = ip1001_config_init,
0589     .soft_reset = genphy_soft_reset,
0590     .suspend    = genphy_suspend,
0591     .resume     = genphy_resume,
0592 }, {
0593     .name       = "ICPlus IP101A",
0594     .match_phy_device = ip101a_match_phy_device,
0595     .probe      = ip101a_g_probe,
0596     .read_page  = ip101a_read_page,
0597     .write_page = ip101a_write_page,
0598     .config_intr    = ip101a_g_config_intr,
0599     .handle_interrupt = ip101a_g_handle_interrupt,
0600     .config_init    = ip101a_config_init,
0601     .config_aneg    = ip101a_g_config_aneg,
0602     .read_status    = ip101a_g_read_status,
0603     .soft_reset = genphy_soft_reset,
0604     .suspend    = genphy_suspend,
0605     .resume     = genphy_resume,
0606 }, {
0607     .name       = "ICPlus IP101G",
0608     .match_phy_device = ip101g_match_phy_device,
0609     .probe      = ip101a_g_probe,
0610     .read_page  = ip101g_read_page,
0611     .write_page = ip101g_write_page,
0612     .config_intr    = ip101a_g_config_intr,
0613     .handle_interrupt = ip101a_g_handle_interrupt,
0614     .config_init    = ip101g_config_init,
0615     .config_aneg    = ip101a_g_config_aneg,
0616     .read_status    = ip101a_g_read_status,
0617     .soft_reset = genphy_soft_reset,
0618     .get_sset_count = ip101g_get_sset_count,
0619     .get_strings    = ip101g_get_strings,
0620     .get_stats  = ip101g_get_stats,
0621     .suspend    = genphy_suspend,
0622     .resume     = genphy_resume,
0623 } };
0624 
0625 module_phy_driver(icplus_driver);
0626 
0627 static struct mdio_device_id __maybe_unused icplus_tbl[] = {
0628     { PHY_ID_MATCH_MODEL(IP175C_PHY_ID) },
0629     { PHY_ID_MATCH_MODEL(IP1001_PHY_ID) },
0630     { PHY_ID_MATCH_EXACT(IP101A_PHY_ID) },
0631     { }
0632 };
0633 
0634 MODULE_DEVICE_TABLE(mdio, icplus_tbl);