stmmac: s32: enable support for Multi-IRQ mode

Based on previous changes in platform driver, the vendor
glue driver can enable Multi-IRQ mode, if needed.

To get enabled Multi-IRQ mode for dwmac-s32, the driver checks:

  1) property of 'snps,mtl-xx-config' subnode
     defines 'snps,xx-queues-to-use' bigger then one, ie:

     ethernet@4033c000 {
         compatible = "nxp,s32g2-dwmac";
         ...
         snps,mtl-rx-config = <&mtl_rx_setup>;
         ...

         mtl_rx_setup: rx-queues-config {
             snps,rx-queues-to-use = <2>;
         };

  2) queue based IRQs are set, ie:

     ethernet@4033c000 {
         compatible = "nxp,s32g2-dwmac";
         ...
         interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
                      /* CHN 0: tx, rx */
                      <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
                      <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
                      /* CHN 1: tx, rx */
                      <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
                      <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
         interrupt-names = "macirq",
                           "tx-queue-0", "rx-queue-0",
                           "tx-queue-1", "rx-queue-1";

If those prerequisites are met, the driver switches to Multi-IRQ mode,
using per-queue IRQs for rx/tx data pathr:

[    1.387045] s32-dwmac 4033c000.ethernet: Multi-IRQ mode (per queue IRQs) selected

Now the driver owns all queues IRQs:

root@s32g399aevb3:~# grep eth /proc/interrupts
 29:    0    0    0    0    0    0    0    0    GICv3  89 Level   eth0:mac
 30:    0    0    0    0    0    0    0    0    GICv3  91 Level   eth0:rx-0
 31:    0    0    0    0    0    0    0    0    GICv3  93 Level   eth0:rx-1
 32:    0    0    0    0    0    0    0    0    GICv3  95 Level   eth0:rx-2
 33:    0    0    0    0    0    0    0    0    GICv3  97 Level   eth0:rx-3
 34:    0    0    0    0    0    0    0    0    GICv3  99 Level   eth0:rx-4
 35:    0    0    0    0    0    0    0    0    GICv3  90 Level   eth0:tx-0
 36:    0    0    0    0    0    0    0    0    GICv3  92 Level   eth0:tx-1
 37:    0    0    0    0    0    0    0    0    GICv3  94 Level   eth0:tx-2
 38:    0    0    0    0    0    0    0    0    GICv3  96 Level   eth0:tx-3
 39:    0    0    0    0    0    0    0    0    GICv3  98 Level   eth0:tx-4

Otherwise, if one of the prerequisite don't met, the driver
continue with MAC IRQ mode:

[    1.387045] s32-dwmac 4033c000.ethernet: MAC IRQ mode selected

And only MAC IRQ will be attached:

root@s32g399aevb3:~# grep eth /proc/interrupts
 29:    0    0    0    0    0    0    0    0    GICv3  89 Level   eth0:mac

What represents the original MAC IRQ mode and is fully backward
compatible.

Reviewed-by: Matthias Brugger <mbrugger@suse.com>
Signed-off-by: Jan Petrous (OSS) <jan.petrous@oss.nxp.com>
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Link: https://patch.msgid.link/20260313-dwmac_multi_irq-v12-4-b5c9d0aa13d6@oss.nxp.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jan Petrous (OSS) 2026-03-13 08:13:35 +01:00 committed by Jakub Kicinski
parent cc7a3435df
commit 66ccb4f1d2

View File

@ -2,7 +2,7 @@
/*
* NXP S32G/R GMAC glue layer
*
* Copyright 2019-2024 NXP
* Copyright 2019-2026 NXP
*
*/
@ -110,6 +110,37 @@ static void s32_gmac_exit(struct device *dev, void *priv)
clk_disable_unprepare(gmac->rx_clk);
}
static void s32_gmac_setup_multi_irq(struct device *dev,
struct plat_stmmacenet_data *plat,
struct stmmac_resources *res)
{
int i;
/* RX IRQs */
for (i = 0; i < plat->rx_queues_to_use; i++) {
if (res->rx_irq[i] <= 0) {
dev_dbg(dev, "Missing RX queue %d interrupt\n", i);
goto mac_irq_mode;
}
}
/* TX IRQs */
for (i = 0; i < plat->tx_queues_to_use; i++) {
if (res->tx_irq[i] <= 0) {
dev_dbg(dev, "Missing TX queue %d interrupt\n", i);
goto mac_irq_mode;
}
}
plat->flags |= STMMAC_FLAG_MULTI_MSI_EN;
dev_info(dev, "Multi-IRQ mode (per queue IRQs) selected\n");
return;
mac_irq_mode:
plat->flags &= ~STMMAC_FLAG_MULTI_MSI_EN;
dev_info(dev, "MAC IRQ mode selected\n");
}
static int s32_dwmac_probe(struct platform_device *pdev)
{
struct plat_stmmacenet_data *plat;
@ -165,6 +196,9 @@ static int s32_dwmac_probe(struct platform_device *pdev)
plat->core_type = DWMAC_CORE_GMAC4;
plat->pmt = true;
plat->flags |= STMMAC_FLAG_SPH_DISABLE;
s32_gmac_setup_multi_irq(dev, plat, &res);
plat->rx_fifo_size = 20480;
plat->tx_fifo_size = 20480;