diff options
Diffstat (limited to 'plat/qti/msm8916')
24 files changed, 1824 insertions, 0 deletions
diff --git a/plat/qti/msm8916/aarch32/msm8916_helpers.S b/plat/qti/msm8916/aarch32/msm8916_helpers.S new file mode 100644 index 0000000..dc35043 --- /dev/null +++ b/plat/qti/msm8916/aarch32/msm8916_helpers.S @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2021-2023, Stephan Gerhold <stephan@gerhold.net> + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <platform_def.h> + +#include <msm8916_mmap.h> + +#if PLATFORM_CORE_COUNT > 1 +#define APCS_TCM_START_ADDR 0x10 +#else +#define APCS_TCM_START_ADDR 0x34 +#endif +#define APCS_TCM_REDIRECT_EN_0 BIT_32(0) + + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_panic_handler + .globl plat_my_core_pos + .globl plat_get_my_entrypoint + .globl plat_reset_handler + .globl platform_mem_init + .globl msm8916_entry_point + + /* ------------------------------------------------- + * int plat_crash_console_init(void) + * Initialize the crash console. + * Out: r0 - 1 on success, 0 on error + * Clobber list : r0 - r4 + * ------------------------------------------------- + */ +func plat_crash_console_init + ldr r1, =BLSP_UART_BASE + mov r0, #1 + b console_uartdm_core_init +endfunc plat_crash_console_init + + /* ------------------------------------------------- + * int plat_crash_console_putc(int c) + * Print a character on the crash console. + * In : r0 - character to be printed + * Out: r0 - printed character on success + * Clobber list : r1, r2 + * ------------------------------------------------- + */ +func plat_crash_console_putc + ldr r1, =BLSP_UART_BASE + b console_uartdm_core_putc +endfunc plat_crash_console_putc + + /* ------------------------------------------------- + * void plat_crash_console_flush(void) + * Force a write of all buffered data that has not + * been output. + * Clobber list : r1, r2 + * ------------------------------------------------- + */ +func plat_crash_console_flush + ldr r1, =BLSP_UART_BASE + b console_uartdm_core_flush +endfunc plat_crash_console_flush + + /* ------------------------------------------------- + * void plat_panic_handler(void) __dead + * Called when an unrecoverable error occurs. + * ------------------------------------------------- + */ +func plat_panic_handler + /* Try to shutdown/reset */ + ldr r0, =MPM_PS_HOLD + mov r1, #0 + str r1, [r0] +1: b 1b +endfunc plat_panic_handler + + /* ------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * Out: r0 - index of the calling CPU + * ------------------------------------------------- + */ +func plat_my_core_pos + .if PLATFORM_CORE_COUNT > 1 + ldcopr r1, MPIDR + and r0, r1, #MPIDR_CPU_MASK + .if PLATFORM_CLUSTER_COUNT > 1 + and r1, r1, #MPIDR_CLUSTER_MASK + orr r0, r0, r1, LSR #(MPIDR_AFFINITY_BITS - \ + PLATFORM_CPU_PER_CLUSTER_SHIFT) + .endif + .else + /* There is just a single core so always 0 */ + mov r0, #0 + .endif + bx lr +endfunc plat_my_core_pos + + /* ------------------------------------------------- + * uintptr_t plat_get_my_entrypoint(void) + * Distinguish cold and warm boot and return warm boot + * entry address if available. + * Out: r0 - warm boot entry point or 0 on cold boot + * ------------------------------------------------- + */ +func plat_get_my_entrypoint + ldr r0, =msm8916_entry_point + ldr r0, [r0] + cmp r0, #0 + bxne lr + + /* + * Cold boot: Disable TCM redirect to L2 cache as early as + * possible to avoid crashes when making use of the cache. + */ + ldr r1, =APCS_CFG(0) + ldr r2, [r1, #APCS_TCM_START_ADDR] + and r2, r2, #~APCS_TCM_REDIRECT_EN_0 + str r2, [r1, #APCS_TCM_START_ADDR] + bx lr +endfunc plat_get_my_entrypoint + + /* ------------------------------------------------- + * void platform_mem_init(void) + * Performs additional memory initialization early + * in the boot process. + * ------------------------------------------------- + */ +func platform_mem_init + /* Nothing to do here, all memory is already initialized */ + bx lr +endfunc platform_mem_init + + .data + .align 3 + + /* ------------------------------------------------- + * Warm boot entry point for CPU. Set by PSCI code. + * ------------------------------------------------- + */ +msm8916_entry_point: + .word 0 diff --git a/plat/qti/msm8916/aarch32/uartdm_console.S b/plat/qti/msm8916/aarch32/uartdm_console.S new file mode 100644 index 0000000..a19776a --- /dev/null +++ b/plat/qti/msm8916/aarch32/uartdm_console.S @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2021-2023, Stephan Gerhold <stephan@gerhold.net> + * + * Based on aarch32/skeleton_console.S: + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <asm_macros.S> +#include <console_macros.S> + +/* UART DM registers */ +#define UART_DM_DMEN 0x03c /* DMA / data packing */ +#define UART_DM_SR 0x0a4 /* status register */ +#define UART_DM_CR 0x0a8 /* command register */ +#define UART_DM_TF 0x100 /* transmit FIFO */ + +#define UART_DM_DMEN_TX_SC BIT_32(4) /* TX single character mode */ + +#define UART_DM_SR_TXRDY BIT_32(2) /* TX FIFO has space */ +#define UART_DM_SR_TXEMT BIT_32(3) /* TX FIFO is empty */ + +#define UART_DM_CR_RESET_RX (U(0x01) << 4) /* reset receiver */ +#define UART_DM_CR_RESET_TX (U(0x02) << 4) /* reset transmitter */ +#define UART_DM_CR_TX_ENABLE BIT_32(2) /* enable transmitter */ + + .globl console_uartdm_register + .globl console_uartdm_core_init + .globl console_uartdm_putc + .globl console_uartdm_core_putc + .globl console_uartdm_flush + .globl console_uartdm_core_flush + + /* ----------------------------------------------------------- + * int console_uartdm_register(console_t *console, + * uintptr_t base_addr) + * Function to initialize and register the console. The caller + * needs to pass an empty console_t structure in which *MUST* + * be allocated in persistent memory (e.g. a global or static + * local variable, *NOT* on the stack). + * In : r0 - pointer to empty console_t structure + * r1 - base address + * Out: r0 - 1 on success, 0 on error + * Clobber list : r0 - r7 + * ----------------------------------------------------------- + */ +func console_uartdm_register + str r1, [r0, #CONSOLE_T_BASE] + mov r7, lr + bl console_uartdm_core_init + mov lr, r7 + + /* Register the new console */ + finish_console_register uartdm putc=1, flush=1 +endfunc console_uartdm_register + + /* ----------------------------------------------------------- + * void console_uartdm_core_init(unused, uintptr_t base_addr) + * Function to initialize the console. + * In : r0 - unused + * r1 - base address + * Out: void + * Clobber list : r1, r2, r3 + * ----------------------------------------------------------- + */ +func console_uartdm_core_init + /* + * Try to flush remaining characters from the TX FIFO before resetting + * the transmitter. Unfortunately there is no good way to check if + * the transmitter is actually enabled (and will finish eventually), + * so use a timeout to avoid looping forever. + */ + mov r2, #65536 +1: + ldr r3, [r1, #UART_DM_SR] + tst r3, #UART_DM_SR_TXEMT + bne 2f + subs r2, r2, #1 + bne 1b + /* Timeout */ + +2: /* Reset receiver */ + mov r3, #UART_DM_CR_RESET_RX + str r3, [r1, #UART_DM_CR] + + /* Reset transmitter */ + mov r3, #UART_DM_CR_RESET_TX + str r3, [r1, #UART_DM_CR] + + /* + * Disable BAM/DMA modes but enable single-character mode for TX. + * The single character mode allows simplifying the putc implementation + * since characters can be written directly to the FIFO instead of + * having to initiate a new transfer and waiting for its completion. + */ + mov r3, #UART_DM_DMEN_TX_SC + str r3, [r1, #UART_DM_DMEN] + + /* Enable transmitter */ + mov r3, #UART_DM_CR_TX_ENABLE + str r3, [r1, #UART_DM_CR] + + bx lr +endfunc console_uartdm_core_init + + /* ----------------------------------------------------------- + * int console_uartdm_putc(int c, console_t *console) + * Function to output a character over the console. + * In : r0 - character to be printed + * r1 - pointer to console_t struct + * Out: r0 - printed character on success, < 0 on error. + * Clobber list : r0, r1, r2 + * ----------------------------------------------------------- + */ +func console_uartdm_putc + ldr r1, [r1, #CONSOLE_T_BASE] + b console_uartdm_core_putc +endfunc console_uartdm_putc + + /* ----------------------------------------------------------- + * int console_uartdm_core_putc(int c, uintptr_t base_addr) + * Function to output a character over the console. + * In : r0 - character to be printed + * r1 - base address + * Out: r0 - printed character on success, < 0 on error. + * Clobber list : r2 + * ----------------------------------------------------------- + */ +func console_uartdm_core_putc + cmp r0, #'\n' + bne 2f + +1: /* Loop until TX FIFO has space */ + ldr r2, [r1, #UART_DM_SR] + tst r2, #UART_DM_SR_TXRDY + beq 1b + + /* Prepend '\r' to '\n' */ + mov r2, #'\r' + str r2, [r1, #UART_DM_TF] + +2: /* Loop until TX FIFO has space */ + ldr r2, [r1, #UART_DM_SR] + tst r2, #UART_DM_SR_TXRDY + beq 2b + + /* Write character to FIFO */ + str r0, [r1, #UART_DM_TF] + bx lr +endfunc console_uartdm_core_putc + + /* ----------------------------------------------------------- + * void console_uartdm_flush(console_t *console) + * Function to force a write of all buffered data + * that has not been output. + * In : r0 - pointer to console_t struct + * Out: void + * Clobber list : r0, r1, r2, r3, r4, r5 + * ----------------------------------------------------------- + */ +func console_uartdm_flush + ldr r1, [r0, #CONSOLE_T_BASE] + b console_uartdm_core_flush +endfunc console_uartdm_flush + + /* ----------------------------------------------------------- + * void console_uartdm_core_flush(unused, uintptr_t base_addr) + * Function to force a write of all buffered data + * that has not been output. + * In : r0 - unused + * r1 - base address + * Out: void + * Clobber list : r2 + * ----------------------------------------------------------- + */ +func console_uartdm_core_flush +1: /* Loop until TX FIFO is empty */ + ldr r2, [r1, #UART_DM_SR] + tst r2, #UART_DM_SR_TXEMT + beq 1b + bx lr +endfunc console_uartdm_core_flush diff --git a/plat/qti/msm8916/aarch64/msm8916_helpers.S b/plat/qti/msm8916/aarch64/msm8916_helpers.S new file mode 100644 index 0000000..de9438a --- /dev/null +++ b/plat/qti/msm8916/aarch64/msm8916_helpers.S @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2021-2023, Stephan Gerhold <stephan@gerhold.net> + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <platform_def.h> + +#include <msm8916_mmap.h> + +#if PLATFORM_CORE_COUNT > 1 +#define APCS_TCM_START_ADDR 0x10 +#else +#define APCS_TCM_START_ADDR 0x34 +#endif +#define APCS_TCM_REDIRECT_EN_0 BIT_32(0) + + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_panic_handler + .globl plat_my_core_pos + .globl plat_get_my_entrypoint + .globl plat_reset_handler + .globl platform_mem_init + .globl msm8916_entry_point + + /* ------------------------------------------------- + * int plat_crash_console_init(void) + * Initialize the crash console. + * Out: x0 - 1 on success, 0 on error + * Clobber list : x0 - x4 + * ------------------------------------------------- + */ +func plat_crash_console_init + mov_imm x1, BLSP_UART_BASE + mov x0, #1 + b console_uartdm_core_init +endfunc plat_crash_console_init + + /* ------------------------------------------------- + * int plat_crash_console_putc(int c) + * Print a character on the crash console. + * In : w0 - character to be printed + * Out: w0 - printed character on success + * Clobber list : x1, x2 + * ------------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, BLSP_UART_BASE + b console_uartdm_core_putc +endfunc plat_crash_console_putc + + /* ------------------------------------------------- + * void plat_crash_console_flush(void) + * Force a write of all buffered data that has not + * been output. + * Clobber list : x1, x2 + * ------------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x1, BLSP_UART_BASE + b console_uartdm_core_flush +endfunc plat_crash_console_flush + + /* ------------------------------------------------- + * void plat_panic_handler(void) __dead + * Called when an unrecoverable error occurs. + * ------------------------------------------------- + */ +func plat_panic_handler + /* Try to shutdown/reset */ + mov_imm x0, MPM_PS_HOLD + str wzr, [x0] +1: b 1b +endfunc plat_panic_handler + + /* ------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * Out: x0 - index of the calling CPU + * ------------------------------------------------- + */ +func plat_my_core_pos + .if PLATFORM_CORE_COUNT > 1 + mrs x1, mpidr_el1 + and x0, x1, #MPIDR_CPU_MASK + .if PLATFORM_CLUSTER_COUNT > 1 + and x1, x1, #MPIDR_CLUSTER_MASK + orr x0, x0, x1, LSR #(MPIDR_AFFINITY_BITS - \ + PLATFORM_CPU_PER_CLUSTER_SHIFT) + .endif + .else + /* There is just a single core so always 0 */ + mov x0, #0 + .endif + ret +endfunc plat_my_core_pos + + /* ------------------------------------------------- + * uintptr_t plat_get_my_entrypoint(void) + * Distinguish cold and warm boot and return warm boot + * entry address if available. + * Out: x0 - warm boot entry point or 0 on cold boot + * ------------------------------------------------- + */ +func plat_get_my_entrypoint + ldr x0, msm8916_entry_point + cbz x0, 1f + ret +1: + /* + * Cold boot: Disable TCM redirect to L2 cache as early as + * possible to avoid crashes when making use of the cache. + */ + mov_imm x1, APCS_CFG(0) + ldr w2, [x1, #APCS_TCM_START_ADDR] + and w2, w2, #~APCS_TCM_REDIRECT_EN_0 + str w2, [x1, #APCS_TCM_START_ADDR] + + /* + * After reset the CPU always starts executing at the fixed reset + * address (0x0), which does not match the link address of BL31. + * The "boot remapper" redirects all memory accesses to the real + * physical address in DRAM. + * + * For warm boots, this is already handled by loading the real + * entry point address above. + * + * For cold boots, check if the CPU is using the boot remapper, + * i.e. if bl31_entrypoint appears to be at the reset address (0x0). + */ + adr x1, bl31_entrypoint + cbnz x1, 2f + + /* + * Add the real BL31_BASE offset to the return address in the link + * register so the CPU will continue at the real address after return. + */ + mov_imm x1, BL31_BASE + add lr, lr, x1 +2: + ret +endfunc plat_get_my_entrypoint + + /* ------------------------------------------------- + * void platform_mem_init(void) + * Performs additional memory initialization early + * in the boot process. + * ------------------------------------------------- + */ +func platform_mem_init + /* Nothing to do here, all memory is already initialized */ + ret +endfunc platform_mem_init + + .data + .align 3 + + /* ------------------------------------------------- + * Warm boot entry point for CPU. Set by PSCI code. + * ------------------------------------------------- + */ +msm8916_entry_point: + .quad 0 diff --git a/plat/qti/msm8916/aarch64/uartdm_console.S b/plat/qti/msm8916/aarch64/uartdm_console.S new file mode 100644 index 0000000..6c65daf --- /dev/null +++ b/plat/qti/msm8916/aarch64/uartdm_console.S @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2021-2023, Stephan Gerhold <stephan@gerhold.net> + * + * Based on aarch64/skeleton_console.S: + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <asm_macros.S> +#include <console_macros.S> + +/* UART DM registers */ +#define UART_DM_DMEN 0x03c /* DMA / data packing */ +#define UART_DM_SR 0x0a4 /* status register */ +#define UART_DM_CR 0x0a8 /* command register */ +#define UART_DM_TF 0x100 /* transmit FIFO */ + +#define UART_DM_DMEN_TX_SC BIT_32(4) /* TX single character mode */ + +#define UART_DM_SR_TXRDY_BIT 2 /* TX FIFO has space */ +#define UART_DM_SR_TXEMT_BIT 3 /* TX FIFO is empty */ + +#define UART_DM_CR_RESET_RX (U(0x01) << 4) /* reset receiver */ +#define UART_DM_CR_RESET_TX (U(0x02) << 4) /* reset transmitter */ +#define UART_DM_CR_TX_ENABLE BIT_32(2) /* enable transmitter */ + + .globl console_uartdm_register + .globl console_uartdm_core_init + .globl console_uartdm_putc + .globl console_uartdm_core_putc + .globl console_uartdm_flush + .globl console_uartdm_core_flush + + /* ----------------------------------------------------------- + * int console_uartdm_register(console_t *console, + * uintptr_t base_addr) + * Function to initialize and register the console. The caller + * needs to pass an empty console_t structure in which *MUST* + * be allocated in persistent memory (e.g. a global or static + * local variable, *NOT* on the stack). + * In : x0 - pointer to empty console_t structure + * x1 - base address + * Out: x0 - 1 on success, 0 on error + * Clobber list : x0 - x7 + * ----------------------------------------------------------- + */ +func console_uartdm_register + str x1, [x0, #CONSOLE_T_BASE] + mov x7, lr + bl console_uartdm_core_init + mov lr, x7 + + /* Register the new console */ + finish_console_register uartdm putc=1, flush=1 +endfunc console_uartdm_register + + /* ----------------------------------------------------------- + * void console_uartdm_core_init(unused, uintptr_t base_addr) + * Function to initialize the console. + * In : x0 - unused + * x1 - base address + * Out: void + * Clobber list : x1, x2, x3 + * ----------------------------------------------------------- + */ +func console_uartdm_core_init + /* + * Try to flush remaining characters from the TX FIFO before resetting + * the transmitter. Unfortunately there is no good way to check if + * the transmitter is actually enabled (and will finish eventually), + * so use a timeout to avoid looping forever. + */ + mov w2, #65536 +1: + ldr w3, [x1, #UART_DM_SR] + tbnz w3, #UART_DM_SR_TXEMT_BIT, 2f + subs w2, w2, #1 + b.ne 1b + /* Timeout */ + +2: /* Reset receiver */ + mov w3, #UART_DM_CR_RESET_RX + str w3, [x1, #UART_DM_CR] + + /* Reset transmitter */ + mov w3, #UART_DM_CR_RESET_TX + str w3, [x1, #UART_DM_CR] + + /* + * Disable BAM/DMA modes but enable single-character mode for TX. + * The single character mode allows simplifying the putc implementation + * since characters can be written directly to the FIFO instead of + * having to initiate a new transfer and waiting for its completion. + */ + mov w3, #UART_DM_DMEN_TX_SC + str w3, [x1, #UART_DM_DMEN] + + /* Enable transmitter */ + mov w3, #UART_DM_CR_TX_ENABLE + str w3, [x1, #UART_DM_CR] + + ret +endfunc console_uartdm_core_init + + /* ----------------------------------------------------------- + * int console_uartdm_putc(int c, console_t *console) + * Function to output a character over the console. + * In : w0 - character to be printed + * x1 - pointer to console_t struct + * Out: w0 - printed character on success, < 0 on error. + * Clobber list : x0, x1, x2 + * ----------------------------------------------------------- + */ +func console_uartdm_putc + ldr x1, [x1, #CONSOLE_T_BASE] + b console_uartdm_core_putc +endfunc console_uartdm_putc + + /* ----------------------------------------------------------- + * int console_uartdm_core_putc(int c, uintptr_t base_addr) + * Function to output a character over the console. + * In : w0 - character to be printed + * x1 - base address + * Out: w0 - printed character on success, < 0 on error. + * Clobber list : x2 + * ----------------------------------------------------------- + */ +func console_uartdm_core_putc + cmp w0, #'\n' + b.ne 2f + +1: /* Loop until TX FIFO has space */ + ldr w2, [x1, #UART_DM_SR] + tbz w2, #UART_DM_SR_TXRDY_BIT, 1b + + /* Prepend '\r' to '\n' */ + mov w2, #'\r' + str w2, [x1, #UART_DM_TF] + +2: /* Loop until TX FIFO has space */ + ldr w2, [x1, #UART_DM_SR] + tbz w2, #UART_DM_SR_TXRDY_BIT, 2b + + /* Write character to FIFO */ + str w0, [x1, #UART_DM_TF] + ret +endfunc console_uartdm_core_putc + + /* ----------------------------------------------------------- + * void console_uartdm_flush(console_t *console) + * Function to force a write of all buffered data + * that has not been output. + * In : x0 - pointer to console_t struct + * Out: void + * Clobber list : x0, x1, x2, x3, x4, x5 + * ----------------------------------------------------------- + */ +func console_uartdm_flush + ldr x1, [x0, #CONSOLE_T_BASE] + b console_uartdm_core_flush +endfunc console_uartdm_flush + + /* ----------------------------------------------------------- + * void console_uartdm_core_flush(unused, uintptr_t base_addr) + * Function to force a write of all buffered data + * that has not been output. + * In : x0 - unused + * x1 - base address + * Out: void + * Clobber list : x2 + * ----------------------------------------------------------- + */ +func console_uartdm_core_flush +1: /* Loop until TX FIFO is empty */ + ldr w2, [x1, #UART_DM_SR] + tbz w2, #UART_DM_SR_TXEMT_BIT, 1b + ret +endfunc console_uartdm_core_flush diff --git a/plat/qti/msm8916/include/msm8916_mmap.h b/plat/qti/msm8916/include/msm8916_mmap.h new file mode 100644 index 0000000..20c5a57 --- /dev/null +++ b/plat/qti/msm8916/include/msm8916_mmap.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021-2023, Stephan Gerhold <stephan@gerhold.net> + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MSM8916_MMAP_H +#define MSM8916_MMAP_H + +#define PCNOC_BASE 0x00000000 +#define PCNOC_SIZE SZ_128M +#define APCS_BASE 0x0b000000 +#define APCS_SIZE SZ_8M + +#define MPM_BASE (PCNOC_BASE + 0x04a0000) +#define MPM_PS_HOLD (MPM_BASE + 0xb000) + +#define TLMM_BASE (PCNOC_BASE + 0x1000000) +#define TLMM_GPIO_CFG(n) (TLMM_BASE + ((n) * 0x1000)) + +#define GCC_BASE (PCNOC_BASE + 0x1800000) + +#define APPS_SMMU_BASE (PCNOC_BASE + 0x1e00000) +#define APPS_SMMU_QCOM (APPS_SMMU_BASE + 0xf0000) +#define GPU_SMMU_BASE (PCNOC_BASE + 0x1f00000) + +#define BLSP1_BASE (PCNOC_BASE + 0x7880000) +#define BLSP1_UART_BASE(n) (BLSP1_BASE + 0x2f000 + (((n) - 1) * 0x1000)) +#define BLSP_UART_BASE BLSP1_UART_BASE(QTI_UART_NUM) + +#define APCS_QGIC2_BASE (APCS_BASE + 0x00000) +#define APCS_QGIC2_GICD (APCS_QGIC2_BASE + 0x0000) +#define APCS_QGIC2_GICC (APCS_QGIC2_BASE + 0x2000) +#define APCS_BANKED_ACS (APCS_BASE + 0x08000) +#define APCS_BANKED_SAW2 (APCS_BASE + 0x09000) + +#define _APCS_CLUSTER(cluster) (APCS_BASE + ((cluster) * 0x100000)) +#define _APCS_CPU(cluster, cpu) (_APCS_CLUSTER(cluster) + ((cpu) * 0x10000)) +#define APCS_CFG(cluster) (_APCS_CLUSTER(cluster) + 0x10000) +#define APCS_GLB(cluster) (_APCS_CLUSTER(cluster) + 0x11000) +#define APCS_L2_SAW2(cluster) (_APCS_CLUSTER(cluster) + 0x12000) +#define APCS_QTMR(cluster) (_APCS_CLUSTER(cluster) + 0x20000) +#define APCS_ALIAS_ACS(cluster, cpu) (_APCS_CPU(cluster, cpu) + 0x88000) +#define APCS_ALIAS_SAW2(cluster, cpu) (_APCS_CPU(cluster, cpu) + 0x89000) + +/* Only on platforms with multiple clusters (e.g. MSM8939) */ +#define APCS_CCI_BASE (APCS_BASE + 0x1c0000) +#define APCS_CCI_SAW2 (APCS_BASE + 0x1d2000) +#define APCS_CCI_ACS (APCS_BASE + 0x1d4000) + +#endif /* MSM8916_MMAP_H */ diff --git a/plat/qti/msm8916/include/plat_macros.S b/plat/qti/msm8916/include/plat_macros.S new file mode 100644 index 0000000..552add2 --- /dev/null +++ b/plat/qti/msm8916/include/plat_macros.S @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +#include <arm_macros.S> + +#include <msm8916_mmap.h> + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant GIC registers whenever + * an unhandled exception is taken in BL31. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + mov_imm x16, APCS_QGIC2_GICD + mov_imm x17, APCS_QGIC2_GICC + arm_print_gic_regs + .endm + +#endif /* PLAT_MACROS_S */ diff --git a/plat/qti/msm8916/include/platform_def.h b/plat/qti/msm8916/include/platform_def.h new file mode 100644 index 0000000..a5baacd --- /dev/null +++ b/plat/qti/msm8916/include/platform_def.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021-2023, Stephan Gerhold <stephan@gerhold.net> + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <plat/common/common_def.h> + +#ifdef __aarch64__ +/* + * There is at least 1 MiB available for BL31. However, at the moment the + * "msm8916_entry_point" variable in the data section is read through the + * 64 KiB region of the "boot remapper" after reset. For simplicity, limit + * the end of the data section (BL31_PROGBITS_LIMIT) to 64 KiB for now and + * the overall limit to 128 KiB. This could be increased if needed by placing + * the "msm8916_entry_point" variable explicitly in the first 64 KiB of BL31. + */ +#define BL31_LIMIT (BL31_BASE + SZ_128K) +#define BL31_PROGBITS_LIMIT (BL31_BASE + SZ_64K) +#endif +#define BL32_LIMIT (BL32_BASE + SZ_128K) + +#define CACHE_WRITEBACK_GRANULE U(64) +#define PLATFORM_STACK_SIZE SZ_4K + +/* CPU topology: one or two clusters with 4 cores each */ +#ifdef PLAT_msm8939 +#define PLATFORM_CLUSTER_COUNT U(2) +#else +#define PLATFORM_CLUSTER_COUNT U(1) +#endif +#if defined(PLAT_mdm9607) +#define PLATFORM_CPU_PER_CLUSTER_SHIFT U(0) /* 1 */ +#else +#define PLATFORM_CPU_PER_CLUSTER_SHIFT U(2) /* 4 */ +#endif +#define PLATFORM_CPUS_PER_CLUSTER (1 << PLATFORM_CPU_PER_CLUSTER_SHIFT) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \ + PLATFORM_CPUS_PER_CLUSTER) + +/* Power management */ +#define PLATFORM_SYSTEM_COUNT U(1) +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_SYSTEM_COUNT + \ + PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 +#define PLAT_MAX_RET_STATE U(2) +#define PLAT_MAX_OFF_STATE U(3) + +/* Translation tables */ +#define MAX_MMAP_REGIONS 8 +#define MAX_XLAT_TABLES 4 + +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32) + +/* Timer */ +#define PLAT_SYSCNT_FREQ 19200000 +#define IRQ_SEC_PHY_TIMER (16 + 2) /* PPI #2 */ + +/* + * The Qualcomm QGIC2 implementation seems to have PIDR0-4 and PIDR4-7 + * erroneously swapped for some reason. PIDR2 is actually at 0xFD8. + * Override the address in <drivers/arm/gicv2.h> to avoid a failing assert(). + */ +#define GICD_PIDR2_GICV2 U(0xFD8) + +/* TSP */ +#define TSP_IRQ_SEC_PHY_TIMER IRQ_SEC_PHY_TIMER +#define TSP_SEC_MEM_BASE BL32_BASE +#define TSP_SEC_MEM_SIZE (BL32_LIMIT - BL32_BASE) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/qti/msm8916/include/uartdm_console.h b/plat/qti/msm8916/include/uartdm_console.h new file mode 100644 index 0000000..0f09ba8 --- /dev/null +++ b/plat/qti/msm8916/include/uartdm_console.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net> + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UARTDM_CONSOLE_H +#define UARTDM_CONSOLE_H + +int console_uartdm_register(console_t *console, uintptr_t base_addr); + +#endif /* UARTDM_CONSOLE_H */ diff --git a/plat/qti/msm8916/msm8916_bl31_setup.c b/plat/qti/msm8916/msm8916_bl31_setup.c new file mode 100644 index 0000000..c588020 --- /dev/null +++ b/plat/qti/msm8916/msm8916_bl31_setup.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2021-2023, Stephan Gerhold <stephan@gerhold.net> + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <arch.h> +#include <common/debug.h> +#include <plat/common/platform.h> + +#include "msm8916_config.h" +#include "msm8916_setup.h" + +static struct { + entry_point_info_t bl32; + entry_point_info_t bl33; +} image_ep_info = { + /* BL32 entry point */ + SET_STATIC_PARAM_HEAD(bl32, PARAM_EP, VERSION_1, + entry_point_info_t, SECURE), + .bl32.pc = BL32_BASE, + + /* BL33 entry point */ + SET_STATIC_PARAM_HEAD(bl33, PARAM_EP, VERSION_1, + entry_point_info_t, NON_SECURE), + .bl33.pc = PRELOADED_BL33_BASE, + .bl33.spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS), +}; + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + msm8916_early_platform_setup(); + msm8916_configure_early(); +} + +void bl31_plat_arch_setup(void) +{ + msm8916_plat_arch_setup(BL31_BASE, BL31_END - BL31_BASE); + enable_mmu_el3(0); +} + +void bl31_platform_setup(void) +{ + INFO("BL31: Platform setup start\n"); + msm8916_platform_setup(); + msm8916_configure(); + INFO("BL31: Platform setup done\n"); +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + switch (type) { + case SECURE: + return &image_ep_info.bl32; + case NON_SECURE: + return &image_ep_info.bl33; + default: + assert(sec_state_is_valid(type)); + return NULL; + } +} diff --git a/plat/qti/msm8916/msm8916_config.c b/plat/qti/msm8916/msm8916_config.c new file mode 100644 index 0000000..0ac604b --- /dev/null +++ b/plat/qti/msm8916/msm8916_config.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2021-2023, Stephan Gerhold <stephan@gerhold.net> + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <arch.h> +#include <drivers/arm/cci.h> +#include <lib/mmio.h> + +#include "msm8916_config.h" +#include "msm8916_gicv2.h" +#include <msm8916_mmap.h> +#include <platform_def.h> + +static const int cci_map[] = { 3, 4 }; + +void msm8916_configure_early(void) +{ + if (PLATFORM_CLUSTER_COUNT > 1) { + cci_init(APCS_CCI_BASE, cci_map, ARRAY_SIZE(cci_map)); + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + } +} + +static void msm8916_configure_timer(uintptr_t base) +{ + /* Set timer frequency */ + mmio_write_32(base + CNTCTLBASE_CNTFRQ, PLAT_SYSCNT_FREQ); + + /* Make all timer frames available to non-secure world */ + mmio_write_32(base + CNTNSAR, GENMASK_32(7, 0)); +} + +/* + * The APCS register regions always start with a SECURE register that should + * be cleared to 0 to only allow secure access. Since BL31 handles most of + * the CPU power management, most of them can be cleared to secure access only. + */ +#define APCS_GLB_SECURE_STS_NS BIT_32(0) +#define APCS_GLB_SECURE_PWR_NS BIT_32(1) +#if PLATFORM_CORE_COUNT > 1 +#define APCS_BOOT_START_ADDR_SEC 0x04 +#define APCS_AA64NAA32_REG 0x0c +#else +#define APCS_BOOT_START_ADDR_SEC 0x18 +#endif +#define REMAP_EN BIT_32(0) + +static void msm8916_configure_apcs_cluster(unsigned int cluster) +{ + uintptr_t cfg = APCS_CFG(cluster); + unsigned int cpu; + + /* Disallow non-secure access to boot remapper / TCM registers */ + mmio_write_32(cfg, 0); + + /* + * Disallow non-secure access to power management registers. + * However, allow STS and PWR since those also seem to control access + * to CPU frequency related registers (e.g. APCS_CMD_RCGR). If these + * bits are not set, CPU frequency control fails in the non-secure world. + */ + mmio_write_32(APCS_GLB(cluster), + APCS_GLB_SECURE_STS_NS | APCS_GLB_SECURE_PWR_NS); + + if (PLATFORM_CORE_COUNT > 1) { + /* Disallow non-secure access to L2 SAW2 */ + mmio_write_32(APCS_L2_SAW2(cluster), 0); + + /* Disallow non-secure access to CPU ACS and SAW2 */ + for (cpu = 0; cpu < PLATFORM_CPUS_PER_CLUSTER; cpu++) { + mmio_write_32(APCS_ALIAS_ACS(cluster, cpu), 0); + mmio_write_32(APCS_ALIAS_SAW2(cluster, cpu), 0); + } + } else { + /* There is just one core so no aliases exist */ + mmio_write_32(APCS_BANKED_ACS, 0); + mmio_write_32(APCS_BANKED_SAW2, 0); + } + +#ifdef __aarch64__ + /* Make sure all further warm boots end up in BL31 and aarch64 state */ + CASSERT((BL31_BASE & 0xffff) == 0, assert_bl31_base_64k_aligned); + mmio_write_32(cfg + APCS_BOOT_START_ADDR_SEC, BL31_BASE | REMAP_EN); + mmio_write_32(cfg + APCS_AA64NAA32_REG, 1); +#else + /* Make sure all further warm boots end up in BL32 */ + CASSERT((BL32_BASE & 0xffff) == 0, assert_bl32_base_64k_aligned); + mmio_write_32(cfg + APCS_BOOT_START_ADDR_SEC, BL32_BASE | REMAP_EN); +#endif + + msm8916_configure_timer(APCS_QTMR(cluster)); +} + +static void msm8916_configure_apcs(void) +{ + unsigned int cluster; + + for (cluster = 0; cluster < PLATFORM_CLUSTER_COUNT; cluster++) { + msm8916_configure_apcs_cluster(cluster); + } + + if (PLATFORM_CLUSTER_COUNT > 1) { + /* Disallow non-secure access to CCI ACS and SAW2 */ + mmio_write_32(APCS_CCI_ACS, 0); + mmio_write_32(APCS_CCI_SAW2, 0); + } +} + +/* + * MSM8916 has a special "interrupt aggregation logic" in the APPS SMMU, + * which allows routing context bank interrupts to one of 3 interrupt numbers + * ("TZ/HYP/NS"). Route all interrupts to the non-secure interrupt number + * by default to avoid special setup on the non-secure side. + */ +#define CLK_OFF BIT_32(31) +#define GCC_APSS_TCU_CBCR (GCC_BASE + 0x12018) +#define GCC_GFX_TCU_CBCR (GCC_BASE + 0x12020) +#define GCC_SMMU_CFG_CBCR (GCC_BASE + 0x12038) +#define GCC_RPM_SMMU_CLOCK_BRANCH_ENA_VOTE (GCC_BASE + 0x3600c) +#define GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE (GCC_BASE + 0x4500c) +#define APSS_TCU_CLK_ENA BIT_32(1) +#define GFX_TCU_CLK_ENA BIT_32(2) +#define GFX_TBU_CLK_ENA BIT_32(3) +#define SMMU_CFG_CLK_ENA BIT_32(12) +#define APPS_SMMU_INTR_SEL_NS (APPS_SMMU_QCOM + 0x2000) +#define APPS_SMMU_INTR_SEL_NS_EN_ALL U(0xffffffff) + +#define SMMU_SACR 0x010 +#define SMMU_SACR_CACHE_LOCK BIT_32(26) +#define SMMU_IDR7 0x03c +#define SMMU_IDR7_MINOR(val) (((val) >> 0) & 0xf) +#define SMMU_IDR7_MAJOR(val) (((val) >> 4) & 0xf) + +static void msm8916_smmu_cache_unlock(uintptr_t smmu_base, uintptr_t clk_cbcr) +{ + uint32_t version; + + /* Wait for clock */ + while (mmio_read_32(clk_cbcr) & CLK_OFF) { + } + + version = mmio_read_32(smmu_base + SMMU_IDR7); + VERBOSE("SMMU(0x%lx) r%dp%d\n", smmu_base, + SMMU_IDR7_MAJOR(version), SMMU_IDR7_MINOR(version)); + + /* For SMMU r2p0+ clear CACHE_LOCK to allow writes to CBn_ACTLR */ + if (SMMU_IDR7_MAJOR(version) >= 2) { + mmio_clrbits_32(smmu_base + SMMU_SACR, SMMU_SACR_CACHE_LOCK); + } +} + +static void msm8916_configure_smmu(void) +{ + uint32_t ena_bits = APSS_TCU_CLK_ENA | SMMU_CFG_CLK_ENA; + + /* Single core (MDM) platforms do not have a GPU */ + if (PLATFORM_CORE_COUNT > 1) { + ena_bits |= GFX_TCU_CLK_ENA | GFX_TBU_CLK_ENA; + } + + /* Enable SMMU clocks to enable register access */ + mmio_write_32(GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE, ena_bits); + + /* Wait for configuration clock */ + while (mmio_read_32(GCC_SMMU_CFG_CBCR) & CLK_OFF) { + } + + /* Route all context bank interrupts to non-secure interrupt */ + mmio_write_32(APPS_SMMU_INTR_SEL_NS, APPS_SMMU_INTR_SEL_NS_EN_ALL); + + /* Clear sACR.CACHE_LOCK bit if needed for MMU-500 r2p0+ */ + msm8916_smmu_cache_unlock(APPS_SMMU_BASE, GCC_APSS_TCU_CBCR); + if (PLATFORM_CORE_COUNT > 1) { + msm8916_smmu_cache_unlock(GPU_SMMU_BASE, GCC_GFX_TCU_CBCR); + } + + /* + * Keep APCS vote for SMMU clocks for rest of booting process, but make + * sure other vote registers (such as RPM) do not keep permanent votes. + */ + VERBOSE("Clearing GCC_RPM_SMMU_CLOCK_BRANCH_ENA_VOTE (was: 0x%x)\n", + mmio_read_32(GCC_RPM_SMMU_CLOCK_BRANCH_ENA_VOTE)); + mmio_write_32(GCC_RPM_SMMU_CLOCK_BRANCH_ENA_VOTE, 0); +} + +void msm8916_configure(void) +{ + msm8916_gicv2_configure(); + msm8916_configure_apcs(); + msm8916_configure_smmu(); +} diff --git a/plat/qti/msm8916/msm8916_config.h b/plat/qti/msm8916/msm8916_config.h new file mode 100644 index 0000000..977d02c --- /dev/null +++ b/plat/qti/msm8916/msm8916_config.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2022-2023, Stephan Gerhold <stephan@gerhold.net> + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MSM8916_CONFIG_H +#define MSM8916_CONFIG_H + +void msm8916_configure(void); +void msm8916_configure_early(void); + +#endif /* MSM8916_CONFIG_H */ diff --git a/plat/qti/msm8916/msm8916_cpu_boot.c b/plat/qti/msm8916/msm8916_cpu_boot.c new file mode 100644 index 0000000..d6faa59 --- /dev/null +++ b/plat/qti/msm8916/msm8916_cpu_boot.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2021-2022, Stephan Gerhold <stephan@gerhold.net> + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/delay_timer.h> +#include <lib/mmio.h> + +#include "msm8916_pm.h" + +#define CPU_PWR_CTL 0x4 +#define APC_PWR_GATE_CTL 0x14 + +#define CPU_PWR_CTL_CLAMP BIT_32(0) +#define CPU_PWR_CTL_CORE_MEM_CLAMP BIT_32(1) +#define CPU_PWR_CTL_L1_RST_DIS BIT_32(2) +#define CPU_PWR_CTL_CORE_MEM_HS BIT_32(3) +#define CPU_PWR_CTL_CORE_RST BIT_32(4) +#define CPU_PWR_CTL_COREPOR_RST BIT_32(5) +#define CPU_PWR_CTL_GATE_CLK BIT_32(6) +#define CPU_PWR_CTL_CORE_PWRD_UP BIT_32(7) + +#define APC_PWR_GATE_CTL_GHDS_EN BIT_32(0) +#define APC_PWR_GATE_CTL_GHDS_CNT(cnt) ((cnt) << 24) + +#define PWR_CTL_OVERRIDE 0xc +#define L2_PWR_CTL 0x14 +#define L2_PWR_STATUS 0x18 +#define CORE_CBCR 0x58 + +#define PWR_CTL_OVERRIDE_PRESETDBG BIT_32(22) + +#define L2_PWR_CTL_L2_ARRAY_HS BIT_32(0) +#define L2_PWR_CTL_SCU_ARRAY_HS BIT_32(1) +#define L2_PWR_CTL_L2_RST_DIS BIT_32(2) +#define L2_PWR_CTL_L2_HS_CLAMP BIT_32(8) +#define L2_PWR_CTL_L2_HS_EN BIT_32(9) +#define L2_PWR_CTL_L2_HS_RST BIT_32(10) +#define L2_PWR_CTL_L2_SLEEP_STATE BIT_32(11) +#define L2_PWR_CTL_SYS_RESET BIT_32(12) +#define L2_PWR_CTL_L2_RET_SLP BIT_32(13) +#define L2_PWR_CTL_SCU_ARRAY_HS_CLAMP BIT_32(14) +#define L2_PWR_CTL_L2_ARRAY_HS_CLAMP BIT_32(15) +#define L2_PWR_CTL_L2_HS_CNT(cnt) ((cnt) << 16) +#define L2_PWR_CTL_PMIC_APC_ON BIT_32(28) + +#define L2_PWR_STATUS_L2_HS_STS BIT_32(9) + +#define CORE_CBCR_CLK_ENABLE BIT_32(0) +#define CORE_CBCR_HW_CTL BIT_32(1) + +/* Boot a secondary CPU core for the first time. */ +void msm8916_cpu_boot(uintptr_t acs) +{ + uint32_t pwr_ctl; + + VERBOSE("PSCI: Powering on CPU @ 0x%08lx\n", acs); + + pwr_ctl = CPU_PWR_CTL_CLAMP | CPU_PWR_CTL_CORE_MEM_CLAMP | + CPU_PWR_CTL_CORE_RST | CPU_PWR_CTL_COREPOR_RST; + mmio_write_32(acs + CPU_PWR_CTL, pwr_ctl); + dsb(); + + mmio_write_32(acs + APC_PWR_GATE_CTL, APC_PWR_GATE_CTL_GHDS_EN | + APC_PWR_GATE_CTL_GHDS_CNT(16)); + dsb(); + udelay(2); + + pwr_ctl &= ~CPU_PWR_CTL_CORE_MEM_CLAMP; + mmio_write_32(acs + CPU_PWR_CTL, pwr_ctl); + dsb(); + + pwr_ctl |= CPU_PWR_CTL_CORE_MEM_HS; + mmio_write_32(acs + CPU_PWR_CTL, pwr_ctl); + dsb(); + udelay(2); + + pwr_ctl &= ~CPU_PWR_CTL_CLAMP; + mmio_write_32(acs + CPU_PWR_CTL, pwr_ctl); + dsb(); + udelay(2); + + pwr_ctl &= ~(CPU_PWR_CTL_CORE_RST | CPU_PWR_CTL_COREPOR_RST); + mmio_write_32(acs + CPU_PWR_CTL, pwr_ctl); + dsb(); + + pwr_ctl |= CPU_PWR_CTL_CORE_PWRD_UP; + mmio_write_32(acs + CPU_PWR_CTL, pwr_ctl); + dsb(); +} + +/* Power on cluster L2 cache for the first time. */ +void msm8916_l2_boot(uintptr_t base) +{ + uint32_t pwr_ctl, cbcr, ovr; + + /* Skip if cluster L2 is already powered on */ + if (mmio_read_32(base + L2_PWR_STATUS) & L2_PWR_STATUS_L2_HS_STS) { + VERBOSE("PSCI: L2 cache @ 0x%08lx is already powered on\n", base); + return; + } + + VERBOSE("PSCI: Powering on L2 cache @ 0x%08lx\n", base); + + pwr_ctl = L2_PWR_CTL_L2_HS_CLAMP | L2_PWR_CTL_L2_HS_EN | + L2_PWR_CTL_L2_HS_RST | L2_PWR_CTL_SYS_RESET | + L2_PWR_CTL_SCU_ARRAY_HS_CLAMP | L2_PWR_CTL_L2_ARRAY_HS_CLAMP | + L2_PWR_CTL_L2_HS_CNT(16); + mmio_write_32(base + L2_PWR_CTL, pwr_ctl); + + ovr = PWR_CTL_OVERRIDE_PRESETDBG; + mmio_write_32(base + PWR_CTL_OVERRIDE, ovr); + dsb(); + udelay(2); + + pwr_ctl &= ~(L2_PWR_CTL_SCU_ARRAY_HS_CLAMP | + L2_PWR_CTL_L2_ARRAY_HS_CLAMP); + mmio_write_32(base + L2_PWR_CTL, pwr_ctl); + + pwr_ctl |= (L2_PWR_CTL_L2_ARRAY_HS | L2_PWR_CTL_SCU_ARRAY_HS); + mmio_write_32(base + L2_PWR_CTL, pwr_ctl); + dsb(); + udelay(2); + + cbcr = CORE_CBCR_CLK_ENABLE; + mmio_write_32(base + CORE_CBCR, cbcr); + + pwr_ctl &= ~L2_PWR_CTL_L2_HS_CLAMP; + mmio_write_32(base + L2_PWR_CTL, pwr_ctl); + dsb(); + udelay(2); + + ovr &= ~PWR_CTL_OVERRIDE_PRESETDBG; + mmio_write_32(base + PWR_CTL_OVERRIDE, ovr); + + pwr_ctl &= ~(L2_PWR_CTL_L2_HS_RST | L2_PWR_CTL_SYS_RESET); + mmio_write_32(base + L2_PWR_CTL, pwr_ctl); + dsb(); + udelay(54); + + pwr_ctl |= L2_PWR_CTL_PMIC_APC_ON; + mmio_write_32(base + L2_PWR_CTL, pwr_ctl); + + cbcr |= CORE_CBCR_HW_CTL; + mmio_write_32(base + CORE_CBCR, cbcr); + dsb(); +} diff --git a/plat/qti/msm8916/msm8916_gicv2.c b/plat/qti/msm8916/msm8916_gicv2.c new file mode 100644 index 0000000..82cecf2 --- /dev/null +++ b/plat/qti/msm8916/msm8916_gicv2.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net> + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <drivers/arm/gicv2.h> +#include <lib/mmio.h> + +#include "msm8916_gicv2.h" +#include <msm8916_mmap.h> +#include <platform_def.h> + +#define IRQ_SEC_SGI_0 8 +#define IRQ_SEC_SGI_1 9 +#define IRQ_SEC_SGI_2 10 +#define IRQ_SEC_SGI_3 11 +#define IRQ_SEC_SGI_4 12 +#define IRQ_SEC_SGI_5 13 +#define IRQ_SEC_SGI_6 14 +#define IRQ_SEC_SGI_7 15 + +static const interrupt_prop_t msm8916_interrupt_props[] = { + INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), +}; + +static const gicv2_driver_data_t msm8916_gic_data = { + .gicd_base = APCS_QGIC2_GICD, + .gicc_base = APCS_QGIC2_GICC, + .interrupt_props = msm8916_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(msm8916_interrupt_props), +}; + +void msm8916_gicv2_init(void) +{ + gicv2_driver_init(&msm8916_gic_data); +} + +void msm8916_gicv2_configure(void) +{ + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} diff --git a/plat/qti/msm8916/msm8916_gicv2.h b/plat/qti/msm8916/msm8916_gicv2.h new file mode 100644 index 0000000..919e294 --- /dev/null +++ b/plat/qti/msm8916/msm8916_gicv2.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net> + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MSM8916_GICV2_H +#define MSM8916_GICV2_H + +void msm8916_gicv2_init(void); +void msm8916_gicv2_configure(void); + +#endif /* MSM8916_GICV2_H */ diff --git a/plat/qti/msm8916/msm8916_pm.c b/plat/qti/msm8916/msm8916_pm.c new file mode 100644 index 0000000..fd44f04 --- /dev/null +++ b/plat/qti/msm8916/msm8916_pm.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2021-2022, Stephan Gerhold <stephan@gerhold.net> + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <arch.h> +#include <arch_helpers.h> +#include <common/debug.h> +#include <drivers/arm/cci.h> +#include <drivers/arm/gicv2.h> +#include <drivers/delay_timer.h> +#include <lib/mmio.h> +#include <lib/psci/psci.h> +#include <plat/common/platform.h> + +#include <msm8916_mmap.h> +#include "msm8916_pm.h" + +/* + * On platforms with two clusters the index of the APCS memory region is swapped + * compared to the MPIDR cluster affinity level: APCS cluster 0 manages CPUs + * with cluster affinity level 1, while APCS cluster 1 manages CPUs with level 0. + * + * On platforms with a single cluster there is only one APCS memory region. + */ +#if PLATFORM_CLUSTER_COUNT == 2 +#define MPIDR_APCS_CLUSTER(mpidr) !MPIDR_AFFLVL1_VAL(mpidr) +#else +#define MPIDR_APCS_CLUSTER(mpidr) 0 +#endif + +#define CLUSTER_PWR_STATE(state) ((state)->pwr_domain_state[MPIDR_AFFLVL1]) + +static int msm8916_pwr_domain_on(u_register_t mpidr) +{ + /* Should be never called on single-core platforms */ + if (PLATFORM_CORE_COUNT == 1) { + assert(false); + return PSCI_E_ALREADY_ON; + } + + /* Power on L2 cache and secondary CPU core for the first time */ + if (PLATFORM_CLUSTER_COUNT > 1) { + msm8916_l2_boot(APCS_GLB(MPIDR_APCS_CLUSTER(mpidr))); + } + msm8916_cpu_boot(APCS_ALIAS_ACS(MPIDR_APCS_CLUSTER(mpidr), + MPIDR_AFFLVL0_VAL(mpidr))); + return PSCI_E_SUCCESS; +} + +static void msm8916_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + /* Should be never called on single-core platforms */ + if (PLATFORM_CORE_COUNT == 1) { + assert(false); + return; + } + + if (PLATFORM_CLUSTER_COUNT > 1 && + CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + } + + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +static void __dead2 msm8916_system_reset(void) +{ + mmio_write_32(MPM_PS_HOLD, 0); + mdelay(1000); + + ERROR("PSCI: System reset failed\n"); + panic(); +} + +static const plat_psci_ops_t msm8916_psci_ops = { + .pwr_domain_on = msm8916_pwr_domain_on, + .pwr_domain_on_finish = msm8916_pwr_domain_on_finish, + .system_off = msm8916_system_reset, + .system_reset = msm8916_system_reset, +}; + +/* Defined and used in msm8916_helpers.S */ +extern uintptr_t msm8916_entry_point; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + /* + * The entry point is read with caches off (and even from two different + * physical addresses when read through the "boot remapper"), so make + * sure it is flushed to memory. + */ + msm8916_entry_point = sec_entrypoint; + flush_dcache_range((uintptr_t)&msm8916_entry_point, sizeof(uintptr_t)); + + *psci_ops = &msm8916_psci_ops; + return 0; +} diff --git a/plat/qti/msm8916/msm8916_pm.h b/plat/qti/msm8916/msm8916_pm.h new file mode 100644 index 0000000..f301d3c --- /dev/null +++ b/plat/qti/msm8916/msm8916_pm.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2021-2022, Stephan Gerhold <stephan@gerhold.net> + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MSM8916_PM_H +#define MSM8916_PM_H + +void msm8916_cpu_boot(uintptr_t acs); +void msm8916_l2_boot(uintptr_t base); + +#endif /* MSM8916_PM_H */ diff --git a/plat/qti/msm8916/msm8916_setup.c b/plat/qti/msm8916/msm8916_setup.c new file mode 100644 index 0000000..69c0d78 --- /dev/null +++ b/plat/qti/msm8916/msm8916_setup.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2021-2023, Stephan Gerhold <stephan@gerhold.net> + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/bl_common.h> +#include <drivers/console.h> +#include <drivers/generic_delay_timer.h> +#include <lib/mmio.h> +#include <lib/xlat_tables/xlat_mmu_helpers.h> +#include <lib/xlat_tables/xlat_tables_v2.h> + +#include "msm8916_gicv2.h" +#include <msm8916_mmap.h> +#include "msm8916_setup.h" +#include <uartdm_console.h> + +static const mmap_region_t msm8916_mmap[] = { + MAP_REGION_FLAT(PCNOC_BASE, PCNOC_SIZE, + MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER), + MAP_REGION_FLAT(APCS_BASE, APCS_SIZE, + MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER), + {}, +}; + +static console_t console; + +unsigned int plat_get_syscnt_freq2(void) +{ + return PLAT_SYSCNT_FREQ; +} + +#define GPIO_CFG_FUNC(n) ((n) << 2) +#define GPIO_CFG_DRV_STRENGTH_MA(ma) (((ma) / 2 - 1) << 6) + +#define CLK_ENABLE BIT_32(0) +#define CLK_OFF BIT_32(31) +#define GCC_BLSP1_AHB_CBCR (GCC_BASE + 0x01008) +#define GCC_BLSP1_UART_APPS_CBCR(n) (GCC_BASE + \ + (((n) == 2) ? (0x0302c) : (0x0203c + (((n) - 1) * 0x1000)))) +#define GCC_APCS_CLOCK_BRANCH_ENA_VOTE (GCC_BASE + 0x45004) +#define BLSP1_AHB_CLK_ENA BIT_32(10) + +struct uartdm_gpios { + unsigned int tx, rx, func; +}; + +static const struct uartdm_gpios uartdm_gpio_map[] = { +#if defined(PLAT_msm8909) + {4, 5, 0x2}, {20, 21, 0x3}, +#elif defined(PLAT_msm8916) || defined(PLAT_msm8939) + {0, 1, 0x2}, {4, 5, 0x2}, +#elif defined(PLAT_mdm9607) + {12, 13, 0x2}, {4, 5, 0x2}, {0, 1, 0x1}, + {16, 17, 0x2}, {8, 9, 0x2}, {20, 21, 0x2}, +#endif +}; + +/* + * The previous boot stage seems to disable most of the UART setup before exit + * so it must be enabled here again before the UART console can be used. + */ +static void msm8916_enable_blsp_uart(void) +{ + const struct uartdm_gpios *gpios = &uartdm_gpio_map[QTI_UART_NUM - 1]; + + CASSERT(QTI_UART_NUM > 0 && QTI_UART_NUM <= ARRAY_SIZE(uartdm_gpio_map), + assert_qti_blsp_uart_valid); + + /* Route GPIOs to BLSP UART */ + mmio_write_32(TLMM_GPIO_CFG(gpios->tx), GPIO_CFG_FUNC(gpios->func) | + GPIO_CFG_DRV_STRENGTH_MA(8)); + mmio_write_32(TLMM_GPIO_CFG(gpios->rx), GPIO_CFG_FUNC(gpios->func) | + GPIO_CFG_DRV_STRENGTH_MA(8)); + + /* Enable AHB clock */ + mmio_setbits_32(GCC_APCS_CLOCK_BRANCH_ENA_VOTE, BLSP1_AHB_CLK_ENA); + while (mmio_read_32(GCC_BLSP1_AHB_CBCR) & CLK_OFF) { + } + + /* Enable BLSP UART clock */ + mmio_setbits_32(GCC_BLSP1_UART_APPS_CBCR(QTI_UART_NUM), CLK_ENABLE); + while (mmio_read_32(GCC_BLSP1_UART_APPS_CBCR(QTI_UART_NUM)) & CLK_OFF) { + } +} + +void msm8916_early_platform_setup(void) +{ + /* Initialize the debug console as early as possible */ + msm8916_enable_blsp_uart(); + console_uartdm_register(&console, BLSP_UART_BASE); + + if (QTI_RUNTIME_UART) { + /* Mark UART as runtime usable */ + console_set_scope(&console, CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME | CONSOLE_FLAG_CRASH); + } +} + +void msm8916_plat_arch_setup(uintptr_t base, size_t size) +{ + mmap_add_region(base, base, size, MT_RW_DATA | MT_SECURE); + mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, + BL_CODE_END - BL_CODE_BASE, + MT_CODE | MT_SECURE); + mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE, + BL_RO_DATA_END - BL_RO_DATA_BASE, + MT_RO_DATA | MT_SECURE); + mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, + MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER); + + mmap_add(msm8916_mmap); + init_xlat_tables(); +} + +void msm8916_platform_setup(void) +{ + generic_delay_timer_init(); + msm8916_gicv2_init(); +} diff --git a/plat/qti/msm8916/msm8916_setup.h b/plat/qti/msm8916/msm8916_setup.h new file mode 100644 index 0000000..d2de943 --- /dev/null +++ b/plat/qti/msm8916/msm8916_setup.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2022-2023, Stephan Gerhold <stephan@gerhold.net> + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MSM8916_SETUP_H +#define MSM8916_SETUP_H + +void msm8916_early_platform_setup(void); +void msm8916_plat_arch_setup(uintptr_t base, size_t size); +void msm8916_platform_setup(void); + +#endif /* MSM8916_SETUP_H */ diff --git a/plat/qti/msm8916/msm8916_topology.c b/plat/qti/msm8916/msm8916_topology.c new file mode 100644 index 0000000..d8cdc0e --- /dev/null +++ b/plat/qti/msm8916/msm8916_topology.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022, Stephan Gerhold <stephan@gerhold.net> + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <plat/common/platform.h> + +#include <platform_def.h> + +static const unsigned char plat_power_domain_tree_desc[] = { + PLATFORM_SYSTEM_COUNT, + PLATFORM_CLUSTER_COUNT, + PLATFORM_CPUS_PER_CLUSTER, +#if PLATFORM_CLUSTER_COUNT > 1 + PLATFORM_CPUS_PER_CLUSTER, +#endif +}; + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster = MPIDR_AFFLVL1_VAL(mpidr); + unsigned int core = MPIDR_AFFLVL0_VAL(mpidr); + + if (MPIDR_AFFLVL3_VAL(mpidr) > 0 || + MPIDR_AFFLVL2_VAL(mpidr) > 0 || + cluster >= PLATFORM_CLUSTER_COUNT || + core >= PLATFORM_CPUS_PER_CLUSTER) { + return -1; + } + return core | (cluster << PLATFORM_CPU_PER_CLUSTER_SHIFT); +} + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return plat_power_domain_tree_desc; +} diff --git a/plat/qti/msm8916/platform.mk b/plat/qti/msm8916/platform.mk new file mode 100644 index 0000000..c71ad94 --- /dev/null +++ b/plat/qti/msm8916/platform.mk @@ -0,0 +1,98 @@ +# +# Copyright (c) 2021-2023, Stephan Gerhold <stephan@gerhold.net> +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include drivers/arm/gic/v2/gicv2.mk +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_BL_COMMON_SOURCES := ${GICV2_SOURCES} \ + ${XLAT_TABLES_LIB_SRCS} \ + drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + plat/common/plat_gicv2.c \ + plat/qti/msm8916/msm8916_gicv2.c \ + plat/qti/msm8916/msm8916_setup.c \ + plat/qti/msm8916/${ARCH}/msm8916_helpers.S \ + plat/qti/msm8916/${ARCH}/uartdm_console.S + +MSM8916_CPU := $(if ${ARM_CORTEX_A7},cortex_a7,cortex_a53) +MSM8916_PM_SOURCES := drivers/arm/cci/cci.c \ + lib/cpus/${ARCH}/${MSM8916_CPU}.S \ + plat/common/plat_psci_common.c \ + plat/qti/msm8916/msm8916_config.c \ + plat/qti/msm8916/msm8916_cpu_boot.c \ + plat/qti/msm8916/msm8916_pm.c \ + plat/qti/msm8916/msm8916_topology.c + +BL31_SOURCES += ${MSM8916_PM_SOURCES} \ + plat/qti/msm8916/msm8916_bl31_setup.c + +PLAT_INCLUDES := -Iplat/qti/msm8916/include + +ifeq (${ARCH},aarch64) +# arm_macros.S exists only on aarch64 currently +PLAT_INCLUDES += -Iinclude/plat/arm/common/${ARCH} +endif + +# Only BL31 is supported at the moment and is entered on a single CPU +RESET_TO_BL31 := 1 +COLD_BOOT_SINGLE_CPU := 1 + +# Have different sections for code and rodata +SEPARATE_CODE_AND_RODATA := 1 + +# Single cluster +WARMBOOT_ENABLE_DCACHE_EARLY := 1 + +# Disable features unsupported in ARMv8.0 +ENABLE_SPE_FOR_NS := 0 +ENABLE_SVE_FOR_NS := 0 + +# Disable workarounds unnecessary for Cortex-A7/A53 +WORKAROUND_CVE_2017_5715 := 0 +WORKAROUND_CVE_2022_23960 := 0 + +ifeq (${MSM8916_CPU},cortex_a53) +# The Cortex-A53 revision varies depending on the SoC revision. +# msm8916 uses r0p0, msm8939 uses r0p1 or r0p4. Enable all errata +# and rely on the runtime detection to apply them only if needed. +ERRATA_A53_819472 := 1 +ERRATA_A53_824069 := 1 +ERRATA_A53_826319 := 1 +ERRATA_A53_827319 := 1 +ERRATA_A53_835769 := 1 +ERRATA_A53_836870 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 +ERRATA_A53_1530924 := 1 +endif + +# Build config flags +# ------------------ +BL31_BASE ?= 0x86500000 +PRELOADED_BL33_BASE ?= 0x8f600000 + +ifeq (${ARCH},aarch64) + BL32_BASE ?= BL31_LIMIT + $(eval $(call add_define,BL31_BASE)) +else + ifeq (${AARCH32_SP},none) + $(error Variable AARCH32_SP has to be set for AArch32) + endif + # There is no BL31 on aarch32, so reuse its location for BL32 + BL32_BASE ?= $(BL31_BASE) +endif +$(eval $(call add_define,BL32_BASE)) + +# UART number to use for TF-A output during early boot +QTI_UART_NUM ?= 2 +$(eval $(call assert_numeric,QTI_UART_NUM)) +$(eval $(call add_define,QTI_UART_NUM)) + +# Set to 1 on the command line to keep using UART after early boot. +# Requires reserving the UART and related clocks inside the normal world. +QTI_RUNTIME_UART ?= 0 +$(eval $(call assert_boolean,QTI_RUNTIME_UART)) +$(eval $(call add_define,QTI_RUNTIME_UART)) diff --git a/plat/qti/msm8916/sp_min/msm8916_sp_min_setup.c b/plat/qti/msm8916/sp_min/msm8916_sp_min_setup.c new file mode 100644 index 0000000..3c93305 --- /dev/null +++ b/plat/qti/msm8916/sp_min/msm8916_sp_min_setup.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022-2023, Stephan Gerhold <stephan@gerhold.net> + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <common/debug.h> +#include <lib/xlat_tables/xlat_mmu_helpers.h> +#include <platform_sp_min.h> + +#include "../msm8916_config.h" +#include "../msm8916_setup.h" + +static struct { + entry_point_info_t bl33; +} image_ep_info = { + /* BL33 entry point */ + SET_STATIC_PARAM_HEAD(bl33, PARAM_EP, VERSION_1, + entry_point_info_t, NON_SECURE), + .bl33.pc = PRELOADED_BL33_BASE, + .bl33.spsr = SPSR_MODE32(MODE32_hyp, SPSR_T_ARM, SPSR_E_LITTLE, + DISABLE_ALL_EXCEPTIONS), +}; + +void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + msm8916_early_platform_setup(); + msm8916_configure_early(); +} + +void sp_min_plat_arch_setup(void) +{ + msm8916_plat_arch_setup(BL32_BASE, BL32_END - BL32_BASE); + enable_mmu_svc_mon(0); +} + +void sp_min_platform_setup(void) +{ + INFO("SP_MIN: Platform setup start\n"); + msm8916_platform_setup(); + msm8916_configure(); + INFO("SP_MIN: Platform setup done\n"); +} + +entry_point_info_t *sp_min_plat_get_bl33_ep_info(void) +{ + return &image_ep_info.bl33; +} diff --git a/plat/qti/msm8916/sp_min/sp_min-msm8916.mk b/plat/qti/msm8916/sp_min/sp_min-msm8916.mk new file mode 100644 index 0000000..be07f94 --- /dev/null +++ b/plat/qti/msm8916/sp_min/sp_min-msm8916.mk @@ -0,0 +1,11 @@ +# +# Copyright (c) 2022-2023, Stephan Gerhold <stephan@gerhold.net> +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL32_SOURCES += ${MSM8916_PM_SOURCES} \ + plat/common/${ARCH}/platform_mp_stack.S \ + plat/qti/msm8916/sp_min/msm8916_sp_min_setup.c + +override RESET_TO_SP_MIN := 1 diff --git a/plat/qti/msm8916/tsp/msm8916_tsp_setup.c b/plat/qti/msm8916/tsp/msm8916_tsp_setup.c new file mode 100644 index 0000000..218af57 --- /dev/null +++ b/plat/qti/msm8916/tsp/msm8916_tsp_setup.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023, Stephan Gerhold <stephan@gerhold.net> + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <platform_tsp.h> + +#include "../msm8916_setup.h" +#include <platform_def.h> + +void tsp_early_platform_setup(void) +{ + msm8916_early_platform_setup(); +} + +void tsp_plat_arch_setup(void) +{ + msm8916_plat_arch_setup(BL32_BASE, BL32_END - BL32_BASE); + enable_mmu_el1(0); +} + +void tsp_platform_setup(void) +{ + INFO("TSP: Platform setup start\n"); + msm8916_platform_setup(); + INFO("TSP: Platform setup done\n"); + + console_switch_state(CONSOLE_FLAG_RUNTIME); +} diff --git a/plat/qti/msm8916/tsp/tsp-msm8916.mk b/plat/qti/msm8916/tsp/tsp-msm8916.mk new file mode 100644 index 0000000..0d50058 --- /dev/null +++ b/plat/qti/msm8916/tsp/tsp-msm8916.mk @@ -0,0 +1,8 @@ +# +# Copyright (c) 2023, Stephan Gerhold <stephan@gerhold.net> +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL32_SOURCES += plat/common/${ARCH}/platform_mp_stack.S \ + plat/qti/msm8916/tsp/msm8916_tsp_setup.c |