diff mbox

[U-Boot,12/14] ARM: AM43xx: EPOS_EVM: Add support for LPDDR2

Message ID 1383625260-22294-13-git-send-email-lokeshvutla@ti.com
State Changes Requested
Delegated to: Tom Rini
Headers show

Commit Message

Lokesh Vutla Nov. 5, 2013, 4:20 a.m. UTC
AM4372 EPOS EVM has 1GB LPDDR2(Part no: MT42L256M32D2LG-25 WT:A)
Adding LPDDR2 init sequence and register details for the same.
Below is the brief description of LPDDR2 init sequence:
-> Configure VTP
-> Configure DDR IO settings
-> Disable initialization and refreshes until EMIF registers are programmed.
-> Program Timing registers
-> Program PHY control and Temp alert and ZQ config registers.
-> Enable initialization and refreshes and configure SDRAM CONFIG register
-> Wait till initialization is complete and the configure MR registers.

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
---
 arch/arm/cpu/armv7/am33xx/Makefile                 |    8 +-
 arch/arm/cpu/armv7/am33xx/emif4d5.c                |  183 ++++++++++++++++++++
 arch/arm/include/asm/arch-am33xx/clocks_am33xx.h   |    3 +
 arch/arm/include/asm/arch-am33xx/cpu.h             |    5 +
 arch/arm/include/asm/arch-am33xx/ddr_defs.h        |   26 +++
 arch/arm/include/asm/arch-am33xx/hardware_am43xx.h |    1 +
 arch/arm/include/asm/emif.h                        |   12 ++
 board/ti/am43xx/board.c                            |   59 +++++++
 8 files changed, 295 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/cpu/armv7/am33xx/emif4d5.c

Comments

Vaibhav Bedia Nov. 6, 2013, 12:57 p.m. UTC | #1
On Mon, Nov 4, 2013 at 11:20 PM, Lokesh Vutla <lokeshvutla@ti.com> wrote:
> AM4372 EPOS EVM has 1GB LPDDR2(Part no: MT42L256M32D2LG-25 WT:A)
> Adding LPDDR2 init sequence and register details for the same.
> Below is the brief description of LPDDR2 init sequence:
> -> Configure VTP
> -> Configure DDR IO settings
> -> Disable initialization and refreshes until EMIF registers are programmed.
> -> Program Timing registers
> -> Program PHY control and Temp alert and ZQ config registers.
> -> Enable initialization and refreshes and configure SDRAM CONFIG register
> -> Wait till initialization is complete and the configure MR registers.
>

Is there any public documentation to go with this?
I would suggest sprinkling the code with comments
to mention the different stages.

BTW, no IO powerdown setting for now?

[...]
>
> +ifeq ($(CONFIG_AM43XX),)
> +COBJS  += ddr.o
> +COBJS  += emif4.o
> +endif
> +COBJS-$(CONFIG_AM43XX) += emif4d5.o
> +

Are the steps really different enough to warrant a new file? Can't the changes
be handled properly in the code? How has this been handled in OMAPx where
DDR3 and LPDDR both are supported?

Regards,
Vaibhav
Lokesh Vutla Nov. 6, 2013, 1:45 p.m. UTC | #2
On Wednesday 06 November 2013 06:27 PM, Vaibhav Bedia wrote:
> On Mon, Nov 4, 2013 at 11:20 PM, Lokesh Vutla <lokeshvutla@ti.com> wrote:
>> AM4372 EPOS EVM has 1GB LPDDR2(Part no: MT42L256M32D2LG-25 WT:A)
>> Adding LPDDR2 init sequence and register details for the same.
>> Below is the brief description of LPDDR2 init sequence:
>> -> Configure VTP
>> -> Configure DDR IO settings
>> -> Disable initialization and refreshes until EMIF registers are programmed.
>> -> Program Timing registers
>> -> Program PHY control and Temp alert and ZQ config registers.
>> -> Enable initialization and refreshes and configure SDRAM CONFIG register
>> -> Wait till initialization is complete and the configure MR registers.
>>
> 
> Is there any public documentation to go with this?
> I would suggest sprinkling the code with comments
> to mention the different stages.
Yep ll add the comments in the code..
> 
> BTW, no IO powerdown setting for now?
You mean DDR IO settings?
> 
> [...]
>>
>> +ifeq ($(CONFIG_AM43XX),)
>> +COBJS  += ddr.o
>> +COBJS  += emif4.o
>> +endif
>> +COBJS-$(CONFIG_AM43XX) += emif4d5.o
>> +
> 
> Are the steps really different enough to warrant a new file? Can't the changes
> be handled properly in the code? How has this been handled in OMAPx where
> DDR3 and LPDDR both are supported?
Initially Tom also suggested not to use a new file. I tried with not to add a new file,
but I ended up with many #ifdefs. EMIF is new IP(reused from OMAP5) very different from AM33xx EMIF IP.
So to make things more cleaner I had to use a new file..

Thanks and regards,
Lokesh

> 
> Regards,
> Vaibhav
>
Vaibhav Bedia Nov. 6, 2013, 4:44 p.m. UTC | #3
On Wed, Nov 6, 2013 at 8:45 AM, Lokesh Vutla <lokeshvutla@ti.com> wrote:
> On Wednesday 06 November 2013 06:27 PM, Vaibhav Bedia wrote:
>> On Mon, Nov 4, 2013 at 11:20 PM, Lokesh Vutla <lokeshvutla@ti.com> wrote:
>>> AM4372 EPOS EVM has 1GB LPDDR2(Part no: MT42L256M32D2LG-25 WT:A)
>>> Adding LPDDR2 init sequence and register details for the same.
>>> Below is the brief description of LPDDR2 init sequence:
>>> -> Configure VTP
>>> -> Configure DDR IO settings
>>> -> Disable initialization and refreshes until EMIF registers are programmed.
>>> -> Program Timing registers
>>> -> Program PHY control and Temp alert and ZQ config registers.
>>> -> Enable initialization and refreshes and configure SDRAM CONFIG register
>>> -> Wait till initialization is complete and the configure MR registers.
>>>
>>
>> Is there any public documentation to go with this?
>> I would suggest sprinkling the code with comments
>> to mention the different stages.
> Yep ll add the comments in the code..
>>
>> BTW, no IO powerdown setting for now?
> You mean DDR IO settings?

Yeah. I assume you have configured the dynamic power down bit properly.
Can't tell without looking at the TRM.

>>
>> [...]
>>>
>>> +ifeq ($(CONFIG_AM43XX),)
>>> +COBJS  += ddr.o
>>> +COBJS  += emif4.o
>>> +endif
>>> +COBJS-$(CONFIG_AM43XX) += emif4d5.o
>>> +
>>
>> Are the steps really different enough to warrant a new file? Can't the changes
>> be handled properly in the code? How has this been handled in OMAPx where
>> DDR3 and LPDDR both are supported?
> Initially Tom also suggested not to use a new file. I tried with not to add a new file,
> but I ended up with many #ifdefs. EMIF is new IP(reused from OMAP5) very different from AM33xx EMIF IP.
> So to make things more cleaner I had to use a new file..
>

It really looks a step backward. The new IP should be an update to the old
version and not just a complete overhaul of the programming model that folks
are familiar with.

Regards,
Vaibhav
Tom Rini Nov. 6, 2013, 9:26 p.m. UTC | #4
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 11/06/2013 11:44 AM, Vaibhav Bedia wrote:
> On Wed, Nov 6, 2013 at 8:45 AM, Lokesh Vutla <lokeshvutla@ti.com>
> wrote:
>> On Wednesday 06 November 2013 06:27 PM, Vaibhav Bedia wrote:
[snip]
>>> Are the steps really different enough to warrant a new file?
>>> Can't the changes be handled properly in the code? How has this
>>> been handled in OMAPx where DDR3 and LPDDR both are supported?
>> Initially Tom also suggested not to use a new file. I tried with
>> not to add a new file, but I ended up with many #ifdefs. EMIF is
>> new IP(reused from OMAP5) very different from AM33xx EMIF IP. So
>> to make things more cleaner I had to use a new file..
>> 
> 
> It really looks a step backward. The new IP should be an update to
> the old version and not just a complete overhaul of the programming
> model that folks are familiar with.

It sounds like we need to re-think the EMIF code here since it's not
all THAT different between the OMAP parts, the am33xx parts, the
am43xx parts and the ti81xx parts (and even the am35xx parts, but I'm
OK setting that aside).

And no, I'm not 100% happy with the OMAP code either, but that's
mainly the bits where we say OMAP rev FOO means memory chip BAR.

- -- 
Tom
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBAgAGBQJSerQdAAoJENk4IS6UOR1WD9QP/jhANTw5BKPyxtHFjGHymSUL
+d4jJ5VwvCsWYLOv/zQ961EtWn3FGedNxiqFjTI2ZUQk9Xge9zycp0ZaHscBybJF
65A+RqUBEJ+jBVdtV7oT/zHq8KLsE4m9yYV9qU8L5bHLbzATulX7mG2waRB+lZcZ
Qz/nFKYQ0cyvW92JAUbf2/Iza4GxIAQ0ZIjJdcEE86VBVJD0E+udVJZtP7RdryMg
usyuxaQOBxM5I9XTCuuV6K1ZFGGOWEOebhfKEegH5MTjn7/apQXY0ufP4u7+IJGl
Ss1vDwTEUQ8qNIZwbGoiiA24wE0E8Ou8Vtn29KNpiWWt0pTYR/VUaGJHK0CdhHEd
MlKlIsmjbpXfLAhm3oCeoPSRJLUcb7QXHyJvhjMmMOxVs7FCvy3H2LRogcXk+I/c
SO5wn7JvlSj12VhGgmc4IYw9I8wqLHxUP9tMVNC5V3D5yVZTOl3YjJGql35hkZmR
mWGIUEqGs4uwD1P4hEonUPFFpn9bNGZLBdFpk9ytuS58ZHGD09WEFqWy8aqKHNC0
2TlPUl3T/YK6jk8PZyz962jwX8ropKKWsOZ2mGBB9ix5OHCeMzF22QYmd7d9dD3B
tt9blk1w817QeWiglMc2ErT2tWIMhlAR+0+3RkVKrBOda8pkBEyRp32uV6Pb7lks
gcky1J0tdq6ViMYX3Pt/
=KnCE
-----END PGP SIGNATURE-----
diff mbox

Patch

diff --git a/arch/arm/cpu/armv7/am33xx/Makefile b/arch/arm/cpu/armv7/am33xx/Makefile
index f6a297c..8414430 100644
--- a/arch/arm/cpu/armv7/am33xx/Makefile
+++ b/arch/arm/cpu/armv7/am33xx/Makefile
@@ -19,12 +19,16 @@  endif
 COBJS-$(CONFIG_TI816X)	+= clock_ti816x.o
 COBJS	+= sys_info.o
 COBJS	+= mem.o
-COBJS	+= ddr.o
-COBJS	+= emif4.o
 COBJS	+= board.o
 COBJS	+= mux.o
 COBJS-$(CONFIG_NAND_OMAP_GPMC)	+= elm.o
 
+ifeq ($(CONFIG_AM43XX),)
+COBJS	+= ddr.o
+COBJS	+= emif4.o
+endif
+COBJS-$(CONFIG_AM43XX)	+= emif4d5.o
+
 SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS) $(COBJS-y) $(SOBJS))
 
diff --git a/arch/arm/cpu/armv7/am33xx/emif4d5.c b/arch/arm/cpu/armv7/am33xx/emif4d5.c
new file mode 100644
index 0000000..eea1fa3
--- /dev/null
+++ b/arch/arm/cpu/armv7/am33xx/emif4d5.c
@@ -0,0 +1,183 @@ 
+/*
+ * emif4d5.c
+ *
+ * AM43XX emif4d5 configuration file
+ *
+ * Copyright (C) 2013, Texas Instruments, Incorporated - http://www.ti.com/
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <common.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/ddr_defs.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/io.h>
+#include <asm/emif.h>
+
+static struct ddr_ctrl *ddrctrl = (struct ddr_ctrl *)DDR_CTRL_ADDR;
+static struct cm_device_inst *cm_device =
+				(struct cm_device_inst *)CM_DEVICE_INST;
+static struct ddr_cmdtctrl *ioctrl_reg =
+			(struct ddr_cmdtctrl *)DDR_CONTROL_BASE_ADDR;
+static struct vtp_reg *vtpreg = (struct vtp_reg *)VTP0_CTRL_ADDR;
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int dram_init(void)
+{
+	/* dram_init must store complete ramsize in gd->ram_size */
+	gd->ram_size = get_ram_size(
+			(void *)CONFIG_SYS_SDRAM_BASE,
+			CONFIG_MAX_RAM_BANK_SIZE);
+	return 0;
+}
+
+static void config_vtp(void)
+{
+	writel(readl(&vtpreg->vtp0ctrlreg) | VTP_CTRL_ENABLE,
+	       &vtpreg->vtp0ctrlreg);
+	writel(readl(&vtpreg->vtp0ctrlreg) & (~VTP_CTRL_START_EN),
+	       &vtpreg->vtp0ctrlreg);
+	writel(readl(&vtpreg->vtp0ctrlreg) | VTP_CTRL_START_EN,
+	       &vtpreg->vtp0ctrlreg);
+
+	while ((readl(&vtpreg->vtp0ctrlreg) & VTP_CTRL_READY) !=
+	       VTP_CTRL_READY)
+		;
+}
+
+static void ext_phy_settings(const struct emif_regs *regs,
+			     const u32 *ext_phy_ctrl_const_regs)
+{
+	u32 *ext_phy_ctrl_base = 0;
+	u32 *emif_ext_phy_ctrl_base = 0;
+	u32 i = 0;
+
+	struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
+
+	ext_phy_ctrl_base = (u32 *)&(regs->emif_ddr_ext_phy_ctrl_1);
+	emif_ext_phy_ctrl_base = (u32 *)&(emif->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++);
+	}
+
+	for (i = 0; i < EMIF_EXT_PHY_CTRL_CONST_REG; 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++);
+	}
+}
+
+static inline u32 get_mr(u32 base, u32 cs, u32 mr_addr)
+{
+	u32 mr;
+	struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
+
+	mr_addr |= cs << EMIF_REG_CS_SHIFT;
+	writel(mr_addr, &emif->emif_lpddr2_mode_reg_cfg);
+
+	mr = readl(&emif->emif_lpddr2_mode_reg_data);
+	debug("get_mr: EMIF1 cs %d mr %08x val 0x%x\n", cs, mr_addr, mr);
+	if (((mr & 0x0000ff00) >>  8) == (mr & 0xff) &&
+	    ((mr & 0x00ff0000) >> 16) == (mr & 0xff) &&
+	    ((mr & 0xff000000) >> 24) == (mr & 0xff))
+		return mr & 0xff;
+	else
+		return mr;
+}
+
+static inline void set_mr(u32 base, u32 cs, u32 mr_addr, u32 mr_val)
+{
+	struct emif_reg_struct *emif = (struct emif_reg_struct *)base;
+
+	mr_addr |= cs << EMIF_REG_CS_SHIFT;
+	writel(mr_addr, &emif->emif_lpddr2_mode_reg_cfg);
+	writel(mr_val, &emif->emif_lpddr2_mode_reg_data);
+}
+
+static void configure_mr(u32 base, u32 cs)
+{
+	u32 mr_addr;
+
+	while (get_mr(base, cs, LPDDR2_MR0) & LPDDR2_MR0_DAI_MASK)
+		;
+	set_mr(base, cs, LPDDR2_MR10, 0x56);
+
+	set_mr(base, cs, LPDDR2_MR1, 0x43);
+	set_mr(base, cs, LPDDR2_MR2, 0x2);
+
+	mr_addr = LPDDR2_MR2 | EMIF_REG_REFRESH_EN_MASK;
+	set_mr(base, cs, mr_addr, 0x2);
+}
+
+void do_sdram_init(const struct ctrl_ioregs *ioregs,
+		   const struct emif_regs *regs,
+		   const u32 *ext_phy_ctrl_const_regs)
+{
+	struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE;
+
+	config_vtp();
+
+	writel(readl(&cm_device->cm_dll_ctrl) & ~0x1, &cm_device->cm_dll_ctrl);
+	while ((readl(&cm_device->cm_dll_ctrl) && CM_DLL_READYST) == 0)
+		;
+
+	/* io settings */
+	writel(ioregs->cm0ioctl, &ioctrl_reg->cm0ioctl);
+	writel(ioregs->cm1ioctl, &ioctrl_reg->cm1ioctl);
+	writel(ioregs->cm2ioctl, &ioctrl_reg->cm2ioctl);
+	writel(ioregs->dt0ioctl, &ioctrl_reg->dt0ioctl);
+	writel(ioregs->dt1ioctl, &ioctrl_reg->dt1ioctl);
+	writel(ioregs->dt2ioctrl, &ioctrl_reg->dt2ioctrl);
+	writel(ioregs->dt3ioctrl, &ioctrl_reg->dt3ioctrl);
+	writel(ioregs->emif_sdram_config_ext,
+	       &ioctrl_reg->emif_sdram_config_ext);
+	writel(0x0, &ddrctrl->ddrioctrl);
+
+	/* Set CKE to be controlled by EMIF/DDR PHY */
+	writel(readl(&ddrctrl->ddrckectrl) | 0x3, &ddrctrl->ddrckectrl);
+
+	/*
+	 * disable initialization and refreshes for now until we
+	 * finish programming EMIF regs.
+	 */
+	setbits_le32(&emif->emif_sdram_ref_ctrl, EMIF_REG_INITREF_DIS_MASK);
+
+	writel(regs->sdram_tim1, &emif->emif_sdram_tim_1);
+	writel(regs->sdram_tim1, &emif->emif_sdram_tim_1_shdw);
+	writel(regs->sdram_tim2, &emif->emif_sdram_tim_2);
+	writel(regs->sdram_tim2, &emif->emif_sdram_tim_2_shdw);
+	writel(regs->sdram_tim3, &emif->emif_sdram_tim_3);
+	writel(regs->sdram_tim3, &emif->emif_sdram_tim_3_shdw);
+
+	writel(0x0, &emif->emif_pwr_mgmt_ctrl);
+	writel(0x0, &emif->emif_pwr_mgmt_ctrl_shdw);
+	writel(0x1, &emif->emif_iodft_tlgc);
+	writel(regs->zq_config, &emif->emif_zq_config);
+
+	writel(regs->temp_alert_config, &emif->emif_temp_alert_config);
+	writel(regs->emif_rd_wr_lvl_rmp_win, &emif->emif_rd_wr_lvl_rmp_win);
+	writel(regs->emif_rd_wr_lvl_rmp_ctl, &emif->emif_rd_wr_lvl_rmp_ctl);
+	writel(regs->emif_rd_wr_lvl_ctl, &emif->emif_rd_wr_lvl_ctl);
+	writel(regs->emif_ddr_phy_ctlr_1, &emif->emif_ddr_phy_ctrl_1);
+	writel(regs->emif_ddr_phy_ctlr_1, &emif->emif_ddr_phy_ctrl_1_shdw);
+	writel(regs->emif_rd_wr_exec_thresh, &emif->emif_rd_wr_exec_thresh);
+
+	ext_phy_settings(regs, ext_phy_ctrl_const_regs);
+
+	clrbits_le32(&emif->emif_sdram_ref_ctrl, EMIF_REG_INITREF_DIS_MASK);
+
+	writel(regs->sdram_config, &emif->emif_sdram_config);
+	writel(regs->ref_ctrl, &emif->emif_sdram_ref_ctrl);
+
+	configure_mr(EMIF1_BASE, 0);
+	configure_mr(EMIF1_BASE, 1);
+}
diff --git a/arch/arm/include/asm/arch-am33xx/clocks_am33xx.h b/arch/arm/include/asm/arch-am33xx/clocks_am33xx.h
index 02ed595..4c9352a 100644
--- a/arch/arm/include/asm/arch-am33xx/clocks_am33xx.h
+++ b/arch/arm/include/asm/arch-am33xx/clocks_am33xx.h
@@ -28,6 +28,9 @@ 
 #define UART_CLK_RUNNING_MASK	0x1
 #define UART_SMART_IDLE_EN	(0x1 << 0x3)
 
+#define CM_DLL_CTRL_NO_OVERRIDE	0x0
+#define CM_DLL_READYST		0x4
+
 extern void enable_dmm_clocks(void);
 extern const struct dpll_params dpll_core_opp100;
 extern struct dpll_params dpll_mpu_opp100;
diff --git a/arch/arm/include/asm/arch-am33xx/cpu.h b/arch/arm/include/asm/arch-am33xx/cpu.h
index f463b27..23af125 100644
--- a/arch/arm/include/asm/arch-am33xx/cpu.h
+++ b/arch/arm/include/asm/arch-am33xx/cpu.h
@@ -401,6 +401,11 @@  struct cm_perpll {
 	unsigned int cpgmac0clkctrl;	/* offset 0xB20 */
 };
 
+struct cm_device_inst {
+	unsigned int cm_clkout1_ctrl;
+	unsigned int cm_dll_ctrl;
+};
+
 struct cm_dpll {
 	unsigned int resv1;
 	unsigned int clktimer2clk;	/* offset 0x04 */
diff --git a/arch/arm/include/asm/arch-am33xx/ddr_defs.h b/arch/arm/include/asm/arch-am33xx/ddr_defs.h
index fe48b5f..1880415 100644
--- a/arch/arm/include/asm/arch-am33xx/ddr_defs.h
+++ b/arch/arm/include/asm/arch-am33xx/ddr_defs.h
@@ -126,6 +126,14 @@ 
 #define K4B2G1646EBIH9_PHY_WR_DATA		0x76
 #define K4B2G1646EBIH9_IOCTRL_VALUE		0x18B
 
+#define  LPDDR2_ADDRCTRL_IOCTRL_VALUE   0x294
+#define  LPDDR2_ADDRCTRL_WD0_IOCTRL_VALUE 0x00000000
+#define  LPDDR2_ADDRCTRL_WD1_IOCTRL_VALUE 0x00000000
+#define  LPDDR2_DATA0_IOCTRL_VALUE   0x20000294
+#define  LPDDR2_DATA1_IOCTRL_VALUE   0x20000294
+#define  LPDDR2_DATA2_IOCTRL_VALUE   0x20000294
+#define  LPDDR2_DATA3_IOCTRL_VALUE   0x20000294
+
 /**
  * Configure DMM
  */
@@ -291,6 +299,21 @@  struct ddr_cmdtctrl {
 	unsigned int resv2[12];
 	unsigned int dt0ioctl;
 	unsigned int dt1ioctl;
+	unsigned int dt2ioctrl;
+	unsigned int dt3ioctrl;
+	unsigned int resv3[4];
+	unsigned int emif_sdram_config_ext;
+};
+
+struct ctrl_ioregs {
+	unsigned int cm0ioctl;
+	unsigned int cm1ioctl;
+	unsigned int cm2ioctl;
+	unsigned int dt0ioctl;
+	unsigned int dt1ioctl;
+	unsigned int dt2ioctrl;
+	unsigned int dt3ioctrl;
+	unsigned int emif_sdram_config_ext;
 };
 
 /**
@@ -308,4 +331,7 @@  void config_ddr(unsigned int pll, unsigned int ioctrl,
 		const struct ddr_data *data, const struct cmd_control *ctrl,
 		const struct emif_regs *regs, int nr);
 
+void do_sdram_init(const struct ctrl_ioregs *ioregs,
+		   const struct emif_regs *emif_regs,
+		   const u32 *ext_phy_ctrl_const_regs);
 #endif  /* _DDR_DEFS_H */
diff --git a/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h b/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h
index 4dbc789..d82f050 100644
--- a/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h
+++ b/arch/arm/include/asm/arch-am33xx/hardware_am43xx.h
@@ -63,5 +63,6 @@ 
 #define PRM_PER_USBPHYOCP2SCP0_CLKCTRL (CM_PER + 0x5b8)
 #define PRM_PER_USBPHYOCP2SCP1_CLKCTRL (CM_PER + 0x5c0)
 #define USBPHYOCPSCP_MODULE_EN	(1 << 2)
+#define CM_DEVICE_INST			0x44df4100
 
 #endif /* __AM43XX_HARDWARE_AM43XX_H */
diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h
index 1b94a99..5edc3a4 100644
--- a/arch/arm/include/asm/emif.h
+++ b/arch/arm/include/asm/emif.h
@@ -690,6 +690,18 @@  struct emif_reg_struct {
 	u32 emif_ddr_ext_phy_ctrl_23_shdw;
 	u32 emif_ddr_ext_phy_ctrl_24;
 	u32 emif_ddr_ext_phy_ctrl_24_shdw;
+	u32 emif_ddr_ext_phy_ctrl_25;
+	u32 emif_ddr_ext_phy_ctrl_25_shdw;
+	u32 emif_ddr_ext_phy_ctrl_26;
+	u32 emif_ddr_ext_phy_ctrl_26_shdw;
+	u32 emif_ddr_ext_phy_ctrl_27;
+	u32 emif_ddr_ext_phy_ctrl_27_shdw;
+	u32 emif_ddr_ext_phy_ctrl_28;
+	u32 emif_ddr_ext_phy_ctrl_28_shdw;
+	u32 emif_ddr_ext_phy_ctrl_29;
+	u32 emif_ddr_ext_phy_ctrl_29_shdw;
+	u32 emif_ddr_ext_phy_ctrl_30;
+	u32 emif_ddr_ext_phy_ctrl_30_shdw;
 };
 
 struct dmm_lisa_map_regs {
diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c
index a700d1f..83d184d 100644
--- a/board/ti/am43xx/board.c
+++ b/board/ti/am43xx/board.c
@@ -15,6 +15,8 @@ 
 #include <asm/arch/clock.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/arch/mux.h>
+#include <asm/arch/ddr_defs.h>
+#include <asm/emif.h>
 #include "board.h"
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -83,6 +85,61 @@  const struct dpll_params gp_evm_dpll_core = {
 const struct dpll_params gp_evm_dpll_per = {
 		960, 23, 5, -1, -1, -1, -1};
 
+const struct ctrl_ioregs ioregs_lpddr2 = {
+	.cm0ioctl		= LPDDR2_ADDRCTRL_IOCTRL_VALUE,
+	.cm1ioctl		= LPDDR2_ADDRCTRL_WD0_IOCTRL_VALUE,
+	.cm2ioctl		= LPDDR2_ADDRCTRL_WD1_IOCTRL_VALUE,
+	.dt0ioctl		= LPDDR2_DATA0_IOCTRL_VALUE,
+	.dt1ioctl		= LPDDR2_DATA0_IOCTRL_VALUE,
+	.dt2ioctrl		= LPDDR2_DATA0_IOCTRL_VALUE,
+	.dt3ioctrl		= LPDDR2_DATA0_IOCTRL_VALUE,
+	.emif_sdram_config_ext	= 0x1,
+};
+
+const struct emif_regs emif_regs_lpddr2 = {
+	.sdram_config			= 0x808012BA,
+	.ref_ctrl			= 0x0000040D,
+	.sdram_tim1			= 0xEA86B411,
+	.sdram_tim2			= 0x103A094A,
+	.sdram_tim3			= 0x0F6BA37F,
+	.read_idle_ctrl			= 0x00050000,
+	.zq_config			= 0x50074BE4,
+	.temp_alert_config		= 0x0,
+	.emif_rd_wr_lvl_rmp_win		= 0x0,
+	.emif_rd_wr_lvl_rmp_ctl		= 0x0,
+	.emif_rd_wr_lvl_ctl		= 0x0,
+	.emif_ddr_phy_ctlr_1		= 0x0E084006,
+	.emif_rd_wr_exec_thresh		= 0x00000405,
+	.emif_ddr_ext_phy_ctrl_1	= 0x04010040,
+	.emif_ddr_ext_phy_ctrl_2	= 0x00500050,
+	.emif_ddr_ext_phy_ctrl_3	= 0x00500050,
+	.emif_ddr_ext_phy_ctrl_4	= 0x00500050,
+	.emif_ddr_ext_phy_ctrl_5	= 0x00500050
+};
+
+const u32 ext_phy_ctrl_const_base_lpddr2[EMIF_EXT_PHY_CTRL_CONST_REG] = {
+	0x00500050,
+	0x00350035,
+	0x00350035,
+	0x00350035,
+	0x00350035,
+	0x00350035,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40001000,
+	0x08102040
+};
+
 const struct dpll_params *get_dpll_ddr_params(void)
 {
 	if (board_is_eposevm())
@@ -134,6 +191,8 @@  void set_mux_conf_regs(void)
 
 void sdram_init(void)
 {
+	do_sdram_init(&ioregs_lpddr2, &emif_regs_lpddr2,
+		      ext_phy_ctrl_const_base_lpddr2);
 }
 #endif