
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