Skip to content

Commit f7824de

Browse files
Dinh Nguyensuryasaimadhu
authored andcommitted
EDAC/synopsys: Add support for version 3 of the Synopsys EDAC DDR
Add support for version 3.80a of the Synopsys DDR controller. This version of the controller has the following differences: - UE/CE are auto cleared - Interrupts are supported by default Signed-off-by: Dinh Nguyen <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Reviewed-by: Michal Simek <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent bd1d6da commit f7824de

File tree

1 file changed

+42
-7
lines changed

1 file changed

+42
-7
lines changed

drivers/edac/synopsys_edac.c

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
/* DDR ECC Quirks */
102102
#define DDR_ECC_INTR_SUPPORT BIT(0)
103103
#define DDR_ECC_DATA_POISON_SUPPORT BIT(1)
104+
#define DDR_ECC_INTR_SELF_CLEAR BIT(2)
104105

105106
/* ZynqMP Enhanced DDR memory controller registers that are relevant to ECC */
106107
/* ECC Configuration Registers */
@@ -171,6 +172,10 @@
171172
#define DDR_QOS_IRQ_EN_OFST 0x20208
172173
#define DDR_QOS_IRQ_DB_OFST 0x2020C
173174

175+
/* DDR QOS Interrupt register definitions */
176+
#define DDR_UE_MASK BIT(9)
177+
#define DDR_CE_MASK BIT(8)
178+
174179
/* ECC Corrected Error Register Mask and Shifts*/
175180
#define ECC_CEADDR0_RW_MASK 0x3FFFF
176181
#define ECC_CEADDR0_RNK_MASK BIT(24)
@@ -533,10 +538,16 @@ static irqreturn_t intr_handler(int irq, void *dev_id)
533538
priv = mci->pvt_info;
534539
p_data = priv->p_data;
535540

536-
regval = readl(priv->baseaddr + DDR_QOS_IRQ_STAT_OFST);
537-
regval &= (DDR_QOSCE_MASK | DDR_QOSUE_MASK);
538-
if (!(regval & ECC_CE_UE_INTR_MASK))
539-
return IRQ_NONE;
541+
/*
542+
* v3.0 of the controller has the ce/ue bits cleared automatically,
543+
* so this condition does not apply.
544+
*/
545+
if (!(priv->p_data->quirks & DDR_ECC_INTR_SELF_CLEAR)) {
546+
regval = readl(priv->baseaddr + DDR_QOS_IRQ_STAT_OFST);
547+
regval &= (DDR_QOSCE_MASK | DDR_QOSUE_MASK);
548+
if (!(regval & ECC_CE_UE_INTR_MASK))
549+
return IRQ_NONE;
550+
}
540551

541552
status = p_data->get_error_info(priv);
542553
if (status)
@@ -548,7 +559,9 @@ static irqreturn_t intr_handler(int irq, void *dev_id)
548559

549560
edac_dbg(3, "Total error count CE %d UE %d\n",
550561
priv->ce_cnt, priv->ue_cnt);
551-
writel(regval, priv->baseaddr + DDR_QOS_IRQ_STAT_OFST);
562+
/* v3.0 of the controller does not have this register */
563+
if (!(priv->p_data->quirks & DDR_ECC_INTR_SELF_CLEAR))
564+
writel(regval, priv->baseaddr + DDR_QOS_IRQ_STAT_OFST);
552565
return IRQ_HANDLED;
553566
}
554567

@@ -834,8 +847,13 @@ static void mc_init(struct mem_ctl_info *mci, struct platform_device *pdev)
834847
static void enable_intr(struct synps_edac_priv *priv)
835848
{
836849
/* Enable UE/CE Interrupts */
837-
writel(DDR_QOSUE_MASK | DDR_QOSCE_MASK,
838-
priv->baseaddr + DDR_QOS_IRQ_EN_OFST);
850+
if (priv->p_data->quirks & DDR_ECC_INTR_SELF_CLEAR)
851+
writel(DDR_UE_MASK | DDR_CE_MASK,
852+
priv->baseaddr + ECC_CLR_OFST);
853+
else
854+
writel(DDR_QOSUE_MASK | DDR_QOSCE_MASK,
855+
priv->baseaddr + DDR_QOS_IRQ_EN_OFST);
856+
839857
}
840858

841859
static void disable_intr(struct synps_edac_priv *priv)
@@ -890,6 +908,19 @@ static const struct synps_platform_data zynqmp_edac_def = {
890908
),
891909
};
892910

911+
static const struct synps_platform_data synopsys_edac_def = {
912+
.get_error_info = zynqmp_get_error_info,
913+
.get_mtype = zynqmp_get_mtype,
914+
.get_dtype = zynqmp_get_dtype,
915+
.get_ecc_state = zynqmp_get_ecc_state,
916+
.quirks = (DDR_ECC_INTR_SUPPORT | DDR_ECC_INTR_SELF_CLEAR
917+
#ifdef CONFIG_EDAC_DEBUG
918+
| DDR_ECC_DATA_POISON_SUPPORT
919+
#endif
920+
),
921+
};
922+
923+
893924
static const struct of_device_id synps_edac_match[] = {
894925
{
895926
.compatible = "xlnx,zynq-ddrc-a05",
@@ -899,6 +930,10 @@ static const struct of_device_id synps_edac_match[] = {
899930
.compatible = "xlnx,zynqmp-ddrc-2.40a",
900931
.data = (void *)&zynqmp_edac_def
901932
},
933+
{
934+
.compatible = "snps,ddrc-3.80a",
935+
.data = (void *)&synopsys_edac_def
936+
},
902937
{
903938
/* end of table */
904939
}

0 commit comments

Comments
 (0)