diff --git a/arch/arm/cpu/armv7/keystone/ddr3.c b/arch/arm/cpu/armv7/keystone/ddr3.c
index 2eabec10f95f6e207ced63295f170a7bf9e2ae3f..923906afb5bec2ab2ff10d149e891cc387918738 100644
--- a/arch/arm/cpu/armv7/keystone/ddr3.c
+++ b/arch/arm/cpu/armv7/keystone/ddr3.c
@@ -9,9 +9,19 @@
 
 #include <asm/io.h>
 #include <common.h>
+#include <asm/arch/msmc.h>
 #include <asm/arch/ddr3.h>
 #include <asm/arch/psc_defs.h>
 
+#include <asm/ti-common/ti-edma3.h>
+
+#define DDR3_EDMA_BLK_SIZE_SHIFT	10
+#define DDR3_EDMA_BLK_SIZE		(1 << DDR3_EDMA_BLK_SIZE_SHIFT)
+#define DDR3_EDMA_BCNT			0x8000
+#define DDR3_EDMA_CCNT			1
+#define DDR3_EDMA_XF_SIZE		(DDR3_EDMA_BLK_SIZE * DDR3_EDMA_BCNT)
+#define DDR3_EDMA_SLOT_NUM		1
+
 void ddr3_init_ddrphy(u32 base, struct ddr3_phy_config *phy_cfg)
 {
 	unsigned int tmp;
@@ -70,6 +80,240 @@ void ddr3_init_ddremif(u32 base, struct ddr3_emif_config *emif_cfg)
 	__raw_writel(emif_cfg->sdrfc,  base + KS2_DDR3_SDRFC_OFFSET);
 }
 
+int ddr3_ecc_support_rmw(u32 base)
+{
+	u32 value = __raw_readl(base + KS2_DDR3_MIDR_OFFSET);
+
+	/* Check the DDR3 controller ID reg if the controllers
+	   supports ECC RMW or not */
+	if (value == 0x40461C02)
+		return 1;
+
+	return 0;
+}
+
+static void ddr3_ecc_config(u32 base, u32 value)
+{
+	u32 data;
+
+	__raw_writel(value,  base + KS2_DDR3_ECC_CTRL_OFFSET);
+	udelay(100000); /* delay required to synchronize across clock domains */
+
+	if (value & KS2_DDR3_ECC_EN) {
+		/* Clear the 1-bit error count */
+		data = __raw_readl(base + KS2_DDR3_ONE_BIT_ECC_ERR_CNT_OFFSET);
+		__raw_writel(data, base + KS2_DDR3_ONE_BIT_ECC_ERR_CNT_OFFSET);
+
+		/* enable the ECC interrupt */
+		__raw_writel(KS2_DDR3_1B_ECC_ERR_SYS | KS2_DDR3_2B_ECC_ERR_SYS |
+			     KS2_DDR3_WR_ECC_ERR_SYS,
+			     base + KS2_DDR3_ECC_INT_ENABLE_SET_SYS_OFFSET);
+
+		/* Clear the ECC error interrupt status */
+		__raw_writel(KS2_DDR3_1B_ECC_ERR_SYS | KS2_DDR3_2B_ECC_ERR_SYS |
+			     KS2_DDR3_WR_ECC_ERR_SYS,
+			     base + KS2_DDR3_ECC_INT_STATUS_OFFSET);
+	}
+}
+
+static void ddr3_reset_data(u32 base, u32 ddr3_size)
+{
+	u32 mpax[2];
+	u32 seg_num;
+	u32 seg, blks, dst, edma_blks;
+	struct edma3_slot_config slot;
+	struct edma3_channel_config edma_channel;
+	u32 edma_src[DDR3_EDMA_BLK_SIZE/4] __aligned(16) = {0, };
+
+	/* Setup an edma to copy the 1k block to the entire DDR */
+	puts("\nClear entire DDR3 memory to enable ECC\n");
+
+	/* save the SES MPAX regs */
+	msmc_get_ses_mpax(8, 0, mpax);
+
+	/* setup edma slot 1 configuration */
+	slot.opt = EDMA3_SLOPT_TRANS_COMP_INT_ENB |
+		   EDMA3_SLOPT_COMP_CODE(0) |
+		   EDMA3_SLOPT_STATIC | EDMA3_SLOPT_AB_SYNC;
+	slot.bcnt = DDR3_EDMA_BCNT;
+	slot.acnt = DDR3_EDMA_BLK_SIZE;
+	slot.ccnt = DDR3_EDMA_CCNT;
+	slot.src_bidx = 0;
+	slot.dst_bidx = DDR3_EDMA_BLK_SIZE;
+	slot.src_cidx = 0;
+	slot.dst_cidx = 0;
+	slot.link = EDMA3_PARSET_NULL_LINK;
+	slot.bcntrld = 0;
+	edma3_slot_configure(KS2_EDMA0_BASE, DDR3_EDMA_SLOT_NUM, &slot);
+
+	/* configure quik edma channel */
+	edma_channel.slot = DDR3_EDMA_SLOT_NUM;
+	edma_channel.chnum = 0;
+	edma_channel.complete_code = 0;
+	/* event trigger after dst update */
+	edma_channel.trigger_slot_word = EDMA3_TWORD(dst);
+	qedma3_start(KS2_EDMA0_BASE, &edma_channel);
+
+	/* DDR3 size in segments (4KB seg size) */
+	seg_num = ddr3_size << (30 - KS2_MSMC_SEG_SIZE_SHIFT);
+
+	for (seg = 0; seg < seg_num; seg += KS2_MSMC_MAP_SEG_NUM) {
+		/* map 2GB 36-bit DDR address to 32-bit DDR address in EMIF
+		   access slave interface so that edma driver can access */
+		msmc_map_ses_segment(8, 0, base >> KS2_MSMC_SEG_SIZE_SHIFT,
+				     KS2_MSMC_DST_SEG_BASE + seg, MPAX_SEG_2G);
+
+		if ((seg_num - seg) > KS2_MSMC_MAP_SEG_NUM)
+			edma_blks = KS2_MSMC_MAP_SEG_NUM <<
+					(KS2_MSMC_SEG_SIZE_SHIFT
+					- DDR3_EDMA_BLK_SIZE_SHIFT);
+		else
+			edma_blks = (seg_num - seg) << (KS2_MSMC_SEG_SIZE_SHIFT
+					- DDR3_EDMA_BLK_SIZE_SHIFT);
+
+		/* Use edma driver to scrub 2GB DDR memory */
+		for (dst = base, blks = 0; blks < edma_blks;
+		     blks += DDR3_EDMA_BCNT, dst += DDR3_EDMA_XF_SIZE) {
+			edma3_set_src_addr(KS2_EDMA0_BASE,
+					   edma_channel.slot, (u32)edma_src);
+			edma3_set_dest_addr(KS2_EDMA0_BASE,
+					    edma_channel.slot, (u32)dst);
+
+			while (edma3_check_for_transfer(KS2_EDMA0_BASE,
+							&edma_channel))
+				udelay(10);
+		}
+	}
+
+	qedma3_stop(KS2_EDMA0_BASE, &edma_channel);
+
+	/* restore the SES MPAX regs */
+	msmc_set_ses_mpax(8, 0, mpax);
+}
+
+static void ddr3_ecc_init_range(u32 base)
+{
+	u32 ecc_val = KS2_DDR3_ECC_EN;
+	u32 rmw = ddr3_ecc_support_rmw(base);
+
+	if (rmw)
+		ecc_val |= KS2_DDR3_ECC_RMW_EN;
+
+	__raw_writel(0, base + KS2_DDR3_ECC_ADDR_RANGE1_OFFSET);
+
+	ddr3_ecc_config(base, ecc_val);
+}
+
+void ddr3_enable_ecc(u32 base, int test)
+{
+	u32 ecc_val = KS2_DDR3_ECC_ENABLE;
+	u32 rmw = ddr3_ecc_support_rmw(base);
+
+	if (test)
+		ecc_val |= KS2_DDR3_ECC_ADDR_RNG_1_EN;
+
+	if (!rmw) {
+		if (!test)
+			/* by default, disable ecc when rmw = 0 and no
+			   ecc test */
+			ecc_val = 0;
+	} else {
+		ecc_val |= KS2_DDR3_ECC_RMW_EN;
+	}
+
+	ddr3_ecc_config(base, ecc_val);
+}
+
+void ddr3_disable_ecc(u32 base)
+{
+	ddr3_ecc_config(base, 0);
+}
+
+#if defined(CONFIG_SOC_K2HK) || defined(CONFIG_SOC_K2L)
+static void cic_init(u32 base)
+{
+	/* Disable CIC global interrupts */
+	__raw_writel(0, base + KS2_CIC_GLOBAL_ENABLE);
+
+	/* Set to normal mode, no nesting, no priority hold */
+	__raw_writel(0, base + KS2_CIC_CTRL);
+	__raw_writel(0, base + KS2_CIC_HOST_CTRL);
+
+	/* Enable CIC global interrupts */
+	__raw_writel(1, base + KS2_CIC_GLOBAL_ENABLE);
+}
+
+static void cic_map_cic_to_gic(u32 base, u32 chan_num, u32 irq_num)
+{
+	/* Map the system interrupt to a CIC channel */
+	__raw_writeb(chan_num, base + KS2_CIC_CHAN_MAP(0) + irq_num);
+
+	/* Enable CIC system interrupt */
+	__raw_writel(irq_num, base + KS2_CIC_SYS_ENABLE_IDX_SET);
+
+	/* Enable CIC Host interrupt */
+	__raw_writel(chan_num, base + KS2_CIC_HOST_ENABLE_IDX_SET);
+}
+
+static void ddr3_map_ecc_cic2_irq(u32 base)
+{
+	cic_init(base);
+	cic_map_cic_to_gic(base, KS2_CIC2_DDR3_ECC_CHAN_NUM,
+			   KS2_CIC2_DDR3_ECC_IRQ_NUM);
+}
+#endif
+
+void ddr3_init_ecc(u32 base)
+{
+	u32 ddr3_size;
+
+	if (!ddr3_ecc_support_rmw(base)) {
+		ddr3_disable_ecc(base);
+		return;
+	}
+
+	ddr3_ecc_init_range(base);
+	ddr3_size = ddr3_get_size();
+	ddr3_reset_data(CONFIG_SYS_SDRAM_BASE, ddr3_size);
+
+	/* mapping DDR3 ECC system interrupt from CIC2 to GIC */
+#if defined(CONFIG_SOC_K2HK) || defined(CONFIG_SOC_K2L)
+	ddr3_map_ecc_cic2_irq(KS2_CIC2_BASE);
+#endif
+	ddr3_enable_ecc(base, 0);
+}
+
+void ddr3_check_ecc_int(u32 base)
+{
+	char *env;
+	int ecc_test = 0;
+	u32 value = __raw_readl(base + KS2_DDR3_ECC_INT_STATUS_OFFSET);
+
+	env = getenv("ecc_test");
+	if (env)
+		ecc_test = simple_strtol(env, NULL, 0);
+
+	if (value & KS2_DDR3_WR_ECC_ERR_SYS)
+		puts("DDR3 ECC write error interrupted\n");
+
+	if (value & KS2_DDR3_2B_ECC_ERR_SYS) {
+		puts("DDR3 ECC 2-bit error interrupted\n");
+
+		if (!ecc_test) {
+			puts("Reseting the device ...\n");
+			reset_cpu(0);
+		}
+	}
+
+	value = __raw_readl(base + KS2_DDR3_ONE_BIT_ECC_ERR_CNT_OFFSET);
+	if (value) {
+		printf("1-bit ECC err count: 0x%x\n", value);
+		value = __raw_readl(base +
+				    KS2_DDR3_ONE_BIT_ECC_ERR_ADDR_LOG_OFFSET);
+		printf("1-bit ECC err address log: 0x%x\n", value);
+	}
+}
+
 void ddr3_reset_ddrphy(void)
 {
 	u32 tmp;
diff --git a/arch/arm/include/asm/arch-keystone/ddr3.h b/arch/arm/include/asm/arch-keystone/ddr3.h
index 6bf35d354366d1aba944d09960f2f571d7016f47..b044d6f18ff2473f44060aab7816f3329e46a097 100644
--- a/arch/arm/include/asm/arch-keystone/ddr3.h
+++ b/arch/arm/include/asm/arch-keystone/ddr3.h
@@ -49,8 +49,14 @@ struct ddr3_emif_config {
 };
 
 void ddr3_init(void);
+int ddr3_get_size(void);
 void ddr3_reset_ddrphy(void);
+void ddr3_init_ecc(u32 base);
+void ddr3_disable_ecc(u32 base);
+void ddr3_check_ecc_int(u32 base);
+int ddr3_ecc_support_rmw(u32 base);
 void ddr3_err_reset_workaround(void);
+void ddr3_enable_ecc(u32 base, int test);
 void ddr3_init_ddrphy(u32 base, struct ddr3_phy_config *phy_cfg);
 void ddr3_init_ddremif(u32 base, struct ddr3_emif_config *emif_cfg);
 
diff --git a/arch/arm/include/asm/arch-keystone/hardware-k2hk.h b/arch/arm/include/asm/arch-keystone/hardware-k2hk.h
index 28de3f5010703c0dc636ccad06263758f84385f4..5a9ea4fbca56dd089af020ab55a9c91c2c3dd2d2 100644
--- a/arch/arm/include/asm/arch-keystone/hardware-k2hk.h
+++ b/arch/arm/include/asm/arch-keystone/hardware-k2hk.h
@@ -79,6 +79,10 @@
 #define KS2_DDR3B_EMIF_DATA_BASE	0x60000000
 #define KS2_DDR3B_DDRPHYC		0x02328000
 
+#define KS2_CIC2_DDR3_ECC_IRQ_NUM	0x0D3 /* DDR3 ECC system irq number */
+#define KS2_CIC2_DDR3_ECC_CHAN_NUM	0x01D /* DDR3 ECC int mapped to CIC2
+						 channel 29 */
+
 /* SGMII SerDes */
 #define KS2_LANES_PER_SGMII_SERDES	4
 
diff --git a/arch/arm/include/asm/arch-keystone/hardware.h b/arch/arm/include/asm/arch-keystone/hardware.h
index 8e0b8798b8c672e8180298caa74d9292737b926d..c6a54d8b91bac618df69390599f6af73d44d5fb5 100644
--- a/arch/arm/include/asm/arch-keystone/hardware.h
+++ b/arch/arm/include/asm/arch-keystone/hardware.h
@@ -87,6 +87,52 @@ typedef volatile unsigned int   *dv_reg_p;
 
 #define KS2_DDR3_PLLCTRL_PHY_RESET	0x80000000
 
+/* DDR3 ECC */
+#define KS2_DDR3_ECC_INT_STATUS_OFFSET			0x0AC
+#define KS2_DDR3_ECC_INT_ENABLE_SET_SYS_OFFSET		0x0B4
+#define KS2_DDR3_ECC_CTRL_OFFSET			0x110
+#define KS2_DDR3_ECC_ADDR_RANGE1_OFFSET			0x114
+#define KS2_DDR3_ONE_BIT_ECC_ERR_CNT_OFFSET		0x130
+#define KS2_DDR3_ONE_BIT_ECC_ERR_ADDR_LOG_OFFSET	0x13C
+
+/* DDR3 ECC Interrupt Status register */
+#define KS2_DDR3_1B_ECC_ERR_SYS		BIT(5)
+#define KS2_DDR3_2B_ECC_ERR_SYS		BIT(4)
+#define KS2_DDR3_WR_ECC_ERR_SYS		BIT(3)
+
+/* DDR3 ECC Control register */
+#define KS2_DDR3_ECC_EN			BIT(31)
+#define KS2_DDR3_ECC_ADDR_RNG_PROT	BIT(30)
+#define KS2_DDR3_ECC_VERIFY_EN		BIT(29)
+#define KS2_DDR3_ECC_RMW_EN		BIT(28)
+#define KS2_DDR3_ECC_ADDR_RNG_1_EN	BIT(0)
+
+#define KS2_DDR3_ECC_ENABLE		(KS2_DDR3_ECC_EN | \
+					KS2_DDR3_ECC_ADDR_RNG_PROT | \
+					KS2_DDR3_ECC_VERIFY_EN)
+
+/* EDMA */
+#define KS2_EDMA0_BASE			0x02700000
+
+/* EDMA3 register offsets */
+#define KS2_EDMA_QCHMAP0		0x0200
+#define KS2_EDMA_IPR			0x1068
+#define KS2_EDMA_ICR			0x1070
+#define KS2_EDMA_QEECR			0x1088
+#define KS2_EDMA_QEESR			0x108c
+#define KS2_EDMA_PARAM_1(x)		(0x4020 + (4 * x))
+
+/* Chip Interrupt Controller */
+#define KS2_CIC2_BASE			0x02608000
+
+/* Chip Interrupt Controller register offsets */
+#define KS2_CIC_CTRL			0x04
+#define KS2_CIC_HOST_CTRL		0x0C
+#define KS2_CIC_GLOBAL_ENABLE		0x10
+#define KS2_CIC_SYS_ENABLE_IDX_SET	0x28
+#define KS2_CIC_HOST_ENABLE_IDX_SET	0x34
+#define KS2_CIC_CHAN_MAP(n)		(0x0400 + (n << 2))
+
 #define KS2_UART0_BASE                	0x02530c00
 #define KS2_UART1_BASE                	0x02531000
 
diff --git a/board/ti/ks2_evm/board.c b/board/ti/ks2_evm/board.c
index 899178606383da9d9b2038c20f853c945fdd15a8..40294934525c9b0518d2a53118c45c6da22fdc13 100644
--- a/board/ti/ks2_evm/board.c
+++ b/board/ti/ks2_evm/board.c
@@ -40,6 +40,7 @@ int dram_init(void)
 	gd->ram_size = get_ram_size((long *)CONFIG_SYS_SDRAM_BASE,
 				    CONFIG_MAX_RAM_BANK_SIZE);
 	aemif_init(ARRAY_SIZE(aemif_configs), aemif_configs);
+	ddr3_init_ecc(KS2_DDR3A_EMIF_CTRL_BASE);
 	return 0;
 }
 
@@ -254,5 +255,7 @@ void ft_board_setup_ex(void *blob, bd_t *bd)
 			reserve_start += 2;
 		}
 	}
+
+	ddr3_check_ecc_int(KS2_DDR3A_EMIF_CTRL_BASE);
 }
 #endif
diff --git a/board/ti/ks2_evm/ddr3_k2hk.c b/board/ti/ks2_evm/ddr3_k2hk.c
index 6070a9977029ad1fc8d222bd9f4381b0f823264e..a1c3d05f8e50e2f7d4f2a62097f8e46379f0aaaa 100644
--- a/board/ti/ks2_evm/ddr3_k2hk.c
+++ b/board/ti/ks2_evm/ddr3_k2hk.c
@@ -12,6 +12,8 @@
 #include <asm/arch/ddr3.h>
 #include <asm/arch/hardware.h>
 
+static int ddr3_size;
+
 struct pll_init_data ddr3a_333 = DDR3_PLL_333(A);
 struct pll_init_data ddr3a_400 = DDR3_PLL_400(A);
 
@@ -44,12 +46,14 @@ void ddr3_init(void)
 			ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE,
 					  &ddr3_1600_8g);
 			printf("DRAM:  Capacity 8 GiB (includes reported below)\n");
+			ddr3_size = 8;
 		} else {
 			ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, &ddr3phy_1600_8g);
 			ddr3_1600_8g.sdcfg |= 0x1000;
 			ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE,
 					  &ddr3_1600_8g);
 			printf("DRAM:  Capacity 4 GiB (includes reported below)\n");
+			ddr3_size = 4;
 		}
 	} else if (!strcmp(dimm_name, "SQR-SD3T-2G1333SED")) {
 		init_pll(&ddr3a_333);
@@ -70,11 +74,15 @@ void ddr3_init(void)
 			}
 			ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE,
 					  &ddr3_1333_2g);
+			ddr3_size = 2;
+			printf("DRAM:  2 GiB");
 		} else {
 			ddr3_init_ddrphy(KS2_DDR3A_DDRPHYC, &ddr3phy_1333_2g);
 			ddr3_1333_2g.sdcfg |= 0x1000;
 			ddr3_init_ddremif(KS2_DDR3A_EMIF_CTRL_BASE,
 					  &ddr3_1333_2g);
+			ddr3_size = 1;
+			printf("DRAM:  1 GiB");
 		}
 	} else {
 		printf("Unknown SO-DIMM. Cannot configure DDR3\n");
@@ -86,3 +94,11 @@ void ddr3_init(void)
 	if (cpu_revision() <= 1)
 		ddr3_err_reset_workaround();
 }
+
+/**
+ * ddr3_get_size - return ddr3 size in GiB
+ */
+int ddr3_get_size(void)
+{
+	return ddr3_size;
+}