[PATCH v2 3/3] pinctrl: implement pinctrl_lookup_state/select_state

Ahmad Fatoum a.fatoum at pengutronix.de
Tue May 21 05:13:57 PDT 2024


From: Ahmad Fatoum <ahmad at a3f.at>

Besides pinctrl_get_select, the Linux API provides separate functions to
lookup a state and verify its existence and activating a state.

To make porting code easier that calls the former during probe and the
latter at runtime, define these functions and implement
of_pinctrl_select_state on top of them.

No functional change intended.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
v1 -> v2:
  - remove out of place semicolon in !CONFIG_PINCTRL stubs
---
 drivers/pinctrl/pinctrl.c        | 98 ++++++++++++++++++++++----------
 include/linux/pinctrl/consumer.h | 23 ++++++++
 2 files changed, 90 insertions(+), 31 deletions(-)

diff --git a/drivers/pinctrl/pinctrl.c b/drivers/pinctrl/pinctrl.c
index 2d331211f71c..dd0ed156ec9e 100644
--- a/drivers/pinctrl/pinctrl.c
+++ b/drivers/pinctrl/pinctrl.c
@@ -10,6 +10,14 @@
 #include <errno.h>
 #include <of.h>
 
+struct pinctrl {
+	struct device_node consumer_np;
+};
+
+struct pinctrl_state {
+	struct property prop;
+};
+
 static LIST_HEAD(pinctrl_list);
 
 static struct pinctrl_device *pin_to_pinctrl(unsigned int pin)
@@ -90,30 +98,28 @@ static int pinctrl_config_one(struct device_node *for_node, struct device_node *
 		return -ENODEV;
 }
 
-int of_pinctrl_select_state(struct device_node *np, const char *name)
+static inline struct pinctrl_state *
+of_property_pinctrl_get_state(struct property *prop)
 {
+	return container_of(prop, struct pinctrl_state, prop);
+}
+
+struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *pinctrl,
+					   const char *name)
+{
+	struct device_node *np = &pinctrl->consumer_np;
 	int state, ret;
 	char propname[sizeof("pinctrl-4294967295")];
-	const __be32 *list;
-	int size, config;
-	phandle phandle;
-	struct device_node *np_config;
+	struct property *prop;
 	const char *statename;
 
-	if (!of_find_property(np, "pinctrl-0", NULL))
-		return 0;
-
 	/* For each defined state ID */
 	for (state = 0; ; state++) {
 		/* Retrieve the pinctrl-* property */
 		sprintf(propname, "pinctrl-%d", state);
-		list = of_get_property(np, propname, &size);
-		if (!list) {
-			ret = -ENODEV;
-			break;
-		}
-
-		size /= sizeof(*list);
+		prop = of_find_property(np, propname, NULL);
+		if (!prop)
+			return ERR_PTR(-ENODEV);
 
 		/* Determine whether pinctrl-names property names the state */
 		ret = of_property_read_string_index(np, "pinctrl-names",
@@ -131,31 +137,61 @@ int of_pinctrl_select_state(struct device_node *np, const char *name)
 		if (strcmp(name, statename))
 			continue;
 
-		/* For every referenced pin configuration node in it */
-		for (config = 0; config < size; config++) {
-			phandle = be32_to_cpup(list++);
+		return of_property_pinctrl_get_state(prop);
+	}
 
-			/* Look up the pin configuration node */
-			np_config = of_find_node_by_phandle(phandle);
-			if (!np_config) {
-				pr_err("prop %pOF %s index %i invalid phandle\n",
-					np, propname, config);
-				ret = -EINVAL;
-				goto err;
-			}
+	return ERR_PTR(ret);
+}
 
-			/* Parse the node */
-			ret = pinctrl_config_one(np, np_config);
-			if (ret < 0)
-				goto err;
+int pinctrl_select_state(struct pinctrl *pinctrl, struct pinctrl_state *state)
+{
+	int ret = -ENODEV;
+	const __be32 *list;
+	int size, config;
+	phandle phandle;
+	struct device_node *np = &pinctrl->consumer_np, *np_config;
+	struct property *prop = &state->prop;
+
+	list = of_property_get_value(prop);
+	size = prop->length / sizeof(*list);
+
+	/* For every referenced pin configuration node in it */
+	for (config = 0; config < size; config++) {
+		phandle = be32_to_cpup(list++);
+
+		/* Look up the pin configuration node */
+		np_config = of_find_node_by_phandle(phandle);
+		if (!np_config) {
+			pr_err("prop %pOF %s index %i invalid phandle\n",
+				np, prop->name, config);
+			ret = -EINVAL;
+			goto err;
 		}
 
-		return 0;
+		/* Parse the node */
+		ret = pinctrl_config_one(np, np_config);
+		if (ret < 0)
+			goto err;
 	}
 err:
 	return ret;
 }
 
+int of_pinctrl_select_state(struct device_node *np, const char *name)
+{
+	struct pinctrl *pinctrl = of_pinctrl_get(np);
+	struct pinctrl_state *state;
+
+	if (!of_find_property(np, "pinctrl-0", NULL))
+		return 0;
+
+	state = pinctrl_lookup_state(pinctrl, name);
+	if (IS_ERR(state))
+		return PTR_ERR(state);
+
+	return pinctrl_select_state(pinctrl, state);
+}
+
 int of_pinctrl_select_state_default(struct device_node *np)
 {
 	return of_pinctrl_select_state(np, "default");
diff --git a/include/linux/pinctrl/consumer.h b/include/linux/pinctrl/consumer.h
index 7fd30cd49bd3..c13f9822ab1a 100644
--- a/include/linux/pinctrl/consumer.h
+++ b/include/linux/pinctrl/consumer.h
@@ -4,6 +4,7 @@
 
 #include <linux/errno.h>
 #include <linux/err.h>
+#include <device.h>
 
 struct device;
 struct device_node;
@@ -11,6 +12,9 @@ struct device_node;
 struct pinctrl;
 
 #ifdef CONFIG_PINCTRL
+struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *pinctrl,
+					   const char *name);
+int pinctrl_select_state(struct pinctrl *pinctrl, struct pinctrl_state *state);
 struct pinctrl *pinctrl_get_select(struct device *dev, const char *state);
 int pinctrl_select_state_default(struct device *dev);
 int of_pinctrl_select_state(struct device_node *np, const char *state);
@@ -20,6 +24,15 @@ int pinctrl_gpio_direction_output(unsigned int pin);
 int pinctrl_gpio_get_direction(unsigned pin);
 int pinctrl_single_probe(struct device *dev);
 #else
+static inline struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *pinctrl,
+							 const char *name)
+{
+        return NULL;
+}
+static inline int pinctrl_select_state(struct pinctrl *pinctrl, struct pinctrl_state *state)
+{
+	return 0;
+}
 static inline struct pinctrl *pinctrl_get_select(struct device *dev, const char *state)
 {
 	return ERR_PTR(-ENODEV);
@@ -63,4 +76,14 @@ static inline int pinctrl_single_probe(struct device *dev)
 
 static inline void pinctrl_put(struct pinctrl *pinctrl) {}
 
+static inline struct pinctrl *of_pinctrl_get(struct device_node *np)
+{
+	return (struct pinctrl *)np;
+}
+
+static inline struct pinctrl *pinctrl_get(struct device *dev)
+{
+	return of_pinctrl_get(dev_of_node(dev));
+}
+
 #endif /* LINUX_PINCTRL_CONSUMER_H */
-- 
2.39.2




More information about the barebox mailing list