summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/Kconfig1
-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
4 files changed, 75 insertions, 3 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e4663ea268..6d38218814 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -123,6 +123,7 @@ config ARCH_MVEBU
select GPIOLIB
select HAS_DEBUG_LL
select HAVE_DEFAULT_ENVIRONMENT_NEW
+ select HAVE_MACH_ARM_HEAD
select HAVE_PBL_MULTI_IMAGES
select HW_HAS_PCI
select MVEBU_MBUS
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