File v2013.04-sunxi.patch of Package u-boot

Index: arch/arm/cpu/armv7/cmd_boot.c
===================================================================
--- /dev/null
+++ arch/arm/cpu/armv7/cmd_boot.c
@@ -0,0 +1,36 @@
+/*
+ * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
+ *
+ * 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
+ */
+
+/*
+ * Misc boot support
+ */
+#include <common.h>
+#include <command.h>
+
+#ifdef CONFIG_CMD_GO
+unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
+				 char * const argv[])
+{
+	invalidate_icache_all();
+	return entry(argc, argv);
+}
+#endif
Index: arch/arm/cpu/armv7/Makefile
===================================================================
--- arch/arm/cpu/armv7/Makefile.orig
+++ arch/arm/cpu/armv7/Makefile
@@ -31,8 +31,9 @@ COBJS	+= cache_v7.o
 
 COBJS	+= cpu.o
 COBJS	+= syslib.o
+COBJS	+= cmd_boot.o
 
-ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA)$(CONFIG_MX6)$(CONFIG_TI814X),)
+ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA)$(CONFIG_MX6)$(CONFIG_TI814X)$(CONFIG_SUNXI),)
 SOBJS	+= lowlevel_init.o
 endif
 
Index: arch/arm/cpu/armv7/sunxi/board.c
===================================================================
--- /dev/null
+++ arch/arm/cpu/armv7/sunxi/board.c
@@ -0,0 +1,166 @@
+/*
+ * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
+ *
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * Some init for sunxi platform.
+ *
+ * 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 <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)
+{
+#if CONFIG_CONS_INDEX == 1 && defined(CONFIG_UART0_PORT_F)
+#ifdef CONFIG_SUN4I
+	/* disable GPB22,23 as uart0 tx,rx to avoid conflict */
+	sunxi_gpio_set_cfgpin(SUNXI_GPB(22), SUNXI_GPIO_INPUT);
+	sunxi_gpio_set_cfgpin(SUNXI_GPB(23), SUNXI_GPIO_INPUT);
+#endif
+	sunxi_gpio_set_cfgpin(SUNXI_GPF(2), SUNXI_GPF2_UART0_TX);
+	sunxi_gpio_set_cfgpin(SUNXI_GPF(4), SUNXI_GPF4_UART0_RX);
+#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_SUN4I)
+	sunxi_gpio_set_cfgpin(SUNXI_GPB(22), SUN4I_GPB22_UART0_TX);
+	sunxi_gpio_set_cfgpin(SUNXI_GPB(23), SUN4I_GPB23_UART0_RX);
+#elif CONFIG_CONS_INDEX == 2 && defined(CONFIG_SUN5I)
+	sunxi_gpio_set_cfgpin(SUNXI_GPG(3), SUN5I_GPG3_UART0_TX);
+	sunxi_gpio_set_cfgpin(SUNXI_GPG(4), SUN5I_GPG4_UART0_RX);
+#else
+#error Unsupported console port number. Please fix pin mux settings in board.c
+#endif
+
+	return 0;
+}
+
+/* watchdog is also used for reset_cpu() and always needed */
+void watchdog_reset(void)
+{
+	static struct sunxi_wdog *const wdog =
+		&((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog;
+
+	/* a little magic to reload the watchdog */
+	writel(0xA57 << 1 | 1 << 0, &wdog->ctl);
+}
+
+static void watchdog_set(int interval)
+{
+	static struct sunxi_wdog *const wdog =
+		&((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog;
+
+	/* Set timeout, reset & enable */
+	if (interval)
+		writel((interval-1) << 2 | 1 << 1 | 1 << 0, &wdog->mode);
+	else
+		writel(0 << 2 | 0 << 1 | 1 << 0, &wdog->mode);
+	watchdog_reset();
+}
+
+static void watchdog_init(void)
+{
+#ifdef CONFIG_WATCHDOG
+	watchdog_set(24);	/* max possible timeout */
+#else
+	watchdog_set(0);	/* no timeout */
+#endif
+}
+
+void reset_cpu(ulong addr)
+{
+	watchdog_set(1);
+	while(1);
+}
+
+/* do some early init */
+void s_init(void)
+{
+	watchdog_init();
+	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
+
+}
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void enable_caches(void)
+{
+	/* Enable D-cache. I-cache is already enabled in start.S */
+	dcache_enable();
+}
+#endif
+
+#if defined(CONFIG_SUNXI_WEMAC)
+/*
+ * Initializes on-chip ethernet controllers.
+ * to override, implement board_eth_init()
+ */
+int cpu_eth_init(bd_t *bis)
+{
+	sunxi_wemac_initialize(bis);
+
+	return 0;
+}
+#endif
+
Index: arch/arm/cpu/armv7/sunxi/clock.c
===================================================================
--- /dev/null
+++ arch/arm/cpu/armv7/sunxi/clock.c
@@ -0,0 +1,180 @@
+/*
+ * (C) Copyright 2007-2012
+ * Allwinner Technology Co., Ltd. <www.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/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);
+	sr32(&ccm->apb1_clk_div_cfg, 0, 5, APB1_FACTOR_M);
+
+	/* open the clock for uart */
+	sr32(&ccm->apb1_gate, 16 + CONFIG_CONS_INDEX - 1, 1, CLK_GATE_OPEN);
+
+#ifdef CONFIG_NAND_SUNXI
+	/* nand clock source is osc24m */
+	sr32(&ccm->nand_sclk_cfg, 24, 2, NAND_CLK_SRC_OSC24);
+	sr32(&ccm->nand_sclk_cfg, 16, 2, NAND_CLK_DIV_N);
+	sr32(&ccm->nand_sclk_cfg, 0, 4, NAND_CLK_DIV_M);
+	sr32(&ccm->nand_sclk_cfg, 31, 1, CLK_GATE_OPEN);
+	/* open clock for nand */
+	sr32(&ccm->ahb_gate0, AHB_GATE_OFFSET_NAND, 1, CLK_GATE_OPEN);
+#endif
+
+	return 0;
+}
+
+/* Return PLL5 frequency in Hz
+ * Note: Assumes PLL5 reference is 24MHz clock
+ */
+unsigned int clock_get_pll5(void)
+{
+	struct sunxi_ccm_reg *const ccm =
+		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+	uint32_t rval = readl(&ccm->pll5_cfg);
+	int n = (rval >> 8) & 0x1f;
+	int k = ((rval >> 4) & 3) + 1;
+	int p = 1 << ((rval >> 16) & 3);
+	return 24000000 * n * k / p;
+}
+
+int clock_twi_onoff(int port, int state)
+{
+	struct sunxi_ccm_reg *const ccm =
+		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+	if (port > 2)
+		return -1;
+
+	/* set the apb1 clock gate for twi */
+	sr32(&ccm->apb1_gate, 0 + port, 1, 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
Index: arch/arm/cpu/armv7/sunxi/cmd_watchdog.c
===================================================================
--- /dev/null
+++ arch/arm/cpu/armv7/sunxi/cmd_watchdog.c
@@ -0,0 +1,54 @@
+/*
+ * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
+ *
+ * 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/arch/timer.h>
+#include <asm/armv7.h>
+#include <asm/io.h>
+
+int do_sunxi_watchdog(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	struct sunxi_wdog *wdog =
+		&((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog;
+	long interval;
+
+	if (argc < 2) {
+		int i;
+		u32 *wd = (void *)wdog;
+		printf("usage: watchdog seconds\n");
+		printf("0 to disable watchdog\n");
+		for (i = 0; i < 4; i++)
+			printf("%p: %08x\n", &wd[i],wd[i]);
+		return 1;
+	}
+	interval = simple_strtoul(argv[1], NULL, 10);
+	if (interval > (1 << 6) - 1)
+		interval = (1 << 6) - 1;
+	writel(0, &wdog->mode); /* make sure bit 0 is 0 to reset counter */
+	CP15DMB;
+	if (interval)
+		writel(interval << 2 | 1 << 1 | 1 << 0, &wdog->mode);
+	return 0;
+}
+
+U_BOOT_CMD(
+	watchdog, 2, 1, do_sunxi_watchdog,
+	"Set watchdog. 0 disables",
+	""
+);
Index: arch/arm/cpu/armv7/sunxi/cpu_info.c
===================================================================
--- /dev/null
+++ arch/arm/cpu/armv7/sunxi/cpu_info.c
@@ -0,0 +1,36 @@
+/*
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.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/cpu.h>
+
+#ifdef CONFIG_DISPLAY_CPUINFO
+int print_cpuinfo(void)
+{
+	puts("CPU:   SUNXI Family\n");
+	return 0;
+}
+#endif
Index: arch/arm/cpu/armv7/sunxi/dram.c
===================================================================
--- /dev/null
+++ arch/arm/cpu/armv7/sunxi/dram.c
@@ -0,0 +1,446 @@
+/*
+ * 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 has completed */
+	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);
+
+	/* reset 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);
+}
Index: arch/arm/cpu/armv7/sunxi/early_print.c
===================================================================
--- /dev/null
+++ arch/arm/cpu/armv7/sunxi/early_print.c
@@ -0,0 +1,59 @@
+/*
+ * (C) Copyright 2007-2012
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * Early uart print for debugging.
+ *
+ * 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/cpu.h>
+#include <asm/arch/early_print.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/sys_proto.h>
+
+int uart0_init(void) {
+
+	/* select dll dlh */
+	writel(0x80, UART0_LCR);
+	/* set baudrate */
+	writel(0, UART0_DLH);
+	writel(BAUD_115200, UART0_DLL);
+	/* set line control */
+	writel(LC_8_N_1, UART0_LCR);
+
+	return 0;
+}
+
+#define TX_READY (readl(UART0_LSR) & (1 << 6))
+void uart0_putc(char c) {
+
+	while(!TX_READY)
+		;
+	writel(c, UART0_THR);
+}
+
+void uart0_puts(const char *s) {
+
+	while(*s)
+		uart0_putc(*s++);
+}
Index: arch/arm/cpu/armv7/sunxi/key.c
===================================================================
--- /dev/null
+++ arch/arm/cpu/armv7/sunxi/key.c
@@ -0,0 +1,72 @@
+/*
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.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/cpu.h>
+#include <asm/arch/key.h>
+#include <asm/arch/sys_proto.h>
+
+
+int sunxi_key_init(void) {
+
+	struct sunxi_lradc *sunxi_key_base =
+		(struct sunxi_lradc *)SUNXI_LRADC_BASE;
+
+	sr32(&sunxi_key_base->ctrl, 0, 1, LRADC_EN);
+	sr32(&sunxi_key_base->ctrl, 2, 2, LRADC_SAMPLE_RATE);
+	sr32(&sunxi_key_base->ctrl, 4, 2, LEVELB_VOL);
+	sr32(&sunxi_key_base->ctrl, 6, 1, LRADC_HOLD_EN);
+	sr32(&sunxi_key_base->ctrl, 12, 2, KEY_MODE_SELECT);
+
+	/* disable all key irq */
+	writel(0x0, &sunxi_key_base->intc);
+	/* clear all key pending */
+	writel(0xFFFFFFFF, &sunxi_key_base->ints);
+
+	return 0;
+}
+
+u32 sunxi_read_key(void) {
+
+	u32 ints;
+	u32 key = 0;
+	struct sunxi_lradc *sunxi_key_base =
+		(struct sunxi_lradc *)SUNXI_LRADC_BASE;
+
+	ints = readl(&sunxi_key_base->ints);
+
+	/* if there is already data pending,
+	 read it */
+	if( ints & ADC0_DATA_PENDING) {
+		key = readl(&sunxi_key_base->data0);
+#ifdef DEBUG
+		printf("key pressed, value=0x%x\n", key);
+#endif
+	}
+	/* clear the pending data */
+	writel(ints, &sunxi_key_base->ints);
+	return key;
+}
+
Index: arch/arm/cpu/armv7/sunxi/Makefile
===================================================================
--- /dev/null
+++ arch/arm/cpu/armv7/sunxi/Makefile
@@ -0,0 +1,63 @@
+#
+# (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
+#
+# Based on some other Makefile
+# (C) Copyright 2000-2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# 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 $(TOPDIR)/config.mk
+
+LIB	=  $(obj)lib$(SOC).o
+
+COBJS	+= timer.o
+COBJS	+= dram.o
+COBJS	+= board.o
+COBJS	+= clock.o
+COBJS	+= pinmux.o
+ifdef DEBUG
+COBJS	+= early_print.o
+endif
+
+ifndef CONFIG_SPL_BUILD
+COBJS	+= key.o
+COBJS	+= cpu_info.o
+ifdef CONFIG_CMD_WATCHDOG
+COBJS   += cmd_watchdog.o
+endif
+endif
+
+SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS) $(COBJS-y) $(SOBJS))
+
+all:	 $(obj).depend $(LIB)
+
+$(LIB):	$(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
Index: arch/arm/cpu/armv7/sunxi/pinmux.c
===================================================================
--- /dev/null
+++ arch/arm/cpu/armv7/sunxi/pinmux.c
@@ -0,0 +1,61 @@
+/*
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.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/gpio.h>
+
+int sunxi_gpio_set_cfgpin(u32 pin, u32 val)
+{
+	u32 cfg;
+	u32 bank = GPIO_BANK(pin);
+	u32 index = GPIO_CFG_INDEX(pin);
+	u32 offset = GPIO_CFG_OFFSET(pin);
+	struct sunxi_gpio *pio =
+	    &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank];
+
+	cfg = readl(&pio->cfg[0] + index);
+	cfg &= ~(0xf << offset);
+	cfg |= val << offset;
+
+	writel(cfg, &pio->cfg[0] + index);
+
+	return 0;
+}
+
+int sunxi_gpio_get_cfgpin(u32 pin)
+{
+	u32 cfg;
+	u32 bank = GPIO_BANK(pin);
+	u32 index = GPIO_CFG_INDEX(pin);
+	u32 offset = GPIO_CFG_OFFSET(pin);
+	struct sunxi_gpio *pio =
+	    &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank];
+
+	cfg = readl(&pio->cfg[0] + index);
+	cfg >>= offset;
+
+	return cfg & 0xf;
+}
+
Index: arch/arm/cpu/armv7/sunxi/timer.c
===================================================================
--- /dev/null
+++ arch/arm/cpu/armv7/sunxi/timer.c
@@ -0,0 +1,120 @@
+/*
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.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/timer.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define TIMER_MODE   (0 << 7)	/* continuous mode */
+#define TIMER_DIV    (0 << 4)	/* pre scale 1 */
+#define TIMER_SRC    (1 << 2)	/* osc24m */
+#define TIMER_RELOAD (1 << 1)	/* reload internal value */
+#define TIMER_EN     (1 << 0)	/* enable timer */
+
+#define TIMER_CLOCK		(24 * 1000 * 1000)
+#define COUNT_TO_USEC(x)	((x) / 24)
+#define USEC_TO_COUNT(x)	((x) * 24)
+#define TICKS_PER_HZ		(TIMER_CLOCK / CONFIG_SYS_HZ)
+#define TICKS_TO_HZ(x)		((x) / TICKS_PER_HZ)
+
+#define TIMER_LOAD_VAL		0xffffffff
+
+#define TIMER_NUM		0	/* we use timer 0 */
+
+static struct sunxi_timer *timer_base =
+	&((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->timer[TIMER_NUM];
+
+/* macro to read the 32 bit timer: since it decrements, we invert read value */
+#define READ_TIMER() (~readl(&timer_base->val))
+
+/* init timer register */
+int timer_init(void)
+{
+	writel(TIMER_LOAD_VAL, &timer_base->inter);
+	writel(TIMER_MODE | TIMER_DIV | TIMER_SRC | TIMER_RELOAD | TIMER_EN,
+	       &timer_base->ctl);
+
+	return 0;
+}
+
+/* timer without interrupts */
+ulong get_timer(ulong base)
+{
+	return get_timer_masked() - base;
+}
+
+ulong get_timer_masked(void)
+{
+	/* current tick value */
+	ulong now = TICKS_TO_HZ(READ_TIMER());
+
+	if (now >= gd->arch.lastinc)	/* normal (non rollover) */
+		gd->arch.tbl += (now - gd->arch.lastinc);
+	else {
+		/* rollover */
+		gd->arch.tbl += (TICKS_TO_HZ(TIMER_LOAD_VAL)
+				- gd->arch.lastinc) + now;
+	}
+	gd->arch.lastinc = now;
+
+	return gd->arch.tbl;
+}
+
+/* delay x useconds */
+void __udelay(unsigned long usec)
+{
+	long tmo = usec * (TIMER_CLOCK / 1000) / 1000;
+	ulong now, last = READ_TIMER();
+
+	while (tmo > 0) {
+		now = READ_TIMER();
+		if (now > last)	/* normal (non rollover) */
+			tmo -= now - last;
+		else		/* rollover */
+			tmo -= TIMER_LOAD_VAL - last + now;
+		last = now;
+	}
+}
+
+/*
+ * This function is derived from PowerPC code (read timebase as long long).
+ * On ARM it just returns the timer value.
+ */
+unsigned long long get_ticks(void)
+{
+	return get_timer(0);
+}
+
+/*
+ * This function is derived from PowerPC code (timebase clock frequency).
+ * On ARM it returns the number of timer ticks per second.
+ */
+ulong get_tbclk(void)
+{
+	ulong tbclk;
+	tbclk = CONFIG_SYS_HZ;
+	return tbclk;
+}
Index: arch/arm/cpu/armv7/sunxi/u-boot-spl.lds
===================================================================
--- /dev/null
+++ arch/arm/cpu/armv7/sunxi/u-boot-spl.lds
@@ -0,0 +1,69 @@
+/*
+ * (C) Copyright 2012
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * Based on omap-common/u-boot-spl.lds:
+ *
+ * (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
+}
Index: arch/arm/include/asm/arch-sunxi/clock.h
===================================================================
--- /dev/null
+++ arch/arm/include/asm/arch-sunxi/clock.h
@@ -0,0 +1,179 @@
+/*
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.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
+ */
+
+#ifndef _SUNXI_CLOCK_H
+#define _SUNXI_CLOCK_H
+
+/* clock control module regs definition */
+
+struct sunxi_ccm_reg {
+	u32 pll1_cfg;		/* 0x00 pll1 control */
+	u32 pll1_tun;		/* 0x04 pll1 tuning */
+	u32 pll2_cfg;		/* 0x08 pll2 control */
+	u32 pll2_tun;		/* 0x0c pll2 tuning */
+	u32 pll3_cfg;		/* 0x10 pll3 control */
+	u8 res0[0x4];
+	u32 pll4_cfg;		/* 0x18 pll4 control */
+	u8 res1[0x4];
+	u32 pll5_cfg;		/* 0x20 pll5 control */
+	u32 pll5_tun;		/* 0x24 pll5 tuning */
+	u32 pll6_cfg;		/* 0x28 pll6 control */
+	u32 pll6_tun;		/* 0x2c pll6 tuning */
+	u32 pll7_cfg;		/* 0x30 pll7 control */
+	u32 pll1_tun2;		/* 0x34 pll5 tuning2 */
+	u8 res2[0x4];
+	u32 pll5_tun2;		/* 0x3c pll5 tuning2 */
+	u8 res3[0xc];
+	u32 pll_lock_dbg;	/* 0x4c pll lock time debug */
+	u32 osc24m_cfg;		/* 0x50 osc24m control */
+	u32 cpu_ahb_apb0_cfg;	/* 0x54 cpu,ahb and apb0 divide ratio */
+	u32 apb1_clk_div_cfg;	/* 0x58 apb1 clock dividor */
+	u32 axi_gate;		/* 0x5c axi module clock gating */
+	u32 ahb_gate0;		/* 0x60 ahb module clock gating 0 */
+	u32 ahb_gate1;		/* 0x64 ahb module clock gating 1 */
+	u32 apb0_gate;		/* 0x68 apb0 module clock gating */
+	u32 apb1_gate;		/* 0x6c apb1 module clock gating */
+	u8 res4[0x10];
+	u32 nand_sclk_cfg;	/* 0x80 nand sub clock control */
+	u32 ms_sclk_cfg;	/* 0x84 memory stick sub clock control */
+	u32 sd0_clk_cfg;	/* 0x88 sd0 clock control */
+	u32 sd1_clk_cfg;	/* 0x8c sd1 clock control */
+	u32 sd2_clk_cfg;	/* 0x90 sd2 clock control */
+	u32 sd3_clk_cfg;	/* 0x94 sd3 clock control */
+	u32 ts_clk_cfg;		/* 0x98 transport stream clock control */
+	u32 ss_clk_cfg;		/* 0x9c */
+	u32 spi0_clk_cfg;	/* 0xa0 */
+	u32 spi1_clk_cfg;	/* 0xa4 */
+	u32 spi2_clk_cfg;	/* 0xa8 */
+	u32 pata_clk_cfg;	/* 0xac */
+	u32 ir0_clk_cfg;	/* 0xb0 */
+	u32 ir1_clk_cfg;	/* 0xb4 */
+	u32 iis_clk_cfg;	/* 0xb8 */
+	u32 ac97_clk_cfg;	/* 0xbc */
+	u32 spdif_clk_cfg;	/* 0xc0 */
+	u32 keypad_clk_cfg;	/* 0xc4 */
+	u32 sata_clk_cfg;	/* 0xc8 */
+	u32 usb_clk_cfg;	/* 0xcc */
+	u32 gps_clk_cfg;	/* 0xd0 */
+	u32 spi3_clk_cfg;	/* 0xd4 */
+	u8 res5[0x28];
+	u32 dram_clk_cfg;	/* 0x100 */
+	u32 be0_clk_cfg;	/* 0x104 */
+	u32 be1_clk_cfg;	/* 0x108 */
+	u32 fe0_clk_cfg;	/* 0x10c */
+	u32 fe1_clk_cfg;	/* 0x110 */
+	u32 mp_clk_cfg;		/* 0x114 */
+	u32 lcd0_ch0_clk_cfg;	/* 0x118 */
+	u32 lcd1_ch0_clk_cfg;	/* 0x11c */
+	u32 csi_isp_clk_cfg;	/* 0x120 */
+	u8 res6[0x4];
+	u32 tvd_clk_reg;	/* 0x128 */
+	u32 lcd0_ch1_clk_cfg;	/* 0x12c */
+	u32 lcd1_ch1_clk_cfg;	/* 0x130 */
+	u32 csi0_clk_cfg;	/* 0x134 */
+	u32 csi1_clk_cfg;	/* 0x138 */
+	u32 ve_clk_cfg;		/* 0x13c */
+	u32 audio_codec_clk_cfg;	/* 0x140 */
+	u32 avs_clk_cfg;	/* 0x144 */
+	u32 ace_clk_cfg;	/* 0x148 */
+	u32 lvds_clk_cfg;	/* 0x14c */
+	u32 hdmi_clk_cfg;	/* 0x150 */
+	u32 mali_clk_cfg;	/* 0x154 */
+	u8 res7[0x4];
+	u32 mbus_clk_cfg;	/* 0x15c */
+};
+
+/* apb1 bit field */
+#define APB1_CLK_SRC_OSC24M		0
+#define APB1_FACTOR_M			0
+#define APB1_FACTOR_N			0
+
+/* clock divide */
+#define CPU_CLK_SRC_OSC24M		1
+#define CPU_CLK_SRC_PLL1		2
+#define AXI_DIV_1			0
+#define AXI_DIV_2			1
+#define AXI_DIV_3			2
+#define AXI_DIV_4			3
+#define AHB_DIV_1			0
+#define AHB_DIV_2			1
+#define AHB_DIV_4			2
+#define AHB_DIV_8			3
+#define APB0_DIV_1			0
+#define APB0_DIV_2			1
+#define APB0_DIV_4			2
+#define APB0_DIV_8			3
+
+#ifdef CONFIG_SUN5I
+#define AHB_CLK_SRC_AXI			0
+#endif
+
+#define CLK_GATE_OPEN			0x1
+#define CLK_GATE_CLOSE			0x0
+
+/* nand clock */
+#define NAND_CLK_SRC_OSC24		0
+#define NAND_CLK_DIV_N			0
+#define NAND_CLK_DIV_M			0
+
+/* gps clock */
+#define GPS_SCLK_GATING_OFF		0
+#define GPS_RESET			0
+
+/* ahb clock gate bit offset */
+#define AHB_GATE_OFFSET_GPS		26
+#define AHB_GATE_OFFSET_SATA		25
+#define AHB_GATE_OFFSET_PATA		24
+#define AHB_GATE_OFFSET_SPI3		23
+#define AHB_GATE_OFFSET_SPI2		22
+#define AHB_GATE_OFFSET_SPI1		21
+#define AHB_GATE_OFFSET_SPI0		20
+#define AHB_GATE_OFFSET_TS0		18
+#define AHB_GATE_OFFSET_EMAC		17
+#define AHB_GATE_OFFSET_ACE		16
+#define AHB_GATE_OFFSET_DLL		15
+#define AHB_GATE_OFFSET_SDRAM		14
+#define AHB_GATE_OFFSET_NAND		13
+#define AHB_GATE_OFFSET_MS		12
+#define AHB_GATE_OFFSET_MMC3		11
+#define AHB_GATE_OFFSET_MMC2		10
+#define AHB_GATE_OFFSET_MMC1		9
+#define AHB_GATE_OFFSET_MMC0		8
+#define AHB_GATE_OFFSET_BIST		7
+#define AHB_GATE_OFFSET_DMA		6
+#define AHB_GATE_OFFSET_SS		5
+#define AHB_GATE_OFFSET_USB_OHCI1	4
+#define AHB_GATE_OFFSET_USB_EHCI1	3
+#define AHB_GATE_OFFSET_USB_OHCI0	2
+#define AHB_GATE_OFFSET_USB_EHCI0	1
+#define AHB_GATE_OFFSET_USB		0
+
+#ifndef __ASSEMBLY__
+int clock_init(void);
+int clock_twi_onoff(int port, int state);
+void clock_set_pll1(int mhz);
+unsigned int clock_get_pll5(void);
+#endif
+
+#endif /* _SUNXI_CLOCK_H */
Index: arch/arm/include/asm/arch-sunxi/cpu.h
===================================================================
--- /dev/null
+++ arch/arm/include/asm/arch-sunxi/cpu.h
@@ -0,0 +1,145 @@
+/*
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.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
+ */
+
+#ifndef _SUNXI_CPU_H
+#define _SUNXI_CPU_H
+
+#define SUNXI_SRAM_A1_BASE		0x00000000
+#define SUNXI_SRAM_A1_SIZE		(16 * 1024)	/* 16k */
+
+#define SUNXI_SRAM_A2_BASE		0x00004000	/* 16k */
+#define SUNXI_SRAM_A3_BASE		0x00008000	/* 13k */
+#define SUNXI_SRAM_A4_BASE		0x0000B400	/* 3k */
+#define SUNXI_SRAM_D_BASE		0x01C00000
+#define SUNXI_SRAM_B_BASE		0x01C00000	/* 64k(secure) */
+
+#define SUNXI_SRAMC_BASE		0x01C00000
+#define SUNXI_DRAMC_BASE		0x01C01000
+#define SUNXI_DMA_BASE			0x01C02000
+#define SUNXI_NFC_BASE			0x01C03000
+#define SUNXI_TS_BASE			0x01C04000
+#define SUNXI_SPI0_BASE			0x01C05000
+#define SUNXI_SPI1_BASE			0x01C06000
+#define SUNXI_MS_BASE			0x01C07000
+#define SUNXI_TVD_BASE			0x01C08000
+#define SUNXI_CSI0_BASE			0x01C09000
+#define SUNXI_TVE0_BASE			0x01C0A000
+#define SUNXI_EMAC_BASE			0x01C0B000
+#define SUNXI_LCD0_BASE			0x01C0C000
+#define SUNXI_LCD1_BASE			0x01C0D000
+#define SUNXI_VE_BASE			0x01C0E000
+#define SUNXI_MMC0_BASE			0x01C0F000
+#define SUNXI_MMC1_BASE			0x01C10000
+#define SUNXI_MMC2_BASE			0x01C11000
+#define SUNXI_MMC3_BASE			0x01C12000
+#define SUNXI_USB0_BASE			0x01C13000
+#define SUNXI_USB1_BASE			0x01C14000
+#define SUNXI_SS_BASE			0x01C15000
+#define SUNXI_HDMI_BASE			0x01C16000
+#define SUNXI_SPI2_BASE			0x01C17000
+#define SUNXI_SATA_BASE			0x01C18000
+#define SUNXI_PATA_BASE			0x01C19000
+#define SUNXI_ACE_BASE			0x01C1A000
+#define SUNXI_TVE1_BASE			0x01C1B000
+#define SUNXI_USB2_BASE			0x01C1C000
+#define SUNXI_CSI1_BASE			0x01C1D000
+#define SUNXI_TZASC_BASE		0x01C1E000
+#define SUNXI_SPI3_BASE			0x01C1F000
+
+#define SUNXI_CCM_BASE			0x01C20000
+#define SUNXI_INTC_BASE			0x01C20400
+#define SUNXI_PIO_BASE			0x01C20800
+#define SUNXI_TIMER_BASE		0x01C20C00
+#define SUNXI_SPDIF_BASE		0x01C21000
+#define SUNXI_AC97_BASE			0x01C21400
+#define SUNXI_IR0_BASE			0x01C21800
+#define SUNXI_IR1_BASE			0x01C21C00
+
+#define SUNXI_IIS_BASE			0x01C22400
+#define SUNXI_LRADC_BASE		0x01C22800
+#define SUNXI_AD_DA_BASE		0x01C22C00
+#define SUNXI_KEYPAD_BASE		0x01C23000
+#define SUNXI_TZPC_BASE			0x01C23400
+#define SUNXI_SID_BASE			0x01C23800
+#define SUNXI_SJTAG_BASE		0x01C23C00
+
+#define SUNXI_TP_BASE			0x01C25000
+#define SUNXI_PMU_BASE			0x01C25400
+
+#define SUNXI_UART0_BASE		0x01C28000
+#define SUNXI_UART1_BASE		0x01C28400
+#define SUNXI_UART2_BASE		0x01C28800
+#define SUNXI_UART3_BASE		0x01C28C00
+#define SUNXI_UART4_BASE		0x01C29000
+#define SUNXI_UART5_BASE		0x01C29400
+#define SUNXI_UART6_BASE		0x01C29800
+#define SUNXI_UART7_BASE		0x01C29C00
+#define SUNXI_PS2_0_BASE		0x01C2A000
+#define SUNXI_PS2_1_BASE		0x01C2A400
+
+#define SUNXI_TWI0_BASE			0x01C2AC00
+#define SUNXI_TWI1_BASE			0x01C2B000
+#define SUNXI_TWI2_BASE			0x01C2B400
+
+#define SUNXI_CAN_BASE			0x01C2BC00
+
+#define SUNXI_SCR_BASE			0x01C2C400
+
+#define SUNXI_GPS_BASE			0x01C30000
+#define SUNXI_MALI400_BASE		0x01C40000
+
+/* module sram */
+#define SUNXI_SRAM_C_BASE		0x01D00000
+
+#define SUNXI_DE_FE0_BASE		0x01E00000
+#define SUNXI_DE_FE1_BASE		0x01E20000
+#define SUNXI_DE_BE0_BASE		0x01E60000
+#define SUNXI_DE_BE1_BASE		0x01E40000
+#define SUNXI_MP_BASE			0x01E80000
+#define SUNXI_AVG_BASE			0x01EA0000
+
+/* CoreSight Debug Module */
+#define SUNXI_CSDM_BASE			0x3F500000
+
+#define SUNXI_DDRII_DDRIII_BASE		0x40000000	/* 2G */
+
+#define SUNXI_BROM_BASE			0xFFFF0000	/* 32K */
+
+#define SUNXI_CPU_CFG			(SUNXI_TIMER_BASE + 0x13c)
+
+#ifndef __ASSEMBLY__
+/* boot type */
+enum sunxi_boot_type_t {
+	SUNXI_BOOT_TYPE_NULL,
+	SUNXI_BOOT_TYPE_MMC0,
+	SUNXI_BOOT_TYPE_NAND,
+	SUNXI_BOOT_TYPE_MMC2,
+	SUNXI_BOOT_TYPE_SPI
+};
+
+void sunxi_board_init(void);
+extern void sunxi_reset(void);
+#endif /* __ASSEMBLY__ */
+
+#endif /* _CPU_H */
Index: arch/arm/include/asm/arch-sunxi/dram.h
===================================================================
--- /dev/null
+++ arch/arm/include/asm/arch-sunxi/dram.h
@@ -0,0 +1,114 @@
+/*
+ * (C) Copyright 2007-2012
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Berg Xing <bergxing@allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * Sunxi platform dram register definition.
+ *
+ * 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 _SUNXI_DRAM_H
+#define _SUNXI_DRAM_H
+
+struct sunxi_dram_reg {
+	u32 ccr;		/* 0x00 controller configuration register */
+	u32 dcr;		/* 0x04 dram configuration register */
+	u32 iocr;		/* 0x08 i/o configuration register */
+	u32 csr;		/* 0x0c controller status register */
+	u32 drr;		/* 0x10 dram refresh register */
+	u32 tpr0;		/* 0x14 dram timing parameters register 0 */
+	u32 tpr1;		/* 0x18 dram timing parameters register 1 */
+	u32 tpr2;		/* 0x1c dram timing parameters register 2 */
+	u32 gdllcr;		/* 0x20 global dll control register */
+	u8 res0[0x28];
+	u32 rslr0;		/* 0x4c rank system latency register */
+	u32 rslr1;		/* 0x50 rank system latency register */
+	u8 res1[0x8];
+	u32 rdgr0;		/* 0x5c rank dqs gating register */
+	u32 rdgr1;		/* 0x60 rank dqs gating register */
+	u8 res2[0x34];
+	u32 odtcr;		/* 0x98 odt configuration register */
+	u32 dtr0;		/* 0x9c data training register 0 */
+	u32 dtr1;		/* 0xa0 data training register 1 */
+	u32 dtar;		/* 0xa4 data training address register */
+	u32 zqcr0;		/* 0xa8 zq control register 0 */
+	u32 zqcr1;		/* 0xac zq control register 1 */
+	u32 zqsr;		/* 0xb0 zq status register */
+	u32 idcr;		/* 0xb4 initializaton delay configure reg */
+	u8 res3[0x138];
+	u32 mr;			/* 0x1f0 mode register */
+	u32 emr;		/* 0x1f4 extended mode register */
+	u32 emr2;		/* 0x1f8 extended mode register */
+	u32 emr3;		/* 0x1fc extended mode register */
+	u32 dllctr;		/* 0x200 dll control register */
+	u32 dllcr[5];		/* 0x204 dll control register 0(byte 0) */
+	/* 0x208 dll control register 1(byte 1) */
+	/* 0x20c dll control register 2(byte 2) */
+	/* 0x210 dll control register 3(byte 3) */
+	/* 0x214 dll control register 4(byte 4) */
+	u32 dqtr0;		/* 0x218 dq timing register */
+	u32 dqtr1;		/* 0x21c dq timing register */
+	u32 dqtr2;		/* 0x220 dq timing register */
+	u32 dqtr3;		/* 0x224 dq timing register */
+	u32 dqstr;		/* 0x228 dqs timing register */
+	u32 dqsbtr;		/* 0x22c dqsb timing register */
+	u32 mcr;		/* 0x230 mode configure register */
+	u8 res[0x8];
+	u32 ppwrsctl;		/* 0x23c pad power save control */
+	u32 apr;		/* 0x240 arbiter period register */
+	u32 pldtr;		/* 0x244 priority level data threshold reg */
+	u8 res5[0x8];
+	u32 hpcr[32];		/* 0x250 host port configure register */
+	u8 res6[0x10];
+	u32 csel;		/* 0x2e0 controller select register */
+};
+
+struct dram_para {
+	u32 clock;
+	u32 type;
+	u32 rank_num;
+	u32 density;
+	u32 io_width;
+	u32 bus_width;
+	u32 cas;
+	u32 zq;
+	u32 odt_en;
+	u32 size;
+	u32 tpr0;
+	u32 tpr1;
+	u32 tpr2;
+	u32 tpr3;
+	u32 tpr4;
+	u32 tpr5;
+	u32 emr1;
+	u32 emr2;
+	u32 emr3;
+};
+
+#define SUN5I_DRAM_MCR_DCLK_OUT_OFFSET	16
+#define SUN4I_CCM_SDRAM_DCLK_OUT_OFFSET  15
+
+#define DRAM_CTRL_SELECT_MAGIC	0x16237495
+
+int sunxi_dram_init(void);
+int dramc_init(struct dram_para *para);
+
+#endif /* _SUNXI_DRAM_H */
Index: arch/arm/include/asm/arch-sunxi/early_print.h
===================================================================
--- /dev/null
+++ arch/arm/include/asm/arch-sunxi/early_print.h
@@ -0,0 +1,58 @@
+/*
+ * (C) Copyright 2007-2012
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * Early uart print for debugging.
+ *
+ * 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 _SUNXI_EARLY_PRINT_H
+#define _SUNXI_EARLY_PRINT_H
+
+#include <asm/arch/clock.h>
+
+#define UART0_RBR (SUNXI_UART0_BASE + 0x0)    /* receive buffer register */
+#define UART0_THR (SUNXI_UART0_BASE + 0x0)    /* transmit holding register */
+#define UART0_DLL (SUNXI_UART0_BASE + 0x0)    /* divisor latch low register */
+
+#define UART0_DLH (SUNXI_UART0_BASE + 0x4)    /* divisor latch high register */
+#define UART0_IER (SUNXI_UART0_BASE + 0x4)    /* interrupt enable reigster */
+
+#define UART0_IIR (SUNXI_UART0_BASE + 0x8)    /* interrupt identity register */
+#define UART0_FCR (SUNXI_UART0_BASE + 0x8)    /* fifo control register */
+
+#define UART0_LCR (SUNXI_UART0_BASE + 0xc)    /* line control register */
+
+#define UART0_LSR (SUNXI_UART0_BASE + 0x14)   /* line status register */
+
+#define BAUD_115200    (0xD) /* 24 * 1000 * 1000 / 16 / 115200 = 13 */
+#define NO_PARITY      (0)
+#define ONE_STOP_BIT   (0)
+#define DAT_LEN_8_BITS (3)
+#define LC_8_N_1          (NO_PARITY << 3 | ONE_STOP_BIT << 2 | DAT_LEN_8_BITS)
+
+#ifndef __ASSEMBLY__
+int uart0_init(void);
+void uart0_putc(char c);
+void uart0_puts(const char *s);
+#endif /* __ASSEMBLY__ */
+
+#endif /* _SUNXI_EARLY_PRINT_H */
Index: arch/arm/include/asm/arch-sunxi/gpio.h
===================================================================
--- /dev/null
+++ arch/arm/include/asm/arch-sunxi/gpio.h
@@ -0,0 +1,166 @@
+/*
+ * (C) Copyright 2007-2012
+ * Allwinner Technology Co., Ltd. <www.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
+ */
+
+#ifndef _SUNXI_GPIO_H
+#define _SUNXI_GPIO_H
+
+/*
+ * sunxi has 9 banks of gpio, they are:
+ * PA0 - PA17 | PB0 - PB23 | PC0 - PC24
+ * PD0 - PD27 | PE0 - PE31 | PF0 - PF5
+ * PG0 - PG9  | PH0 - PH27 | PI0 - PI12
+ */
+
+#define SUNXI_GPIO_A	0
+#define SUNXI_GPIO_B	1
+#define SUNXI_GPIO_C	2
+#define SUNXI_GPIO_D	3
+#define SUNXI_GPIO_E	4
+#define SUNXI_GPIO_F	5
+#define SUNXI_GPIO_G	6
+#define SUNXI_GPIO_H	7
+#define SUNXI_GPIO_I	8
+
+struct sunxi_gpio {
+	u32 cfg[4];
+	u32 dat;
+	u32 drv[2];
+	u32 pull[2];
+};
+
+/* gpio interrupt control */
+struct sunxi_gpio_int {
+	u32 cfg[3];
+	u32 ctl;
+	u32 sta;
+	u32 deb;		/* interrupt debounce */
+};
+
+struct sunxi_gpio_reg {
+	struct sunxi_gpio gpio_bank[9];
+	u8 res[0xbc];
+	struct sunxi_gpio_int gpio_int;
+};
+
+#define GPIO_BANK(pin)		((pin) >> 5)
+#define GPIO_NUM(pin)		((pin) & 0x1F)
+
+#define GPIO_CFG_INDEX(pin)	(((pin) & 0x1F) >> 3)
+#define GPIO_CFG_OFFSET(pin)	((((pin) & 0x1F) & 0x7) << 2)
+
+/* GPIO bank sizes */
+#define SUNXI_GPIO_A_NR		32
+#define SUNXI_GPIO_B_NR		32
+#define SUNXI_GPIO_C_NR		32
+#define SUNXI_GPIO_D_NR		32
+#define SUNXI_GPIO_E_NR		32
+#define SUNXI_GPIO_F_NR		32
+#define SUNXI_GPIO_G_NR		32
+#define SUNXI_GPIO_H_NR		32
+#define SUNXI_GPIO_I_NR		32
+
+#define SUNXI_GPIO_NEXT(__gpio) \
+	((__gpio##_START) + (__gpio##_NR) + 0)
+
+enum sunxi_gpio_number {
+	SUNXI_GPIO_A_START = 0,
+	SUNXI_GPIO_B_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_A),
+	SUNXI_GPIO_C_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_B),
+	SUNXI_GPIO_D_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_C),
+	SUNXI_GPIO_E_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_D),
+	SUNXI_GPIO_F_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_E),
+	SUNXI_GPIO_G_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_F),
+	SUNXI_GPIO_H_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_G),
+	SUNXI_GPIO_I_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_H),
+};
+
+/* SUNXI GPIO number definitions */
+#define SUNXI_GPA(_nr)	(SUNXI_GPIO_A_START + (_nr))
+#define SUNXI_GPB(_nr)	(SUNXI_GPIO_B_START + (_nr))
+#define SUNXI_GPC(_nr)	(SUNXI_GPIO_C_START + (_nr))
+#define SUNXI_GPD(_nr)	(SUNXI_GPIO_D_START + (_nr))
+#define SUNXI_GPE(_nr)	(SUNXI_GPIO_E_START + (_nr))
+#define SUNXI_GPF(_nr)	(SUNXI_GPIO_F_START + (_nr))
+#define SUNXI_GPG(_nr)	(SUNXI_GPIO_G_START + (_nr))
+#define SUNXI_GPH(_nr)	(SUNXI_GPIO_H_START + (_nr))
+#define SUNXI_GPI(_nr)	(SUNXI_GPIO_I_START + (_nr))
+
+/* GPIO pin function config */
+#define SUNXI_GPIO_INPUT	0
+#define SUNXI_GPIO_OUTPUT	1
+
+#define SUNXI_GPA0_ERXD3	2
+#define SUNXI_GPA0_SPI1_CS0	3
+#define SUNXI_GPA0_UART2_RTS	4
+
+#define SUNXI_GPA1_ERXD2	2
+#define SUNXI_GPA1_SPI1_CLK	3
+#define SUNXI_GPA1_UART2_CTS	4
+
+#define SUNXI_GPA2_ERXD1	2
+#define SUNXI_GPA2_SPI1_MOSI	3
+#define SUNXI_GPA2_UART2_TX	4
+
+#define SUNXI_GPA10_UART1_TX	4
+#define SUNXI_GPA11_UART1_RX	4
+
+#define SUN4I_GPB22_UART0_TX	2
+#define SUN4I_GPB23_UART0_RX	2
+
+#define SUN5I_GPG3_UART0_TX	4
+#define SUN5I_GPG4_UART0_RX	4
+
+#define SUNXI_GPC2_NCLE		2
+#define SUNXI_GPC2_SPI0_CLK	3
+
+#define SUNXI_GPC6_NRB0		2
+#define SUNXI_GPC6_SDC2_CMD	3
+
+#define SUNXI_GPC7_NRB1		2
+#define SUNXI_GPC7_SDC2_CLK	3
+
+#define SUNXI_GPC8_NDQ0		2
+#define SUNXI_GPC8_SDC2_D0	3
+
+#define SUNXI_GPC9_NDQ1		2
+#define SUNXI_GPC9_SDC2_D1	3
+
+#define SUNXI_GPC10_NDQ2	2
+#define SUNXI_GPC10_SDC2_D2	3
+
+#define SUNXI_GPC11_NDQ3	2
+#define SUNXI_GPC11_SDC2_D3	3
+
+#define SUNXI_GPF2_SDC0_CLK	2
+#define SUNXI_GPF2_UART0_TX	4
+
+#define SUNXI_GPF4_SDC0_D3	2
+#define SUNXI_GPF4_UART0_RX	4
+
+int sunxi_gpio_set_cfgpin(u32 pin, u32 val);
+int sunxi_gpio_get_cfgpin(u32 pin);
+int name_to_gpio(const char *name);
+#define name_to_gpio	name_to_gpio
+
+#endif /* _SUNXI_GPIO_H */
Index: arch/arm/include/asm/arch-sunxi/i2c.h
===================================================================
--- /dev/null
+++ arch/arm/include/asm/arch-sunxi/i2c.h
@@ -0,0 +1,185 @@
+/*
+ * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
+ *
+ * Based on sun4i linux kernle i2c.h
+ * (C) Copyright 2007-2012
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tanglaing@allwinnertech.com>
+ * Victor Wei <weiziheng@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
+ */
+#ifndef _SUNXI_I2C_H_
+#define _SUNXI_I2C_H_
+
+struct i2c {
+	u32 saddr;	/*  31:8bit res,7-1bit for slave addr,0 bit for GCE */
+	u32 xsaddr;	/*  31:8bit res,7-0bit for second addr in 10bit addr */
+	u32 data;	/*  31:8bit res, 7-0bit send or receive data byte */
+	u32 ctl;	/*  INT_EN,BUS_EN,M_STA,INT_FLAG,A_ACK */
+	u32 status;	/*  28 interrupt types + 0xF8 normal type = 29  */
+	u32 clkr;	/*  31:7bit res,6-3bit,CLK_M,2-0bit CLK_N */
+	u32 reset;	/*  31:1bit res;0bit,write 1 to clear 0. */
+	u32 efr;	/*  31:2bit res,1:0 bit data byte follow read comand */
+	u32 lctl;	/*  31:6bits res 5:0bit for sda&scl control */
+};
+
+/* TWI address register */
+#define TWI_GCE_EN	(0x1 << 0)	/* gen call addr enable slave mode */
+#define TWI_ADDR_MASK	(0x7f << 1)	/* 7:1bits */
+#define TWI_XADDR_MASK	0xff		/* 7:0bits for extend slave address */
+
+#define TWI_DATA_MASK	0xff		/* 7:0bits for send or received */
+
+/* TWI Control Register Bit Fields */
+/* 1:0 bits reserved */
+/* set 1 to send A_ACK,then low level on SDA */
+#define TWI_CTL_ACK	(0x1 << 2)
+/* INT_FLAG,interrupt status flag: set '1' when interrupt coming */
+#define TWI_CTL_INTFLG	(0x1 << 3)
+#define TWI_CTL_STP	(0x1 << 4)	/* M_STP,Automatic clear 0 */
+#define TWI_CTL_STA	(0x1 << 5)	/* M_STA,atutomatic clear 0 */
+#define TWI_CTL_BUSEN	(0x1 << 6)	/* BUS_EN, mastr mode should be set 1 */
+#define TWI_CTL_INTEN	(0x1 << 7)	/* INT_EN */
+/* 31:8 bit reserved */
+
+/*
+ * TWI Clock Register Bit Fields & Masks,default value:0x0000_0000
+ * Fin is APB CLOCK INPUT;
+ * Fsample = F0 = Fin/2^CLK_N;
+ *           F1 = F0/(CLK_M+1);
+ *
+ * Foscl = F1/10 = Fin/(2^CLK_N * (CLK_M+1)*10);
+ * Foscl is clock SCL;standard mode:100KHz or fast mode:400KHz
+ */
+
+#define TWI_CLK_DIV_M		(0xF << 3)	/* 6:3bit  */
+#define TWI_CLK_DIV_N		(0x7 << 0)	/* 2:0bit */
+#define TWI_CLK_DIV(N, M)	((((N) & 0xF) << 3) | (((M) & 0x7) << 0))
+
+/* TWI Soft Reset Register Bit Fields & Masks  */
+/* write 1 to clear 0, when complete soft reset clear 0 */
+#define TWI_SRST_SRST		(0x1 << 0)
+
+/* TWI Enhance Feature Register Bit Fields & Masks  */
+/* default -- 0x0 */
+/* 00:no,01: 1byte, 10:2 bytes, 11: 3bytes */
+#define TWI_EFR_MASK		(0x3 << 0)
+#define TWI_EFR_WARC_0		(0x0 << 0)
+#define TWI_EFR_WARC_1		(0x1 << 0)
+#define TWI_EFR_WARC_2		(0x2 << 0)
+#define TWI_EFR_WARC_3		(0x3 << 0)
+
+/* twi line control register -default value: 0x0000_003a */
+/* SDA line state control enable ,1:enable;0:disable */
+#define TWI_LCR_SDA_EN		(0x01 << 0)
+/* SDA line state control bit, 1:high level;0:low level */
+#define TWI_LCR_SDA_CTL		(0x01 << 1)
+/* SCL line state control enable ,1:enable;0:disable */
+#define TWI_LCR_SCL_EN		(0x01 << 2)
+/* SCL line state control bit, 1:high level;0:low level */
+#define TWI_LCR_SCL_CTL		(0x01 << 3)
+/* current state of SDA,readonly bit */
+#define TWI_LCR_SDA_STATE_MASK	(0x01 << 4)
+/* current state of SCL,readonly bit */
+#define TWI_LCR_SCL_STATE_MASK	(0x01 << 5)
+/* 31:6bits reserved */
+#define TWI_LCR_IDLE_STATUS	0x3a
+
+/* TWI Status Register Bit Fields & Masks  */
+#define TWI_STAT_MASK		0xff
+/* 7:0 bits use only,default is 0xF8 */
+#define TWI_STAT_BUS_ERR	0x00	/* BUS ERROR */
+
+/* Master mode use only */
+#define TWI_STAT_TX_STA		0x08	/* START condition transmitted */
+/* Repeated START condition transmitted */
+#define TWI_STAT_TX_RESTA	0x10
+/* Address+Write bit transmitted, ACK received */
+#define TWI_STAT_TX_AW_ACK	0x18
+/* Address+Write bit transmitted, ACK not received */
+#define TWI_STAT_TX_AW_NAK	0x20
+/* data byte transmitted in master mode,ack received */
+#define TWI_STAT_TXD_ACK	0x28
+/* data byte transmitted in master mode ,ack not received */
+#define TWI_STAT_TXD_NAK	0x30
+/* arbitration lost in address or data byte */
+#define TWI_STAT_ARBLOST	0x38
+/* Address+Read bit transmitted, ACK received */
+#define TWI_STAT_TX_AR_ACK	0x40
+/* Address+Read bit transmitted, ACK not received */
+#define TWI_STAT_TX_AR_NAK	0x48
+/* Second Address byte + Write bit transmitted, ACK received */
+#define TWI_STAT_TX_2AW_ACK	0xD0
+/* Second Address byte + Write bit transmitted, ACK received */
+#define TWI_STAT_TX_2AW_NAK	0xD8
+/* data byte received in master mode ,ack transmitted */
+#define TWI_STAT_RXD_ACK	0x50
+/* date byte received in master mode,not ack transmitted */
+#define TWI_STAT_RXD_NAK	0x58
+
+/* Slave mode use only */
+/* Slave address+Write bit received, ACK transmitted */
+#define TWI_STAT_RXWS_ACK	0x60
+/*
+ * Arbitration lost in address as master, slave address + Write bit received,
+ * ACK transmitted
+ */
+#define TWI_STAT_ARBLOST_RXWS_ACK 0x68
+/* General Call address received, ACK transmitted */
+#define TWI_STAT_RXGCAS_ACK	0x70
+/*
+ * Arbitration lost in address as master, General Call address received,
+ * ACK transmitted
+ */
+#define TWI_STAT_ARBLOST_RXGCAS_ACK 0x78
+/* Data byte received after slave address received, ACK transmitted */
+#define TWI_STAT_RXDS_ACK	0x80
+/* Data byte received after slave address received, not ACK transmitted */
+#define TWI_STAT_RXDS_NAK	0x88
+/* Data byte received after General Call received, ACK transmitted */
+#define TWI_STAT_RXDGCAS_ACK	0x90
+/* Data byte received after General Call received, not ACK transmitted */
+#define TWI_STAT_RXDGCAS_NAK	0x98
+/* STOP or repeated START condition received in slave  */
+#define TWI_STAT_RXSTPS_RXRESTAS 0xA0
+/* Slave address + Read bit received, ACK transmitted */
+#define TWI_STAT_RXRS_ACK	0xA8
+/*
+ * Arbitration lost in address as master, slave address + Read bit received,
+ * ACK transmitted
+ */
+#define TWI_STAT_ARBLOST_SLAR_ACK 0xB0
+/* Data byte transmitted in slave mode, ACK received */
+#define TWI_STAT_TXDS_ACK	0xB8
+/* Data byte transmitted in slave mode, ACK not received */
+#define TWI_STAT_TXDS_NAK	0xC0
+/* Last byte transmitted in slave mode, ACK received */
+#define TWI_STAT_TXDSL_ACK	0xC8
+
+/* 10bit Address, second part of address */
+/* Second Address byte+Write bit transmitted,ACK received */
+#define TWI_STAT_TX_SAW_ACK	0xD0
+/* Second Address byte+Write bit transmitted,ACK not received */
+#define TWI_STAT_TX_SAW_NAK	0xD8
+
+/* No relevant status infomation,INT_FLAG = 0 */
+#define TWI_STAT_IDLE		0xF8
+
+#endif
Index: arch/arm/include/asm/arch-sunxi/key.h
===================================================================
--- /dev/null
+++ arch/arm/include/asm/arch-sunxi/key.h
@@ -0,0 +1,51 @@
+/*
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.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
+ */
+
+#ifndef _SUNXI_KEY_H
+#define _SUNXI_KEY_H
+
+struct sunxi_lradc {
+	u32 ctrl;         /* lradc control */
+	u32 intc;         /* interrupt control */
+	u32 ints;         /* interrupt status */
+	u32 data0;        /* lradc 0 data */
+	u32 data1;        /* lradc 1 data */
+};
+
+#define LRADC_EN                  0x1    /* LRADC enable */
+#define LRADC_SAMPLE_RATE         0x2    /* 32.25 Hz */
+#define LEVELB_VOL                0x2    /* 0x33(~1.6v) */
+#define LRADC_HOLD_EN             0x1    /* sample hold enable */
+#define KEY_MODE_SELECT           0x0    /* normal mode */
+
+#define ADC0_DATA_PENDING         (1 << 0)    /* adc0 has data */
+#define ADC0_KEYDOWN_PENDING      (1 << 1)    /* key down */
+#define ADC0_HOLDKEY_PENDING      (1 << 2)    /* key hold */
+#define ADC0_ALRDY_HOLD_PENDING   (1 << 3)    /* key already hold */
+#define ADC0_KEYUP_PENDING        (1 << 4)    /* key up */
+
+int sunxi_key_init(void);
+u32 sunxi_read_key(void);
+
+#endif
Index: arch/arm/include/asm/arch-sunxi/mmc.h
===================================================================
--- /dev/null
+++ arch/arm/include/asm/arch-sunxi/mmc.h
@@ -0,0 +1,64 @@
+/*
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Aaron <leafy.myeh@allwinnertech.com>
+ *
+ * MMC register definition for allwinner sunxi platform.
+ *
+ * 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 _SUNXI_MMC_H
+#define _SUNXI_MMC_H
+
+struct sunxi_mmc {
+	u32 gctrl;		/* (0x00) SMC Global Control Register */
+	u32 clkcr;		/* (0x04) SMC Clock Control Register */
+	u32 timeout;		/* (0x08) SMC Time Out Register */
+	u32 width;		/* (0x0C) SMC Bus Width Register */
+	u32 blksz;		/* (0x10) SMC Block Size Register */
+	u32 bytecnt;		/* (0x14) SMC Byte Count Register */
+	u32 cmd;		/* (0x18) SMC Command Register */
+	u32 arg;		/* (0x1C) SMC Argument Register */
+	u32 resp0;		/* (0x20) SMC Response Register 0 */
+	u32 resp1;		/* (0x24) SMC Response Register 1 */
+	u32 resp2;		/* (0x28) SMC Response Register 2 */
+	u32 resp3;		/* (0x2C) SMC Response Register 3 */
+	u32 imask;		/* (0x30) SMC Interrupt Mask Register */
+	u32 mint;		/* (0x34) SMC Masked Interrupt Status Reg */
+	u32 rint;		/* (0x38) SMC Raw Interrupt Status Register */
+	u32 status;		/* (0x3C) SMC Status Register */
+	u32 ftrglevel;		/* (0x40) SMC FIFO Threshold Watermark Reg */
+	u32 funcsel;		/* (0x44) SMC Function Select Register */
+	u32 cbcr;		/* (0x48) SMC CIU Byte Count Register */
+	u32 bbcr;		/* (0x4C) SMC BIU Byte Count Register */
+	u32 dbgc;		/* (0x50) SMC Debug Enable Register */
+	u32 res0[11];		/* (0x54~0x7c) */
+	u32 dmac;		/* (0x80) SMC IDMAC Control Register */
+	u32 dlba;		/* (0x84) SMC IDMAC Descr List Base Addr Reg */
+	u32 idst;		/* (0x88) SMC IDMAC Status Register */
+	u32 idie;		/* (0x8C) SMC IDMAC Interrupt Enable Register */
+	u32 chda;		/* (0x90) */
+	u32 cbda;		/* (0x94) */
+	u32 res1[26];		/* (0x98~0xff) */
+	u32 fifo;		/* (0x100) SMC FIFO Access Address */
+};
+
+int sunxi_mmc_init(int sdc_no);
+#endif /* _SUNXI_MMC_H */
Index: arch/arm/include/asm/arch-sunxi/spl.h
===================================================================
--- /dev/null
+++ arch/arm/include/asm/arch-sunxi/spl.h
@@ -0,0 +1,36 @@
+/*
+ * This is a copy of omap3/spl.h:
+ *
+ * (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*/
+#define BOOT_DEVICE_MMC1	6
+#define BOOT_DEVICE_XIPWAIT	7
+#define BOOT_DEVICE_MMC2_2      0xFF
+#endif
Index: arch/arm/include/asm/arch-sunxi/sys_proto.h
===================================================================
--- /dev/null
+++ arch/arm/include/asm/arch-sunxi/sys_proto.h
@@ -0,0 +1,31 @@
+/*
+ * (C) Copyright 2007-2012
+ * Allwinner Technology Co., Ltd. <www.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
+ */
+
+#ifndef _SYS_PROTO_H_
+#define _SYS_PROTO_H_
+
+void sr32(u32 *, u32, u32, u32);
+void sdelay(unsigned long);
+
+#endif
Index: arch/arm/include/asm/arch-sunxi/timer.h
===================================================================
--- /dev/null
+++ arch/arm/include/asm/arch-sunxi/timer.h
@@ -0,0 +1,102 @@
+/*
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * Configuration settings for the Allwinner A10-evb board.
+ *
+ * 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 _SUNXI_TIMER_H_
+#define _SUNXI_TIMER_H_
+
+#ifndef __ASSEMBLY__
+
+/* General purpose timer */
+struct sunxi_timer {
+	u32 ctl;
+	u32 inter;
+	u32 val;
+	u8 res[4];
+};
+
+/* Audio video sync*/
+struct sunxi_avs {
+	u32 ctl;		/* 0x80 */
+	u32 cnt0;		/* 0x84 */
+	u32 cnt1;		/* 0x88 */
+	u32 div;		/* 0x8c */
+};
+
+/* 64 bit counter */
+struct sunxi_64cnt {
+	u32 ctl;		/* 0xa0 */
+	u32 lo;			/* 0xa4 */
+	u32 hi;			/* 0xa8 */
+};
+
+/* Watchdog */
+struct sunxi_wdog {
+	u32 ctl;		/* 0x90 */
+	u32 mode;		/* 0x94 */
+};
+
+/* Rtc */
+struct sunxi_rtc {
+	u32 ctl;		/* 0x100 */
+	u32 yymmdd;		/* 0x104 */
+	u32 hhmmss;		/* 0x108 */
+};
+
+/* Alarm */
+struct sunxi_alarm {
+	u32 ddhhmmss;		/* 0x10c */
+	u32 hhmmss;		/* 0x110 */
+	u32 en;			/* 0x114 */
+	u32 irqen;		/* 0x118 */
+	u32 irqsta;		/* 0x11c */
+};
+
+/* Timer general purpose register */
+struct sunxi_tgp {
+	u32 tgpd;
+};
+
+struct sunxi_timer_reg {
+	u32 tirqen;		/* 0x00 */
+	u32 tirqsta;		/* 0x04 */
+	u8 res1[8];
+	struct sunxi_timer timer[6];	/* We have 6 timers */
+	u8 res2[16];
+	struct sunxi_avs avs;
+	struct sunxi_wdog wdog;
+	u8 res3[8];
+	struct sunxi_64cnt cnt64;
+	u8 res4[0x58];
+	struct sunxi_rtc rtc;
+	struct sunxi_alarm alarm;
+	struct sunxi_tgp tgp[4];
+	u8 res5[8];
+	u32 cpu_cfg;
+};
+
+#endif /* __ASSEMBLY__ */
+
+#endif
Index: board/sunxi/board.c
===================================================================
--- /dev/null
+++ board/sunxi/board.c
@@ -0,0 +1,114 @@
+/*
+ * (C) Copyright 2012-2013 Henrik Nordstrom <henrik@henriknordstrom.net>
+ *
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * Some board init for the Allwinner A10-evb board.
+ *
+ * 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/arch/dram.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/mmc.h>
+#include <axp209.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* add board specific code here */
+int board_init(void)
+{
+	gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100);
+
+	return 0;
+}
+
+#ifdef CONFIG_DISPLAY_BOARDINFO
+int checkboard(void)
+{
+	printf("Board: %s\n", CONFIG_SYS_BOARD_NAME);
+
+	return 0;
+}
+#endif
+
+int dram_init(void)
+{
+	gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, 1 << 30);
+
+	return 0;
+}
+
+#ifdef CONFIG_GENERIC_MMC
+int board_mmc_init(bd_t *bis)
+{
+	sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT);
+
+	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
Index: board/sunxi/dram_a13_mid.c
===================================================================
--- /dev/null
+++ board/sunxi/dram_a13_mid.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 = 408,
+	.type = 3,
+	.rank_num = 1,
+	.density = 2048,
+	.io_width = 8,
+	.bus_width = 16,
+	.cas = 9,
+	.zq = 123,
+	.odt_en = 1,
+	.size = 512,
+	.tpr0 = 0x42d899b7,
+	.tpr1 = 0xa090,
+	.tpr2 = 0x22a00,
+	.tpr3 = 0,
+	.tpr4 = 0,
+	.tpr5 = 0,
+	.emr1 = 0x4,
+	.emr2 = 0x10,
+	.emr3 = 0,
+};
+
+int sunxi_dram_init(void)
+{
+	return dramc_init(&dram_para);
+}
Index: board/sunxi/dram_a13_oli_micro.c
===================================================================
--- /dev/null
+++ board/sunxi/dram_a13_oli_micro.c
@@ -0,0 +1,32 @@
+/* this file is generated, don't edit it yourself */
+
+#include <common.h>
+#include <asm/arch/dram.h>
+
+static struct dram_para dram_para = {
+	.clock = 408,
+	.type = 3,
+	.rank_num = 1,
+	.density = 2048,
+	.io_width = 16,
+	.bus_width = 16,
+	.cas = 9,
+	.zq = 123,
+	.odt_en = 0,
+	.size = 256,
+	.tpr0 = 0x42d899b7,
+	.tpr1 = 0xa090,
+	.tpr2 = 0x22a00,
+	.tpr3 = 0,
+	.tpr4 = 0,
+	.tpr5 = 0,
+	.emr1 = 0,
+	.emr2 = 0x10,
+	.emr3 = 0,
+
+};
+
+int sunxi_dram_init(void)
+{
+	return dramc_init(&dram_para);
+}
Index: board/sunxi/dram_a13_olinuxino.c
===================================================================
--- /dev/null
+++ board/sunxi/dram_a13_olinuxino.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 = 408,
+	.type = 3,
+	.rank_num = 1,
+	.density = 2048,
+	.io_width = 8,
+	.bus_width = 16,
+	.cas = 9,
+	.zq = 123,
+	.odt_en = 0,
+	.size = 512,
+	.tpr0 = 0x42d899b7,
+	.tpr1 = 0xa090,
+	.tpr2 = 0x22a00,
+	.tpr3 = 0,
+	.tpr4 = 0,
+	.tpr5 = 0,
+	.emr1 = 0,
+	.emr2 = 0x10,
+	.emr3 = 0,
+};
+
+int sunxi_dram_init(void)
+{
+	return dramc_init(&dram_para);
+}
Index: board/sunxi/dram_cubieboard_512.c
===================================================================
--- /dev/null
+++ board/sunxi/dram_cubieboard_512.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 = 2048,
+	.io_width = 16,
+	.bus_width = 32,
+	.cas = 6,
+	.zq = 123,
+	.odt_en = 0,
+	.size = 512,
+	.tpr0 = 0x30926692,
+	.tpr1 = 0x1090,
+	.tpr2 = 0x1a0c8,
+	.tpr3 = 0,
+	.tpr4 = 0,
+	.tpr5 = 0,
+	.emr1 = 0,
+	.emr2 = 0,
+	.emr3 = 0,
+};
+
+int sunxi_dram_init(void)
+{
+	return dramc_init(&dram_para);
+}
Index: board/sunxi/dram_cubieboard.c
===================================================================
--- /dev/null
+++ board/sunxi/dram_cubieboard.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 = 32,
+	.cas = 6,
+	.zq = 123,
+	.odt_en = 0,
+	.size = 1024,
+	.tpr0 = 0x30926692,
+	.tpr1 = 0x1090,
+	.tpr2 = 0x1a0c8,
+	.tpr3 = 0,
+	.tpr4 = 0,
+	.tpr5 = 0,
+	.emr1 = 0,
+	.emr2 = 0,
+	.emr3 = 0,
+};
+
+int sunxi_dram_init(void)
+{
+	return dramc_init(&dram_para);
+}
Index: board/sunxi/dram_hackberry.c
===================================================================
--- /dev/null
+++ board/sunxi/dram_hackberry.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 = 408,
+	.type = 3,
+	.rank_num = 1,
+	.density = 4096,
+	.io_width = 16,
+	.bus_width = 32,
+	.cas = 6,
+	.zq = 123,
+	.odt_en = 1,
+	.size = 1024,
+	.tpr0 = 0x30926692,
+	.tpr1 = 0x1090,
+	.tpr2 = 0x1a0c8,
+	.tpr3 = 0,
+	.tpr4 = 0,
+	.tpr5 = 0,
+	.emr1 = 0,
+	.emr2 = 0,
+	.emr3 = 0,
+};
+
+int sunxi_dram_init(void)
+{
+	return dramc_init(&dram_para);
+}
Index: board/sunxi/dram_hyundai_a7hd.c
===================================================================
--- /dev/null
+++ board/sunxi/dram_hyundai_a7hd.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 = 360,
+	.type = 3,
+	.rank_num = 1,
+	.density = 2048,
+	.io_width = 8,
+	.bus_width = 32,
+	.cas = 6,
+	.zq = 123,
+	.odt_en = 0,
+	.size = 1024,
+	.tpr0 = 0x30926692,
+	.tpr1 = 0x1090,
+	.tpr2 = 0x1a0c8,
+	.tpr3 = 0,
+	.tpr4 = 0,
+	.tpr5 = 0,
+	.emr1 = 0,
+	.emr2 = 0,
+	.emr3 = 0,
+};
+
+int sunxi_dram_init(void)
+{
+	return dramc_init(&dram_para);
+}
Index: board/sunxi/dram_mele_a1000.c
===================================================================
--- /dev/null
+++ board/sunxi/dram_mele_a1000.c
@@ -0,0 +1,24 @@
+/* this file is generated, don't edit it yourself */
+
+#include <common.h>
+#include <asm/arch/dram.h>
+
+static struct dram_para dram_para = {
+	.clock = 360,
+	.type = 3,
+	.rank_num = 1,
+	.density = 2048,
+	.io_width = 16,
+	.bus_width = 32,
+	.cas = 6,
+	.zq = 123,
+	.size = 512,
+	.tpr0 = 0x30926692,
+	.tpr1 = 0x1090,
+	.tpr2 = 0x1a0c8,
+};
+
+int sunxi_dram_init(void)
+{
+	return dramc_init(&dram_para);
+}
Index: board/sunxi/dram_mele_a3700.c
===================================================================
--- /dev/null
+++ board/sunxi/dram_mele_a3700.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 = 360,
+	.type = 3,
+	.rank_num = 1,
+	.density = 2048,
+	.io_width = 8,
+	.bus_width = 32,
+	.cas = 6,
+	.zq = 123,
+	.odt_en = 0,
+	.size = 1024,
+	.tpr0 = 0x30926692,
+	.tpr1 = 0x1090,
+	.tpr2 = 0x1a0c8,
+	.tpr3 = 0,
+	.tpr4 = 0,
+	.tpr5 = 0,
+	.emr1 = 0,
+	.emr2 = 0,
+	.emr3 = 0,
+};
+
+int sunxi_dram_init(void)
+{
+	return dramc_init(&dram_para);
+}
Index: board/sunxi/dram_mini_x.c
===================================================================
--- /dev/null
+++ board/sunxi/dram_mini_x.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 = 360,
+	.type = 3,
+	.rank_num = 1,
+	.density = 2048,
+	.io_width = 16,
+	.bus_width = 32,
+	.cas = 6,
+	.zq = 123,
+	.odt_en = 0,
+	.size = 512,
+	.tpr0 = 0x30926692,
+	.tpr1 = 0x1090,
+	.tpr2 = 0x1a0c8,
+	.tpr3 = 0,
+	.tpr4 = 0,
+	.tpr5 = 0,
+	.emr1 = 0,
+	.emr2 = 0,
+	.emr3 = 0,
+};
+
+int sunxi_dram_init(void)
+{
+	return dramc_init(&dram_para);
+}
Index: board/sunxi/dram_mk802.c
===================================================================
--- /dev/null
+++ board/sunxi/dram_mk802.c
@@ -0,0 +1,24 @@
+/* this file is generated, don't edit it yourself */
+
+#include <common.h>
+#include <asm/arch/dram.h>
+
+static struct dram_para dram_para = {
+	.clock = 360,
+	.type = 3,
+	.rank_num = 1,
+	.density = 2048,
+	.io_width = 16,
+	.bus_width = 32,
+	.cas = 6,
+	.zq = 123,
+	.size = 512,
+	.tpr0 = 0x30926692,
+	.tpr1 = 0x1090,
+	.tpr2 = 0x1a0c8,
+};
+
+int sunxi_dram_init(void)
+{
+	return dramc_init(&dram_para);
+}
Index: board/sunxi/dram_mk802ii.c
===================================================================
--- /dev/null
+++ board/sunxi/dram_mk802ii.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 = 408,
+	.type = 3,
+	.rank_num = 1,
+	.density = 4096,
+	.io_width = 16,
+	.bus_width = 32,
+	.cas = 6,
+	.zq = 123,
+	.odt_en = 0,
+	.size = 1024,
+	.tpr0 = 0x30926692,
+	.tpr1 = 0x1090,
+	.tpr2 = 0x1a0c8,
+	.tpr3 = 0,
+	.tpr4 = 0,
+	.tpr5 = 0,
+	.emr1 = 0x4,
+	.emr2 = 0,
+	.emr3 = 0,
+};
+
+int sunxi_dram_init(void)
+{
+	return dramc_init(&dram_para);
+}
Index: board/sunxi/dram_r7dongle.c
===================================================================
--- /dev/null
+++ board/sunxi/dram_r7dongle.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 = 384,
+	.type = 3,
+	.rank_num = 1,
+	.density = 4096,
+	.io_width = 16,
+	.bus_width = 32,
+	.cas = 9,
+	.zq = 123,
+	.odt_en = 0,
+	.size = 1024,
+	.tpr0 = 0x42d899b7,
+	.tpr1 = 0xa090,
+	.tpr2 = 0x22a00,
+	.tpr3 = 0,
+	.tpr4 = 0,
+	.tpr5 = 0,
+	.emr1 = 0x04,
+	.emr2 = 0x10,
+	.emr3 = 0,
+};
+
+int sunxi_dram_init(void)
+{
+	return DRAMC_init(&dram_para);
+}
Index: board/sunxi/Makefile
===================================================================
--- /dev/null
+++ board/sunxi/Makefile
@@ -0,0 +1,63 @@
+#
+# (C) Copyriht 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
+#
+# Based on some other board Makefile
+#
+# (C) Copyright 2000-2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# 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 $(TOPDIR)/config.mk
+
+LIB	:= $(obj)lib$(BOARD).o
+
+COBJS-y	:= board.o
+COBJS-$(CONFIG_A13_OLINUXINO)	+= dram_a13_olinuxino.o
+COBJS-$(CONFIG_A13_OLINUXINOM)	+= dram_a13_oli_micro.o
+COBJS-$(CONFIG_A13_MID)		+= dram_a13_mid.o
+COBJS-$(CONFIG_CUBIEBOARD)	+= dram_cubieboard.o
+COBJS-$(CONFIG_CUBIEBOARD_512)	+= dram_cubieboard_512.o
+COBJS-$(CONFIG_HACKBERRY)	+= dram_hackberry.o
+COBJS-$(CONFIG_MELE_A1000)	+= dram_mele_a1000.o
+COBJS-$(CONFIG_MINI_X)		+= dram_mini_x.o
+COBJS-$(CONFIG_A7HD)		+= dram_hyundai_a7hd.o
+COBJS-$(CONFIG_MK802)		+= dram_mk802.o
+COBJS-$(CONFIG_MK802II)		+= dram_mk802ii.o
+COBJS-$(CONFIG_MELE_A3700)	+= dram_mele_a3700.o
+COBJS-$(CONFIG_R7DONGLE)	+= dram_r7dongle.o
+
+COBJS	:= $(COBJS-y)
+SRCS 	:= $(COBJS:.o=.c)
+OBJS 	:= $(addprefix $(obj),$(COBJS))
+
+all:	$(LIB)
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+########################################################################
Index: boards.cfg
===================================================================
--- boards.cfg.orig
+++ boards.cfg
@@ -316,6 +316,23 @@ dalmore                      arm
 colibri_t20_iris             arm         armv7:arm720t colibri_t20_iris  toradex        tegra20
 u8500_href                   arm         armv7       u8500               st-ericsson    u8500
 snowball                     arm         armv7       snowball               st-ericsson    u8500
+A13-OLinuXino                arm         armv7       sunxi               -              sunxi       sun5i:A13_OLINUXINO,SPL
+A13-OLinuXinoM               arm         armv7       sunxi               -              sunxi       sun5i:A13_OLINUXINOM,SPL,NO_AXP
+A13_MID                      arm         armv7       sunxi               -              sunxi       sun5i:A13_MID,SPL
+Cubieboard                   arm         armv7       sunxi               -              sunxi       sun4i:CUBIEBOARD,SPL
+Cubieboard_512               arm         armv7       sunxi               -              sunxi       sun4i:CUBIEBOARD_512,SPL
+Hackberry                    arm         armv7       sunxi               -              sunxi       sun4i:HACKBERRY,SPL
+Hyundai_A7HD                 arm         armv7       sunxi               -              sunxi       sun4i:A7HD,SPL
+Mele_A1000                   arm         armv7       sunxi               -              sunxi       sun4i:MELE_A1000,SPL
+Mele_A3700                   arm         armv7       sunxi               -              sunxi       sun4i:MELE_A3700,SPL
+Mini-X                       arm         armv7       sunxi               -              sunxi       sun4i:MINI_X,SPL
+sun4i                        arm         armv7       sunxi               -              sunxi       sun4i
+sun4i_sdcon                  arm         armv7       sunxi               -              sunxi       sun4i:UART0_PORT_F
+sun5i                        arm         armv7       sunxi               -              sunxi       sun5i
+sun5i_sdcon                  arm         armv7       sunxi               -              sunxi       sun5i:UART0_PORT_F
+mk802                        arm         armv7       sunxi               -              sunxi       sun4i:MK802,SPL
+mk802ii                      arm         armv7       sunxi               -              sunxi       sun4i:MK802II,SPL
+r7-tv-dongle                 arm         armv7       sunxi	  	 -              sunxi       sun5i:R7DONGLE,SPL,AXP152
 kzm9g                        arm         armv7       kzm9g               kmc            rmobile
 armadillo-800eva             arm         armv7       armadillo-800eva    atmark-techno  rmobile
 zynq                         arm         armv7       zynq                xilinx         zynq
Index: drivers/gpio/Makefile
===================================================================
--- drivers/gpio/Makefile.orig
+++ drivers/gpio/Makefile
@@ -47,6 +47,7 @@ COBJS-$(CONFIG_OMAP_GPIO)	+= omap_gpio.o
 COBJS-$(CONFIG_DB8500_GPIO)	+= db8500_gpio.o
 COBJS-$(CONFIG_BCM2835_GPIO)	+= bcm2835_gpio.o
 COBJS-$(CONFIG_S3C2440_GPIO)	+= s3c2440_gpio.o
+COBJS-$(CONFIG_SUNXI_GPIO)	+= sunxi_gpio.o
 
 COBJS	:= $(COBJS-y)
 SRCS 	:= $(COBJS:.o=.c)
Index: drivers/gpio/sunxi_gpio.c
===================================================================
--- /dev/null
+++ drivers/gpio/sunxi_gpio.c
@@ -0,0 +1,120 @@
+/*
+ * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
+ *
+ * Based on earlier arch/arm/cpu/armv7/sunxi/gpio.c:
+ *
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.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/gpio.h>
+
+static int sunxi_gpio_output(u32 pin, u32 val)
+{
+	u32 dat;
+	u32 bank = GPIO_BANK(pin);
+	u32 num = GPIO_NUM(pin);
+	struct sunxi_gpio *pio =
+	    &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank];
+
+	dat = readl(&pio->dat);
+	if (val)
+		dat |= 1 << num;
+	else
+		dat &= ~(1 << num);
+
+	writel(dat, &pio->dat);
+
+	return 0;
+}
+
+static int sunxi_gpio_input(u32 pin)
+{
+	u32 dat;
+	u32 bank = GPIO_BANK(pin);
+	u32 num = GPIO_NUM(pin);
+	struct sunxi_gpio *pio =
+	    &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank];
+
+	dat = readl(&pio->dat);
+	dat >>= num;
+
+	return dat & 0x1;
+}
+
+int gpio_request(unsigned gpio, const char *label)
+{
+	return 0;
+}
+
+int gpio_free(unsigned gpio)
+{
+	return 0;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+	sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_INPUT);
+
+	return sunxi_gpio_input(gpio);
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+	sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT);
+
+	return sunxi_gpio_output(gpio, value);
+}
+
+int gpio_get_value(unsigned gpio)
+{
+	return sunxi_gpio_input(gpio);
+}
+
+int gpio_set_value(unsigned gpio, int value)
+{
+	return sunxi_gpio_output(gpio, value);
+}
+
+int name_to_gpio(const char *name)
+{
+	int group = 0;
+	int groupsize = 9 * 32;
+	long pin;
+	const char *eptr;
+	if (*name == 'P' || *name == 'p')
+		name++;
+	if (*name >= 'A') {
+		group = *name - (*name > 'a' ? 'a' : 'A');
+		groupsize = 32;
+		name++;
+	}
+
+	pin = simple_strtol(name, &eptr, 10);
+	if (!*name || *eptr)
+		return -1;
+	if (pin < 0 || pin > groupsize || group >= 9)
+		return -1;
+	return group * 32 + pin;
+}
Index: drivers/i2c/Makefile
===================================================================
--- drivers/i2c/Makefile.orig
+++ drivers/i2c/Makefile
@@ -46,6 +46,7 @@ COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c
 COBJS-$(CONFIG_U8500_I2C) += u8500_i2c.o
 COBJS-$(CONFIG_SH_I2C) += sh_i2c.o
 COBJS-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
+COBJS-$(CONFIG_SUNXI_I2C) += sunxi_i2c.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
Index: drivers/i2c/sunxi_i2c.c
===================================================================
--- /dev/null
+++ drivers/i2c/sunxi_i2c.c
@@ -0,0 +1,276 @@
+/*
+ * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
+ *
+ * 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 <i2c.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/i2c.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/clock.h>
+
+static struct i2c __attribute__ ((section(".data"))) *i2c_base =
+	(struct i2c *)0x1c2ac00;
+
+void i2c_init(int speed, int slaveaddr)
+{
+	int timeout = 0x2ff;
+
+	sunxi_gpio_set_cfgpin(SUNXI_GPB(0), 2);
+	sunxi_gpio_set_cfgpin(SUNXI_GPB(1), 2);
+	clock_twi_onoff(0, 1);
+
+	/* Enable the i2c bus */
+	writel(TWI_CTL_BUSEN, &i2c_base->ctl);
+
+	/* 400KHz operation M=2, N=1, 24MHz APB clock */
+	writel(TWI_CLK_DIV(2, 1), &i2c_base->clkr);
+	writel(TWI_SRST_SRST, &i2c_base->reset);
+
+	while ((readl(&i2c_base->reset) & TWI_SRST_SRST) && timeout--);
+}
+
+int i2c_probe(uchar chip)
+{
+	return -1;
+}
+
+static int i2c_wait_ctl(int mask, int state)
+{
+	int timeout = 0x2ff;
+	int value = state ? mask : 0;
+
+	debug("i2c_wait_ctl(%x == %x), ctl=%x, status=%x\n", mask, value,
+	      i2c_base->ctl, i2c_base->status);
+
+	while (((readl(&i2c_base->ctl) & mask) != value) && timeout-- > 0);
+
+	debug("i2c_wait_ctl(), timeout=%d, ctl=%x, status=%x\n", timeout,
+	      i2c_base->ctl, i2c_base->status);
+
+	if (timeout != 0)
+		return 0;
+	else
+		return -1;
+}
+
+static void i2c_clear_irq(void)
+{
+	writel(readl(&i2c_base->ctl) & ~TWI_CTL_INTFLG, &i2c_base->ctl);
+}
+
+static int i2c_wait_irq(void)
+{
+	return i2c_wait_ctl(TWI_CTL_INTFLG, 1);
+}
+
+static int i2c_wait_status(int status)
+{
+	int timeout = 0x2ff;
+
+	while (readl(&i2c_base->status) != status && timeout-- > 0);
+
+	if (timeout != 0)
+		return 0;
+	else
+		return -1;
+}
+
+static int i2c_wait_irq_status(int status)
+{
+	if (i2c_wait_irq() != 0)
+		return -1;
+
+	if (readl(&i2c_base->status) != status)
+		return -1;
+
+	return 0;
+}
+
+static int i2c_wait_bus_idle(void)
+{
+	int timeout = 0x2ff;
+
+	while (readl(&i2c_base->lctl) != 0x3a && timeout-- > 0);
+
+	if (timeout != 0)
+		return 0;
+	else
+		return -1;
+}
+
+static int i2c_stop(void)
+{
+	u32 ctl;
+
+	ctl = readl(&i2c_base->ctl) & 0xc0;
+	ctl |= TWI_CTL_STP;
+
+	writel(ctl, &i2c_base->ctl);
+
+	/* dummy to delay one I/O operation to make sure it's started */
+	(void)readl(&i2c_base->ctl);
+
+	if (i2c_wait_ctl(TWI_CTL_STP, 0) != 0)
+		return -1;
+	if (i2c_wait_status(TWI_STAT_IDLE))
+		return -1;
+	if (i2c_wait_bus_idle() != 0)
+		return -1;
+
+	return 0;
+}
+
+static int i2c_send_data(u8 data, u8 status)
+{
+	debug("i2c_write(%02x, %x), ctl=%x, status=%x\n", data, status,
+	      i2c_base->ctl, i2c_base->status);
+
+	writel(data, &i2c_base->data);
+	i2c_clear_irq();
+
+	if (i2c_wait_irq_status(status) != 0)
+		return -1;
+
+	return 0;
+}
+
+static int i2c_start(int status)
+{
+	u32 ctl;
+
+	debug("i2c_start(%x), ctl=%x, status=%x\n", status, i2c_base->ctl,
+	      i2c_base->status);
+	/* Check that the controller is idle */
+	if (status == TWI_STAT_TX_STA
+	    && readl(&i2c_base->status) != TWI_STAT_IDLE) {
+		return -1;
+	}
+
+	writel(0, &i2c_base->efr);
+
+	/* Send start */
+	ctl = readl(&i2c_base->ctl);
+	ctl |= TWI_CTL_STA;	/* Set start bit */
+	ctl &= ~TWI_CTL_INTFLG;	/* Clear int flag */
+	writel(ctl, &i2c_base->ctl);
+
+	if (i2c_wait_ctl(TWI_CTL_STA, 0) != 0)
+		return -1;
+	if (i2c_wait_irq_status(status) != 0)
+		return -1;
+
+	return 0;
+}
+
+int i2c_do_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+	u32 status;
+	u32 ctl;
+
+	if (i2c_start(TWI_STAT_TX_STA) != 0)
+		return -1;
+
+	/* Send chip address */
+	if (i2c_send_data(chip << 1 | 0, TWI_STAT_TX_AW_ACK) != 0)
+		return -1;
+
+	/* Send data address */
+	if (i2c_send_data(addr, TWI_STAT_TXD_ACK) != 0)
+		return -1;
+
+	/* Send restart for read */
+	if (i2c_start(TWI_STAT_TX_RESTA) != 0)
+		return -1;
+
+	/* Send chip address */
+	if (i2c_send_data(chip << 1 | 1, TWI_STAT_TX_AR_ACK) != 0)
+		return -1;
+
+	/* Set ACK mode */
+	ctl = readl(&i2c_base->ctl);
+	ctl |= TWI_CTL_ACK;
+	writel(ctl, &i2c_base->ctl);
+	status = TWI_STAT_RXD_ACK;
+
+	/* Read data */
+	while (len > 0) {
+		if (len == 1) {
+			/* Set NACK mode (last byte) */
+			ctl = readl(&i2c_base->ctl);
+			ctl &= ~TWI_CTL_ACK;
+			writel(ctl, &i2c_base->ctl);
+			status = TWI_STAT_RXD_NAK;
+		}
+
+		i2c_clear_irq();
+		if (i2c_wait_irq_status(status) != 0)
+			return -1;
+
+		*buffer++ = readl(&i2c_base->data);
+		len--;
+	}
+
+	return 0;
+}
+
+int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+	int rc = i2c_do_read(chip, addr, alen, buffer, len);
+
+	i2c_stop();
+
+	return rc;
+}
+
+static int i2c_do_write(uchar chip, uint addr, int alen, uchar *buffer,
+			int len)
+{
+	if (i2c_start(TWI_STAT_TX_STA) != 0)
+		return -1;
+
+	/* Send chip address */
+	if (i2c_send_data(chip << 1 | 0, TWI_STAT_TX_AW_ACK) != 0)
+		return -1;
+
+	/* Send data address */
+	if (i2c_send_data(addr, TWI_STAT_TXD_ACK) != 0)
+		return -1;
+
+	/* Send data */
+	while (len > 0) {
+		if (i2c_send_data(*buffer++, TWI_STAT_TXD_ACK) != 0)
+			return -1;
+		len--;
+	}
+
+	return 0;
+}
+
+int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
+{
+	int rc = i2c_do_write(chip, addr, alen, buffer, len);
+
+	i2c_stop();
+
+	return rc;
+}
Index: drivers/mmc/Makefile
===================================================================
--- drivers/mmc/Makefile.orig
+++ drivers/mmc/Makefile
@@ -49,6 +49,7 @@ COBJS-$(CONFIG_SH_MMCIF) += sh_mmcif.o
 COBJS-$(CONFIG_TEGRA_MMC) += tegra_mmc.o
 COBJS-$(CONFIG_DWMMC) += dw_mmc.o
 COBJS-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o
+COBJS-$(CONFIG_MMC_SUNXI) += sunxi_mmc.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
Index: drivers/mmc/sunxi_mmc.c
===================================================================
--- /dev/null
+++ drivers/mmc/sunxi_mmc.c
@@ -0,0 +1,665 @@
+/*
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Aaron <leafy.myeh@allwinnertech.com>
+ *
+ * MMC driver for allwinner sunxi platform.
+ *
+ * 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/cpu.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mmc.h>
+#include <malloc.h>
+#include <mmc.h>
+
+static void dumphex32(char *name, char *base, int len)
+{
+	__u32 i;
+
+	debug("dump %s registers:", name);
+	for (i = 0; i < len; i += 4) {
+		if (!(i & 0xf))
+			debug("\n0x%p : ", base + i);
+		debug("0x%08x ", readl(base + i));
+	}
+	debug("\n");
+}
+
+static void dumpmmcreg(struct sunxi_mmc *reg)
+{
+	debug("dump mmc registers:\n");
+	debug("gctrl     0x%08x\n", reg->gctrl);
+	debug("clkcr     0x%08x\n", reg->clkcr);
+	debug("timeout   0x%08x\n", reg->timeout);
+	debug("width     0x%08x\n", reg->width);
+	debug("blksz     0x%08x\n", reg->blksz);
+	debug("bytecnt   0x%08x\n", reg->bytecnt);
+	debug("cmd       0x%08x\n", reg->cmd);
+	debug("arg       0x%08x\n", reg->arg);
+	debug("resp0     0x%08x\n", reg->resp0);
+	debug("resp1     0x%08x\n", reg->resp1);
+	debug("resp2     0x%08x\n", reg->resp2);
+	debug("resp3     0x%08x\n", reg->resp3);
+	debug("imask     0x%08x\n", reg->imask);
+	debug("mint      0x%08x\n", reg->mint);
+	debug("rint      0x%08x\n", reg->rint);
+	debug("status    0x%08x\n", reg->status);
+	debug("ftrglevel 0x%08x\n", reg->ftrglevel);
+	debug("funcsel   0x%08x\n", reg->funcsel);
+	debug("dmac      0x%08x\n", reg->dmac);
+	debug("dlba      0x%08x\n", reg->dlba);
+	debug("idst      0x%08x\n", reg->idst);
+	debug("idie      0x%08x\n", reg->idie);
+}
+
+struct sunxi_mmc_des {
+	u32 reserved1_1:1;
+	u32 dic:1;		/* disable interrupt on completion */
+	u32 last_des:1;		/* 1-this data buffer is the last buffer */
+	u32 first_des:1;		/* 1-data buffer is the first buffer,
+				   0-data buffer contained in the next
+				   descriptor is 1st buffer */
+	u32 des_chain:1;	/* 1-the 2nd address in the descriptor is the
+				   next descriptor address */
+	u32 end_of_ring:1;	/* 1-last descriptor flag when using dual
+				   data buffer in descriptor */
+	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 */
+#if defined 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
+#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;
+};
+
+struct sunxi_mmc_host {
+	unsigned mmc_no;
+	uint32_t *mclkreg;
+	unsigned database;
+	unsigned fatal_err;
+	unsigned mod_clk;
+	struct sunxi_mmc *reg;
+	struct sunxi_mmc_des *pdes;
+};
+
+/* support 4 mmc hosts */
+struct mmc mmc_dev[4];
+struct sunxi_mmc_host mmc_host[4];
+
+static int mmc_resource_init(int sdc_no)
+{
+	struct sunxi_mmc_host *mmchost = &mmc_host[sdc_no];
+	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+	debug("init mmc %d resource\n", sdc_no);
+
+	switch (sdc_no) {
+	case 0:
+		mmchost->reg = (struct sunxi_mmc *)SUNXI_MMC0_BASE;
+		mmchost->mclkreg = &ccm->sd0_clk_cfg;
+		break;
+	case 1:
+		mmchost->reg = (struct sunxi_mmc *)SUNXI_MMC1_BASE;
+		mmchost->mclkreg = &ccm->sd1_clk_cfg;
+		break;
+	case 2:
+		mmchost->reg = (struct sunxi_mmc *)SUNXI_MMC2_BASE;
+		mmchost->mclkreg = &ccm->sd2_clk_cfg;
+		break;
+	case 3:
+		mmchost->reg = (struct sunxi_mmc *)SUNXI_MMC3_BASE;
+		mmchost->mclkreg = &ccm->sd3_clk_cfg;
+		break;
+	default:
+		printf("Wrong mmc number %d\n", sdc_no);
+		return -1;
+	}
+	mmchost->database = (unsigned int)mmchost->reg + 0x100;
+	mmchost->mmc_no = sdc_no;
+
+	return 0;
+}
+
+static int mmc_clk_io_on(int sdc_no)
+{
+	unsigned int rval;
+	unsigned int pll5_clk;
+	unsigned int divider;
+	struct sunxi_mmc_host *mmchost = &mmc_host[sdc_no];
+	static struct sunxi_gpio *gpio_c =
+	    &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[SUNXI_GPIO_C];
+	static struct sunxi_gpio *gpio_f =
+	    &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[SUNXI_GPIO_F];
+#if CONFIG_MMC1_PG
+	static struct sunxi_gpio *gpio_g =
+	    &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[SUNXI_GPIO_G];
+#endif
+	static struct sunxi_gpio *gpio_h =
+	    &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[SUNXI_GPIO_H];
+	static struct sunxi_gpio *gpio_i =
+	    &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[SUNXI_GPIO_I];
+	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+	debug("init mmc %d clock and io\n", sdc_no);
+
+	/* config gpio */
+	switch (sdc_no) {
+	case 0:
+		/* D1-PF0, D0-PF1, CLK-PF2, CMD-PF3, D3-PF4, D4-PF5 */
+		writel(0x222222, &gpio_f->cfg[0]);
+		writel(0x555, &gpio_f->pull[0]);
+		writel(0xaaa, &gpio_f->drv[0]);
+		break;
+
+	case 1:
+#if CONFIG_MMC1_PG
+		/* PG0-CMD, PG1-CLK, PG2~5-D0~3 : 4 */
+		writel(0x444444, &gpio_g->cfg[0]);
+		writel(0x555, &gpio_g->pull[0]);
+		writel(0xaaa, &gpio_g->drv[0]);
+#else
+		/* PH22-CMD, PH23-CLK, PH24~27-D0~D3 : 5 */
+		writel(0x55 << 24, &gpio_h->cfg[2]);
+		writel(0x5555, &gpio_h->cfg[3]);
+		writel(0x555 << 12, &gpio_h->pull[1]);
+		writel(0xaaa << 12, &gpio_h->drv[1]);
+#endif
+		break;
+
+	case 2:
+		/* CMD-PC6, CLK-PC7, D0-PC8, D1-PC9, D2-PC10, D3-PC11 */
+		writel(0x33 << 24, &gpio_c->cfg[0]);
+		writel(0x3333, &gpio_c->cfg[1]);
+		writel(0x555 << 12, &gpio_c->pull[0]);
+		writel(0xaaa << 12, &gpio_c->drv[0]);
+		break;
+
+	case 3:
+		/* PI4-CMD, PI5-CLK, PI6~9-D0~D3 : 2 */
+		writel(0x2222 << 16, &gpio_i->cfg[0]);
+		writel(0x22, &gpio_i->cfg[1]);
+		writel(0x555 << 8, &gpio_i->pull[0]);
+		writel(0x555 << 8, &gpio_i->drv[0]);
+		break;
+
+	default:
+		return -1;
+	}
+
+	/* config ahb clock */
+	rval = readl(&ccm->ahb_gate0);
+	rval |= (1 << (8 + sdc_no));
+	writel(rval, &ccm->ahb_gate0);
+
+	/* config mod clock */
+	pll5_clk = clock_get_pll5();
+	if (pll5_clk > 400000000)
+		divider = 4;
+	else
+		divider = 3;
+	writel((1U << 31) | (2U << 24) | divider, mmchost->mclkreg);
+	mmchost->mod_clk = pll5_clk / (divider + 1);
+
+	dumphex32("ccmu", (char *)SUNXI_CCM_BASE, 0x100);
+	dumphex32("gpio", (char *)SUNXI_PIO_BASE, 0x100);
+	dumphex32("mmc", (char *)mmchost->reg, 0x100);
+	dumpmmcreg(mmchost->reg);
+
+	return 0;
+}
+
+static int mmc_update_clk(struct mmc *mmc)
+{
+	struct sunxi_mmc_host *mmchost = (struct sunxi_mmc_host *)mmc->priv;
+	unsigned int cmd;
+	unsigned timeout = 0xfffff;
+
+	cmd = (1U << 31) | (1 << 21) | (1 << 13);
+	writel(cmd, &mmchost->reg->cmd);
+	while ((readl(&mmchost->reg->cmd) & 0x80000000) && timeout--);
+	if (!timeout)
+		return -1;
+
+	writel(readl(&mmchost->reg->rint), &mmchost->reg->rint);
+
+	return 0;
+}
+
+static int mmc_config_clock(struct mmc *mmc, unsigned div)
+{
+	struct sunxi_mmc_host *mmchost = (struct sunxi_mmc_host *)mmc->priv;
+	unsigned rval = readl(&mmchost->reg->clkcr);
+
+	/*
+	 * CLKCREG[7:0]: divider
+	 * CLKCREG[16]:  on/off
+	 * CLKCREG[17]:  power save
+	 */
+	/* Disable Clock */
+	rval &= ~(1 << 16);
+	writel(rval, &mmchost->reg->clkcr);
+	if (mmc_update_clk(mmc))
+		return -1;
+
+	/* Change Divider Factor */
+	rval &= ~(0xFF);
+	rval |= div;
+	writel(rval, &mmchost->reg->clkcr);
+	if (mmc_update_clk(mmc))
+		return -1;
+	/* Re-enable Clock */
+	rval |= (1 << 16);
+	writel(rval, &mmchost->reg->clkcr);
+
+	if (mmc_update_clk(mmc))
+		return -1;
+
+	return 0;
+}
+
+static void mmc_set_ios(struct mmc *mmc)
+{
+	struct sunxi_mmc_host *mmchost = (struct sunxi_mmc_host *)mmc->priv;
+	unsigned int clkdiv = 0;
+
+	debug("set ios: bus_width: %x, clock: %d, mod_clk\n", mmc->bus_width,
+	       mmc->clock, mmchost->mod_clk);
+
+	/* Change clock first */
+	clkdiv = (mmchost->mod_clk + (mmc->clock >> 1)) / mmc->clock / 2;
+	if (mmc->clock)
+		if (mmc_config_clock(mmc, clkdiv)) {
+			mmchost->fatal_err = 1;
+			return;
+		}
+
+	/* Change bus width */
+	if (mmc->bus_width == 8)
+		writel(2, &mmchost->reg->width);
+	else if (mmc->bus_width == 4)
+		writel(1, &mmchost->reg->width);
+	else
+		writel(0, &mmchost->reg->width);
+}
+
+static int mmc_core_init(struct mmc *mmc)
+{
+	struct sunxi_mmc_host *mmchost = (struct sunxi_mmc_host *)mmc->priv;
+
+	/* Reset controller */
+	writel(0x7, &mmchost->reg->gctrl);
+
+	return 0;
+}
+
+static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data)
+{
+	struct sunxi_mmc_host *mmchost = (struct sunxi_mmc_host *)mmc->priv;
+	unsigned i;
+	unsigned byte_cnt = data->blocksize * data->blocks;
+	unsigned *buff;
+	unsigned timeout = 0xfffff;
+
+	if (data->flags & MMC_DATA_READ) {
+		buff = (unsigned int *)data->dest;
+		for (i = 0; i < (byte_cnt >> 2); i++) {
+			while (--timeout
+			       && (readl(&mmchost->reg->status) & (1 << 2)));
+			if (timeout <= 0)
+				goto out;
+			buff[i] = readl(mmchost->database);
+			timeout = 0xfffff;
+		}
+	} else {
+		buff = (unsigned int *)data->src;
+		for (i = 0; i < (byte_cnt >> 2); i++) {
+			while (--timeout
+				&& (readl(&mmchost->reg->status) & (1 << 3)));
+			if (timeout <= 0)
+				goto out;
+			writel(buff[i], mmchost->database);
+			timeout = 0xfffff;
+		}
+	}
+
+out:
+	if (timeout <= 0)
+		return -1;
+
+	return 0;
+}
+
+static int mmc_trans_data_by_dma(struct mmc *mmc, struct mmc_data *data)
+{
+	struct sunxi_mmc_host *mmchost = (struct sunxi_mmc_host *)mmc->priv;
+	struct sunxi_mmc_des *pdes = mmchost->pdes;
+	unsigned byte_cnt = data->blocksize * data->blocks;
+	unsigned char *buff;
+	unsigned des_idx = 0;
+	unsigned buff_frag_num = 0;
+	unsigned remain;
+	unsigned i, rval;
+
+	buff = data->flags & MMC_DATA_READ ?
+	    (unsigned char *)data->dest : (unsigned char *)data->src;
+	buff_frag_num = byte_cnt >> SDXC_DES_NUM_SHIFT;
+
+	remain = byte_cnt & (SDXC_DES_BUFFER_MAX_LEN - 1);
+	if (remain)
+		buff_frag_num++;
+	else
+		remain = SDXC_DES_BUFFER_MAX_LEN;
+
+	flush_cache((unsigned long)buff, (unsigned long)byte_cnt);
+	for (i = 0; i < buff_frag_num; i++, des_idx++) {
+		memset((void *)&pdes[des_idx], 0, sizeof(struct sunxi_mmc_des));
+		pdes[des_idx].des_chain = 1;
+		pdes[des_idx].own = 1;
+		pdes[des_idx].dic = 1;
+		if (buff_frag_num > 1 && i != buff_frag_num - 1)
+			pdes[des_idx].data_buf1_sz =
+			    (SDXC_DES_BUFFER_MAX_LEN -
+			     1) & SDXC_DES_BUFFER_MAX_LEN;
+		else
+			pdes[des_idx].data_buf1_sz = remain;
+
+		pdes[des_idx].buf_addr_ptr1 =
+		    (u32) buff + i * SDXC_DES_BUFFER_MAX_LEN;
+		if (i == 0)
+			pdes[des_idx].first_des = 1;
+
+		if (i == buff_frag_num - 1) {
+			pdes[des_idx].dic = 0;
+			pdes[des_idx].last_des = 1;
+			pdes[des_idx].end_of_ring = 1;
+			pdes[des_idx].buf_addr_ptr2 = 0;
+		} else {
+			pdes[des_idx].buf_addr_ptr2 = (u32)&pdes[des_idx + 1];
+		}
+		debug("frag %d, remain %d, des[%d](%08x): "
+			"[0] = %08x, [1] = %08x, [2] = %08x, [3] = %08x\n",
+			i, remain, des_idx, (u32)&pdes[des_idx],
+			(u32)((u32 *)&pdes[des_idx])[0],
+			(u32)((u32 *)&pdes[des_idx])[1],
+			(u32)((u32 *)&pdes[des_idx])[2],
+			(u32)((u32 *)&pdes[des_idx])[3]);
+	}
+	flush_cache((unsigned long)pdes,
+		    sizeof(struct sunxi_mmc_des) * (des_idx + 1));
+
+	/*
+	 * GCTRLREG
+	 * GCTRL[2]     : DMA reset
+	 * GCTRL[5]     : DMA enable
+	 *
+	 * IDMACREG
+	 * IDMAC[0]     : IDMA soft reset
+	 * IDMAC[1]     : IDMA fix burst flag
+	 * IDMAC[7]     : IDMA on
+	 *
+	 * IDIECREG
+	 * IDIE[0]      : IDMA transmit interrupt flag
+	 * IDIE[1]      : IDMA receive interrupt flag
+	 */
+	rval = readl(&mmchost->reg->gctrl);
+	/* Enable DMA */
+	writel(rval | (1 << 5) | (1 << 2), &mmchost->reg->gctrl);
+	/* Reset iDMA */
+	writel((1 << 0), &mmchost->reg->dmac);
+	/* Enable iDMA */
+	writel((1 << 1) | (1 << 7), &mmchost->reg->dmac);
+	rval = readl(&mmchost->reg->idie) & (~3);
+	if (data->flags & MMC_DATA_WRITE)
+		rval |= (1 << 0);
+	else
+		rval |= (1 << 1);
+	writel(rval, &mmchost->reg->idie);
+	writel((u32) pdes, &mmchost->reg->dlba);
+	writel((2U << 28) | (7 << 16) | 8, &mmchost->reg->ftrglevel);
+
+	return 0;
+}
+
+static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+			struct mmc_data *data)
+{
+	struct sunxi_mmc_host *mmchost = (struct sunxi_mmc_host *)mmc->priv;
+	unsigned int cmdval = 0x80000000;
+	signed int timeout = 0;
+	int error = 0;
+	unsigned int status = 0;
+	unsigned int usedma = 0;
+	unsigned int bytecnt = 0;
+
+	if (mmchost->fatal_err)
+		return -1;
+	if (cmd->resp_type & MMC_RSP_BUSY)
+		debug("mmc cmd %d check rsp busy\n", cmd->cmdidx);
+	if (cmd->cmdidx == 12)
+		return 0;
+
+	/*
+	 * CMDREG
+	 * CMD[5:0]     : Command index
+	 * CMD[6]       : Has response
+	 * CMD[7]       : Long response
+	 * CMD[8]       : Check response CRC
+	 * CMD[9]       : Has data
+	 * CMD[10]      : Write
+	 * CMD[11]      : Steam mode
+	 * CMD[12]      : Auto stop
+	 * CMD[13]      : Wait previous over
+	 * CMD[14]      : About cmd
+	 * CMD[15]      : Send initialization
+	 * CMD[21]      : Update clock
+	 * CMD[31]      : Load cmd
+	 */
+	if (!cmd->cmdidx)
+		cmdval |= (1 << 15);
+	if (cmd->resp_type & MMC_RSP_PRESENT)
+		cmdval |= (1 << 6);
+	if (cmd->resp_type & MMC_RSP_136)
+		cmdval |= (1 << 7);
+	if (cmd->resp_type & MMC_RSP_CRC)
+		cmdval |= (1 << 8);
+
+	if (data) {
+		if ((u32) data->dest & 0x3) {
+			error = -1;
+			goto out;
+		}
+
+		cmdval |= (1 << 9) | (1 << 13);
+		if (data->flags & MMC_DATA_WRITE)
+			cmdval |= (1 << 10);
+		if (data->blocks > 1)
+			cmdval |= (1 << 12);
+		writel(data->blocksize, &mmchost->reg->blksz);
+		writel(data->blocks * data->blocksize, &mmchost->reg->bytecnt);
+	}
+
+	debug("mmc %d, cmd %d(0x%08x), arg 0x%08x\n", mmchost->mmc_no,
+	       cmd->cmdidx, cmdval | cmd->cmdidx, cmd->cmdarg);
+	writel(cmd->cmdarg, &mmchost->reg->arg);
+
+	if (!data)
+		writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd);
+
+	/*
+	 * transfer data and check status
+	 * STATREG[2] : FIFO empty
+	 * STATREG[3] : FIFO full
+	 */
+	if (data) {
+		int ret = 0;
+
+		bytecnt = data->blocksize * data->blocks;
+		debug("trans data %d bytes\n", bytecnt);
+#if defined(CONFIG_MMC_SUNXI_USE_DMA) && !defined(CONFIG_SPL_BUILD)
+		if (bytecnt > 64) {
+#else
+		if (0) {
+#endif
+			usedma = 1;
+			writel(readl(&mmchost->reg->gctrl) & (~0x80000000),
+			       &mmchost->reg->gctrl);
+			ret = mmc_trans_data_by_dma(mmc, data);
+			writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd);
+		} else {
+			writel(readl(&mmchost->reg->gctrl) | 0x80000000,
+			       &mmchost->reg->gctrl);
+			writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd);
+			ret = mmc_trans_data_by_cpu(mmc, data);
+		}
+		if (ret) {
+			error = readl(&mmchost->reg->rint) & 0xbfc2;
+			goto out;
+		}
+	}
+
+	timeout = 0xfffff;
+	do {
+		status = readl(&mmchost->reg->rint);
+		if (!timeout-- || (status & 0xbfc2)) {
+			error = status & 0xbfc2;
+			debug("cmd timeout %x\n", error);
+			goto out;
+		}
+	} while (!(status & 0x4));
+
+	if (data) {
+		unsigned done = 0;
+		timeout = usedma ? 0xffff * bytecnt : 0xffff;
+		debug("cacl timeout %x\n", timeout);
+		do {
+			status = readl(&mmchost->reg->rint);
+			if (!timeout-- || (status & 0xbfc2)) {
+				error = status & 0xbfc2;
+				debug("data timeout %x\n", error);
+				goto out;
+			}
+			if (data->blocks > 1)
+				done = status & (1 << 14);
+			else
+				done = status & (1 << 3);
+		} while (!done);
+	}
+
+	if (cmd->resp_type & MMC_RSP_BUSY) {
+		timeout = 0xfffff;
+		do {
+			status = readl(&mmchost->reg->status);
+			if (!timeout--) {
+				error = -1;
+				debug("busy timeout\n");
+				goto out;
+			}
+		} while (status & (1 << 9));
+	}
+
+	if (cmd->resp_type & MMC_RSP_136) {
+		cmd->response[0] = readl(&mmchost->reg->resp3);
+		cmd->response[1] = readl(&mmchost->reg->resp2);
+		cmd->response[2] = readl(&mmchost->reg->resp1);
+		cmd->response[3] = readl(&mmchost->reg->resp0);
+		debug("mmc resp 0x%08x 0x%08x 0x%08x 0x%08x\n",
+		       cmd->response[3], cmd->response[2],
+		       cmd->response[1], cmd->response[0]);
+	} else {
+		cmd->response[0] = readl(&mmchost->reg->resp0);
+		debug("mmc resp 0x%08x\n", cmd->response[0]);
+	}
+out:
+	if (data && usedma) {
+		/* IDMASTAREG
+		 * IDST[0] : idma tx int
+		 * IDST[1] : idma rx int
+		 * IDST[2] : idma fatal bus error
+		 * IDST[4] : idma descriptor invalid
+		 * IDST[5] : idma error summary
+		 * IDST[8] : idma normal interrupt sumary
+		 * IDST[9] : idma abnormal interrupt sumary
+		 */
+		status = readl(&mmchost->reg->idst);
+		writel(status, &mmchost->reg->idst);
+		writel(0, &mmchost->reg->idie);
+		writel(0, &mmchost->reg->dmac);
+		writel(readl(&mmchost->reg->gctrl) & (~(1 << 5)),
+		       &mmchost->reg->gctrl);
+	}
+	if (error) {
+		writel(0x7, &mmchost->reg->gctrl);
+		mmc_update_clk(mmc);
+		debug("mmc cmd %d err 0x%08x\n", cmd->cmdidx, error);
+	}
+	writel(0xffffffff, &mmchost->reg->rint);
+	writel(readl(&mmchost->reg->gctrl) | (1 << 1), &mmchost->reg->gctrl);
+
+	if (error)
+		return -1;
+	else
+		return 0;
+}
+
+int sunxi_mmc_init(int sdc_no)
+{
+	struct mmc *mmc;
+
+	memset(&mmc_dev[sdc_no], 0, sizeof(struct mmc));
+	memset(&mmc_host[sdc_no], 0, sizeof(struct sunxi_mmc_host));
+	mmc = &mmc_dev[sdc_no];
+
+	sprintf(mmc->name, "SUNXI SD/MMC");
+	mmc->priv = &mmc_host[sdc_no];
+	mmc->send_cmd = mmc_send_cmd;
+	mmc->set_ios = mmc_set_ios;
+	mmc->init = mmc_core_init;
+
+	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+	mmc->host_caps = MMC_MODE_4BIT;
+	mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
+
+	mmc->f_min = 400000;
+	mmc->f_max = 52000000;
+
+	mmc_host[sdc_no].pdes = (struct sunxi_mmc_des *)0x50000000;
+	mmc_resource_init(sdc_no);
+	mmc_clk_io_on(sdc_no);
+
+	mmc_register(mmc);
+
+	return 0;
+}
Index: drivers/net/Makefile
===================================================================
--- drivers/net/Makefile.orig
+++ drivers/net/Makefile
@@ -68,6 +68,7 @@ COBJS-$(CONFIG_RTL8169) += rtl8169.o
 COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
 COBJS-$(CONFIG_SMC91111) += smc91111.o
 COBJS-$(CONFIG_SMC911X) += smc911x.o
+COBJS-$(CONFIG_SUNXI_WEMAC) += sunxi_wemac.o
 COBJS-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o
 COBJS-$(CONFIG_TSEC_ENET) += tsec.o fsl_mdio.o
 COBJS-$(CONFIG_DRIVER_TI_CPSW) += cpsw.o
Index: drivers/net/sunxi_wemac.c
===================================================================
--- /dev/null
+++ drivers/net/sunxi_wemac.c
@@ -0,0 +1,533 @@
+/*
+ * sunxi_wemac.c -- Allwinner A10 ethernet driver
+ *
+ * (C) Copyright 2012, Stefan Roese <sr@denx.de>
+ *
+ * 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.
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <net.h>
+#include <miiphy.h>
+#include <linux/err.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/gpio.h>
+
+/* EMAC register  */
+struct wemac_regs {
+	u32 ctl;	/* 0x00 */
+	u32 tx_mode;	/* 0x04 */
+	u32 tx_flow;	/* 0x08 */
+	u32 tx_ctl0;	/* 0x0c */
+	u32 tx_ctl1;	/* 0x10 */
+	u32 tx_ins;	/* 0x14 */
+	u32 tx_pl0;	/* 0x18 */
+	u32 tx_pl1;	/* 0x1c */
+	u32 tx_sta;	/* 0x20 */
+	u32 tx_io_data;	/* 0x24 */
+	u32 tx_io_data1; /* 0x28 */
+	u32 tx_tsvl0;	/* 0x2c */
+	u32 tx_tsvh0;	/* 0x30 */
+	u32 tx_tsvl1;	/* 0x34 */
+	u32 tx_tsvh1;	/* 0x38 */
+	u32 rx_ctl;	/* 0x3c */
+	u32 rx_hash0;	/* 0x40 */
+	u32 rx_hash1;	/* 0x44 */
+	u32 rx_sta;	/* 0x48 */
+	u32 rx_io_data;	/* 0x4c */
+	u32 rx_fbc;	/* 0x50 */
+	u32 int_ctl;	/* 0x54 */
+	u32 int_sta;	/* 0x58 */
+	u32 mac_ctl0;	/* 0x5c */
+	u32 mac_ctl1;	/* 0x60 */
+	u32 mac_ipgt;	/* 0x64 */
+	u32 mac_ipgr;	/* 0x68 */
+	u32 mac_clrt;	/* 0x6c */
+	u32 mac_maxf;	/* 0x70 */
+	u32 mac_supp;	/* 0x74 */
+	u32 mac_test;	/* 0x78 */
+	u32 mac_mcfg;	/* 0x7c */
+	u32 mac_mcmd;	/* 0x80 */
+	u32 mac_madr;	/* 0x84 */
+	u32 mac_mwtd;	/* 0x88 */
+	u32 mac_mrdd;	/* 0x8c */
+	u32 mac_mind;	/* 0x90 */
+	u32 mac_ssrr;	/* 0x94 */
+	u32 mac_a0;	/* 0x98 */
+	u32 mac_a1;	/* 0x9c */
+};
+
+/* SRAMC register  */
+struct sunxi_sramc_regs {
+	u32 ctrl0;
+	u32 ctrl1;
+};
+
+/* 0: Disable       1: Aborted frame enable(default) */
+#define EMAC_TX_AB_M		(0x1 << 0)
+/* 0: CPU           1: DMA(default) */
+#define EMAC_TX_TM		(0x1 << 1)
+
+#define EMAC_TX_SETUP		(0)
+
+/* 0: DRQ asserted  1: DRQ automatically(default) */
+#define EMAC_RX_DRQ_MODE	(0x1 << 1)
+/* 0: CPU           1: DMA(default) */
+#define EMAC_RX_TM		(0x1 << 2)
+/* 0: Normal(default)        1: Pass all Frames */
+#define EMAC_RX_PA		(0x1 << 4)
+/* 0: Normal(default)        1: Pass Control Frames */
+#define EMAC_RX_PCF		(0x1 << 5)
+/* 0: Normal(default)        1: Pass Frames with CRC Error */
+#define EMAC_RX_PCRCE		(0x1 << 6)
+/* 0: Normal(default)        1: Pass Frames with Length Error */
+#define EMAC_RX_PLE		(0x1 << 7)
+/* 0: Normal                 1: Pass Frames length out of range(default) */
+#define EMAC_RX_POR		(0x1 << 8)
+/* 0: Not accept             1: Accept unicast Packets(default) */
+#define EMAC_RX_UCAD		(0x1 << 16)
+/* 0: Normal(default)        1: DA Filtering */
+#define EMAC_RX_DAF		(0x1 << 17)
+/* 0: Not accept             1: Accept multicast Packets(default) */
+#define EMAC_RX_MCO		(0x1 << 20)
+/* 0: Disable(default)       1: Enable Hash filter */
+#define EMAC_RX_MHF		(0x1 << 21)
+/* 0: Not accept             1: Accept Broadcast Packets(default) */
+#define EMAC_RX_BCO		(0x1 << 22)
+/* 0: Disable(default)       1: Enable SA Filtering */
+#define EMAC_RX_SAF		(0x1 << 24)
+/* 0: Normal(default)        1: Inverse Filtering */
+#define EMAC_RX_SAIF		(0x1 << 25)
+
+#define EMAC_RX_SETUP		(EMAC_RX_POR | EMAC_RX_UCAD | EMAC_RX_DAF | \
+				 EMAC_RX_MCO | EMAC_RX_BCO)
+
+/* 0: Disable                1: Enable Receive Flow Control(default) */
+#define EMAC_MAC_CTL0_RFC	(0x1 << 2)
+/* 0: Disable                1: Enable Transmit Flow Control(default) */
+#define EMAC_MAC_CTL0_TFC	(0x1 << 3)
+
+#define EMAC_MAC_CTL0_SETUP	(EMAC_MAC_CTL0_RFC | EMAC_MAC_CTL0_TFC)
+
+/* 0: Disable                1: Enable MAC Frame Length Checking(default) */
+#define EMAC_MAC_CTL1_FLC	(0x1 << 1)
+/* 0: Disable(default)       1: Enable Huge Frame */
+#define EMAC_MAC_CTL1_HF	(0x1 << 2)
+/* 0: Disable(default)       1: Enable MAC Delayed CRC */
+#define EMAC_MAC_CTL1_DCRC	(0x1 << 3)
+/* 0: Disable                1: Enable MAC CRC(default) */
+#define EMAC_MAC_CTL1_CRC	(0x1 << 4)
+/* 0: Disable                1: Enable MAC PAD Short frames(default) */
+#define EMAC_MAC_CTL1_PC	(0x1 << 5)
+/* 0: Disable(default)       1: Enable MAC PAD Short frames and append CRC */
+#define EMAC_MAC_CTL1_VC	(0x1 << 6)
+/* 0: Disable(default)       1: Enable MAC auto detect Short frames */
+#define EMAC_MAC_CTL1_ADP	(0x1 << 7)
+/* 0: Disable(default)       1: Enable */
+#define EMAC_MAC_CTL1_PRE	(0x1 << 8)
+/* 0: Disable(default)       1: Enable */
+#define EMAC_MAC_CTL1_LPE	(0x1 << 9)
+/* 0: Disable(default)       1: Enable no back off */
+#define EMAC_MAC_CTL1_NB	(0x1 << 12)
+/* 0: Disable(default)       1: Enable */
+#define EMAC_MAC_CTL1_BNB	(0x1 << 13)
+/* 0: Disable(default)       1: Enable */
+#define EMAC_MAC_CTL1_ED	(0x1 << 14)
+
+#define EMAC_MAC_CTL1_SETUP	(EMAC_MAC_CTL1_FLC | EMAC_MAC_CTL1_CRC | \
+				 EMAC_MAC_CTL1_PC)
+
+#define EMAC_MAC_IPGT		0x15
+
+#define EMAC_MAC_NBTB_IPG1	0xC
+#define EMAC_MAC_NBTB_IPG2	0x12
+
+#define EMAC_MAC_CW		0x37
+#define EMAC_MAC_RM		0xF
+
+#define EMAC_MAC_MFL		0x0600
+
+/* Receive status */
+#define EMAC_CRCERR		(1 << 4)
+#define EMAC_LENERR		(3 << 5)
+
+#define DMA_CPU_TRRESHOLD	2000
+
+struct wemac_eth_dev {
+	u32 speed;
+	u32 duplex;
+	u32 phy_configured;
+	int link_printed;
+};
+
+struct wemac_rxhdr {
+	s16 rx_len;
+	u16 rx_status;
+};
+
+static void wemac_inblk_32bit(void *reg, void *data, int count)
+{
+	int cnt = (count + 3) >> 2;
+
+	if (cnt) {
+		u32 *buf = data;
+
+		do {
+			u32 x = readl(reg);
+			*buf++ = x;
+		} while (--cnt);
+	}
+}
+
+static void wemac_outblk_32bit(void *reg, void *data, int count)
+{
+	int cnt = (count + 3) >> 2;
+
+	if (cnt) {
+		const u32 *buf = data;
+
+		do {
+			writel(*buf++, reg);
+		} while (--cnt);
+	}
+}
+
+/*
+ * Read a word from phyxcer
+ */
+static int wemac_phy_read(const char *devname, unsigned char addr,
+			  unsigned char reg, unsigned short *value)
+{
+	struct eth_device *dev = eth_get_dev_by_name(devname);
+	struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+
+	/* issue the phy address and reg */
+	writel(addr << 8 | reg, &regs->mac_madr);
+
+	/* pull up the phy io line */
+	writel(0x1, &regs->mac_mcmd);
+
+	/* Wait read complete */
+	mdelay(1);
+
+	/* push down the phy io line */
+	writel(0x0, &regs->mac_mcmd);
+
+	/* and write data */
+	*value = readl(&regs->mac_mrdd);
+
+	return 0;
+}
+
+/*
+ * Write a word to phyxcer
+ */
+static int wemac_phy_write(const char *devname, unsigned char addr,
+			   unsigned char reg, unsigned short value)
+{
+	struct eth_device *dev = eth_get_dev_by_name(devname);
+	struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+
+	/* issue the phy address and reg */
+	writel(addr << 8 | reg, &regs->mac_madr);
+
+	/* pull up the phy io line */
+	writel(0x1, &regs->mac_mcmd);
+
+	/* Wait write complete */
+	mdelay(1);
+
+	/* push down the phy io line */
+	writel(0x0, &regs->mac_mcmd);
+
+	/* and write data */
+	writel(value, &regs->mac_mwtd);
+
+	return 0;
+}
+
+static void emac_setup(struct eth_device *dev)
+{
+	struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+	u32 reg_val;
+	u16 phy_val;
+	u32 duplex_flag;
+
+	/* Set up TX */
+	writel(EMAC_TX_SETUP, &regs->tx_mode);
+
+	/* Set up RX */
+	writel(EMAC_RX_SETUP, &regs->rx_ctl);
+
+	/* Set MAC */
+	/* Set MAC CTL0 */
+	writel(EMAC_MAC_CTL0_SETUP, &regs->mac_ctl0);
+
+	/* Set MAC CTL1 */
+	wemac_phy_read(dev->name, 1, 0, &phy_val);
+	debug("PHY SETUP, reg 0 value: %x\n", phy_val);
+	duplex_flag = !!(phy_val & (1 << 8));
+
+	reg_val = 0;
+	if (duplex_flag)
+		reg_val = (0x1 << 0);
+	writel(EMAC_MAC_CTL1_SETUP | reg_val, &regs->mac_ctl1);
+
+	/* Set up IPGT */
+	writel(EMAC_MAC_IPGT, &regs->mac_ipgt);
+
+	/* Set up IPGR */
+	writel(EMAC_MAC_NBTB_IPG2 | (EMAC_MAC_NBTB_IPG1 << 8), &regs->mac_ipgr);
+
+	/* Set up Collison window */
+	writel(EMAC_MAC_RM | (EMAC_MAC_CW << 8), &regs->mac_clrt);
+
+	/* Set up Max Frame Length */
+	writel(EMAC_MAC_MFL, &regs->mac_maxf);
+}
+
+static void wemac_reset(struct eth_device *dev)
+{
+	struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+
+	debug("resetting device\n");
+
+	/* RESET device */
+	writel(0, &regs->ctl);
+	udelay(200);
+
+	writel(1, &regs->ctl);
+	udelay(200);
+}
+
+static int sunxi_wemac_eth_init(struct eth_device *dev, bd_t *bd)
+{
+	struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+	struct wemac_eth_dev *priv = dev->priv;
+	u16 phy_reg;
+
+	/* Init EMAC */
+
+	/* Flush RX FIFO */
+	setbits_le32(&regs->rx_ctl, 0x8);
+	udelay(1);
+
+	/* Init MAC */
+
+	/* Soft reset MAC */
+	clrbits_le32(&regs->mac_ctl0, 1 << 15);
+
+	/* Set MII clock */
+	clrsetbits_le32(&regs->mac_mcfg, 0xf << 2, 0xd << 2);
+
+	/* Clear RX counter */
+	writel(0x0, &regs->rx_fbc);
+	udelay(1);
+
+	/* Set up EMAC */
+	emac_setup(dev);
+
+	writel(dev->enetaddr[0] << 16 | dev->enetaddr[1] << 8 |
+	       dev->enetaddr[2], &regs->mac_a1);
+	writel(dev->enetaddr[3] << 16 | dev->enetaddr[4] << 8 |
+	       dev->enetaddr[5], &regs->mac_a0);
+
+	mdelay(1);
+
+	wemac_reset(dev);
+
+	/* PHY POWER UP */
+	wemac_phy_read(dev->name, 1, 0, &phy_reg);
+	wemac_phy_write(dev->name, 1, 0, phy_reg & (~(1 << 11)));
+	mdelay(1);
+
+	wemac_phy_read(dev->name, 1, 0, &phy_reg);
+
+	priv->speed = miiphy_speed(dev->name, 0);
+	priv->duplex = miiphy_duplex(dev->name, 0);
+
+	/* Print link status only once */
+	if (!priv->link_printed) {
+		printf("ENET Speed is %d Mbps - %s duplex connection\n",
+		       priv->speed, (priv->duplex == HALF) ? "HALF" : "FULL");
+		priv->link_printed = 1;
+	}
+
+	/* Set EMAC SPEED depend on PHY */
+	clrsetbits_le32(&regs->mac_supp, 1 << 8,
+			((phy_reg & (1 << 13)) >> 13) << 8);
+
+	/* Set duplex depend on phy */
+	clrsetbits_le32(&regs->mac_ctl1, 1 << 0,
+			((phy_reg & (1 << 8)) >> 8) << 0);
+
+	/* Enable RX/TX */
+	setbits_le32(&regs->ctl, 0x7);
+
+	return 0;
+}
+
+static void sunxi_wemac_eth_halt(struct eth_device *dev)
+{
+	/* Nothing to do here */
+}
+
+static int sunxi_wemac_eth_recv(struct eth_device *dev)
+{
+	struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+	struct wemac_rxhdr rxhdr;
+	u32 rxcount;
+	u32 reg_val;
+	int rx_len;
+	int rx_status;
+	int good_packet;
+
+	/* Check packet ready or not */
+
+	/*
+	 * Race warning: The first packet might arrive with
+	 * the interrupts disabled, but the second will fix
+	 */
+	rxcount = readl(&regs->rx_fbc);
+	if (!rxcount) {
+		/* Had one stuck? */
+		rxcount = readl(&regs->rx_fbc);
+		if (!rxcount)
+			return 0;
+	}
+
+	reg_val = readl(&regs->rx_io_data);
+	if (reg_val != 0x0143414d) {
+		/* Disable RX */
+		clrbits_le32(&regs->ctl, 1 << 2);
+
+		/* Flush RX FIFO */
+		setbits_le32(&regs->rx_ctl, 1 << 3);
+		while (readl(&regs->rx_ctl) & (1 << 3))
+			;
+
+		/* Enable RX */
+		setbits_le32(&regs->ctl, 1 << 2);
+
+		return 0;
+	}
+
+	/*
+	 * A packet ready now
+	 * Get status/length
+	 */
+	good_packet = 1;
+
+	wemac_inblk_32bit(&regs->rx_io_data, &rxhdr, sizeof(rxhdr));
+
+	rx_len = rxhdr.rx_len;
+	rx_status = rxhdr.rx_status;
+
+	/* Packet Status check */
+	if (rx_len < 0x40) {
+		good_packet = 0;
+		debug("RX: Bad Packet (runt)\n");
+	}
+
+	/* rx_status is identical to RSR register. */
+	if (0 & rx_status & (EMAC_CRCERR | EMAC_LENERR)) {
+		good_packet = 0;
+		if (rx_status & EMAC_CRCERR)
+			printf("crc error\n");
+		if (rx_status & EMAC_LENERR)
+			printf("length error\n");
+	}
+
+	/* Move data from WEMAC */
+	if (good_packet) {
+		if (rx_len > DMA_CPU_TRRESHOLD) {
+			printf("Received packet is too big (len=%d)\n", rx_len);
+		} else {
+			wemac_inblk_32bit((void *)&regs->rx_io_data,
+					  NetRxPackets[0], rx_len);
+
+			/* Pass to upper layer */
+			NetReceive(NetRxPackets[0], rx_len);
+			return rx_len;
+		}
+	}
+
+	return 0;
+}
+
+static int sunxi_wemac_eth_send(struct eth_device *dev, void *packet, int len)
+{
+	struct wemac_regs *regs = (struct wemac_regs *)dev->iobase;
+
+	/* Select channel 0 */
+	writel(0, &regs->tx_ins);
+
+	/* Write packet */
+	wemac_outblk_32bit((void *)&regs->tx_io_data, packet, len);
+
+	/* Set TX len */
+	writel(len, &regs->tx_pl0);
+
+	/* Start translate from fifo to phy */
+	setbits_le32(&regs->tx_ctl0, 1);
+
+	return 0;
+}
+
+int sunxi_wemac_initialize(void)
+{
+	struct sunxi_ccm_reg *const ccm =
+		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+	struct sunxi_sramc_regs *sram =
+		(struct sunxi_sramc_regs *)SUNXI_SRAMC_BASE;
+	struct eth_device *dev;
+	struct wemac_eth_dev *priv;
+	int pin;
+
+	dev = malloc(sizeof(*dev));
+	if (dev == NULL)
+		return -ENOMEM;
+
+	priv = (struct wemac_eth_dev *)malloc(sizeof(struct wemac_eth_dev));
+	if (!priv) {
+		free(dev);
+		return -ENOMEM;
+	}
+
+	memset(dev, 0, sizeof(*dev));
+	memset(priv, 0, sizeof(struct wemac_eth_dev));
+
+	/* Map SRAM to EMAC */
+	setbits_le32(&sram->ctrl1, 0x5 << 2);
+
+	/* Configure pin mux settings for MII Ethernet */
+	for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(17); pin++)
+		sunxi_gpio_set_cfgpin(pin, 2);
+
+	/* Set up clock gating */
+	setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_EMAC);
+
+	dev->iobase = SUNXI_EMAC_BASE;
+	dev->priv = priv;
+	dev->init = sunxi_wemac_eth_init;
+	dev->halt = sunxi_wemac_eth_halt;
+	dev->send = sunxi_wemac_eth_send;
+	dev->recv = sunxi_wemac_eth_recv;
+	strcpy(dev->name, "wemac");
+
+	eth_register(dev);
+
+	miiphy_register(dev->name, wemac_phy_read, wemac_phy_write);
+
+	return 0;
+}
Index: drivers/power/axp209.c
===================================================================
--- /dev/null
+++ drivers/power/axp209.c
@@ -0,0 +1,182 @@
+/*
+ * (C) Copyright 2012
+ * Henrik Nordstrom <henrik@henriknordstrom.net>
+ *
+ * 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 <i2c.h>
+#include <axp209.h>
+
+enum axp209_reg {
+	AXP209_CHIP_VERSION = 0x3,
+	AXP209_DCDC2_VOLTAGE = 0x23,
+	AXP209_DCDC3_VOLTAGE = 0x27,
+	AXP209_LDO24_VOLTAGE = 0x28,
+	AXP209_LDO3_VOLTAGE = 0x29,
+	AXP209_SHUTDOWN = 0x32,
+};
+
+int axp209_write(enum axp209_reg reg, u8 val)
+{
+	return i2c_write(0x34, reg, 1, &val, 1);
+}
+
+int axp209_read(enum axp209_reg reg, u8 *val)
+{
+	return i2c_read(0x34, reg, 1, val, 1);
+}
+
+int axp209_set_dcdc2(int mvolt)
+{
+	int cfg = (mvolt - 700) / 25;
+	int rc;
+	u8 current;
+
+	if (cfg < 0)
+		cfg = 0;
+	if (cfg > (1 << 6) - 1)
+		cfg = (1 << 6) - 1;
+
+	/* Do we really need to be this gentle? It has built-in voltage slope */
+	while ((rc = axp209_read(AXP209_DCDC2_VOLTAGE, &current)) == 0
+	       && current != cfg) {
+		if (current < cfg)
+			current++;
+		else
+			current--;
+
+		rc = axp209_write(AXP209_DCDC2_VOLTAGE, current);
+		if (rc)
+			break;
+	}
+
+	return rc;
+}
+
+int axp209_set_dcdc3(int mvolt)
+{
+	int cfg = (mvolt - 700) / 25;
+	u8 reg;
+	int rc;
+
+	if (cfg < 0)
+		cfg = 0;
+	if (cfg > (1 << 7) - 1)
+		cfg = (1 << 7) - 1;
+
+	rc = axp209_write(AXP209_DCDC3_VOLTAGE, cfg);
+	rc |= axp209_read(AXP209_DCDC3_VOLTAGE, &reg);
+
+	return rc;
+}
+
+int axp209_set_ldo2(int mvolt)
+{
+	int cfg = (mvolt - 1800) / 100;
+	int rc;
+	u8 reg;
+
+	if (cfg < 0)
+		cfg = 0;
+	if (cfg > 15)
+		cfg = 15;
+
+	rc = axp209_read(AXP209_LDO24_VOLTAGE, &reg);
+	if (rc)
+		return rc;
+
+	reg = (reg & 0x0f) | (cfg << 4);
+	rc = axp209_write(AXP209_LDO24_VOLTAGE, reg);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+int axp209_set_ldo3(int mvolt)
+{
+	int cfg = (mvolt - 700) / 25;
+
+	if (cfg < 0)
+		cfg = 0;
+	if (cfg > 127)
+		cfg = 127;
+	if (mvolt == -1)
+		cfg = 0x80;	/* detemined by LDO3IN pin */
+
+	return axp209_write(AXP209_LDO3_VOLTAGE, cfg);
+}
+
+int axp209_set_ldo4(int mvolt)
+{
+	int cfg = (mvolt - 1800) / 100;
+	int rc;
+	static const int vindex[] = {
+		1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2500,
+		2700, 2800, 3000, 3100, 3200, 3300
+	};
+	u8 reg;
+
+	/* Translate mvolt to register cfg value, requested <= selected */
+	for (cfg = 0; mvolt < vindex[cfg] && cfg < 15; cfg++);
+
+	rc = axp209_read(AXP209_LDO24_VOLTAGE, &reg);
+	if (rc)
+		return rc;
+
+	/* LDO4 configuration is in lower 4 bits */
+	reg = (reg & 0xf0) | (cfg << 0);
+	rc = axp209_write(AXP209_LDO24_VOLTAGE, reg);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+void axp209_poweroff(void)
+{
+	u8 val;
+
+	if (axp209_read(AXP209_SHUTDOWN, &val) != 0)
+		return;
+
+	val |= 1 << 7;
+
+	if (axp209_write(AXP209_SHUTDOWN, val) != 0)
+		return;
+
+	udelay(10000);		/* wait for power to drain */
+}
+
+int axp209_init(void)
+{
+	u8 ver;
+	int rc;
+
+	rc = axp209_read(AXP209_CHIP_VERSION, &ver);
+	if (rc)
+		return rc;
+
+	if (ver != 0x21)
+		return -1;
+
+	return 0;
+}
Index: drivers/power/Makefile
===================================================================
--- drivers/power/Makefile.orig
+++ drivers/power/Makefile
@@ -25,6 +25,7 @@ include $(TOPDIR)/config.mk
 
 LIB	:= $(obj)libpower.o
 
+COBJS-$(CONFIG_AXP209_POWER)	+= axp209.o
 COBJS-$(CONFIG_EXYNOS_TMU)	+= exynos-tmu.o
 COBJS-$(CONFIG_FTPMU010_POWER)	+= ftpmu010.o
 COBJS-$(CONFIG_TPS6586X_POWER)	+= tps6586x.o
Index: drivers/serial/arm_dcc.c
===================================================================
--- drivers/serial/arm_dcc.c.orig
+++ drivers/serial/arm_dcc.c
@@ -29,7 +29,7 @@
 #include <common.h>
 #include <stdio_dev.h>
 
-#if defined(CONFIG_CPU_V6)
+#if defined(CONFIG_CPU_V6) || 1
 /*
  * ARMV6
  */
Index: include/axp209.h
===================================================================
--- /dev/null
+++ include/axp209.h
@@ -0,0 +1,29 @@
+/*
+ * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
+ *
+ * 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
+ */
+
+extern int axp209_set_dcdc2(int mvolt);
+extern int axp209_set_dcdc3(int mvolt);
+extern int axp209_set_ldo2(int mvolt);
+extern int axp209_set_ldo3(int mvolt);
+extern int axp209_set_ldo4(int mvolt);
+extern void axp209_poweroff(void);
+extern int axp209_init(void);
Index: include/config_fallbacks.h
===================================================================
--- include/config_fallbacks.h.orig
+++ include/config_fallbacks.h
@@ -53,4 +53,8 @@
 #define HAVE_BLOCK_DEVICE
 #endif
 
+#ifndef CONFIG_SYS_BOARD_NAME
+#define CONFIG_SYS_BOARD_NAME CONFIG_SYS_TARGET
+#endif
+
 #endif	/* __CONFIG_FALLBACKS_H */
Index: include/configs/sun4i.h
===================================================================
--- /dev/null
+++ include/configs/sun4i.h
@@ -0,0 +1,74 @@
+/*
+ * (C) Copyright 2012
+ * Henrik Nordstrom <henrik@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
+
+/*
+ * Include common sunxi configuration where most the settings are
+ */
+#include <configs/sunxi-common.h>
+
+/*
+ * A10 specific configuration
+ */
+#define CONFIG_SUN4I		/* sun4i SoC generation */
+
+#define CONFIG_SYS_PROMPT		"sun4i#"
+#define CONFIG_MACH_TYPE		4104
+
+/* Define this to have console redirected to SD port */
+/* #define CONFIG_UART0_PORT_F */
+
+#define CONFIG_CONS_INDEX		1	/* UART0 */
+
+/* Ethernet support on A10 */
+#define CONFIG_SUNXI_WEMAC
+#define CONFIG_MII			/* MII PHY management		*/
+#define CONFIG_CMD_MII
+#define CONFIG_CMD_NET
+#define CONFIG_CMD_PING
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_NFS
+#define CONFIG_CMD_SNTP
+#define CONFIG_CMD_DNS
+#define CONFIG_NETCONSOLE
+#define CONFIG_BOOTP_SUBNETMASK
+#define CONFIG_BOOTP_GATEWAY
+#define CONFIG_BOOTP_HOSTNAME
+#define CONFIG_BOOTP_NISDOMAIN
+#define CONFIG_BOOTP_BOOTPATH
+#define CONFIG_BOOTP_BOOTFILESIZE
+#define CONFIG_BOOTP_DNS
+#define CONFIG_BOOTP_DNS2
+#define CONFIG_BOOTP_SEND_HOSTNAME
+#define CONFIG_BOOTP_NTPSERVER
+#define CONFIG_BOOTP_TIMEOFFSET
+#define CONFIG_BOOTP_MAY_FAIL
+#define CONFIG_BOOTP_SERVERIP
+#define CONFIG_BOOTP_DHCP_REQUEST_DELAY		50000
+#define CONFIG_TIMESTAMP
+
+#endif /* __CONFIG_H */
Index: include/configs/sun5i.h
===================================================================
--- /dev/null
+++ include/configs/sun5i.h
@@ -0,0 +1,56 @@
+/*
+ * (C) Copyright 2012
+ * Henrik Nordstrom <henrik@henriknordstrom.net>
+ *
+ * Configuration settings for the Allwinner A13 (sun5i) 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
+
+/*
+ * Include common sunxi configuration where most the settings are
+ */
+#include <configs/sunxi-common.h>
+
+/*
+ * High Level Configuration Options
+ */
+#define CONFIG_SUN5I		/* sun5i SoC generation */
+
+#define CONFIG_SYS_PROMPT		"sun5i#"
+#define CONFIG_MACH_TYPE		4138
+
+/* Define this to have serial channel 1 (UART0) redirected to SD port */
+/* #define CONFIG_UART0_PORT_F */
+
+#ifndef CONFIG_CONS_INDEX
+#ifdef CONFIG_UART0_PORT_F
+#define CONFIG_CONS_INDEX		1	/* UART0 on PORT_F (sdcard) */
+#else
+#define CONFIG_CONS_INDEX		2	/* UART1 */
+#endif
+#endif
+
+/* Leave ICACHE off while debugging with OpenOCD */
+#define CONFIG_SYS_ICACHE_OFF
+
+#endif /* __CONFIG_H */
Index: include/configs/sunxi-common.h
===================================================================
--- /dev/null
+++ include/configs/sunxi-common.h
@@ -0,0 +1,261 @@
+/*
+ * (C) Copyright 2012-2012 Henrik Nordstrom <henrik@henriknordstrom.net>
+ *
+ * Based on older sun4i config
+ *
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * Configuration settings for the Allwinner A10-evb board.
+ *
+ * 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 _SUNXI_COMMON_CONFIG_H
+#define _SUNXI_COMMON_CONFIG_H
+
+/*
+ * High Level Configuration Options
+ */
+#define CONFIG_ALLWINNER	/* It's a Allwinner chip */
+#define CONFIG_SUNXI		/* which is sunxi family */
+
+#include <asm/arch/cpu.h>	/* get chip and board defs */
+
+#define CONFIG_SYS_TEXT_BASE		0x4A000000
+
+/*
+ * Display CPU and Board information
+ */
+#define CONFIG_DISPLAY_CPUINFO
+#define CONFIG_DISPLAY_BOARDINFO
+
+/* Serial & console */
+#define CONFIG_SYS_NS16550
+#define CONFIG_SYS_NS16550_SERIAL
+/* ns16550 reg in the low bits of cpu reg */
+#define CONFIG_SYS_NS16550_REG_SIZE	(-4)
+#define CONFIG_SYS_NS16550_CLK		(24000000)
+#define CONFIG_SYS_NS16550_COM1		SUNXI_UART0_BASE
+#define CONFIG_SYS_NS16550_COM2		SUNXI_UART1_BASE
+#define CONFIG_SYS_NS16550_COM3		SUNXI_UART2_BASE
+#define CONFIG_SYS_NS16550_COM4		SUNXI_UART3_BASE
+
+/* DRAM Base */
+#define CONFIG_SYS_SDRAM_BASE		0x40000000
+#define CONFIG_SYS_INIT_RAM_ADDR	0x0
+#define CONFIG_SYS_INIT_RAM_SIZE	0x8000	/* 32K */
+
+#define CONFIG_SYS_INIT_SP_OFFSET \
+	(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
+#define CONFIG_SYS_INIT_SP_ADDR \
+	(CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET)
+
+/* A10-EVB has 1 banks of DRAM, we use only one in U-Boot */
+#define CONFIG_NR_DRAM_BANKS		1
+#define PHYS_SDRAM_1			CONFIG_SYS_SDRAM_BASE
+#if 0
+/* Nand config */
+#define CONFIG_NAND
+#define CONFIG_NAND_SUNXI
+#define CONFIG_CMD_NAND                         /* NAND support */
+#define CONFIG_SYS_MAX_NAND_DEVICE      1
+#define CONFIG_SYS_NAND_BASE            0x00
+#endif
+
+#define CONFIG_CMD_MEMORY
+#define CONFIG_CMD_SETEXPR
+
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_CMDLINE_TAG
+#define CONFIG_INITRD_TAG
+#define CONFIG_CMDLINE_EDITING
+
+/* mmc config */
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_CMD_MMC
+#define CONFIG_MMC_SUNXI
+#define CONFIG_MMC_SUNXI_SLOT		0
+#define CONFIG_MMC_SUNXI_USE_DMA
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_SYS_MMC_ENV_DEV		CONFIG_MMC_SUNXI_SLOT
+
+/*
+ * Size of malloc() pool
+ * 1MB = 0x100000, 0x100000 = 1024 * 1024
+ */
+#define CONFIG_SYS_MALLOC_LEN		(CONFIG_ENV_SIZE + (1 << 20))
+
+/* Flat Device Tree (FDT/DT) support */
+#define CONFIG_OF_LIBFDT
+#define CONFIG_SYS_BOOTMAPSZ		(16 << 20)
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CONFIG_SYS_LONGHELP	/* undef to save memory */
+#define CONFIG_SYS_HUSH_PARSER	/* use "hush" command parser    */
+#define CONFIG_CMD_ECHO
+#define CONFIG_SYS_PROMPT_HUSH_PS2	"> "
+#define CONFIG_SYS_CBSIZE	256	/* Console I/O Buffer Size */
+#define CONFIG_SYS_PBSIZE	384	/* Print Buffer Size */
+#define CONFIG_SYS_MAXARGS	16	/* max number of command args */
+
+/* Boot Argument Buffer Size */
+#define CONFIG_SYS_BARGSIZE		CONFIG_SYS_CBSIZE
+
+/* memtest works on */
+#define CONFIG_SYS_MEMTEST_START	CONFIG_SYS_SDRAM_BASE
+#define CONFIG_SYS_MEMTEST_END		(CONFIG_SYS_SDRAM_BASE + (256 << 20))
+#define CONFIG_SYS_LOAD_ADDR		0x50000000 /* default load address */
+
+/* standalone support */
+#define CONFIG_STANDALONE_LOAD_ADDR	0x50000000
+
+#define CONFIG_SYS_HZ			1000
+
+/* valid baudrates */
+#define CONFIG_BAUDRATE			115200
+#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 }
+
+/* The stack sizes are set up in start.S using the settings below */
+#define CONFIG_STACKSIZE		(256 << 10)	/* 256 KB */
+
+/* FLASH and environment organization */
+
+#define CONFIG_SYS_NO_FLASH
+
+#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 */
+#define CONFIG_ENV_SIZE			(128 << 10)	/* 128KB */
+
+#define CONFIG_BOOTCOMMAND \
+	"if run loadbootenv; then " \
+		"echo Loaded environment from ${bootenv};" \
+		"env import -t ${scriptaddr} ${filesize};" \
+	"fi;" \
+	"if test -n ${uenvcmd}; then " \
+		"echo Running uenvcmd ...;" \
+		"run uenvcmd;" \
+	"fi;" \
+	"if run loadbootscr; then "\
+		"echo Jumping to ${bootscr};" \
+		"source ${scriptaddr};" \
+	"fi;" \
+	"run setargs boot_mmc;" \
+
+#ifdef CONFIG_CMD_WATCHDOG
+#define	RESET_WATCHDOG " watchdog 0 &&"
+#else
+#define RESET_WATCHDOG ""
+#endif
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"console=ttyS0,115200\0" \
+	"root=/dev/mmcblk0p2 rootwait\0" \
+	"panicarg=panic=10\0" \
+	"extraargs=\0" \
+	"loglevel=8\0" \
+	"scriptaddr=0x44000000\0" \
+	"setargs=setenv bootargs console=${console} root=${root}" \
+		" loglevel=${loglevel} ${panicarg} ${extraargs}\0" \
+	"kernel=uImage\0" \
+	"bootenv=uEnv.txt\0" \
+	"bootscr=boot/boot.scr\0" \
+	"loadbootscr=fatload mmc 0 $scriptaddr ${bootscr} ||" \
+		" ext2load mmc 0 $scriptaddr ${bootscr} ||" \
+		" ext2load mmc 0 $scriptaddr boot/${bootscr}\0" \
+	"loadbootenv=fatload mmc 0 $scriptaddr ${bootenv} ||" \
+		" ext2load mmc 0 $scriptaddr ${bootenv} ||" \
+		" ext2load mmc 0 $scriptaddr boot/${bootenv}\0" \
+	"boot_mmc=fatload mmc 0 0x43000000 script.bin &&" \
+		" fatload mmc 0 0x48000000 ${kernel} &&" \
+		RESET_WATCHDOG \
+		" && bootm 0x48000000\0"
+
+#define CONFIG_BOOTDELAY	3
+#define CONFIG_SYS_BOOT_GET_CMDLINE
+#define CONFIG_AUTO_COMPLETE
+
+#include <config_cmd_default.h>
+
+#define CONFIG_DOS_PARTITION
+#define CONFIG_CMD_FAT		/* with this we can access fat bootfs */
+#define CONFIG_FAT_WRITE	/* enable write access */
+#define CONFIG_CMD_EXT2		/* with this we can access ext2 bootfs */
+#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		0x6000		/* 24 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
+
+/* I2C */
+#define CONFIG_SPL_I2C_SUPPORT
+#define CONFIG_SYS_I2C_SPEED		400000
+#define CONFIG_HARD_I2C
+#define CONFIG_SUNXI_I2C
+#define CONFIG_SYS_I2C_SLAVE		0x7f
+#define CONFIG_CMD_I2C
+
+/* Watchdog */
+#if 0
+#define CONFIG_WATCHDOG			/* automatic watchdog support */
+#define CONFIG_CMD_WATCHDOG		/* watchdog command setting the watchdog timeout */
+#endif
+
+/* GPIO */
+#define CONFIG_SUNXI_GPIO
+#define CONFIG_CMD_GPIO
+
+/* PMU */
+#define CONFIG_SPL_POWER_SUPPORT
+#ifndef CONFIG_NO_AXP
+#define CONFIG_AXP209_POWER
+#endif
+
+#endif /* _SUNXI_COMMON_CONFIG_H */
Index: include/netdev.h
===================================================================
--- include/netdev.h.orig
+++ include/netdev.h
@@ -94,6 +94,7 @@ int sh_eth_initialize(bd_t *bis);
 int skge_initialize(bd_t *bis);
 int smc91111_initialize(u8 dev_num, int base_addr);
 int smc911x_initialize(u8 dev_num, int base_addr);
+int sunxi_wemac_initialize(bd_t *bis);
 int tsi108_eth_initialize(bd_t *bis);
 int uec_standard_init(bd_t *bis);
 int uli526x_initialize(bd_t *bis);
Index: MAINTAINERS
===================================================================
--- MAINTAINERS.orig
+++ MAINTAINERS
@@ -337,6 +337,19 @@ Reinhard Meyer <reinhard.meyer@emk-elekt
 	TOP5200		MPC5200
 	TOP9000		ARM926EJS (AT91SAM9xxx SoC)
 
+Henrik Nordstrom <henrik@henriknordstrom.net>
+	A13_OLINUXINO	ARM V7 (Allwinner A13 SoC)
+	A13_MID		ARM V7 (Allwinner A13 SoC)
+	CUBIEBOARD	ARM V7 (Allwinner A10 SoC)
+	CUBIEBOARD_512	ARM V7 (Allwinner A10 SoC)
+	HACKBERRY	ARM V7 (Allwinner A10 SoC)
+	MELE_A1000	ARM V7 (Allwinner A10 SoC)
+	MINI-X		ARM V7 (Allwinner A10 SoC)
+	SUN4I		ARM V7 (Allwinner A10 SoC)
+	SUN4I_SDCON	ARM V7 (Allwinner A10 SoC)
+	SUN5I		ARM V7 (Allwinner A13 SoC)
+	SUN5I_SDCON	ARM V7 (Allwinner A13 SoC)
+
 Kyle Moffett <Kyle.D.Moffett@boeing.com>
 
 	HWW1U1A		P2020
Index: Makefile
===================================================================
--- Makefile.orig
+++ Makefile
@@ -536,6 +536,16 @@ $(obj)u-boot.spr:	$(obj)u-boot.img $(obj
 			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
+
 ifneq ($(CONFIG_TEGRA),)
 ifeq ($(CONFIG_OF_SEPARATE),y)
 nodtb=dtb
@@ -778,6 +788,7 @@ unconfig:
 sinclude $(obj).boards.depend
 $(obj).boards.depend:	boards.cfg
 	@awk '(NF && $$1 !~ /^#/) { print $$1 ": " $$1 "_config; $$(MAKE)" }' $< > $@
+	@awk '(NF && $$1 !~ /^#/ && tolower($$1) != $$1) { print tolower($$1) ": " $$1 "_config; $$(MAKE)" }' $< >> $@
 
 #
 # Functions to generate common board directory names
@@ -807,6 +818,7 @@ clean:
 	       $(obj)tools/gen_eth_addr    $(obj)tools/img2srec		  \
 	       $(obj)tools/mk{env,}image   $(obj)tools/mpc86x_clk	  \
 	       $(obj)tools/mk{smdk5250,}spl				  \
+	       $(obj)tools/mksunxiboot					  \
 	       $(obj)tools/mxsboot					  \
 	       $(obj)tools/ncb		   $(obj)tools/ubsha1		  \
 	       $(obj)tools/kernel-doc/docproc
@@ -864,6 +876,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
Index: mkconfig
===================================================================
--- mkconfig.orig
+++ mkconfig
@@ -164,6 +164,7 @@ done
 echo "#define CONFIG_SYS_ARCH  \"${arch}\""  >> config.h
 echo "#define CONFIG_SYS_CPU   \"${cpu}\""   >> config.h
 echo "#define CONFIG_SYS_BOARD \"${board}\"" >> config.h
+echo "#define CONFIG_SYS_TARGET \"${BOARD_NAME}\"" >> config.h
 
 [ "${vendor}" ] && echo "#define CONFIG_SYS_VENDOR \"${vendor}\"" >> config.h
 
Index: snapshot.commit
===================================================================
--- snapshot.commit.orig
+++ snapshot.commit
@@ -1 +1 @@
-d10f68ae47b67acab8b110b5c605dde4197a1820  Fri, 19 Apr 2013 10:25:43 -0400
+$Format:%H  %cD$
Index: spl/Makefile
===================================================================
--- spl/Makefile.orig
+++ spl/Makefile
@@ -153,6 +153,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
@@ -161,6 +165,12 @@ $(obj)$(BOARD)-spl.bin: $(obj)u-boot-spl
 		$(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 $< $@
 
Index: tools/.gitignore
===================================================================
--- tools/.gitignore.orig
+++ tools/.gitignore
@@ -7,6 +7,7 @@
 /mkimage
 /mpc86x_clk
 /mxsboot
+/mksunxiboot
 /ncb
 /ncp
 /ubsha1
Index: tools/Makefile
===================================================================
--- tools/Makefile.orig
+++ tools/Makefile
@@ -70,6 +70,7 @@ BIN_FILES-y += mkenvimage$(SFX)
 BIN_FILES-y += mkimage$(SFX)
 BIN_FILES-$(CONFIG_SMDK5250) += mksmdk5250spl$(SFX)
 BIN_FILES-$(CONFIG_MX23) += mxsboot$(SFX)
+BIN_FILES-$(CONFIG_SUNXI) += mksunxiboot$(SFX)
 BIN_FILES-$(CONFIG_MX28) += mxsboot$(SFX)
 BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX)
 BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX)
@@ -100,6 +101,7 @@ NOPED_OBJ_FILES-y += mkenvimage.o
 NOPED_OBJ_FILES-y += mkimage.o
 OBJ_FILES-$(CONFIG_SMDK5250) += mkexynosspl.o
 OBJ_FILES-$(CONFIG_MX23) += mxsboot.o
+OBJ_FILES-$(CONFIG_SUNXI) += mksunxiboot.o
 OBJ_FILES-$(CONFIG_MX28) += mxsboot.o
 OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o
 NOPED_OBJ_FILES-y += os_support.o
@@ -231,6 +233,10 @@ $(obj)mpc86x_clk$(SFX):	$(obj)mpc86x_clk
 	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
 	$(HOSTSTRIP) $@
 
+$(obj)mksunxiboot$(SFX):	$(obj)mksunxiboot.o
+	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
+	$(HOSTSTRIP) $@
+
 $(obj)mxsboot$(SFX):	$(obj)mxsboot.o
 	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
 	$(HOSTSTRIP) $@
Index: tools/mksunxiboot.c
===================================================================
--- /dev/null
+++ tools/mksunxiboot.c
@@ -0,0 +1,162 @@
+/*
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * a simple tool to generate bootable image for sunxi platform.
+ *
+ * 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 <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+typedef unsigned char u8;
+typedef unsigned int u32;
+
+/* boot head definition from sun4i boot code */
+struct boot_file_head {
+	u32 jump_instruction;	/* one intruction jumping to real code */
+	u8 magic[8];		/* ="eGON.BT0" or "eGON.BT1", not C-style str */
+	u32 check_sum;		/* generated by PC */
+	u32 length;		/* generated by PC */
+#if 1
+	/* We use a simplified header, only filling in what is needed by the
+	 * boot ROM. To be compatible with Allwinner tools the larger header
+	 * below should be used, followed by a custom header if desired. */
+	u8 pad[12];		/* align to 32 bytes */
+#else
+	u32 pub_head_size;	/* the size of boot_file_head */
+	u8 pub_head_vsn[4];	/* the version of boot_file_head */
+	u8 file_head_vsn[4];	/* the version of boot0_file_head or
+				   boot1_file_head */
+	u8 Boot_vsn[4];		/* Boot version */
+	u8 eGON_vsn[4];		/* eGON version */
+	u8 platform[8];		/* platform information */
+#endif
+};
+
+#define BOOT0_MAGIC                     "eGON.BT0"
+#define STAMP_VALUE                     0x5F0A6C39
+
+/* check sum functon from sun4i boot code */
+int gen_check_sum(void *boot_buf)
+{
+	struct boot_file_head *head_p;
+	u32 length;
+	u32 *buf;
+	u32 loop;
+	u32 i;
+	u32 sum;
+
+	head_p = (struct boot_file_head *) boot_buf;
+	length = head_p->length;
+	if ((length & 0x3) != 0)	/* must 4-byte-aligned */
+		return -1;
+	buf = (u32 *) boot_buf;
+	head_p->check_sum = STAMP_VALUE;	/* fill stamp */
+	loop = length >> 2;
+
+	/* calculate the sum */
+	for (i = 0, sum = 0; i < loop; i++)
+		sum += buf[i];
+
+	/* write back check sum */
+	head_p->check_sum = sum;
+
+	return 0;
+}
+
+#define ALIGN(x, a) __ALIGN_MASK((x), (typeof(x))(a)-1)
+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
+
+#define SUN4I_SRAM_SIZE (24 * 1024)
+#define SRAM_LOAD_MAX_SIZE (SUN4I_SRAM_SIZE - sizeof(struct boot_file_head))
+#define BLOCK_SIZE 512
+
+struct boot_img {
+	struct boot_file_head header;
+	char code[SRAM_LOAD_MAX_SIZE];
+	char pad[BLOCK_SIZE];
+};
+
+int main(int argc, char *argv[])
+{
+	int fd_in, fd_out;
+	struct boot_img img;
+	unsigned file_size, load_size;
+	int count;
+
+	if (argc < 2) {
+		printf("\tThis program makes an input bin file to sun4i "
+		       "bootable image.\n"
+		       "\tUsage: %s input_file out_putfile\n", argv[0]);
+		return EXIT_FAILURE;
+	}
+
+	fd_in = open(argv[1], O_RDONLY);
+	if (fd_in < 0) {
+		perror("Open input file:");
+		return EXIT_FAILURE;
+	}
+
+	fd_out = open(argv[2], O_WRONLY | O_CREAT, 0666);
+	if (fd_out < 0) {
+		perror("Open output file:");
+		return EXIT_FAILURE;
+	}
+
+	memset((void *)img.pad, 0, BLOCK_SIZE);
+
+	/* get input file size */
+	file_size = lseek(fd_in, 0, SEEK_END);
+	printf("File size: 0x%x\n", file_size);
+
+	if (file_size > SRAM_LOAD_MAX_SIZE)
+		load_size = SRAM_LOAD_MAX_SIZE;
+	else
+		load_size = ALIGN(file_size, sizeof(int));
+	printf("Load size: 0x%x\n", load_size);
+
+	/* read file to buffer to calculate checksum */
+	lseek(fd_in, 0, SEEK_SET);
+	count = read(fd_in, img.code, load_size);
+	printf("Read 0x%x bytes\n", count);
+
+	/* fill the header */
+	img.header.jump_instruction =	/* b instruction */
+		0xEA000000 |	/* jump to the first instr after the header */
+		((sizeof(struct boot_file_head) / sizeof(int) - 2)
+		 & 0x00FFFFFF);
+	memcpy(img.header.magic, BOOT0_MAGIC, 8);	/* no '0' termination */
+	img.header.length =
+		ALIGN(load_size + sizeof(struct boot_file_head), BLOCK_SIZE);
+	gen_check_sum((void *)&img);
+
+	count = write(fd_out, (void *)&img, img.header.length);
+	printf("Write 0x%x bytes\n", count);
+
+	close(fd_in);
+	close(fd_out);
+
+	return EXIT_SUCCESS;
+}
Index: tools/mksunxiboot.README
===================================================================
--- /dev/null
+++ tools/mksunxiboot.README
@@ -0,0 +1,13 @@
+This program make a arm binary file can be loaded by Allwinner A10 and releated
+chips from storage media such as nand and mmc.
+
+More information about A10 boot, please refer to
+http://rhombus-tech.net/allwinner_a10/a10_boot_process/
+
+To compile this program, just type make, you will get 'mksunxiboot'.
+
+To use it,
+$./mksunxiboot u-boot.bin u-boot-mmc.bin
+then you can write it to a mmc card with dd.
+$sudo dd if=u-boot-mmc.bin of=/dev/sdb bs=1024 seek=8
+then insert your mmc card to your A10 tablet, you can boot from mmc card.
openSUSE Build Service is sponsored by