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 <jensku...@gmail.com>
---
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] = {
+ /* 256Mb 512Mb 1Gb 2Gb 4Gb 8Gb */
+ /* DDR2 75ns 105ns 127.5ns 195ns 327.5ns invalid */
+ { 77, 108, 131, 200, 336, 336 },
+ /* DDR3 invalid 90ns 110ns 160ns 300ns 350ns */
+ { 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 = DRAM_DCR_CHIP_DENSITY_8192M;
else
- reg_val |= DRAM_DCR_CHIP_DENSITY(DRAM_DCR_CHIP_DENSITY_256M);
+ density = DRAM_DCR_CHIP_DENSITY_256M;
+ reg_val |= DRAM_DCR_CHIP_DENSITY(density);
reg_val |= DRAM_DCR_BUS_WIDTH((para->bus_width >> 3) - 1);
reg_val |= DRAM_DCR_RANK_SEL(para->rank_num - 1);
reg_val |= DRAM_DCR_CMD_RANK_ALL;
@@ -571,7 +549,7 @@ unsigned long dramc_init(struct dram_para *para)
#endif
/* set refresh period */
- dramc_set_autorefresh_cycle(para->clock);
+ dramc_set_autorefresh_cycle(para->clock, para->type - 2, density);
/* set timing parameters */
writel(para->tpr0, &dram->tpr0);
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h
b/arch/arm/include/asm/arch-sunxi/dram.h
index 041a02d..67fbfad 100644
--- a/arch/arm/include/asm/arch-sunxi/dram.h
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -134,6 +134,10 @@ struct dram_para {
#define DRAM_CSR_FAILED (0x1 << 20)
+#define DRAM_DRR_TRFC(n) ((n) & 0xff)
+#define DRAM_DRR_TREFI(n) (((n) & 0xffff) << 8)
+#define DRAM_DRR_BURST(n) ((((n) - 1) & 0xf) << 24)
+
#define DRAM_MCR_MODE_NORM(n) (((n) & 0x3) << 0)
#define DRAM_MCR_MODE_NORM_MASK DRAM_MCR_MOD_NORM(0x3)
#define DRAM_MCR_MODE_DQ_OUT(n) (((n) & 0x3) << 2)
--
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.