Re: [linux-sunxi] [RFC PATCH u-boot 2/2] sunxi: dram: Fix autorefresh timing setup

2014-04-29 Thread Siarhei Siamashka
On Sun, 06 Apr 2014 11:49:22 +0200
Jens Kuske  wrote:

> 
> On 06/04/14 04:19, Siarhei Siamashka wrote:
> > On Wed, 26 Mar 2014 17:40:50 +0100
> > Jens Kuske  wrote:
> > 
> >> This patch unifies sun4i and sun[5,7]i autorefresh setup functions
> >> and adds proper tRFC calculation.
> >>
> >> tRFC (REF command to ACT time) depends on DDR type and chip density.
> >>
> >> On sun4i there were two steps, 127.5ns for <=1Gb density and 327.5ns
> >> for the rest. This fits DDR2 specification for 1Gb and 4Gb chips
> >> and shouldn't be a problems with DDR3 chips <8Gb either, but it will
> >> waste some performance.
> >>
> >> On sun[5,7]i however, tRFC was hardcoded to 131 clock cycles, which
> >> seems to come from 4Gb DDR2 chips at 400MHz (327.5ns * 400MHz = 131).
> >> For 4Gb DDR3 chips, like those on cubieboard2 and cubietruck, this
> >> means the memory frequency was limited to ~435MHz if one doesn't want
> >> to fall below the minimum specified tRFC for these chips.
> >>
> >> Signed-off-by: Jens Kuske 
> >> ---
> >>  arch/arm/cpu/armv7/sunxi/dram.c| 70 
> >> --
> >>  arch/arm/include/asm/arch-sunxi/dram.h |  4 ++
> >>  2 files changed, 28 insertions(+), 46 deletions(-)
> >>
> >> diff --git a/arch/arm/cpu/armv7/sunxi/dram.c 
> >> b/arch/arm/cpu/armv7/sunxi/dram.c
> >> index 957db59..921f683 100644
> >> --- a/arch/arm/cpu/armv7/sunxi/dram.c
> >> +++ b/arch/arm/cpu/armv7/sunxi/dram.c
> >> @@ -412,53 +412,30 @@ static void dramc_clock_output_en(u32 on)
> >>  #endif
> >>  }
> >>  
> >> -#ifdef CONFIG_SUN4I
> >> -static void dramc_set_autorefresh_cycle(u32 clk)
> >> -{
> >> -  struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
> >> -  u32 reg_val;
> >> -  u32 tmp_val;
> >> -  u32 reg_dcr;
> >> -
> >> -  if (clk < 600) {
> >> -  reg_dcr = readl(&dram->dcr);
> >> -  if ((reg_dcr & DRAM_DCR_CHIP_DENSITY_MASK) <=
> >> -  DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_1024M))
> >> -  reg_val = (131 * clk) >> 10;
> >> -  else
> >> -  reg_val = (336 * clk) >> 10;
> >> -
> >> -  tmp_val = (7987 * clk) >> 10;
> >> -  tmp_val = tmp_val * 9 - 200;
> >> -  reg_val |= tmp_val << 8;
> >> -  reg_val |= 0x8 << 24;
> >> -  writel(reg_val, &dram->drr);
> >> -  } else {
> >> -  writel(0x0, &dram->drr);
> >> -  }
> >> -}
> >> -#endif /* SUN4I */
> >> +static const u16 tRFC_table[2][6] = {
> >> +  /*   256Mb512Mb1Gb  2Gb  4Gb  8Gb  */
> >> +  /* DDR2  75ns 105ns127.5ns  195ns327.5ns  invalid  */
> >> +  {77,  108, 131, 200, 336, 336 },
> >> +  /* DDR3  invalid  90ns 110ns160ns300ns350ns*/
> >> +  {93,  93,  113, 164, 308, 359 }
> >> +};
> >>  
> >> -#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
> >> -static void dramc_set_autorefresh_cycle(u32 clk)
> >> +static void dramc_set_autorefresh_cycle(u32 clk, u32 type, u32 density)
> >>  {
> >>struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
> >> -  u32 reg_val;
> >> -  u32 tmp_val;
> >> -  reg_val = 0x83;
> >> -
> >> -  tmp_val = (7987 * clk) >> 10;
> >> -  tmp_val = tmp_val * 9 - 200;
> >> -  reg_val |= tmp_val << 8;
> >> -  reg_val |= 0x8 << 24;
> >> -  writel(reg_val, &dram->drr);
> >> +  u32 tRFC, tREFI;
> >> +
> >> +  tRFC = (tRFC_table[type][density] * clk + 1023) >> 10;
> >> +  tREFI = (7987 * clk) >> 10; /* <= 7.8us */
> > 
> > Maybe I'm missing something, but what has happened to the "tmp_val =
> > tmp_val * 9 - 200" part of the old code? 
> > 
> > Also looks like there was an intention to replace "reg_val |= 0x8 <<
> > 24" with the use of the new DRAM_DRR_BURST macro, but I can't see it
> > anywhere either.
> > 
> 
> I forgot to explain that, I removed the burst refresh. Don't know
> whether this was a good idea, but there are some resources stating burst
> refreshes reduce power consumption at the expense of increased latency.
> Normally there is a tRFC-long refresh every tREFI, with burst there are
> 9*tRFC breaks every 9*tREFI. This leads to dram "hangs" of up to 3us
> every ~70us.
> 
> "reg_val |= 0x8 << 24" made the controller issue 9 refresh commands in
> burst, and thus the period between refresh had to be multiplied by 9.
> I don't know why they subtract 200, but it looks like some safety
> margin. Maybe I shouldn't have removed that...
> 
> This patch was a RFC to discuss such things, so thanks for the comments.
> Maybe it should be added again, but I don't think they originally wasted
> any thoughts on this, they simply took the default values (reset-value
> for burst is 0x8).

I have found a very interesting document, which seems to describe some
aspects of our dram controller:
http://www.ti.com/lit/pdf/spruhn7 (TI KeyStone II Architecture
   DDR3 Memory Controller)

Texas Instruments has apparently licensed the

Re: [linux-sunxi] [RFC PATCH u-boot 2/2] sunxi: dram: Fix autorefresh timing setup

2014-04-09 Thread Siarhei Siamashka
On Sun, 06 Apr 2014 11:49:22 +0200
Jens Kuske  wrote:
> On 06/04/14 04:19, Siarhei Siamashka wrote:
> > On Wed, 26 Mar 2014 17:40:50 +0100
> > Jens Kuske  wrote:
> > 
> >> -#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
> >> -static void dramc_set_autorefresh_cycle(u32 clk)
> >> +static void dramc_set_autorefresh_cycle(u32 clk, u32 type, u32 density)
> >>  {
> >>struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
> >> -  u32 reg_val;
> >> -  u32 tmp_val;
> >> -  reg_val = 0x83;
> >> -
> >> -  tmp_val = (7987 * clk) >> 10;
> >> -  tmp_val = tmp_val * 9 - 200;
> >> -  reg_val |= tmp_val << 8;
> >> -  reg_val |= 0x8 << 24;
> >> -  writel(reg_val, &dram->drr);
> >> +  u32 tRFC, tREFI;
> >> +
> >> +  tRFC = (tRFC_table[type][density] * clk + 1023) >> 10;
> >> +  tREFI = (7987 * clk) >> 10; /* <= 7.8us */
> > 
> > Maybe I'm missing something, but what has happened to the "tmp_val =
> > tmp_val * 9 - 200" part of the old code? 
> > 
> > Also looks like there was an intention to replace "reg_val |= 0x8 <<
> > 24" with the use of the new DRAM_DRR_BURST macro, but I can't see it
> > anywhere either.
> > 
> 
> I forgot to explain that, I removed the burst refresh. Don't know
> whether this was a good idea, but there are some resources stating burst
> refreshes reduce power consumption at the expense of increased latency.
> Normally there is a tRFC-long refresh every tREFI, with burst there are
> 9*tRFC breaks every 9*tREFI. This leads to dram "hangs" of up to 3us
> every ~70us.
> 
> "reg_val |= 0x8 << 24" made the controller issue 9 refresh commands in
> burst, and thus the period between refresh had to be multiplied by 9.
> I don't know why they subtract 200, but it looks like some safety
> margin. Maybe I shouldn't have removed that...
> 
> This patch was a RFC to discuss such things, so thanks for the comments.
> Maybe it should be added again, but I don't think they originally wasted
> any thoughts on this, they simply took the default values (reset-value
> for burst is 0x8).

Thanks a lot for the explanations. It all makes sense.

Have you tried to check if disabling burst refresh helps to prevent
the occasional HDMI signal disruption, sometimes observed when
driving a 1920x1080 monitor and doing something memory intensive
at the same time? I believe that this could have been your original
intention when introducing this tweak ;-)

-- 
Best regards,
Siarhei Siamashka

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [linux-sunxi] [RFC PATCH u-boot 2/2] sunxi: dram: Fix autorefresh timing setup

2014-04-06 Thread Jens Kuske

On 06/04/14 04:19, Siarhei Siamashka wrote:
> On Wed, 26 Mar 2014 17:40:50 +0100
> Jens Kuske  wrote:
> 
>> This patch unifies sun4i and sun[5,7]i autorefresh setup functions
>> and adds proper tRFC calculation.
>>
>> tRFC (REF command to ACT time) depends on DDR type and chip density.
>>
>> On sun4i there were two steps, 127.5ns for <=1Gb density and 327.5ns
>> for the rest. This fits DDR2 specification for 1Gb and 4Gb chips
>> and shouldn't be a problems with DDR3 chips <8Gb either, but it will
>> waste some performance.
>>
>> On sun[5,7]i however, tRFC was hardcoded to 131 clock cycles, which
>> seems to come from 4Gb DDR2 chips at 400MHz (327.5ns * 400MHz = 131).
>> For 4Gb DDR3 chips, like those on cubieboard2 and cubietruck, this
>> means the memory frequency was limited to ~435MHz if one doesn't want
>> to fall below the minimum specified tRFC for these chips.
>>
>> Signed-off-by: Jens Kuske 
>> ---
>>  arch/arm/cpu/armv7/sunxi/dram.c| 70 
>> --
>>  arch/arm/include/asm/arch-sunxi/dram.h |  4 ++
>>  2 files changed, 28 insertions(+), 46 deletions(-)
>>
>> diff --git a/arch/arm/cpu/armv7/sunxi/dram.c 
>> b/arch/arm/cpu/armv7/sunxi/dram.c
>> index 957db59..921f683 100644
>> --- a/arch/arm/cpu/armv7/sunxi/dram.c
>> +++ b/arch/arm/cpu/armv7/sunxi/dram.c
>> @@ -412,53 +412,30 @@ static void dramc_clock_output_en(u32 on)
>>  #endif
>>  }
>>  
>> -#ifdef CONFIG_SUN4I
>> -static void dramc_set_autorefresh_cycle(u32 clk)
>> -{
>> -struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
>> -u32 reg_val;
>> -u32 tmp_val;
>> -u32 reg_dcr;
>> -
>> -if (clk < 600) {
>> -reg_dcr = readl(&dram->dcr);
>> -if ((reg_dcr & DRAM_DCR_CHIP_DENSITY_MASK) <=
>> -DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_1024M))
>> -reg_val = (131 * clk) >> 10;
>> -else
>> -reg_val = (336 * clk) >> 10;
>> -
>> -tmp_val = (7987 * clk) >> 10;
>> -tmp_val = tmp_val * 9 - 200;
>> -reg_val |= tmp_val << 8;
>> -reg_val |= 0x8 << 24;
>> -writel(reg_val, &dram->drr);
>> -} else {
>> -writel(0x0, &dram->drr);
>> -}
>> -}
>> -#endif /* SUN4I */
>> +static const u16 tRFC_table[2][6] = {
>> +/*   256Mb512Mb1Gb  2Gb  4Gb  8Gb  */
>> +/* DDR2  75ns 105ns127.5ns  195ns327.5ns  invalid  */
>> +{77,  108, 131, 200, 336, 336 },
>> +/* DDR3  invalid  90ns 110ns160ns300ns350ns*/
>> +{93,  93,  113, 164, 308, 359 }
>> +};
>>  
>> -#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
>> -static void dramc_set_autorefresh_cycle(u32 clk)
>> +static void dramc_set_autorefresh_cycle(u32 clk, u32 type, u32 density)
>>  {
>>  struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
>> -u32 reg_val;
>> -u32 tmp_val;
>> -reg_val = 0x83;
>> -
>> -tmp_val = (7987 * clk) >> 10;
>> -tmp_val = tmp_val * 9 - 200;
>> -reg_val |= tmp_val << 8;
>> -reg_val |= 0x8 << 24;
>> -writel(reg_val, &dram->drr);
>> +u32 tRFC, tREFI;
>> +
>> +tRFC = (tRFC_table[type][density] * clk + 1023) >> 10;
>> +tREFI = (7987 * clk) >> 10; /* <= 7.8us */
> 
> Maybe I'm missing something, but what has happened to the "tmp_val =
> tmp_val * 9 - 200" part of the old code? 
> 
> Also looks like there was an intention to replace "reg_val |= 0x8 <<
> 24" with the use of the new DRAM_DRR_BURST macro, but I can't see it
> anywhere either.
> 

I forgot to explain that, I removed the burst refresh. Don't know
whether this was a good idea, but there are some resources stating burst
refreshes reduce power consumption at the expense of increased latency.
Normally there is a tRFC-long refresh every tREFI, with burst there are
9*tRFC breaks every 9*tREFI. This leads to dram "hangs" of up to 3us
every ~70us.

"reg_val |= 0x8 << 24" made the controller issue 9 refresh commands in
burst, and thus the period between refresh had to be multiplied by 9.
I don't know why they subtract 200, but it looks like some safety
margin. Maybe I shouldn't have removed that...

This patch was a RFC to discuss such things, so thanks for the comments.
Maybe it should be added again, but I don't think they originally wasted
any thoughts on this, they simply took the default values (reset-value
for burst is 0x8).

>> +
>> +writel(DRAM_DRR_TREFI(tREFI) | DRAM_DRR_TRFC(tRFC), &dram->drr);
>>  }
>> -#endif /* SUN5I */
>>  
>>  unsigned long dramc_init(struct dram_para *para)
>>  {
>>  struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
>>  u32 reg_val;
>> +u32 density;
>>  int ret_val;
>>  
>>  /* check input dram parameter structure */
>> @@ -497,20 +474,21 @@ unsigned long dramc_init(struct dram_para *para)
>>  reg_val |= DRAM_DCR_IO_WIDTH(para->io

Re: [linux-sunxi] [RFC PATCH u-boot 2/2] sunxi: dram: Fix autorefresh timing setup

2014-04-05 Thread Siarhei Siamashka
On Wed, 26 Mar 2014 17:40:50 +0100
Jens Kuske  wrote:

> This patch unifies sun4i and sun[5,7]i autorefresh setup functions
> and adds proper tRFC calculation.
> 
> tRFC (REF command to ACT time) depends on DDR type and chip density.
> 
> On sun4i there were two steps, 127.5ns for <=1Gb density and 327.5ns
> for the rest. This fits DDR2 specification for 1Gb and 4Gb chips
> and shouldn't be a problems with DDR3 chips <8Gb either, but it will
> waste some performance.
> 
> On sun[5,7]i however, tRFC was hardcoded to 131 clock cycles, which
> seems to come from 4Gb DDR2 chips at 400MHz (327.5ns * 400MHz = 131).
> For 4Gb DDR3 chips, like those on cubieboard2 and cubietruck, this
> means the memory frequency was limited to ~435MHz if one doesn't want
> to fall below the minimum specified tRFC for these chips.
> 
> Signed-off-by: Jens Kuske 
> ---
>  arch/arm/cpu/armv7/sunxi/dram.c| 70 
> --
>  arch/arm/include/asm/arch-sunxi/dram.h |  4 ++
>  2 files changed, 28 insertions(+), 46 deletions(-)
> 
> diff --git a/arch/arm/cpu/armv7/sunxi/dram.c b/arch/arm/cpu/armv7/sunxi/dram.c
> index 957db59..921f683 100644
> --- a/arch/arm/cpu/armv7/sunxi/dram.c
> +++ b/arch/arm/cpu/armv7/sunxi/dram.c
> @@ -412,53 +412,30 @@ static void dramc_clock_output_en(u32 on)
>  #endif
>  }
>  
> -#ifdef CONFIG_SUN4I
> -static void dramc_set_autorefresh_cycle(u32 clk)
> -{
> - struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
> - u32 reg_val;
> - u32 tmp_val;
> - u32 reg_dcr;
> -
> - if (clk < 600) {
> - reg_dcr = readl(&dram->dcr);
> - if ((reg_dcr & DRAM_DCR_CHIP_DENSITY_MASK) <=
> - DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_1024M))
> - reg_val = (131 * clk) >> 10;
> - else
> - reg_val = (336 * clk) >> 10;
> -
> - tmp_val = (7987 * clk) >> 10;
> - tmp_val = tmp_val * 9 - 200;
> - reg_val |= tmp_val << 8;
> - reg_val |= 0x8 << 24;
> - writel(reg_val, &dram->drr);
> - } else {
> - writel(0x0, &dram->drr);
> - }
> -}
> -#endif /* SUN4I */
> +static const u16 tRFC_table[2][6] = {
> + /*   256Mb512Mb1Gb  2Gb  4Gb  8Gb  */
> + /* DDR2  75ns 105ns127.5ns  195ns327.5ns  invalid  */
> + {77,  108, 131, 200, 336, 336 },
> + /* DDR3  invalid  90ns 110ns160ns300ns350ns*/
> + {93,  93,  113, 164, 308, 359 }
> +};
>  
> -#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
> -static void dramc_set_autorefresh_cycle(u32 clk)
> +static void dramc_set_autorefresh_cycle(u32 clk, u32 type, u32 density)
>  {
>   struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
> - u32 reg_val;
> - u32 tmp_val;
> - reg_val = 0x83;
> -
> - tmp_val = (7987 * clk) >> 10;
> - tmp_val = tmp_val * 9 - 200;
> - reg_val |= tmp_val << 8;
> - reg_val |= 0x8 << 24;
> - writel(reg_val, &dram->drr);
> + u32 tRFC, tREFI;
> +
> + tRFC = (tRFC_table[type][density] * clk + 1023) >> 10;
> + tREFI = (7987 * clk) >> 10; /* <= 7.8us */

Maybe I'm missing something, but what has happened to the "tmp_val =
tmp_val * 9 - 200" part of the old code? 

Also looks like there was an intention to replace "reg_val |= 0x8 <<
24" with the use of the new DRAM_DRR_BURST macro, but I can't see it
anywhere either.

> +
> + writel(DRAM_DRR_TREFI(tREFI) | DRAM_DRR_TRFC(tRFC), &dram->drr);
>  }
> -#endif /* SUN5I */
>  
>  unsigned long dramc_init(struct dram_para *para)
>  {
>   struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
>   u32 reg_val;
> + u32 density;
>   int ret_val;
>  
>   /* check input dram parameter structure */
> @@ -497,20 +474,21 @@ unsigned long dramc_init(struct dram_para *para)
>   reg_val |= DRAM_DCR_IO_WIDTH(para->io_width >> 3);
>  
>   if (para->density == 256)
> - reg_val |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_256M);
> + density = DRAM_DCR_CHIP_DENSITY_256M;
>   else if (para->density == 512)
> - reg_val |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_512M);
> + density = DRAM_DCR_CHIP_DENSITY_512M;
>   else if (para->density == 1024)
> - reg_val |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_1024M);
> + density = DRAM_DCR_CHIP_DENSITY_1024M;
>   else if (para->density == 2048)
> - reg_val |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_2048M);
> + density = DRAM_DCR_CHIP_DENSITY_2048M;
>   else if (para->density == 4096)
> - reg_val |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_4096M);
> + density = DRAM_DCR_CHIP_DENSITY_4096M;
>   else if (para->density == 8192)
> - reg_val |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_

Re: [linux-sunxi] [RFC PATCH u-boot 2/2] sunxi: dram: Fix autorefresh timing setup

2014-03-27 Thread Olliver Schinagl

On 03/26/2014 05:40 PM, Jens Kuske wrote:

This patch unifies sun4i and sun[5,7]i autorefresh setup functions
and adds proper tRFC calculation.

tRFC (REF command to ACT time) depends on DDR type and chip density.

On sun4i there were two steps, 127.5ns for <=1Gb density and 327.5ns
for the rest. This fits DDR2 specification for 1Gb and 4Gb chips
and shouldn't be a problems with DDR3 chips <8Gb either, but it will
waste some performance.

On sun[5,7]i however, tRFC was hardcoded to 131 clock cycles, which
seems to come from 4Gb DDR2 chips at 400MHz (327.5ns * 400MHz = 131).
For 4Gb DDR3 chips, like those on cubieboard2 and cubietruck, this
means the memory frequency was limited to ~435MHz if one doesn't want
to fall below the minimum specified tRFC for these chips.


The math here all seems to make sense and add up. I really love that you 
took time to investigate this.


With this being a pretty crucial change, I would like for people to test 
this extensively, over a longer period (say a few weeks?). As this may 
seem to work 'just fine' for a day  you get what I'm saying anyway :)



Olliver



Signed-off-by: Jens Kuske 
---
  arch/arm/cpu/armv7/sunxi/dram.c| 70 --
  arch/arm/include/asm/arch-sunxi/dram.h |  4 ++
  2 files changed, 28 insertions(+), 46 deletions(-)

diff --git a/arch/arm/cpu/armv7/sunxi/dram.c b/arch/arm/cpu/armv7/sunxi/dram.c
index 957db59..921f683 100644
--- a/arch/arm/cpu/armv7/sunxi/dram.c
+++ b/arch/arm/cpu/armv7/sunxi/dram.c
@@ -412,53 +412,30 @@ static void dramc_clock_output_en(u32 on)
  #endif
  }

-#ifdef CONFIG_SUN4I
-static void dramc_set_autorefresh_cycle(u32 clk)
-{
-   struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
-   u32 reg_val;
-   u32 tmp_val;
-   u32 reg_dcr;
-
-   if (clk < 600) {
-   reg_dcr = readl(&dram->dcr);
-   if ((reg_dcr & DRAM_DCR_CHIP_DENSITY_MASK) <=
-   DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_1024M))
-   reg_val = (131 * clk) >> 10;
-   else
-   reg_val = (336 * clk) >> 10;
-
-   tmp_val = (7987 * clk) >> 10;
-   tmp_val = tmp_val * 9 - 200;
-   reg_val |= tmp_val << 8;
-   reg_val |= 0x8 << 24;
-   writel(reg_val, &dram->drr);
-   } else {
-   writel(0x0, &dram->drr);
-   }
-}
-#endif /* SUN4I */
+static const u16 tRFC_table[2][6] = {
+   /*   256Mb512Mb1Gb  2Gb  4Gb  8Gb  */
+   /* DDR2  75ns 105ns127.5ns  195ns327.5ns  invalid  */
+   {77,  108, 131, 200, 336, 336 },
+   /* DDR3  invalid  90ns 110ns160ns300ns350ns*/
+   {93,  93,  113, 164, 308, 359 }
+};

-#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
-static void dramc_set_autorefresh_cycle(u32 clk)
+static void dramc_set_autorefresh_cycle(u32 clk, u32 type, u32 density)
  {
struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
-   u32 reg_val;
-   u32 tmp_val;
-   reg_val = 0x83;
-
-   tmp_val = (7987 * clk) >> 10;
-   tmp_val = tmp_val * 9 - 200;
-   reg_val |= tmp_val << 8;
-   reg_val |= 0x8 << 24;
-   writel(reg_val, &dram->drr);
+   u32 tRFC, tREFI;
+
+   tRFC = (tRFC_table[type][density] * clk + 1023) >> 10;
+   tREFI = (7987 * clk) >> 10;   /* <= 7.8us */
+
+   writel(DRAM_DRR_TREFI(tREFI) | DRAM_DRR_TRFC(tRFC), &dram->drr);
  }
-#endif /* SUN5I */

  unsigned long dramc_init(struct dram_para *para)
  {
struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
u32 reg_val;
+   u32 density;
int ret_val;

/* check input dram parameter structure */
@@ -497,20 +474,21 @@ unsigned long dramc_init(struct dram_para *para)
reg_val |= DRAM_DCR_IO_WIDTH(para->io_width >> 3);

if (para->density == 256)
-   reg_val |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_256M);
+   density = DRAM_DCR_CHIP_DENSITY_256M;
else if (para->density == 512)
-   reg_val |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_512M);
+   density = DRAM_DCR_CHIP_DENSITY_512M;
else if (para->density == 1024)
-   reg_val |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_1024M);
+   density = DRAM_DCR_CHIP_DENSITY_1024M;
else if (para->density == 2048)
-   reg_val |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_2048M);
+   density = DRAM_DCR_CHIP_DENSITY_2048M;
else if (para->density == 4096)
-   reg_val |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_4096M);
+   density = DRAM_DCR_CHIP_DENSITY_4096M;
else if (para->density == 8192)
-   reg_val |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_8192M);
+   density = DRA