[U-Boot] [PATCH 2/2] sunxi: Universal Allwinner A10/A13/A20 u-boot binary support

Siarhei Siamashka siarhei.siamashka at gmail.com
Sun Aug 3 05:26:03 CEST 2014


Two new defconfigs ('sunxi-generic-a10-a13-a20_defconfig' and
'sunxi-generic-a10-a13-a20_FEL_defconfig') can be used to build
universal u-boot binaries, suitable for all Allwinner
A10/A13/A20 devices. The supported peripherals are just UART
and MMC (the lowest common denominator approach).

MMC support is completely problem free for runtime detection,
because it must be supported by BROM and no strange pin muxing
configurations are expected.

UART is a bit more difficult, but in practice very few
configurations exist. And they can be successfully detected
at runtime. CONFIG_CONS_INDEX=1 is used on almost all devices.
And CONFIG_CONS_INDEX=2 is only used on Allwinner A13, where
the SoC just does not have the B19/B20 pins on the package,
which are normally used for CONFIG_CONS_INDEX=1 UART on Allwiner
A10S. So it is a matter of necessity and not a random choice.

The universal u-boot binary should be sufficient for booting
the system from SD card and/or getting the u-boot command
prompt on the serial console.

Signed-off-by: Siarhei Siamashka <siarhei.siamashka at gmail.com>
---
 arch/arm/Kconfig                                |  3 ++
 arch/arm/cpu/armv7/sunxi/Makefile               |  2 +
 arch/arm/cpu/armv7/sunxi/board.c                | 52 +++++++++++++++++++++++--
 arch/arm/cpu/armv7/sunxi/clock_sun4i.c          |  3 +-
 arch/arm/cpu/armv7/sunxi/cpu_info.c             |  1 +
 arch/arm/include/asm/arch-sunxi/sys_proto.h     |  5 +++
 board/sunxi/Kconfig                             | 20 ++++++++++
 board/sunxi/MAINTAINERS                         |  7 ++++
 board/sunxi/Makefile                            |  1 +
 board/sunxi/board.c                             |  1 +
 board/sunxi/dram_sunxi_ddr3_failsafe.c          | 28 +++++++++++++
 configs/sunxi-generic-a10-a13-a20_FEL_defconfig |  4 ++
 configs/sunxi-generic-a10-a13-a20_defconfig     |  4 ++
 include/configs/sun4i_sun5i_sun7i.h             | 38 ++++++++++++++++++
 14 files changed, 165 insertions(+), 4 deletions(-)
 create mode 100644 board/sunxi/dram_sunxi_ddr3_failsafe.c
 create mode 100644 configs/sunxi-generic-a10-a13-a20_FEL_defconfig
 create mode 100644 configs/sunxi-generic-a10-a13-a20_defconfig
 create mode 100644 include/configs/sun4i_sun5i_sun7i.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e385eda..95887f6 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -650,6 +650,9 @@ config TARGET_SUN5I
 config TARGET_SUN7I
 	bool "Support sun7i"
 
+config TARGET_SUN4I_SUN5I_SUN7I
+	bool "Support sun4i/sun5i/sun7i"
+
 config TARGET_SNOWBALL
 	bool "Support snowball"
 
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
index e9721b2..e8844ad 100644
--- a/arch/arm/cpu/armv7/sunxi/Makefile
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -14,6 +14,7 @@ obj-y	+= pinmux.o
 obj-$(CONFIG_SUN4I)	+= clock_sun4i.o
 obj-$(CONFIG_SUN5I)	+= clock_sun4i.o
 obj-$(CONFIG_SUN7I)	+= clock_sun4i.o
+obj-$(CONFIG_SUN4I_SUN5I_SUN7I)	+= clock_sun4i.o
 
 ifndef CONFIG_SPL_BUILD
 obj-y	+= cpu_info.o
@@ -26,6 +27,7 @@ ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_SUN4I)	+= dram.o
 obj-$(CONFIG_SUN5I)	+= dram.o
 obj-$(CONFIG_SUN7I)	+= dram.o
+obj-$(CONFIG_SUN4I_SUN5I_SUN7I)	+= dram.o
 ifdef CONFIG_SPL_FEL
 obj-y	+= start.o
 endif
diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c
index 90e957c..422d224 100644
--- a/arch/arm/cpu/armv7/sunxi/board.c
+++ b/arch/arm/cpu/armv7/sunxi/board.c
@@ -48,17 +48,62 @@ u32 spl_boot_mode(void)
 }
 #endif
 
+static void sunxi_soc_detect_init(void)
+{
+	/* Enable VER_REG (set the VER_R_EN bit) */
+	setbits_le32((u32 *)(SUNXI_SRAMC_BASE + 0x24), 1 << 15);
+}
+
+int soc_is_sun4i(void)
+{
+	return (readl((u32 *)(SUNXI_SRAMC_BASE + 0x24)) >> 16) == 0x1623;
+}
+
+int soc_is_sun5i(void)
+{
+	return (readl((u32 *)(SUNXI_SRAMC_BASE + 0x24)) >> 16) == 0x1625;
+}
+
+int soc_is_sun7i(void)
+{
+	return (readl((u32 *)(SUNXI_SRAMC_BASE + 0x24)) >> 16) == 0x1651;
+}
+
+int sunxi_cons_index(void)
+{
+	int cons_index = CONFIG_CONS_INDEX;
+
+	if (cons_index == 1 && SOC_IS_SUN5I()) {
+		u32 val = readl(SUNXI_SID_BASE + 0x08);
+		if (((val >> 12) & 0xf) == 3) {
+			/* Allwinner A13 */
+			cons_index = 2;
+		}
+	}
+	return cons_index;
+}
+
+struct serial_device *default_serial_console(void)
+{
+	if (sunxi_cons_index() == 1)
+		return &eserial1_device;
+	else
+		return &eserial2_device;
+}
+
 int gpio_init(void)
 {
-	if (CONFIG_CONS_INDEX == 1 && (SOC_IS_SUN4I() || SOC_IS_SUN7I())) {
+	int cons_index = sunxi_cons_index();
+
+	if (cons_index == 1 && (SOC_IS_SUN4I() || SOC_IS_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);
-	} else if (CONFIG_CONS_INDEX == 1 && SOC_IS_SUN5I()) {
+	} else if (cons_index == 1 && SOC_IS_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);
-	} else if (CONFIG_CONS_INDEX == 2 && SOC_IS_SUN5I()) {
+	} else if (cons_index == 2 && SOC_IS_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);
@@ -88,6 +133,7 @@ void reset_cpu(ulong addr)
 /* do some early init */
 void s_init(void)
 {
+	sunxi_soc_detect_init();
 #if !defined CONFIG_SPL_BUILD
 	int soc_is_sun6i = 0;
 #ifdef CONFIG_SUN6I
diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun4i.c b/arch/arm/cpu/armv7/sunxi/clock_sun4i.c
index 1af285e..3d0f1ad 100644
--- a/arch/arm/cpu/armv7/sunxi/clock_sun4i.c
+++ b/arch/arm/cpu/armv7/sunxi/clock_sun4i.c
@@ -51,6 +51,7 @@ void clock_init_uart(void)
 {
 	struct sunxi_ccm_reg *const ccm =
 		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+	int cons_index = sunxi_cons_index();
 
 	/* uart clock source is apb1 */
 	writel(APB1_CLK_SRC_OSC24M|
@@ -60,7 +61,7 @@ void clock_init_uart(void)
 
 	/* open the clock for uart */
 	setbits_le32(&ccm->apb1_gate,
-		CLK_GATE_OPEN << (APB1_GATE_UART_SHIFT+CONFIG_CONS_INDEX-1));
+		CLK_GATE_OPEN << (APB1_GATE_UART_SHIFT + cons_index - 1));
 }
 
 int clock_twi_onoff(int port, int state)
diff --git a/arch/arm/cpu/armv7/sunxi/cpu_info.c b/arch/arm/cpu/armv7/sunxi/cpu_info.c
index 1134b21..483b98c 100644
--- a/arch/arm/cpu/armv7/sunxi/cpu_info.c
+++ b/arch/arm/cpu/armv7/sunxi/cpu_info.c
@@ -9,6 +9,7 @@
 #include <common.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
+#include <asm/arch/sys_proto.h>
 
 #ifdef CONFIG_DISPLAY_CPUINFO
 int print_cpuinfo(void)
diff --git a/arch/arm/include/asm/arch-sunxi/sys_proto.h b/arch/arm/include/asm/arch-sunxi/sys_proto.h
index c3e636e..b422581 100644
--- a/arch/arm/include/asm/arch-sunxi/sys_proto.h
+++ b/arch/arm/include/asm/arch-sunxi/sys_proto.h
@@ -13,4 +13,9 @@
 
 void sdelay(unsigned long);
 
+int  sunxi_cons_index(void);
+int  soc_is_sun4i(void);
+int  soc_is_sun5i(void);
+int  soc_is_sun7i(void);
+
 #endif
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig
index b06b5e0..098b0df 100644
--- a/board/sunxi/Kconfig
+++ b/board/sunxi/Kconfig
@@ -57,3 +57,23 @@ config SYS_CONFIG_NAME
 	default "sun7i"
 
 endif
+
+if TARGET_SUN4I_SUN5I_SUN7I
+
+config SYS_CPU
+	string
+	default "armv7"
+
+config SYS_BOARD
+	string
+	default "sunxi"
+
+config SYS_SOC
+	string
+	default "sunxi"
+
+config SYS_CONFIG_NAME
+	string
+	default "sun4i_sun5i_sun7i"
+
+endif
diff --git a/board/sunxi/MAINTAINERS b/board/sunxi/MAINTAINERS
index b0b1804..e438bf2 100644
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -32,3 +32,10 @@ F:	configs/Cubieboard2_defconfig
 F:	configs/Cubieboard2_FEL_defconfig
 F:	configs/Cubietruck_defconfig
 F:	configs/Cubietruck_FEL_defconfig
+
+SUNXI GENERIC
+M:	Siarhei Siamashka <siarhei.siamashka at gmail.com>
+S:	Maintained
+F:	include/configs/sun4i_sun5i_sun7i.h
+F:	configs/sunxi-generic-a10-a13-a20_defconfig
+F:	configs/sunxi-generic-a10-a13-a20_FEL_defconfig
diff --git a/board/sunxi/Makefile b/board/sunxi/Makefile
index cf001e7..dd70a95 100644
--- a/board/sunxi/Makefile
+++ b/board/sunxi/Makefile
@@ -11,6 +11,7 @@
 obj-y	+= board.o
 obj-$(CONFIG_SUNXI_GMAC)	+= gmac.o
 obj-$(CONFIG_SUNXI_AHCI)	+= ahci.o
+obj-$(CONFIG_SUNXI_GENERIC_A10_A13_A20) += dram_sunxi_ddr3_failsafe.o
 obj-$(CONFIG_A10_OLINUXINO_L)	+= dram_a10_olinuxino_l.o
 obj-$(CONFIG_A10S_OLINUXINO_M)	+= dram_a10s_olinuxino_m.o
 obj-$(CONFIG_A13_OLINUXINO)	+= dram_a13_olinuxino.o
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 2179e23..edbfc44 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -23,6 +23,7 @@
 #include <asm/arch/dram.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/sys_proto.h>
 #include <asm/io.h>
 #include <net.h>
 
diff --git a/board/sunxi/dram_sunxi_ddr3_failsafe.c b/board/sunxi/dram_sunxi_ddr3_failsafe.c
new file mode 100644
index 0000000..348e0b9
--- /dev/null
+++ b/board/sunxi/dram_sunxi_ddr3_failsafe.c
@@ -0,0 +1,28 @@
+/* this file is generated, don't edit it yourself */
+
+#include "common.h"
+#include <asm/arch/dram.h>
+
+static struct dram_para dram_para = { /* DRAM timings: 6-5-5-13 (360 MHz) */
+	.clock = 360,
+	.type = 3,
+	.rank_num = 1,
+	.cas = 6,
+	.zq = 0x7b,
+	.odt_en = 0,
+	.tpr0 = 0x248d5590,
+	.tpr1 = 0xa088,
+	.tpr2 = 0x22a00,
+	.tpr3 = 0x0,
+	.tpr4 = 0x0,
+	.tpr5 = 0x0,
+	.emr1 = 0x0,
+	.emr2 = 0x0,
+	.emr3 = 0x0,
+	.active_windowing = 1,
+};
+
+unsigned long sunxi_dram_init(void)
+{
+	return dramc_init(&dram_para);
+}
diff --git a/configs/sunxi-generic-a10-a13-a20_FEL_defconfig b/configs/sunxi-generic-a10-a13-a20_FEL_defconfig
new file mode 100644
index 0000000..2a8a303
--- /dev/null
+++ b/configs/sunxi-generic-a10-a13-a20_FEL_defconfig
@@ -0,0 +1,4 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="SUNXI_GENERIC_A10_A13_A20,SPL_FEL"
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_SUN4I_SUN5I_SUN7I=y
diff --git a/configs/sunxi-generic-a10-a13-a20_defconfig b/configs/sunxi-generic-a10-a13-a20_defconfig
new file mode 100644
index 0000000..c42699c
--- /dev/null
+++ b/configs/sunxi-generic-a10-a13-a20_defconfig
@@ -0,0 +1,4 @@
+CONFIG_SPL=y
+CONFIG_SYS_EXTRA_OPTIONS="SUNXI_GENERIC_A10_A13_A20,SPL"
++S:CONFIG_ARM=y
++S:CONFIG_TARGET_SUN4I_SUN5I_SUN7I=y
diff --git a/include/configs/sun4i_sun5i_sun7i.h b/include/configs/sun4i_sun5i_sun7i.h
new file mode 100644
index 0000000..16dbce1
--- /dev/null
+++ b/include/configs/sun4i_sun5i_sun7i.h
@@ -0,0 +1,38 @@
+/*
+ * (C) Copyright 2012-2013 Henrik Nordstrom <henrik at henriknordstrom.net>
+ *
+ * Configuration settings for the Allwinner A10 (sun4i) CPU
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define SOC_IS_SUN4I()			(soc_is_sun4i())
+#define SOC_IS_SUN5I()			(soc_is_sun5i())
+#define SOC_IS_SUN7I()			(soc_is_sun7i())
+
+#define CONFIG_SUN4I_SUN5I_SUN7I
+#define CONFIG_CLK_FULL_SPEED		(SOC_IS_SUN7I() ? 912000000 : \
+							  1008000000)
+
+#define CONFIG_SYS_PROMPT		"sunxi# "
+
+/* The Cortex-A8 CPU in sun4i/sun5i is going to fail runtime
+ * check and will fallback to booting the kernel in secure mode */
+#define CONFIG_ARMV7_ALLOW_SECURE_MODE_FALLBACK 1
+
+/* This is going to be used for sun7i */
+#define CONFIG_ARMV7_VIRT		1
+#define CONFIG_ARMV7_NONSEC		1
+#define CONFIG_ARMV7_PSCI		1
+#define CONFIG_ARMV7_PSCI_NR_CPUS	2
+#define CONFIG_ARMV7_SECURE_BASE	SUNXI_SRAM_B_BASE
+#define CONFIG_SYS_CLK_FREQ		24000000
+
+/*
+ * Include common sunxi configuration where most the settings are
+ */
+#include <configs/sunxi-common.h>
+
+#endif /* __CONFIG_H */
-- 
1.8.3.2



More information about the U-Boot mailing list