From 07aa0c7e0e13db4b22de135247b4aa3a5b18f15b Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Thu, 12 Mar 2020 14:20:04 +0000 Subject: rpi: move plat_helpers.S to common The plat_helpers.S file was almost identical between its RPi3 and RPi4 versions. Unify the two files, moving it into the common/ directory. This adds a plat_rpi_get_model() function, which can be used to trigger RPi4 specific action, detected at runtime. We use that to do the RPi4 specific L2 cache initialisation. Change-Id: I2295704fd6dde7c76fe83b6d98c7bf998d4bf074 Signed-off-by: Andre Przywara --- plat/rpi/common/aarch64/plat_helpers.S | 214 +++++++++++++++++++++++++++++++++ plat/rpi/common/include/rpi_shared.h | 2 + plat/rpi/rpi3/aarch64/plat_helpers.S | 163 ------------------------- plat/rpi/rpi3/include/platform_def.h | 2 +- plat/rpi/rpi3/platform.mk | 4 +- plat/rpi/rpi4/aarch64/plat_helpers.S | 185 ---------------------------- plat/rpi/rpi4/include/platform_def.h | 2 +- plat/rpi/rpi4/platform.mk | 2 +- 8 files changed, 220 insertions(+), 354 deletions(-) create mode 100644 plat/rpi/common/aarch64/plat_helpers.S delete mode 100644 plat/rpi/rpi3/aarch64/plat_helpers.S delete mode 100644 plat/rpi/rpi4/aarch64/plat_helpers.S diff --git a/plat/rpi/common/aarch64/plat_helpers.S b/plat/rpi/common/aarch64/plat_helpers.S new file mode 100644 index 000000000..93c8f7f7f --- /dev/null +++ b/plat/rpi/common/aarch64/plat_helpers.S @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .globl plat_crash_console_flush + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl platform_mem_init + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_reset_handler + .globl plat_rpi3_calc_core_pos + .globl plat_secondary_cold_boot_setup + .globl plat_rpi_get_model + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * + * This function uses the plat_rpi3_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b plat_rpi3_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr); + * + * CorePos = (ClusterId * 4) + CoreId + * ----------------------------------------------------- + */ +func plat_rpi3_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_rpi3_calc_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary + * cpu. + * ----------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #RPI_PRIMARY_CPU + cset w0, eq + ret +endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + /* Calculate address of our hold entry */ + bl plat_my_core_pos + lsl x0, x0, #3 + mov_imm x2, PLAT_RPI3_TM_HOLD_BASE + add x0, x0, x2 + + /* + * This code runs way before requesting the warmboot of this core, + * so it is possible to clear the mailbox before getting a request + * to boot. + */ + mov x1, PLAT_RPI3_TM_HOLD_STATE_WAIT + str x1,[x0] + + /* Wait until we have a go */ +poll_mailbox: + wfe + ldr x1, [x0] + cmp x1, PLAT_RPI3_TM_HOLD_STATE_GO + bne poll_mailbox + + /* Jump to the provided entrypoint */ + mov_imm x0, PLAT_RPI3_TM_ENTRYPOINT + ldr x1, [x0] + br x1 +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * uintptr_t plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and a warm + * boot. + * + * This functions returns: + * - 0 for a cold boot. + * - Any other value for a warm boot. + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* TODO: support warm boot */ + mov x0, #0 + ret +endfunc plat_get_my_entrypoint + + /* --------------------------------------------- + * void platform_mem_init (void); + * + * No need to carry out any memory initialization. + * --------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0 - x3 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, PLAT_RPI_MINI_UART_BASE + mov x1, xzr + mov x2, xzr + b console_16550_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, PLAT_RPI_MINI_UART_BASE + b console_16550_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * int plat_crash_console_flush() + * Function to force a write of all buffered + * data that hasn't been output. + * Out : return -1 on error else return 0. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x0, PLAT_RPI_MINI_UART_BASE + b console_16550_core_flush +endfunc plat_crash_console_flush + + /* --------------------------------------------- + * int plat_rpi_get_model() + * Macro to determine whether we are running on + * a Raspberry Pi 3 or 4. Just checks the MIDR for + * being either a Cortex-A72 or a Cortex-A53. + * Out : return 4 if RPi4, 3 otherwise. + * Clobber list : x0 + * --------------------------------------------- + */ + .macro _plat_rpi_get_model + mrs x0, midr_el1 + and x0, x0, #0xf0 /* Isolate low byte of part number */ + cmp w0, #0x80 /* Cortex-A72 (RPi4) is 0xd08, A53 is 0xd03 */ + mov w0, #3 + csinc w0, w0, w0, ne + .endm + + func plat_rpi_get_model + _plat_rpi_get_model + ret + endfunc plat_rpi_get_model + + /* --------------------------------------------- + * void plat_reset_handler(void); + * --------------------------------------------- + */ +func plat_reset_handler + /* L2 cache setup only needed on RPi4 */ + _plat_rpi_get_model + cmp w0, #4 + b.ne 1f + + /* ------------------------------------------------ + * Set L2 read/write cache latency: + * - L2 Data RAM latency: 3 cycles (0b010) + * - L2 Data RAM setup: 1 cycle (bit 5) + * ------------------------------------------------ + */ + mrs x0, CORTEX_A72_L2CTLR_EL1 + mov x1, #0x22 + orr x0, x0, x1 + msr CORTEX_A72_L2CTLR_EL1, x0 + isb + +1: + ret +endfunc plat_reset_handler diff --git a/plat/rpi/common/include/rpi_shared.h b/plat/rpi/common/include/rpi_shared.h index 686343892..ddf239eb5 100644 --- a/plat/rpi/common/include/rpi_shared.h +++ b/plat/rpi/common/include/rpi_shared.h @@ -36,4 +36,6 @@ void plat_rpi3_io_setup(void); /* VideoCore firmware commands */ int rpi3_vc_hardware_get_board_revision(uint32_t *revision); +int plat_rpi_get_model(void); + #endif /* RPI3_PRIVATE_H */ diff --git a/plat/rpi/rpi3/aarch64/plat_helpers.S b/plat/rpi/rpi3/aarch64/plat_helpers.S deleted file mode 100644 index ab925b6c0..000000000 --- a/plat/rpi/rpi3/aarch64/plat_helpers.S +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include -#include -#include -#include - - .globl plat_crash_console_flush - .globl plat_crash_console_init - .globl plat_crash_console_putc - .globl platform_mem_init - .globl plat_get_my_entrypoint - .globl plat_is_my_cpu_primary - .globl plat_my_core_pos - .globl plat_rpi3_calc_core_pos - .globl plat_secondary_cold_boot_setup - - /* ----------------------------------------------------- - * unsigned int plat_my_core_pos(void) - * - * This function uses the plat_rpi3_calc_core_pos() - * definition to get the index of the calling CPU. - * ----------------------------------------------------- - */ -func plat_my_core_pos - mrs x0, mpidr_el1 - b plat_rpi3_calc_core_pos -endfunc plat_my_core_pos - - /* ----------------------------------------------------- - * unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr); - * - * CorePos = (ClusterId * 4) + CoreId - * ----------------------------------------------------- - */ -func plat_rpi3_calc_core_pos - and x1, x0, #MPIDR_CPU_MASK - and x0, x0, #MPIDR_CLUSTER_MASK - add x0, x1, x0, LSR #6 - ret -endfunc plat_rpi3_calc_core_pos - - /* ----------------------------------------------------- - * unsigned int plat_is_my_cpu_primary (void); - * - * Find out whether the current cpu is the primary - * cpu. - * ----------------------------------------------------- - */ -func plat_is_my_cpu_primary - mrs x0, mpidr_el1 - and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) - cmp x0, #RPI3_PRIMARY_CPU - cset w0, eq - ret -endfunc plat_is_my_cpu_primary - - /* ----------------------------------------------------- - * void plat_secondary_cold_boot_setup (void); - * - * This function performs any platform specific actions - * needed for a secondary cpu after a cold reset e.g - * mark the cpu's presence, mechanism to place it in a - * holding pen etc. - * ----------------------------------------------------- - */ -func plat_secondary_cold_boot_setup - /* Calculate address of our hold entry */ - bl plat_my_core_pos - lsl x0, x0, #3 - mov_imm x2, PLAT_RPI3_TM_HOLD_BASE - add x0, x0, x2 - - /* - * This code runs way before requesting the warmboot of this core, - * so it is possible to clear the mailbox before getting a request - * to boot. - */ - mov x1, PLAT_RPI3_TM_HOLD_STATE_WAIT - str x1,[x0] - - /* Wait until we have a go */ -poll_mailbox: - wfe - ldr x1, [x0] - cmp x1, PLAT_RPI3_TM_HOLD_STATE_GO - bne poll_mailbox - - /* Jump to the provided entrypoint */ - mov_imm x0, PLAT_RPI3_TM_ENTRYPOINT - ldr x1, [x0] - br x1 -endfunc plat_secondary_cold_boot_setup - - /* --------------------------------------------------------------------- - * uintptr_t plat_get_my_entrypoint (void); - * - * Main job of this routine is to distinguish between a cold and a warm - * boot. - * - * This functions returns: - * - 0 for a cold boot. - * - Any other value for a warm boot. - * --------------------------------------------------------------------- - */ -func plat_get_my_entrypoint - /* TODO: support warm boot */ - mov x0, #0 - ret -endfunc plat_get_my_entrypoint - - /* --------------------------------------------- - * void platform_mem_init (void); - * - * No need to carry out any memory initialization. - * --------------------------------------------- - */ -func platform_mem_init - ret -endfunc platform_mem_init - - /* --------------------------------------------- - * int plat_crash_console_init(void) - * Function to initialize the crash console - * without a C Runtime to print crash report. - * Clobber list : x0 - x3 - * --------------------------------------------- - */ -func plat_crash_console_init - mov_imm x0, PLAT_RPI_MINI_UART_BASE - mov x1, xzr - mov x2, xzr - b console_16550_core_init -endfunc plat_crash_console_init - - /* --------------------------------------------- - * int plat_crash_console_putc(int c) - * Function to print a character on the crash - * console without a C Runtime. - * Clobber list : x1, x2 - * --------------------------------------------- - */ -func plat_crash_console_putc - mov_imm x1, PLAT_RPI_MINI_UART_BASE - b console_16550_core_putc -endfunc plat_crash_console_putc - - /* --------------------------------------------- - * int plat_crash_console_flush() - * Function to force a write of all buffered - * data that hasn't been output. - * Out : return -1 on error else return 0. - * Clobber list : x0, x1 - * --------------------------------------------- - */ -func plat_crash_console_flush - mov_imm x0, PLAT_RPI_MINI_UART_BASE - b console_16550_core_flush -endfunc plat_crash_console_flush diff --git a/plat/rpi/rpi3/include/platform_def.h b/plat/rpi/rpi3/include/platform_def.h index 9cacd9915..2bcf53ee9 100644 --- a/plat/rpi/rpi3/include/platform_def.h +++ b/plat/rpi/rpi3/include/platform_def.h @@ -24,7 +24,7 @@ #define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER #define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT -#define RPI3_PRIMARY_CPU U(0) +#define RPI_PRIMARY_CPU U(0) #define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 #define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ diff --git a/plat/rpi/rpi3/platform.mk b/plat/rpi/rpi3/platform.mk index a5b8904d5..bcfc34e20 100644 --- a/plat/rpi/rpi3/platform.mk +++ b/plat/rpi/rpi3/platform.mk @@ -15,6 +15,7 @@ PLAT_BL_COMMON_SOURCES := drivers/ti/uart/aarch64/16550_console.S \ drivers/gpio/gpio.c \ drivers/delay_timer/delay_timer.c \ drivers/rpi3/gpio/rpi3_gpio.c \ + plat/rpi/common/aarch64/plat_helpers.S \ plat/rpi/common/rpi3_common.c \ ${XLAT_TABLES_LIB_SRCS} @@ -23,7 +24,6 @@ BL1_SOURCES += drivers/io/io_fip.c \ drivers/io/io_storage.c \ lib/cpus/aarch64/cortex_a53.S \ plat/common/aarch64/platform_mp_stack.S \ - plat/rpi/rpi3/aarch64/plat_helpers.S \ plat/rpi/rpi3/rpi3_bl1_setup.c \ plat/rpi/common/rpi3_io_storage.c \ drivers/rpi3/mailbox/rpi3_mbox.c \ @@ -38,7 +38,6 @@ BL2_SOURCES += common/desc_image_load.c \ drivers/mmc/mmc.c \ drivers/rpi3/sdhost/rpi3_sdhost.c \ plat/common/aarch64/platform_mp_stack.S \ - plat/rpi/rpi3/aarch64/plat_helpers.S \ plat/rpi/rpi3/aarch64/rpi3_bl2_mem_params_desc.c \ plat/rpi/rpi3/rpi3_bl2_setup.c \ plat/rpi/common/rpi3_image_load.c \ @@ -46,7 +45,6 @@ BL2_SOURCES += common/desc_image_load.c \ BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ plat/common/plat_psci_common.c \ - plat/rpi/rpi3/aarch64/plat_helpers.S \ plat/rpi/rpi3/rpi3_bl31_setup.c \ plat/rpi/common/rpi3_pm.c \ plat/rpi/common/rpi3_topology.c \ diff --git a/plat/rpi/rpi4/aarch64/plat_helpers.S b/plat/rpi/rpi4/aarch64/plat_helpers.S deleted file mode 100644 index fac1b2075..000000000 --- a/plat/rpi/rpi4/aarch64/plat_helpers.S +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include -#include -#include -#include -#include - - .globl plat_crash_console_flush - .globl plat_crash_console_init - .globl plat_crash_console_putc - .globl platform_mem_init - .globl plat_get_my_entrypoint - .globl plat_is_my_cpu_primary - .globl plat_my_core_pos - .globl plat_reset_handler - .globl plat_rpi3_calc_core_pos - .globl plat_secondary_cold_boot_setup - - /* ----------------------------------------------------- - * unsigned int plat_my_core_pos(void) - * - * This function uses the plat_rpi3_calc_core_pos() - * definition to get the index of the calling CPU. - * ----------------------------------------------------- - */ -func plat_my_core_pos - mrs x0, mpidr_el1 - b plat_rpi3_calc_core_pos -endfunc plat_my_core_pos - - /* ----------------------------------------------------- - * unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr); - * - * CorePos = (ClusterId * 4) + CoreId - * ----------------------------------------------------- - */ -func plat_rpi3_calc_core_pos - and x1, x0, #MPIDR_CPU_MASK - and x0, x0, #MPIDR_CLUSTER_MASK - add x0, x1, x0, LSR #6 - ret -endfunc plat_rpi3_calc_core_pos - - /* ----------------------------------------------------- - * unsigned int plat_is_my_cpu_primary (void); - * - * Find out whether the current cpu is the primary - * cpu. - * ----------------------------------------------------- - */ -func plat_is_my_cpu_primary - mrs x0, mpidr_el1 - and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) - cmp x0, #RPI4_PRIMARY_CPU - cset w0, eq - ret -endfunc plat_is_my_cpu_primary - - /* ----------------------------------------------------- - * void plat_secondary_cold_boot_setup (void); - * - * This function performs any platform specific actions - * needed for a secondary cpu after a cold reset e.g - * mark the cpu's presence, mechanism to place it in a - * holding pen etc. - * ----------------------------------------------------- - */ -func plat_secondary_cold_boot_setup - /* Calculate address of our hold entry */ - bl plat_my_core_pos - lsl x0, x0, #3 - mov_imm x2, PLAT_RPI3_TM_HOLD_BASE - add x0, x0, x2 - - /* - * This code runs way before requesting the warmboot of this core, - * so it is possible to clear the mailbox before getting a request - * to boot. - */ - mov x1, PLAT_RPI3_TM_HOLD_STATE_WAIT - str x1,[x0] - - /* Wait until we have a go */ -poll_mailbox: - wfe - ldr x1, [x0] - cmp x1, PLAT_RPI3_TM_HOLD_STATE_GO - bne poll_mailbox - - /* Jump to the provided entrypoint */ - mov_imm x0, PLAT_RPI3_TM_ENTRYPOINT - ldr x1, [x0] - br x1 -endfunc plat_secondary_cold_boot_setup - - /* --------------------------------------------------------------------- - * uintptr_t plat_get_my_entrypoint (void); - * - * Main job of this routine is to distinguish between a cold and a warm - * boot. - * - * This functions returns: - * - 0 for a cold boot. - * - Any other value for a warm boot. - * --------------------------------------------------------------------- - */ -func plat_get_my_entrypoint - /* TODO: support warm boot */ - mov x0, #0 - ret -endfunc plat_get_my_entrypoint - - /* --------------------------------------------- - * void platform_mem_init (void); - * - * No need to carry out any memory initialization. - * --------------------------------------------- - */ -func platform_mem_init - ret -endfunc platform_mem_init - - /* --------------------------------------------- - * int plat_crash_console_init(void) - * Function to initialize the crash console - * without a C Runtime to print crash report. - * Clobber list : x0 - x3 - * --------------------------------------------- - */ -func plat_crash_console_init - mov_imm x0, PLAT_RPI_MINI_UART_BASE - mov x1, xzr - mov x2, xzr - b console_16550_core_init -endfunc plat_crash_console_init - - /* --------------------------------------------- - * int plat_crash_console_putc(int c) - * Function to print a character on the crash - * console without a C Runtime. - * Clobber list : x1, x2 - * --------------------------------------------- - */ -func plat_crash_console_putc - mov_imm x1, PLAT_RPI_MINI_UART_BASE - b console_16550_core_putc -endfunc plat_crash_console_putc - - /* --------------------------------------------- - * int plat_crash_console_flush() - * Function to force a write of all buffered - * data that hasn't been output. - * Out : return -1 on error else return 0. - * Clobber list : x0, x1 - * --------------------------------------------- - */ -func plat_crash_console_flush - mov_imm x0, PLAT_RPI_MINI_UART_BASE - b console_16550_core_flush -endfunc plat_crash_console_flush - - /* --------------------------------------------- - * void plat_reset_handler(void); - * --------------------------------------------- - */ -func plat_reset_handler - /* ------------------------------------------------ - * Set L2 read/write cache latency: - * - L2 Data RAM latency: 3 cycles (0b010) - * - L2 Data RAM setup: 1 cycle (bit 5) - * ------------------------------------------------ - */ - mrs x0, CORTEX_A72_L2CTLR_EL1 - mov x1, #0x22 - orr x0, x0, x1 - msr CORTEX_A72_L2CTLR_EL1, x0 - isb - - ret -endfunc plat_reset_handler diff --git a/plat/rpi/rpi4/include/platform_def.h b/plat/rpi/rpi4/include/platform_def.h index 6f6bbbe7a..d03eea6e9 100644 --- a/plat/rpi/rpi4/include/platform_def.h +++ b/plat/rpi/rpi4/include/platform_def.h @@ -24,7 +24,7 @@ #define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER #define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT -#define RPI4_PRIMARY_CPU U(0) +#define RPI_PRIMARY_CPU U(0) #define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 #define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ diff --git a/plat/rpi/rpi4/platform.mk b/plat/rpi/rpi4/platform.mk index 49e78dfed..0744bceb4 100644 --- a/plat/rpi/rpi4/platform.mk +++ b/plat/rpi/rpi4/platform.mk @@ -16,7 +16,7 @@ PLAT_BL_COMMON_SOURCES := drivers/ti/uart/aarch64/16550_console.S \ ${XLAT_TABLES_LIB_SRCS} BL31_SOURCES += lib/cpus/aarch64/cortex_a72.S \ - plat/rpi/rpi4/aarch64/plat_helpers.S \ + plat/rpi/common/aarch64/plat_helpers.S \ plat/rpi/rpi4/aarch64/armstub8_header.S \ drivers/arm/gic/common/gic_common.c \ drivers/arm/gic/v2/gicv2_helpers.c \ -- cgit v1.2.3 From af2a4877a76498a03edb12908164978a7ab0c7fe Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Sat, 21 Mar 2020 11:22:13 +0000 Subject: rpi: rpi3_pwr_domain_on(): Use MMIO accessor When writing to arbitrary locations in memory using a constructed pointer, there is no guarantee that the compiler does not optimise away the access, since it cannot detect any dependency. One typical solution is to use the "volatile" keyword, but using MMIO accessors in usually the better answer, to avoid torn writes. Replace the usage of an array with such an MMIO accessor function in rpi3_pwr_domain_on(), to make sure the write is really happening. Change-Id: Ia18163c95e92f1557471089fd18abc6dc7fee0c7 Signed-off-by: Andre Przywara --- plat/rpi/common/rpi3_pm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plat/rpi/common/rpi3_pm.c b/plat/rpi/common/rpi3_pm.c index 2a6bf076b..83270260f 100644 --- a/plat/rpi/common/rpi3_pm.c +++ b/plat/rpi/common/rpi3_pm.c @@ -140,11 +140,14 @@ static int rpi3_pwr_domain_on(u_register_t mpidr) { int rc = PSCI_E_SUCCESS; unsigned int pos = plat_core_pos_by_mpidr(mpidr); - uint64_t *hold_base = (uint64_t *)PLAT_RPI3_TM_HOLD_BASE; + uintptr_t hold_base = PLAT_RPI3_TM_HOLD_BASE; assert(pos < PLATFORM_CORE_COUNT); - hold_base[pos] = PLAT_RPI3_TM_HOLD_STATE_GO; + hold_base += pos * PLAT_RPI3_TM_HOLD_ENTRY_SIZE; + + mmio_write_64(hold_base, PLAT_RPI3_TM_HOLD_STATE_GO); + /* No cache maintenance here, hold_base is mapped as device memory. */ /* Make sure that the write has completed */ dsb(); -- cgit v1.2.3 From 2e5f84432dabd74cbcd045e5007e02c7d3b25a91 Mon Sep 17 00:00:00 2001 From: Andrei Warkentin Date: Wed, 11 Mar 2020 22:11:06 -0700 Subject: rpi: Implement PSCI CPU_OFF We simulate the PSCI CPU_OFF operation by reseting the core via RMR. For secondaries, that already puts them in the holding pen waiting for a "warm boot" request as part of PSCI CPU_ON. For the BSP, we have to add logic to distinguish a regular boot from a CPU_OFF state, where, like the secondaries, the BSP needs to wait foor a "warm boot" request as part of CPU_ON. Testing done: - ACS suite now passes more tests (since it repeatedly calls code on secondaries via CPU_ON). - Linux testing including offlining/onlineing CPU0, e.g. "echo 0 > /sys/devices/system/cpu/cpu0/online". Change-Id: Id0ae11a0ee0721b20fa2578b54dadc72dcbd69e0 Link: https://developer.trustedfirmware.org/T686 Signed-off-by: Andrei Warkentin [Andre: adapt to unified plat_helpers.S, smaller fixes] Signed-off-by: Andre Przywara --- plat/rpi/common/aarch64/plat_helpers.S | 50 +++++++++++++++++++++++++++------- plat/rpi/common/rpi3_pm.c | 27 ++++++++++++++++++ plat/rpi/rpi3/include/platform_def.h | 1 + plat/rpi/rpi4/include/platform_def.h | 1 + 4 files changed, 69 insertions(+), 10 deletions(-) diff --git a/plat/rpi/common/aarch64/plat_helpers.S b/plat/rpi/common/aarch64/plat_helpers.S index 93c8f7f7f..e21233a1d 100644 --- a/plat/rpi/common/aarch64/plat_helpers.S +++ b/plat/rpi/common/aarch64/plat_helpers.S @@ -63,21 +63,23 @@ func plat_is_my_cpu_primary endfunc plat_is_my_cpu_primary /* ----------------------------------------------------- - * void plat_secondary_cold_boot_setup (void); + * void plat_wait_for_warm_boot (void); * * This function performs any platform specific actions - * needed for a secondary cpu after a cold reset e.g - * mark the cpu's presence, mechanism to place it in a - * holding pen etc. + * needed for a CPU to be put into holding pen to wait + * for a warm boot request. + * The function will never return. * ----------------------------------------------------- */ -func plat_secondary_cold_boot_setup - /* Calculate address of our hold entry */ +func plat_wait_for_warm_boot + /* + * Calculate address of our hold entry. + * As the function will never return, there is no need to save LR. + */ bl plat_my_core_pos lsl x0, x0, #3 mov_imm x2, PLAT_RPI3_TM_HOLD_BASE add x0, x0, x2 - /* * This code runs way before requesting the warmboot of this core, * so it is possible to clear the mailbox before getting a request @@ -97,6 +99,19 @@ poll_mailbox: mov_imm x0, PLAT_RPI3_TM_ENTRYPOINT ldr x1, [x0] br x1 +endfunc plat_wait_for_warm_boot + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + b plat_wait_for_warm_boot endfunc plat_secondary_cold_boot_setup /* --------------------------------------------------------------------- @@ -111,9 +126,24 @@ endfunc plat_secondary_cold_boot_setup * --------------------------------------------------------------------- */ func plat_get_my_entrypoint - /* TODO: support warm boot */ - mov x0, #0 - ret + mov x1, x30 + bl plat_is_my_cpu_primary + /* + * Secondaries always cold boot. + */ + cbz w0, 1f + /* + * Primaries warm boot if they are requested + * to power off. + */ + mov_imm x0, PLAT_RPI3_TM_HOLD_BASE + ldr x0, [x0] + cmp x0, PLAT_RPI3_TM_HOLD_STATE_BSP_OFF + adr x0, plat_wait_for_warm_boot + csel x0, x0, xzr, eq + ret x1 +1: mov x0, #0 + ret x1 endfunc plat_get_my_entrypoint /* --------------------------------------------- diff --git a/plat/rpi/common/rpi3_pm.c b/plat/rpi/common/rpi3_pm.c index 83270260f..86c61f7a6 100644 --- a/plat/rpi/common/rpi3_pm.c +++ b/plat/rpi/common/rpi3_pm.c @@ -174,6 +174,32 @@ static void rpi3_pwr_domain_on_finish(const psci_power_state_t *target_state) #endif } +static void __dead2 rpi3_pwr_down_wfi( + const psci_power_state_t *target_state) +{ + uintptr_t hold_base = PLAT_RPI3_TM_HOLD_BASE; + unsigned int pos = plat_my_core_pos(); + + if (pos == 0) { + /* + * The secondaries will always be in a wait + * for warm boot on reset, but the BSP needs + * to be able to distinguish between waiting + * for warm boot (e.g. after psci_off, waiting + * for psci_on) and a cold boot. + */ + mmio_write_64(hold_base, PLAT_RPI3_TM_HOLD_STATE_BSP_OFF); + /* No cache maintenance here, we run with caches off already. */ + dsb(); + isb(); + } + + write_rmr_el3(RMR_EL3_RR_BIT | RMR_EL3_AA64_BIT); + + while (1) + ; +} + /******************************************************************************* * Platform handlers for system reset and system off. ******************************************************************************/ @@ -239,6 +265,7 @@ static const plat_psci_ops_t plat_rpi3_psci_pm_ops = { .pwr_domain_pwr_down_wfi = rpi3_pwr_domain_pwr_down_wfi, .pwr_domain_on = rpi3_pwr_domain_on, .pwr_domain_on_finish = rpi3_pwr_domain_on_finish, + .pwr_domain_pwr_down_wfi = rpi3_pwr_down_wfi, .system_off = rpi3_system_off, .system_reset = rpi3_system_reset, .validate_power_state = rpi3_validate_power_state, diff --git a/plat/rpi/rpi3/include/platform_def.h b/plat/rpi/rpi3/include/platform_def.h index 2bcf53ee9..f44d1f526 100644 --- a/plat/rpi/rpi3/include/platform_def.h +++ b/plat/rpi/rpi3/include/platform_def.h @@ -153,6 +153,7 @@ #define PLAT_RPI3_TM_HOLD_STATE_WAIT ULL(0) #define PLAT_RPI3_TM_HOLD_STATE_GO ULL(1) +#define PLAT_RPI3_TM_HOLD_STATE_BSP_OFF ULL(2) /* * BL1 specific defines. diff --git a/plat/rpi/rpi4/include/platform_def.h b/plat/rpi/rpi4/include/platform_def.h index d03eea6e9..6787ebfee 100644 --- a/plat/rpi/rpi4/include/platform_def.h +++ b/plat/rpi/rpi4/include/platform_def.h @@ -93,6 +93,7 @@ #define PLAT_RPI3_TM_HOLD_STATE_WAIT ULL(0) #define PLAT_RPI3_TM_HOLD_STATE_GO ULL(1) +#define PLAT_RPI3_TM_HOLD_STATE_BSP_OFF ULL(2) /* * BL31 specific defines. -- cgit v1.2.3