From nobody Thu Sep 24 12:09:41 2026 Received: from smtpout-02.galae.net (smtpout-02.galae.net [185.246.84.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5BDBE35677C; Thu, 24 Sep 2026 09:31:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.84.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790242272; cv=none; b=BFnSBWsJEsKDgzwBHrKX+eRBdxVVLawDO2L9kyr9r7o7wAwkszx1XckaGcEJt/TfMH23Ceza5T7nFC99k8/46TtZwaciiuNrYXbqHBrg2MfpovWJhdxNf3jEnw9BuUpsX8zzU6n6wk7rij1JvRHApPtVmEXFGz/HwJ13zFjaWKs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790242272; c=relaxed/simple; bh=n3hyLzFoSxZdeb4xNzn2eva8ul3VuNt/ZX3nznZtTzE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pDPVQ0H10jOhiH2+WeIHH5AM9swNI+AKrbDukXhWivjQkhqK90i+uUBslHT68gjhiYBsXi88B6hNqpae2uYqzgVnv5T1x2U2nQYGQOkRhD0THfHyL8GHdHil3kBkusniKlIysl/RsMXgmZP3wyJOHT+tsQ356ltVpOf+ZC3pJOU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=cbjx7603; arc=none smtp.client-ip=185.246.84.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="cbjx7603" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-02.galae.net (Postfix) with ESMTPS id 9AF601A0FFD; Thu, 24 Sep 2026 09:31:08 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 6EA6D5FB45; Thu, 24 Sep 2026 09:31:08 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id CB50E103294DF; Thu, 24 Sep 2026 11:31:04 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1790242266; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=/Y0MZScFajZWrkKqKqZGddXZHSBkTqkV4VwI6jO7es8=; b=cbjx76032+yxA84PRpvb/hbtbgfVA165PZVk6QEPTiYwXar/gI+6fE6cqGL4TlI7BDymi2 OePdTECG7g7rb3EkZ32aAxAypmyTKSsyaKD8uPyOagKkR+GyYu0VivI/0iNsDRf7tqSdGA g9BFcsG3e/OouaAD7txW5LRJULvYTgvWuZbNd213Y2T4zXRK4cgNmp0q3ENIvLLM2C7NXe G+yypfxKNhMBljt7v4h755j8oMNudokd6nnGKzyzFgQ76hYzlwyktrJZu5xI3017gMNBrY p2zrhlCaS5WnWXVvFDXZqYa6sSBFdiB7sxjxhV2LuHEQmzC39mw8O3KJPlExDw== From: Paul Louvel Date: Thu, 24 Sep 2026 11:30:25 +0200 Subject: [PATCH 1/3] dt-bindings: edac: cdns,ddr-edac: add Cadence DDR EDAC binding Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260924-paul-v7-3-rc1-edac-v1-1-70be37c41a18@bootlin.com> References: <20260924-paul-v7-3-rc1-edac-v1-0-70be37c41a18@bootlin.com> In-Reply-To: <20260924-paul-v7-3-rc1-edac-v1-0-70be37c41a18@bootlin.com> To: Borislav Petkov , Tony Luck , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Geert Uytterhoeven , Magnus Damm Cc: linux-kernel@vger.kernel.org, linux-edac@vger.kernel.org, devicetree@vger.kernel.org, Thomas Petazzoni , Miquel Raynal , Herve Codina , "Paul Louvel (Schneider Electric)" X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1790242261; l=2780; i=paul.louvel@bootlin.com; s=20260313; h=from:subject:message-id; bh=n3hyLzFoSxZdeb4xNzn2eva8ul3VuNt/ZX3nznZtTzE=; b=2YFbjH+z6vyy6L5CjY4RYC5+B6C7fNkReith/uoamBCdeWV0C5sxIfoBHhlUOfcBgt8u4fcPS awHG/JFq2jxCzhVn/0cL8oDiA82sOe7jNTw9mrmyvMGf23HY1osY1jj X-Developer-Key: i=paul.louvel@bootlin.com; a=ed25519; pk=eLW50NT18UAvUT5cAcYf88zNbBCZDLFXuptpyLVhVIU= X-Last-TLS-Session-Version: TLSv1.3 Add the Cadence EDAC DT binding. Signed-off-by: Paul Louvel (Schneider Electric) --- .../devicetree/bindings/edac/cdns,ddr-edac.yaml | 62 ++++++++++++++++++= ++++ MAINTAINERS | 6 +++ 2 files changed, 68 insertions(+) diff --git a/Documentation/devicetree/bindings/edac/cdns,ddr-edac.yaml b/Do= cumentation/devicetree/bindings/edac/cdns,ddr-edac.yaml new file mode 100644 index 000000000000..e0deeb3dfb81 --- /dev/null +++ b/Documentation/devicetree/bindings/edac/cdns,ddr-edac.yaml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/edac/cdns,ddr-edac.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Cadence DDR EDAC + +maintainers: + - Paul Louvel + +description: > + The Cadence DDR supports DDR2 and DDR3 memory with or without ECC. + The bootloader must configure ECC mode in the memory controller. + + The memory controller supports SECDED (single bit error correction, doub= le bit + error detection). ECC scrubbing has to be done via software. + +properties: + compatible: + items: + - const: renesas,r9a06g032-ddr-edac # RZ/N1D + - const: renesas,rzn1-ddr-edac # RZ/N1 + - const: cdns,ddr-edac + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: DDR controller clock + - description: APB internal bus clock + + clock-names: + items: + - const: ddrc + - const: pclk + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include + #include + + edac: memory-controller@4000d000 { + compatible =3D "renesas,r9a06g032-ddr-edac", "renesas,rzn1-ddr-edac"= , "cdns,ddr-edac"; + reg =3D <0x4000d000 0x1000>; + interrupts =3D ; + clocks =3D <&sysctrl R9A06G032_CLK_DDRC>, <&sysctrl R9A06G032_HCLK_D= DRC>; + clock-names =3D "ddrc", "pclk"; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 3a19da74d00c..60db3734df5b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5760,6 +5760,12 @@ L: linux-mm@kvack.org S: Maintained F: tools/testing/selftests/cachestat/test_cachestat.c =20 +CADENCE DDR EDAC DRIVER +M: Paul Louvel +L: linux-edac@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/edac/cdns,ddr-edac.yaml + CADENCE MIPI-CSI2 BRIDGES M: Maxime Ripard L: linux-media@vger.kernel.org --=20 2.55.0 From nobody Thu Sep 24 12:09:41 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CD3CF3A6EF0; Thu, 24 Sep 2026 09:31:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790242275; cv=none; b=HrRr2diO9Lljc/qUvjf83C1m8tEC/8/qG9OVEy9pHHZP4L7AQf8lZgZBG7tr4oktFdOF/ec0UgZnLDiJLVpN38oXPr0oi59VBLy7xWwskRwJNhk7VELjw7kApom1yfHmue32TBswD6JVL10V8MeQ2rkZXbnJOZrGOyS7i1j8BnY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790242275; c=relaxed/simple; bh=67P2mpc7B9O9eL1CkjwCRNT6AUmT7BnyNqsZPKqVcw8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=PBPWQBEYyHh9p3U+dP/ALCTk4wKCGg+3174vsdrRlCYgtJUeBu/TkbP/41PaQkpvuWTWj1IyJwl0FMUUCVUhB471Y7aySfwMdXlYHUQEVoigceTZOUq3i/3ccD5KzYpR1eL8vVQ6XbfuJV7EYKwqTGM6Cm+F77X+2UDgYmbVr+I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=XRj+KOzF; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="XRj+KOzF" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 231884E41057; Thu, 24 Sep 2026 09:31:11 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id EBBCD5FB45; Thu, 24 Sep 2026 09:31:10 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 389F51032900E; Thu, 24 Sep 2026 11:31:07 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1790242269; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=sYsWQpqrIhdimOH+oXMxMX/wD0emBRSB69Kepr67Fso=; b=XRj+KOzF0ctekM1SBxX2TxIPnJ9FGvnRy6hRu0sRn8/oLCh66V2yZlB1GsjbgbZ2xM7cdt XJ91EHKxGMq6ZBHy4k5q0FrN4H2YvJLgSJchVUi6mWSKhiuik0NLns5Ix4VxEScnUQtTMS cF7q14X6RU1Z0pYuir0ij1qOeFInDPvuYGuL5CGdh2wnRlE0vJhyhyx5SNJ1VslUTW5UEa nBPCnTlw1l2CdFskQKSxJ0PJLY8rlkqpoCmAtTs+luFXffbqe/aRu5/GyFVstz0OMtpjoC VAFbYeIZzt8FKdCJedrCbyC1se4432ZrtZ1HJ+3zcFQCVX8uzIwKbmS25SEgxQ== From: Paul Louvel Date: Thu, 24 Sep 2026 11:30:26 +0200 Subject: [PATCH 2/3] EDAC/cadence: Add Cadence DDR EDAC driver Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260924-paul-v7-3-rc1-edac-v1-2-70be37c41a18@bootlin.com> References: <20260924-paul-v7-3-rc1-edac-v1-0-70be37c41a18@bootlin.com> In-Reply-To: <20260924-paul-v7-3-rc1-edac-v1-0-70be37c41a18@bootlin.com> To: Borislav Petkov , Tony Luck , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Geert Uytterhoeven , Magnus Damm Cc: linux-kernel@vger.kernel.org, linux-edac@vger.kernel.org, devicetree@vger.kernel.org, Thomas Petazzoni , Miquel Raynal , Herve Codina , "Paul Louvel (Schneider Electric)" X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1790242261; l=12509; i=paul.louvel@bootlin.com; s=20260313; h=from:subject:message-id; bh=67P2mpc7B9O9eL1CkjwCRNT6AUmT7BnyNqsZPKqVcw8=; b=1JmpVgk8O32Li0CsWnGLCcbjMj+Y9306pJQJYOIWFYNoZqZtGEEho/eCx9X1vSnDbmjTUFKUC wUxWtQDOeXIDEDb1a+IBokWmVRe2G9PLP1PUitTm1jCy6uAnE+xvv7z X-Developer-Key: i=paul.louvel@bootlin.com; a=ed25519; pk=eLW50NT18UAvUT5cAcYf88zNbBCZDLFXuptpyLVhVIU= X-Last-TLS-Session-Version: TLSv1.3 Add the Cadence EDAC driver found on Renesas RZ/N1x SoC. The memory controller supports ECC, software scrubbing, and SECDED. Signed-off-by: Paul Louvel (Schneider Electric) --- MAINTAINERS | 1 + drivers/edac/Kconfig | 10 ++ drivers/edac/Makefile | 1 + drivers/edac/cadence_edac.c | 333 ++++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 345 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 60db3734df5b..0c7ab1d22172 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5765,6 +5765,7 @@ M: Paul Louvel L: linux-edac@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/edac/cdns,ddr-edac.yaml +F: drivers/edac/cadence_edac.c =20 CADENCE MIPI-CSI2 BRIDGES M: Maxime Ripard diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index a44b85c440ca..1707fe76b53c 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -503,6 +503,16 @@ config EDAC_QCOM For debugging issues having to do with stability and overall system health, you should probably say 'Y' here. =20 +config EDAC_CADENCE + tristate "Cadence EDAC Controller" + depends on HAS_IOMEM && OF + depends on ARCH_RZN1 || COMPILE_TEST + help + Support for error detection and correction on RZN1x SoCs. ECC must be + configured by the bootloader. + The controller supports single bit error correction, double bit error + detection. + config EDAC_ASPEED tristate "Aspeed AST BMC SoC" depends on ARCH_ASPEED diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index a37534300ab9..0d66a072b15c 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -82,6 +82,7 @@ obj-$(CONFIG_EDAC_SYNOPSYS) +=3D synopsys_edac.o obj-$(CONFIG_EDAC_XGENE) +=3D xgene_edac.o obj-$(CONFIG_EDAC_TI) +=3D ti_edac.o obj-$(CONFIG_EDAC_QCOM) +=3D qcom_edac.o +obj-$(CONFIG_EDAC_CADENCE) +=3D cadence_edac.o obj-$(CONFIG_EDAC_ASPEED) +=3D aspeed_edac.o obj-$(CONFIG_EDAC_BLUEFIELD) +=3D bluefield_edac.o obj-$(CONFIG_EDAC_DMC520) +=3D dmc520_edac.o diff --git a/drivers/edac/cadence_edac.c b/drivers/edac/cadence_edac.c new file mode 100644 index 000000000000..6567ac5147d0 --- /dev/null +++ b/drivers/edac/cadence_edac.c @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2015 Renesas Electronics Europe Ltd. + * Copyright 2026 Bootlin + * + * Based on highbank EDAC driver: + * + * Copyright 2011-2012 Calxeda, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "edac_mc.h" + +#define DRV_NAME "cdns_edac" + +#define REG_BYTE_SZ 4 +#define DDR_CTL(n) ((n) * REG_BYTE_SZ) + +#define CDNS_DDR_DDR_STAT DDR_CTL(0) +#define CDNS_DDR_DDR_STAT_DRAM_CLASS GENMASK_U32(11, 8) +#define CDNS_DDR_DDR_STAT_DRAM_DDR2 BIT(2) +#define CDNS_DDR_DDR_STAT_GET_DRAM_CLASS(reg) FIELD_GET(CDNS_DDR_DDR_STAT_= DRAM_CLASS, reg) + +#define CDNS_DDR_ECC_STAT DDR_CTL(36) +#define CDNS_DDR_ECC_STAT_ENABLED BIT(16) +#define CDNS_DDR_ECC_STAT_IS_ENABLED(reg) FIELD_GET(CDNS_DDR_ECC_STAT_ENAB= LED, reg) +#define CDNS_DDR_ECC_STAT_FWC BIT(24) + +#define CDNS_DDR_ECC_XOR DDR_CTL(37) +#define CDNS_DDR_ECC_XOR_CHECK_BITS GENMASK_U32(13, 0) + +#define CDNS_DDR_BUS_CTRL DDR_CTL(54) +#define CDNS_DDR_BUS_CTRL_REDUC BIT(1) + +/* DDR Controller Error Registers */ + +#define CDNS_DDR_ECC_U_ERR_ADDR DDR_CTL(38) +#define CDNS_DDR_ECC_U_ERR_STAT DDR_CTL(39) + +#define CDNS_DDR_ECC_C_ERR_ADDR DDR_CTL(41) +#define CDNS_DDR_ECC_C_ERR_STAT DDR_CTL(42) + +#define CDNS_DDR_ECC_ERR_STAT_GET_SYNDROME(reg) FIELD_GET(GENMASK(6, 0), r= eg) + +#define CDNS_DDR_PORT_CMD_ERR_ADDR DDR_CTL(61) +#define CDNS_DDR_PORT_CMD_ERR_TYPE DDR_CTL(62) +#define CDNS_DDR_PORT_CMD_ERR_TYPE_GET(reg) FIELD_GET(GENMASK_U32(10, 8), = reg) + +/* DDR Controller Interrupt Registers */ + +#define CDNS_DDR_ECC_INT_STAT DDR_CTL(56) +#define CDNS_DDR_ECC_INT_STAT_CE BIT(3) +#define CDNS_DDR_ECC_INT_STAT_MULTIPLE_CE BIT(4) +#define CDNS_DDR_ECC_INT_STAT_UE BIT(5) +#define CDNS_DDR_ECC_INT_STAT_MULTIPLE_UE BIT(6) +#define CDNS_DDR_ECC_INT_STAT_PORT_CMD_CHAN BIT(7) + +#define CDNS_DDR_ECC_INT_ACK DDR_CTL(57) +#define CDNS_DDR_ECC_INT_ACK_MASK GENMASK_U32(21, 0) + +#define CDNS_DDR_ECC_INT_CTRL DDR_CTL(58) +#define CDNS_DDR_ECC_INT_CTRL_MASK GENMASK_U32(21, 0) +#define CDNS_DDR_ECC_INT_CTRL_MASK_ALL BIT(22) +#define CDNS_DDR_ECC_INT_CTRL_UNMASK(i) ((~(i)) & CDNS_DDR_ECC_INT_CTRL_MA= SK) + +struct cdns_mc_priv { + void __iomem *io_base; +}; + +static void cdns_rmw(struct cdns_mc_priv *drv, u32 reg, u32 mask, u32 val) +{ + u32 regval; + + regval =3D readl(drv->io_base + reg); + FIELD_MODIFY(mask, ®val, val); + writel(regval, drv->io_base + reg); +} + +static irqreturn_t cdns_mc_err_handler(int irq, void *dev_id) +{ + struct mem_ctl_info *mci =3D dev_id; + struct cdns_mc_priv *priv =3D mci->pvt_info; + u32 addr, status, err_addr, syndrome, reg; + char other_details_str[32]; + u8 type; + + /* Read the interrupt status register */ + status =3D readl(priv->io_base + CDNS_DDR_ECC_INT_STAT); + + /* + * We can't know how many CE / UE occurred since last ACK in case of + * multiple errors. Just report it. + */ + + if ((status & CDNS_DDR_ECC_INT_STAT_UE) || (status & CDNS_DDR_ECC_INT_STA= T_MULTIPLE_UE)) { + reg =3D readl(priv->io_base + CDNS_DDR_ECC_U_ERR_STAT); + syndrome =3D CDNS_DDR_ECC_ERR_STAT_GET_SYNDROME(reg); + + err_addr =3D readl(priv->io_base + CDNS_DDR_ECC_U_ERR_ADDR); + + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, err_addr >> PAGE_= SHIFT, + err_addr & ~PAGE_MASK, syndrome, 0, 0, -1, mci->ctl_name, ""); + } + + if ((status & CDNS_DDR_ECC_INT_STAT_CE) || (status & CDNS_DDR_ECC_INT_STA= T_MULTIPLE_CE)) { + reg =3D readl(priv->io_base + CDNS_DDR_ECC_C_ERR_STAT); + syndrome =3D CDNS_DDR_ECC_ERR_STAT_GET_SYNDROME(reg); + + err_addr =3D readl(priv->io_base + CDNS_DDR_ECC_C_ERR_ADDR); + + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, err_addr >> PAGE_SH= IFT, + err_addr & ~PAGE_MASK, syndrome, 0, 0, -1, mci->ctl_name, ""); + } + + if (status & CDNS_DDR_ECC_INT_STAT_PORT_CMD_CHAN) { + addr =3D readl(priv->io_base + CDNS_DDR_PORT_CMD_ERR_ADDR); + reg =3D readl(priv->io_base + CDNS_DDR_PORT_CMD_ERR_TYPE); + type =3D CDNS_DDR_PORT_CMD_ERR_TYPE_GET(reg); + + snprintf(other_details_str, sizeof(other_details_str), "type 0x%02x", ty= pe); + + edac_mc_handle_error(HW_EVENT_ERR_INFO, mci, 1, addr >> PAGE_SHIFT, + addr & ~PAGE_MASK, 0, 0, 0, -1, mci->ctl_name, + other_details_str); + } + + /* clear the error, clears the interrupt */ + writel(status & CDNS_DDR_ECC_INT_ACK_MASK, priv->io_base + CDNS_DDR_ECC_I= NT_ACK); + + return IRQ_HANDLED; +} + +static void cdns_mc_err_inject(struct mem_ctl_info *mci, u16 synd) +{ + struct cdns_mc_priv *priv =3D mci->pvt_info; + + cdns_rmw(priv, CDNS_DDR_ECC_XOR, CDNS_DDR_ECC_XOR_CHECK_BITS, synd); + cdns_rmw(priv, CDNS_DDR_ECC_STAT, CDNS_DDR_ECC_STAT_FWC, 1); +} + +static ssize_t inject_ctrl_store(struct device *dev, struct device_attribu= te *attr, const char *buf, + size_t count) +{ + struct mem_ctl_info *mci =3D to_mci(dev); + u16 synd; + + if (kstrtou16(buf, 16, &synd)) + return -EINVAL; + + cdns_mc_err_inject(mci, synd); + + return count; +} + +static DEVICE_ATTR_WO(inject_ctrl); + +static struct attribute *cdns_edac_attrs[] =3D { &dev_attr_inject_ctrl.att= r, NULL }; + +ATTRIBUTE_GROUPS(cdns_edac); + +static void devm_cdns_edac_free(void *data) +{ + edac_mc_free(data); +} + +static void devm_cdns_edac_del(void *data) +{ + edac_mc_del_mc(data); +} + +static int cdns_get_mem_sz(resource_size_t *mem_sz) +{ + struct device_node *np; + struct resource res; + int ret; + + np =3D of_find_node_by_name(NULL, "memory"); + if (!np) + return -ENODEV; + + ret =3D of_address_to_resource(np, 0, &res); + + of_node_put(np); + + if (ret) + return ret; + + *mem_sz =3D resource_size(&res); + + return 0; +} + +static int cdns_mc_probe(struct platform_device *pdev) +{ +struct edac_mc_layer layers[2]; + struct clk_bulk_data clks[2] =3D { + { .id =3D "ddrc" }, + { .id =3D "pclk" }, + }; + struct cdns_mc_priv *priv; + struct mem_ctl_info *mci; + struct dimm_info *dimm; + resource_size_t mem_sz; + int ret, irq; + u32 reg; + + layers[0].type =3D EDAC_MC_LAYER_CHIP_SELECT; + layers[0].size =3D 1; + layers[0].is_virt_csrow =3D true; + layers[1].type =3D EDAC_MC_LAYER_CHANNEL; + layers[1].size =3D 1; + layers[1].is_virt_csrow =3D false; + mci =3D edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(struct cdns_m= c_priv)); + if (!mci) + return dev_err_probe(&pdev->dev, -ENOMEM, "unable to allocate edac mc\n"= ); + + ret =3D devm_add_action_or_reset(&pdev->dev, devm_cdns_edac_free, mci); + if (ret) + return ret; + + mci->pdev =3D &pdev->dev; + priv =3D mci->pvt_info; + + priv->io_base =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->io_base)) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->io_base), "unable to map = regs\n"); + + ret =3D devm_clk_bulk_get_enable(&pdev->dev, ARRAY_SIZE(clks), clks); + if (ret) + return dev_err_probe(&pdev->dev, ret, "unable to enable clocks\n"); + + reg =3D readl(priv->io_base + CDNS_DDR_ECC_STAT); + if (!CDNS_DDR_ECC_STAT_IS_ENABLED(reg)) + mci->edac_cap =3D EDAC_FLAG_NONE; + else + mci->edac_cap =3D EDAC_FLAG_SECDED; + + mci->mtype_cap =3D MEM_FLAG_DDR2 | MEM_FLAG_DDR3; + mci->edac_ctl_cap =3D EDAC_FLAG_NONE | EDAC_FLAG_SECDED; + mci->mod_name =3D pdev->dev.driver->name; + mci->ctl_name =3D "cdns-ddr-ctrl"; + mci->dev_name =3D dev_name(&pdev->dev); + mci->scrub_mode =3D SCRUB_SW_SRC; + + ret =3D cdns_get_mem_sz(&mem_sz); + if (ret) + return dev_err_probe(&pdev->dev, ret, "unable to get memory size\n"); + + dimm =3D *mci->dimms; + dimm->nr_pages =3D PFN_UP(mem_sz); + dimm->grain =3D 4; + dimm->edac_mode =3D EDAC_SECDED; + + /* Check if half datapath feature of the controller is active. */ + reg =3D readl(priv->io_base + CDNS_DDR_BUS_CTRL); + if (reg & CDNS_DDR_BUS_CTRL_REDUC) + dimm->dtype =3D DEV_X8; + else + dimm->dtype =3D DEV_X16; + + strscpy(dimm->label, "Channel#0_DIMM#0", sizeof(dimm->label)); + + reg =3D readl(priv->io_base + CDNS_DDR_DDR_STAT); + if (CDNS_DDR_DDR_STAT_GET_DRAM_CLASS(reg) =3D=3D CDNS_DDR_DDR_STAT_DRAM_D= DR2) + dimm->mtype =3D MEM_DDR2; + else + dimm->mtype =3D MEM_DDR3; + + ret =3D edac_mc_add_mc_with_groups(mci, cdns_edac_groups); + if (ret) + return dev_err_probe(&pdev->dev, ret, "failed to add mc\n"); + + ret =3D devm_add_action_or_reset(&pdev->dev, devm_cdns_edac_del, &pdev->d= ev); + if (ret) + return ret; + + writel(CDNS_DDR_ECC_INT_CTRL_MASK_ALL, priv->io_base + CDNS_DDR_ECC_INT_C= TRL); + + irq =3D platform_get_irq(pdev, 0); + if (irq < 0) + return dev_err_probe(&pdev->dev, irq, "unable to get irq\n"); + + ret =3D devm_request_irq(&pdev->dev, irq, cdns_mc_err_handler, 0, dev_nam= e(&pdev->dev), mci); + if (ret) + return dev_err_probe(&pdev->dev, ret, "unable to request irq %d\n", irq); + + /* + * Unmask ECC recoverable and unrecoverable interrupts, and port + * command errors. + */ + writel(CDNS_DDR_ECC_INT_CTRL_UNMASK( + CDNS_DDR_ECC_INT_STAT_CE | CDNS_DDR_ECC_INT_STAT_MULTIPLE_CE | + CDNS_DDR_ECC_INT_STAT_UE | CDNS_DDR_ECC_INT_STAT_MULTIPLE_UE | + CDNS_DDR_ECC_INT_STAT_PORT_CMD_CHAN), + priv->io_base + CDNS_DDR_ECC_INT_CTRL); + + edac_mc_chipset_printk(mci, KERN_DEBUG, DRV_NAME, "ECC %s", + (mci->edac_cap =3D=3D EDAC_FLAG_NONE) ? "disabled" : "enabled"); + + return 0; +} + +static const struct of_device_id cdns_ddr_ctrl_of_match[] =3D { + { .compatible =3D "cdns,ddr-edac" }, + {}, +}; +MODULE_DEVICE_TABLE(of, cdns_ddr_ctrl_of_match); + +static struct platform_driver cdns_mc_edac_driver =3D { + .probe =3D cdns_mc_probe, + .driver =3D { + .name =3D DRV_NAME, + .of_match_table =3D cdns_ddr_ctrl_of_match, + }, +}; + +module_platform_driver(cdns_mc_edac_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Renesas Electronics Europe Ltd."); +MODULE_AUTHOR("Paul Louvel "); +MODULE_DESCRIPTION("EDAC driver for Cadence DDR controller"); --=20 2.55.0 From nobody Thu Sep 24 12:09:41 2026 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8888E3B14D0 for ; Thu, 24 Sep 2026 09:31:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790242277; cv=none; b=AiwlOhaoGBM17/QIAzzRuxIapWKiJKPXYJU9bWJDnDNJf+zHXEc016dU8FruBX07UVxzD3NfEZhjYW9P8thVD7qtINE8BhWQBDbOW9SUEpQJtRD7hZ+VCy2P/OEQBlyYen5P4SHshz5S/CPYvaEDxAZCYrxSrWwDoj0Kyku/4v4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790242277; c=relaxed/simple; bh=nA/rC2OvJeW0AaqvGfx1Brf8SxDvZIsuz7E/iVHMkZM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lonG376AQ6XlfAgZeSygeeF4ZoxA7n177fTrGy/sV1xMIc3weO4ExkuejPMUDxtLer7klFKlyD+Izkf3TMuJUVM6BLj0MSsiGn3XkZaGJ2ckkmu+A1F8vlIRxVaOGiYglysa49ocK/iddppBE2xGBlo7XtCbwvQ9RSl06tOgEYA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=KcT7W6kL; arc=none smtp.client-ip=185.171.202.116 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="KcT7W6kL" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id D713CC211E2; Thu, 24 Sep 2026 09:32:00 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 832F35FB45; Thu, 24 Sep 2026 09:31:13 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id D0EA4103294C2; Thu, 24 Sep 2026 11:31:09 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1790242271; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=xLAWXoAqE+60g1cvgidm3NIwGVVBCvvmj/eG9JwqIno=; b=KcT7W6kLL70eJuB76f+jLJ9U+aPl4Z0E+mE3bLRn4ts6yPymaa9yAyAbizruUp+nl77J27 oQ099gprTWyMjfpMtvtEw++b9ZmcINkBIcTCNXwKVmWK1Y8d9Yj5kT14Sd5YCgIi4qwdgX jkyDjccdS85O6T5B6WdsZMkhm5nk/Fs5a5LxDdldHJscxzEKC8g0ljGq7eAmEfidTlMotQ jwvcmNot4dmWv/hWJ+snLpJnSkApphs4m/LVTLwQmEdnpC1v2as4MWgy51co81rlCOS5Zi 6BH4k8AoZGLeKcPnOfoEBmsxcKn5wA8hPf89dFeQIRG+rVvzMNDHPzr+iT+Uow== From: Paul Louvel Date: Thu, 24 Sep 2026 11:30:27 +0200 Subject: [PATCH 3/3] ARM: dts: renesas: r9a06g032: add EDAC node Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260924-paul-v7-3-rc1-edac-v1-3-70be37c41a18@bootlin.com> References: <20260924-paul-v7-3-rc1-edac-v1-0-70be37c41a18@bootlin.com> In-Reply-To: <20260924-paul-v7-3-rc1-edac-v1-0-70be37c41a18@bootlin.com> To: Borislav Petkov , Tony Luck , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Geert Uytterhoeven , Magnus Damm Cc: linux-kernel@vger.kernel.org, linux-edac@vger.kernel.org, devicetree@vger.kernel.org, Thomas Petazzoni , Miquel Raynal , Herve Codina , "Paul Louvel (Schneider Electric)" X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1790242261; l=1034; i=paul.louvel@bootlin.com; s=20260313; h=from:subject:message-id; bh=nA/rC2OvJeW0AaqvGfx1Brf8SxDvZIsuz7E/iVHMkZM=; b=/awqOfeqO5xSucxLXU+EiYTn+ORlLqiat2BlCwyf4j7SGQNBnKdLkgn5zyl8WR7RW+yf8IrSm CXvPq7u0RI+CqwNqbXZ7v4zlTNXFCIn0HLaiOdSfMSRMogUBHeXHasY X-Developer-Key: i=paul.louvel@bootlin.com; a=ed25519; pk=eLW50NT18UAvUT5cAcYf88zNbBCZDLFXuptpyLVhVIU= X-Last-TLS-Session-Version: TLSv1.3 Add EDAC node to the SoC base device tree file. Signed-off-by: Paul Louvel (Schneider Electric) --- arch/arm/boot/dts/renesas/r9a06g032.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/renesas/r9a06g032.dtsi b/arch/arm/boot/dts/r= enesas/r9a06g032.dtsi index 19c9bce0a26d..779221931fb6 100644 --- a/arch/arm/boot/dts/renesas/r9a06g032.dtsi +++ b/arch/arm/boot/dts/renesas/r9a06g032.dtsi @@ -164,6 +164,16 @@ dmamux: dma-router@a0 { }; }; =20 + edac: memory-controller@4000d000 { + compatible =3D "renesas,r9a06g032-ddr-edac", "renesas,rzn1-ddr-edac", + "cdns,ddr-edac"; + reg =3D <0x4000d000 0x1000>; + interrupts =3D ; + clocks =3D <&sysctrl R9A06G032_CLK_DDRC>, <&sysctrl R9A06G032_HCLK_DDRC= >; + clock-names =3D "ddrc", "pclk"; + status =3D "disabled"; + }; + udc: usb@4001e000 { compatible =3D "renesas,r9a06g032-usbf", "renesas,rzn1-usbf"; reg =3D <0x4001e000 0x2000>; --=20 2.55.0