1*dddba19aSStephan Gerhold/* 2*dddba19aSStephan Gerhold * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net> 3*dddba19aSStephan Gerhold * 4*dddba19aSStephan Gerhold * SPDX-License-Identifier: BSD-3-Clause 5*dddba19aSStephan Gerhold */ 6*dddba19aSStephan Gerhold 7*dddba19aSStephan Gerhold#include <arch.h> 8*dddba19aSStephan Gerhold#include <asm_macros.S> 9*dddba19aSStephan Gerhold 10*dddba19aSStephan Gerhold#include <msm8916_mmap.h> 11*dddba19aSStephan Gerhold 12*dddba19aSStephan Gerhold#define APCS_TCM_START_ADDR 0x10 13*dddba19aSStephan Gerhold#define APCS_TCM_REDIRECT_EN_0 BIT_32(0) 14*dddba19aSStephan Gerhold 15*dddba19aSStephan Gerhold .globl plat_crash_console_init 16*dddba19aSStephan Gerhold .globl plat_crash_console_putc 17*dddba19aSStephan Gerhold .globl plat_crash_console_flush 18*dddba19aSStephan Gerhold .globl plat_panic_handler 19*dddba19aSStephan Gerhold .globl plat_my_core_pos 20*dddba19aSStephan Gerhold .globl plat_get_my_entrypoint 21*dddba19aSStephan Gerhold .globl plat_reset_handler 22*dddba19aSStephan Gerhold .globl platform_mem_init 23*dddba19aSStephan Gerhold .globl msm8916_entry_point 24*dddba19aSStephan Gerhold 25*dddba19aSStephan Gerhold /* ------------------------------------------------- 26*dddba19aSStephan Gerhold * int plat_crash_console_init(void) 27*dddba19aSStephan Gerhold * Initialize the crash console. 28*dddba19aSStephan Gerhold * Out: x0 - 1 on success, 0 on error 29*dddba19aSStephan Gerhold * Clobber list : x0 - x4 30*dddba19aSStephan Gerhold * ------------------------------------------------- 31*dddba19aSStephan Gerhold */ 32*dddba19aSStephan Gerholdfunc plat_crash_console_init 33*dddba19aSStephan Gerhold mov x1, #BLSP_UART2_BASE 34*dddba19aSStephan Gerhold 35*dddba19aSStephan Gerhold /* 36*dddba19aSStephan Gerhold * If the non-secure world has been actively using the UART there might 37*dddba19aSStephan Gerhold * be still some characters left to be sent in the FIFO. In that case, 38*dddba19aSStephan Gerhold * resetting the transmitter too early might cause all output to become 39*dddba19aSStephan Gerhold * corrupted. To avoid that, try to flush (wait until FIFO empty) first. 40*dddba19aSStephan Gerhold */ 41*dddba19aSStephan Gerhold mov x4, lr 42*dddba19aSStephan Gerhold bl console_uartdm_core_flush 43*dddba19aSStephan Gerhold mov lr, x4 44*dddba19aSStephan Gerhold 45*dddba19aSStephan Gerhold mov x0, #1 46*dddba19aSStephan Gerhold b console_uartdm_core_init 47*dddba19aSStephan Gerholdendfunc plat_crash_console_init 48*dddba19aSStephan Gerhold 49*dddba19aSStephan Gerhold /* ------------------------------------------------- 50*dddba19aSStephan Gerhold * int plat_crash_console_putc(int c) 51*dddba19aSStephan Gerhold * Print a character on the crash console. 52*dddba19aSStephan Gerhold * In : w0 - character to be printed 53*dddba19aSStephan Gerhold * Out: w0 - printed character on success 54*dddba19aSStephan Gerhold * Clobber list : x1, x2 55*dddba19aSStephan Gerhold * ------------------------------------------------- 56*dddba19aSStephan Gerhold */ 57*dddba19aSStephan Gerholdfunc plat_crash_console_putc 58*dddba19aSStephan Gerhold mov x1, #BLSP_UART2_BASE 59*dddba19aSStephan Gerhold b console_uartdm_core_putc 60*dddba19aSStephan Gerholdendfunc plat_crash_console_putc 61*dddba19aSStephan Gerhold 62*dddba19aSStephan Gerhold /* ------------------------------------------------- 63*dddba19aSStephan Gerhold * void plat_crash_console_flush(void) 64*dddba19aSStephan Gerhold * Force a write of all buffered data that has not 65*dddba19aSStephan Gerhold * been output. 66*dddba19aSStephan Gerhold * Clobber list : x1, x2 67*dddba19aSStephan Gerhold * ------------------------------------------------- 68*dddba19aSStephan Gerhold */ 69*dddba19aSStephan Gerholdfunc plat_crash_console_flush 70*dddba19aSStephan Gerhold mov x1, #BLSP_UART2_BASE 71*dddba19aSStephan Gerhold b console_uartdm_core_flush 72*dddba19aSStephan Gerholdendfunc plat_crash_console_flush 73*dddba19aSStephan Gerhold 74*dddba19aSStephan Gerhold /* ------------------------------------------------- 75*dddba19aSStephan Gerhold * void plat_panic_handler(void) __dead 76*dddba19aSStephan Gerhold * Called when an unrecoverable error occurs. 77*dddba19aSStephan Gerhold * ------------------------------------------------- 78*dddba19aSStephan Gerhold */ 79*dddba19aSStephan Gerholdfunc plat_panic_handler 80*dddba19aSStephan Gerhold /* Try to shutdown/reset */ 81*dddba19aSStephan Gerhold mov_imm x0, MPM_PS_HOLD 82*dddba19aSStephan Gerhold str wzr, [x0] 83*dddba19aSStephan Gerhold1: b 1b 84*dddba19aSStephan Gerholdendfunc plat_panic_handler 85*dddba19aSStephan Gerhold 86*dddba19aSStephan Gerhold /* ------------------------------------------------- 87*dddba19aSStephan Gerhold * unsigned int plat_my_core_pos(void) 88*dddba19aSStephan Gerhold * Out: x0 - index of the calling CPU 89*dddba19aSStephan Gerhold * ------------------------------------------------- 90*dddba19aSStephan Gerhold */ 91*dddba19aSStephan Gerholdfunc plat_my_core_pos 92*dddba19aSStephan Gerhold /* There is just a single cluster so this is very simple */ 93*dddba19aSStephan Gerhold mrs x0, mpidr_el1 94*dddba19aSStephan Gerhold and x0, x0, #MPIDR_CPU_MASK 95*dddba19aSStephan Gerhold ret 96*dddba19aSStephan Gerholdendfunc plat_my_core_pos 97*dddba19aSStephan Gerhold 98*dddba19aSStephan Gerhold /* ------------------------------------------------- 99*dddba19aSStephan Gerhold * uintptr_t plat_get_my_entrypoint(void) 100*dddba19aSStephan Gerhold * Distinguish cold and warm boot and return warm boot 101*dddba19aSStephan Gerhold * entry address if available. 102*dddba19aSStephan Gerhold * Out: x0 - warm boot entry point or 0 on cold boot 103*dddba19aSStephan Gerhold * ------------------------------------------------- 104*dddba19aSStephan Gerhold */ 105*dddba19aSStephan Gerholdfunc plat_get_my_entrypoint 106*dddba19aSStephan Gerhold ldr x0, msm8916_entry_point 107*dddba19aSStephan Gerhold ret 108*dddba19aSStephan Gerholdendfunc plat_get_my_entrypoint 109*dddba19aSStephan Gerhold 110*dddba19aSStephan Gerhold /* ------------------------------------------------- 111*dddba19aSStephan Gerhold * void plat_reset_handler(void) 112*dddba19aSStephan Gerhold * Perform additional initialization after reset. 113*dddba19aSStephan Gerhold * Clobber list : x0 - x18, x30 114*dddba19aSStephan Gerhold * ------------------------------------------------- 115*dddba19aSStephan Gerhold */ 116*dddba19aSStephan Gerholdfunc plat_reset_handler 117*dddba19aSStephan Gerhold /* 118*dddba19aSStephan Gerhold * Check if the CPU is running at the correct address. 119*dddba19aSStephan Gerhold * During cold boot the CPU enters here at the wrong address 120*dddba19aSStephan Gerhold * using the "boot remapper". (It remaps the BL31_BASE to 121*dddba19aSStephan Gerhold * the CPU reset address 0x0). 122*dddba19aSStephan Gerhold */ 123*dddba19aSStephan Gerhold mov x0, #BL31_BASE 124*dddba19aSStephan Gerhold adr x1, bl31_entrypoint 125*dddba19aSStephan Gerhold cmp x0, x1 126*dddba19aSStephan Gerhold b.ne _remapped_cold_boot 127*dddba19aSStephan Gerhold /* Already running at correct address, just return directly */ 128*dddba19aSStephan Gerhold ret 129*dddba19aSStephan Gerhold 130*dddba19aSStephan Gerhold_remapped_cold_boot: 131*dddba19aSStephan Gerhold /* 132*dddba19aSStephan Gerhold * The previous boot stage seems to use the L2 cache as TCM. 133*dddba19aSStephan Gerhold * Disable the TCM redirect before enabling caches to avoid 134*dddba19aSStephan Gerhold * strange crashes. 135*dddba19aSStephan Gerhold */ 136*dddba19aSStephan Gerhold mov x2, #APCS_CFG 137*dddba19aSStephan Gerhold ldr w3, [x2, #APCS_TCM_START_ADDR] 138*dddba19aSStephan Gerhold and w3, w3, #~APCS_TCM_REDIRECT_EN_0 139*dddba19aSStephan Gerhold str w3, [x2, #APCS_TCM_START_ADDR] 140*dddba19aSStephan Gerhold 141*dddba19aSStephan Gerhold /* Enter BL31 again at the real address */ 142*dddba19aSStephan Gerhold br x0 143*dddba19aSStephan Gerholdendfunc plat_reset_handler 144*dddba19aSStephan Gerhold 145*dddba19aSStephan Gerhold /* ------------------------------------------------- 146*dddba19aSStephan Gerhold * void platform_mem_init(void) 147*dddba19aSStephan Gerhold * Performs additional memory initialization early 148*dddba19aSStephan Gerhold * in the boot process. 149*dddba19aSStephan Gerhold * ------------------------------------------------- 150*dddba19aSStephan Gerhold */ 151*dddba19aSStephan Gerholdfunc platform_mem_init 152*dddba19aSStephan Gerhold /* Nothing to do here, all memory is already initialized */ 153*dddba19aSStephan Gerhold ret 154*dddba19aSStephan Gerholdendfunc platform_mem_init 155*dddba19aSStephan Gerhold 156*dddba19aSStephan Gerhold .data 157*dddba19aSStephan Gerhold .align 3 158*dddba19aSStephan Gerhold 159*dddba19aSStephan Gerhold /* ------------------------------------------------- 160*dddba19aSStephan Gerhold * Warm boot entry point for CPU. Set by PSCI code. 161*dddba19aSStephan Gerhold * ------------------------------------------------- 162*dddba19aSStephan Gerhold */ 163*dddba19aSStephan Gerholdmsm8916_entry_point: 164*dddba19aSStephan Gerhold .quad 0 165