aboutsummaryrefslogtreecommitdiff
path: root/plat/renesas/rcar/aarch64/plat_helpers.S
diff options
context:
space:
mode:
Diffstat (limited to 'plat/renesas/rcar/aarch64/plat_helpers.S')
-rw-r--r--plat/renesas/rcar/aarch64/plat_helpers.S376
1 files changed, 376 insertions, 0 deletions
diff --git a/plat/renesas/rcar/aarch64/plat_helpers.S b/plat/renesas/rcar/aarch64/plat_helpers.S
new file mode 100644
index 0000000000..50799379b5
--- /dev/null
+++ b/plat/renesas/rcar/aarch64/plat_helpers.S
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+#include <cortex_a57.h>
+#include <platform_def.h>
+#include <runtime_svc.h>
+#include "rcar_def.h"
+
+ .globl plat_get_my_entrypoint
+ .extern plat_set_my_stack
+ .globl platform_mem_init
+
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_invalidate_icache
+ .globl plat_report_exception
+ .globl plat_secondary_reset
+ .globl plat_reset_handler
+ .globl plat_my_core_pos
+ .extern rcar_log_init
+
+#if IMAGE_BL2
+ #define INT_ID_MASK (0x3ff)
+ .extern bl2_interrupt_error_type
+ .extern bl2_interrupt_error_id
+ .globl bl2_enter_bl31
+ .extern gicv2_acknowledge_interrupt
+ .extern rcar_swdt_exec
+#endif
+
+ /* -----------------------------------------------------
+ * void platform_get_core_pos (mpidr)
+ * -----------------------------------------------------
+ */
+func platform_get_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ add x0, x1, x0, LSR #6
+ ret
+endfunc platform_get_core_pos
+
+ /* -----------------------------------------------------
+ * void platform_my_core_pos
+ * -----------------------------------------------------
+ */
+func plat_my_core_pos
+ mrs x0, mpidr_el1
+ b platform_get_core_pos
+endfunc plat_my_core_pos
+
+ /* -----------------------------------------------------
+ * void platform_get_my_entrypoint (unsigned int mpid);
+ *
+ * Main job of this routine is to distinguish between
+ * a cold and warm boot.
+ * On a cold boot the secondaries first wait for the
+ * platform to be initialized after which they are
+ * hotplugged in. The primary proceeds to perform the
+ * platform initialization.
+ * On a warm boot, each cpu jumps to the address in its
+ * mailbox.
+ *
+ * TODO: Not a good idea to save lr in a temp reg
+ * -----------------------------------------------------
+ */
+func plat_get_my_entrypoint
+ mrs x0, mpidr_el1
+ mov x9, x30 /* lr */
+
+#if defined(IMAGE_BL2)
+ /* always cold boot on bl2 */
+ mov x0, #0
+ ret x9
+#else
+ ldr x1, =BOOT_KIND_BASE
+ ldr x21, [x1]
+
+ /* Check the reset info */
+ and x1, x21, #0x000c
+ cmp x1, #0x0008
+ beq el3_panic
+ cmp x1, #0x000c
+ beq el3_panic
+
+ /* Check the boot kind */
+ and x1, x21, #0x0003
+ cmp x1, #0x0002
+ beq el3_panic
+ cmp x1, #0x0003
+ beq el3_panic
+
+ /* warm boot or cold boot */
+ and x1, x21, #1
+ cmp x1, #0
+ bne warm_reset
+
+ /* Cold boot */
+ mov x0, #0
+ b exit
+
+warm_reset:
+ /* --------------------------------------------------------------------
+ * A per-cpu mailbox is maintained in the trusted SDRAM. Its flushed out
+ * of the caches after every update using normal memory so its safe to
+ * read it here with SO attributes
+ * ---------------------------------------------------------------------
+ */
+ ldr x10, =MBOX_BASE
+ bl platform_get_core_pos
+ lsl x0, x0, #CACHE_WRITEBACK_SHIFT
+ ldr x0, [x10, x0]
+ cbz x0, _panic
+exit:
+ ret x9
+_panic:
+ b do_panic
+#endif
+
+endfunc plat_get_my_entrypoint
+
+ /* ---------------------------------------------
+ * plat_secondary_reset
+ *
+ * ---------------------------------------------
+ */
+func plat_secondary_reset
+ mrs x0, sctlr_el3
+ bic x0, x0, #SCTLR_EE_BIT
+ msr sctlr_el3, x0
+ isb
+
+ mrs x0, cptr_el3
+ bic w0, w0, #TCPAC_BIT
+ bic w0, w0, #TTA_BIT
+ bic w0, w0, #TFP_BIT
+ msr cptr_el3, x0
+
+ mov_imm x0, PARAMS_BASE
+ mov_imm x2, BL31_BASE
+ ldr x3, =BOOT_KIND_BASE
+ mov x1, #0x1
+ str x1, [x3]
+ br x2 /* jump to BL31 */
+ nop
+ nop
+ nop
+endfunc plat_secondary_reset
+
+ /* ---------------------------------------------
+ * plat_enter_bl31
+ *
+ * ---------------------------------------------
+ */
+func bl2_enter_bl31
+ mov x20, x0
+ /*
+ * MMU needs to be disabled because both BL2 and BL31 execute
+ * in EL3, and therefore share the same address space.
+ * BL31 will initialize the address space according to its
+ * own requirement.
+ */
+#if RCAR_BL2_DCACHE == 1
+ /* Disable mmu and data cache */
+ bl disable_mmu_el3
+ /* Data cache clean and invalidate */
+ mov x0, #DCCISW
+ bl dcsw_op_all
+ /* TLB invalidate all, EL3 */
+ tlbi alle3
+#endif /* RCAR_BL2_DCACHE == 1 */
+ bl disable_mmu_icache_el3
+ /* Invalidate instruction cache */
+ ic iallu
+ dsb sy
+ isb
+ ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET]
+ msr elr_el3, x0
+ msr spsr_el3, x1
+ eret
+endfunc bl2_enter_bl31
+
+ /* -----------------------------------------------------
+ * void platform_mem_init (void);
+ *
+ * Zero out the mailbox registers in the shared memory
+ * and set the rcar_boot_kind_flag.
+ * The mmu is turned off right now and only the primary can
+ * ever execute this code. Secondaries will read the
+ * mailboxes using SO accesses.
+ * -----------------------------------------------------
+ */
+func platform_mem_init
+#if !IMAGE_BL2
+ ldr x0, =MBOX_BASE
+ mov w1, #PLATFORM_CORE_COUNT
+loop:
+ str xzr, [x0], #CACHE_WRITEBACK_GRANULE
+ subs w1, w1, #1
+ b.gt loop
+#endif
+ ret
+endfunc platform_mem_init
+
+ /* ---------------------------------------------
+ * void plat_report_exception(unsigned int type)
+ * Function to report an unhandled exception
+ * with platform-specific means.
+ * ---------------------------------------------
+ */
+func plat_report_exception
+#if IMAGE_BL2
+ mov w1, #FIQ_SP_EL0
+ cmp w0, w1
+ beq rep_exec_fiq_elx
+ b rep_exec_panic_type
+rep_exec_fiq_elx:
+ bl gicv2_acknowledge_interrupt
+ mov x2, #INT_ID_MASK
+ and x0, x0, x2
+ mov x1, #ARM_IRQ_SEC_WDT
+ cmp x0, x1
+ bne rep_exec_panic_id
+ mrs x0, ELR_EL3
+ b rcar_swdt_exec
+rep_exec_panic_type:
+ /* x0 is interrupt TYPE */
+ b bl2_interrupt_error_type
+rep_exec_panic_id:
+ /* x0 is interrupt ID */
+ b bl2_interrupt_error_id
+rep_exec_end:
+#endif
+ ret
+endfunc plat_report_exception
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize log area
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+#if IMAGE_BL2
+ mov x0, #0
+#else
+ mov x1, sp
+ mov_imm x2, RCAR_CRASH_STACK
+ mov sp, x2
+ str x1, [sp, #-16]!
+ str x30, [sp, #-16]!
+ bl console_core_init
+ ldr x30, [sp], #16
+ ldr x1, [sp], #16
+ mov sp, x1
+#endif
+ ret
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Function to store a character to log area
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov x1, sp
+ mov_imm x2, RCAR_CRASH_STACK
+ mov sp, x2
+ str x1, [sp, #-16]!
+ str x30, [sp, #-16]!
+ str x3, [sp, #-16]!
+ str x4, [sp, #-16]!
+ str x5, [sp, #-16]!
+ bl console_core_putc
+ ldr x5, [sp], #16
+ ldr x4, [sp], #16
+ ldr x3, [sp], #16
+ ldr x30, [sp], #16
+ ldr x1, [sp], #16
+ mov sp, x1
+ ret
+endfunc plat_crash_console_putc
+
+ /* --------------------------------------------------------------------
+ * void plat_reset_handler(void);
+ *
+ * Before adding code in this function, refer to the guidelines in
+ * docs/firmware-design.md to determine whether the code should reside
+ * within the FIRST_RESET_HANDLER_CALL block or not.
+ *
+ * For R-Car H3:
+ * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
+ * - Set the L2 Data setup latency to 1 (i.e. 1 cycles) for Cortex-A57
+ * - Set the L2 Data RAM latency to 3 (i.e. 4 cycles) for Cortex-A57
+ * For R-Car M3/M3N:
+ * - Set the L2 Tag RAM latency to 2 (i.e. 3 cycles) for Cortex-A57
+ * - Set the L2 Data setup latency to 0 (i.e. 0 cycles) for Cortex-A57
+ * - Set the L2 Data RAM latency to 3 (i.e. 4 cycles) for Cortex-A57
+ *
+ * --------------------------------------------------------------------
+ */
+func plat_reset_handler
+ /*
+ * On R-Car H3 : x2 := 0
+ * On R-Car M3/M3N: x2 := 1
+ */
+ /* read PRR */
+ ldr x0, =0xFFF00044
+ ldr w0, [x0]
+ ubfx w0, w0, 8, 8
+ /* H3? */
+ cmp w0, #0x4F
+ b.eq H3
+ /* set R-Car M3/M3N */
+ mov x2, #1
+ b CHK_A5x
+H3:
+ /* set R-Car H3 */
+ mov x2, #0
+ /* --------------------------------------------------------------------
+ * Determine whether this code is executed on a Cortex-A53 or on a
+ * Cortex-A57 core.
+ * --------------------------------------------------------------------
+ */
+CHK_A5x:
+ mrs x0, midr_el1
+ ubfx x1, x0, MIDR_PN_SHIFT, #12
+ cmp w1, #((CORTEX_A57_MIDR >> MIDR_PN_SHIFT) & MIDR_PN_MASK)
+ b.eq A57
+ ret
+A57:
+ /* Get data from CORTEX_A57_L2CTLR_EL1 */
+ mrs x0, CORTEX_A57_L2CTLR_EL1
+ /*
+ * On R-Car H3/M3/M3N
+ *
+ * L2 Tag RAM latency is bit8-6 of CORTEX_A57_L2CTLR_EL1
+ * L2 Data RAM setup is bit5 of CORTEX_A57_L2CTLR_EL1
+ * L2 Data RAM latency is bit2-0 of CORTEX_A57_L2CTLR_EL1
+ */
+ /* clear bit of L2 RAM */
+ /* ~(0x1e7) -> x1 */
+ mov x1, #0x1e7
+ neg x1, x1
+ /* clear bit of L2 RAM -> x0 */
+ and x0, x0, x1
+ /* L2 Tag RAM latency (3 cycles) */
+ orr x0, x0, #0x2 << 6
+ /* If M3/M3N then L2 RAM setup is 0 */
+ cbnz x2, M3_L2
+ /* L2 Data RAM setup (1 cycle) */
+ orr x0, x0, #0x1 << 5
+M3_L2:
+ /* L2 Data RAM latency (4 cycles) */
+ orr x0, x0, #0x3
+ /* Store data to L2CTLR_EL1 */
+ msr CORTEX_A57_L2CTLR_EL1, x0
+apply_l2_ram_latencies:
+ ret
+endfunc plat_reset_handler
+
+ /* ---------------------------------------------
+ * void plat_invalidate_icache(void)
+ * Instruction Cache Invalidate All to PoU
+ * ---------------------------------------------
+ */
+func plat_invalidate_icache
+ ic iallu
+
+ ret
+endfunc plat_invalidate_icache