diff options
Diffstat (limited to 'drivers/net/usb/smsc75xx.c')
-rw-r--r-- | drivers/net/usb/smsc75xx.c | 57 |
1 files changed, 37 insertions, 20 deletions
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index a2349483cd2a..fb1a087b101d 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c | |||
@@ -98,7 +98,7 @@ static int __must_check smsc75xx_read_reg(struct usbnet *dev, u32 index, | |||
98 | 98 | ||
99 | if (unlikely(ret < 0)) | 99 | if (unlikely(ret < 0)) |
100 | netdev_warn(dev->net, | 100 | netdev_warn(dev->net, |
101 | "Failed to read register index 0x%08x", index); | 101 | "Failed to read reg index 0x%08x: %d", index, ret); |
102 | 102 | ||
103 | le32_to_cpus(buf); | 103 | le32_to_cpus(buf); |
104 | *data = *buf; | 104 | *data = *buf; |
@@ -128,7 +128,7 @@ static int __must_check smsc75xx_write_reg(struct usbnet *dev, u32 index, | |||
128 | 128 | ||
129 | if (unlikely(ret < 0)) | 129 | if (unlikely(ret < 0)) |
130 | netdev_warn(dev->net, | 130 | netdev_warn(dev->net, |
131 | "Failed to write register index 0x%08x", index); | 131 | "Failed to write reg index 0x%08x: %d", index, ret); |
132 | 132 | ||
133 | kfree(buf); | 133 | kfree(buf); |
134 | 134 | ||
@@ -171,7 +171,7 @@ static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx) | |||
171 | idx &= dev->mii.reg_num_mask; | 171 | idx &= dev->mii.reg_num_mask; |
172 | addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR) | 172 | addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR) |
173 | | ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR) | 173 | | ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR) |
174 | | MII_ACCESS_READ; | 174 | | MII_ACCESS_READ | MII_ACCESS_BUSY; |
175 | ret = smsc75xx_write_reg(dev, MII_ACCESS, addr); | 175 | ret = smsc75xx_write_reg(dev, MII_ACCESS, addr); |
176 | check_warn_goto_done(ret, "Error writing MII_ACCESS"); | 176 | check_warn_goto_done(ret, "Error writing MII_ACCESS"); |
177 | 177 | ||
@@ -210,7 +210,7 @@ static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx, | |||
210 | idx &= dev->mii.reg_num_mask; | 210 | idx &= dev->mii.reg_num_mask; |
211 | addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR) | 211 | addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR) |
212 | | ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR) | 212 | | ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR) |
213 | | MII_ACCESS_WRITE; | 213 | | MII_ACCESS_WRITE | MII_ACCESS_BUSY; |
214 | ret = smsc75xx_write_reg(dev, MII_ACCESS, addr); | 214 | ret = smsc75xx_write_reg(dev, MII_ACCESS, addr); |
215 | check_warn_goto_done(ret, "Error writing MII_ACCESS"); | 215 | check_warn_goto_done(ret, "Error writing MII_ACCESS"); |
216 | 216 | ||
@@ -508,9 +508,9 @@ static int smsc75xx_link_reset(struct usbnet *dev) | |||
508 | u16 lcladv, rmtadv; | 508 | u16 lcladv, rmtadv; |
509 | int ret; | 509 | int ret; |
510 | 510 | ||
511 | /* clear interrupt status */ | 511 | /* write to clear phy interrupt status */ |
512 | ret = smsc75xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC); | 512 | smsc75xx_mdio_write(dev->net, mii->phy_id, PHY_INT_SRC, |
513 | check_warn_return(ret, "Error reading PHY_INT_SRC"); | 513 | PHY_INT_SRC_CLEAR_ALL); |
514 | 514 | ||
515 | ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL); | 515 | ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL); |
516 | check_warn_return(ret, "Error writing INT_STS"); | 516 | check_warn_return(ret, "Error writing INT_STS"); |
@@ -643,7 +643,7 @@ static int smsc75xx_set_mac_address(struct usbnet *dev) | |||
643 | 643 | ||
644 | static int smsc75xx_phy_initialize(struct usbnet *dev) | 644 | static int smsc75xx_phy_initialize(struct usbnet *dev) |
645 | { | 645 | { |
646 | int bmcr, timeout = 0; | 646 | int bmcr, ret, timeout = 0; |
647 | 647 | ||
648 | /* Initialize MII structure */ | 648 | /* Initialize MII structure */ |
649 | dev->mii.dev = dev->net; | 649 | dev->mii.dev = dev->net; |
@@ -651,6 +651,7 @@ static int smsc75xx_phy_initialize(struct usbnet *dev) | |||
651 | dev->mii.mdio_write = smsc75xx_mdio_write; | 651 | dev->mii.mdio_write = smsc75xx_mdio_write; |
652 | dev->mii.phy_id_mask = 0x1f; | 652 | dev->mii.phy_id_mask = 0x1f; |
653 | dev->mii.reg_num_mask = 0x1f; | 653 | dev->mii.reg_num_mask = 0x1f; |
654 | dev->mii.supports_gmii = 1; | ||
654 | dev->mii.phy_id = SMSC75XX_INTERNAL_PHY_ID; | 655 | dev->mii.phy_id = SMSC75XX_INTERNAL_PHY_ID; |
655 | 656 | ||
656 | /* reset phy and wait for reset to complete */ | 657 | /* reset phy and wait for reset to complete */ |
@@ -661,7 +662,7 @@ static int smsc75xx_phy_initialize(struct usbnet *dev) | |||
661 | bmcr = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR); | 662 | bmcr = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR); |
662 | check_warn_return(bmcr, "Error reading MII_BMCR"); | 663 | check_warn_return(bmcr, "Error reading MII_BMCR"); |
663 | timeout++; | 664 | timeout++; |
664 | } while ((bmcr & MII_BMCR) && (timeout < 100)); | 665 | } while ((bmcr & BMCR_RESET) && (timeout < 100)); |
665 | 666 | ||
666 | if (timeout >= 100) { | 667 | if (timeout >= 100) { |
667 | netdev_warn(dev->net, "timeout on PHY Reset"); | 668 | netdev_warn(dev->net, "timeout on PHY Reset"); |
@@ -671,10 +672,13 @@ static int smsc75xx_phy_initialize(struct usbnet *dev) | |||
671 | smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, | 672 | smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, |
672 | ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP | | 673 | ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP | |
673 | ADVERTISE_PAUSE_ASYM); | 674 | ADVERTISE_PAUSE_ASYM); |
675 | smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000, | ||
676 | ADVERTISE_1000FULL); | ||
674 | 677 | ||
675 | /* read to clear */ | 678 | /* read and write to clear phy interrupt status */ |
676 | smsc75xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC); | 679 | ret = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC); |
677 | check_warn_return(bmcr, "Error reading PHY_INT_SRC"); | 680 | check_warn_return(ret, "Error reading PHY_INT_SRC"); |
681 | smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_SRC, 0xffff); | ||
678 | 682 | ||
679 | smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK, | 683 | smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK, |
680 | PHY_INT_MASK_DEFAULT); | 684 | PHY_INT_MASK_DEFAULT); |
@@ -899,15 +903,20 @@ static int smsc75xx_reset(struct usbnet *dev) | |||
899 | 903 | ||
900 | netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x", buf); | 904 | netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x", buf); |
901 | 905 | ||
902 | /* Configure GPIO pins as LED outputs */ | 906 | ret = smsc75xx_read_reg(dev, E2P_CMD, &buf); |
903 | ret = smsc75xx_read_reg(dev, LED_GPIO_CFG, &buf); | 907 | check_warn_return(ret, "Failed to read E2P_CMD: %d", ret); |
904 | check_warn_return(ret, "Failed to read LED_GPIO_CFG: %d", ret); | 908 | |
909 | /* only set default GPIO/LED settings if no EEPROM is detected */ | ||
910 | if (!(buf & E2P_CMD_LOADED)) { | ||
911 | ret = smsc75xx_read_reg(dev, LED_GPIO_CFG, &buf); | ||
912 | check_warn_return(ret, "Failed to read LED_GPIO_CFG: %d", ret); | ||
905 | 913 | ||
906 | buf &= ~(LED_GPIO_CFG_LED2_FUN_SEL | LED_GPIO_CFG_LED10_FUN_SEL); | 914 | buf &= ~(LED_GPIO_CFG_LED2_FUN_SEL | LED_GPIO_CFG_LED10_FUN_SEL); |
907 | buf |= LED_GPIO_CFG_LEDGPIO_EN | LED_GPIO_CFG_LED2_FUN_SEL; | 915 | buf |= LED_GPIO_CFG_LEDGPIO_EN | LED_GPIO_CFG_LED2_FUN_SEL; |
908 | 916 | ||
909 | ret = smsc75xx_write_reg(dev, LED_GPIO_CFG, buf); | 917 | ret = smsc75xx_write_reg(dev, LED_GPIO_CFG, buf); |
910 | check_warn_return(ret, "Failed to write LED_GPIO_CFG: %d", ret); | 918 | check_warn_return(ret, "Failed to write LED_GPIO_CFG: %d", ret); |
919 | } | ||
911 | 920 | ||
912 | ret = smsc75xx_write_reg(dev, FLOW, 0); | 921 | ret = smsc75xx_write_reg(dev, FLOW, 0); |
913 | check_warn_return(ret, "Failed to write FLOW: %d", ret); | 922 | check_warn_return(ret, "Failed to write FLOW: %d", ret); |
@@ -946,6 +955,14 @@ static int smsc75xx_reset(struct usbnet *dev) | |||
946 | ret = smsc75xx_write_reg(dev, INT_EP_CTL, buf); | 955 | ret = smsc75xx_write_reg(dev, INT_EP_CTL, buf); |
947 | check_warn_return(ret, "Failed to write INT_EP_CTL: %d", ret); | 956 | check_warn_return(ret, "Failed to write INT_EP_CTL: %d", ret); |
948 | 957 | ||
958 | /* allow mac to detect speed and duplex from phy */ | ||
959 | ret = smsc75xx_read_reg(dev, MAC_CR, &buf); | ||
960 | check_warn_return(ret, "Failed to read MAC_CR: %d", ret); | ||
961 | |||
962 | buf |= (MAC_CR_ADD | MAC_CR_ASD); | ||
963 | ret = smsc75xx_write_reg(dev, MAC_CR, buf); | ||
964 | check_warn_return(ret, "Failed to write MAC_CR: %d", ret); | ||
965 | |||
949 | ret = smsc75xx_read_reg(dev, MAC_TX, &buf); | 966 | ret = smsc75xx_read_reg(dev, MAC_TX, &buf); |
950 | check_warn_return(ret, "Failed to read MAC_TX: %d", ret); | 967 | check_warn_return(ret, "Failed to read MAC_TX: %d", ret); |
951 | 968 | ||
@@ -1212,7 +1229,7 @@ static const struct driver_info smsc75xx_info = { | |||
1212 | .rx_fixup = smsc75xx_rx_fixup, | 1229 | .rx_fixup = smsc75xx_rx_fixup, |
1213 | .tx_fixup = smsc75xx_tx_fixup, | 1230 | .tx_fixup = smsc75xx_tx_fixup, |
1214 | .status = smsc75xx_status, | 1231 | .status = smsc75xx_status, |
1215 | .flags = FLAG_ETHER | FLAG_SEND_ZLP, | 1232 | .flags = FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR, |
1216 | }; | 1233 | }; |
1217 | 1234 | ||
1218 | static const struct usb_device_id products[] = { | 1235 | static const struct usb_device_id products[] = { |