aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/smsc/smsc911x.c111
1 files changed, 100 insertions, 11 deletions
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index 8843071fe987..06d0df61bee6 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -44,6 +44,7 @@
44#include <linux/module.h> 44#include <linux/module.h>
45#include <linux/netdevice.h> 45#include <linux/netdevice.h>
46#include <linux/platform_device.h> 46#include <linux/platform_device.h>
47#include <linux/regulator/consumer.h>
47#include <linux/sched.h> 48#include <linux/sched.h>
48#include <linux/timer.h> 49#include <linux/timer.h>
49#include <linux/bug.h> 50#include <linux/bug.h>
@@ -88,6 +89,8 @@ struct smsc911x_ops {
88 unsigned int *buf, unsigned int wordcount); 89 unsigned int *buf, unsigned int wordcount);
89}; 90};
90 91
92#define SMSC911X_NUM_SUPPLIES 2
93
91struct smsc911x_data { 94struct smsc911x_data {
92 void __iomem *ioaddr; 95 void __iomem *ioaddr;
93 96
@@ -138,6 +141,9 @@ struct smsc911x_data {
138 141
139 /* register access functions */ 142 /* register access functions */
140 const struct smsc911x_ops *ops; 143 const struct smsc911x_ops *ops;
144
145 /* regulators */
146 struct regulator_bulk_data supplies[SMSC911X_NUM_SUPPLIES];
141}; 147};
142 148
143/* Easy access to information */ 149/* Easy access to information */
@@ -362,6 +368,76 @@ out:
362 spin_unlock_irqrestore(&pdata->dev_lock, flags); 368 spin_unlock_irqrestore(&pdata->dev_lock, flags);
363} 369}
364 370
371/*
372 * enable resources, currently just regulators.
373 */
374static int smsc911x_enable_resources(struct platform_device *pdev)
375{
376 struct net_device *ndev = platform_get_drvdata(pdev);
377 struct smsc911x_data *pdata = netdev_priv(ndev);
378 int ret = 0;
379
380 ret = regulator_bulk_enable(ARRAY_SIZE(pdata->supplies),
381 pdata->supplies);
382 if (ret)
383 netdev_err(ndev, "failed to enable regulators %d\n",
384 ret);
385 return ret;
386}
387
388/*
389 * disable resources, currently just regulators.
390 */
391static int smsc911x_disable_resources(struct platform_device *pdev)
392{
393 struct net_device *ndev = platform_get_drvdata(pdev);
394 struct smsc911x_data *pdata = netdev_priv(ndev);
395 int ret = 0;
396
397 ret = regulator_bulk_disable(ARRAY_SIZE(pdata->supplies),
398 pdata->supplies);
399 return ret;
400}
401
402/*
403 * Request resources, currently just regulators.
404 *
405 * The SMSC911x has two power pins: vddvario and vdd33a, in designs where
406 * these are not always-on we need to request regulators to be turned on
407 * before we can try to access the device registers.
408 */
409static int smsc911x_request_resources(struct platform_device *pdev)
410{
411 struct net_device *ndev = platform_get_drvdata(pdev);
412 struct smsc911x_data *pdata = netdev_priv(ndev);
413 int ret = 0;
414
415 /* Request regulators */
416 pdata->supplies[0].supply = "vdd33a";
417 pdata->supplies[1].supply = "vddvario";
418 ret = regulator_bulk_get(&pdev->dev,
419 ARRAY_SIZE(pdata->supplies),
420 pdata->supplies);
421 if (ret)
422 netdev_err(ndev, "couldn't get regulators %d\n",
423 ret);
424 return ret;
425}
426
427/*
428 * Free resources, currently just regulators.
429 *
430 */
431static void smsc911x_free_resources(struct platform_device *pdev)
432{
433 struct net_device *ndev = platform_get_drvdata(pdev);
434 struct smsc911x_data *pdata = netdev_priv(ndev);
435
436 /* Free regulators */
437 regulator_bulk_free(ARRAY_SIZE(pdata->supplies),
438 pdata->supplies);
439}
440
365/* waits for MAC not busy, with timeout. Only called by smsc911x_mac_read 441/* waits for MAC not busy, with timeout. Only called by smsc911x_mac_read
366 * and smsc911x_mac_write, so assumes mac_lock is held */ 442 * and smsc911x_mac_write, so assumes mac_lock is held */
367static int smsc911x_mac_complete(struct smsc911x_data *pdata) 443static int smsc911x_mac_complete(struct smsc911x_data *pdata)
@@ -2092,6 +2168,9 @@ static int __devexit smsc911x_drv_remove(struct platform_device *pdev)
2092 2168
2093 iounmap(pdata->ioaddr); 2169 iounmap(pdata->ioaddr);
2094 2170
2171 (void)smsc911x_disable_resources(pdev);
2172 smsc911x_free_resources(pdev);
2173
2095 free_netdev(dev); 2174 free_netdev(dev);
2096 2175
2097 return 0; 2176 return 0;
@@ -2218,10 +2297,20 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
2218 pdata->dev = dev; 2297 pdata->dev = dev;
2219 pdata->msg_enable = ((1 << debug) - 1); 2298 pdata->msg_enable = ((1 << debug) - 1);
2220 2299
2300 platform_set_drvdata(pdev, dev);
2301
2302 retval = smsc911x_request_resources(pdev);
2303 if (retval)
2304 goto out_return_resources;
2305
2306 retval = smsc911x_enable_resources(pdev);
2307 if (retval)
2308 goto out_disable_resources;
2309
2221 if (pdata->ioaddr == NULL) { 2310 if (pdata->ioaddr == NULL) {
2222 SMSC_WARN(pdata, probe, "Error smsc911x base address invalid"); 2311 SMSC_WARN(pdata, probe, "Error smsc911x base address invalid");
2223 retval = -ENOMEM; 2312 retval = -ENOMEM;
2224 goto out_free_netdev_2; 2313 goto out_disable_resources;
2225 } 2314 }
2226 2315
2227 retval = smsc911x_probe_config_dt(&pdata->config, np); 2316 retval = smsc911x_probe_config_dt(&pdata->config, np);
@@ -2233,7 +2322,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
2233 2322
2234 if (retval) { 2323 if (retval) {
2235 SMSC_WARN(pdata, probe, "Error smsc911x config not found"); 2324 SMSC_WARN(pdata, probe, "Error smsc911x config not found");
2236 goto out_unmap_io_3; 2325 goto out_disable_resources;
2237 } 2326 }
2238 2327
2239 /* assume standard, non-shifted, access to HW registers */ 2328 /* assume standard, non-shifted, access to HW registers */
@@ -2244,7 +2333,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
2244 2333
2245 retval = smsc911x_init(dev); 2334 retval = smsc911x_init(dev);
2246 if (retval < 0) 2335 if (retval < 0)
2247 goto out_unmap_io_3; 2336 goto out_disable_resources;
2248 2337
2249 /* configure irq polarity and type before connecting isr */ 2338 /* configure irq polarity and type before connecting isr */
2250 if (pdata->config.irq_polarity == SMSC911X_IRQ_POLARITY_ACTIVE_HIGH) 2339 if (pdata->config.irq_polarity == SMSC911X_IRQ_POLARITY_ACTIVE_HIGH)
@@ -2264,15 +2353,13 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
2264 if (retval) { 2353 if (retval) {
2265 SMSC_WARN(pdata, probe, 2354 SMSC_WARN(pdata, probe,
2266 "Unable to claim requested irq: %d", dev->irq); 2355 "Unable to claim requested irq: %d", dev->irq);
2267 goto out_unmap_io_3; 2356 goto out_free_irq;
2268 } 2357 }
2269 2358
2270 platform_set_drvdata(pdev, dev);
2271
2272 retval = register_netdev(dev); 2359 retval = register_netdev(dev);
2273 if (retval) { 2360 if (retval) {
2274 SMSC_WARN(pdata, probe, "Error %i registering device", retval); 2361 SMSC_WARN(pdata, probe, "Error %i registering device", retval);
2275 goto out_unset_drvdata_4; 2362 goto out_free_irq;
2276 } else { 2363 } else {
2277 SMSC_TRACE(pdata, probe, 2364 SMSC_TRACE(pdata, probe,
2278 "Network interface: \"%s\"", dev->name); 2365 "Network interface: \"%s\"", dev->name);
@@ -2321,12 +2408,14 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
2321 2408
2322out_unregister_netdev_5: 2409out_unregister_netdev_5:
2323 unregister_netdev(dev); 2410 unregister_netdev(dev);
2324out_unset_drvdata_4: 2411out_free_irq:
2325 platform_set_drvdata(pdev, NULL);
2326 free_irq(dev->irq, dev); 2412 free_irq(dev->irq, dev);
2327out_unmap_io_3: 2413out_disable_resources:
2414 (void)smsc911x_disable_resources(pdev);
2415out_return_resources:
2416 smsc911x_free_resources(pdev);
2417 platform_set_drvdata(pdev, NULL);
2328 iounmap(pdata->ioaddr); 2418 iounmap(pdata->ioaddr);
2329out_free_netdev_2:
2330 free_netdev(dev); 2419 free_netdev(dev);
2331out_release_io_1: 2420out_release_io_1:
2332 release_mem_region(res->start, resource_size(res)); 2421 release_mem_region(res->start, resource_size(res));