diff mbox

[7/7] drivers/regulator: Initialize regulator init data for ACPI regulators

Message ID 20170125000641.25520-8-furquan@chromium.org
State New
Headers show

Commit Message

Furquan Shaikh Jan. 25, 2017, 12:06 a.m. UTC
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 <furquan@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 mbox

Patch

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);