gpio: rcar: Add R-Car X5H (R8A78000) support

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@mailbox.org>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Link: https://patch.msgid.link/20260917035438.523010-2-marek.vasut+renesas@mailbox.org
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
This commit is contained in:
Marek Vasut 2026-09-17 05:54:17 +02:00 committed by Bartosz Golaszewski
parent 373c23eab4
commit 79ec1b1b33

View File

@ -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,