lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1419614799-5770-3-git-send-email-gregory.clement@free-electrons.com>
Date:	Fri, 26 Dec 2014 18:26:39 +0100
From:	Gregory CLEMENT <gregory.clement@...e-electrons.com>
To:	Liam Girdwood <lgirdwood@...il.com>,
	Mark Brown <broonie@...nel.org>, linux-kernel@...r.kernel.org
Cc:	Thomas Petazzoni <thomas.petazzoni@...e-electrons.com>,
	Ezequiel Garcia <ezequiel.garcia@...e-electrons.com>,
	Maxime Ripard <maxime.ripard@...e-electrons.com>,
	Boris BREZILLON <boris.brezillon@...e-electrons.com>,
	Lior Amsalem <alior@...vell.com>,
	Tawfik Bayouk <tawfik@...vell.com>,
	Nadav Haklai <nadavh@...vell.com>, linux-ide@...r.kernel.org,
	Gregory CLEMENT <gregory.clement@...e-electrons.com>
Subject: [PATCH 2/2] regulator: core: Add the device tree version to the regulator_get family

This patch adds the device tree version (of_) for each member of the
regulator_get family: normal, exclusive, optional and all of the
manageable version.

The of_regulator_get* functions allow using a device node to get the
regulator instead using the device object. It is needed for the
regulator associated to a child node which is not a device, it is the
case of the SATA ports of an ahci controller for instance.

Signed-off-by: Gregory CLEMENT <gregory.clement@...e-electrons.com>
---
 drivers/regulator/core.c           | 114 +++++++++++++++++++++++++++++++++----
 drivers/regulator/devres.c         |  70 ++++++++++++++++++++---
 include/linux/regulator/consumer.h |  20 +++++++
 3 files changed, 187 insertions(+), 17 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index de29399b5430..74167b98797a 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -127,26 +127,37 @@ static bool have_full_constraints(void)
 
 /**
  * of_get_regulator - get a regulator device node based on supply name
+ * and on device node if provided
+ *
  * @dev: Device pointer for the consumer (of regulator) device
+ * @np: Device tree node pointer on the node containing the regulator
  * @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_by_node(struct device *dev,
+						    const char *supply,
+						    struct device_node *np)
 {
 	struct device_node *regnode = NULL;
 	char prop_name[32]; /* 32 is max size of property name */
+	struct device_node *node;
+
+	if (np)
+		node = np;
+	else
+		node = dev->of_node;
 
 	dev_dbg(dev, "Looking up %s-supply from device tree\n", supply);
 
 	snprintf(prop_name, 32, "%s-supply", supply);
-	regnode = of_parse_phandle(dev->of_node, prop_name, 0);
+	regnode = of_parse_phandle(node, prop_name, 0);
 
 	if (!regnode) {
 		dev_dbg(dev, "Looking up %s property in node %s failed",
-				prop_name, dev->of_node->full_name);
+				prop_name, node->full_name);
 		return NULL;
 	}
 	return regnode;
@@ -1268,6 +1279,7 @@ static void regulator_supply_alias(struct device **dev, const char **supply)
 
 static struct regulator_dev *regulator_dev_lookup(struct device *dev,
 						  const char *supply,
+						  struct device_node *np,
 						  int *ret)
 {
 	struct regulator_dev *r;
@@ -1278,8 +1290,8 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
 	regulator_supply_alias(&dev, &supply);
 
 	/* first do a dt based lookup */
-	if (dev && dev->of_node) {
-		node = of_get_regulator(dev, supply);
+	if ((dev && dev->of_node) || np) {
+		node = of_get_regulator_by_node(dev, supply, np);
 		if (node) {
 			list_for_each_entry(r, &regulator_list, list)
 				if (r->dev.parent &&
@@ -1322,6 +1334,7 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
 
 /* Internal regulator request function */
 static struct regulator *_regulator_get(struct device *dev, const char *id,
+					struct device_node *node,
 					bool exclusive, bool allow_dummy)
 {
 	struct regulator_dev *rdev;
@@ -1344,7 +1357,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_lookup(dev, id, node, &ret);
 	if (rdev)
 		goto found;
 
@@ -1431,7 +1444,7 @@ out:
  */
 struct regulator *regulator_get(struct device *dev, const char *id)
 {
-	return _regulator_get(dev, id, false, true);
+	return _regulator_get(dev, id, NULL, false, true);
 }
 EXPORT_SYMBOL_GPL(regulator_get);
 
@@ -1458,7 +1471,7 @@ EXPORT_SYMBOL_GPL(regulator_get);
  */
 struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
 {
-	return _regulator_get(dev, id, true, false);
+	return _regulator_get(dev, id, NULL, true, false);
 }
 EXPORT_SYMBOL_GPL(regulator_get_exclusive);
 
@@ -1484,10 +1497,91 @@ EXPORT_SYMBOL_GPL(regulator_get_exclusive);
  */
 struct regulator *regulator_get_optional(struct device *dev, const char *id)
 {
-	return _regulator_get(dev, id, false, false);
+	return _regulator_get(dev, id, NULL, false, false);
 }
 EXPORT_SYMBOL_GPL(regulator_get_optional);
 
+/**
+ * of_regulator_get - lookup and obtain a reference to a regulator.
+ * @dev: device for regulator "consumer"
+ * @node: device node for which to get the regulator
+ * @id: Supply name or regulator ID.
+ *
+ * Returns a struct regulator corresponding to the regulator producer,
+ * or IS_ERR() condition containing errno.
+ *
+ * Use of supply names configured via regulator_set_device_supply() is
+ * strongly encouraged.  It is recommended that the supply name used
+ * should match the name used for the supply and/or the relevant
+ * device pins in the datasheet.
+ */
+struct regulator *of_regulator_get(struct device *dev,
+				   const char *id,
+				struct device_node *node)
+{
+	return _regulator_get(dev, id, node, false, true);
+}
+EXPORT_SYMBOL_GPL(of_regulator_get);
+
+/**
+ * of_regulator_get_exclusive - obtain exclusive access to a regulator.
+ * @dev: device for regulator "consumer"
+ * @node: device node for which to get the regulator
+ * @id: Supply name or regulator ID.
+ *
+ * Returns a struct regulator corresponding to the regulator producer,
+ * or IS_ERR() condition containing errno.  Other consumers will be
+ * unable to obtain this regulator while this reference is held and the
+ * use count for the regulator will be initialised to reflect the current
+ * state of the regulator.
+ *
+ * This is intended for use by consumers which cannot tolerate shared
+ * use of the regulator such as those which need to force the
+ * regulator off for correct operation of the hardware they are
+ * controlling.
+ *
+ * Use of supply names configured via regulator_set_device_supply() is
+ * strongly encouraged.  It is recommended that the supply name used
+ * should match the name used for the supply and/or the relevant
+ * device pins in the datasheet.
+ */
+struct regulator *of_regulator_get_exclusive(struct device *dev,
+					     const char *id,
+					     struct device_node *node)
+{
+	return _regulator_get(dev, id, node, true, false);
+}
+EXPORT_SYMBOL_GPL(of_regulator_get_exclusive);
+
+/**
+ * of_regulator_get_optional - obtain optional access to a regulator.
+ * @dev: device for regulator "consumer"
+ * @node: device node for which to get the regulator
+ * @id: Supply name or regulator ID.
+ *
+ * Returns a struct regulator corresponding to the regulator producer,
+ * or IS_ERR() condition containing errno.
+ *
+ * This is intended for use by consumers for devices which can have
+ * some supplies unconnected in normal use, such as some MMC devices.
+ * It can allow the regulator core to provide stub supplies for other
+ * supplies requested using normal regulator_get() calls without
+ * disrupting the operation of drivers that can handle absent
+ * supplies.
+ *
+ * Use of supply names configured via regulator_set_device_supply() is
+ * strongly encouraged.  It is recommended that the supply name used
+ * should match the name used for the supply and/or the relevant
+ * device pins in the datasheet.
+ */
+struct regulator *of_regulator_get_optional(struct device *dev,
+					    const char *id,
+					    struct device_node *node)
+{
+	return _regulator_get(dev, id, node, false, false);
+}
+EXPORT_SYMBOL_GPL(of_regulator_get_optional);
+
 /* Locks held by regulator_put() */
 static void _regulator_put(struct regulator *regulator)
 {
@@ -3714,7 +3808,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_lookup(dev, supply, NULL, &ret);
 
 		if (ret == -ENODEV) {
 			/*
diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c
index 8f785bc9e510..755fc07ebc33 100644
--- a/drivers/regulator/devres.c
+++ b/drivers/regulator/devres.c
@@ -30,7 +30,9 @@ static void devm_regulator_release(struct device *dev, void *res)
 	regulator_put(*(struct regulator **)res);
 }
 
-static struct regulator *_devm_regulator_get(struct device *dev, const char *id,
+static struct regulator *_devm_regulator_get(struct device *dev,
+					     const char *id,
+					     struct device_node *node,
 					     int get_type)
 {
 	struct regulator **ptr, *regulator;
@@ -41,13 +43,13 @@ static struct regulator *_devm_regulator_get(struct device *dev, const char *id,
 
 	switch (get_type) {
 	case NORMAL_GET:
-		regulator = regulator_get(dev, id);
+		regulator = of_regulator_get(dev, id, node);
 		break;
 	case EXCLUSIVE_GET:
-		regulator = regulator_get_exclusive(dev, id);
+		regulator = of_regulator_get_exclusive(dev, id, node);
 		break;
 	case OPTIONAL_GET:
-		regulator = regulator_get_optional(dev, id);
+		regulator = of_regulator_get_optional(dev, id, node);
 		break;
 	default:
 		regulator = ERR_PTR(-EINVAL);
@@ -74,7 +76,7 @@ static struct regulator *_devm_regulator_get(struct device *dev, const char *id,
  */
 struct regulator *devm_regulator_get(struct device *dev, const char *id)
 {
-	return _devm_regulator_get(dev, id, NORMAL_GET);
+	return _devm_regulator_get(dev, id, NULL, NORMAL_GET);
 }
 EXPORT_SYMBOL_GPL(devm_regulator_get);
 
@@ -90,7 +92,7 @@ EXPORT_SYMBOL_GPL(devm_regulator_get);
 struct regulator *devm_regulator_get_exclusive(struct device *dev,
 					       const char *id)
 {
-	return _devm_regulator_get(dev, id, EXCLUSIVE_GET);
+	return _devm_regulator_get(dev, id, NULL, EXCLUSIVE_GET);
 }
 EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
 
@@ -106,10 +108,64 @@ EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
 struct regulator *devm_regulator_get_optional(struct device *dev,
 					      const char *id)
 {
-	return _devm_regulator_get(dev, id, OPTIONAL_GET);
+	return _devm_regulator_get(dev, id, NULL, OPTIONAL_GET);
 }
 EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
 
+/**
+ * devm_regulator_get - Resource managed regulator_get()
+ * @dev: device for regulator "consumer"
+ * @node: device node for which to get the regulator
+ * @id: Supply name or regulator ID.
+ *
+ * Managed regulator_get(). Regulators returned from this function are
+ * automatically regulator_put() on driver detach. See regulator_get()
+ * for more information.
+ */
+struct regulator *devm_of_regulator_get(struct device *dev,
+					const char *id,
+					struct device_node *node)
+{
+	return _devm_regulator_get(dev, id, node, NORMAL_GET);
+}
+EXPORT_SYMBOL_GPL(devm_of_regulator_get);
+
+/**
+ * devm_regulator_get_exclusive - Resource managed regulator_get_exclusive()
+ * @dev: device for regulator "consumer"
+ * @node: device node for which to get the regulator
+ * @id: Supply name or regulator ID.
+ *
+ * Managed regulator_get_exclusive(). Regulators returned from this
+ * function are automatically regulator_put() on driver detach. See
+ * regulator_get_exclusive() for more information.
+ */
+struct regulator *devm_of_regulator_get_exclusive(struct device *dev,
+						 const char *id,
+						 struct device_node *node)
+{
+	return _devm_regulator_get(dev, id, node, EXCLUSIVE_GET);
+}
+EXPORT_SYMBOL_GPL(devm_of_regulator_get_exclusive);
+
+/**
+ * devm_regulator_get_optional - Resource managed regulator_get_optional()
+ * @dev: device for regulator "consumer"
+ * @node: device node for which to get the regulator
+ * @id: Supply name or regulator ID.
+ *
+ * Managed regulator_get_optional(). Regulators returned from this
+ * function are automatically regulator_put() on driver detach. See
+ * regulator_get_optional() for more information.
+ */
+struct regulator *devm_of_regulator_get_optional(struct device *dev,
+						 const char *id,
+						 struct device_node *node)
+{
+	return _devm_regulator_get(dev, id, node, OPTIONAL_GET);
+}
+EXPORT_SYMBOL_GPL(devm_of_regulator_get_optional);
+
 static int devm_regulator_match(struct device *dev, void *res, void *data)
 {
 	struct regulator **r = res;
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index d17e1ff7ad01..1c88ce1aaa3f 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -40,6 +40,7 @@
 struct device;
 struct notifier_block;
 struct regmap;
+struct device_node;
 
 /*
  * Regulator operating modes.
@@ -162,14 +163,33 @@ struct regulator *__must_check regulator_get(struct device *dev,
 					     const char *id);
 struct regulator *__must_check devm_regulator_get(struct device *dev,
 					     const char *id);
+struct regulator *__must_check of_regulator_get(struct device *dev,
+						const char *id,
+						struct device_node *node);
+struct regulator *__must_check devm_of_regulator_get(struct device *dev,
+						const char *id,
+						struct device_node *node);
 struct regulator *__must_check regulator_get_exclusive(struct device *dev,
 						       const char *id);
 struct regulator *__must_check devm_regulator_get_exclusive(struct device *dev,
 							const char *id);
+struct regulator *__must_check of_regulator_get_exclusive(struct device *dev,
+						      const char *id,
+						      struct device_node *node);
+struct regulator *__must_check devm_of_regulator_get_exclusive(struct device *dev,
+						      const char *id,
+						      struct device_node *node);
 struct regulator *__must_check regulator_get_optional(struct device *dev,
 						      const char *id);
 struct regulator *__must_check devm_regulator_get_optional(struct device *dev,
 							   const char *id);
+struct regulator *__must_check of_regulator_get_optional(struct device *dev,
+						      const char *id,
+						      struct device_node *node);
+struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev,
+						      const char *id,
+						      struct device_node *node);
+
 void regulator_put(struct regulator *regulator);
 void devm_regulator_put(struct regulator *regulator);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ