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

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
......@@ -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)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment