mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH] pinctrl: support selecting states from command line
@ 2025-10-27  6:39 Ahmad Fatoum
  2025-10-28  7:46 ` Sascha Hauer
  0 siblings, 1 reply; 2+ messages in thread
From: Ahmad Fatoum @ 2025-10-27  6:39 UTC (permalink / raw)
  To: barebox; +Cc: Ahmad Fatoum

This can be useful for debugging to exercise pinctrl for nodes that have
no driver yet. Example:

  setenv adc-joystick.of.pinctrl_state=default

Signed-off-by: Ahmad Fatoum <a.fatoum@barebox.org>
---
 drivers/base/driver.c     |  4 ++
 drivers/pinctrl/Kconfig   |  4 ++
 drivers/pinctrl/pinctrl.c | 92 +++++++++++++++++++++++++++++++++++++++
 include/param.h           |  2 +
 include/pinctrl.h         | 10 +++++
 lib/parameter.c           |  6 ++-
 6 files changed, 116 insertions(+), 2 deletions(-)

diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 61118385f1df..33d9e2bcde5a 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -268,6 +268,8 @@ int register_device(struct device *new_device)
 
 	bobject_init(&new_device->bobject);
 
+	of_pinctrl_register_consumer(new_device, new_device->device_node);
+
 	if (new_device->bus) {
 		if (!new_device->parent)
 			new_device->parent = &new_device->bus->dev;
@@ -298,6 +300,8 @@ int unregister_device(struct device *old_dev)
 
 	bobject_del(&old_dev->bobject);
 
+	of_pinctrl_unregister_consumer(old_dev);
+
 	if (old_dev->driver)
 		device_remove(old_dev);
 
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 72ca79aa9880..1d237db106ba 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -10,6 +10,10 @@ config PINCTRL
 	  from the devicetree. Legacy drivers here may not need this core
 	  support but instead provide their own SoC specific APIs
 
+config PINCTRL_STATE_PARAM
+	bool "pinctrl state control via device parameters"
+	depends on PARAMETER && PINCTRL
+
 # The following drivers are needed even without PINCTRL because
 # the either have a legacy iomux interface or also register a gpio
 # chip.
diff --git a/drivers/pinctrl/pinctrl.c b/drivers/pinctrl/pinctrl.c
index 106a4423184c..2f85a0f08f08 100644
--- a/drivers/pinctrl/pinctrl.c
+++ b/drivers/pinctrl/pinctrl.c
@@ -7,6 +7,7 @@
 #include <common.h>
 #include <malloc.h>
 #include <pinctrl.h>
+#include <linux/overflow.h>
 #include <errno.h>
 #include <of.h>
 
@@ -14,10 +15,20 @@ struct pinctrl {
 	struct device_node consumer_np;
 };
 
+static LIST_HEAD(pinctrl_consumer_list);
+
 struct pinctrl_state {
 	struct property prop;
 };
 
+struct pinctrl_consumer_info {
+	struct device *dev;
+	struct device_node *np;
+	int state;
+	struct list_head list;
+	const char *states[];
+};
+
 LIST_HEAD(pinctrl_list);
 
 static struct pinctrl_device *pin_to_pinctrl(unsigned int pin)
@@ -104,6 +115,33 @@ of_property_pinctrl_get_state(struct property *prop)
 	return container_of(prop, struct pinctrl_state, prop);
 }
 
+static void pinctrl_update_state_param(struct pinctrl *pinctrl,
+				       struct pinctrl_state *state)
+{
+	struct device_node *np = &pinctrl->consumer_np;
+	struct property *prop = &state->prop;
+	struct pinctrl_consumer_info *info;
+	u16 idx;
+	int ret;
+
+	if (!IS_ENABLED(CONFIG_PINCTRL_STATE_PARAM))
+		return;
+
+	if (!strstarts(prop->name, "pinctrl-"))
+		return;
+
+	ret = kstrtou16(&prop->name[sizeof("pinctrl-") - 1], 10, &idx);
+	if (ret)
+		return;
+
+	list_for_each_entry(info, &pinctrl_consumer_list, list) {
+		if (info->np != np)
+			continue;
+
+		info->state = idx;
+	}
+}
+
 struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *pinctrl,
 					   const char *name)
 {
@@ -173,6 +211,8 @@ int pinctrl_select_state(struct pinctrl *pinctrl, struct pinctrl_state *state)
 		if (ret < 0)
 			goto err;
 	}
+
+	pinctrl_update_state_param(pinctrl, state);
 err:
 	return ret;
 }
@@ -238,3 +278,55 @@ void pinctrl_unregister(struct pinctrl_device *pdev)
 {
 	list_del(&pdev->list);
 }
+
+
+#ifdef CONFIG_PINCTRL_STATE_PARAM
+static int pinctrl_state_param_set(struct param_d *p, void *priv)
+{
+	struct pinctrl_consumer_info *info = priv;
+
+	return of_pinctrl_select_state(info->np, info->states[info->state]);
+}
+
+void of_pinctrl_register_consumer(struct device *dev,
+				  struct device_node *np)
+{
+	struct pinctrl_consumer_info *info;
+	int ret, nstates;
+
+	nstates = of_property_count_strings(np, "pinctrl-names");
+	if (nstates <= 0)
+		return;
+
+	info = malloc(struct_size(info, states, nstates));
+	if (!info)
+		return;
+
+	info->dev = dev;
+	info->np = np;
+	info->state = PARAM_ENUM_UNKNOWN;
+
+	ret = of_property_read_string_array(np, "pinctrl-names", info->states, nstates);
+	if (ret < 0)
+		return;
+
+	list_add(&info->list, &pinctrl_consumer_list);
+
+	dev_add_param_enum(dev, "pinctrl_state",
+			   pinctrl_state_param_set, NULL,
+			   &info->state, info->states, nstates, info);
+}
+
+void of_pinctrl_unregister_consumer(struct device *dev)
+{
+	struct pinctrl_consumer_info *info;
+
+	list_for_each_entry(info, &pinctrl_consumer_list, list) {
+		if (info->dev != dev)
+			continue;
+
+		list_del(&info->list);
+		return;
+	}
+}
+#endif
diff --git a/include/param.h b/include/param.h
index 59aa8a3a385f..1713a18c378e 100644
--- a/include/param.h
+++ b/include/param.h
@@ -42,6 +42,8 @@ struct param_d {
 	enum param_type type;
 };
 
+#define PARAM_ENUM_UNKNOWN	(-1000000)
+
 enum param_tristate { PARAM_TRISTATE_UNKNOWN, PARAM_TRISTATE_TRUE, PARAM_TRISTATE_FALSE };
 
 #ifdef CONFIG_PARAMETER
diff --git a/include/pinctrl.h b/include/pinctrl.h
index 4ba7b489345b..5c031fb4008b 100644
--- a/include/pinctrl.h
+++ b/include/pinctrl.h
@@ -25,4 +25,14 @@ struct pinctrl_device {
 int pinctrl_register(struct pinctrl_device *pdev);
 void pinctrl_unregister(struct pinctrl_device *pdev);
 
+#ifdef CONFIG_PINCTRL_STATE_PARAM
+void of_pinctrl_register_consumer(struct device *dev, struct device_node *np);
+void of_pinctrl_unregister_consumer(struct device *dev);
+#else
+static inline void of_pinctrl_register_consumer(struct device *dev, struct device_node *np)
+{
+}
+static inline void of_pinctrl_unregister_consumer(struct device *dev) {}
+#endif
+
 #endif /* PINCTRL_H */
diff --git a/lib/parameter.c b/lib/parameter.c
index f36d77d119fa..b9a449c32657 100644
--- a/lib/parameter.c
+++ b/lib/parameter.c
@@ -612,7 +612,9 @@ static const char *param_enum_get(struct bobject *bobj, struct param_d *p)
 
 	free(p->value);
 
-	if (*pe->value >= pe->num_names)
+	if (*pe->value == PARAM_ENUM_UNKNOWN)
+		p->value = strdup("unknown");
+	else if (*pe->value >= pe->num_names)
 		p->value = basprintf("invalid:%d", *pe->value);
 	else
 		p->value = strdup(pe->names[*pe->value]);
@@ -625,7 +627,7 @@ static void param_enum_info(struct param_d *p)
 	struct param_enum *pe = to_param_enum(p);
 	int i;
 
-	if (pe->num_names <= 1)
+	if (pe->num_names <= 1 && *pe->value != PARAM_ENUM_UNKNOWN)
 		return;
 
 	printf(" (values: ");
-- 
2.47.3




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

* Re: [PATCH] pinctrl: support selecting states from command line
  2025-10-27  6:39 [PATCH] pinctrl: support selecting states from command line Ahmad Fatoum
@ 2025-10-28  7:46 ` Sascha Hauer
  0 siblings, 0 replies; 2+ messages in thread
From: Sascha Hauer @ 2025-10-28  7:46 UTC (permalink / raw)
  To: barebox, Ahmad Fatoum


On Mon, 27 Oct 2025 07:39:00 +0100, Ahmad Fatoum wrote:
> This can be useful for debugging to exercise pinctrl for nodes that have
> no driver yet. Example:
> 
>   setenv adc-joystick.of.pinctrl_state=default
> 
> 

Applied, thanks!

[1/1] pinctrl: support selecting states from command line
      https://git.pengutronix.de/cgit/barebox/commit/?id=27ae60915e43 (link may not be stable)

Best regards,
-- 
Sascha Hauer <s.hauer@pengutronix.de>




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

end of thread, other threads:[~2025-10-28  7:46 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-10-27  6:39 [PATCH] pinctrl: support selecting states from command line Ahmad Fatoum
2025-10-28  7:46 ` Sascha Hauer

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