[PATCH v2 05/13] ARM: sunxi: Add lowlevel switch to aarch64

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Allwinner A64 SoC (and probably others) boots in 32-bits mode. Switching
to aarch64 is achieved by writing to the Reset Management Register (RMR)
which can be accessed through the memory space thanks to an alias.

On A64 this alias is located at 0x017000a0

Signed-off-by: Jules Maselbas <jmaselbas@xxxxxxxx>
---
rfc->v2:
 - code is no longer assembled from .S, it now an array of 16 u32
 - added 3 nops at the end of padding (aligning the header on 16*4 bytes)
 - the code can be "modified" for other rvbar addresses

 include/mach/sunxi/rmr_switch.h | 50 +++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)
 create mode 100644 include/mach/sunxi/rmr_switch.h

diff --git a/include/mach/sunxi/rmr_switch.h b/include/mach/sunxi/rmr_switch.h
new file mode 100644
index 0000000000..f136b11e46
--- /dev/null
+++ b/include/mach/sunxi/rmr_switch.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef MACH_SUNXI_RMR_SWITCH_H
+#define MACH_SUNXI_RMR_SWITCH_H
+
+/*
+ * ARMv8 RMR reset sequence on Allwinner SoCs.
+ *
+ * All 64-bit capable Allwinner SoCs reset in AArch32 (and continue to
+ * execute the Boot ROM in this state), so we need to switch to AArch64
+ * at some point.
+ * Section G6.2.133 of the ARMv8 ARM describes the Reset Management Register
+ * (RMR), which triggers a warm-reset of a core and can request to switch
+ * into a different execution state (AArch32 or AArch64).
+ * The address at which execution starts after the reset is held in the
+ * RVBAR system register, which is architecturally read-only.
+ * Allwinner provides a writable alias of this register in MMIO space, so
+ * we can easily set the start address of AArch64 code.
+ * This code below switches to AArch64 and starts execution at the specified
+ * start address.
+ *
+ * This file has been adapted from U-Boot code sources:
+ *  - arch/arm/mach-sunxi/rmr_switch.S
+ *  - arch/arm/include/asm/arch-sunxi/boot0.h.
+ *
+ * The aarch32 assembly has already been assembled and are inserted verbatime
+ * as .word statements (the asm source is commented for each statement).
+ *
+ */
+#define SUNXI_RMR_SWITCH_CODE(rvbar_addr) {		       \
+	0xeb000000, /* bl   .+8             subs x0, x0, x0 */ \
+	0x1400000c, /* .word 0x1400000c     b end           */ \
+	0xe59f0020, /* ldr  r0, [pc, #32] ; rvbar           */ \
+	0xe580e000, /* str  lr, [r0]                        */ \
+	0xf57ff04f, /* dsb  sy                              */ \
+	0xf57ff06f, /* isb  syo                             */ \
+	0xee1c0f50, /* mrc  15, 0, r0, cr12, cr0, {2}       */ \
+	0xe3800003, /* orr  r0, r0, #3                      */ \
+	0xee0c0f50, /* mcr  15, 0, r0, cr12, cr0, {2}       */ \
+	0xf57ff06f, /* isb  sy                              */ \
+	0xe320f003, /* 1b: wfi                              */ \
+	0xeafffffd, /* b    1b                              */ \
+	rvbar_addr, \
+	0xd503201f, 0xd503201f, 0xd503201f } /* nop * 3 */
+#define sunxi_switch_to_aarch64(section, rvbar_addr) {			\
+		__section(section) static const u32 rmr_switch[] =	\
+			SUNXI_RMR_SWITCH_CODE(rvbar_addr);		\
+		__keep_symbolref(rmr_switch);				\
+	}
+
+#endif
-- 
2.40.1





[Index of Archives]     [Linux Embedded]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux