diff options
Diffstat (limited to 'arch/arm/cpu/armv7/sunxi/dram.c')
-rw-r--r-- | arch/arm/cpu/armv7/sunxi/dram.c | 81 |
1 files changed, 78 insertions, 3 deletions
diff --git a/arch/arm/cpu/armv7/sunxi/dram.c b/arch/arm/cpu/armv7/sunxi/dram.c index b43c4b41d3..1de752904b 100644 --- a/arch/arm/cpu/armv7/sunxi/dram.c +++ b/arch/arm/cpu/armv7/sunxi/dram.c @@ -53,16 +53,37 @@ static void mctl_ddr3_reset(void) struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; - clrbits_le32(&dram->mcr, DRAM_MCR_RESET); - udelay(2); - setbits_le32(&dram->mcr, DRAM_MCR_RESET); +#ifdef CONFIG_SUN4I + struct sunxi_timer_reg *timer = + (struct sunxi_timer_reg *)SUNXI_TIMER_BASE; + u32 reg_val; + + writel(0, &timer->cpu_cfg); + reg_val = readl(&timer->cpu_cfg); + + if ((reg_val & CPU_CFG_CHIP_VER_MASK) != + CPU_CFG_CHIP_VER(CPU_CFG_CHIP_REV_A)) { + setbits_le32(&dram->mcr, DRAM_MCR_RESET); + udelay(2); + clrbits_le32(&dram->mcr, DRAM_MCR_RESET); + } else +#endif + { + clrbits_le32(&dram->mcr, DRAM_MCR_RESET); + udelay(2); + setbits_le32(&dram->mcr, DRAM_MCR_RESET); + } } static void mctl_set_drive(void) { struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; +#ifdef CONFIG_SUN7I clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3) | (0x3 << 28), +#else + clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3), +#endif DRAM_MCR_MODE_EN(0x3) | 0xffc); } @@ -134,6 +155,16 @@ static void mctl_enable_dllx(u32 phase) } static u32 hpcr_value[32] = { +#ifdef CONFIG_SUN4I + 0x0301, 0x0301, 0x0301, 0x0301, + 0x0301, 0x0301, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0x1031, 0x1031, 0x0735, 0x5031, + 0x1035, 0x0731, 0x1031, 0x0735, + 0x1035, 0x1031, 0x0731, 0x1035, + 0x1031, 0x0301, 0x0301, 0x0731 +#endif #ifdef CONFIG_SUN7I 0x0301, 0x0301, 0x0301, 0x0301, 0x0301, 0x0301, 0x0301, 0x0301, @@ -223,22 +254,32 @@ static void mctl_setup_dram_clock(u32 clk) clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_GPS); #endif +#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I) /* setup MBUS clock */ reg_val = CCM_MBUS_CTRL_GATE | CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL6) | CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(2)) | CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(2)); writel(reg_val, &ccm->mbus_clk_cfg); +#endif /* * open DRAMC AHB & DLL register clock * close it first */ +#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I) clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL); +#else + clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM); +#endif udelay(22); /* then open it */ +#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I) setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL); +#else + setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM); +#endif udelay(22); } @@ -385,6 +426,13 @@ static void dramc_clock_output_en(u32 on) else clrbits_le32(&dram->mcr, DRAM_MCR_DCLK_OUT); #endif +#ifdef CONFIG_SUN4I + struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + if (on) + setbits_le32(&ccm->dram_clk_cfg, CCM_DRAM_CTRL_DCLK_OUT); + else + clrbits_le32(&ccm->dram_clk_cfg, CCM_DRAM_CTRL_DCLK_OUT); +#endif } static const u16 tRFC_table[2][6] = { @@ -421,11 +469,19 @@ unsigned long dramc_init(struct dram_para *para) mctl_setup_dram_clock(para->clock); /* reset external DRAM */ +#ifndef CONFIG_SUN7I + mctl_ddr3_reset(); +#endif mctl_set_drive(); /* dram clock off */ dramc_clock_output_en(0); +#ifdef CONFIG_SUN4I + /* select dram controller 1 */ + writel(DRAM_CSEL_MAGIC, &dram->csel); +#endif + mctl_itm_disable(); mctl_enable_dll0(para->tpr3); @@ -482,6 +538,9 @@ unsigned long dramc_init(struct dram_para *para) mctl_ddr3_reset(); else setbits_le32(&dram->mcr, DRAM_MCR_RESET); +#else + /* dram clock on */ + dramc_clock_output_en(1); #endif udelay(1); @@ -490,6 +549,22 @@ unsigned long dramc_init(struct dram_para *para) mctl_enable_dllx(para->tpr3); +#ifdef CONFIG_SUN4I + /* set odt impedance divide ratio */ + reg_val = ((para->zq) >> 8) & 0xfffff; + reg_val |= ((para->zq) & 0xff) << 20; + reg_val |= (para->zq) & 0xf0000000; + writel(reg_val, &dram->zqcr0); +#endif + +#ifdef CONFIG_SUN4I + /* set I/O configure register */ + reg_val = 0x00cc0000; + reg_val |= (para->odt_en) & 0x3; + reg_val |= ((para->odt_en) & 0x3) << 30; + writel(reg_val, &dram->iocr); +#endif + /* set refresh period */ dramc_set_autorefresh_cycle(para->clock, para->type - 2, density); |