[PATCH 2/2] gpio: mmio: get the direction from pinctrl when there are no direction registers
Mehmet Fide
mehmet.fide at gmail.com
Tue Sep 1 23:23:52 PDT 2026
From: Mehmet Fide <mehmet.fide at screeningeagle.com>
A generic chip with GPIO_GENERIC_PINCTRL_BACKEND and no direction
registers already sets the direction through pinctrl, but leaves
gc->get_direction unset, so every gpiod_get_direction() call trips the
WARN in gpiolib and the initial line state is guessed. On a Vybrid
Colibri module that is 21 backtraces per boot.
Install a get_direction callback for that combination which asks the
pinctrl backend for PIN_CONFIG_OUTPUT_ENABLE, the same way
gpio-by-pinctrl does it and mirroring how the direction setters are
forwarded. Pins the pin controller cannot answer for report -ENOTSUPP;
gpiolib ignores that when requesting a line and in the debugfs dump, and
such pins cannot change direction through this chip either, as the
setters fail for them too. The one caller that does not ignore it is
gpiochip_lock_as_irq(), which now refuses such a pin as an interrupt
where it previously had nothing to check against.
Suggested-by: Bartosz Golaszewski <brgl at kernel.org>
Signed-off-by: Mehmet Fide <mehmet.fide at screeningeagle.com>
---
drivers/gpio/gpio-mmio.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index 7e4b3e8d609f..b2aa74a734e4 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -49,6 +49,7 @@ o ` ~~~~\___/~~~~ ` controller in FPGA is ,.`
#include <linux/log2.h>
#include <linux/module.h>
#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/pinconf-generic.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/spinlock.h>
@@ -365,6 +366,28 @@ static int gpio_mmio_dir_return(struct gpio_chip *gc, unsigned int gpio,
return pinctrl_gpio_direction_input(gc, gpio);
}
+/*
+ * Without direction registers the direction lives in the pin controller
+ * (Vybrid: the OBE bit in the iomuxc pad), so ask pinctrl.
+ */
+static int gpio_mmio_pinctrl_get_dir(struct gpio_chip *gc, unsigned int gpio)
+{
+ unsigned long config;
+ int ret;
+
+#ifdef CONFIG_PINCTRL
+ if (list_empty(&gc->gpiodev->pin_ranges))
+ return -EOPNOTSUPP;
+#endif
+
+ config = pinconf_to_config_packed(PIN_CONFIG_OUTPUT_ENABLE, 0);
+ ret = pinctrl_gpio_get_config(gc, gpio, &config);
+ if (ret)
+ return ret;
+
+ return config ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
+}
+
static int gpio_mmio_dir_in_err(struct gpio_chip *gc, unsigned int gpio)
{
return -EINVAL;
@@ -601,6 +624,10 @@ static int gpio_mmio_setup_direction(struct gpio_generic_chip *chip,
gc->direction_input = gpio_mmio_dir_in_err;
else
gc->direction_input = gpio_mmio_simple_dir_in;
+
+ if (IS_ENABLED(CONFIG_PINCTRL) &&
+ cfg->flags & GPIO_GENERIC_PINCTRL_BACKEND)
+ gc->get_direction = gpio_mmio_pinctrl_get_dir;
}
return 0;
--
2.54.0
More information about the linux-arm-kernel
mailing list