add cubietruck u-boot image

This commit is contained in:
Dennis Gilmore 2014-04-26 21:49:55 -05:00
parent 0454bb3cbb
commit 1619496436
39 changed files with 5562 additions and 36 deletions

View File

@ -1,7 +1,7 @@
From 797867f56b9e3e2307fc2537b062b8a482d4b472 Mon Sep 17 00:00:00 2001
From 8e9b2c56256a14264fb52b2ea6d9a862948a53e8 Mon Sep 17 00:00:00 2001
From: Tom Rini <trini@ti.com>
Date: Tue, 11 Mar 2014 15:42:01 -0400
Subject: [PATCH 01/14] TI: Add, use a DEFAULT_LINUX_BOOT_ENV environment
Subject: [PATCH 01/36] TI: Add, use a DEFAULT_LINUX_BOOT_ENV environment
string
To deal with a reoccurring problem properly we need to specify addresses

View File

@ -1,7 +1,7 @@
From 9c80863e93e251b7068a7a9945694a72a300f505 Mon Sep 17 00:00:00 2001
From 039bd0adca69ba7e415115620840c02f98f8e58b Mon Sep 17 00:00:00 2001
From: Tom Rini <trini@ti.com>
Date: Tue, 11 Mar 2014 15:42:02 -0400
Subject: [PATCH 02/14] am335x_evm: Update the ramdisk args, we pass things in
Subject: [PATCH 02/36] am335x_evm: Update the ramdisk args, we pass things in
just fine via DT
Signed-off-by: Tom Rini <trini@ti.com>

View File

@ -1,7 +1,7 @@
From d7b992e954721ce563093ab480e93ebe5222ca6e Mon Sep 17 00:00:00 2001
From 598c3e06f09b85e8eceac86e4d1df6c65491c662 Mon Sep 17 00:00:00 2001
From: Tom Rini <trini@ti.com>
Date: Tue, 11 Mar 2014 15:42:03 -0400
Subject: [PATCH 03/14] am43xx_evm: Update the ramdisk args, we pass things in
Subject: [PATCH 03/36] am43xx_evm: Update the ramdisk args, we pass things in
just fine via DT
Signed-off-by: Tom Rini <trini@ti.com>

View File

@ -1,7 +1,7 @@
From 93d278a447956d0ec62c23215d1998cadd4c5f09 Mon Sep 17 00:00:00 2001
From d96ac74e4d59c4dfbd70420b22d47dd6927a585e Mon Sep 17 00:00:00 2001
From: Dennis Gilmore <dennis@ausil.us>
Date: Mon, 21 Apr 2014 12:07:23 -0500
Subject: [PATCH 04/14] pxe: additionaly check for fdt_file env variable
Subject: [PATCH 04/36] pxe: additionaly check for fdt_file env variable
some boards have used fdt_file while others have used fdtfile to
define the name of the fdt file. If we do notget a fdtfile environment

View File

@ -1,7 +1,7 @@
From 77d98dff1c43a7d87c3a1d4c55f4abea47d4d6f9 Mon Sep 17 00:00:00 2001
From db17b881ade00837d1f6a8d979c05eccf98bda6c Mon Sep 17 00:00:00 2001
From: Dennis Gilmore <dennis@ausil.us>
Date: Mon, 21 Apr 2014 12:15:35 -0500
Subject: [PATCH 05/14] convert snowball to distro generic config
Subject: [PATCH 05/36] convert snowball to distro generic config
---
include/configs/snowball.h | 78 +++++++++-------------------------------------

View File

@ -1,7 +1,7 @@
From fa49dd96a3b4e9ca66480d4b729f6ae543b82e17 Mon Sep 17 00:00:00 2001
From 990f5975ff3cd68db9d47a8c00769342dc72a647 Mon Sep 17 00:00:00 2001
From: Dennis Gilmore <dennis@ausil.us>
Date: Mon, 21 Apr 2014 12:17:14 -0500
Subject: [PATCH 06/14] move wandboard over to use the generic distro
Subject: [PATCH 06/36] move wandboard over to use the generic distro
configuation and environment
port wandboard to use the generic distro configuation.

View File

@ -1,7 +1,7 @@
From 48eb6e1d1daf48f333dbb3210dc9866afecf9c38 Mon Sep 17 00:00:00 2001
From 925dbd3bdb96e13449577b1386bf76c2e9f970a3 Mon Sep 17 00:00:00 2001
From: Dennis Gilmore <dennis@ausil.us>
Date: Mon, 21 Apr 2014 12:18:26 -0500
Subject: [PATCH 07/14] move udoo over to use the generic distro configuation
Subject: [PATCH 07/36] move udoo over to use the generic distro configuation
and environment
port udoo to use the generic distro configuation.

View File

@ -1,7 +1,7 @@
From b46336f269ee46536322315706b27c00f02e06c5 Mon Sep 17 00:00:00 2001
From 25f764594b2f826b1cd90119e6d58c4e4b6f097a Mon Sep 17 00:00:00 2001
From: Dennis Gilmore <dennis@ausil.us>
Date: Mon, 21 Apr 2014 12:23:10 -0500
Subject: [PATCH 08/14] move pandaboard over to use the generic distro
Subject: [PATCH 08/36] move pandaboard over to use the generic distro
configuation and environment
port pandaboard to use the generic distro configuation.

View File

@ -1,7 +1,7 @@
From c541b9036bccc359f13c73924e6ee2f837daaa55 Mon Sep 17 00:00:00 2001
From 2d29a19e398f752ce7398d184051d12a191ccbb1 Mon Sep 17 00:00:00 2001
From: Dennis Gilmore <dennis@ausil.us>
Date: Mon, 21 Apr 2014 12:27:22 -0500
Subject: [PATCH 09/14] move beaglebone over to use the generic distro
Subject: [PATCH 09/36] move beaglebone over to use the generic distro
configuation and environment
port beaglebone to use the generic distro configuation.

View File

@ -1,7 +1,7 @@
From 99b529d14da75487600043d3f0c209d1c54d14e9 Mon Sep 17 00:00:00 2001
From b8dfe74309a4f61fa0078ad04fd4bb4141b13a51 Mon Sep 17 00:00:00 2001
From: Dennis Gilmore <dennis@ausil.us>
Date: Mon, 21 Apr 2014 12:29:04 -0500
Subject: [PATCH 10/14] add header with a generic set of boot commands defined.
Subject: [PATCH 10/36] add header with a generic set of boot commands defined.
As the next step in a generic config we are introducing a set of generic boot
paramaters. Depending on the hardwares configuration, booting from supported
@ -18,7 +18,7 @@ boots. for example simply be able to pxe boot to reinstall
diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h
new file mode 100644
index 0000000..f0620ff
index 0000000..025c4d4
--- /dev/null
+++ b/include/config_distro_bootcmd.h
@@ -0,0 +1,209 @@

View File

@ -1,7 +1,7 @@
From 92e9920fc35a3e53ab1fdf3ad934e951c597e7c2 Mon Sep 17 00:00:00 2001
From f7806a439761d63332b35d20275f08bacf5ac32a Mon Sep 17 00:00:00 2001
From: Dennis Gilmore <dennis@ausil.us>
Date: Mon, 21 Apr 2014 12:29:49 -0500
Subject: [PATCH 11/14] add README.distro file
Subject: [PATCH 11/36] add README.distro file
Add documentation on how to setup a system to use the generic distro
configs and boot commands. This spells out what is needed to make a

View File

@ -1,7 +1,7 @@
From fcadba88c2e9d7214b25a8ed4d263ebbc22f0680 Mon Sep 17 00:00:00 2001
From 7dca6801753c89aef0afd5731a08fdf88c45127e Mon Sep 17 00:00:00 2001
From: Dennis Gilmore <dennis@ausil.us>
Date: Mon, 21 Apr 2014 12:31:22 -0500
Subject: [PATCH 12/14] cleanup duplicate options in paz00 config
Subject: [PATCH 12/36] cleanup duplicate options in paz00 config
---
include/configs/paz00.h | 2 --

View File

@ -1,7 +1,7 @@
From f57beade9b49254f82f2e817e727161c08f0c38a Mon Sep 17 00:00:00 2001
From 9c3e5ff69a47086bb7428043ed91261a6b6b9d18 Mon Sep 17 00:00:00 2001
From: Dennis Gilmore <dennis@ausil.us>
Date: Mon, 21 Apr 2014 12:33:43 -0500
Subject: [PATCH 13/14] add hackish utilite build based on wandboard
Subject: [PATCH 13/36] add hackish utilite build based on wandboard
---
board/compulab/utilite/Makefile | 7 +

View File

@ -1,7 +1,7 @@
From f972c558cbf06331f0738946304a0cca3e163d85 Mon Sep 17 00:00:00 2001
From 619b07ef07df8f06039a5502df8408ad9abed960 Mon Sep 17 00:00:00 2001
From: Dennis Gilmore <dennis@ausil.us>
Date: Mon, 21 Apr 2014 12:35:27 -0500
Subject: [PATCH 14/14] add to ti_armv7_common.h generic distro environment
Subject: [PATCH 14/36] add to ti_armv7_common.h generic distro environment
variables
there are two new environment variables and addresses that need

View File

@ -1,7 +1,7 @@
From 250fb75f8233cd3502736b474618e6c5d7f13aae Mon Sep 17 00:00:00 2001
From 8ef41c6750f256383ea38ee7aa6d03924cdeeeb4 Mon Sep 17 00:00:00 2001
From: Dennis Gilmore <dennis@ausil.us>
Date: Mon, 21 Apr 2014 14:44:07 -0500
Subject: [PATCH 15/15] omap4 buildfixes
Subject: [PATCH 15/36] omap4 buildfixes
---
include/configs/ti_omap4_common.h | 4 ----

View File

@ -1,7 +1,7 @@
From 838ea5b6076ba27c6d20c6370ff0a996acaa5eec Mon Sep 17 00:00:00 2001
From 7dace4fe678448c98ebb7beaa01ca64788ab02b4 Mon Sep 17 00:00:00 2001
From: Dennis Gilmore <dennis@ausil.us>
Date: Wed, 23 Apr 2014 15:54:57 -0500
Subject: [PATCH 16/17] automatically add console= to bootline when not
Subject: [PATCH 16/36] automatically add console= to bootline when not
existing
if there is a console variable in the u-boot environment and not one on

View File

@ -1,7 +1,7 @@
From 84f7df44e38f8d721e17a585b95dce4027062ada Mon Sep 17 00:00:00 2001
From 9296c4b08240aecda4abb4ff405ab48a26cf444d Mon Sep 17 00:00:00 2001
From: Dennis Gilmore <dennis@ausil.us>
Date: Wed, 23 Apr 2014 15:58:49 -0500
Subject: [PATCH 17/17] make bootdelay match the generic distro default
Subject: [PATCH 17/36] make bootdelay match the generic distro default
---
include/configs/ti_armv7_common.h | 2 +-

View File

@ -0,0 +1,818 @@
From 5ada9882f4e92cb978cd8d06c6dd3410c92e1f33 Mon Sep 17 00:00:00 2001
From: Ian Campbell <ijc@hellion.org.uk>
Date: Fri, 18 Apr 2014 19:05:42 +0100
Subject: [PATCH 18/36] sunxi: add sun7i clocks and timer support.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch adds the basic clocks and timer support for the Allwinner A20
(sun7i) processor. This code will not been compiled until the build is hooked
up in a later patch. It has been split out to keep the patches manageable.
Some of the code here is common to multiple sunxi subarchtectures, hence files
are named sun4i which is the earliest similar variant.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Emilio López <emilio@elopez.com.ar>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Henrik Nordstrom <henrik@henriknordstrom.net>
Signed-off-by: Jens Kuske <jenskuske@gmail.com>
Signed-off-by: Luke Leighton <lkcl@lkcl.net>
Signed-off-by: Oliver Schinagl <oliver@schinagl.nl>
Signed-off-by: Ian Campbell <ijc@hellion.org.uk>
Cc: Stefan Roese <sr@denx.de>
Cc: Tom Cubie <Mr.hipboi@gmail.com>
---
arch/arm/cpu/armv7/sunxi/Makefile | 12 ++
arch/arm/cpu/armv7/sunxi/clock.c | 35 ++++
arch/arm/cpu/armv7/sunxi/clock_sun4i.c | 176 ++++++++++++++++++
arch/arm/cpu/armv7/sunxi/timer.c | 110 +++++++++++
arch/arm/include/asm/arch-sunxi/clock.h | 29 +++
arch/arm/include/asm/arch-sunxi/clock_sun4i.h | 256 ++++++++++++++++++++++++++
arch/arm/include/asm/arch-sunxi/sys_proto.h | 16 ++
arch/arm/include/asm/arch-sunxi/timer.h | 88 +++++++++
8 files changed, 722 insertions(+)
create mode 100644 arch/arm/cpu/armv7/sunxi/Makefile
create mode 100644 arch/arm/cpu/armv7/sunxi/clock.c
create mode 100644 arch/arm/cpu/armv7/sunxi/clock_sun4i.c
create mode 100644 arch/arm/cpu/armv7/sunxi/timer.c
create mode 100644 arch/arm/include/asm/arch-sunxi/clock.h
create mode 100644 arch/arm/include/asm/arch-sunxi/clock_sun4i.h
create mode 100644 arch/arm/include/asm/arch-sunxi/sys_proto.h
create mode 100644 arch/arm/include/asm/arch-sunxi/timer.h
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
new file mode 100644
index 0000000..440d266
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -0,0 +1,12 @@
+#
+# (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.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+obj-y += timer.o
+obj-y += clock.o
+obj-$(CONFIG_SUN7I) += clock_sun4i.o
diff --git a/arch/arm/cpu/armv7/sunxi/clock.c b/arch/arm/cpu/armv7/sunxi/clock.c
new file mode 100644
index 0000000..94ba6e0
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/clock.c
@@ -0,0 +1,35 @@
+/*
+ * (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/gpio.h>
+#include <asm/arch/sys_proto.h>
+
+int clock_init(void)
+{
+#ifdef CONFIG_SPL_BUILD
+ clock_init_safe();
+#endif
+ clock_init_uart();
+
+ 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;
+ 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/clock_sun4i.c b/arch/arm/cpu/armv7/sunxi/clock_sun4i.c
new file mode 100644
index 0000000..566a69e
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/clock_sun4i.c
@@ -0,0 +1,176 @@
+/*
+ * sun4i, sun5i and sun7i 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/gpio.h>
+#include <asm/arch/sys_proto.h>
+
+#ifdef CONFIG_SPL_BUILD
+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 << AXI_DIV_SHIFT |
+ AHB_DIV_2 << AHB_DIV_SHIFT |
+ APB0_DIV_1 << APB0_DIV_SHIFT |
+ CPU_CLK_SRC_OSC24M << CPU_CLK_SRC_SHIFT,
+ &ccm->cpu_ahb_apb0_cfg);
+ writel(PLL1_CFG_DEFAULT, &ccm->pll1_cfg);
+ sdelay(200);
+ writel(AXI_DIV_1 << AXI_DIV_SHIFT |
+ AHB_DIV_2 << AHB_DIV_SHIFT |
+ APB0_DIV_1 << APB0_DIV_SHIFT |
+ CPU_CLK_SRC_PLL1 << CPU_CLK_SRC_SHIFT,
+ &ccm->cpu_ahb_apb0_cfg);
+#ifdef CONFIG_SUN7I
+ writel(0x1 << AHB_GATE_OFFSET_DMA | readl(&ccm->ahb_gate0),
+ &ccm->ahb_gate0);
+#endif
+ writel(PLL6_CFG_DEFAULT, &ccm->pll6_cfg);
+}
+#endif
+
+void clock_init_uart(void)
+{
+ struct sunxi_ccm_reg *const ccm =
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+ /* uart clock source is apb1 */
+ writel(APB1_CLK_SRC_OSC24M|
+ APB1_CLK_RATE_N_1|
+ APB1_CLK_RATE_M(1),
+ &ccm->apb1_clk_div_cfg);
+
+ /* open the clock for uart */
+ setbits_le32(&ccm->apb1_gate,
+ CLK_GATE_OPEN << (APB1_GATE_UART_SHIFT+CONFIG_CONS_INDEX-1));
+}
+
+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 apb clock gate for twi */
+ if (state)
+ setbits_le32(&ccm->apb1_gate,
+ CLK_GATE_OPEN << (APB1_GATE_TWI_SHIFT+port));
+ else
+ clrbits_le32(&ccm->apb1_gate,
+ CLK_GATE_OPEN << (APB1_GATE_TWI_SHIFT+port));
+
+ return 0;
+}
+
+#ifdef CONFIG_SPL_BUILD
+#define PLL1_CFG(N, K, M, P) ( 1 << CCM_PLL1_CFG_ENABLE_SHIFT | \
+ 0 << CCM_PLL1_CFG_VCO_RST_SHIFT | \
+ 8 << CCM_PLL1_CFG_VCO_BIAS_SHIFT | \
+ 0 << CCM_PLL1_CFG_PLL4_EXCH_SHIFT | \
+ 16 << CCM_PLL1_CFG_BIAS_CUR_SHIFT | \
+ (P)<< CCM_PLL1_CFG_DIVP_SHIFT | \
+ 2 << CCM_PLL1_CFG_LCK_TMR_SHIFT | \
+ (N)<< CCM_PLL1_CFG_FACTOR_N_SHIFT | \
+ (K)<< CCM_PLL1_CFG_FACTOR_K_SHIFT | \
+ 0 << CCM_PLL1_CFG_SIG_DELT_PAT_IN_SHIFT | \
+ 0 << CCM_PLL1_CFG_SIG_DELT_PAT_EN_SHIFT | \
+ (M)<< CCM_PLL1_CFG_FACTOR_M_SHIFT)
+
+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 = DIV_ROUND_UP(hz, 432000000); /* Max 450MHz */
+ ahb = DIV_ROUND_UP(hz/axi, 204000000); /* Max 250MHz */
+ apb0 = 2; /* Max 150MHz */
+
+ printf("CPU: %dHz, AXI/AHB/APB: %d/%d/%d\n", hz, axi, ahb, apb0);
+
+ /* 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 << AXI_DIV_SHIFT |
+ AHB_DIV_2 << AHB_DIV_SHIFT |
+ APB0_DIV_1 << APB0_DIV_SHIFT |
+ CPU_CLK_SRC_OSC24M << CPU_CLK_SRC_SHIFT,
+ &ccm->cpu_ahb_apb0_cfg);
+ sdelay(20);
+
+ /* Configure sys clock divisors */
+ writel(axi << AXI_DIV_SHIFT |
+ ahb << AHB_DIV_SHIFT |
+ apb0 << APB0_DIV_SHIFT |
+ CPU_CLK_SRC_OSC24M << CPU_CLK_SRC_SHIFT,
+ &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 << AXI_DIV_SHIFT |
+ ahb << AHB_DIV_SHIFT |
+ apb0 << APB0_DIV_SHIFT |
+ CPU_CLK_SRC_PLL1 << CPU_CLK_SRC_SHIFT,
+ &ccm->cpu_ahb_apb0_cfg);
+ sdelay(20);
+}
+#endif
diff --git a/arch/arm/cpu/armv7/sunxi/timer.c b/arch/arm/cpu/armv7/sunxi/timer.c
new file mode 100644
index 0000000..ca951a2
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/timer.c
@@ -0,0 +1,110 @@
+/*
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/timer.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define TIMER_MODE (0x0 << 7) /* continuous mode */
+#define TIMER_DIV (0x0 << 4) /* pre scale 1 */
+#define TIMER_SRC (0x1 << 2) /* osc24m */
+#define TIMER_RELOAD (0x1 << 1) /* reload internal value */
+#define TIMER_EN (0x1 << 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 */
+
+/* read the 32-bit timer */
+static ulong read_timer(void)
+{
+ struct sunxi_timer_reg *timers =
+ (struct sunxi_timer_reg *)SUNXI_TIMER_BASE;
+ struct sunxi_timer *timer = &timers->timer[TIMER_NUM];
+ /* The hardware timer counts down, therefore we invert to
+ * produce an incrementing timer. */
+ return ~readl(&timer->val);
+}
+
+/* init timer register */
+int timer_init(void)
+{
+ struct sunxi_timer_reg *timers =
+ (struct sunxi_timer_reg *)SUNXI_TIMER_BASE;
+ struct sunxi_timer *timer = &timers->timer[TIMER_NUM];
+ writel(TIMER_LOAD_VAL, &timer->inter);
+ writel(TIMER_MODE | TIMER_DIV | TIMER_SRC | TIMER_RELOAD | TIMER_EN,
+ &timer->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_TO_COUNT(usec);
+ 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)
+{
+ return CONFIG_SYS_HZ;
+}
diff --git a/arch/arm/include/asm/arch-sunxi/clock.h b/arch/arm/include/asm/arch-sunxi/clock.h
new file mode 100644
index 0000000..5d1b6a6
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/clock.h
@@ -0,0 +1,29 @@
+/*
+ * (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_H
+#define _SUNXI_CLOCK_H
+
+#include <linux/types.h>
+
+#define CLK_GATE_OPEN 0x1
+#define CLK_GATE_CLOSE 0x0
+
+/* clock control module regs definition */
+#include <asm/arch/clock_sun4i.h>
+
+#ifndef __ASSEMBLY__
+int clock_init(void);
+int clock_twi_onoff(int port, int state);
+void clock_set_pll1(int hz);
+unsigned int clock_get_pll6(void);
+void clock_init_safe(void);
+void clock_init_uart(void);
+#endif
+
+#endif /* _SUNXI_CLOCK_H */
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
new file mode 100644
index 0000000..928f3f2
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
@@ -0,0 +1,256 @@
+/*
+ * sun4i, sun5i and sun7i 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_SUN4I_H
+#define _SUNXI_CLOCK_SUN4I_H
+
+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 */
+ u8 res8[0x4];
+ u32 gmac_clk_cfg; /* 0x164 */
+};
+
+/* apb1 bit field */
+#define APB1_CLK_SRC_OSC24M (0x0 << 24)
+#define APB1_CLK_SRC_PLL6 (0x1 << 24)
+#define APB1_CLK_SRC_LOSC (0x2 << 24)
+#define APB1_CLK_SRC_MASK (0x3 << 24)
+#define APB1_CLK_RATE_N_1 (0x0 << 16)
+#define APB1_CLK_RATE_N_2 (0x1 << 16)
+#define APB1_CLK_RATE_N_4 (0x2 << 16)
+#define APB1_CLK_RATE_N_8 (0x3 << 16)
+#define APB1_CLK_RATE_N_MASK (3 << 16)
+#define APB1_CLK_RATE_M(m) (((m)-1) << 0)
+#define APB1_CLK_RATE_M_MASK (0x1f << 0)
+
+/* apb1 gate field */
+#define APB1_GATE_UART_SHIFT (16)
+#define APB1_GATE_UART_MASK (0xff << APB1_GATE_UART_SHIFT)
+#define APB1_GATE_TWI_SHIFT (0)
+#define APB1_GATE_TWI_MASK (0xf << APB1_GATE_TWI_SHIFT)
+
+/* clock divide */
+#define AXI_DIV_SHIFT (0)
+#define AXI_DIV_1 0
+#define AXI_DIV_2 1
+#define AXI_DIV_3 2
+#define AXI_DIV_4 3
+#define AHB_DIV_SHIFT (4)
+#define AHB_DIV_1 0
+#define AHB_DIV_2 1
+#define AHB_DIV_4 2
+#define AHB_DIV_8 3
+#define APB0_DIV_SHIFT (8)
+#define APB0_DIV_1 0
+#define APB0_DIV_2 1
+#define APB0_DIV_4 2
+#define APB0_DIV_8 3
+#define CPU_CLK_SRC_SHIFT (16)
+#define CPU_CLK_SRC_OSC24M 1
+#define CPU_CLK_SRC_PLL1 2
+
+#define CCM_PLL1_CFG_ENABLE_SHIFT 31
+#define CCM_PLL1_CFG_VCO_RST_SHIFT 30
+#define CCM_PLL1_CFG_VCO_BIAS_SHIFT 26
+#define CCM_PLL1_CFG_PLL4_EXCH_SHIFT 25
+#define CCM_PLL1_CFG_BIAS_CUR_SHIFT 20
+#define CCM_PLL1_CFG_DIVP_SHIFT 16
+#define CCM_PLL1_CFG_LCK_TMR_SHIFT 13
+#define CCM_PLL1_CFG_FACTOR_N_SHIFT 8
+#define CCM_PLL1_CFG_FACTOR_K_SHIFT 4
+#define CCM_PLL1_CFG_SIG_DELT_PAT_IN_SHIFT 3
+#define CCM_PLL1_CFG_SIG_DELT_PAT_EN_SHIFT 2
+#define CCM_PLL1_CFG_FACTOR_M_SHIFT 0
+
+#define PLL1_CFG_DEFAULT 0xa1005000
+
+#define PLL6_CFG_DEFAULT 0xa1009911
+
+/* 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_MMC(n) (AHB_GATE_OFFSET_MMC0 + (n))
+#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
+
+/* ahb clock gate bit offset (second register) */
+#define AHB_GATE_OFFSET_GMAC 17
+
+#define CCM_AHB_GATE_GPS (0x1 << 26)
+#define CCM_AHB_GATE_SDRAM (0x1 << 14)
+#define CCM_AHB_GATE_DLL (0x1 << 15)
+#define CCM_AHB_GATE_ACE (0x1 << 16)
+
+#define CCM_PLL5_CTRL_M(n) (((n) & 0x3) << 0)
+#define CCM_PLL5_CTRL_M_MASK CCM_PLL5_CTRL_M(0x3)
+#define CCM_PLL5_CTRL_M_X(n) ((n) - 1)
+#define CCM_PLL5_CTRL_M1(n) (((n) & 0x3) << 2)
+#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_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_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_MASK CCM_PLL5_CTRL_P(0x3)
+#define CCM_PLL5_CTRL_P_X(n) ((n) - 1)
+#define CCM_PLL5_CTRL_BW (0x1 << 18)
+#define CCM_PLL5_CTRL_VCO_GAIN (0x1 << 19)
+#define CCM_PLL5_CTRL_BIAS(n) (((n) & 0x1f) << 20)
+#define CCM_PLL5_CTRL_BIAS_MASK CCM_PLL5_CTRL_BIAS(0x1f)
+#define CCM_PLL5_CTRL_BIAS_X(n) ((n) - 1)
+#define CCM_PLL5_CTRL_VCO_BIAS (0x1 << 25)
+#define CCM_PLL5_CTRL_DDR_CLK (0x1 << 29)
+#define CCM_PLL5_CTRL_BYPASS (0x1 << 30)
+#define CCM_PLL5_CTRL_EN (0x1 << 31)
+
+#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 CCM_GPS_CTRL_RESET (0x1 << 0)
+#define CCM_GPS_CTRL_GATE (0x1 << 1)
+
+#define CCM_DRAM_CTRL_DCLK_OUT (0x1 << 15)
+
+#define CCM_MBUS_CTRL_M(n) (((n) & 0xf) << 0)
+#define CCM_MBUS_CTRL_M_MASK CCM_MBUS_CTRL_M(0xf)
+#define CCM_MBUS_CTRL_M_X(n) ((n) - 1)
+#define CCM_MBUS_CTRL_N(n) (((n) & 0xf) << 16)
+#define CCM_MBUS_CTRL_N_MASK CCM_MBUS_CTRL_N(0xf)
+#define CCM_MBUS_CTRL_N_X(n) (((n) >> 3) ? 3 : (((n) >> 2) ? 2 : (((n) >> 1) ? 1 : 0)))
+#define CCM_MBUS_CTRL_CLK_SRC(n) (((n) & 0x3) << 24)
+#define CCM_MBUS_CTRL_CLK_SRC_MASK CCM_MBUS_CTRL_CLK_SRC(0x3)
+#define CCM_MBUS_CTRL_CLK_SRC_HOSC 0x0
+#define CCM_MBUS_CTRL_CLK_SRC_PLL6 0x1
+#define CCM_MBUS_CTRL_CLK_SRC_PLL5 0x2
+#define CCM_MBUS_CTRL_GATE (0x1 << 31)
+
+#define CCM_MMC_CTRL_OSCM24 (0x0 << 24)
+#define CCM_MMC_CTRL_PLL6 (0x1 << 24)
+#define CCM_MMC_CTRL_PLL5 (0x2 << 24)
+
+#define CCM_MMC_CTRL_ENABLE (0x1 << 31)
+
+#define CCM_GMAC_CTRL_TX_CLK_SRC_MII 0x0
+#define CCM_GMAC_CTRL_TX_CLK_SRC_EXT_RGMII 0x1
+#define CCM_GMAC_CTRL_TX_CLK_SRC_INT_RGMII 0x2
+#define CCM_GMAC_CTRL_GPIT_MII (0x0 << 2)
+#define CCM_GMAC_CTRL_GPIT_RGMII (0x1 << 2)
+
+#endif /* _SUNXI_CLOCK_SUN4I_H */
diff --git a/arch/arm/include/asm/arch-sunxi/sys_proto.h b/arch/arm/include/asm/arch-sunxi/sys_proto.h
new file mode 100644
index 0000000..c3e636e
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/sys_proto.h
@@ -0,0 +1,16 @@
+/*
+ * (C) Copyright 2007-2012
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _SYS_PROTO_H_
+#define _SYS_PROTO_H_
+
+#include <linux/types.h>
+
+void sdelay(unsigned long);
+
+#endif
diff --git a/arch/arm/include/asm/arch-sunxi/timer.h b/arch/arm/include/asm/arch-sunxi/timer.h
new file mode 100644
index 0000000..6aacfd7
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/timer.h
@@ -0,0 +1,88 @@
+/*
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * Configuration settings for the Allwinner A10-evb board.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _SUNXI_TIMER_H_
+#define _SUNXI_TIMER_H_
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+/* 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
--
1.9.0

View File

@ -0,0 +1,262 @@
From 98fdf764f9eb70fb312ebeeab903ad438783c3ba Mon Sep 17 00:00:00 2001
From: Ian Campbell <ijc@hellion.org.uk>
Date: Fri, 18 Apr 2014 19:05:43 +0100
Subject: [PATCH 19/36] sunxi: add sun7i pinmux and gpio support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch adds the basic pinmux and gpio support for the Allwinner A20 (sun7i)
processor. This code will not been compiled until the build is hooked up in a
later patch. It has been split out to keep the patches manageable.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Ma Haijun <mahaijuns@gmail.com>
Signed-off-by: Oliver Schinagl <oliver@schinagl.nl>
Signed-off-by: Henrik Nordström <henrik@henriknordstrom.net>
Signed-off-by: Ian Campbell <ijc@hellion.org.uk>
Reviewed-by: Tom Rini <trini@ti.com>
Cc: Stefan Roese <sr@denx.de>
Cc: Tom Cubie <Mr.hipboi@gmail.com>
---
arch/arm/cpu/armv7/sunxi/Makefile | 1 +
arch/arm/cpu/armv7/sunxi/pinmux.c | 61 ++++++++++++++
arch/arm/include/asm/arch-sunxi/gpio.h | 147 +++++++++++++++++++++++++++++++++
3 files changed, 209 insertions(+)
create mode 100644 arch/arm/cpu/armv7/sunxi/pinmux.c
create mode 100644 arch/arm/include/asm/arch-sunxi/gpio.h
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
index 440d266..529e7ec 100644
--- a/arch/arm/cpu/armv7/sunxi/Makefile
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -9,4 +9,5 @@
#
obj-y += timer.o
obj-y += clock.o
+obj-y += pinmux.o
obj-$(CONFIG_SUN7I) += clock_sun4i.o
diff --git a/arch/arm/cpu/armv7/sunxi/pinmux.c b/arch/arm/cpu/armv7/sunxi/pinmux.c
new file mode 100644
index 0000000..1f2843f
--- /dev/null
+++ b/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>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/gpio.h>
+
+int sunxi_gpio_set_cfgpin(u32 pin, u32 val)
+{
+ u32 bank = GPIO_BANK(pin);
+ u32 index = GPIO_CFG_INDEX(pin);
+ u32 offset = GPIO_CFG_OFFSET(pin);
+ struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+
+ clrsetbits_le32(&pio->cfg[0] + index, 0xf << offset, val << offset);
+
+ 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 = BANK_TO_GPIO(bank);
+
+ cfg = readl(&pio->cfg[0] + index);
+ cfg >>= offset;
+
+ return cfg & 0xf;
+}
+
+int sunxi_gpio_set_drv(u32 pin, u32 val)
+{
+ u32 bank = GPIO_BANK(pin);
+ u32 index = GPIO_DRV_INDEX(pin);
+ u32 offset = GPIO_DRV_OFFSET(pin);
+ struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+
+ clrsetbits_le32(&pio->drv[0] + index, 0x3 << offset, val << offset);
+
+ return 0;
+}
+
+int sunxi_gpio_set_pull(u32 pin, u32 val)
+{
+ u32 bank = GPIO_BANK(pin);
+ u32 index = GPIO_PULL_INDEX(pin);
+ u32 offset = GPIO_PULL_OFFSET(pin);
+ struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
+
+ clrsetbits_le32(&pio->pull[0] + index, 0x3 << offset, val << offset);
+
+ return 0;
+}
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
new file mode 100644
index 0000000..892479c
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
@@ -0,0 +1,147 @@
+/*
+ * (C) Copyright 2007-2012
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _SUNXI_GPIO_H
+#define _SUNXI_GPIO_H
+
+#include <linux/types.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
+#define SUNXI_GPIO_BANKS 9
+
+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[SUNXI_GPIO_BANKS];
+ u8 res[0xbc];
+ struct sunxi_gpio_int gpio_int;
+};
+
+#define BANK_TO_GPIO(bank) \
+ &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank]
+
+#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)
+
+#define GPIO_DRV_INDEX(pin) (((pin) & 0x1f) >> 4)
+#define GPIO_DRV_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1)
+
+#define GPIO_PULL_INDEX(pin) (((pin) & 0x1f) >> 4)
+#define GPIO_PULL_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1)
+
+/* 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_EMAC 2
+#define SUN7I_GPA0_GMAC 5
+
+#define SUNXI_GPB0_TWI0 2
+
+#define SUN4I_GPB22_UART0_TX 2
+#define SUN4I_GPB23_UART0_RX 2
+
+#define SUN5I_GPB19_UART0_TX 2
+#define SUN5I_GPB20_UART0_RX 2
+
+#define SUN5I_GPG3_UART1_TX 4
+#define SUN5I_GPG4_UART1_RX 4
+
+#define SUNXI_GPC6_SDC2 3
+
+#define SUNXI_GPF0_SDC0 2
+
+#define SUNXI_GPF2_SDC0 2
+#define SUNXI_GPF2_UART0_TX 4
+#define SUNXI_GPF4_UART0_RX 4
+
+#define SUN4I_GPG0_SDC1 4
+
+#define SUN4I_GPH22_SDC1 5
+
+#define SUN4I_GPI4_SDC3 2
+
+/* GPIO pin pull-up/down config */
+#define SUNXI_GPIO_PULL_DISABLE 0
+#define SUNXI_GPIO_PULL_UP 1
+#define SUNXI_GPIO_PULL_DOWN 2
+
+int sunxi_gpio_set_cfgpin(u32 pin, u32 val);
+int sunxi_gpio_get_cfgpin(u32 pin);
+int sunxi_gpio_set_drv(u32 pin, u32 val);
+int sunxi_gpio_set_pull(u32 pin, u32 val);
+
+#endif /* _SUNXI_GPIO_H */
--
1.9.0

View File

@ -0,0 +1,786 @@
From 515037543e7270b853bb6c6170257a30df91eb37 Mon Sep 17 00:00:00 2001
From: Ian Campbell <ijc@hellion.org.uk>
Date: Fri, 18 Apr 2014 19:05:44 +0100
Subject: [PATCH 20/36] sunxi: add sun7i dram setup support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch adds DRAM initialisation support for the Allwinner A20 (sun7i)
processor. This code will not been compiled until the build is hooked up in a
later patch. It has been split out to keep the patches manageable.
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Signed-off-by: Emilio López <emilio@elopez.com.ar>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Henrik Nordstrom <henrik@henriknordstrom.net>
Signed-off-by: Jens Kuske <jenskuske@gmail.com>
Signed-off-by: Luke Leighton <lkcl@lkcl.net>
Signed-off-by: Oliver Schinagl <oliver@schinagl.nl>
Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: Ian Campbell <ijc@hellion.org.uk>
Cc: Tom Cubie <Mr.hipboi@gmail.com>
---
arch/arm/cpu/armv7/sunxi/Makefile | 1 +
arch/arm/cpu/armv7/sunxi/dram.c | 553 +++++++++++++++++++++++++++++++++
arch/arm/include/asm/arch-sunxi/dram.h | 179 +++++++++++
3 files changed, 733 insertions(+)
create mode 100644 arch/arm/cpu/armv7/sunxi/dram.c
create mode 100644 arch/arm/include/asm/arch-sunxi/dram.h
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
index 529e7ec..d81d26c 100644
--- a/arch/arm/cpu/armv7/sunxi/Makefile
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -11,3 +11,4 @@ obj-y += timer.o
obj-y += clock.o
obj-y += pinmux.o
obj-$(CONFIG_SUN7I) += clock_sun4i.o
+obj-$(CONFIG_SUN7I) += dram.o
diff --git a/arch/arm/cpu/armv7/sunxi/dram.c b/arch/arm/cpu/armv7/sunxi/dram.c
new file mode 100644
index 0000000..52ae788
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/dram.c
@@ -0,0 +1,553 @@
+/*
+ * sunxi DRAM controller initialization
+ * (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
+ * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.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>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * Unfortunately the only documentation we have on the sun7i DRAM
+ * controller is Allwinner boot0 + boot1 code, and that code uses
+ * magic numbers & shifts with no explanations. Hence this code is
+ * rather undocumented and full of magic.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/dram.h>
+#include <asm/arch/timer.h>
+#include <asm/arch/sys_proto.h>
+
+#define CPU_CFG_CHIP_VER(n) ((n) << 6)
+#define CPU_CFG_CHIP_VER_MASK CPU_CFG_CHIP_VER(0x3)
+#define CPU_CFG_CHIP_REV_A 0x0
+#define CPU_CFG_CHIP_REV_C1 0x1
+#define CPU_CFG_CHIP_REV_C2 0x2
+#define CPU_CFG_CHIP_REV_B 0x3
+
+static void mctl_ddr3_reset(void)
+{
+ struct sunxi_dram_reg *dram =
+ (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
+
+ clrbits_le32(&dram->mcr, DRAM_MCR_RESET);
+ udelay(2);
+ setbits_le32(&dram->mcr, DRAM_MCR_RESET);
+}
+
+static void mctl_set_drive(void)
+{
+ struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
+
+ clrsetbits_le32(&dram->mcr, DRAM_MCR_MODE_NORM(0x3) | (0x3 << 28),
+ DRAM_MCR_MODE_EN(0x3) |
+ 0xffc);
+}
+
+static void mctl_itm_disable(void)
+{
+ struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
+
+ clrsetbits_le32(&dram->ccr, DRAM_CCR_INIT, DRAM_CCR_ITM_OFF);
+}
+
+static void mctl_itm_enable(void)
+{
+ struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
+
+ clrbits_le32(&dram->ccr, DRAM_CCR_ITM_OFF);
+}
+
+static void mctl_enable_dll0(u32 phase)
+{
+ struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
+
+ clrsetbits_le32(&dram->dllcr[0], 0x3f << 6,
+ ((phase >> 16) & 0x3f) << 6);
+ clrsetbits_le32(&dram->dllcr[0], DRAM_DLLCR_NRESET, DRAM_DLLCR_DISABLE);
+ udelay(2);
+
+ clrbits_le32(&dram->dllcr[0], DRAM_DLLCR_NRESET | DRAM_DLLCR_DISABLE);
+ udelay(22);
+
+ clrsetbits_le32(&dram->dllcr[0], DRAM_DLLCR_DISABLE, DRAM_DLLCR_NRESET);
+ udelay(22);
+}
+
+/*
+ * Note: This differs from pm/standby in that it checks the bus width
+ */
+static void mctl_enable_dllx(u32 phase)
+{
+ struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
+ u32 i, n, bus_width;
+
+ bus_width = readl(&dram->dcr);
+
+ if ((bus_width & DRAM_DCR_BUS_WIDTH_MASK) ==
+ DRAM_DCR_BUS_WIDTH(DRAM_DCR_BUS_WIDTH_32BIT))
+ n = DRAM_DCR_NR_DLLCR_32BIT;
+ else
+ n = DRAM_DCR_NR_DLLCR_16BIT;
+
+ for (i = 1; i < n; i++) {
+ clrsetbits_le32(&dram->dllcr[i], 0xf << 14,
+ (phase & 0xf) << 14);
+ clrsetbits_le32(&dram->dllcr[i], DRAM_DLLCR_NRESET,
+ DRAM_DLLCR_DISABLE);
+ phase >>= 4;
+ }
+ udelay(2);
+
+ for (i = 1; i < n; i++)
+ clrbits_le32(&dram->dllcr[i], DRAM_DLLCR_NRESET |
+ DRAM_DLLCR_DISABLE);
+ udelay(22);
+
+ for (i = 1; i < n; i++)
+ clrsetbits_le32(&dram->dllcr[i], DRAM_DLLCR_DISABLE,
+ DRAM_DLLCR_NRESET);
+ udelay(22);
+}
+
+static u32 hpcr_value[32] = {
+#ifdef CONFIG_SUN7I
+ 0x0301, 0x0301, 0x0301, 0x0301,
+ 0x0301, 0x0301, 0x0301, 0x0301,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0x1031, 0x1031, 0x0735, 0x1035,
+ 0x1035, 0x0731, 0x1031, 0x0735,
+ 0x1035, 0x1031, 0x0731, 0x1035,
+ 0x0001, 0x1031, 0, 0x1031
+ /* last row differs from boot0 source table
+ * 0x1031, 0x0301, 0x0301, 0x0731
+ * but boot0 code skips #28 and #30, and sets #29 and #31 to the
+ * value from #28 entry (0x1031)
+ */
+#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 &= ~CCM_PLL5_CTRL_M_MASK; /* set M to 0 (x1) */
+ reg_val |= CCM_PLL5_CTRL_M(CCM_PLL5_CTRL_M_X(2));
+ reg_val &= ~CCM_PLL5_CTRL_K_MASK; /* set K to 0 (x1) */
+ reg_val |= CCM_PLL5_CTRL_K(CCM_PLL5_CTRL_K_X(2));
+ reg_val &= ~CCM_PLL5_CTRL_N_MASK; /* set N to 0 (x0) */
+ reg_val |= CCM_PLL5_CTRL_N(CCM_PLL5_CTRL_N_X(clk / 24));
+ reg_val &= ~CCM_PLL5_CTRL_P_MASK; /* set P to 0 (x1) */
+ reg_val |= CCM_PLL5_CTRL_P(CCM_PLL5_CTRL_P_X(2));
+ reg_val &= ~CCM_PLL5_CTRL_VCO_GAIN; /* PLL VCO Gain off */
+ reg_val |= CCM_PLL5_CTRL_EN; /* PLL On */
+ writel(reg_val, &ccm->pll5_cfg);
+ udelay(5500);
+
+ setbits_le32(&ccm->pll5_cfg, CCM_PLL5_CTRL_DDR_CLK);
+
+#if defined(CONFIG_SUN4I) || defined(CONFIG_SUN7I)
+ /* reset GPS */
+ clrbits_le32(&ccm->gps_clk_cfg, CCM_GPS_CTRL_RESET | CCM_GPS_CTRL_GATE);
+ setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_GPS);
+ udelay(1);
+ clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_GPS);
+#endif
+
+ /* setup MBUS clock */
+ reg_val = CCM_MBUS_CTRL_GATE |
+ CCM_MBUS_CTRL_CLK_SRC(CCM_MBUS_CTRL_CLK_SRC_PLL6) |
+ CCM_MBUS_CTRL_N(CCM_MBUS_CTRL_N_X(2)) |
+ CCM_MBUS_CTRL_M(CCM_MBUS_CTRL_M_X(2));
+ writel(reg_val, &ccm->mbus_clk_cfg);
+
+ /*
+ * open DRAMC AHB & DLL register clock
+ * close it first
+ */
+ clrbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL);
+ udelay(22);
+
+ /* then open it */
+ setbits_le32(&ccm->ahb_gate0, CCM_AHB_GATE_SDRAM | CCM_AHB_GATE_DLL);
+ udelay(22);
+}
+
+static int dramc_scan_readpipe(void)
+{
+ struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
+ u32 reg_val;
+
+ /* data training trigger */
+#ifdef CONFIG_SUN7I
+ clrbits_le32(&dram->csr, DRAM_CSR_FAILED);
+#endif
+ setbits_le32(&dram->ccr, DRAM_CCR_DATA_TRAINING);
+
+ /* check whether data training process has completed */
+ while (readl(&dram->ccr) & DRAM_CCR_DATA_TRAINING)
+ ;
+
+ /* check data training result */
+ reg_val = readl(&dram->csr);
+ if (reg_val & DRAM_CSR_FAILED)
+ return -1;
+
+ return 0;
+}
+
+static int dramc_scan_dll_para(void)
+{
+ struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
+ const u32 dqs_dly[7] = {0x3, 0x2, 0x1, 0x0, 0xe, 0xd, 0xc};
+ const u32 clk_dly[15] = {0x07, 0x06, 0x05, 0x04, 0x03,
+ 0x02, 0x01, 0x00, 0x08, 0x10,
+ 0x18, 0x20, 0x28, 0x30, 0x38};
+ u32 clk_dqs_count[15];
+ u32 dqs_i, clk_i, cr_i;
+ u32 max_val, min_val;
+ u32 dqs_index, clk_index;
+
+ /* Find DQS_DLY Pass Count for every CLK_DLY */
+ for (clk_i = 0; clk_i < 15; clk_i++) {
+ clk_dqs_count[clk_i] = 0;
+ clrsetbits_le32(&dram->dllcr[0], 0x3f << 6,
+ (clk_dly[clk_i] & 0x3f) << 6);
+ for (dqs_i = 0; dqs_i < 7; dqs_i++) {
+ for (cr_i = 1; cr_i < 5; cr_i++) {
+ clrsetbits_le32(&dram->dllcr[cr_i],
+ 0x4f << 14,
+ (dqs_dly[dqs_i] & 0x4f) << 14);
+ }
+ udelay(2);
+ if (dramc_scan_readpipe() == 0)
+ clk_dqs_count[clk_i]++;
+ }
+ }
+ /* Test DQS_DLY Pass Count for every CLK_DLY from up to down */
+ for (dqs_i = 15; dqs_i > 0; dqs_i--) {
+ max_val = 15;
+ min_val = 15;
+ for (clk_i = 0; clk_i < 15; clk_i++) {
+ if (clk_dqs_count[clk_i] == dqs_i) {
+ max_val = clk_i;
+ if (min_val == 15)
+ min_val = clk_i;
+ }
+ }
+ if (max_val < 15)
+ break;
+ }
+
+ /* Check if Find a CLK_DLY failed */
+ if (!dqs_i)
+ goto fail;
+
+ /* Find the middle index of CLK_DLY */
+ clk_index = (max_val + min_val) >> 1;
+ if ((max_val == (15 - 1)) && (min_val > 0))
+ /* if CLK_DLY[MCTL_CLK_DLY_COUNT] is very good, then the middle
+ * value can be more close to the max_val
+ */
+ clk_index = (15 + clk_index) >> 1;
+ else if ((max_val < (15 - 1)) && (min_val == 0))
+ /* if CLK_DLY[0] is very good, then the middle value can be more
+ * close to the min_val
+ */
+ clk_index >>= 1;
+ if (clk_dqs_count[clk_index] < dqs_i)
+ clk_index = min_val;
+
+ /* Find the middle index of DQS_DLY for the CLK_DLY got above, and Scan
+ * read pipe again
+ */
+ clrsetbits_le32(&dram->dllcr[0], 0x3f << 6,
+ (clk_dly[clk_index] & 0x3f) << 6);
+ max_val = 7;
+ min_val = 7;
+ for (dqs_i = 0; dqs_i < 7; dqs_i++) {
+ clk_dqs_count[dqs_i] = 0;
+ for (cr_i = 1; cr_i < 5; cr_i++) {
+ clrsetbits_le32(&dram->dllcr[cr_i],
+ 0x4f << 14,
+ (dqs_dly[dqs_i] & 0x4f) << 14);
+ }
+ udelay(2);
+ if (dramc_scan_readpipe() == 0) {
+ clk_dqs_count[dqs_i] = 1;
+ max_val = dqs_i;
+ if (min_val == 7)
+ min_val = dqs_i;
+ }
+ }
+
+ if (max_val < 7) {
+ dqs_index = (max_val + min_val) >> 1;
+ if ((max_val == (7-1)) && (min_val > 0))
+ dqs_index = (7 + dqs_index) >> 1;
+ else if ((max_val < (7-1)) && (min_val == 0))
+ dqs_index >>= 1;
+ if (!clk_dqs_count[dqs_index])
+ dqs_index = min_val;
+ for (cr_i = 1; cr_i < 5; cr_i++) {
+ clrsetbits_le32(&dram->dllcr[cr_i],
+ 0x4f << 14,
+ (dqs_dly[dqs_index] & 0x4f) << 14);
+ }
+ udelay(2);
+ return dramc_scan_readpipe();
+ }
+
+fail:
+ clrbits_le32(&dram->dllcr[0], 0x3f << 6);
+ for (cr_i = 1; cr_i < 5; cr_i++)
+ clrbits_le32(&dram->dllcr[cr_i], 0x4f << 14);
+ udelay(2);
+
+ return dramc_scan_readpipe();
+}
+
+static void dramc_clock_output_en(u32 on)
+{
+#if defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I)
+ struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
+
+ if (on)
+ setbits_le32(&dram->mcr, DRAM_MCR_DCLK_OUT);
+ else
+ clrbits_le32(&dram->mcr, DRAM_MCR_DCLK_OUT);
+#endif
+}
+
+static const u16 tRFC_table[2][6] = {
+ /* 256Mb 512Mb 1Gb 2Gb 4Gb 8Gb */
+ /* DDR2 75ns 105ns 127.5ns 195ns 327.5ns invalid */
+ { 77, 108, 131, 200, 336, 336 },
+ /* DDR3 invalid 90ns 110ns 160ns 300ns 350ns */
+ { 93, 93, 113, 164, 308, 359 }
+};
+
+static void dramc_set_autorefresh_cycle(u32 clk, u32 type, u32 density)
+{
+ struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
+ u32 tRFC, tREFI;
+
+ tRFC = (tRFC_table[type][density] * clk + 1023) >> 10;
+ tREFI = (7987 * clk) >> 10; /* <= 7.8us */
+
+ writel(DRAM_DRR_TREFI(tREFI) | DRAM_DRR_TRFC(tRFC), &dram->drr);
+}
+
+unsigned long dramc_init(struct dram_para *para)
+{
+ struct sunxi_dram_reg *dram = (struct sunxi_dram_reg *)SUNXI_DRAMC_BASE;
+ u32 reg_val;
+ u32 density;
+ int ret_val;
+
+ /* check input dram parameter structure */
+ if (!para)
+ return 0;
+
+ /* setup DRAM relative clock */
+ mctl_setup_dram_clock(para->clock);
+
+ /* reset external DRAM */
+ mctl_set_drive();
+
+ /* dram clock off */
+ dramc_clock_output_en(0);
+
+ mctl_itm_disable();
+ mctl_enable_dll0(para->tpr3);
+
+ /* configure external DRAM */
+ reg_val = 0x0;
+ if (para->type == DRAM_MEMORY_TYPE_DDR3)
+ reg_val |= DRAM_DCR_TYPE_DDR3;
+ reg_val |= DRAM_DCR_IO_WIDTH(para->io_width >> 3);
+
+ if (para->density == 256)
+ density = DRAM_DCR_CHIP_DENSITY_256M;
+ else if (para->density == 512)
+ density = DRAM_DCR_CHIP_DENSITY_512M;
+ else if (para->density == 1024)
+ density = DRAM_DCR_CHIP_DENSITY_1024M;
+ else if (para->density == 2048)
+ density = DRAM_DCR_CHIP_DENSITY_2048M;
+ else if (para->density == 4096)
+ density = DRAM_DCR_CHIP_DENSITY_4096M;
+ else if (para->density == 8192)
+ density = DRAM_DCR_CHIP_DENSITY_8192M;
+ else
+ density = DRAM_DCR_CHIP_DENSITY_256M;
+
+ reg_val |= DRAM_DCR_CHIP_DENSITY(density);
+ reg_val |= DRAM_DCR_BUS_WIDTH((para->bus_width >> 3) - 1);
+ reg_val |= DRAM_DCR_RANK_SEL(para->rank_num - 1);
+ reg_val |= DRAM_DCR_CMD_RANK_ALL;
+ reg_val |= DRAM_DCR_MODE(DRAM_DCR_MODE_INTERLEAVE);
+ writel(reg_val, &dram->dcr);
+
+#ifdef CONFIG_SUN7I
+ setbits_le32(&dram->zqcr1, (0x1 << 24) | (0x1 << 1));
+ if (para->tpr4 & 0x2)
+ clrsetbits_le32(&dram->zqcr1, (0x1 << 24), (0x1 << 1));
+ dramc_clock_output_en(1);
+#endif
+
+#if (defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I))
+ /* 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_SUN7I
+ /* Set CKE Delay to about 1ms */
+ setbits_le32(&dram->idcr, 0x1ffff);
+#endif
+
+#ifdef CONFIG_SUN7I
+ if ((readl(&dram->ppwrsctl) & 0x1) != 0x1)
+ mctl_ddr3_reset();
+ else
+ setbits_le32(&dram->mcr, DRAM_MCR_RESET);
+#endif
+
+ udelay(1);
+
+ while (readl(&dram->ccr) & DRAM_CCR_INIT)
+ ;
+
+ mctl_enable_dllx(para->tpr3);
+
+ /* set refresh period */
+ dramc_set_autorefresh_cycle(para->clock, para->type - 2, density);
+
+ /* set timing parameters */
+ writel(para->tpr0, &dram->tpr0);
+ writel(para->tpr1, &dram->tpr1);
+ writel(para->tpr2, &dram->tpr2);
+
+ if (para->type == DRAM_MEMORY_TYPE_DDR3) {
+ reg_val = DRAM_MR_BURST_LENGTH(0x0);
+#if (defined(CONFIG_SUN5I) || defined(CONFIG_SUN7I))
+ reg_val |= DRAM_MR_POWER_DOWN;
+#endif
+ reg_val |= DRAM_MR_CAS_LAT(para->cas - 4);
+ reg_val |= DRAM_MR_WRITE_RECOVERY(0x5);
+ } else if (para->type == DRAM_MEMORY_TYPE_DDR2) {
+ reg_val = DRAM_MR_BURST_LENGTH(0x2);
+ reg_val |= DRAM_MR_CAS_LAT(para->cas);
+ reg_val |= DRAM_MR_WRITE_RECOVERY(0x5);
+ }
+ 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, DRAM_CCR_DQS_DRIFT_COMP, DRAM_CCR_DQS_GATE);
+
+#ifdef CONFIG_SUN7I
+ /* Command rate timing mode 2T & 1T */
+ if (para->tpr4 & 0x1)
+ setbits_le32(&dram->ccr, DRAM_CCR_COMMAND_RATE_1T);
+#endif
+ /* reset external DRAM */
+ setbits_le32(&dram->ccr, DRAM_CCR_INIT);
+ while (readl(&dram->ccr) & DRAM_CCR_INIT)
+ ;
+
+#ifdef CONFIG_SUN7I
+ /* setup zq calibration manual */
+ reg_val = readl(&dram->ppwrsctl);
+ if ((reg_val & 0x1) == 1) {
+ /* super_standby_flag = 1 */
+
+ reg_val = readl(0x01c20c00 + 0x120); /* rtc */
+ reg_val &= 0x000fffff;
+ reg_val |= 0x17b00000;
+ writel(reg_val, &dram->zqcr0);
+
+ /* exit self-refresh state */
+ clrsetbits_le32(&dram->dcr, 0x1f << 27, 0x12 << 27);
+ /* check whether command has been executed */
+ while (readl(&dram->dcr) & (0x1 << 31))
+ ;
+
+ udelay(2);
+
+ /* dram pad hold off */
+ setbits_le32(&dram->ppwrsctl, 0x16510000);
+
+ while (readl(&dram->ppwrsctl) & 0x1)
+ ;
+
+ /* exit self-refresh state */
+ clrsetbits_le32(&dram->dcr, 0x1f << 27, 0x12 << 27);
+
+ /* check whether command has been executed */
+ while (readl(&dram->dcr) & (0x1 << 31))
+ ;
+ udelay(2);
+
+ /* issue a refresh command */
+ clrsetbits_le32(&dram->dcr, 0x1f << 27, 0x13 << 27);
+ while (readl(&dram->dcr) & (0x1 << 31))
+ ;
+
+ udelay(2);
+ }
+#endif
+
+ /* scan read pipe value */
+ mctl_itm_enable();
+ if (para->tpr3 & (0x1 << 31)) {
+ ret_val = dramc_scan_dll_para();
+ if (ret_val == 0)
+ para->tpr3 =
+ (((readl(&dram->dllcr[0]) >> 6) & 0x3f) << 16) |
+ (((readl(&dram->dllcr[1]) >> 14) & 0xf) << 0) |
+ (((readl(&dram->dllcr[2]) >> 14) & 0xf) << 4) |
+ (((readl(&dram->dllcr[3]) >> 14) & 0xf) << 8) |
+ (((readl(&dram->dllcr[4]) >> 14) & 0xf) << 12
+ );
+ } else {
+ 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_0, PHYS_SDRAM_0_SIZE);
+}
diff --git a/arch/arm/include/asm/arch-sunxi/dram.h b/arch/arm/include/asm/arch-sunxi/dram.h
new file mode 100644
index 0000000..67fbfad
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/dram.h
@@ -0,0 +1,179 @@
+/*
+ * (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.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _SUNXI_DRAM_H
+#define _SUNXI_DRAM_H
+
+#include <linux/types.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 DRAM_CCR_COMMAND_RATE_1T (0x1 << 5)
+#define DRAM_CCR_DQS_GATE (0x1 << 14)
+#define DRAM_CCR_DQS_DRIFT_COMP (0x1 << 17)
+#define DRAM_CCR_ITM_OFF (0x1 << 28)
+#define DRAM_CCR_DATA_TRAINING (0x1 << 30)
+#define DRAM_CCR_INIT (0x1 << 31)
+
+#define DRAM_MEMORY_TYPE_DDR1 1
+#define DRAM_MEMORY_TYPE_DDR2 2
+#define DRAM_MEMORY_TYPE_DDR3 3
+#define DRAM_MEMORY_TYPE_LPDDR2 4
+#define DRAM_MEMORY_TYPE_LPDDR 5
+#define DRAM_DCR_TYPE (0x1 << 0)
+#define DRAM_DCR_TYPE_DDR2 0x0
+#define DRAM_DCR_TYPE_DDR3 0x1
+#define DRAM_DCR_IO_WIDTH(n) (((n) & 0x3) << 1)
+#define DRAM_DCR_IO_WIDTH_MASK DRAM_DCR_IO_WIDTH(0x3)
+#define DRAM_DCR_IO_WIDTH_8BIT 0x0
+#define DRAM_DCR_IO_WIDTH_16BIT 0x1
+#define DRAM_DCR_CHIP_DENSITY(n) (((n) & 0x7) << 3)
+#define DRAM_DCR_CHIP_DENSITY_MASK DRAM_DCR_CHIP_DENSITY(0x7)
+#define DRAM_DCR_CHIP_DENSITY_256M 0x0
+#define DRAM_DCR_CHIP_DENSITY_512M 0x1
+#define DRAM_DCR_CHIP_DENSITY_1024M 0x2
+#define DRAM_DCR_CHIP_DENSITY_2048M 0x3
+#define DRAM_DCR_CHIP_DENSITY_4096M 0x4
+#define DRAM_DCR_CHIP_DENSITY_8192M 0x5
+#define DRAM_DCR_BUS_WIDTH(n) (((n) & 0x7) << 6)
+#define DRAM_DCR_BUS_WIDTH_MASK DRAM_DCR_BUS_WIDTH(0x7)
+#define DRAM_DCR_BUS_WIDTH_32BIT 0x3
+#define DRAM_DCR_BUS_WIDTH_16BIT 0x1
+#define DRAM_DCR_BUS_WIDTH_8BIT 0x0
+#define DRAM_DCR_NR_DLLCR_32BIT 5
+#define DRAM_DCR_NR_DLLCR_16BIT 3
+#define DRAM_DCR_NR_DLLCR_8BIT 2
+#define DRAM_DCR_RANK_SEL(n) (((n) & 0x3) << 10)
+#define DRAM_DCR_RANK_SEL_MASK DRAM_DCR_CMD_RANK(0x3)
+#define DRAM_DCR_CMD_RANK_ALL (0x1 << 12)
+#define DRAM_DCR_MODE(n) (((n) & 0x3) << 13)
+#define DRAM_DCR_MODE_MASK DRAM_DCR_MODE(0x3)
+#define DRAM_DCR_MODE_SEQ 0x0
+#define DRAM_DCR_MODE_INTERLEAVE 0x1
+
+#define DRAM_CSR_FAILED (0x1 << 20)
+
+#define DRAM_DRR_TRFC(n) ((n) & 0xff)
+#define DRAM_DRR_TREFI(n) (((n) & 0xffff) << 8)
+#define DRAM_DRR_BURST(n) ((((n) - 1) & 0xf) << 24)
+
+#define DRAM_MCR_MODE_NORM(n) (((n) & 0x3) << 0)
+#define DRAM_MCR_MODE_NORM_MASK DRAM_MCR_MOD_NORM(0x3)
+#define DRAM_MCR_MODE_DQ_OUT(n) (((n) & 0x3) << 2)
+#define DRAM_MCR_MODE_DQ_OUT_MASK DRAM_MCR_MODE_DQ_OUT(0x3)
+#define DRAM_MCR_MODE_ADDR_OUT(n) (((n) & 0x3) << 4)
+#define DRAM_MCR_MODE_ADDR_OUT_MASK DRAM_MCR_MODE_ADDR_OUT(0x3)
+#define DRAM_MCR_MODE_DQ_IN_OUT(n) (((n) & 0x3) << 6)
+#define DRAM_MCR_MODE_DQ_IN_OUT_MASK DRAM_MCR_MODE_DQ_IN_OUT(0x3)
+#define DRAM_MCR_MODE_DQ_TURNON_DELAY(n) (((n) & 0x7) << 8)
+#define DRAM_MCR_MODE_DQ_TURNON_DELAY_MASK DRAM_MCR_MODE_DQ_TURNON_DELAY(0x7)
+#define DRAM_MCR_MODE_ADDR_IN (0x1 << 11)
+#define DRAM_MCR_RESET (0x1 << 12)
+#define DRAM_MCR_MODE_EN(n) (((n) & 0x3) << 13)
+#define DRAM_MCR_MODE_EN_MASK DRAM_MCR_MOD_EN(0x3)
+#define DRAM_MCR_DCLK_OUT (0x1 << 16)
+
+#define DRAM_DLLCR_NRESET (0x1 << 30)
+#define DRAM_DLLCR_DISABLE (0x1 << 31)
+
+#define DRAM_ZQCR0_IMP_DIV(n) (((n) & 0xff) << 20)
+#define DRAM_ZQCR0_IMP_DIV_MASK DRAM_ZQCR0_IMP_DIV(0xff)
+
+#define DRAM_IOCR_ODT_EN(n) ((((n) & 0x3) << 30) | ((n) & 0x3) << 0)
+#define DRAM_IOCR_ODT_EN_MASK DRAM_IOCR_ODT_EN(0x3)
+
+#define DRAM_MR_BURST_LENGTH(n) (((n) & 0x7) << 0)
+#define DRAM_MR_BURST_LENGTH_MASK DRAM_MR_BURST_LENGTH(0x7)
+#define DRAM_MR_CAS_LAT(n) (((n) & 0x7) << 4)
+#define DRAM_MR_CAS_LAT_MASK DRAM_MR_CAS_LAT(0x7)
+#define DRAM_MR_WRITE_RECOVERY(n) (((n) & 0x7) << 9)
+#define DRAM_MR_WRITE_RECOVERY_MASK DRAM_MR_WRITE_RECOVERY(0x7)
+#define DRAM_MR_POWER_DOWN (0x1 << 12)
+
+#define DRAM_CSEL_MAGIC 0x16237495
+
+unsigned long sunxi_dram_init(void);
+unsigned long dramc_init(struct dram_para *para);
+
+#endif /* _SUNXI_DRAM_H */
--
1.9.0

View File

@ -0,0 +1,713 @@
From 785ba593d5fa67ed2997ce937cafd5286459beaf Mon Sep 17 00:00:00 2001
From: Ian Campbell <ijc@hellion.org.uk>
Date: Fri, 18 Apr 2014 19:05:45 +0100
Subject: [PATCH 21/36] sunxi: add sun7i cpu, board and start of day support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch adds generic board, start of day and basic build system support for
the Allwinner A20 (sun7i) processor. This code will not been compiled until the
build is hooked up in a later patch. It has been split out to keep the patches
manageable.
Signed-off-by: Adam Sampson <ats@offog.org>
Signed-off-by: Aleksei Mamlin <mamlinav@gmail.com>
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Emilio López <emilio@elopez.com.ar>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Henrik Nordstrom <henrik@henriknordstrom.net>
Signed-off-by: Jens Kuske <jenskuske@gmail.com>
Signed-off-by: Luc Verhaegen <libv@skynet.be>
Signed-off-by: Luke Leighton <lkcl@lkcl.net>
Signed-off-by: Oliver Schinagl <oliver@schinagl.nl>
Signed-off-by: Patrick Wood <patrickhwood@gmail.com>
Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: Wills Wang <wills.wang.open@gmail.com>
Signed-off-by: Ian Campbell <ijc@hellion.org.uk>
Cc: Tom Cubie <Mr.hipboi@gmail.com>
---
arch/arm/cpu/armv7/Makefile | 2 +-
arch/arm/cpu/armv7/sunxi/Makefile | 11 +++
arch/arm/cpu/armv7/sunxi/board.c | 88 +++++++++++++++++
arch/arm/cpu/armv7/sunxi/cpu_info.c | 19 ++++
arch/arm/cpu/armv7/sunxi/start.c | 1 +
arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds | 77 +++++++++++++++
arch/arm/include/asm/arch-sunxi/cpu.h | 122 ++++++++++++++++++++++++
arch/arm/include/asm/arch-sunxi/spl.h | 20 ++++
board/sunxi/Makefile | 11 +++
board/sunxi/board.c | 57 +++++++++++
include/configs/sun7i.h | 24 +++++
include/configs/sunxi-common.h | 141 ++++++++++++++++++++++++++++
12 files changed, 572 insertions(+), 1 deletion(-)
create mode 100644 arch/arm/cpu/armv7/sunxi/board.c
create mode 100644 arch/arm/cpu/armv7/sunxi/cpu_info.c
create mode 100644 arch/arm/cpu/armv7/sunxi/start.c
create mode 100644 arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds
create mode 100644 arch/arm/include/asm/arch-sunxi/cpu.h
create mode 100644 arch/arm/include/asm/arch-sunxi/spl.h
create mode 100644 board/sunxi/Makefile
create mode 100644 board/sunxi/board.c
create mode 100644 include/configs/sun7i.h
create mode 100644 include/configs/sunxi-common.h
diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
index 119ebb3..ddf00f3 100644
--- a/arch/arm/cpu/armv7/Makefile
+++ b/arch/arm/cpu/armv7/Makefile
@@ -12,7 +12,7 @@ obj-y += cache_v7.o
obj-y += cpu.o
obj-y += syslib.o
-ifneq ($(CONFIG_AM43XX)$(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA)$(CONFIG_MX6)$(CONFIG_TI81XX)$(CONFIG_AT91FAMILY),)
+ifneq ($(CONFIG_AM43XX)$(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA)$(CONFIG_MX6)$(CONFIG_TI81XX)$(CONFIG_AT91FAMILY)$(CONFIG_SUNXI),)
ifneq ($(CONFIG_SKIP_LOWLEVEL_INIT),y)
obj-y += lowlevel_init.o
endif
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
index d81d26c..a64bfa1 100644
--- a/arch/arm/cpu/armv7/sunxi/Makefile
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -8,7 +8,18 @@
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += timer.o
+obj-y += board.o
obj-y += clock.o
obj-y += pinmux.o
obj-$(CONFIG_SUN7I) += clock_sun4i.o
+
+ifndef CONFIG_SPL_BUILD
+obj-y += cpu_info.o
+endif
+
+ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_SUN7I) += dram.o
+ifdef CONFIG_SPL_FEL
+obj-y += start.o
+endif
+endif
diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c
new file mode 100644
index 0000000..b5c0cb7
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/board.c
@@ -0,0 +1,88 @@
+/*
+ * (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.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <serial.h>
+#ifdef CONFIG_SPL_BUILD
+#include <spl.h>
+#endif
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/timer.h>
+
+#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, nand 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 confirmation data available in SPL yet. Hardcode bootmode */
+u32 spl_boot_mode(void)
+{
+ return MMCSD_MODE_RAW;
+}
+#endif
+
+int gpio_init(void)
+{
+ 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);
+
+ return 0;
+}
+
+void reset_cpu(ulong addr)
+{
+}
+
+/* do some early init */
+void s_init(void)
+{
+#if !defined CONFIG_SPL_BUILD && (defined CONFIG_SUN7I || defined CONFIG_SUN6I)
+ /* Enable SMP mode for CPU0, by setting bit 6 of Auxiliary Ctl reg */
+ asm volatile(
+ "mrc p15, 0, r0, c1, c0, 1\n"
+ "orr r0, r0, #1 << 6\n"
+ "mcr p15, 0, r0, c1, c0, 1\n");
+#endif
+
+ clock_init();
+ timer_init();
+ gpio_init();
+
+#ifdef CONFIG_SPL_BUILD
+ gd = &gdata;
+ preloader_console_init();
+
+ 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
diff --git a/arch/arm/cpu/armv7/sunxi/cpu_info.c b/arch/arm/cpu/armv7/sunxi/cpu_info.c
new file mode 100644
index 0000000..b4c3d5c
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/cpu_info.c
@@ -0,0 +1,19 @@
+/*
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+
+#ifdef CONFIG_DISPLAY_CPUINFO
+int print_cpuinfo(void)
+{
+ puts("CPU: Allwinner A20 (SUN7I)\n");
+ return 0;
+}
+#endif
diff --git a/arch/arm/cpu/armv7/sunxi/start.c b/arch/arm/cpu/armv7/sunxi/start.c
new file mode 100644
index 0000000..6b392fa
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/start.c
@@ -0,0 +1 @@
+/* Intentionally empty. Only needed to get FEL SPL link line right */
diff --git a/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds b/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds
new file mode 100644
index 0000000..364e35c
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds
@@ -0,0 +1,77 @@
+/*
+ * (C) Copyright 2013
+ * Henrik Nordstrom <henrik@henriknordstrom.net>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(s_init)
+SECTIONS
+{
+ . = 0x00002000;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text.s_init)
+ *(.text*)
+ }
+
+ . = ALIGN(4);
+ .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+ . = ALIGN(4);
+ .data : {
+ *(.data*)
+ }
+
+ . = ALIGN(4);
+ . = .;
+
+ . = ALIGN(4);
+ .rel.dyn : {
+ __rel_dyn_start = .;
+ *(.rel*)
+ __rel_dyn_end = .;
+ }
+
+ .dynsym : {
+ __dynsym_start = .;
+ *(.dynsym)
+ }
+
+ . = ALIGN(4);
+ .note.gnu.build-id :
+ {
+ *(.note.gnu.build-id)
+ }
+ _end = .;
+
+ . = ALIGN(4096);
+ .mmutable : {
+ *(.mmutable)
+ }
+
+ .bss_start __rel_dyn_start (OVERLAY) : {
+ KEEP(*(.__bss_start));
+ __bss_base = .;
+ }
+
+ .bss __bss_base (OVERLAY) : {
+ *(.bss*)
+ . = ALIGN(4);
+ __bss_limit = .;
+ }
+
+ .bss_end __bss_limit (OVERLAY) : {
+ KEEP(*(.__bss_end));
+ }
+
+ /DISCARD/ : { *(.dynstr*) }
+ /DISCARD/ : { *(.dynamic*) }
+ /DISCARD/ : { *(.plt*) }
+ /DISCARD/ : { *(.interp*) }
+ /DISCARD/ : { *(.gnu*) }
+ /DISCARD/ : { *(.note*) }
+}
diff --git a/arch/arm/include/asm/arch-sunxi/cpu.h b/arch/arm/include/asm/arch-sunxi/cpu.h
new file mode 100644
index 0000000..7400559
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/cpu.h
@@ -0,0 +1,122 @@
+/*
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _SUNXI_CPU_H
+#define _SUNXI_CPU_H
+
+#define SUNXI_SRAM_A1_BASE 0x00000000
+#define SUNXI_SRAM_A1_SIZE (16 * 1024) /* 16 kiB */
+
+#define SUNXI_SRAM_A2_BASE 0x00004000 /* 16 kiB */
+#define SUNXI_SRAM_A3_BASE 0x00008000 /* 13 kiB */
+#define SUNXI_SRAM_A4_BASE 0x0000b400 /* 3 kiB */
+#define SUNXI_SRAM_D_BASE 0x01c00000
+#define SUNXI_SRAM_B_BASE 0x01c00000 /* 64 kiB (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_CPUCFG_BASE 0x01c25c00
+
+#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
+#define SUNXI_GMAC_BASE 0x01c50000
+
+/* 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 /* 2 GiB */
+
+#define SUNXI_BROM_BASE 0xffff0000 /* 32 kiB */
+
+#define SUNXI_CPU_CFG (SUNXI_TIMER_BASE + 0x13c)
+
+#ifndef __ASSEMBLY__
+void sunxi_board_init(void);
+void sunxi_reset(void);
+#endif /* __ASSEMBLY__ */
+
+#endif /* _CPU_H */
diff --git a/arch/arm/include/asm/arch-sunxi/spl.h b/arch/arm/include/asm/arch-sunxi/spl.h
new file mode 100644
index 0000000..ff871bc
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/spl.h
@@ -0,0 +1,20 @@
+/*
+ * This is a copy of omap3/spl.h:
+ *
+ * (C) Copyright 2012
+ * Texas Instruments, <www.ti.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#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
diff --git a/board/sunxi/Makefile b/board/sunxi/Makefile
new file mode 100644
index 0000000..559112e
--- /dev/null
+++ b/board/sunxi/Makefile
@@ -0,0 +1,11 @@
+#
+# (C) Copyright 2012 Henrik Nordstrom <henrik@henriknordstrom.net>
+#
+# Based on some other board Makefile
+#
+# (C) Copyright 2000-2003
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+obj-y += board.o
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
new file mode 100644
index 0000000..328334a
--- /dev/null
+++ b/board/sunxi/board.c
@@ -0,0 +1,57 @@
+/*
+ * (C) Copyright 2012-2013 Henrik Nordstrom <henrik@henriknordstrom.net>
+ * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.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.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/dram.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* add board specific code here */
+int board_init(void)
+{
+ int id_pfr1;
+
+ gd->bd->bi_boot_params = (PHYS_SDRAM_0 + 0x100);
+
+ asm volatile("mrc p15, 0, %0, c0, c1, 1" : "=r"(id_pfr1));
+ debug("id_pfr1: 0x%08x\n", id_pfr1);
+ /* Generic Timer Extension available? */
+ if ((id_pfr1 >> 16) & 0xf) {
+ debug("Setting CNTFRQ\n");
+ /* CNTFRQ == 24 MHz */
+ asm volatile("mcr p15, 0, %0, c14, c0, 0" : : "r"(24000000));
+ }
+
+ return 0;
+}
+
+int dram_init(void)
+{
+ gd->ram_size = get_ram_size((long *)PHYS_SDRAM_0, PHYS_SDRAM_0_SIZE);
+
+ return 0;
+}
+
+#ifdef CONFIG_SPL_BUILD
+void sunxi_board_init(void)
+{
+ unsigned long ramsize;
+
+ printf("DRAM:");
+ ramsize = sunxi_dram_init();
+ printf(" %lu MiB\n", ramsize >> 20);
+ if (!ramsize)
+ hang();
+}
+#endif
diff --git a/include/configs/sun7i.h b/include/configs/sun7i.h
new file mode 100644
index 0000000..9b693f7
--- /dev/null
+++ b/include/configs/sun7i.h
@@ -0,0 +1,24 @@
+/*
+ * (C) Copyright 2012-2013 Henrik Nordstrom <henrik@henriknordstrom.net>
+ * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
+ *
+ * Configuration settings for the Allwinner A20 (sun7i) CPU
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * A20 specific configuration
+ */
+#define CONFIG_SUN7I /* sun7i SoC generation */
+
+#define CONFIG_SYS_PROMPT "sun7i# "
+
+/*
+ * 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
new file mode 100644
index 0000000..3f7e314
--- /dev/null
+++ b/include/configs/sunxi-common.h
@@ -0,0 +1,141 @@
+/*
+ * (C) Copyright 2012-2012 Henrik Nordstrom <henrik@henriknordstrom.net>
+ *
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Tom Cubie <tangliang@allwinnertech.com>
+ *
+ * Configuration settings for the Allwinner sunxi series of boards.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _SUNXI_COMMON_CONFIG_H
+#define _SUNXI_COMMON_CONFIG_H
+
+/*
+ * High Level Configuration Options
+ */
+#define CONFIG_SUNXI /* sunxi family */
+
+#include <asm/arch/cpu.h> /* get chip and board defs */
+
+#define CONFIG_SYS_TEXT_BASE 0x4a000000
+
+/*
+ * Display CPU information
+ */
+#define CONFIG_DISPLAY_CPUINFO
+
+/* 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 /* 32 KiB */
+
+#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)
+
+#define CONFIG_NR_DRAM_BANKS 1
+#define PHYS_SDRAM_0 CONFIG_SYS_SDRAM_BASE
+#define PHYS_SDRAM_0_SIZE 0x80000000 /* 2 GiB */
+
+#define CONFIG_CMD_MEMORY
+#define CONFIG_CMD_SETEXPR
+
+#define CONFIG_SETUP_MEMORY_TAGS
+#define CONFIG_CMDLINE_TAG
+#define CONFIG_INITRD_TAG
+
+/* 4MB of malloc() pool */
+#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + (4 << 20))
+
+/*
+ * 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_MAXARGS 16 /* max number of command args */
+#define CONFIG_SYS_GENERIC_BOARD
+
+/* Boot Argument Buffer Size */
+#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
+
+#define CONFIG_SYS_LOAD_ADDR 0x48000000 /* default load address */
+
+/* standalone support */
+#define CONFIG_STANDALONE_LOAD_ADDR 0x48000000
+
+#define CONFIG_SYS_HZ 1000
+
+/* baudrate */
+#define CONFIG_BAUDRATE 115200
+
+/* The stack sizes are set up in start.S using the settings below */
+#define CONFIG_STACKSIZE (256 << 10) /* 256 KiB */
+
+/* FLASH and environment organization */
+
+#define CONFIG_SYS_NO_FLASH
+
+#define CONFIG_SYS_MONITOR_LEN (512 << 10) /* 512 KiB */
+#define CONFIG_IDENT_STRING " Allwinner Technology"
+
+#define CONFIG_ENV_SIZE (128 << 10) /* 128 KiB */
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "bootm_size=0x10000000\0"
+
+#define CONFIG_SYS_BOOT_GET_CMDLINE
+
+#include <config_cmd_default.h>
+
+#define CONFIG_FAT_WRITE /* enable write access */
+
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+
+#define CONFIG_SPL
+#define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds"
+#define CONFIG_SPL_START_S_PATH "arch/arm/cpu/armv7/sunxi"
+#define CONFIG_SPL_TEXT_BASE 0x2000
+#define CONFIG_SPL_MAX_SIZE 0x4000 /* 16 KiB */
+/* end of 32 KiB in sram */
+#define LOW_LEVEL_SRAM_STACK 0x00008000 /* End of sram */
+#define CONFIG_SPL_STACK LOW_LEVEL_SRAM_STACK
+#define CONFIG_SYS_SPL_MALLOC_START 0x4ff00000
+#define CONFIG_SYS_SPL_MALLOC_SIZE 0x00080000 /* 512 KiB */
+
+#undef CONFIG_CMD_FPGA
+#undef CONFIG_CMD_NET
+#undef CONFIG_CMD_NFS
+
+#define CONFIG_CONS_INDEX 1 /* UART0 */
+
+#if !defined CONFIG_ENV_IS_IN_MMC && \
+ !defined CONFIG_ENV_IS_IN_NAND && \
+ !defined CONFIG_ENV_IS_IN_FAT && \
+ !defined CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_IS_NOWHERE
+#endif
+
+#ifndef CONFIG_SPL_BUILD
+#include <config_distro_defaults.h>
+#endif
+
+#endif /* _SUNXI_COMMON_CONFIG_H */
--
1.9.0

View File

@ -0,0 +1,77 @@
From b2c413d8119dbbef34189e9beb84a0b2a00fa86d Mon Sep 17 00:00:00 2001
From: Ian Campbell <ijc@hellion.org.uk>
Date: Fri, 18 Apr 2014 19:05:46 +0100
Subject: [PATCH 22/36] sunxi: add support for Cubietruck booting in FEL mode
Signed-off-by: Oliver Schinagl <oliver@schinagl.nl>
Signed-off-by: Jens Kuske <jenskuske@gmail.com>
Signed-off-by: Ian Campbell <ijc@hellion.org.uk>
Reviewed-by: Tom Rini <trini@ti.com>
---
board/sunxi/Makefile | 1 +
board/sunxi/dram_cubietruck.c | 31 +++++++++++++++++++++++++++++++
boards.cfg | 1 +
3 files changed, 33 insertions(+)
create mode 100644 board/sunxi/dram_cubietruck.c
diff --git a/board/sunxi/Makefile b/board/sunxi/Makefile
index 559112e..18b1e11 100644
--- a/board/sunxi/Makefile
+++ b/board/sunxi/Makefile
@@ -9,3 +9,4 @@
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += board.o
+obj-$(CONFIG_CUBIETRUCK) += dram_cubietruck.o
diff --git a/board/sunxi/dram_cubietruck.c b/board/sunxi/dram_cubietruck.c
new file mode 100644
index 0000000..fbcd687
--- /dev/null
+++ b/board/sunxi/dram_cubietruck.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 = 432,
+ .type = 3,
+ .rank_num = 1,
+ .density = 4096,
+ .io_width = 8,
+ .bus_width = 32,
+ .cas = 9,
+ .zq = 0x7f,
+ .odt_en = 0,
+ .size = 2048,
+ .tpr0 = 0x42d899b7,
+ .tpr1 = 0xa090,
+ .tpr2 = 0x22a00,
+ .tpr3 = 0x0,
+ .tpr4 = 0x1,
+ .tpr5 = 0x0,
+ .emr1 = 0x4,
+ .emr2 = 0x10,
+ .emr3 = 0x0,
+};
+
+unsigned long sunxi_dram_init(void)
+{
+ return dramc_init(&dram_para);
+}
diff --git a/boards.cfg b/boards.cfg
index 49ea4ab..306f891 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -372,6 +372,7 @@ Active arm armv7 rmobile renesas lager
Active arm armv7 s5pc1xx samsung goni s5p_goni - Mateusz Zalega <m.zalega@samsung.com>
Active arm armv7 s5pc1xx samsung smdkc100 smdkc100 - Minkyu Kang <mk7.kang@samsung.com>
Active arm armv7 socfpga altera socfpga socfpga_cyclone5 - -
+Active arm armv7 sunxi - sunxi Cubietruck_FEL sun7i:CUBIETRUCK,SPL_FEL -
Active arm armv7 u8500 st-ericsson snowball snowball - Mathieu Poirier <mathieu.poirier@linaro.org>
Active arm armv7 u8500 st-ericsson u8500 u8500_href - -
Active arm armv7 vf610 freescale vf610twr vf610twr vf610twr:IMX_CONFIG=board/freescale/vf610twr/imximage.cfg Alison Wang <b18965@freescale.com>
--
1.9.0

View File

@ -0,0 +1,168 @@
From 4b39387594767ac865caa8710d1be39e869926e3 Mon Sep 17 00:00:00 2001
From: Ian Campbell <ijc@hellion.org.uk>
Date: Fri, 18 Apr 2014 19:05:47 +0100
Subject: [PATCH 23/36] sunxi: add gmac Ethernet support
Add support for the GMAC Ethernet controller on Allwinner A20 (sun7i)
processors. Enable for the Cubietruck.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Jens Kuske <jenskuske@gmail.com>
Signed-off-by: Ian Campbell <ijc@hellion.org.uk>
---
arch/arm/cpu/armv7/sunxi/board.c | 15 +++++++++++++++
boards.cfg | 2 +-
drivers/net/Makefile | 1 +
drivers/net/sunxi_gmac.c | 34 ++++++++++++++++++++++++++++++++++
include/configs/sunxi-common.h | 26 ++++++++++++++++++++++++++
include/netdev.h | 1 +
6 files changed, 78 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/sunxi_gmac.c
diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c
index b5c0cb7..9755320 100644
--- a/arch/arm/cpu/armv7/sunxi/board.c
+++ b/arch/arm/cpu/armv7/sunxi/board.c
@@ -11,6 +11,8 @@
*/
#include <common.h>
+#include <netdev.h>
+#include <miiphy.h>
#include <serial.h>
#ifdef CONFIG_SPL_BUILD
#include <spl.h>
@@ -86,3 +88,16 @@ void enable_caches(void)
dcache_enable();
}
#endif
+
+#if defined(CONFIG_SUNXI_GMAC)
+/*
+ * Initializes on-chip ethernet controllers.
+ * to override, implement board_eth_init()
+ */
+int cpu_eth_init(bd_t *bis)
+{
+ sunxi_gmac_initialize(bis);
+
+ return 0;
+}
+#endif
diff --git a/boards.cfg b/boards.cfg
index 306f891..ddc3c86 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -372,7 +372,7 @@ Active arm armv7 rmobile renesas lager
Active arm armv7 s5pc1xx samsung goni s5p_goni - Mateusz Zalega <m.zalega@samsung.com>
Active arm armv7 s5pc1xx samsung smdkc100 smdkc100 - Minkyu Kang <mk7.kang@samsung.com>
Active arm armv7 socfpga altera socfpga socfpga_cyclone5 - -
-Active arm armv7 sunxi - sunxi Cubietruck_FEL sun7i:CUBIETRUCK,SPL_FEL -
+Active arm armv7 sunxi - sunxi Cubietruck_FEL sun7i:CUBIETRUCK,SPL_FEL,SUNXI_GMAC,RGMII -
Active arm armv7 u8500 st-ericsson snowball snowball - Mathieu Poirier <mathieu.poirier@linaro.org>
Active arm armv7 u8500 st-ericsson u8500 u8500_href - -
Active arm armv7 vf610 freescale vf610twr vf610twr vf610twr:IMX_CONFIG=board/freescale/vf610twr/imximage.cfg Alison Wang <b18965@freescale.com>
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 7f9ce90..2300c00 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_SH_ETHER) += sh_eth.o
obj-$(CONFIG_SMC91111) += smc91111.o
obj-$(CONFIG_SMC911X) += smc911x.o
obj-$(CONFIG_SUNXI_WEMAC) += sunxi_wemac.o
+obj-$(CONFIG_SUNXI_GMAC) += sunxi_gmac.o
obj-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o
obj-$(CONFIG_TSEC_ENET) += tsec.o fsl_mdio.o
obj-$(CONFIG_DRIVER_TI_CPSW) += cpsw.o
diff --git a/drivers/net/sunxi_gmac.c b/drivers/net/sunxi_gmac.c
new file mode 100644
index 0000000..15cd1fb
--- /dev/null
+++ b/drivers/net/sunxi_gmac.c
@@ -0,0 +1,34 @@
+#include <common.h>
+#include <netdev.h>
+#include <miiphy.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/gpio.h>
+
+int sunxi_gmac_initialize(bd_t *bis)
+{
+ int pin;
+ struct sunxi_ccm_reg *const ccm =
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+
+ /* Set up clock gating */
+ setbits_le32(&ccm->ahb_gate1, 0x1 << AHB_GATE_OFFSET_GMAC);
+
+ /* Set MII clock */
+ setbits_le32(&ccm->gmac_clk_cfg, CCM_GMAC_CTRL_TX_CLK_SRC_INT_RGMII |
+ CCM_GMAC_CTRL_GPIT_RGMII);
+
+ /* Configure pin mux settings for GMAC */
+ for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(16); pin++) {
+ /* skip unused pins in RGMII mode */
+ if (pin == SUNXI_GPA(9) || pin == SUNXI_GPA(14))
+ continue;
+ sunxi_gpio_set_cfgpin(pin, SUN7I_GPA0_GMAC);
+ sunxi_gpio_set_drv(pin, 3);
+ }
+
+ designware_initialize(SUNXI_GMAC_BASE, PHY_INTERFACE_MODE_RGMII);
+
+ return 0;
+}
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index 3f7e314..b76c3b0 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -127,6 +127,32 @@
#define CONFIG_CONS_INDEX 1 /* UART0 */
+#ifdef CONFIG_SUNXI_GMAC
+#define CONFIG_DESIGNWARE_ETH /* GMAC can use designware driver */
+#define CONFIG_DW_AUTONEG
+#define CONFIG_PHY_GIGE /* GMAC can use gigabit PHY */
+#define CONFIG_PHY_ADDR 1
+#define CONFIG_MII /* MII PHY management */
+#define CONFIG_PHYLIB
+#endif
+
+#ifdef CONFIG_CMD_NET
+#define CONFIG_CMD_NFS
+#define CONFIG_CMD_SNTP
+#define CONFIG_TIMESTAMP /* Needed by SNTP */
+#define CONFIG_CMD_DNS
+#define CONFIG_NETCONSOLE
+#define CONFIG_BOOTP_NISDOMAIN
+#define CONFIG_BOOTP_BOOTFILESIZE
+#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
+#endif
+
#if !defined CONFIG_ENV_IS_IN_MMC && \
!defined CONFIG_ENV_IS_IN_NAND && \
!defined CONFIG_ENV_IS_IN_FAT && \
diff --git a/include/netdev.h b/include/netdev.h
index 32b5073..fc4a2f8 100644
--- a/include/netdev.h
+++ b/include/netdev.h
@@ -79,6 +79,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_gmac_initialize(bd_t *bis);
int sunxi_wemac_initialize(bd_t *bis);
int tsi108_eth_initialize(bd_t *bis);
int uec_standard_init(bd_t *bis);
--
1.9.0

View File

@ -0,0 +1,797 @@
From ec8c2c931fda9e06eee7203c72025f6ecd25ef7f Mon Sep 17 00:00:00 2001
From: Ian Campbell <ijc@hellion.org.uk>
Date: Fri, 18 Apr 2014 19:05:48 +0100
Subject: [PATCH 24/36] sunxi: mmc support
This adds support for the MMC controller on the Allwinner A20 (sun7i)
processor.
Signed-off-by: Henrik Nordstrom <henrik@henriknordstrom.net>
Signed-off-by: Luke Leighton <lkcl@lkcl.net>
Signed-off-by: Oliver Schinagl <oliver@schinagl.nl>
Signed-off-by: Wills Wang <wills.wang.open@gmail.com>
Signed-off-by: Ian Campbell <ijc@hellion.org.uk>
Cc: Stefan Roese <sr@denx.de>
Cc: Tom Cubie <Mr.hipboi@gmail.com>
Cc: Aaron Maoye <leafy.myeh@allwinnertech.com>
Cc: Pantelis Antoniou <panto@antoniou-consulting.com>
---
arch/arm/include/asm/arch-sunxi/mmc.h | 124 ++++++++
board/sunxi/board.c | 13 +
drivers/mmc/Makefile | 1 +
drivers/mmc/sunxi_mmc.c | 559 ++++++++++++++++++++++++++++++++++
include/configs/sunxi-common.h | 11 +
5 files changed, 708 insertions(+)
create mode 100644 arch/arm/include/asm/arch-sunxi/mmc.h
create mode 100644 drivers/mmc/sunxi_mmc.c
diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h
new file mode 100644
index 0000000..53196e3
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/mmc.h
@@ -0,0 +1,124 @@
+/*
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Aaron <leafy.myeh@allwinnertech.com>
+ *
+ * MMC register definition for allwinner sunxi platform.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _SUNXI_MMC_H
+#define _SUNXI_MMC_H
+
+#include <linux/types.h>
+
+struct sunxi_mmc {
+ u32 gctrl; /* 0x00 global control */
+ u32 clkcr; /* 0x04 clock control */
+ u32 timeout; /* 0x08 time out */
+ u32 width; /* 0x0c bus width */
+ u32 blksz; /* 0x10 block size */
+ u32 bytecnt; /* 0x14 byte count */
+ u32 cmd; /* 0x18 command */
+ u32 arg; /* 0x1c argument */
+ u32 resp0; /* 0x20 response 0 */
+ u32 resp1; /* 0x24 response 1 */
+ u32 resp2; /* 0x28 response 2 */
+ u32 resp3; /* 0x2c response 3 */
+ u32 imask; /* 0x30 interrupt mask */
+ u32 mint; /* 0x34 masked interrupt status */
+ u32 rint; /* 0x38 raw interrupt status */
+ u32 status; /* 0x3c status */
+ u32 ftrglevel; /* 0x40 FIFO threshold watermark*/
+ u32 funcsel; /* 0x44 function select */
+ u32 cbcr; /* 0x48 CIU byte count */
+ u32 bbcr; /* 0x4c BIU byte count */
+ u32 dbgc; /* 0x50 debug enable */
+ u32 res0[11];
+ u32 dmac; /* 0x80 internal DMA control */
+ u32 dlba; /* 0x84 internal DMA descr list base address */
+ u32 idst; /* 0x88 internal DMA status */
+ u32 idie; /* 0x8c internal DMA interrupt enable */
+ u32 chda; /* 0x90 */
+ u32 cbda; /* 0x94 */
+ u32 res1[26];
+ u32 fifo; /* 0x100 FIFO access address */
+};
+
+#define SUNXI_MMC_CLK_POWERSAVE (0x1 << 17)
+#define SUNXI_MMC_CLK_ENABLE (0x1 << 16)
+#define SUNXI_MMC_CLK_DIVIDER_MASK (0xff)
+
+#define SUNXI_MMC_GCTRL_SOFT_RESET (0x1 << 0)
+#define SUNXI_MMC_GCTRL_FIFO_RESET (0x1 << 1)
+#define SUNXI_MMC_GCTRL_DMA_RESET (0x1 << 2)
+#define SUNXI_MMC_GCTRL_RESET (SUNXI_MMC_GCTRL_SOFT_RESET|\
+ SUNXI_MMC_GCTRL_FIFO_RESET|\
+ SUNXI_MMC_GCTRL_DMA_RESET)
+#define SUNXI_MMC_GCTRL_DMA_ENABLE (0x1 << 5)
+#define SUNXI_MMC_GCTRL_ACCESS_BY_AHB (0x1 << 31)
+
+#define SUNXI_MMC_CMD_RESP_EXPIRE (0x1 << 6)
+#define SUNXI_MMC_CMD_LONG_RESPONSE (0x1 << 7)
+#define SUNXI_MMC_CMD_CHK_RESPONSE_CRC (0x1 << 8)
+#define SUNXI_MMC_CMD_DATA_EXPIRE (0x1 << 9)
+#define SUNXI_MMC_CMD_WRITE (0x1 << 10)
+#define SUNXI_MMC_CMD_AUTO_STOP (0x1 << 12)
+#define SUNXI_MMC_CMD_WAIT_PRE_OVER (0x1 << 13)
+#define SUNXI_MMC_CMD_SEND_INIT_SEQ (0x1 << 15)
+#define SUNXI_MMC_CMD_UPCLK_ONLY (0x1 << 21)
+#define SUNXI_MMC_CMD_START (0x1 << 31)
+
+#define SUNXI_MMC_RINT_RESP_ERROR (0x1 << 1)
+#define SUNXI_MMC_RINT_COMMAND_DONE (0x1 << 2)
+#define SUNXI_MMC_RINT_DATA_OVER (0x1 << 3)
+#define SUNXI_MMC_RINT_TX_DATA_REQUEST (0x1 << 4)
+#define SUNXI_MMC_RINT_RX_DATA_REQUEST (0x1 << 5)
+#define SUNXI_MMC_RINT_RESP_CRC_ERROR (0x1 << 6)
+#define SUNXI_MMC_RINT_DATA_CRC_ERROR (0x1 << 7)
+#define SUNXI_MMC_RINT_RESP_TIMEOUT (0x1 << 8)
+#define SUNXI_MMC_RINT_DATA_TIMEOUT (0x1 << 9)
+#define SUNXI_MMC_RINT_VOLTAGE_CHANGE_DONE (0x1 << 10)
+#define SUNXI_MMC_RINT_FIFO_RUN_ERROR (0x1 << 11)
+#define SUNXI_MMC_RINT_HARD_WARE_LOCKED (0x1 << 12)
+#define SUNXI_MMC_RINT_START_BIT_ERROR (0x1 << 13)
+#define SUNXI_MMC_RINT_AUTO_COMMAND_DONE (0x1 << 14)
+#define SUNXI_MMC_RINT_END_BIT_ERROR (0x1 << 15)
+#define SUNXI_MMC_RINT_SDIO_INTERRUPT (0x1 << 16)
+#define SUNXI_MMC_RINT_CARD_INSERT (0x1 << 30)
+#define SUNXI_MMC_RINT_CARD_REMOVE (0x1 << 31)
+#define SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT \
+ (SUNXI_MMC_RINT_RESP_ERROR | \
+ SUNXI_MMC_RINT_RESP_CRC_ERROR | \
+ SUNXI_MMC_RINT_DATA_CRC_ERROR | \
+ SUNXI_MMC_RINT_RESP_TIMEOUT | \
+ SUNXI_MMC_RINT_DATA_TIMEOUT | \
+ SUNXI_MMC_RINT_VOLTAGE_CHANGE_DONE | \
+ SUNXI_MMC_RINT_FIFO_RUN_ERROR | \
+ SUNXI_MMC_RINT_HARD_WARE_LOCKED | \
+ SUNXI_MMC_RINT_START_BIT_ERROR | \
+ SUNXI_MMC_RINT_END_BIT_ERROR) /* 0xbfc2 */
+#define SUNXI_MMC_RINT_INTERRUPT_DONE_BIT \
+ (SUNXI_MMC_RINT_AUTO_COMMAND_DONE | \
+ SUNXI_MMC_RINT_DATA_OVER | \
+ SUNXI_MMC_RINT_COMMAND_DONE | \
+ SUNXI_MMC_RINT_VOLTAGE_CHANGE_DONE)
+
+#define SUNXI_MMC_STATUS_RXWL_FLAG (0x1 << 0)
+#define SUNXI_MMC_STATUS_TXWL_FLAG (0x1 << 1)
+#define SUNXI_MMC_STATUS_FIFO_EMPTY (0x1 << 2)
+#define SUNXI_MMC_STATUS_FIFO_FULL (0x1 << 3)
+#define SUNXI_MMC_STATUS_CARD_PRESENT (0x1 << 8)
+#define SUNXI_MMC_STATUS_CARD_DATA_BUSY (0x1 << 9)
+#define SUNXI_MMC_STATUS_DATA_FSM_BUSY (0x1 << 10)
+
+#define SUNXI_MMC_IDMAC_RESET (0x1 << 0)
+#define SUNXI_MMC_IDMAC_FIXBURST (0x1 << 1)
+#define SUNXI_MMC_IDMAC_ENABLE (0x1 << 7)
+
+#define SUNXI_MMC_IDIE_TXIRQ (0x1 << 0)
+#define SUNXI_MMC_IDIE_RXIRQ (0x1 << 1)
+
+int sunxi_mmc_init(int sdc_no);
+#endif /* _SUNXI_MMC_H */
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 328334a..06c9264 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -14,6 +14,7 @@
#include <common.h>
#include <asm/arch/clock.h>
#include <asm/arch/dram.h>
+#include <asm/arch/mmc.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -43,6 +44,18 @@ int dram_init(void)
return 0;
}
+#ifdef CONFIG_GENERIC_MMC
+int board_mmc_init(bd_t *bis)
+{
+ sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT);
+#if !defined (CONFIG_SPL_BUILD) && defined (CONFIG_MMC_SUNXI_SLOT_EXTRA)
+ sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT_EXTRA);
+#endif
+
+ return 0;
+}
+#endif
+
#ifdef CONFIG_SPL_BUILD
void sunxi_board_init(void)
{
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 931922b..5e67098 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_SPEAR_SDHCI) += spear_sdhci.o
obj-$(CONFIG_TEGRA_MMC) += tegra_mmc.o
obj-$(CONFIG_DWMMC) += dw_mmc.o
obj-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o
+obj-$(CONFIG_MMC_SUNXI) += sunxi_mmc.o
obj-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o
obj-$(CONFIG_SOCFPGA_DWMMC) += socfpga_dw_mmc.o
ifdef CONFIG_SPL_BUILD
diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
new file mode 100644
index 0000000..f002694
--- /dev/null
+++ b/drivers/mmc/sunxi_mmc.c
@@ -0,0 +1,559 @@
+/*
+ * (C) Copyright 2007-2011
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ * Aaron <leafy.myeh@allwinnertech.com>
+ *
+ * MMC driver for allwinner sunxi platform.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <mmc.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mmc.h>
+
+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 */
+#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;
+ 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 mmc_config cfg;
+};
+
+/* support 4 mmc hosts */
+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 pin;
+ unsigned int rval;
+ unsigned int pll_clk;
+ unsigned int divider;
+ 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 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 */
+ for (pin = SUNXI_GPF(0); pin <= SUNXI_GPF(5); pin++) {
+ sunxi_gpio_set_cfgpin(pin, SUNXI_GPF0_SDC0);
+ sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
+ sunxi_gpio_set_drv(pin, 2);
+ }
+ break;
+
+ case 1:
+#if CONFIG_MMC1_PG
+ /* PG0-CMD, PG1-CLK, PG2~5-D0~3 : 4 */
+ for (pin = SUNXI_GPG(0); pin <= SUNXI_GPG(5); pin++) {
+ sunxi_gpio_set_cfgpin(pin, SUN4I_GPG0_SDC1);
+ sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
+ sunxi_gpio_set_drv(pin, 2);
+ }
+#else
+ /* PH22-CMD, PH23-CLK, PH24~27-D0~D3 : 5 */
+ for (pin = SUNXI_GPH(22); pin <= SUNXI_GPH(27); pin++) {
+ sunxi_gpio_set_cfgpin(pin, SUN4I_GPH22_SDC1);
+ sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
+ sunxi_gpio_set_drv(pin, 2);
+ }
+#endif
+ break;
+
+ case 2:
+ /* CMD-PC6, CLK-PC7, D0-PC8, D1-PC9, D2-PC10, D3-PC11 */
+ for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(11); pin++) {
+ sunxi_gpio_set_cfgpin(pin, SUNXI_GPC6_SDC2);
+ sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
+ sunxi_gpio_set_drv(pin, 2);
+ }
+ break;
+
+ case 3:
+ /* PI4-CMD, PI5-CLK, PI6~9-D0~D3 : 2 */
+ for (pin = SUNXI_GPI(4); pin <= SUNXI_GPI(9); pin++) {
+ sunxi_gpio_set_cfgpin(pin, SUN4I_GPI4_SDC3);
+ sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
+ sunxi_gpio_set_drv(pin, 2);
+ }
+ break;
+
+ default:
+ return -1;
+ }
+
+ /* config ahb clock */
+ rval = readl(&ccm->ahb_gate0);
+ rval |= 1 << AHB_GATE_OFFSET_MMC(sdc_no);
+ writel(rval, &ccm->ahb_gate0);
+
+ /* config mod clock */
+ pll_clk = clock_get_pll6();
+ /* should be close to 100 MHz but no more, so round up */
+ divider = ((pll_clk + 99999999) / 100000000) - 1;
+ writel(CCM_MMC_CTRL_ENABLE | CCM_MMC_CTRL_PLL6 | divider,
+ mmchost->mclkreg);
+ mmchost->mod_clk = pll_clk / (divider + 1);
+
+ return 0;
+}
+
+static int mmc_update_clk(struct mmc *mmc)
+{
+ struct sunxi_mmc_host *mmchost = mmc->priv;
+ unsigned int cmd;
+ unsigned timeout_msecs = 2000;
+
+ cmd = SUNXI_MMC_CMD_START |
+ SUNXI_MMC_CMD_UPCLK_ONLY |
+ SUNXI_MMC_CMD_WAIT_PRE_OVER;
+ writel(cmd, &mmchost->reg->cmd);
+ while (readl(&mmchost->reg->cmd) & SUNXI_MMC_CMD_START) {
+ if (!timeout_msecs--)
+ return -1;
+ udelay(1000);
+ }
+
+ /* clock update sets various irq status bits, clear these */
+ 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 = mmc->priv;
+ unsigned rval = readl(&mmchost->reg->clkcr);
+
+ /* Disable Clock */
+ rval &= ~SUNXI_MMC_CLK_ENABLE;
+ writel(rval, &mmchost->reg->clkcr);
+ if (mmc_update_clk(mmc))
+ return -1;
+
+ /* Change Divider Factor */
+ rval &= ~SUNXI_MMC_CLK_DIVIDER_MASK;
+ rval |= div;
+ writel(rval, &mmchost->reg->clkcr);
+ if (mmc_update_clk(mmc))
+ return -1;
+ /* Re-enable Clock */
+ rval |= SUNXI_MMC_CLK_ENABLE;
+ 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 = mmc->priv;
+ unsigned int clkdiv = 0;
+
+ debug("set ios: bus_width: %x, clock: %d, mod_clk: %d\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(0x2, &mmchost->reg->width);
+ else if (mmc->bus_width == 4)
+ writel(0x1, &mmchost->reg->width);
+ else
+ writel(0x0, &mmchost->reg->width);
+}
+
+static int mmc_core_init(struct mmc *mmc)
+{
+ struct sunxi_mmc_host *mmchost = mmc->priv;
+
+ /* Reset controller */
+ writel(SUNXI_MMC_GCTRL_RESET, &mmchost->reg->gctrl);
+
+ return 0;
+}
+
+static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data)
+{
+ struct sunxi_mmc_host *mmchost = mmc->priv;
+ const int reading = !!(data->flags & MMC_DATA_READ);
+ const uint32_t status_bit = reading ? SUNXI_MMC_STATUS_FIFO_EMPTY :
+ SUNXI_MMC_STATUS_FIFO_FULL;
+ unsigned i;
+ unsigned byte_cnt = data->blocksize * data->blocks;
+ unsigned timeout_msecs = 2000;
+ unsigned *buff = (unsigned int *)(reading ? data->dest : data->src);
+
+ for (i = 0; i < (byte_cnt >> 2); i++) {
+ while (readl(&mmchost->reg->status) & status_bit) {
+ if (!timeout_msecs--)
+ return -1;
+ udelay(1000);
+ }
+
+ if (reading)
+ buff[i] = readl(mmchost->database);
+ else
+ writel(buff[i], mmchost->database);
+ }
+
+ return 0;
+}
+
+static int mmc_trans_data_by_dma(struct mmc *mmc, struct mmc_data *data)
+{
+ struct sunxi_mmc_host *mmchost = mmc->priv;
+ unsigned byte_cnt = data->blocksize * data->blocks;
+ unsigned char *buff;
+ unsigned des_idx = 0;
+ unsigned buff_frag_num =
+ (byte_cnt + SDXC_DES_BUFFER_MAX_LEN - 1) >> SDXC_DES_NUM_SHIFT;
+ unsigned remain;
+ unsigned i, rval;
+ ALLOC_CACHE_ALIGN_BUFFER(struct sunxi_mmc_des, pdes, buff_frag_num);
+
+ buff = data->flags & MMC_DATA_READ ?
+ (unsigned char *)data->dest : (unsigned char *)data->src;
+ remain = byte_cnt & (SDXC_DES_BUFFER_MAX_LEN - 1);
+
+ 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 = 0; /* 0 == 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];
+ }
+ }
+ flush_cache((unsigned long)pdes,
+ sizeof(struct sunxi_mmc_des) * (des_idx + 1));
+
+ rval = readl(&mmchost->reg->gctrl);
+ /* Enable DMA */
+ writel(rval | SUNXI_MMC_GCTRL_DMA_RESET | SUNXI_MMC_GCTRL_DMA_ENABLE,
+ &mmchost->reg->gctrl);
+ /* Reset iDMA */
+ writel(SUNXI_MMC_IDMAC_RESET, &mmchost->reg->dmac);
+ /* Enable iDMA */
+ writel(SUNXI_MMC_IDMAC_FIXBURST | SUNXI_MMC_IDMAC_ENABLE,
+ &mmchost->reg->dmac);
+ rval = readl(&mmchost->reg->idie) &
+ ~(SUNXI_MMC_IDIE_TXIRQ|SUNXI_MMC_IDIE_RXIRQ);
+ if (data->flags & MMC_DATA_WRITE)
+ rval |= SUNXI_MMC_IDIE_TXIRQ;
+ else
+ rval |= SUNXI_MMC_IDIE_RXIRQ;
+ writel(rval, &mmchost->reg->idie);
+ writel((u32) pdes, &mmchost->reg->dlba);
+ writel((0x2 << 28) | (0x7 << 16) | (0x01 << 3),
+ &mmchost->reg->ftrglevel);
+
+ return 0;
+}
+
+static void mmc_enable_dma_accesses(struct mmc *mmc, int dma)
+{
+ struct sunxi_mmc_host *mmchost = mmc->priv;
+
+ unsigned int gctrl = readl(&mmchost->reg->gctrl);
+ if (dma)
+ gctrl &= ~SUNXI_MMC_GCTRL_ACCESS_BY_AHB;
+ else
+ gctrl |= SUNXI_MMC_GCTRL_ACCESS_BY_AHB;
+ writel(gctrl, &mmchost->reg->gctrl);
+}
+
+static int mmc_rint_wait(struct mmc *mmc, unsigned int timeout_msecs,
+ unsigned int done_bit, const char *what)
+{
+ struct sunxi_mmc_host *mmchost = mmc->priv;
+ unsigned int status;
+
+ do {
+ status = readl(&mmchost->reg->rint);
+ if (!timeout_msecs-- ||
+ (status & SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT)) {
+ debug("%s timeout %x\n", what,
+ status & SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT);
+ return TIMEOUT;
+ }
+ udelay(1000);
+ } while (!(status & done_bit));
+
+ return 0;
+}
+
+static int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ struct sunxi_mmc_host *mmchost = mmc->priv;
+ unsigned int cmdval = SUNXI_MMC_CMD_START;
+ unsigned int timeout_msecs;
+ 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;
+
+ if (!cmd->cmdidx)
+ cmdval |= SUNXI_MMC_CMD_SEND_INIT_SEQ;
+ if (cmd->resp_type & MMC_RSP_PRESENT)
+ cmdval |= SUNXI_MMC_CMD_RESP_EXPIRE;
+ if (cmd->resp_type & MMC_RSP_136)
+ cmdval |= SUNXI_MMC_CMD_LONG_RESPONSE;
+ if (cmd->resp_type & MMC_RSP_CRC)
+ cmdval |= SUNXI_MMC_CMD_CHK_RESPONSE_CRC;
+
+ if (data) {
+ if ((u32) data->dest & 0x3) {
+ error = -1;
+ goto out;
+ }
+
+ cmdval |= SUNXI_MMC_CMD_DATA_EXPIRE|SUNXI_MMC_CMD_WAIT_PRE_OVER;
+ if (data->flags & MMC_DATA_WRITE)
+ cmdval |= SUNXI_MMC_CMD_WRITE;
+ if (data->blocks > 1)
+ cmdval |= SUNXI_MMC_CMD_AUTO_STOP;
+ 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;
+ mmc_enable_dma_accesses(mmc, 1);
+ ret = mmc_trans_data_by_dma(mmc, data);
+ writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd);
+ } else {
+ mmc_enable_dma_accesses(mmc, 0);
+ writel(cmdval | cmd->cmdidx, &mmchost->reg->cmd);
+ ret = mmc_trans_data_by_cpu(mmc, data);
+ }
+ if (ret) {
+ error = readl(&mmchost->reg->rint) & \
+ SUNXI_MMC_RINT_INTERRUPT_ERROR_BIT;
+ error = TIMEOUT;
+ goto out;
+ }
+ }
+
+ error = mmc_rint_wait(mmc, 0xfffff, SUNXI_MMC_RINT_COMMAND_DONE, "cmd");
+ if (error)
+ goto out;
+
+ if (data) {
+ timeout_msecs = usedma ? 120 * bytecnt : 120;
+ debug("cacl timeout %x msec\n", timeout_msecs);
+ error = mmc_rint_wait(mmc, timeout_msecs,
+ data->blocks > 1 ?
+ SUNXI_MMC_RINT_AUTO_COMMAND_DONE :
+ SUNXI_MMC_RINT_DATA_OVER,
+ "data");
+ if (error)
+ goto out;
+ }
+
+ if (cmd->resp_type & MMC_RSP_BUSY) {
+ timeout_msecs = 2000;
+ do {
+ status = readl(&mmchost->reg->status);
+ if (!timeout_msecs--) {
+ debug("busy timeout\n");
+ error = TIMEOUT;
+ goto out;
+ }
+ udelay(1000);
+ } while (status & SUNXI_MMC_STATUS_CARD_DATA_BUSY);
+ }
+
+ 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) & ~SUNXI_MMC_GCTRL_DMA_ENABLE,
+ &mmchost->reg->gctrl);
+ }
+ if (error < 0) {
+ writel(SUNXI_MMC_GCTRL_RESET, &mmchost->reg->gctrl);
+ mmc_update_clk(mmc);
+ }
+ writel(0xffffffff, &mmchost->reg->rint);
+ writel(readl(&mmchost->reg->gctrl) | SUNXI_MMC_GCTRL_FIFO_RESET,
+ &mmchost->reg->gctrl);
+
+ return error;
+}
+
+static const struct mmc_ops sunxi_mmc_ops = {
+ .send_cmd = mmc_send_cmd,
+ .set_ios = mmc_set_ios,
+ .init = mmc_core_init,
+};
+
+int sunxi_mmc_init(int sdc_no)
+{
+ struct mmc_config *cfg = &mmc_host[sdc_no].cfg;
+
+ memset(&mmc_host[sdc_no], 0, sizeof(struct sunxi_mmc_host));
+
+ cfg->name = "SUNXI SD/MMC";
+ cfg->ops = &sunxi_mmc_ops;
+
+ 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;
+ cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+ cfg->f_min = 400000;
+ cfg->f_max = 52000000;
+
+ mmc_resource_init(sdc_no);
+ mmc_clk_io_on(sdc_no);
+
+ if (mmc_create(cfg, &mmc_host[sdc_no]) == NULL)
+ return -1;
+
+ return 0;
+}
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index b76c3b0..ede3d50 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -59,6 +59,16 @@
#define CONFIG_CMDLINE_TAG
#define CONFIG_INITRD_TAG
+/* 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 0 /* first detected MMC controller */
+
/* 4MB of malloc() pool */
#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + (4 << 20))
@@ -94,6 +104,7 @@
#define CONFIG_SYS_MONITOR_LEN (512 << 10) /* 512 KiB */
#define CONFIG_IDENT_STRING " Allwinner Technology"
+#define CONFIG_ENV_OFFSET (544 << 10) /* (8 + 24 + 512) KiB */
#define CONFIG_ENV_SIZE (128 << 10) /* 128 KiB */
#define CONFIG_EXTRA_ENV_SETTINGS \
--
1.9.0

View File

@ -0,0 +1,409 @@
From 432b9a0f1fcd3ebff235755b9f26d996f36ce946 Mon Sep 17 00:00:00 2001
From: Ian Campbell <ijc@hellion.org.uk>
Date: Fri, 18 Apr 2014 19:05:49 +0100
Subject: [PATCH 25/36] sunxi: non-FEL SPL boot support for sun7i
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add support for booting from an MMC card.
Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: Henrik Nordström <henrik@henriknordstrom.net>
Signed-off-by: Ian Campbell <ijc@hellion.org.uk>
Cc: Tom Cubie <Mr.hipboi@gmail.com>
---
Makefile | 10 +++
arch/arm/cpu/armv7/sunxi/config.mk | 8 ++
arch/arm/cpu/armv7/sunxi/u-boot-spl.lds | 52 +++++++++++
boards.cfg | 1 +
include/configs/sunxi-common.h | 26 ++++++
spl/Makefile | 13 +++
tools/.gitignore | 1 +
tools/Makefile | 2 +
tools/mksunxiboot.c | 154 ++++++++++++++++++++++++++++++++
9 files changed, 267 insertions(+)
create mode 100644 arch/arm/cpu/armv7/sunxi/config.mk
create mode 100644 arch/arm/cpu/armv7/sunxi/u-boot-spl.lds
create mode 100644 tools/mksunxiboot.c
diff --git a/Makefile b/Makefile
index c91c10e..379731c 100644
--- a/Makefile
+++ b/Makefile
@@ -870,6 +870,13 @@ OBJCOPYFLAGS_u-boot.spr = -I binary -O binary --pad-to=$(CONFIG_SPL_PAD_TO) \
u-boot.spr: spl/u-boot-spl.img u-boot.img FORCE
$(call if_changed,pad_cat)
+ifneq ($(CONFIG_SUNXI),)
+OBJCOPYFLAGS_u-boot-sunxi-with-spl.bin = -I binary -O binary \
+ --pad-to=$(CONFIG_SPL_PAD_TO) --gap-fill=0xff
+u-boot-sunxi-with-spl.bin: spl/sunxi-spl.bin u-boot.img FORCE
+ $(call if_changed,pad_cat)
+endif
+
ifneq ($(CONFIG_TEGRA),)
OBJCOPYFLAGS_u-boot-nodtb-tegra.bin = -O binary --pad-to=$(CONFIG_SYS_TEXT_BASE)
u-boot-nodtb-tegra.bin: spl/u-boot-spl u-boot.bin FORCE
@@ -1081,6 +1088,9 @@ spl/u-boot-spl.bin: spl/u-boot-spl
spl/u-boot-spl: tools prepare
$(Q)$(MAKE) obj=spl -f $(srctree)/spl/Makefile all
+spl/sunxi-spl.bin: spl/u-boot-spl
+ @:
+
tpl/u-boot-tpl.bin: tools prepare
$(Q)$(MAKE) obj=tpl -f $(srctree)/spl/Makefile all CONFIG_TPL_BUILD=y
diff --git a/arch/arm/cpu/armv7/sunxi/config.mk b/arch/arm/cpu/armv7/sunxi/config.mk
new file mode 100644
index 0000000..00f5ffc
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/config.mk
@@ -0,0 +1,8 @@
+# Build a combined spl + u-boot image
+ifdef CONFIG_SPL
+ifndef CONFIG_SPL_BUILD
+ifndef CONFIG_SPL_FEL
+ALL-y += u-boot-sunxi-with-spl.bin
+endif
+endif
+endif
diff --git a/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds b/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds
new file mode 100644
index 0000000..5008028
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/u-boot-spl.lds
@@ -0,0 +1,52 @@
+/*
+ * (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>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE,\
+ LENGTH = CONFIG_SPL_MAX_SIZE }
+MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, \
+ LENGTH = CONFIG_SPL_BSS_MAX_SIZE }
+
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+ENTRY(_start)
+SECTIONS
+{
+ .text :
+ {
+ __start = .;
+ arch/arm/cpu/armv7/start.o (.text)
+ *(.text*)
+ } > .sram
+
+ . = ALIGN(4);
+ .rodata : { *(SORT_BY_ALIGNMENT(.rodata*)) } >.sram
+
+ . = ALIGN(4);
+ .data : { *(SORT_BY_ALIGNMENT(.data*)) } >.sram
+
+ . = ALIGN(4);
+ __image_copy_end = .;
+ _end = .;
+
+ .bss :
+ {
+ . = ALIGN(4);
+ __bss_start = .;
+ *(.bss*)
+ . = ALIGN(4);
+ __bss_end = .;
+ } > .sdram
+}
diff --git a/boards.cfg b/boards.cfg
index ddc3c86..65ec99f 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -372,6 +372,7 @@ Active arm armv7 rmobile renesas lager
Active arm armv7 s5pc1xx samsung goni s5p_goni - Mateusz Zalega <m.zalega@samsung.com>
Active arm armv7 s5pc1xx samsung smdkc100 smdkc100 - Minkyu Kang <mk7.kang@samsung.com>
Active arm armv7 socfpga altera socfpga socfpga_cyclone5 - -
+Active arm armv7 sunxi - sunxi Cubietruck sun7i:CUBIETRUCK,SPL,SUNXI_GMAC,RGMII -
Active arm armv7 sunxi - sunxi Cubietruck_FEL sun7i:CUBIETRUCK,SPL_FEL,SUNXI_GMAC,RGMII -
Active arm armv7 u8500 st-ericsson snowball snowball - Mathieu Poirier <mathieu.poirier@linaro.org>
Active arm armv7 u8500 st-ericsson u8500 u8500_href - -
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index ede3d50..56a89b9 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -17,6 +17,11 @@
* High Level Configuration Options
*/
#define CONFIG_SUNXI /* sunxi family */
+#ifdef CONFIG_SPL_BUILD
+#ifndef CONFIG_SPL_FEL
+#define CONFIG_SYS_THUMB_BUILD /* Thumbs mode to save space in SPL */
+#endif
+#endif
#include <asm/arch/cpu.h> /* get chip and board defs */
@@ -121,11 +126,32 @@
#define CONFIG_SPL_SERIAL_SUPPORT
#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#ifdef CONFIG_SPL_FEL
+
#define CONFIG_SPL
#define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/armv7/sunxi/u-boot-spl-fel.lds"
#define CONFIG_SPL_START_S_PATH "arch/arm/cpu/armv7/sunxi"
#define CONFIG_SPL_TEXT_BASE 0x2000
#define CONFIG_SPL_MAX_SIZE 0x4000 /* 16 KiB */
+
+#else /* CONFIG_SPL */
+
+#define CONFIG_SPL_BSS_START_ADDR 0x4ff80000
+#define CONFIG_SPL_BSS_MAX_SIZE 0x80000 /* 512 KiB */
+
+#define CONFIG_SPL_TEXT_BASE 0x20 /* sram start+header */
+#define CONFIG_SPL_MAX_SIZE 0x5fe0 /* 24KB on sun4i/sun7i */
+
+#define CONFIG_SPL_LIBDISK_SUPPORT
+#define CONFIG_SPL_MMC_SUPPORT
+
+#define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/armv7/sunxi/u-boot-spl.lds"
+
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 80 /* 40KiB */
+#define CONFIG_SPL_PAD_TO 32768 /* decimal for 'dd' */
+
+#endif /* CONFIG_SPL */
+
/* end of 32 KiB in sram */
#define LOW_LEVEL_SRAM_STACK 0x00008000 /* End of sram */
#define CONFIG_SPL_STACK LOW_LEVEL_SRAM_STACK
diff --git a/spl/Makefile b/spl/Makefile
index 6fec252..e7c7a95 100644
--- a/spl/Makefile
+++ b/spl/Makefile
@@ -188,6 +188,12 @@ ifdef CONFIG_SAMSUNG
ALL-y += $(obj)/$(BOARD)-spl.bin
endif
+ifdef CONFIG_SUNXI
+ifndef CONFIG_SPL_FEL
+ALL-y += $(obj)/sunxi-spl.bin
+endif
+endif
+
all: $(ALL-y)
ifdef CONFIG_SAMSUNG
@@ -215,6 +221,13 @@ ifneq ($(CONFIG_SPL_TEXT_BASE),)
LDFLAGS_$(SPL_BIN) += -Ttext $(CONFIG_SPL_TEXT_BASE)
endif
+ifdef CONFIG_SUNXI
+quiet_cmd_mksunxiboot = MKSUNXI $@
+cmd_mksunxiboot = $(objtree)/tools/mksunxiboot $< $@
+$(obj)/sunxi-spl.bin: $(obj)/$(SPL_BIN).bin
+ $(call if_changed,mksunxiboot)
+endif
+
quiet_cmd_u-boot-spl = LD $@
cmd_u-boot-spl = cd $(obj) && $(LD) $(LDFLAGS) $(LDFLAGS_$(@F)) \
$(patsubst $(obj)/%,%,$(u-boot-spl-init)) --start-group \
diff --git a/tools/.gitignore b/tools/.gitignore
index 2a90dfe..3ad5db3 100644
--- a/tools/.gitignore
+++ b/tools/.gitignore
@@ -9,6 +9,7 @@
/mkexynosspl
/mpc86x_clk
/mxsboot
+/mksunxiboot
/ncb
/proftool
/relocate-rela
diff --git a/tools/Makefile b/tools/Makefile
index 097cc1d..062a404 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -120,6 +120,8 @@ hostprogs-$(CONFIG_MX23) += mxsboot$(SFX)
hostprogs-$(CONFIG_MX28) += mxsboot$(SFX)
HOSTCFLAGS_mxsboot$(SFX).o := -pedantic
+hostprogs-$(CONFIG_SUNXI) += mksunxiboot$(SFX)
+
hostprogs-$(CONFIG_NETCONSOLE) += ncb$(SFX)
hostprogs-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX)
diff --git a/tools/mksunxiboot.c b/tools/mksunxiboot.c
new file mode 100644
index 0000000..50fcda5
--- /dev/null
+++ b/tools/mksunxiboot.c
@@ -0,0 +1,154 @@
+/*
+ * (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.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#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 0x7600 /* 0x7748+ is used by BROM */
+#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;
+ }
+
+ memset((void *)img.pad, 0, BLOCK_SIZE);
+
+ /* get input file size */
+ file_size = lseek(fd_in, 0, SEEK_END);
+
+ if (file_size > SRAM_LOAD_MAX_SIZE) {
+ fprintf(stderr, "ERROR: File too large!\n");
+ return EXIT_FAILURE;
+ } else {
+ load_size = ALIGN(file_size, sizeof(int));
+ }
+
+ fd_out = open(argv[2], O_WRONLY | O_CREAT, 0666);
+ if (fd_out < 0) {
+ perror("Open output file");
+ return EXIT_FAILURE;
+ }
+
+ /* read file to buffer to calculate checksum */
+ lseek(fd_in, 0, SEEK_SET);
+ count = read(fd_in, img.code, load_size);
+ if (count != load_size) {
+ perror("Reading input image");
+ return EXIT_FAILURE;
+ }
+
+ /* 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);
+ if (count != img.header.length) {
+ perror("Writing output");
+ return EXIT_FAILURE;
+ }
+
+ close(fd_in);
+ close(fd_out);
+
+ return EXIT_SUCCESS;
+}
--
1.9.0

View File

@ -0,0 +1,53 @@
From f66618b23bc59f2a6374edd2611e88838dc6e854 Mon Sep 17 00:00:00 2001
From: Dennis Gilmore <dennis@ausil.us>
Date: Thu, 24 Apr 2014 18:21:53 -0500
Subject: [PATCH 26/36] port over to generic bootcommands
---
include/configs/sunxi-common.h | 24 +++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index 56a89b9..65f3244 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -112,8 +112,26 @@
#define CONFIG_ENV_OFFSET (544 << 10) /* (8 + 24 + 512) KiB */
#define CONFIG_ENV_SIZE (128 << 10) /* 128 KiB */
+#ifndef CONFIG_SPL_BUILD
+#include <config_distro_defaults.h>
+#include <config_distro_bootcmd.h>
+
+#define CONFIG_DEFAULT_FDT_FILE "sun7i-a20-cubietruck.dtb"
+
#define CONFIG_EXTRA_ENV_SETTINGS \
- "bootm_size=0x10000000\0"
+ "kernel_addr_r=0x42000000\0" \
+ "pxe_addr_r=0x4FE00000\0" \
+ "scriptaddr=0x4FF00000\0" \
+ "fdt_addr_r=0x50000000\0" \
+ "ramdisk_addr_r=0x51000000\0" \
+ "bootm_size=0x10000000\0" \
+ "console=ttyS0,115200\0" \
+ "fdt_file=" CONFIG_DEFAULT_FDT_FILE "\0" \
+ BOOTCMDS_COMMON
+
+#define CONFIG_BOOTCOMMAND \
+ "for target in ${boot_targets}; do run bootcmd_${target}; done ;"
+#endif
#define CONFIG_SYS_BOOT_GET_CMDLINE
@@ -197,8 +215,4 @@
#define CONFIG_ENV_IS_NOWHERE
#endif
-#ifndef CONFIG_SPL_BUILD
-#include <config_distro_defaults.h>
-#endif
-
#endif /* _SUNXI_COMMON_CONFIG_H */
--
1.9.0

View File

@ -0,0 +1,44 @@
From f2c485bd04fe493ff06255a8be2bd754f6f0f766 Mon Sep 17 00:00:00 2001
From: Marc Zyngier <marc.zyngier@arm.com>
Date: Sat, 26 Apr 2014 13:17:02 +0100
Subject: [PATCH 27/36] ARM: HYP/non-sec: move switch to non-sec to the last
boot phase
Having the switch to non-secure in the "prep" phase is causing
all kind of troubles, as that stage can be called multiple times.
Instead, move the switch to non-secure to the last possible phase,
when there is no turning back anymore.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/lib/bootm.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 47ee070..10634a4 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -242,7 +242,6 @@ static void boot_prep_linux(bootm_headers_t *images)
printf("FDT and ATAGS support not compiled in - hanging\n");
hang();
}
- do_nonsec_virt_switch();
}
/* Subcommand: GO */
@@ -287,8 +286,10 @@ static void boot_jump_linux(bootm_headers_t *images, int flag)
else
r2 = gd->bd->bi_boot_params;
- if (!fake)
+ if (!fake) {
+ do_nonsec_virt_switch();
kernel_entry(0, machid, r2);
+ }
#endif
}
--
1.9.0

View File

@ -0,0 +1,28 @@
From ffddd794d834f39e120603d6764d7f25bf24ddc0 Mon Sep 17 00:00:00 2001
From: Marc Zyngier <marc.zyngier@arm.com>
Date: Sat, 26 Apr 2014 13:17:03 +0100
Subject: [PATCH 28/36] ARM: HYP/non-sec: add a barrier after setting SCR.NS==1
A CP15 instruction execution can be reordered, requiring an
isb to be sure it is executed in program order.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/cpu/armv7/nonsec_virt.S | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/cpu/armv7/nonsec_virt.S b/arch/arm/cpu/armv7/nonsec_virt.S
index 6367e09..12de5c2 100644
--- a/arch/arm/cpu/armv7/nonsec_virt.S
+++ b/arch/arm/cpu/armv7/nonsec_virt.S
@@ -46,6 +46,7 @@ _secure_monitor:
#endif
mcr p15, 0, r1, c1, c1, 0 @ write SCR (with NS bit set)
+ isb
#ifdef CONFIG_ARMV7_VIRT
mrceq p15, 0, r0, c12, c0, 1 @ get MVBAR value
--
1.9.0

View File

@ -0,0 +1,50 @@
From 2e19eb7de158a26c335d8820becaf859602dd401 Mon Sep 17 00:00:00 2001
From: Marc Zyngier <marc.zyngier@arm.com>
Date: Sat, 26 Apr 2014 13:17:04 +0100
Subject: [PATCH 29/36] ARM: non-sec: reset CNTVOFF to zero
Before switching to non-secure, make sure that CNTVOFF is set
to zero on all CPUs. Otherwise, kernel running in non-secure
without HYP enabled (hence using virtual timers) may observe
timers that are not synchronized, effectively seeing time
going backward...
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/cpu/armv7/nonsec_virt.S | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/arch/arm/cpu/armv7/nonsec_virt.S b/arch/arm/cpu/armv7/nonsec_virt.S
index 12de5c2..b5c946f 100644
--- a/arch/arm/cpu/armv7/nonsec_virt.S
+++ b/arch/arm/cpu/armv7/nonsec_virt.S
@@ -38,10 +38,10 @@ _secure_monitor:
bic r1, r1, #0x4e @ clear IRQ, FIQ, EA, nET bits
orr r1, r1, #0x31 @ enable NS, AW, FW bits
-#ifdef CONFIG_ARMV7_VIRT
mrc p15, 0, r0, c0, c1, 1 @ read ID_PFR1
and r0, r0, #CPUID_ARM_VIRT_MASK @ mask virtualization bits
cmp r0, #(1 << CPUID_ARM_VIRT_SHIFT)
+#ifdef CONFIG_ARMV7_VIRT
orreq r1, r1, #0x100 @ allow HVC instruction
#endif
@@ -52,7 +52,14 @@ _secure_monitor:
mrceq p15, 0, r0, c12, c0, 1 @ get MVBAR value
mcreq p15, 4, r0, c12, c0, 0 @ write HVBAR
#endif
+ bne 1f
+ @ Reset CNTVOFF to 0 before leaving monitor mode
+ mrc p15, 0, r0, c0, c1, 1 @ read ID_PFR1
+ ands r0, r0, #CPUID_ARM_GENTIMER_MASK @ test arch timer bits
+ movne r0, #0
+ mcrrne p15, 4, r0, r0, c14 @ Reset CNTVOFF to zero
+1:
movs pc, lr @ return to non-secure SVC
_hyp_trap:
--
1.9.0

View File

@ -0,0 +1,53 @@
From eed1c957b6294e0205cc8521516c51dce7bb72c1 Mon Sep 17 00:00:00 2001
From: Marc Zyngier <marc.zyngier@arm.com>
Date: Sat, 26 Apr 2014 13:17:05 +0100
Subject: [PATCH 30/36] ARM: add missing HYP mode constant
In order to be able to use the various mode constants (far more
readable than random hex values), add the missing HYP and A
values.
Also update arm/lib/interrupts.c to display HYP instead of an
unknown value.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/include/asm/proc-armv/ptrace.h | 2 ++
arch/arm/lib/interrupts.c | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/arm/include/asm/proc-armv/ptrace.h b/arch/arm/include/asm/proc-armv/ptrace.h
index 21aef58..71df5a9 100644
--- a/arch/arm/include/asm/proc-armv/ptrace.h
+++ b/arch/arm/include/asm/proc-armv/ptrace.h
@@ -38,12 +38,14 @@ struct pt_regs {
#define IRQ_MODE 0x12
#define SVC_MODE 0x13
#define ABT_MODE 0x17
+#define HYP_MODE 0x1a
#define UND_MODE 0x1b
#define SYSTEM_MODE 0x1f
#define MODE_MASK 0x1f
#define T_BIT 0x20
#define F_BIT 0x40
#define I_BIT 0x80
+#define A_BIT 0x100
#define CC_V_BIT (1 << 28)
#define CC_C_BIT (1 << 29)
#define CC_Z_BIT (1 << 30)
diff --git a/arch/arm/lib/interrupts.c b/arch/arm/lib/interrupts.c
index 758b013..f6b7c03 100644
--- a/arch/arm/lib/interrupts.c
+++ b/arch/arm/lib/interrupts.c
@@ -103,7 +103,7 @@ void show_regs (struct pt_regs *regs)
"UK12_26", "UK13_26", "UK14_26", "UK15_26",
"USER_32", "FIQ_32", "IRQ_32", "SVC_32",
"UK4_32", "UK5_32", "UK6_32", "ABT_32",
- "UK8_32", "UK9_32", "UK10_32", "UND_32",
+ "UK8_32", "UK9_32", "HYP_32", "UND_32",
"UK12_32", "UK13_32", "UK14_32", "SYS_32",
};
--
1.9.0

View File

@ -0,0 +1,93 @@
From 4c35371fe7e2ed9e057cd3eb9380380099d0ea19 Mon Sep 17 00:00:00 2001
From: Marc Zyngier <marc.zyngier@arm.com>
Date: Sat, 26 Apr 2014 13:17:06 +0100
Subject: [PATCH 31/36] ARM: HYP/non-sec: add separate section for secure code
In anticipation of refactoring the HYP/non-secure code to run
from secure RAM, add a new linker section that will contain that
code.
Nothing is using it just yet.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/config.mk | 2 +-
arch/arm/cpu/u-boot.lds | 30 ++++++++++++++++++++++++++++++
arch/arm/lib/sections.c | 2 ++
3 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/arch/arm/config.mk b/arch/arm/config.mk
index 66ecc2e..a729ed2 100644
--- a/arch/arm/config.mk
+++ b/arch/arm/config.mk
@@ -113,7 +113,7 @@ endif
ifdef CONFIG_ARM64
OBJCOPYFLAGS += -j .text -j .rodata -j .data -j .u_boot_list -j .rela.dyn
else
-OBJCOPYFLAGS += -j .text -j .rodata -j .hash -j .data -j .got.plt -j .u_boot_list -j .rel.dyn
+OBJCFLAGS += -j .text -j .secure_text -j .rodata -j .hash -j .data -j .got.plt -j .u_boot_list -j .rel.dyn
endif
ifneq ($(CONFIG_IMX_CONFIG),)
diff --git a/arch/arm/cpu/u-boot.lds b/arch/arm/cpu/u-boot.lds
index 33c1f99..f45885d 100644
--- a/arch/arm/cpu/u-boot.lds
+++ b/arch/arm/cpu/u-boot.lds
@@ -7,6 +7,8 @@
* SPDX-License-Identifier: GPL-2.0+
*/
+#include <config.h>
+
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
@@ -22,6 +24,34 @@ SECTIONS
*(.text*)
}
+#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT) || defined(CONFIG_ARMV7_PSCI)
+
+#ifndef CONFIG_ARMV7_SECURE_BASE
+#define CONFIG_ARMV7_SECURE_BASE
+#endif
+
+ .__secure_start : {
+ . = ALIGN(0x1000);
+ *(.__secure_start)
+ }
+
+ .secure_text CONFIG_ARMV7_SECURE_BASE :
+ AT(ADDR(.__secure_start) + SIZEOF(.__secure_start))
+ {
+ *(._secure.text)
+ }
+
+ . = LOADADDR(.__secure_start) +
+ SIZEOF(.__secure_start) +
+ SIZEOF(.secure_text);
+
+ __secure_end_lma = .;
+ .__secure_end : AT(__secure_end_lma) {
+ *(.__secure_end)
+ LONG(0x1d1071c); /* Must output something to reset LMA */
+ }
+#endif
+
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
diff --git a/arch/arm/lib/sections.c b/arch/arm/lib/sections.c
index 5b30bcb..a1205c3 100644
--- a/arch/arm/lib/sections.c
+++ b/arch/arm/lib/sections.c
@@ -25,4 +25,6 @@ char __image_copy_start[0] __attribute__((section(".__image_copy_start")));
char __image_copy_end[0] __attribute__((section(".__image_copy_end")));
char __rel_dyn_start[0] __attribute__((section(".__rel_dyn_start")));
char __rel_dyn_end[0] __attribute__((section(".__rel_dyn_end")));
+char __secure_start[0] __attribute__((section(".__secure_start")));
+char __secure_end[0] __attribute__((section(".__secure_end")));
char _end[0] __attribute__((section(".__end")));
--
1.9.0

View File

@ -0,0 +1,499 @@
From a32061fdf5a5d582e62293bfa8a5c28911c4209f Mon Sep 17 00:00:00 2001
From: Marc Zyngier <marc.zyngier@arm.com>
Date: Sat, 26 Apr 2014 13:17:07 +0100
Subject: [PATCH 32/36] ARM: HYP/non-sec: allow relocation to secure RAM
The current non-sec switching code suffers from one major issue:
it cannot run in secure RAM, as a large part of u-boot still needs
to be run while we're switched to non-secure.
This patch reworks the whole HYP/non-secure strategy by:
- making sure the secure code is the *last* thing u-boot executes
before entering the payload
- performing an exception return from secure mode directly into
the payload
- allowing the code to be dynamically relocated to secure RAM
before switching to non-secure.
This involves quite a bit of horrible code, specially as u-boot
relocation is quite primitive.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/cpu/armv7/nonsec_virt.S | 161 +++++++++++++++++++--------------------
arch/arm/cpu/armv7/virt-v7.c | 59 +++++---------
arch/arm/include/asm/armv7.h | 10 ++-
arch/arm/include/asm/secure.h | 26 +++++++
arch/arm/lib/bootm.c | 22 +++---
5 files changed, 138 insertions(+), 140 deletions(-)
create mode 100644 arch/arm/include/asm/secure.h
diff --git a/arch/arm/cpu/armv7/nonsec_virt.S b/arch/arm/cpu/armv7/nonsec_virt.S
index b5c946f..2a43e3c 100644
--- a/arch/arm/cpu/armv7/nonsec_virt.S
+++ b/arch/arm/cpu/armv7/nonsec_virt.S
@@ -10,10 +10,13 @@
#include <linux/linkage.h>
#include <asm/gic.h>
#include <asm/armv7.h>
+#include <asm/proc-armv/ptrace.h>
.arch_extension sec
.arch_extension virt
+ .pushsection ._secure.text, "ax"
+
.align 5
/* the vector table for secure state and HYP mode */
_monitor_vectors:
@@ -22,51 +25,86 @@ _monitor_vectors:
adr pc, _secure_monitor
.word 0
.word 0
- adr pc, _hyp_trap
+ .word 0
.word 0
.word 0
+.macro is_cpu_virt_capable tmp
+ mrc p15, 0, \tmp, c0, c1, 1 @ read ID_PFR1
+ and \tmp, \tmp, #CPUID_ARM_VIRT_MASK @ mask virtualization bits
+ cmp \tmp, #(1 << CPUID_ARM_VIRT_SHIFT)
+.endm
+
/*
* secure monitor handler
* U-boot calls this "software interrupt" in start.S
* This is executed on a "smc" instruction, we use a "smc #0" to switch
* to non-secure state.
- * We use only r0 and r1 here, due to constraints in the caller.
+ * r0, r1, r2: passed to the callee
+ * ip: target PC
*/
_secure_monitor:
- mrc p15, 0, r1, c1, c1, 0 @ read SCR
- bic r1, r1, #0x4e @ clear IRQ, FIQ, EA, nET bits
- orr r1, r1, #0x31 @ enable NS, AW, FW bits
+ mrc p15, 0, r5, c1, c1, 0 @ read SCR
+ bic r5, r5, #0x4e @ clear IRQ, FIQ, EA, nET bits
+ orr r5, r5, #0x31 @ enable NS, AW, FW bits
- mrc p15, 0, r0, c0, c1, 1 @ read ID_PFR1
- and r0, r0, #CPUID_ARM_VIRT_MASK @ mask virtualization bits
- cmp r0, #(1 << CPUID_ARM_VIRT_SHIFT)
+ mov r6, #SVC_MODE @ default mode is SVC
+ is_cpu_virt_capable r4
#ifdef CONFIG_ARMV7_VIRT
- orreq r1, r1, #0x100 @ allow HVC instruction
+ orreq r5, r5, #0x100 @ allow HVC instruction
+ moveq r6, #HYP_MODE @ Enter the kernel as HYP
#endif
- mcr p15, 0, r1, c1, c1, 0 @ write SCR (with NS bit set)
+ mcr p15, 0, r5, c1, c1, 0 @ write SCR (with NS bit set)
isb
-#ifdef CONFIG_ARMV7_VIRT
- mrceq p15, 0, r0, c12, c0, 1 @ get MVBAR value
- mcreq p15, 4, r0, c12, c0, 0 @ write HVBAR
-#endif
bne 1f
@ Reset CNTVOFF to 0 before leaving monitor mode
- mrc p15, 0, r0, c0, c1, 1 @ read ID_PFR1
- ands r0, r0, #CPUID_ARM_GENTIMER_MASK @ test arch timer bits
- movne r0, #0
- mcrrne p15, 4, r0, r0, c14 @ Reset CNTVOFF to zero
+ mrc p15, 0, r4, c0, c1, 1 @ read ID_PFR1
+ ands r4, r4, #CPUID_ARM_GENTIMER_MASK @ test arch timer bits
+ movne r4, #0
+ mcrrne p15, 4, r4, r4, c14 @ Reset CNTVOFF to zero
1:
- movs pc, lr @ return to non-secure SVC
-
-_hyp_trap:
- mrs lr, elr_hyp @ for older asm: .byte 0x00, 0xe3, 0x0e, 0xe1
- mov pc, lr @ do no switch modes, but
- @ return to caller
-
+ mov lr, ip
+ mov ip, #(F_BIT | I_BIT | A_BIT) @ Set A, I and F
+ tst lr, #1 @ Check for Thumb PC
+ orrne ip, ip, #T_BIT @ Set T if Thumb
+ orr ip, ip, r6 @ Slot target mode in
+ msr spsr_cxfs, ip @ Set full SPSR
+ movs pc, lr @ ERET to non-secure
+
+ENTRY(_do_nonsec_entry)
+ mov ip, r0
+ mov r0, r1
+ mov r1, r2
+ mov r2, r3
+ smc #0
+ENDPROC(_do_nonsec_entry)
+
+.macro get_cbar_addr addr
+#ifdef CONFIG_ARM_GIC_BASE_ADDRESS
+ ldr \addr, =CONFIG_ARM_GIC_BASE_ADDRESS
+#else
+ mrc p15, 4, \addr, c15, c0, 0 @ read CBAR
+ bfc \addr, #0, #15 @ clear reserved bits
+#endif
+.endm
+
+.macro get_gicd_addr addr
+ get_cbar_addr \addr
+ add \addr, \addr, #GIC_DIST_OFFSET @ GIC dist i/f offset
+.endm
+
+.macro get_gicc_addr addr, tmp
+ get_cbar_addr \addr
+ is_cpu_virt_capable \tmp
+ movne \tmp, #GIC_CPU_OFFSET_A9 @ GIC CPU offset for A9
+ moveq \tmp, #GIC_CPU_OFFSET_A15 @ GIC CPU offset for A15/A7
+ add \addr, \addr, \tmp
+.endm
+
+#ifndef CONFIG_ARMV7_PSCI
/*
* Secondary CPUs start here and call the code for the core specific parts
* of the non-secure and HYP mode transition. The GIC distributor specific
@@ -74,31 +112,21 @@ _hyp_trap:
* Then they go back to wfi and wait to be woken up by the kernel again.
*/
ENTRY(_smp_pen)
- mrs r0, cpsr
- orr r0, r0, #0xc0
- msr cpsr, r0 @ disable interrupts
- ldr r1, =_start
- mcr p15, 0, r1, c12, c0, 0 @ set VBAR
+ cpsid i
+ cpsid f
bl _nonsec_init
- mov r12, r0 @ save GICC address
-#ifdef CONFIG_ARMV7_VIRT
- bl _switch_to_hyp
-#endif
-
- ldr r1, [r12, #GICC_IAR] @ acknowledge IPI
- str r1, [r12, #GICC_EOIR] @ signal end of interrupt
adr r0, _smp_pen @ do not use this address again
b smp_waitloop @ wait for IPIs, board specific
ENDPROC(_smp_pen)
+#endif
/*
* Switch a core to non-secure state.
*
* 1. initialize the GIC per-core interface
* 2. allow coprocessor access in non-secure modes
- * 3. switch the cpu mode (by calling "smc #0")
*
* Called from smp_pen by secondary cores and directly by the BSP.
* Do not assume that the stack is available and only use registers
@@ -108,38 +136,23 @@ ENDPROC(_smp_pen)
* though, but we check this in C before calling this function.
*/
ENTRY(_nonsec_init)
-#ifdef CONFIG_ARM_GIC_BASE_ADDRESS
- ldr r2, =CONFIG_ARM_GIC_BASE_ADDRESS
-#else
- mrc p15, 4, r2, c15, c0, 0 @ read CBAR
- bfc r2, #0, #15 @ clear reserved bits
-#endif
- add r3, r2, #GIC_DIST_OFFSET @ GIC dist i/f offset
+ get_gicd_addr r3
+
mvn r1, #0 @ all bits to 1
str r1, [r3, #GICD_IGROUPRn] @ allow private interrupts
- mrc p15, 0, r0, c0, c0, 0 @ read MIDR
- ldr r1, =MIDR_PRIMARY_PART_MASK
- and r0, r0, r1 @ mask out variant and revision
+ get_gicc_addr r3, r1
- ldr r1, =MIDR_CORTEX_A7_R0P0 & MIDR_PRIMARY_PART_MASK
- cmp r0, r1 @ check for Cortex-A7
-
- ldr r1, =MIDR_CORTEX_A15_R0P0 & MIDR_PRIMARY_PART_MASK
- cmpne r0, r1 @ check for Cortex-A15
-
- movne r1, #GIC_CPU_OFFSET_A9 @ GIC CPU offset for A9
- moveq r1, #GIC_CPU_OFFSET_A15 @ GIC CPU offset for A15/A7
- add r3, r2, r1 @ r3 = GIC CPU i/f addr
-
- mov r1, #1 @ set GICC_CTLR[enable]
+ mov r1, #3 @ Enable both groups
str r1, [r3, #GICC_CTLR] @ and clear all other bits
mov r1, #0xff
str r1, [r3, #GICC_PMR] @ set priority mask register
+ mrc p15, 0, r0, c1, c1, 2
movw r1, #0x3fff
- movt r1, #0x0006
- mcr p15, 0, r1, c1, c1, 2 @ NSACR = all copros to non-sec
+ movt r1, #0x0004
+ orr r0, r0, r1
+ mcr p15, 0, r0, c1, c1, 2 @ NSACR = all copros to non-sec
/* The CNTFRQ register of the generic timer needs to be
* programmed in secure state. Some primary bootloaders / firmware
@@ -157,21 +170,9 @@ ENTRY(_nonsec_init)
adr r1, _monitor_vectors
mcr p15, 0, r1, c12, c0, 1 @ set MVBAR to secure vectors
-
- mrc p15, 0, ip, c12, c0, 0 @ save secure copy of VBAR
-
isb
- smc #0 @ call into MONITOR mode
-
- mcr p15, 0, ip, c12, c0, 0 @ write non-secure copy of VBAR
-
- mov r1, #1
- str r1, [r3, #GICC_CTLR] @ enable non-secure CPU i/f
- add r2, r2, #GIC_DIST_OFFSET
- str r1, [r2, #GICD_CTLR] @ allow private interrupts
mov r0, r3 @ return GICC address
-
bx lr
ENDPROC(_nonsec_init)
@@ -183,18 +184,10 @@ ENTRY(smp_waitloop)
ldr r1, [r1]
cmp r0, r1 @ make sure we dont execute this code
beq smp_waitloop @ again (due to a spurious wakeup)
- mov pc, r1
+ mov r0, r1
+ b _do_nonsec_entry
ENDPROC(smp_waitloop)
.weak smp_waitloop
#endif
-ENTRY(_switch_to_hyp)
- mov r0, lr
- mov r1, sp @ save SVC copy of LR and SP
- isb
- hvc #0 @ for older asm: .byte 0x70, 0x00, 0x40, 0xe1
- mov sp, r1
- mov lr, r0 @ restore SVC copy of LR and SP
-
- bx lr
-ENDPROC(_switch_to_hyp)
+ .popsection
diff --git a/arch/arm/cpu/armv7/virt-v7.c b/arch/arm/cpu/armv7/virt-v7.c
index 2cd604f..6500030 100644
--- a/arch/arm/cpu/armv7/virt-v7.c
+++ b/arch/arm/cpu/armv7/virt-v7.c
@@ -13,17 +13,10 @@
#include <asm/armv7.h>
#include <asm/gic.h>
#include <asm/io.h>
+#include <asm/secure.h>
unsigned long gic_dist_addr;
-static unsigned int read_cpsr(void)
-{
- unsigned int reg;
-
- asm volatile ("mrs %0, cpsr\n" : "=r" (reg));
- return reg;
-}
-
static unsigned int read_id_pfr1(void)
{
unsigned int reg;
@@ -72,6 +65,18 @@ static unsigned long get_gicd_base_address(void)
#endif
}
+static void relocate_secure_section(void)
+{
+#ifdef CONFIG_ARMV7_SECURE_BASE
+ size_t sz = __secure_end - __secure_start;
+
+ memcpy((void *)CONFIG_ARMV7_SECURE_BASE, __secure_start, sz);
+ flush_dcache_range(CONFIG_ARMV7_SECURE_BASE,
+ CONFIG_ARMV7_SECURE_BASE + sz + 1);
+ invalidate_icache_all();
+#endif
+}
+
static void kick_secondary_cpus_gic(unsigned long gicdaddr)
{
/* kick all CPUs (except this one) by writing to GICD_SGIR */
@@ -83,35 +88,7 @@ void __weak smp_kick_all_cpus(void)
kick_secondary_cpus_gic(gic_dist_addr);
}
-int armv7_switch_hyp(void)
-{
- unsigned int reg;
-
- /* check whether we are in HYP mode already */
- if ((read_cpsr() & 0x1f) == 0x1a) {
- debug("CPU already in HYP mode\n");
- return 0;
- }
-
- /* check whether the CPU supports the virtualization extensions */
- reg = read_id_pfr1();
- if ((reg & CPUID_ARM_VIRT_MASK) != 1 << CPUID_ARM_VIRT_SHIFT) {
- printf("HYP mode: Virtualization extensions not implemented.\n");
- return -1;
- }
-
- /* call the HYP switching code on this CPU also */
- _switch_to_hyp();
-
- if ((read_cpsr() & 0x1F) != 0x1a) {
- printf("HYP mode: switch not successful.\n");
- return -1;
- }
-
- return 0;
-}
-
-int armv7_switch_nonsec(void)
+int armv7_init_nonsec(void)
{
unsigned int reg;
unsigned itlinesnr, i;
@@ -147,11 +124,13 @@ int armv7_switch_nonsec(void)
for (i = 1; i <= itlinesnr; i++)
writel((unsigned)-1, gic_dist_addr + GICD_IGROUPRn + 4 * i);
- smp_set_core_boot_addr((unsigned long)_smp_pen, -1);
+#ifndef CONFIG_ARMV7_PSCI
+ smp_set_core_boot_addr((unsigned long)secure_ram_addr(_smp_pen), -1);
smp_kick_all_cpus();
+#endif
/* call the non-sec switching code on this CPU also */
- _nonsec_init();
-
+ relocate_secure_section();
+ secure_ram_addr(_nonsec_init)();
return 0;
}
diff --git a/arch/arm/include/asm/armv7.h b/arch/arm/include/asm/armv7.h
index 395444e..11476dd 100644
--- a/arch/arm/include/asm/armv7.h
+++ b/arch/arm/include/asm/armv7.h
@@ -78,13 +78,17 @@ void v7_outer_cache_inval_range(u32 start, u32 end);
#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT)
-int armv7_switch_nonsec(void);
-int armv7_switch_hyp(void);
+int armv7_init_nonsec(void);
/* defined in assembly file */
unsigned int _nonsec_init(void);
+void _do_nonsec_entry(void *target_pc, unsigned long r0,
+ unsigned long r1, unsigned long r2);
void _smp_pen(void);
-void _switch_to_hyp(void);
+
+extern char __secure_start[];
+extern char __secure_end[];
+
#endif /* CONFIG_ARMV7_NONSEC || CONFIG_ARMV7_VIRT */
#endif /* ! __ASSEMBLY__ */
diff --git a/arch/arm/include/asm/secure.h b/arch/arm/include/asm/secure.h
new file mode 100644
index 0000000..effdb18
--- /dev/null
+++ b/arch/arm/include/asm/secure.h
@@ -0,0 +1,26 @@
+#ifndef __ASM_SECURE_H
+#define __ASM_SECURE_H
+
+#include <config.h>
+
+#ifdef CONFIG_ARMV7_SECURE_BASE
+/*
+ * Warning, horror ahead.
+ *
+ * The target code lives in our "secure ram", but u-boot doesn't know
+ * that, and has blindly added reloc_off to every relocation
+ * entry. Gahh. Do the opposite conversion. This hack also prevents
+ * GCC from generating code veeners, which u-boot doesn't relocate at
+ * all...
+ */
+#define secure_ram_addr(_fn) ({ \
+ DECLARE_GLOBAL_DATA_PTR; \
+ void *__fn = _fn; \
+ typeof(_fn) *__tmp = (__fn - gd->reloc_off); \
+ __tmp; \
+ })
+#else
+#define secure_ram_addr(_fn) (_fn)
+#endif
+
+#endif
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 10634a4..61aa14e 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -20,6 +20,7 @@
#include <libfdt.h>
#include <fdt_support.h>
#include <asm/bootm.h>
+#include <asm/secure.h>
#include <linux/compiler.h>
#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT)
@@ -184,27 +185,17 @@ static void setup_end_tag(bd_t *bd)
__weak void setup_board_tags(struct tag **in_params) {}
+#ifdef CONFIG_ARM64
static void do_nonsec_virt_switch(void)
{
-#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT)
- if (armv7_switch_nonsec() == 0)
-#ifdef CONFIG_ARMV7_VIRT
- if (armv7_switch_hyp() == 0)
- debug("entered HYP mode\n");
-#else
- debug("entered non-secure state\n");
-#endif
-#endif
-
-#ifdef CONFIG_ARM64
smp_kick_all_cpus();
flush_dcache_all(); /* flush cache before swtiching to EL2 */
armv8_switch_to_el2();
#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
armv8_switch_to_el1();
#endif
-#endif
}
+#endif
/* Subcommand: PREP */
static void boot_prep_linux(bootm_headers_t *images)
@@ -287,8 +278,13 @@ static void boot_jump_linux(bootm_headers_t *images, int flag)
r2 = gd->bd->bi_boot_params;
if (!fake) {
- do_nonsec_virt_switch();
+#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT)
+ armv7_init_nonsec();
+ secure_ram_addr(_do_nonsec_entry)(kernel_entry,
+ 0, machid, r2);
+#else
kernel_entry(0, machid, r2);
+#endif
}
#endif
}
--
1.9.0

View File

@ -0,0 +1,185 @@
From a1d59cb7f8618db44730dcd0d3fb8708aeb8901d Mon Sep 17 00:00:00 2001
From: Marc Zyngier <marc.zyngier@arm.com>
Date: Sat, 26 Apr 2014 13:17:08 +0100
Subject: [PATCH 33/36] ARM: HYP/non-sec: add generic ARMv7 PSCI code
Implement core support for PSCI. As this is generic code, it doesn't
implement anything really useful (all the functions are returning
Not Implemented).
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/cpu/armv7/Makefile | 4 ++
arch/arm/cpu/armv7/psci.S | 102 ++++++++++++++++++++++++++++++++++++++++++++
arch/arm/include/asm/psci.h | 35 +++++++++++++++
3 files changed, 141 insertions(+)
create mode 100644 arch/arm/cpu/armv7/psci.S
create mode 100644 arch/arm/include/asm/psci.h
diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
index ddf00f3..da5ce22 100644
--- a/arch/arm/cpu/armv7/Makefile
+++ b/arch/arm/cpu/armv7/Makefile
@@ -23,6 +23,10 @@ obj-y += nonsec_virt.o
obj-y += virt-v7.o
endif
+ifneq ($(CONFIG_ARMV7_PSCI),)
+obj-y += psci.o
+endif
+
obj-$(CONFIG_KONA) += kona-common/
obj-$(CONFIG_OMAP_COMMON) += omap-common/
obj-$(CONFIG_TEGRA) += tegra-common/
diff --git a/arch/arm/cpu/armv7/psci.S b/arch/arm/cpu/armv7/psci.S
new file mode 100644
index 0000000..bf11a34
--- /dev/null
+++ b/arch/arm/cpu/armv7/psci.S
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2013,2014 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+#include <asm/psci.h>
+
+ .pushsection ._secure.text, "ax"
+
+ .arch_extension sec
+
+ .align 5
+ .globl _psci_vectors
+_psci_vectors:
+ b default_psci_vector @ reset
+ b default_psci_vector @ undef
+ b _smc_psci @ smc
+ b default_psci_vector @ pabort
+ b default_psci_vector @ dabort
+ b default_psci_vector @ hyp
+ b default_psci_vector @ irq
+ b psci_fiq_enter @ fiq
+
+ENTRY(psci_fiq_enter)
+ movs pc, lr
+ENDPROC(psci_fiq_enter)
+.weak psci_fiq_enter
+
+ENTRY(default_psci_vector)
+ movs pc, lr
+ENDPROC(default_psci_vector)
+.weak default_psci_vector
+
+ENTRY(psci_cpu_suspend)
+ENTRY(psci_cpu_off)
+ENTRY(psci_cpu_on)
+ENTRY(psci_migrate)
+ mov r0, #ARM_PSCI_RET_NI @ Return -1 (Not Implemented)
+ mov pc, lr
+ENDPROC(psci_migrate)
+ENDPROC(psci_cpu_on)
+ENDPROC(psci_cpu_off)
+ENDPROC(psci_cpu_suspend)
+.weak psci_cpu_suspend
+.weak psci_cpu_off
+.weak psci_cpu_on
+.weak psci_migrate
+
+_psci_table:
+ .word ARM_PSCI_FN_CPU_SUSPEND
+ .word psci_cpu_suspend
+ .word ARM_PSCI_FN_CPU_OFF
+ .word psci_cpu_off
+ .word ARM_PSCI_FN_CPU_ON
+ .word psci_cpu_on
+ .word ARM_PSCI_FN_MIGRATE
+ .word psci_migrate
+ .word 0
+ .word 0
+
+_smc_psci:
+ push {r4-r7,lr}
+
+ @ Switch to secure
+ mrc p15, 0, r7, c1, c1, 0
+ bic r4, r7, #1
+ mcr p15, 0, r4, c1, c1, 0
+ isb
+
+ adr r4, _psci_table
+1: ldr r5, [r4] @ Load PSCI function ID
+ ldr r6, [r4, #4] @ Load target PC
+ cmp r5, #0 @ If reach the end, bail out
+ moveq r0, #ARM_PSCI_RET_INVAL @ Return -2 (Invalid)
+ beq 2f
+ cmp r0, r5 @ If not matching, try next entry
+ addne r4, r4, #8
+ bne 1b
+
+ blx r6 @ Execute PSCI function
+
+ @ Switch back to non-secure
+2: mcr p15, 0, r7, c1, c1, 0
+
+ pop {r4-r7, lr}
+ movs pc, lr @ Return to the kernel
+
+ .popsection
diff --git a/arch/arm/include/asm/psci.h b/arch/arm/include/asm/psci.h
new file mode 100644
index 0000000..704b4b0
--- /dev/null
+++ b/arch/arm/include/asm/psci.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARM_PSCI_H__
+#define __ARM_PSCI_H__
+
+/* PSCI interface */
+#define ARM_PSCI_FN_BASE 0x95c1ba5e
+#define ARM_PSCI_FN(n) (ARM_PSCI_FN_BASE + (n))
+
+#define ARM_PSCI_FN_CPU_SUSPEND ARM_PSCI_FN(0)
+#define ARM_PSCI_FN_CPU_OFF ARM_PSCI_FN(1)
+#define ARM_PSCI_FN_CPU_ON ARM_PSCI_FN(2)
+#define ARM_PSCI_FN_MIGRATE ARM_PSCI_FN(3)
+
+#define ARM_PSCI_RET_SUCCESS 0
+#define ARM_PSCI_RET_NI (-1)
+#define ARM_PSCI_RET_INVAL (-2)
+#define ARM_PSCI_RET_DENIED (-3)
+
+#endif /* __ARM_PSCI_H__ */
--
1.9.0

View File

@ -0,0 +1,47 @@
From e9b55c2e26b83bffe6dea6ea4be8fbc249bb85d5 Mon Sep 17 00:00:00 2001
From: Marc Zyngier <marc.zyngier@arm.com>
Date: Sat, 26 Apr 2014 13:17:09 +0100
Subject: [PATCH 34/36] ARM: HYP/non-sec: add the option for a second-stage
monitor
Allow the switch to a second stage secure monitor just before
switching to non-secure.
This allows a resident piece of firmware to be active once the
kernel has been entered (the u-boot monitor is dead anyway,
its pages being reused).
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/cpu/armv7/nonsec_virt.S | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/arch/arm/cpu/armv7/nonsec_virt.S b/arch/arm/cpu/armv7/nonsec_virt.S
index 2a43e3c..745670e 100644
--- a/arch/arm/cpu/armv7/nonsec_virt.S
+++ b/arch/arm/cpu/armv7/nonsec_virt.S
@@ -44,10 +44,19 @@ _monitor_vectors:
* ip: target PC
*/
_secure_monitor:
+#ifdef CONFIG_ARMV7_PSCI
+ ldr r5, =_psci_vectors @ Switch to the next monitor
+ mcr p15, 0, r5, c12, c0, 1
+ isb
+
+ @ Obtain a secure stack, and configure the PSCI backend
+ bl psci_arch_init
+#endif
+
mrc p15, 0, r5, c1, c1, 0 @ read SCR
- bic r5, r5, #0x4e @ clear IRQ, FIQ, EA, nET bits
+ bic r5, r5, #0x4a @ clear IRQ, EA, nET bits
orr r5, r5, #0x31 @ enable NS, AW, FW bits
-
+ @ FIQ preserved for secure mode
mov r6, #SVC_MODE @ default mode is SVC
is_cpu_virt_capable r4
#ifdef CONFIG_ARMV7_VIRT
--
1.9.0

View File

@ -0,0 +1,97 @@
From 7b63229b282e0be1e1e81da79ad4ee10ab4e1c19 Mon Sep 17 00:00:00 2001
From: Ma Haijun <mahaijuns@gmail.com>
Date: Sat, 26 Apr 2014 13:17:10 +0100
Subject: [PATCH 35/36] ARM: convert arch_fixup_memory_node to a generic FDT
fixup function
Some architecture needs extra device tree setup. Instead of adding
yet another hook, convert arch_fixup_memory_node to be a generic
FDT fixup function.
[maz: collapsed 3 patches into one, rewrote commit message]
Signed-off-by: Ma Haijun <mahaijuns@gmail.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/lib/bootm-fdt.c | 2 +-
arch/arm/lib/bootm.c | 2 +-
common/image-fdt.c | 7 +++++--
include/common.h | 6 +++---
4 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/arch/arm/lib/bootm-fdt.c b/arch/arm/lib/bootm-fdt.c
index e40691d..8394e15 100644
--- a/arch/arm/lib/bootm-fdt.c
+++ b/arch/arm/lib/bootm-fdt.c
@@ -20,7 +20,7 @@
DECLARE_GLOBAL_DATA_PTR;
-int arch_fixup_memory_node(void *blob)
+int arch_fixup_fdt(void *blob)
{
bd_t *bd = gd->bd;
int bank;
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 61aa14e..4cff6b0 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -357,7 +357,7 @@ void boot_prep_vxworks(bootm_headers_t *images)
if (images->ft_addr) {
off = fdt_path_offset(images->ft_addr, "/memory");
if (off < 0) {
- if (arch_fixup_memory_node(images->ft_addr))
+ if (arch_fixup_fdt(images->ft_addr))
puts("## WARNING: fixup memory failed!\n");
}
}
diff --git a/common/image-fdt.c b/common/image-fdt.c
index a54a919..6f074de 100644
--- a/common/image-fdt.c
+++ b/common/image-fdt.c
@@ -445,7 +445,7 @@ __weak int ft_verify_fdt(void *fdt)
return 1;
}
-__weak int arch_fixup_memory_node(void *blob)
+__weak int arch_fixup_fdt(void *blob)
{
return 0;
}
@@ -462,7 +462,10 @@ int image_setup_libfdt(bootm_headers_t *images, void *blob,
puts(" - must RESET the board to recover.\n");
return -1;
}
- arch_fixup_memory_node(blob);
+ if (arch_fixup_fdt(blob) < 0) {
+ puts("ERROR: arch specific fdt fixup failed");
+ return -1;
+ }
if (IMAGE_OF_BOARD_SETUP)
ft_board_setup(blob, gd->bd);
fdt_fixup_ethernet(blob);
diff --git a/include/common.h b/include/common.h
index cbd3c9e..700b015 100644
--- a/include/common.h
+++ b/include/common.h
@@ -326,14 +326,14 @@ int arch_early_init_r(void);
void board_show_dram(ulong size);
/**
- * arch_fixup_memory_node() - Write arch-specific memory information to fdt
+ * arch_fixup_fdt() - Write arch-specific information to fdt
*
- * Defined in arch/$(ARCH)/lib/bootm.c
+ * Defined in arch/$(ARCH)/lib/bootm-fdt.c
*
* @blob: FDT blob to write to
* @return 0 if ok, or -ve FDT_ERR_... on failure
*/
-int arch_fixup_memory_node(void *blob);
+int arch_fixup_fdt(void *blob);
/* common/flash.c */
void flash_perror (int);
--
1.9.0

View File

@ -0,0 +1,187 @@
From 010232aa443377cc848cd60fc55cf53d2db4b286 Mon Sep 17 00:00:00 2001
From: Marc Zyngier <marc.zyngier@arm.com>
Date: Sat, 26 Apr 2014 13:17:11 +0100
Subject: [PATCH 36/36] ARM: HYP/non-sec/PSCI: emit DT nodes
Generate the PSCI node in the device tree.
Also add a reserve section for the "secure" code that lives in
in normal RAM, so that the kernel knows it'd better not trip on
it.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/cpu/armv7/Makefile | 1 +
arch/arm/cpu/armv7/virt-dt.c | 100 +++++++++++++++++++++++++++++++++++++++++++
arch/arm/include/asm/armv7.h | 1 +
arch/arm/lib/bootm-fdt.c | 12 +++++-
4 files changed, 112 insertions(+), 2 deletions(-)
create mode 100644 arch/arm/cpu/armv7/virt-dt.c
diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile
index da5ce22..ea7b9a5 100644
--- a/arch/arm/cpu/armv7/Makefile
+++ b/arch/arm/cpu/armv7/Makefile
@@ -21,6 +21,7 @@ endif
ifneq ($(CONFIG_ARMV7_NONSEC)$(CONFIG_ARMV7_VIRT),)
obj-y += nonsec_virt.o
obj-y += virt-v7.o
+obj-y += virt-dt.o
endif
ifneq ($(CONFIG_ARMV7_PSCI),)
diff --git a/arch/arm/cpu/armv7/virt-dt.c b/arch/arm/cpu/armv7/virt-dt.c
new file mode 100644
index 0000000..0b0d6a7
--- /dev/null
+++ b/arch/arm/cpu/armv7/virt-dt.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2013 - ARM Ltd
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <common.h>
+#include <stdio_dev.h>
+#include <linux/ctype.h>
+#include <linux/types.h>
+#include <asm/global_data.h>
+#include <libfdt.h>
+#include <fdt_support.h>
+#include <asm/armv7.h>
+#include <asm/psci.h>
+
+static int fdt_psci(void *fdt)
+{
+#ifdef CONFIG_ARMV7_PSCI
+ int nodeoff;
+ int tmp;
+
+ nodeoff = fdt_path_offset(fdt, "/cpus");
+ if (nodeoff < 0) {
+ printf("couldn't find /cpus\n");
+ return nodeoff;
+ }
+
+ /* add 'enable-method = "psci"' to each cpu node */
+ for (tmp = fdt_first_subnode(fdt, nodeoff);
+ tmp >= 0;
+ tmp = fdt_next_subnode(fdt, tmp)) {
+ const struct fdt_property *prop;
+ int len;
+
+ prop = fdt_get_property(fdt, tmp, "device_type", &len);
+ if (!prop)
+ continue;
+ if (len < 4)
+ continue;
+ if (strcmp(prop->data, "cpu"))
+ continue;
+
+ fdt_setprop_string(fdt, tmp, "enable-method", "psci");
+ }
+
+ nodeoff = fdt_path_offset(fdt, "/psci");
+ if (nodeoff < 0) {
+ nodeoff = fdt_path_offset(fdt, "/");
+ if (nodeoff < 0)
+ return nodeoff;
+
+ nodeoff = fdt_add_subnode(fdt, nodeoff, "psci");
+ if (nodeoff < 0)
+ return nodeoff;
+ }
+
+ tmp = fdt_setprop_string(fdt, nodeoff, "compatible", "arm,psci");
+ if (tmp)
+ return tmp;
+ tmp = fdt_setprop_string(fdt, nodeoff, "method", "smc");
+ if (tmp)
+ return tmp;
+ tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_suspend", ARM_PSCI_FN_CPU_SUSPEND);
+ if (tmp)
+ return tmp;
+ tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_off", ARM_PSCI_FN_CPU_OFF);
+ if (tmp)
+ return tmp;
+ tmp = fdt_setprop_u32(fdt, nodeoff, "cpu_on", ARM_PSCI_FN_CPU_ON);
+ if (tmp)
+ return tmp;
+ tmp = fdt_setprop_u32(fdt, nodeoff, "migrate", ARM_PSCI_FN_MIGRATE);
+ if (tmp)
+ return tmp;
+#endif
+ return 0;
+}
+
+int armv7_update_dt(void *fdt)
+{
+#ifndef CONFIG_ARMV7_SECURE_BASE
+ /* secure code lives in RAM, keep it alive */
+ fdt_add_mem_rsv(fdt, (unsigned long)__secure_start,
+ __secure_end - __secure_start);
+#endif
+
+ return fdt_psci(fdt);
+}
diff --git a/arch/arm/include/asm/armv7.h b/arch/arm/include/asm/armv7.h
index 11476dd..323f282 100644
--- a/arch/arm/include/asm/armv7.h
+++ b/arch/arm/include/asm/armv7.h
@@ -79,6 +79,7 @@ void v7_outer_cache_inval_range(u32 start, u32 end);
#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT)
int armv7_init_nonsec(void);
+int armv7_update_dt(void *fdt);
/* defined in assembly file */
unsigned int _nonsec_init(void);
diff --git a/arch/arm/lib/bootm-fdt.c b/arch/arm/lib/bootm-fdt.c
index 8394e15..d4f1578 100644
--- a/arch/arm/lib/bootm-fdt.c
+++ b/arch/arm/lib/bootm-fdt.c
@@ -17,13 +17,14 @@
#include <common.h>
#include <fdt_support.h>
+#include <asm/armv7.h>
DECLARE_GLOBAL_DATA_PTR;
int arch_fixup_fdt(void *blob)
{
bd_t *bd = gd->bd;
- int bank;
+ int bank, ret;
u64 start[CONFIG_NR_DRAM_BANKS];
u64 size[CONFIG_NR_DRAM_BANKS];
@@ -32,5 +33,12 @@ int arch_fixup_fdt(void *blob)
size[bank] = bd->bi_dram[bank].size;
}
- return fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS);
+ ret = fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS);
+#if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT)
+ if (ret)
+ return ret;
+
+ ret = armv7_update_dt(blob);
+#endif
+ return ret;
}
--
1.9.0

View File

@ -0,0 +1,68 @@
From fb578a53288ecf8b0d9bbc5ebfbaead6f5b9a5e9 Mon Sep 17 00:00:00 2001
From: Dennis Gilmore <dennis@ausil.us>
Date: Sat, 26 Apr 2014 10:50:14 -0500
Subject: [PATCH 37/37] PXE: syslinux implenets some keywords found in configs
we do not support
distros write out extlinux.conf files and documentation lists pxe config
options we do not support. today the user gets ugly messages like:
Ignoring unknown command: ui
Ignoring malformed menu command: autoboot
Ignoring malformed menu command: hidden
Ignoring unknown command: totaltimeout
instead fo printing the messages for known but unsupported options lets
silently pass over them.
---
common/cmd_pxe.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c
index eb5f9c3..18e140d 100644
--- a/common/cmd_pxe.c
+++ b/common/cmd_pxe.c
@@ -825,7 +825,8 @@ enum token_type {
T_FDTDIR,
T_ONTIMEOUT,
T_IPAPPEND,
- T_INVALID
+ T_INVALID,
+ T_UNIMPLEMENTED
};
/*
@@ -858,6 +859,10 @@ static const struct token keywords[] = {
{"fdtdir", T_FDTDIR},
{"ontimeout", T_ONTIMEOUT,},
{"ipappend", T_IPAPPEND,},
+ {"ui", T_UNIMPLEMENTED},
+ {"autoboot", T_UNIMPLEMENTED},
+ {"hidden", T_UNIMPLEMENTED},
+ {"totaltimeout", T_UNIMPLEMENTED},
{NULL, T_INVALID}
};
@@ -1127,6 +1132,9 @@ static int parse_menu(cmd_tbl_t *cmdtp, char **c, struct pxe_menu *cfg, char *b,
nest_level + 1);
break;
+ case T_UNIMPLEMENTED:
+ break;
+
default:
printf("Ignoring malformed menu command: %.*s\n",
(int)(*c - s), s);
@@ -1351,6 +1359,9 @@ static int parse_pxefile_top(cmd_tbl_t *cmdtp, char *p, struct pxe_menu *cfg, in
case T_EOF:
return 1;
+ case T_UNIMPLEMENTED:
+ break;
+
default:
printf("Ignoring unknown command: %.*s\n",
(int)(p - s), s);
--
1.9.0

View File

@ -0,0 +1,38 @@
From abc7809628fb201f32da2069158305540b64e5c8 Mon Sep 17 00:00:00 2001
From: Dennis Gilmore <dennis@ausil.us>
Date: Sat, 26 Apr 2014 10:57:05 -0500
Subject: [PATCH 38/38] PXE: distros implementing syslinux will be using raw
kernels and initramfs
Since we are not detecting if the image is raw or wrapped and we expect
distros to be using raw images attempt bootz before bootm. This prevents
the user from getting a confusing error message:
Wrong Image Format for sysboot command
ERROR: can't get kernel image!
---
common/cmd_pxe.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c
index 18e140d..250243a 100644
--- a/common/cmd_pxe.c
+++ b/common/cmd_pxe.c
@@ -793,12 +793,12 @@ static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
if (bootm_argv[3])
bootm_argc = 4;
- do_bootm(cmdtp, 0, bootm_argc, bootm_argv);
-
#ifdef CONFIG_CMD_BOOTZ
/* Try booting a zImage if do_bootm returns */
do_bootz(cmdtp, 0, bootm_argc, bootm_argv);
#endif
+
+ do_bootm(cmdtp, 0, bootm_argc, bootm_argv);
return 1;
}
--
1.9.0

View File

@ -2,7 +2,7 @@
Name: uboot-tools
Version: 2014.04
Release: 2%{?candidate:.%{candidate}}%{?dist}
Release: 3%{?candidate:.%{candidate}}%{?dist}
Summary: U-Boot utilities
Group: Development/Tools
@ -29,6 +29,27 @@ Patch23: 0014-add-to-ti_armv7_common.h-generic-distro-environment-.patch
Patch24: 0015-omap4-buildfixes.patch
Patch25: 0016-automatically-add-console-to-bootline-when-not-exist.patch
Patch26: 0017-make-bootdelay-match-the-generic-distro-default.patch
Patch27: 0018-sunxi-add-sun7i-clocks-and-timer-support.patch
Patch28: 0019-sunxi-add-sun7i-pinmux-and-gpio-support.patch
Patch29: 0020-sunxi-add-sun7i-dram-setup-support.patch
Patch30: 0021-sunxi-add-sun7i-cpu-board-and-start-of-day-support.patch
Patch31: 0022-sunxi-add-support-for-Cubietruck-booting-in-FEL-mode.patch
Patch32: 0023-sunxi-add-gmac-Ethernet-support.patch
Patch33: 0024-sunxi-mmc-support.patch
Patch34: 0025-sunxi-non-FEL-SPL-boot-support-for-sun7i.patch
Patch35: 0026-port-over-to-generic-bootcommands.patch
Patch36: 0027-ARM-HYP-non-sec-move-switch-to-non-sec-to-the-last-b.patch
Patch37: 0028-ARM-HYP-non-sec-add-a-barrier-after-setting-SCR.NS-1.patch
Patch38: 0029-ARM-non-sec-reset-CNTVOFF-to-zero.patch
Patch39: 0030-ARM-add-missing-HYP-mode-constant.patch
Patch40: 0031-ARM-HYP-non-sec-add-separate-section-for-secure-code.patch
Patch41: 0032-ARM-HYP-non-sec-allow-relocation-to-secure-RAM.patch
Patch42: 0033-ARM-HYP-non-sec-add-generic-ARMv7-PSCI-code.patch
Patch43: 0034-ARM-HYP-non-sec-add-the-option-for-a-second-stage-mo.patch
Patch44: 0035-ARM-convert-arch_fixup_memory_node-to-a-generic-FDT-.patch
Patch45: 0036-ARM-HYP-non-sec-PSCI-emit-DT-nodes.patch
Patch46: 0037-PXE-syslinux-implenets-some-keywords-found-in-config.patch
Patch47: 0038-PXE-distros-implementing-syslinux-will-be-using-raw-.patch
%ifnarch %{arm}
BuildRequires: gcc-arm-linux-gnu
@ -112,6 +133,27 @@ u-boot bootloader binaries for armv7 boards
%patch24 -p1
%patch25 -p1
%patch26 -p1
%patch27 -p1
%patch28 -p1
%patch29 -p1
%patch30 -p1
%patch31 -p1
%patch32 -p1
%patch33 -p1
%patch34 -p1
%patch35 -p1
%patch36 -p1
%patch37 -p1
%patch38 -p1
%patch39 -p1
%patch40 -p1
%patch41 -p1
%patch42 -p1
%patch43 -p1
%patch44 -p1
%patch45 -p1
%patch46 -p1
%patch47 -p1
mkdir builds
# convert fedora logo to bmp for use in u-boot
@ -151,6 +193,11 @@ cp -p spl/arndale-spl.bin builds/arndale-spl.bin.arndale
cp -p u-boot-dtb.bin builds/u-boot-dtb.bin.arndale
make mrproper
make Cubietruck_config
make HOSTCC="gcc $RPM_OPT_FLAGS" CROSS_COMPILE="" %{?_smp_mflags}
cp -p u-boot-sunxi-with-spl.bin builds/u-boot-sunxi-with-spl.bin.Cubietruck
make mrproper
make highbank_config
make HOSTCC="gcc $RPM_OPT_FLAGS" CROSS_COMPILE="" %{?_smp_mflags}
cp -p u-boot.bin builds/u-boot.bin.highbank
@ -256,6 +303,7 @@ mkdir -p $RPM_BUILD_ROOT%{_datadir}/uboot/
mkdir -p $RPM_BUILD_ROOT%{_datadir}/uboot/arndale/
mkdir -p $RPM_BUILD_ROOT%{_datadir}/uboot/beagle/
mkdir -p $RPM_BUILD_ROOT%{_datadir}/uboot/beaglebone/
mkdir -p $RPM_BUILD_ROOT%{_datadir}/uboot/Cubietruck/
mkdir -p $RPM_BUILD_ROOT%{_datadir}/uboot/highbank/
mkdir -p $RPM_BUILD_ROOT%{_datadir}/uboot/origen/
mkdir -p $RPM_BUILD_ROOT%{_datadir}/uboot/panda/
@ -288,6 +336,8 @@ done
install -p -m 0644 builds/arndale-spl.bin.arndale $RPM_BUILD_ROOT%{_datadir}/uboot/arndale/arndale-spl.bin
install -p -m 0644 builds/u-boot-dtb.bin.arndale $RPM_BUILD_ROOT%{_datadir}/uboot/arndale/u-boot-dtb.bin
install -p -m 0644 builds/u-boot-sunxi-with-spl.bin.Cubietruck $RPM_BUILD_ROOT%{_datadir}/uboot/Cubietruck/u-boot-sunxi-with-spl.bin
install -p -m 0644 builds/u-boot.bin.highbank $RPM_BUILD_ROOT%{_datadir}/uboot/highbank/u-boot.bin
install -p -m 0644 builds/origen-spl.bin.origen $RPM_BUILD_ROOT%{_datadir}/uboot/origen/origen-spl.bin
@ -343,6 +393,7 @@ rm -rf $RPM_BUILD_ROOT
%{_datadir}/uboot/arndale/
%{_datadir}/uboot/beaglebone/
%{_datadir}/uboot/beagle/
%{_datadir}/uboot/Cubietruck/
%{_datadir}/uboot/highbank/
%{_datadir}/uboot/panda/
%{_datadir}/uboot/paz00/
@ -359,6 +410,9 @@ rm -rf $RPM_BUILD_ROOT
%endif
%changelog
* Thu Apr 24 2014 Dennis Gilmore <dennis@ausil.us> - 2014.04-3
- add cubietruck u-boot image
* Wed Apr 23 2014 Dennis Gilmore <dennis@ausil.us> - 2014.04-2
- automatically add console line from u-boot environment to bootargs
- when there is no console argument in the extlinux.conf file