aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/smsc/smsc911x.c
diff options
context:
space:
mode:
authorRobert Marklund <robert.marklund@stericsson.com>2011-11-23 20:03:07 -0500
committerDavid S. Miller <davem@davemloft.net>2011-11-29 18:36:56 -0500
commitc7e963f6888816f04d1f5da0e07bec4e0092f227 (patch)
tree5eb1267457573a711b98928f04fcb73c49b123e9 /drivers/net/ethernet/smsc/smsc911x.c
parent1839a6c6f1eb8c0e20dc87d57024a85707f1a2f8 (diff)
net/smsc911x: Add regulator support
Add some basic regulator support for the power pins, as needed by the ST-Ericsson Snowball platform that powers up the SMSC911 chip using an external regulator. Platforms that use regulators and the smsc911x and have no defined regulator for the smsc911x and claim complete regulator constraints with no dummy regulators will need to provide it, for example using a fixed voltage regulator. It appears that this may affect (apart from Ux500 Snowball) possibly these archs/machines that from some grep:s appear to define both CONFIG_SMSC911X and CONFIG_REGULATOR: - ARM Freescale mx3 and OMAP 2 plus, Raumfeld machines - Blackfin - Super-H Cc: Paul Mundt <lethal@linux-sh.org> Cc: linux-sh@vger.kernel.org Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Tony Lindgren <tony@atomide.com> Cc: linux-omap@vger.kernel.org Cc: Mike Frysinger <vapier@gentoo.org> Cc: uclinux-dist-devel@blackfin.uclinux.org Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Robert Marklund <robert.marklund@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/smsc/smsc911x.c')
-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));