Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 10 Aug 2023 07:22:11 GMT
From:      Emmanuel Vadot <manu@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: b07fed8180a6 - main - arm: xilinx: gpio: Make the driver more generic
Message-ID:  <202308100722.37A7MBTe023214@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by manu:

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

commit b07fed8180a6b97f44c7d900d17b94fa3f1974cf
Author:     Emmanuel Vadot <manu@FreeBSD.org>
AuthorDate: 2022-09-29 08:05:19 +0000
Commit:     Emmanuel Vadot <manu@FreeBSD.org>
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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202308100722.37A7MBTe023214>