diff options
Diffstat (limited to 'drivers/net/smsc911x.c')
-rw-r--r-- | drivers/net/smsc911x.c | 152 |
1 files changed, 85 insertions, 67 deletions
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 9a78daec2fe9..dceae8a65809 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c | |||
@@ -368,48 +368,53 @@ out: | |||
368 | return reg; | 368 | return reg; |
369 | } | 369 | } |
370 | 370 | ||
371 | /* Autodetects and initialises external phy for SMSC9115 and SMSC9117 flavors. | 371 | /* Switch to external phy. Assumes tx and rx are stopped. */ |
372 | * If something goes wrong, returns -ENODEV to revert back to internal phy. | 372 | static void smsc911x_phy_enable_external(struct smsc911x_data *pdata) |
373 | * Performed at initialisation only, so interrupts are enabled */ | ||
374 | static int smsc911x_phy_initialise_external(struct smsc911x_data *pdata) | ||
375 | { | 373 | { |
376 | unsigned int hwcfg = smsc911x_reg_read(pdata, HW_CFG); | 374 | unsigned int hwcfg = smsc911x_reg_read(pdata, HW_CFG); |
377 | 375 | ||
378 | /* External phy is requested, supported, and detected */ | 376 | /* Disable phy clocks to the MAC */ |
379 | if (hwcfg & HW_CFG_EXT_PHY_DET_) { | 377 | hwcfg &= (~HW_CFG_PHY_CLK_SEL_); |
378 | hwcfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_; | ||
379 | smsc911x_reg_write(pdata, HW_CFG, hwcfg); | ||
380 | udelay(10); /* Enough time for clocks to stop */ | ||
380 | 381 | ||
381 | /* Switch to external phy. Assuming tx and rx are stopped | 382 | /* Switch to external phy */ |
382 | * because smsc911x_phy_initialise is called before | 383 | hwcfg |= HW_CFG_EXT_PHY_EN_; |
383 | * smsc911x_rx_initialise and tx_initialise. */ | 384 | smsc911x_reg_write(pdata, HW_CFG, hwcfg); |
384 | 385 | ||
385 | /* Disable phy clocks to the MAC */ | 386 | /* Enable phy clocks to the MAC */ |
386 | hwcfg &= (~HW_CFG_PHY_CLK_SEL_); | 387 | hwcfg &= (~HW_CFG_PHY_CLK_SEL_); |
387 | hwcfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_; | 388 | hwcfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_; |
388 | smsc911x_reg_write(pdata, HW_CFG, hwcfg); | 389 | smsc911x_reg_write(pdata, HW_CFG, hwcfg); |
389 | udelay(10); /* Enough time for clocks to stop */ | 390 | udelay(10); /* Enough time for clocks to restart */ |
390 | 391 | ||
391 | /* Switch to external phy */ | 392 | hwcfg |= HW_CFG_SMI_SEL_; |
392 | hwcfg |= HW_CFG_EXT_PHY_EN_; | 393 | smsc911x_reg_write(pdata, HW_CFG, hwcfg); |
393 | smsc911x_reg_write(pdata, HW_CFG, hwcfg); | 394 | } |
394 | |||
395 | /* Enable phy clocks to the MAC */ | ||
396 | hwcfg &= (~HW_CFG_PHY_CLK_SEL_); | ||
397 | hwcfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_; | ||
398 | smsc911x_reg_write(pdata, HW_CFG, hwcfg); | ||
399 | udelay(10); /* Enough time for clocks to restart */ | ||
400 | 395 | ||
401 | hwcfg |= HW_CFG_SMI_SEL_; | 396 | /* Autodetects and enables external phy if present on supported chips. |
402 | smsc911x_reg_write(pdata, HW_CFG, hwcfg); | 397 | * autodetection can be overridden by specifying SMSC911X_FORCE_INTERNAL_PHY |
398 | * or SMSC911X_FORCE_EXTERNAL_PHY in the platform_data flags. */ | ||
399 | static void smsc911x_phy_initialise_external(struct smsc911x_data *pdata) | ||
400 | { | ||
401 | unsigned int hwcfg = smsc911x_reg_read(pdata, HW_CFG); | ||
403 | 402 | ||
404 | SMSC_TRACE(HW, "Successfully switched to external PHY"); | 403 | if (pdata->config.flags & SMSC911X_FORCE_INTERNAL_PHY) { |
404 | SMSC_TRACE(HW, "Forcing internal PHY"); | ||
405 | pdata->using_extphy = 0; | ||
406 | } else if (pdata->config.flags & SMSC911X_FORCE_EXTERNAL_PHY) { | ||
407 | SMSC_TRACE(HW, "Forcing external PHY"); | ||
408 | smsc911x_phy_enable_external(pdata); | ||
409 | pdata->using_extphy = 1; | ||
410 | } else if (hwcfg & HW_CFG_EXT_PHY_DET_) { | ||
411 | SMSC_TRACE(HW, "HW_CFG EXT_PHY_DET set, using external PHY"); | ||
412 | smsc911x_phy_enable_external(pdata); | ||
405 | pdata->using_extphy = 1; | 413 | pdata->using_extphy = 1; |
406 | } else { | 414 | } else { |
407 | SMSC_WARNING(HW, "No external PHY detected, " | 415 | SMSC_TRACE(HW, "HW_CFG EXT_PHY_DET clear, using internal PHY"); |
408 | "Using internal PHY instead."); | 416 | pdata->using_extphy = 0; |
409 | /* Use internal phy */ | ||
410 | return -ENODEV; | ||
411 | } | 417 | } |
412 | return 0; | ||
413 | } | 418 | } |
414 | 419 | ||
415 | /* Fetches a tx status out of the status fifo */ | 420 | /* Fetches a tx status out of the status fifo */ |
@@ -769,7 +774,7 @@ static int smsc911x_mii_probe(struct net_device *dev) | |||
769 | return -ENODEV; | 774 | return -ENODEV; |
770 | } | 775 | } |
771 | 776 | ||
772 | phydev = phy_connect(dev, phydev->dev.bus_id, | 777 | phydev = phy_connect(dev, dev_name(&phydev->dev), |
773 | &smsc911x_phy_adjust_link, 0, pdata->config.phy_interface); | 778 | &smsc911x_phy_adjust_link, 0, pdata->config.phy_interface); |
774 | 779 | ||
775 | if (IS_ERR(phydev)) { | 780 | if (IS_ERR(phydev)) { |
@@ -778,7 +783,8 @@ static int smsc911x_mii_probe(struct net_device *dev) | |||
778 | } | 783 | } |
779 | 784 | ||
780 | pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", | 785 | pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", |
781 | dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq); | 786 | dev->name, phydev->drv->name, |
787 | dev_name(&phydev->dev), phydev->irq); | ||
782 | 788 | ||
783 | /* mask with MAC supported features */ | 789 | /* mask with MAC supported features */ |
784 | phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause | | 790 | phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause | |
@@ -824,22 +830,18 @@ static int __devinit smsc911x_mii_init(struct platform_device *pdev, | |||
824 | 830 | ||
825 | pdata->mii_bus->parent = &pdev->dev; | 831 | pdata->mii_bus->parent = &pdev->dev; |
826 | 832 | ||
827 | pdata->using_extphy = 0; | ||
828 | |||
829 | switch (pdata->idrev & 0xFFFF0000) { | 833 | switch (pdata->idrev & 0xFFFF0000) { |
830 | case 0x01170000: | 834 | case 0x01170000: |
831 | case 0x01150000: | 835 | case 0x01150000: |
832 | case 0x117A0000: | 836 | case 0x117A0000: |
833 | case 0x115A0000: | 837 | case 0x115A0000: |
834 | /* External PHY supported, try to autodetect */ | 838 | /* External PHY supported, try to autodetect */ |
835 | if (smsc911x_phy_initialise_external(pdata) < 0) { | 839 | smsc911x_phy_initialise_external(pdata); |
836 | SMSC_TRACE(HW, "No external PHY detected, " | ||
837 | "using internal PHY"); | ||
838 | } | ||
839 | break; | 840 | break; |
840 | default: | 841 | default: |
841 | SMSC_TRACE(HW, "External PHY is not supported, " | 842 | SMSC_TRACE(HW, "External PHY is not supported, " |
842 | "using internal PHY"); | 843 | "using internal PHY"); |
844 | pdata->using_extphy = 0; | ||
843 | break; | 845 | break; |
844 | } | 846 | } |
845 | 847 | ||
@@ -984,7 +986,7 @@ static int smsc911x_poll(struct napi_struct *napi, int budget) | |||
984 | /* We processed all packets available. Tell NAPI it can | 986 | /* We processed all packets available. Tell NAPI it can |
985 | * stop polling then re-enable rx interrupts */ | 987 | * stop polling then re-enable rx interrupts */ |
986 | smsc911x_reg_write(pdata, INT_STS, INT_STS_RSFL_); | 988 | smsc911x_reg_write(pdata, INT_STS, INT_STS_RSFL_); |
987 | netif_rx_complete(napi); | 989 | napi_complete(napi); |
988 | temp = smsc911x_reg_read(pdata, INT_EN); | 990 | temp = smsc911x_reg_read(pdata, INT_EN); |
989 | temp |= INT_EN_RSFL_EN_; | 991 | temp |= INT_EN_RSFL_EN_; |
990 | smsc911x_reg_write(pdata, INT_EN, temp); | 992 | smsc911x_reg_write(pdata, INT_EN, temp); |
@@ -1246,7 +1248,7 @@ static int smsc911x_open(struct net_device *dev) | |||
1246 | napi_enable(&pdata->napi); | 1248 | napi_enable(&pdata->napi); |
1247 | 1249 | ||
1248 | temp = smsc911x_reg_read(pdata, INT_EN); | 1250 | temp = smsc911x_reg_read(pdata, INT_EN); |
1249 | temp |= (INT_EN_TDFA_EN_ | INT_EN_RSFL_EN_); | 1251 | temp |= (INT_EN_TDFA_EN_ | INT_EN_RSFL_EN_ | INT_EN_RXSTOP_INT_EN_); |
1250 | smsc911x_reg_write(pdata, INT_EN, temp); | 1252 | smsc911x_reg_write(pdata, INT_EN, temp); |
1251 | 1253 | ||
1252 | spin_lock_irq(&pdata->mac_lock); | 1254 | spin_lock_irq(&pdata->mac_lock); |
@@ -1418,11 +1420,6 @@ static void smsc911x_set_multicast_list(struct net_device *dev) | |||
1418 | 1420 | ||
1419 | /* Request the hardware to stop, then perform the | 1421 | /* Request the hardware to stop, then perform the |
1420 | * update when we get an RX_STOP interrupt */ | 1422 | * update when we get an RX_STOP interrupt */ |
1421 | smsc911x_reg_write(pdata, INT_STS, INT_STS_RXSTOP_INT_); | ||
1422 | temp = smsc911x_reg_read(pdata, INT_EN); | ||
1423 | temp |= INT_EN_RXSTOP_INT_EN_; | ||
1424 | smsc911x_reg_write(pdata, INT_EN, temp); | ||
1425 | |||
1426 | temp = smsc911x_mac_read(pdata, MAC_CR); | 1423 | temp = smsc911x_mac_read(pdata, MAC_CR); |
1427 | temp &= ~(MAC_CR_RXEN_); | 1424 | temp &= ~(MAC_CR_RXEN_); |
1428 | smsc911x_mac_write(pdata, MAC_CR, temp); | 1425 | smsc911x_mac_write(pdata, MAC_CR, temp); |
@@ -1461,11 +1458,9 @@ static irqreturn_t smsc911x_irqhandler(int irq, void *dev_id) | |||
1461 | /* Called when there is a multicast update scheduled and | 1458 | /* Called when there is a multicast update scheduled and |
1462 | * it is now safe to complete the update */ | 1459 | * it is now safe to complete the update */ |
1463 | SMSC_TRACE(INTR, "RX Stop interrupt"); | 1460 | SMSC_TRACE(INTR, "RX Stop interrupt"); |
1464 | temp = smsc911x_reg_read(pdata, INT_EN); | ||
1465 | temp &= (~INT_EN_RXSTOP_INT_EN_); | ||
1466 | smsc911x_reg_write(pdata, INT_EN, temp); | ||
1467 | smsc911x_reg_write(pdata, INT_STS, INT_STS_RXSTOP_INT_); | 1461 | smsc911x_reg_write(pdata, INT_STS, INT_STS_RXSTOP_INT_); |
1468 | smsc911x_rx_multicast_update_workaround(pdata); | 1462 | if (pdata->multicast_update_pending) |
1463 | smsc911x_rx_multicast_update_workaround(pdata); | ||
1469 | serviced = IRQ_HANDLED; | 1464 | serviced = IRQ_HANDLED; |
1470 | } | 1465 | } |
1471 | 1466 | ||
@@ -1485,16 +1480,16 @@ static irqreturn_t smsc911x_irqhandler(int irq, void *dev_id) | |||
1485 | } | 1480 | } |
1486 | 1481 | ||
1487 | if (likely(intsts & inten & INT_STS_RSFL_)) { | 1482 | if (likely(intsts & inten & INT_STS_RSFL_)) { |
1488 | if (likely(netif_rx_schedule_prep(&pdata->napi))) { | 1483 | if (likely(napi_schedule_prep(&pdata->napi))) { |
1489 | /* Disable Rx interrupts */ | 1484 | /* Disable Rx interrupts */ |
1490 | temp = smsc911x_reg_read(pdata, INT_EN); | 1485 | temp = smsc911x_reg_read(pdata, INT_EN); |
1491 | temp &= (~INT_EN_RSFL_EN_); | 1486 | temp &= (~INT_EN_RSFL_EN_); |
1492 | smsc911x_reg_write(pdata, INT_EN, temp); | 1487 | smsc911x_reg_write(pdata, INT_EN, temp); |
1493 | /* Schedule a NAPI poll */ | 1488 | /* Schedule a NAPI poll */ |
1494 | __netif_rx_schedule(&pdata->napi); | 1489 | __napi_schedule(&pdata->napi); |
1495 | } else { | 1490 | } else { |
1496 | SMSC_WARNING(RX_ERR, | 1491 | SMSC_WARNING(RX_ERR, |
1497 | "netif_rx_schedule_prep failed"); | 1492 | "napi_schedule_prep failed"); |
1498 | } | 1493 | } |
1499 | serviced = IRQ_HANDLED; | 1494 | serviced = IRQ_HANDLED; |
1500 | } | 1495 | } |
@@ -1545,7 +1540,7 @@ static void smsc911x_ethtool_getdrvinfo(struct net_device *dev, | |||
1545 | { | 1540 | { |
1546 | strlcpy(info->driver, SMSC_CHIPNAME, sizeof(info->driver)); | 1541 | strlcpy(info->driver, SMSC_CHIPNAME, sizeof(info->driver)); |
1547 | strlcpy(info->version, SMSC_DRV_VERSION, sizeof(info->version)); | 1542 | strlcpy(info->version, SMSC_DRV_VERSION, sizeof(info->version)); |
1548 | strlcpy(info->bus_info, dev->dev.parent->bus_id, | 1543 | strlcpy(info->bus_info, dev_name(dev->dev.parent), |
1549 | sizeof(info->bus_info)); | 1544 | sizeof(info->bus_info)); |
1550 | } | 1545 | } |
1551 | 1546 | ||
@@ -1747,6 +1742,21 @@ static const struct net_device_ops smsc911x_netdev_ops = { | |||
1747 | #endif | 1742 | #endif |
1748 | }; | 1743 | }; |
1749 | 1744 | ||
1745 | /* copies the current mac address from hardware to dev->dev_addr */ | ||
1746 | static void __devinit smsc911x_read_mac_address(struct net_device *dev) | ||
1747 | { | ||
1748 | struct smsc911x_data *pdata = netdev_priv(dev); | ||
1749 | u32 mac_high16 = smsc911x_mac_read(pdata, ADDRH); | ||
1750 | u32 mac_low32 = smsc911x_mac_read(pdata, ADDRL); | ||
1751 | |||
1752 | dev->dev_addr[0] = (u8)(mac_low32); | ||
1753 | dev->dev_addr[1] = (u8)(mac_low32 >> 8); | ||
1754 | dev->dev_addr[2] = (u8)(mac_low32 >> 16); | ||
1755 | dev->dev_addr[3] = (u8)(mac_low32 >> 24); | ||
1756 | dev->dev_addr[4] = (u8)(mac_high16); | ||
1757 | dev->dev_addr[5] = (u8)(mac_high16 >> 8); | ||
1758 | } | ||
1759 | |||
1750 | /* Initializing private device structures, only called from probe */ | 1760 | /* Initializing private device structures, only called from probe */ |
1751 | static int __devinit smsc911x_init(struct net_device *dev) | 1761 | static int __devinit smsc911x_init(struct net_device *dev) |
1752 | { | 1762 | { |
@@ -1834,6 +1844,12 @@ static int __devinit smsc911x_init(struct net_device *dev) | |||
1834 | SMSC_WARNING(PROBE, | 1844 | SMSC_WARNING(PROBE, |
1835 | "This driver is not intended for this chip revision"); | 1845 | "This driver is not intended for this chip revision"); |
1836 | 1846 | ||
1847 | /* workaround for platforms without an eeprom, where the mac address | ||
1848 | * is stored elsewhere and set by the bootloader. This saves the | ||
1849 | * mac address before resetting the device */ | ||
1850 | if (pdata->config.flags & SMSC911X_SAVE_MAC_ADDRESS) | ||
1851 | smsc911x_read_mac_address(dev); | ||
1852 | |||
1837 | /* Reset the LAN911x */ | 1853 | /* Reset the LAN911x */ |
1838 | if (smsc911x_soft_reset(pdata)) | 1854 | if (smsc911x_soft_reset(pdata)) |
1839 | return -ENODEV; | 1855 | return -ENODEV; |
@@ -1892,9 +1908,9 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) | |||
1892 | struct net_device *dev; | 1908 | struct net_device *dev; |
1893 | struct smsc911x_data *pdata; | 1909 | struct smsc911x_data *pdata; |
1894 | struct smsc911x_platform_config *config = pdev->dev.platform_data; | 1910 | struct smsc911x_platform_config *config = pdev->dev.platform_data; |
1895 | struct resource *res; | 1911 | struct resource *res, *irq_res; |
1896 | unsigned int intcfg = 0; | 1912 | unsigned int intcfg = 0; |
1897 | int res_size; | 1913 | int res_size, irq_flags; |
1898 | int retval; | 1914 | int retval; |
1899 | DECLARE_MAC_BUF(mac); | 1915 | DECLARE_MAC_BUF(mac); |
1900 | 1916 | ||
@@ -1919,6 +1935,14 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) | |||
1919 | } | 1935 | } |
1920 | res_size = res->end - res->start; | 1936 | res_size = res->end - res->start; |
1921 | 1937 | ||
1938 | irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
1939 | if (!irq_res) { | ||
1940 | pr_warning("%s: Could not allocate irq resource.\n", | ||
1941 | SMSC_CHIPNAME); | ||
1942 | retval = -ENODEV; | ||
1943 | goto out_0; | ||
1944 | } | ||
1945 | |||
1922 | if (!request_mem_region(res->start, res_size, SMSC_CHIPNAME)) { | 1946 | if (!request_mem_region(res->start, res_size, SMSC_CHIPNAME)) { |
1923 | retval = -EBUSY; | 1947 | retval = -EBUSY; |
1924 | goto out_0; | 1948 | goto out_0; |
@@ -1935,7 +1959,8 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) | |||
1935 | 1959 | ||
1936 | pdata = netdev_priv(dev); | 1960 | pdata = netdev_priv(dev); |
1937 | 1961 | ||
1938 | dev->irq = platform_get_irq(pdev, 0); | 1962 | dev->irq = irq_res->start; |
1963 | irq_flags = irq_res->flags & IRQF_TRIGGER_MASK; | ||
1939 | pdata->ioaddr = ioremap_nocache(res->start, res_size); | 1964 | pdata->ioaddr = ioremap_nocache(res->start, res_size); |
1940 | 1965 | ||
1941 | /* copy config parameters across to pdata */ | 1966 | /* copy config parameters across to pdata */ |
@@ -1968,8 +1993,8 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) | |||
1968 | smsc911x_reg_write(pdata, INT_EN, 0); | 1993 | smsc911x_reg_write(pdata, INT_EN, 0); |
1969 | smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF); | 1994 | smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF); |
1970 | 1995 | ||
1971 | retval = request_irq(dev->irq, smsc911x_irqhandler, IRQF_DISABLED, | 1996 | retval = request_irq(dev->irq, smsc911x_irqhandler, |
1972 | dev->name, dev); | 1997 | irq_flags | IRQF_SHARED, dev->name, dev); |
1973 | if (retval) { | 1998 | if (retval) { |
1974 | SMSC_WARNING(PROBE, | 1999 | SMSC_WARNING(PROBE, |
1975 | "Unable to claim requested irq: %d", dev->irq); | 2000 | "Unable to claim requested irq: %d", dev->irq); |
@@ -2005,14 +2030,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) | |||
2005 | } else { | 2030 | } else { |
2006 | /* Try reading mac address from device. if EEPROM is present | 2031 | /* Try reading mac address from device. if EEPROM is present |
2007 | * it will already have been set */ | 2032 | * it will already have been set */ |
2008 | u32 mac_high16 = smsc911x_mac_read(pdata, ADDRH); | 2033 | smsc911x_read_mac_address(dev); |
2009 | u32 mac_low32 = smsc911x_mac_read(pdata, ADDRL); | ||
2010 | dev->dev_addr[0] = (u8)(mac_low32); | ||
2011 | dev->dev_addr[1] = (u8)(mac_low32 >> 8); | ||
2012 | dev->dev_addr[2] = (u8)(mac_low32 >> 16); | ||
2013 | dev->dev_addr[3] = (u8)(mac_low32 >> 24); | ||
2014 | dev->dev_addr[4] = (u8)(mac_high16); | ||
2015 | dev->dev_addr[5] = (u8)(mac_high16 >> 8); | ||
2016 | 2034 | ||
2017 | if (is_valid_ether_addr(dev->dev_addr)) { | 2035 | if (is_valid_ether_addr(dev->dev_addr)) { |
2018 | /* eeprom values are valid so use them */ | 2036 | /* eeprom values are valid so use them */ |