diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index f48244919a5c..81d14042ed4c 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -81,7 +81,7 @@
 #define ECC_POISON1_OFST		0xBC
 
 /* DDR Address map0 Registers */
-#define ECC_ADDRMAP0_OFST		0x200
+#define DDR_ADDRMAP0_OFST		0x200
 
 /* DDR Software control register */
 #define DDR_SWCTL			0x320
@@ -156,17 +156,28 @@
 #define ECC_CEPOISON_MASK		GENMASK(1, 0)
 #define ECC_UEPOISON_MASK		BIT(0)
 
-/* DDRC Device config shifts/masks */
-#define DDR_MAX_ROW_SHIFT		18
-#define DDR_MAX_COL_SHIFT		14
-#define DDR_MAX_BANK_SHIFT		3
-#define DDR_MAX_BANKGRP_SHIFT		2
+/* DDRC address mapping parameters */
+#define DDR_ADDRMAP_NREGS		12
 
-#define ROW_MAX_VAL_MASK		0xF
-#define COL_MAX_VAL_MASK		0xF
-#define BANK_MAX_VAL_MASK		0x1F
-#define BANKGRP_MAX_VAL_MASK		0x1F
-#define RANK_MAX_VAL_MASK		0x1F
+#define DDR_MAX_ROW_WIDTH		18
+#define DDR_MAX_COL_WIDTH		14
+#define DDR_MAX_BANK_WIDTH		3
+#define DDR_MAX_BANKGRP_WIDTH		2
+#define DDR_MAX_RANK_WIDTH		2
+
+#define DDR_ADDRMAP_B0_M15		GENMASK(3, 0)
+#define DDR_ADDRMAP_B8_M15		GENMASK(11, 8)
+#define DDR_ADDRMAP_B16_M15		GENMASK(19, 16)
+#define DDR_ADDRMAP_B24_M15		GENMASK(27, 24)
+
+#define DDR_ADDRMAP_B0_M31		GENMASK(4, 0)
+#define DDR_ADDRMAP_B8_M31		GENMASK(12, 8)
+#define DDR_ADDRMAP_B16_M31		GENMASK(20, 16)
+#define DDR_ADDRMAP_B24_M31		GENMASK(28, 24)
+
+#define DDR_ADDRMAP_UNUSED		((u8)-1)
+#define DDR_ADDRMAP_MAX_15		DDR_ADDRMAP_B0_M15
+#define DDR_ADDRMAP_MAX_31		DDR_ADDRMAP_B0_M31
 
 #define ROW_B0_BASE			6
 #define ROW_B1_BASE			7
@@ -208,6 +219,7 @@
 #define BANKGRP_B1_BASE			3
 
 #define RANK_B0_BASE			6
+#define RANK_B1_BASE			7
 
 /**
  * enum snps_dq_width - SDRAM DQ bus width (ECC capable).
@@ -294,6 +306,41 @@ struct snps_ddrc_info {
 	unsigned int ranks;
 };
 
+/**
+ * struct snps_hif_sdram_map - HIF/SDRAM mapping table.
+ * @row:	HIF bit offsets used as row address bits.
+ * @col:	HIF bit offsets used as column address bits.
+ * @bank:	HIF bit offsets used as bank address bits.
+ * @bankgrp:	HIF bit offsets used as bank group address bits.
+ * @rank:	HIF bit offsets used as rank address bits.
+ *
+ * For example, row[0] = 6 means row bit #0 is encoded by the HIF
+ * address bit #6 and vice-versa.
+ */
+struct snps_hif_sdram_map {
+	u8 row[DDR_MAX_ROW_WIDTH];
+	u8 col[DDR_MAX_COL_WIDTH];
+	u8 bank[DDR_MAX_BANK_WIDTH];
+	u8 bankgrp[DDR_MAX_BANKGRP_WIDTH];
+	u8 rank[DDR_MAX_RANK_WIDTH];
+};
+
+/**
+ * struct snps_sdram_addr - SDRAM address.
+ * @row:	Row number.
+ * @col:	Column number.
+ * @bank:	Bank number.
+ * @bankgrp:	Bank group number.
+ * @rank:	Rank number.
+ */
+struct snps_sdram_addr {
+	u16 row;
+	u16 col;
+	u8 bank;
+	u8 bankgrp;
+	u8 rank;
+};
+
 /**
  * struct snps_ecc_error_info - ECC error log information.
  * @row:	Row number.
@@ -331,20 +378,17 @@ struct snps_ecc_status {
 /**
  * struct snps_edac_priv - DDR memory controller private data.
  * @info:		DDR controller config info.
+ * @hif_sdram_map:	HIF/SDRAM mapping table.
  * @pdev:		Platform device.
  * @baseaddr:		Base address of the DDR controller.
  * @lock:		Concurrent CSRs access lock.
  * @message:		Buffer for framing the event specific info.
  * @stat:		ECC status information.
  * @poison_addr:	Data poison address.
- * @row_shift:		Bit shifts for row bit.
- * @col_shift:		Bit shifts for column bit.
- * @bank_shift:		Bit shifts for bank bit.
- * @bankgrp_shift:	Bit shifts for bank group bit.
- * @rank_shift:		Bit shifts for rank bit.
  */
 struct snps_edac_priv {
 	struct snps_ddrc_info info;
+	struct snps_hif_sdram_map hif_sdram_map;
 	struct platform_device *pdev;
 	void __iomem *baseaddr;
 	spinlock_t lock;
@@ -352,14 +396,97 @@ struct snps_edac_priv {
 	struct snps_ecc_status stat;
 #ifdef CONFIG_EDAC_DEBUG
 	ulong poison_addr;
-	u32 row_shift[18];
-	u32 col_shift[14];
-	u32 bank_shift[3];
-	u32 bankgrp_shift[2];
-	u32 rank_shift[1];
 #endif
 };
 
+/**
+ * snps_map_app_to_hif - Map Application address to HIF address.
+ * @priv:	DDR memory controller private instance data.
+ * @app:	Application address (source).
+ * @hif:	HIF address (destination).
+ *
+ * HIF address is used to perform the DQ bus width aligned burst transactions.
+ * So in order to perform the Application-to-HIF address translation we just
+ * need to discard the SDRAM-word bits of the Application address.
+ */
+static void snps_map_app_to_hif(struct snps_edac_priv *priv,
+				u64 app, u64 *hif)
+{
+	*hif = app >> priv->info.dq_width;
+}
+
+/**
+ * snps_map_hif_to_sdram - Map HIF address to SDRAM address.
+ * @priv:	DDR memory controller private instance data.
+ * @hif:	HIF address (source).
+ * @sdram:	SDRAM address (destination).
+ *
+ * HIF-SDRAM address mapping is configured with the ADDRMAPx registers, Based
+ * on the CSRs value the HIF address bits are mapped to the corresponding bits
+ * in the SDRAM rank/bank/column/row. If an SDRAM address bit is unused (there
+ * is no any HIF address bit corresponding to it) it will be set to zero. Using
+ * this fact we can freely set the output SDRAM address with zeros and walk
+ * over the set HIF address bits only. Similarly the unmapped HIF address bits
+ * are just ignored.
+ */
+static void snps_map_hif_to_sdram(struct snps_edac_priv *priv,
+				  u64 hif, struct snps_sdram_addr *sdram)
+{
+	struct snps_hif_sdram_map *map = &priv->hif_sdram_map;
+	int i;
+
+	sdram->row = 0;
+	for (i = 0; i < DDR_MAX_ROW_WIDTH; i++) {
+		if (map->row[i] != DDR_ADDRMAP_UNUSED && hif & BIT(map->row[i]))
+			sdram->row |= BIT(i);
+	}
+
+	sdram->col = 0;
+	for (i = 0; i < DDR_MAX_COL_WIDTH; i++) {
+		if (map->col[i] != DDR_ADDRMAP_UNUSED && hif & BIT(map->col[i]))
+			sdram->col |= BIT(i);
+	}
+
+	sdram->bank = 0;
+	for (i = 0; i < DDR_MAX_BANK_WIDTH; i++) {
+		if (map->bank[i] != DDR_ADDRMAP_UNUSED && hif & BIT(map->bank[i]))
+			sdram->bank |= BIT(i);
+	}
+
+	sdram->bankgrp = 0;
+	for (i = 0; i < DDR_MAX_BANKGRP_WIDTH; i++) {
+		if (map->bankgrp[i] != DDR_ADDRMAP_UNUSED && hif & BIT(map->bankgrp[i]))
+			sdram->bankgrp |= BIT(i);
+	}
+
+	sdram->rank = 0;
+	for (i = 0; i < DDR_MAX_RANK_WIDTH; i++) {
+		if (map->rank[i] != DDR_ADDRMAP_UNUSED && hif & BIT(map->rank[i]))
+			sdram->rank |= BIT(i);
+	}
+}
+
+/**
+ * snps_map_sys_to_sdram - Map System address to SDRAM address.
+ * @priv:	DDR memory controller private instance data.
+ * @sys:	System address (source).
+ * @sdram:	SDRAM address (destination).
+ *
+ * Perform a full mapping of the system address (detected on the controller
+ * ports) to the SDRAM address tuple row/column/bank/etc.
+ */
+static void snps_map_sys_to_sdram(struct snps_edac_priv *priv,
+				  dma_addr_t sys, struct snps_sdram_addr *sdram)
+{
+	u64 app, hif;
+
+	app = sys;
+
+	snps_map_app_to_hif(priv, app, &hif);
+
+	snps_map_hif_to_sdram(priv, hif, sdram);
+}
+
 /**
  * snps_get_bitpos - Get DQ-bus corrected bit position.
  * @bitnum:	Bit number retrieved from the ECCSTAT.corrected_bit_num field.
@@ -749,6 +876,301 @@ static int snps_get_ddrc_info(struct snps_edac_priv *priv)
 	return init_plat ? init_plat(priv) : 0;
 }
 
+/**
+ * snps_get_hif_row_map - Get HIF/SDRAM-row address map.
+ * @priv:	DDR memory controller private instance data.
+ * @addrmap:	Array with ADDRMAP registers value.
+ *
+ * SDRAM-row address is defined by the fields in the ADDRMAP[5-7,9-11]
+ * registers. Those fields value indicate the HIF address bits used to encode
+ * the DDR row address.
+ */
+static void snps_get_hif_row_map(struct snps_edac_priv *priv, u32 *addrmap)
+{
+	struct snps_hif_sdram_map *map = &priv->hif_sdram_map;
+	u8 map_row_b2_10;
+	int i;
+
+	for (i = 0; i < DDR_MAX_ROW_WIDTH; i++)
+		map->row[i] = DDR_ADDRMAP_UNUSED;
+
+	map->row[0] = FIELD_GET(DDR_ADDRMAP_B0_M15, addrmap[5]) + ROW_B0_BASE;
+	map->row[1] = FIELD_GET(DDR_ADDRMAP_B8_M15, addrmap[5]) + ROW_B1_BASE;
+
+	map_row_b2_10 = FIELD_GET(DDR_ADDRMAP_B16_M15, addrmap[5]);
+	if (map_row_b2_10 != DDR_ADDRMAP_MAX_15) {
+		for (i = 2; i < 11; i++)
+			map->row[i] = map_row_b2_10 + i + ROW_B0_BASE;
+	} else {
+		map->row[2] = FIELD_GET(DDR_ADDRMAP_B0_M15, addrmap[9]) + ROW_B2_BASE;
+		map->row[3] = FIELD_GET(DDR_ADDRMAP_B8_M15, addrmap[9]) + ROW_B3_BASE;
+		map->row[4] = FIELD_GET(DDR_ADDRMAP_B16_M15, addrmap[9]) + ROW_B4_BASE;
+		map->row[5] = FIELD_GET(DDR_ADDRMAP_B24_M15, addrmap[9]) + ROW_B5_BASE;
+		map->row[6] = FIELD_GET(DDR_ADDRMAP_B0_M15, addrmap[10]) + ROW_B6_BASE;
+		map->row[7] = FIELD_GET(DDR_ADDRMAP_B8_M15, addrmap[10]) + ROW_B7_BASE;
+		map->row[8] = FIELD_GET(DDR_ADDRMAP_B16_M15, addrmap[10]) + ROW_B8_BASE;
+		map->row[9] = FIELD_GET(DDR_ADDRMAP_B24_M15, addrmap[10]) + ROW_B9_BASE;
+		map->row[10] = FIELD_GET(DDR_ADDRMAP_B0_M15, addrmap[11]) + ROW_B10_BASE;
+	}
+
+	map->row[11] = FIELD_GET(DDR_ADDRMAP_B24_M15, addrmap[5]);
+	map->row[11] = map->row[11] == DDR_ADDRMAP_MAX_15 ?
+		       DDR_ADDRMAP_UNUSED : map->row[11] + ROW_B11_BASE;
+
+	map->row[12] = FIELD_GET(DDR_ADDRMAP_B0_M15, addrmap[6]);
+	map->row[12] = map->row[12] == DDR_ADDRMAP_MAX_15 ?
+		       DDR_ADDRMAP_UNUSED : map->row[12] + ROW_B12_BASE;
+
+	map->row[13] = FIELD_GET(DDR_ADDRMAP_B8_M15, addrmap[6]);
+	map->row[13] = map->row[13] == DDR_ADDRMAP_MAX_15 ?
+		       DDR_ADDRMAP_UNUSED : map->row[13] + ROW_B13_BASE;
+
+	map->row[14] = FIELD_GET(DDR_ADDRMAP_B16_M15, addrmap[6]);
+	map->row[14] = map->row[14] == DDR_ADDRMAP_MAX_15 ?
+		       DDR_ADDRMAP_UNUSED : map->row[14] + ROW_B14_BASE;
+
+	map->row[15] = FIELD_GET(DDR_ADDRMAP_B24_M15, addrmap[6]);
+	map->row[15] = map->row[15] == DDR_ADDRMAP_MAX_15 ?
+		       DDR_ADDRMAP_UNUSED : map->row[15] + ROW_B15_BASE;
+
+	if (priv->info.sdram_mode == MEM_DDR4 || priv->info.sdram_mode == MEM_LPDDR4) {
+		map->row[16] = FIELD_GET(DDR_ADDRMAP_B0_M15, addrmap[7]);
+		map->row[16] = map->row[16] == DDR_ADDRMAP_MAX_15 ?
+			       DDR_ADDRMAP_UNUSED : map->row[16] + ROW_B16_BASE;
+
+		map->row[17] = FIELD_GET(DDR_ADDRMAP_B8_M15, addrmap[7]);
+		map->row[17] = map->row[17] == DDR_ADDRMAP_MAX_15 ?
+			       DDR_ADDRMAP_UNUSED : map->row[17] + ROW_B17_BASE;
+	}
+}
+
+/**
+ * snps_get_hif_col_map - Get HIF/SDRAM-column address map.
+ * @priv:	DDR memory controller private instance data.
+ * @addrmap:	Array with ADDRMAP registers value.
+ *
+ * SDRAM-column address is defined by the fields in the ADDRMAP[2-4]
+ * registers. Those fields value indicate the HIF address bits used to encode
+ * the DDR row address.
+ */
+static void snps_get_hif_col_map(struct snps_edac_priv *priv, u32 *addrmap)
+{
+	struct snps_hif_sdram_map *map = &priv->hif_sdram_map;
+	int i;
+
+	for (i = 0; i < DDR_MAX_COL_WIDTH; i++)
+		map->col[i] = DDR_ADDRMAP_UNUSED;
+
+	map->col[0] = 0;
+	map->col[1] = 1;
+	map->col[2] = FIELD_GET(DDR_ADDRMAP_B0_M15, addrmap[2]) + COL_B2_BASE;
+	map->col[3] = FIELD_GET(DDR_ADDRMAP_B8_M15, addrmap[2]) + COL_B3_BASE;
+
+	map->col[4] = FIELD_GET(DDR_ADDRMAP_B16_M15, addrmap[2]);
+	map->col[4] = map->col[4] == DDR_ADDRMAP_MAX_15 ?
+		      DDR_ADDRMAP_UNUSED : map->col[4] + COL_B4_BASE;
+
+	map->col[5] = FIELD_GET(DDR_ADDRMAP_B24_M15, addrmap[2]);
+	map->col[5] = map->col[5] == DDR_ADDRMAP_MAX_15 ?
+		      DDR_ADDRMAP_UNUSED : map->col[5] + COL_B5_BASE;
+
+	map->col[6] = FIELD_GET(DDR_ADDRMAP_B0_M15, addrmap[3]);
+	map->col[6] = map->col[6] == DDR_ADDRMAP_MAX_15 ?
+		      DDR_ADDRMAP_UNUSED : map->col[6] + COL_B6_BASE;
+
+	map->col[7] = FIELD_GET(DDR_ADDRMAP_B8_M15, addrmap[3]);
+	map->col[7] = map->col[7] == DDR_ADDRMAP_MAX_15 ?
+		      DDR_ADDRMAP_UNUSED : map->col[7] + COL_B7_BASE;
+
+	map->col[8] = FIELD_GET(DDR_ADDRMAP_B16_M15, addrmap[3]);
+	map->col[8] = map->col[8] == DDR_ADDRMAP_MAX_15 ?
+		      DDR_ADDRMAP_UNUSED : map->col[8] + COL_B8_BASE;
+
+	map->col[9] = FIELD_GET(DDR_ADDRMAP_B24_M15, addrmap[3]);
+	map->col[9] = map->col[9] == DDR_ADDRMAP_MAX_15 ?
+		      DDR_ADDRMAP_UNUSED : map->col[9] + COL_B9_BASE;
+
+	if (priv->info.dq_mode) {
+		for (i = 9; i > priv->info.dq_mode; i--) {
+			map->col[i] = map->col[i - priv->info.dq_mode];
+			map->col[i - priv->info.dq_mode] = DDR_ADDRMAP_UNUSED;
+		}
+	}
+
+	/*
+	 * Per JEDEC DDR2/3/4/mDDR specification, column address bit 10 is
+	 * reserved for indicating auto-precharge, and hence no source
+	 * address bit can be mapped to col[10].
+	 * Per JEDEC specification, column address bit 12 is reserved
+	 * for the Burst-chop status, so no source address bit mapping
+	 * for col[12] either.
+	 */
+	if (priv->info.dq_mode == SNPS_DQ_FULL) {
+		if (priv->info.sdram_mode == MEM_LPDDR3) {
+			map->col[10] = FIELD_GET(DDR_ADDRMAP_B0_M15, addrmap[4]);
+			map->col[10] = map->col[10] == DDR_ADDRMAP_MAX_15 ?
+				       DDR_ADDRMAP_UNUSED : map->col[10] + COL_B10_BASE;
+
+			map->col[11] = FIELD_GET(DDR_ADDRMAP_B8_M15, addrmap[4]);
+			map->col[11] = map->col[11] == DDR_ADDRMAP_MAX_15 ?
+				       DDR_ADDRMAP_UNUSED : map->col[11] + COL_B11_BASE;
+		} else {
+			map->col[11] = FIELD_GET(DDR_ADDRMAP_B0_M15, addrmap[4]);
+			map->col[11] = map->col[11] == DDR_ADDRMAP_MAX_15 ?
+				       DDR_ADDRMAP_UNUSED : map->col[11] + COL_B10_BASE;
+
+			map->col[13] = FIELD_GET(DDR_ADDRMAP_B8_M15, addrmap[4]);
+			map->col[13] = map->col[13] == DDR_ADDRMAP_MAX_15 ?
+				       DDR_ADDRMAP_UNUSED : map->col[13] + COL_B11_BASE;
+		}
+	} else if (priv->info.dq_mode == SNPS_DQ_HALF) {
+		if (priv->info.sdram_mode == MEM_LPDDR3) {
+			map->col[10] = FIELD_GET(DDR_ADDRMAP_B24_M15, addrmap[3]);
+			map->col[10] = map->col[10] == DDR_ADDRMAP_MAX_15 ?
+				       DDR_ADDRMAP_UNUSED : map->col[10] + COL_B9_BASE;
+
+			map->col[11] = FIELD_GET(DDR_ADDRMAP_B0_M15, addrmap[4]);
+			map->col[11] = map->col[11] == DDR_ADDRMAP_MAX_15 ?
+				       DDR_ADDRMAP_UNUSED : map->col[11] + COL_B10_BASE;
+		} else {
+			map->col[11] = FIELD_GET(DDR_ADDRMAP_B24_M15, addrmap[3]);
+			map->col[11] = map->col[11] == DDR_ADDRMAP_MAX_15 ?
+				       DDR_ADDRMAP_UNUSED : map->col[11] + COL_B9_BASE;
+
+			map->col[13] = FIELD_GET(DDR_ADDRMAP_B0_M15, addrmap[4]);
+			map->col[13] = map->col[13] == DDR_ADDRMAP_MAX_15 ?
+				       DDR_ADDRMAP_UNUSED : map->col[13] + COL_B10_BASE;
+		}
+	} else {
+		if (priv->info.sdram_mode == MEM_LPDDR3) {
+			map->col[10] = FIELD_GET(DDR_ADDRMAP_B16_M15, addrmap[3]);
+			map->col[10] = map->col[10] == DDR_ADDRMAP_MAX_15 ?
+				       DDR_ADDRMAP_UNUSED : map->col[10] + COL_B8_BASE;
+
+			map->col[11] = FIELD_GET(DDR_ADDRMAP_B24_M15, addrmap[3]);
+			map->col[11] = map->col[11] == DDR_ADDRMAP_MAX_15 ?
+				       DDR_ADDRMAP_UNUSED : map->col[11] + COL_B9_BASE;
+		} else {
+			map->col[11] = FIELD_GET(DDR_ADDRMAP_B16_M15, addrmap[3]);
+			map->col[11] = map->col[11] == DDR_ADDRMAP_MAX_15 ?
+				       DDR_ADDRMAP_UNUSED : map->col[11] + COL_B8_BASE;
+
+			map->col[11] = FIELD_GET(DDR_ADDRMAP_B24_M15, addrmap[3]);
+			map->col[13] = map->col[13] == DDR_ADDRMAP_MAX_15 ?
+				       DDR_ADDRMAP_UNUSED : map->col[13] + COL_B9_BASE;
+		}
+	}
+}
+
+/**
+ * snps_get_hif_bank_map - Get HIF/SDRAM-bank address map.
+ * @priv:	DDR memory controller private instance data.
+ * @addrmap:	Array with ADDRMAP registers value.
+ *
+ * SDRAM-bank address is defined by the fields in the ADDRMAP[1]
+ * register. Those fields value indicate the HIF address bits used to encode
+ * the DDR bank address.
+ */
+static void snps_get_hif_bank_map(struct snps_edac_priv *priv, u32 *addrmap)
+{
+	struct snps_hif_sdram_map *map = &priv->hif_sdram_map;
+	int i;
+
+	for (i = 0; i < DDR_MAX_BANK_WIDTH; i++)
+		map->bank[i] = DDR_ADDRMAP_UNUSED;
+
+	map->bank[0] = FIELD_GET(DDR_ADDRMAP_B0_M31, addrmap[1]) + BANK_B0_BASE;
+	map->bank[1] = FIELD_GET(DDR_ADDRMAP_B8_M31, addrmap[1]) + BANK_B1_BASE;
+
+	map->bank[2] = FIELD_GET(DDR_ADDRMAP_B16_M31, addrmap[1]);
+	map->bank[2] = map->bank[2] == DDR_ADDRMAP_MAX_31 ?
+		       DDR_ADDRMAP_UNUSED : map->bank[2] + BANK_B2_BASE;
+}
+
+/**
+ * snps_get_hif_bankgrp_map - Get HIF/SDRAM-bank group address map.
+ * @priv:	DDR memory controller private instance data.
+ * @addrmap:	Array with ADDRMAP registers value.
+ *
+ * SDRAM-bank group address is defined by the fields in the ADDRMAP[8]
+ * register. Those fields value indicate the HIF address bits used to encode
+ * the DDR bank group address.
+ */
+static void snps_get_hif_bankgrp_map(struct snps_edac_priv *priv, u32 *addrmap)
+{
+	struct snps_hif_sdram_map *map = &priv->hif_sdram_map;
+	int i;
+
+	for (i = 0; i < DDR_MAX_BANKGRP_WIDTH; i++)
+		map->bankgrp[i] = DDR_ADDRMAP_UNUSED;
+
+	/* Bank group signals are available on the DDR4 memory only */
+	if (priv->info.sdram_mode != MEM_DDR4)
+		return;
+
+	map->bankgrp[0] = FIELD_GET(DDR_ADDRMAP_B0_M31, addrmap[8]) + BANKGRP_B0_BASE;
+
+	map->bankgrp[1] = FIELD_GET(DDR_ADDRMAP_B8_M31, addrmap[8]);
+	map->bankgrp[1] = map->bankgrp[1] == DDR_ADDRMAP_MAX_31 ?
+			  DDR_ADDRMAP_UNUSED : map->bankgrp[1] + BANKGRP_B1_BASE;
+}
+
+/**
+ * snps_get_hif_rank_map - Get HIF/SDRAM-rank address map.
+ * @priv:	DDR memory controller private instance data.
+ * @addrmap:	Array with ADDRMAP registers value.
+ *
+ * SDRAM-rank address is defined by the fields in the ADDRMAP[0]
+ * register. Those fields value indicate the HIF address bits used to encode
+ * the DDR rank address.
+ */
+static void snps_get_hif_rank_map(struct snps_edac_priv *priv, u32 *addrmap)
+{
+	struct snps_hif_sdram_map *map = &priv->hif_sdram_map;
+	int i;
+
+	for (i = 0; i < DDR_MAX_RANK_WIDTH; i++)
+		map->rank[i] = DDR_ADDRMAP_UNUSED;
+
+	if (priv->info.ranks > 1) {
+		map->rank[0] = FIELD_GET(DDR_ADDRMAP_B0_M31, addrmap[0]);
+		map->rank[0] = map->rank[0] == DDR_ADDRMAP_MAX_31 ?
+			       DDR_ADDRMAP_UNUSED : map->rank[0] + RANK_B0_BASE;
+	}
+
+	if (priv->info.ranks > 2) {
+		map->rank[1] = FIELD_GET(DDR_ADDRMAP_B8_M31, addrmap[0]);
+		map->rank[1] = map->rank[1] == DDR_ADDRMAP_MAX_31 ?
+			       DDR_ADDRMAP_UNUSED : map->rank[1] + RANK_B1_BASE;
+	}
+}
+
+/**
+ * snps_get_addr_map - Get HIF/SDRAM/etc address map from CSRs.
+ * @priv:	DDR memory controller private instance data.
+ *
+ * Parse the controller registers content creating the addresses mapping tables.
+ * They will be used for the erroneous and poison addresses encode/decode.
+ */
+static void snps_get_addr_map(struct snps_edac_priv *priv)
+{
+	u32 regval[DDR_ADDRMAP_NREGS];
+	int i;
+
+	for (i = 0; i < DDR_ADDRMAP_NREGS; i++)
+		regval[i] = readl(priv->baseaddr + DDR_ADDRMAP0_OFST + i * 4);
+
+	snps_get_hif_row_map(priv, regval);
+
+	snps_get_hif_col_map(priv, regval);
+
+	snps_get_hif_bank_map(priv, regval);
+
+	snps_get_hif_bankgrp_map(priv, regval);
+
+	snps_get_hif_rank_map(priv, regval);
+}
+
 /**
  * snps_init_csrows - Initialize the csrow data.
  * @mci:	EDAC memory controller instance.
@@ -934,285 +1356,21 @@ DEFINE_SHOW_ATTRIBUTE(snps_ddrc_info);
  */
 static void snps_data_poison_setup(struct snps_edac_priv *priv)
 {
-	int col = 0, row = 0, bank = 0, bankgrp = 0, rank = 0, regval;
-	int index;
-	ulong hif_addr = 0;
-
-	hif_addr = priv->poison_addr >> 3;
-
-	for (index = 0; index < DDR_MAX_ROW_SHIFT; index++) {
-		if (priv->row_shift[index])
-			row |= (((hif_addr >> priv->row_shift[index]) &
-						BIT(0)) << index);
-		else
-			break;
-	}
-
-	for (index = 0; index < DDR_MAX_COL_SHIFT; index++) {
-		if (priv->col_shift[index] || index < 3)
-			col |= (((hif_addr >> priv->col_shift[index]) &
-						BIT(0)) << index);
-		else
-			break;
-	}
-
-	for (index = 0; index < DDR_MAX_BANK_SHIFT; index++) {
-		if (priv->bank_shift[index])
-			bank |= (((hif_addr >> priv->bank_shift[index]) &
-						BIT(0)) << index);
-		else
-			break;
-	}
-
-	for (index = 0; index < DDR_MAX_BANKGRP_SHIFT; index++) {
-		if (priv->bankgrp_shift[index])
-			bankgrp |= (((hif_addr >> priv->bankgrp_shift[index])
-						& BIT(0)) << index);
-		else
-			break;
-	}
+	struct snps_sdram_addr sdram;
+	u32 regval;
 
-	if (priv->rank_shift[0])
-		rank = (hif_addr >> priv->rank_shift[0]) & BIT(0);
+	snps_map_sys_to_sdram(priv, priv->poison_addr, &sdram);
 
-	regval = FIELD_PREP(ECC_POISON0_RANK_MASK, rank) |
-		 FIELD_PREP(ECC_POISON0_COL_MASK, col);
+	regval = FIELD_PREP(ECC_POISON0_RANK_MASK, sdram.rank) |
+		 FIELD_PREP(ECC_POISON0_COL_MASK, sdram.col);
 	writel(regval, priv->baseaddr + ECC_POISON0_OFST);
 
-	regval = FIELD_PREP(ECC_POISON1_BANKGRP_MASK, bankgrp) |
-		 FIELD_PREP(ECC_POISON1_BANK_MASK, bank) |
-		 FIELD_PREP(ECC_POISON1_ROW_MASK, row);
+	regval = FIELD_PREP(ECC_POISON1_BANKGRP_MASK, sdram.bankgrp) |
+		 FIELD_PREP(ECC_POISON1_BANK_MASK, sdram.bank) |
+		 FIELD_PREP(ECC_POISON1_ROW_MASK, sdram.row);
 	writel(regval, priv->baseaddr + ECC_POISON1_OFST);
 }
 
-static void snps_setup_row_address_map(struct snps_edac_priv *priv, u32 *addrmap)
-{
-	u32 addrmap_row_b2_10;
-	int index;
-
-	priv->row_shift[0] = (addrmap[5] & ROW_MAX_VAL_MASK) + ROW_B0_BASE;
-	priv->row_shift[1] = ((addrmap[5] >> 8) &
-			ROW_MAX_VAL_MASK) + ROW_B1_BASE;
-
-	addrmap_row_b2_10 = (addrmap[5] >> 16) & ROW_MAX_VAL_MASK;
-	if (addrmap_row_b2_10 != ROW_MAX_VAL_MASK) {
-		for (index = 2; index < 11; index++)
-			priv->row_shift[index] = addrmap_row_b2_10 +
-				index + ROW_B0_BASE;
-
-	} else {
-		priv->row_shift[2] = (addrmap[9] &
-				ROW_MAX_VAL_MASK) + ROW_B2_BASE;
-		priv->row_shift[3] = ((addrmap[9] >> 8) &
-				ROW_MAX_VAL_MASK) + ROW_B3_BASE;
-		priv->row_shift[4] = ((addrmap[9] >> 16) &
-				ROW_MAX_VAL_MASK) + ROW_B4_BASE;
-		priv->row_shift[5] = ((addrmap[9] >> 24) &
-				ROW_MAX_VAL_MASK) + ROW_B5_BASE;
-		priv->row_shift[6] = (addrmap[10] &
-				ROW_MAX_VAL_MASK) + ROW_B6_BASE;
-		priv->row_shift[7] = ((addrmap[10] >> 8) &
-				ROW_MAX_VAL_MASK) + ROW_B7_BASE;
-		priv->row_shift[8] = ((addrmap[10] >> 16) &
-				ROW_MAX_VAL_MASK) + ROW_B8_BASE;
-		priv->row_shift[9] = ((addrmap[10] >> 24) &
-				ROW_MAX_VAL_MASK) + ROW_B9_BASE;
-		priv->row_shift[10] = (addrmap[11] &
-				ROW_MAX_VAL_MASK) + ROW_B10_BASE;
-	}
-
-	priv->row_shift[11] = (((addrmap[5] >> 24) & ROW_MAX_VAL_MASK) ==
-				ROW_MAX_VAL_MASK) ? 0 : (((addrmap[5] >> 24) &
-				ROW_MAX_VAL_MASK) + ROW_B11_BASE);
-	priv->row_shift[12] = ((addrmap[6] & ROW_MAX_VAL_MASK) ==
-				ROW_MAX_VAL_MASK) ? 0 : ((addrmap[6] &
-				ROW_MAX_VAL_MASK) + ROW_B12_BASE);
-	priv->row_shift[13] = (((addrmap[6] >> 8) & ROW_MAX_VAL_MASK) ==
-				ROW_MAX_VAL_MASK) ? 0 : (((addrmap[6] >> 8) &
-				ROW_MAX_VAL_MASK) + ROW_B13_BASE);
-	priv->row_shift[14] = (((addrmap[6] >> 16) & ROW_MAX_VAL_MASK) ==
-				ROW_MAX_VAL_MASK) ? 0 : (((addrmap[6] >> 16) &
-				ROW_MAX_VAL_MASK) + ROW_B14_BASE);
-	priv->row_shift[15] = (((addrmap[6] >> 24) & ROW_MAX_VAL_MASK) ==
-				ROW_MAX_VAL_MASK) ? 0 : (((addrmap[6] >> 24) &
-				ROW_MAX_VAL_MASK) + ROW_B15_BASE);
-
-	if (priv->info.sdram_mode == MEM_DDR4 || priv->info.sdram_mode == MEM_LPDDR4) {
-		priv->row_shift[16] = ((addrmap[7] & ROW_MAX_VAL_MASK) ==
-					ROW_MAX_VAL_MASK) ? 0 : ((addrmap[7] &
-					ROW_MAX_VAL_MASK) + ROW_B16_BASE);
-		priv->row_shift[17] = (((addrmap[7] >> 8) & ROW_MAX_VAL_MASK) ==
-					ROW_MAX_VAL_MASK) ? 0 : (((addrmap[7] >> 8) &
-					ROW_MAX_VAL_MASK) + ROW_B17_BASE);
-	}
-}
-
-static void snps_setup_column_address_map(struct snps_edac_priv *priv, u32 *addrmap)
-{
-	int index;
-
-	priv->col_shift[0] = 0;
-	priv->col_shift[1] = 1;
-	priv->col_shift[2] = (addrmap[2] & COL_MAX_VAL_MASK) + COL_B2_BASE;
-	priv->col_shift[3] = ((addrmap[2] >> 8) &
-			COL_MAX_VAL_MASK) + COL_B3_BASE;
-	priv->col_shift[4] = (((addrmap[2] >> 16) & COL_MAX_VAL_MASK) ==
-			COL_MAX_VAL_MASK) ? 0 : (((addrmap[2] >> 16) &
-					COL_MAX_VAL_MASK) + COL_B4_BASE);
-	priv->col_shift[5] = (((addrmap[2] >> 24) & COL_MAX_VAL_MASK) ==
-			COL_MAX_VAL_MASK) ? 0 : (((addrmap[2] >> 24) &
-					COL_MAX_VAL_MASK) + COL_B5_BASE);
-	priv->col_shift[6] = ((addrmap[3] & COL_MAX_VAL_MASK) ==
-			COL_MAX_VAL_MASK) ? 0 : ((addrmap[3] &
-					COL_MAX_VAL_MASK) + COL_B6_BASE);
-	priv->col_shift[7] = (((addrmap[3] >> 8) & COL_MAX_VAL_MASK) ==
-			COL_MAX_VAL_MASK) ? 0 : (((addrmap[3] >> 8) &
-					COL_MAX_VAL_MASK) + COL_B7_BASE);
-	priv->col_shift[8] = (((addrmap[3] >> 16) & COL_MAX_VAL_MASK) ==
-			COL_MAX_VAL_MASK) ? 0 : (((addrmap[3] >> 16) &
-					COL_MAX_VAL_MASK) + COL_B8_BASE);
-	priv->col_shift[9] = (((addrmap[3] >> 24) & COL_MAX_VAL_MASK) ==
-			COL_MAX_VAL_MASK) ? 0 : (((addrmap[3] >> 24) &
-					COL_MAX_VAL_MASK) + COL_B9_BASE);
-	if (priv->info.dq_mode == SNPS_DQ_FULL) {
-		if (priv->info.sdram_mode == MEM_LPDDR3) {
-			priv->col_shift[10] = ((addrmap[4] &
-				COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
-				((addrmap[4] & COL_MAX_VAL_MASK) +
-				 COL_B10_BASE);
-			priv->col_shift[11] = (((addrmap[4] >> 8) &
-				COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
-				(((addrmap[4] >> 8) & COL_MAX_VAL_MASK) +
-				 COL_B11_BASE);
-		} else {
-			priv->col_shift[11] = ((addrmap[4] &
-				COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
-				((addrmap[4] & COL_MAX_VAL_MASK) +
-				 COL_B10_BASE);
-			priv->col_shift[13] = (((addrmap[4] >> 8) &
-				COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
-				(((addrmap[4] >> 8) & COL_MAX_VAL_MASK) +
-				 COL_B11_BASE);
-		}
-	} else if (priv->info.dq_mode == SNPS_DQ_HALF) {
-		if (priv->info.sdram_mode == MEM_LPDDR3) {
-			priv->col_shift[10] = (((addrmap[3] >> 24) &
-				COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
-				(((addrmap[3] >> 24) & COL_MAX_VAL_MASK) +
-				 COL_B9_BASE);
-			priv->col_shift[11] = ((addrmap[4] &
-				COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
-				((addrmap[4] & COL_MAX_VAL_MASK) +
-				 COL_B10_BASE);
-		} else {
-			priv->col_shift[11] = (((addrmap[3] >> 24) &
-				COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
-				(((addrmap[3] >> 24) & COL_MAX_VAL_MASK) +
-				 COL_B9_BASE);
-			priv->col_shift[13] = ((addrmap[4] &
-				COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
-				((addrmap[4] & COL_MAX_VAL_MASK) +
-				 COL_B10_BASE);
-		}
-	} else {
-		if (priv->info.sdram_mode == MEM_LPDDR3) {
-			priv->col_shift[10] = (((addrmap[3] >> 16) &
-				COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
-				(((addrmap[3] >> 16) & COL_MAX_VAL_MASK) +
-				 COL_B8_BASE);
-			priv->col_shift[11] = (((addrmap[3] >> 24) &
-				COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
-				(((addrmap[3] >> 24) & COL_MAX_VAL_MASK) +
-				 COL_B9_BASE);
-		} else {
-			priv->col_shift[11] = (((addrmap[3] >> 16) &
-				COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
-				(((addrmap[3] >> 16) & COL_MAX_VAL_MASK) +
-				 COL_B8_BASE);
-			priv->col_shift[13] = (((addrmap[3] >> 24) &
-				COL_MAX_VAL_MASK) == COL_MAX_VAL_MASK) ? 0 :
-				(((addrmap[3] >> 24) & COL_MAX_VAL_MASK) +
-				 COL_B9_BASE);
-		}
-	}
-
-	if (priv->info.dq_mode) {
-		for (index = 9; index > priv->info.dq_mode; index--) {
-			priv->col_shift[index] =
-				priv->col_shift[index - priv->info.dq_mode];
-			priv->col_shift[index - priv->info.dq_mode] = 0;
-		}
-	}
-
-}
-
-static void snps_setup_bank_address_map(struct snps_edac_priv *priv, u32 *addrmap)
-{
-	priv->bank_shift[0] = (addrmap[1] & BANK_MAX_VAL_MASK) + BANK_B0_BASE;
-	priv->bank_shift[1] = ((addrmap[1] >> 8) &
-				BANK_MAX_VAL_MASK) + BANK_B1_BASE;
-	priv->bank_shift[2] = (((addrmap[1] >> 16) &
-				BANK_MAX_VAL_MASK) == BANK_MAX_VAL_MASK) ? 0 :
-				(((addrmap[1] >> 16) & BANK_MAX_VAL_MASK) +
-				 BANK_B2_BASE);
-
-}
-
-static void snps_setup_bg_address_map(struct snps_edac_priv *priv, u32 *addrmap)
-{
-	/* Bank group signals are available on the DDR4 memory only */
-	if (priv->info.sdram_mode != MEM_DDR4)
-		return;
-
-	priv->bankgrp_shift[0] = (addrmap[8] &
-				BANKGRP_MAX_VAL_MASK) + BANKGRP_B0_BASE;
-	priv->bankgrp_shift[1] = (((addrmap[8] >> 8) & BANKGRP_MAX_VAL_MASK) ==
-				BANKGRP_MAX_VAL_MASK) ? 0 : (((addrmap[8] >> 8)
-				& BANKGRP_MAX_VAL_MASK) + BANKGRP_B1_BASE);
-
-}
-
-static void snps_setup_rank_address_map(struct snps_edac_priv *priv, u32 *addrmap)
-{
-	/* Ranks mapping is unavailable for the single-ranked memory */
-	if (priv->info.ranks > 1) {
-		priv->rank_shift[0] = ((addrmap[0] & RANK_MAX_VAL_MASK) ==
-					RANK_MAX_VAL_MASK) ? 0 : ((addrmap[0] &
-					RANK_MAX_VAL_MASK) + RANK_B0_BASE);
-	}
-}
-
-/**
- * snps_setup_address_map -	Set Address Map by querying ADDRMAP registers.
- * @priv:		DDR memory controller private instance data.
- *
- * Set Address Map by querying ADDRMAP registers.
- *
- * Return: none.
- */
-static void snps_setup_address_map(struct snps_edac_priv *priv)
-{
-	u32 addrmap[12];
-	int index;
-
-	for (index = 0; index < 12; index++) {
-		u32 addrmap_offset;
-
-		addrmap_offset = ECC_ADDRMAP0_OFST + (index * 4);
-		addrmap[index] = readl(priv->baseaddr + addrmap_offset);
-	}
-
-	snps_setup_row_address_map(priv, addrmap);
-
-	snps_setup_column_address_map(priv, addrmap);
-
-	snps_setup_bank_address_map(priv, addrmap);
-
-	snps_setup_bg_address_map(priv, addrmap);
-
-	snps_setup_rank_address_map(priv, addrmap);
-}
-
 static ssize_t snps_inject_data_error_read(struct file *filep, char __user *ubuf,
 					   size_t size, loff_t *offp)
 {
@@ -1305,10 +1463,6 @@ SNPS_DEBUGFS_FOPS(snps_inject_data_poison, snps_inject_data_poison_read,
  */
 static void snps_create_debugfs_nodes(struct mem_ctl_info *mci)
 {
-	struct snps_edac_priv *priv = mci->pvt_info;
-
-	snps_setup_address_map(priv);
-
 	edac_debugfs_create_file("ddrc_info", 0400, mci->debugfs, mci,
 				 &snps_ddrc_info_fops);
 
@@ -1348,6 +1502,8 @@ static int snps_mc_probe(struct platform_device *pdev)
 	if (rc)
 		return rc;
 
+	snps_get_addr_map(priv);
+
 	mci = snps_mc_create(priv);
 	if (IS_ERR(mci))
 		return PTR_ERR(mci);
