#include <linux/input.h>
 #include <linux/interrupt.h>
 #include <linux/leds.h>
+#include <linux/mutex.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
 #include <linux/serial_8250.h>
 #include <linux/export.h>
 
                .flags  = GPIOF_OUT_INIT_LOW,
                .label  = "scard_cmdvcc",
        },
-       {
-               .gpio   = AMS_DELTA_GPIO_PIN_MODEM_NRESET,
-               .flags  = GPIOF_OUT_INIT_LOW,
-               .label  = "modem_nreset",
-       },
        {
                .gpio   = AMS_DELTA_GPIO_PIN_MODEM_CODEC,
                .flags  = GPIOF_OUT_INIT_LOW,
        },
 };
 
+static struct regulator_consumer_supply modem_nreset_consumers[] = {
+       REGULATOR_SUPPLY("RESET#", "serial8250.1"),
+       REGULATOR_SUPPLY("POR", "cx20442-codec"),
+};
+
+static struct regulator_init_data modem_nreset_data = {
+       .constraints            = {
+               .valid_ops_mask         = REGULATOR_CHANGE_STATUS,
+               .boot_on                = 1,
+       },
+       .num_consumer_supplies  = ARRAY_SIZE(modem_nreset_consumers),
+       .consumer_supplies      = modem_nreset_consumers,
+};
+
+static struct fixed_voltage_config modem_nreset_config = {
+       .supply_name            = "modem_nreset",
+       .microvolts             = 3300000,
+       .gpio                   = AMS_DELTA_GPIO_PIN_MODEM_NRESET,
+       .startup_delay          = 25000,
+       .enable_high            = 1,
+       .enabled_at_boot        = 1,
+       .init_data              = &modem_nreset_data,
+};
+
+static struct platform_device modem_nreset_device = {
+       .name   = "reg-fixed-voltage",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &modem_nreset_config,
+       },
+};
+
+struct modem_private_data {
+       struct regulator *regulator;
+       struct {
+               struct mutex lock;
+               bool enabled;
+       } consumer;
+};
+
+static int regulator_toggle(struct modem_private_data *priv, bool enable)
+{
+       int err = 0;
+
+       mutex_lock(&priv->consumer.lock);
+       if (IS_ERR(priv->regulator)) {
+               err = PTR_ERR(priv->regulator);
+       } else if (enable) {
+               if (!priv->consumer.enabled) {
+                       err = regulator_enable(priv->regulator);
+                       priv->consumer.enabled = true;
+               }
+       } else {
+               if (priv->consumer.enabled) {
+                       err = regulator_disable(priv->regulator);
+                       priv->consumer.enabled = false;
+               }
+       }
+       mutex_unlock(&priv->consumer.lock);
+
+       return err;
+}
+
+static struct modem_private_data modem_priv;
+
 void ams_delta_latch_write(int base, int ngpio, u16 mask, u16 value)
 {
        int bit = 0;
        for (; bit < ngpio; bit++, bitpos = bitpos << 1) {
                if (!(mask & bitpos))
                        continue;
-               gpio_set_value(base + bit, (value & bitpos) != 0);
+               else if (base + bit == AMS_DELTA_GPIO_PIN_MODEM_NRESET)
+                       regulator_toggle(&modem_priv, (value & bitpos) != 0);
+               else
+                       gpio_set_value(base + bit, (value & bitpos) != 0);
        }
 }
 EXPORT_SYMBOL(ams_delta_latch_write);
 
        platform_add_devices(late_devices, ARRAY_SIZE(late_devices));
 
+       err = platform_device_register(&modem_nreset_device);
+       if (err) {
+               pr_err("Couldn't register the modem regulator device\n");
+               return err;
+       }
+
        omap_cfg_reg(M14_1510_GPIO2);
        ams_delta_modem_ports[0].irq =
                        gpio_to_irq(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
        }
        gpio_direction_input(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
 
+       /* Initialize the modem_nreset regulator consumer before use */
+       mutex_init(&modem_priv.consumer.lock);
+       modem_priv.regulator = ERR_PTR(-ENODEV);
+
        ams_delta_latch2_write(
                AMS_DELTA_LATCH2_MODEM_NRESET | AMS_DELTA_LATCH2_MODEM_CODEC,
                AMS_DELTA_LATCH2_MODEM_NRESET | AMS_DELTA_LATCH2_MODEM_CODEC);
        err = platform_device_register(&ams_delta_modem_device);
        if (err)
                goto gpio_free;
+
+       /*
+        * Once the modem device is registered, the modem_nreset
+        * regulator can be requested on behalf of that device.
+        * The regulator is used via ams_delta_latch_write()
+        * by the modem and ASoC drivers until updated.
+        */
+       modem_priv.regulator = regulator_get(&ams_delta_modem_device.dev,
+                       "RESET#");
+       if (IS_ERR(modem_priv.regulator)) {
+               err = PTR_ERR(modem_priv.regulator);
+               goto unregister;
+       }
        return 0;
 
+unregister:
+       platform_device_unregister(&ams_delta_modem_device);
 gpio_free:
        gpio_free(AMS_DELTA_GPIO_PIN_MODEM_IRQ);
        return err;