[PATCH v1] gpio: mpc8xxx: add set_flags/get_flags ops

Vincent Jardin vjardin at free.fr
Thu Jul 2 17:09:49 CEST 2026


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 at free.fr>

---

 drivers/gpio/mpc8xxx_gpio.c | 54 +++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

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[] = {
-- 
2.43.0

base-commit: f605dcee103c897b6f1a8873549a36949bd4e2a1
branch: for-upstream/gpio-mpc8xxx-set-flags


More information about the U-Boot mailing list