summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Jardin <vjardin@free.fr>2026-07-02 17:09:49 +0200
committerPeng Fan <peng.fan@nxp.com>2026-07-06 09:59:58 +0800
commitd74dea04e3a15d38d6139776cdda99c376e9e3e9 (patch)
tree52b47bffd278280a897771be857f88fdb0517377
parent8d3963a0971caa4b0b16c1e531cee5eeea20c865 (diff)
downloadu-boot-d74dea04e3a15d38d6139776cdda99c376e9e3e9.tar.gz
u-boot-d74dea04e3a15d38d6139776cdda99c376e9e3e9.zip
gpio: mpc8xxx: add set_flags/get_flags ops
mpc8xxx_gpio_open_drain_on() / _off() helpers can program GPODR (open-drain enable) on QorIQ silicon, but they are not called. The open-drain capability is therefore unreachable from the GPIO uclass. Adding a set_flags op for the GPIOD_OPEN_DRAIN, plus a get_flags for the reports of state by reading GPDIR and GPODR back. For existing callers, it is unchanged: direction_input, direction_output, get_value, set_value and get_function still drive the same registers as before. The new ops only become observable when a caller explicitly asks for the GPIOD_OPEN_DRAIN flag (or queries flags via the uclass). Signed-off-by: Vincent Jardin <vjardin@free.fr> Signed-off-by: Peng Fan <peng.fan@nxp.com>
-rw-r--r--drivers/gpio/mpc8xxx_gpio.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/drivers/gpio/mpc8xxx_gpio.c b/drivers/gpio/mpc8xxx_gpio.c
index 709d04017d1..40646407369 100644
--- a/drivers/gpio/mpc8xxx_gpio.c
+++ b/drivers/gpio/mpc8xxx_gpio.c
@@ -171,6 +171,58 @@ static int mpc8xxx_gpio_get_function(struct udevice *dev, uint gpio)
return dir ? GPIOF_OUTPUT : GPIOF_INPUT;
}
+static int mpc8xxx_gpio_set_flags(struct udevice *dev, uint gpio,
+ ulong flags)
+{
+ u32 mask = gpio_mask(gpio);
+ int ret;
+
+ /* The QorIQ GPIO pad supports open-drain only; open-source has
+ * no silicon counterpart, so reject it rather than silently
+ * pretending.
+ */
+ if (flags & GPIOD_OPEN_SOURCE)
+ return -EOPNOTSUPP;
+
+ /* GPODR is per-pin and meaningful in both directions (it stays
+ * latched when the pin is re-purposed), so apply it before the
+ * direction change.
+ */
+ if (flags & GPIOD_OPEN_DRAIN)
+ mpc8xxx_gpio_open_drain_on(dev, mask);
+ else
+ mpc8xxx_gpio_open_drain_off(dev, mask);
+
+ if (flags & GPIOD_IS_OUT) {
+ ret = mpc8xxx_gpio_direction_output(dev, gpio,
+ !!(flags & GPIOD_IS_OUT_ACTIVE));
+ } else if (flags & GPIOD_IS_IN) {
+ ret = mpc8xxx_gpio_direction_input(dev, gpio);
+ } else {
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static int mpc8xxx_gpio_get_flags(struct udevice *dev, uint gpio,
+ ulong *flagsp)
+{
+ u32 mask = gpio_mask(gpio);
+ ulong flags = 0;
+
+ if (mpc8xxx_gpio_get_dir(dev, mask))
+ flags |= GPIOD_IS_OUT;
+ else
+ flags |= GPIOD_IS_IN;
+
+ if (mpc8xxx_gpio_open_drain_val(dev, mask))
+ flags |= GPIOD_OPEN_DRAIN;
+
+ *flagsp = flags;
+ return 0;
+}
+
#if CONFIG_IS_ENABLED(OF_CONTROL)
static int mpc8xxx_gpio_of_to_plat(struct udevice *dev)
{
@@ -255,6 +307,8 @@ static const struct dm_gpio_ops gpio_mpc8xxx_ops = {
.get_value = mpc8xxx_gpio_get_value,
.set_value = mpc8xxx_gpio_set_value,
.get_function = mpc8xxx_gpio_get_function,
+ .set_flags = mpc8xxx_gpio_set_flags,
+ .get_flags = mpc8xxx_gpio_get_flags,
};
static const struct udevice_id mpc8xxx_gpio_ids[] = {