Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 25 Sep 2025 17:48:02 GMT
From:      Ahmad Khalifa <vexeduxr@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: ace98a8fb8fe - main - rk_gpio: Enable gpio allocation via fdt
Message-ID:  <202509251748.58PHm2dR073989@gitrepo.freebsd.org>

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

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

commit ace98a8fb8fe18d47ccbb55619a9ffd4ac10f98c
Author:     Evgenii Ivanov <devivanov@proton.me>
AuthorDate: 2025-09-25 17:15:08 +0000
Commit:     Ahmad Khalifa <vexeduxr@FreeBSD.org>
CommitDate: 2025-09-25 17:28:37 +0000

    rk_gpio: Enable gpio allocation via fdt
    
    The code is based on bcm2835_gpio.c. This enables allocating gpio
    interrupts via interrupts property in fdt.
    
    Reviewed by:    vexeduxr
    MFC after:      5 days
    Differential Revision:  https://reviews.freebsd.org/D52513
---
 sys/arm64/rockchip/rk_gpio.c | 98 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 80 insertions(+), 18 deletions(-)

diff --git a/sys/arm64/rockchip/rk_gpio.c b/sys/arm64/rockchip/rk_gpio.c
index 7358239a7c35..145d9769f35f 100644
--- a/sys/arm64/rockchip/rk_gpio.c
+++ b/sys/arm64/rockchip/rk_gpio.c
@@ -663,46 +663,108 @@ rk_gpio_get_node(device_t bus, device_t dev)
 }
 
 static int
-rk_pic_map_intr(device_t dev, struct intr_map_data *data,
-    struct intr_irqsrc **isrcp)
+rk_gpio_pic_map_fdt(struct rk_gpio_softc *sc,
+    struct intr_map_data_fdt *daf,
+    u_int *irqp, uint32_t *modep)
 {
-	struct rk_gpio_softc *sc = device_get_softc(dev);
-	struct intr_map_data_gpio *gdata;
 	uint32_t irq;
+	uint32_t mode;
 
-	if (data->type != INTR_MAP_DATA_GPIO) {
-		device_printf(dev, "Wrong type\n");
-		return (ENOTSUP);
-	}
-	gdata = (struct intr_map_data_gpio *)data;
-	irq = gdata->gpio_pin_num;
+	if (daf->ncells != 2)
+		return (EINVAL);
+
+	irq = daf->cells[0];
+	if (irq >= RK_GPIO_MAX_PINS)
+		return (EINVAL);
+
+	/* Only reasonable modes are supported. */
+	if (daf->cells[1] == 1)
+		mode = GPIO_INTR_EDGE_RISING;
+	else if (daf->cells[1] == 2)
+		mode = GPIO_INTR_EDGE_FALLING;
+	else if (daf->cells[1] == 3)
+		mode = GPIO_INTR_EDGE_BOTH;
+	else if (daf->cells[1] == 4)
+		mode = GPIO_INTR_LEVEL_HIGH;
+	else if (daf->cells[1] == 8)
+		mode = GPIO_INTR_LEVEL_LOW;
+	else
+		return (EINVAL);
+
+	*irqp = irq;
+	if (modep != NULL)
+		*modep = mode;
+	return (0);
+}
+
+static int
+rk_gpio_pic_map_gpio(struct rk_gpio_softc *sc,
+    struct intr_map_data_gpio *dag,
+    u_int *irqp, uint32_t *modep)
+{
+	uint32_t irq;
+	irq = dag->gpio_pin_num;
 	if (irq >= RK_GPIO_MAX_PINS) {
-		device_printf(dev, "Invalid interrupt %u\n", irq);
+		device_printf(sc->sc_dev, "Invalid interrupt %u\n",
+		    irq);
 		return (EINVAL);
 	}
-	*isrcp = RK_GPIO_ISRC(sc, irq);
+
+	*irqp = irq;
+	if (modep != NULL)
+		*modep = dag->gpio_intr_mode;
 	return (0);
 }
 
+static int
+rk_gpio_pic_map(struct rk_gpio_softc *sc, struct intr_map_data *data,
+    u_int *irqp, uint32_t *modep)
+{
+	switch (data->type) {
+	case INTR_MAP_DATA_FDT:
+		return (rk_gpio_pic_map_fdt(sc,
+		    (struct intr_map_data_fdt *)data, irqp, modep));
+	case INTR_MAP_DATA_GPIO:
+		return (rk_gpio_pic_map_gpio(sc,
+		    (struct intr_map_data_gpio *)data, irqp, modep));
+	default:
+		device_printf(sc->sc_dev, "Wrong type\n");
+		return (ENOTSUP);
+	}
+}
+
+static int
+rk_pic_map_intr(device_t dev, struct intr_map_data *data,
+    struct intr_irqsrc **isrcp)
+{
+	int error;
+	struct rk_gpio_softc *sc = device_get_softc(dev);
+	uint32_t irq;
+
+	error = rk_gpio_pic_map(sc, data, &irq, NULL);
+	if (error == 0)
+		*isrcp = RK_GPIO_ISRC(sc, irq);
+	return (error);
+}
+
 static int
 rk_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
     struct resource *res, struct intr_map_data *data)
 {
 	struct rk_gpio_softc *sc = device_get_softc(dev);
 	struct rk_pin_irqsrc *rkisrc = (struct rk_pin_irqsrc *)isrc;
-	struct intr_map_data_gpio *gdata;
 	uint32_t mode;
-	uint8_t pin;
+	uint32_t pin;
 
 	if (!data) {
 		device_printf(dev, "No map data\n");
 		return (ENOTSUP);
 	}
-	gdata = (struct intr_map_data_gpio *)data;
-	mode = gdata->gpio_intr_mode;
-	pin = gdata->gpio_pin_num;
 
-	if (rkisrc->irq != gdata->gpio_pin_num) {
+	if (rk_gpio_pic_map(sc, data, &pin, &mode) != 0)
+		return (EINVAL);
+
+	if (rkisrc->irq != pin) {
 		device_printf(dev, "Interrupts don't match\n");
 		return (EINVAL);
 	}



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