* [PATCH v6 0/9] EDAC drivers for Armada XP L2 and DDR @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham The current plan is for these to go in via the ARM tree once appropriate Reviews/Acks have been given http://lists.infradead.org/pipermail/linux-arm-kernel/2017-August/525561.html This series adds drivers for the L2 cache and DDR RAM ECC functionality as found on the MV78230/MV78x60 SoCs. Jan has tested these changes with the MV78460 (on a custom board with a DDR3 ECC DIMM), Chris has tested these changes with 88F6820 and 98dx3236 (both a custom boards with fixed DDR3 + ECC). Also contained in this series is an additional debugfs wrapper. Compared to the previous v5 series I've split the dt-binding documentation into its own patch and updated armada_xp_edac.c to use a SPDX license. Compared to the previous v4 series I've added my s-o-b to some of Jan's patches and rebased against v4.19.0. Compared to the previous v3 series, the following changes have been made: - Use shorter names for the AURORA ECC and parity registers - Numerous formatting changes to edac/armada_xp.c (as requested by Boris) - Added support for Armada-38x and 98dx3236 SoCs Compared to the previous v2 series, the following changes have been made: - Allocate EDAC structures later during probing and drop devres support patches (requested by Boris) - Make drvdata->width usage consistent according to the comment (suggested by Chris) Compared to the previous v1 series, the following changes have been made: - Add the aurora-l2 register defines earlier in the series (suggested by Russell King and Gregory CLEMENT ) - Changed the DT vendor prefix from "arm" to "marvell" for the ecc-enable/disable properties on the aurora-l2 (suggested by Russell King) - Fix some warnings reported by checkpatch Compared to the original RFC series, the following changes have been made: - Integrated Chris' patches for parity and ECC configuration via DT - Merged the DDR RAM and L2 cache drivers (as requested by Boris, analogous to fsl_ddr_edac.c and mpc85xx_edac.c) - Added myself to MAINTAINERS (requested by Boris) - L2 cache: Track the msg size and use snprintf (review comment by Chris) - L2 cache: Split error injection from the check function (review comment by Chris) - DDR RAM: Allow 16 bit width in addition to 32 and 64 bit (review comment by Chris) - Use of_match_ptr() (review comments by Chris) - Minor checkpatch cleanups Chris Packham (4): ARM: l2x0: support parity-enable/disable on aurora dt-bindings: ARM: document marvell,ecc-enable binding ARM: l2x0: add marvell,ecc-enable property for aurora EDAC: armada_xp: Add support for more SoCs Jan Luebbe (5): ARM: l2c: move cache-aurora-l2.h to asm/hardware ARM: aurora-l2: add prefix to MAX_RANGE_SIZE ARM: aurora-l2: add defines for parity and ECC registers EDAC: Add missing debugfs_create_x32 wrapper EDAC: Add driver for the Marvell Armada XP SDRAM and L2 cache ECC .../devicetree/bindings/arm/l2c2x0.txt | 2 + MAINTAINERS | 6 + .../asm/hardware}/cache-aurora-l2.h | 50 +- arch/arm/mm/cache-l2x0.c | 20 +- drivers/edac/Kconfig | 7 + drivers/edac/Makefile | 1 + drivers/edac/armada_xp_edac.c | 635 ++++++++++++++++++ drivers/edac/debugfs.c | 11 + drivers/edac/edac_module.h | 5 + 9 files changed, 733 insertions(+), 4 deletions(-) rename arch/arm/{mm => include/asm/hardware}/cache-aurora-l2.h (50%) create mode 100644 drivers/edac/armada_xp_edac.c -- 2.19.1 ^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v6 0/9] EDAC drivers for Armada XP L2 and DDR @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux-arm-kernel The current plan is for these to go in via the ARM tree once appropriate Reviews/Acks have been given http://lists.infradead.org/pipermail/linux-arm-kernel/2017-August/525561.html This series adds drivers for the L2 cache and DDR RAM ECC functionality as found on the MV78230/MV78x60 SoCs. Jan has tested these changes with the MV78460 (on a custom board with a DDR3 ECC DIMM), Chris has tested these changes with 88F6820 and 98dx3236 (both a custom boards with fixed DDR3 + ECC). Also contained in this series is an additional debugfs wrapper. Compared to the previous v5 series I've split the dt-binding documentation into its own patch and updated armada_xp_edac.c to use a SPDX license. Compared to the previous v4 series I've added my s-o-b to some of Jan's patches and rebased against v4.19.0. Compared to the previous v3 series, the following changes have been made: - Use shorter names for the AURORA ECC and parity registers - Numerous formatting changes to edac/armada_xp.c (as requested by Boris) - Added support for Armada-38x and 98dx3236 SoCs Compared to the previous v2 series, the following changes have been made: - Allocate EDAC structures later during probing and drop devres support patches (requested by Boris) - Make drvdata->width usage consistent according to the comment (suggested by Chris) Compared to the previous v1 series, the following changes have been made: - Add the aurora-l2 register defines earlier in the series (suggested by Russell King and Gregory CLEMENT ) - Changed the DT vendor prefix from "arm" to "marvell" for the ecc-enable/disable properties on the aurora-l2 (suggested by Russell King) - Fix some warnings reported by checkpatch Compared to the original RFC series, the following changes have been made: - Integrated Chris' patches for parity and ECC configuration via DT - Merged the DDR RAM and L2 cache drivers (as requested by Boris, analogous to fsl_ddr_edac.c and mpc85xx_edac.c) - Added myself to MAINTAINERS (requested by Boris) - L2 cache: Track the msg size and use snprintf (review comment by Chris) - L2 cache: Split error injection from the check function (review comment by Chris) - DDR RAM: Allow 16 bit width in addition to 32 and 64 bit (review comment by Chris) - Use of_match_ptr() (review comments by Chris) - Minor checkpatch cleanups Chris Packham (4): ARM: l2x0: support parity-enable/disable on aurora dt-bindings: ARM: document marvell,ecc-enable binding ARM: l2x0: add marvell,ecc-enable property for aurora EDAC: armada_xp: Add support for more SoCs Jan Luebbe (5): ARM: l2c: move cache-aurora-l2.h to asm/hardware ARM: aurora-l2: add prefix to MAX_RANGE_SIZE ARM: aurora-l2: add defines for parity and ECC registers EDAC: Add missing debugfs_create_x32 wrapper EDAC: Add driver for the Marvell Armada XP SDRAM and L2 cache ECC .../devicetree/bindings/arm/l2c2x0.txt | 2 + MAINTAINERS | 6 + .../asm/hardware}/cache-aurora-l2.h | 50 +- arch/arm/mm/cache-l2x0.c | 20 +- drivers/edac/Kconfig | 7 + drivers/edac/Makefile | 1 + drivers/edac/armada_xp_edac.c | 635 ++++++++++++++++++ drivers/edac/debugfs.c | 11 + drivers/edac/edac_module.h | 5 + 9 files changed, 733 insertions(+), 4 deletions(-) rename arch/arm/{mm => include/asm/hardware}/cache-aurora-l2.h (50%) create mode 100644 drivers/edac/armada_xp_edac.c -- 2.19.1 ^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v6 1/9] ARM: l2c: move cache-aurora-l2.h to asm/hardware @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham From: Jan Luebbe <jlu@pengutronix.de> This include file will be used by the AURORA EDAC code. Signed-off-by: Jan Luebbe <jlu@pengutronix.de> Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- arch/arm/{mm => include/asm/hardware}/cache-aurora-l2.h | 0 arch/arm/mm/cache-l2x0.c | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename arch/arm/{mm => include/asm/hardware}/cache-aurora-l2.h (100%) diff --git a/arch/arm/mm/cache-aurora-l2.h b/arch/arm/include/asm/hardware/cache-aurora-l2.h similarity index 100% rename from arch/arm/mm/cache-aurora-l2.h rename to arch/arm/include/asm/hardware/cache-aurora-l2.h diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 808efbb89b88..a00d6f7fd34c 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -30,8 +30,8 @@ #include <asm/cp15.h> #include <asm/cputype.h> #include <asm/hardware/cache-l2x0.h> +#include <asm/hardware/cache-aurora-l2.h> #include "cache-tauros3.h" -#include "cache-aurora-l2.h" struct l2c_init_data { const char *type; -- 2.19.1 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v6 1/9] ARM: l2c: move cache-aurora-l2.h to asm/hardware @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux-arm-kernel From: Jan Luebbe <jlu@pengutronix.de> This include file will be used by the AURORA EDAC code. Signed-off-by: Jan Luebbe <jlu@pengutronix.de> Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- arch/arm/{mm => include/asm/hardware}/cache-aurora-l2.h | 0 arch/arm/mm/cache-l2x0.c | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename arch/arm/{mm => include/asm/hardware}/cache-aurora-l2.h (100%) diff --git a/arch/arm/mm/cache-aurora-l2.h b/arch/arm/include/asm/hardware/cache-aurora-l2.h similarity index 100% rename from arch/arm/mm/cache-aurora-l2.h rename to arch/arm/include/asm/hardware/cache-aurora-l2.h diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 808efbb89b88..a00d6f7fd34c 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -30,8 +30,8 @@ #include <asm/cp15.h> #include <asm/cputype.h> #include <asm/hardware/cache-l2x0.h> +#include <asm/hardware/cache-aurora-l2.h> #include "cache-tauros3.h" -#include "cache-aurora-l2.h" struct l2c_init_data { const char *type; -- 2.19.1 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [v6,1/9] ARM: l2c: move cache-aurora-l2.h to asm/hardware @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham From: Jan Luebbe <jlu@pengutronix.de> This include file will be used by the AURORA EDAC code. Signed-off-by: Jan Luebbe <jlu@pengutronix.de> Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- arch/arm/{mm => include/asm/hardware}/cache-aurora-l2.h | 0 arch/arm/mm/cache-l2x0.c | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename arch/arm/{mm => include/asm/hardware}/cache-aurora-l2.h (100%) diff --git a/arch/arm/mm/cache-aurora-l2.h b/arch/arm/include/asm/hardware/cache-aurora-l2.h similarity index 100% rename from arch/arm/mm/cache-aurora-l2.h rename to arch/arm/include/asm/hardware/cache-aurora-l2.h diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 808efbb89b88..a00d6f7fd34c 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -30,8 +30,8 @@ #include <asm/cp15.h> #include <asm/cputype.h> #include <asm/hardware/cache-l2x0.h> +#include <asm/hardware/cache-aurora-l2.h> #include "cache-tauros3.h" -#include "cache-aurora-l2.h" struct l2c_init_data { const char *type; ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v6 2/9] ARM: aurora-l2: add prefix to MAX_RANGE_SIZE @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham From: Jan Luebbe <jlu@pengutronix.de> The macro name is too generic, so add a AURORA_ prefix. Signed-off-by: Jan Luebbe <jlu@pengutronix.de> Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- arch/arm/include/asm/hardware/cache-aurora-l2.h | 2 +- arch/arm/mm/cache-l2x0.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/include/asm/hardware/cache-aurora-l2.h b/arch/arm/include/asm/hardware/cache-aurora-l2.h index c86124769831..dc5c479ec4c3 100644 --- a/arch/arm/include/asm/hardware/cache-aurora-l2.h +++ b/arch/arm/include/asm/hardware/cache-aurora-l2.h @@ -41,7 +41,7 @@ #define AURORA_ACR_FORCE_WRITE_THRO_POLICY \ (2 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET) -#define MAX_RANGE_SIZE 1024 +#define AURORA_MAX_RANGE_SIZE 1024 #define AURORA_WAY_SIZE_SHIFT 2 diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index a00d6f7fd34c..7d2d2a3c67d0 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -1364,8 +1364,8 @@ static unsigned long aurora_range_end(unsigned long start, unsigned long end) * since cache range operations stall the CPU pipeline * until completion. */ - if (end > start + MAX_RANGE_SIZE) - end = start + MAX_RANGE_SIZE; + if (end > start + AURORA_MAX_RANGE_SIZE) + end = start + AURORA_MAX_RANGE_SIZE; /* * Cache range operations can't straddle a page boundary. -- 2.19.1 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v6 2/9] ARM: aurora-l2: add prefix to MAX_RANGE_SIZE @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux-arm-kernel From: Jan Luebbe <jlu@pengutronix.de> The macro name is too generic, so add a AURORA_ prefix. Signed-off-by: Jan Luebbe <jlu@pengutronix.de> Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- arch/arm/include/asm/hardware/cache-aurora-l2.h | 2 +- arch/arm/mm/cache-l2x0.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/include/asm/hardware/cache-aurora-l2.h b/arch/arm/include/asm/hardware/cache-aurora-l2.h index c86124769831..dc5c479ec4c3 100644 --- a/arch/arm/include/asm/hardware/cache-aurora-l2.h +++ b/arch/arm/include/asm/hardware/cache-aurora-l2.h @@ -41,7 +41,7 @@ #define AURORA_ACR_FORCE_WRITE_THRO_POLICY \ (2 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET) -#define MAX_RANGE_SIZE 1024 +#define AURORA_MAX_RANGE_SIZE 1024 #define AURORA_WAY_SIZE_SHIFT 2 diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index a00d6f7fd34c..7d2d2a3c67d0 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -1364,8 +1364,8 @@ static unsigned long aurora_range_end(unsigned long start, unsigned long end) * since cache range operations stall the CPU pipeline * until completion. */ - if (end > start + MAX_RANGE_SIZE) - end = start + MAX_RANGE_SIZE; + if (end > start + AURORA_MAX_RANGE_SIZE) + end = start + AURORA_MAX_RANGE_SIZE; /* * Cache range operations can't straddle a page boundary. -- 2.19.1 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [v6,2/9] ARM: aurora-l2: add prefix to MAX_RANGE_SIZE @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham From: Jan Luebbe <jlu@pengutronix.de> The macro name is too generic, so add a AURORA_ prefix. Signed-off-by: Jan Luebbe <jlu@pengutronix.de> Reviewed-by: Gregory CLEMENT <gregory.clement@free-electrons.com> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- arch/arm/include/asm/hardware/cache-aurora-l2.h | 2 +- arch/arm/mm/cache-l2x0.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/include/asm/hardware/cache-aurora-l2.h b/arch/arm/include/asm/hardware/cache-aurora-l2.h index c86124769831..dc5c479ec4c3 100644 --- a/arch/arm/include/asm/hardware/cache-aurora-l2.h +++ b/arch/arm/include/asm/hardware/cache-aurora-l2.h @@ -41,7 +41,7 @@ #define AURORA_ACR_FORCE_WRITE_THRO_POLICY \ (2 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET) -#define MAX_RANGE_SIZE 1024 +#define AURORA_MAX_RANGE_SIZE 1024 #define AURORA_WAY_SIZE_SHIFT 2 diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index a00d6f7fd34c..7d2d2a3c67d0 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -1364,8 +1364,8 @@ static unsigned long aurora_range_end(unsigned long start, unsigned long end) * since cache range operations stall the CPU pipeline * until completion. */ - if (end > start + MAX_RANGE_SIZE) - end = start + MAX_RANGE_SIZE; + if (end > start + AURORA_MAX_RANGE_SIZE) + end = start + AURORA_MAX_RANGE_SIZE; /* * Cache range operations can't straddle a page boundary. ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v6 3/9] ARM: aurora-l2: add defines for parity and ECC registers @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham From: Jan Luebbe <jlu@pengutronix.de> These defines will be used by subsequent patches to add support for the parity check and error correction functionality in the Aurora L2 cache controller. Signed-off-by: Jan Luebbe <jlu@pengutronix.de> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- .../include/asm/hardware/cache-aurora-l2.h | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/arch/arm/include/asm/hardware/cache-aurora-l2.h b/arch/arm/include/asm/hardware/cache-aurora-l2.h index dc5c479ec4c3..39769ffa0051 100644 --- a/arch/arm/include/asm/hardware/cache-aurora-l2.h +++ b/arch/arm/include/asm/hardware/cache-aurora-l2.h @@ -31,6 +31,9 @@ #define AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU \ (3 << AURORA_ACR_REPLACEMENT_OFFSET) +#define AURORA_ACR_PARITY_EN (1 << 21) +#define AURORA_ACR_ECC_EN (1 << 20) + #define AURORA_ACR_FORCE_WRITE_POLICY_OFFSET 0 #define AURORA_ACR_FORCE_WRITE_POLICY_MASK \ (0x3 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET) @@ -41,6 +44,51 @@ #define AURORA_ACR_FORCE_WRITE_THRO_POLICY \ (2 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET) +#define AURORA_ERR_CNT_REG 0x600 +#define AURORA_ERR_ATTR_CAP_REG 0x608 +#define AURORA_ERR_ADDR_CAP_REG 0x60c +#define AURORA_ERR_WAY_CAP_REG 0x610 +#define AURORA_ERR_INJECT_CTL_REG 0x614 +#define AURORA_ERR_INJECT_MASK_REG 0x618 + +#define AURORA_ERR_CNT_CLR_OFFSET 31 +#define AURORA_ERR_CNT_CLR \ + (0x1 << AURORA_ERR_CNT_CLR_OFFSET) +#define AURORA_ERR_CNT_UE_OFFSET 16 +#define AURORA_ERR_CNT_UE_MASK \ + (0x7fff << AURORA_ERR_CNT_UE_OFFSET) +#define AURORA_ERR_CNT_CE_OFFSET 0 +#define AURORA_ERR_CNT_CE_MASK \ + (0xffff << AURORA_ERR_CNT_CE_OFFSET) + +#define AURORA_ERR_ATTR_SRC_OFF 16 +#define AURORA_ERR_ATTR_SRC_MSK \ + (0x7 << AURORA_ERR_ATTR_SRC_OFF) +#define AURORA_ERR_ATTR_TXN_OFF 12 +#define AURORA_ERR_ATTR_TXN_MSK \ + (0xf << AURORA_ERR_ATTR_TXN_OFF) +#define AURORA_ERR_ATTR_ERR_OFF 8 +#define AURORA_ERR_ATTR_ERR_MSK \ + (0x3 << AURORA_ERR_ATTR_ERR_OFF) +#define AURORA_ERR_ATTR_CAP_VALID_OFF 0 +#define AURORA_ERR_ATTR_CAP_VALID \ + (0x1 << AURORA_ERR_ATTR_CAP_VALID_OFF) + +#define AURORA_ERR_ADDR_CAP_ADDR_MASK 0xffffffe0 + +#define AURORA_ERR_WAY_IDX_OFF 8 +#define AURORA_ERR_WAY_IDX_MSK \ + (0xfff << AURORA_ERR_WAY_IDX_OFF) +#define AURORA_ERR_WAY_CAP_WAY_OFFSET 1 +#define AURORA_ERR_WAY_CAP_WAY_MASK \ + (0xf << AURORA_ERR_WAY_CAP_WAY_OFFSET) + +#define AURORA_ERR_INJECT_CTL_ADDR_MASK 0xfffffff0 +#define AURORA_ERR_ATTR_TXN_OFF 12 +#define AURORA_ERR_INJECT_CTL_EN_MASK 0x3 +#define AURORA_ERR_INJECT_CTL_EN_PARITY 0x2 +#define AURORA_ERR_INJECT_CTL_EN_ECC 0x1 + #define AURORA_MAX_RANGE_SIZE 1024 #define AURORA_WAY_SIZE_SHIFT 2 -- 2.19.1 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v6 3/9] ARM: aurora-l2: add defines for parity and ECC registers @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux-arm-kernel From: Jan Luebbe <jlu@pengutronix.de> These defines will be used by subsequent patches to add support for the parity check and error correction functionality in the Aurora L2 cache controller. Signed-off-by: Jan Luebbe <jlu@pengutronix.de> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- .../include/asm/hardware/cache-aurora-l2.h | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/arch/arm/include/asm/hardware/cache-aurora-l2.h b/arch/arm/include/asm/hardware/cache-aurora-l2.h index dc5c479ec4c3..39769ffa0051 100644 --- a/arch/arm/include/asm/hardware/cache-aurora-l2.h +++ b/arch/arm/include/asm/hardware/cache-aurora-l2.h @@ -31,6 +31,9 @@ #define AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU \ (3 << AURORA_ACR_REPLACEMENT_OFFSET) +#define AURORA_ACR_PARITY_EN (1 << 21) +#define AURORA_ACR_ECC_EN (1 << 20) + #define AURORA_ACR_FORCE_WRITE_POLICY_OFFSET 0 #define AURORA_ACR_FORCE_WRITE_POLICY_MASK \ (0x3 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET) @@ -41,6 +44,51 @@ #define AURORA_ACR_FORCE_WRITE_THRO_POLICY \ (2 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET) +#define AURORA_ERR_CNT_REG 0x600 +#define AURORA_ERR_ATTR_CAP_REG 0x608 +#define AURORA_ERR_ADDR_CAP_REG 0x60c +#define AURORA_ERR_WAY_CAP_REG 0x610 +#define AURORA_ERR_INJECT_CTL_REG 0x614 +#define AURORA_ERR_INJECT_MASK_REG 0x618 + +#define AURORA_ERR_CNT_CLR_OFFSET 31 +#define AURORA_ERR_CNT_CLR \ + (0x1 << AURORA_ERR_CNT_CLR_OFFSET) +#define AURORA_ERR_CNT_UE_OFFSET 16 +#define AURORA_ERR_CNT_UE_MASK \ + (0x7fff << AURORA_ERR_CNT_UE_OFFSET) +#define AURORA_ERR_CNT_CE_OFFSET 0 +#define AURORA_ERR_CNT_CE_MASK \ + (0xffff << AURORA_ERR_CNT_CE_OFFSET) + +#define AURORA_ERR_ATTR_SRC_OFF 16 +#define AURORA_ERR_ATTR_SRC_MSK \ + (0x7 << AURORA_ERR_ATTR_SRC_OFF) +#define AURORA_ERR_ATTR_TXN_OFF 12 +#define AURORA_ERR_ATTR_TXN_MSK \ + (0xf << AURORA_ERR_ATTR_TXN_OFF) +#define AURORA_ERR_ATTR_ERR_OFF 8 +#define AURORA_ERR_ATTR_ERR_MSK \ + (0x3 << AURORA_ERR_ATTR_ERR_OFF) +#define AURORA_ERR_ATTR_CAP_VALID_OFF 0 +#define AURORA_ERR_ATTR_CAP_VALID \ + (0x1 << AURORA_ERR_ATTR_CAP_VALID_OFF) + +#define AURORA_ERR_ADDR_CAP_ADDR_MASK 0xffffffe0 + +#define AURORA_ERR_WAY_IDX_OFF 8 +#define AURORA_ERR_WAY_IDX_MSK \ + (0xfff << AURORA_ERR_WAY_IDX_OFF) +#define AURORA_ERR_WAY_CAP_WAY_OFFSET 1 +#define AURORA_ERR_WAY_CAP_WAY_MASK \ + (0xf << AURORA_ERR_WAY_CAP_WAY_OFFSET) + +#define AURORA_ERR_INJECT_CTL_ADDR_MASK 0xfffffff0 +#define AURORA_ERR_ATTR_TXN_OFF 12 +#define AURORA_ERR_INJECT_CTL_EN_MASK 0x3 +#define AURORA_ERR_INJECT_CTL_EN_PARITY 0x2 +#define AURORA_ERR_INJECT_CTL_EN_ECC 0x1 + #define AURORA_MAX_RANGE_SIZE 1024 #define AURORA_WAY_SIZE_SHIFT 2 -- 2.19.1 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [v6,3/9] ARM: aurora-l2: add defines for parity and ECC registers @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham From: Jan Luebbe <jlu@pengutronix.de> These defines will be used by subsequent patches to add support for the parity check and error correction functionality in the Aurora L2 cache controller. Signed-off-by: Jan Luebbe <jlu@pengutronix.de> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- .../include/asm/hardware/cache-aurora-l2.h | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/arch/arm/include/asm/hardware/cache-aurora-l2.h b/arch/arm/include/asm/hardware/cache-aurora-l2.h index dc5c479ec4c3..39769ffa0051 100644 --- a/arch/arm/include/asm/hardware/cache-aurora-l2.h +++ b/arch/arm/include/asm/hardware/cache-aurora-l2.h @@ -31,6 +31,9 @@ #define AURORA_ACR_REPLACEMENT_TYPE_SEMIPLRU \ (3 << AURORA_ACR_REPLACEMENT_OFFSET) +#define AURORA_ACR_PARITY_EN (1 << 21) +#define AURORA_ACR_ECC_EN (1 << 20) + #define AURORA_ACR_FORCE_WRITE_POLICY_OFFSET 0 #define AURORA_ACR_FORCE_WRITE_POLICY_MASK \ (0x3 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET) @@ -41,6 +44,51 @@ #define AURORA_ACR_FORCE_WRITE_THRO_POLICY \ (2 << AURORA_ACR_FORCE_WRITE_POLICY_OFFSET) +#define AURORA_ERR_CNT_REG 0x600 +#define AURORA_ERR_ATTR_CAP_REG 0x608 +#define AURORA_ERR_ADDR_CAP_REG 0x60c +#define AURORA_ERR_WAY_CAP_REG 0x610 +#define AURORA_ERR_INJECT_CTL_REG 0x614 +#define AURORA_ERR_INJECT_MASK_REG 0x618 + +#define AURORA_ERR_CNT_CLR_OFFSET 31 +#define AURORA_ERR_CNT_CLR \ + (0x1 << AURORA_ERR_CNT_CLR_OFFSET) +#define AURORA_ERR_CNT_UE_OFFSET 16 +#define AURORA_ERR_CNT_UE_MASK \ + (0x7fff << AURORA_ERR_CNT_UE_OFFSET) +#define AURORA_ERR_CNT_CE_OFFSET 0 +#define AURORA_ERR_CNT_CE_MASK \ + (0xffff << AURORA_ERR_CNT_CE_OFFSET) + +#define AURORA_ERR_ATTR_SRC_OFF 16 +#define AURORA_ERR_ATTR_SRC_MSK \ + (0x7 << AURORA_ERR_ATTR_SRC_OFF) +#define AURORA_ERR_ATTR_TXN_OFF 12 +#define AURORA_ERR_ATTR_TXN_MSK \ + (0xf << AURORA_ERR_ATTR_TXN_OFF) +#define AURORA_ERR_ATTR_ERR_OFF 8 +#define AURORA_ERR_ATTR_ERR_MSK \ + (0x3 << AURORA_ERR_ATTR_ERR_OFF) +#define AURORA_ERR_ATTR_CAP_VALID_OFF 0 +#define AURORA_ERR_ATTR_CAP_VALID \ + (0x1 << AURORA_ERR_ATTR_CAP_VALID_OFF) + +#define AURORA_ERR_ADDR_CAP_ADDR_MASK 0xffffffe0 + +#define AURORA_ERR_WAY_IDX_OFF 8 +#define AURORA_ERR_WAY_IDX_MSK \ + (0xfff << AURORA_ERR_WAY_IDX_OFF) +#define AURORA_ERR_WAY_CAP_WAY_OFFSET 1 +#define AURORA_ERR_WAY_CAP_WAY_MASK \ + (0xf << AURORA_ERR_WAY_CAP_WAY_OFFSET) + +#define AURORA_ERR_INJECT_CTL_ADDR_MASK 0xfffffff0 +#define AURORA_ERR_ATTR_TXN_OFF 12 +#define AURORA_ERR_INJECT_CTL_EN_MASK 0x3 +#define AURORA_ERR_INJECT_CTL_EN_PARITY 0x2 +#define AURORA_ERR_INJECT_CTL_EN_ECC 0x1 + #define AURORA_MAX_RANGE_SIZE 1024 #define AURORA_WAY_SIZE_SHIFT 2 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v6 4/9] ARM: l2x0: support parity-enable/disable on aurora @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham The aurora cache on the Marvell Armada-XP SoC supports the same tag parity features as the other l2x0 cache implementations. Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> [jlu@pengutronix.de: use aurora specific define AURORA_ACR_PARITY_EN] Signed-off-by: Jan Luebbe <jlu@pengutronix.de> --- arch/arm/mm/cache-l2x0.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 7d2d2a3c67d0..b70bee74750d 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -1505,6 +1505,13 @@ static void __init aurora_of_parse(const struct device_node *np, mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK; } + if (of_property_read_bool(np, "arm,parity-enable")) { + mask |= AURORA_ACR_PARITY_EN; + val |= AURORA_ACR_PARITY_EN; + } else if (of_property_read_bool(np, "arm,parity-disable")) { + mask |= AURORA_ACR_PARITY_EN; + } + *aux_val &= ~mask; *aux_val |= val; *aux_mask &= ~mask; -- 2.19.1 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v6 4/9] ARM: l2x0: support parity-enable/disable on aurora @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux-arm-kernel The aurora cache on the Marvell Armada-XP SoC supports the same tag parity features as the other l2x0 cache implementations. Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> [jlu at pengutronix.de: use aurora specific define AURORA_ACR_PARITY_EN] Signed-off-by: Jan Luebbe <jlu@pengutronix.de> --- arch/arm/mm/cache-l2x0.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 7d2d2a3c67d0..b70bee74750d 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -1505,6 +1505,13 @@ static void __init aurora_of_parse(const struct device_node *np, mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK; } + if (of_property_read_bool(np, "arm,parity-enable")) { + mask |= AURORA_ACR_PARITY_EN; + val |= AURORA_ACR_PARITY_EN; + } else if (of_property_read_bool(np, "arm,parity-disable")) { + mask |= AURORA_ACR_PARITY_EN; + } + *aux_val &= ~mask; *aux_val |= val; *aux_mask &= ~mask; -- 2.19.1 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [v6,4/9] ARM: l2x0: support parity-enable/disable on aurora @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham The aurora cache on the Marvell Armada-XP SoC supports the same tag parity features as the other l2x0 cache implementations. Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> [jlu@pengutronix.de: use aurora specific define AURORA_ACR_PARITY_EN] Signed-off-by: Jan Luebbe <jlu@pengutronix.de> --- arch/arm/mm/cache-l2x0.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 7d2d2a3c67d0..b70bee74750d 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -1505,6 +1505,13 @@ static void __init aurora_of_parse(const struct device_node *np, mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK; } + if (of_property_read_bool(np, "arm,parity-enable")) { + mask |= AURORA_ACR_PARITY_EN; + val |= AURORA_ACR_PARITY_EN; + } else if (of_property_read_bool(np, "arm,parity-disable")) { + mask |= AURORA_ACR_PARITY_EN; + } + *aux_val &= ~mask; *aux_val |= val; *aux_mask &= ~mask; ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v6 5/9] dt-bindings: ARM: document marvell,ecc-enable binding @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham, Rob Herring, Mark Rutland Add documentation for the marvell,ecc-enable and marvell,ecc-disable properties which can be used to enable/disable ECC on the Marvell aurora cache. Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- Notes: Changes in v6: - new (split binding doc from implementation). Documentation/devicetree/bindings/arm/l2c2x0.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/l2c2x0.txt b/Documentation/devicetree/bindings/arm/l2c2x0.txt index fbe6cb21f4cf..15a84f0ba9f1 100644 --- a/Documentation/devicetree/bindings/arm/l2c2x0.txt +++ b/Documentation/devicetree/bindings/arm/l2c2x0.txt @@ -76,6 +76,8 @@ Optional properties: specified to indicate that such transforms are precluded. - arm,parity-enable : enable parity checking on the L2 cache (L220 or PL310). - arm,parity-disable : disable parity checking on the L2 cache (L220 or PL310). +- marvell,ecc-enable : enable ECC protection on the L2 cache +- marvell,ecc-disable : disable ECC protection on the L2 cache - arm,outer-sync-disable : disable the outer sync operation on the L2 cache. Some core tiles, especially ARM PB11MPCore have a faulty L220 cache that will randomly hang unless outer sync operations are disabled. -- 2.19.1 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v6 5/9] dt-bindings: ARM: document marvell,ecc-enable binding @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux-arm-kernel Add documentation for the marvell,ecc-enable and marvell,ecc-disable properties which can be used to enable/disable ECC on the Marvell aurora cache. Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- Notes: Changes in v6: - new (split binding doc from implementation). Documentation/devicetree/bindings/arm/l2c2x0.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/l2c2x0.txt b/Documentation/devicetree/bindings/arm/l2c2x0.txt index fbe6cb21f4cf..15a84f0ba9f1 100644 --- a/Documentation/devicetree/bindings/arm/l2c2x0.txt +++ b/Documentation/devicetree/bindings/arm/l2c2x0.txt @@ -76,6 +76,8 @@ Optional properties: specified to indicate that such transforms are precluded. - arm,parity-enable : enable parity checking on the L2 cache (L220 or PL310). - arm,parity-disable : disable parity checking on the L2 cache (L220 or PL310). +- marvell,ecc-enable : enable ECC protection on the L2 cache +- marvell,ecc-disable : disable ECC protection on the L2 cache - arm,outer-sync-disable : disable the outer sync operation on the L2 cache. Some core tiles, especially ARM PB11MPCore have a faulty L220 cache that will randomly hang unless outer sync operations are disabled. -- 2.19.1 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [v6,5/9] dt-bindings: ARM: document marvell,ecc-enable binding @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham, Rob Herring, Mark Rutland Add documentation for the marvell,ecc-enable and marvell,ecc-disable properties which can be used to enable/disable ECC on the Marvell aurora cache. Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- Notes: Changes in v6: - new (split binding doc from implementation). Documentation/devicetree/bindings/arm/l2c2x0.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/l2c2x0.txt b/Documentation/devicetree/bindings/arm/l2c2x0.txt index fbe6cb21f4cf..15a84f0ba9f1 100644 --- a/Documentation/devicetree/bindings/arm/l2c2x0.txt +++ b/Documentation/devicetree/bindings/arm/l2c2x0.txt @@ -76,6 +76,8 @@ Optional properties: specified to indicate that such transforms are precluded. - arm,parity-enable : enable parity checking on the L2 cache (L220 or PL310). - arm,parity-disable : disable parity checking on the L2 cache (L220 or PL310). +- marvell,ecc-enable : enable ECC protection on the L2 cache +- marvell,ecc-disable : disable ECC protection on the L2 cache - arm,outer-sync-disable : disable the outer sync operation on the L2 cache. Some core tiles, especially ARM PB11MPCore have a faulty L220 cache that will randomly hang unless outer sync operations are disabled. ^ permalink raw reply related [flat|nested] 48+ messages in thread
* Re: [PATCH v6 5/9] dt-bindings: ARM: document marvell,ecc-enable binding @ 2018-11-09 11:40 ` Arnd Bergmann 0 siblings, 0 replies; 48+ messages in thread From: Arnd Bergmann @ 2018-11-09 11:40 UTC (permalink / raw) To: Chris Packham Cc: Russell King - ARM Linux, Borislav Petkov, jlu, Gregory CLEMENT, Linux ARM, DTML, linux-edac, Linux Kernel Mailing List, Rob Herring, Mark Rutland On Fri, Nov 9, 2018 at 8:04 AM Chris Packham <chris.packham@alliedtelesis.co.nz> wrote: > > Add documentation for the marvell,ecc-enable and marvell,ecc-disable > properties which can be used to enable/disable ECC on the Marvell aurora > cache. > > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> > --- Why do you need both enable and disable? Wouldn't one of them be enough here? Arnd ^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v6 5/9] dt-bindings: ARM: document marvell, ecc-enable binding @ 2018-11-09 11:40 ` Arnd Bergmann 0 siblings, 0 replies; 48+ messages in thread From: Arnd Bergmann @ 2018-11-09 11:40 UTC (permalink / raw) To: linux-arm-kernel On Fri, Nov 9, 2018 at 8:04 AM Chris Packham <chris.packham@alliedtelesis.co.nz> wrote: > > Add documentation for the marvell,ecc-enable and marvell,ecc-disable > properties which can be used to enable/disable ECC on the Marvell aurora > cache. > > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> > --- Why do you need both enable and disable? Wouldn't one of them be enough here? Arnd ^ permalink raw reply [flat|nested] 48+ messages in thread
* [v6,5/9] dt-bindings: ARM: document marvell,ecc-enable binding @ 2018-11-09 11:40 ` Arnd Bergmann 0 siblings, 0 replies; 48+ messages in thread From: Arnd Bergmann @ 2018-11-09 11:40 UTC (permalink / raw) To: Chris Packham Cc: Russell King - ARM Linux, Borislav Petkov, jlu, Gregory CLEMENT, Linux ARM, DTML, linux-edac, Linux Kernel Mailing List, Rob Herring, Mark Rutland On Fri, Nov 9, 2018 at 8:04 AM Chris Packham <chris.packham@alliedtelesis.co.nz> wrote: > > Add documentation for the marvell,ecc-enable and marvell,ecc-disable > properties which can be used to enable/disable ECC on the Marvell aurora > cache. > > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> > --- Why do you need both enable and disable? Wouldn't one of them be enough here? Arnd ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v6 5/9] dt-bindings: ARM: document marvell,ecc-enable binding @ 2018-11-09 11:48 ` Russell King - ARM Linux 0 siblings, 0 replies; 48+ messages in thread From: Russell King - ARM Linux @ 2018-11-09 11:48 UTC (permalink / raw) To: Arnd Bergmann Cc: Chris Packham, Borislav Petkov, jlu, Gregory CLEMENT, Linux ARM, DTML, linux-edac, Linux Kernel Mailing List, Rob Herring, Mark Rutland On Fri, Nov 09, 2018 at 12:40:06PM +0100, Arnd Bergmann wrote: > On Fri, Nov 9, 2018 at 8:04 AM Chris Packham > <chris.packham@alliedtelesis.co.nz> wrote: > > > > Add documentation for the marvell,ecc-enable and marvell,ecc-disable > > properties which can be used to enable/disable ECC on the Marvell aurora > > cache. > > > > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> > > --- > > Why do you need both enable and disable? Wouldn't one of them be enough here? It isn't an "on when ecc-enable is present, off when not" because the current behaviour is to preserve these bits in the control register. If we were to implement it as "if no ecc-enable property, turn off ECC" then that would drastically change the behaviour - systems which were configured for ECC suddenly lose ECC support. Since we don't know which have it and which don't, we can't implement the option like that. -- RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up According to speedtest.net: 11.9Mbps down 500kbps up ^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v6 5/9] dt-bindings: ARM: document marvell,ecc-enable binding @ 2018-11-09 11:48 ` Russell King - ARM Linux 0 siblings, 0 replies; 48+ messages in thread From: Russell King - ARM Linux @ 2018-11-09 11:48 UTC (permalink / raw) To: linux-arm-kernel On Fri, Nov 09, 2018 at 12:40:06PM +0100, Arnd Bergmann wrote: > On Fri, Nov 9, 2018 at 8:04 AM Chris Packham > <chris.packham@alliedtelesis.co.nz> wrote: > > > > Add documentation for the marvell,ecc-enable and marvell,ecc-disable > > properties which can be used to enable/disable ECC on the Marvell aurora > > cache. > > > > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> > > --- > > Why do you need both enable and disable? Wouldn't one of them be enough here? It isn't an "on when ecc-enable is present, off when not" because the current behaviour is to preserve these bits in the control register. If we were to implement it as "if no ecc-enable property, turn off ECC" then that would drastically change the behaviour - systems which were configured for ECC suddenly lose ECC support. Since we don't know which have it and which don't, we can't implement the option like that. -- RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up According to speedtest.net: 11.9Mbps down 500kbps up ^ permalink raw reply [flat|nested] 48+ messages in thread
* [v6,5/9] dt-bindings: ARM: document marvell,ecc-enable binding @ 2018-11-09 11:48 ` Russell King - ARM Linux 0 siblings, 0 replies; 48+ messages in thread From: Russell King - ARM Linux @ 2018-11-09 11:48 UTC (permalink / raw) To: Arnd Bergmann Cc: Chris Packham, Borislav Petkov, jlu, Gregory CLEMENT, Linux ARM, DTML, linux-edac, Linux Kernel Mailing List, Rob Herring, Mark Rutland On Fri, Nov 09, 2018 at 12:40:06PM +0100, Arnd Bergmann wrote: > On Fri, Nov 9, 2018 at 8:04 AM Chris Packham > <chris.packham@alliedtelesis.co.nz> wrote: > > > > Add documentation for the marvell,ecc-enable and marvell,ecc-disable > > properties which can be used to enable/disable ECC on the Marvell aurora > > cache. > > > > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> > > --- > > Why do you need both enable and disable? Wouldn't one of them be enough here? It isn't an "on when ecc-enable is present, off when not" because the current behaviour is to preserve these bits in the control register. If we were to implement it as "if no ecc-enable property, turn off ECC" then that would drastically change the behaviour - systems which were configured for ECC suddenly lose ECC support. Since we don't know which have it and which don't, we can't implement the option like that. ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v6 5/9] dt-bindings: ARM: document marvell,ecc-enable binding @ 2018-11-09 15:58 ` Arnd Bergmann 0 siblings, 0 replies; 48+ messages in thread From: Arnd Bergmann @ 2018-11-09 15:58 UTC (permalink / raw) To: Russell King - ARM Linux Cc: Chris Packham, Borislav Petkov, jlu, Gregory CLEMENT, Linux ARM, DTML, linux-edac, Linux Kernel Mailing List, Rob Herring, Mark Rutland On Fri, Nov 9, 2018 at 12:48 PM Russell King - ARM Linux <linux@armlinux.org.uk> wrote: > > On Fri, Nov 09, 2018 at 12:40:06PM +0100, Arnd Bergmann wrote: > > On Fri, Nov 9, 2018 at 8:04 AM Chris Packham > > <chris.packham@alliedtelesis.co.nz> wrote: > > > > > > Add documentation for the marvell,ecc-enable and marvell,ecc-disable > > > properties which can be used to enable/disable ECC on the Marvell aurora > > > cache. > > > > > > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> > > > --- > > > > Why do you need both enable and disable? Wouldn't one of them be enough here? > > It isn't an "on when ecc-enable is present, off when not" because the > current behaviour is to preserve these bits in the control register. > > If we were to implement it as "if no ecc-enable property, turn off > ECC" then that would drastically change the behaviour - systems which > were configured for ECC suddenly lose ECC support. > > Since we don't know which have it and which don't, we can't implement > the option like that. What I meant was why we need support force-disabling it. I understand that we need to allow leaving it at the boot-time default as well as force-enabling it. Arnd ^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v6 5/9] dt-bindings: ARM: document marvell, ecc-enable binding @ 2018-11-09 15:58 ` Arnd Bergmann 0 siblings, 0 replies; 48+ messages in thread From: Arnd Bergmann @ 2018-11-09 15:58 UTC (permalink / raw) To: linux-arm-kernel On Fri, Nov 9, 2018 at 12:48 PM Russell King - ARM Linux <linux@armlinux.org.uk> wrote: > > On Fri, Nov 09, 2018 at 12:40:06PM +0100, Arnd Bergmann wrote: > > On Fri, Nov 9, 2018 at 8:04 AM Chris Packham > > <chris.packham@alliedtelesis.co.nz> wrote: > > > > > > Add documentation for the marvell,ecc-enable and marvell,ecc-disable > > > properties which can be used to enable/disable ECC on the Marvell aurora > > > cache. > > > > > > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> > > > --- > > > > Why do you need both enable and disable? Wouldn't one of them be enough here? > > It isn't an "on when ecc-enable is present, off when not" because the > current behaviour is to preserve these bits in the control register. > > If we were to implement it as "if no ecc-enable property, turn off > ECC" then that would drastically change the behaviour - systems which > were configured for ECC suddenly lose ECC support. > > Since we don't know which have it and which don't, we can't implement > the option like that. What I meant was why we need support force-disabling it. I understand that we need to allow leaving it at the boot-time default as well as force-enabling it. Arnd ^ permalink raw reply [flat|nested] 48+ messages in thread
* [v6,5/9] dt-bindings: ARM: document marvell,ecc-enable binding @ 2018-11-09 15:58 ` Arnd Bergmann 0 siblings, 0 replies; 48+ messages in thread From: Arnd Bergmann @ 2018-11-09 15:58 UTC (permalink / raw) To: Russell King - ARM Linux Cc: Chris Packham, Borislav Petkov, jlu, Gregory CLEMENT, Linux ARM, DTML, linux-edac, Linux Kernel Mailing List, Rob Herring, Mark Rutland On Fri, Nov 9, 2018 at 12:48 PM Russell King - ARM Linux <linux@armlinux.org.uk> wrote: > > On Fri, Nov 09, 2018 at 12:40:06PM +0100, Arnd Bergmann wrote: > > On Fri, Nov 9, 2018 at 8:04 AM Chris Packham > > <chris.packham@alliedtelesis.co.nz> wrote: > > > > > > Add documentation for the marvell,ecc-enable and marvell,ecc-disable > > > properties which can be used to enable/disable ECC on the Marvell aurora > > > cache. > > > > > > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> > > > --- > > > > Why do you need both enable and disable? Wouldn't one of them be enough here? > > It isn't an "on when ecc-enable is present, off when not" because the > current behaviour is to preserve these bits in the control register. > > If we were to implement it as "if no ecc-enable property, turn off > ECC" then that would drastically change the behaviour - systems which > were configured for ECC suddenly lose ECC support. > > Since we don't know which have it and which don't, we can't implement > the option like that. What I meant was why we need support force-disabling it. I understand that we need to allow leaving it at the boot-time default as well as force-enabling it. Arnd ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v6 5/9] dt-bindings: ARM: document marvell,ecc-enable binding @ 2018-11-11 19:57 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-11 19:57 UTC (permalink / raw) To: Arnd Bergmann, Russell King - ARM Linux Cc: Borislav Petkov, jlu, Gregory CLEMENT, Linux ARM, DTML, linux-edac, Linux Kernel Mailing List, Rob Herring, Mark Rutland On 10/11/18 4:58 AM, Arnd Bergmann wrote: > On Fri, Nov 9, 2018 at 12:48 PM Russell King - ARM Linux > <linux@armlinux.org.uk> wrote: >> >> On Fri, Nov 09, 2018 at 12:40:06PM +0100, Arnd Bergmann wrote: >>> On Fri, Nov 9, 2018 at 8:04 AM Chris Packham >>> <chris.packham@alliedtelesis.co.nz> wrote: >>>> >>>> Add documentation for the marvell,ecc-enable and marvell,ecc-disable >>>> properties which can be used to enable/disable ECC on the Marvell aurora >>>> cache. >>>> >>>> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> >>>> --- >>> >>> Why do you need both enable and disable? Wouldn't one of them be enough here? >> >> It isn't an "on when ecc-enable is present, off when not" because the >> current behaviour is to preserve these bits in the control register. >> >> If we were to implement it as "if no ecc-enable property, turn off >> ECC" then that would drastically change the behaviour - systems which >> were configured for ECC suddenly lose ECC support. >> >> Since we don't know which have it and which don't, we can't implement >> the option like that. > > What I meant was why we need support force-disabling it. I understand > that we need to allow leaving it at the boot-time default as well as > force-enabling it. I added ecc-disable because I was modeling it after arm,parity-enable/arm,parity-disable. The only reason I can imagine wanting to force disable this would be some mis-behaving SoC which has it enabled by default in hardware, to my knowledge no such system exists (that would use this driver). I'd be happy to drop the binding an implementation and send a v7 if you feel strongly that it marvell,ecc-disable should be removed. ^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v6 5/9] dt-bindings: ARM: document marvell,ecc-enable binding @ 2018-11-11 19:57 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-11 19:57 UTC (permalink / raw) To: linux-arm-kernel On 10/11/18 4:58 AM, Arnd Bergmann wrote: > On Fri, Nov 9, 2018 at 12:48 PM Russell King - ARM Linux > <linux@armlinux.org.uk> wrote: >> >> On Fri, Nov 09, 2018 at 12:40:06PM +0100, Arnd Bergmann wrote: >>> On Fri, Nov 9, 2018 at 8:04 AM Chris Packham >>> <chris.packham@alliedtelesis.co.nz> wrote: >>>> >>>> Add documentation for the marvell,ecc-enable and marvell,ecc-disable >>>> properties which can be used to enable/disable ECC on the Marvell aurora >>>> cache. >>>> >>>> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> >>>> --- >>> >>> Why do you need both enable and disable? Wouldn't one of them be enough here? >> >> It isn't an "on when ecc-enable is present, off when not" because the >> current behaviour is to preserve these bits in the control register. >> >> If we were to implement it as "if no ecc-enable property, turn off >> ECC" then that would drastically change the behaviour - systems which >> were configured for ECC suddenly lose ECC support. >> >> Since we don't know which have it and which don't, we can't implement >> the option like that. > > What I meant was why we need support force-disabling it. I understand > that we need to allow leaving it at the boot-time default as well as > force-enabling it. I added ecc-disable because I was modeling it after arm,parity-enable/arm,parity-disable. The only reason I can imagine wanting to force disable this would be some mis-behaving SoC which has it enabled by default in hardware, to my knowledge no such system exists (that would use this driver). I'd be happy to drop the binding an implementation and send a v7 if you feel strongly that it marvell,ecc-disable should be removed. ^ permalink raw reply [flat|nested] 48+ messages in thread
* [v6,5/9] dt-bindings: ARM: document marvell,ecc-enable binding @ 2018-11-11 19:57 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-11 19:57 UTC (permalink / raw) To: Arnd Bergmann, Russell King - ARM Linux Cc: Borislav Petkov, jlu, Gregory CLEMENT, Linux ARM, DTML, linux-edac, Linux Kernel Mailing List, Rob Herring, Mark Rutland On 10/11/18 4:58 AM, Arnd Bergmann wrote: > On Fri, Nov 9, 2018 at 12:48 PM Russell King - ARM Linux > <linux@armlinux.org.uk> wrote: >> >> On Fri, Nov 09, 2018 at 12:40:06PM +0100, Arnd Bergmann wrote: >>> On Fri, Nov 9, 2018 at 8:04 AM Chris Packham >>> <chris.packham@alliedtelesis.co.nz> wrote: >>>> >>>> Add documentation for the marvell,ecc-enable and marvell,ecc-disable >>>> properties which can be used to enable/disable ECC on the Marvell aurora >>>> cache. >>>> >>>> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> >>>> --- >>> >>> Why do you need both enable and disable? Wouldn't one of them be enough here? >> >> It isn't an "on when ecc-enable is present, off when not" because the >> current behaviour is to preserve these bits in the control register. >> >> If we were to implement it as "if no ecc-enable property, turn off >> ECC" then that would drastically change the behaviour - systems which >> were configured for ECC suddenly lose ECC support. >> >> Since we don't know which have it and which don't, we can't implement >> the option like that. > > What I meant was why we need support force-disabling it. I understand > that we need to allow leaving it at the boot-time default as well as > force-enabling it. I added ecc-disable because I was modeling it after arm,parity-enable/arm,parity-disable. The only reason I can imagine wanting to force disable this would be some mis-behaving SoC which has it enabled by default in hardware, to my knowledge no such system exists (that would use this driver). I'd be happy to drop the binding an implementation and send a v7 if you feel strongly that it marvell,ecc-disable should be removed. ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v6 5/9] dt-bindings: ARM: document marvell,ecc-enable binding @ 2018-11-11 22:35 ` Rob Herring 0 siblings, 0 replies; 48+ messages in thread From: Rob Herring @ 2018-11-11 22:35 UTC (permalink / raw) To: Chris Packham Cc: linux, bp, arnd, jlu, gregory.clement, linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham, Mark Rutland On Fri, 9 Nov 2018 20:03:45 +1300, Chris Packham wrote: > Add documentation for the marvell,ecc-enable and marvell,ecc-disable > properties which can be used to enable/disable ECC on the Marvell aurora > cache. > > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> > --- > > Notes: > Changes in v6: > - new (split binding doc from implementation). > > Documentation/devicetree/bindings/arm/l2c2x0.txt | 2 ++ > 1 file changed, 2 insertions(+) > Reviewed-by: Rob Herring <robh@kernel.org> ^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v6 5/9] dt-bindings: ARM: document marvell,ecc-enable binding @ 2018-11-11 22:35 ` Rob Herring 0 siblings, 0 replies; 48+ messages in thread From: Rob Herring @ 2018-11-11 22:35 UTC (permalink / raw) To: linux-arm-kernel On Fri, 9 Nov 2018 20:03:45 +1300, Chris Packham wrote: > Add documentation for the marvell,ecc-enable and marvell,ecc-disable > properties which can be used to enable/disable ECC on the Marvell aurora > cache. > > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> > --- > > Notes: > Changes in v6: > - new (split binding doc from implementation). > > Documentation/devicetree/bindings/arm/l2c2x0.txt | 2 ++ > 1 file changed, 2 insertions(+) > Reviewed-by: Rob Herring <robh@kernel.org> ^ permalink raw reply [flat|nested] 48+ messages in thread
* Re: [PATCH v6 5/9] dt-bindings: ARM: document marvell,ecc-enable binding @ 2018-11-11 22:35 ` Rob Herring 0 siblings, 0 replies; 48+ messages in thread From: Rob Herring @ 2018-11-11 22:35 UTC (permalink / raw) Cc: linux, bp, arnd, jlu, gregory.clement, linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham, Mark Rutland On Fri, 9 Nov 2018 20:03:45 +1300, Chris Packham wrote: > Add documentation for the marvell,ecc-enable and marvell,ecc-disable > properties which can be used to enable/disable ECC on the Marvell aurora > cache. > > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> > --- > > Notes: > Changes in v6: > - new (split binding doc from implementation). > > Documentation/devicetree/bindings/arm/l2c2x0.txt | 2 ++ > 1 file changed, 2 insertions(+) > Reviewed-by: Rob Herring <robh@kernel.org> ^ permalink raw reply [flat|nested] 48+ messages in thread
* [v6,5/9] dt-bindings: ARM: document marvell,ecc-enable binding @ 2018-11-11 22:35 ` Rob Herring 0 siblings, 0 replies; 48+ messages in thread From: Rob Herring @ 2018-11-11 22:35 UTC (permalink / raw) To: Chris Packham Cc: linux, bp, arnd, jlu, gregory.clement, linux-arm-kernel, devicetree, linux-edac, linux-kernel, Mark Rutland On Fri, 9 Nov 2018 20:03:45 +1300, Chris Packham wrote: > Add documentation for the marvell,ecc-enable and marvell,ecc-disable > properties which can be used to enable/disable ECC on the Marvell aurora > cache. > > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> > --- > > Notes: > Changes in v6: > - new (split binding doc from implementation). > > Documentation/devicetree/bindings/arm/l2c2x0.txt | 2 ++ > 1 file changed, 2 insertions(+) > Reviewed-by: Rob Herring <robh@kernel.org> ^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v6 6/9] ARM: l2x0: add marvell,ecc-enable property for aurora @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham The aurora cache on the Marvell Armada-XP SoC supports ECC protection for the L2 data arrays. Add a "marvell,ecc-enable" device tree property which can be used to enable this. Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> [jlu@pengutronix.de: use aurora specific define AURORA_ACR_ECC_EN] Signed-off-by: Jan Luebbe <jlu@pengutronix.de> --- arch/arm/mm/cache-l2x0.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index b70bee74750d..644f786e4fa9 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -1505,6 +1505,13 @@ static void __init aurora_of_parse(const struct device_node *np, mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK; } + if (of_property_read_bool(np, "marvell,ecc-enable")) { + mask |= AURORA_ACR_ECC_EN; + val |= AURORA_ACR_ECC_EN; + } else if (of_property_read_bool(np, "marvell,ecc-disable")) { + mask |= AURORA_ACR_ECC_EN; + } + if (of_property_read_bool(np, "arm,parity-enable")) { mask |= AURORA_ACR_PARITY_EN; val |= AURORA_ACR_PARITY_EN; -- 2.19.1 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v6 6/9] ARM: l2x0: add marvell,ecc-enable property for aurora @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux-arm-kernel The aurora cache on the Marvell Armada-XP SoC supports ECC protection for the L2 data arrays. Add a "marvell,ecc-enable" device tree property which can be used to enable this. Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> [jlu at pengutronix.de: use aurora specific define AURORA_ACR_ECC_EN] Signed-off-by: Jan Luebbe <jlu@pengutronix.de> --- arch/arm/mm/cache-l2x0.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index b70bee74750d..644f786e4fa9 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -1505,6 +1505,13 @@ static void __init aurora_of_parse(const struct device_node *np, mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK; } + if (of_property_read_bool(np, "marvell,ecc-enable")) { + mask |= AURORA_ACR_ECC_EN; + val |= AURORA_ACR_ECC_EN; + } else if (of_property_read_bool(np, "marvell,ecc-disable")) { + mask |= AURORA_ACR_ECC_EN; + } + if (of_property_read_bool(np, "arm,parity-enable")) { mask |= AURORA_ACR_PARITY_EN; val |= AURORA_ACR_PARITY_EN; -- 2.19.1 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [v6,6/9] ARM: l2x0: add marvell,ecc-enable property for aurora @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham The aurora cache on the Marvell Armada-XP SoC supports ECC protection for the L2 data arrays. Add a "marvell,ecc-enable" device tree property which can be used to enable this. Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> [jlu@pengutronix.de: use aurora specific define AURORA_ACR_ECC_EN] Signed-off-by: Jan Luebbe <jlu@pengutronix.de> --- arch/arm/mm/cache-l2x0.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index b70bee74750d..644f786e4fa9 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -1505,6 +1505,13 @@ static void __init aurora_of_parse(const struct device_node *np, mask |= AURORA_ACR_FORCE_WRITE_POLICY_MASK; } + if (of_property_read_bool(np, "marvell,ecc-enable")) { + mask |= AURORA_ACR_ECC_EN; + val |= AURORA_ACR_ECC_EN; + } else if (of_property_read_bool(np, "marvell,ecc-disable")) { + mask |= AURORA_ACR_ECC_EN; + } + if (of_property_read_bool(np, "arm,parity-enable")) { mask |= AURORA_ACR_PARITY_EN; val |= AURORA_ACR_PARITY_EN; ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v6 7/9] EDAC: Add missing debugfs_create_x32 wrapper @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham, Mauro Carvalho Chehab From: Jan Luebbe <jlu@pengutronix.de> We already have wrappers for x8 and x16, so add the missing x32 one. Signed-off-by: Jan Luebbe <jlu@pengutronix.de> Reviewed-by: Borislav Petkov <bp@suse.de> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- drivers/edac/debugfs.c | 11 +++++++++++ drivers/edac/edac_module.h | 5 +++++ 2 files changed, 16 insertions(+) diff --git a/drivers/edac/debugfs.c b/drivers/edac/debugfs.c index 92dbb7e2320c..268ede7a60b2 100644 --- a/drivers/edac/debugfs.c +++ b/drivers/edac/debugfs.c @@ -161,3 +161,14 @@ struct dentry *edac_debugfs_create_x16(const char *name, umode_t mode, return debugfs_create_x16(name, mode, parent, value); } EXPORT_SYMBOL_GPL(edac_debugfs_create_x16); + +/* Wrapper for debugfs_create_x32() */ +struct dentry *edac_debugfs_create_x32(const char *name, umode_t mode, + struct dentry *parent, u32 *value) +{ + if (!parent) + parent = edac_debugfs; + + return debugfs_create_x32(name, mode, parent, value); +} +EXPORT_SYMBOL_GPL(edac_debugfs_create_x32); diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h index dec88dcea036..546b16e29221 100644 --- a/drivers/edac/edac_module.h +++ b/drivers/edac/edac_module.h @@ -82,6 +82,8 @@ struct dentry * edac_debugfs_create_x8(const char *name, umode_t mode, struct dentry *parent, u8 *value); struct dentry * edac_debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent, u16 *value); +struct dentry * +edac_debugfs_create_x32(const char *name, umode_t mode, struct dentry *parent, u32 *value); #else static inline int edac_debugfs_init(void) { return -ENODEV; } static inline void edac_debugfs_exit(void) { } @@ -98,6 +100,9 @@ edac_debugfs_create_x8(const char *name, umode_t mode, static inline struct dentry * edac_debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent, u16 *value) { return NULL; } +static inline struct dentry * +edac_debugfs_create_x32(const char *name, umode_t mode, + struct dentry *parent, u32 *value) { return NULL; } #endif /* -- 2.19.1 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v6 7/9] EDAC: Add missing debugfs_create_x32 wrapper @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux-arm-kernel From: Jan Luebbe <jlu@pengutronix.de> We already have wrappers for x8 and x16, so add the missing x32 one. Signed-off-by: Jan Luebbe <jlu@pengutronix.de> Reviewed-by: Borislav Petkov <bp@suse.de> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- drivers/edac/debugfs.c | 11 +++++++++++ drivers/edac/edac_module.h | 5 +++++ 2 files changed, 16 insertions(+) diff --git a/drivers/edac/debugfs.c b/drivers/edac/debugfs.c index 92dbb7e2320c..268ede7a60b2 100644 --- a/drivers/edac/debugfs.c +++ b/drivers/edac/debugfs.c @@ -161,3 +161,14 @@ struct dentry *edac_debugfs_create_x16(const char *name, umode_t mode, return debugfs_create_x16(name, mode, parent, value); } EXPORT_SYMBOL_GPL(edac_debugfs_create_x16); + +/* Wrapper for debugfs_create_x32() */ +struct dentry *edac_debugfs_create_x32(const char *name, umode_t mode, + struct dentry *parent, u32 *value) +{ + if (!parent) + parent = edac_debugfs; + + return debugfs_create_x32(name, mode, parent, value); +} +EXPORT_SYMBOL_GPL(edac_debugfs_create_x32); diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h index dec88dcea036..546b16e29221 100644 --- a/drivers/edac/edac_module.h +++ b/drivers/edac/edac_module.h @@ -82,6 +82,8 @@ struct dentry * edac_debugfs_create_x8(const char *name, umode_t mode, struct dentry *parent, u8 *value); struct dentry * edac_debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent, u16 *value); +struct dentry * +edac_debugfs_create_x32(const char *name, umode_t mode, struct dentry *parent, u32 *value); #else static inline int edac_debugfs_init(void) { return -ENODEV; } static inline void edac_debugfs_exit(void) { } @@ -98,6 +100,9 @@ edac_debugfs_create_x8(const char *name, umode_t mode, static inline struct dentry * edac_debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent, u16 *value) { return NULL; } +static inline struct dentry * +edac_debugfs_create_x32(const char *name, umode_t mode, + struct dentry *parent, u32 *value) { return NULL; } #endif /* -- 2.19.1 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [v6,7/9] EDAC: Add missing debugfs_create_x32 wrapper @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham, Mauro Carvalho Chehab From: Jan Luebbe <jlu@pengutronix.de> We already have wrappers for x8 and x16, so add the missing x32 one. Signed-off-by: Jan Luebbe <jlu@pengutronix.de> Reviewed-by: Borislav Petkov <bp@suse.de> Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- drivers/edac/debugfs.c | 11 +++++++++++ drivers/edac/edac_module.h | 5 +++++ 2 files changed, 16 insertions(+) diff --git a/drivers/edac/debugfs.c b/drivers/edac/debugfs.c index 92dbb7e2320c..268ede7a60b2 100644 --- a/drivers/edac/debugfs.c +++ b/drivers/edac/debugfs.c @@ -161,3 +161,14 @@ struct dentry *edac_debugfs_create_x16(const char *name, umode_t mode, return debugfs_create_x16(name, mode, parent, value); } EXPORT_SYMBOL_GPL(edac_debugfs_create_x16); + +/* Wrapper for debugfs_create_x32() */ +struct dentry *edac_debugfs_create_x32(const char *name, umode_t mode, + struct dentry *parent, u32 *value) +{ + if (!parent) + parent = edac_debugfs; + + return debugfs_create_x32(name, mode, parent, value); +} +EXPORT_SYMBOL_GPL(edac_debugfs_create_x32); diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h index dec88dcea036..546b16e29221 100644 --- a/drivers/edac/edac_module.h +++ b/drivers/edac/edac_module.h @@ -82,6 +82,8 @@ struct dentry * edac_debugfs_create_x8(const char *name, umode_t mode, struct dentry *parent, u8 *value); struct dentry * edac_debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent, u16 *value); +struct dentry * +edac_debugfs_create_x32(const char *name, umode_t mode, struct dentry *parent, u32 *value); #else static inline int edac_debugfs_init(void) { return -ENODEV; } static inline void edac_debugfs_exit(void) { } @@ -98,6 +100,9 @@ edac_debugfs_create_x8(const char *name, umode_t mode, static inline struct dentry * edac_debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent, u16 *value) { return NULL; } +static inline struct dentry * +edac_debugfs_create_x32(const char *name, umode_t mode, + struct dentry *parent, u32 *value) { return NULL; } #endif /* ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v6 8/9] EDAC: Add driver for the Marvell Armada XP SDRAM and L2 cache ECC @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham, Mauro Carvalho Chehab From: Jan Luebbe <jlu@pengutronix.de> Add support for the ECC functionality as found in the DDR RAM and L2 cache controllers on the MV78230/MV78x60 SoCs. This driver has been tested on the MV78460 (on a custom board with a DDR3 ECC DIMM). Signed-off-by: Jan Luebbe <jlu@pengutronix.de> [cp use SPDX license] Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- MAINTAINERS | 6 + drivers/edac/Kconfig | 7 + drivers/edac/Makefile | 1 + drivers/edac/armada_xp_edac.c | 630 ++++++++++++++++++++++++++++++++++ 4 files changed, 644 insertions(+) create mode 100644 drivers/edac/armada_xp_edac.c diff --git a/MAINTAINERS b/MAINTAINERS index 6c7ed26e84fa..7ae4cfa5c121 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5242,6 +5242,12 @@ L: linux-edac@vger.kernel.org S: Maintained F: drivers/edac/amd64_edac* +EDAC-ARMADA +M: Jan Luebbe <jlu@pengutronix.de> +L: linux-edac@vger.kernel.org +S: Maintained +F: drivers/edac/armada_xp_* + EDAC-CALXEDA M: Robert Richter <rric@kernel.org> L: linux-edac@vger.kernel.org diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 57304b2e989f..4567757d9f82 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -439,6 +439,13 @@ config EDAC_ALTERA_SDMMC Support for error detection and correction on the Altera SDMMC FIFO Memory for Altera SoCs. +config EDAC_ARMADA_XP + bool "Marvell Armada XP DDR and L2 Cache ECC" + depends on MACH_MVEBU_V7 + help + Support for error correction and detection on the Marvell Aramada XP + DDR RAM and L2 cache controllers. + config EDAC_SYNOPSYS tristate "Synopsys DDR Memory Controller" depends on ARCH_ZYNQ diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index 02b43a7d8c3e..f3ea40b0ce9c 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -74,6 +74,7 @@ obj-$(CONFIG_EDAC_OCTEON_PCI) += octeon_edac-pci.o obj-$(CONFIG_EDAC_THUNDERX) += thunderx_edac.o obj-$(CONFIG_EDAC_ALTERA) += altera_edac.o +obj-$(CONFIG_EDAC_ARMADA_XP) += armada_xp_edac.o obj-$(CONFIG_EDAC_SYNOPSYS) += synopsys_edac.o obj-$(CONFIG_EDAC_XGENE) += xgene_edac.o obj-$(CONFIG_EDAC_TI) += ti_edac.o diff --git a/drivers/edac/armada_xp_edac.c b/drivers/edac/armada_xp_edac.c new file mode 100644 index 000000000000..3759a4fbbdee --- /dev/null +++ b/drivers/edac/armada_xp_edac.c @@ -0,0 +1,630 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2017 Pengutronix, Jan Luebbe <kernel@pengutronix.de> + */ + +#include <linux/kernel.h> +#include <linux/edac.h> +#include <linux/of_platform.h> + +#include <asm/hardware/cache-l2x0.h> +#include <asm/hardware/cache-aurora-l2.h> + +#include "edac_mc.h" +#include "edac_device.h" +#include "edac_module.h" + +/************************ EDAC MC (DDR RAM) ********************************/ + +#define SDRAM_NUM_CS 4 + +#define SDRAM_CONFIG_REG 0x0 +#define SDRAM_CONFIG_ECC_MASK BIT(18) +#define SDRAM_CONFIG_REGISTERED_MASK BIT(17) +#define SDRAM_CONFIG_BUS_WIDTH_MASK BIT(15) + +#define SDRAM_ADDR_CTRL_REG 0x10 +#define SDRAM_ADDR_CTRL_SIZE_HIGH_OFFSET(cs) (20+cs) +#define SDRAM_ADDR_CTRL_SIZE_HIGH_MASK(cs) (0x1 << SDRAM_ADDR_CTRL_SIZE_HIGH_OFFSET(cs)) +#define SDRAM_ADDR_CTRL_ADDR_SEL_MASK(cs) BIT(16+cs) +#define SDRAM_ADDR_CTRL_SIZE_LOW_OFFSET(cs) (cs*4+2) +#define SDRAM_ADDR_CTRL_SIZE_LOW_MASK(cs) (0x3 << SDRAM_ADDR_CTRL_SIZE_LOW_OFFSET(cs)) +#define SDRAM_ADDR_CTRL_STRUCT_OFFSET(cs) (cs*4) +#define SDRAM_ADDR_CTRL_STRUCT_MASK(cs) (0x3 << SDRAM_ADDR_CTRL_STRUCT_OFFSET(cs)) + +#define SDRAM_ERR_DATA_H_REG 0x40 +#define SDRAM_ERR_DATA_L_REG 0x44 + +#define SDRAM_ERR_RECV_ECC_REG 0x48 +#define SDRAM_ERR_RECV_ECC_VALUE_MASK 0xff + +#define SDRAM_ERR_CALC_ECC_REG 0x4c +#define SDRAM_ERR_CALC_ECC_ROW_OFFSET 8 +#define SDRAM_ERR_CALC_ECC_ROW_MASK (0xffff << SDRAM_ERR_CALC_ECC_ROW_OFFSET) +#define SDRAM_ERR_CALC_ECC_VALUE_MASK 0xff + +#define SDRAM_ERR_ADDR_REG 0x50 +#define SDRAM_ERR_ADDR_BANK_OFFSET 23 +#define SDRAM_ERR_ADDR_BANK_MASK (0x7 << SDRAM_ERR_ADDR_BANK_OFFSET) +#define SDRAM_ERR_ADDR_COL_OFFSET 8 +#define SDRAM_ERR_ADDR_COL_MASK (0x7fff << SDRAM_ERR_ADDR_COL_OFFSET) +#define SDRAM_ERR_ADDR_CS_OFFSET 1 +#define SDRAM_ERR_ADDR_CS_MASK (0x3 << SDRAM_ERR_ADDR_CS_OFFSET) +#define SDRAM_ERR_ADDR_TYPE_MASK BIT(0) + +#define SDRAM_ERR_CTRL_REG 0x54 +#define SDRAM_ERR_CTRL_THR_OFFSET 16 +#define SDRAM_ERR_CTRL_THR_MASK (0xff << SDRAM_ERR_CTRL_THR_OFFSET) +#define SDRAM_ERR_CTRL_PROP_MASK BIT(9) + +#define SDRAM_ERR_SBE_COUNT_REG 0x58 +#define SDRAM_ERR_DBE_COUNT_REG 0x5c + +#define SDRAM_ERR_CAUSE_ERR_REG 0xd0 +#define SDRAM_ERR_CAUSE_MSG_REG 0xd8 +#define SDRAM_ERR_CAUSE_DBE_MASK BIT(1) +#define SDRAM_ERR_CAUSE_SBE_MASK BIT(0) + +#define SDRAM_RANK_CTRL_REG 0x1e0 +#define SDRAM_RANK_CTRL_EXIST_MASK(cs) BIT(cs) + +struct axp_mc_drvdata { + void __iomem *base; + /* width in bytes */ + unsigned int width; + /* bank interleaving */ + bool cs_addr_sel[SDRAM_NUM_CS]; + + char msg[128]; +}; + +/* derived from "DRAM Address Multiplexing" in the ARAMDA XP Functional Spec */ +static uint32_t axp_mc_calc_address(struct axp_mc_drvdata *drvdata, + uint8_t cs, uint8_t bank, uint16_t row, + uint16_t col) +{ + if (drvdata->width == 8) { + /* 64 bit */ + if (drvdata->cs_addr_sel[cs]) + /* bank interleaved */ + return (((row & 0xfff8) << 16) | + ((bank & 0x7) << 16) | + ((row & 0x7) << 13) | + ((col & 0x3ff) << 3)); + else + return (((row & 0xffff << 16) | + ((bank & 0x7) << 13) | + ((col & 0x3ff)) << 3)); + } else if (drvdata->width == 4) { + /* 32 bit */ + if (drvdata->cs_addr_sel[cs]) + /* bank interleaved */ + return (((row & 0xfff0) << 15) | + ((bank & 0x7) << 16) | + ((row & 0xf) << 12) | + ((col & 0x3ff) << 2)); + else + return (((row & 0xffff << 15) | + ((bank & 0x7) << 12) | + ((col & 0x3ff)) << 2)); + } else { + /* 16 bit */ + if (drvdata->cs_addr_sel[cs]) + /* bank interleaved */ + return (((row & 0xffe0) << 14) | + ((bank & 0x7) << 16) | + ((row & 0x1f) << 11) | + ((col & 0x3ff) << 1)); + else + return (((row & 0xffff << 14) | + ((bank & 0x7) << 11) | + ((col & 0x3ff)) << 1)); + } +} + +static void axp_mc_check(struct mem_ctl_info *mci) +{ + struct axp_mc_drvdata *drvdata = mci->pvt_info; + uint32_t data_h, data_l, recv_ecc, calc_ecc, addr; + uint32_t cnt_sbe, cnt_dbe, cause_err, cause_msg; + uint32_t row_val, col_val, bank_val, addr_val; + uint8_t syndrome_val, cs_val; + char *msg = drvdata->msg; + + data_h = readl(drvdata->base + SDRAM_ERR_DATA_H_REG); + data_l = readl(drvdata->base + SDRAM_ERR_DATA_L_REG); + recv_ecc = readl(drvdata->base + SDRAM_ERR_RECV_ECC_REG); + calc_ecc = readl(drvdata->base + SDRAM_ERR_CALC_ECC_REG); + addr = readl(drvdata->base + SDRAM_ERR_ADDR_REG); + cnt_sbe = readl(drvdata->base + SDRAM_ERR_SBE_COUNT_REG); + cnt_dbe = readl(drvdata->base + SDRAM_ERR_DBE_COUNT_REG); + cause_err = readl(drvdata->base + SDRAM_ERR_CAUSE_ERR_REG); + cause_msg = readl(drvdata->base + SDRAM_ERR_CAUSE_MSG_REG); + + /* clear cause registers */ + writel(~(SDRAM_ERR_CAUSE_DBE_MASK | SDRAM_ERR_CAUSE_SBE_MASK), + drvdata->base + SDRAM_ERR_CAUSE_ERR_REG); + writel(~(SDRAM_ERR_CAUSE_DBE_MASK | SDRAM_ERR_CAUSE_SBE_MASK), + drvdata->base + SDRAM_ERR_CAUSE_MSG_REG); + + /* clear error counter registers */ + if (cnt_sbe) + writel(0, drvdata->base + SDRAM_ERR_SBE_COUNT_REG); + if (cnt_dbe) + writel(0, drvdata->base + SDRAM_ERR_DBE_COUNT_REG); + + if (!cnt_sbe && !cnt_dbe) + return; + + if (!(addr & SDRAM_ERR_ADDR_TYPE_MASK)) { + if (cnt_sbe) + cnt_sbe--; + else + dev_warn(mci->pdev, "inconsistent SBE count detected"); + } else { + if (cnt_dbe) + cnt_dbe--; + else + dev_warn(mci->pdev, "inconsistent DBE count detected"); + } + + /* report earlier errors */ + if (cnt_sbe) + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + cnt_sbe, /* error count */ + 0, 0, 0, /* pfn, offset, syndrome */ + -1, -1, -1, /* top, mid, low layer */ + mci->ctl_name, + "details unavailable (multiple errors)"); + if (cnt_dbe) + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + cnt_sbe, /* error count */ + 0, 0, 0, /* pfn, offset, syndrome */ + -1, -1, -1, /* top, mid, low layer */ + mci->ctl_name, + "details unavailable (multiple errors)"); + + /* report details for most recent error */ + cs_val = (addr & SDRAM_ERR_ADDR_CS_MASK) >> SDRAM_ERR_ADDR_CS_OFFSET; + bank_val = (addr & SDRAM_ERR_ADDR_BANK_MASK) >> SDRAM_ERR_ADDR_BANK_OFFSET; + row_val = (calc_ecc & SDRAM_ERR_CALC_ECC_ROW_MASK) >> SDRAM_ERR_CALC_ECC_ROW_OFFSET; + col_val = (addr & SDRAM_ERR_ADDR_COL_MASK) >> SDRAM_ERR_ADDR_COL_OFFSET; + syndrome_val = (recv_ecc ^ calc_ecc) & 0xff; + addr_val = axp_mc_calc_address(drvdata, cs_val, bank_val, row_val, + col_val); + msg += sprintf(msg, "row=0x%04x ", row_val); /* 11 chars */ + msg += sprintf(msg, "bank=0x%x ", bank_val); /* 9 chars */ + msg += sprintf(msg, "col=0x%04x ", col_val); /* 11 chars */ + msg += sprintf(msg, "cs=%d", cs_val); /* 4 chars */ + + if (!(addr & SDRAM_ERR_ADDR_TYPE_MASK)) { + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + 1, /* error count */ + addr_val >> PAGE_SHIFT, + addr_val & ~PAGE_MASK, + syndrome_val, + cs_val, -1, -1, /* top, mid, low layer */ + mci->ctl_name, drvdata->msg); + } else { + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + 1, /* error count */ + addr_val >> PAGE_SHIFT, + addr_val & ~PAGE_MASK, + syndrome_val, + cs_val, -1, -1, /* top, mid, low layer */ + mci->ctl_name, drvdata->msg); + } +} + +static void axp_mc_read_config(struct mem_ctl_info *mci) +{ + struct axp_mc_drvdata *drvdata = mci->pvt_info; + uint32_t config, addr_ctrl, rank_ctrl; + unsigned int i, cs_struct, cs_size; + struct dimm_info *dimm; + + config = readl(drvdata->base + SDRAM_CONFIG_REG); + if (config & SDRAM_CONFIG_BUS_WIDTH_MASK) + /* 64 bit */ + drvdata->width = 8; + else + /* 32 bit */ + drvdata->width = 4; + + addr_ctrl = readl(drvdata->base + SDRAM_ADDR_CTRL_REG); + rank_ctrl = readl(drvdata->base + SDRAM_RANK_CTRL_REG); + for (i = 0; i < SDRAM_NUM_CS; i++) { + dimm = mci->dimms[i]; + + if (!(rank_ctrl & SDRAM_RANK_CTRL_EXIST_MASK(i))) + continue; + + drvdata->cs_addr_sel[i] = + !!(addr_ctrl & SDRAM_ADDR_CTRL_ADDR_SEL_MASK(i)); + + cs_struct = (addr_ctrl & SDRAM_ADDR_CTRL_STRUCT_MASK(i)) >> SDRAM_ADDR_CTRL_STRUCT_OFFSET(i); + cs_size = ((addr_ctrl & SDRAM_ADDR_CTRL_SIZE_HIGH_MASK(i)) >> (SDRAM_ADDR_CTRL_SIZE_HIGH_OFFSET(i) - 2) | + ((addr_ctrl & SDRAM_ADDR_CTRL_SIZE_LOW_MASK(i)) >> SDRAM_ADDR_CTRL_SIZE_LOW_OFFSET(i))); + + switch (cs_size) { + case 0: /* 2GBit */ + dimm->nr_pages = 524288; + break; + case 1: /* 256MBit */ + dimm->nr_pages = 65536; + break; + case 2: /* 512MBit */ + dimm->nr_pages = 131072; + break; + case 3: /* 1GBit */ + dimm->nr_pages = 262144; + break; + case 4: /* 4GBit */ + dimm->nr_pages = 1048576; + break; + case 5: /* 8GBit */ + dimm->nr_pages = 2097152; + break; + } + dimm->grain = 8; + dimm->dtype = cs_struct ? DEV_X16 : DEV_X8; + dimm->mtype = (config & SDRAM_CONFIG_REGISTERED_MASK) ? + MEM_RDDR3 : MEM_DDR3; + dimm->edac_mode = EDAC_SECDED; + } +} + +static const struct of_device_id axp_mc_of_match[] = { + {.compatible = "marvell,armada-xp-sdram-controller",}, + {}, +}; +MODULE_DEVICE_TABLE(of, axp_mc_of_match); + +static int axp_mc_probe(struct platform_device *pdev) +{ + struct axp_mc_drvdata *drvdata; + struct edac_mc_layer layers[1]; + const struct of_device_id *id; + struct mem_ctl_info *mci; + struct resource *r; + void __iomem *base; + uint32_t config; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "Unable to get mem resource\n"); + return -ENODEV; + } + + base = devm_ioremap_resource(&pdev->dev, r); + if (IS_ERR(base)) { + dev_err(&pdev->dev, "Unable to map regs\n"); + return PTR_ERR(base); + } + + config = readl(base + SDRAM_CONFIG_REG); + if (!(config & SDRAM_CONFIG_ECC_MASK)) { + dev_warn(&pdev->dev, "SDRAM ECC is not enabled"); + return -EINVAL; + } + + layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; + layers[0].size = SDRAM_NUM_CS; + layers[0].is_virt_csrow = true; + + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*drvdata)); + if (!mci) + return -ENOMEM; + + drvdata = mci->pvt_info; + drvdata->base = base; + mci->pdev = &pdev->dev; + platform_set_drvdata(pdev, mci); + + id = of_match_device(axp_mc_of_match, &pdev->dev); + mci->edac_check = axp_mc_check; + mci->mtype_cap = MEM_FLAG_DDR3; + mci->edac_cap = EDAC_FLAG_SECDED; + mci->mod_name = pdev->dev.driver->name; + mci->ctl_name = id ? id->compatible : "unknown"; + mci->dev_name = dev_name(&pdev->dev); + mci->scrub_mode = SCRUB_NONE; + + axp_mc_read_config(mci); + + /* configure SBE threshold */ + /* it seems that SBEs are not captured otherwise */ + writel(1 << SDRAM_ERR_CTRL_THR_OFFSET, drvdata->base + SDRAM_ERR_CTRL_REG); + + /* clear cause registers */ + writel(~(SDRAM_ERR_CAUSE_DBE_MASK | SDRAM_ERR_CAUSE_SBE_MASK), drvdata->base + SDRAM_ERR_CAUSE_ERR_REG); + writel(~(SDRAM_ERR_CAUSE_DBE_MASK | SDRAM_ERR_CAUSE_SBE_MASK), drvdata->base + SDRAM_ERR_CAUSE_MSG_REG); + + /* clear counter registers */ + writel(0, drvdata->base + SDRAM_ERR_SBE_COUNT_REG); + writel(0, drvdata->base + SDRAM_ERR_DBE_COUNT_REG); + + if (edac_mc_add_mc(mci)) { + edac_mc_free(mci); + return -EINVAL; + } + edac_op_state = EDAC_OPSTATE_POLL; + + return 0; +} + +static int axp_mc_remove(struct platform_device *pdev) +{ + struct mem_ctl_info *mci = platform_get_drvdata(pdev); + + edac_mc_del_mc(&pdev->dev); + edac_mc_free(mci); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver axp_mc_driver = { + .probe = axp_mc_probe, + .remove = axp_mc_remove, + .driver = { + .name = "armada_xp_mc_edac", + .of_match_table = of_match_ptr(axp_mc_of_match), + }, +}; + +/************************ EDAC Device (L2 Cache) ***************************/ + +struct aurora_l2_drvdata { + void __iomem *base; + + char msg[128]; + + /* error injection via debugfs */ + uint32_t inject_addr; + uint32_t inject_mask; + uint8_t inject_ctl; + + struct dentry *debugfs; +}; + +#ifdef CONFIG_EDAC_DEBUG +static void aurora_l2_inject(struct aurora_l2_drvdata *drvdata) +{ + drvdata->inject_addr &= AURORA_ERR_INJECT_CTL_ADDR_MASK; + drvdata->inject_ctl &= AURORA_ERR_INJECT_CTL_EN_MASK; + writel(0, drvdata->base + AURORA_ERR_INJECT_CTL_REG); + writel(drvdata->inject_mask, drvdata->base + AURORA_ERR_INJECT_MASK_REG); + writel(drvdata->inject_addr | drvdata->inject_ctl, drvdata->base + AURORA_ERR_INJECT_CTL_REG); +} +#endif + +static void aurora_l2_check(struct edac_device_ctl_info *dci) +{ + struct aurora_l2_drvdata *drvdata = dci->pvt_info; + uint32_t cnt, src, txn, err, attr_cap, addr_cap, way_cap; + unsigned int cnt_ce, cnt_ue; + char *msg = drvdata->msg; + size_t size = sizeof(drvdata->msg); + size_t len = 0; + + cnt = readl(drvdata->base + AURORA_ERR_CNT_REG); + attr_cap = readl(drvdata->base + AURORA_ERR_ATTR_CAP_REG); + addr_cap = readl(drvdata->base + AURORA_ERR_ADDR_CAP_REG); + way_cap = readl(drvdata->base + AURORA_ERR_WAY_CAP_REG); + + cnt_ce = (cnt & AURORA_ERR_CNT_CE_MASK) >> AURORA_ERR_CNT_CE_OFFSET; + cnt_ue = (cnt & AURORA_ERR_CNT_UE_MASK) >> AURORA_ERR_CNT_UE_OFFSET; + /* clear error counter registers */ + if (cnt_ce || cnt_ue) + writel(AURORA_ERR_CNT_CLR, drvdata->base + AURORA_ERR_CNT_REG); + + if (!(attr_cap & AURORA_ERR_ATTR_CAP_VALID)) + goto clear_remaining; + + src = (attr_cap & AURORA_ERR_ATTR_SRC_MSK) >> AURORA_ERR_ATTR_SRC_OFF; + if (src <= 3) + len += snprintf(msg+len, size-len, "src=CPU%d ", src); + else + len += snprintf(msg+len, size-len, "src=IO "); + + txn = (attr_cap & AURORA_ERR_ATTR_TXN_MSK) >> AURORA_ERR_ATTR_TXN_OFF; + switch (txn) { + case 0: + len += snprintf(msg+len, size-len, "txn=Data-Read "); + break; + case 1: + len += snprintf(msg+len, size-len, "txn=Isn-Read "); + break; + case 2: + len += snprintf(msg+len, size-len, "txn=Clean-Flush "); + break; + case 3: + len += snprintf(msg+len, size-len, "txn=Eviction "); + break; + case 4: + len += snprintf(msg+len, size-len, + "txn=Read-Modify-Write "); + break; + } + + err = (attr_cap & AURORA_ERR_ATTR_ERR_MSK) >> AURORA_ERR_ATTR_ERR_OFF; + switch (err) { + case 0: + len += snprintf(msg+len, size-len, "err=CorrECC "); + break; + case 1: + len += snprintf(msg+len, size-len, "err=UnCorrECC "); + break; + case 2: + len += snprintf(msg+len, size-len, "err=TagParity "); + break; + } + + len += snprintf(msg+len, size-len, "addr=0x%x ", addr_cap & AURORA_ERR_ADDR_CAP_ADDR_MASK); + len += snprintf(msg+len, size-len, "index=0x%x ", (way_cap & AURORA_ERR_WAY_IDX_MSK) >> AURORA_ERR_WAY_IDX_OFF); + len += snprintf(msg+len, size-len, "way=0x%x", (way_cap & AURORA_ERR_WAY_CAP_WAY_MASK) >> AURORA_ERR_WAY_CAP_WAY_OFFSET); + + /* clear error capture registers */ + writel(AURORA_ERR_ATTR_CAP_VALID, drvdata->base + AURORA_ERR_ATTR_CAP_REG); + if (err) { + /* UnCorrECC or TagParity */ + if (cnt_ue) + cnt_ue--; + edac_device_handle_ue(dci, 0, 0, drvdata->msg); + } else { + if (cnt_ce) + cnt_ce--; + edac_device_handle_ce(dci, 0, 0, drvdata->msg); + } + +clear_remaining: + /* report remaining errors */ + while (cnt_ue--) + edac_device_handle_ue(dci, 0, 0, "details unavailable (multiple errors)"); + while (cnt_ce--) + edac_device_handle_ue(dci, 0, 0, "details unavailable (multiple errors)"); +} + +static void aurora_l2_poll(struct edac_device_ctl_info *dci) +{ +#ifdef CONFIG_EDAC_DEBUG + struct aurora_l2_drvdata *drvdata = dci->pvt_info; +#endif + + aurora_l2_check(dci); +#ifdef CONFIG_EDAC_DEBUG + aurora_l2_inject(drvdata); +#endif +} + +static const struct of_device_id aurora_l2_of_match[] = { + {.compatible = "marvell,aurora-system-cache",}, + {}, +}; +MODULE_DEVICE_TABLE(of, aurora_l2_of_match); + +static int aurora_l2_probe(struct platform_device *pdev) +{ + struct aurora_l2_drvdata *drvdata; + struct edac_device_ctl_info *dci; + const struct of_device_id *id; + uint32_t l2x0_aux_ctrl; + void __iomem *base; + struct resource *r; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "Unable to get mem resource\n"); + return -ENODEV; + } + + base = devm_ioremap_resource(&pdev->dev, r); + if (IS_ERR(base)) { + dev_err(&pdev->dev, "Unable to map regs\n"); + return PTR_ERR(base); + } + + l2x0_aux_ctrl = readl(base + L2X0_AUX_CTRL); + if (!(l2x0_aux_ctrl & AURORA_ACR_PARITY_EN)) + dev_warn(&pdev->dev, "tag parity is not enabled"); + if (!(l2x0_aux_ctrl & AURORA_ACR_ECC_EN)) + dev_warn(&pdev->dev, "data ECC is not enabled"); + + dci = edac_device_alloc_ctl_info(sizeof(*drvdata), + "cpu", 1, "L", 1, 2, NULL, 0, 0); + if (!dci) + return -ENOMEM; + + drvdata = dci->pvt_info; + drvdata->base = base; + dci->dev = &pdev->dev; + platform_set_drvdata(pdev, dci); + + id = of_match_device(aurora_l2_of_match, &pdev->dev); + dci->edac_check = aurora_l2_poll; + dci->mod_name = pdev->dev.driver->name; + dci->ctl_name = id ? id->compatible : "unknown"; + dci->dev_name = dev_name(&pdev->dev); + + /* clear registers */ + writel(AURORA_ERR_CNT_CLR, drvdata->base + AURORA_ERR_CNT_REG); + writel(AURORA_ERR_ATTR_CAP_VALID, drvdata->base + AURORA_ERR_ATTR_CAP_REG); + + if (edac_device_add_device(dci)) { + edac_device_free_ctl_info(dci); + return -EINVAL; + } + +#ifdef CONFIG_EDAC_DEBUG + drvdata->debugfs = edac_debugfs_create_dir(dev_name(&pdev->dev)); + if (drvdata->debugfs) { + edac_debugfs_create_x32("inject_addr", 0644, + drvdata->debugfs, + &drvdata->inject_addr); + edac_debugfs_create_x32("inject_mask", 0644, + drvdata->debugfs, + &drvdata->inject_mask); + edac_debugfs_create_x8("inject_ctl", 0644, + drvdata->debugfs, &drvdata->inject_ctl); + } +#endif + + return 0; +} + +static int aurora_l2_remove(struct platform_device *pdev) +{ + struct edac_device_ctl_info *dci = platform_get_drvdata(pdev); +#ifdef CONFIG_EDAC_DEBUG + struct aurora_l2_drvdata *drvdata = dci->pvt_info; + + edac_debugfs_remove_recursive(drvdata->debugfs); +#endif + edac_device_del_device(&pdev->dev); + edac_device_free_ctl_info(dci); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver aurora_l2_driver = { + .probe = aurora_l2_probe, + .remove = aurora_l2_remove, + .driver = { + .name = "aurora_l2_edac", + .of_match_table = of_match_ptr(aurora_l2_of_match), + }, +}; + +/************************ Driver registration ******************************/ + +static struct platform_driver * const drivers[] = { + &axp_mc_driver, + &aurora_l2_driver, +}; + +static int __init armada_xp_edac_init(void) +{ + int res; + + /* only polling is supported */ + edac_op_state = EDAC_OPSTATE_POLL; + + res = platform_register_drivers(drivers, ARRAY_SIZE(drivers)); + if (res) + pr_warn("Aramda XP EDAC drivers fail to register\n"); + + return 0; +} +module_init(armada_xp_edac_init); + +static void __exit armada_xp_edac_exit(void) +{ + platform_unregister_drivers(drivers, ARRAY_SIZE(drivers)); +} +module_exit(armada_xp_edac_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Pengutronix"); +MODULE_DESCRIPTION("EDAC Drivers for Marvell Armada XP SDRAM and L2 Cache Controller"); -- 2.19.1 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v6 8/9] EDAC: Add driver for the Marvell Armada XP SDRAM and L2 cache ECC @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux-arm-kernel From: Jan Luebbe <jlu@pengutronix.de> Add support for the ECC functionality as found in the DDR RAM and L2 cache controllers on the MV78230/MV78x60 SoCs. This driver has been tested on the MV78460 (on a custom board with a DDR3 ECC DIMM). Signed-off-by: Jan Luebbe <jlu@pengutronix.de> [cp use SPDX license] Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- MAINTAINERS | 6 + drivers/edac/Kconfig | 7 + drivers/edac/Makefile | 1 + drivers/edac/armada_xp_edac.c | 630 ++++++++++++++++++++++++++++++++++ 4 files changed, 644 insertions(+) create mode 100644 drivers/edac/armada_xp_edac.c diff --git a/MAINTAINERS b/MAINTAINERS index 6c7ed26e84fa..7ae4cfa5c121 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5242,6 +5242,12 @@ L: linux-edac at vger.kernel.org S: Maintained F: drivers/edac/amd64_edac* +EDAC-ARMADA +M: Jan Luebbe <jlu@pengutronix.de> +L: linux-edac at vger.kernel.org +S: Maintained +F: drivers/edac/armada_xp_* + EDAC-CALXEDA M: Robert Richter <rric@kernel.org> L: linux-edac at vger.kernel.org diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 57304b2e989f..4567757d9f82 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -439,6 +439,13 @@ config EDAC_ALTERA_SDMMC Support for error detection and correction on the Altera SDMMC FIFO Memory for Altera SoCs. +config EDAC_ARMADA_XP + bool "Marvell Armada XP DDR and L2 Cache ECC" + depends on MACH_MVEBU_V7 + help + Support for error correction and detection on the Marvell Aramada XP + DDR RAM and L2 cache controllers. + config EDAC_SYNOPSYS tristate "Synopsys DDR Memory Controller" depends on ARCH_ZYNQ diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index 02b43a7d8c3e..f3ea40b0ce9c 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -74,6 +74,7 @@ obj-$(CONFIG_EDAC_OCTEON_PCI) += octeon_edac-pci.o obj-$(CONFIG_EDAC_THUNDERX) += thunderx_edac.o obj-$(CONFIG_EDAC_ALTERA) += altera_edac.o +obj-$(CONFIG_EDAC_ARMADA_XP) += armada_xp_edac.o obj-$(CONFIG_EDAC_SYNOPSYS) += synopsys_edac.o obj-$(CONFIG_EDAC_XGENE) += xgene_edac.o obj-$(CONFIG_EDAC_TI) += ti_edac.o diff --git a/drivers/edac/armada_xp_edac.c b/drivers/edac/armada_xp_edac.c new file mode 100644 index 000000000000..3759a4fbbdee --- /dev/null +++ b/drivers/edac/armada_xp_edac.c @@ -0,0 +1,630 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2017 Pengutronix, Jan Luebbe <kernel@pengutronix.de> + */ + +#include <linux/kernel.h> +#include <linux/edac.h> +#include <linux/of_platform.h> + +#include <asm/hardware/cache-l2x0.h> +#include <asm/hardware/cache-aurora-l2.h> + +#include "edac_mc.h" +#include "edac_device.h" +#include "edac_module.h" + +/************************ EDAC MC (DDR RAM) ********************************/ + +#define SDRAM_NUM_CS 4 + +#define SDRAM_CONFIG_REG 0x0 +#define SDRAM_CONFIG_ECC_MASK BIT(18) +#define SDRAM_CONFIG_REGISTERED_MASK BIT(17) +#define SDRAM_CONFIG_BUS_WIDTH_MASK BIT(15) + +#define SDRAM_ADDR_CTRL_REG 0x10 +#define SDRAM_ADDR_CTRL_SIZE_HIGH_OFFSET(cs) (20+cs) +#define SDRAM_ADDR_CTRL_SIZE_HIGH_MASK(cs) (0x1 << SDRAM_ADDR_CTRL_SIZE_HIGH_OFFSET(cs)) +#define SDRAM_ADDR_CTRL_ADDR_SEL_MASK(cs) BIT(16+cs) +#define SDRAM_ADDR_CTRL_SIZE_LOW_OFFSET(cs) (cs*4+2) +#define SDRAM_ADDR_CTRL_SIZE_LOW_MASK(cs) (0x3 << SDRAM_ADDR_CTRL_SIZE_LOW_OFFSET(cs)) +#define SDRAM_ADDR_CTRL_STRUCT_OFFSET(cs) (cs*4) +#define SDRAM_ADDR_CTRL_STRUCT_MASK(cs) (0x3 << SDRAM_ADDR_CTRL_STRUCT_OFFSET(cs)) + +#define SDRAM_ERR_DATA_H_REG 0x40 +#define SDRAM_ERR_DATA_L_REG 0x44 + +#define SDRAM_ERR_RECV_ECC_REG 0x48 +#define SDRAM_ERR_RECV_ECC_VALUE_MASK 0xff + +#define SDRAM_ERR_CALC_ECC_REG 0x4c +#define SDRAM_ERR_CALC_ECC_ROW_OFFSET 8 +#define SDRAM_ERR_CALC_ECC_ROW_MASK (0xffff << SDRAM_ERR_CALC_ECC_ROW_OFFSET) +#define SDRAM_ERR_CALC_ECC_VALUE_MASK 0xff + +#define SDRAM_ERR_ADDR_REG 0x50 +#define SDRAM_ERR_ADDR_BANK_OFFSET 23 +#define SDRAM_ERR_ADDR_BANK_MASK (0x7 << SDRAM_ERR_ADDR_BANK_OFFSET) +#define SDRAM_ERR_ADDR_COL_OFFSET 8 +#define SDRAM_ERR_ADDR_COL_MASK (0x7fff << SDRAM_ERR_ADDR_COL_OFFSET) +#define SDRAM_ERR_ADDR_CS_OFFSET 1 +#define SDRAM_ERR_ADDR_CS_MASK (0x3 << SDRAM_ERR_ADDR_CS_OFFSET) +#define SDRAM_ERR_ADDR_TYPE_MASK BIT(0) + +#define SDRAM_ERR_CTRL_REG 0x54 +#define SDRAM_ERR_CTRL_THR_OFFSET 16 +#define SDRAM_ERR_CTRL_THR_MASK (0xff << SDRAM_ERR_CTRL_THR_OFFSET) +#define SDRAM_ERR_CTRL_PROP_MASK BIT(9) + +#define SDRAM_ERR_SBE_COUNT_REG 0x58 +#define SDRAM_ERR_DBE_COUNT_REG 0x5c + +#define SDRAM_ERR_CAUSE_ERR_REG 0xd0 +#define SDRAM_ERR_CAUSE_MSG_REG 0xd8 +#define SDRAM_ERR_CAUSE_DBE_MASK BIT(1) +#define SDRAM_ERR_CAUSE_SBE_MASK BIT(0) + +#define SDRAM_RANK_CTRL_REG 0x1e0 +#define SDRAM_RANK_CTRL_EXIST_MASK(cs) BIT(cs) + +struct axp_mc_drvdata { + void __iomem *base; + /* width in bytes */ + unsigned int width; + /* bank interleaving */ + bool cs_addr_sel[SDRAM_NUM_CS]; + + char msg[128]; +}; + +/* derived from "DRAM Address Multiplexing" in the ARAMDA XP Functional Spec */ +static uint32_t axp_mc_calc_address(struct axp_mc_drvdata *drvdata, + uint8_t cs, uint8_t bank, uint16_t row, + uint16_t col) +{ + if (drvdata->width == 8) { + /* 64 bit */ + if (drvdata->cs_addr_sel[cs]) + /* bank interleaved */ + return (((row & 0xfff8) << 16) | + ((bank & 0x7) << 16) | + ((row & 0x7) << 13) | + ((col & 0x3ff) << 3)); + else + return (((row & 0xffff << 16) | + ((bank & 0x7) << 13) | + ((col & 0x3ff)) << 3)); + } else if (drvdata->width == 4) { + /* 32 bit */ + if (drvdata->cs_addr_sel[cs]) + /* bank interleaved */ + return (((row & 0xfff0) << 15) | + ((bank & 0x7) << 16) | + ((row & 0xf) << 12) | + ((col & 0x3ff) << 2)); + else + return (((row & 0xffff << 15) | + ((bank & 0x7) << 12) | + ((col & 0x3ff)) << 2)); + } else { + /* 16 bit */ + if (drvdata->cs_addr_sel[cs]) + /* bank interleaved */ + return (((row & 0xffe0) << 14) | + ((bank & 0x7) << 16) | + ((row & 0x1f) << 11) | + ((col & 0x3ff) << 1)); + else + return (((row & 0xffff << 14) | + ((bank & 0x7) << 11) | + ((col & 0x3ff)) << 1)); + } +} + +static void axp_mc_check(struct mem_ctl_info *mci) +{ + struct axp_mc_drvdata *drvdata = mci->pvt_info; + uint32_t data_h, data_l, recv_ecc, calc_ecc, addr; + uint32_t cnt_sbe, cnt_dbe, cause_err, cause_msg; + uint32_t row_val, col_val, bank_val, addr_val; + uint8_t syndrome_val, cs_val; + char *msg = drvdata->msg; + + data_h = readl(drvdata->base + SDRAM_ERR_DATA_H_REG); + data_l = readl(drvdata->base + SDRAM_ERR_DATA_L_REG); + recv_ecc = readl(drvdata->base + SDRAM_ERR_RECV_ECC_REG); + calc_ecc = readl(drvdata->base + SDRAM_ERR_CALC_ECC_REG); + addr = readl(drvdata->base + SDRAM_ERR_ADDR_REG); + cnt_sbe = readl(drvdata->base + SDRAM_ERR_SBE_COUNT_REG); + cnt_dbe = readl(drvdata->base + SDRAM_ERR_DBE_COUNT_REG); + cause_err = readl(drvdata->base + SDRAM_ERR_CAUSE_ERR_REG); + cause_msg = readl(drvdata->base + SDRAM_ERR_CAUSE_MSG_REG); + + /* clear cause registers */ + writel(~(SDRAM_ERR_CAUSE_DBE_MASK | SDRAM_ERR_CAUSE_SBE_MASK), + drvdata->base + SDRAM_ERR_CAUSE_ERR_REG); + writel(~(SDRAM_ERR_CAUSE_DBE_MASK | SDRAM_ERR_CAUSE_SBE_MASK), + drvdata->base + SDRAM_ERR_CAUSE_MSG_REG); + + /* clear error counter registers */ + if (cnt_sbe) + writel(0, drvdata->base + SDRAM_ERR_SBE_COUNT_REG); + if (cnt_dbe) + writel(0, drvdata->base + SDRAM_ERR_DBE_COUNT_REG); + + if (!cnt_sbe && !cnt_dbe) + return; + + if (!(addr & SDRAM_ERR_ADDR_TYPE_MASK)) { + if (cnt_sbe) + cnt_sbe--; + else + dev_warn(mci->pdev, "inconsistent SBE count detected"); + } else { + if (cnt_dbe) + cnt_dbe--; + else + dev_warn(mci->pdev, "inconsistent DBE count detected"); + } + + /* report earlier errors */ + if (cnt_sbe) + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + cnt_sbe, /* error count */ + 0, 0, 0, /* pfn, offset, syndrome */ + -1, -1, -1, /* top, mid, low layer */ + mci->ctl_name, + "details unavailable (multiple errors)"); + if (cnt_dbe) + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + cnt_sbe, /* error count */ + 0, 0, 0, /* pfn, offset, syndrome */ + -1, -1, -1, /* top, mid, low layer */ + mci->ctl_name, + "details unavailable (multiple errors)"); + + /* report details for most recent error */ + cs_val = (addr & SDRAM_ERR_ADDR_CS_MASK) >> SDRAM_ERR_ADDR_CS_OFFSET; + bank_val = (addr & SDRAM_ERR_ADDR_BANK_MASK) >> SDRAM_ERR_ADDR_BANK_OFFSET; + row_val = (calc_ecc & SDRAM_ERR_CALC_ECC_ROW_MASK) >> SDRAM_ERR_CALC_ECC_ROW_OFFSET; + col_val = (addr & SDRAM_ERR_ADDR_COL_MASK) >> SDRAM_ERR_ADDR_COL_OFFSET; + syndrome_val = (recv_ecc ^ calc_ecc) & 0xff; + addr_val = axp_mc_calc_address(drvdata, cs_val, bank_val, row_val, + col_val); + msg += sprintf(msg, "row=0x%04x ", row_val); /* 11 chars */ + msg += sprintf(msg, "bank=0x%x ", bank_val); /* 9 chars */ + msg += sprintf(msg, "col=0x%04x ", col_val); /* 11 chars */ + msg += sprintf(msg, "cs=%d", cs_val); /* 4 chars */ + + if (!(addr & SDRAM_ERR_ADDR_TYPE_MASK)) { + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + 1, /* error count */ + addr_val >> PAGE_SHIFT, + addr_val & ~PAGE_MASK, + syndrome_val, + cs_val, -1, -1, /* top, mid, low layer */ + mci->ctl_name, drvdata->msg); + } else { + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + 1, /* error count */ + addr_val >> PAGE_SHIFT, + addr_val & ~PAGE_MASK, + syndrome_val, + cs_val, -1, -1, /* top, mid, low layer */ + mci->ctl_name, drvdata->msg); + } +} + +static void axp_mc_read_config(struct mem_ctl_info *mci) +{ + struct axp_mc_drvdata *drvdata = mci->pvt_info; + uint32_t config, addr_ctrl, rank_ctrl; + unsigned int i, cs_struct, cs_size; + struct dimm_info *dimm; + + config = readl(drvdata->base + SDRAM_CONFIG_REG); + if (config & SDRAM_CONFIG_BUS_WIDTH_MASK) + /* 64 bit */ + drvdata->width = 8; + else + /* 32 bit */ + drvdata->width = 4; + + addr_ctrl = readl(drvdata->base + SDRAM_ADDR_CTRL_REG); + rank_ctrl = readl(drvdata->base + SDRAM_RANK_CTRL_REG); + for (i = 0; i < SDRAM_NUM_CS; i++) { + dimm = mci->dimms[i]; + + if (!(rank_ctrl & SDRAM_RANK_CTRL_EXIST_MASK(i))) + continue; + + drvdata->cs_addr_sel[i] = + !!(addr_ctrl & SDRAM_ADDR_CTRL_ADDR_SEL_MASK(i)); + + cs_struct = (addr_ctrl & SDRAM_ADDR_CTRL_STRUCT_MASK(i)) >> SDRAM_ADDR_CTRL_STRUCT_OFFSET(i); + cs_size = ((addr_ctrl & SDRAM_ADDR_CTRL_SIZE_HIGH_MASK(i)) >> (SDRAM_ADDR_CTRL_SIZE_HIGH_OFFSET(i) - 2) | + ((addr_ctrl & SDRAM_ADDR_CTRL_SIZE_LOW_MASK(i)) >> SDRAM_ADDR_CTRL_SIZE_LOW_OFFSET(i))); + + switch (cs_size) { + case 0: /* 2GBit */ + dimm->nr_pages = 524288; + break; + case 1: /* 256MBit */ + dimm->nr_pages = 65536; + break; + case 2: /* 512MBit */ + dimm->nr_pages = 131072; + break; + case 3: /* 1GBit */ + dimm->nr_pages = 262144; + break; + case 4: /* 4GBit */ + dimm->nr_pages = 1048576; + break; + case 5: /* 8GBit */ + dimm->nr_pages = 2097152; + break; + } + dimm->grain = 8; + dimm->dtype = cs_struct ? DEV_X16 : DEV_X8; + dimm->mtype = (config & SDRAM_CONFIG_REGISTERED_MASK) ? + MEM_RDDR3 : MEM_DDR3; + dimm->edac_mode = EDAC_SECDED; + } +} + +static const struct of_device_id axp_mc_of_match[] = { + {.compatible = "marvell,armada-xp-sdram-controller",}, + {}, +}; +MODULE_DEVICE_TABLE(of, axp_mc_of_match); + +static int axp_mc_probe(struct platform_device *pdev) +{ + struct axp_mc_drvdata *drvdata; + struct edac_mc_layer layers[1]; + const struct of_device_id *id; + struct mem_ctl_info *mci; + struct resource *r; + void __iomem *base; + uint32_t config; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "Unable to get mem resource\n"); + return -ENODEV; + } + + base = devm_ioremap_resource(&pdev->dev, r); + if (IS_ERR(base)) { + dev_err(&pdev->dev, "Unable to map regs\n"); + return PTR_ERR(base); + } + + config = readl(base + SDRAM_CONFIG_REG); + if (!(config & SDRAM_CONFIG_ECC_MASK)) { + dev_warn(&pdev->dev, "SDRAM ECC is not enabled"); + return -EINVAL; + } + + layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; + layers[0].size = SDRAM_NUM_CS; + layers[0].is_virt_csrow = true; + + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*drvdata)); + if (!mci) + return -ENOMEM; + + drvdata = mci->pvt_info; + drvdata->base = base; + mci->pdev = &pdev->dev; + platform_set_drvdata(pdev, mci); + + id = of_match_device(axp_mc_of_match, &pdev->dev); + mci->edac_check = axp_mc_check; + mci->mtype_cap = MEM_FLAG_DDR3; + mci->edac_cap = EDAC_FLAG_SECDED; + mci->mod_name = pdev->dev.driver->name; + mci->ctl_name = id ? id->compatible : "unknown"; + mci->dev_name = dev_name(&pdev->dev); + mci->scrub_mode = SCRUB_NONE; + + axp_mc_read_config(mci); + + /* configure SBE threshold */ + /* it seems that SBEs are not captured otherwise */ + writel(1 << SDRAM_ERR_CTRL_THR_OFFSET, drvdata->base + SDRAM_ERR_CTRL_REG); + + /* clear cause registers */ + writel(~(SDRAM_ERR_CAUSE_DBE_MASK | SDRAM_ERR_CAUSE_SBE_MASK), drvdata->base + SDRAM_ERR_CAUSE_ERR_REG); + writel(~(SDRAM_ERR_CAUSE_DBE_MASK | SDRAM_ERR_CAUSE_SBE_MASK), drvdata->base + SDRAM_ERR_CAUSE_MSG_REG); + + /* clear counter registers */ + writel(0, drvdata->base + SDRAM_ERR_SBE_COUNT_REG); + writel(0, drvdata->base + SDRAM_ERR_DBE_COUNT_REG); + + if (edac_mc_add_mc(mci)) { + edac_mc_free(mci); + return -EINVAL; + } + edac_op_state = EDAC_OPSTATE_POLL; + + return 0; +} + +static int axp_mc_remove(struct platform_device *pdev) +{ + struct mem_ctl_info *mci = platform_get_drvdata(pdev); + + edac_mc_del_mc(&pdev->dev); + edac_mc_free(mci); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver axp_mc_driver = { + .probe = axp_mc_probe, + .remove = axp_mc_remove, + .driver = { + .name = "armada_xp_mc_edac", + .of_match_table = of_match_ptr(axp_mc_of_match), + }, +}; + +/************************ EDAC Device (L2 Cache) ***************************/ + +struct aurora_l2_drvdata { + void __iomem *base; + + char msg[128]; + + /* error injection via debugfs */ + uint32_t inject_addr; + uint32_t inject_mask; + uint8_t inject_ctl; + + struct dentry *debugfs; +}; + +#ifdef CONFIG_EDAC_DEBUG +static void aurora_l2_inject(struct aurora_l2_drvdata *drvdata) +{ + drvdata->inject_addr &= AURORA_ERR_INJECT_CTL_ADDR_MASK; + drvdata->inject_ctl &= AURORA_ERR_INJECT_CTL_EN_MASK; + writel(0, drvdata->base + AURORA_ERR_INJECT_CTL_REG); + writel(drvdata->inject_mask, drvdata->base + AURORA_ERR_INJECT_MASK_REG); + writel(drvdata->inject_addr | drvdata->inject_ctl, drvdata->base + AURORA_ERR_INJECT_CTL_REG); +} +#endif + +static void aurora_l2_check(struct edac_device_ctl_info *dci) +{ + struct aurora_l2_drvdata *drvdata = dci->pvt_info; + uint32_t cnt, src, txn, err, attr_cap, addr_cap, way_cap; + unsigned int cnt_ce, cnt_ue; + char *msg = drvdata->msg; + size_t size = sizeof(drvdata->msg); + size_t len = 0; + + cnt = readl(drvdata->base + AURORA_ERR_CNT_REG); + attr_cap = readl(drvdata->base + AURORA_ERR_ATTR_CAP_REG); + addr_cap = readl(drvdata->base + AURORA_ERR_ADDR_CAP_REG); + way_cap = readl(drvdata->base + AURORA_ERR_WAY_CAP_REG); + + cnt_ce = (cnt & AURORA_ERR_CNT_CE_MASK) >> AURORA_ERR_CNT_CE_OFFSET; + cnt_ue = (cnt & AURORA_ERR_CNT_UE_MASK) >> AURORA_ERR_CNT_UE_OFFSET; + /* clear error counter registers */ + if (cnt_ce || cnt_ue) + writel(AURORA_ERR_CNT_CLR, drvdata->base + AURORA_ERR_CNT_REG); + + if (!(attr_cap & AURORA_ERR_ATTR_CAP_VALID)) + goto clear_remaining; + + src = (attr_cap & AURORA_ERR_ATTR_SRC_MSK) >> AURORA_ERR_ATTR_SRC_OFF; + if (src <= 3) + len += snprintf(msg+len, size-len, "src=CPU%d ", src); + else + len += snprintf(msg+len, size-len, "src=IO "); + + txn = (attr_cap & AURORA_ERR_ATTR_TXN_MSK) >> AURORA_ERR_ATTR_TXN_OFF; + switch (txn) { + case 0: + len += snprintf(msg+len, size-len, "txn=Data-Read "); + break; + case 1: + len += snprintf(msg+len, size-len, "txn=Isn-Read "); + break; + case 2: + len += snprintf(msg+len, size-len, "txn=Clean-Flush "); + break; + case 3: + len += snprintf(msg+len, size-len, "txn=Eviction "); + break; + case 4: + len += snprintf(msg+len, size-len, + "txn=Read-Modify-Write "); + break; + } + + err = (attr_cap & AURORA_ERR_ATTR_ERR_MSK) >> AURORA_ERR_ATTR_ERR_OFF; + switch (err) { + case 0: + len += snprintf(msg+len, size-len, "err=CorrECC "); + break; + case 1: + len += snprintf(msg+len, size-len, "err=UnCorrECC "); + break; + case 2: + len += snprintf(msg+len, size-len, "err=TagParity "); + break; + } + + len += snprintf(msg+len, size-len, "addr=0x%x ", addr_cap & AURORA_ERR_ADDR_CAP_ADDR_MASK); + len += snprintf(msg+len, size-len, "index=0x%x ", (way_cap & AURORA_ERR_WAY_IDX_MSK) >> AURORA_ERR_WAY_IDX_OFF); + len += snprintf(msg+len, size-len, "way=0x%x", (way_cap & AURORA_ERR_WAY_CAP_WAY_MASK) >> AURORA_ERR_WAY_CAP_WAY_OFFSET); + + /* clear error capture registers */ + writel(AURORA_ERR_ATTR_CAP_VALID, drvdata->base + AURORA_ERR_ATTR_CAP_REG); + if (err) { + /* UnCorrECC or TagParity */ + if (cnt_ue) + cnt_ue--; + edac_device_handle_ue(dci, 0, 0, drvdata->msg); + } else { + if (cnt_ce) + cnt_ce--; + edac_device_handle_ce(dci, 0, 0, drvdata->msg); + } + +clear_remaining: + /* report remaining errors */ + while (cnt_ue--) + edac_device_handle_ue(dci, 0, 0, "details unavailable (multiple errors)"); + while (cnt_ce--) + edac_device_handle_ue(dci, 0, 0, "details unavailable (multiple errors)"); +} + +static void aurora_l2_poll(struct edac_device_ctl_info *dci) +{ +#ifdef CONFIG_EDAC_DEBUG + struct aurora_l2_drvdata *drvdata = dci->pvt_info; +#endif + + aurora_l2_check(dci); +#ifdef CONFIG_EDAC_DEBUG + aurora_l2_inject(drvdata); +#endif +} + +static const struct of_device_id aurora_l2_of_match[] = { + {.compatible = "marvell,aurora-system-cache",}, + {}, +}; +MODULE_DEVICE_TABLE(of, aurora_l2_of_match); + +static int aurora_l2_probe(struct platform_device *pdev) +{ + struct aurora_l2_drvdata *drvdata; + struct edac_device_ctl_info *dci; + const struct of_device_id *id; + uint32_t l2x0_aux_ctrl; + void __iomem *base; + struct resource *r; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "Unable to get mem resource\n"); + return -ENODEV; + } + + base = devm_ioremap_resource(&pdev->dev, r); + if (IS_ERR(base)) { + dev_err(&pdev->dev, "Unable to map regs\n"); + return PTR_ERR(base); + } + + l2x0_aux_ctrl = readl(base + L2X0_AUX_CTRL); + if (!(l2x0_aux_ctrl & AURORA_ACR_PARITY_EN)) + dev_warn(&pdev->dev, "tag parity is not enabled"); + if (!(l2x0_aux_ctrl & AURORA_ACR_ECC_EN)) + dev_warn(&pdev->dev, "data ECC is not enabled"); + + dci = edac_device_alloc_ctl_info(sizeof(*drvdata), + "cpu", 1, "L", 1, 2, NULL, 0, 0); + if (!dci) + return -ENOMEM; + + drvdata = dci->pvt_info; + drvdata->base = base; + dci->dev = &pdev->dev; + platform_set_drvdata(pdev, dci); + + id = of_match_device(aurora_l2_of_match, &pdev->dev); + dci->edac_check = aurora_l2_poll; + dci->mod_name = pdev->dev.driver->name; + dci->ctl_name = id ? id->compatible : "unknown"; + dci->dev_name = dev_name(&pdev->dev); + + /* clear registers */ + writel(AURORA_ERR_CNT_CLR, drvdata->base + AURORA_ERR_CNT_REG); + writel(AURORA_ERR_ATTR_CAP_VALID, drvdata->base + AURORA_ERR_ATTR_CAP_REG); + + if (edac_device_add_device(dci)) { + edac_device_free_ctl_info(dci); + return -EINVAL; + } + +#ifdef CONFIG_EDAC_DEBUG + drvdata->debugfs = edac_debugfs_create_dir(dev_name(&pdev->dev)); + if (drvdata->debugfs) { + edac_debugfs_create_x32("inject_addr", 0644, + drvdata->debugfs, + &drvdata->inject_addr); + edac_debugfs_create_x32("inject_mask", 0644, + drvdata->debugfs, + &drvdata->inject_mask); + edac_debugfs_create_x8("inject_ctl", 0644, + drvdata->debugfs, &drvdata->inject_ctl); + } +#endif + + return 0; +} + +static int aurora_l2_remove(struct platform_device *pdev) +{ + struct edac_device_ctl_info *dci = platform_get_drvdata(pdev); +#ifdef CONFIG_EDAC_DEBUG + struct aurora_l2_drvdata *drvdata = dci->pvt_info; + + edac_debugfs_remove_recursive(drvdata->debugfs); +#endif + edac_device_del_device(&pdev->dev); + edac_device_free_ctl_info(dci); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver aurora_l2_driver = { + .probe = aurora_l2_probe, + .remove = aurora_l2_remove, + .driver = { + .name = "aurora_l2_edac", + .of_match_table = of_match_ptr(aurora_l2_of_match), + }, +}; + +/************************ Driver registration ******************************/ + +static struct platform_driver * const drivers[] = { + &axp_mc_driver, + &aurora_l2_driver, +}; + +static int __init armada_xp_edac_init(void) +{ + int res; + + /* only polling is supported */ + edac_op_state = EDAC_OPSTATE_POLL; + + res = platform_register_drivers(drivers, ARRAY_SIZE(drivers)); + if (res) + pr_warn("Aramda XP EDAC drivers fail to register\n"); + + return 0; +} +module_init(armada_xp_edac_init); + +static void __exit armada_xp_edac_exit(void) +{ + platform_unregister_drivers(drivers, ARRAY_SIZE(drivers)); +} +module_exit(armada_xp_edac_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Pengutronix"); +MODULE_DESCRIPTION("EDAC Drivers for Marvell Armada XP SDRAM and L2 Cache Controller"); -- 2.19.1 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [v6,8/9] EDAC: Add driver for the Marvell Armada XP SDRAM and L2 cache ECC @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham, Mauro Carvalho Chehab From: Jan Luebbe <jlu@pengutronix.de> Add support for the ECC functionality as found in the DDR RAM and L2 cache controllers on the MV78230/MV78x60 SoCs. This driver has been tested on the MV78460 (on a custom board with a DDR3 ECC DIMM). Signed-off-by: Jan Luebbe <jlu@pengutronix.de> [cp use SPDX license] Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- MAINTAINERS | 6 + drivers/edac/Kconfig | 7 + drivers/edac/Makefile | 1 + drivers/edac/armada_xp_edac.c | 630 ++++++++++++++++++++++++++++++++++ 4 files changed, 644 insertions(+) create mode 100644 drivers/edac/armada_xp_edac.c diff --git a/MAINTAINERS b/MAINTAINERS index 6c7ed26e84fa..7ae4cfa5c121 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5242,6 +5242,12 @@ L: linux-edac@vger.kernel.org S: Maintained F: drivers/edac/amd64_edac* +EDAC-ARMADA +M: Jan Luebbe <jlu@pengutronix.de> +L: linux-edac@vger.kernel.org +S: Maintained +F: drivers/edac/armada_xp_* + EDAC-CALXEDA M: Robert Richter <rric@kernel.org> L: linux-edac@vger.kernel.org diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 57304b2e989f..4567757d9f82 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -439,6 +439,13 @@ config EDAC_ALTERA_SDMMC Support for error detection and correction on the Altera SDMMC FIFO Memory for Altera SoCs. +config EDAC_ARMADA_XP + bool "Marvell Armada XP DDR and L2 Cache ECC" + depends on MACH_MVEBU_V7 + help + Support for error correction and detection on the Marvell Aramada XP + DDR RAM and L2 cache controllers. + config EDAC_SYNOPSYS tristate "Synopsys DDR Memory Controller" depends on ARCH_ZYNQ diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index 02b43a7d8c3e..f3ea40b0ce9c 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -74,6 +74,7 @@ obj-$(CONFIG_EDAC_OCTEON_PCI) += octeon_edac-pci.o obj-$(CONFIG_EDAC_THUNDERX) += thunderx_edac.o obj-$(CONFIG_EDAC_ALTERA) += altera_edac.o +obj-$(CONFIG_EDAC_ARMADA_XP) += armada_xp_edac.o obj-$(CONFIG_EDAC_SYNOPSYS) += synopsys_edac.o obj-$(CONFIG_EDAC_XGENE) += xgene_edac.o obj-$(CONFIG_EDAC_TI) += ti_edac.o diff --git a/drivers/edac/armada_xp_edac.c b/drivers/edac/armada_xp_edac.c new file mode 100644 index 000000000000..3759a4fbbdee --- /dev/null +++ b/drivers/edac/armada_xp_edac.c @@ -0,0 +1,630 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2017 Pengutronix, Jan Luebbe <kernel@pengutronix.de> + */ + +#include <linux/kernel.h> +#include <linux/edac.h> +#include <linux/of_platform.h> + +#include <asm/hardware/cache-l2x0.h> +#include <asm/hardware/cache-aurora-l2.h> + +#include "edac_mc.h" +#include "edac_device.h" +#include "edac_module.h" + +/************************ EDAC MC (DDR RAM) ********************************/ + +#define SDRAM_NUM_CS 4 + +#define SDRAM_CONFIG_REG 0x0 +#define SDRAM_CONFIG_ECC_MASK BIT(18) +#define SDRAM_CONFIG_REGISTERED_MASK BIT(17) +#define SDRAM_CONFIG_BUS_WIDTH_MASK BIT(15) + +#define SDRAM_ADDR_CTRL_REG 0x10 +#define SDRAM_ADDR_CTRL_SIZE_HIGH_OFFSET(cs) (20+cs) +#define SDRAM_ADDR_CTRL_SIZE_HIGH_MASK(cs) (0x1 << SDRAM_ADDR_CTRL_SIZE_HIGH_OFFSET(cs)) +#define SDRAM_ADDR_CTRL_ADDR_SEL_MASK(cs) BIT(16+cs) +#define SDRAM_ADDR_CTRL_SIZE_LOW_OFFSET(cs) (cs*4+2) +#define SDRAM_ADDR_CTRL_SIZE_LOW_MASK(cs) (0x3 << SDRAM_ADDR_CTRL_SIZE_LOW_OFFSET(cs)) +#define SDRAM_ADDR_CTRL_STRUCT_OFFSET(cs) (cs*4) +#define SDRAM_ADDR_CTRL_STRUCT_MASK(cs) (0x3 << SDRAM_ADDR_CTRL_STRUCT_OFFSET(cs)) + +#define SDRAM_ERR_DATA_H_REG 0x40 +#define SDRAM_ERR_DATA_L_REG 0x44 + +#define SDRAM_ERR_RECV_ECC_REG 0x48 +#define SDRAM_ERR_RECV_ECC_VALUE_MASK 0xff + +#define SDRAM_ERR_CALC_ECC_REG 0x4c +#define SDRAM_ERR_CALC_ECC_ROW_OFFSET 8 +#define SDRAM_ERR_CALC_ECC_ROW_MASK (0xffff << SDRAM_ERR_CALC_ECC_ROW_OFFSET) +#define SDRAM_ERR_CALC_ECC_VALUE_MASK 0xff + +#define SDRAM_ERR_ADDR_REG 0x50 +#define SDRAM_ERR_ADDR_BANK_OFFSET 23 +#define SDRAM_ERR_ADDR_BANK_MASK (0x7 << SDRAM_ERR_ADDR_BANK_OFFSET) +#define SDRAM_ERR_ADDR_COL_OFFSET 8 +#define SDRAM_ERR_ADDR_COL_MASK (0x7fff << SDRAM_ERR_ADDR_COL_OFFSET) +#define SDRAM_ERR_ADDR_CS_OFFSET 1 +#define SDRAM_ERR_ADDR_CS_MASK (0x3 << SDRAM_ERR_ADDR_CS_OFFSET) +#define SDRAM_ERR_ADDR_TYPE_MASK BIT(0) + +#define SDRAM_ERR_CTRL_REG 0x54 +#define SDRAM_ERR_CTRL_THR_OFFSET 16 +#define SDRAM_ERR_CTRL_THR_MASK (0xff << SDRAM_ERR_CTRL_THR_OFFSET) +#define SDRAM_ERR_CTRL_PROP_MASK BIT(9) + +#define SDRAM_ERR_SBE_COUNT_REG 0x58 +#define SDRAM_ERR_DBE_COUNT_REG 0x5c + +#define SDRAM_ERR_CAUSE_ERR_REG 0xd0 +#define SDRAM_ERR_CAUSE_MSG_REG 0xd8 +#define SDRAM_ERR_CAUSE_DBE_MASK BIT(1) +#define SDRAM_ERR_CAUSE_SBE_MASK BIT(0) + +#define SDRAM_RANK_CTRL_REG 0x1e0 +#define SDRAM_RANK_CTRL_EXIST_MASK(cs) BIT(cs) + +struct axp_mc_drvdata { + void __iomem *base; + /* width in bytes */ + unsigned int width; + /* bank interleaving */ + bool cs_addr_sel[SDRAM_NUM_CS]; + + char msg[128]; +}; + +/* derived from "DRAM Address Multiplexing" in the ARAMDA XP Functional Spec */ +static uint32_t axp_mc_calc_address(struct axp_mc_drvdata *drvdata, + uint8_t cs, uint8_t bank, uint16_t row, + uint16_t col) +{ + if (drvdata->width == 8) { + /* 64 bit */ + if (drvdata->cs_addr_sel[cs]) + /* bank interleaved */ + return (((row & 0xfff8) << 16) | + ((bank & 0x7) << 16) | + ((row & 0x7) << 13) | + ((col & 0x3ff) << 3)); + else + return (((row & 0xffff << 16) | + ((bank & 0x7) << 13) | + ((col & 0x3ff)) << 3)); + } else if (drvdata->width == 4) { + /* 32 bit */ + if (drvdata->cs_addr_sel[cs]) + /* bank interleaved */ + return (((row & 0xfff0) << 15) | + ((bank & 0x7) << 16) | + ((row & 0xf) << 12) | + ((col & 0x3ff) << 2)); + else + return (((row & 0xffff << 15) | + ((bank & 0x7) << 12) | + ((col & 0x3ff)) << 2)); + } else { + /* 16 bit */ + if (drvdata->cs_addr_sel[cs]) + /* bank interleaved */ + return (((row & 0xffe0) << 14) | + ((bank & 0x7) << 16) | + ((row & 0x1f) << 11) | + ((col & 0x3ff) << 1)); + else + return (((row & 0xffff << 14) | + ((bank & 0x7) << 11) | + ((col & 0x3ff)) << 1)); + } +} + +static void axp_mc_check(struct mem_ctl_info *mci) +{ + struct axp_mc_drvdata *drvdata = mci->pvt_info; + uint32_t data_h, data_l, recv_ecc, calc_ecc, addr; + uint32_t cnt_sbe, cnt_dbe, cause_err, cause_msg; + uint32_t row_val, col_val, bank_val, addr_val; + uint8_t syndrome_val, cs_val; + char *msg = drvdata->msg; + + data_h = readl(drvdata->base + SDRAM_ERR_DATA_H_REG); + data_l = readl(drvdata->base + SDRAM_ERR_DATA_L_REG); + recv_ecc = readl(drvdata->base + SDRAM_ERR_RECV_ECC_REG); + calc_ecc = readl(drvdata->base + SDRAM_ERR_CALC_ECC_REG); + addr = readl(drvdata->base + SDRAM_ERR_ADDR_REG); + cnt_sbe = readl(drvdata->base + SDRAM_ERR_SBE_COUNT_REG); + cnt_dbe = readl(drvdata->base + SDRAM_ERR_DBE_COUNT_REG); + cause_err = readl(drvdata->base + SDRAM_ERR_CAUSE_ERR_REG); + cause_msg = readl(drvdata->base + SDRAM_ERR_CAUSE_MSG_REG); + + /* clear cause registers */ + writel(~(SDRAM_ERR_CAUSE_DBE_MASK | SDRAM_ERR_CAUSE_SBE_MASK), + drvdata->base + SDRAM_ERR_CAUSE_ERR_REG); + writel(~(SDRAM_ERR_CAUSE_DBE_MASK | SDRAM_ERR_CAUSE_SBE_MASK), + drvdata->base + SDRAM_ERR_CAUSE_MSG_REG); + + /* clear error counter registers */ + if (cnt_sbe) + writel(0, drvdata->base + SDRAM_ERR_SBE_COUNT_REG); + if (cnt_dbe) + writel(0, drvdata->base + SDRAM_ERR_DBE_COUNT_REG); + + if (!cnt_sbe && !cnt_dbe) + return; + + if (!(addr & SDRAM_ERR_ADDR_TYPE_MASK)) { + if (cnt_sbe) + cnt_sbe--; + else + dev_warn(mci->pdev, "inconsistent SBE count detected"); + } else { + if (cnt_dbe) + cnt_dbe--; + else + dev_warn(mci->pdev, "inconsistent DBE count detected"); + } + + /* report earlier errors */ + if (cnt_sbe) + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + cnt_sbe, /* error count */ + 0, 0, 0, /* pfn, offset, syndrome */ + -1, -1, -1, /* top, mid, low layer */ + mci->ctl_name, + "details unavailable (multiple errors)"); + if (cnt_dbe) + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + cnt_sbe, /* error count */ + 0, 0, 0, /* pfn, offset, syndrome */ + -1, -1, -1, /* top, mid, low layer */ + mci->ctl_name, + "details unavailable (multiple errors)"); + + /* report details for most recent error */ + cs_val = (addr & SDRAM_ERR_ADDR_CS_MASK) >> SDRAM_ERR_ADDR_CS_OFFSET; + bank_val = (addr & SDRAM_ERR_ADDR_BANK_MASK) >> SDRAM_ERR_ADDR_BANK_OFFSET; + row_val = (calc_ecc & SDRAM_ERR_CALC_ECC_ROW_MASK) >> SDRAM_ERR_CALC_ECC_ROW_OFFSET; + col_val = (addr & SDRAM_ERR_ADDR_COL_MASK) >> SDRAM_ERR_ADDR_COL_OFFSET; + syndrome_val = (recv_ecc ^ calc_ecc) & 0xff; + addr_val = axp_mc_calc_address(drvdata, cs_val, bank_val, row_val, + col_val); + msg += sprintf(msg, "row=0x%04x ", row_val); /* 11 chars */ + msg += sprintf(msg, "bank=0x%x ", bank_val); /* 9 chars */ + msg += sprintf(msg, "col=0x%04x ", col_val); /* 11 chars */ + msg += sprintf(msg, "cs=%d", cs_val); /* 4 chars */ + + if (!(addr & SDRAM_ERR_ADDR_TYPE_MASK)) { + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, + 1, /* error count */ + addr_val >> PAGE_SHIFT, + addr_val & ~PAGE_MASK, + syndrome_val, + cs_val, -1, -1, /* top, mid, low layer */ + mci->ctl_name, drvdata->msg); + } else { + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, + 1, /* error count */ + addr_val >> PAGE_SHIFT, + addr_val & ~PAGE_MASK, + syndrome_val, + cs_val, -1, -1, /* top, mid, low layer */ + mci->ctl_name, drvdata->msg); + } +} + +static void axp_mc_read_config(struct mem_ctl_info *mci) +{ + struct axp_mc_drvdata *drvdata = mci->pvt_info; + uint32_t config, addr_ctrl, rank_ctrl; + unsigned int i, cs_struct, cs_size; + struct dimm_info *dimm; + + config = readl(drvdata->base + SDRAM_CONFIG_REG); + if (config & SDRAM_CONFIG_BUS_WIDTH_MASK) + /* 64 bit */ + drvdata->width = 8; + else + /* 32 bit */ + drvdata->width = 4; + + addr_ctrl = readl(drvdata->base + SDRAM_ADDR_CTRL_REG); + rank_ctrl = readl(drvdata->base + SDRAM_RANK_CTRL_REG); + for (i = 0; i < SDRAM_NUM_CS; i++) { + dimm = mci->dimms[i]; + + if (!(rank_ctrl & SDRAM_RANK_CTRL_EXIST_MASK(i))) + continue; + + drvdata->cs_addr_sel[i] = + !!(addr_ctrl & SDRAM_ADDR_CTRL_ADDR_SEL_MASK(i)); + + cs_struct = (addr_ctrl & SDRAM_ADDR_CTRL_STRUCT_MASK(i)) >> SDRAM_ADDR_CTRL_STRUCT_OFFSET(i); + cs_size = ((addr_ctrl & SDRAM_ADDR_CTRL_SIZE_HIGH_MASK(i)) >> (SDRAM_ADDR_CTRL_SIZE_HIGH_OFFSET(i) - 2) | + ((addr_ctrl & SDRAM_ADDR_CTRL_SIZE_LOW_MASK(i)) >> SDRAM_ADDR_CTRL_SIZE_LOW_OFFSET(i))); + + switch (cs_size) { + case 0: /* 2GBit */ + dimm->nr_pages = 524288; + break; + case 1: /* 256MBit */ + dimm->nr_pages = 65536; + break; + case 2: /* 512MBit */ + dimm->nr_pages = 131072; + break; + case 3: /* 1GBit */ + dimm->nr_pages = 262144; + break; + case 4: /* 4GBit */ + dimm->nr_pages = 1048576; + break; + case 5: /* 8GBit */ + dimm->nr_pages = 2097152; + break; + } + dimm->grain = 8; + dimm->dtype = cs_struct ? DEV_X16 : DEV_X8; + dimm->mtype = (config & SDRAM_CONFIG_REGISTERED_MASK) ? + MEM_RDDR3 : MEM_DDR3; + dimm->edac_mode = EDAC_SECDED; + } +} + +static const struct of_device_id axp_mc_of_match[] = { + {.compatible = "marvell,armada-xp-sdram-controller",}, + {}, +}; +MODULE_DEVICE_TABLE(of, axp_mc_of_match); + +static int axp_mc_probe(struct platform_device *pdev) +{ + struct axp_mc_drvdata *drvdata; + struct edac_mc_layer layers[1]; + const struct of_device_id *id; + struct mem_ctl_info *mci; + struct resource *r; + void __iomem *base; + uint32_t config; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "Unable to get mem resource\n"); + return -ENODEV; + } + + base = devm_ioremap_resource(&pdev->dev, r); + if (IS_ERR(base)) { + dev_err(&pdev->dev, "Unable to map regs\n"); + return PTR_ERR(base); + } + + config = readl(base + SDRAM_CONFIG_REG); + if (!(config & SDRAM_CONFIG_ECC_MASK)) { + dev_warn(&pdev->dev, "SDRAM ECC is not enabled"); + return -EINVAL; + } + + layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; + layers[0].size = SDRAM_NUM_CS; + layers[0].is_virt_csrow = true; + + mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(*drvdata)); + if (!mci) + return -ENOMEM; + + drvdata = mci->pvt_info; + drvdata->base = base; + mci->pdev = &pdev->dev; + platform_set_drvdata(pdev, mci); + + id = of_match_device(axp_mc_of_match, &pdev->dev); + mci->edac_check = axp_mc_check; + mci->mtype_cap = MEM_FLAG_DDR3; + mci->edac_cap = EDAC_FLAG_SECDED; + mci->mod_name = pdev->dev.driver->name; + mci->ctl_name = id ? id->compatible : "unknown"; + mci->dev_name = dev_name(&pdev->dev); + mci->scrub_mode = SCRUB_NONE; + + axp_mc_read_config(mci); + + /* configure SBE threshold */ + /* it seems that SBEs are not captured otherwise */ + writel(1 << SDRAM_ERR_CTRL_THR_OFFSET, drvdata->base + SDRAM_ERR_CTRL_REG); + + /* clear cause registers */ + writel(~(SDRAM_ERR_CAUSE_DBE_MASK | SDRAM_ERR_CAUSE_SBE_MASK), drvdata->base + SDRAM_ERR_CAUSE_ERR_REG); + writel(~(SDRAM_ERR_CAUSE_DBE_MASK | SDRAM_ERR_CAUSE_SBE_MASK), drvdata->base + SDRAM_ERR_CAUSE_MSG_REG); + + /* clear counter registers */ + writel(0, drvdata->base + SDRAM_ERR_SBE_COUNT_REG); + writel(0, drvdata->base + SDRAM_ERR_DBE_COUNT_REG); + + if (edac_mc_add_mc(mci)) { + edac_mc_free(mci); + return -EINVAL; + } + edac_op_state = EDAC_OPSTATE_POLL; + + return 0; +} + +static int axp_mc_remove(struct platform_device *pdev) +{ + struct mem_ctl_info *mci = platform_get_drvdata(pdev); + + edac_mc_del_mc(&pdev->dev); + edac_mc_free(mci); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver axp_mc_driver = { + .probe = axp_mc_probe, + .remove = axp_mc_remove, + .driver = { + .name = "armada_xp_mc_edac", + .of_match_table = of_match_ptr(axp_mc_of_match), + }, +}; + +/************************ EDAC Device (L2 Cache) ***************************/ + +struct aurora_l2_drvdata { + void __iomem *base; + + char msg[128]; + + /* error injection via debugfs */ + uint32_t inject_addr; + uint32_t inject_mask; + uint8_t inject_ctl; + + struct dentry *debugfs; +}; + +#ifdef CONFIG_EDAC_DEBUG +static void aurora_l2_inject(struct aurora_l2_drvdata *drvdata) +{ + drvdata->inject_addr &= AURORA_ERR_INJECT_CTL_ADDR_MASK; + drvdata->inject_ctl &= AURORA_ERR_INJECT_CTL_EN_MASK; + writel(0, drvdata->base + AURORA_ERR_INJECT_CTL_REG); + writel(drvdata->inject_mask, drvdata->base + AURORA_ERR_INJECT_MASK_REG); + writel(drvdata->inject_addr | drvdata->inject_ctl, drvdata->base + AURORA_ERR_INJECT_CTL_REG); +} +#endif + +static void aurora_l2_check(struct edac_device_ctl_info *dci) +{ + struct aurora_l2_drvdata *drvdata = dci->pvt_info; + uint32_t cnt, src, txn, err, attr_cap, addr_cap, way_cap; + unsigned int cnt_ce, cnt_ue; + char *msg = drvdata->msg; + size_t size = sizeof(drvdata->msg); + size_t len = 0; + + cnt = readl(drvdata->base + AURORA_ERR_CNT_REG); + attr_cap = readl(drvdata->base + AURORA_ERR_ATTR_CAP_REG); + addr_cap = readl(drvdata->base + AURORA_ERR_ADDR_CAP_REG); + way_cap = readl(drvdata->base + AURORA_ERR_WAY_CAP_REG); + + cnt_ce = (cnt & AURORA_ERR_CNT_CE_MASK) >> AURORA_ERR_CNT_CE_OFFSET; + cnt_ue = (cnt & AURORA_ERR_CNT_UE_MASK) >> AURORA_ERR_CNT_UE_OFFSET; + /* clear error counter registers */ + if (cnt_ce || cnt_ue) + writel(AURORA_ERR_CNT_CLR, drvdata->base + AURORA_ERR_CNT_REG); + + if (!(attr_cap & AURORA_ERR_ATTR_CAP_VALID)) + goto clear_remaining; + + src = (attr_cap & AURORA_ERR_ATTR_SRC_MSK) >> AURORA_ERR_ATTR_SRC_OFF; + if (src <= 3) + len += snprintf(msg+len, size-len, "src=CPU%d ", src); + else + len += snprintf(msg+len, size-len, "src=IO "); + + txn = (attr_cap & AURORA_ERR_ATTR_TXN_MSK) >> AURORA_ERR_ATTR_TXN_OFF; + switch (txn) { + case 0: + len += snprintf(msg+len, size-len, "txn=Data-Read "); + break; + case 1: + len += snprintf(msg+len, size-len, "txn=Isn-Read "); + break; + case 2: + len += snprintf(msg+len, size-len, "txn=Clean-Flush "); + break; + case 3: + len += snprintf(msg+len, size-len, "txn=Eviction "); + break; + case 4: + len += snprintf(msg+len, size-len, + "txn=Read-Modify-Write "); + break; + } + + err = (attr_cap & AURORA_ERR_ATTR_ERR_MSK) >> AURORA_ERR_ATTR_ERR_OFF; + switch (err) { + case 0: + len += snprintf(msg+len, size-len, "err=CorrECC "); + break; + case 1: + len += snprintf(msg+len, size-len, "err=UnCorrECC "); + break; + case 2: + len += snprintf(msg+len, size-len, "err=TagParity "); + break; + } + + len += snprintf(msg+len, size-len, "addr=0x%x ", addr_cap & AURORA_ERR_ADDR_CAP_ADDR_MASK); + len += snprintf(msg+len, size-len, "index=0x%x ", (way_cap & AURORA_ERR_WAY_IDX_MSK) >> AURORA_ERR_WAY_IDX_OFF); + len += snprintf(msg+len, size-len, "way=0x%x", (way_cap & AURORA_ERR_WAY_CAP_WAY_MASK) >> AURORA_ERR_WAY_CAP_WAY_OFFSET); + + /* clear error capture registers */ + writel(AURORA_ERR_ATTR_CAP_VALID, drvdata->base + AURORA_ERR_ATTR_CAP_REG); + if (err) { + /* UnCorrECC or TagParity */ + if (cnt_ue) + cnt_ue--; + edac_device_handle_ue(dci, 0, 0, drvdata->msg); + } else { + if (cnt_ce) + cnt_ce--; + edac_device_handle_ce(dci, 0, 0, drvdata->msg); + } + +clear_remaining: + /* report remaining errors */ + while (cnt_ue--) + edac_device_handle_ue(dci, 0, 0, "details unavailable (multiple errors)"); + while (cnt_ce--) + edac_device_handle_ue(dci, 0, 0, "details unavailable (multiple errors)"); +} + +static void aurora_l2_poll(struct edac_device_ctl_info *dci) +{ +#ifdef CONFIG_EDAC_DEBUG + struct aurora_l2_drvdata *drvdata = dci->pvt_info; +#endif + + aurora_l2_check(dci); +#ifdef CONFIG_EDAC_DEBUG + aurora_l2_inject(drvdata); +#endif +} + +static const struct of_device_id aurora_l2_of_match[] = { + {.compatible = "marvell,aurora-system-cache",}, + {}, +}; +MODULE_DEVICE_TABLE(of, aurora_l2_of_match); + +static int aurora_l2_probe(struct platform_device *pdev) +{ + struct aurora_l2_drvdata *drvdata; + struct edac_device_ctl_info *dci; + const struct of_device_id *id; + uint32_t l2x0_aux_ctrl; + void __iomem *base; + struct resource *r; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "Unable to get mem resource\n"); + return -ENODEV; + } + + base = devm_ioremap_resource(&pdev->dev, r); + if (IS_ERR(base)) { + dev_err(&pdev->dev, "Unable to map regs\n"); + return PTR_ERR(base); + } + + l2x0_aux_ctrl = readl(base + L2X0_AUX_CTRL); + if (!(l2x0_aux_ctrl & AURORA_ACR_PARITY_EN)) + dev_warn(&pdev->dev, "tag parity is not enabled"); + if (!(l2x0_aux_ctrl & AURORA_ACR_ECC_EN)) + dev_warn(&pdev->dev, "data ECC is not enabled"); + + dci = edac_device_alloc_ctl_info(sizeof(*drvdata), + "cpu", 1, "L", 1, 2, NULL, 0, 0); + if (!dci) + return -ENOMEM; + + drvdata = dci->pvt_info; + drvdata->base = base; + dci->dev = &pdev->dev; + platform_set_drvdata(pdev, dci); + + id = of_match_device(aurora_l2_of_match, &pdev->dev); + dci->edac_check = aurora_l2_poll; + dci->mod_name = pdev->dev.driver->name; + dci->ctl_name = id ? id->compatible : "unknown"; + dci->dev_name = dev_name(&pdev->dev); + + /* clear registers */ + writel(AURORA_ERR_CNT_CLR, drvdata->base + AURORA_ERR_CNT_REG); + writel(AURORA_ERR_ATTR_CAP_VALID, drvdata->base + AURORA_ERR_ATTR_CAP_REG); + + if (edac_device_add_device(dci)) { + edac_device_free_ctl_info(dci); + return -EINVAL; + } + +#ifdef CONFIG_EDAC_DEBUG + drvdata->debugfs = edac_debugfs_create_dir(dev_name(&pdev->dev)); + if (drvdata->debugfs) { + edac_debugfs_create_x32("inject_addr", 0644, + drvdata->debugfs, + &drvdata->inject_addr); + edac_debugfs_create_x32("inject_mask", 0644, + drvdata->debugfs, + &drvdata->inject_mask); + edac_debugfs_create_x8("inject_ctl", 0644, + drvdata->debugfs, &drvdata->inject_ctl); + } +#endif + + return 0; +} + +static int aurora_l2_remove(struct platform_device *pdev) +{ + struct edac_device_ctl_info *dci = platform_get_drvdata(pdev); +#ifdef CONFIG_EDAC_DEBUG + struct aurora_l2_drvdata *drvdata = dci->pvt_info; + + edac_debugfs_remove_recursive(drvdata->debugfs); +#endif + edac_device_del_device(&pdev->dev); + edac_device_free_ctl_info(dci); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver aurora_l2_driver = { + .probe = aurora_l2_probe, + .remove = aurora_l2_remove, + .driver = { + .name = "aurora_l2_edac", + .of_match_table = of_match_ptr(aurora_l2_of_match), + }, +}; + +/************************ Driver registration ******************************/ + +static struct platform_driver * const drivers[] = { + &axp_mc_driver, + &aurora_l2_driver, +}; + +static int __init armada_xp_edac_init(void) +{ + int res; + + /* only polling is supported */ + edac_op_state = EDAC_OPSTATE_POLL; + + res = platform_register_drivers(drivers, ARRAY_SIZE(drivers)); + if (res) + pr_warn("Aramda XP EDAC drivers fail to register\n"); + + return 0; +} +module_init(armada_xp_edac_init); + +static void __exit armada_xp_edac_exit(void) +{ + platform_unregister_drivers(drivers, ARRAY_SIZE(drivers)); +} +module_exit(armada_xp_edac_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Pengutronix"); +MODULE_DESCRIPTION("EDAC Drivers for Marvell Armada XP SDRAM and L2 Cache Controller"); ^ permalink raw reply related [flat|nested] 48+ messages in thread
* Re: [PATCH v6 8/9] EDAC: Add driver for the Marvell Armada XP SDRAM and L2 cache ECC @ 2018-11-11 19:40 ` Borislav Petkov 0 siblings, 0 replies; 48+ messages in thread From: Borislav Petkov @ 2018-11-11 19:40 UTC (permalink / raw) To: Chris Packham Cc: linux, arnd, jlu, gregory.clement, linux-arm-kernel, devicetree, linux-edac, linux-kernel, Mauro Carvalho Chehab On Fri, Nov 09, 2018 at 08:03:48PM +1300, Chris Packham wrote: > From: Jan Luebbe <jlu@pengutronix.de> > > Add support for the ECC functionality as found in the DDR RAM and L2 > cache controllers on the MV78230/MV78x60 SoCs. This driver has been > tested on the MV78460 (on a custom board with a DDR3 ECC DIMM). > > Signed-off-by: Jan Luebbe <jlu@pengutronix.de> > [cp use SPDX license] > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> > --- > MAINTAINERS | 6 + > drivers/edac/Kconfig | 7 + > drivers/edac/Makefile | 1 + > drivers/edac/armada_xp_edac.c | 630 ++++++++++++++++++++++++++++++++++ > 4 files changed, 644 insertions(+) > create mode 100644 drivers/edac/armada_xp_edac.c Looks ok at a glance. Those overly long lines could use some macros or breaking but it is not a big deal: Reviewed-by: Borislav Petkov <bp@suse.de> -- Regards/Gruss, Boris. Good mailing practices for 400: avoid top-posting and trim the reply. ^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v6 8/9] EDAC: Add driver for the Marvell Armada XP SDRAM and L2 cache ECC @ 2018-11-11 19:40 ` Borislav Petkov 0 siblings, 0 replies; 48+ messages in thread From: Borislav Petkov @ 2018-11-11 19:40 UTC (permalink / raw) To: linux-arm-kernel On Fri, Nov 09, 2018 at 08:03:48PM +1300, Chris Packham wrote: > From: Jan Luebbe <jlu@pengutronix.de> > > Add support for the ECC functionality as found in the DDR RAM and L2 > cache controllers on the MV78230/MV78x60 SoCs. This driver has been > tested on the MV78460 (on a custom board with a DDR3 ECC DIMM). > > Signed-off-by: Jan Luebbe <jlu@pengutronix.de> > [cp use SPDX license] > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> > --- > MAINTAINERS | 6 + > drivers/edac/Kconfig | 7 + > drivers/edac/Makefile | 1 + > drivers/edac/armada_xp_edac.c | 630 ++++++++++++++++++++++++++++++++++ > 4 files changed, 644 insertions(+) > create mode 100644 drivers/edac/armada_xp_edac.c Looks ok at a glance. Those overly long lines could use some macros or breaking but it is not a big deal: Reviewed-by: Borislav Petkov <bp@suse.de> -- Regards/Gruss, Boris. Good mailing practices for 400: avoid top-posting and trim the reply. ^ permalink raw reply [flat|nested] 48+ messages in thread
* [v6,8/9] EDAC: Add driver for the Marvell Armada XP SDRAM and L2 cache ECC @ 2018-11-11 19:40 ` Borislav Petkov 0 siblings, 0 replies; 48+ messages in thread From: Borislav Petkov @ 2018-11-11 19:40 UTC (permalink / raw) To: Chris Packham Cc: linux, arnd, jlu, gregory.clement, linux-arm-kernel, devicetree, linux-edac, linux-kernel, Mauro Carvalho Chehab On Fri, Nov 09, 2018 at 08:03:48PM +1300, Chris Packham wrote: > From: Jan Luebbe <jlu@pengutronix.de> > > Add support for the ECC functionality as found in the DDR RAM and L2 > cache controllers on the MV78230/MV78x60 SoCs. This driver has been > tested on the MV78460 (on a custom board with a DDR3 ECC DIMM). > > Signed-off-by: Jan Luebbe <jlu@pengutronix.de> > [cp use SPDX license] > Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> > --- > MAINTAINERS | 6 + > drivers/edac/Kconfig | 7 + > drivers/edac/Makefile | 1 + > drivers/edac/armada_xp_edac.c | 630 ++++++++++++++++++++++++++++++++++ > 4 files changed, 644 insertions(+) > create mode 100644 drivers/edac/armada_xp_edac.c Looks ok at a glance. Those overly long lines could use some macros or breaking but it is not a big deal: Reviewed-by: Borislav Petkov <bp@suse.de> ^ permalink raw reply [flat|nested] 48+ messages in thread
* [PATCH v6 9/9] EDAC: armada_xp: Add support for more SoCs @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham, Mauro Carvalho Chehab The Armada 38x and other integrated SoCs use a reduced pin count so the width of the SDRAM interface is smaller than the Armada XP SoCs. This means that the definition of "full" and "half" width is reduced from 64/32 to 32/16. Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- drivers/edac/armada_xp_edac.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/edac/armada_xp_edac.c b/drivers/edac/armada_xp_edac.c index 3759a4fbbdee..7f227bdcbc84 100644 --- a/drivers/edac/armada_xp_edac.c +++ b/drivers/edac/armada_xp_edac.c @@ -332,6 +332,11 @@ static int axp_mc_probe(struct platform_device *pdev) axp_mc_read_config(mci); + /* These SoCs have a reduced width bus */ + if (of_machine_is_compatible("marvell,armada380") || + of_machine_is_compatible("marvell,armadaxp-98dx3236")) + drvdata->width /= 2; + /* configure SBE threshold */ /* it seems that SBEs are not captured otherwise */ writel(1 << SDRAM_ERR_CTRL_THR_OFFSET, drvdata->base + SDRAM_ERR_CTRL_REG); -- 2.19.1 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [PATCH v6 9/9] EDAC: armada_xp: Add support for more SoCs @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux-arm-kernel The Armada 38x and other integrated SoCs use a reduced pin count so the width of the SDRAM interface is smaller than the Armada XP SoCs. This means that the definition of "full" and "half" width is reduced from 64/32 to 32/16. Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- drivers/edac/armada_xp_edac.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/edac/armada_xp_edac.c b/drivers/edac/armada_xp_edac.c index 3759a4fbbdee..7f227bdcbc84 100644 --- a/drivers/edac/armada_xp_edac.c +++ b/drivers/edac/armada_xp_edac.c @@ -332,6 +332,11 @@ static int axp_mc_probe(struct platform_device *pdev) axp_mc_read_config(mci); + /* These SoCs have a reduced width bus */ + if (of_machine_is_compatible("marvell,armada380") || + of_machine_is_compatible("marvell,armadaxp-98dx3236")) + drvdata->width /= 2; + /* configure SBE threshold */ /* it seems that SBEs are not captured otherwise */ writel(1 << SDRAM_ERR_CTRL_THR_OFFSET, drvdata->base + SDRAM_ERR_CTRL_REG); -- 2.19.1 ^ permalink raw reply related [flat|nested] 48+ messages in thread
* [v6,9/9] EDAC: armada_xp: Add support for more SoCs @ 2018-11-09 7:03 ` Chris Packham 0 siblings, 0 replies; 48+ messages in thread From: Chris Packham @ 2018-11-09 7:03 UTC (permalink / raw) To: linux, bp, arnd, jlu, gregory.clement Cc: linux-arm-kernel, devicetree, linux-edac, linux-kernel, Chris Packham, Mauro Carvalho Chehab The Armada 38x and other integrated SoCs use a reduced pin count so the width of the SDRAM interface is smaller than the Armada XP SoCs. This means that the definition of "full" and "half" width is reduced from 64/32 to 32/16. Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz> --- drivers/edac/armada_xp_edac.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/edac/armada_xp_edac.c b/drivers/edac/armada_xp_edac.c index 3759a4fbbdee..7f227bdcbc84 100644 --- a/drivers/edac/armada_xp_edac.c +++ b/drivers/edac/armada_xp_edac.c @@ -332,6 +332,11 @@ static int axp_mc_probe(struct platform_device *pdev) axp_mc_read_config(mci); + /* These SoCs have a reduced width bus */ + if (of_machine_is_compatible("marvell,armada380") || + of_machine_is_compatible("marvell,armadaxp-98dx3236")) + drvdata->width /= 2; + /* configure SBE threshold */ /* it seems that SBEs are not captured otherwise */ writel(1 << SDRAM_ERR_CTRL_THR_OFFSET, drvdata->base + SDRAM_ERR_CTRL_REG); ^ permalink raw reply related [flat|nested] 48+ messages in thread
end of thread, other threads:[~2018-11-11 22:35 UTC | newest] Thread overview: 48+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-11-09 7:03 [PATCH v6 0/9] EDAC drivers for Armada XP L2 and DDR Chris Packham 2018-11-09 7:03 ` Chris Packham 2018-11-09 7:03 ` [PATCH v6 1/9] ARM: l2c: move cache-aurora-l2.h to asm/hardware Chris Packham 2018-11-09 7:03 ` Chris Packham 2018-11-09 7:03 ` [v6,1/9] " Chris Packham 2018-11-09 7:03 ` [PATCH v6 2/9] ARM: aurora-l2: add prefix to MAX_RANGE_SIZE Chris Packham 2018-11-09 7:03 ` Chris Packham 2018-11-09 7:03 ` [v6,2/9] " Chris Packham 2018-11-09 7:03 ` [PATCH v6 3/9] ARM: aurora-l2: add defines for parity and ECC registers Chris Packham 2018-11-09 7:03 ` Chris Packham 2018-11-09 7:03 ` [v6,3/9] " Chris Packham 2018-11-09 7:03 ` [PATCH v6 4/9] ARM: l2x0: support parity-enable/disable on aurora Chris Packham 2018-11-09 7:03 ` Chris Packham 2018-11-09 7:03 ` [v6,4/9] " Chris Packham 2018-11-09 7:03 ` [PATCH v6 5/9] dt-bindings: ARM: document marvell,ecc-enable binding Chris Packham 2018-11-09 7:03 ` Chris Packham 2018-11-09 7:03 ` [v6,5/9] " Chris Packham 2018-11-09 11:40 ` [PATCH v6 5/9] " Arnd Bergmann 2018-11-09 11:40 ` [PATCH v6 5/9] dt-bindings: ARM: document marvell, ecc-enable binding Arnd Bergmann 2018-11-09 11:40 ` [v6,5/9] dt-bindings: ARM: document marvell,ecc-enable binding Arnd Bergmann 2018-11-09 11:48 ` [PATCH v6 5/9] " Russell King - ARM Linux 2018-11-09 11:48 ` Russell King - ARM Linux 2018-11-09 11:48 ` [v6,5/9] " Russell King - ARM Linux 2018-11-09 15:58 ` [PATCH v6 5/9] " Arnd Bergmann 2018-11-09 15:58 ` [PATCH v6 5/9] dt-bindings: ARM: document marvell, ecc-enable binding Arnd Bergmann 2018-11-09 15:58 ` [v6,5/9] dt-bindings: ARM: document marvell,ecc-enable binding Arnd Bergmann 2018-11-11 19:57 ` [PATCH v6 5/9] " Chris Packham 2018-11-11 19:57 ` Chris Packham 2018-11-11 19:57 ` [v6,5/9] " Chris Packham 2018-11-11 22:35 ` [PATCH v6 5/9] " Rob Herring 2018-11-11 22:35 ` Rob Herring 2018-11-11 22:35 ` Rob Herring 2018-11-11 22:35 ` [v6,5/9] " Rob Herring 2018-11-09 7:03 ` [PATCH v6 6/9] ARM: l2x0: add marvell,ecc-enable property for aurora Chris Packham 2018-11-09 7:03 ` Chris Packham 2018-11-09 7:03 ` [v6,6/9] " Chris Packham 2018-11-09 7:03 ` [PATCH v6 7/9] EDAC: Add missing debugfs_create_x32 wrapper Chris Packham 2018-11-09 7:03 ` Chris Packham 2018-11-09 7:03 ` [v6,7/9] " Chris Packham 2018-11-09 7:03 ` [PATCH v6 8/9] EDAC: Add driver for the Marvell Armada XP SDRAM and L2 cache ECC Chris Packham 2018-11-09 7:03 ` Chris Packham 2018-11-09 7:03 ` [v6,8/9] " Chris Packham 2018-11-11 19:40 ` [PATCH v6 8/9] " Borislav Petkov 2018-11-11 19:40 ` Borislav Petkov 2018-11-11 19:40 ` [v6,8/9] " Borislav Petkov 2018-11-09 7:03 ` [PATCH v6 9/9] EDAC: armada_xp: Add support for more SoCs Chris Packham 2018-11-09 7:03 ` Chris Packham 2018-11-09 7:03 ` [v6,9/9] " Chris Packham
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.