]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
irqchip/renesas-rzv2h: Add struct rzv2h_hw_info with t_offs variable
authorBiju Das <biju.das.jz@bp.renesas.com>
Mon, 24 Feb 2025 13:11:23 +0000 (13:11 +0000)
committerThomas Gleixner <tglx@linutronix.de>
Wed, 26 Feb 2025 10:59:50 +0000 (11:59 +0100)
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.com
drivers/irqchip/irq-renesas-rzv2h.c

index 10b9b63a1f0920f5f108cafcf1875a3f6d02639c..43b805b6df94ae23a1e898af54f6a119ec6e6839 100644 (file)
 #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
  * @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;
        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)
@@ -109,7 +119,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);
@@ -137,12 +147,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)
@@ -245,8 +255,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);
 
        /*
@@ -255,7 +265,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)
@@ -306,21 +316,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;
 }
@@ -424,7 +434,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;
@@ -490,6 +501,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.
@@ -502,6 +515,15 @@ pm_put:
        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)