mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-17 10:04:26 +00:00

Reference code: ============== rar_gen3: IPL and Secure Monitor Rev1.0.22 https://github.com/renesas-rcar/arm-trusted-firmware [rcar_gen3] Author: Takuya Sakata <takuya.sakata.wz@bp.renesas.com> Date: Thu Aug 30 21:26:41 2018 +0900 Update IPL and Secure Monitor Rev1.0.22 General Information: =================== This port has been tested on the Salvator-X Soc_id r8a7795 revision ES1.1 (uses an SPD). Build Tested: ------------- ATFW_OPT="LSI=H3 RCAR_DRAM_SPLIT=1 RCAR_LOSSY_ENABLE=1" MBEDTLS_DIR=$mbedtls $ make clean bl2 bl31 rcar PLAT=rcar ${ATFW_OPT} SPD=opteed Other dependencies: ------------------ * mbed_tls: git@github.com:ARMmbed/mbedtls.git [devel] Merge: 68dbc94 f34a4c1 Author: Simon Butcher <simon.butcher@arm.com> Date: Thu Aug 30 00:57:28 2018 +0100 * optee_os: https://github.com/BayLibre/optee_os Until it gets merged into OP-TEE, the port requires Renesas' Trusted Environment with a modification to support power management. Author: Jorge Ramirez-Ortiz <jramirez@baylibre.com> Date: Thu Aug 30 16:49:49 2018 +0200 plat-rcar: cpu-suspend: handle the power level Signed-off-by: Jorge Ramirez-Ortiz <jramirez@baylibre.com> * u-boot: The port has beent tested using mainline uboot. Author: Fabio Estevam <festevam@gmail.com> Date: Tue Sep 4 10:23:12 2018 -0300 *linux: The port has beent tested using mainline kernel. Author: Linus Torvalds <torvalds@linux-foundation.org> Date: Sun Sep 16 11:52:37 2018 -0700 Linux 4.19-rc4 Overview --------- BOOTROM starts the cpu at EL3; In this port BL2 will therefore be entered at this exception level (the Renesas' ATF reference tree [1] resets into EL1 before entering BL2 - see its bl2.ld.S) BL2 initializes DDR (and i2c to talk to the PMIC on some platforms) before determining the boot reason (cold or warm). During suspend all CPUs are switched off and the DDR is put in backup mode (some kind of self-refresh mode). This means that BL2 is always entered in a cold boot scenario. Once BL2 boots, it determines the boot reason, writes it to shared memory (BOOT_KIND_BASE) together with the BL31 parameters (PARAMS_BASE) and jumps to BL31. To all effects, BL31 is as if it is being entered in reset mode since it still needs to initialize the rest of the cores; this is the reason behind using direct shared memory access to BOOT_KIND_BASE and PARAMS_BASE instead of using registers to get to those locations (see el3_common_macros.S and bl31_entrypoint.S for the RESET_TO_BL31 use case). Depending on the boot reason BL31 initializes the rest of the cores: in case of suspend, it uses a MBOX memory region to recover the program counters. [1] https://github.com/renesas-rcar/arm-trusted-firmware Tests ----- * cpuidle ------- enable kernel's cpuidle arm_idle driver and boot * system suspend -------------- $ cat suspend.sh #!/bin/bash i2cset -f -y 7 0x30 0x20 0x0F read -p "Switch off SW23 and press return " foo echo mem > /sys/power/state * cpu hotplug: ------------ $ cat offline.sh #!/bin/bash nbr=$1 echo 0 > /sys/devices/system/cpu/cpu$nbr/online printf "ONLINE: " && cat /sys/devices/system/cpu/online printf "OFFLINE: " && cat /sys/devices/system/cpu/offline $ cat online.sh #!/bin/bash nbr=$1 echo 1 > /sys/devices/system/cpu/cpu$nbr/online printf "ONLINE: " && cat /sys/devices/system/cpu/online printf "OFFLINE: " && cat /sys/devices/system/cpu/offline Signed-off-by: ldts <jramirez@baylibre.com>
376 lines
9.2 KiB
ArmAsm
376 lines
9.2 KiB
ArmAsm
/*
|
|
* 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
|