git: 9fd527140ae8 - stable/15 - rk_gpio: Fix register read/write on rk3568

From: Ahmad Khalifa <vexeduxr_at_FreeBSD.org>
Date: Wed, 01 Oct 2025 09:38:59 UTC
The branch stable/15 has been updated by vexeduxr:

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

commit 9fd527140ae8b6b44b9a1a992e6e424a70895c38
Author:     Evgenii Ivanov <devivanov@proton.me>
AuthorDate: 2025-09-25 17:15:01 +0000
Commit:     Ahmad Khalifa <vexeduxr@FreeBSD.org>
CommitDate: 2025-10-01 09:37:35 +0000

    rk_gpio: Fix register read/write on rk3568
    
    Not all registers have a write mask with high/low register on rk3568.
    
    Reviewed by:    vexeduxr
    MFC after:      5 days
    Differential Revision:  https://reviews.freebsd.org/D52512
    
    (cherry picked from commit 34ec8c9ccaa473d2d0c177a92c041bb8fdb083db)
---
 sys/arm64/rockchip/rk_gpio.c | 99 ++++++++++++++++++++++++--------------------
 1 file changed, 54 insertions(+), 45 deletions(-)

diff --git a/sys/arm64/rockchip/rk_gpio.c b/sys/arm64/rockchip/rk_gpio.c
index 61614f532634..7358239a7c35 100644
--- a/sys/arm64/rockchip/rk_gpio.c
+++ b/sys/arm64/rockchip/rk_gpio.c
@@ -90,6 +90,11 @@ struct rk_pin_irqsrc {
 	uint32_t		mode;
 };
 
+struct rk_gpio_reg {
+        uint8_t single;
+        uint8_t offset;
+};
+
 struct rk_gpio_softc {
 	device_t		sc_dev;
 	device_t		sc_busdev;
@@ -103,7 +108,7 @@ struct rk_gpio_softc {
 	uint32_t		swporta_ddr;
 	uint32_t		version;
 	struct pin_cached	pin_cached[RK_GPIO_MAX_PINS];
-	uint8_t			regs[RK_GPIO_REGNUM];
+	struct rk_gpio_reg	regs[RK_GPIO_REGNUM];
 	void			*ihandle;
 	struct rk_pin_irqsrc	isrcs[RK_GPIO_MAX_PINS];
 };
@@ -138,14 +143,15 @@ static int rk_gpio_detach(device_t dev);
 static int
 rk_gpio_read_bit(struct rk_gpio_softc *sc, int reg, int bit)
 {
-	int offset = sc->regs[reg];
+	struct rk_gpio_reg *rk_reg = &sc->regs[reg];
 	uint32_t value;
 
-	if (sc->version == RK_GPIO_TYPE_V1) {
-		value = RK_GPIO_READ(sc, offset);
+	if (rk_reg->single) {
+		value = RK_GPIO_READ(sc, rk_reg->offset);
 		value >>= bit;
 	} else {
-		value = RK_GPIO_READ(sc, bit > 15 ? offset + 4 : offset);
+		value = RK_GPIO_READ(sc, bit > 15 ?
+		    rk_reg->offset + 4 : rk_reg->offset);
 		value >>= (bit % 16);
 	}
 	return (value & 1);
@@ -154,50 +160,53 @@ rk_gpio_read_bit(struct rk_gpio_softc *sc, int reg, int bit)
 static void
 rk_gpio_write_bit(struct rk_gpio_softc *sc, int reg, int bit, int data)
 {
-	int offset = sc->regs[reg];
+	struct rk_gpio_reg *rk_reg = &sc->regs[reg];
 	uint32_t value;
 
-	if (sc->version == RK_GPIO_TYPE_V1) {
-		value = RK_GPIO_READ(sc, offset);
+	if (rk_reg->single) {
+		value = RK_GPIO_READ(sc, rk_reg->offset);
 		if (data)
 			value |= (1 << bit);
 		else
 			value &= ~(1 << bit);
-		RK_GPIO_WRITE(sc, offset, value);
+		RK_GPIO_WRITE(sc, rk_reg->offset, value);
 	} else {
 		if (data)
 			value = (1 << (bit % 16));
 		else
 			value = 0;
 		value |= (1 << ((bit % 16) + 16));
-		RK_GPIO_WRITE(sc, bit > 15 ? offset + 4 : offset, value);
+		RK_GPIO_WRITE(sc, bit > 15 ?
+		    rk_reg->offset + 4 : rk_reg->offset, value);
 	}
 }
 
 static uint32_t
 rk_gpio_read_4(struct rk_gpio_softc *sc, int reg)
 {
-	int offset = sc->regs[reg];
+	struct rk_gpio_reg *rk_reg = &sc->regs[reg];
 	uint32_t value;
 
-	if (sc->version == RK_GPIO_TYPE_V1)
-		value = RK_GPIO_READ(sc, offset);
+	if (rk_reg->single)
+		value = RK_GPIO_READ(sc, rk_reg->offset);
 	else
-		value = (RK_GPIO_READ(sc, offset) & 0xffff) |
-		    (RK_GPIO_READ(sc, offset + 4) << 16);
+		value = (RK_GPIO_READ(sc, rk_reg->offset) & 0xffff) |
+		    (RK_GPIO_READ(sc, rk_reg->offset + 4) << 16);
 	return (value);
 }
 
 static void
 rk_gpio_write_4(struct rk_gpio_softc *sc, int reg, uint32_t value)
 {
-	int offset = sc->regs[reg];
+	struct rk_gpio_reg *rk_reg = &sc->regs[reg];
 
-	if (sc->version == RK_GPIO_TYPE_V1)
-		RK_GPIO_WRITE(sc, offset, value);
+	if (rk_reg->single)
+		RK_GPIO_WRITE(sc, rk_reg->offset, value);
 	else {
-		RK_GPIO_WRITE(sc, offset, (value & 0xffff) | 0xffff0000);
-		RK_GPIO_WRITE(sc, offset + 4, (value >> 16) | 0xffff0000);
+		RK_GPIO_WRITE(sc, rk_reg->offset,
+		    (value & 0xffff) | 0xffff0000);
+		RK_GPIO_WRITE(sc, rk_reg->offset + 4,
+		    (value >> 16) | 0xffff0000);
 	}
 }
 
@@ -313,31 +322,31 @@ rk_gpio_attach(device_t dev)
 
 	switch (sc->version) {
 	case RK_GPIO_TYPE_V1:
-		sc->regs[RK_GPIO_SWPORTA_DR] = 0x00;
-		sc->regs[RK_GPIO_SWPORTA_DDR] = 0x04;
-		sc->regs[RK_GPIO_INTEN] = 0x30;
-		sc->regs[RK_GPIO_INTMASK] = 0x34;
-		sc->regs[RK_GPIO_INTTYPE_LEVEL] = 0x38;
-		sc->regs[RK_GPIO_INT_POLARITY] = 0x3c;
-		sc->regs[RK_GPIO_INT_STATUS] = 0x40;
-		sc->regs[RK_GPIO_INT_RAWSTATUS] = 0x44;
-		sc->regs[RK_GPIO_DEBOUNCE] = 0x48;
-		sc->regs[RK_GPIO_PORTA_EOI] = 0x4c;
-		sc->regs[RK_GPIO_EXT_PORTA] = 0x50;
+		sc->regs[RK_GPIO_SWPORTA_DR] = (struct rk_gpio_reg){ 1, 0x00 };
+		sc->regs[RK_GPIO_SWPORTA_DDR] = (struct rk_gpio_reg){ 1, 0x04 };
+		sc->regs[RK_GPIO_INTEN] = (struct rk_gpio_reg){ 1, 0x30 };
+		sc->regs[RK_GPIO_INTMASK] = (struct rk_gpio_reg){ 1, 0x34 };
+		sc->regs[RK_GPIO_INTTYPE_LEVEL] = (struct rk_gpio_reg){ 1, 0x38 };
+		sc->regs[RK_GPIO_INT_POLARITY] = (struct rk_gpio_reg){ 1, 0x3c };
+		sc->regs[RK_GPIO_INT_STATUS] = (struct rk_gpio_reg){ 1, 0x40 };
+		sc->regs[RK_GPIO_INT_RAWSTATUS] = (struct rk_gpio_reg){ 1, 0x44 };
+		sc->regs[RK_GPIO_DEBOUNCE] = (struct rk_gpio_reg){ 1, 0x48 };
+		sc->regs[RK_GPIO_PORTA_EOI] = (struct rk_gpio_reg){ 1, 0x4c };
+		sc->regs[RK_GPIO_EXT_PORTA] = (struct rk_gpio_reg){ 1, 0x50 };
 		break;
 	case RK_GPIO_TYPE_V2:
-		sc->regs[RK_GPIO_SWPORTA_DR] = 0x00;
-		sc->regs[RK_GPIO_SWPORTA_DDR] = 0x08;
-		sc->regs[RK_GPIO_INTEN] = 0x10;
-		sc->regs[RK_GPIO_INTMASK] = 0x18;
-		sc->regs[RK_GPIO_INTTYPE_LEVEL] = 0x20;
-		sc->regs[RK_GPIO_INTTYPE_BOTH] = 0x30;
-		sc->regs[RK_GPIO_INT_POLARITY] = 0x28;
-		sc->regs[RK_GPIO_INT_STATUS] = 0x50;
-		sc->regs[RK_GPIO_INT_RAWSTATUS] = 0x58;
-		sc->regs[RK_GPIO_DEBOUNCE] = 0x38;
-		sc->regs[RK_GPIO_PORTA_EOI] = 0x60;
-		sc->regs[RK_GPIO_EXT_PORTA] = 0x70;
+		sc->regs[RK_GPIO_SWPORTA_DR] = (struct rk_gpio_reg){ 0, 0x00 };
+		sc->regs[RK_GPIO_SWPORTA_DDR] = (struct rk_gpio_reg){ 0, 0x08 };
+		sc->regs[RK_GPIO_INTEN] = (struct rk_gpio_reg){ 0, 0x10 };
+		sc->regs[RK_GPIO_INTMASK] = (struct rk_gpio_reg){ 0, 0x18 };
+		sc->regs[RK_GPIO_INTTYPE_LEVEL] = (struct rk_gpio_reg){ 0, 0x20 };
+		sc->regs[RK_GPIO_INTTYPE_BOTH] = (struct rk_gpio_reg){ 0, 0x30 };
+		sc->regs[RK_GPIO_INT_POLARITY] = (struct rk_gpio_reg){ 0, 0x28 };
+		sc->regs[RK_GPIO_INT_STATUS] = (struct rk_gpio_reg){ 1, 0x50 };
+		sc->regs[RK_GPIO_INT_RAWSTATUS] = (struct rk_gpio_reg){ 1, 0x58 };
+		sc->regs[RK_GPIO_DEBOUNCE] = (struct rk_gpio_reg){ 0, 0x38 };
+		sc->regs[RK_GPIO_PORTA_EOI] = (struct rk_gpio_reg){ 0, 0x60 };
+		sc->regs[RK_GPIO_EXT_PORTA] = (struct rk_gpio_reg){ 1, 0x70 };
 		break;
 	default:
 		device_printf(dev, "Unknown gpio version %08x\n", sc->version);
@@ -394,7 +403,7 @@ rk_gpio_detach(device_t dev)
 	mtx_destroy(&sc->sc_mtx);
 	clk_disable(sc->clk);
 
-	return(0);
+	return (0);
 }
 
 static device_t
@@ -471,7 +480,7 @@ rk_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
 {
 
 	if (pin >= RK_GPIO_MAX_PINS)
-		return EINVAL;
+		return (EINVAL);
 
 	*caps = RK_GPIO_DEFAULT_CAPS;
 	return (0);