public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Luka Perkov <luka@openwrt.org>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 11/22] ARM: sunxi: U-Boot SPL capable of booting directly from MMC
Date: Sun, 25 Nov 2012 16:11:34 +0100	[thread overview]
Message-ID: <20121125151134-9180@mutt-kz> (raw)
In-Reply-To: <1353843857.17518.23.camel@home.hno.se>

Hi Henrik,

On Sun, Nov 25, 2012 at 12:44:17PM +0100, Henrik Nordstr?m wrote:
> Allwinner sunxi family of SoCs boots from MMC0/NAND/NOR/MMC2 loading
> boot code into an embedded 32KB SRAM.
> 
> This patch adds support for booting u-boot SPL from MMC0
> 
> We first initializes the console UART, then DRAM controller with board
> specific DRAM configuration details, configure CPU core voltage and
> clocks before loading the full u-boot image into DRAM.
> 
> From: Henrik Nordstrom <henrik@henriknordstrom.net>
> Signed-off-by: Tom Cubie <tangliang@allwinnertech.com>
> Signed-off-by: Stefan Roese <sr@denx.de>
> Signed-off-by: Henrik Nordstrom <henrik@henriknordstrom.net>
> ---
>  Makefile                                |   11 +
>  arch/arm/cpu/armv7/sunxi/board.c        |   38 +++
>  arch/arm/cpu/armv7/sunxi/clock.c        |   99 +++++++
>  arch/arm/cpu/armv7/sunxi/dram.c         |  445 +++++++++++++++++++++++++++++++
>  arch/arm/cpu/armv7/sunxi/u-boot-spl.lds |   63 +++++
>  arch/arm/include/asm/arch-sunxi/spl.h   |   34 +++
>  board/sunxi/board.c                     |   46 ++++
>  include/configs/sunxi-common.h          |   30 ++-
>  spl/Makefile                            |   10 +
>  9 files changed, 775 insertions(+), 1 deletions(-)
>  create mode 100644 arch/arm/cpu/armv7/sunxi/dram.c
>  create mode 100644 arch/arm/cpu/armv7/sunxi/u-boot-spl.lds
>  create mode 100644 arch/arm/include/asm/arch-sunxi/spl.h
> 
> diff --git a/Makefile b/Makefile
> index 81fe532..d1b7f97 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -517,6 +517,16 @@ $(obj)u-boot.spr:	$(obj)u-boot.img $(obj)spl/u-boot-spl.bin
>  			conv=notrunc 2>/dev/null
>  		cat $(obj)spl/u-boot-spl-pad.img $(obj)u-boot.img > $@
>  
> +# sunxi: Combined object with SPL U-Boot with sunxi header (sunxi-spl.bin)
> +# and the full-blown U-Boot attached to it
> +$(obj)u-boot-sunxi-with-spl.bin: $(obj)spl/sunxi-spl.bin $(obj)u-boot.bin
> +		tr "\000" "\377" < /dev/zero | dd ibs=1 count=$(CONFIG_SPL_PAD_TO) \
> +			of=$(obj)spl/sunxi-spl-pad.bin 2>/dev/null
> +		dd if=$(obj)spl/sunxi-spl.bin of=$(obj)spl/sunxi-spl-pad.bin \
> +			conv=notrunc 2>/dev/null
> +		cat $(obj)spl/sunxi-spl-pad.bin $(obj)u-boot.bin > $@
> +		rm $(obj)spl/sunxi-spl-pad.bin
> +
>  ifeq ($(SOC),tegra20)
>  ifeq ($(CONFIG_OF_SEPARATE),y)
>  nodtb=dtb
> @@ -854,6 +864,7 @@ clobber:	tidy
>  	@[ ! -d $(obj)nand_spl ] || find $(obj)nand_spl -name "*" -type l -print | xargs rm -f
>  	@rm -f $(obj)dts/*.tmp
>  	@rm -f $(obj)spl/u-boot-spl{,-pad}.ais
> +	@rm -f $(obj)spl/sun?i-spl.bin
>  
>  mrproper \
>  distclean:	clobber unconfig
> diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c
> index 29cc4bd..6dc2bd0 100644
> --- a/arch/arm/cpu/armv7/sunxi/board.c
> +++ b/arch/arm/cpu/armv7/sunxi/board.c
> @@ -27,12 +27,37 @@
>  #include <common.h>
>  #include <asm/io.h>
>  #include <serial.h>
> +#include <i2c.h>
>  #include <asm/gpio.h>
>  #include <asm/arch/clock.h>
>  #include <asm/arch/timer.h>
>  #include <asm/arch/gpio.h>
>  #include <asm/arch/sys_proto.h>
>  #include <netdev.h>
> +#ifdef CONFIG_SPL_BUILD
> +#include <spl.h>
> +#endif
> +
> +#ifdef CONFIG_SPL_BUILD
> +/* Pointer to the global data structure for SPL */
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* The sunxi internal brom will try to loader external bootloader
> + * from mmc0, nannd flash, mmc2.
> + * Unfortunately we can't check how SPL was loaded so assume
> + * it's always the first SD/MMC controller
> + */
> +u32 spl_boot_device(void)
> +{
> +	return BOOT_DEVICE_MMC1;
> +}
> +
> +/* No confiration data available in SPL yet. Hardcode bootmode */
> +u32 spl_boot_mode(void)
> +{
> +	return MMCSD_MODE_RAW;
> +}
> +#endif
>  
>  int gpio_init(void)
>  {
> @@ -65,6 +90,19 @@ void s_init(void)
>  #endif
>  	clock_init();
>  	gpio_init();
> +
> +#ifdef CONFIG_SPL_BUILD
> +	gd = &gdata;
> +	preloader_console_init();
> +
> +#ifdef CONFIG_SPL_I2C_SUPPORT
> +	/* Needed early by sunxi_board_init if PMU is enabled */
> +	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
> +#endif
> +
> +	sunxi_board_init();
> +#endif
> +
>  }
>  
>  void reset_cpu(ulong addr)
> diff --git a/arch/arm/cpu/armv7/sunxi/clock.c b/arch/arm/cpu/armv7/sunxi/clock.c
> index b9bbb7d..91cfae3 100644
> --- a/arch/arm/cpu/armv7/sunxi/clock.c
> +++ b/arch/arm/cpu/armv7/sunxi/clock.c
> @@ -24,13 +24,34 @@
>  #include <common.h>
>  #include <asm/io.h>
>  #include <asm/arch/clock.h>
> +#include <asm/arch/gpio.h>
>  #include <asm/arch/sys_proto.h>
>  
> +#ifdef CONFIG_SPL_BUILD
> +static void clock_init_safe(void)
> +{
> +	struct sunxi_ccm_reg * const ccm =
> +		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> +
> +	/* Set safe defaults until PMU is configured */
> +	writel(AXI_DIV_1 << 0 | AHB_DIV_2 << 4 | APB0_DIV_1 << 8 |
> +	       CPU_CLK_SRC_OSC24M << 16, &ccm->cpu_ahb_apb0_cfg);
> +	writel(0xa1005000, &ccm->pll1_cfg);
> +	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);
> +}
> +#endif
> +
>  int clock_init(void)
>  {
>  	struct sunxi_ccm_reg *const ccm =
>  		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
>  
> +#ifdef CONFIG_SPL_BUILD
> +	clock_init_safe();
> +#endif
> +
>  	/* uart clock source is apb1 */
>  	sr32(&ccm->apb1_clk_div_cfg, 24, 2, APB1_CLK_SRC_OSC24M);
>  	sr32(&ccm->apb1_clk_div_cfg, 16, 2, APB1_FACTOR_N);
> @@ -70,3 +91,81 @@ int clock_twi_onoff(int port, int state)
>  
>  	return 0;
>  }
> +
> +#ifdef CONFIG_SPL_BUILD
> +#define PLL1_CFG(N, K, M, P)	(1 << 31 | 0 << 30 | 8 << 26 | 0 << 25 | \
> +				 16 << 20 | (P) << 16 | 2 << 13 | (N) << 8 | \
> +				 (K) << 4 | 0 << 3 | 0 << 2 | (M) << 0)
> +#define RDIV(a, b)		((a + (b) - 1) / (b))
> +
> +struct {
> +	u32 pll1_cfg;
> +	unsigned int freq;
> +} pll1_para[] = {
> +	{ PLL1_CFG(16, 0, 0, 0), 384000000 },
> +	{ PLL1_CFG(16, 1, 0, 0), 768000000 },
> +	{ PLL1_CFG(20, 1, 0, 0), 960000000 },
> +	{ PLL1_CFG(21, 1, 0, 0), 1008000000},
> +	{ PLL1_CFG(22, 1, 0, 0), 1056000000},
> +	{ PLL1_CFG(23, 1, 0, 0), 1104000000},
> +	{ PLL1_CFG(24, 1, 0, 0), 1152000000},
> +	{ PLL1_CFG(25, 1, 0, 0), 1200000000},
> +	{ PLL1_CFG(26, 1, 0, 0), 1248000000},
> +	{ PLL1_CFG(27, 1, 0, 0), 1296000000},
> +	{ PLL1_CFG(28, 1, 0, 0), 1344000000},
> +	{ PLL1_CFG(29, 1, 0, 0), 1392000000},
> +	{ PLL1_CFG(30, 1, 0, 0), 1440000000},
> +	{ PLL1_CFG(31, 1, 0, 0), 1488000000},
> +	{ PLL1_CFG(31, 1, 0, 0), ~0},
> +};
> +
> +void clock_set_pll1(int hz)
> +{
> +	int i = 0;
> +	int axi, ahb, apb0;
> +	struct sunxi_ccm_reg * const ccm =
> +		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> +
> +	/* Find target frequency */
> +	while (pll1_para[i].freq < hz)
> +		i++;
> +
> +	hz = pll1_para[i].freq;
> +
> +	/* Calculate system clock divisors */
> +	axi = RDIV(hz, 432000000);		/* Max 450MHz */
> +	ahb = RDIV(hz/axi, 204000000);		/* Max 250MHz */
> +	apb0 = 2;				/* Max 150MHz */
> +
> +	/* Map divisors to register values */
> +	axi = axi - 1;
> +	if (ahb > 4)
> +		ahb = 3;
> +	else if (ahb > 2)
> +		ahb = 2;
> +	else if (ahb > 1)
> +		ahb = 1;
> +	else
> +		ahb = 0;
> +
> +	apb0 = apb0 - 1;
> +
> +	/* Switch to 24MHz clock while changing PLL1 */
> +	writel(AXI_DIV_1 << 0 | AHB_DIV_2 << 4 | APB0_DIV_1 << 8 |
> +	       CPU_CLK_SRC_OSC24M << 16, &ccm->cpu_ahb_apb0_cfg);
> +	sdelay(20);
> +
> +	/* Configure sys clock divisors */
> +	writel(axi << 0 | ahb << 4 | apb0 << 8 | CPU_CLK_SRC_OSC24M << 16,
> +	       &ccm->cpu_ahb_apb0_cfg);
> +
> +	/* Configure PLL1 at the desired frequency */
> +	writel(pll1_para[i].pll1_cfg, &ccm->pll1_cfg);
> +	sdelay(200);
> +
> +	/* Switch CPU to PLL1 */
> +	writel(axi << 0 | ahb << 4 | apb0 << 8 | CPU_CLK_SRC_PLL1 << 16,
> +	       &ccm->cpu_ahb_apb0_cfg);
> +	sdelay(20);
> +}
> +#endif
> diff --git a/arch/arm/cpu/armv7/sunxi/dram.c b/arch/arm/cpu/armv7/sunxi/dram.c
> new file mode 100644
> index 0000000..f169b7b
> --- /dev/null
> +++ b/arch/arm/cpu/armv7/sunxi/dram.c
> @@ -0,0 +1,445 @@
> +/*
> + * sunxi DRAM controller initialization
> + * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
> + *
> + * Based on sun4i Linux kernel sources mach-sunxi/pm/standby/dram*.c
> + * and earlier U-Boot Allwiner A10 SPL work
> + *
> + * (C) Copyright 2007-2012
> + * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
> + * Berg Xing <bergxing@allwinnertech.com>
> + * Tom Cubie <tangliang@allwinnertech.com>
> + *
> + * 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
> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <asm/arch/dram.h>
> +#include <asm/arch/timer.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/sys_proto.h>
> +
> +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);
> +	reg_val >>= 6;
> +	reg_val &= 0x3;
> +
> +	if (reg_val != 0) {
> +		setbits_le32(&dram->mcr, 0x1 << 12);
> +		sdelay(0x100);
> +		clrbits_le32(&dram->mcr, 0x1 << 12);
> +	} else
> +#endif
> +	{
> +		clrbits_le32(&dram->mcr, 0x1 << 12);
> +		sdelay(0x100);
> +		setbits_le32(&dram->mcr, 0x1 << 12);
> +	}
> +}
> +
> +static void mctl_set_drive(void)
> +{
> +	struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
> +
> +	clrsetbits_le32(&dram->mcr, 0x3, (0x6 << 12) | 0xFFC);
> +}
> +
> +static void mctl_itm_disable(void)
> +{
> +	struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
> +
> +	setbits_le32(&dram->ccr, 0x1 << 28);
> +}
> +
> +static void mctl_itm_enable(void)
> +{
> +	struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
> +
> +	clrbits_le32(&dram->ccr, 0x1 << 28);
> +}
> +
> +static void mctl_enable_dll0(void)
> +{
> +	struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
> +
> +	clrsetbits_le32(&dram->dllcr[0], 0x40000000, 0x80000000);
> +	sdelay(0x100);
> +
> +	clrbits_le32(&dram->dllcr[0], 0xC0000000);
> +	sdelay(0x1000);
> +
> +	clrsetbits_le32(&dram->dllcr[0], 0x80000000, 0x40000000);
> +	sdelay(0x1000);
> +}
> +
> +/*
> + * Note: This differs from pm/standby in that it checks the bus width
> + */
> +static void mctl_enable_dllx(void)
> +{
> +	struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
> +	u32 i, n, bus_width;
> +
> +	bus_width = readl(&dram->dcr);
> +	bus_width >>= 6;
> +	bus_width &= 7;
> +
> +	if (bus_width == 3)
> +		n = 5;
> +	else
> +		n = 3;
> +
> +	for (i = 1; i < n; i++)
> +		clrsetbits_le32(&dram->dllcr[i], 0x40000000, 0x80000000);
> +	sdelay(0x100);
> +
> +	for (i = 1; i < n; i++)
> +		clrbits_le32(&dram->dllcr[i], 0xC0000000);
> +	sdelay(0x1000);
> +
> +	for (i = 1; i < n; i++)
> +		clrsetbits_le32(&dram->dllcr[i], 0x80000000, 0x40000000);
> +	sdelay(0x1000);
> +}
> +
> +static u32 hpcr_value[32] = {
> +#ifdef CONFIG_SUN5I
> +	0, 0, 0, 0,
> +	0, 0, 0, 0,
> +	0, 0, 0, 0,
> +	0, 0, 0, 0,
> +	0x1031, 0x1031, 0x0735, 0x1035,
> +	0x1035, 0x0731, 0x1031, 0,
> +	0x0301, 0x0301, 0x0301, 0x0301,
> +	0x0301, 0x0301, 0x0301, 0
> +#endif
> +#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
> +};
> +
> +static void mctl_configure_hostport(void)
> +{
> +	struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
> +	u32 i;
> +
> +	for (i = 0; i < 32; i++)
> +		writel(hpcr_value[i], &dram->hpcr[i]);
> +}
> +
> +static void mctl_setup_dram_clock(u32 clk)
> +{
> +	u32 reg_val;
> +	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> +
> +	/* setup DRAM PLL */
> +	reg_val = readl(&ccm->pll5_cfg);
> +	reg_val &= ~0x3;
> +	reg_val |= 0x1;			/* m factor */
> +	reg_val &= ~(0x3 << 4);
> +	reg_val |= 0x1 << 4;		/* k factor */
> +	reg_val &= ~(0x1f << 8);
> +	reg_val |= ((clk / 24) & 0x1f) << 8;	/* n factor */
> +	reg_val &= ~(0x3 << 16);
> +	reg_val |= 0x1 << 16;		/* p factor */
> +	reg_val &= ~(0x1 << 29);	/* PLL on */
> +	reg_val |= (u32) 0x1 << 31;	/* PLL En */
> +	writel(reg_val, &ccm->pll5_cfg);
> +	sdelay(0x100000);
> +
> +	setbits_le32(&ccm->pll5_cfg, 0x1 << 29);
> +
> +#ifdef CONFIG_SUN4I
> +	/* reset GPS */
> +	clrbits_le32(&ccm->gps_clk_cfg, 0x3);
> +	setbits_le32(&ccm->ahb_gate0, 0x1 << 26);
> +	sdelay(0x20);
> +	clrbits_le32(&ccm->ahb_gate0, 0x1 << 26);
> +#endif
> +
> +	/* setup MBUS clock */
> +	reg_val = (0x1 << 31) | (0x2 << 24) | (0x1);
> +	writel(reg_val, &ccm->mbus_clk_cfg);
> +
> +	/*
> +	 * open DRAMC AHB & DLL register clock
> +	 * close it first
> +	 */
> +#ifdef CONFIG_SUN5I
> +	clrbits_le32(&ccm->ahb_gate0, 0x3 << 14);
> +#else
> +	clrbits_le32(&ccm->ahb_gate0, 0x1 << 14);
> +#endif
> +	sdelay(0x1000);
> +
> +	/* then open it */
> +#ifdef CONFIG_SUN5I
> +	setbits_le32(&ccm->ahb_gate0, 0x3 << 14);
> +#else
> +	setbits_le32(&ccm->ahb_gate0, 0x1 << 14);
> +#endif
> +	sdelay(0x1000);
> +}
> +
> +static int dramc_scan_readpipe(void)
> +{
> +	struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
> +	u32 reg_val;
> +
> +	/* data training trigger */
> +	setbits_le32(&dram->ccr, 0x1 << 30);
> +
> +	/* check whether data training process is end */
> +	while (readl(&dram->ccr) & (0x1 << 30))
> +		;
> +
> +	/* check data training result */
> +	reg_val = readl(&dram->csr);
> +	if (reg_val & (0x1 << 20))
> +		return -1;
> +
> +	return 0;
> +}
> +
> +static void dramc_clock_output_en(u32 on)
> +{
> +#ifdef CONFIG_SUN5I
> +	struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
> +
> +	if (on)
> +		setbits_le32(&dram->mcr, 0x1 << SUN5I_DRAM_MCR_DCLK_OUT_OFFSET);
> +	else
> +		clrbits_le32(&dram->mcr, 0x1 << SUN5I_DRAM_MCR_DCLK_OUT_OFFSET);
> +#endif
> +#ifdef CONFIG_SUN4I
> +	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> +	if (on)
> +		setbits_le32(&ccm->dram_clk_cfg, 0x1 << SUN4I_CCM_SDRAM_DCLK_OUT_OFFSET);
> +	else
> +		clrbits_le32(&ccm->dram_clk_cfg, 0x1 << SUN4I_CCM_SDRAM_DCLK_OUT_OFFSET);
> +#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 dram_size;
> +
> +	if (clk < 600) {
> +		dram_size = readl(&dram->dcr);
> +		dram_size >>= 3;
> +		dram_size &= 0x7;
> +		if (dram_size <= 0x2)
> +			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 */
> +
> +#ifdef CONFIG_SUN5I
> +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;
> +	reg_val = 131;
> +
> +	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);
> +}
> +#endif /* SUN5I */
> +
> +int dramc_init(struct dram_para *para)
> +{
> +	struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
> +	u32 reg_val;
> +	int ret_val;
> +
> +	/* check input dram parameter structure */
> +	if (!para)
> +		return -1;
> +
> +	/* setup DRAM relative clock */
> +	mctl_setup_dram_clock(para->clock);
> +
> +#ifdef CONFIG_SUN5I
> +	/* Disable any pad power save control */
> +	writel(0, &dram->ppwrsctl);
> +#endif
> +
> +	/* reset external DRAM */
> +	mctl_ddr3_reset();
> +	mctl_set_drive();
> +
> +	/* dram clock off */
> +	dramc_clock_output_en(0);
> +
> +#ifdef CONFIG_SUN4I
> +	/* select dram controller 1 */
> +	writel(0x16237495, &dram->csel);
> +#endif
> +
> +	mctl_itm_disable();
> +	mctl_enable_dll0();
> +
> +	/* configure external DRAM */
> +	reg_val = 0;
> +	if (para->type == 3)
> +		reg_val |= 0x1;
> +	reg_val |= (para->io_width >> 3) << 1;
> +
> +	if (para->density == 256)
> +		reg_val |= 0x0 << 3;
> +	else if (para->density == 512)
> +		reg_val |= 0x1 << 3;
> +	else if (para->density == 1024)
> +		reg_val |= 0x2 << 3;
> +	else if (para->density == 2048)
> +		reg_val |= 0x3 << 3;
> +	else if (para->density == 4096)
> +		reg_val |= 0x4 << 3;
> +	else if (para->density == 8192)
> +		reg_val |= 0x5 << 3;
> +	else
> +		reg_val |= 0x0 << 3;
> +
> +	reg_val |= ((para->bus_width >> 3) - 1) << 6;
> +
> +	reg_val |= (para->rank_num - 1) << 10;
> +
> +	reg_val |= 0x1 << 12;
> +	reg_val |= ((0x1) & 0x3) << 13;
> +
> +	writel(reg_val, &dram->dcr);
> +
> +#ifdef CONFIG_SUN5I
> +	/* 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
> +
> +	/* dram clock on */
> +	dramc_clock_output_en(1);
> +
> +	sdelay(0x10);
> +
> +	while (readl(&dram->ccr) & (0x1U << 31))
> +		;
> +
> +	mctl_enable_dllx();
> +
> +#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);
> +
> +	/* set timing parameters */
> +	writel(para->tpr0, &dram->tpr0);
> +	writel(para->tpr1, &dram->tpr1);
> +	writel(para->tpr2, &dram->tpr2);
> +
> +	/* set mode register */
> +	if (para->type == 3) {
> +		/* ddr3 */
> +		reg_val = 0x0;
> +#ifdef CONFIG_SUN5I
> +		reg_val |= 0x1000;
> +#endif
> +		reg_val |= (para->cas - 4) << 4;
> +		reg_val |= 0x5 << 9;
> +	} else if (para->type == 2) {
> +		/* ddr2 */
> +		reg_val = 0x2;
> +		reg_val |= para->cas << 4;
> +		reg_val |= 0x5 << 9;
> +	}
> +	writel(reg_val, &dram->mr);
> +
> +	writel(para->emr1, &dram->emr);
> +	writel(para->emr2, &dram->emr2);
> +	writel(para->emr3, &dram->emr3);
> +
> +	/* set DQS window mode */
> +	clrsetbits_le32(&dram->ccr, 0x1U << 17, 0x1U << 14);
> +
> +	/* initial external DRAM */
> +	setbits_le32(&dram->ccr, 0x1U << 31);
> +
> +	while (readl(&dram->ccr) & (0x1U << 31))
> +		;
> +
> +	/* scan read pipe value */
> +	mctl_itm_enable();
> +	ret_val = dramc_scan_readpipe();
> +
> +	if (ret_val < 0)
> +		return 0;
> +
> +	/* configure all host port */
> +	mctl_configure_hostport();
> +
> +	return get_ram_size((long *)PHYS_SDRAM_1, 1 << 30);
> +}
> diff --git a/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds b/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds
> new file mode 100644
> index 0000000..cb418e1
> --- /dev/null
> +++ b/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds
> @@ -0,0 +1,63 @@
> +/*
> + * (C) Copyright 2002
> + * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
> + *
> + * (C) Copyright 2010
> + * Texas Instruments, <www.ti.com>
> + *	Aneesh V <aneesh@ti.com>
> + *
> + * 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
> + */
> +
> +MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\
> +		LENGTH = CONFIG_SPL_MAX_SIZE }
> +MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
> +		LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
> +
> +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
> +OUTPUT_ARCH(arm)
> +ENTRY(_start)
> +SECTIONS
> +{
> +	.text      :
> +	{
> +		__start = .;
> +		arch/arm/cpu/armv7/start.o	(.text)
> +		*(.text*)
> +	} > .sram
> +
> +	. = ALIGN(4);
> +	.rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
> +
> +	. = ALIGN(4);
> +	.data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
> +
> +	. = ALIGN(4);
> +	__image_copy_end = .;
> +	_end = .;
> +
> +	.bss :
> +	{
> +		. = ALIGN(4);
> +		__bss_start = .;
> +		*(.bss*)
> +		. = ALIGN(4);
> +		__bss_end__ = .;
> +	} > .sdram
> +}
> diff --git a/arch/arm/include/asm/arch-sunxi/spl.h b/arch/arm/include/asm/arch-sunxi/spl.h
> new file mode 100644
> index 0000000..404e16a
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-sunxi/spl.h
> @@ -0,0 +1,34 @@
> +/*
> + * (C) Copyright 2012
> + * Texas Instruments, <www.ti.com>
> + *
> + * 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	_ASM_ARCH_SPL_H_
> +#define	_ASM_SPL_H_
> +
> +#define BOOT_DEVICE_NONE	0
> +#define BOOT_DEVICE_XIP		1
> +#define BOOT_DEVICE_NAND	2
> +#define BOOT_DEVICE_ONE_NAND	3
> +#define BOOT_DEVICE_MMC2	5 /*emmc*/

Add spaces in comment above.

> +#define BOOT_DEVICE_MMC1	6
> +#define BOOT_DEVICE_XIPWAIT	7
> +#define BOOT_DEVICE_MMC2_2      0xFF
> +#endif
> diff --git a/board/sunxi/board.c b/board/sunxi/board.c
> index 50fb40f..b917a0a 100644
> --- a/board/sunxi/board.c
> +++ b/board/sunxi/board.c
> @@ -64,3 +64,49 @@ int board_mmc_init(bd_t *bis)
>  	return 0;
>  }
>  #endif
> +
> +#ifdef CONFIG_SPL_BUILD
> +void sunxi_board_init(void)
> +{
> +	int power_failed = 0;
> +	int ramsize;
> +
> +	printf("DRAM:");
> +	ramsize = sunxi_dram_init();
> +	if (!ramsize) {
> +		printf(" ?");
> +		ramsize = sunxi_dram_init();
> +	}
> +	if (!ramsize) {
> +		printf(" ?");
> +		ramsize = sunxi_dram_init();
> +	}
> +	printf(" %dMB\n", ramsize>>20);
> +	if (!ramsize)
> +		hang();
> +
> +#ifdef CONFIG_AXP209_POWER
> +	power_failed |= axp209_init();
> +	power_failed |= axp209_set_dcdc2(1400);
> +	power_failed |= axp209_set_dcdc3(1250);
> +	power_failed |= axp209_set_ldo2(3000);
> +	power_failed |= axp209_set_ldo3(2800);
> +	power_failed |= axp209_set_ldo4(2800);
> +#endif
> +
> +	/*
> +	 * Only clock up the CPU to full speed if we are reasonably
> +	 * assured it's being powered with suitable core voltage
> +	 */
> +	if (!power_failed)
> +		clock_set_pll1(1008000000);
> +}
> +
> +#ifdef CONFIG_SPL_DISPLAY_PRINT
> +void spl_display_print(void)
> +{
> +	printf("Board: %s\n", CONFIG_SYS_BOARD_NAME);
> +}
> +#endif
> +
> +#endif
> diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
> index bc1f200..b0dcfdb 100644
> --- a/include/configs/sunxi-common.h
> +++ b/include/configs/sunxi-common.h
> @@ -134,7 +134,7 @@
>   */
>  #define CONFIG_SYS_NO_FLASH
>  
> -#define CONFIG_SYS_MONITOR_LEN		(256 << 10)	/* 256 KB */
> +#define CONFIG_SYS_MONITOR_LEN		(512 << 10)	/* 512 KB */
>  #define CONFIG_IDENT_STRING		" Allwinner Technology "
>  
>  #define CONFIG_ENV_OFFSET		(544 << 10) /* (8 + 24 + 512)KB */
> @@ -190,6 +190,30 @@
>  #define CONFIG_CMD_EXT4		/* with this we can access ext4 bootfs */
>  #define CONFIG_CMD_ZFS		/* with this we can access ZFS bootfs */
>  
> +#define CONFIG_SPL_FRAMEWORK
> +#define CONFIG_SPL_BSS_START_ADDR	0x50000000
> +#define CONFIG_SPL_BSS_MAX_SIZE		0x80000		/* 512 KB */
> +
> +#define CONFIG_SPL_TEXT_BASE		0x20		/* sram start+header */
> +#define CONFIG_SPL_MAX_SIZE		0x8000		/* 32 KB */
> +
> +#define CONFIG_SPL_LIBCOMMON_SUPPORT
> +#define CONFIG_SPL_LIBDISK_SUPPORT
> +#define CONFIG_SPL_SERIAL_SUPPORT
> +#define CONFIG_SPL_LIBGENERIC_SUPPORT
> +#define CONFIG_SPL_MMC_SUPPORT
> +#define CONFIG_SPL_DISPLAY_PRINT
> +
> +/* end of 24KB in sram */
> +#define LOW_LEVEL_SRAM_STACK		0x00006000
> +#define CONFIG_SPL_STACK		LOW_LEVEL_SRAM_STACK
> +#define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/armv7/sunxi/u-boot-spl.lds"
> +
> +/* 32KB offset */
> +#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR	64
> +/* SPL starts at offset 8KiB im MMC and has the size of 24KiB */
> +#define CONFIG_SPL_PAD_TO		24576		/* decimal for 'dd' */
> +
>  #undef CONFIG_CMD_FPGA
>  #undef CONFIG_CMD_NET
>  #undef CONFIG_CMD_NFS
> @@ -210,4 +234,8 @@
>  #define CONFIG_SUNXI_GPIO
>  #define CONFIG_CMD_GPIO
>  
> +/* PMU */
> +#define CONFIG_SPL_POWER_SUPPORT
> +#define CONFIG_AXP209_POWER
> +
>  #endif /* __CONFIG_H */
> diff --git a/spl/Makefile b/spl/Makefile
> index 3195390..74d27b1 100644
> --- a/spl/Makefile
> +++ b/spl/Makefile
> @@ -126,6 +126,10 @@ ifdef CONFIG_SAMSUNG
>  ALL-y	+= $(obj)$(BOARD)-spl.bin
>  endif
>  
> +ifdef CONFIG_SUNXI
> +ALL-y	+= $(obj)sunxi-spl.bin
> +endif
> +
>  all:	$(ALL-y)
>  
>  ifdef CONFIG_SAMSUNG
> @@ -134,6 +138,12 @@ $(obj)$(BOARD)-spl.bin: $(obj)u-boot-spl.bin
>  		$(obj)u-boot-spl.bin $(obj)$(BOARD)-spl.bin
>  endif
>  
> +ifdef CONFIG_SUNXI
> +$(obj)sunxi-spl.bin: $(obj)u-boot-spl.bin
> +	$(OBJTREE)/tools/mksunxiboot \
> +		$(obj)u-boot-spl.bin $(obj)sunxi-spl.bin
> +endif
> +
>  $(obj)u-boot-spl.bin:	$(obj)u-boot-spl
>  	$(OBJCOPY) $(OBJCFLAGS) -O binary $< $@
>  
> -- 
> 1.7.7.6

Luka

  reply	other threads:[~2012-11-25 15:11 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <cover.1353842684.git.henrik@henriknordstrom.net>
2012-11-25 11:37 ` [U-Boot] [PATCH 01/22] ARM: sunxi: Basic Allwinner A10/A13 (sun4i/sun5i) support Henrik Nordström
2012-11-25 12:23   ` Luka Perkov
2012-11-25 13:08     ` Henrik Nordström
2012-11-25 19:55       ` Wolfgang Denk
2012-11-26  1:05         ` [U-Boot] [PATCH 01/22] Re: Copyright on board makefiles Henrik Nordström
2012-11-26  5:54           ` Wolfgang Denk
2012-11-25 19:52     ` [U-Boot] [PATCH 01/22] ARM: sunxi: Basic Allwinner A10/A13 (sun4i/sun5i) support Wolfgang Denk
2012-11-25 18:06   ` Marek Vasut
2012-11-26  0:21     ` Henrik Nordström
2012-11-26  0:33       ` Marek Vasut
2012-11-26  5:52       ` Wolfgang Denk
2012-11-25 19:33   ` Wolfgang Denk
2012-11-25 23:53     ` Henrik Nordström
2012-11-26  8:00       ` Stefan Roese
2012-11-25 19:40   ` Wolfgang Denk
2012-11-25 11:37 ` [U-Boot] [PATCH 02/22] ARM: sunxi: MMC driver Henrik Nordström
2012-11-25 14:33   ` Luka Perkov
2012-11-25 15:39     ` Henrik Nordström
2012-11-25 17:07       ` Luka Perkov
2012-11-25 19:58       ` Wolfgang Denk
2012-11-25 19:56     ` Wolfgang Denk
2012-11-25 18:09   ` Marek Vasut
2012-11-25 19:44   ` Wolfgang Denk
2012-11-25 11:38 ` [U-Boot] [PATCH 03/22] ARM sunxi: I2C driver Henrik Nordström
2012-11-25 14:41   ` Luka Perkov
2012-11-25 15:47     ` Henrik Nordström
2012-11-25 18:11   ` Marek Vasut
2012-11-25 19:47   ` Wolfgang Denk
2012-11-26 11:13   ` Heiko Schocher
2012-11-26 13:39     ` Henrik Nordström
2012-11-25 11:39 ` [U-Boot] [PATCH 05/22] power: Add AXP209 Power Management controller (I2C) Henrik Nordström
2012-11-25 14:44   ` Luka Perkov
2012-11-25 18:13   ` Marek Vasut
2012-11-25 19:48   ` Wolfgang Denk
2012-11-25 11:40 ` [U-Boot] [PATCH 06/22] ARM sunxi: Basic GPIO driver Henrik Nordström
2012-11-25 14:52   ` Luka Perkov
2012-11-25 18:14   ` Marek Vasut
2012-11-25 19:50   ` Wolfgang Denk
2012-11-25 21:47     ` Marek Vasut
2012-11-25 23:41     ` Henrik Nordström
2012-11-25 11:40 ` [U-Boot] [PATCH 07/22] tools: mksunixboot adding a Allwinner boot header Henrik Nordström
2012-11-25 15:01   ` Luka Perkov
2012-11-25 17:47   ` Wolfgang Denk
2012-11-25 11:41 ` [U-Boot] [PATCH 08/22] net: Add sunxi (Allwinner) wemac driver Henrik Nordström
2013-07-08 15:43   ` Joe Hershberger
2013-07-08 16:16     ` Tom Rini
2013-07-08 16:29       ` Joe Hershberger
2013-07-08 19:03         ` Tom Rini
2012-11-25 11:42 ` [U-Boot] [PATCH 09/22] ARM: sun4i: Enable ethernet support (wemac) on A10 boards Henrik Nordström
2012-11-25 15:05   ` Luka Perkov
2012-11-25 11:43 ` [U-Boot] [PATCH 10/22] sunxi: Add more network commands and netconsole support Henrik Nordström
2012-11-25 15:07   ` Luka Perkov
2012-11-25 11:44 ` [U-Boot] [PATCH 11/22] ARM: sunxi: U-Boot SPL capable of booting directly from MMC Henrik Nordström
2012-11-25 15:11   ` Luka Perkov [this message]
2012-11-25 11:44 ` [U-Boot] [PATCH 12/22] ARM sunxi: SPL support for Olimex A13-OLinuXino board Henrik Nordström
2012-11-25 15:17   ` Luka Perkov
2012-11-25 11:44 ` [U-Boot] [PATCH 13/22] ARM sunxi: SPL support for Mele A1000 board Henrik Nordström
2012-11-25 11:45 ` [U-Boot] [PATCH 14/22] ARM sunxi: SPL support for Cubieboard board Henrik Nordström
2012-11-25 11:45 ` [U-Boot] [PATCH 15/22] ARM sunxi: SPL support for Hackberry 1GB board Henrik Nordström
2012-11-25 11:45 ` [U-Boot] [PATCH 16/22] ARM sunxi: SPL support for a13_mid board Henrik Nordström
2012-11-25 11:45 ` [U-Boot] [PATCH 17/22] ARM sunxi: SPL support for Mini-X board Henrik Nordström
2012-11-25 11:46 ` [U-Boot] [PATCH 18/22] ARM sunxi: SPL support for hyundai A7HD board Henrik Nordström
2012-11-25 11:46 ` [U-Boot] [PATCH 19/22] ARM sunxi: SPL support for MK802 board Henrik Nordström
2012-11-25 11:46 ` [U-Boot] [PATCH 20/22] ARM sunxi: SPL support for Rikomagic MK802II board Henrik Nordström
2012-11-25 11:46 ` [U-Boot] [PATCH 21/22] ARM sunxi: SPL support for Mele A3700 board Henrik Nordström
2012-11-25 11:46 ` [U-Boot] [PATCH 22/22] ARM sunxi: SPL support for Olinuxino A13 Micro Henrik Nordström
2012-11-25 11:47 ` [U-Boot] [PATCH 04/22] ARM: sunxi: watchdog support Henrik Nordström
2013-02-02 23:55   ` Albert ARIBAUD

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20121125151134-9180@mutt-kz \
    --to=luka@openwrt.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox