Signed-off-by: Hans de Goede <hdego...@redhat.com> --- arch/arm/cpu/armv7/sunxi/board.c | 2 +- arch/arm/cpu/armv7/sunxi/clock.c | 2 + arch/arm/cpu/armv7/sunxi/cpu_info.c | 7 ++ arch/arm/cpu/armv7/sunxi/dram.c | 129 ++++++++++++++++++++++++++++++++++++ board/sunxi/Makefile | 3 +- board/sunxi/dram_a10_olinuxino_l.c | 31 +++++++++ boards.cfg | 1 + drivers/mmc/sunxi_mmc.c | 10 +++ include/configs/sun4i.h | 40 +++++++++++ 9 files changed, 223 insertions(+), 2 deletions(-) create mode 100644 board/sunxi/dram_a10_olinuxino_l.c create mode 100644 include/configs/sun4i.h
diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c index 2668d52..2225e31 100644 --- a/arch/arm/cpu/armv7/sunxi/board.c +++ b/arch/arm/cpu/armv7/sunxi/board.c @@ -82,7 +82,7 @@ void reset_cpu(ulong addr) /* do some early init */ void s_init(void) { -#if !defined CONFIG_SPL_BUILD +#if !defined CONFIG_SPL_BUILD && defined CONFIG_SUN7I /* Enable SMP mode for CPU0, by setting bit 6 of Auxiliary Ctl reg */ asm volatile( "mrc p15, 0, r0, c1, c0, 1\n" diff --git a/arch/arm/cpu/armv7/sunxi/clock.c b/arch/arm/cpu/armv7/sunxi/clock.c index e3abaf0..f685dda 100644 --- a/arch/arm/cpu/armv7/sunxi/clock.c +++ b/arch/arm/cpu/armv7/sunxi/clock.c @@ -43,8 +43,10 @@ static void clock_init_safe(void) sdelay(200); writel(AXI_DIV_1 << 0 | AHB_DIV_2 << 4 | APB0_DIV_1 << 8 | CPU_CLK_SRC_PLL1 << 16, &ccm->cpu_ahb_apb0_cfg); +#ifdef CONFIG_SUN7I writel(0x1 << 6 | readl(&ccm->ahb_gate0), &ccm->ahb_gate0); writel(0x1 << 31 | readl(&ccm->pll6_cfg), &ccm->pll6_cfg); +#endif } #endif diff --git a/arch/arm/cpu/armv7/sunxi/cpu_info.c b/arch/arm/cpu/armv7/sunxi/cpu_info.c index 14093dd..31c9f96 100644 --- a/arch/arm/cpu/armv7/sunxi/cpu_info.c +++ b/arch/arm/cpu/armv7/sunxi/cpu_info.c @@ -29,7 +29,14 @@ #ifdef CONFIG_DISPLAY_CPUINFO int print_cpuinfo(void) { +#ifdef CONFIG_SUN4I + puts("CPU: Allwinner A10 (SUN4I)\n"); +#elif defined CONFIG_SUN7I puts("CPU: Allwinner A20 (SUN7I)\n"); +#else +#warning Please update cpu_info.c with correct CPU information + puts("CPU: SUNXI Family\n"); +#endif return 0; } #endif diff --git a/arch/arm/cpu/armv7/sunxi/dram.c b/arch/arm/cpu/armv7/sunxi/dram.c index c34322d..08db987 100644 --- a/arch/arm/cpu/armv7/sunxi/dram.c +++ b/arch/arm/cpu/armv7/sunxi/dram.c @@ -49,6 +49,21 @@ static void mctl_ddr3_reset(void) struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; +#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); @@ -60,7 +75,11 @@ 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); } @@ -112,7 +131,11 @@ static void mctl_enable_dllx(u32 phase) n = DRAM_DCR_NR_DLLCR_16BIT; for (i = 1; i < n; i++) { +#ifdef CONFIG_SUN7I clrsetbits_le32(&dram->dllcr[i], 0xf << 14, +#else + clrsetbits_le32(&dram->dllcr[i], 0x4 << 14, +#endif (phase & 0xf) << 14); clrsetbits_le32(&dram->dllcr[i], DRAM_DLLCR_NRESET, DRAM_DLLCR_DISABLE); @@ -132,6 +155,17 @@ 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, 0x1035, + 0x1035, 0x0731, 0x1031, 0x0735, + 0x1035, 0x1031, 0x0731, 0x1035, + 0x1031, 0x0301, 0x0301, 0x0731 +#endif +#ifdef CONFIG_SUN7I 0x0301, 0x0301, 0x0301, 0x0301, 0x0301, 0x0301, 0x0301, 0x0301, 0, 0, 0, 0, @@ -145,6 +179,7 @@ static u32 hpcr_value[32] = { * but boot0 code skips #28 and #30, and sets #29 and #31 to the * value from #28 entry (0x1031) */ +#endif }; static void mctl_configure_hostport(void) @@ -186,20 +221,34 @@ static void mctl_setup_dram_clock(u32 clk) /* setup MBUS clock */ reg_val = CCM_MBUS_CTRL_GATE | +#if defined(CONFIG_SUN7I) 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)); +#else /* defined(CONFIG_SUN7I) */ + CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL5) | + CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(1)) | + CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(2)); +#endif writel(reg_val, &ccm->mbus_clk_cfg); /* * open DRAMC AHB & DLL register clock * close it first */ +#if 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_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); } @@ -209,7 +258,9 @@ static int dramc_scan_readpipe(void) u32 reg_val; /* data training trigger */ +#ifdef CONFIG_SUN7I clrbits_le32(&dram->csr, DRAM_CSR_FAILED); +#endif setbits_le32(&dram->ccr, DRAM_CCR_DATA_TRAINING); /* check whether data training process has completed */ @@ -336,15 +387,51 @@ fail: static void dramc_clock_output_en(u32 on) { +#if defined(CONFIG_SUN7I) struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; if (on) setbits_le32(&dram->mcr, DRAM_MCR_DCLK_OUT); 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 } +#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 */ +#if defined(CONFIG_SUN7I) static void dramc_set_autorefresh_cycle(u32 clk) { struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE; @@ -358,6 +445,7 @@ static void dramc_set_autorefresh_cycle(u32 clk) reg_val |= 0x8 << 24; writel(reg_val, &dram->drr); } +#endif /* SUN7I */ unsigned long dramc_init(struct dram_para *para) { @@ -373,11 +461,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); @@ -408,24 +504,35 @@ unsigned long dramc_init(struct dram_para *para) reg_val |= DRAM_DCR_MODE(DRAM_DCR_MODE_INTERLEAVE); writel(reg_val, &dram->dcr); +#ifdef CONFIG_SUN7I setbits_le32(&dram->zqcr1, (0x1 << 24) | (0x1 << 1)); if (para->tpr4 & 0x2) clrsetbits_le32(&dram->zqcr1, (0x1 << 24), (0x1 << 1)); dramc_clock_output_en(1); +#endif +#ifdef CONFIG_SUN7I /* set odt impendance 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_SUN7I /* Set CKE Delay to about 1ms */ setbits_le32(&dram->idcr, 0x1ffff); +#endif +#ifdef CONFIG_SUN7I if ((readl(&dram->ppwrsctl) & 0x1) != 0x1) mctl_ddr3_reset(); else setbits_le32(&dram->mcr, DRAM_MCR_RESET); +#else + /* dram clock on */ + dramc_clock_output_en(1); +#endif udelay(1); @@ -433,6 +540,22 @@ unsigned long dramc_init(struct dram_para *para) mctl_enable_dllx(para->tpr3); +#ifdef CONFIG_SUN4I + /* set odt impendance 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); @@ -443,7 +566,9 @@ unsigned long dramc_init(struct dram_para *para) if (para->type == DRAM_MEMORY_TYPE_DDR3) { reg_val = DRAM_MR_BURST_LENGTH(0x0); +#if defined(CONFIG_SUN7I) reg_val |= DRAM_MR_POWER_DOWN; +#endif reg_val |= DRAM_MR_CAS_LAT(para->cas - 4); reg_val |= DRAM_MR_WRITE_RECOVERY(0x5); } else if (para->type == DRAM_MEMORY_TYPE_DDR2) { @@ -460,13 +585,16 @@ unsigned long dramc_init(struct dram_para *para) /* set DQS window mode */ clrsetbits_le32(&dram->ccr, DRAM_CCR_DQS_DRIFT_COMP, DRAM_CCR_DQS_GATE); +#ifdef CONFIG_SUN7I /* Command rate timing mode 2T & 1T */ if (para->tpr4 & 0x1) setbits_le32(&dram->ccr, DRAM_CCR_COMMAND_RATE_1T); +#endif /* reset external DRAM */ setbits_le32(&dram->ccr, DRAM_CCR_INIT); while (readl(&dram->ccr) & DRAM_CCR_INIT); +#ifdef CONFIG_SUN7I /* setup zq calibration manual */ reg_val = readl(&dram->ppwrsctl); if ((reg_val & 0x1) == 1) { @@ -502,6 +630,7 @@ unsigned long dramc_init(struct dram_para *para) udelay(2); } +#endif /* scan read pipe value */ mctl_itm_enable(); diff --git a/board/sunxi/Makefile b/board/sunxi/Makefile index 180adc9..2ebcd8a 100644 --- a/board/sunxi/Makefile +++ b/board/sunxi/Makefile @@ -26,4 +26,5 @@ # obj-y += board.o -obj-y += dram_cubietruck.o +obj-$(CONFIG_A10_OLINUXINO_L) += dram_a10_olinuxino_l.o +obj-$(CONFIG_CUBIETRUCK) += dram_cubietruck.o diff --git a/board/sunxi/dram_a10_olinuxino_l.c b/board/sunxi/dram_a10_olinuxino_l.c new file mode 100644 index 0000000..24a1bd9 --- /dev/null +++ b/board/sunxi/dram_a10_olinuxino_l.c @@ -0,0 +1,31 @@ +/* this file is generated, don't edit it yourself */ + +#include <common.h> +#include <asm/arch/dram.h> + +static struct dram_para dram_para = { + .clock = 480, + .type = 3, + .rank_num = 1, + .density = 4096, + .io_width = 16, + .bus_width = 16, + .cas = 6, + .zq = 123, + .odt_en = 0, + .size = 512, + .tpr0 = 0x30926692, + .tpr1 = 0x1090, + .tpr2 = 0x1a0c8, + .tpr3 = 0, + .tpr4 = 0, + .tpr5 = 0, + .emr1 = 0x4, + .emr2 = 0, + .emr3 = 0, +}; + +unsigned long sunxi_dram_init(void) +{ + return dramc_init(&dram_para); +} diff --git a/boards.cfg b/boards.cfg index a513376..07dd65a 100644 --- a/boards.cfg +++ b/boards.cfg @@ -353,6 +353,7 @@ Active arm armv7 rmobile renesas koelsch Active arm armv7 s5pc1xx samsung goni s5p_goni - Mateusz Zalega <m.zal...@samsung.com> Active arm armv7 s5pc1xx samsung smdkc100 smdkc100 - Minkyu Kang <mk7.k...@samsung.com> Active arm armv7 socfpga altera socfpga socfpga_cyclone5 - - +Active arm armv7 sunxi - sunxi A10-OLinuXino-Lime sun4i:A10_OLINUXINO_L,SPL - Active arm armv7 sunxi - sunxi Cubietruck sun7i:CUBIETRUCK,SPL - Active arm armv7 sunxi - sunxi Cubietruck_FEL sun7i:CUBIETRUCK,SPL_FEL - Active arm armv7 u8500 st-ericsson snowball snowball - Mathieu Poirier <mathieu.poir...@linaro.org> diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index 13eba76..be5f301 100755 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -87,10 +87,20 @@ struct sunxi_mmc_des { u32 reserved1_2:24; u32 card_err_sum:1; /* transfer error flag */ u32 own:1; /* des owner:1-idma owns it, 0-host owns it */ +#ifdef CONFIG_SUN4I +#define SDXC_DES_NUM_SHIFT 13 +#define SDXC_DES_BUFFER_MAX_LEN (1 << SDXC_DES_NUM_SHIFT) + u32 data_buf1_sz:13; + u32 data_buf2_sz:13; + u32 reserverd2_1:6; +#elif defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I) #define SDXC_DES_NUM_SHIFT 16 #define SDXC_DES_BUFFER_MAX_LEN (1 << SDXC_DES_NUM_SHIFT) u32 data_buf1_sz:16; u32 data_buf2_sz:16; +#else +#error ">>>> Wrong Platform for MMC <<<<" +#endif u32 buf_addr_ptr1; u32 buf_addr_ptr2; }; diff --git a/include/configs/sun4i.h b/include/configs/sun4i.h new file mode 100644 index 0000000..4f37372 --- /dev/null +++ b/include/configs/sun4i.h @@ -0,0 +1,40 @@ +/* + * (C) Copyright 2012-2013 Henrik Nordstrom <hen...@henriknordstrom.net> + * + * Configuration settings for the Allwinner A10 (sun4i) CPU + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * A10 specific configuration + */ +#define CONFIG_SUN4I /* sun4i SoC generation */ + +#define CONFIG_SYS_PROMPT "sun4i# " + +/* + * Include common sunxi configuration where most the settings are + */ +#include <configs/sunxi-common.h> + +#endif /* __CONFIG_H */ -- 1.9.0 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot