From 1619496436087ded318042cbc8c1a5b0513c2b7f Mon Sep 17 00:00:00 2001 From: Dennis Gilmore Date: Sat, 26 Apr 2014 21:49:55 -0500 Subject: [PATCH] add cubietruck u-boot image --- ...AULT_LINUX_BOOT_ENV-environment-stri.patch | 4 +- ...e-the-ramdisk-args-we-pass-things-in.patch | 4 +- ...e-the-ramdisk-args-we-pass-things-in.patch | 4 +- ...naly-check-for-fdt_file-env-variable.patch | 4 +- ...rt-snowball-to-distro-generic-config.patch | 4 +- ...ver-to-use-the-generic-distro-config.patch | 4 +- ...o-use-the-generic-distro-configuatio.patch | 4 +- ...over-to-use-the-generic-distro-confi.patch | 4 +- ...over-to-use-the-generic-distro-confi.patch | 4 +- ...a-generic-set-of-boot-commands-defin.patch | 6 +- 0011-add-README.distro-file.patch | 4 +- ...up-duplicate-options-in-paz00-config.patch | 4 +- ...ish-utilite-build-based-on-wandboard.patch | 4 +- ...common.h-generic-distro-environment-.patch | 4 +- 0015-omap4-buildfixes.patch | 4 +- ...d-console-to-bootline-when-not-exist.patch | 4 +- ...lay-match-the-generic-distro-default.patch | 4 +- ...i-add-sun7i-clocks-and-timer-support.patch | 818 ++++++++++++++++++ ...xi-add-sun7i-pinmux-and-gpio-support.patch | 262 ++++++ 0020-sunxi-add-sun7i-dram-setup-support.patch | 786 +++++++++++++++++ ...i-cpu-board-and-start-of-day-support.patch | 713 +++++++++++++++ ...t-for-Cubietruck-booting-in-FEL-mode.patch | 77 ++ 0023-sunxi-add-gmac-Ethernet-support.patch | 168 ++++ 0024-sunxi-mmc-support.patch | 797 +++++++++++++++++ ...i-non-FEL-SPL-boot-support-for-sun7i.patch | 409 +++++++++ 0026-port-over-to-generic-bootcommands.patch | 53 ++ ...move-switch-to-non-sec-to-the-last-b.patch | 44 + ...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 ++ ...add-separate-section-for-secure-code.patch | 93 ++ ...n-sec-allow-relocation-to-secure-RAM.patch | 499 +++++++++++ ...-non-sec-add-generic-ARMv7-PSCI-code.patch | 185 ++++ ...add-the-option-for-a-second-stage-mo.patch | 47 + ..._fixup_memory_node-to-a-generic-FDT-.patch | 97 +++ 0036-ARM-HYP-non-sec-PSCI-emit-DT-nodes.patch | 187 ++++ ...lenets-some-keywords-found-in-config.patch | 68 ++ ...ementing-syslinux-will-be-using-raw-.patch | 38 + uboot-tools.spec | 56 +- 39 files changed, 5562 insertions(+), 36 deletions(-) create mode 100644 0018-sunxi-add-sun7i-clocks-and-timer-support.patch create mode 100644 0019-sunxi-add-sun7i-pinmux-and-gpio-support.patch create mode 100644 0020-sunxi-add-sun7i-dram-setup-support.patch create mode 100644 0021-sunxi-add-sun7i-cpu-board-and-start-of-day-support.patch create mode 100644 0022-sunxi-add-support-for-Cubietruck-booting-in-FEL-mode.patch create mode 100644 0023-sunxi-add-gmac-Ethernet-support.patch create mode 100644 0024-sunxi-mmc-support.patch create mode 100644 0025-sunxi-non-FEL-SPL-boot-support-for-sun7i.patch create mode 100644 0026-port-over-to-generic-bootcommands.patch create mode 100644 0027-ARM-HYP-non-sec-move-switch-to-non-sec-to-the-last-b.patch create mode 100644 0028-ARM-HYP-non-sec-add-a-barrier-after-setting-SCR.NS-1.patch create mode 100644 0029-ARM-non-sec-reset-CNTVOFF-to-zero.patch create mode 100644 0030-ARM-add-missing-HYP-mode-constant.patch create mode 100644 0031-ARM-HYP-non-sec-add-separate-section-for-secure-code.patch create mode 100644 0032-ARM-HYP-non-sec-allow-relocation-to-secure-RAM.patch create mode 100644 0033-ARM-HYP-non-sec-add-generic-ARMv7-PSCI-code.patch create mode 100644 0034-ARM-HYP-non-sec-add-the-option-for-a-second-stage-mo.patch create mode 100644 0035-ARM-convert-arch_fixup_memory_node-to-a-generic-FDT-.patch create mode 100644 0036-ARM-HYP-non-sec-PSCI-emit-DT-nodes.patch create mode 100644 0037-PXE-syslinux-implenets-some-keywords-found-in-config.patch create mode 100644 0038-PXE-distros-implementing-syslinux-will-be-using-raw-.patch 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 +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 +Signed-off-by: Chen-Yu Tsai +Signed-off-by: Emilio López +Signed-off-by: Hans de Goede +Signed-off-by: Henrik Nordstrom +Signed-off-by: Jens Kuske +Signed-off-by: Luke Leighton +Signed-off-by: Oliver Schinagl +Signed-off-by: Ian Campbell +Cc: Stefan Roese +Cc: Tom Cubie +--- + 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 ++# ++# Based on some other Makefile ++# (C) Copyright 2000-2003 ++# Wolfgang Denk, DENX Software Engineering, wd@denx.de. ++# ++# SPDX-License-Identifier: GPL-2.0+ ++# ++obj-y += timer.o ++obj-y += clock.o ++obj-$(CONFIG_SUN7I) += clock_sun4i.o +diff --git a/arch/arm/cpu/armv7/sunxi/clock.c b/arch/arm/cpu/armv7/sunxi/clock.c +new file mode 100644 +index 0000000..94ba6e0 +--- /dev/null ++++ b/arch/arm/cpu/armv7/sunxi/clock.c +@@ -0,0 +1,35 @@ ++/* ++ * (C) Copyright 2007-2012 ++ * Allwinner Technology Co., Ltd. ++ * Tom Cubie ++ * ++ * (C) Copyright 2013 Luke Kenneth Casson Leighton ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++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. ++ * Tom Cubie ++ * ++ * (C) Copyright 2013 Luke Kenneth Casson Leighton ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#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. ++ * Tom Cubie ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#include ++#include ++#include ++ ++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. ++ * Tom Cubie ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#ifndef _SUNXI_CLOCK_H ++#define _SUNXI_CLOCK_H ++ ++#include ++ ++#define CLK_GATE_OPEN 0x1 ++#define CLK_GATE_CLOSE 0x0 ++ ++/* clock control module regs definition */ ++#include ++ ++#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. ++ * Tom Cubie ++ * ++ * 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. ++ * Tom Cubie ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#ifndef _SYS_PROTO_H_ ++#define _SYS_PROTO_H_ ++ ++#include ++ ++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. ++ * Tom Cubie ++ * ++ * 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 ++ ++/* 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 +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 +Signed-off-by: Hans de Goede +Signed-off-by: Ma Haijun +Signed-off-by: Oliver Schinagl +Signed-off-by: Henrik Nordström +Signed-off-by: Ian Campbell +Reviewed-by: Tom Rini +Cc: Stefan Roese +Cc: Tom Cubie +--- + 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. ++ * Tom Cubie ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#include ++#include ++#include ++ ++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. ++ * Tom Cubie ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#ifndef _SUNXI_GPIO_H ++#define _SUNXI_GPIO_H ++ ++#include ++ ++/* ++ * 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 +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 +Signed-off-by: Emilio López +Signed-off-by: Hans de Goede +Signed-off-by: Henrik Nordstrom +Signed-off-by: Jens Kuske +Signed-off-by: Luke Leighton +Signed-off-by: Oliver Schinagl +Signed-off-by: Stefan Roese +Signed-off-by: Ian Campbell +Cc: Tom Cubie +--- + 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 ++ * (C) Copyright 2013 Luke Kenneth Casson Leighton ++ * ++ * 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. ++ * Berg Xing ++ * Tom Cubie ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++ ++#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. ++ * Berg Xing ++ * Tom Cubie ++ * ++ * Sunxi platform dram register definition. ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#ifndef _SUNXI_DRAM_H ++#define _SUNXI_DRAM_H ++ ++#include ++ ++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 +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 +Signed-off-by: Aleksei Mamlin +Signed-off-by: Alexandru Gagniuc +Signed-off-by: Chen-Yu Tsai +Signed-off-by: Emilio López +Signed-off-by: Hans de Goede +Signed-off-by: Henrik Nordstrom +Signed-off-by: Jens Kuske +Signed-off-by: Luc Verhaegen +Signed-off-by: Luke Leighton +Signed-off-by: Oliver Schinagl +Signed-off-by: Patrick Wood +Signed-off-by: Stefan Roese +Signed-off-by: Wills Wang +Signed-off-by: Ian Campbell +Cc: Tom Cubie +--- + 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 ++ * ++ * (C) Copyright 2007-2011 ++ * Allwinner Technology Co., Ltd. ++ * Tom Cubie ++ * ++ * Some init for sunxi platform. ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#include ++#include ++#ifdef CONFIG_SPL_BUILD ++#include ++#endif ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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. ++ * Tom Cubie ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#include ++#include ++#include ++ ++#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 ++ * ++ * 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. ++ * Tom Cubie ++ * ++ * 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, ++ * ++ * 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 ++# ++# Based on some other board Makefile ++# ++# (C) Copyright 2000-2003 ++# Wolfgang Denk, DENX Software Engineering, wd@denx.de. ++# ++# SPDX-License-Identifier: GPL-2.0+ ++# ++obj-y += board.o +diff --git a/board/sunxi/board.c b/board/sunxi/board.c +new file mode 100644 +index 0000000..328334a +--- /dev/null ++++ b/board/sunxi/board.c +@@ -0,0 +1,57 @@ ++/* ++ * (C) Copyright 2012-2013 Henrik Nordstrom ++ * (C) Copyright 2013 Luke Kenneth Casson Leighton ++ * ++ * (C) Copyright 2007-2011 ++ * Allwinner Technology Co., Ltd. ++ * Tom Cubie ++ * ++ * Some board init for the Allwinner A10-evb board. ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#include ++#include ++#include ++ ++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 ++ * (C) Copyright 2013 Luke Kenneth Casson Leighton ++ * ++ * 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 ++ ++#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 ++ * ++ * (C) Copyright 2007-2011 ++ * Allwinner Technology Co., Ltd. ++ * Tom Cubie ++ * ++ * 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 /* 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 ++ ++#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 ++#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 +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 +Signed-off-by: Jens Kuske +Signed-off-by: Ian Campbell +Reviewed-by: Tom Rini +--- + 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 ++#include ++ ++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 + Active arm armv7 s5pc1xx samsung smdkc100 smdkc100 - Minkyu Kang + 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 + 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 +-- +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 +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 +Signed-off-by: Jens Kuske +Signed-off-by: Ian Campbell +--- + 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 ++#include ++#include + #include + #ifdef CONFIG_SPL_BUILD + #include +@@ -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 + Active arm armv7 s5pc1xx samsung smdkc100 smdkc100 - Minkyu Kang + 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 + 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 +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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 +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 +Signed-off-by: Luke Leighton +Signed-off-by: Oliver Schinagl +Signed-off-by: Wills Wang +Signed-off-by: Ian Campbell +Cc: Stefan Roese +Cc: Tom Cubie +Cc: Aaron Maoye +Cc: Pantelis Antoniou +--- + 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. ++ * Aaron ++ * ++ * MMC register definition for allwinner sunxi platform. ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#ifndef _SUNXI_MMC_H ++#define _SUNXI_MMC_H ++ ++#include ++ ++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 + #include + #include ++#include + + 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. ++ * Aaron ++ * ++ * MMC driver for allwinner sunxi platform. ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 +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 +Signed-off-by: Henrik Nordström +Signed-off-by: Ian Campbell +Cc: Tom Cubie +--- + 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. ++ * Tom Cubie ++ * ++ * Based on omap-common/u-boot-spl.lds: ++ * ++ * (C) Copyright 2002 ++ * Gary Jennejohn, DENX Software Engineering, ++ * ++ * (C) Copyright 2010 ++ * Texas Instruments, ++ * Aneesh V ++ * ++ * 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 + Active arm armv7 s5pc1xx samsung smdkc100 smdkc100 - Minkyu Kang + 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 + 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 /* 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. ++ * Tom Cubie ++ * ++ * a simple tool to generate bootable image for sunxi platform. ++ * ++ * SPDX-License-Identifier: GPL-2.0+ ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 +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 ++#include ++ ++#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 +-#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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 ++ + 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 +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 +--- + 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 + #include + #include ++#include + + .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 + #include + #include ++#include + + 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 ++ ++#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 + #include + #include ++#include + #include + + #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 +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 +--- + 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 ++ * ++ * 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 . ++ */ ++ ++#include ++#include ++#include ++ ++ .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 ++ * ++ * 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 . ++ */ ++ ++#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 +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 +--- + 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 +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 +Signed-off-by: Marc Zyngier +--- + 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 +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 +--- + 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 ++ * ++ * 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 . ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 + #include ++#include + + 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 +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 +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 - 2014.04-3 +- add cubietruck u-boot image + * Wed Apr 23 2014 Dennis Gilmore - 2014.04-2 - automatically add console line from u-boot environment to bootargs - when there is no console argument in the extlinux.conf file