diff mbox

[U-Boot,V2,13/14] ARM: AM43xx: GP_EVM: Add support for DDR3

Message ID 1385014699-7257-14-git-send-email-lokeshvutla@ti.com
State Changes Requested
Delegated to: Tom Rini
Headers show

Commit Message

Lokesh Vutla Nov. 21, 2013, 6:18 a.m. UTC
GP EVM has 1GB DDR3 attached(Part no: MT41K512M8RH).
Adding details for the same.
Below is the brief description of DDR3 init sequence(SW leveling):
-> Enable VTT regulator
-> Configure VTP
-> Configure DDR IO settings
-> Disable initialization and refreshes until EMIF registers are programmed.
-> Program Timing registers
-> Program leveling registers
-> Program PHY control and Temp alert and ZQ config registers.
-> Enable initialization and refreshes and configure SDRAM CONFIG register

Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
---
 arch/arm/cpu/armv7/am33xx/ddr.c              |    6 +-
 arch/arm/cpu/armv7/omap-common/emif-common.c |   14 ----
 arch/arm/include/asm/arch-am33xx/ddr_defs.h  |    8 +++
 arch/arm/include/asm/emif.h                  |   14 ++++
 board/ti/am43xx/board.c                      |   92 +++++++++++++++++++++++++-
 board/ti/am43xx/mux.c                        |    8 +++
 6 files changed, 123 insertions(+), 19 deletions(-)

Comments

Vaibhav Bedia Nov. 21, 2013, 8:52 p.m. UTC | #1
On Thu, Nov 21, 2013 at 1:18 AM, Lokesh Vutla <lokeshvutla@ti.com> wrote:
[...]

> -/*
> - * Get SDRAM type connected to EMIF.
> - * Assuming similar SDRAM parts are connected to both EMIF's
> - * which is typically the case. So it is sufficient to get
> - * SDRAM type from EMIF1.
> - */
> -u32 emif_sdram_type()
> -{
> -       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;
> -}
> -
>  static inline u32 get_mr(u32 base, u32 cs, u32 mr_addr)
>  {
>         u32 mr;
> diff --git a/arch/arm/include/asm/arch-am33xx/ddr_defs.h b/arch/arm/include/asm/arch-am33xx/ddr_defs.h
> index c98ab7f..646e50f 100644
> --- a/arch/arm/include/asm/arch-am33xx/ddr_defs.h
> +++ b/arch/arm/include/asm/arch-am33xx/ddr_defs.h
> @@ -138,6 +138,14 @@
>  #define  LPDDR2_DATA2_IOCTRL_VALUE   0x20000294
>  #define  LPDDR2_DATA3_IOCTRL_VALUE   0x20000294
>
> +#define  DDR3_ADDRCTRL_WD0_IOCTRL_VALUE 0x00000000
> +#define  DDR3_ADDRCTRL_WD1_IOCTRL_VALUE 0x00000000
> +#define  DDR3_ADDRCTRL_IOCTRL_VALUE   0x84
> +#define  DDR3_DATA0_IOCTRL_VALUE   0x84
> +#define  DDR3_DATA1_IOCTRL_VALUE   0x84
> +#define  DDR3_DATA2_IOCTRL_VALUE   0x84
> +#define  DDR3_DATA3_IOCTRL_VALUE   0x84
> +
>  /**
>   * Configure DMM
>   */
> diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h
> index ce6b229..b4a8c9f 100644
> --- a/arch/arm/include/asm/emif.h
> +++ b/arch/arm/include/asm/emif.h
> @@ -1151,6 +1151,20 @@ static inline u32 get_emif_rev(u32 base)
>                 >> EMIF_REG_MAJOR_REVISION_SHIFT;
>  }
>
> +/*
> + * Get SDRAM type connected to EMIF.
> + * Assuming similar SDRAM parts are connected to both EMIF's
> + * which is typically the case. So it is sufficient to get
> + * SDRAM type from EMIF1.
> + */
> +static inline u32 emif_sdram_type(void)
> +{
> +       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;
> +}
> +

This change don't make any sense to me. How are the EMIF register bits
any indication
of what memory time is used especially for DDR2/3?

[...]
>
> +static void enable_vtt_regulator(void)
> +{
> +       u32 temp;
> +
> +       /* enable module */
> +       writel(0x0, AM33XX_GPIO0_BASE + OMAP_GPIO_CTRL);
> +
> +       /*enable output for GPIO0_22*/
> +       writel((1 << 22), AM33XX_GPIO0_BASE + OMAP_GPIO_SETDATAOUT);
> +       temp = readl(AM33XX_GPIO0_BASE + OMAP_GPIO_OE);
> +       temp = temp & ~(1 << 22);
> +       writel(temp, AM33XX_GPIO0_BASE + OMAP_GPIO_OE);
> +}
> +

No magic nos. please. I think you have a #def the pin used for VTT regulator
in the config file - makes it simpler for others who design their own board.

Regards,
Vaibhav
Lokesh Vutla Nov. 25, 2013, 5:18 a.m. UTC | #2
On Friday 22 November 2013 02:22 AM, Vaibhav Bedia wrote:
> On Thu, Nov 21, 2013 at 1:18 AM, Lokesh Vutla <lokeshvutla@ti.com> wrote:
> [...]
> 
>> -/*
>> - * Get SDRAM type connected to EMIF.
>> - * Assuming similar SDRAM parts are connected to both EMIF's
>> - * which is typically the case. So it is sufficient to get
>> - * SDRAM type from EMIF1.
>> - */
>> -u32 emif_sdram_type()
>> -{
>> -       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;
>> -}
>> -
>>  static inline u32 get_mr(u32 base, u32 cs, u32 mr_addr)
>>  {
>>         u32 mr;
>> diff --git a/arch/arm/include/asm/arch-am33xx/ddr_defs.h b/arch/arm/include/asm/arch-am33xx/ddr_defs.h
>> index c98ab7f..646e50f 100644
>> --- a/arch/arm/include/asm/arch-am33xx/ddr_defs.h
>> +++ b/arch/arm/include/asm/arch-am33xx/ddr_defs.h
>> @@ -138,6 +138,14 @@
>>  #define  LPDDR2_DATA2_IOCTRL_VALUE   0x20000294
>>  #define  LPDDR2_DATA3_IOCTRL_VALUE   0x20000294
>>
>> +#define  DDR3_ADDRCTRL_WD0_IOCTRL_VALUE 0x00000000
>> +#define  DDR3_ADDRCTRL_WD1_IOCTRL_VALUE 0x00000000
>> +#define  DDR3_ADDRCTRL_IOCTRL_VALUE   0x84
>> +#define  DDR3_DATA0_IOCTRL_VALUE   0x84
>> +#define  DDR3_DATA1_IOCTRL_VALUE   0x84
>> +#define  DDR3_DATA2_IOCTRL_VALUE   0x84
>> +#define  DDR3_DATA3_IOCTRL_VALUE   0x84
>> +
>>  /**
>>   * Configure DMM
>>   */
>> diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h
>> index ce6b229..b4a8c9f 100644
>> --- a/arch/arm/include/asm/emif.h
>> +++ b/arch/arm/include/asm/emif.h
>> @@ -1151,6 +1151,20 @@ static inline u32 get_emif_rev(u32 base)
>>                 >> EMIF_REG_MAJOR_REVISION_SHIFT;
>>  }
>>
>> +/*
>> + * Get SDRAM type connected to EMIF.
>> + * Assuming similar SDRAM parts are connected to both EMIF's
>> + * which is typically the case. So it is sufficient to get
>> + * SDRAM type from EMIF1.
>> + */
>> +static inline u32 emif_sdram_type(void)
>> +{
>> +       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;
>> +}
>> +
> 
> This change don't make any sense to me. How are the EMIF register bits
> any indication
> of what memory time is used especially for DDR2/3?
What is not making sense here ?
If you go and read EMIF spec, it is clearly written that on coming out of reset 
HW sequence starts according to the value populated in SDRAM config register.
As far as I am concerned this is the best way to differentiate between Memories.

Can you tell me a better way to differentiate between memories in emif file ?
Definitely  I should not use board_is_foo() functions.

Thanks
Lokesh
> 
> [...]
>>
>> +static void enable_vtt_regulator(void)
>> +{
>> +       u32 temp;
>> +
>> +       /* enable module */
>> +       writel(0x0, AM33XX_GPIO0_BASE + OMAP_GPIO_CTRL);
>> +
>> +       /*enable output for GPIO0_22*/
>> +       writel((1 << 22), AM33XX_GPIO0_BASE + OMAP_GPIO_SETDATAOUT);
>> +       temp = readl(AM33XX_GPIO0_BASE + OMAP_GPIO_OE);
>> +       temp = temp & ~(1 << 22);
>> +       writel(temp, AM33XX_GPIO0_BASE + OMAP_GPIO_OE);
>> +}
>> +
> 
> No magic nos. please. I think you have a #def the pin used for VTT regulator
> in the config file - makes it simpler for others who design their own board.
> 
> Regards,
> Vaibhav
>
Vaibhav Bedia Nov. 27, 2013, 12:17 a.m. UTC | #3
On Mon, Nov 25, 2013 at 12:18 AM, Lokesh Vutla <lokeshvutla@ti.com> wrote:
> On Friday 22 November 2013 02:22 AM, Vaibhav Bedia wrote:
>> On Thu, Nov 21, 2013 at 1:18 AM, Lokesh Vutla <lokeshvutla@ti.com> wrote:
>> [...]
>>
>>> -/*
>>> - * Get SDRAM type connected to EMIF.
>>> - * Assuming similar SDRAM parts are connected to both EMIF's
>>> - * which is typically the case. So it is sufficient to get
>>> - * SDRAM type from EMIF1.
>>> - */
>>> -u32 emif_sdram_type()
>>> -{
>>> -       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;
>>> -}
>>> -
>>>  static inline u32 get_mr(u32 base, u32 cs, u32 mr_addr)
>>>  {
>>>         u32 mr;
>>> diff --git a/arch/arm/include/asm/arch-am33xx/ddr_defs.h b/arch/arm/include/asm/arch-am33xx/ddr_defs.h
>>> index c98ab7f..646e50f 100644
>>> --- a/arch/arm/include/asm/arch-am33xx/ddr_defs.h
>>> +++ b/arch/arm/include/asm/arch-am33xx/ddr_defs.h
>>> @@ -138,6 +138,14 @@
>>>  #define  LPDDR2_DATA2_IOCTRL_VALUE   0x20000294
>>>  #define  LPDDR2_DATA3_IOCTRL_VALUE   0x20000294
>>>
>>> +#define  DDR3_ADDRCTRL_WD0_IOCTRL_VALUE 0x00000000
>>> +#define  DDR3_ADDRCTRL_WD1_IOCTRL_VALUE 0x00000000
>>> +#define  DDR3_ADDRCTRL_IOCTRL_VALUE   0x84
>>> +#define  DDR3_DATA0_IOCTRL_VALUE   0x84
>>> +#define  DDR3_DATA1_IOCTRL_VALUE   0x84
>>> +#define  DDR3_DATA2_IOCTRL_VALUE   0x84
>>> +#define  DDR3_DATA3_IOCTRL_VALUE   0x84
>>> +
>>>  /**
>>>   * Configure DMM
>>>   */
>>> diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h
>>> index ce6b229..b4a8c9f 100644
>>> --- a/arch/arm/include/asm/emif.h
>>> +++ b/arch/arm/include/asm/emif.h
>>> @@ -1151,6 +1151,20 @@ static inline u32 get_emif_rev(u32 base)
>>>                 >> EMIF_REG_MAJOR_REVISION_SHIFT;
>>>  }
>>>
>>> +/*
>>> + * Get SDRAM type connected to EMIF.
>>> + * Assuming similar SDRAM parts are connected to both EMIF's
>>> + * which is typically the case. So it is sufficient to get
>>> + * SDRAM type from EMIF1.
>>> + */
>>> +static inline u32 emif_sdram_type(void)
>>> +{
>>> +       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;
>>> +}
>>> +
>>
>> This change don't make any sense to me. How are the EMIF register bits
>> any indication
>> of what memory time is used especially for DDR2/3?
> What is not making sense here ?
> If you go and read EMIF spec, it is clearly written that on coming out of reset
> HW sequence starts according to the value populated in SDRAM config register.
> As far as I am concerned this is the best way to differentiate between Memories.
>

Take a moment to think about where that register value comes from. Does it
somehow automagically get reconfigured when the chip is put in a board with
LPDDR2 vs DDR2 vs DDR3? While you are at it also look at the JEDEC specs
to figure out is there's some way to probe the DDR2/3 memory types.

> Can you tell me a better way to differentiate between memories in emif file ?
> Definitely  I should not use board_is_foo() functions.
>

AFAIK there is none and hence this way of trying to get the memory type
is broken.

Moreover, my understanding was that one of the prime functions of the EEPROM
board data was to enable differentiation between the memory types.
Lokesh Vutla Nov. 27, 2013, 9:34 a.m. UTC | #4
On Wednesday 27 November 2013 05:47 AM, Vaibhav Bedia wrote:
> On Mon, Nov 25, 2013 at 12:18 AM, Lokesh Vutla <lokeshvutla@ti.com> wrote:
>> On Friday 22 November 2013 02:22 AM, Vaibhav Bedia wrote:
>>> On Thu, Nov 21, 2013 at 1:18 AM, Lokesh Vutla <lokeshvutla@ti.com> wrote:
>>> [...]
>>>
>>>> -/*
>>>> - * Get SDRAM type connected to EMIF.
>>>> - * Assuming similar SDRAM parts are connected to both EMIF's
>>>> - * which is typically the case. So it is sufficient to get
>>>> - * SDRAM type from EMIF1.
>>>> - */
>>>> -u32 emif_sdram_type()
>>>> -{
>>>> -       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;
>>>> -}
>>>> -
>>>>  static inline u32 get_mr(u32 base, u32 cs, u32 mr_addr)
>>>>  {
>>>>         u32 mr;
>>>> diff --git a/arch/arm/include/asm/arch-am33xx/ddr_defs.h b/arch/arm/include/asm/arch-am33xx/ddr_defs.h
>>>> index c98ab7f..646e50f 100644
>>>> --- a/arch/arm/include/asm/arch-am33xx/ddr_defs.h
>>>> +++ b/arch/arm/include/asm/arch-am33xx/ddr_defs.h
>>>> @@ -138,6 +138,14 @@
>>>>  #define  LPDDR2_DATA2_IOCTRL_VALUE   0x20000294
>>>>  #define  LPDDR2_DATA3_IOCTRL_VALUE   0x20000294
>>>>
>>>> +#define  DDR3_ADDRCTRL_WD0_IOCTRL_VALUE 0x00000000
>>>> +#define  DDR3_ADDRCTRL_WD1_IOCTRL_VALUE 0x00000000
>>>> +#define  DDR3_ADDRCTRL_IOCTRL_VALUE   0x84
>>>> +#define  DDR3_DATA0_IOCTRL_VALUE   0x84
>>>> +#define  DDR3_DATA1_IOCTRL_VALUE   0x84
>>>> +#define  DDR3_DATA2_IOCTRL_VALUE   0x84
>>>> +#define  DDR3_DATA3_IOCTRL_VALUE   0x84
>>>> +
>>>>  /**
>>>>   * Configure DMM
>>>>   */
>>>> diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h
>>>> index ce6b229..b4a8c9f 100644
>>>> --- a/arch/arm/include/asm/emif.h
>>>> +++ b/arch/arm/include/asm/emif.h
>>>> @@ -1151,6 +1151,20 @@ static inline u32 get_emif_rev(u32 base)
>>>>                 >> EMIF_REG_MAJOR_REVISION_SHIFT;
>>>>  }
>>>>
>>>> +/*
>>>> + * Get SDRAM type connected to EMIF.
>>>> + * Assuming similar SDRAM parts are connected to both EMIF's
>>>> + * which is typically the case. So it is sufficient to get
>>>> + * SDRAM type from EMIF1.
>>>> + */
>>>> +static inline u32 emif_sdram_type(void)
>>>> +{
>>>> +       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;
>>>> +}
>>>> +
>>>
>>> This change don't make any sense to me. How are the EMIF register bits
>>> any indication
>>> of what memory time is used especially for DDR2/3?
>> What is not making sense here ?
>> If you go and read EMIF spec, it is clearly written that on coming out of reset
>> HW sequence starts according to the value populated in SDRAM config register.
>> As far as I am concerned this is the best way to differentiate between Memories.
>>
> 
> Take a moment to think about where that register value comes from. Does it
> somehow automagically get reconfigured when the chip is put in a board with
> LPDDR2 vs DDR2 vs DDR3? While you are at it also look at the JEDEC specs
> to figure out is there's some way to probe the DDR2/3 memory types.
Ideally the default value should be exported from e-fuse values.
EMIF does some HW sequence according to the value exported here. This filed tells 
what type of memory it is.

I understand the point what if efuse is not blown. I am using this only after we write into sdarm_config register.
This can confirm that we get a correct value.
 If this is not sufficient we can hardcode the register during startup only ?
One more thing is we can get from MR registers of DDR.
But for DDR3 we cannot access MR registers. That is why I didn't go with this approach.

Currently EEPROM doesn't have any details about DDR.
Please let me know if this approach is not good enough.

Thanks and regards,
Lokesh

> 
>> Can you tell me a better way to differentiate between memories in emif file ?
>> Definitely  I should not use board_is_foo() functions.
>>
> 
> AFAIK there is none and hence this way of trying to get the memory type
> is broken.
> 
> Moreover, my understanding was that one of the prime functions of the EEPROM
> board data was to enable differentiation between the memory types.
>
Vaibhav Bedia Nov. 27, 2013, 11:03 p.m. UTC | #5
On Wed, Nov 27, 2013 at 4:34 AM, Lokesh Vutla <lokeshvutla@ti.com> wrote:
[...]
> Ideally the default value should be exported from e-fuse values.
> EMIF does some HW sequence according to the value exported here. This filed tells
> what type of memory it is.
>

No, eFuse is not the right place for this information. If you were to do that
you would be restricting what memory type is supported on a particular
device that gets shipped and that's not a scalable model.

> I understand the point what if efuse is not blown. I am using this only after we write into sdarm_config register.
> This can confirm that we get a correct value.
>  If this is not sufficient we can hardcode the register during startup only ?

I don't see any value in writing some value in the EMIF register at one place
and then using that here. If you already know what register values to program
you already know the memory type.

Another place where the memory type information is needed is when the device
enters low power state and the EMIF contents are lost. Rather than having to
invent one more way of detecting the memory type in resume from low power state
you could work out a persistent storage area (RTC scratchpad maybe? assuming
the RTC is powered up) and use that in all the places. Requires some thought
about the whole sequence but definitely doable IMHO.

> One more thing is we can get from MR registers of DDR.
> But for DDR3 we cannot access MR registers. That is why I didn't go with this approach.
>

So now you know why things just worked on OMAP3 (and OMAP4?) and not
on TI81xx, AM335x and AM437x :)

> Currently EEPROM doesn't have any details about DDR.
> Please let me know if this approach is not good enough.
>

Since there's no speced way of detecting the memory type you should push for
the right information to be made available via the EEPROM and write
generic code.
But hey that's for you to decide :)

Regards,
Vaibhav
Lokesh Vutla Dec. 2, 2013, 4:21 a.m. UTC | #6
On Thursday 28 November 2013 04:33 AM, Vaibhav Bedia wrote:
> On Wed, Nov 27, 2013 at 4:34 AM, Lokesh Vutla <lokeshvutla@ti.com> wrote:
> [...]
>> Ideally the default value should be exported from e-fuse values.
>> EMIF does some HW sequence according to the value exported here. This filed tells
>> what type of memory it is.
>>
> 
> No, eFuse is not the right place for this information. If you were to do that
> you would be restricting what memory type is supported on a particular
> device that gets shipped and that's not a scalable model.
At least this was the case for OMAPs. So it worked well..:)
> 
>> I understand the point what if efuse is not blown. I am using this only after we write into sdarm_config register.
>> This can confirm that we get a correct value.
>>  If this is not sufficient we can hardcode the register during startup only ?
> 
> I don't see any value in writing some value in the EMIF register at one place
> and then using that here. If you already know what register values to program
> you already know the memory type.
Yes, according to the board we are passing the registers that means we know
the memory type. The same information I am getting from registers.
> 
> Another place where the memory type information is needed is when the device
> enters low power state and the EMIF contents are lost. Rather than having to
> invent one more way of detecting the memory type in resume from low power state
> you could work out a persistent storage area (RTC scratchpad maybe? assuming
> the RTC is powered up) and use that in all the places. Requires some thought
> about the whole sequence but definitely doable IMHO.
We should not rely on RTC here. I don't think U-Boot should worry about low power state. You mean to
say about passing this information to kernel?
In the current kernel also memory type is derived according to the SDRAM CONFIG register only.
So I thought this would be good enough.


Thanks and regards,
Lokesh

> 
>> One more thing is we can get from MR registers of DDR.
>> But for DDR3 we cannot access MR registers. That is why I didn't go with this approach.
>>
> 
> So now you know why things just worked on OMAP3 (and OMAP4?) and not
> on TI81xx, AM335x and AM437x :)
> 
>> Currently EEPROM doesn't have any details about DDR.
>> Please let me know if this approach is not good enough.
>>
> 
> Since there's no speced way of detecting the memory type you should push for
> the right information to be made available via the EEPROM and write
> generic code.
> But hey that's for you to decide :)
> 
> Regards,
> Vaibhav
>
Vaibhav Bedia Dec. 4, 2013, 3:24 a.m. UTC | #7
On Sun, Dec 1, 2013 at 11:21 PM, Lokesh Vutla <lokeshvutla@ti.com> wrote:
][...]
> We should not rely on RTC here. I don't think U-Boot should worry about low power state. You mean to
> say about passing this information to kernel?

No. I am not asking you to pass this to the kernel.

> In the current kernel also memory type is derived according to the SDRAM CONFIG register only.
> So I thought this would be good enough.
>

The only problem with this being that register is also lost when you
go lower than DeepSleep
and would require you to figure out how to get the memory type.

Your call though. I guess i am just trying to over-engineer things ;)
diff mbox

Patch

diff --git a/arch/arm/cpu/armv7/am33xx/ddr.c b/arch/arm/cpu/armv7/am33xx/ddr.c
index fbee51d..389fdfc 100644
--- a/arch/arm/cpu/armv7/am33xx/ddr.c
+++ b/arch/arm/cpu/armv7/am33xx/ddr.c
@@ -100,8 +100,10 @@  void config_sdram_emif4d5(const struct emif_regs *regs, int nr)
 	writel(regs->sdram_config, &emif_reg[nr]->emif_sdram_config);
 	writel(regs->ref_ctrl, &emif_reg[nr]->emif_sdram_ref_ctrl);
 
-	configure_mr(nr, 0);
-	configure_mr(nr, 1);
+	if (emif_sdram_type() == EMIF_SDRAM_TYPE_LPDDR2) {
+		configure_mr(nr, 0);
+		configure_mr(nr, 1);
+	}
 }
 
 /**
diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c
index b0e1caa..d8a15be 100644
--- a/arch/arm/cpu/armv7/omap-common/emif-common.c
+++ b/arch/arm/cpu/armv7/omap-common/emif-common.c
@@ -50,20 +50,6 @@  inline u32 emif_num(u32 base)
 		return 0;
 }
 
-/*
- * Get SDRAM type connected to EMIF.
- * Assuming similar SDRAM parts are connected to both EMIF's
- * which is typically the case. So it is sufficient to get
- * SDRAM type from EMIF1.
- */
-u32 emif_sdram_type()
-{
-	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;
-}
-
 static inline u32 get_mr(u32 base, u32 cs, u32 mr_addr)
 {
 	u32 mr;
diff --git a/arch/arm/include/asm/arch-am33xx/ddr_defs.h b/arch/arm/include/asm/arch-am33xx/ddr_defs.h
index c98ab7f..646e50f 100644
--- a/arch/arm/include/asm/arch-am33xx/ddr_defs.h
+++ b/arch/arm/include/asm/arch-am33xx/ddr_defs.h
@@ -138,6 +138,14 @@ 
 #define  LPDDR2_DATA2_IOCTRL_VALUE   0x20000294
 #define  LPDDR2_DATA3_IOCTRL_VALUE   0x20000294
 
+#define  DDR3_ADDRCTRL_WD0_IOCTRL_VALUE 0x00000000
+#define  DDR3_ADDRCTRL_WD1_IOCTRL_VALUE 0x00000000
+#define  DDR3_ADDRCTRL_IOCTRL_VALUE   0x84
+#define  DDR3_DATA0_IOCTRL_VALUE   0x84
+#define  DDR3_DATA1_IOCTRL_VALUE   0x84
+#define  DDR3_DATA2_IOCTRL_VALUE   0x84
+#define  DDR3_DATA3_IOCTRL_VALUE   0x84
+
 /**
  * Configure DMM
  */
diff --git a/arch/arm/include/asm/emif.h b/arch/arm/include/asm/emif.h
index ce6b229..b4a8c9f 100644
--- a/arch/arm/include/asm/emif.h
+++ b/arch/arm/include/asm/emif.h
@@ -1151,6 +1151,20 @@  static inline u32 get_emif_rev(u32 base)
 		>> EMIF_REG_MAJOR_REVISION_SHIFT;
 }
 
+/*
+ * Get SDRAM type connected to EMIF.
+ * Assuming similar SDRAM parts are connected to both EMIF's
+ * which is typically the case. So it is sufficient to get
+ * SDRAM type from EMIF1.
+ */
+static inline u32 emif_sdram_type(void)
+{
+	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;
+}
+
 /* assert macros */
 #if defined(DEBUG)
 #define emif_assert(c)	({ if (!(c)) for (;;); })
diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c
index 10c6a2b..e3a94ad 100644
--- a/board/ti/am43xx/board.c
+++ b/board/ti/am43xx/board.c
@@ -16,6 +16,7 @@ 
 #include <asm/arch/sys_proto.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/ddr_defs.h>
+#include <asm/arch/gpio.h>
 #include <asm/emif.h>
 #include "board.h"
 
@@ -140,10 +141,70 @@  const u32 ext_phy_ctrl_const_base_lpddr2[] = {
 	0x08102040
 };
 
+const struct ctrl_ioregs ioregs_ddr3 = {
+	.cm0ioctl		= DDR3_ADDRCTRL_IOCTRL_VALUE,
+	.cm1ioctl		= DDR3_ADDRCTRL_WD0_IOCTRL_VALUE,
+	.cm2ioctl		= DDR3_ADDRCTRL_WD1_IOCTRL_VALUE,
+	.dt0ioctl		= DDR3_DATA0_IOCTRL_VALUE,
+	.dt1ioctl		= DDR3_DATA0_IOCTRL_VALUE,
+	.dt2ioctrl		= DDR3_DATA0_IOCTRL_VALUE,
+	.dt3ioctrl		= DDR3_DATA0_IOCTRL_VALUE,
+	.emif_sdram_config_ext	= 0x0043,
+};
+
+const struct emif_regs ddr3_emif_regs_400Mhz = {
+	.sdram_config			= 0x638413B2,
+	.ref_ctrl			= 0x00000C30,
+	.sdram_tim1			= 0xEAAAD4DB,
+	.sdram_tim2			= 0x266B7FDA,
+	.sdram_tim3			= 0x107F8678,
+	.read_idle_ctrl			= 0x00050000,
+	.zq_config			= 0x50074BE4,
+	.temp_alert_config		= 0x0,
+	.emif_ddr_phy_ctlr_1		= 0x0E084008,
+	.emif_ddr_ext_phy_ctrl_1	= 0x08020080,
+	.emif_ddr_ext_phy_ctrl_2	= 0x00400040,
+	.emif_ddr_ext_phy_ctrl_3	= 0x00400040,
+	.emif_ddr_ext_phy_ctrl_4	= 0x00400040,
+	.emif_ddr_ext_phy_ctrl_5	= 0x00400040,
+	.emif_rd_wr_lvl_rmp_win		= 0x0,
+	.emif_rd_wr_lvl_rmp_ctl		= 0x0,
+	.emif_rd_wr_lvl_ctl		= 0x0,
+	.emif_rd_wr_exec_thresh		= 0x00000405
+};
+
+const u32 ext_phy_ctrl_const_base_ddr3[] = {
+	0x00400040,
+	0x00350035,
+	0x00350035,
+	0x00350035,
+	0x00350035,
+	0x00350035,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00340034,
+	0x00340034,
+	0x00340034,
+	0x00340034,
+	0x00340034,
+	0x0,
+	0x0,
+	0x40000000,
+	0x08102040
+};
+
 void emif_get_ext_phy_ctrl_const_regs(const u32 **regs, u32 *size)
 {
-	*regs = ext_phy_ctrl_const_base_lpddr2;
-	*size = ARRAY_SIZE(ext_phy_ctrl_const_base_lpddr2);
+	if (board_is_eposevm()) {
+		*regs = ext_phy_ctrl_const_base_lpddr2;
+		*size = ARRAY_SIZE(ext_phy_ctrl_const_base_lpddr2);
+	} else if (board_is_gpevm()) {
+		*regs = ext_phy_ctrl_const_base_ddr3;
+		*size = ARRAY_SIZE(ext_phy_ctrl_const_base_ddr3);
+	}
 
 	return;
 }
@@ -197,9 +258,34 @@  void set_mux_conf_regs(void)
 	enable_board_pin_mux();
 }
 
+static void enable_vtt_regulator(void)
+{
+	u32 temp;
+
+	/* enable module */
+	writel(0x0, AM33XX_GPIO0_BASE + OMAP_GPIO_CTRL);
+
+	/*enable output for GPIO0_22*/
+	writel((1 << 22), AM33XX_GPIO0_BASE + OMAP_GPIO_SETDATAOUT);
+	temp = readl(AM33XX_GPIO0_BASE + OMAP_GPIO_OE);
+	temp = temp & ~(1 << 22);
+	writel(temp, AM33XX_GPIO0_BASE + OMAP_GPIO_OE);
+}
+
 void sdram_init(void)
 {
-	config_ddr(0, &ioregs_lpddr2, NULL, NULL, &emif_regs_lpddr2, 0);
+	/*
+	 * EPOS EVM has 1GB LPDDR2 connected to EMIF.
+	 * GP EMV has 1GB DDR3 connected to EMIF
+	 * along with VTT regulator.
+	 */
+	if (board_is_eposevm()) {
+		config_ddr(0, &ioregs_lpddr2, NULL, NULL, &emif_regs_lpddr2, 0);
+	} else if (board_is_gpevm()) {
+		enable_vtt_regulator();
+		config_ddr(0, &ioregs_ddr3, NULL, NULL,
+			   &ddr3_emif_regs_400Mhz, 0);
+	}
 }
 #endif
 
diff --git a/board/ti/am43xx/mux.c b/board/ti/am43xx/mux.c
index a2d72dd..810b194 100644
--- a/board/ti/am43xx/mux.c
+++ b/board/ti/am43xx/mux.c
@@ -33,6 +33,11 @@  static struct module_pin_mux i2c0_pin_mux[] = {
 	{-1},
 };
 
+static struct module_pin_mux gpio0_22_pin_mux[] = {
+	{OFFSET(ddr_ba2), (MODE(9) | PULLUP_EN)},	/* GPIO0_22 */
+	{-1},
+};
+
 void enable_uart0_pin_mux(void)
 {
 	configure_module_pin_mux(uart0_pin_mux);
@@ -42,6 +47,9 @@  void enable_board_pin_mux(void)
 {
 	configure_module_pin_mux(mmc0_pin_mux);
 	configure_module_pin_mux(i2c0_pin_mux);
+
+	if (board_is_gpevm())
+		configure_module_pin_mux(gpio0_22_pin_mux);
 }
 
 void enable_i2c0_pin_mux(void)