From: Dinh Nguyen <dinguyen@kernel.org>
To: bp@alien8.de, tony.luck@intel.com
Cc: dinguyen@kernel.org, rounakdas2025@gmail.com,
niravkumar.l.rabara@altera.com, robh@kernel.org,
krzk+dt@kernel.org, conor+dt@kernel.org,
linux-edac@vger.kernel.org, linux-kernel@vger.kernel.org,
devicetree@vger.kernel.org
Subject: [PATCHv2 3/4] EDAC/altera: Add support for Agilex5 ECC manager
Date: Mon, 9 Nov 2026 10:25:22 -0600 [thread overview]
Message-ID: <20261109162523.1698129-3-dinguyen@kernel.org> (raw)
In-Reply-To: <20261109162523.1698129-1-dinguyen@kernel.org>
Add support for the Agilex5 ECC manager, unlike Stratix10/Agilex7,
Agilex5 exposes up to 7 named interrupts on its DT node:
global_sbe - aggregate single-bit error (chained, drives IRQ domain)
global_dbe - aggregate double-bit error (chained; DBE is no longer
delivered exclusively through Asynchronous SError)
io96b0 - IO96B0 DRAM controller ECC
io96b1 - IO96B1 DRAM controller ECC
sdm_qspi_sbe - SDM QSPI single-bit error
sdm_qspi_dbe - SDM QSPI double-bit error
sdm_seu - SDM single-event-upset
Place all seven interrupt's name in a new agilex5_irqs[] array on struct
altr_arria10_edac so subsequent peripheral support (IO96B, SDM QSPI, CRAM
SEU) can consume them without re-parsing the DT. Only the global_sbe is
mandatory, the rest are optional.
global_sbe is wired up as the chained SBE handler (replacing the legacy
index-0 lookup). global_dbe is hooked into the same
altr_edac_a10_irq_handler() so that the existing sb_irq/db_irq demux
routes DBE events through the manager's IRQ domain.
Legacy A10/S10 probe paths are unchanged.
Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
---
v2: Reorganize db_error so Agilex5 goes last to prevent going into
default condition for A10
Clean up the commit message to be less wordy
---
drivers/edac/altera_edac.c | 84 ++++++++++++++++++++++++++++++++++++--
drivers/edac/altera_edac.h | 29 +++++++++++++
2 files changed, 109 insertions(+), 4 deletions(-)
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
index 78f4a1b0fc64a..7d9dd66170c9a 100644
--- a/drivers/edac/altera_edac.c
+++ b/drivers/edac/altera_edac.c
@@ -2107,11 +2107,63 @@ static int s10_edac_dberr_handler(struct notifier_block *this,
return NOTIFY_DONE;
}
+/*
+ * Ordered table of named interrupts published by an
+ * "altr,socfpga-agilex5-ecc-manager" device tree node. Indices match
+ * enum altr_agilex5_irq_idx. Only "global_sbe" is mandatory; the rest are
+ * optional so platforms can omit interrupts for unused subsystems.
+ */
+static const char * const altr_agilex5_irq_names[ALTR_AGILEX5_NUM_IRQS] = {
+ [ALTR_AGILEX5_IRQ_GLOBAL_SBE] = "global_sbe",
+ [ALTR_AGILEX5_IRQ_GLOBAL_DBE] = "global_dbe",
+ [ALTR_AGILEX5_IRQ_IO96B0] = "io96b0",
+ [ALTR_AGILEX5_IRQ_IO96B1] = "io96b1",
+ [ALTR_AGILEX5_IRQ_SDM_QSPI_SBE] = "sdm_qspi_sbe",
+ [ALTR_AGILEX5_IRQ_SDM_QSPI_DBE] = "sdm_qspi_dbe",
+ [ALTR_AGILEX5_IRQ_SDM_SEU] = "sdm_seu",
+};
+
+/*
+ * Populate edac->agilex5_irqs[] from the named interrupts on the manager
+ * platform device. Missing optional interrupts are stored as a negative
+ * errno (-ENXIO) so that subsequent feature code can probe whether the
+ * resource exists. global_sbe is required because it drives the manager's
+ * IRQ domain dispatch path.
+ *
+ * platform_get_irq_byname_optional() can return -EPROBE_DEFER when the
+ * parent irqchip (e.g. the GIC) is not yet probed. Propagate that error
+ * up so the kernel re-tries the probe later instead of permanently
+ * disabling the named interrupt.
+ */
+static int altr_agilex5_get_named_irqs(struct platform_device *pdev,
+ struct altr_arria10_edac *edac)
+{
+ int i, irq;
+
+ for (i = 0; i < ALTR_AGILEX5_NUM_IRQS; i++) {
+ irq = platform_get_irq_byname_optional(pdev,
+ altr_agilex5_irq_names[i]);
+ if (irq == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ edac->agilex5_irqs[i] = irq > 0 ? irq : -ENXIO;
+ }
+
+ if (edac->agilex5_irqs[ALTR_AGILEX5_IRQ_GLOBAL_SBE] < 0) {
+ dev_err(&pdev->dev,
+ "Agilex5 ECC manager missing required 'global_sbe' interrupt\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
/****************** Arria 10 EDAC Probe Function *********************/
static int altr_edac_a10_probe(struct platform_device *pdev)
{
struct altr_arria10_edac *edac;
struct device_node *child;
+ int rc;
edac = devm_kzalloc(&pdev->dev, sizeof(*edac), GFP_KERNEL);
if (!edac)
@@ -2147,14 +2199,30 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
return -ENOMEM;
}
- edac->sb_irq = platform_get_irq(pdev, 0);
- if (edac->sb_irq < 0)
- return edac->sb_irq;
+ if (edac->flag == SOCFPGA_AGILEX5) {
+ rc = altr_agilex5_get_named_irqs(pdev, edac);
+ if (rc)
+ return rc;
+
+ edac->sb_irq = edac->agilex5_irqs[ALTR_AGILEX5_IRQ_GLOBAL_SBE];
+ } else {
+ edac->sb_irq = platform_get_irq(pdev, 0);
+ if (edac->sb_irq < 0)
+ return edac->sb_irq;
+ }
irq_set_chained_handler_and_data(edac->sb_irq,
altr_edac_a10_irq_handler,
edac);
+ /*
+ * Unlike Stratix10/Agilex7 (which deliver uncorrectable errors as
+ * Asynchronous SError), Agilex5 routes the global double-bit error
+ * through a dedicated SPI ("global_dbe"). Hook it into the same
+ * chained handler so the existing sb_irq/db_irq demux in
+ * altr_edac_a10_irq_handler() routes DBE events through the manager's
+ * IRQ domain.
+ */
if (edac->flag == SOCFPGA_S10) {
int dberror, err_addr;
@@ -2177,13 +2245,19 @@ static int altr_edac_a10_probe(struct platform_device *pdev)
regmap_write(edac->ecc_mgr_map,
S10_SYSMGR_UE_ADDR_OFST, 0);
}
- } else {
+ } else if (edac->flag == SOCFPGA_A10) {
edac->db_irq = platform_get_irq(pdev, 1);
if (edac->db_irq < 0)
return edac->db_irq;
irq_set_chained_handler_and_data(edac->db_irq,
altr_edac_a10_irq_handler, edac);
+ } else if (edac->flag == SOCFPGA_AGILEX5 &&
+ edac->agilex5_irqs[ALTR_AGILEX5_IRQ_GLOBAL_DBE] >= 0) {
+ edac->db_irq = edac->agilex5_irqs[ALTR_AGILEX5_IRQ_GLOBAL_DBE];
+ irq_set_chained_handler_and_data(edac->db_irq,
+ altr_edac_a10_irq_handler,
+ edac);
}
for_each_child_of_node(pdev->dev.of_node, child) {
@@ -2209,6 +2283,8 @@ static const struct of_device_id altr_edac_a10_of_match[] = {
.data = (void *)SOCFPGA_A10 },
{ .compatible = "altr,socfpga-s10-ecc-manager",
.data = (void *)SOCFPGA_S10 },
+ { .compatible = "altr,socfpga-agilex5-ecc-manager",
+ .data = (void *)SOCFPGA_AGILEX5 },
{},
};
MODULE_DEVICE_TABLE(of, altr_edac_a10_of_match);
diff --git a/drivers/edac/altera_edac.h b/drivers/edac/altera_edac.h
index 4a9da28fa96ba..03b50079b657a 100644
--- a/drivers/edac/altera_edac.h
+++ b/drivers/edac/altera_edac.h
@@ -326,6 +326,27 @@ struct altr_sdram_mc_data {
#define S10_DDR0_IRQ_MASK BIT(16)
#define S10_DBE_IRQ_MASK 0x3FFFE
+/************* Agilex5 Defines **************/
+/*
+ * The Agilex5 ECC manager exposes up to 7 named interrupts on the manager
+ * node. global_sbe and global_dbe are aggregate single/double-bit error
+ * interrupts that fan-out through the manager's IRQ domain to the child
+ * peripheral ECCs. The remaining named interrupts are routed directly from
+ * dedicated controllers (IO96B memory controllers and Secure Device Manager)
+ * to the GIC.
+ */
+#define ALTR_AGILEX5_NUM_IRQS 7
+
+enum altr_agilex5_irq_idx {
+ ALTR_AGILEX5_IRQ_GLOBAL_SBE,
+ ALTR_AGILEX5_IRQ_GLOBAL_DBE,
+ ALTR_AGILEX5_IRQ_IO96B0,
+ ALTR_AGILEX5_IRQ_IO96B1,
+ ALTR_AGILEX5_IRQ_SDM_QSPI_SBE,
+ ALTR_AGILEX5_IRQ_SDM_QSPI_DBE,
+ ALTR_AGILEX5_IRQ_SDM_SEU,
+};
+
/* Define ECC Block Offsets for peripherals */
#define ECC_BLK_ADDRESS_OFST 0x40
#define ECC_BLK_RDATA0_OFST 0x44
@@ -401,6 +422,14 @@ struct altr_arria10_edac {
struct list_head a10_ecc_devices;
struct notifier_block panic_notifier;
unsigned long flag;
+
+ /*
+ * Agilex5 ECC manager supports up to 7 named interrupts. Entries
+ * are indexed by the altr_agilex5_irq_idx enum and hold the virtual
+ * IRQ number, or a negative errno when the corresponding interrupt
+ * was not provided in the device tree.
+ */
+ int agilex5_irqs[ALTR_AGILEX5_NUM_IRQS];
};
#endif /* #ifndef _ALTERA_EDAC_H */
--
2.42.0.411.g813d9a9188
next prev parent reply other threads:[~2026-11-09 16:25 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-09 16:25 [PATCHv2 1/4] EDAC/altera: use flag to differentiate 64-bit platforms Dinh Nguyen
2026-11-09 16:25 ` [PATCHv2 2/4] dt-bindings: edac: altera: agilex5: document new edac support Dinh Nguyen
2026-11-09 16:25 ` Dinh Nguyen [this message]
2026-11-09 16:25 ` [PATCHv2 4/4] arm64: dts: socfpga: agilex5: add support for the ECC manager Dinh Nguyen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261109162523.1698129-3-dinguyen@kernel.org \
--to=dinguyen@kernel.org \
--cc=bp@alien8.de \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=krzk+dt@kernel.org \
--cc=linux-edac@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=niravkumar.l.rabara@altera.com \
--cc=robh@kernel.org \
--cc=rounakdas2025@gmail.com \
--cc=tony.luck@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®