[PATCH v4 2/2] gpio: rcar: Add R-Car X5H (R8A78000) support

From: Marek Vasut

Date: Wed Sep 16 2026 - 23:56:44 EST


R-Car X5H (R8A78000) is the first member of the R-Car Gen5 family.
Add support for R-Car X5H, which has slightly different GPIO block
register layout compared to previous generations. Introduce offset
remap table which performs 1:1 remap for R-Car Gen1..4 and a bit
more complex remap for R-Car Gen5.

The GPIO block register offsets on R-Car Gen5 changed and the change
can be divided into five groups, registers which remained at the
same offset, INDT register shifted by +0x10, OUTDTSEL register
shifted by -0x34, INEN register shifted by -0x38 and the rest of
the registers used by the driver shifted by +0x70 .

Signed-off-by: Marek Vasut <marek.vasut+renesas@xxxxxxxxxxx>
---
Cc: Bartosz Golaszewski <brgl@xxxxxxxxxx>
Cc: Conor Dooley <conor+dt@xxxxxxxxxx>
Cc: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
Cc: Krzysztof Kozlowski <krzk+dt@xxxxxxxxxx>
Cc: Linus Walleij <linusw@xxxxxxxxxx>
Cc: Magnus Damm <magnus.damm@xxxxxxxxx>
Cc: Rob Herring <robh@xxxxxxxxxx>
Cc: devicetree@xxxxxxxxxxxxxxx
Cc: linux-gpio@xxxxxxxxxxxxxxx
Cc: linux-kernel@xxxxxxxxxxxxxxx
Cc: linux-renesas-soc@xxxxxxxxxxxxxxx
---
V2: Rewrite this into a table look up
V3: - Use enum gpio_rcar_reg
- Drop the IOINTSEL initializer
- Drop REG_COUNT
- s/int offs/enum gpio_rcar_reg reg/
- Make offsetmap into two maps, and static const
- Use C99-style initializers
- Drop BUILD_BUG_ON
- Store a pointer to the offset map table to use in priv
V4: Rebase on current next-20260916
---
drivers/gpio/gpio-rcar.c | 86 +++++++++++++++++++++++++++++++---------
1 file changed, 68 insertions(+), 18 deletions(-)

diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c
index 09bebde5c4260..54dc47d45de7e 100644
--- a/drivers/gpio/gpio-rcar.c
+++ b/drivers/gpio/gpio-rcar.c
@@ -36,6 +36,7 @@ struct gpio_rcar_info {
bool has_both_edge_trigger;
bool has_always_in;
bool has_inen;
+ const u8 *offsetmap;
};

struct gpio_rcar_priv {
@@ -49,34 +50,68 @@ struct gpio_rcar_priv {
struct gpio_rcar_bank_info bank_info;
};

-#define IOINTSEL 0x00 /* General IO/Interrupt Switching Register */
-#define INOUTSEL 0x04 /* General Input/Output Switching Register */
-#define OUTDT 0x08 /* General Output Register */
-#define INDT 0x0c /* General Input Register */
-#define INTDT 0x10 /* Interrupt Display Register */
-#define INTCLR 0x14 /* Interrupt Clear Register */
-#define INTMSK 0x18 /* Interrupt Mask Register */
-#define MSKCLR 0x1c /* Interrupt Mask Clear Register */
-#define POSNEG 0x20 /* Positive/Negative Logic Select Register */
-#define EDGLEVEL 0x24 /* Edge/level Select Register */
-#define OUTDTSEL 0x40 /* Output Data Select Register */
-#define BOTHEDGE 0x4c /* One Edge/Both Edge Select Register */
-#define INEN 0x50 /* General Input Enable Register */
+enum gpio_rcar_reg {
+ IOINTSEL, /* General IO/Interrupt Switching Register */
+ INOUTSEL, /* General Input/Output Switching Register */
+ OUTDT, /* General Output Register */
+ INDT, /* General Input Register */
+ INTDT, /* Interrupt Display Register */
+ INTCLR, /* Interrupt Clear Register */
+ INTMSK, /* Interrupt Mask Register */
+ MSKCLR, /* Interrupt Mask Clear Register */
+ POSNEG, /* Positive/Negative Logic Select Register */
+ EDGLEVEL, /* Edge/level Select Register */
+ OUTDTSEL, /* Output Data Select Register */
+ BOTHEDGE, /* One Edge/Both Edge Select Register */
+ INEN, /* General Input Enable Register */
+};
+
+static const u8 gpio_rcar_offsetmap_gen1[] = {
+ [IOINTSEL] = 0x00,
+ [INOUTSEL] = 0x04,
+ [OUTDT] = 0x08,
+ [INDT] = 0x0c,
+ [INTDT] = 0x10,
+ [INTCLR] = 0x14,
+ [INTMSK] = 0x18,
+ [MSKCLR] = 0x1c,
+ [POSNEG] = 0x20,
+ [EDGLEVEL] = 0x24,
+ [OUTDTSEL] = 0x40,
+ [BOTHEDGE] = 0x4c,
+ [INEN] = 0x50,
+};
+
+static const u8 gpio_rcar_offsetmap_gen5[] = {
+ [IOINTSEL] = 0x00,
+ [INOUTSEL] = 0x04,
+ [OUTDT] = 0x08,
+ [INDT] = 0x1c,
+ [INTDT] = 0x80,
+ [INTCLR] = 0x84,
+ [INTMSK] = 0x88,
+ [MSKCLR] = 0x8c,
+ [POSNEG] = 0x90,
+ [EDGLEVEL] = 0x94,
+ [OUTDTSEL] = 0x0c,
+ [BOTHEDGE] = 0xbc,
+ [INEN] = 0x18,
+};

#define RCAR_MAX_GPIO_PER_BANK 32

-static inline u32 gpio_rcar_read(struct gpio_rcar_priv *p, int offs)
+static inline u32 gpio_rcar_read(struct gpio_rcar_priv *p, enum gpio_rcar_reg offs)
{
- return ioread32(p->base + offs);
+ return ioread32(p->base + p->info.offsetmap[offs]);
}

-static inline void gpio_rcar_write(struct gpio_rcar_priv *p, int offs,
+static inline void gpio_rcar_write(struct gpio_rcar_priv *p, enum gpio_rcar_reg offs,
u32 value)
{
- iowrite32(value, p->base + offs);
+ iowrite32(value, p->base + p->info.offsetmap[offs]);
}

-static void gpio_rcar_modify_bit(struct gpio_rcar_priv *p, int offs,
+static void gpio_rcar_modify_bit(struct gpio_rcar_priv *p, enum gpio_rcar_reg offs,
int bit, bool value)
{
u32 tmp = gpio_rcar_read(p, offs);
@@ -399,6 +434,7 @@ static const struct gpio_rcar_info gpio_rcar_info_gen1 = {
.has_both_edge_trigger = false,
.has_always_in = false,
.has_inen = false,
+ .offsetmap = gpio_rcar_offsetmap_gen1,
};

static const struct gpio_rcar_info gpio_rcar_info_gen2 = {
@@ -406,6 +442,7 @@ static const struct gpio_rcar_info gpio_rcar_info_gen2 = {
.has_both_edge_trigger = true,
.has_always_in = false,
.has_inen = false,
+ .offsetmap = gpio_rcar_offsetmap_gen1,
};

static const struct gpio_rcar_info gpio_rcar_info_gen3 = {
@@ -413,6 +450,7 @@ static const struct gpio_rcar_info gpio_rcar_info_gen3 = {
.has_both_edge_trigger = true,
.has_always_in = true,
.has_inen = false,
+ .offsetmap = gpio_rcar_offsetmap_gen1,
};

static const struct gpio_rcar_info gpio_rcar_info_gen4 = {
@@ -420,6 +458,15 @@ static const struct gpio_rcar_info gpio_rcar_info_gen4 = {
.has_both_edge_trigger = true,
.has_always_in = true,
.has_inen = true,
+ .offsetmap = gpio_rcar_offsetmap_gen1,
+};
+
+static const struct gpio_rcar_info gpio_rcar_info_gen5 = {
+ .has_outdtsel = true,
+ .has_both_edge_trigger = true,
+ .has_always_in = true,
+ .has_inen = true,
+ .offsetmap = gpio_rcar_offsetmap_gen5,
};

static const struct of_device_id gpio_rcar_of_table[] = {
@@ -438,6 +485,9 @@ static const struct of_device_id gpio_rcar_of_table[] = {
}, {
.compatible = "renesas,rcar-gen4-gpio",
.data = &gpio_rcar_info_gen4,
+ }, {
+ .compatible = "renesas,rcar-gen5-gpio",
+ .data = &gpio_rcar_info_gen5,
}, {
.compatible = "renesas,gpio-rcar",
.data = &gpio_rcar_info_gen1,
--
2.53.0