diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index cd3defb11ff..70c678cccaf 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -954,7 +955,7 @@ static void smsc911x_phy_adjust_link(struct net_device *dev) (!pdata->using_extphy)) { /* Restore original GPIO configuration */ pdata->gpio_setting = pdata->gpio_orig_setting; - smsc911x_reg_write(pdata, GPIO_CFG, + smsc911x_reg_write(pdata, SMSC_GPIO_CFG, pdata->gpio_setting); } } else { @@ -962,7 +963,7 @@ static void smsc911x_phy_adjust_link(struct net_device *dev) /* Check global setting that LED1 * usage is 10/100 indicator */ pdata->gpio_setting = smsc911x_reg_read(pdata, - GPIO_CFG); + SMSC_GPIO_CFG); if ((pdata->gpio_setting & GPIO_CFG_LED1_EN_) && (!pdata->using_extphy)) { /* Force 10/100 LED off, after saving @@ -973,7 +974,7 @@ static void smsc911x_phy_adjust_link(struct net_device *dev) pdata->gpio_setting |= (GPIO_CFG_GPIOBUF0_ | GPIO_CFG_GPIODIR0_ | GPIO_CFG_GPIOD0_); - smsc911x_reg_write(pdata, GPIO_CFG, + smsc911x_reg_write(pdata, SMSC_GPIO_CFG, pdata->gpio_setting); } } @@ -1485,7 +1486,7 @@ static int smsc911x_open(struct net_device *dev) SMSC_WARN(pdata, ifup, "Timed out waiting for EEPROM busy bit to clear"); - smsc911x_reg_write(pdata, GPIO_CFG, 0x70070000); + smsc911x_reg_write(pdata, SMSC_GPIO_CFG, 0x70070000); /* The soft reset above cleared the device's MAC address, * restore it from local copy (set in probe) */ @@ -1931,9 +1932,9 @@ smsc911x_ethtool_getregs(struct net_device *dev, struct ethtool_regs *regs, static void smsc911x_eeprom_enable_access(struct smsc911x_data *pdata) { - unsigned int temp = smsc911x_reg_read(pdata, GPIO_CFG); + unsigned int temp = smsc911x_reg_read(pdata, SMSC_GPIO_CFG); temp &= ~GPIO_CFG_EEPR_EN_; - smsc911x_reg_write(pdata, GPIO_CFG, temp); + smsc911x_reg_write(pdata, SMSC_GPIO_CFG, temp); msleep(1); } @@ -2241,6 +2242,12 @@ static int __devexit smsc911x_drv_remove(struct platform_device *pdev) SMSC_TRACE(pdata, ifdown, "Stopping driver"); + if (pdata->config.has_reset_gpio) { + gpio_set_value_cansleep(pdata->config.reset_gpio, 0); + gpio_free(pdata->config.reset_gpio); + } + + phy_disconnect(pdata->phy_dev); pdata->phy_dev = NULL; mdiobus_unregister(pdata->mii_bus); @@ -2528,6 +2535,10 @@ static int smsc911x_suspend(struct device *dev) PMT_CTRL_PM_MODE_D1_ | PMT_CTRL_WOL_EN_ | PMT_CTRL_ED_EN_ | PMT_CTRL_PME_EN_); + /* Drive the GPIO Ethernet_Reset Line low to Suspend */ + if (pdata->config.has_reset_gpio) + gpio_set_value_cansleep(pdata->config.reset_gpio, 0); + return 0; } @@ -2537,6 +2548,10 @@ static int smsc911x_resume(struct device *dev) struct smsc911x_data *pdata = netdev_priv(ndev); unsigned int to = 100; + if (pdata->config.has_reset_gpio) + gpio_set_value_cansleep(pdata->config.reset_gpio, 1); + + /* Note 3.11 from the datasheet: * "When the LAN9220 is in a power saving state, a write of any * data to the BYTE_TEST register will wake-up the device." diff --git a/drivers/net/ethernet/smsc/smsc911x.h b/drivers/net/ethernet/smsc/smsc911x.h index 9ad5e5d39a0..43e53980de4 100644 --- a/drivers/net/ethernet/smsc/smsc911x.h +++ b/drivers/net/ethernet/smsc/smsc911x.h @@ -236,7 +236,7 @@ #define PMT_CTRL_PME_EN_ 0x00000002 #define PMT_CTRL_READY_ 0x00000001 -#define GPIO_CFG 0x88 +#define SMSC_GPIO_CFG 0x88 #define GPIO_CFG_LED3_EN_ 0x40000000 #define GPIO_CFG_LED2_EN_ 0x20000000 #define GPIO_CFG_LED1_EN_ 0x10000000 diff --git a/include/linux/smsc911x.h b/include/linux/smsc911x.h index 4dde70e7482..0493fbdf776 100644 --- a/include/linux/smsc911x.h +++ b/include/linux/smsc911x.h @@ -24,7 +24,14 @@ #include /* platform_device configuration data, should be assigned to - * the platform_device's dev.platform_data */ + * the platform_device's dev.platform_data + * Provides 2 GPIO-related fields + * reset_gpio to map the ETHERNET_RESET GPIO pin + * has_reset_gpio - to indicate if the GPIO is being set(1) or not(0) + * and remain compatible with architectures not using GPIOs + * Default would be zero if its not being assigned any value. + * Both values would need to set in the appropriate board file + */ struct smsc911x_platform_config { unsigned int irq_polarity; unsigned int irq_type; @@ -32,6 +39,8 @@ struct smsc911x_platform_config { unsigned int shift; phy_interface_t phy_interface; unsigned char mac[6]; + unsigned char has_reset_gpio; + unsigned int reset_gpio; }; /* Constants for platform_device irq polarity configuration */