6.14-stable review patch. If anyone has any objections, please let me know.
------------------
From: Biju Das biju.das.jz@bp.renesas.com
[ Upstream commit 0a9d6ef64e5e917f93db98935cd09bac38507ebf ]
The ICU block on the RZ/G3E SoC is almost identical to the one found on the RZ/V2H SoC, with the following differences:
- The TINT register base offset is 0x800 instead of zero. - The number of GPIO interrupts for TINT selection is 141 instead of 86. - The pin index and TINT selection index are not in the 1:1 map - The number of TSSR registers is 16 instead of 8 - Each TSSR register can program 2 TINTs instead of 4 TINTs
Introduce struct rzv2h_hw_info to describe the SoC properties and refactor the code by moving rzv2h_icu_init() into rzv2h_icu_init_common() and pass the variable containing hw difference to support both these SoCs.
As a first step add t_offs to the new struct and replace the hardcoded constants in the code.
Signed-off-by: Biju Das biju.das.jz@bp.renesas.com Signed-off-by: Thomas Gleixner tglx@linutronix.de Reviewed-by: Fabrizio Castro fabrizio.castro.jz@renesas.com Reviewed-by: Tommaso Merciai tommaso.merciai.xr@bp.renesas.com Reviewed-by: Geert Uytterhoeven geert+renesas@glider.be Link: https://lore.kernel.org/all/20250224131253.134199-8-biju.das.jz@bp.renesas.c... Stable-dep-of: 28e89cdac648 ("irqchip/renesas-rzv2h: Prevent TINT spurious interrupt") Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/irqchip/irq-renesas-rzv2h.c | 46 +++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 12 deletions(-)
diff --git a/drivers/irqchip/irq-renesas-rzv2h.c b/drivers/irqchip/irq-renesas-rzv2h.c index 6be38aa86f9b8..5fcc6ed4086cd 100644 --- a/drivers/irqchip/irq-renesas-rzv2h.c +++ b/drivers/irqchip/irq-renesas-rzv2h.c @@ -80,18 +80,28 @@ #define ICU_TINT_EXTRACT_GPIOINT(x) FIELD_GET(GENMASK(31, 16), (x)) #define ICU_PB5_TINT 0x55
+/** + * struct rzv2h_hw_info - Interrupt Control Unit controller hardware info structure. + * @t_offs: TINT offset + */ +struct rzv2h_hw_info { + u16 t_offs; +}; + /** * struct rzv2h_icu_priv - Interrupt Control Unit controller private data structure. * @base: Controller's base address * @irqchip: Pointer to struct irq_chip * @fwspec: IRQ firmware specific data * @lock: Lock to serialize access to hardware registers + * @info: Pointer to struct rzv2h_hw_info */ struct rzv2h_icu_priv { void __iomem *base; const struct irq_chip *irqchip; struct irq_fwspec fwspec[ICU_NUM_IRQ]; raw_spinlock_t lock; + const struct rzv2h_hw_info *info; };
static inline struct rzv2h_icu_priv *irq_data_to_priv(struct irq_data *data) @@ -111,7 +121,7 @@ static void rzv2h_icu_eoi(struct irq_data *d) tintirq_nr = hw_irq - ICU_TINT_START; bit = BIT(tintirq_nr); if (!irqd_is_level_type(d)) - writel_relaxed(bit, priv->base + ICU_TSCLR); + writel_relaxed(bit, priv->base + priv->info->t_offs + ICU_TSCLR); } else if (hw_irq >= ICU_IRQ_START) { tintirq_nr = hw_irq - ICU_IRQ_START; bit = BIT(tintirq_nr); @@ -139,12 +149,12 @@ static void rzv2h_tint_irq_endisable(struct irq_data *d, bool enable) tssel_n = ICU_TSSR_TSSEL_N(tint_nr);
guard(raw_spinlock)(&priv->lock); - tssr = readl_relaxed(priv->base + ICU_TSSR(k)); + tssr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TSSR(k)); if (enable) tssr |= ICU_TSSR_TIEN(tssel_n); else tssr &= ~ICU_TSSR_TIEN(tssel_n); - writel_relaxed(tssr, priv->base + ICU_TSSR(k)); + writel_relaxed(tssr, priv->base + priv->info->t_offs + ICU_TSSR(k)); }
static void rzv2h_icu_irq_disable(struct irq_data *d) @@ -247,8 +257,8 @@ static void rzv2h_clear_tint_int(struct rzv2h_icu_priv *priv, unsigned int hwirq u32 bit = BIT(tint_nr); int k = tint_nr / 16;
- tsctr = readl_relaxed(priv->base + ICU_TSCTR); - titsr = readl_relaxed(priv->base + ICU_TITSR(k)); + tsctr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TSCTR); + titsr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TITSR(k)); titsel = ICU_TITSR_TITSEL_GET(titsr, titsel_n);
/* @@ -257,7 +267,7 @@ static void rzv2h_clear_tint_int(struct rzv2h_icu_priv *priv, unsigned int hwirq */ if ((tsctr & bit) && ((titsel == ICU_TINT_EDGE_RISING) || (titsel == ICU_TINT_EDGE_FALLING))) - writel_relaxed(bit, priv->base + ICU_TSCLR); + writel_relaxed(bit, priv->base + priv->info->t_offs + ICU_TSCLR); }
static int rzv2h_tint_set_type(struct irq_data *d, unsigned int type) @@ -308,21 +318,21 @@ static int rzv2h_tint_set_type(struct irq_data *d, unsigned int type)
guard(raw_spinlock)(&priv->lock);
- tssr = readl_relaxed(priv->base + ICU_TSSR(tssr_k)); + tssr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TSSR(tssr_k)); tssr &= ~(ICU_TSSR_TSSEL_MASK(tssel_n) | tien); tssr |= ICU_TSSR_TSSEL_PREP(tint, tssel_n);
- writel_relaxed(tssr, priv->base + ICU_TSSR(tssr_k)); + writel_relaxed(tssr, priv->base + priv->info->t_offs + ICU_TSSR(tssr_k));
- titsr = readl_relaxed(priv->base + ICU_TITSR(titsr_k)); + titsr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TITSR(titsr_k)); titsr &= ~ICU_TITSR_TITSEL_MASK(titsel_n); titsr |= ICU_TITSR_TITSEL_PREP(sense, titsel_n);
- writel_relaxed(titsr, priv->base + ICU_TITSR(titsr_k)); + writel_relaxed(titsr, priv->base + priv->info->t_offs + ICU_TITSR(titsr_k));
rzv2h_clear_tint_int(priv, hwirq);
- writel_relaxed(tssr | tien, priv->base + ICU_TSSR(tssr_k)); + writel_relaxed(tssr | tien, priv->base + priv->info->t_offs + ICU_TSSR(tssr_k));
return 0; } @@ -426,7 +436,8 @@ static void rzv2h_icu_put_device(void *data) put_device(data); }
-static int rzv2h_icu_init(struct device_node *node, struct device_node *parent) +static int rzv2h_icu_init_common(struct device_node *node, struct device_node *parent, + const struct rzv2h_hw_info *hw_info) { struct irq_domain *irq_domain, *parent_domain; struct rzv2h_icu_priv *rzv2h_icu_data; @@ -492,6 +503,8 @@ static int rzv2h_icu_init(struct device_node *node, struct device_node *parent) goto pm_put; }
+ rzv2h_icu_data->info = hw_info; + /* * coccicheck complains about a missing put_device call before returning, but it's a false * positive. We still need &pdev->dev after successfully returning from this function. @@ -507,6 +520,15 @@ static int rzv2h_icu_init(struct device_node *node, struct device_node *parent) return ret; }
+static const struct rzv2h_hw_info rzv2h_hw_params = { + .t_offs = 0, +}; + +static int rzv2h_icu_init(struct device_node *node, struct device_node *parent) +{ + return rzv2h_icu_init_common(node, parent, &rzv2h_hw_params); +} + IRQCHIP_PLATFORM_DRIVER_BEGIN(rzv2h_icu) IRQCHIP_MATCH("renesas,r9a09g057-icu", rzv2h_icu_init) IRQCHIP_PLATFORM_DRIVER_END(rzv2h_icu)