Merge remote-tracking branch 'regulator/topic/change' into regulator-next
[linux-3.10.git] / drivers / regulator / fixed.c
index 393f039..185468c 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/fixed.h>
 #include <linux/gpio.h>
-#include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
@@ -36,10 +35,6 @@ struct fixed_voltage_data {
        struct regulator_desc desc;
        struct regulator_dev *dev;
        int microvolts;
-       int gpio;
-       unsigned startup_delay;
-       bool enable_high;
-       bool is_enabled;
 };
 
 
@@ -62,13 +57,14 @@ of_get_fixed_voltage_config(struct device *dev)
        config = devm_kzalloc(dev, sizeof(struct fixed_voltage_config),
                                                                 GFP_KERNEL);
        if (!config)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        config->init_data = of_get_regulator_init_data(dev, dev->of_node);
        if (!config->init_data)
-               return NULL;
+               return ERR_PTR(-EINVAL);
 
        init_data = config->init_data;
+       init_data->constraints.apply_uV = 0;
 
        config->supply_name = init_data->constraints.name;
        if (init_data->constraints.min_uV == init_data->constraints.max_uV) {
@@ -76,13 +72,26 @@ of_get_fixed_voltage_config(struct device *dev)
        } else {
                dev_err(dev,
                         "Fixed regulator specified with variable voltages\n");
-               return NULL;
+               return ERR_PTR(-EINVAL);
        }
 
        if (init_data->constraints.boot_on)
                config->enabled_at_boot = true;
 
        config->gpio = of_get_named_gpio(np, "gpio", 0);
+       /*
+        * of_get_named_gpio() currently returns ENODEV rather than
+        * EPROBE_DEFER. This code attempts to be compatible with both
+        * for now; the ENODEV check can be removed once the API is fixed.
+        * of_get_named_gpio() doesn't differentiate between a missing
+        * property (which would be fine here, since the GPIO is optional)
+        * and some other error. Patches have been posted for both issues.
+        * Once they are check in, we should replace this with:
+        * if (config->gpio < 0 && config->gpio != -ENOENT)
+        */
+       if ((config->gpio == -ENODEV) || (config->gpio == -EPROBE_DEFER))
+               return ERR_PTR(-EPROBE_DEFER);
+
        delay = of_get_property(np, "startup-delay-us", NULL);
        if (delay)
                config->startup_delay = be32_to_cpu(*delay);
@@ -90,45 +99,13 @@ of_get_fixed_voltage_config(struct device *dev)
        if (of_find_property(np, "enable-active-high", NULL))
                config->enable_high = true;
 
-       return config;
-}
-
-static int fixed_voltage_is_enabled(struct regulator_dev *dev)
-{
-       struct fixed_voltage_data *data = rdev_get_drvdata(dev);
-
-       return data->is_enabled;
-}
-
-static int fixed_voltage_enable(struct regulator_dev *dev)
-{
-       struct fixed_voltage_data *data = rdev_get_drvdata(dev);
-
-       if (gpio_is_valid(data->gpio)) {
-               gpio_set_value_cansleep(data->gpio, data->enable_high);
-               data->is_enabled = true;
-       }
-
-       return 0;
-}
-
-static int fixed_voltage_disable(struct regulator_dev *dev)
-{
-       struct fixed_voltage_data *data = rdev_get_drvdata(dev);
+       if (of_find_property(np, "gpio-open-drain", NULL))
+               config->gpio_is_open_drain = true;
 
-       if (gpio_is_valid(data->gpio)) {
-               gpio_set_value_cansleep(data->gpio, !data->enable_high);
-               data->is_enabled = false;
-       }
+       if (of_find_property(np, "vin-supply", NULL))
+               config->input_supply = "vin";
 
-       return 0;
-}
-
-static int fixed_voltage_enable_time(struct regulator_dev *dev)
-{
-       struct fixed_voltage_data *data = rdev_get_drvdata(dev);
-
-       return data->startup_delay;
+       return config;
 }
 
 static int fixed_voltage_get_voltage(struct regulator_dev *dev)
@@ -153,10 +130,6 @@ static int fixed_voltage_list_voltage(struct regulator_dev *dev,
 }
 
 static struct regulator_ops fixed_voltage_ops = {
-       .is_enabled = fixed_voltage_is_enabled,
-       .enable = fixed_voltage_enable,
-       .disable = fixed_voltage_disable,
-       .enable_time = fixed_voltage_enable_time,
        .get_voltage = fixed_voltage_get_voltage,
        .list_voltage = fixed_voltage_list_voltage,
 };
@@ -165,17 +138,22 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
 {
        struct fixed_voltage_config *config;
        struct fixed_voltage_data *drvdata;
+       struct regulator_config cfg = { };
        int ret;
 
-       if (pdev->dev.of_node)
+       if (pdev->dev.of_node) {
                config = of_get_fixed_voltage_config(&pdev->dev);
-       else
+               if (IS_ERR(config))
+                       return PTR_ERR(config);
+       } else {
                config = pdev->dev.platform_data;
+       }
 
        if (!config)
                return -ENOMEM;
 
-       drvdata = kzalloc(sizeof(struct fixed_voltage_data), GFP_KERNEL);
+       drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),
+                              GFP_KERNEL);
        if (drvdata == NULL) {
                dev_err(&pdev->dev, "Failed to allocate device data\n");
                ret = -ENOMEM;
@@ -191,67 +169,54 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
        drvdata->desc.type = REGULATOR_VOLTAGE;
        drvdata->desc.owner = THIS_MODULE;
        drvdata->desc.ops = &fixed_voltage_ops;
-       drvdata->desc.n_voltages = 1;
 
-       drvdata->microvolts = config->microvolts;
-       drvdata->gpio = config->gpio;
-       drvdata->startup_delay = config->startup_delay;
-
-       if (gpio_is_valid(config->gpio)) {
-               drvdata->enable_high = config->enable_high;
-
-               /* FIXME: Remove below print warning
-                *
-                * config->gpio must be set to -EINVAL by platform code if
-                * GPIO control is not required. However, early adopters
-                * not requiring GPIO control may forget to initialize
-                * config->gpio to -EINVAL. This will cause GPIO 0 to be used
-                * for GPIO control.
-                *
-                * This warning will be removed once there are a couple of users
-                * for this driver.
-                */
-               if (!config->gpio)
-                       dev_warn(&pdev->dev,
-                               "using GPIO 0 for regulator enable control\n");
-
-               ret = gpio_request(config->gpio, config->supply_name);
-               if (ret) {
+       drvdata->desc.enable_time = config->startup_delay;
+
+       if (config->input_supply) {
+               drvdata->desc.supply_name = kstrdup(config->input_supply,
+                                                       GFP_KERNEL);
+               if (!drvdata->desc.supply_name) {
                        dev_err(&pdev->dev,
-                          "Could not obtain regulator enable GPIO %d: %d\n",
-                                                       config->gpio, ret);
+                               "Failed to allocate input supply\n");
+                       ret = -ENOMEM;
                        goto err_name;
                }
+       }
 
-               /* set output direction without changing state
-                * to prevent glitch
-                */
-               drvdata->is_enabled = config->enabled_at_boot;
-               ret = drvdata->is_enabled ?
-                               config->enable_high : !config->enable_high;
+       if (config->microvolts)
+               drvdata->desc.n_voltages = 1;
 
-               ret = gpio_direction_output(config->gpio, ret);
-               if (ret) {
-                       dev_err(&pdev->dev,
-                          "Could not configure regulator enable GPIO %d direction: %d\n",
-                                                       config->gpio, ret);
-                       goto err_gpio;
-               }
+       drvdata->microvolts = config->microvolts;
 
+       if (config->gpio >= 0)
+               cfg.ena_gpio = config->gpio;
+       cfg.ena_gpio_invert = !config->enable_high;
+       if (config->enabled_at_boot) {
+               if (config->enable_high) {
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
+               } else {
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
+               }
        } else {
-               /* Regulator without GPIO control is considered
-                * always enabled
-                */
-               drvdata->is_enabled = true;
+               if (config->enable_high) {
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
+               } else {
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
+               }
        }
+       if (config->gpio_is_open_drain)
+               cfg.ena_gpio_flags |= GPIOF_OPEN_DRAIN;
+
+       cfg.dev = &pdev->dev;
+       cfg.init_data = config->init_data;
+       cfg.driver_data = drvdata;
+       cfg.of_node = pdev->dev.of_node;
 
-       drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev,
-                                         config->init_data, drvdata,
-                                         pdev->dev.of_node);
+       drvdata->dev = regulator_register(&drvdata->desc, &cfg);
        if (IS_ERR(drvdata->dev)) {
                ret = PTR_ERR(drvdata->dev);
                dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
-               goto err_gpio;
+               goto err_input;
        }
 
        platform_set_drvdata(pdev, drvdata);
@@ -261,13 +226,11 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
 
        return 0;
 
-err_gpio:
-       if (gpio_is_valid(config->gpio))
-               gpio_free(config->gpio);
+err_input:
+       kfree(drvdata->desc.supply_name);
 err_name:
        kfree(drvdata->desc.name);
 err:
-       kfree(drvdata);
        return ret;
 }
 
@@ -276,10 +239,8 @@ static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev)
        struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev);
 
        regulator_unregister(drvdata->dev);
-       if (gpio_is_valid(drvdata->gpio))
-               gpio_free(drvdata->gpio);
+       kfree(drvdata->desc.supply_name);
        kfree(drvdata->desc.name);
-       kfree(drvdata);
 
        return 0;
 }
@@ -290,8 +251,6 @@ static const struct of_device_id fixed_of_match[] __devinitconst = {
        {},
 };
 MODULE_DEVICE_TABLE(of, fixed_of_match);
-#else
-#define fixed_of_match NULL
 #endif
 
 static struct platform_driver regulator_fixed_voltage_driver = {
@@ -300,7 +259,7 @@ static struct platform_driver regulator_fixed_voltage_driver = {
        .driver         = {
                .name           = "reg-fixed-voltage",
                .owner          = THIS_MODULE,
-               .of_match_table = fixed_of_match,
+               .of_match_table = of_match_ptr(fixed_of_match),
        },
 };