Thread (3 messages) 3 messages, 2 authors, 12d ago

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

From: Geert Uytterhoeven <geert@linux-m68k.org>
Date: 2026-09-09 07:24:57
Also in: linux-renesas-soc

Hi Marek,

On Wed, 9 Sept 2026 at 04:14, Marek Vasut
[off-list ref] wrote:

It's getting late/early ;-)
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 function 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@mailbox.org>
---
V2: Rewrite this into a table look up
Thanks for the update!
quoted hunk ↗ jump to hunk
--- a/drivers/gpio/gpio-rcar.c
+++ b/drivers/gpio/gpio-rcar.c
@@ -49,31 +50,48 @@ 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 {
enum gpio_rcar_reg
+       IOINTSEL = 0,   /* General IO/Interrupt Switching Register */
You can drop the initializer.
+       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 */
+       REG_COUNT
Not needed (even harmful, see below).
+};

 #define RCAR_MAX_GPIO_PER_BANK         32

+static volatile void __iomem *gpio_rcar_remap_offset(struct gpio_rcar_priv *p, int offs)
s/int offs/enum gpio_rcar_reg reg/ (everywhere), so the compiler knows
the valid range.
+{
+       const u32 offsetmap[2][REG_COUNT] = {
static ...
+               /* Gen1..Gen4 */
+               { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x40, 0x4c, 0x50 },
+               /* Gen5 */
+               { 0x00, 0x04, 0x08, 0x1c, 0x80, 0x84, 0x88, 0x8c, 0x90, 0x94, 0x0c, 0xbc, 0x18 },
Please use C99-style initializers, for both readability and safety.
+       };
+
+       BUILD_BUG_ON(offs < 0 || offs >= REG_COUNT);
Not needed.
+
+       return p->base + offsetmap[p->info.has_layout_gen5][offs];
Please store a pointer to the table to use in priv, so you don't need
to check p->info.has_layout_gen5 over and over again.

After all of that, this function has become very simple, so you can
just inline it below.
+}
+
 static inline u32 gpio_rcar_read(struct gpio_rcar_priv *p, int offs)
 {
-       return ioread32(p->base + offs);
+       return ioread32(gpio_rcar_remap_offset(p, offs));
return ioread32((p->base + p->offs_table[reg]);
 }
Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help