[uboot-tools] add cubietruck u-boot image

Dennis Gilmore ausil at fedoraproject.org
Sun Apr 27 02:50:00 UTC 2014


commit 1619496436087ded318042cbc8c1a5b0513c2b7f
Author: Dennis Gilmore <dennis at ausil.us>
Date:   Sat Apr 26 21:49:55 2014 -0500

    add cubietruck u-boot image

 ...a-DEFAULT_LINUX_BOOT_ENV-environment-stri.patch |    4 +-
 ...Update-the-ramdisk-args-we-pass-things-in.patch |    4 +-
 ...Update-the-ramdisk-args-we-pass-things-in.patch |    4 +-
 ...ditionaly-check-for-fdt_file-env-variable.patch |    4 +-
 ...convert-snowball-to-distro-generic-config.patch |    4 +-
 ...ard-over-to-use-the-generic-distro-config.patch |    4 +-
 ...ver-to-use-the-generic-distro-configuatio.patch |    4 +-
 ...oard-over-to-use-the-generic-distro-confi.patch |    4 +-
 ...bone-over-to-use-the-generic-distro-confi.patch |    4 +-
 ...with-a-generic-set-of-boot-commands-defin.patch |    6 +-
 0011-add-README.distro-file.patch                  |    4 +-
 ...cleanup-duplicate-options-in-paz00-config.patch |    4 +-
 ...-hackish-utilite-build-based-on-wandboard.patch |    4 +-
 ...rmv7_common.h-generic-distro-environment-.patch |    4 +-
 0015-omap4-buildfixes.patch                        |    4 +-
 ...ly-add-console-to-bootline-when-not-exist.patch |    4 +-
 ...ootdelay-match-the-generic-distro-default.patch |    4 +-
 ...-sunxi-add-sun7i-clocks-and-timer-support.patch |  818 ++++++++++++++++++++
 0019-sunxi-add-sun7i-pinmux-and-gpio-support.patch |  262 +++++++
 0020-sunxi-add-sun7i-dram-setup-support.patch      |  786 +++++++++++++++++++
 ...-sun7i-cpu-board-and-start-of-day-support.patch |  713 +++++++++++++++++
 ...upport-for-Cubietruck-booting-in-FEL-mode.patch |   77 ++
 0023-sunxi-add-gmac-Ethernet-support.patch         |  168 ++++
 0024-sunxi-mmc-support.patch                       |  797 +++++++++++++++++++
 ...-sunxi-non-FEL-SPL-boot-support-for-sun7i.patch |  409 ++++++++++
 0026-port-over-to-generic-bootcommands.patch       |   53 ++
 ...-sec-move-switch-to-non-sec-to-the-last-b.patch |   44 ++
 ...-sec-add-a-barrier-after-setting-SCR.NS-1.patch |   28 +
 0029-ARM-non-sec-reset-CNTVOFF-to-zero.patch       |   50 ++
 0030-ARM-add-missing-HYP-mode-constant.patch       |   53 ++
 ...-sec-add-separate-section-for-secure-code.patch |   93 +++
 ...YP-non-sec-allow-relocation-to-secure-RAM.patch |  499 ++++++++++++
 ...M-HYP-non-sec-add-generic-ARMv7-PSCI-code.patch |  185 +++++
 ...-sec-add-the-option-for-a-second-stage-mo.patch |   47 ++
 ...-arch_fixup_memory_node-to-a-generic-FDT-.patch |   97 +++
 0036-ARM-HYP-non-sec-PSCI-emit-DT-nodes.patch      |  187 +++++
 ...x-implenets-some-keywords-found-in-config.patch |   68 ++
 ...-implementing-syslinux-will-be-using-raw-.patch |   38 +
 uboot-tools.spec                                   |   56 ++-
 39 files changed, 5562 insertions(+), 36 deletions(-)
---
diff --git a/0001-TI-Add-use-a-DEFAULT_LINUX_BOOT_ENV-environment-stri.patch b/0001-TI-Add-use-a-DEFAULT_LINUX_BOOT_ENV-environment-stri.patch
index 36980b1..e9d7f02 100644
--- a/0001-TI-Add-use-a-DEFAULT_LINUX_BOOT_ENV-environment-stri.patch
+++ b/0001-TI-Add-use-a-DEFAULT_LINUX_BOOT_ENV-environment-stri.patch
@@ -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 at 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
diff --git a/0002-am335x_evm-Update-the-ramdisk-args-we-pass-things-in.patch b/0002-am335x_evm-Update-the-ramdisk-args-we-pass-things-in.patch
index f275400..204d442 100644
--- a/0002-am335x_evm-Update-the-ramdisk-args-we-pass-things-in.patch
+++ b/0002-am335x_evm-Update-the-ramdisk-args-we-pass-things-in.patch
@@ -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 at 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 at ti.com>
diff --git a/0003-am43xx_evm-Update-the-ramdisk-args-we-pass-things-in.patch b/0003-am43xx_evm-Update-the-ramdisk-args-we-pass-things-in.patch
index 086aafd..a3aa7be 100644
--- a/0003-am43xx_evm-Update-the-ramdisk-args-we-pass-things-in.patch
+++ b/0003-am43xx_evm-Update-the-ramdisk-args-we-pass-things-in.patch
@@ -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 at 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 at ti.com>
diff --git a/0004-pxe-additionaly-check-for-fdt_file-env-variable.patch b/0004-pxe-additionaly-check-for-fdt_file-env-variable.patch
index 91c68b5..943683c 100644
--- a/0004-pxe-additionaly-check-for-fdt_file-env-variable.patch
+++ b/0004-pxe-additionaly-check-for-fdt_file-env-variable.patch
@@ -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 at 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
diff --git a/0005-convert-snowball-to-distro-generic-config.patch b/0005-convert-snowball-to-distro-generic-config.patch
index 5948baf..1181b70 100644
--- a/0005-convert-snowball-to-distro-generic-config.patch
+++ b/0005-convert-snowball-to-distro-generic-config.patch
@@ -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 at 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 +++++++++-------------------------------------
diff --git a/0006-move-wandboard-over-to-use-the-generic-distro-config.patch b/0006-move-wandboard-over-to-use-the-generic-distro-config.patch
index 15f016f..678a995 100644
--- a/0006-move-wandboard-over-to-use-the-generic-distro-config.patch
+++ b/0006-move-wandboard-over-to-use-the-generic-distro-config.patch
@@ -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 at 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.
diff --git a/0007-move-udoo-over-to-use-the-generic-distro-configuatio.patch b/0007-move-udoo-over-to-use-the-generic-distro-configuatio.patch
index ae94722..120a3f8 100644
--- a/0007-move-udoo-over-to-use-the-generic-distro-configuatio.patch
+++ b/0007-move-udoo-over-to-use-the-generic-distro-configuatio.patch
@@ -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 at 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.
diff --git a/0008-move-pandaboard-over-to-use-the-generic-distro-confi.patch b/0008-move-pandaboard-over-to-use-the-generic-distro-confi.patch
index 02dc899..0c12a07 100644
--- a/0008-move-pandaboard-over-to-use-the-generic-distro-confi.patch
+++ b/0008-move-pandaboard-over-to-use-the-generic-distro-confi.patch
@@ -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 at 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.
diff --git a/0009-move-beaglebone-over-to-use-the-generic-distro-confi.patch b/0009-move-beaglebone-over-to-use-the-generic-distro-confi.patch
index 49ff099..3411b7b 100644
--- a/0009-move-beaglebone-over-to-use-the-generic-distro-confi.patch
+++ b/0009-move-beaglebone-over-to-use-the-generic-distro-confi.patch
@@ -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 at 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.
diff --git a/0010-add-header-with-a-generic-set-of-boot-commands-defin.patch b/0010-add-header-with-a-generic-set-of-boot-commands-defin.patch
index d977d56..f43f86e 100644
--- a/0010-add-header-with-a-generic-set-of-boot-commands-defin.patch
+++ b/0010-add-header-with-a-generic-set-of-boot-commands-defin.patch
@@ -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 at 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 @@
diff --git a/0011-add-README.distro-file.patch b/0011-add-README.distro-file.patch
index a7bdfa0..1be782b 100644
--- a/0011-add-README.distro-file.patch
+++ b/0011-add-README.distro-file.patch
@@ -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 at 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
diff --git a/0012-cleanup-duplicate-options-in-paz00-config.patch b/0012-cleanup-duplicate-options-in-paz00-config.patch
index 957ac15..13432fa 100644
--- a/0012-cleanup-duplicate-options-in-paz00-config.patch
+++ b/0012-cleanup-duplicate-options-in-paz00-config.patch
@@ -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 at 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 --
diff --git a/0013-add-hackish-utilite-build-based-on-wandboard.patch b/0013-add-hackish-utilite-build-based-on-wandboard.patch
index 79ed7ad..c2e85b9 100644
--- a/0013-add-hackish-utilite-build-based-on-wandboard.patch
+++ b/0013-add-hackish-utilite-build-based-on-wandboard.patch
@@ -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 at 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 +
diff --git a/0014-add-to-ti_armv7_common.h-generic-distro-environment-.patch b/0014-add-to-ti_armv7_common.h-generic-distro-environment-.patch
index d7af853..57eddc3 100644
--- a/0014-add-to-ti_armv7_common.h-generic-distro-environment-.patch
+++ b/0014-add-to-ti_armv7_common.h-generic-distro-environment-.patch
@@ -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 at 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
diff --git a/0015-omap4-buildfixes.patch b/0015-omap4-buildfixes.patch
index 315967e..8125bb4 100644
--- a/0015-omap4-buildfixes.patch
+++ b/0015-omap4-buildfixes.patch
@@ -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 at 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 ----
diff --git a/0016-automatically-add-console-to-bootline-when-not-exist.patch b/0016-automatically-add-console-to-bootline-when-not-exist.patch
index 1a77976..00b2360 100644
--- a/0016-automatically-add-console-to-bootline-when-not-exist.patch
+++ b/0016-automatically-add-console-to-bootline-when-not-exist.patch
@@ -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 at 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
diff --git a/0017-make-bootdelay-match-the-generic-distro-default.patch b/0017-make-bootdelay-match-the-generic-distro-default.patch
index 40842d7..71184bb 100644
--- a/0017-make-bootdelay-match-the-generic-distro-default.patch
+++ b/0017-make-bootdelay-match-the-generic-distro-default.patch
@@ -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 at 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 +-
diff --git a/0018-sunxi-add-sun7i-clocks-and-timer-support.patch b/0018-sunxi-add-sun7i-clocks-and-timer-support.patch
new file mode 100644
index 0000000..a338091
--- /dev/null
+++ b/0018-sunxi-add-sun7i-clocks-and-timer-support.patch
@@ -0,0 +1,818 @@
+From 5ada9882f4e92cb978cd8d06c6dd3410c92e1f33 Mon Sep 17 00:00:00 2001
+From: Ian Campbell <ijc at 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 at gmail.com>
+Signed-off-by: Chen-Yu Tsai <wens at csie.org>
+Signed-off-by: Emilio López <emilio at elopez.com.ar>
+Signed-off-by: Hans de Goede <hdegoede at redhat.com>
+Signed-off-by: Henrik Nordstrom <henrik at henriknordstrom.net>
+Signed-off-by: Jens Kuske <jenskuske at gmail.com>
+Signed-off-by: Luke Leighton <lkcl at lkcl.net>
+Signed-off-by: Oliver Schinagl <oliver at schinagl.nl>
+Signed-off-by: Ian Campbell <ijc at hellion.org.uk>
+Cc: Stefan Roese <sr at denx.de>
+Cc: Tom Cubie <Mr.hipboi at 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 at henriknordstrom.net>
++#
++# Based on some other Makefile
++# (C) Copyright 2000-2003
++# Wolfgang Denk, DENX Software Engineering, wd at 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 at allwinnertech.com>
++ *
++ * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl at 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 at allwinnertech.com>
++ *
++ * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl at 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 at 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 at 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 at 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 at 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 at 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
+
diff --git a/0019-sunxi-add-sun7i-pinmux-and-gpio-support.patch b/0019-sunxi-add-sun7i-pinmux-and-gpio-support.patch
new file mode 100644
index 0000000..703dc58
--- /dev/null
+++ b/0019-sunxi-add-sun7i-pinmux-and-gpio-support.patch
@@ -0,0 +1,262 @@
+From 98fdf764f9eb70fb312ebeeab903ad438783c3ba Mon Sep 17 00:00:00 2001
+From: Ian Campbell <ijc at 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 at csie.org>
+Signed-off-by: Hans de Goede <hdegoede at redhat.com>
+Signed-off-by: Ma Haijun <mahaijuns at gmail.com>
+Signed-off-by: Oliver Schinagl <oliver at schinagl.nl>
+Signed-off-by: Henrik Nordström <henrik at henriknordstrom.net>
+Signed-off-by: Ian Campbell <ijc at hellion.org.uk>
+Reviewed-by: Tom Rini <trini at ti.com>
+Cc: Stefan Roese <sr at denx.de>
+Cc: Tom Cubie <Mr.hipboi at 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 at 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 at 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
+
diff --git a/0020-sunxi-add-sun7i-dram-setup-support.patch b/0020-sunxi-add-sun7i-dram-setup-support.patch
new file mode 100644
index 0000000..97dd37c
--- /dev/null
+++ b/0020-sunxi-add-sun7i-dram-setup-support.patch
@@ -0,0 +1,786 @@
+From 515037543e7270b853bb6c6170257a30df91eb37 Mon Sep 17 00:00:00 2001
+From: Ian Campbell <ijc at 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 at gmail.com>
+Signed-off-by: Emilio López <emilio at elopez.com.ar>
+Signed-off-by: Hans de Goede <hdegoede at redhat.com>
+Signed-off-by: Henrik Nordstrom <henrik at henriknordstrom.net>
+Signed-off-by: Jens Kuske <jenskuske at gmail.com>
+Signed-off-by: Luke Leighton <lkcl at lkcl.net>
+Signed-off-by: Oliver Schinagl <oliver at schinagl.nl>
+Signed-off-by: Stefan Roese <sr at denx.de>
+Signed-off-by: Ian Campbell <ijc at hellion.org.uk>
+Cc: Tom Cubie <Mr.hipboi at 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 at henriknordstrom.net>
++ * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl at 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 at allwinnertech.com>
++ * Tom Cubie <tangliang at 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 at allwinnertech.com>
++ * Tom Cubie <tangliang at 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
+
diff --git a/0021-sunxi-add-sun7i-cpu-board-and-start-of-day-support.patch b/0021-sunxi-add-sun7i-cpu-board-and-start-of-day-support.patch
new file mode 100644
index 0000000..5705d65
--- /dev/null
+++ b/0021-sunxi-add-sun7i-cpu-board-and-start-of-day-support.patch
@@ -0,0 +1,713 @@
+From 785ba593d5fa67ed2997ce937cafd5286459beaf Mon Sep 17 00:00:00 2001
+From: Ian Campbell <ijc at 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 at offog.org>
+Signed-off-by: Aleksei Mamlin <mamlinav at gmail.com>
+Signed-off-by: Alexandru Gagniuc <mr.nuke.me at gmail.com>
+Signed-off-by: Chen-Yu Tsai <wens at csie.org>
+Signed-off-by: Emilio López <emilio at elopez.com.ar>
+Signed-off-by: Hans de Goede <hdegoede at redhat.com>
+Signed-off-by: Henrik Nordstrom <henrik at henriknordstrom.net>
+Signed-off-by: Jens Kuske <jenskuske at gmail.com>
+Signed-off-by: Luc Verhaegen <libv at skynet.be>
+Signed-off-by: Luke Leighton <lkcl at lkcl.net>
+Signed-off-by: Oliver Schinagl <oliver at schinagl.nl>
+Signed-off-by: Patrick Wood <patrickhwood at gmail.com>
+Signed-off-by: Stefan Roese <sr at denx.de>
+Signed-off-by: Wills Wang <wills.wang.open at gmail.com>
+Signed-off-by: Ian Campbell <ijc at hellion.org.uk>
+Cc: Tom Cubie <Mr.hipboi at 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 at henriknordstrom.net>
++ *
++ * (C) Copyright 2007-2011
++ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
++ * Tom Cubie <tangliang at 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 at 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 at 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 at 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 at henriknordstrom.net>
++#
++# Based on some other board Makefile
++#
++# (C) Copyright 2000-2003
++# Wolfgang Denk, DENX Software Engineering, wd at 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 at henriknordstrom.net>
++ * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl at lkcl.net>
++ *
++ * (C) Copyright 2007-2011
++ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
++ * Tom Cubie <tangliang at 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 at henriknordstrom.net>
++ * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl at 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 at henriknordstrom.net>
++ *
++ * (C) Copyright 2007-2011
++ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
++ * Tom Cubie <tangliang at 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
+
diff --git a/0022-sunxi-add-support-for-Cubietruck-booting-in-FEL-mode.patch b/0022-sunxi-add-support-for-Cubietruck-booting-in-FEL-mode.patch
new file mode 100644
index 0000000..39c1cdc
--- /dev/null
+++ b/0022-sunxi-add-support-for-Cubietruck-booting-in-FEL-mode.patch
@@ -0,0 +1,77 @@
+From b2c413d8119dbbef34189e9beb84a0b2a00fa86d Mon Sep 17 00:00:00 2001
+From: Ian Campbell <ijc at 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 at schinagl.nl>
+Signed-off-by: Jens Kuske <jenskuske at gmail.com>
+Signed-off-by: Ian Campbell <ijc at hellion.org.uk>
+Reviewed-by: Tom Rini <trini at 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 at samsung.com>
+ Active  arm         armv7          s5pc1xx     samsung         smdkc100            smdkc100                             -                                                                                                                                 Minkyu Kang <mk7.kang at 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 at 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 at freescale.com>
+-- 
+1.9.0
+
diff --git a/0023-sunxi-add-gmac-Ethernet-support.patch b/0023-sunxi-add-gmac-Ethernet-support.patch
new file mode 100644
index 0000000..df7fbbe
--- /dev/null
+++ b/0023-sunxi-add-gmac-Ethernet-support.patch
@@ -0,0 +1,168 @@
+From 4b39387594767ac865caa8710d1be39e869926e3 Mon Sep 17 00:00:00 2001
+From: Ian Campbell <ijc at 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 at csie.org>
+Signed-off-by: Jens Kuske <jenskuske at gmail.com>
+Signed-off-by: Ian Campbell <ijc at 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 at samsung.com>
+ Active  arm         armv7          s5pc1xx     samsung         smdkc100            smdkc100                             -                                                                                                                                 Minkyu Kang <mk7.kang at 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 at 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 at 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
+
diff --git a/0024-sunxi-mmc-support.patch b/0024-sunxi-mmc-support.patch
new file mode 100644
index 0000000..a10326b
--- /dev/null
+++ b/0024-sunxi-mmc-support.patch
@@ -0,0 +1,797 @@
+From ec8c2c931fda9e06eee7203c72025f6ecd25ef7f Mon Sep 17 00:00:00 2001
+From: Ian Campbell <ijc at 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 at henriknordstrom.net>
+Signed-off-by: Luke Leighton <lkcl at lkcl.net>
+Signed-off-by: Oliver Schinagl <oliver at schinagl.nl>
+Signed-off-by: Wills Wang <wills.wang.open at gmail.com>
+Signed-off-by: Ian Campbell <ijc at hellion.org.uk>
+Cc: Stefan Roese <sr at denx.de>
+Cc: Tom Cubie <Mr.hipboi at gmail.com>
+Cc: Aaron Maoye <leafy.myeh at allwinnertech.com>
+Cc: Pantelis Antoniou <panto at 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 at 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 at 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
+
diff --git a/0025-sunxi-non-FEL-SPL-boot-support-for-sun7i.patch b/0025-sunxi-non-FEL-SPL-boot-support-for-sun7i.patch
new file mode 100644
index 0000000..6982ca6
--- /dev/null
+++ b/0025-sunxi-non-FEL-SPL-boot-support-for-sun7i.patch
@@ -0,0 +1,409 @@
+From 432b9a0f1fcd3ebff235755b9f26d996f36ce946 Mon Sep 17 00:00:00 2001
+From: Ian Campbell <ijc at 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 at denx.de>
+Signed-off-by: Henrik Nordström <henrik at henriknordstrom.net>
+Signed-off-by: Ian Campbell <ijc at hellion.org.uk>
+Cc: Tom Cubie <Mr.hipboi at 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 at allwinnertech.com>
++ *
++ * Based on omap-common/u-boot-spl.lds:
++ *
++ * (C) Copyright 2002
++ * Gary Jennejohn, DENX Software Engineering, <garyj at denx.de>
++ *
++ * (C) Copyright 2010
++ * Texas Instruments, <www.ti.com>
++ *	Aneesh V <aneesh at 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 at samsung.com>
+ Active  arm         armv7          s5pc1xx     samsung         smdkc100            smdkc100                             -                                                                                                                                 Minkyu Kang <mk7.kang at 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 at 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 at 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
+
diff --git a/0026-port-over-to-generic-bootcommands.patch b/0026-port-over-to-generic-bootcommands.patch
new file mode 100644
index 0000000..63fc14e
--- /dev/null
+++ b/0026-port-over-to-generic-bootcommands.patch
@@ -0,0 +1,53 @@
+From f66618b23bc59f2a6374edd2611e88838dc6e854 Mon Sep 17 00:00:00 2001
+From: Dennis Gilmore <dennis at 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
+
diff --git a/0027-ARM-HYP-non-sec-move-switch-to-non-sec-to-the-last-b.patch b/0027-ARM-HYP-non-sec-move-switch-to-non-sec-to-the-last-b.patch
new file mode 100644
index 0000000..daae610
--- /dev/null
+++ b/0027-ARM-HYP-non-sec-move-switch-to-non-sec-to-the-last-b.patch
@@ -0,0 +1,44 @@
+From f2c485bd04fe493ff06255a8be2bd754f6f0f766 Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <marc.zyngier at 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 at 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
+
diff --git a/0028-ARM-HYP-non-sec-add-a-barrier-after-setting-SCR.NS-1.patch b/0028-ARM-HYP-non-sec-add-a-barrier-after-setting-SCR.NS-1.patch
new file mode 100644
index 0000000..f282a7b
--- /dev/null
+++ b/0028-ARM-HYP-non-sec-add-a-barrier-after-setting-SCR.NS-1.patch
@@ -0,0 +1,28 @@
+From ffddd794d834f39e120603d6764d7f25bf24ddc0 Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <marc.zyngier at 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 at 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
+
diff --git a/0029-ARM-non-sec-reset-CNTVOFF-to-zero.patch b/0029-ARM-non-sec-reset-CNTVOFF-to-zero.patch
new file mode 100644
index 0000000..5b129d3
--- /dev/null
+++ b/0029-ARM-non-sec-reset-CNTVOFF-to-zero.patch
@@ -0,0 +1,50 @@
+From 2e19eb7de158a26c335d8820becaf859602dd401 Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <marc.zyngier at 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 at 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
+
diff --git a/0030-ARM-add-missing-HYP-mode-constant.patch b/0030-ARM-add-missing-HYP-mode-constant.patch
new file mode 100644
index 0000000..c60431d
--- /dev/null
+++ b/0030-ARM-add-missing-HYP-mode-constant.patch
@@ -0,0 +1,53 @@
+From eed1c957b6294e0205cc8521516c51dce7bb72c1 Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <marc.zyngier at 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 at 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
+
diff --git a/0031-ARM-HYP-non-sec-add-separate-section-for-secure-code.patch b/0031-ARM-HYP-non-sec-add-separate-section-for-secure-code.patch
new file mode 100644
index 0000000..1dcbcbd
--- /dev/null
+++ b/0031-ARM-HYP-non-sec-add-separate-section-for-secure-code.patch
@@ -0,0 +1,93 @@
+From 4c35371fe7e2ed9e057cd3eb9380380099d0ea19 Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <marc.zyngier at 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 at 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
+
diff --git a/0032-ARM-HYP-non-sec-allow-relocation-to-secure-RAM.patch b/0032-ARM-HYP-non-sec-allow-relocation-to-secure-RAM.patch
new file mode 100644
index 0000000..8eeb663
--- /dev/null
+++ b/0032-ARM-HYP-non-sec-allow-relocation-to-secure-RAM.patch
@@ -0,0 +1,499 @@
+From a32061fdf5a5d582e62293bfa8a5c28911c4209f Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <marc.zyngier at 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 at 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
+
diff --git a/0033-ARM-HYP-non-sec-add-generic-ARMv7-PSCI-code.patch b/0033-ARM-HYP-non-sec-add-generic-ARMv7-PSCI-code.patch
new file mode 100644
index 0000000..a88fea2
--- /dev/null
+++ b/0033-ARM-HYP-non-sec-add-generic-ARMv7-PSCI-code.patch
@@ -0,0 +1,185 @@
+From a1d59cb7f8618db44730dcd0d3fb8708aeb8901d Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <marc.zyngier at 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 at 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 at 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 at 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
+
diff --git a/0034-ARM-HYP-non-sec-add-the-option-for-a-second-stage-mo.patch b/0034-ARM-HYP-non-sec-add-the-option-for-a-second-stage-mo.patch
new file mode 100644
index 0000000..291a570
--- /dev/null
+++ b/0034-ARM-HYP-non-sec-add-the-option-for-a-second-stage-mo.patch
@@ -0,0 +1,47 @@
+From e9b55c2e26b83bffe6dea6ea4be8fbc249bb85d5 Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <marc.zyngier at 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 at 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
+
diff --git a/0035-ARM-convert-arch_fixup_memory_node-to-a-generic-FDT-.patch b/0035-ARM-convert-arch_fixup_memory_node-to-a-generic-FDT-.patch
new file mode 100644
index 0000000..f0c640b
--- /dev/null
+++ b/0035-ARM-convert-arch_fixup_memory_node-to-a-generic-FDT-.patch
@@ -0,0 +1,97 @@
+From 7b63229b282e0be1e1e81da79ad4ee10ab4e1c19 Mon Sep 17 00:00:00 2001
+From: Ma Haijun <mahaijuns at 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 at gmail.com>
+Signed-off-by: Marc Zyngier <marc.zyngier at 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
+
diff --git a/0036-ARM-HYP-non-sec-PSCI-emit-DT-nodes.patch b/0036-ARM-HYP-non-sec-PSCI-emit-DT-nodes.patch
new file mode 100644
index 0000000..ed4a691
--- /dev/null
+++ b/0036-ARM-HYP-non-sec-PSCI-emit-DT-nodes.patch
@@ -0,0 +1,187 @@
+From 010232aa443377cc848cd60fc55cf53d2db4b286 Mon Sep 17 00:00:00 2001
+From: Marc Zyngier <marc.zyngier at 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 at 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 at 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
+
diff --git a/0037-PXE-syslinux-implenets-some-keywords-found-in-config.patch b/0037-PXE-syslinux-implenets-some-keywords-found-in-config.patch
new file mode 100644
index 0000000..35fa43e
--- /dev/null
+++ b/0037-PXE-syslinux-implenets-some-keywords-found-in-config.patch
@@ -0,0 +1,68 @@
+From fb578a53288ecf8b0d9bbc5ebfbaead6f5b9a5e9 Mon Sep 17 00:00:00 2001
+From: Dennis Gilmore <dennis at 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
+
diff --git a/0038-PXE-distros-implementing-syslinux-will-be-using-raw-.patch b/0038-PXE-distros-implementing-syslinux-will-be-using-raw-.patch
new file mode 100644
index 0000000..c217ded
--- /dev/null
+++ b/0038-PXE-distros-implementing-syslinux-will-be-using-raw-.patch
@@ -0,0 +1,38 @@
+From abc7809628fb201f32da2069158305540b64e5c8 Mon Sep 17 00:00:00 2001
+From: Dennis Gilmore <dennis at 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
+
diff --git a/uboot-tools.spec b/uboot-tools.spec
index 633f9bf..abef4e7 100644
--- a/uboot-tools.spec
+++ b/uboot-tools.spec
@@ -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 at ausil.us> - 2014.04-3
+- add cubietruck u-boot image
+
 * Wed Apr 23 2014 Dennis Gilmore <dennis at 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


More information about the scm-commits mailing list