regulator: fixed: add support for ACPI interface
[sfrench/cifs-2.6.git] / drivers / regulator / fixed.c
index 354105eff1f80ed392951b41518e3062eac70582..a43b0e8a438d305a959d3d745c7c65bf796ca9f9 100644 (file)
@@ -30,6 +30,9 @@
 #include <linux/of_gpio.h>
 #include <linux/regulator/of_regulator.h>
 #include <linux/regulator/machine.h>
+#include <linux/acpi.h>
+#include <linux/property.h>
+#include <linux/gpio/consumer.h>
 
 struct fixed_voltage_data {
        struct regulator_desc desc;
@@ -40,13 +43,15 @@ struct fixed_voltage_data {
 /**
  * of_get_fixed_voltage_config - extract fixed_voltage_config structure info
  * @dev: device requesting for fixed_voltage_config
+ * @desc: regulator description
  *
  * Populates fixed_voltage_config structure by extracting data from device
  * tree node, returns a pointer to the populated structure of NULL if memory
  * alloc fails.
  */
 static struct fixed_voltage_config *
-of_get_fixed_voltage_config(struct device *dev)
+of_get_fixed_voltage_config(struct device *dev,
+                           const struct regulator_desc *desc)
 {
        struct fixed_voltage_config *config;
        struct device_node *np = dev->of_node;
@@ -57,7 +62,7 @@ of_get_fixed_voltage_config(struct device *dev)
        if (!config)
                return ERR_PTR(-ENOMEM);
 
-       config->init_data = of_get_regulator_init_data(dev, dev->of_node);
+       config->init_data = of_get_regulator_init_data(dev, dev->of_node, desc);
        if (!config->init_data)
                return ERR_PTR(-EINVAL);
 
@@ -77,18 +82,8 @@ of_get_fixed_voltage_config(struct device *dev)
                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);
+       if ((config->gpio < 0) && (config->gpio != -ENOENT))
+               return ERR_PTR(config->gpio);
 
        of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
 
@@ -102,6 +97,44 @@ of_get_fixed_voltage_config(struct device *dev)
        return config;
 }
 
+/**
+ * acpi_get_fixed_voltage_config - extract fixed_voltage_config structure info
+ * @dev: device requesting for fixed_voltage_config
+ * @desc: regulator description
+ *
+ * Populates fixed_voltage_config structure by extracting data through ACPI
+ * interface, returns a pointer to the populated structure of NULL if memory
+ * alloc fails.
+ */
+static struct fixed_voltage_config *
+acpi_get_fixed_voltage_config(struct device *dev,
+                             const struct regulator_desc *desc)
+{
+       struct fixed_voltage_config *config;
+       const char *supply_name;
+       struct gpio_desc *gpiod;
+       int ret;
+
+       config = devm_kzalloc(dev, sizeof(*config), GFP_KERNEL);
+       if (!config)
+               return ERR_PTR(-ENOMEM);
+
+       ret = device_property_read_string(dev, "supply-name", &supply_name);
+       if (!ret)
+               config->supply_name = supply_name;
+
+       gpiod = gpiod_get(dev, "gpio", GPIOD_ASIS);
+       if (IS_ERR(gpiod))
+               return ERR_PTR(-ENODEV);
+
+       config->gpio = desc_to_gpio(gpiod);
+       config->enable_high = device_property_read_bool(dev,
+                                                       "enable-active-high");
+       gpiod_put(gpiod);
+
+       return config;
+}
+
 static struct regulator_ops fixed_voltage_ops = {
 };
 
@@ -112,8 +145,19 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
        struct regulator_config cfg = { };
        int ret;
 
+       drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),
+                              GFP_KERNEL);
+       if (!drvdata)
+               return -ENOMEM;
+
        if (pdev->dev.of_node) {
-               config = of_get_fixed_voltage_config(&pdev->dev);
+               config = of_get_fixed_voltage_config(&pdev->dev,
+                                                    &drvdata->desc);
+               if (IS_ERR(config))
+                       return PTR_ERR(config);
+       } else if (ACPI_HANDLE(&pdev->dev)) {
+               config = acpi_get_fixed_voltage_config(&pdev->dev,
+                                                      &drvdata->desc);
                if (IS_ERR(config))
                        return PTR_ERR(config);
        } else {
@@ -123,11 +167,6 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
        if (!config)
                return -ENOMEM;
 
-       drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),
-                              GFP_KERNEL);
-       if (!drvdata)
-               return -ENOMEM;
-
        drvdata->desc.name = devm_kstrdup(&pdev->dev,
                                          config->supply_name,
                                          GFP_KERNEL);
@@ -157,8 +196,11 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
 
        drvdata->desc.fixed_uV = config->microvolts;
 
-       if (config->gpio >= 0)
+       if (gpio_is_valid(config->gpio)) {
                cfg.ena_gpio = config->gpio;
+               if (pdev->dev.of_node)
+                       cfg.ena_gpio_initialized = true;
+       }
        cfg.ena_gpio_invert = !config->enable_high;
        if (config->enabled_at_boot) {
                if (config->enable_high)
@@ -207,7 +249,6 @@ static struct platform_driver regulator_fixed_voltage_driver = {
        .probe          = reg_fixed_voltage_probe,
        .driver         = {
                .name           = "reg-fixed-voltage",
-               .owner          = THIS_MODULE,
                .of_match_table = of_match_ptr(fixed_of_match),
        },
 };