git: c15106da820b - main - arm64: xilinx: gpio: Add support for ZynqMP SoC

From: Emmanuel Vadot <manu_at_FreeBSD.org>
Date: Thu, 10 Aug 2023 07:22:12 UTC
The branch main has been updated by manu:

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

commit c15106da820bd2e042fa8bc7cfba56ae69b371d6
Author:     Emmanuel Vadot <manu@FreeBSD.org>
AuthorDate: 2022-09-29 08:41:24 +0000
Commit:     Emmanuel Vadot <manu@FreeBSD.org>
CommitDate: 2023-08-10 07:21:55 +0000

    arm64: xilinx: gpio: Add support for ZynqMP SoC
    
    Add support for the gpio controller found in the ZynqMP SoC.
    The registers are the same as the Zynq 7000, just the number of
    banks/pins per banks differs.
    
    Sponsored by:   Beckhoff Automation GmbH & Co. KG
    MFC after:      2 weeks
---
 sys/arm/xilinx/zy7_gpio.c | 140 +++++++++++++++++++++++++++++++++-------------
 sys/conf/files.arm64      |   1 +
 2 files changed, 102 insertions(+), 39 deletions(-)

diff --git a/sys/arm/xilinx/zy7_gpio.c b/sys/arm/xilinx/zy7_gpio.c
index d487fc8e79d1..3dea34dc47fd 100644
--- a/sys/arm/xilinx/zy7_gpio.c
+++ b/sys/arm/xilinx/zy7_gpio.c
@@ -70,30 +70,49 @@ __FBSDID("$FreeBSD$");
 
 #include "gpio_if.h"
 
-#define	ZYNQ_MAX_BANK		4
+#define	ZYNQ7_MAX_BANK		4
+#define	ZYNQMP_MAX_BANK		6
 
 /* 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	ZYNQ7_BANK0_PIN_MIN	0
+#define	ZYNQ7_BANK0_NPIN	32
+#define	ZYNQ7_BANK1_PIN_MIN	32
+#define	ZYNQ7_BANK1_NPIN	22
+#define	ZYNQ7_BANK2_PIN_MIN	64
+#define	ZYNQ7_BANK2_NPIN	32
+#define	ZYNQ7_BANK3_PIN_MIN	96
+#define	ZYNQ7_BANK3_NPIN	32
+#define	ZYNQ7_PIN_MIO_MIN	0
+#define	ZYNQ7_PIN_MIO_MAX	54
+#define	ZYNQ7_PIN_EMIO_MIN	64
+#define	ZYNQ7_PIN_EMIO_MAX	118
+
+/* ZynqMP */
+#define	ZYNQMP_BANK0_PIN_MIN	0
+#define	ZYNQMP_BANK0_NPIN	26
+#define	ZYNQMP_BANK1_PIN_MIN	26
+#define	ZYNQMP_BANK1_NPIN	26
+#define	ZYNQMP_BANK2_PIN_MIN	52
+#define	ZYNQMP_BANK2_NPIN	26
+#define	ZYNQMP_BANK3_PIN_MIN	78
+#define	ZYNQMP_BANK3_NPIN	32
+#define	ZYNQMP_BANK4_PIN_MIN	110
+#define	ZYNQMP_BANK4_NPIN	32
+#define	ZYNQMP_BANK5_PIN_MIN	142
+#define	ZYNQMP_BANK5_NPIN	32
+#define	ZYNQMP_PIN_MIO_MIN	0
+#define	ZYNQMP_PIN_MIO_MAX	77
+#define	ZYNQMP_PIN_EMIO_MIN	78
+#define	ZYNQMP_PIN_EMIO_MAX	174
+
+#define	ZYNQ_BANK_NPIN(type, bank)	(ZYNQ##type##_BANK##bank##_NPIN)
+#define	ZYNQ_BANK_PIN_MIN(type, bank)	(ZYNQ##type##_BANK##bank##_PIN_MIN)
+#define	ZYNQ_BANK_PIN_MAX(type, bank)	(ZYNQ##type##_BANK##bank##_PIN_MIN + ZYNQ##type##_BANK##bank##_NPIN - 1)
+
+#define	ZYNQ_PIN_IS_MIO(type, pin)	(pin >= ZYNQ##type##_PIN_MIO_MIN &&	\
+	  pin <= ZYNQ##type##_PIN_MIO_MAX)
+#define	ZYNQ_PIN_IS_EMIO(type, pin)	(pin >= ZYNQ##type##_PIN_EMIO_MIN &&	\
+	  pin <= ZYNQ##type##_PIN_EMIO_MAX)
 
 #define ZGPIO_LOCK(sc)			mtx_lock(&(sc)->sc_mtx)
 #define	ZGPIO_UNLOCK(sc)		mtx_unlock(&(sc)->sc_mtx)
@@ -102,12 +121,18 @@ __FBSDID("$FreeBSD$");
 	    "gpio", MTX_DEF)
 #define ZGPIO_LOCK_DESTROY(_sc)	mtx_destroy(&_sc->sc_mtx);
 
+enum zynq_gpio_type {
+	ZYNQ_7000 = 0,
+	ZYNQMP,
+};
+
 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];
+	char			*name;
+	enum zynq_gpio_type	type;
+	uint32_t		nbanks;
+	uint32_t		maxpin;
+	uint32_t		bank_min[ZYNQMP_MAX_BANK];
+	uint32_t		bank_max[ZYNQMP_MAX_BANK];
 };
 
 struct zy7_gpio_softc {
@@ -120,20 +145,41 @@ struct zy7_gpio_softc {
 
 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),
+	.type = ZYNQ_7000,
+	.nbanks = ZYNQ7_MAX_BANK,
+	.maxpin = ZYNQ7_PIN_EMIO_MAX,
+	.bank_min[0] = ZYNQ_BANK_PIN_MIN(7, 0),
+	.bank_max[0] = ZYNQ_BANK_PIN_MAX(7, 0),
+	.bank_min[1] = ZYNQ_BANK_PIN_MIN(7, 1),
+	.bank_max[1] = ZYNQ_BANK_PIN_MAX(7, 1),
+	.bank_min[2] = ZYNQ_BANK_PIN_MIN(7, 2),
+	.bank_max[2] = ZYNQ_BANK_PIN_MAX(7, 2),
+	.bank_min[3] = ZYNQ_BANK_PIN_MIN(7, 3),
+	.bank_max[3] = ZYNQ_BANK_PIN_MAX(7, 3),
+};
+
+static struct zynq_gpio_conf zynqmp_gpio_conf = {
+	.name = "ZynqMP GPIO Controller",
+	.type = ZYNQMP,
+	.nbanks = ZYNQMP_MAX_BANK,
+	.maxpin = ZYNQMP_PIN_EMIO_MAX,
+	.bank_min[0] = ZYNQ_BANK_PIN_MIN(MP, 0),
+	.bank_max[0] = ZYNQ_BANK_PIN_MAX(MP, 0),
+	.bank_min[1] = ZYNQ_BANK_PIN_MIN(MP, 1),
+	.bank_max[1] = ZYNQ_BANK_PIN_MAX(MP, 1),
+	.bank_min[2] = ZYNQ_BANK_PIN_MIN(MP, 2),
+	.bank_max[2] = ZYNQ_BANK_PIN_MAX(MP, 2),
+	.bank_min[3] = ZYNQ_BANK_PIN_MIN(MP, 3),
+	.bank_max[3] = ZYNQ_BANK_PIN_MAX(MP, 3),
+	.bank_min[4] = ZYNQ_BANK_PIN_MIN(MP, 4),
+	.bank_max[4] = ZYNQ_BANK_PIN_MAX(MP, 4),
+	.bank_min[5] = ZYNQ_BANK_PIN_MIN(MP, 5),
+	.bank_max[5] = ZYNQ_BANK_PIN_MAX(MP, 5),
 };
 
 static struct ofw_compat_data compat_data[] = {
 	{"xlnx,zy7_gpio",		(uintptr_t)&z7_gpio_conf},
+	{"xlnx,zynqmp-gpio-1.0",	(uintptr_t)&zynqmp_gpio_conf},
 	{NULL, 0},
 };
 
@@ -212,15 +258,31 @@ zy7_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
 static int
 zy7_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
 {
+	struct zy7_gpio_softc *sc;
+	uint32_t emio_min;
+	bool is_mio;
 
+	sc = device_get_softc(dev);
 	if (!zy7_pin_valid(dev, pin))
 		return (EINVAL);
 
-	if (ZYNQ_PIN_IS_MIO(pin)) {
+	switch (sc->conf->type) {
+	case ZYNQ_7000:
+		is_mio = ZYNQ_PIN_IS_MIO(7, pin);
+		emio_min = ZYNQ7_PIN_EMIO_MIN;
+		break;
+	case ZYNQMP:
+		is_mio = ZYNQ_PIN_IS_MIO(MP, pin);
+		emio_min = ZYNQMP_PIN_EMIO_MIN;
+		break;
+	default:
+		return (EINVAL);
+	}
+	if (is_mio) {
 		snprintf(name, GPIOMAXNAME, "MIO_%d", pin);
 		name[GPIOMAXNAME - 1] = '\0';
 	} else {
-		snprintf(name, GPIOMAXNAME, "EMIO_%d", pin - ZYNQ_PIN_EMIO_MIN);
+		snprintf(name, GPIOMAXNAME, "EMIO_%d", pin - emio_min);
 		name[GPIOMAXNAME - 1] = '\0';
 	}
 
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index 7eb0c0d04367..31c296d49d86 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -692,3 +692,4 @@ arm64/rockchip/clk/rk3568_pmucru.c		optional fdt soc_rockchip_rk3568
 
 # Xilinx
 arm/xilinx/uart_dev_cdnc.c			optional uart soc_xilinx_zynq fdt
+arm/xilinx/zy7_gpio.c				optional gpio soc_xilinx_zynq fdt