Commit 4bcffe94 authored by Sherry Sun's avatar Sherry Sun Committed by Borislav Petkov
Browse files

EDAC/synopsys: Re-enable the error interrupts on v3 hw



zynqmp_get_error_info() writes 0 to the ECC_CLR_OFST register after
an interrupt for a {un-,}correctable error is raised, which disables
the error interrupts. Then the interrupt handler will be called only
once. Therefore, re-enable the error interrupt line at the end of
intr_handler() for v3.x Synopsys EDAC DDR.

Fixes: f7824ded ("EDAC/synopsys: Add support for version 3 of the Synopsys EDAC DDR")
Signed-off-by: default avatarSherry Sun <sherry.sun@nxp.com>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Reviewed-by: default avatarShubhrajyoti Datta <Shubhrajyoti.datta@xilinx.com>
Acked-by: default avatarMichal Simek <michal.simek@xilinx.com>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20220427015137.8406-3-sherry.sun@nxp.com
parent be76ceaf
Loading
Loading
Loading
Loading
+25 −22
Original line number Diff line number Diff line
@@ -514,6 +514,28 @@ static void handle_error(struct mem_ctl_info *mci, struct synps_ecc_status *p)
	memset(p, 0, sizeof(*p));
}

static void enable_intr(struct synps_edac_priv *priv)
{
	/* Enable UE/CE Interrupts */
	if (priv->p_data->quirks & DDR_ECC_INTR_SELF_CLEAR)
		writel(DDR_UE_MASK | DDR_CE_MASK,
		       priv->baseaddr + ECC_CLR_OFST);
	else
		writel(DDR_QOSUE_MASK | DDR_QOSCE_MASK,
		       priv->baseaddr + DDR_QOS_IRQ_EN_OFST);

}

static void disable_intr(struct synps_edac_priv *priv)
{
	/* Disable UE/CE Interrupts */
	if (priv->p_data->quirks & DDR_ECC_INTR_SELF_CLEAR)
		writel(0x0, priv->baseaddr + ECC_CLR_OFST);
	else
		writel(DDR_QOSUE_MASK | DDR_QOSCE_MASK,
		       priv->baseaddr + DDR_QOS_IRQ_DB_OFST);
}

/**
 * intr_handler - Interrupt Handler for ECC interrupts.
 * @irq:        IRQ number.
@@ -555,6 +577,9 @@ static irqreturn_t intr_handler(int irq, void *dev_id)
	/* v3.0 of the controller does not have this register */
	if (!(priv->p_data->quirks & DDR_ECC_INTR_SELF_CLEAR))
		writel(regval, priv->baseaddr + DDR_QOS_IRQ_STAT_OFST);
	else
		enable_intr(priv);

	return IRQ_HANDLED;
}

@@ -837,28 +862,6 @@ static void mc_init(struct mem_ctl_info *mci, struct platform_device *pdev)
	init_csrows(mci);
}

static void enable_intr(struct synps_edac_priv *priv)
{
	/* Enable UE/CE Interrupts */
	if (priv->p_data->quirks & DDR_ECC_INTR_SELF_CLEAR)
		writel(DDR_UE_MASK | DDR_CE_MASK,
		       priv->baseaddr + ECC_CLR_OFST);
	else
		writel(DDR_QOSUE_MASK | DDR_QOSCE_MASK,
		       priv->baseaddr + DDR_QOS_IRQ_EN_OFST);

}

static void disable_intr(struct synps_edac_priv *priv)
{
	/* Disable UE/CE Interrupts */
	if (priv->p_data->quirks & DDR_ECC_INTR_SELF_CLEAR)
		writel(0x0, priv->baseaddr + ECC_CLR_OFST);
	else
		writel(DDR_QOSUE_MASK | DDR_QOSCE_MASK,
		       priv->baseaddr + DDR_QOS_IRQ_DB_OFST);
}

static int setup_irq(struct mem_ctl_info *mci,
		     struct platform_device *pdev)
{