]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
irqchip/imx-irqsteer: Add NXP S32N79 support
authorCiprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
Wed, 11 Mar 2026 08:11:52 +0000 (09:11 +0100)
committerThomas Gleixner <tglx@kernel.org>
Wed, 11 Mar 2026 08:55:26 +0000 (09:55 +0100)
Add support for the interrupt steering controller found in NXP S32N79
series automotive SoCs.

The S32N79 IRQ_STEER variant differs from the i.MX version by not
implementing the CHANCTRL register. To handle this hardware difference,
introduce a device type data structure with quirks field. The
IRQSTEER_QUIRK_NO_CHANCTRL quirk skips CHANCTRL register access for S32N79
variants.

The interrupt routing functionality and register layout are otherwise
identical between the two variants.

Co-developed-by: Larisa Grigore <larisa.grigore@nxp.com>
Signed-off-by: Larisa Grigore <larisa.grigore@nxp.com>
Signed-off-by: Ciprian Marian Costea <ciprianmarian.costea@oss.nxp.com>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/20260311081154.381881-4-ciprianmarian.costea@oss.nxp.com
drivers/irqchip/Kconfig
drivers/irqchip/irq-imx-irqsteer.c

index dc26effa5b364331d50d2d7bb823a11cac88ae4e..2feecfb5a28d9784f51143f653363eaca3b4dcf0 100644 (file)
@@ -544,11 +544,11 @@ config CSKY_APB_INTC
 
 config IMX_IRQSTEER
        bool "i.MX IRQSTEER support"
-       depends on ARCH_MXC || COMPILE_TEST
-       default ARCH_MXC
+       depends on ARCH_MXC || ARCH_S32 || COMPILE_TEST
+       default y if ARCH_MXC || ARCH_S32
        select IRQ_DOMAIN
        help
-         Support for the i.MX IRQSTEER interrupt multiplexer/remapper.
+         Support for the i.MX and S32 IRQSTEER interrupt multiplexer/remapper.
 
 config IMX_INTMUX
        bool "i.MX INTMUX support" if COMPILE_TEST
index 4682ce5bf8d3c7a41bfb3427ad8a4f531563b46f..87b07f517be35e4333d0081d3d3c663221217c91 100644 (file)
 
 #define CHAN_MAX_OUTPUT_INT    0xF
 
+/* SoC does not implement the CHANCTRL register */
+#define IRQSTEER_QUIRK_NO_CHANCTRL     BIT(0)
+
+struct irqsteer_devtype_data {
+       u32     quirks;
+};
+
 struct irqsteer_data {
-       void __iomem            *regs;
-       struct clk              *ipg_clk;
-       int                     irq[CHAN_MAX_OUTPUT_INT];
-       int                     irq_count;
-       raw_spinlock_t          lock;
-       int                     reg_num;
-       int                     channel;
-       struct irq_domain       *domain;
-       u32                     *saved_reg;
-       struct device           *dev;
+       void __iomem                            *regs;
+       struct clk                              *ipg_clk;
+       int                                     irq[CHAN_MAX_OUTPUT_INT];
+       int                                     irq_count;
+       raw_spinlock_t                          lock;
+       int                                     reg_num;
+       int                                     channel;
+       struct irq_domain                       *domain;
+       u32                                     *saved_reg;
+       struct device                           *dev;
+       const struct irqsteer_devtype_data      *devtype_data;
+};
+
+static const struct irqsteer_devtype_data imx_data = { };
+
+static const struct irqsteer_devtype_data s32n79_data = {
+       .quirks = IRQSTEER_QUIRK_NO_CHANCTRL,
 };
 
+static bool irqsteer_has_chanctrl(const struct irqsteer_devtype_data *data)
+{
+       return !(data->quirks & IRQSTEER_QUIRK_NO_CHANCTRL);
+}
+
 static int imx_irqsteer_get_reg_index(struct irqsteer_data *data,
                                      unsigned long irqnum)
 {
@@ -188,6 +207,10 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
+       data->devtype_data = device_get_match_data(&pdev->dev);
+       if (!data->devtype_data)
+               return dev_err_probe(&pdev->dev, -ENODEV, "failed to match device data\n");
+
        /*
         * There is one output irq for each group of 64 inputs.
         * One register bit map can represent 32 input interrupts.
@@ -210,7 +233,8 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
        }
 
        /* steer all IRQs into configured channel */
-       writel_relaxed(BIT(data->channel), data->regs + CHANCTRL);
+       if (irqsteer_has_chanctrl(data->devtype_data))
+               writel_relaxed(BIT(data->channel), data->regs + CHANCTRL);
 
        data->domain = irq_domain_create_linear(dev_fwnode(&pdev->dev), data->reg_num * 32,
                                                &imx_irqsteer_domain_ops, data);
@@ -279,7 +303,9 @@ static void imx_irqsteer_restore_regs(struct irqsteer_data *data)
 {
        int i;
 
-       writel_relaxed(BIT(data->channel), data->regs + CHANCTRL);
+       if (irqsteer_has_chanctrl(data->devtype_data))
+               writel_relaxed(BIT(data->channel), data->regs + CHANCTRL);
+
        for (i = 0; i < data->reg_num; i++)
                writel_relaxed(data->saved_reg[i],
                               data->regs + CHANMASK(i, data->reg_num));
@@ -319,7 +345,8 @@ static const struct dev_pm_ops imx_irqsteer_pm_ops = {
 };
 
 static const struct of_device_id imx_irqsteer_dt_ids[] = {
-       { .compatible = "fsl,imx-irqsteer", },
+       { .compatible = "fsl,imx-irqsteer",     .data = &imx_data },
+       { .compatible = "nxp,s32n79-irqsteer",  .data = &s32n79_data },
        {},
 };