The branch main has been updated by vexeduxr: URL: https://cgit.FreeBSD.org/src/commit/?id=39bdc7d19b1ac1443b1fb7adf81cfa3715625717
commit 39bdc7d19b1ac1443b1fb7adf81cfa3715625717 Author: Ahmad Khalifa <vexed...@freebsd.org> AuthorDate: 2025-08-27 21:24:28 +0000 Commit: Ahmad Khalifa <vexed...@freebsd.org> CommitDate: 2025-08-27 21:38:31 +0000 gpiobus: add pin_config_32 and pin_access_32 Add pin_config_32 and pin_access_32 to the gpiobus interface. These work like the rest of the gpiobus interface. For example, if a child has the following pins in it's ivars: {2, 7 ... 38} calling these functions with pin 1 will configure/access pins 7 - 38 on the controller. Reviewed by: mmel Approved by: imp (mentor) Differential Revision: https://reviews.freebsd.org/D51931 --- sys/dev/gpio/gpiobus.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++ sys/dev/gpio/gpiobus_if.m | 30 +++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c index 650e662e4d86..5723c487e36b 100644 --- a/sys/dev/gpio/gpiobus.c +++ b/sys/dev/gpio/gpiobus.c @@ -1015,6 +1015,56 @@ gpiobus_pin_toggle(device_t dev, device_t child, uint32_t pin) return (GPIO_PIN_TOGGLE(sc->sc_dev, devi->pins[pin])); } +/* + * Verify that a child has all the pins they are requesting + * to access in their ivars. + */ +static bool +gpiobus_pin_verify_32(struct gpiobus_ivar *devi, uint32_t first_pin, + uint32_t num_pins) +{ + if (first_pin + num_pins > devi->npins) + return (false); + + /* Make sure the pins are consecutive. */ + for (uint32_t pin = first_pin; pin < first_pin + num_pins - 1; pin++) { + if (devi->pins[pin] + 1 != devi->pins[pin + 1]) + return (false); + } + + return (true); +} + +static int +gpiobus_pin_access_32(device_t dev, device_t child, uint32_t first_pin, + uint32_t clear_pins, uint32_t change_pins, uint32_t *orig_pins) +{ + struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); + struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); + + if (!gpiobus_pin_verify_32(devi, first_pin, 32)) + return (EINVAL); + + return (GPIO_PIN_ACCESS_32(sc->sc_dev, devi->pins[first_pin], + clear_pins, change_pins, orig_pins)); +} + +static int +gpiobus_pin_config_32(device_t dev, device_t child, uint32_t first_pin, + uint32_t num_pins, uint32_t *pin_flags) +{ + struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); + struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); + + if (num_pins > 32) + return (EINVAL); + if (!gpiobus_pin_verify_32(devi, first_pin, num_pins)) + return (EINVAL); + + return (GPIO_PIN_CONFIG_32(sc->sc_dev, + devi->pins[first_pin], num_pins, pin_flags)); +} + static int gpiobus_pin_getname(device_t dev, uint32_t pin, char *name) { @@ -1093,6 +1143,8 @@ static device_method_t gpiobus_methods[] = { DEVMETHOD(gpiobus_pin_get, gpiobus_pin_get), DEVMETHOD(gpiobus_pin_set, gpiobus_pin_set), DEVMETHOD(gpiobus_pin_toggle, gpiobus_pin_toggle), + DEVMETHOD(gpiobus_pin_access_32,gpiobus_pin_access_32), + DEVMETHOD(gpiobus_pin_config_32,gpiobus_pin_config_32), DEVMETHOD(gpiobus_pin_getname, gpiobus_pin_getname), DEVMETHOD(gpiobus_pin_setname, gpiobus_pin_setname), diff --git a/sys/dev/gpio/gpiobus_if.m b/sys/dev/gpio/gpiobus_if.m index 8bf29839ef4e..890738c4e809 100644 --- a/sys/dev/gpio/gpiobus_if.m +++ b/sys/dev/gpio/gpiobus_if.m @@ -106,6 +106,36 @@ METHOD int pin_setflags { uint32_t flags; }; +# +# Simultaneously read and/or change up to 32 adjacent pins. +# If the device cannot change the pins simultaneously, returns EOPNOTSUPP. +# +# More details about using this interface can be found in sys/gpio.h +# +METHOD int pin_access_32 { + device_t dev; + device_t child; + uint32_t first_pin; + uint32_t clear_pins; + uint32_t change_pins; + uint32_t *orig_pins; +}; + +# +# Simultaneously configure up to 32 adjacent pins. +# This is intended to change the configuration of all the pins simultaneously, +# but unlike pin_access_32, this will not fail if the hardware can't do so. +# +# More details about using this interface can be found in sys/gpio.h +# +METHOD int pin_config_32 { + device_t dev; + device_t child; + uint32_t first_pin; + uint32_t num_pins; + uint32_t *pin_flags; +}; + # # Get the pin name #