summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mvebu
diff options
context:
space:
mode:
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>2017-02-24 11:26:38 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2017-03-02 14:03:43 +0100
commitf15bb506aa7d5d17c299fa8ef7330996a7393fce (patch)
tree0715d56dd819c1e894949c83931e294d18dbab1f /arch/arm/mach-mvebu
parent7ada71351b6ed1f42cf8ae5159016a767cbca2c1 (diff)
downloadbarebox-f15bb506aa7d5d17c299fa8ef7330996a7393fce.tar.gz
barebox-f15bb506aa7d5d17c299fa8ef7330996a7393fce.tar.xz
mvebu: get initial position of register window from image header
A problem when using 2nd stage booting on mvebu is that the first bootloader already switched the register window location from 0xd0000000 to 0xf1000000 by writing to 0xd0000080. When the second bootloader also tries to do this switch it writes to the wrong location resulting in an exception and so a boot failure. For this reason the base address of the register window is passed in the barebox header and picked up from there by early code. In a further patch bootm is taught to put the actual position of the window there for the second bootloader to finally make second stage booting work. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Diffstat (limited to 'arch/arm/mach-mvebu')
-rw-r--r--arch/arm/mach-mvebu/common.c6
-rw-r--r--arch/arm/mach-mvebu/include/mach/barebox-arm-head.h54
-rw-r--r--arch/arm/mach-mvebu/include/mach/common.h17
3 files changed, 74 insertions, 3 deletions
diff --git a/arch/arm/mach-mvebu/common.c b/arch/arm/mach-mvebu/common.c
index 7534d8dd01..06bfb72615 100644
--- a/arch/arm/mach-mvebu/common.c
+++ b/arch/arm/mach-mvebu/common.c
@@ -180,14 +180,14 @@ mem_initcall(mvebu_meminit);
* safely later on, as the remap register itself is within the
* internal registers.
*/
-#define MVEBU_BOOTUP_INT_REG_BASE 0xd0000000
#define MVEBU_BRIDGE_REG_BASE 0x20000
#define DEVICE_INTERNAL_BASE_ADDR (MVEBU_BRIDGE_REG_BASE + 0x80)
static void mvebu_remap_registers(void)
{
- writel(MVEBU_REMAP_INT_REG_BASE,
- IOMEM(MVEBU_BOOTUP_INT_REG_BASE) + DEVICE_INTERNAL_BASE_ADDR);
+ void __iomem *base = mvebu_get_initial_int_reg_base();
+
+ writel(MVEBU_REMAP_INT_REG_BASE, base + DEVICE_INTERNAL_BASE_ADDR);
}
void __naked __noreturn dove_barebox_entry(void *boarddata)
diff --git a/arch/arm/mach-mvebu/include/mach/barebox-arm-head.h b/arch/arm/mach-mvebu/include/mach/barebox-arm-head.h
new file mode 100644
index 0000000000..3035f40ddf
--- /dev/null
+++ b/arch/arm/mach-mvebu/include/mach/barebox-arm-head.h
@@ -0,0 +1,54 @@
+#include <linux/stringify.h>
+#include <mach/common.h>
+
+static inline void __barebox_arm_head(void)
+{
+ __asm__ __volatile__ (
+#ifdef CONFIG_THUMB2_BAREBOX
+ ".arm\n"
+ "adr r9, 1f + 1\n"
+ "bx r9\n"
+ ".thumb\n"
+ "1:\n"
+ "bl 2f\n"
+ ".rept 10\n"
+ "1: b 1b\n"
+ ".endr\n"
+#else
+ "b 2f\n"
+ "1: b 1b\n"
+ "1: b 1b\n"
+ "1: b 1b\n"
+ "1: b 1b\n"
+ "1: b 1b\n"
+ "1: b 1b\n"
+ "1: b 1b\n"
+#endif
+ ".asciz \"barebox\"\n"
+ ".word _text\n" /* text base. If copied there,
+ * barebox can skip relocation
+ */
+ ".word _barebox_image_size\n" /* image size to copy */
+
+ /*
+ * The following entry (at offset 0x30) is the only intended
+ * difference to the original arm __barebox_arm_head. This value
+ * holds the address of the internal register window when the
+ * image is started. If the window is not at the reset default
+ * position any more the caller can pass the actual value here.
+ */
+ ".word " __stringify(MVEBU_BOOTUP_INT_REG_BASE) "\n"
+ ".rept 7\n"
+ ".word 0x55555555\n"
+ ".endr\n"
+ "2:\n"
+ );
+}
+
+static inline void barebox_arm_head(void)
+{
+ __barebox_arm_head();
+ __asm__ __volatile__ (
+ "b barebox_arm_reset_vector\n"
+ );
+}
diff --git a/arch/arm/mach-mvebu/include/mach/common.h b/arch/arm/mach-mvebu/include/mach/common.h
index 3cc1bf71c0..529eb61cfd 100644
--- a/arch/arm/mach-mvebu/include/mach/common.h
+++ b/arch/arm/mach-mvebu/include/mach/common.h
@@ -18,6 +18,23 @@
#ifndef __MACH_COMMON_H__
#define __MACH_COMMON_H__
+#include <asm/sections.h>
+#include <asm/unaligned.h>
+
+#define MVEBU_BOOTUP_INT_REG_BASE 0xd0000000
#define MVEBU_REMAP_INT_REG_BASE 0xf1000000
+/* #including <asm/barebox-arm.h> yields a circle, so we need a forward decl */
+uint32_t get_runtime_offset(void);
+
+static inline void __iomem *mvebu_get_initial_int_reg_base(void)
+{
+#ifdef __PBL__
+ u32 base = __get_unaligned_le32(_text - get_runtime_offset() + 0x30);
+ return (void __force __iomem *)base;
+#else
+ return (void __force __iomem *)MVEBU_REMAP_INT_REG_BASE;
+#endif
+}
+
#endif