aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2024-10-02 12:20:16 +0200
committerUlf Hansson <ulf.hansson@linaro.org>2024-10-02 12:20:16 +0200
commit576cc535ce4ea85e900384766c4cb113750d4b69 (patch)
tree8dd66f4ddf330f858e07e1041f73c891c081a5b2
parentOPP: fix error code in dev_pm_opp_set_config() (diff)
parentregulator: Add devres version of of_regulator_get_optional() (diff)
downloadwireguard-linux-576cc535ce4ea85e900384766c4cb113750d4b69.tar.xz
wireguard-linux-576cc535ce4ea85e900384766c4cb113750d4b69.zip
Merge tag 'regulator-of-get-optional' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator
regulator: Add of_regulator_get_optional() APIs Add of_regulator_get_optional() APIs, which can be used by generic code to improve integration of regulator management helpers for their users. Merge this into the pmdomain tree to allow new users to be added.
Diffstat (limited to '')
-rw-r--r--drivers/regulator/core.c4
-rw-r--r--drivers/regulator/devres.c39
-rw-r--r--drivers/regulator/internal.h18
-rw-r--r--drivers/regulator/of_regulator.c51
-rw-r--r--include/linux/regulator/consumer.h37
5 files changed, 135 insertions, 14 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 1179766811f5..d0b3879f2746 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1959,8 +1959,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) {
- r = of_regulator_dev_lookup(dev, supply);
+ if (dev_of_node(dev)) {
+ r = of_regulator_dev_lookup(dev, dev_of_node(dev), supply);
if (!IS_ERR(r))
return r;
if (PTR_ERR(r) == -EPROBE_DEFER)
diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c
index 1b893cdd1aad..36164aec30e8 100644
--- a/drivers/regulator/devres.c
+++ b/drivers/regulator/devres.c
@@ -749,3 +749,42 @@ void *devm_regulator_irq_helper(struct device *dev,
return ptr;
}
EXPORT_SYMBOL_GPL(devm_regulator_irq_helper);
+
+#if IS_ENABLED(CONFIG_OF)
+static struct regulator *_devm_of_regulator_get(struct device *dev, struct device_node *node,
+ const char *id, int get_type)
+{
+ struct regulator **ptr, *regulator;
+
+ ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ regulator = _of_regulator_get(dev, node, id, get_type);
+ if (!IS_ERR(regulator)) {
+ *ptr = regulator;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return regulator;
+}
+
+/**
+ * devm_of_regulator_get_optional - Resource managed of_regulator_get_optional()
+ * @dev: device used for dev_printk() messages and resource lifetime management
+ * @node: device node for regulator "consumer"
+ * @id: supply name or regulator ID.
+ *
+ * Managed regulator_get_optional(). Regulators returned from this
+ * function are automatically regulator_put() on driver detach. See
+ * of_regulator_get_optional() for more information.
+ */
+struct regulator *devm_of_regulator_get_optional(struct device *dev, struct device_node *node,
+ const char *id)
+{
+ return _devm_of_regulator_get(dev, node, id, OPTIONAL_GET);
+}
+EXPORT_SYMBOL_GPL(devm_of_regulator_get_optional);
+#endif
diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h
index 5b43f802468d..b3d48dc38bc4 100644
--- a/drivers/regulator/internal.h
+++ b/drivers/regulator/internal.h
@@ -65,14 +65,25 @@ static inline struct regulator_dev *dev_to_rdev(struct device *dev)
return container_of(dev, struct regulator_dev, dev);
}
+enum regulator_get_type {
+ NORMAL_GET,
+ EXCLUSIVE_GET,
+ OPTIONAL_GET,
+ MAX_GET_TYPE
+};
+
#ifdef CONFIG_OF
struct regulator_dev *of_regulator_dev_lookup(struct device *dev,
+ struct device_node *np,
const char *supply);
struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
const struct regulator_desc *desc,
struct regulator_config *config,
struct device_node **node);
+struct regulator *_of_regulator_get(struct device *dev, struct device_node *node,
+ const char *id, enum regulator_get_type get_type);
+
struct regulator_dev *of_parse_coupled_regulator(struct regulator_dev *rdev,
int index);
@@ -82,6 +93,7 @@ bool of_check_coupling_data(struct regulator_dev *rdev);
#else
static inline struct regulator_dev *of_regulator_dev_lookup(struct device *dev,
+ struct device_node *np,
const char *supply)
{
return ERR_PTR(-ENODEV);
@@ -114,12 +126,6 @@ static inline bool of_check_coupling_data(struct regulator_dev *rdev)
}
#endif
-enum regulator_get_type {
- NORMAL_GET,
- EXCLUSIVE_GET,
- OPTIONAL_GET,
- MAX_GET_TYPE
-};
int _regulator_get_common_check(struct device *dev, const char *id,
enum regulator_get_type get_type);
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 3f490d81abc2..3d85762beda6 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -588,7 +588,8 @@ err_node_put:
/**
* of_get_regulator - get a regulator device node based on supply name
- * @dev: Device pointer for the consumer (of regulator) device
+ * @dev: Device pointer for dev_printk() messages
+ * @node: Device node pointer for supply property lookup
* @supply: regulator supply name
*
* Extract the regulator device node corresponding to the supply name.
@@ -596,15 +597,16 @@ err_node_put:
* Return: Pointer to the &struct device_node corresponding to the regulator
* if found, or %NULL if not found.
*/
-static struct device_node *of_get_regulator(struct device *dev, const char *supply)
+static struct device_node *of_get_regulator(struct device *dev, struct device_node *node,
+ const char *supply)
{
struct device_node *regnode = NULL;
char prop_name[64]; /* 64 is max size of property name */
- dev_dbg(dev, "Looking up %s-supply from device tree\n", supply);
+ dev_dbg(dev, "Looking up %s-supply from device node %pOF\n", supply, node);
snprintf(prop_name, 64, "%s-supply", supply);
- regnode = of_parse_phandle(dev->of_node, prop_name, 0);
+ regnode = of_parse_phandle(node, prop_name, 0);
if (regnode)
return regnode;
@@ -628,6 +630,7 @@ static struct regulator_dev *of_find_regulator_by_node(struct device_node *np)
/**
* of_regulator_dev_lookup - lookup a regulator device with device tree only
* @dev: Device pointer for regulator supply lookup.
+ * @np: Device node pointer for regulator supply lookup.
* @supply: Supply name or regulator ID.
*
* Return: Pointer to the &struct regulator_dev on success, or ERR_PTR()
@@ -642,13 +645,13 @@ static struct regulator_dev *of_find_regulator_by_node(struct device_node *np)
* * -%ENODEV if lookup fails permanently.
* * -%EPROBE_DEFER if lookup could succeed in the future.
*/
-struct regulator_dev *of_regulator_dev_lookup(struct device *dev,
+struct regulator_dev *of_regulator_dev_lookup(struct device *dev, struct device_node *np,
const char *supply)
{
struct regulator_dev *r;
struct device_node *node;
- node = of_get_regulator(dev, supply);
+ node = of_get_regulator(dev, np, supply);
if (node) {
r = of_find_regulator_by_node(node);
of_node_put(node);
@@ -665,6 +668,42 @@ struct regulator_dev *of_regulator_dev_lookup(struct device *dev,
return ERR_PTR(-ENODEV);
}
+struct regulator *_of_regulator_get(struct device *dev, struct device_node *node,
+ const char *id, enum regulator_get_type get_type)
+{
+ struct regulator_dev *r;
+ int ret;
+
+ ret = _regulator_get_common_check(dev, id, get_type);
+ if (ret)
+ return ERR_PTR(ret);
+
+ r = of_regulator_dev_lookup(dev, node, id);
+ return _regulator_get_common(r, dev, id, get_type);
+}
+
+/**
+ * of_regulator_get_optional - get optional regulator via device tree lookup
+ * @dev: device used for dev_printk() messages
+ * @node: device node for regulator "consumer"
+ * @id: Supply name
+ *
+ * Return: pointer to struct regulator corresponding to the regulator producer,
+ * or PTR_ERR() encoded error number.
+ *
+ * This is intended for use by consumers that want to get a regulator
+ * supply directly from a device node, and can and want to deal with
+ * absence of such supplies. This will _not_ consider supply aliases.
+ * See regulator_dev_lookup().
+ */
+struct regulator *of_regulator_get_optional(struct device *dev,
+ struct device_node *node,
+ const char *id)
+{
+ return _of_regulator_get(dev, node, id, OPTIONAL_GET);
+}
+EXPORT_SYMBOL_GPL(of_regulator_get_optional);
+
/*
* Returns number of regulators coupled with rdev.
*/
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index b9ce521910a0..8c3c372ad735 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -168,6 +168,29 @@ int devm_regulator_get_enable_read_voltage(struct device *dev, const char *id);
void regulator_put(struct regulator *regulator);
void devm_regulator_put(struct regulator *regulator);
+#if IS_ENABLED(CONFIG_OF)
+struct regulator *__must_check of_regulator_get_optional(struct device *dev,
+ struct device_node *node,
+ const char *id);
+struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev,
+ struct device_node *node,
+ const char *id);
+#else
+static inline struct regulator *__must_check of_regulator_get_optional(struct device *dev,
+ struct device_node *node,
+ const char *id)
+{
+ return ERR_PTR(-ENODEV);
+}
+
+static inline struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev,
+ struct device_node *node,
+ const char *id)
+{
+ return ERR_PTR(-ENODEV);
+}
+#endif
+
int regulator_register_supply_alias(struct device *dev, const char *id,
struct device *alias_dev,
const char *alias_id);
@@ -350,6 +373,20 @@ devm_regulator_get_optional(struct device *dev, const char *id)
return ERR_PTR(-ENODEV);
}
+static inline struct regulator *__must_check of_regulator_get_optional(struct device *dev,
+ struct device_node *node,
+ const char *id)
+{
+ return ERR_PTR(-ENODEV);
+}
+
+static inline struct regulator *__must_check devm_of_regulator_get_optional(struct device *dev,
+ struct device_node *node,
+ const char *id)
+{
+ return ERR_PTR(-ENODEV);
+}
+
static inline void regulator_put(struct regulator *regulator)
{
}