Regulator init data and regulation constraints need to be setup by
ACPI regulators similar to OF regulators. This is required to ensure
that drivers can properly enable/disable the regulators.

Since, regulator properties remain the same across OF and ACPI
regulators, provide common routines for obtaining the regulation
constraints from device tree/ACPI node. Update fixed regulator driver
to use this newly added routine.

Signed-off-by: Furquan Shaikh <furq...@chromium.org>
---
 drivers/regulator/Makefile          |   2 +-
 drivers/regulator/fixed.c           | 100 +++++++------------
 drivers/regulator/internal.h        |   3 +
 drivers/regulator/of_regulator.c    | 156 +----------------------------
 drivers/regulator/regulator_props.c | 189 ++++++++++++++++++++++++++++++++++++
 5 files changed, 229 insertions(+), 221 deletions(-)
 create mode 100644 drivers/regulator/regulator_props.c

diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 14294692beb9..7701cb9e9bec 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -3,7 +3,7 @@
 #
 
 
-obj-$(CONFIG_REGULATOR) += core.o dummy.o fixed-helper.o helpers.o devres.o
+obj-$(CONFIG_REGULATOR) += core.o dummy.o fixed-helper.o helpers.o devres.o 
regulator_props.o
 obj-$(CONFIG_OF) += of_regulator.o
 obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
 obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index a43b0e8a438d..572f352095c3 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -34,39 +34,40 @@
 #include <linux/property.h>
 #include <linux/gpio/consumer.h>
 
+#include "internal.h"
+
 struct fixed_voltage_data {
        struct regulator_desc desc;
        struct regulator_dev *dev;
 };
 
-
 /**
- * of_get_fixed_voltage_config - extract fixed_voltage_config structure info
+ * reg_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.
+ * tree or ACPI node, returns a pointer to the populated structure or NULL if
+ * memory alloc fails.
  */
 static struct fixed_voltage_config *
-of_get_fixed_voltage_config(struct device *dev,
-                           const struct regulator_desc *desc)
+reg_fixed_voltage_get_config(struct device *dev,
+                       const struct regulator_desc *desc)
 {
        struct fixed_voltage_config *config;
-       struct device_node *np = dev->of_node;
        struct regulator_init_data *init_data;
+       struct gpio_desc *gpiod;
 
-       config = devm_kzalloc(dev, sizeof(struct fixed_voltage_config),
-                                                                GFP_KERNEL);
+       config = devm_kzalloc(dev, sizeof(*config), GFP_KERNEL);
        if (!config)
                return ERR_PTR(-ENOMEM);
 
-       config->init_data = of_get_regulator_init_data(dev, dev->of_node, desc);
-       if (!config->init_data)
+       init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL);
+       if (!init_data)
                return ERR_PTR(-EINVAL);
 
-       init_data = config->init_data;
+       device_get_regulation_constraints(dev_fwnode(dev), init_data, desc);
+
        init_data->constraints.apply_uV = 0;
 
        config->supply_name = init_data->constraints.name;
@@ -74,63 +75,35 @@ of_get_fixed_voltage_config(struct device *dev,
                config->microvolts = init_data->constraints.min_uV;
        } else {
                dev_err(dev,
-                        "Fixed regulator specified with variable voltages\n");
+                       "Fixed regulator specified with variable voltages\n");
                return ERR_PTR(-EINVAL);
        }
 
        if (init_data->constraints.boot_on)
                config->enabled_at_boot = true;
 
-       config->gpio = of_get_named_gpio(np, "gpio", 0);
-       if ((config->gpio < 0) && (config->gpio != -ENOENT))
-               return ERR_PTR(config->gpio);
-
-       of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
+       gpiod = gpiod_lookup(dev, NULL);
 
-       config->enable_high = of_property_read_bool(np, "enable-active-high");
-       config->gpio_is_open_drain = of_property_read_bool(np,
-                                                          "gpio-open-drain");
+       if (gpiod == ERR_PTR(-EPROBE_DEFER))
+               return ERR_PTR(-EPROBE_DEFER);
 
-       if (of_find_property(np, "vin-supply", NULL))
-               config->input_supply = "vin";
+       if (!IS_ERR(gpiod))
+               config->gpio = desc_to_gpio(gpiod);
+       else
+               config->gpio = -1;
 
-       return config;
-}
+       device_property_read_u32(dev, "startup-delay-us",
+                               &config->startup_delay);
 
-/**
- * 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);
+       config->gpio_is_open_drain = device_property_read_bool(dev,
+                                                       "gpio-open-drain");
+
+       if (device_property_present(dev, "vin-supply"))
+               config->input_supply = "vin";
+
+       config->init_data = init_data;
 
        return config;
 }
@@ -150,14 +123,9 @@ static int reg_fixed_voltage_probe(struct platform_device 
*pdev)
        if (!drvdata)
                return -ENOMEM;
 
-       if (pdev->dev.of_node) {
-               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 (pdev->dev.of_node || ACPI_HANDLE(&pdev->dev)) {
+               config = reg_fixed_voltage_get_config(&pdev->dev,
+                                                     &drvdata->desc);
                if (IS_ERR(config))
                        return PTR_ERR(config);
        } else {
@@ -198,7 +166,7 @@ static int reg_fixed_voltage_probe(struct platform_device 
*pdev)
 
        if (gpio_is_valid(config->gpio)) {
                cfg.ena_gpio = config->gpio;
-               if (pdev->dev.of_node)
+               if (pdev->dev.of_node || ACPI_HANDLE(&pdev->dev))
                        cfg.ena_gpio_initialized = true;
        }
        cfg.ena_gpio_invert = !config->enable_high;
diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h
index c74ac8734023..3a699b2cbea9 100644
--- a/drivers/regulator/internal.h
+++ b/drivers/regulator/internal.h
@@ -51,4 +51,7 @@ regulator_of_get_init_data(struct device *dev,
 }
 #endif
 
+void device_get_regulation_constraints(struct fwnode_handle *fwnode,
+                                       struct regulator_init_data *init_data,
+                                       const struct regulator_desc *desc);
 #endif
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 13d4dc2c287e..0ff5259c34f0 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -19,159 +19,6 @@
 
 #include "internal.h"
 
-static const char *const regulator_states[PM_SUSPEND_MAX + 1] = {
-       [PM_SUSPEND_MEM]        = "regulator-state-mem",
-       [PM_SUSPEND_MAX]        = "regulator-state-disk",
-};
-
-static void of_get_regulation_constraints(struct device_node *np,
-                                       struct regulator_init_data **init_data,
-                                       const struct regulator_desc *desc)
-{
-       struct regulation_constraints *constraints = &(*init_data)->constraints;
-       struct regulator_state *suspend_state;
-       struct device_node *suspend_np;
-       int ret, i;
-       u32 pval;
-
-       constraints->name = of_get_property(np, "regulator-name", NULL);
-
-       if (!of_property_read_u32(np, "regulator-min-microvolt", &pval))
-               constraints->min_uV = pval;
-
-       if (!of_property_read_u32(np, "regulator-max-microvolt", &pval))
-               constraints->max_uV = pval;
-
-       /* Voltage change possible? */
-       if (constraints->min_uV != constraints->max_uV)
-               constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE;
-
-       /* Do we have a voltage range, if so try to apply it? */
-       if (constraints->min_uV && constraints->max_uV)
-               constraints->apply_uV = true;
-
-       if (!of_property_read_u32(np, "regulator-microvolt-offset", &pval))
-               constraints->uV_offset = pval;
-       if (!of_property_read_u32(np, "regulator-min-microamp", &pval))
-               constraints->min_uA = pval;
-       if (!of_property_read_u32(np, "regulator-max-microamp", &pval))
-               constraints->max_uA = pval;
-
-       if (!of_property_read_u32(np, "regulator-input-current-limit-microamp",
-                                 &pval))
-               constraints->ilim_uA = pval;
-
-       /* Current change possible? */
-       if (constraints->min_uA != constraints->max_uA)
-               constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT;
-
-       constraints->boot_on = of_property_read_bool(np, "regulator-boot-on");
-       constraints->always_on = of_property_read_bool(np, 
"regulator-always-on");
-       if (!constraints->always_on) /* status change should be possible. */
-               constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS;
-
-       constraints->pull_down = of_property_read_bool(np, 
"regulator-pull-down");
-
-       if (of_property_read_bool(np, "regulator-allow-bypass"))
-               constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS;
-
-       if (of_property_read_bool(np, "regulator-allow-set-load"))
-               constraints->valid_ops_mask |= REGULATOR_CHANGE_DRMS;
-
-       ret = of_property_read_u32(np, "regulator-ramp-delay", &pval);
-       if (!ret) {
-               if (pval)
-                       constraints->ramp_delay = pval;
-               else
-                       constraints->ramp_disable = true;
-       }
-
-       ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval);
-       if (!ret)
-               constraints->enable_time = pval;
-
-       constraints->soft_start = of_property_read_bool(np,
-                                       "regulator-soft-start");
-       ret = of_property_read_u32(np, "regulator-active-discharge", &pval);
-       if (!ret) {
-               constraints->active_discharge =
-                               (pval) ? REGULATOR_ACTIVE_DISCHARGE_ENABLE :
-                                       REGULATOR_ACTIVE_DISCHARGE_DISABLE;
-       }
-
-       if (!of_property_read_u32(np, "regulator-initial-mode", &pval)) {
-               if (desc && desc->map_mode) {
-                       ret = desc->map_mode(pval);
-                       if (ret == -EINVAL)
-                               pr_err("%s: invalid mode %u\n", np->name, pval);
-                       else
-                               constraints->initial_mode = ret;
-               } else {
-                       pr_warn("%s: mapping for mode %d not defined\n",
-                               np->name, pval);
-               }
-       }
-
-       if (!of_property_read_u32(np, "regulator-system-load", &pval))
-               constraints->system_load = pval;
-
-       constraints->over_current_protection = of_property_read_bool(np,
-                                       "regulator-over-current-protection");
-
-       for (i = 0; i < ARRAY_SIZE(regulator_states); i++) {
-               switch (i) {
-               case PM_SUSPEND_MEM:
-                       suspend_state = &constraints->state_mem;
-                       break;
-               case PM_SUSPEND_MAX:
-                       suspend_state = &constraints->state_disk;
-                       break;
-               case PM_SUSPEND_ON:
-               case PM_SUSPEND_FREEZE:
-               case PM_SUSPEND_STANDBY:
-               default:
-                       continue;
-               }
-
-               suspend_np = of_get_child_by_name(np, regulator_states[i]);
-               if (!suspend_np || !suspend_state)
-                       continue;
-
-               if (!of_property_read_u32(suspend_np, "regulator-mode",
-                                         &pval)) {
-                       if (desc && desc->map_mode) {
-                               ret = desc->map_mode(pval);
-                               if (ret == -EINVAL)
-                                       pr_err("%s: invalid mode %u\n",
-                                              np->name, pval);
-                               else
-                                       suspend_state->mode = ret;
-                       } else {
-                               pr_warn("%s: mapping for mode %d not defined\n",
-                                       np->name, pval);
-                       }
-               }
-
-               if (of_property_read_bool(suspend_np,
-                                       "regulator-on-in-suspend"))
-                       suspend_state->enabled = true;
-               else if (of_property_read_bool(suspend_np,
-                                       "regulator-off-in-suspend"))
-                       suspend_state->disabled = true;
-
-               if (!of_property_read_u32(suspend_np,
-                                       "regulator-suspend-microvolt", &pval))
-                       suspend_state->uV = pval;
-
-               if (i == PM_SUSPEND_MEM)
-                       constraints->initial_state = PM_SUSPEND_MEM;
-
-               of_node_put(suspend_np);
-               suspend_state = NULL;
-               suspend_np = NULL;
-       }
-}
-
 /**
  * of_get_regulator_init_data - extract regulator_init_data structure info
  * @dev: device requesting for regulator_init_data
@@ -195,7 +42,8 @@ struct regulator_init_data 
*of_get_regulator_init_data(struct device *dev,
        if (!init_data)
                return NULL; /* Out of memory? */
 
-       of_get_regulation_constraints(node, &init_data, desc);
+       device_get_regulation_constraints(&node->fwnode, init_data, desc);
+
        return init_data;
 }
 EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
diff --git a/drivers/regulator/regulator_props.c 
b/drivers/regulator/regulator_props.c
new file mode 100644
index 000000000000..65e78ad1f494
--- /dev/null
+++ b/drivers/regulator/regulator_props.c
@@ -0,0 +1,189 @@
+/*
+ * ACPI helpers for regulator framework
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc
+ * Copyright (C) 2016 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/of.h>
+#include <linux/property.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+static const char *const regulator_states[PM_SUSPEND_MAX + 1] = {
+       [PM_SUSPEND_MEM]        = "regulator-state-mem",
+       [PM_SUSPEND_MAX]        = "regulator-state-disk",
+};
+
+/**
+ * device_get_regulation_constraints - extract regulation_constraints info
+ * @fwnode: fwnode of device requesting for regulation_constraints
+ * @init_data: regulator_init_data structure containing regulation_constraints
+ * @desc: regulator description
+ *
+ * Populates regulation_constraints structure by extracting data from device
+ * tree or ACPI node.
+ */
+void device_get_regulation_constraints(struct fwnode_handle *fwnode,
+                                       struct regulator_init_data *init_data,
+                                       const struct regulator_desc *desc)
+{
+       struct regulation_constraints *constraints = &init_data->constraints;
+       int ret, i;
+       u32 pval;
+       struct regulator_state *suspend_state = NULL;
+       struct fwnode_handle *suspend_fwnode;
+
+       fwnode_property_read_string(fwnode, "regulator-name",
+                                       &constraints->name);
+
+       if (!fwnode_property_read_u32(fwnode, "regulator-min-microvolt", &pval))
+               constraints->min_uV = pval;
+
+       if (!fwnode_property_read_u32(fwnode, "regulator-max-microvolt", &pval))
+               constraints->max_uV = pval;
+
+       /* Voltage change possible? */
+       if (constraints->min_uV != constraints->max_uV)
+               constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE;
+
+       /* Do we have a voltage range, if so try to apply it? */
+       if (constraints->min_uV && constraints->max_uV)
+               constraints->apply_uV = true;
+
+       if (!fwnode_property_read_u32(fwnode, "regulator-microvolt-offset",
+                                       &pval))
+               constraints->uV_offset = pval;
+       if (!fwnode_property_read_u32(fwnode, "regulator-min-microamp", &pval))
+               constraints->min_uA = pval;
+       if (!fwnode_property_read_u32(fwnode, "regulator-max-microamp", &pval))
+               constraints->max_uA = pval;
+
+       if (!fwnode_property_read_u32(fwnode,
+                               "regulator-input-current-limit-microamp",
+                               &pval))
+               constraints->ilim_uA = pval;
+
+       /* Current change possible? */
+       if (constraints->min_uA != constraints->max_uA)
+               constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT;
+
+       constraints->boot_on = fwnode_property_read_bool(fwnode,
+                                                       "regulator-boot-on");
+       constraints->always_on = fwnode_property_read_bool(fwnode,
+                                                       "regulator-always-on");
+       if (!constraints->always_on) /* status change should be possible. */
+               constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS;
+
+       constraints->pull_down = fwnode_property_read_bool(fwnode,
+                                                       "regulator-pull-down");
+
+       if (fwnode_property_read_bool(fwnode, "regulator-allow-bypass"))
+               constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS;
+
+       if (fwnode_property_read_bool(fwnode, "regulator-allow-set-load"))
+               constraints->valid_ops_mask |= REGULATOR_CHANGE_DRMS;
+
+       ret = fwnode_property_read_u32(fwnode, "regulator-ramp-delay", &pval);
+       if (!ret) {
+               if (pval)
+                       constraints->ramp_delay = pval;
+               else
+                       constraints->ramp_disable = true;
+       }
+
+       ret = fwnode_property_read_u32(fwnode, "regulator-enable-ramp-delay",
+                                       &pval);
+       if (!ret)
+               constraints->enable_time = pval;
+
+       constraints->soft_start = fwnode_property_read_bool(fwnode,
+                                                       "regulator-soft-start");
+       ret = fwnode_property_read_u32(fwnode, "regulator-active-discharge",
+                                       &pval);
+       if (!ret) {
+               constraints->active_discharge =
+                               (pval) ? REGULATOR_ACTIVE_DISCHARGE_ENABLE :
+                                       REGULATOR_ACTIVE_DISCHARGE_DISABLE;
+       }
+
+       if (!fwnode_property_read_u32(fwnode, "regulator-initial-mode",
+                                       &pval)) {
+               if (desc && desc->map_mode) {
+                       ret = desc->map_mode(pval);
+                       if (ret == -EINVAL)
+                               pr_err("invalid mode %u\n", pval);
+                       else
+                               constraints->initial_mode = ret;
+               } else {
+                       pr_warn("mapping for mode %d not defined\n", pval);
+               }
+       }
+
+       if (!fwnode_property_read_u32(fwnode, "regulator-system-load", &pval))
+               constraints->system_load = pval;
+
+       constraints->over_current_protection = fwnode_property_read_bool(fwnode,
+                                       "regulator-over-current-protection");
+
+       for (i = 0; i < ARRAY_SIZE(regulator_states); i++) {
+               switch (i) {
+               case PM_SUSPEND_MEM:
+                       suspend_state = &constraints->state_mem;
+                       break;
+               case PM_SUSPEND_MAX:
+                       suspend_state = &constraints->state_disk;
+                       break;
+               case PM_SUSPEND_ON:
+               case PM_SUSPEND_FREEZE:
+               case PM_SUSPEND_STANDBY:
+               default:
+                       continue;
+               }
+
+               suspend_fwnode = fwnode_get_named_child_node(fwnode,
+                                                       regulator_states[i]);
+               if (!suspend_fwnode || !suspend_state)
+                       continue;
+
+               if (!fwnode_property_read_u32(suspend_fwnode, "regulator-mode",
+                                               &pval)) {
+                       if (desc && desc->map_mode) {
+                               ret = desc->map_mode(pval);
+                               if (ret == -EINVAL)
+                                       pr_err("invalid mode %u\n", pval);
+                               else
+                                       suspend_state->mode = ret;
+                       } else {
+                               pr_warn("mapping for mode %d not defined\n",
+                                       pval);
+                       }
+               }
+
+               if (fwnode_property_read_bool(suspend_fwnode,
+                                       "regulator-on-in-suspend"))
+                       suspend_state->enabled = true;
+               else if (fwnode_property_read_bool(suspend_fwnode,
+                                               "regulator-off-in-suspend"))
+                       suspend_state->disabled = true;
+
+               if (!fwnode_property_read_u32(suspend_fwnode,
+                                       "regulator-suspend-microvolt", &pval))
+                       suspend_state->uV = pval;
+
+               if (i == PM_SUSPEND_MEM)
+                       constraints->initial_state = PM_SUSPEND_MEM;
+
+               fwnode_handle_put(suspend_fwnode);
+               suspend_state = NULL;
+               suspend_fwnode = NULL;
+       }
+}
+EXPORT_SYMBOL_GPL(device_get_regulation_constraints);
-- 
2.11.0.483.g087da7b7c-goog

Reply via email to