diff mbox

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

Message ID 1407036363-29620-3-git-send-email-siarhei.siamashka@gmail.com
State Deferred
Delegated to: Hans de Goede
Headers show

Commit Message

Siarhei Siamashka Aug. 3, 2014, 3:26 a.m. UTC
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@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

Comments

Ian Campbell Aug. 6, 2014, 7:31 a.m. UTC | #1
On Sun, 2014-08-03 at 06:26 +0300, Siarhei Siamashka wrote:

> 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"

Is the intention to eventually support sun6i/sun8i etc here too? I think
we should try and avoid enumerating them in the names of everything
(Kconfig, filenames etc) and instead us TARGET_SUNXI_GENERIC or
TARGET_SUNXI_MULTI or something along those lines, or perhaps Kconfig
could present a bool for each of the subarches and enabling more than
one would enable multiple mode.

Not directly related to this series but probably arch/arm/Kconfig should
have TARGET_SUNXI and the 4i/5i/7i stuff ought to move down into
arch/arm/sunxi/Kconfig.

> @@ -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);

Please can you #define 0x24 and the various masks/shifts.
> +}
> +
> +int soc_is_sun4i(void)

All of these should use a common helper which takes the ID as a
parameter or the SOC_IS_xxx macros could just use that helper directly
if the wrappers turn out not that useful.

A bit of cpp trickery could also lead to:

#define SUNXI_SOC_ID_SUN4I 0x1623
#define SUNXO_SOC_ID...
#define SUNXI_SOC_IS(X) soc_is(SUNXI_SOC_ID_#X)

Used as SUNXI_SOC_IS(SUN4I) etc. What do you think?

> +
> +	if (cons_index == 1 && SOC_IS_SUN5I()) {
> +		u32 val = readl(SUNXI_SID_BASE + 0x08);
> +		if (((val >> 12) & 0xf) == 3) {

Can we use some #defines for the masks and shifts please.

> 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

How about putting this stuff in dram.c (or a new dram_default.c if you
prefer) marked as __weak? IOW make it the default for everything which
doesn't add a more specific dram_foo.c.

> @@ -0,0 +1,28 @@
> +/* this file is generated, don't edit it yourself */

I've had my doubts about this comment in the past, but here in
particular I was under the impression that you had manually selected the
safest values.

> +#define CONFIG_SYS_PROMPT		"sunxi# "

TBH I think we should just move this to -common.h and nuke the sun[457]i
ones, they don't serve much purpose, the specific SOC is identified in
the boot banner already.

FYI I'm now AFK until the 18th.

Ian.
diff mbox

Patch

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@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@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 */