public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] regulator: Support different config and dev of_nodes in regulator_register
@ 2015-02-04 23:19 Tim Bird
  2015-02-05  1:59 ` Mark Brown
  0 siblings, 1 reply; 13+ messages in thread
From: Tim Bird @ 2015-02-04 23:19 UTC (permalink / raw)
  To: broonie, lgirdwood; +Cc: linux-kernel@vger.kernel.org, Bjorn Andersson

Support calling regulator_register with a dev node and a config node
with different of_nodes.  This is useful when a single driver
wishes to register multiple child regulators.

Without this you get silent failures allocating a supply
for a regulator which is registered using the device node of the
regulator's DT parent (but it's own DT node).

Signed-off-by: Tim Bird <tim.bird@sonymobile.com>
---
I encountered a problem where I did a devm_regulator_register with
a dev (for a charger driver) and a config (for the regulator child
of the driver) that had different of_nodes.  In this case, inside
regulator_dev_lookup the code did not find the supply that I had
specified in the child regulator's DT node.  The DT setup looked
as follows:

charger@1000 {
      compatible = "qcom,pm8941-charger";
      reg = <0x1000 0x700>;
      ....
      chg_otg {
          regulator_name = "chg_otg";
          otg-supply = <&pm8941_mvs1>;
          ...
      }
}

This code checks the of_node of specified in the struct regulator_config
if the supply is not found in the dev.of_node.  This code has no effect
if dev.of_node and config.of_node are the same, so it shouldn't affect
any existing (working) code.

 drivers/regulator/core.c | 29 ++++++++++++++++++++---------
 1 file changed, 20 insertions(+), 9 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 128b432..36c5d78 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -128,13 +128,16 @@ static bool have_full_constraints(void)
 /**
  * of_get_regulator - get a regulator device node based on supply name
  * @dev: Device pointer for the consumer (of regulator) device
+ * @config: pointer to config for regulator registration
  * @supply: regulator supply name
  *
  * Extract the regulator device node corresponding to the supply name.
  * returns the device node corresponding to the regulator if found, else
  * returns NULL.
  */
-static struct device_node *of_get_regulator(struct device *dev, const char *supply)
+static struct device_node *of_get_regulator(struct device *dev,
+				const struct regulator_config *config,
+				const char *supply)
 {
 	struct device_node *regnode = NULL;
 	char prop_name[32]; /* 32 is max size of property name */
@@ -147,7 +150,15 @@ static struct device_node *of_get_regulator(struct device *dev, const char *supp
 	if (!regnode) {
 		dev_dbg(dev, "Looking up %s property in node %s failed",
 				prop_name, dev->of_node->full_name);
-		return NULL;
+		if (!config || !config->of_node ||
+				config->of_node == dev->of_node)
+			return NULL;
+		regnode = of_parse_phandle(config->of_node, prop_name, 0);
+		if (!regnode) {
+			dev_dbg(dev, "Looking up %s property in node %s failed",
+				prop_name, dev->of_node->full_name);
+			return NULL;
+		}
 	}
 	return regnode;
 }
@@ -1284,9 +1295,10 @@ static void regulator_supply_alias(struct device **dev, const char **supply)
 	}
 }
 
-static struct regulator_dev *regulator_dev_lookup(struct device *dev,
-						  const char *supply,
-						  int *ret)
+static struct regulator_dev *regulator_dev_config_lookup(struct device *dev,
+					const struct regulator_config *config,
+					const char *supply,
+					int *ret)
 {
 	struct regulator_dev *r;
 	struct device_node *node;
@@ -1297,7 +1309,7 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
 
 	/* first do a dt based lookup */
 	if (dev && dev->of_node) {
-		node = of_get_regulator(dev, supply);
+		node = of_get_regulator(dev, config, supply);
 		if (node) {
 			list_for_each_entry(r, &regulator_list, list)
 				if (r->dev.parent &&
@@ -1334,7 +1346,6 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
 			return map->regulator;
 	}
 
-
 	return NULL;
 }
 
@@ -1362,7 +1373,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
 
 	mutex_lock(&regulator_list_mutex);
 
-	rdev = regulator_dev_lookup(dev, id, &ret);
+	rdev = regulator_dev_config_lookup(dev, NULL, id, &ret);
 	if (rdev)
 		goto found;
 
@@ -3642,7 +3653,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
 	if (supply) {
 		struct regulator_dev *r;
 
-		r = regulator_dev_lookup(dev, supply, &ret);
+		r = regulator_dev_config_lookup(dev, config, supply, &ret);
 
 		if (ret == -ENODEV) {
 			/*
-- 
1.8.2.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2015-02-12  2:33 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-04 23:19 [PATCH] regulator: Support different config and dev of_nodes in regulator_register Tim Bird
2015-02-05  1:59 ` Mark Brown
2015-02-05 17:33   ` Tim Bird
2015-02-05 17:43     ` Mark Brown
2015-02-05 18:37       ` Tim Bird
2015-02-05 19:27         ` Mark Brown
2015-02-05 22:08           ` Bjorn Andersson
2015-02-06  0:32             ` Mark Brown
2015-02-06  0:52               ` Bjorn Andersson
2015-02-06 11:49                 ` Mark Brown
2015-02-06 19:56                   ` Tim Bird
2015-02-11 17:21                     ` Tim Bird
2015-02-12  2:32                       ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox