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
 #

Reply via email to