[U-Boot] [PATCH u-boot sunxi 4/4] sunxi: Add sun4i support
Hans de Goede
hdegoede at redhat.com
Sun Mar 16 14:58:03 CET 2014
Hi,
On 03/16/2014 02:53 PM, Hans de Goede wrote:
Woops I forgot to add a commit msg here, I've jut fixed this locally:
Based linux-sunxi#sunxi commit d854c4de2f57 "arm: Handle .gnu.hash section in
ldscripts" vs v2014.01.
As well as the following signed-off-by the sunxi branch shows commits to
the new sun4i dram bits by:
Berg Xing <bergxing at allwinnertech.com>
Tom Cubie <tangliang at allwinnertech.com>
Signed-off-by: Henrik Nordstrom <henrik at henriknordstrom.net>
Signed-off-by: Stefan Roese <sr at denx.de>
Signed-off-by: Oliver Schinagl <oliver at schinagl.nl>
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
Regards,
Hans
> ---
> 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.zalega at samsung.com>
> Active arm armv7 s5pc1xx samsung smdkc100 smdkc100 - Minkyu Kang <mk7.kang at 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.poirier at 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 <henrik at 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 */
>
More information about the U-Boot
mailing list