Skip to content

Commit b1dc7f0

Browse files
shubhraamdbp3tk0v
authored andcommitted
EDAC/synopsys: Clear the ECC counters on init
Clear the ECC error and counter registers during initialization/probe to avoid reporting stale errors that may have occurred before EDAC registration. For that, unify the Zynq and ZynqMP ECC state reading paths and simplify the code. [ bp: Massage commit message. Fix an -Wsometimes-uninitialized warning as reported by Reported-by: kernel test robot <[email protected]> Closes: https://lore.kernel.org/oe-kbuild-all/[email protected] ] Signed-off-by: Shubhrajyoti Datta <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Link: https://lore.kernel.org/[email protected]
1 parent 05a61c6 commit b1dc7f0

File tree

1 file changed

+46
-51
lines changed

1 file changed

+46
-51
lines changed

drivers/edac/synopsys_edac.c

Lines changed: 46 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -332,20 +332,26 @@ struct synps_edac_priv {
332332
#endif
333333
};
334334

335+
enum synps_platform_type {
336+
ZYNQ,
337+
ZYNQMP,
338+
SYNPS,
339+
};
340+
335341
/**
336342
* struct synps_platform_data - synps platform data structure.
343+
* @platform: Identifies the target hardware platform
337344
* @get_error_info: Get EDAC error info.
338345
* @get_mtype: Get mtype.
339346
* @get_dtype: Get dtype.
340-
* @get_ecc_state: Get ECC state.
341347
* @get_mem_info: Get EDAC memory info
342348
* @quirks: To differentiate IPs.
343349
*/
344350
struct synps_platform_data {
351+
enum synps_platform_type platform;
345352
int (*get_error_info)(struct synps_edac_priv *priv);
346353
enum mem_type (*get_mtype)(const void __iomem *base);
347354
enum dev_type (*get_dtype)(const void __iomem *base);
348-
bool (*get_ecc_state)(void __iomem *base);
349355
#ifdef CONFIG_EDAC_DEBUG
350356
u64 (*get_mem_info)(struct synps_edac_priv *priv);
351357
#endif
@@ -720,51 +726,38 @@ static enum dev_type zynqmp_get_dtype(const void __iomem *base)
720726
return dt;
721727
}
722728

723-
/**
724-
* zynq_get_ecc_state - Return the controller ECC enable/disable status.
725-
* @base: DDR memory controller base address.
726-
*
727-
* Get the ECC enable/disable status of the controller.
728-
*
729-
* Return: true if enabled, otherwise false.
730-
*/
731-
static bool zynq_get_ecc_state(void __iomem *base)
729+
static bool get_ecc_state(struct synps_edac_priv *priv)
732730
{
731+
u32 ecctype, clearval;
733732
enum dev_type dt;
734-
u32 ecctype;
735-
736-
dt = zynq_get_dtype(base);
737-
if (dt == DEV_UNKNOWN)
738-
return false;
739733

740-
ecctype = readl(base + SCRUB_OFST) & SCRUB_MODE_MASK;
741-
if ((ecctype == SCRUB_MODE_SECDED) && (dt == DEV_X2))
742-
return true;
743-
744-
return false;
745-
}
746-
747-
/**
748-
* zynqmp_get_ecc_state - Return the controller ECC enable/disable status.
749-
* @base: DDR memory controller base address.
750-
*
751-
* Get the ECC enable/disable status for the controller.
752-
*
753-
* Return: a ECC status boolean i.e true/false - enabled/disabled.
754-
*/
755-
static bool zynqmp_get_ecc_state(void __iomem *base)
756-
{
757-
enum dev_type dt;
758-
u32 ecctype;
759-
760-
dt = zynqmp_get_dtype(base);
761-
if (dt == DEV_UNKNOWN)
762-
return false;
763-
764-
ecctype = readl(base + ECC_CFG0_OFST) & SCRUB_MODE_MASK;
765-
if ((ecctype == SCRUB_MODE_SECDED) &&
766-
((dt == DEV_X2) || (dt == DEV_X4) || (dt == DEV_X8)))
767-
return true;
734+
if (priv->p_data->platform == ZYNQ) {
735+
dt = zynq_get_dtype(priv->baseaddr);
736+
if (dt == DEV_UNKNOWN)
737+
return false;
738+
739+
ecctype = readl(priv->baseaddr + SCRUB_OFST) & SCRUB_MODE_MASK;
740+
if (ecctype == SCRUB_MODE_SECDED && dt == DEV_X2) {
741+
clearval = ECC_CTRL_CLR_CE_ERR | ECC_CTRL_CLR_UE_ERR;
742+
writel(clearval, priv->baseaddr + ECC_CTRL_OFST);
743+
writel(0x0, priv->baseaddr + ECC_CTRL_OFST);
744+
return true;
745+
}
746+
} else {
747+
dt = zynqmp_get_dtype(priv->baseaddr);
748+
if (dt == DEV_UNKNOWN)
749+
return false;
750+
751+
ecctype = readl(priv->baseaddr + ECC_CFG0_OFST) & SCRUB_MODE_MASK;
752+
if (ecctype == SCRUB_MODE_SECDED &&
753+
(dt == DEV_X2 || dt == DEV_X4 || dt == DEV_X8)) {
754+
clearval = readl(priv->baseaddr + ECC_CLR_OFST) |
755+
ECC_CTRL_CLR_CE_ERR | ECC_CTRL_CLR_CE_ERRCNT |
756+
ECC_CTRL_CLR_UE_ERR | ECC_CTRL_CLR_UE_ERRCNT;
757+
writel(clearval, priv->baseaddr + ECC_CLR_OFST);
758+
return true;
759+
}
760+
}
768761

769762
return false;
770763
}
@@ -934,18 +927,18 @@ static int setup_irq(struct mem_ctl_info *mci,
934927
}
935928

936929
static const struct synps_platform_data zynq_edac_def = {
930+
.platform = ZYNQ,
937931
.get_error_info = zynq_get_error_info,
938932
.get_mtype = zynq_get_mtype,
939933
.get_dtype = zynq_get_dtype,
940-
.get_ecc_state = zynq_get_ecc_state,
941934
.quirks = 0,
942935
};
943936

944937
static const struct synps_platform_data zynqmp_edac_def = {
938+
.platform = ZYNQMP,
945939
.get_error_info = zynqmp_get_error_info,
946940
.get_mtype = zynqmp_get_mtype,
947941
.get_dtype = zynqmp_get_dtype,
948-
.get_ecc_state = zynqmp_get_ecc_state,
949942
#ifdef CONFIG_EDAC_DEBUG
950943
.get_mem_info = zynqmp_get_mem_info,
951944
#endif
@@ -957,10 +950,10 @@ static const struct synps_platform_data zynqmp_edac_def = {
957950
};
958951

959952
static const struct synps_platform_data synopsys_edac_def = {
953+
.platform = SYNPS,
960954
.get_error_info = zynqmp_get_error_info,
961955
.get_mtype = zynqmp_get_mtype,
962956
.get_dtype = zynqmp_get_dtype,
963-
.get_ecc_state = zynqmp_get_ecc_state,
964957
.quirks = (DDR_ECC_INTR_SUPPORT | DDR_ECC_INTR_SELF_CLEAR
965958
#ifdef CONFIG_EDAC_DEBUG
966959
| DDR_ECC_DATA_POISON_SUPPORT
@@ -1390,10 +1383,6 @@ static int mc_probe(struct platform_device *pdev)
13901383
if (!p_data)
13911384
return -ENODEV;
13921385

1393-
if (!p_data->get_ecc_state(baseaddr)) {
1394-
edac_printk(KERN_INFO, EDAC_MC, "ECC not enabled\n");
1395-
return -ENXIO;
1396-
}
13971386

13981387
layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
13991388
layers[0].size = SYNPS_EDAC_NR_CSROWS;
@@ -1413,6 +1402,12 @@ static int mc_probe(struct platform_device *pdev)
14131402
priv = mci->pvt_info;
14141403
priv->baseaddr = baseaddr;
14151404
priv->p_data = p_data;
1405+
if (!get_ecc_state(priv)) {
1406+
edac_printk(KERN_INFO, EDAC_MC, "ECC not enabled\n");
1407+
rc = -ENODEV;
1408+
goto free_edac_mc;
1409+
}
1410+
14161411
spin_lock_init(&priv->reglock);
14171412

14181413
mc_init(mci, pdev);

0 commit comments

Comments
 (0)