diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 109d49f57db7b4a409064fbb49fa5bc263c17f3c..8f910f39a37ec5350d094070fdfdd6a2986519b8 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -450,9 +450,15 @@ config TARGET_SUN4I
 config TARGET_SUN5I
 	bool "Support sun5i"
 
+config TARGET_SUN6I
+	bool "Support sun6i"
+
 config TARGET_SUN7I
 	bool "Support sun7i"
 
+config TARGET_SUN8I
+	bool "Support sun8i"
+
 config TARGET_SNOWBALL
 	bool "Support snowball"
 
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
index e9721b27b64595d27918a396954329ae68acc44c..24f1daee64766d1631122a65dcb13dcb88dbc8ea 100644
--- a/arch/arm/cpu/armv7/sunxi/Makefile
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -11,9 +11,13 @@ obj-y	+= timer.o
 obj-y	+= board.o
 obj-y	+= clock.o
 obj-y	+= pinmux.o
+obj-$(CONFIG_SUN6I)	+= prcm.o
+obj-$(CONFIG_SUN8I)	+= prcm.o
 obj-$(CONFIG_SUN4I)	+= clock_sun4i.o
 obj-$(CONFIG_SUN5I)	+= clock_sun4i.o
+obj-$(CONFIG_SUN6I)	+= clock_sun6i.o
 obj-$(CONFIG_SUN7I)	+= clock_sun4i.o
+obj-$(CONFIG_SUN8I)	+= clock_sun6i.o
 
 ifndef CONFIG_SPL_BUILD
 obj-y	+= cpu_info.o
diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c
index f2cedbb1568a8eaf5dd7c8a3c6ef4acc085286a1..06eb6768e8f2b58ddbe1b2408157f8e4e89ccaab 100644
--- a/arch/arm/cpu/armv7/sunxi/board.c
+++ b/arch/arm/cpu/armv7/sunxi/board.c
@@ -50,18 +50,35 @@ u32 spl_boot_mode(void)
 
 int gpio_init(void)
 {
-#if CONFIG_CONS_INDEX == 1 && (defined(CONFIG_SUN4I) || defined(CONFIG_SUN7I))
+#if CONFIG_CONS_INDEX == 1 && defined(CONFIG_UART0_PORT_F)
+#if defined(CONFIG_SUN4I) || defined(CONFIG_SUN7I)
+	/* 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);
+	sunxi_gpio_set_pull(SUNXI_GPF(4), 1);
+#elif CONFIG_CONS_INDEX == 1 && (defined(CONFIG_SUN4I) || defined(CONFIG_SUN7I))
 	sunxi_gpio_set_cfgpin(SUNXI_GPB(22), SUN4I_GPB22_UART0_TX);
 	sunxi_gpio_set_cfgpin(SUNXI_GPB(23), SUN4I_GPB23_UART0_RX);
-	sunxi_gpio_set_pull(SUNXI_GPB(23), 1);
+	sunxi_gpio_set_pull(SUNXI_GPB(23), SUNXI_GPIO_PULL_UP);
 #elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_SUN5I)
 	sunxi_gpio_set_cfgpin(SUNXI_GPB(19), SUN5I_GPB19_UART0_TX);
 	sunxi_gpio_set_cfgpin(SUNXI_GPB(20), SUN5I_GPB20_UART0_RX);
-	sunxi_gpio_set_pull(SUNXI_GPB(20), 1);
+	sunxi_gpio_set_pull(SUNXI_GPB(20), SUNXI_GPIO_PULL_UP);
+#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_SUN6I)
+	sunxi_gpio_set_cfgpin(SUNXI_GPH(20), SUN6I_GPH20_UART0_TX);
+	sunxi_gpio_set_cfgpin(SUNXI_GPH(21), SUN6I_GPH21_UART0_RX);
+	sunxi_gpio_set_pull(SUNXI_GPH(21), SUNXI_GPIO_PULL_UP);
 #elif CONFIG_CONS_INDEX == 2 && defined(CONFIG_SUN5I)
 	sunxi_gpio_set_cfgpin(SUNXI_GPG(3), SUN5I_GPG3_UART1_TX);
 	sunxi_gpio_set_cfgpin(SUNXI_GPG(4), SUN5I_GPG4_UART1_RX);
-	sunxi_gpio_set_pull(SUNXI_GPG(4), 1);
+	sunxi_gpio_set_pull(SUNXI_GPG(4), SUNXI_GPIO_PULL_UP);
+#elif CONFIG_CONS_INDEX == 5 && defined(CONFIG_SUN8I)
+	sunxi_gpio_set_cfgpin(SUNXI_GPL(2), SUN8I_GPL2_R_UART_TX);
+	sunxi_gpio_set_cfgpin(SUNXI_GPL(3), SUN8I_GPL3_R_UART_RX);
+	sunxi_gpio_set_pull(SUNXI_GPL(3), SUNXI_GPIO_PULL_UP);
 #else
 #error Unsupported console port number. Please fix pin mux settings in board.c
 #endif
@@ -71,6 +88,7 @@ int gpio_init(void)
 
 void reset_cpu(ulong addr)
 {
+#if defined(CONFIG_SUN4I) || defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
 	static const struct sunxi_wdog *wdog =
 		 &((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog;
 
@@ -82,12 +100,22 @@ void reset_cpu(ulong addr)
 		/* sun5i sometimes gets stuck without this */
 		writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode);
 	}
+#else /* CONFIG_SUN6I || CONFIG_SUN8I || .. */
+	static const struct sunxi_wdog *wdog =
+		 ((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog;
+
+	/* Set the watchdog for its shortest interval (.5s) and wait */
+	writel(WDT_CFG_RESET, &wdog->cfg);
+	writel(WDT_MODE_EN, &wdog->mode);
+	writel(WDT_CTRL_KEY | WDT_CTRL_RESTART, &wdog->ctl);
+#endif
 }
 
 /* do some early init */
 void s_init(void)
 {
-#if !defined CONFIG_SPL_BUILD && (defined CONFIG_SUN7I || defined CONFIG_SUN6I)
+#if !defined CONFIG_SPL_BUILD && (defined CONFIG_SUN7I || \
+		defined CONFIG_SUN6I || defined CONFIG_SUN8I)
 	/* Enable SMP mode for CPU0, by setting bit 6 of Auxiliary Ctl reg */
 	asm volatile(
 		"mrc p15, 0, r0, c1, c0, 1\n"
diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun4i.c b/arch/arm/cpu/armv7/sunxi/clock_sun4i.c
index ecbdb0162b2efcd17f6c6ee2a357543e2a71cab2..4a0d64fb30e64db6b996d35e4134469a0ccfd385 100644
--- a/arch/arm/cpu/armv7/sunxi/clock_sun4i.c
+++ b/arch/arm/cpu/armv7/sunxi/clock_sun4i.c
@@ -180,6 +180,17 @@ void clock_set_pll1(unsigned int hz)
 }
 #endif
 
+unsigned int clock_get_pll5p(void)
+{
+	struct sunxi_ccm_reg *const ccm =
+		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+	uint32_t rval = readl(&ccm->pll5_cfg);
+	int n = ((rval & CCM_PLL5_CTRL_N_MASK) >> CCM_PLL5_CTRL_N_SHIFT);
+	int k = ((rval & CCM_PLL5_CTRL_K_MASK) >> CCM_PLL5_CTRL_K_SHIFT) + 1;
+	int p = ((rval & CCM_PLL5_CTRL_P_MASK) >> CCM_PLL5_CTRL_P_SHIFT);
+	return (24000000 * n * k) >> p;
+}
+
 unsigned int clock_get_pll6(void)
 {
 	struct sunxi_ccm_reg *const ccm =
diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun6i.c b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
new file mode 100644
index 0000000000000000000000000000000000000000..1eae9767d0da4ecad39f70be69727d904a141732
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/clock_sun6i.c
@@ -0,0 +1,76 @@
+/*
+ * sun6i specific clock code
+ *
+ * (C) Copyright 2007-2012
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/prcm.h>
+#include <asm/arch/sys_proto.h>
+
+void clock_init_uart(void)
+{
+	struct sunxi_ccm_reg *const ccm =
+		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+#if CONFIG_CONS_INDEX < 5
+	/* uart clock source is apb2 */
+	writel(APB2_CLK_SRC_OSC24M|
+	       APB2_CLK_RATE_N_1|
+	       APB2_CLK_RATE_M(1),
+	       &ccm->apb2_div);
+
+	/* open the clock for uart */
+	setbits_le32(&ccm->apb2_gate,
+		     CLK_GATE_OPEN << (APB2_GATE_UART_SHIFT +
+				       CONFIG_CONS_INDEX - 1));
+
+	/* deassert uart reset */
+	setbits_le32(&ccm->apb2_reset_cfg,
+		     1 << (APB2_RESET_UART_SHIFT +
+			   CONFIG_CONS_INDEX - 1));
+#else
+	/* enable R_PIO and R_UART clocks, and de-assert resets */
+	prcm_apb0_enable(PRCM_APB0_GATE_PIO | PRCM_APB0_GATE_UART);
+#endif
+
+	/* Dup with clock_init_safe(), drop once sun6i SPL support lands */
+	writel(PLL6_CFG_DEFAULT, &ccm->pll6_cfg);
+}
+
+int clock_twi_onoff(int port, int state)
+{
+	struct sunxi_ccm_reg *const ccm =
+		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+	if (port > 3)
+		return -1;
+
+	/* set the apb clock gate for twi */
+	if (state)
+		setbits_le32(&ccm->apb2_gate,
+			     CLK_GATE_OPEN << (APB2_GATE_TWI_SHIFT+port));
+	else
+		clrbits_le32(&ccm->apb2_gate,
+			     CLK_GATE_OPEN << (APB2_GATE_TWI_SHIFT+port));
+
+	return 0;
+}
+
+unsigned int clock_get_pll6(void)
+{
+	struct sunxi_ccm_reg *const ccm =
+		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+	uint32_t rval = readl(&ccm->pll6_cfg);
+	int n = ((rval & CCM_PLL6_CTRL_N_MASK) >> CCM_PLL6_CTRL_N_SHIFT) + 1;
+	int k = ((rval & CCM_PLL6_CTRL_K_MASK) >> CCM_PLL6_CTRL_K_SHIFT) + 1;
+	return 24000000 * n * k / 2;
+}
diff --git a/arch/arm/cpu/armv7/sunxi/cpu_info.c b/arch/arm/cpu/armv7/sunxi/cpu_info.c
index 5cf35acc1e60127df04bc9b2c178ed5f46d8671c..4f2a09cd2e28cbd69a498bab61c06341f4235473 100644
--- a/arch/arm/cpu/armv7/sunxi/cpu_info.c
+++ b/arch/arm/cpu/armv7/sunxi/cpu_info.c
@@ -23,8 +23,12 @@ int print_cpuinfo(void)
 	case 7: puts("CPU:   Allwinner A10s (SUN5I)\n"); break;
 	default: puts("CPU:   Allwinner A1X (SUN5I)\n");
 	}
+#elif defined CONFIG_SUN6I
+	puts("CPU:   Allwinner A31 (SUN6I)\n");
 #elif defined CONFIG_SUN7I
 	puts("CPU:   Allwinner A20 (SUN7I)\n");
+#elif defined CONFIG_SUN8I
+	puts("CPU:   Allwinner A23 (SUN8I)\n");
 #else
 #warning Please update cpu_info.c with correct CPU information
 	puts("CPU:   SUNXI Family\n");
diff --git a/arch/arm/cpu/armv7/sunxi/dram.c b/arch/arm/cpu/armv7/sunxi/dram.c
index 584f7420d7d239098e8924db9185fd2a7f24c5a3..3cf3cbf19adb25fce553a4f88a8d35ca6909999a 100644
--- a/arch/arm/cpu/armv7/sunxi/dram.c
+++ b/arch/arm/cpu/armv7/sunxi/dram.c
@@ -252,15 +252,9 @@ static void mctl_setup_dram_clock(u32 clk, u32 mbus_clk)
 {
 	u32 reg_val;
 	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
-
-	/* PLL5P and PLL6 are the potential clock sources for MBUS */
-	u32 pll6x_div, pll5p_div;
-	u32 pll6x_clk = clock_get_pll6() / 1000000;
-	u32 pll5p_clk = clk / 24 * 48;
+	u32 pll5p_clk, pll6x_clk;
+	u32 pll5p_div, pll6x_div;
 	u32 pll5p_rate, pll6x_rate;
-#ifdef CONFIG_SUN7I
-	pll6x_clk *= 2; /* sun7i uses PLL6*2, sun5i uses just PLL6 */
-#endif
 
 	/* setup DRAM PLL */
 	reg_val = readl(&ccm->pll5_cfg);
@@ -268,33 +262,32 @@ static void mctl_setup_dram_clock(u32 clk, u32 mbus_clk)
 	reg_val &= ~CCM_PLL5_CTRL_K_MASK;		/* set K to 0 (x1) */
 	reg_val &= ~CCM_PLL5_CTRL_N_MASK;		/* set N to 0 (x0) */
 	reg_val &= ~CCM_PLL5_CTRL_P_MASK;		/* set P to 0 (x1) */
+#ifdef CONFIG_OLD_SUNXI_KERNEL_COMPAT
+	/* Old kernels are hardcoded to P=1 (divide by 2) */
+	reg_val |= CCM_PLL5_CTRL_P(1);
+#endif
 	if (clk >= 540 && clk < 552) {
-		/* dram = 540MHz, pll5p = 1080MHz */
-		pll5p_clk = 1080;
+		/* dram = 540MHz */
 		reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
 		reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3));
 		reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(15));
 	} else if (clk >= 512 && clk < 528) {
-		/* dram = 512MHz, pll5p = 1536MHz */
-		pll5p_clk = 1536;
+		/* dram = 512MHz */
 		reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(3));
 		reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(4));
 		reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(16));
 	} else if (clk >= 496 && clk < 504) {
-		/* dram = 496MHz, pll5p = 1488MHz */
-		pll5p_clk = 1488;
+		/* dram = 496MHz */
 		reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(3));
 		reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(2));
 		reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(31));
 	} else if (clk >= 468 && clk < 480) {
-		/* dram = 468MHz, pll5p = 936MHz */
-		pll5p_clk = 936;
+		/* dram = 468MHz */
 		reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
 		reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3));
 		reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(13));
 	} else if (clk >= 396 && clk < 408) {
-		/* dram = 396MHz, pll5p = 792MHz */
-		pll5p_clk = 792;
+		/* dram = 396MHz */
 		reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
 		reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(3));
 		reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(11));
@@ -322,6 +315,13 @@ static void mctl_setup_dram_clock(u32 clk, u32 mbus_clk)
 	/* setup MBUS clock */
 	if (!mbus_clk)
 		mbus_clk = 300;
+
+	/* PLL5P and PLL6 are the potential clock sources for MBUS */
+	pll6x_clk = clock_get_pll6() / 1000000;
+#ifdef CONFIG_SUN7I
+	pll6x_clk *= 2; /* sun7i uses PLL6*2, sun5i uses just PLL6 */
+#endif
+	pll5p_clk = clock_get_pll5p() / 1000000;
 	pll6x_div = DIV_ROUND_UP(pll6x_clk, mbus_clk);
 	pll5p_div = DIV_ROUND_UP(pll5p_clk, mbus_clk);
 	pll6x_rate = pll6x_clk / pll6x_div;
diff --git a/arch/arm/cpu/armv7/sunxi/prcm.c b/arch/arm/cpu/armv7/sunxi/prcm.c
new file mode 100644
index 0000000000000000000000000000000000000000..19b4938dc9742c0ed453529838821bc17eb8747c
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/prcm.c
@@ -0,0 +1,35 @@
+/*
+ * Sunxi A31 Power Management Unit
+ *
+ * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
+ * http://linux-sunxi.org
+ *
+ * Based on sun6i sources and earlier U-Boot Allwinner A10 SPL work
+ *
+ * (C) Copyright 2006-2013
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Berg Xing <bergxing@allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/prcm.h>
+#include <asm/arch/sys_proto.h>
+
+/* APB0 clock gate and reset bit offsets are the same. */
+void prcm_apb0_enable(u32 flags)
+{
+	struct sunxi_prcm_reg *prcm =
+		(struct sunxi_prcm_reg *)SUNXI_PRCM_BASE;
+
+	/* open the clock for module */
+	setbits_le32(&prcm->apb0_gate, flags);
+
+	/* deassert reset for module */
+	setbits_le32(&prcm->apb0_reset, flags);
+}
diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
index 5669f392fab7a38e56558cc2f74ea5c903009b30..c562f621c22624ddf8589afb3e2cc3090eac8b1c 100644
--- a/arch/arm/include/asm/arch-sunxi/clock.h
+++ b/arch/arm/include/asm/arch-sunxi/clock.h
@@ -15,12 +15,17 @@
 #define CLK_GATE_CLOSE			0x0
 
 /* clock control module regs definition */
+#if defined(CONFIG_SUN6I) || defined(CONFIG_SUN8I)
+#include <asm/arch/clock_sun6i.h>
+#else
 #include <asm/arch/clock_sun4i.h>
+#endif
 
 #ifndef __ASSEMBLY__
 int clock_init(void);
 int clock_twi_onoff(int port, int state);
 void clock_set_pll1(unsigned int hz);
+unsigned int clock_get_pll5p(void);
 unsigned int clock_get_pll6(void);
 void clock_init_safe(void);
 void clock_init_uart(void);
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
index 1ba997adf9f8b4bf1f2b71c71bc5f1816e308794..90af8e250699b835bbf94c080e798d9eaa575121 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
@@ -199,13 +199,16 @@ struct sunxi_ccm_reg {
 #define CCM_PLL5_CTRL_M1_MASK CCM_PLL5_CTRL_M1(0x3)
 #define CCM_PLL5_CTRL_M1_X(n) ((n) - 1)
 #define CCM_PLL5_CTRL_K(n) (((n) & 0x3) << 4)
+#define CCM_PLL5_CTRL_K_SHIFT 4
 #define CCM_PLL5_CTRL_K_MASK CCM_PLL5_CTRL_K(0x3)
 #define CCM_PLL5_CTRL_K_X(n) ((n) - 1)
 #define CCM_PLL5_CTRL_LDO (0x1 << 7)
 #define CCM_PLL5_CTRL_N(n) (((n) & 0x1f) << 8)
+#define CCM_PLL5_CTRL_N_SHIFT 8
 #define CCM_PLL5_CTRL_N_MASK CCM_PLL5_CTRL_N(0x1f)
 #define CCM_PLL5_CTRL_N_X(n) (n)
 #define CCM_PLL5_CTRL_P(n) (((n) & 0x3) << 16)
+#define CCM_PLL5_CTRL_P_SHIFT 16
 #define CCM_PLL5_CTRL_P_MASK CCM_PLL5_CTRL_P(0x3)
 #define CCM_PLL5_CTRL_P_X(n) ((n) - 1)
 #define CCM_PLL5_CTRL_BW (0x1 << 18)
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
new file mode 100644
index 0000000000000000000000000000000000000000..1397b35889837e7b144f9dc8f1f65a1dce7d7b13
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -0,0 +1,205 @@
+/*
+ * sun6i clock register definitions
+ *
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _SUNXI_CLOCK_SUN6I_H
+#define _SUNXI_CLOCK_SUN6I_H
+
+struct sunxi_ccm_reg {
+	u32 pll1_cfg;		/* 0x00 pll1 control */
+	u32 reserved0;
+	u32 pll2_cfg;		/* 0x08 pll2 control */
+	u32 reserved1;
+	u32 pll3_cfg;		/* 0x10 pll3 control */
+	u32 reserved2;
+	u32 pll4_cfg;		/* 0x18 pll4 control */
+	u32 reserved3;
+	u32 pll5_cfg;		/* 0x20 pll5 control */
+	u32 reserved4;
+	u32 pll6_cfg;		/* 0x28 pll6 control */
+	u32 reserved5;
+	u32 pll7_cfg;		/* 0x30 pll7 control */
+	u32 reserved6;
+	u32 pll8_cfg;		/* 0x38 pll8 control */
+	u32 reserved7;
+	u32 mipi_pll_cfg;	/* 0x40 MIPI pll control */
+	u32 pll9_cfg;		/* 0x44 pll9 control */
+	u32 pll10_cfg;		/* 0x48 pll10 control */
+	u32 reserved8;
+	u32 cpu_axi_cfg;	/* 0x50 CPU/AXI divide ratio */
+	u32 ahb1_apb1_div;	/* 0x54 AHB1/APB1 divide ratio */
+	u32 apb2_div;		/* 0x58 APB2 divide ratio */
+	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 apb1_gate;		/* 0x68 apb1 module clock gating */
+	u32 apb2_gate;		/* 0x6c apb2 module clock gating */
+	u32 reserved9[4];
+	u32 nand0_clk_cfg;	/* 0x80 nand0 clock control */
+	u32 nand1_clk_cfg;	/* 0x84 nand1 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 security system clock control */
+	u32 spi0_clk_cfg;	/* 0xa0 spi0 clock control */
+	u32 spi1_clk_cfg;	/* 0xa4 spi1 clock control */
+	u32 spi2_clk_cfg;	/* 0xa8 spi2 clock control */
+	u32 spi3_clk_cfg;	/* 0xac spi3 clock control */
+	u32 i2s0_clk_cfg;	/* 0xb0 I2S0 clock control*/
+	u32 i2s1_clk_cfg;	/* 0xb4 I2S1 clock control */
+	u32 reserved10[2];
+	u32 spdif_clk_cfg;	/* 0xc0 SPDIF clock control */
+	u32 reserved11[2];
+	u32 usb_clk_cfg;	/* 0xcc USB clock control */
+	u32 gmac_clk_cfg;	/* 0xd0 GMAC clock control */
+	u32 reserved12[7];
+	u32 mdfs_clk_cfg;	/* 0xf0 MDFS clock control */
+	u32 dram_clk_cfg;	/* 0xf4 DRAM configuration clock control */
+	u32 reserved13[2];
+	u32 dram_clk_gate;	/* 0x100 DRAM module gating */
+	u32 be0_clk_cfg;	/* 0x104 BE0 module clock */
+	u32 be1_clk_cfg;	/* 0x108 BE1 module clock */
+	u32 fe0_clk_cfg;	/* 0x10c FE0 module clock */
+	u32 fe1_clk_cfg;	/* 0x110 FE1 module clock */
+	u32 mp_clk_cfg;		/* 0x114 MP module clock */
+	u32 lcd0_ch0_clk_cfg;	/* 0x118 LCD0 CH0 module clock */
+	u32 lcd1_ch0_clk_cfg;	/* 0x11c LCD1 CH0 module clock */
+	u32 reserved14[3];
+	u32 lcd0_ch1_clk_cfg;	/* 0x12c LCD0 CH1 module clock */
+	u32 lcd1_ch1_clk_cfg;	/* 0x130 LCD1 CH1 module clock */
+	u32 csi0_clk_cfg;	/* 0x134 CSI0 module clock */
+	u32 csi1_clk_cfg;	/* 0x138 CSI1 module clock */
+	u32 ve_clk_cfg;		/* 0x13c VE module clock */
+	u32 adda_clk_cfg;	/* 0x140 ADDA module clock */
+	u32 avs_clk_cfg;	/* 0x144 AVS module clock */
+	u32 dmic_clk_cfg;	/* 0x148 Digital Mic module clock*/
+	u32 reserved15;
+	u32 hdmi_clk_cfg;	/* 0x150 HDMI module clock */
+	u32 ps_clk_cfg;		/* 0x154 PS module clock */
+	u32 mtc_clk_cfg;	/* 0x158 MTC module clock */
+	u32 mbus0_clk_cfg;	/* 0x15c MBUS0 module clock */
+	u32 mbus1_clk_cfg;	/* 0x160 MBUS1 module clock */
+	u32 reserved16;
+	u32 mipi_dsi_clk_cfg;	/* 0x168 MIPI DSI clock control */
+	u32 mipi_csi_clk_cfg;	/* 0x16c MIPI CSI clock control */
+	u32 reserved17[4];
+	u32 iep_drc0_clk_cfg;	/* 0x180 IEP DRC0 module clock */
+	u32 iep_drc1_clk_cfg;	/* 0x184 IEP DRC1 module clock */
+	u32 iep_deu0_clk_cfg;	/* 0x188 IEP DEU0 module clock */
+	u32 iep_deu1_clk_cfg;	/* 0x18c IEP DEU1 module clock */
+	u32 reserved18[4];
+	u32 gpu_core_clk_cfg;	/* 0x1a0 GPU core clock config */
+	u32 gpu_mem_clk_cfg;	/* 0x1a4 GPU memory clock config */
+	u32 gpu_hyd_clk_cfg;	/* 0x1a0 GPU HYD clock config */
+	u32 reserved19[21];
+	u32 pll_lock;		/* 0x200 PLL Lock Time */
+	u32 pll1_lock;		/* 0x204 PLL1 Lock Time */
+	u32 reserved20[6];
+	u32 pll1_bias_cfg;	/* 0x220 PLL1 Bias config */
+	u32 pll2_bias_cfg;	/* 0x224 PLL2 Bias config */
+	u32 pll3_bias_cfg;	/* 0x228 PLL3 Bias config */
+	u32 pll4_bias_cfg;	/* 0x22c PLL4 Bias config */
+	u32 pll5_bias_cfg;	/* 0x230 PLL5 Bias config */
+	u32 pll6_bias_cfg;	/* 0x234 PLL6 Bias config */
+	u32 pll7_bias_cfg;	/* 0x238 PLL7 Bias config */
+	u32 pll8_bias_cfg;	/* 0x23c PLL8 Bias config */
+	u32 mipi_bias_cfg;	/* 0x240 MIPI Bias config */
+	u32 pll9_bias_cfg;	/* 0x244 PLL9 Bias config */
+	u32 pll10_bias_cfg;	/* 0x248 PLL10 Bias config */
+	u32 reserved21[13];
+	u32 pll1_pattern_cfg;	/* 0x280 PLL1 Pattern config */
+	u32 pll2_pattern_cfg;	/* 0x284 PLL2 Pattern config */
+	u32 pll3_pattern_cfg;	/* 0x288 PLL3 Pattern config */
+	u32 pll4_pattern_cfg;	/* 0x28c PLL4 Pattern config */
+	u32 pll5_pattern_cfg;	/* 0x290 PLL5 Pattern config */
+	u32 pll6_pattern_cfg;	/* 0x294 PLL6 Pattern config */
+	u32 pll7_pattern_cfg;	/* 0x298 PLL7 Pattern config */
+	u32 pll8_pattern_cfg;	/* 0x29c PLL8 Pattern config */
+	u32 mipi_pattern_cfg;	/* 0x2a0 MIPI Pattern config */
+	u32 pll9_pattern_cfg;	/* 0x2a4 PLL9 Pattern config */
+	u32 pll10_pattern_cfg;	/* 0x2a8 PLL10 Pattern config */
+	u32 reserved22[5];
+	u32 ahb_reset0_cfg;	/* 0x2c0 AHB1 Reset 0 config */
+	u32 ahb_reset1_cfg;	/* 0x2c4 AHB1 Reset 1 config */
+	u32 ahb_reset2_cfg;	/* 0x2c8 AHB1 Reset 2 config */
+	u32 reserved23;
+	u32 apb1_reset_cfg;	/* 0x2d0 APB1 Reset config */
+	u32 reserved24;
+	u32 apb2_reset_cfg;	/* 0x2d8 APB2 Reset config */
+};
+
+/* apb2 bit field */
+#define APB2_CLK_SRC_LOSC		(0x0 << 24)
+#define APB2_CLK_SRC_OSC24M		(0x1 << 24)
+#define APB2_CLK_SRC_PLL6		(0x2 << 24)
+#define APB2_CLK_SRC_MASK		(0x3 << 24)
+#define APB2_CLK_RATE_N_1		(0x0 << 16)
+#define APB2_CLK_RATE_N_2		(0x1 << 16)
+#define APB2_CLK_RATE_N_4		(0x2 << 16)
+#define APB2_CLK_RATE_N_8		(0x3 << 16)
+#define APB2_CLK_RATE_N_MASK		(3 << 16)
+#define APB2_CLK_RATE_M(m)		(((m)-1) << 0)
+#define APB2_CLK_RATE_M_MASK            (0x1f << 0)
+
+/* apb2 gate field */
+#define APB2_GATE_UART_SHIFT	(16)
+#define APB2_GATE_UART_MASK		(0xff << APB2_GATE_UART_SHIFT)
+#define APB2_GATE_TWI_SHIFT	(0)
+#define APB2_GATE_TWI_MASK		(0xf << APB2_GATE_TWI_SHIFT)
+
+/* cpu_axi_cfg bits */
+#define AXI_DIV_SHIFT			0
+#define ATB_DIV_SHIFT			8
+#define CPU_CLK_SRC_SHIFT		16
+
+#define AXI_DIV_1			0
+#define AXI_DIV_2			1
+#define AXI_DIV_3			2
+#define AXI_DIV_4			3
+#define ATB_DIV_1			0
+#define ATB_DIV_2			1
+#define ATB_DIV_4			2
+#define CPU_CLK_SRC_OSC24M		1
+#define CPU_CLK_SRC_PLL1		2
+
+#define PLL1_CFG_DEFAULT		0x90011b21
+
+#define PLL6_CFG_DEFAULT		0x90041811
+
+#define CCM_PLL6_CTRL_N_SHIFT		8
+#define CCM_PLL6_CTRL_N_MASK		(0x1f << CCM_PLL6_CTRL_N_SHIFT)
+#define CCM_PLL6_CTRL_K_SHIFT		4
+#define CCM_PLL6_CTRL_K_MASK		(0x3 << CCM_PLL6_CTRL_K_SHIFT)
+
+#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_MMC(n)		(AHB_GATE_OFFSET_MMC0 + (n))
+
+#define CCM_MMC_CTRL_OSCM24 (0x0 << 24)
+#define CCM_MMC_CTRL_PLL6   (0x1 << 24)
+
+#define CCM_MMC_CTRL_ENABLE (0x1 << 31)
+
+#define AHB_RESET_OFFSET_MMC3		11
+#define AHB_RESET_OFFSET_MMC2		10
+#define AHB_RESET_OFFSET_MMC1		9
+#define AHB_RESET_OFFSET_MMC0		8
+#define AHB_RESET_OFFSET_MMC(n)		(AHB_RESET_OFFSET_MMC0 + (n))
+
+/* apb2 reset */
+#define APB2_RESET_UART_SHIFT		(16)
+#define APB2_RESET_UART_MASK		(0xff << APB2_RESET_UART_SHIFT)
+#define APB2_RESET_TWI_SHIFT		(0)
+#define APB2_RESET_TWI_MASK		(0xf << APB2_RESET_TWI_SHIFT)
+
+#endif /* _SUNXI_CLOCK_SUN6I_H */
diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
index a987e51d576902d9ec94c6f4196a97e14e899e7f..0de79a0d50890b8463b59b83169ac0703748aec0 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu.h
@@ -95,6 +95,11 @@
 #define SUNXI_MALI400_BASE		0x01c40000
 #define SUNXI_GMAC_BASE			0x01c50000
 
+#define SUNXI_DRAM_COM_BASE		0x01c62000
+#define SUNXI_DRAM_CTL_BASE		0x01c63000
+#define SUNXI_DRAM_PHY_CH1_BASE		0x01c65000
+#define SUNXI_DRAM_PHY_CH2_BASE		0x01c66000
+
 /* module sram */
 #define SUNXI_SRAM_C_BASE		0x01d00000
 
@@ -105,6 +110,11 @@
 #define SUNXI_MP_BASE			0x01e80000
 #define SUNXI_AVG_BASE			0x01ea0000
 
+#define SUNXI_PRCM_BASE			0x01f01400
+#define SUNXI_R_UART_BASE		0x01f02800
+#define SUNXI_R_PIO_BASE		0x01f02c00
+#define SUNXI_P2WI_BASE			0x01f03400
+
 /* CoreSight Debug Module */
 #define SUNXI_CSDM_BASE			0x3f500000
 
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
index f7f3d8c41ad4c3cd0f8e5673513b9477f15541dc..7bb649950a982d19d9ea293352a35e82414e06ad 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
@@ -10,6 +10,7 @@
 #define _SUNXI_GPIO_H
 
 #include <linux/types.h>
+#include <asm/arch/cpu.h>
 
 /*
  * sunxi has 9 banks of gpio, they are:
@@ -27,8 +28,27 @@
 #define SUNXI_GPIO_G	6
 #define SUNXI_GPIO_H	7
 #define SUNXI_GPIO_I	8
+
+/*
+ * This defines the number of GPIO banks for the _main_ GPIO controller.
+ * You should fix up the padding in struct sunxi_gpio_reg below if you
+ * change this.
+ */
 #define SUNXI_GPIO_BANKS 9
 
+/*
+ * sun6i/sun8i and later SoCs have an additional GPIO controller (R_PIO)
+ * at a different register offset.
+ *
+ * sun6i has 2 banks:
+ * PL0 - PL8  | PM0 - PM7
+ *
+ * sun8i has 1 bank:
+ * PL0 - PL11
+ */
+#define SUNXI_GPIO_L	11
+#define SUNXI_GPIO_M	12
+
 struct sunxi_gpio {
 	u32 cfg[4];
 	u32 dat;
@@ -50,8 +70,9 @@ struct sunxi_gpio_reg {
 	struct sunxi_gpio_int gpio_int;
 };
 
-#define BANK_TO_GPIO(bank) \
-	&((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank]
+#define BANK_TO_GPIO(bank)	(((bank) < SUNXI_GPIO_L) ? \
+	&((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank] : \
+	&((struct sunxi_gpio_reg *)SUNXI_R_PIO_BASE)->gpio_bank[(bank) - SUNXI_GPIO_L])
 
 #define GPIO_BANK(pin)		((pin) >> 5)
 #define GPIO_NUM(pin)		((pin) & 0x1f)
@@ -75,6 +96,8 @@ struct sunxi_gpio_reg {
 #define SUNXI_GPIO_G_NR		32
 #define SUNXI_GPIO_H_NR		32
 #define SUNXI_GPIO_I_NR		32
+#define SUNXI_GPIO_L_NR		32
+#define SUNXI_GPIO_M_NR		32
 
 #define SUNXI_GPIO_NEXT(__gpio) \
 	((__gpio##_START) + (__gpio##_NR) + 0)
@@ -89,6 +112,8 @@ enum sunxi_gpio_number {
 	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_L_START = 352,
+	SUNXI_GPIO_M_START = SUNXI_GPIO_NEXT(SUNXI_GPIO_L),
 };
 
 /* SUNXI GPIO number definitions */
@@ -101,6 +126,8 @@ enum sunxi_gpio_number {
 #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))
+#define SUNXI_GPL(_nr)	(SUNXI_GPIO_L_START + (_nr))
+#define SUNXI_GPM(_nr)	(SUNXI_GPIO_M_START + (_nr))
 
 /* GPIO pin function config */
 #define SUNXI_GPIO_INPUT	0
@@ -117,6 +144,8 @@ enum sunxi_gpio_number {
 #define SUN5I_GPB19_UART0_TX	2
 #define SUN5I_GPB20_UART0_RX	2
 
+#define SUN5I_GPG3_SDC1		2
+
 #define SUN5I_GPG3_UART1_TX	4
 #define SUN5I_GPG4_UART1_RX	4
 
@@ -125,15 +154,27 @@ enum sunxi_gpio_number {
 #define SUNXI_GPF0_SDC0		2
 
 #define SUNXI_GPF2_SDC0		2
+
+#ifdef CONFIG_SUN8I
+#define SUNXI_GPF2_UART0_TX	3
+#define SUNXI_GPF4_UART0_RX	3
+#else
 #define SUNXI_GPF2_UART0_TX	4
 #define SUNXI_GPF4_UART0_RX	4
+#endif
 
 #define SUN4I_GPG0_SDC1		4
 
 #define SUN4I_GPH22_SDC1	5
 
+#define SUN6I_GPH20_UART0_TX	2
+#define SUN6I_GPH21_UART0_RX	2
+
 #define SUN4I_GPI4_SDC3		2
 
+#define SUN8I_GPL2_R_UART_TX	2
+#define SUN8I_GPL3_R_UART_RX	2
+
 /* GPIO pin pull-up/down config */
 #define SUNXI_GPIO_PULL_DISABLE	0
 #define SUNXI_GPIO_PULL_UP	1
diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h
index 53196e3b024c68f3232a1596f29910f16f2131f0..8a216740a722e4471f4f39680634fe9db861b354 100644
--- a/arch/arm/include/asm/arch-sunxi/mmc.h
+++ b/arch/arm/include/asm/arch-sunxi/mmc.h
@@ -43,7 +43,10 @@ struct sunxi_mmc {
 	u32 chda;		/* 0x90 */
 	u32 cbda;		/* 0x94 */
 	u32 res1[26];
-	u32 fifo;		/* 0x100 FIFO access address */
+#if defined(CONFIG_SUN6I) || defined(CONFIG_SUN8I)
+	u32 res2[64];
+#endif
+	u32 fifo;		/* 0x100 (0x200 on sun6i) FIFO access address */
 };
 
 #define SUNXI_MMC_CLK_POWERSAVE		(0x1 << 17)
@@ -120,5 +123,5 @@ struct sunxi_mmc {
 #define SUNXI_MMC_IDIE_TXIRQ		(0x1 << 0)
 #define SUNXI_MMC_IDIE_RXIRQ		(0x1 << 1)
 
-int sunxi_mmc_init(int sdc_no);
+struct mmc *sunxi_mmc_init(int sdc_no);
 #endif /* _SUNXI_MMC_H */
diff --git a/arch/arm/include/asm/arch-sunxi/prcm.h b/arch/arm/include/asm/arch-sunxi/prcm.h
new file mode 100644
index 0000000000000000000000000000000000000000..3d3bfa6cd1b0ccabf23ed0885123e739b9302199
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/prcm.h
@@ -0,0 +1,238 @@
+/*
+ * Sunxi A31 Power Management Unit register definition.
+ *
+ * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl>
+ * http://linux-sunxi.org
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Berg Xing <bergxing@allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _SUNXI_PRCM_H
+#define _SUNXI_PRCM_H
+
+#define __PRCM_CPUS_CFG_PRE(n) (((n) & 0x3) << 4)
+#define PRCM_CPUS_CFG_PRE_MASK __PRCM_CPUS_CFG_PRE(0x3)
+#define __PRCM_CPUS_CFG_PRE_DIV(n) (((n) >> 1) - 1)
+#define PRCM_CPUS_CFG_PRE_DIV(n) \
+	__PRCM_CPUS_CFG_PRE(__PRCM_CPUS_CFG_CLK_PRE(n))
+#define __PRCM_CPUS_CFG_POST(n) (((n) & 0x1f) << 8)
+#define PRCM_CPUS_CFG_POST_MASK __PRCM_CPUS_CFG_POST(0x1f)
+#define __PRCM_CPUS_CFG_POST_DIV(n) ((n) - 1)
+#define PRCM_CPUS_CFG_POST_DIV(n) \
+	__PRCM_CPUS_CFG_POST_DIV(__PRCM_CPUS_CFG_POST_DIV(n))
+#define __PRCM_CPUS_CFG_CLK_SRC(n) (((n) & 0x3) << 16)
+#define PRCM_CPUS_CFG_CLK_SRC_MASK __PRCM_CPUS_CFG_CLK_SRC(0x3)
+#define __PRCM_CPUS_CFG_CLK_SRC_LOSC 0x0
+#define __PRCM_CPUS_CFG_CLK_SRC_HOSC 0x1
+#define __PRCM_CPUS_CFG_CLK_SRC_PLL6 0x2
+#define __PRCM_CPUS_CFG_CLK_SRC_PDIV 0x3
+#define PRCM_CPUS_CFG_CLK_SRC_LOSC \
+	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_LOSC)
+#define PRCM_CPUS_CFG_CLK_SRC_HOSC \
+	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_HOSC)
+#define PRCM_CPUS_CFG_CLK_SRC_PLL6 \
+	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_PLL6)
+#define PRCM_CPUS_CFG_CLK_SRC_PDIV \
+	__PRCM_CPUS_CFG_CLK_SRC(__PRCM_CPUS_CFG_CLK_SRC_PDIV)
+
+#define __PRCM_APB0_RATIO(n) (((n) & 0x3) << 0)
+#define PRCM_APB0_RATIO_DIV_MASK __PRCM_APB0_RATIO_DIV(0x3)
+#define __PRCM_APB0_RATIO_DIV(n) (((n) >> 1) - 1)
+#define PRCM_APB0_RATIO_DIV(n) \
+	__PRCM_APB0_RATIO(__PRCM_APB0_RATIO_DIV(n))
+
+#define PRCM_CPU_CFG_NEON_CLK_EN (0x1 << 0)
+#define PRCM_CPU_CFG_CPU_CLK_EN (0x1 << 1)
+
+#define PRCM_APB0_GATE_PIO (0x1 << 0)
+#define PRCM_APB0_GATE_IR (0x1 << 1)
+#define PRCM_APB0_GATE_TIMER01 (0x1 << 2)
+#define PRCM_APB0_GATE_P2WI (0x1 << 3)
+#define PRCM_APB0_GATE_UART (0x1 << 4)
+#define PRCM_APB0_GATE_1WIRE (0x1 << 5)
+#define PRCM_APB0_GATE_I2C (0x1 << 6)
+
+#define PRCM_APB0_RESET_PIO (0x1 << 0)
+#define PRCM_APB0_RESET_IR (0x1 << 1)
+#define PRCM_APB0_RESET_TIMER01 (0x1 << 2)
+#define PRCM_APB0_RESET_P2WI (0x1 << 3)
+#define PRCM_APB0_RESET_UART (0x1 << 4)
+#define PRCM_APB0_RESET_1WIRE (0x1 << 5)
+#define PRCM_APB0_RESET_I2C (0x1 << 6)
+
+#define PRCM_PLL_CTRL_PLL_BIAS (0x1 << 0)
+#define PRCM_PLL_CTRL_HOSC_GAIN_ENH (0x1 << 1)
+#define __PRCM_PLL_CTRL_USB_CLK_SRC(n) (((n) & 0x3) << 4)
+#define PRCM_PLL_CTRL_USB_CLK_SRC_MASK \
+	__PRCM_PLL_CTRL_USB_CLK_SRC(0x3)
+#define __PRCM_PLL_CTRL_USB_CLK_0 0x0
+#define __PRCM_PLL_CTRL_USB_CLK_1 0x1
+#define __PRCM_PLL_CTRL_USB_CLK_2 0x2
+#define __PRCM_PLL_CTRL_USB_CLK_3 0x3
+#define PRCM_PLL_CTRL_USB_CLK_0 \
+	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_0)
+#define PRCM_PLL_CTRL_USB_CLK_1 \
+	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_1)
+#define PRCM_PLL_CTRL_USB_CLK_2 \
+	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_2)
+#define PRCM_PLL_CTRL_USB_CLK_3 \
+	__PRCM_PLL_CTRL_USB_CLK_SRC(__PRCM_PLL_CTRL_USB_CLK_3)
+#define __PRCM_PLL_CTRL_INT_PLL_IN_SEL(n) (((n) & 0x3) << 12)
+#define PRCM_PLL_CTRL_INT_PLL_IN_SEL_MASK \
+	__PRCM_PLL_CTRL_INT_PLL_IN_SEL(0x3)
+#define PRCM_PLL_CTRL_INT_PLL_IN_SEL(n) \
+	__PRCM_PLL_CTRL_INT_PLL_IN_SEL(n)
+#define __PRCM_PLL_CTRL_HOSC_CLK_SEL(n) (((n) & 0x3) << 20)
+#define PRCM_PLL_CTRL_HOSC_CLK_SEL_MASK \
+	__PRCM_PLL_CTRL_HOSC_CLK_SEL(0x3)
+#define __PRCM_PLL_CTRL_HOSC_CLK_0 0x0
+#define __PRCM_PLL_CTRL_HOSC_CLK_1 0x1
+#define __PRCM_PLL_CTRL_HOSC_CLK_2 0x2
+#define __PRCM_PLL_CTRL_HOSC_CLK_3 0x3
+#define PRCM_PLL_CTRL_HOSC_CLK_0 \
+	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_0)
+#define PRCM_PLL_CTRL_HOSC_CLK_1 \
+	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_1)
+#define PRCM_PLL_CTRL_HOSC_CLK_2 \
+	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_2)
+#define PRCM_PLL_CTRL_HOSC_CLK_3 \
+	__PRCM_PLL_CTRL_HOSC_CLK_SEL(__PRCM_PLL_CTRL_HOSC_CLK_3)
+#define PRCM_PLL_CTRL_PLL_TST_SRC_EXT (0x1 << 24)
+#define PRCM_PLL_CTRL_LDO_DIGITAL_EN (0x1 << 0)
+#define PRCM_PLL_CTRL_LDO_ANALOG_EN (0x1 << 1)
+#define PRCM_PLL_CTRL_EXT_OSC_EN (0x1 << 2)
+#define PRCM_PLL_CTRL_CLK_TST_EN (0x1 << 3)
+#define PRCM_PLL_CTRL_IN_PWR_HIGH (0x1 << 15) /* 3.3 for hi 2.5 for lo */
+#define __PRCM_PLL_CTRL_VDD_LDO_OUT(n) (((n) & 0x7) << 16)
+#define PRCM_PLL_CTRL_LDO_OUT_MASK \
+	__PRCM_PLL_CTRL_LDO_OUT(0x7)
+/* When using the low voltage 20 mV steps, and high voltage 30 mV steps */
+#define PRCM_PLL_CTRL_LDO_OUT_L(n) \
+	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1000) / 20) & 0x7)
+#define PRCM_PLL_CTRL_LDO_OUT_H(n) \
+	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) - 1160) / 30) & 0x7)
+#define PRCM_PLL_CTRL_LDO_OUT_LV(n) \
+	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 20) + 1000)
+#define PRCM_PLL_CTRL_LDO_OUT_HV(n) \
+	__PRCM_PLL_CTRL_VDD_LDO_OUT((((n) & 0x7) * 30) + 1160)
+#define PRCM_PLL_CTRL_LDO_KEY (0xa7 << 24)
+
+#define PRCM_CLK_1WIRE_GATE (0x1 << 31)
+
+#define __PRCM_CLK_MOD0_M(n) (((n) & 0xf) << 0)
+#define PRCM_CLK_MOD0_M_MASK __PRCM_CLK_MOD0_M(0xf)
+#define __PRCM_CLK_MOD0_M_X(n) (n - 1)
+#define PRCM_CLK_MOD0_M(n) __PRCM_CLK_MOD0_M(__PRCM_CLK_MOD0_M_X(n))
+#define PRCM_CLK_MOD0_OUT_PHASE(n) (((n) & 0x7) << 8)
+#define PRCM_CLK_MOD0_OUT_PHASE_MASK(n) PRCM_CLK_MOD0_OUT_PHASE(0x7)
+#define _PRCM_CLK_MOD0_N(n) (((n) & 0x3) << 16)
+#define PRCM_CLK_MOD0_N_MASK __PRCM_CLK_MOD_N(0x3)
+#define __PRCM_CLK_MOD0_N_X(n) (((n) >> 1) - 1)
+#define PRCM_CLK_MOD0_N(n) __PRCM_CLK_MOD0_N(__PRCM_CLK_MOD0_N_X(n))
+#define PRCM_CLK_MOD0_SMPL_PHASE(n) (((n) & 0x7) << 20)
+#define PRCM_CLK_MOD0_SMPL_PHASE_MASK PRCM_CLK_MOD0_SMPL_PHASE(0x7)
+#define PRCM_CLK_MOD0_SRC_SEL(n) (((n) & 0x7) << 24)
+#define PRCM_CLK_MOD0_SRC_SEL_MASK PRCM_CLK_MOD0_SRC_SEL(0x7)
+#define PRCM_CLK_MOD0_GATE_EN (0x1 << 31)
+
+#define PRCM_APB0_RESET_PIO (0x1 << 0)
+#define PRCM_APB0_RESET_IR (0x1 << 1)
+#define PRCM_APB0_RESET_TIMER01 (0x1 << 2)
+#define PRCM_APB0_RESET_P2WI (0x1 << 3)
+#define PRCM_APB0_RESET_UART (0x1 << 4)
+#define PRCM_APB0_RESET_1WIRE (0x1 << 5)
+#define PRCM_APB0_RESET_I2C (0x1 << 6)
+
+#define __PRCM_CLK_OUTD_M(n) (((n) & 0x7) << 8)
+#define PRCM_CLK_OUTD_M_MASK __PRCM_CLK_OUTD_M(0x7)
+#define __PRCM_CLK_OUTD_M_X() ((n) - 1)
+#define PRCM_CLK_OUTD_M(n) __PRCM_CLK_OUTD_M(__PRCM_CLK_OUTD_M_X(n))
+#define __PRCM_CLK_OUTD_N(n) (((n) & 0x7) << 20)
+#define PRCM_CLK_OUTD_N_MASK __PRCM_CLK_OUTD_N(0x7)
+#define __PRCM_CLK_OUTD_N_X(n) (((n) >> 1) - 1)
+#define PRCM_CLK_OUTD_N(n) __PRCM_CLK_OUTD_N(__PRCM_CLK_OUTD_N_X(n)
+#define __PRCM_CLK_OUTD_SRC_SEL(n) (((n) & 0x3) << 24)
+#define PRCM_CLK_OUTD_SRC_SEL_MASK __PRCM_CLK_OUTD_SRC_SEL(0x3)
+#define __PRCM_CLK_OUTD_SRC_LOSC2 0x0
+#define __PRCM_CLK_OUTD_SRC_LOSC 0x1
+#define __PRCM_CLK_OUTD_SRC_HOSC 0x2
+#define __PRCM_CLK_OUTD_SRC_ERR 0x3
+#define PRCM_CLK_OUTD_SRC_LOSC2 \
+#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_LOSC2)
+#define PRCM_CLK_OUTD_SRC_LOSC \
+#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_LOSC)
+#define PRCM_CLK_OUTD_SRC_HOSC \
+#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_HOSC)
+#define PRCM_CLK_OUTD_SRC_ERR \
+#deifne __PRCM_CLK_OUTD_SRC_SEL(__PRCM_CLK_OUTD_SRC_ERR)
+#define PRCM_CLK_OUTD_EN (0x1 << 31)
+
+#define PRCM_CPU0_PWROFF (0x1 << 0)
+#define PRCM_CPU1_PWROFF (0x1 << 1)
+#define PRCM_CPU2_PWROFF (0x1 << 2)
+#define PRCM_CPU3_PWROFF (0x1 << 3)
+#define PRCM_CPU_ALL_PWROFF (0xf << 0)
+
+#define PRCM_VDD_SYS_DRAM_CH0_PAD_HOLD_PWROFF (0x1 << 0)
+#define PRCM_VDD_SYS_DRAM_CH1_PAD_HOLD_PWROFF (0x1 << 1)
+#define PRCM_VDD_SYS_AVCC_A_PWROFF (0x1 << 2)
+#define PRCM_VDD_SYS_CPU0_VDD_PWROFF (0x1 << 3)
+
+#define PRCM_VDD_GPU_PWROFF (0x1 << 0)
+
+#define PRCM_VDD_SYS_RESET (0x1 << 0)
+
+#define PRCM_CPU1_PWR_CLAMP(n) (((n) & 0xff) << 0)
+#define PRCM_CPU1_PWR_CLAMP_MASK PRCM_CPU1_PWR_CLAMP(0xff)
+
+#define PRCM_CPU2_PWR_CLAMP(n) (((n) & 0xff) << 0)
+#define PRCM_CPU2_PWR_CLAMP_MASK PRCM_CPU2_PWR_CLAMP(0xff)
+
+#define PRCM_CPU3_PWR_CLAMP(n) (((n) & 0xff) << 0)
+#define PRCM_CPU3_PWR_CLAMP_MASK PRCM_CPU3_PWR_CLAMP(0xff)
+
+#ifndef __ASSEMBLY__
+struct sunxi_prcm_reg {
+	u32 cpus_cfg;		/* 0x000 */
+	u8 res0[0x8];		/* 0x004 */
+	u32 apb0_ratio;		/* 0x00c */
+	u32 cpu0_cfg;		/* 0x010 */
+	u32 cpu1_cfg;		/* 0x014 */
+	u32 cpu2_cfg;		/* 0x018 */
+	u32 cpu3_cfg;		/* 0x01c */
+	u8 res1[0x8];		/* 0x020 */
+	u32 apb0_gate;		/* 0x028 */
+	u8 res2[0x14];		/* 0x02c */
+	u32 pll_ctrl0;		/* 0x040 */
+	u32 pll_ctrl1;		/* 0x044 */
+	u8 res3[0x8];		/* 0x048 */
+	u32 clk_1wire;		/* 0x050 */
+	u32 clk_ir;		/* 0x054 */
+	u8 res4[0x58];		/* 0x058 */
+	u32 apb0_reset;		/* 0x0b0 */
+	u8 res5[0x3c];		/* 0x0b4 */
+	u32 clk_outd;		/* 0x0f0 */
+	u8 res6[0xc];		/* 0x0f4 */
+	u32 cpu_pwroff;		/* 0x100 */
+	u8 res7[0xc];		/* 0x104 */
+	u32 vdd_sys_pwroff;	/* 0x110 */
+	u8 res8[0x4];		/* 0x114 */
+	u32 gpu_pwroff;		/* 0x118 */
+	u8 res9[0x4];		/* 0x11c */
+	u32 vdd_pwr_reset;	/* 0x120 */
+	u8 res10[0x20];		/* 0x124 */
+	u32 cpu1_pwr_clamp;	/* 0x144 */
+	u32 cpu2_pwr_clamp;	/* 0x148 */
+	u32 cpu3_pwr_clamp;	/* 0x14c */
+	u8 res11[0x30];		/* 0x150 */
+	u32 dram_pwr;		/* 0x180 */
+	u8 res12[0xc];		/* 0x184 */
+	u32 dram_tst;		/* 0x190 */
+};
+
+void prcm_apb0_enable(u32 flags);
+#endif /* __ASSEMBLY__ */
+#endif /* _PRCM_H */
diff --git a/arch/arm/include/asm/arch-sunxi/timer.h b/arch/arm/include/asm/arch-sunxi/timer.h
index 58e14fd0f713033aeaa2e2b0976b40444a8e1399..03a0684c797a3c28179886a283ca2382d249b17b 100644
--- a/arch/arm/include/asm/arch-sunxi/timer.h
+++ b/arch/arm/include/asm/arch-sunxi/timer.h
@@ -11,14 +11,10 @@
 #ifndef _SUNXI_TIMER_H_
 #define _SUNXI_TIMER_H_
 
-#define WDT_CTRL_RESTART	(0x1 << 0)
-#define WDT_CTRL_KEY		(0x0a57 << 1)
-#define WDT_MODE_EN		(0x1 << 0)
-#define WDT_MODE_RESET_EN	(0x1 << 1)
-
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
+#include <asm/arch/watchdog.h>
 
 /* General purpose timer */
 struct sunxi_timer {
@@ -43,12 +39,6 @@ struct sunxi_64cnt {
 	u32 hi;			/* 0xa8 */
 };
 
-/* Watchdog */
-struct sunxi_wdog {
-	u32 ctl;		/* 0x90 */
-	u32 mode;		/* 0x94 */
-};
-
 /* Rtc */
 struct sunxi_rtc {
 	u32 ctl;		/* 0x100 */
@@ -77,15 +67,20 @@ struct sunxi_timer_reg {
 	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;
+#if defined(CONFIG_SUN4I) || defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
+	struct sunxi_wdog wdog;	/* 0x90 */
+	/* XXX the following is not accurate for sun5i/sun7i */
+	struct sunxi_64cnt cnt64;	/* 0xa0 */
 	u8 res4[0x58];
 	struct sunxi_rtc rtc;
 	struct sunxi_alarm alarm;
 	struct sunxi_tgp tgp[4];
 	u8 res5[8];
 	u32 cpu_cfg;
+#else /* CONFIG_SUN6I || CONFIG_SUN8I || ... */
+	u8 res3[16];
+	struct sunxi_wdog wdog[5];	/* We have 5 watchdogs */
+#endif
 };
 
 #endif /* __ASSEMBLY__ */
diff --git a/arch/arm/include/asm/arch-sunxi/watchdog.h b/arch/arm/include/asm/arch-sunxi/watchdog.h
new file mode 100644
index 0000000000000000000000000000000000000000..ccc8fa32c49df2244e7d6ff67b994824722ec3f4
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/watchdog.h
@@ -0,0 +1,44 @@
+/*
+ * (C) Copyright 2014
+ * Chen-Yu Tsai <wens@csie.org>
+ *
+ * Watchdog register definitions
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _SUNXI_WATCHDOG_H_
+#define _SUNXI_WATCHDOG_H_
+
+#define WDT_CTRL_RESTART	(0x1 << 0)
+#define WDT_CTRL_KEY		(0x0a57 << 1)
+
+#if defined(CONFIG_SUN4I) || defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
+
+#define WDT_MODE_EN		(0x1 << 0)
+#define WDT_MODE_RESET_EN	(0x1 << 1)
+
+struct sunxi_wdog {
+	u32 ctl;		/* 0x00 */
+	u32 mode;		/* 0x04 */
+	u32 res[2];
+};
+
+#else
+
+#define WDT_CFG_RESET		(0x1)
+#define WDT_MODE_EN		(0x1)
+
+struct sunxi_wdog {
+	u32 irq_en;		/* 0x00 */
+	u32 irq_sta;		/* 0x04 */
+	u32 res1[2];
+	u32 ctl;		/* 0x10 */
+	u32 cfg;		/* 0x14 */
+	u32 mode;		/* 0x18 */
+	u32 res2;
+};
+
+#endif
+
+#endif /* _SUNXI_WATCHDOG_H_ */
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig
index bcd0a55a1e584410e13689b691f9d2d3614cdf67..31a15037d07cf950059f9a23d80e7b8fe6259c6f 100644
--- a/board/sunxi/Kconfig
+++ b/board/sunxi/Kconfig
@@ -1,25 +1,12 @@
-if TARGET_SUN4I
+if TARGET_SUN4I || TARGET_SUN5I || TARGET_SUN6I || TARGET_SUN7I || TARGET_SUN8I
 
 config SYS_CONFIG_NAME
-	default "sun4i"
-
-endif
-
-if TARGET_SUN5I
-
-config SYS_CONFIG_NAME
-	default "sun5i"
-
-endif
-
-if TARGET_SUN7I
-
-config SYS_CONFIG_NAME
-	default "sun7i"
-
-endif
-
-if TARGET_SUN4I || TARGET_SUN5I || TARGET_SUN7I
+	string
+	default "sun4i" if TARGET_SUN4I
+	default "sun5i" if TARGET_SUN5I
+	default "sun6i" if TARGET_SUN6I
+	default "sun7i" if TARGET_SUN7I
+	default "sun8i" if TARGET_SUN8I
 
 config SYS_CPU
 	default "armv7"
@@ -33,4 +20,45 @@ config SYS_SOC
 config FDTFILE
 	string "Default fdtfile env setting for this board"
 
+config OLD_SUNXI_KERNEL_COMPAT
+	boolean "Enable workarounds for booting old kernels"
+	default n
+	---help---
+	Set this to enable various workarounds for old kernels, this results in
+	sub-optimal settings for newer kernels, only enable if needed.
+
+config MMC0_CD_PIN
+	string "Card detect pin for mmc0"
+	default ""
+	---help---
+	Set the card detect pin for mmc0, leave empty to not use cd. This
+	takes a string in the format understood by sunxi_name_to_gpio, e.g.
+	PH1 for pin 1 of port H.
+
+config MMC1_CD_PIN
+	string "Card detect pin for mmc1"
+	default ""
+	---help---
+	See MMC0_CD_PIN help text.
+
+config MMC2_CD_PIN
+	string "Card detect pin for mmc2"
+	default ""
+	---help---
+	See MMC0_CD_PIN help text.
+
+config MMC3_CD_PIN
+	string "Card detect pin for mmc3"
+	default ""
+	---help---
+	See MMC0_CD_PIN help text.
+
+config MMC_SUNXI_SLOT_EXTRA
+	int "mmc extra slot number"
+	default -1
+	---help---
+	sunxi builds always enable mmc0, some boards also have a second sdcard
+	slot or emmc on mmc1 - mmc3. Setting this to 1, 2 or 3 will enable
+	support for this.
+
 endif
diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index 4f32195dcd92372858a2ff0170f45059531d8adf..febd126cb83bb15518515422ac35e25cba071dfa 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -8,6 +8,7 @@ F:	configs/ba10_tv_box_defconfig
 F:	configs/Cubieboard_defconfig
 F:	configs/Mele_A1000_defconfig
 F:	configs/Mele_A1000G_defconfig
+F:	configs/Mele_M3_defconfig
 F:	configs/Mini-X_defconfig
 F:	configs/Mini-X-1Gb_defconfig
 F:	include/configs/sun5i.h
@@ -38,3 +39,19 @@ M:	FUKAUMI Naoki <naobsd@gmail.com>
 S:	Maintained
 F:	board/sunxi/dram_a20_olinuxino_l.c
 F:	configs/A20-OLinuXino-Lime_defconfig
+
+A20-OLINUXINO-LIME2 BOARD
+M:	Iain Paton <ipaton0@gmail.com>
+S:	Maintained
+F:	board/sunxi/dram_a20_olinuxino_l2.c
+F:	configs/A20-OLinuXino-Lime2_defconfig
+
+COLOMBUS BOARD
+M:	Maxime Ripard <maxime.ripard@free-electrons.com>
+S:	Maintained
+F:	configs/Colombus_defconfig
+
+IPPO-Q8H-V5 BOARD
+M:	CHen-Yu Tsai <wens@csie.org>
+S:	Maintained
+F:	configs/Ippo_q8h_v5_defconfig
diff --git a/board/sunxi/Makefile b/board/sunxi/Makefile
index 56073a024d1a4c58940671b325e7c0ad71d75427..6a2e4c9d5b5553d52a6325277109a201d10a1ca3 100644
--- a/board/sunxi/Makefile
+++ b/board/sunxi/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_A10S_OLINUXINO_M)	+= dram_a10s_olinuxino_m.o
 obj-$(CONFIG_A13_OLINUXINO)	+= dram_a13_olinuxino.o
 obj-$(CONFIG_A13_OLINUXINOM)	+= dram_a13_oli_micro.o
 obj-$(CONFIG_A20_OLINUXINO_L)	+= dram_a20_olinuxino_l.o
+obj-$(CONFIG_A20_OLINUXINO_L2)	+= dram_a20_olinuxino_l2.o
 obj-$(CONFIG_A20_OLINUXINO_M)	+= dram_sun7i_384_1024_iow16.o
 # This is not a typo, uses the same mem settings as the a10s-olinuxino-m
 obj-$(CONFIG_AUXTEK_T004)	+= dram_a10s_olinuxino_m.o
@@ -27,6 +28,7 @@ obj-$(CONFIG_CUBIETRUCK)	+= dram_cubietruck.o
 obj-$(CONFIG_I12_TVBOX)		+= dram_sun7i_384_1024_iow16.o
 obj-$(CONFIG_MELE_A1000)	+= dram_sun4i_360_512.o
 obj-$(CONFIG_MELE_A1000G)	+= dram_sun4i_360_1024_iow8.o
+obj-$(CONFIG_MELE_M3)		+= dram_sun7i_384_1024_iow16.o
 obj-$(CONFIG_MINI_X)		+= dram_sun4i_360_512.o
 obj-$(CONFIG_MINI_X_1GB)	+= dram_sun4i_360_1024_iow16.o
 obj-$(CONFIG_PCDUINO3)		+= dram_linksprite_pcduino3.o
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 2179e234e21d67b0fec064de792fca175db90ca5..03890c8c9ceb62c40279c4fb910a56441858ec8a 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -12,6 +12,7 @@
  */
 
 #include <common.h>
+#include <mmc.h>
 #ifdef CONFIG_AXP152_POWER
 #include <axp152.h>
 #endif
@@ -70,9 +71,9 @@ static void mmc_pinmux_setup(int sdc)
 		break;
 
 	case 1:
-		/* CMD-PH22, CLK-PH23, D0~D3-PH24~27 : 5 */
-		for (pin = SUNXI_GPH(22); pin <= SUNXI_GPH(27); pin++) {
-			sunxi_gpio_set_cfgpin(pin, SUN4I_GPH22_SDC1);
+		/* CMD-PG3, CLK-PG4, D0~D3-PG5-8 */
+		for (pin = SUNXI_GPG(3); pin <= SUNXI_GPG(8); pin++) {
+			sunxi_gpio_set_cfgpin(pin, SUN5I_GPG3_SDC1);
 			sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 			sunxi_gpio_set_drv(pin, 2);
 		}
@@ -104,11 +105,36 @@ static void mmc_pinmux_setup(int sdc)
 
 int board_mmc_init(bd_t *bis)
 {
+	__maybe_unused struct mmc *mmc0, *mmc1;
+	__maybe_unused char buf[512];
+
 	mmc_pinmux_setup(CONFIG_MMC_SUNXI_SLOT);
-	sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT);
-#if !defined (CONFIG_SPL_BUILD) && defined (CONFIG_MMC_SUNXI_SLOT_EXTRA)
+	mmc0 = sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT);
+	if (!mmc0)
+		return -1;
+
+#if CONFIG_MMC_SUNXI_SLOT_EXTRA != -1
 	mmc_pinmux_setup(CONFIG_MMC_SUNXI_SLOT_EXTRA);
-	sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT_EXTRA);
+	mmc1 = sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT_EXTRA);
+	if (!mmc1)
+		return -1;
+#endif
+
+#if CONFIG_MMC_SUNXI_SLOT == 0 && CONFIG_MMC_SUNXI_SLOT_EXTRA == 2
+	/*
+	 * Both mmc0 and mmc2 are bootable, figure out where we're booting
+	 * from. Try mmc0 first, just like the brom does.
+	 */
+	if (mmc_getcd(mmc0) && mmc_init(mmc0) == 0 &&
+	    mmc0->block_dev.block_read(0, 16, 1, buf) == 1) {
+		buf[12] = 0;
+		if (strcmp(&buf[4], "eGON.BT0") == 0)
+			return 0;
+	}
+
+	/* no bootable card in mmc0, so we must be booting from mmc2, swap */
+	mmc0->block_dev.dev = 1;
+	mmc1->block_dev.dev = 0;
 #endif
 
 	return 0;
diff --git a/board/sunxi/dram_a20_olinuxino_l2.c b/board/sunxi/dram_a20_olinuxino_l2.c
new file mode 100644
index 0000000000000000000000000000000000000000..2115d37470abff78d0dd3e0a263f92d021f7a361
--- /dev/null
+++ b/board/sunxi/dram_a20_olinuxino_l2.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 = 9,
+	.zq = 0x7f,
+	.odt_en = 0,
+	.size = 1024,
+	.tpr0 = 0x42d899b7,
+	.tpr1 = 0xa090,
+	.tpr2 = 0x22a00,
+	.tpr3 = 0,
+	.tpr4 = 0,
+	.tpr5 = 0,
+	.emr1 = 0x4,
+	.emr2 = 0x10,
+	.emr3 = 0,
+};
+
+unsigned long sunxi_dram_init(void)
+{
+	return dramc_init(&dram_para);
+}
diff --git a/configs/A10s-OLinuXino-M_defconfig b/configs/A10s-OLinuXino-M_defconfig
index a578c067d4d0dd5dcb39854a1197abdeb24cb86c..2aad834fa840c5b1390c3621442e9ab444240349 100644
--- a/configs/A10s-OLinuXino-M_defconfig
+++ b/configs/A10s-OLinuXino-M_defconfig
@@ -1,5 +1,8 @@
 CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="A10S_OLINUXINO_M,AXP152_POWER,SUNXI_EMAC,USB_EHCI,SUNXI_USB_VBUS0_GPIO=SUNXI_GPB(10)"
 CONFIG_FDTFILE="sun5i-a10s-olinuxino-micro.dtb"
+CONFIG_MMC_SUNXI_SLOT_EXTRA=1
++S:CONFIG_MMC0_CD_PIN="PG1"
++S:CONFIG_MMC1_CD_PIN="PG13"
 +S:CONFIG_ARM=y
 +S:CONFIG_TARGET_SUN5I=y
diff --git a/configs/A20-OLinuXino-Lime2_defconfig b/configs/A20-OLinuXino-Lime2_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..75ef87278026650dae58b97eedc16e153b1e2b28
--- /dev/null
+++ b/configs/A20-OLinuXino-Lime2_defconfig
@@ -0,0 +1,5 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="A20_OLINUXINO_L2,AXP209_POWER,SUNXI_GMAC,RGMII,AHCI,SATAPWR=SUNXI_GPC(3),USB_EHCI"
+CONFIG_FDTFILE="sun7i-a20-olinuxino-lime2.dtb"
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_SUN7I=y
diff --git a/configs/A20-OLinuXino_MICRO_defconfig b/configs/A20-OLinuXino_MICRO_defconfig
index 20a947ca723adc5e110437dd47914399930ddc0c..0e0a7def2de600f0fc06aaf6898f3644fdd4243e 100644
--- a/configs/A20-OLinuXino_MICRO_defconfig
+++ b/configs/A20-OLinuXino_MICRO_defconfig
@@ -1,5 +1,8 @@
 CONFIG_SPL=y
 CONFIG_SYS_EXTRA_OPTIONS="A20_OLINUXINO_M,AXP209_POWER,SUNXI_GMAC,AHCI,SATAPWR=SUNXI_GPB(8),USB_EHCI"
 CONFIG_FDTFILE="sun7i-a20-olinuxino-micro.dtb"
+CONFIG_MMC_SUNXI_SLOT_EXTRA=3
++S:CONFIG_MMC0_CD_PIN="PH1"
++S:CONFIG_MMC3_CD_PIN="PH11"
 +S:CONFIG_ARM=y
 +S:CONFIG_TARGET_SUN7I=y
diff --git a/configs/Colombus_defconfig b/configs/Colombus_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..16800de2bcd3154b320d6761478cf6101e552927
--- /dev/null
+++ b/configs/Colombus_defconfig
@@ -0,0 +1,4 @@
+CONFIG_SYS_EXTRA_OPTIONS="COLOMBUS"
+CONFIG_ARM=y
+CONFIG_TARGET_SUN6I=y
+CONFIG_FDTFILE="sun6i-a31-colombus.dtb"
diff --git a/configs/Ippo_q8h_defconfig b/configs/Ippo_q8h_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..781f13785b24cbbb653bf35faf60a58b16a2dbe3
--- /dev/null
+++ b/configs/Ippo_q8h_defconfig
@@ -0,0 +1,4 @@
+CONFIG_SYS_EXTRA_OPTIONS="IPPO_Q8H_V5,CONS_INDEX=5"
+CONFIG_ARM=y
+CONFIG_TARGET_SUN8I=y
+CONFIG_DEFAULT_DEVICE_TREE="sun8i-a23-ippo-q8h-v5.dtb"
diff --git a/configs/Mele_M3_defconfig b/configs/Mele_M3_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..a043ad277d79efd5546e223b57664dc8413958bb
--- /dev/null
+++ b/configs/Mele_M3_defconfig
@@ -0,0 +1,7 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="MELE_M3,AXP209_POWER,SUNXI_GMAC,USB_EHCI"
+CONFIG_FDTFILE="sun7i-a20-m3.dtb"
++S:CONFIG_MMC_SUNXI_SLOT_EXTRA=2
++S:CONFIG_MMC0_CD_PIN="PH1"
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_SUN7I=y
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
index d4e574fe191b0e8edd587b733be4b9cf5ec6ee24..16592e3d7cf2454e00013181576dcb0ea437822e 100644
--- a/drivers/mmc/sunxi_mmc.c
+++ b/drivers/mmc/sunxi_mmc.c
@@ -14,12 +14,13 @@
 #include <asm/io.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
 #include <asm/arch/mmc.h>
+#include <asm-generic/gpio.h>
 
 struct sunxi_mmc_host {
 	unsigned mmc_no;
 	uint32_t *mclkreg;
-	unsigned database;
 	unsigned fatal_err;
 	unsigned mod_clk;
 	struct sunxi_mmc *reg;
@@ -57,7 +58,6 @@ static int mmc_resource_init(int sdc_no)
 		printf("Wrong mmc number %d\n", sdc_no);
 		return -1;
 	}
-	mmchost->database = (unsigned int)mmchost->reg + 0x100;
 	mmchost->mmc_no = sdc_no;
 
 	return 0;
@@ -75,6 +75,11 @@ static int mmc_clk_io_on(int sdc_no)
 	/* config ahb clock */
 	setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no));
 
+#if defined(CONFIG_SUN6I) || defined(CONFIG_SUN8I)
+	/* unassert reset */
+	setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MMC(sdc_no));
+#endif
+
 	/* config mod clock */
 	pll_clk = clock_get_pll6();
 	/* should be close to 100 MHz but no more, so round up */
@@ -194,9 +199,9 @@ static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data)
 		}
 
 		if (reading)
-			buff[i] = readl(mmchost->database);
+			buff[i] = readl(&mmchost->reg->fifo);
 		else
-			writel(buff[i], mmchost->database);
+			writel(buff[i], &mmchost->reg->fifo);
 	}
 
 	return 0;
@@ -343,13 +348,32 @@ out:
 	return error;
 }
 
+static int sunxi_mmc_getcd(struct mmc *mmc)
+{
+	struct sunxi_mmc_host *mmchost = mmc->priv;
+	int cd_pin = -1;
+
+	switch (mmchost->mmc_no) {
+	case 0: cd_pin = sunxi_name_to_gpio(CONFIG_MMC0_CD_PIN); break;
+	case 1: cd_pin = sunxi_name_to_gpio(CONFIG_MMC1_CD_PIN); break;
+	case 2: cd_pin = sunxi_name_to_gpio(CONFIG_MMC2_CD_PIN); break;
+	case 3: cd_pin = sunxi_name_to_gpio(CONFIG_MMC3_CD_PIN); break;
+	}
+
+	if (cd_pin == -1)
+		return 1;
+
+	return !gpio_direction_input(cd_pin);
+}
+
 static const struct mmc_ops sunxi_mmc_ops = {
 	.send_cmd	= mmc_send_cmd,
 	.set_ios	= mmc_set_ios,
 	.init		= mmc_core_init,
+	.getcd		= sunxi_mmc_getcd,
 };
 
-int sunxi_mmc_init(int sdc_no)
+struct mmc *sunxi_mmc_init(int sdc_no)
 {
 	struct mmc_config *cfg = &mmc_host[sdc_no].cfg;
 
@@ -361,6 +385,9 @@ int sunxi_mmc_init(int sdc_no)
 	cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
 	cfg->host_caps = MMC_MODE_4BIT;
 	cfg->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
+#if defined(CONFIG_SUN6I) || defined(CONFIG_SUN7I) || defined(CONFIG_SUN8I)
+	cfg->host_caps |= MMC_MODE_HC;
+#endif
 	cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
 
 	cfg->f_min = 400000;
@@ -369,8 +396,5 @@ int sunxi_mmc_init(int sdc_no)
 	mmc_resource_init(sdc_no);
 	mmc_clk_io_on(sdc_no);
 
-	if (mmc_create(cfg, &mmc_host[sdc_no]) == NULL)
-		return -1;
-
-	return 0;
+	return mmc_create(cfg, &mmc_host[sdc_no]);
 }
diff --git a/include/configs/sun4i.h b/include/configs/sun4i.h
index 5611ecc85f22bf3f3d949211c54cabc3eb54db92..d0191a32b1a6d99807cf75becf4821f2e6879cfd 100644
--- a/include/configs/sun4i.h
+++ b/include/configs/sun4i.h
@@ -15,6 +15,7 @@
 #define CONFIG_CLK_FULL_SPEED		1008000000
 
 #define CONFIG_SYS_PROMPT		"sun4i# "
+#define CONFIG_MACH_TYPE		4104
 
 #ifdef CONFIG_USB_EHCI
 #define CONFIG_USB_EHCI_SUNXI
diff --git a/include/configs/sun5i.h b/include/configs/sun5i.h
index 6066371a17d8d172c62d00cff4f4a508c5de53ee..7b683e9c8908394e56072d545f873d0e5f798c6a 100644
--- a/include/configs/sun5i.h
+++ b/include/configs/sun5i.h
@@ -15,6 +15,7 @@
 #define CONFIG_CLK_FULL_SPEED		1008000000
 
 #define CONFIG_SYS_PROMPT		"sun5i# "
+#define CONFIG_MACH_TYPE		4138
 
 #ifdef CONFIG_USB_EHCI
 #define CONFIG_USB_EHCI_SUNXI
diff --git a/include/configs/sun6i.h b/include/configs/sun6i.h
new file mode 100644
index 0000000000000000000000000000000000000000..93a1d965ca4e680e27f24ff7fd8efac3f154faf6
--- /dev/null
+++ b/include/configs/sun6i.h
@@ -0,0 +1,26 @@
+/*
+ * (C) Copyright 2012-2013 Henrik Nordstrom <henrik@henriknordstrom.net>
+ * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+ * (C) Copyright 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * Configuration settings for the Allwinner A31 (sun6i) CPU
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * A31 specific configuration
+ */
+#define CONFIG_SUN6I		/* sun6i SoC generation */
+
+#define CONFIG_SYS_PROMPT		"sun6i# "
+
+/*
+ * Include common sunxi configuration where most the settings are
+ */
+#include <configs/sunxi-common.h>
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/sun7i.h b/include/configs/sun7i.h
index a902b845744707e64fb5a064c6039bc93b0150d9..966cbd8e83f6cb2659f64798cfeb502a1b5e6aa4 100644
--- a/include/configs/sun7i.h
+++ b/include/configs/sun7i.h
@@ -16,6 +16,7 @@
 #define CONFIG_CLK_FULL_SPEED		912000000
 
 #define CONFIG_SYS_PROMPT		"sun7i# "
+#define CONFIG_MACH_TYPE		4283
 
 #ifdef CONFIG_USB_EHCI
 #define CONFIG_USB_EHCI_SUNXI
diff --git a/include/configs/sun8i.h b/include/configs/sun8i.h
new file mode 100644
index 0000000000000000000000000000000000000000..1c1a7cde5ec1762d6a1702ed5a295c17c4696459
--- /dev/null
+++ b/include/configs/sun8i.h
@@ -0,0 +1,23 @@
+/*
+ * (C) Copyright 2014 Chen-Yu Tsai <wens@csie.org>
+ *
+ * Configuration settings for the Allwinner A23 (sun8i) CPU
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * A23 specific configuration
+ */
+#define CONFIG_SUN8I		/* sun8i SoC generation */
+#define CONFIG_SYS_PROMPT	"sun8i# "
+
+/*
+ * Include common sunxi configuration where most the settings are
+ */
+#include <configs/sunxi-common.h>
+
+#endif /* __CONFIG_H */
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index 0c117bc5e7a8b64e7711ba4758cb16030d7637e8..cc450e02e67e041b248a47c84c05aa1a5325c57b 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -42,6 +42,7 @@
 #define CONFIG_SYS_NS16550_COM2		SUNXI_UART1_BASE
 #define CONFIG_SYS_NS16550_COM3		SUNXI_UART2_BASE
 #define CONFIG_SYS_NS16550_COM4		SUNXI_UART3_BASE
+#define CONFIG_SYS_NS16550_COM5		SUNXI_R_UART_BASE
 
 /* DRAM Base */
 #define CONFIG_SYS_SDRAM_BASE		0x40000000
@@ -77,6 +78,7 @@
 #define CONFIG_INITRD_TAG
 
 /* mmc config */
+#if !defined(CONFIG_UART0_PORT_F)
 #define CONFIG_MMC
 #define CONFIG_GENERIC_MMC
 #define CONFIG_CMD_MMC
@@ -84,6 +86,7 @@
 #define CONFIG_MMC_SUNXI_SLOT		0
 #define CONFIG_ENV_IS_IN_MMC
 #define CONFIG_SYS_MMC_ENV_DEV		0	/* first detected MMC controller */
+#endif
 
 /* 4MB of malloc() pool */
 #define CONFIG_SYS_MALLOC_LEN		(CONFIG_ENV_SIZE + (4 << 20))
@@ -92,8 +95,8 @@
  * Miscellaneous configurable options
  */
 #define CONFIG_CMD_ECHO
-#define CONFIG_SYS_CBSIZE	256	/* Console I/O Buffer Size */
-#define CONFIG_SYS_PBSIZE	384	/* Print Buffer Size */
+#define CONFIG_SYS_CBSIZE	1024	/* Console I/O Buffer Size */
+#define CONFIG_SYS_PBSIZE	1024	/* Print Buffer Size */
 #define CONFIG_SYS_MAXARGS	16	/* max number of command args */
 #define CONFIG_SYS_GENERIC_BOARD
 
@@ -181,6 +184,7 @@
 
 /* GPIO */
 #define CONFIG_SUNXI_GPIO
+#define CONFIG_SPL_GPIO_SUPPORT
 #define CONFIG_CMD_GPIO
 
 /* Ethernet support */
@@ -225,16 +229,28 @@
 	"pxefile_addr_r=0x43200000\0" \
 	"ramdisk_addr_r=0x43300000\0"
 
+#ifdef CONFIG_MMC
+#define BOOT_TARGET_DEVICES_MMC(func) func(MMC, mmc, 0)
+#else
+#define BOOT_TARGET_DEVICES_MMC(func)
+#endif
+
 #ifdef CONFIG_AHCI
 #define BOOT_TARGET_DEVICES_SCSI(func) func(SCSI, scsi, 0)
 #else
 #define BOOT_TARGET_DEVICES_SCSI(func)
 #endif
 
+#ifdef CONFIG_USB_EHCI
+#define BOOT_TARGET_DEVICES_USB(func) func(USB, usb, 0)
+#else
+#define BOOT_TARGET_DEVICES_USB(func)
+#endif
+
 #define BOOT_TARGET_DEVICES(func) \
-	func(MMC, mmc, 0) \
+	BOOT_TARGET_DEVICES_MMC(func) \
 	BOOT_TARGET_DEVICES_SCSI(func) \
-	func(USB, usb, 0) \
+	BOOT_TARGET_DEVICES_USB(func) \
 	func(PXE, pxe, na) \
 	func(DHCP, dhcp, na)