#include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/bug.h>
                                unsigned int *buf, unsigned int wordcount);
 };
 
+#define SMSC911X_NUM_SUPPLIES 2
+
 struct smsc911x_data {
        void __iomem *ioaddr;
 
 
        /* register access functions */
        const struct smsc911x_ops *ops;
+
+       /* regulators */
+       struct regulator_bulk_data supplies[SMSC911X_NUM_SUPPLIES];
 };
 
 /* Easy access to information */
        spin_unlock_irqrestore(&pdata->dev_lock, flags);
 }
 
+/*
+ * enable resources, currently just regulators.
+ */
+static int smsc911x_enable_resources(struct platform_device *pdev)
+{
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct smsc911x_data *pdata = netdev_priv(ndev);
+       int ret = 0;
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(pdata->supplies),
+                       pdata->supplies);
+       if (ret)
+               netdev_err(ndev, "failed to enable regulators %d\n",
+                               ret);
+       return ret;
+}
+
+/*
+ * disable resources, currently just regulators.
+ */
+static int smsc911x_disable_resources(struct platform_device *pdev)
+{
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct smsc911x_data *pdata = netdev_priv(ndev);
+       int ret = 0;
+
+       ret = regulator_bulk_disable(ARRAY_SIZE(pdata->supplies),
+                       pdata->supplies);
+       return ret;
+}
+
+/*
+ * Request resources, currently just regulators.
+ *
+ * The SMSC911x has two power pins: vddvario and vdd33a, in designs where
+ * these are not always-on we need to request regulators to be turned on
+ * before we can try to access the device registers.
+ */
+static int smsc911x_request_resources(struct platform_device *pdev)
+{
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct smsc911x_data *pdata = netdev_priv(ndev);
+       int ret = 0;
+
+       /* Request regulators */
+       pdata->supplies[0].supply = "vdd33a";
+       pdata->supplies[1].supply = "vddvario";
+       ret = regulator_bulk_get(&pdev->dev,
+                       ARRAY_SIZE(pdata->supplies),
+                       pdata->supplies);
+       if (ret)
+               netdev_err(ndev, "couldn't get regulators %d\n",
+                               ret);
+       return ret;
+}
+
+/*
+ * Free resources, currently just regulators.
+ *
+ */
+static void smsc911x_free_resources(struct platform_device *pdev)
+{
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct smsc911x_data *pdata = netdev_priv(ndev);
+
+       /* Free regulators */
+       regulator_bulk_free(ARRAY_SIZE(pdata->supplies),
+                       pdata->supplies);
+}
+
 /* waits for MAC not busy, with timeout.  Only called by smsc911x_mac_read
  * and smsc911x_mac_write, so assumes mac_lock is held */
 static int smsc911x_mac_complete(struct smsc911x_data *pdata)
 
        iounmap(pdata->ioaddr);
 
+       (void)smsc911x_disable_resources(pdev);
+       smsc911x_free_resources(pdev);
+
        free_netdev(dev);
 
        return 0;
        pdata->dev = dev;
        pdata->msg_enable = ((1 << debug) - 1);
 
+       platform_set_drvdata(pdev, dev);
+
+       retval = smsc911x_request_resources(pdev);
+       if (retval)
+               goto out_return_resources;
+
+       retval = smsc911x_enable_resources(pdev);
+       if (retval)
+               goto out_disable_resources;
+
        if (pdata->ioaddr == NULL) {
                SMSC_WARN(pdata, probe, "Error smsc911x base address invalid");
                retval = -ENOMEM;
-               goto out_free_netdev_2;
+               goto out_disable_resources;
        }
 
        retval = smsc911x_probe_config_dt(&pdata->config, np);
 
        if (retval) {
                SMSC_WARN(pdata, probe, "Error smsc911x config not found");
-               goto out_unmap_io_3;
+               goto out_disable_resources;
        }
 
        /* assume standard, non-shifted, access to HW registers */
 
        retval = smsc911x_init(dev);
        if (retval < 0)
-               goto out_unmap_io_3;
+               goto out_disable_resources;
 
        /* configure irq polarity and type before connecting isr */
        if (pdata->config.irq_polarity == SMSC911X_IRQ_POLARITY_ACTIVE_HIGH)
        if (retval) {
                SMSC_WARN(pdata, probe,
                          "Unable to claim requested irq: %d", dev->irq);
-               goto out_unmap_io_3;
+               goto out_free_irq;
        }
 
-       platform_set_drvdata(pdev, dev);
-
        retval = register_netdev(dev);
        if (retval) {
                SMSC_WARN(pdata, probe, "Error %i registering device", retval);
-               goto out_unset_drvdata_4;
+               goto out_free_irq;
        } else {
                SMSC_TRACE(pdata, probe,
                           "Network interface: \"%s\"", dev->name);
 
 out_unregister_netdev_5:
        unregister_netdev(dev);
-out_unset_drvdata_4:
-       platform_set_drvdata(pdev, NULL);
+out_free_irq:
        free_irq(dev->irq, dev);
-out_unmap_io_3:
+out_disable_resources:
+       (void)smsc911x_disable_resources(pdev);
+out_return_resources:
+       smsc911x_free_resources(pdev);
+       platform_set_drvdata(pdev, NULL);
        iounmap(pdata->ioaddr);
-out_free_netdev_2:
        free_netdev(dev);
 out_release_io_1:
        release_mem_region(res->start, resource_size(res));