diff --git a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
index 088cf4564718949733cd8c70609b35c328481837..8bed5fe925b8130ecc1d14aba850881c8242fa02 100644
--- a/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
+++ b/arch/powerpc/cpu/mpc85xx/ddr-gen3.c
@@ -18,12 +18,13 @@
 void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 			     unsigned int ctrl_num)
 {
-	unsigned int i;
+	unsigned int i, bus_width;
 	volatile ccsr_ddr_t *ddr;
 	u32 temp_sdram_cfg;
+	u32 total_gb_size_per_controller;
+	int timeout, timeout_save;
 #ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134
 	volatile ccsr_local_ecm_t *ecm = (void *)CONFIG_SYS_MPC85xx_ECM_ADDR;
-	u32 total_gb_size_per_controller;
 	unsigned int csn_bnds_backup = 0, cs_sa, cs_ea, *csn_bnds_t;
 	int csn = -1;
 #endif
@@ -52,8 +53,8 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 		return;
 	}
 
-	out_be32(&ddr->eor, regs->ddr_eor);
-
+	if (regs->ddr_eor)
+		out_be32(&ddr->eor, regs->ddr_eor);
 #ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134
 	debug("Workaround for ERRATUM_DDR111_DDR134\n");
 	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
@@ -275,9 +276,46 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 	out_be32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN);
 	asm volatile("sync;isync");
 
+	total_gb_size_per_controller = 0;
+	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
+		if (!(regs->cs[i].config & 0x80000000))
+			continue;
+		total_gb_size_per_controller += 1 << (
+			((regs->cs[i].config >> 14) & 0x3) + 2 +
+			((regs->cs[i].config >> 8) & 0x7) + 12 +
+			((regs->cs[i].config >> 0) & 0x7) + 8 +
+			3 - ((regs->ddr_sdram_cfg >> 19) & 0x3) -
+			26);			/* minus 26 (count of 64M) */
+	}
+	if (fsl_ddr_get_intl3r() & 0x80000000)	/* 3-way interleaving */
+		total_gb_size_per_controller *= 3;
+	else if (regs->cs[0].config & 0x20000000) /* 2-way interleaving */
+		total_gb_size_per_controller <<= 1;
+	/*
+	 * total memory / bus width = transactions needed
+	 * transactions needed / data rate = seconds
+	 * to add plenty of buffer, double the time
+	 * For example, 2GB on 666MT/s 64-bit bus takes about 402ms
+	 * Let's wait for 800ms
+	 */
+	bus_width = 3 - ((ddr->sdram_cfg & SDRAM_CFG_DBW_MASK)
+			>> SDRAM_CFG_DBW_SHIFT);
+	timeout = ((total_gb_size_per_controller << (6 - bus_width)) * 100 /
+		(get_ddr_freq(0) >> 20)) << 1;
+	timeout_save = timeout;
+	total_gb_size_per_controller >>= 4;	/* shift down to gb size */
+	debug("total %d GB\n", total_gb_size_per_controller);
+	debug("Need to wait up to %d * 10ms\n", timeout);
+
 	/* Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done.  */
-	while (in_be32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT)
+	while ((in_be32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT) &&
+		(timeout >= 0)) {
 		udelay(10000);		/* throttle polling rate */
+		timeout--;
+	}
+
+	if (timeout <= 0)
+		printf("Waiting for D_INIT timeout. Memory may not work.\n");
 
 #ifdef CONFIG_SYS_FSL_ERRATUM_DDR111_DDR134
 	/* continue this workaround */
@@ -335,23 +373,9 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 	while (in_be32(&ddr->debug[1]) & 0x400)
 		udelay(10000);          /* throttle polling rate */
 
-	/* 7. Wait for 400ms/GB */
-	total_gb_size_per_controller = 0;
-	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) {
-		if (i == csn) {
-			total_gb_size_per_controller +=
-				((csn_bnds_backup & 0xFFFF) >> 6)
-				- (csn_bnds_backup >> 22) + 1;
-		} else {
-			total_gb_size_per_controller +=
-				((regs->cs[i].bnds & 0xFFFF) >> 6)
-				- (regs->cs[i].bnds >> 22) + 1;
-		}
-	}
-	if (in_be32(&ddr->sdram_cfg) & 0x80000)
-		total_gb_size_per_controller <<= 1;
-	debug("Wait for %d ms\n", total_gb_size_per_controller * 400);
-	udelay(total_gb_size_per_controller * 400000);
+	/* 7. Wait for state machine 2nd run, roughly 400ms/GB */
+	debug("Wait for %d * 10ms\n", timeout_save);
+	udelay(timeout_save * 10000);
 
 	/* 8. Set sdram_cfg_2[dinit] if options requires */
 	setbits_be32(&ddr->sdram_cfg_2,
@@ -359,8 +383,16 @@ void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 	debug("Setting sdram_cfg_2 to 0x%08x\n", in_be32(&ddr->sdram_cfg_2));
 
 	/* 9. Poll until dinit is cleared */
-	while (in_be32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT)
-		udelay(10000);
+	timeout = timeout_save;
+	debug("Need to wait up to %d * 10ms\n", timeout);
+	while ((in_be32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT) &&
+		(timeout >= 0)) {
+		udelay(10000);		/* throttle polling rate */
+		timeout--;
+	}
+
+	if (timeout <= 0)
+		printf("Waiting for D_INIT timeout. Memory may not work.\n");
 
 	/* 10. Clear EEBACR[3] */
 	clrbits_be32(&ecm->eebacr, 10000000);
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/main.c b/arch/powerpc/cpu/mpc8xxx/ddr/main.c
index b47268c20eacc22e31fe1314e3c18999b24ab9e4..2885906e875c6498136f9c6be35c9d1d38193655 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/main.c
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/main.c
@@ -526,6 +526,17 @@ phys_size_t fsl_ddr_sdram(void)
 #endif
 		total_memory = fsl_ddr_compute(&info, STEP_GET_SPD, 0);
 
+	/* setup 3-way interleaving before enabling DDRC */
+	switch (info.memctl_opts[0].memctl_interleaving_mode) {
+	case FSL_DDR_3WAY_1KB_INTERLEAVING:
+	case FSL_DDR_3WAY_4KB_INTERLEAVING:
+	case FSL_DDR_3WAY_8KB_INTERLEAVING:
+		fsl_ddr_set_intl3r(info.memctl_opts[0].memctl_interleaving_mode);
+		break;
+	default:
+		break;
+	}
+
 	/* Program configuration registers. */
 	for (i = 0; i < CONFIG_NUM_DDR_CONTROLLERS; i++) {
 		debug("Programming controller %u\n", i);
@@ -561,7 +572,6 @@ phys_size_t fsl_ddr_sdram(void)
 			case FSL_DDR_3WAY_8KB_INTERLEAVING:
 				law_memctl = LAW_TRGT_IF_DDR_INTLV_123;
 				if (i == 0) {
-					fsl_ddr_set_intl3r(info.memctl_opts[i].memctl_interleaving_mode);
 					fsl_ddr_set_lawbar(&info.common_timing_params[i],
 						law_memctl, i);
 				}
diff --git a/arch/powerpc/cpu/mpc8xxx/ddr/util.c b/arch/powerpc/cpu/mpc8xxx/ddr/util.c
index b439cc9750d33533e0bed793cac2240d8ac2d4b3..afc5fae497a3c9a1e4ee2cc726959ff82f1c9d28 100644
--- a/arch/powerpc/cpu/mpc8xxx/ddr/util.c
+++ b/arch/powerpc/cpu/mpc8xxx/ddr/util.c
@@ -142,13 +142,13 @@ void board_add_ram_info(int use_default)
 
 #if CONFIG_NUM_DDR_CONTROLLERS >= 2
 	if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) {
-		ddr = (void *)CONFIG_SYS_MPC85xx_DDR2_ADDR;
+		ddr = (void __iomem *)CONFIG_SYS_MPC85xx_DDR2_ADDR;
 		sdram_cfg = in_be32(&ddr->sdram_cfg);
 	}
 #endif
 #if CONFIG_NUM_DDR_CONTROLLERS >= 3
 	if (!(sdram_cfg & SDRAM_CFG_MEM_EN)) {
-		ddr = (void *)CONFIG_SYS_MPC85xx_DDR3_ADDR;
+		ddr = (void __iomem *)CONFIG_SYS_MPC85xx_DDR3_ADDR;
 		sdram_cfg = in_be32(&ddr->sdram_cfg);
 	}
 #endif
diff --git a/arch/powerpc/include/asm/fsl_ddr_sdram.h b/arch/powerpc/include/asm/fsl_ddr_sdram.h
index bb79335b188ec896889ceb62c738b5cc49237454..640d3297d6c89a36725eacd1413911e045d1456c 100644
--- a/arch/powerpc/include/asm/fsl_ddr_sdram.h
+++ b/arch/powerpc/include/asm/fsl_ddr_sdram.h
@@ -98,6 +98,7 @@ typedef ddr3_spd_eeprom_t generic_spd_eeprom_t;
 #define SDRAM_CFG_SDRAM_TYPE_SHIFT	24
 #define SDRAM_CFG_DYN_PWR		0x00200000
 #define SDRAM_CFG_DBW_MASK		0x00180000
+#define SDRAM_CFG_DBW_SHIFT		19
 #define SDRAM_CFG_32_BE			0x00080000
 #define SDRAM_CFG_16_BE			0x00100000
 #define SDRAM_CFG_8_BE			0x00040000
@@ -330,6 +331,7 @@ extern phys_size_t fsl_ddr_sdram_size(void);
 extern int fsl_use_spd(void);
 extern void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs,
 					unsigned int ctrl_num);
+u32 fsl_ddr_get_intl3r(void);
 
 /*
  * The 85xx boards have a common prototype for fixed_sdram so put the