diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index 6a47e53deab5..8d8952826bce 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -80,6 +80,12 @@
 #define ECC_POISON0_OFST		0xB8
 #define ECC_POISON1_OFST		0xBC
 
+/* DDR CRC/Parity register */
+#define DDR_CRCPARCTL0_OFST		0xC0
+#define DDR_CRCPARCTL1_OFST		0xC4
+#define DDR_CRCPARCTL2_OFST		0xC8
+#define DDR_CRCPARSTAT_OFST		0xCC
+
 /* DDR Address map0 Registers */
 #define DDR_ADDRMAP0_OFST		0x200
 
@@ -153,6 +159,13 @@
 #define ECC_CEADDR1_BANK_MASK		GENMASK(23, 16)
 #define ECC_CEADDR1_COL_MASK		GENMASK(11, 0)
 
+/* DDR CRC/Parity register definitions */
+#define DDR_CRCPARCTL0_CLR_ALRT_ERRCNT	BIT(2)
+#define DDR_CRCPARCTL0_CLR_ALRT_ERR	BIT(1)
+#define DDR_CRCPARCTL0_EN_ALRT_IRQ	BIT(0)
+#define DDR_CRCPARSTAT_ALRT_ERR		BIT(16)
+#define DDR_CRCPARSTAT_ALRT_CNT_MASK	GENMASK(15, 0)
+
 /* ECC Poison register shifts */
 #define ECC_POISON0_RANK_MASK		GENMASK(27, 24)
 #define ECC_POISON0_COL_MASK		GENMASK(11, 0)
@@ -829,6 +842,48 @@ static irqreturn_t snps_ue_irq_handler(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+/**
+ * snps_dfi_irq_handler - DFI CRC/Parity error interrupt handler.
+ * @irq:        IRQ number.
+ * @dev_id:     Device ID.
+ *
+ * Return: IRQ_NONE, if interrupt not set or IRQ_HANDLED otherwise.
+ */
+static irqreturn_t snps_dfi_irq_handler(int irq, void *dev_id)
+{
+	struct mem_ctl_info *mci = dev_id;
+	struct snps_edac_priv *priv = mci->pvt_info;
+	unsigned long flags;
+	u32 regval;
+	u16 ecnt;
+
+	/* Make sure IRQ is caused by an DFI alert error */
+	regval = readl(priv->baseaddr + DDR_CRCPARSTAT_OFST);
+	if (!(regval & DDR_CRCPARSTAT_ALRT_ERR))
+		return IRQ_NONE;
+
+	/* Just a number of CRC/Parity errors is available */
+	ecnt = FIELD_GET(DDR_CRCPARSTAT_ALRT_CNT_MASK, regval);
+
+	/* Report the detected errors with just the custom message */
+	snprintf(priv->message, SNPS_EDAC_MSG_SIZE,
+		 "DFI CRC/Parity error detected on dfi_alert_n");
+
+	edac_mc_handle_error(HW_EVENT_ERR_FATAL, mci, ecnt,
+			     0, 0, 0, 0, 0, -1, priv->message, "");
+
+	/* Make sure the DFI alert IRQ status is cleared */
+	spin_lock_irqsave(&priv->lock, flags);
+
+	regval = readl(priv->baseaddr + DDR_CRCPARCTL0_OFST) |
+		 DDR_CRCPARCTL0_CLR_ALRT_ERR | DDR_CRCPARCTL0_CLR_ALRT_ERRCNT;
+	writel(regval, priv->baseaddr + DDR_CRCPARCTL0_OFST);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return IRQ_HANDLED;
+}
+
 /**
  * snps_com_irq_handler - Interrupt IRQ signal handler.
  * @irq:        IRQ number.
@@ -844,6 +899,8 @@ static irqreturn_t snps_com_irq_handler(int irq, void *dev_id)
 
 	rc |= snps_ue_irq_handler(irq, dev_id);
 
+	rc |= snps_dfi_irq_handler(irq, dev_id);
+
 	return rc;
 }
 
@@ -859,11 +916,16 @@ static void snps_enable_irq(struct snps_edac_priv *priv)
 		return;
 	}
 
-	/* IRQs Enable/Disable feature has been available since v3.10a */
+	/*
+	 * ECC IRQs Enable/Disable feature has been available since v3.10a,
+	 * while CRC/Parity interrupts control - since v2.10a.
+	 */
 	spin_lock_irqsave(&priv->lock, flags);
 
 	writel(ECC_CTRL_EN_CE_IRQ | ECC_CTRL_EN_UE_IRQ,
 	       priv->baseaddr + ECC_CLR_OFST);
+	writel(DDR_CRCPARCTL0_EN_ALRT_IRQ,
+	       priv->baseaddr + DDR_CRCPARCTL0_OFST);
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 }
@@ -883,6 +945,7 @@ static void snps_disable_irq(struct snps_edac_priv *priv)
 	spin_lock_irqsave(&priv->lock, flags);
 
 	writel(0, priv->baseaddr + ECC_CLR_OFST);
+	writel(0, priv->baseaddr + DDR_CRCPARCTL0_OFST);
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 }
@@ -1483,7 +1546,8 @@ static struct mem_ctl_info *snps_mc_create(struct snps_edac_priv *priv)
 	mci->mtype_cap = MEM_FLAG_LPDDR | MEM_FLAG_DDR2 | MEM_FLAG_LPDDR2 |
 			 MEM_FLAG_DDR3 | MEM_FLAG_LPDDR3 |
 			 MEM_FLAG_DDR4 | MEM_FLAG_LPDDR4;
-	mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
+	mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_PARITY;
+	mci->edac_cap = mci->edac_ctl_cap;
 
 	if (priv->info.caps & SNPS_CAP_ECC_SCRUB) {
 		mci->scrub_mode = SCRUB_HW_SRC;
@@ -1493,7 +1557,6 @@ static struct mem_ctl_info *snps_mc_create(struct snps_edac_priv *priv)
 		mci->scrub_cap = SCRUB_FLAG_SW_SRC;
 	}
 
-	mci->edac_cap = EDAC_FLAG_SECDED;
 	mci->ctl_name = "snps_umctl2_ddrc";
 	mci->dev_name = SNPS_EDAC_MOD_STRING;
 	mci->mod_name = SNPS_EDAC_MOD_VER;
@@ -1559,6 +1622,15 @@ static int snps_request_ind_irq(struct mem_ctl_info *mci)
 		return rc;
 	}
 
+	irq = platform_get_irq_byname_optional(priv->pdev, "dfi_e");
+	if (irq > 0) {
+		rc = devm_request_irq(dev, irq, snps_dfi_irq_handler, 0, "dfi_e", mci);
+		if (rc) {
+			edac_printk(KERN_ERR, EDAC_MC, "Failed to request DFI IRQ\n");
+			return rc;
+		}
+	}
+
 	return 0;
 }
 
