On Wed, 26 Mar 2014 17:40:50 +0100 Jens Kuske <jensku...@gmail.com> 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 <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 */ 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_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) -- 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.