diff options
| author | Vincent Jardin <vjardin@free.fr> | 2026-07-02 17:09:49 +0200 |
|---|---|---|
| committer | Peng Fan <peng.fan@nxp.com> | 2026-07-06 09:59:58 +0800 |
| commit | d74dea04e3a15d38d6139776cdda99c376e9e3e9 (patch) | |
| tree | 52b47bffd278280a897771be857f88fdb0517377 | |
| parent | 8d3963a0971caa4b0b16c1e531cee5eeea20c865 (diff) | |
| download | u-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.c | 54 |
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[] = { |
