The branch main has been updated by manu:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=b07fed8180a6b97f44c7d900d17b94fa3f1974cf

commit b07fed8180a6b97f44c7d900d17b94fa3f1974cf
Author:     Emmanuel Vadot <[email protected]>
AuthorDate: 2022-09-29 08:05:19 +0000
Commit:     Emmanuel Vadot <[email protected]>
CommitDate: 2023-08-10 07:21:55 +0000

    arm: xilinx: gpio: Make the driver more generic
    
    All other Zynq SoCs have the same GPIO controller, the only difference
    is the number of banks/pins so make this driver more generic to add
    other SoCs more easily.
    No functional changes intended.
    
    Sponsored by:   Beckhoff Automation GmbH & Co. KG
    MFC after:      2 weeks
---
 sys/arm/xilinx/zy7_gpio.c | 120 +++++++++++++++++++++++++++++++++++-----------
 1 file changed, 93 insertions(+), 27 deletions(-)

diff --git a/sys/arm/xilinx/zy7_gpio.c b/sys/arm/xilinx/zy7_gpio.c
index 9e9cf2b7f86a..d487fc8e79d1 100644
--- a/sys/arm/xilinx/zy7_gpio.c
+++ b/sys/arm/xilinx/zy7_gpio.c
@@ -70,16 +70,30 @@ __FBSDID("$FreeBSD$");
 
 #include "gpio_if.h"
 
-#define NUMBANKS       4
-#define MAXPIN         (32*NUMBANKS)
-
-#define MIO_PIN                0       /* pins 0-53 go to MIO */
-#define NUM_MIO_PINS   54
-#define EMIO_PIN       64      /* pins 64-127 go to PL */
-#define NUM_EMIO_PINS  64
-
-#define VALID_PIN(u)   (((u) >= MIO_PIN && (u) < MIO_PIN + NUM_MIO_PINS) || \
-                        ((u) >= EMIO_PIN && (u) < EMIO_PIN + NUM_EMIO_PINS))
+#define        ZYNQ_MAX_BANK           4
+
+/* Zynq 7000 */
+#define        ZYNQ_BANK0_PIN_MIN      0
+#define        ZYNQ_BANK0_NPIN         32
+#define        ZYNQ_BANK1_PIN_MIN      32
+#define        ZYNQ_BANK1_NPIN         22
+#define        ZYNQ_BANK2_PIN_MIN      64
+#define        ZYNQ_BANK2_NPIN         32
+#define        ZYNQ_BANK3_PIN_MIN      96
+#define        ZYNQ_BANK3_NPIN         32
+#define        ZYNQ_PIN_MIO_MIN        0
+#define        ZYNQ_PIN_MIO_MAX        54
+#define        ZYNQ_PIN_EMIO_MIN       64
+#define        ZYNQ_PIN_EMIO_MAX       118
+
+#define        ZYNQ_BANK_NPIN(bank)    (ZYNQ_BANK##bank##_NPIN)
+#define        ZYNQ_BANK_PIN_MIN(bank) (ZYNQ_BANK##bank##_PIN_MIN)
+#define        ZYNQ_BANK_PIN_MAX(bank) (ZYNQ_BANK##bank##_PIN_MIN + 
ZYNQ_BANK##bank##_NPIN - 1)
+
+#define        ZYNQ_PIN_IS_MIO(pin)    (pin >= ZYNQ_PIN_MIO_MIN && \
+         pin <= ZYNQ_PIN_MIO_MAX)
+#define        ZYNQ_PIN_IS_EMIO(pin)   (pin >= ZYNQ_PIN_EMIO_MIN && \
+         pin <= ZYNQ_PIN_EMIO_MAX)
 
 #define ZGPIO_LOCK(sc)                 mtx_lock(&(sc)->sc_mtx)
 #define        ZGPIO_UNLOCK(sc)                mtx_unlock(&(sc)->sc_mtx)
@@ -88,11 +102,39 @@ __FBSDID("$FreeBSD$");
            "gpio", MTX_DEF)
 #define ZGPIO_LOCK_DESTROY(_sc)        mtx_destroy(&_sc->sc_mtx);
 
+struct zynq_gpio_conf {
+       char            *name;
+       uint32_t        nbanks;
+       uint32_t        maxpin;
+       uint32_t        bank_min[ZYNQ_MAX_BANK];
+       uint32_t        bank_max[ZYNQ_MAX_BANK];
+};
+
 struct zy7_gpio_softc {
-       device_t        dev;
-       device_t        busdev;
-       struct mtx      sc_mtx;
-       struct resource *mem_res;       /* Memory resource */
+       device_t                dev;
+       device_t                busdev;
+       struct mtx              sc_mtx;
+       struct resource         *mem_res;       /* Memory resource */
+       struct zynq_gpio_conf   *conf;
+};
+
+static struct zynq_gpio_conf z7_gpio_conf = {
+       .name = "Zynq-7000 GPIO Controller",
+       .nbanks = ZYNQ_MAX_BANK,
+       .maxpin = ZYNQ_PIN_EMIO_MAX,
+       .bank_min[0] = ZYNQ_BANK_PIN_MIN(0),
+       .bank_max[0] = ZYNQ_BANK_PIN_MAX(0),
+       .bank_min[1] = ZYNQ_BANK_PIN_MIN(1),
+       .bank_max[1] = ZYNQ_BANK_PIN_MAX(1),
+       .bank_min[2] = ZYNQ_BANK_PIN_MIN(2),
+       .bank_max[2] = ZYNQ_BANK_PIN_MAX(2),
+       .bank_min[3] = ZYNQ_BANK_PIN_MIN(3),
+       .bank_max[3] = ZYNQ_BANK_PIN_MAX(3),
+};
+
+static struct ofw_compat_data compat_data[] = {
+       {"xlnx,zy7_gpio",               (uintptr_t)&z7_gpio_conf},
+       {NULL, 0},
 };
 
 #define WR4(sc, off, val)      bus_write_4((sc)->mem_res, (off), (val))
@@ -128,17 +170,37 @@ zy7_gpio_get_bus(device_t dev)
 static int
 zy7_gpio_pin_max(device_t dev, int *maxpin)
 {
+       struct zy7_gpio_softc *sc;
 
-       *maxpin = MAXPIN;
+       sc = device_get_softc(dev);
+       *maxpin = sc->conf->maxpin;
        return (0);
 }
 
+static inline bool
+zy7_pin_valid(device_t dev, uint32_t pin)
+{
+       struct zy7_gpio_softc *sc;
+       int i;
+       bool found = false;
+
+       sc = device_get_softc(dev);
+       for (i = 0; i < sc->conf->nbanks; i++) {
+               if (pin >= sc->conf->bank_min[i] && pin <= 
sc->conf->bank_max[i]) {
+                       found = true;
+                       break;
+               }
+       }
+
+       return (found);
+}
+
 /* Get a specific pin's capabilities. */
 static int
 zy7_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
 {
 
-       if (!VALID_PIN(pin))
+       if (!zy7_pin_valid(dev, pin))
                return (EINVAL);
 
        *caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE);
@@ -151,14 +213,14 @@ static int
 zy7_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
 {
 
-       if (!VALID_PIN(pin))
+       if (!zy7_pin_valid(dev, pin))
                return (EINVAL);
 
-       if (pin < NUM_MIO_PINS) {
+       if (ZYNQ_PIN_IS_MIO(pin)) {
                snprintf(name, GPIOMAXNAME, "MIO_%d", pin);
                name[GPIOMAXNAME - 1] = '\0';
        } else {
-               snprintf(name, GPIOMAXNAME, "EMIO_%d", pin - EMIO_PIN);
+               snprintf(name, GPIOMAXNAME, "EMIO_%d", pin - ZYNQ_PIN_EMIO_MIN);
                name[GPIOMAXNAME - 1] = '\0';
        }
 
@@ -171,7 +233,7 @@ zy7_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t 
*flags)
 {
        struct zy7_gpio_softc *sc = device_get_softc(dev);
 
-       if (!VALID_PIN(pin))
+       if (!zy7_pin_valid(dev, pin))
                return (EINVAL);
 
        ZGPIO_LOCK(sc);
@@ -197,7 +259,7 @@ zy7_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t 
flags)
 {
        struct zy7_gpio_softc *sc = device_get_softc(dev);
 
-       if (!VALID_PIN(pin))
+       if (!zy7_pin_valid(dev, pin))
                return (EINVAL);
 
        ZGPIO_LOCK(sc);
@@ -234,7 +296,7 @@ zy7_gpio_pin_set(device_t dev, uint32_t pin, unsigned int 
value)
 {
        struct zy7_gpio_softc *sc = device_get_softc(dev);
 
-       if (!VALID_PIN(pin) || value > 1)
+       if (!zy7_pin_valid(dev, pin) || value > 1)
                return (EINVAL);
 
        /* Fancy register tricks allow atomic set or reset. */
@@ -256,7 +318,7 @@ zy7_gpio_pin_get(device_t dev, uint32_t pin, unsigned int 
*value)
 {
        struct zy7_gpio_softc *sc = device_get_softc(dev);
 
-       if (!VALID_PIN(pin))
+       if (!zy7_pin_valid(dev, pin))
                return (EINVAL);
 
        *value = (RD4(sc, ZY7_GPIO_DATA_RO(pin >> 5)) >> (pin & 31)) & 1;
@@ -270,7 +332,7 @@ zy7_gpio_pin_toggle(device_t dev, uint32_t pin)
 {
        struct zy7_gpio_softc *sc = device_get_softc(dev);
 
-       if (!VALID_PIN(pin))
+       if (!zy7_pin_valid(dev, pin))
                return (EINVAL);
 
        ZGPIO_LOCK(sc);
@@ -286,14 +348,16 @@ zy7_gpio_pin_toggle(device_t dev, uint32_t pin)
 static int
 zy7_gpio_probe(device_t dev)
 {
+       struct zynq_gpio_conf *conf;
 
        if (!ofw_bus_status_okay(dev))
                return (ENXIO);
 
-       if (!ofw_bus_is_compatible(dev, "xlnx,zy7_gpio"))
+       conf = (struct zynq_gpio_conf *)ofw_bus_search_compatible(dev, 
compat_data)->ocd_data;
+       if (conf == 0)
                return (ENXIO);
 
-       device_set_desc(dev, "Zynq-7000 GPIO driver");
+       device_set_desc(dev, conf->name);
        return (0);
 }
 
@@ -306,6 +370,7 @@ zy7_gpio_attach(device_t dev)
        int rid;
 
        sc->dev = dev;
+       sc->conf = (struct zynq_gpio_conf *)ofw_bus_search_compatible(dev, 
compat_data)->ocd_data;
 
        ZGPIO_LOCK_INIT(sc);
 
@@ -372,4 +437,5 @@ static driver_t zy7_gpio_driver = {
        sizeof(struct zy7_gpio_softc),
 };
 
-DRIVER_MODULE(zy7_gpio, simplebus, zy7_gpio_driver, NULL, NULL);
+EARLY_DRIVER_MODULE(zy7_gpio, simplebus, zy7_gpio_driver, 0, 0,
+    BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);

Reply via email to