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