Adding Fixed PHY support to the lan78xx driver.

Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 
Ethernet device driver")
Signed-off-by: Raghuram Chary J <raghuramchary.jallipa...@microchip.com>
---
 drivers/net/usb/Kconfig   |  1 +
 drivers/net/usb/lan78xx.c | 42 ++++++++++++++++++++++++++++++++++++++----
 2 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index f28bd74ac275..418b0904cecb 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -111,6 +111,7 @@ config USB_LAN78XX
        select MII
        select PHYLIB
        select MICROCHIP_PHY
+       select FIXED_PHY
        help
          This option adds support for Microchip LAN78XX based USB 2
          & USB 3 10/100/1000 Ethernet adapters.
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index e3cc3b504c87..e67b2dabde66 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -36,7 +36,7 @@
 #include <linux/irq.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/microchipphy.h>
-#include <linux/phy.h>
+#include <linux/phy_fixed.h>
 #include "lan78xx.h"
 
 #define DRIVER_AUTHOR  "WOOJUNG HUH <woojung....@microchip.com>"
@@ -426,6 +426,7 @@ struct lan78xx_net {
        struct statstage        stats;
 
        struct irq_domain_data  domain_data;
+       struct phy_device       *fixedphy;
 };
 
 /* define external phy id */
@@ -2058,11 +2059,39 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
        int ret;
        u32 mii_adv;
        struct phy_device *phydev;
+       struct fixed_phy_status fphy_status = {
+               .link = 1,
+               .speed = SPEED_1000,
+               .duplex = DUPLEX_FULL,
+       };
 
        phydev = phy_find_first(dev->mdiobus);
        if (!phydev) {
-               netdev_err(dev->net, "no PHY found\n");
-               return -EIO;
+               if (dev->chipid == ID_REV_CHIP_ID_7801_) {
+                       u32 buf;
+
+                       netdev_info(dev->net, "PHY Not Found!! Registering 
Fixed PHY\n");
+                       phydev = fixed_phy_register(PHY_POLL, &fphy_status, -1,
+                                                   NULL);
+                       if (IS_ERR(phydev)) {
+                               netdev_err(dev->net, "No PHY/fixed_PHY 
found\n");
+                               return -ENODEV;
+                       }
+                       netdev_info(dev->net, "Registered FIXED PHY\n");
+                       dev->interface = PHY_INTERFACE_MODE_RGMII;
+                       dev->fixedphy = phydev;
+                       ret = lan78xx_write_reg(dev, MAC_RGMII_ID,
+                                               MAC_RGMII_ID_TXC_DELAY_EN_);
+                       ret = lan78xx_write_reg(dev, RGMII_TX_BYP_DLL, 0x3D00);
+                       ret = lan78xx_read_reg(dev, HW_CFG, &buf);
+                       buf |= HW_CFG_CLK125_EN_;
+                       buf |= HW_CFG_REFCLK25_EN_;
+                       ret = lan78xx_write_reg(dev, HW_CFG, buf);
+                       goto phyinit;
+               } else {
+                       netdev_err(dev->net, "no PHY found\n");
+                       return -EIO;
+               }
        }
 
        if ((dev->chipid == ID_REV_CHIP_ID_7800_) ||
@@ -2100,7 +2129,7 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
                ret = -EIO;
                goto error;
        }
-
+phyinit:
        /* if phyirq is not set, use polling mode in phylib */
        if (dev->domain_data.phyirq > 0)
                phydev->irq = dev->domain_data.phyirq;
@@ -3559,6 +3588,11 @@ static void lan78xx_disconnect(struct usb_interface 
*intf)
        udev = interface_to_usbdev(intf);
 
        net = dev->net;
+
+       if (dev->fixedphy) {
+               fixed_phy_unregister(dev->fixedphy);
+               dev->fixedphy = NULL;
+       }
        unregister_netdev(net);
 
        cancel_delayed_work_sync(&dev->wq);
-- 
2.16.2

Reply via email to