Loading drivers/net/usb/Kconfig +5 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,11 @@ config USB_LAN78XX help This option adds support for Microchip LAN78XX based USB 2 & USB 3 10/100/1000 Ethernet adapters. LAN7800 : USB 3 to 10/100/1000 Ethernet adapter LAN7850 : USB 2 to 10/100/1000 Ethernet adapter LAN7801 : USB 3 to 10/100/1000 Ethernet adapter (MAC only) Proper PHY driver is required for LAN7801. To compile this driver as a module, choose M here: the module will be called lan78xx. Loading drivers/net/usb/lan78xx.c +107 −2 Original line number Diff line number Diff line Loading @@ -40,7 +40,7 @@ #define DRIVER_AUTHOR "WOOJUNG HUH <woojung.huh@microchip.com>" #define DRIVER_DESC "LAN78XX USB 3.0 Gigabit Ethernet Devices" #define DRIVER_NAME "lan78xx" #define DRIVER_VERSION "1.0.5" #define DRIVER_VERSION "1.0.6" #define TX_TIMEOUT_JIFFIES (5 * HZ) #define THROTTLE_JIFFIES (HZ / 8) Loading @@ -67,6 +67,7 @@ #define LAN78XX_USB_VENDOR_ID (0x0424) #define LAN7800_USB_PRODUCT_ID (0x7800) #define LAN7850_USB_PRODUCT_ID (0x7850) #define LAN7801_USB_PRODUCT_ID (0x7801) #define LAN78XX_EEPROM_MAGIC (0x78A5) #define LAN78XX_OTP_MAGIC (0x78F3) Loading Loading @@ -390,6 +391,7 @@ struct lan78xx_net { u32 chipid; u32 chiprev; struct mii_bus *mdiobus; phy_interface_t interface; int fc_autoneg; u8 fc_request_control; Loading @@ -400,6 +402,10 @@ struct lan78xx_net { struct irq_domain_data domain_data; }; /* define external phy id */ #define PHY_LAN8835 (0x0007C130) #define PHY_KSZ9031RNX (0x00221620) /* use ethtool to change the level for any given device */ static int msg_level = -1; module_param(msg_level, int, 0); Loading Loading @@ -1697,6 +1703,7 @@ static int lan78xx_mdiobus_read(struct mii_bus *bus, int phy_id, int idx) done: mutex_unlock(&dev->phy_mutex); usb_autopm_put_interface(dev->intf); return ret; } Loading Loading @@ -1759,6 +1766,10 @@ static int lan78xx_mdio_init(struct lan78xx_net *dev) /* set to internal PHY id */ dev->mdiobus->phy_mask = ~(1 << 1); break; case ID_REV_CHIP_ID_7801_: /* scan thru PHYAD[2..0] */ dev->mdiobus->phy_mask = ~(0xFF); break; } ret = mdiobus_register(dev->mdiobus); Loading Loading @@ -1933,6 +1944,47 @@ static void lan78xx_remove_irq_domain(struct lan78xx_net *dev) dev->domain_data.irqdomain = NULL; } static int lan8835_fixup(struct phy_device *phydev) { int buf; int ret; struct lan78xx_net *dev = netdev_priv(phydev->attached_dev); /* LED2/PME_N/IRQ_N/RGMII_ID pin to IRQ_N mode */ buf = phy_read_mmd_indirect(phydev, 0x8010, 3); buf &= ~0x1800; buf |= 0x0800; phy_write_mmd_indirect(phydev, 0x8010, 3, buf); /* RGMII MAC TXC Delay Enable */ ret = lan78xx_write_reg(dev, MAC_RGMII_ID, MAC_RGMII_ID_TXC_DELAY_EN_); /* RGMII TX DLL Tune Adjust */ ret = lan78xx_write_reg(dev, RGMII_TX_BYP_DLL, 0x3D00); dev->interface = PHY_INTERFACE_MODE_RGMII_TXID; return 1; } static int ksz9031rnx_fixup(struct phy_device *phydev) { struct lan78xx_net *dev = netdev_priv(phydev->attached_dev); /* Micrel9301RNX PHY configuration */ /* RGMII Control Signal Pad Skew */ phy_write_mmd_indirect(phydev, 4, 2, 0x0077); /* RGMII RX Data Pad Skew */ phy_write_mmd_indirect(phydev, 5, 2, 0x7777); /* RGMII RX Clock Pad Skew */ phy_write_mmd_indirect(phydev, 8, 2, 0x1FF); dev->interface = PHY_INTERFACE_MODE_RGMII_RXID; return 1; } static int lan78xx_phy_init(struct lan78xx_net *dev) { int ret; Loading @@ -1945,6 +1997,42 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) return -EIO; } if ((dev->chipid == ID_REV_CHIP_ID_7800_) || (dev->chipid == ID_REV_CHIP_ID_7850_)) { phydev->is_internal = true; dev->interface = PHY_INTERFACE_MODE_GMII; } else if (dev->chipid == ID_REV_CHIP_ID_7801_) { if (!phydev->drv) { netdev_err(dev->net, "no PHY driver found\n"); return -EIO; } dev->interface = PHY_INTERFACE_MODE_RGMII; /* external PHY fixup for KSZ9031RNX */ ret = phy_register_fixup_for_uid(PHY_KSZ9031RNX, 0xfffffff0, ksz9031rnx_fixup); if (ret < 0) { netdev_err(dev->net, "fail to register fixup\n"); return ret; } /* external PHY fixup for LAN8835 */ ret = phy_register_fixup_for_uid(PHY_LAN8835, 0xfffffff0, lan8835_fixup); if (ret < 0) { netdev_err(dev->net, "fail to register fixup\n"); return ret; } /* add more external PHY fixup here if needed */ phydev->is_internal = false; } else { netdev_err(dev->net, "unknown ID found\n"); ret = -EIO; goto error; } /* if phyirq is not set, use polling mode in phylib */ if (dev->domain_data.phyirq > 0) phydev->irq = dev->domain_data.phyirq; Loading @@ -1957,7 +2045,7 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) ret = phy_connect_direct(dev->net, phydev, lan78xx_link_status_change, PHY_INTERFACE_MODE_GMII); dev->interface); if (ret) { netdev_err(dev->net, "can't attach PHY to %s\n", dev->mdiobus->id); Loading @@ -1982,6 +2070,12 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) netif_dbg(dev, ifup, dev->net, "phy initialised successfully"); return 0; error: phy_unregister_fixup_for_uid(PHY_KSZ9031RNX, 0xfffffff0); phy_unregister_fixup_for_uid(PHY_LAN8835, 0xfffffff0); return ret; } static int lan78xx_set_rx_max_frame_length(struct lan78xx_net *dev, int size) Loading Loading @@ -2338,6 +2432,9 @@ static int lan78xx_reset(struct lan78xx_net *dev) } while ((buf & PMT_CTL_PHY_RST_) || !(buf & PMT_CTL_READY_)); ret = lan78xx_read_reg(dev, MAC_CR, &buf); /* LAN7801 only has RGMII mode */ if (dev->chipid == ID_REV_CHIP_ID_7801_) buf &= ~MAC_CR_GMII_EN_; buf |= MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_; ret = lan78xx_write_reg(dev, MAC_CR, buf); Loading Loading @@ -2464,8 +2561,12 @@ static int lan78xx_stop(struct net_device *net) if (timer_pending(&dev->stat_monitor)) del_timer_sync(&dev->stat_monitor); phy_unregister_fixup_for_uid(PHY_KSZ9031RNX, 0xfffffff0); phy_unregister_fixup_for_uid(PHY_LAN8835, 0xfffffff0); phy_stop(net->phydev); phy_disconnect(net->phydev); net->phydev = NULL; clear_bit(EVENT_DEV_OPEN, &dev->flags); Loading Loading @@ -3888,6 +3989,10 @@ static const struct usb_device_id products[] = { /* LAN7850 USB Gigabit Ethernet Device */ USB_DEVICE(LAN78XX_USB_VENDOR_ID, LAN7850_USB_PRODUCT_ID), }, { /* LAN7801 USB Gigabit Ethernet Device */ USB_DEVICE(LAN78XX_USB_VENDOR_ID, LAN7801_USB_PRODUCT_ID), }, {}, }; MODULE_DEVICE_TABLE(usb, products); Loading drivers/net/usb/lan78xx.h +14 −0 Original line number Diff line number Diff line Loading @@ -108,6 +108,7 @@ #define ID_REV_CHIP_REV_MASK_ (0x0000FFFF) #define ID_REV_CHIP_ID_7800_ (0x7800) #define ID_REV_CHIP_ID_7850_ (0x7850) #define ID_REV_CHIP_ID_7801_ (0x7801) #define FPGA_REV (0x04) #define FPGA_REV_MINOR_MASK_ (0x0000FF00) Loading Loading @@ -550,6 +551,7 @@ #define LTM_INACTIVE1_TIMER10_ (0x0000FFFF) #define MAC_CR (0x100) #define MAC_CR_GMII_EN_ (0x00080000) #define MAC_CR_EEE_TX_CLK_STOP_EN_ (0x00040000) #define MAC_CR_EEE_EN_ (0x00020000) #define MAC_CR_EEE_TLAR_EN_ (0x00010000) Loading Loading @@ -787,6 +789,18 @@ #define PHY_DEV_ID_MODEL_MASK_ (0x0FC00000) #define PHY_DEV_ID_OUI_MASK_ (0x003FFFFF) #define RGMII_TX_BYP_DLL (0x708) #define RGMII_TX_BYP_DLL_TX_TUNE_ADJ_MASK_ (0x000FC00) #define RGMII_TX_BYP_DLL_TX_TUNE_SEL_MASK_ (0x00003F0) #define RGMII_TX_BYP_DLL_TX_DLL_RESET_ (0x0000002) #define RGMII_TX_BYP_DLL_TX_DLL_BYPASS_ (0x0000001) #define RGMII_RX_BYP_DLL (0x70C) #define RGMII_RX_BYP_DLL_RX_TUNE_ADJ_MASK_ (0x000FC00) #define RGMII_RX_BYP_DLL_RX_TUNE_SEL_MASK_ (0x00003F0) #define RGMII_RX_BYP_DLL_RX_DLL_RESET_ (0x0000002) #define RGMII_RX_BYP_DLL_RX_DLL_BYPASS_ (0x0000001) #define OTP_BASE_ADDR (0x00001000) #define OTP_ADDR_RANGE_ (0x1FF) Loading Loading
drivers/net/usb/Kconfig +5 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,11 @@ config USB_LAN78XX help This option adds support for Microchip LAN78XX based USB 2 & USB 3 10/100/1000 Ethernet adapters. LAN7800 : USB 3 to 10/100/1000 Ethernet adapter LAN7850 : USB 2 to 10/100/1000 Ethernet adapter LAN7801 : USB 3 to 10/100/1000 Ethernet adapter (MAC only) Proper PHY driver is required for LAN7801. To compile this driver as a module, choose M here: the module will be called lan78xx. Loading
drivers/net/usb/lan78xx.c +107 −2 Original line number Diff line number Diff line Loading @@ -40,7 +40,7 @@ #define DRIVER_AUTHOR "WOOJUNG HUH <woojung.huh@microchip.com>" #define DRIVER_DESC "LAN78XX USB 3.0 Gigabit Ethernet Devices" #define DRIVER_NAME "lan78xx" #define DRIVER_VERSION "1.0.5" #define DRIVER_VERSION "1.0.6" #define TX_TIMEOUT_JIFFIES (5 * HZ) #define THROTTLE_JIFFIES (HZ / 8) Loading @@ -67,6 +67,7 @@ #define LAN78XX_USB_VENDOR_ID (0x0424) #define LAN7800_USB_PRODUCT_ID (0x7800) #define LAN7850_USB_PRODUCT_ID (0x7850) #define LAN7801_USB_PRODUCT_ID (0x7801) #define LAN78XX_EEPROM_MAGIC (0x78A5) #define LAN78XX_OTP_MAGIC (0x78F3) Loading Loading @@ -390,6 +391,7 @@ struct lan78xx_net { u32 chipid; u32 chiprev; struct mii_bus *mdiobus; phy_interface_t interface; int fc_autoneg; u8 fc_request_control; Loading @@ -400,6 +402,10 @@ struct lan78xx_net { struct irq_domain_data domain_data; }; /* define external phy id */ #define PHY_LAN8835 (0x0007C130) #define PHY_KSZ9031RNX (0x00221620) /* use ethtool to change the level for any given device */ static int msg_level = -1; module_param(msg_level, int, 0); Loading Loading @@ -1697,6 +1703,7 @@ static int lan78xx_mdiobus_read(struct mii_bus *bus, int phy_id, int idx) done: mutex_unlock(&dev->phy_mutex); usb_autopm_put_interface(dev->intf); return ret; } Loading Loading @@ -1759,6 +1766,10 @@ static int lan78xx_mdio_init(struct lan78xx_net *dev) /* set to internal PHY id */ dev->mdiobus->phy_mask = ~(1 << 1); break; case ID_REV_CHIP_ID_7801_: /* scan thru PHYAD[2..0] */ dev->mdiobus->phy_mask = ~(0xFF); break; } ret = mdiobus_register(dev->mdiobus); Loading Loading @@ -1933,6 +1944,47 @@ static void lan78xx_remove_irq_domain(struct lan78xx_net *dev) dev->domain_data.irqdomain = NULL; } static int lan8835_fixup(struct phy_device *phydev) { int buf; int ret; struct lan78xx_net *dev = netdev_priv(phydev->attached_dev); /* LED2/PME_N/IRQ_N/RGMII_ID pin to IRQ_N mode */ buf = phy_read_mmd_indirect(phydev, 0x8010, 3); buf &= ~0x1800; buf |= 0x0800; phy_write_mmd_indirect(phydev, 0x8010, 3, buf); /* RGMII MAC TXC Delay Enable */ ret = lan78xx_write_reg(dev, MAC_RGMII_ID, MAC_RGMII_ID_TXC_DELAY_EN_); /* RGMII TX DLL Tune Adjust */ ret = lan78xx_write_reg(dev, RGMII_TX_BYP_DLL, 0x3D00); dev->interface = PHY_INTERFACE_MODE_RGMII_TXID; return 1; } static int ksz9031rnx_fixup(struct phy_device *phydev) { struct lan78xx_net *dev = netdev_priv(phydev->attached_dev); /* Micrel9301RNX PHY configuration */ /* RGMII Control Signal Pad Skew */ phy_write_mmd_indirect(phydev, 4, 2, 0x0077); /* RGMII RX Data Pad Skew */ phy_write_mmd_indirect(phydev, 5, 2, 0x7777); /* RGMII RX Clock Pad Skew */ phy_write_mmd_indirect(phydev, 8, 2, 0x1FF); dev->interface = PHY_INTERFACE_MODE_RGMII_RXID; return 1; } static int lan78xx_phy_init(struct lan78xx_net *dev) { int ret; Loading @@ -1945,6 +1997,42 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) return -EIO; } if ((dev->chipid == ID_REV_CHIP_ID_7800_) || (dev->chipid == ID_REV_CHIP_ID_7850_)) { phydev->is_internal = true; dev->interface = PHY_INTERFACE_MODE_GMII; } else if (dev->chipid == ID_REV_CHIP_ID_7801_) { if (!phydev->drv) { netdev_err(dev->net, "no PHY driver found\n"); return -EIO; } dev->interface = PHY_INTERFACE_MODE_RGMII; /* external PHY fixup for KSZ9031RNX */ ret = phy_register_fixup_for_uid(PHY_KSZ9031RNX, 0xfffffff0, ksz9031rnx_fixup); if (ret < 0) { netdev_err(dev->net, "fail to register fixup\n"); return ret; } /* external PHY fixup for LAN8835 */ ret = phy_register_fixup_for_uid(PHY_LAN8835, 0xfffffff0, lan8835_fixup); if (ret < 0) { netdev_err(dev->net, "fail to register fixup\n"); return ret; } /* add more external PHY fixup here if needed */ phydev->is_internal = false; } else { netdev_err(dev->net, "unknown ID found\n"); ret = -EIO; goto error; } /* if phyirq is not set, use polling mode in phylib */ if (dev->domain_data.phyirq > 0) phydev->irq = dev->domain_data.phyirq; Loading @@ -1957,7 +2045,7 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) ret = phy_connect_direct(dev->net, phydev, lan78xx_link_status_change, PHY_INTERFACE_MODE_GMII); dev->interface); if (ret) { netdev_err(dev->net, "can't attach PHY to %s\n", dev->mdiobus->id); Loading @@ -1982,6 +2070,12 @@ static int lan78xx_phy_init(struct lan78xx_net *dev) netif_dbg(dev, ifup, dev->net, "phy initialised successfully"); return 0; error: phy_unregister_fixup_for_uid(PHY_KSZ9031RNX, 0xfffffff0); phy_unregister_fixup_for_uid(PHY_LAN8835, 0xfffffff0); return ret; } static int lan78xx_set_rx_max_frame_length(struct lan78xx_net *dev, int size) Loading Loading @@ -2338,6 +2432,9 @@ static int lan78xx_reset(struct lan78xx_net *dev) } while ((buf & PMT_CTL_PHY_RST_) || !(buf & PMT_CTL_READY_)); ret = lan78xx_read_reg(dev, MAC_CR, &buf); /* LAN7801 only has RGMII mode */ if (dev->chipid == ID_REV_CHIP_ID_7801_) buf &= ~MAC_CR_GMII_EN_; buf |= MAC_CR_AUTO_DUPLEX_ | MAC_CR_AUTO_SPEED_; ret = lan78xx_write_reg(dev, MAC_CR, buf); Loading Loading @@ -2464,8 +2561,12 @@ static int lan78xx_stop(struct net_device *net) if (timer_pending(&dev->stat_monitor)) del_timer_sync(&dev->stat_monitor); phy_unregister_fixup_for_uid(PHY_KSZ9031RNX, 0xfffffff0); phy_unregister_fixup_for_uid(PHY_LAN8835, 0xfffffff0); phy_stop(net->phydev); phy_disconnect(net->phydev); net->phydev = NULL; clear_bit(EVENT_DEV_OPEN, &dev->flags); Loading Loading @@ -3888,6 +3989,10 @@ static const struct usb_device_id products[] = { /* LAN7850 USB Gigabit Ethernet Device */ USB_DEVICE(LAN78XX_USB_VENDOR_ID, LAN7850_USB_PRODUCT_ID), }, { /* LAN7801 USB Gigabit Ethernet Device */ USB_DEVICE(LAN78XX_USB_VENDOR_ID, LAN7801_USB_PRODUCT_ID), }, {}, }; MODULE_DEVICE_TABLE(usb, products); Loading
drivers/net/usb/lan78xx.h +14 −0 Original line number Diff line number Diff line Loading @@ -108,6 +108,7 @@ #define ID_REV_CHIP_REV_MASK_ (0x0000FFFF) #define ID_REV_CHIP_ID_7800_ (0x7800) #define ID_REV_CHIP_ID_7850_ (0x7850) #define ID_REV_CHIP_ID_7801_ (0x7801) #define FPGA_REV (0x04) #define FPGA_REV_MINOR_MASK_ (0x0000FF00) Loading Loading @@ -550,6 +551,7 @@ #define LTM_INACTIVE1_TIMER10_ (0x0000FFFF) #define MAC_CR (0x100) #define MAC_CR_GMII_EN_ (0x00080000) #define MAC_CR_EEE_TX_CLK_STOP_EN_ (0x00040000) #define MAC_CR_EEE_EN_ (0x00020000) #define MAC_CR_EEE_TLAR_EN_ (0x00010000) Loading Loading @@ -787,6 +789,18 @@ #define PHY_DEV_ID_MODEL_MASK_ (0x0FC00000) #define PHY_DEV_ID_OUI_MASK_ (0x003FFFFF) #define RGMII_TX_BYP_DLL (0x708) #define RGMII_TX_BYP_DLL_TX_TUNE_ADJ_MASK_ (0x000FC00) #define RGMII_TX_BYP_DLL_TX_TUNE_SEL_MASK_ (0x00003F0) #define RGMII_TX_BYP_DLL_TX_DLL_RESET_ (0x0000002) #define RGMII_TX_BYP_DLL_TX_DLL_BYPASS_ (0x0000001) #define RGMII_RX_BYP_DLL (0x70C) #define RGMII_RX_BYP_DLL_RX_TUNE_ADJ_MASK_ (0x000FC00) #define RGMII_RX_BYP_DLL_RX_TUNE_SEL_MASK_ (0x00003F0) #define RGMII_RX_BYP_DLL_RX_DLL_RESET_ (0x0000002) #define RGMII_RX_BYP_DLL_RX_DLL_BYPASS_ (0x0000001) #define OTP_BASE_ADDR (0x00001000) #define OTP_ADDR_RANGE_ (0x1FF) Loading