diff options
Diffstat (limited to 'drivers/net/ethernet/smsc')
-rw-r--r-- | drivers/net/ethernet/smsc/smc91x.c | 78 | ||||
-rw-r--r-- | drivers/net/ethernet/smsc/smc91x.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/smsc/smsc911x.c | 61 |
3 files changed, 123 insertions, 19 deletions
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index 5e94d00b96b3..6cc3cf6f17c8 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c | |||
@@ -81,6 +81,7 @@ static const char version[] = | |||
81 | #include <linux/workqueue.h> | 81 | #include <linux/workqueue.h> |
82 | #include <linux/of.h> | 82 | #include <linux/of.h> |
83 | #include <linux/of_device.h> | 83 | #include <linux/of_device.h> |
84 | #include <linux/of_gpio.h> | ||
84 | 85 | ||
85 | #include <linux/netdevice.h> | 86 | #include <linux/netdevice.h> |
86 | #include <linux/etherdevice.h> | 87 | #include <linux/etherdevice.h> |
@@ -2188,6 +2189,41 @@ static const struct of_device_id smc91x_match[] = { | |||
2188 | {}, | 2189 | {}, |
2189 | }; | 2190 | }; |
2190 | MODULE_DEVICE_TABLE(of, smc91x_match); | 2191 | MODULE_DEVICE_TABLE(of, smc91x_match); |
2192 | |||
2193 | /** | ||
2194 | * of_try_set_control_gpio - configure a gpio if it exists | ||
2195 | */ | ||
2196 | static int try_toggle_control_gpio(struct device *dev, | ||
2197 | struct gpio_desc **desc, | ||
2198 | const char *name, int index, | ||
2199 | int value, unsigned int nsdelay) | ||
2200 | { | ||
2201 | struct gpio_desc *gpio = *desc; | ||
2202 | int res; | ||
2203 | |||
2204 | gpio = devm_gpiod_get_index(dev, name, index); | ||
2205 | if (IS_ERR(gpio)) { | ||
2206 | if (PTR_ERR(gpio) == -ENOENT) { | ||
2207 | *desc = NULL; | ||
2208 | return 0; | ||
2209 | } | ||
2210 | |||
2211 | return PTR_ERR(gpio); | ||
2212 | } | ||
2213 | res = gpiod_direction_output(gpio, !value); | ||
2214 | if (res) { | ||
2215 | dev_err(dev, "unable to toggle gpio %s: %i\n", name, res); | ||
2216 | devm_gpiod_put(dev, gpio); | ||
2217 | gpio = NULL; | ||
2218 | return res; | ||
2219 | } | ||
2220 | if (nsdelay) | ||
2221 | usleep_range(nsdelay, 2 * nsdelay); | ||
2222 | gpiod_set_value_cansleep(gpio, value); | ||
2223 | *desc = gpio; | ||
2224 | |||
2225 | return 0; | ||
2226 | } | ||
2191 | #endif | 2227 | #endif |
2192 | 2228 | ||
2193 | /* | 2229 | /* |
@@ -2207,9 +2243,10 @@ static int smc_drv_probe(struct platform_device *pdev) | |||
2207 | const struct of_device_id *match = NULL; | 2243 | const struct of_device_id *match = NULL; |
2208 | struct smc_local *lp; | 2244 | struct smc_local *lp; |
2209 | struct net_device *ndev; | 2245 | struct net_device *ndev; |
2210 | struct resource *res, *ires; | 2246 | struct resource *res; |
2211 | unsigned int __iomem *addr; | 2247 | unsigned int __iomem *addr; |
2212 | unsigned long irq_flags = SMC_IRQ_FLAGS; | 2248 | unsigned long irq_flags = SMC_IRQ_FLAGS; |
2249 | unsigned long irq_resflags; | ||
2213 | int ret; | 2250 | int ret; |
2214 | 2251 | ||
2215 | ndev = alloc_etherdev(sizeof(struct smc_local)); | 2252 | ndev = alloc_etherdev(sizeof(struct smc_local)); |
@@ -2237,6 +2274,28 @@ static int smc_drv_probe(struct platform_device *pdev) | |||
2237 | struct device_node *np = pdev->dev.of_node; | 2274 | struct device_node *np = pdev->dev.of_node; |
2238 | u32 val; | 2275 | u32 val; |
2239 | 2276 | ||
2277 | /* Optional pwrdwn GPIO configured? */ | ||
2278 | ret = try_toggle_control_gpio(&pdev->dev, &lp->power_gpio, | ||
2279 | "power", 0, 0, 100); | ||
2280 | if (ret) | ||
2281 | return ret; | ||
2282 | |||
2283 | /* | ||
2284 | * Optional reset GPIO configured? Minimum 100 ns reset needed | ||
2285 | * according to LAN91C96 datasheet page 14. | ||
2286 | */ | ||
2287 | ret = try_toggle_control_gpio(&pdev->dev, &lp->reset_gpio, | ||
2288 | "reset", 0, 0, 100); | ||
2289 | if (ret) | ||
2290 | return ret; | ||
2291 | |||
2292 | /* | ||
2293 | * Need to wait for optional EEPROM to load, max 750 us according | ||
2294 | * to LAN91C96 datasheet page 55. | ||
2295 | */ | ||
2296 | if (lp->reset_gpio) | ||
2297 | usleep_range(750, 1000); | ||
2298 | |||
2240 | /* Combination of IO widths supported, default to 16-bit */ | 2299 | /* Combination of IO widths supported, default to 16-bit */ |
2241 | if (!of_property_read_u32(np, "reg-io-width", &val)) { | 2300 | if (!of_property_read_u32(np, "reg-io-width", &val)) { |
2242 | if (val & 1) | 2301 | if (val & 1) |
@@ -2279,16 +2338,19 @@ static int smc_drv_probe(struct platform_device *pdev) | |||
2279 | goto out_free_netdev; | 2338 | goto out_free_netdev; |
2280 | } | 2339 | } |
2281 | 2340 | ||
2282 | ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 2341 | ndev->irq = platform_get_irq(pdev, 0); |
2283 | if (!ires) { | 2342 | if (ndev->irq <= 0) { |
2284 | ret = -ENODEV; | 2343 | ret = -ENODEV; |
2285 | goto out_release_io; | 2344 | goto out_release_io; |
2286 | } | 2345 | } |
2287 | 2346 | /* | |
2288 | ndev->irq = ires->start; | 2347 | * If this platform does not specify any special irqflags, or if |
2289 | 2348 | * the resource supplies a trigger, override the irqflags with | |
2290 | if (irq_flags == -1 || ires->flags & IRQF_TRIGGER_MASK) | 2349 | * the trigger flags from the resource. |
2291 | irq_flags = ires->flags & IRQF_TRIGGER_MASK; | 2350 | */ |
2351 | irq_resflags = irqd_get_trigger_type(irq_get_irq_data(ndev->irq)); | ||
2352 | if (irq_flags == -1 || irq_resflags & IRQF_TRIGGER_MASK) | ||
2353 | irq_flags = irq_resflags & IRQF_TRIGGER_MASK; | ||
2292 | 2354 | ||
2293 | ret = smc_request_attrib(pdev, ndev); | 2355 | ret = smc_request_attrib(pdev, ndev); |
2294 | if (ret) | 2356 | if (ret) |
diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h index 47dce918eb0f..2a38dacbbd27 100644 --- a/drivers/net/ethernet/smsc/smc91x.h +++ b/drivers/net/ethernet/smsc/smc91x.h | |||
@@ -298,6 +298,9 @@ struct smc_local { | |||
298 | struct sk_buff *pending_tx_skb; | 298 | struct sk_buff *pending_tx_skb; |
299 | struct tasklet_struct tx_task; | 299 | struct tasklet_struct tx_task; |
300 | 300 | ||
301 | struct gpio_desc *power_gpio; | ||
302 | struct gpio_desc *reset_gpio; | ||
303 | |||
301 | /* version/revision of the SMC91x chip */ | 304 | /* version/revision of the SMC91x chip */ |
302 | int version; | 305 | int version; |
303 | 306 | ||
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index affb29da353e..77ed74561e5f 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c | |||
@@ -1342,6 +1342,42 @@ static void smsc911x_rx_multicast_update_workaround(struct smsc911x_data *pdata) | |||
1342 | spin_unlock(&pdata->mac_lock); | 1342 | spin_unlock(&pdata->mac_lock); |
1343 | } | 1343 | } |
1344 | 1344 | ||
1345 | static int smsc911x_phy_general_power_up(struct smsc911x_data *pdata) | ||
1346 | { | ||
1347 | int rc = 0; | ||
1348 | |||
1349 | if (!pdata->phy_dev) | ||
1350 | return rc; | ||
1351 | |||
1352 | /* If the internal PHY is in General Power-Down mode, all, except the | ||
1353 | * management interface, is powered-down and stays in that condition as | ||
1354 | * long as Phy register bit 0.11 is HIGH. | ||
1355 | * | ||
1356 | * In that case, clear the bit 0.11, so the PHY powers up and we can | ||
1357 | * access to the phy registers. | ||
1358 | */ | ||
1359 | rc = phy_read(pdata->phy_dev, MII_BMCR); | ||
1360 | if (rc < 0) { | ||
1361 | SMSC_WARN(pdata, drv, "Failed reading PHY control reg"); | ||
1362 | return rc; | ||
1363 | } | ||
1364 | |||
1365 | /* If the PHY general power-down bit is not set is not necessary to | ||
1366 | * disable the general power down-mode. | ||
1367 | */ | ||
1368 | if (rc & BMCR_PDOWN) { | ||
1369 | rc = phy_write(pdata->phy_dev, MII_BMCR, rc & ~BMCR_PDOWN); | ||
1370 | if (rc < 0) { | ||
1371 | SMSC_WARN(pdata, drv, "Failed writing PHY control reg"); | ||
1372 | return rc; | ||
1373 | } | ||
1374 | |||
1375 | usleep_range(1000, 1500); | ||
1376 | } | ||
1377 | |||
1378 | return 0; | ||
1379 | } | ||
1380 | |||
1345 | static int smsc911x_phy_disable_energy_detect(struct smsc911x_data *pdata) | 1381 | static int smsc911x_phy_disable_energy_detect(struct smsc911x_data *pdata) |
1346 | { | 1382 | { |
1347 | int rc = 0; | 1383 | int rc = 0; |
@@ -1356,12 +1392,8 @@ static int smsc911x_phy_disable_energy_detect(struct smsc911x_data *pdata) | |||
1356 | return rc; | 1392 | return rc; |
1357 | } | 1393 | } |
1358 | 1394 | ||
1359 | /* | 1395 | /* Only disable if energy detect mode is already enabled */ |
1360 | * If energy is detected the PHY is already awake so is not necessary | 1396 | if (rc & MII_LAN83C185_EDPWRDOWN) { |
1361 | * to disable the energy detect power-down mode. | ||
1362 | */ | ||
1363 | if ((rc & MII_LAN83C185_EDPWRDOWN) && | ||
1364 | !(rc & MII_LAN83C185_ENERGYON)) { | ||
1365 | /* Disable energy detect mode for this SMSC Transceivers */ | 1397 | /* Disable energy detect mode for this SMSC Transceivers */ |
1366 | rc = phy_write(pdata->phy_dev, MII_LAN83C185_CTRL_STATUS, | 1398 | rc = phy_write(pdata->phy_dev, MII_LAN83C185_CTRL_STATUS, |
1367 | rc & (~MII_LAN83C185_EDPWRDOWN)); | 1399 | rc & (~MII_LAN83C185_EDPWRDOWN)); |
@@ -1370,8 +1402,8 @@ static int smsc911x_phy_disable_energy_detect(struct smsc911x_data *pdata) | |||
1370 | SMSC_WARN(pdata, drv, "Failed writing PHY control reg"); | 1402 | SMSC_WARN(pdata, drv, "Failed writing PHY control reg"); |
1371 | return rc; | 1403 | return rc; |
1372 | } | 1404 | } |
1373 | 1405 | /* Allow PHY to wakeup */ | |
1374 | mdelay(1); | 1406 | mdelay(2); |
1375 | } | 1407 | } |
1376 | 1408 | ||
1377 | return 0; | 1409 | return 0; |
@@ -1393,7 +1425,6 @@ static int smsc911x_phy_enable_energy_detect(struct smsc911x_data *pdata) | |||
1393 | 1425 | ||
1394 | /* Only enable if energy detect mode is already disabled */ | 1426 | /* Only enable if energy detect mode is already disabled */ |
1395 | if (!(rc & MII_LAN83C185_EDPWRDOWN)) { | 1427 | if (!(rc & MII_LAN83C185_EDPWRDOWN)) { |
1396 | mdelay(100); | ||
1397 | /* Enable energy detect mode for this SMSC Transceivers */ | 1428 | /* Enable energy detect mode for this SMSC Transceivers */ |
1398 | rc = phy_write(pdata->phy_dev, MII_LAN83C185_CTRL_STATUS, | 1429 | rc = phy_write(pdata->phy_dev, MII_LAN83C185_CTRL_STATUS, |
1399 | rc | MII_LAN83C185_EDPWRDOWN); | 1430 | rc | MII_LAN83C185_EDPWRDOWN); |
@@ -1402,8 +1433,6 @@ static int smsc911x_phy_enable_energy_detect(struct smsc911x_data *pdata) | |||
1402 | SMSC_WARN(pdata, drv, "Failed writing PHY control reg"); | 1433 | SMSC_WARN(pdata, drv, "Failed writing PHY control reg"); |
1403 | return rc; | 1434 | return rc; |
1404 | } | 1435 | } |
1405 | |||
1406 | mdelay(1); | ||
1407 | } | 1436 | } |
1408 | return 0; | 1437 | return 0; |
1409 | } | 1438 | } |
@@ -1415,6 +1444,16 @@ static int smsc911x_soft_reset(struct smsc911x_data *pdata) | |||
1415 | int ret; | 1444 | int ret; |
1416 | 1445 | ||
1417 | /* | 1446 | /* |
1447 | * Make sure to power-up the PHY chip before doing a reset, otherwise | ||
1448 | * the reset fails. | ||
1449 | */ | ||
1450 | ret = smsc911x_phy_general_power_up(pdata); | ||
1451 | if (ret) { | ||
1452 | SMSC_WARN(pdata, drv, "Failed to power-up the PHY chip"); | ||
1453 | return ret; | ||
1454 | } | ||
1455 | |||
1456 | /* | ||
1418 | * LAN9210/LAN9211/LAN9220/LAN9221 chips have an internal PHY that | 1457 | * LAN9210/LAN9211/LAN9220/LAN9221 chips have an internal PHY that |
1419 | * are initialized in a Energy Detect Power-Down mode that prevents | 1458 | * are initialized in a Energy Detect Power-Down mode that prevents |
1420 | * the MAC chip to be software reseted. So we have to wakeup the PHY | 1459 | * the MAC chip to be software reseted. So we have to wakeup the PHY |