diff --git a/arch/arm/cpu/armv7/am33xx/ddr.c b/arch/arm/cpu/armv7/am33xx/ddr.c
index f5b16b4b722605729997892d41007580690ddb58..b3fb0c47ab2dfba7d393c4a3b9d5717031b030af 100644
--- a/arch/arm/cpu/armv7/am33xx/ddr.c
+++ b/arch/arm/cpu/armv7/am33xx/ddr.c
@@ -123,30 +123,33 @@ void config_sdram_emif4d5(const struct emif_regs *regs, int nr)
 	writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl);
 	writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl_shdw);
 
-	/* Perform hardware leveling. */
-	udelay(1000);
-	writel(readl(&emif_reg[nr]->emif_ddr_ext_phy_ctrl_36) |
-	       0x100, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_36);
-	writel(readl(&emif_reg[nr]->emif_ddr_ext_phy_ctrl_36_shdw) |
-	       0x100, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_36_shdw);
-
-	writel(0x80000000, &emif_reg[nr]->emif_rd_wr_lvl_rmp_ctl);
-
-	/* Enable read leveling */
-	writel(0x80000000, &emif_reg[nr]->emif_rd_wr_lvl_ctl);
-
-	/*
-	 * Enable full read and write leveling.  Wait for read and write
-	 * leveling bit to clear RDWRLVLFULL_START bit 31
-	 */
-	while((readl(&emif_reg[nr]->emif_rd_wr_lvl_ctl) & 0x80000000) != 0)
-		;
-
-	/* Check the timeout register to see if leveling is complete */
-	if((readl(&emif_reg[nr]->emif_status) & 0x70) != 0)
-		puts("DDR3 H/W leveling incomplete with errors\n");
-
-	if (emif_sdram_type() == EMIF_SDRAM_TYPE_LPDDR2) {
+	/* Perform hardware leveling for DDR3 */
+	if (emif_sdram_type(regs->sdram_config) == EMIF_SDRAM_TYPE_DDR3) {
+		udelay(1000);
+		writel(readl(&emif_reg[nr]->emif_ddr_ext_phy_ctrl_36) |
+		       0x100, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_36);
+		writel(readl(&emif_reg[nr]->emif_ddr_ext_phy_ctrl_36_shdw) |
+		       0x100, &emif_reg[nr]->emif_ddr_ext_phy_ctrl_36_shdw);
+
+		writel(0x80000000, &emif_reg[nr]->emif_rd_wr_lvl_rmp_ctl);
+
+		/* Enable read leveling */
+		writel(0x80000000, &emif_reg[nr]->emif_rd_wr_lvl_ctl);
+
+		/*
+		 * Enable full read and write leveling.  Wait for read and write
+		 * leveling bit to clear RDWRLVLFULL_START bit 31
+		 */
+		while ((readl(&emif_reg[nr]->emif_rd_wr_lvl_ctl) & 0x80000000)
+		      != 0)
+			;
+
+		/* Check the timeout register to see if leveling is complete */
+		if ((readl(&emif_reg[nr]->emif_status) & 0x70) != 0)
+			puts("DDR3 H/W leveling incomplete with errors\n");
+
+	} else {
+		/* DDR2 */
 		configure_mr(nr, 0);
 		configure_mr(nr, 1);
 	}
@@ -182,10 +185,50 @@ void set_sdram_timings(const struct emif_regs *regs, int nr)
 	writel(regs->sdram_tim3, &emif_reg[nr]->emif_sdram_tim_3_shdw);
 }
 
+/*
+ * Configure EXT PHY registers for software leveling
+ */
+static void ext_phy_settings_swlvl(const struct emif_regs *regs, int nr)
+{
+	u32 *ext_phy_ctrl_base = 0;
+	u32 *emif_ext_phy_ctrl_base = 0;
+	__maybe_unused const u32 *ext_phy_ctrl_const_regs;
+	u32 i = 0;
+	__maybe_unused u32 size;
+
+	ext_phy_ctrl_base = (u32 *)&(regs->emif_ddr_ext_phy_ctrl_1);
+	emif_ext_phy_ctrl_base =
+			(u32 *)&(emif_reg[nr]->emif_ddr_ext_phy_ctrl_1);
+
+	/* Configure external phy control timing registers */
+	for (i = 0; i < EMIF_EXT_PHY_CTRL_TIMING_REG; i++) {
+		writel(*ext_phy_ctrl_base, emif_ext_phy_ctrl_base++);
+		/* Update shadow registers */
+		writel(*ext_phy_ctrl_base++, emif_ext_phy_ctrl_base++);
+	}
+
+#ifdef CONFIG_AM43XX
+	/*
+	 * External phy 6-24 registers do not change with ddr frequency.
+	 * These only need to be set on DDR2 on AM43xx.
+	 */
+	emif_get_ext_phy_ctrl_const_regs(&ext_phy_ctrl_const_regs, &size);
+
+	if (!size)
+		return;
+
+	for (i = 0; i < size; i++) {
+		writel(ext_phy_ctrl_const_regs[i], emif_ext_phy_ctrl_base++);
+		/* Update shadow registers */
+		writel(ext_phy_ctrl_const_regs[i], emif_ext_phy_ctrl_base++);
+	}
+#endif
+}
+
 /*
  * Configure EXT PHY registers for hardware leveling
  */
-static void ext_phy_settings(const struct emif_regs *regs, int nr)
+static void ext_phy_settings_hwlvl(const struct emif_regs *regs, int nr)
 {
 	/*
 	 * Enable hardware leveling on the EMIF.  For details about these
@@ -256,8 +299,12 @@ void config_ddr_phy(const struct emif_regs *regs, int nr)
 	writel(regs->emif_ddr_phy_ctlr_1,
 		&emif_reg[nr]->emif_ddr_phy_ctrl_1_shdw);
 
-	if (get_emif_rev((u32)emif_reg[nr]) == EMIF_4D5)
-		ext_phy_settings(regs, nr);
+	if (get_emif_rev((u32)emif_reg[nr]) == EMIF_4D5) {
+		if (emif_sdram_type(regs->sdram_config) == EMIF_SDRAM_TYPE_DDR3)
+			ext_phy_settings_hwlvl(regs, nr);
+		else
+			ext_phy_settings_swlvl(regs, nr);
+	}
 }
 
 /**
diff --git a/arch/arm/cpu/armv7/am33xx/emif4.c b/arch/arm/cpu/armv7/am33xx/emif4.c
index 9cf816c89a627b32230f5b03d00c2e5ba3b01069..27fa3fb4628bbfa08ff38a29386d09144e799668 100644
--- a/arch/arm/cpu/armv7/am33xx/emif4.c
+++ b/arch/arm/cpu/armv7/am33xx/emif4.c
@@ -124,8 +124,9 @@ void config_ddr(unsigned int pll, const struct ctrl_ioregs *ioregs,
 	/* Set CKE to be controlled by EMIF/DDR PHY */
 	writel(DDR_CKE_CTRL_NORMAL, &ddrctrl->ddrckectrl);
 
-	/* Allow EMIF to control DDR_RESET */
-	writel(0x00000000, &ddrctrl->ddrioctrl);
+	if (emif_sdram_type(regs->sdram_config) == EMIF_SDRAM_TYPE_DDR3)
+		/* Allow EMIF to control DDR_RESET */
+		writel(0x00000000, &ddrctrl->ddrioctrl);
 #endif
 
 	/* Program EMIF instance */
diff --git a/arch/arm/cpu/armv7/omap-common/clocks-common.c b/arch/arm/cpu/armv7/omap-common/clocks-common.c
index fa04bbedf9ea780841f7b96fc37d79f2351581ee..c94a807819310fb2a3b00e7a79d45ce3074a3eb0 100644
--- a/arch/arm/cpu/armv7/omap-common/clocks-common.c
+++ b/arch/arm/cpu/armv7/omap-common/clocks-common.c
@@ -372,6 +372,7 @@ static void setup_dplls(void)
 {
 	u32 temp;
 	const struct dpll_params *params;
+	struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
 
 	debug("setup_dplls\n");
 
@@ -382,7 +383,8 @@ static void setup_dplls(void)
 	 * Core DPLL will be locked after setting up EMIF
 	 * using the FREQ_UPDATE method(freq_update_core())
 	 */
-	if (emif_sdram_type() == EMIF_SDRAM_TYPE_LPDDR2)
+	if (emif_sdram_type(readl(&emif->emif_sdram_config)) ==
+	    EMIF_SDRAM_TYPE_LPDDR2)
 		do_setup_dpll((*prcm)->cm_clkmode_dpll_core, params,
 							DPLL_NO_LOCK, "core");
 	else
diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c
index 3ee4695ea31755486be60441c00417e676fbfccb..ca22c0060182d776c3240e7632b0e4544e9697b2 100644
--- a/arch/arm/cpu/armv7/omap-common/emif-common.c
+++ b/arch/arm/cpu/armv7/omap-common/emif-common.c
@@ -1171,12 +1171,14 @@ static void do_sdram_init(u32 base)
 	 * OPP to another)
 	 */
 	if (!(in_sdram || warm_reset())) {
-		if (emif_sdram_type() == EMIF_SDRAM_TYPE_LPDDR2)
+		if (emif_sdram_type(regs->sdram_config) ==
+		    EMIF_SDRAM_TYPE_LPDDR2)
 			lpddr2_init(base, regs);
 		else
 			ddr3_init(base, regs);
 	}
-	if (warm_reset() && (emif_sdram_type() == EMIF_SDRAM_TYPE_DDR3)) {
+	if (warm_reset() && (emif_sdram_type(regs->sdram_config) ==
+	    EMIF_SDRAM_TYPE_DDR3)) {
 		set_lpmode_selfrefresh(base);
 		emif_reset_phy(base);
 		omap5_ddr3_leveling(base, regs);
@@ -1398,7 +1400,8 @@ static void do_bug0039_workaround(u32 base)
 void sdram_init(void)
 {
 	u32 in_sdram, size_prog, size_detect;
-	u32 sdram_type = emif_sdram_type();
+	struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
+	u32 sdram_type = emif_sdram_type(emif->emif_sdram_config);
 
 	debug(">>sdram_init()\n");
 
diff --git a/arch/arm/cpu/armv7/omap5/hwinit.c b/arch/arm/cpu/armv7/omap5/hwinit.c
index 222540f9c1f189b7fdaeed0a69764f1ee2d6201e..39f8d0d5e20013d7a269e29682db436fbc18f8af 100644
--- a/arch/arm/cpu/armv7/omap5/hwinit.c
+++ b/arch/arm/cpu/armv7/omap5/hwinit.c
@@ -122,6 +122,7 @@ static void io_settings_ddr3(void)
 void do_io_settings(void)
 {
 	u32 io_settings = 0, mask = 0;
+	struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
 
 	/* Impedance settings EMMC, C2C 1,2, hsi2 */
 	mask = (ds_mask << 2) | (ds_mask << 8) |
@@ -177,7 +178,7 @@ void do_io_settings(void)
 		       (sc_fast << 17) | (sc_fast << 14);
 	writel(io_settings, (*ctrl)->control_smart3io_padconf_1);
 
-	if (emif_sdram_type() == EMIF_SDRAM_TYPE_LPDDR2)
+	if (emif_sdram_type(emif->emif_sdram_config) == EMIF_SDRAM_TYPE_LPDDR2)
 		io_settings_lpddr2();
 	else
 		io_settings_ddr3();
diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h
index a97d2fd4eade83e3bdcccb9ffa81d2841d55adf7..7986e6e7949094d23995977f87f78c29435cf466 100644
--- a/arch/arm/include/asm/emif.h
+++ b/arch/arm/include/asm/emif.h
@@ -1209,12 +1209,10 @@ static inline u32 get_emif_rev(u32 base)
  * which is typically the case. So it is sufficient to get
  * SDRAM type from EMIF1.
  */
-static inline u32 emif_sdram_type(void)
+static inline u32 emif_sdram_type(u32 sdram_config)
 {
-	struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
-
-	return (readl(&emif->emif_sdram_config) &
-		EMIF_REG_SDRAM_TYPE_MASK) >> EMIF_REG_SDRAM_TYPE_SHIFT;
+	return (sdram_config & EMIF_REG_SDRAM_TYPE_MASK)
+	       >> EMIF_REG_SDRAM_TYPE_SHIFT;
 }
 
 /* assert macros */
@@ -1244,6 +1242,5 @@ extern u32 *const T_den;
 #endif
 
 void config_data_eye_leveling_samples(u32 emif_base);
-u32 emif_sdram_type(void);
 const struct read_write_regs *get_bug_regs(u32 *iterations);
 #endif
diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c
index 4aae2306086bda50724e227543857d9837768648..d7b9e5af88fc8ed6bf3a2f1a1d8d4a48cf12db87 100644
--- a/board/ti/am43xx/board.c
+++ b/board/ti/am43xx/board.c
@@ -148,6 +148,29 @@ static const struct dpll_params idk_dpll_ddr = {
 	400, 23, 1, -1, 2, -1, -1
 };
 
+static const u32 ext_phy_ctrl_const_base_lpddr2[] = {
+	0x00500050,
+	0x00350035,
+	0x00350035,
+	0x00350035,
+	0x00350035,
+	0x00350035,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40001000,
+	0x08102040
+};
+
 const struct ctrl_ioregs ioregs_lpddr2 = {
 	.cm0ioctl		= LPDDR2_ADDRCTRL_IOCTRL_VALUE,
 	.cm1ioctl		= LPDDR2_ADDRCTRL_WD0_IOCTRL_VALUE,
@@ -318,6 +341,16 @@ static const struct emif_regs ddr3_idk_emif_regs_400Mhz = {
 	.emif_cos_config		= 0x00ffffff
 };
 
+void emif_get_ext_phy_ctrl_const_regs(const u32 **regs, u32 *size)
+{
+	if (board_is_eposevm()) {
+		*regs = ext_phy_ctrl_const_base_lpddr2;
+		*size = ARRAY_SIZE(ext_phy_ctrl_const_base_lpddr2);
+	}
+
+	return;
+}
+
 /*
  * get_sys_clk_index : returns the index of the sys_clk read from
  *			ctrl status register. This value is either