From 97ef53052b1a45ae82de696b8f56ae76afd9ba9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20B=C4=83l=C4=83nic=C4=83?= Date: Fri, 1 Dec 2023 04:30:13 +0200 Subject: [PATCH 1/6] refactor(rpi): move more platform-specific code into common MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for RPi 5 support, which will reuse most of the RPi 4 logic except for DTB patching. Change-Id: I6f6ef96933711a1798757a3389adae1b8ee3de6c Signed-off-by: Mario Bălănică --- .../aarch64/armstub8_header.S | 2 +- .../{rpi3 => common}/include/plat_macros.S | 2 +- plat/rpi/common/include/rpi_shared.h | 10 +- plat/rpi/{rpi4 => common}/rpi4_bl31_setup.c | 111 ++---------------- plat/rpi/rpi4/include/plat_macros.S | 20 ---- plat/rpi/rpi4/platform.mk | 5 +- plat/rpi/rpi4/rpi4_setup.c | 109 +++++++++++++++++ 7 files changed, 131 insertions(+), 128 deletions(-) rename plat/rpi/{rpi4 => common}/aarch64/armstub8_header.S (89%) rename plat/rpi/{rpi3 => common}/include/plat_macros.S (87%) rename plat/rpi/{rpi4 => common}/rpi4_bl31_setup.c (67%) delete mode 100644 plat/rpi/rpi4/include/plat_macros.S create mode 100644 plat/rpi/rpi4/rpi4_setup.c diff --git a/plat/rpi/rpi4/aarch64/armstub8_header.S b/plat/rpi/common/aarch64/armstub8_header.S similarity index 89% rename from plat/rpi/rpi4/aarch64/armstub8_header.S rename to plat/rpi/common/aarch64/armstub8_header.S index 246358d04..dc1e54e13 100644 --- a/plat/rpi/rpi4/aarch64/armstub8_header.S +++ b/plat/rpi/common/aarch64/armstub8_header.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/plat/rpi/rpi3/include/plat_macros.S b/plat/rpi/common/include/plat_macros.S similarity index 87% rename from plat/rpi/rpi3/include/plat_macros.S rename to plat/rpi/common/include/plat_macros.S index c0c396791..576d0ffc9 100644 --- a/plat/rpi/rpi3/include/plat_macros.S +++ b/plat/rpi/common/include/plat_macros.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/plat/rpi/common/include/rpi_shared.h b/plat/rpi/common/include/rpi_shared.h index ddf239eb5..1b6c426f3 100644 --- a/plat/rpi/common/include/rpi_shared.h +++ b/plat/rpi/common/include/rpi_shared.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -23,6 +23,8 @@ void rpi3_setup_page_tables(uintptr_t total_base, size_t total_size, #endif ); +uintptr_t rpi4_get_dtb_address(void); + /* Optional functions required in the Raspberry Pi 3 port */ unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr); @@ -38,4 +40,10 @@ int rpi3_vc_hardware_get_board_revision(uint32_t *revision); int plat_rpi_get_model(void); +/******************************************************************************* + * Platform implemented functions + ******************************************************************************/ + +void plat_rpi_bl31_custom_setup(void); + #endif /* RPI3_PRIVATE_H */ diff --git a/plat/rpi/rpi4/rpi4_bl31_setup.c b/plat/rpi/common/rpi4_bl31_setup.c similarity index 67% rename from plat/rpi/rpi4/rpi4_bl31_setup.c rename to plat/rpi/common/rpi4_bl31_setup.c index 2fb4d3df1..a7228fd4f 100644 --- a/plat/rpi/rpi4/rpi4_bl31_setup.c +++ b/plat/rpi/common/rpi4_bl31_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,21 +8,15 @@ #include #include -#include - -#include #include #include +#include #include #include #include #include #include -#include -#include -#include - -#include +#include #include @@ -85,7 +79,7 @@ uintptr_t plat_get_ns_image_entrypoint(void) #endif } -static uintptr_t rpi4_get_dtb_address(void) +uintptr_t rpi4_get_dtb_address(void) { #ifdef RPI3_PRELOADED_DTB_BASE return RPI3_PRELOADED_DTB_BASE; @@ -151,7 +145,7 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, * r1 = machine type number, optional in DT-only platforms (~0 if so) * r2 = Physical address of the device tree blob */ - VERBOSE("rpi4: Preparing to boot 32-bit Linux kernel\n"); + VERBOSE("rpi: Preparing to boot 32-bit Linux kernel\n"); bl33_image_ep_info.args.arg0 = 0U; bl33_image_ep_info.args.arg1 = ~0U; bl33_image_ep_info.args.arg2 = rpi4_get_dtb_address(); @@ -162,7 +156,7 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, * tree blob (DTB) in x0, while x1-x3 are reserved for future use and * must be 0. */ - VERBOSE("rpi4: Preparing to boot 64-bit Linux kernel\n"); + VERBOSE("rpi: Preparing to boot 64-bit Linux kernel\n"); bl33_image_ep_info.args.arg0 = rpi4_get_dtb_address(); bl33_image_ep_info.args.arg1 = 0ULL; bl33_image_ep_info.args.arg2 = 0ULL; @@ -203,102 +197,13 @@ void bl31_plat_arch_setup(void) enable_mmu_el3(0); } -/* - * Remove the FDT /memreserve/ entry that covers the region at the very - * beginning of memory (if that exists). This is where the secondaries - * originally spin, but we pull them out there. - * Having overlapping /reserved-memory and /memreserve/ regions confuses - * the Linux kernel, so we need to get rid of this one. - */ -static void remove_spintable_memreserve(void *dtb) -{ - uint64_t addr, size; - int regions = fdt_num_mem_rsv(dtb); - int i; - - for (i = 0; i < regions; i++) { - if (fdt_get_mem_rsv(dtb, i, &addr, &size) != 0) { - return; - } - if (size == 0U) { - return; - } - /* We only look for the region at the beginning of DRAM. */ - if (addr != 0U) { - continue; - } - /* - * Currently the region in the existing DTs is exactly 4K - * in size. Should this value ever change, there is probably - * a reason for that, so inform the user about this. - */ - if (size == 4096U) { - fdt_del_mem_rsv(dtb, i); - return; - } - WARN("Keeping unknown /memreserve/ region at 0, size: %" PRId64 "\n", - size); - } -} - -static void rpi4_prepare_dtb(void) -{ - void *dtb = (void *)rpi4_get_dtb_address(); - uint32_t gic_int_prop[3]; - int ret, offs; - - /* Return if no device tree is detected */ - if (fdt_check_header(dtb) != 0) - return; - - ret = fdt_open_into(dtb, dtb, 0x100000); - if (ret < 0) { - ERROR("Invalid Device Tree at %p: error %d\n", dtb, ret); - return; - } - - if (dt_add_psci_node(dtb)) { - ERROR("Failed to add PSCI Device Tree node\n"); - return; - } - - if (dt_add_psci_cpu_enable_methods(dtb)) { - ERROR("Failed to add PSCI cpu enable methods in Device Tree\n"); - return; - } - - /* - * Remove the original reserved region (used for the spintable), and - * replace it with a region describing the whole of Trusted Firmware. - */ - remove_spintable_memreserve(dtb); - if (fdt_add_reserved_memory(dtb, "atf@0", 0, 0x80000)) - WARN("Failed to add reserved memory nodes to DT.\n"); - - offs = fdt_node_offset_by_compatible(dtb, 0, "arm,gic-400"); - gic_int_prop[0] = cpu_to_fdt32(1); // PPI - gic_int_prop[1] = cpu_to_fdt32(9); // PPI #9 - gic_int_prop[2] = cpu_to_fdt32(0x0f04); // all cores, level high - fdt_setprop(dtb, offs, "interrupts", gic_int_prop, 12); - - offs = fdt_path_offset(dtb, "/chosen"); - fdt_setprop_string(dtb, offs, "stdout-path", "serial0"); - - ret = fdt_pack(dtb); - if (ret < 0) - ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, ret); - - clean_dcache_range((uintptr_t)dtb, fdt_blob_size(dtb)); - INFO("Changed device tree to advertise PSCI.\n"); -} - void bl31_platform_setup(void) { - rpi4_prepare_dtb(); - /* Configure the interrupt controller */ gicv2_driver_init(&rpi4_gic_data); gicv2_distif_init(); gicv2_pcpu_distif_init(); gicv2_cpuif_enable(); + + plat_rpi_bl31_custom_setup(); } diff --git a/plat/rpi/rpi4/include/plat_macros.S b/plat/rpi/rpi4/include/plat_macros.S deleted file mode 100644 index 6007d031e..000000000 --- a/plat/rpi/rpi4/include/plat_macros.S +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ -#ifndef PLAT_MACROS_S -#define PLAT_MACROS_S - - /* --------------------------------------------- - * The below required platform porting macro - * prints out relevant platform registers - * whenever an unhandled exception is taken in - * BL31. - * Clobbers: x0 - x10, x16, x17, sp - * --------------------------------------------- - */ - .macro plat_crash_print_regs - .endm - -#endif /* PLAT_MACROS_S */ diff --git a/plat/rpi/rpi4/platform.mk b/plat/rpi/rpi4/platform.mk index 42a54164e..2e3188ef1 100644 --- a/plat/rpi/rpi4/platform.mk +++ b/plat/rpi/rpi4/platform.mk @@ -19,12 +19,13 @@ PLAT_BL_COMMON_SOURCES := drivers/ti/uart/aarch64/16550_console.S \ BL31_SOURCES += lib/cpus/aarch64/cortex_a72.S \ plat/rpi/common/aarch64/plat_helpers.S \ - plat/rpi/rpi4/aarch64/armstub8_header.S \ + plat/rpi/common/aarch64/armstub8_header.S \ drivers/delay_timer/delay_timer.c \ drivers/gpio/gpio.c \ drivers/rpi3/gpio/rpi3_gpio.c \ plat/common/plat_gicv2.c \ - plat/rpi/rpi4/rpi4_bl31_setup.c \ + plat/rpi/common/rpi4_bl31_setup.c \ + plat/rpi/rpi4/rpi4_setup.c \ plat/rpi/common/rpi3_pm.c \ plat/common/plat_psci_common.c \ plat/rpi/common/rpi3_topology.c \ diff --git a/plat/rpi/rpi4/rpi4_setup.c b/plat/rpi/rpi4/rpi4_setup.c new file mode 100644 index 000000000..82200b976 --- /dev/null +++ b/plat/rpi/rpi4/rpi4_setup.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#include + +/* + * Remove the FDT /memreserve/ entry that covers the region at the very + * beginning of memory (if that exists). This is where the secondaries + * originally spin, but we pull them out there. + * Having overlapping /reserved-memory and /memreserve/ regions confuses + * the Linux kernel, so we need to get rid of this one. + */ +static void remove_spintable_memreserve(void *dtb) +{ + uint64_t addr, size; + int regions = fdt_num_mem_rsv(dtb); + int i; + + for (i = 0; i < regions; i++) { + if (fdt_get_mem_rsv(dtb, i, &addr, &size) != 0) { + return; + } + if (size == 0U) { + return; + } + /* We only look for the region at the beginning of DRAM. */ + if (addr != 0U) { + continue; + } + /* + * Currently the region in the existing DTs is exactly 4K + * in size. Should this value ever change, there is probably + * a reason for that, so inform the user about this. + */ + if (size == 4096U) { + fdt_del_mem_rsv(dtb, i); + return; + } + WARN("Keeping unknown /memreserve/ region at 0, size: %" PRId64 "\n", + size); + } +} + +static void rpi4_prepare_dtb(void) +{ + void *dtb = (void *)rpi4_get_dtb_address(); + uint32_t gic_int_prop[3]; + int ret, offs; + + /* Return if no device tree is detected */ + if (fdt_check_header(dtb) != 0) + return; + + ret = fdt_open_into(dtb, dtb, 0x100000); + if (ret < 0) { + ERROR("Invalid Device Tree at %p: error %d\n", dtb, ret); + return; + } + + if (dt_add_psci_node(dtb)) { + ERROR("Failed to add PSCI Device Tree node\n"); + return; + } + + if (dt_add_psci_cpu_enable_methods(dtb)) { + ERROR("Failed to add PSCI cpu enable methods in Device Tree\n"); + return; + } + + /* + * Remove the original reserved region (used for the spintable), and + * replace it with a region describing the whole of Trusted Firmware. + */ + remove_spintable_memreserve(dtb); + if (fdt_add_reserved_memory(dtb, "atf@0", 0, 0x80000)) + WARN("Failed to add reserved memory nodes to DT.\n"); + + offs = fdt_node_offset_by_compatible(dtb, 0, "arm,gic-400"); + gic_int_prop[0] = cpu_to_fdt32(1); // PPI + gic_int_prop[1] = cpu_to_fdt32(9); // PPI #9 + gic_int_prop[2] = cpu_to_fdt32(0x0f04); // all cores, level high + fdt_setprop(dtb, offs, "interrupts", gic_int_prop, 12); + + offs = fdt_path_offset(dtb, "/chosen"); + fdt_setprop_string(dtb, offs, "stdout-path", "serial0"); + + ret = fdt_pack(dtb); + if (ret < 0) + ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, ret); + + clean_dcache_range((uintptr_t)dtb, fdt_blob_size(dtb)); + INFO("Changed device tree to advertise PSCI.\n"); +} + +void plat_rpi_bl31_custom_setup(void) +{ + rpi4_prepare_dtb(); +} From b502978278cc4d782d4ef9e125dc391f88ea491d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20B=C4=83l=C4=83nic=C4=83?= Date: Fri, 1 Dec 2023 04:59:43 +0200 Subject: [PATCH 2/6] refactor(rpi): split out console registration logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Detection of the UART in use and GPIO code only apply to RPi 3 and 4. RPi 5 has a dedicated PL011 debug port. Change-Id: Iddf8aea01278e2b79b4e7c476740f1add8c419f0 Signed-off-by: Mario Bălănică --- plat/rpi/common/include/rpi_shared.h | 8 ++++++- plat/rpi/common/rpi3_common.c | 24 ++----------------- plat/rpi/common/rpi3_console_dual.c | 35 ++++++++++++++++++++++++++++ plat/rpi/common/rpi3_console_pl011.c | 20 ++++++++++++++++ plat/rpi/rpi3/platform.mk | 1 + plat/rpi/rpi4/platform.mk | 1 + 6 files changed, 66 insertions(+), 23 deletions(-) create mode 100644 plat/rpi/common/rpi3_console_dual.c create mode 100644 plat/rpi/common/rpi3_console_pl011.c diff --git a/plat/rpi/common/include/rpi_shared.h b/plat/rpi/common/include/rpi_shared.h index 1b6c426f3..8562c3d56 100644 --- a/plat/rpi/common/include/rpi_shared.h +++ b/plat/rpi/common/include/rpi_shared.h @@ -7,14 +7,20 @@ #ifndef RPI_SHARED_H #define RPI_SHARED_H +#include #include +#include + /******************************************************************************* * Function and variable prototypes ******************************************************************************/ -/* Utility functions */ +/* Serial console functions */ void rpi3_console_init(void); +int rpi3_register_used_uart(console_t *console); + +/* Utility functions */ void rpi3_setup_page_tables(uintptr_t total_base, size_t total_size, uintptr_t code_start, uintptr_t code_limit, uintptr_t rodata_start, uintptr_t rodata_limit diff --git a/plat/rpi/common/rpi3_common.c b/plat/rpi/common/rpi3_common.c index ef88bf10e..89764969d 100644 --- a/plat/rpi/common/rpi3_common.c +++ b/plat/rpi/common/rpi3_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -13,9 +13,6 @@ #include #include #include -#include -#include -#include #include #include @@ -106,12 +103,6 @@ static const mmap_region_t plat_rpi3_mmap[] = { ******************************************************************************/ static console_t rpi3_console; - -static bool rpi3_use_mini_uart(void) -{ - return rpi3_gpio_get_select(14) == RPI3_GPIO_FUNC_ALT5; -} - void rpi3_console_init(void) { int console_scope = CONSOLE_FLAG_BOOT; @@ -120,18 +111,7 @@ void rpi3_console_init(void) if (RPI3_RUNTIME_UART != -1) console_scope |= CONSOLE_FLAG_RUNTIME; - rpi3_gpio_init(); - - if (rpi3_use_mini_uart()) - rc = console_16550_register(PLAT_RPI_MINI_UART_BASE, - 0, - PLAT_RPI_UART_BAUDRATE, - &rpi3_console); - else - rc = console_pl011_register(PLAT_RPI_PL011_UART_BASE, - PLAT_RPI_PL011_UART_CLOCK, - PLAT_RPI_UART_BAUDRATE, - &rpi3_console); + rc = rpi3_register_used_uart(&rpi3_console); if (rc == 0) { /* diff --git a/plat/rpi/common/rpi3_console_dual.c b/plat/rpi/common/rpi3_console_dual.c new file mode 100644 index 000000000..15ee3e70a --- /dev/null +++ b/plat/rpi/common/rpi3_console_dual.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2024, Mario Bălănică + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include + +static bool rpi3_use_mini_uart(void) +{ + return rpi3_gpio_get_select(14) == RPI3_GPIO_FUNC_ALT5; +} + +int rpi3_register_used_uart(console_t *console) +{ + rpi3_gpio_init(); + + if (rpi3_use_mini_uart()) + return console_16550_register(PLAT_RPI_MINI_UART_BASE, + 0, + PLAT_RPI_UART_BAUDRATE, + console); + else + return console_pl011_register(PLAT_RPI_PL011_UART_BASE, + PLAT_RPI_PL011_UART_CLOCK, + PLAT_RPI_UART_BAUDRATE, + console); +} diff --git a/plat/rpi/common/rpi3_console_pl011.c b/plat/rpi/common/rpi3_console_pl011.c new file mode 100644 index 000000000..6ab720972 --- /dev/null +++ b/plat/rpi/common/rpi3_console_pl011.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2024, Mario Bălănică + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +int rpi3_register_used_uart(console_t *console) +{ + return console_pl011_register(PLAT_RPI_PL011_UART_BASE, + PLAT_RPI_PL011_UART_CLOCK, + PLAT_RPI_UART_BAUDRATE, + console); +} diff --git a/plat/rpi/rpi3/platform.mk b/plat/rpi/rpi3/platform.mk index 26a3268bc..8034fa479 100644 --- a/plat/rpi/rpi3/platform.mk +++ b/plat/rpi/rpi3/platform.mk @@ -17,6 +17,7 @@ PLAT_BL_COMMON_SOURCES := drivers/ti/uart/aarch64/16550_console.S \ drivers/rpi3/gpio/rpi3_gpio.c \ plat/rpi/common/aarch64/plat_helpers.S \ plat/rpi/common/rpi3_common.c \ + plat/rpi/common/rpi3_console_dual.c \ ${XLAT_TABLES_LIB_SRCS} BL1_SOURCES += drivers/io/io_fip.c \ diff --git a/plat/rpi/rpi4/platform.mk b/plat/rpi/rpi4/platform.mk index 2e3188ef1..f17911fec 100644 --- a/plat/rpi/rpi4/platform.mk +++ b/plat/rpi/rpi4/platform.mk @@ -15,6 +15,7 @@ PLAT_INCLUDES := -Iplat/rpi/common/include \ PLAT_BL_COMMON_SOURCES := drivers/ti/uart/aarch64/16550_console.S \ drivers/arm/pl011/aarch64/pl011_console.S \ plat/rpi/common/rpi3_common.c \ + plat/rpi/common/rpi3_console_dual.c \ ${XLAT_TABLES_LIB_SRCS} BL31_SOURCES += lib/cpus/aarch64/cortex_a72.S \ From bbf92fe958af23efe4d935c6f69c4f5d7e8d8f4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20B=C4=83l=C4=83nic=C4=83?= Date: Fri, 1 Dec 2023 05:12:58 +0200 Subject: [PATCH 3/6] refactor(rpi): add platform macro for the crash UART base address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I164c579cbf7c26547a47794cd80152e13fd1937b Signed-off-by: Mario Bălănică --- plat/rpi/common/aarch64/plat_helpers.S | 22 ++++++++++++++++++---- plat/rpi/rpi3/include/platform_def.h | 3 ++- plat/rpi/rpi4/include/platform_def.h | 3 ++- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/plat/rpi/common/aarch64/plat_helpers.S b/plat/rpi/common/aarch64/plat_helpers.S index f045e2113..bc6b8c5a8 100644 --- a/plat/rpi/common/aarch64/plat_helpers.S +++ b/plat/rpi/common/aarch64/plat_helpers.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -164,10 +164,16 @@ endfunc platform_mem_init * --------------------------------------------- */ func plat_crash_console_init - mov_imm x0, PLAT_RPI_MINI_UART_BASE + mov_imm x0, PLAT_RPI_CRASH_UART_BASE +#if PLAT_RPI_CRASH_UART_BASE == PLAT_RPI_PL011_UART_BASE + mov_imm x1, RPI4_PL011_UART_CLOCK + mov_imm x2, PLAT_RPI_UART_BAUDRATE + b console_pl011_core_init +#else mov x1, xzr mov x2, xzr b console_16550_core_init +#endif endfunc plat_crash_console_init /* --------------------------------------------- @@ -178,8 +184,12 @@ endfunc plat_crash_console_init * --------------------------------------------- */ func plat_crash_console_putc - mov_imm x1, PLAT_RPI_MINI_UART_BASE + mov_imm x1, PLAT_RPI_CRASH_UART_BASE +#if PLAT_RPI_CRASH_UART_BASE == PLAT_RPI_PL011_UART_BASE + b console_pl011_core_putc +#else b console_16550_core_putc +#endif endfunc plat_crash_console_putc /* --------------------------------------------- @@ -191,8 +201,12 @@ endfunc plat_crash_console_putc * --------------------------------------------- */ func plat_crash_console_flush - mov_imm x0, PLAT_RPI_MINI_UART_BASE + mov_imm x0, PLAT_RPI_CRASH_UART_BASE +#if PLAT_RPI_CRASH_UART_BASE == PLAT_RPI_PL011_UART_BASE + b console_pl011_core_flush +#else b console_16550_core_flush +#endif endfunc plat_crash_console_flush /* --------------------------------------------- diff --git a/plat/rpi/rpi3/include/platform_def.h b/plat/rpi/rpi3/include/platform_def.h index f44d1f526..757c64ad9 100644 --- a/plat/rpi/rpi3/include/platform_def.h +++ b/plat/rpi/rpi3/include/platform_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -254,6 +254,7 @@ #define PLAT_RPI_PL011_UART_BASE RPI3_PL011_UART_BASE #define PLAT_RPI_PL011_UART_CLOCK RPI3_PL011_UART_CLOCK #define PLAT_RPI_UART_BAUDRATE ULL(115200) +#define PLAT_RPI_CRASH_UART_BASE PLAT_RPI_MINI_UART_BASE /* * System counter diff --git a/plat/rpi/rpi4/include/platform_def.h b/plat/rpi/rpi4/include/platform_def.h index 6787ebfee..b72aedcfa 100644 --- a/plat/rpi/rpi4/include/platform_def.h +++ b/plat/rpi/rpi4/include/platform_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -131,6 +131,7 @@ #define PLAT_RPI_PL011_UART_BASE RPI4_PL011_UART_BASE #define PLAT_RPI_PL011_UART_CLOCK RPI4_PL011_UART_CLOCK #define PLAT_RPI_UART_BAUDRATE ULL(115200) +#define PLAT_RPI_CRASH_UART_BASE PLAT_RPI_MINI_UART_BASE /* * System counter From 7a9cdf58c27f5a0b2f9523cce14545b3bd0f9035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20B=C4=83l=C4=83nic=C4=83?= Date: Wed, 6 Dec 2023 21:36:25 +0200 Subject: [PATCH 4/6] refactor(rpi): move register definitions out of rpi_hw.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I2bd48441359468efb9e94fd2fffb079683f7a7fd Signed-off-by: Mario Bălănică --- drivers/rpi3/rng/rpi3_rng.c | 15 +++++++- include/drivers/rpi3/mailbox/rpi3_mbox.h | 18 +++++++++- plat/rpi/common/rpi3_pm.c | 18 +++++++++- plat/rpi/rpi3/include/rpi_hw.h | 44 +----------------------- plat/rpi/rpi4/include/rpi_hw.h | 44 +----------------------- 5 files changed, 50 insertions(+), 89 deletions(-) diff --git a/drivers/rpi3/rng/rpi3_rng.c b/drivers/rpi3/rng/rpi3_rng.c index b6bf0052a..16733e15c 100644 --- a/drivers/rpi3/rng/rpi3_rng.c +++ b/drivers/rpi3/rng/rpi3_rng.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -11,6 +11,19 @@ #include +#define RPI3_RNG_CTRL_OFFSET ULL(0x00000000) +#define RPI3_RNG_STATUS_OFFSET ULL(0x00000004) +#define RPI3_RNG_DATA_OFFSET ULL(0x00000008) +#define RPI3_RNG_INT_MASK_OFFSET ULL(0x00000010) +/* Enable/disable RNG */ +#define RPI3_RNG_CTRL_ENABLE U(0x1) +#define RPI3_RNG_CTRL_DISABLE U(0x0) +/* Number of currently available words */ +#define RPI3_RNG_STATUS_NUM_WORDS_SHIFT U(24) +#define RPI3_RNG_STATUS_NUM_WORDS_MASK U(0xFF) +/* Value to mask interrupts caused by the RNG */ +#define RPI3_RNG_INT_MASK_DISABLE U(0x1) + /* Initial amount of values to discard */ #define RNG_WARMUP_COUNT U(0x40000) diff --git a/include/drivers/rpi3/mailbox/rpi3_mbox.h b/include/drivers/rpi3/mailbox/rpi3_mbox.h index c1074402b..33458e384 100644 --- a/include/drivers/rpi3/mailbox/rpi3_mbox.h +++ b/include/drivers/rpi3/mailbox/rpi3_mbox.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -16,6 +16,22 @@ typedef struct __packed __aligned(16) rpi3_mbox_request { uint32_t tags[0]; } rpi3_mbox_request_t; +/* VideoCore -> ARM */ +#define RPI3_MBOX0_READ_OFFSET ULL(0x00000000) +#define RPI3_MBOX0_PEEK_OFFSET ULL(0x00000010) +#define RPI3_MBOX0_SENDER_OFFSET ULL(0x00000014) +#define RPI3_MBOX0_STATUS_OFFSET ULL(0x00000018) +#define RPI3_MBOX0_CONFIG_OFFSET ULL(0x0000001C) +/* ARM -> VideoCore */ +#define RPI3_MBOX1_WRITE_OFFSET ULL(0x00000020) +#define RPI3_MBOX1_PEEK_OFFSET ULL(0x00000030) +#define RPI3_MBOX1_SENDER_OFFSET ULL(0x00000034) +#define RPI3_MBOX1_STATUS_OFFSET ULL(0x00000038) +#define RPI3_MBOX1_CONFIG_OFFSET ULL(0x0000003C) +/* Mailbox status constants */ +#define RPI3_MBOX_STATUS_FULL_MASK U(0x80000000) /* Set if full */ +#define RPI3_MBOX_STATUS_EMPTY_MASK U(0x40000000) /* Set if empty */ + #define RPI3_MBOX_BUFFER_SIZE U(256) /* Constants to perform a request/check the status of a request. */ diff --git a/plat/rpi/common/rpi3_pm.c b/plat/rpi/common/rpi3_pm.c index d98ac66f4..456e1603c 100644 --- a/plat/rpi/common/rpi3_pm.c +++ b/plat/rpi/common/rpi3_pm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -21,6 +21,22 @@ #include #endif +/* Registers on top of RPI3_PM_BASE. */ +#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C) +#define RPI3_PM_RSTS_OFFSET ULL(0x00000020) +#define RPI3_PM_WDOG_OFFSET ULL(0x00000024) +/* Watchdog constants */ +#define RPI3_PM_PASSWORD U(0x5A000000) +#define RPI3_PM_RSTC_WRCFG_MASK U(0x00000030) +#define RPI3_PM_RSTC_WRCFG_FULL_RESET U(0x00000020) +/* + * The RSTS register is used by the VideoCore firmware when booting the + * Raspberry Pi to know which partition to boot from. The partition value is + * formed by bits 0, 2, 4, 6, 8 and 10. Partition 63 is used by said firmware + * to indicate halt. + */ +#define RPI3_PM_RSTS_WRCFG_HALT U(0x00000555) + /* Make composite power state parameter till power level 0 */ #if PSCI_EXTENDED_STATE_ID diff --git a/plat/rpi/rpi3/include/rpi_hw.h b/plat/rpi/rpi3/include/rpi_hw.h index 2aecab379..dec596333 100644 --- a/plat/rpi/rpi3/include/rpi_hw.h +++ b/plat/rpi/rpi3/include/rpi_hw.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -21,60 +21,18 @@ */ #define RPI3_MBOX_OFFSET ULL(0x0000B880) #define RPI3_MBOX_BASE (RPI_IO_BASE + RPI3_MBOX_OFFSET) -/* VideoCore -> ARM */ -#define RPI3_MBOX0_READ_OFFSET ULL(0x00000000) -#define RPI3_MBOX0_PEEK_OFFSET ULL(0x00000010) -#define RPI3_MBOX0_SENDER_OFFSET ULL(0x00000014) -#define RPI3_MBOX0_STATUS_OFFSET ULL(0x00000018) -#define RPI3_MBOX0_CONFIG_OFFSET ULL(0x0000001C) -/* ARM -> VideoCore */ -#define RPI3_MBOX1_WRITE_OFFSET ULL(0x00000020) -#define RPI3_MBOX1_PEEK_OFFSET ULL(0x00000030) -#define RPI3_MBOX1_SENDER_OFFSET ULL(0x00000034) -#define RPI3_MBOX1_STATUS_OFFSET ULL(0x00000038) -#define RPI3_MBOX1_CONFIG_OFFSET ULL(0x0000003C) -/* Mailbox status constants */ -#define RPI3_MBOX_STATUS_FULL_MASK U(0x80000000) /* Set if full */ -#define RPI3_MBOX_STATUS_EMPTY_MASK U(0x40000000) /* Set if empty */ /* * Power management, reset controller, watchdog. */ #define RPI3_IO_PM_OFFSET ULL(0x00100000) #define RPI3_PM_BASE (RPI_IO_BASE + RPI3_IO_PM_OFFSET) -/* Registers on top of RPI3_PM_BASE. */ -#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C) -#define RPI3_PM_RSTS_OFFSET ULL(0x00000020) -#define RPI3_PM_WDOG_OFFSET ULL(0x00000024) -/* Watchdog constants */ -#define RPI3_PM_PASSWORD U(0x5A000000) -#define RPI3_PM_RSTC_WRCFG_MASK U(0x00000030) -#define RPI3_PM_RSTC_WRCFG_FULL_RESET U(0x00000020) -/* - * The RSTS register is used by the VideoCore firmware when booting the - * Raspberry Pi to know which partition to boot from. The partition value is - * formed by bits 0, 2, 4, 6, 8 and 10. Partition 63 is used by said firmware - * to indicate halt. - */ -#define RPI3_PM_RSTS_WRCFG_HALT U(0x00000555) /* * Hardware random number generator. */ #define RPI3_IO_RNG_OFFSET ULL(0x00104000) #define RPI3_RNG_BASE (RPI_IO_BASE + RPI3_IO_RNG_OFFSET) -#define RPI3_RNG_CTRL_OFFSET ULL(0x00000000) -#define RPI3_RNG_STATUS_OFFSET ULL(0x00000004) -#define RPI3_RNG_DATA_OFFSET ULL(0x00000008) -#define RPI3_RNG_INT_MASK_OFFSET ULL(0x00000010) -/* Enable/disable RNG */ -#define RPI3_RNG_CTRL_ENABLE U(0x1) -#define RPI3_RNG_CTRL_DISABLE U(0x0) -/* Number of currently available words */ -#define RPI3_RNG_STATUS_NUM_WORDS_SHIFT U(24) -#define RPI3_RNG_STATUS_NUM_WORDS_MASK U(0xFF) -/* Value to mask interrupts caused by the RNG */ -#define RPI3_RNG_INT_MASK_DISABLE U(0x1) /* * Serial ports: diff --git a/plat/rpi/rpi4/include/rpi_hw.h b/plat/rpi/rpi4/include/rpi_hw.h index 0430d464d..816249212 100644 --- a/plat/rpi/rpi4/include/rpi_hw.h +++ b/plat/rpi/rpi4/include/rpi_hw.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -23,60 +23,18 @@ */ #define RPI3_MBOX_OFFSET ULL(0x0000B880) #define RPI3_MBOX_BASE (RPI_LEGACY_BASE + RPI3_MBOX_OFFSET) -/* VideoCore -> ARM */ -#define RPI3_MBOX0_READ_OFFSET ULL(0x00000000) -#define RPI3_MBOX0_PEEK_OFFSET ULL(0x00000010) -#define RPI3_MBOX0_SENDER_OFFSET ULL(0x00000014) -#define RPI3_MBOX0_STATUS_OFFSET ULL(0x00000018) -#define RPI3_MBOX0_CONFIG_OFFSET ULL(0x0000001C) -/* ARM -> VideoCore */ -#define RPI3_MBOX1_WRITE_OFFSET ULL(0x00000020) -#define RPI3_MBOX1_PEEK_OFFSET ULL(0x00000030) -#define RPI3_MBOX1_SENDER_OFFSET ULL(0x00000034) -#define RPI3_MBOX1_STATUS_OFFSET ULL(0x00000038) -#define RPI3_MBOX1_CONFIG_OFFSET ULL(0x0000003C) -/* Mailbox status constants */ -#define RPI3_MBOX_STATUS_FULL_MASK U(0x80000000) /* Set if full */ -#define RPI3_MBOX_STATUS_EMPTY_MASK U(0x40000000) /* Set if empty */ /* * Power management, reset controller, watchdog. */ #define RPI3_IO_PM_OFFSET ULL(0x00100000) #define RPI3_PM_BASE (RPI_LEGACY_BASE + RPI3_IO_PM_OFFSET) -/* Registers on top of RPI3_PM_BASE. */ -#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C) -#define RPI3_PM_RSTS_OFFSET ULL(0x00000020) -#define RPI3_PM_WDOG_OFFSET ULL(0x00000024) -/* Watchdog constants */ -#define RPI3_PM_PASSWORD U(0x5A000000) -#define RPI3_PM_RSTC_WRCFG_MASK U(0x00000030) -#define RPI3_PM_RSTC_WRCFG_FULL_RESET U(0x00000020) -/* - * The RSTS register is used by the VideoCore firmware when booting the - * Raspberry Pi to know which partition to boot from. The partition value is - * formed by bits 0, 2, 4, 6, 8 and 10. Partition 63 is used by said firmware - * to indicate halt. - */ -#define RPI3_PM_RSTS_WRCFG_HALT U(0x00000555) /* * Hardware random number generator. */ #define RPI3_IO_RNG_OFFSET ULL(0x00104000) #define RPI3_RNG_BASE (RPI_LEGACY_BASE + RPI3_IO_RNG_OFFSET) -#define RPI3_RNG_CTRL_OFFSET ULL(0x00000000) -#define RPI3_RNG_STATUS_OFFSET ULL(0x00000004) -#define RPI3_RNG_DATA_OFFSET ULL(0x00000008) -#define RPI3_RNG_INT_MASK_OFFSET ULL(0x00000010) -/* Enable/disable RNG */ -#define RPI3_RNG_CTRL_ENABLE U(0x1) -#define RPI3_RNG_CTRL_DISABLE U(0x0) -/* Number of currently available words */ -#define RPI3_RNG_STATUS_NUM_WORDS_SHIFT U(24) -#define RPI3_RNG_STATUS_NUM_WORDS_MASK U(0xFF) -/* Value to mask interrupts caused by the RNG */ -#define RPI3_RNG_INT_MASK_DISABLE U(0x1) /* * Serial ports: From 6744d07d9475adb49352fa57aa72fce17a95d757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20B=C4=83l=C4=83nic=C4=83?= Date: Fri, 1 Dec 2023 05:43:53 +0200 Subject: [PATCH 5/6] fix(rpi): consider MT when calculating core index from MPIDR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RPi 5 has newer Armv8.2 cores where the MT bit is set to indicate that the lowest affinity level represents a thread, but there is only one thread per core. To deal with this, simply right shift MPIDR by one affinity level to get the cluster and core IDs back into Aff1 and Aff0 as expected. Change-Id: I2bafba38f82fd9a6ef6f2fdf2c089b754279a6de Signed-off-by: Mario Bălănică --- plat/rpi/common/aarch64/plat_helpers.S | 9 +++++++++ plat/rpi/common/rpi3_topology.c | 21 ++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/plat/rpi/common/aarch64/plat_helpers.S b/plat/rpi/common/aarch64/plat_helpers.S index bc6b8c5a8..18873af7f 100644 --- a/plat/rpi/common/aarch64/plat_helpers.S +++ b/plat/rpi/common/aarch64/plat_helpers.S @@ -27,10 +27,19 @@ * * This function uses the plat_rpi3_calc_core_pos() * definition to get the index of the calling CPU. + * + * When MT is set, lowest affinity represents the thread ID. + * Since we only support one thread per core, discard this field + * so cluster and core IDs go back into Aff1 and Aff0 respectively. + * The upper bits are also affected, but plat_rpi3_calc_core_pos() + * does not use them. * ----------------------------------------------------- */ func plat_my_core_pos mrs x0, mpidr_el1 + tst x0, #MPIDR_MT_MASK + lsr x1, x0, #MPIDR_AFFINITY_BITS + csel x0, x1, x0, ne b plat_rpi3_calc_core_pos endfunc plat_my_core_pos diff --git a/plat/rpi/common/rpi3_topology.c b/plat/rpi/common/rpi3_topology.c index 3747287c2..5fef777c3 100644 --- a/plat/rpi/common/rpi3_topology.c +++ b/plat/rpi/common/rpi3_topology.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -39,12 +39,27 @@ int plat_core_pos_by_mpidr(u_register_t mpidr) unsigned int cluster_id, cpu_id; mpidr &= MPIDR_AFFINITY_MASK; + + /* + * When MT is set, lowest affinity represents the thread ID. + * Since we only support one thread per core, discard this field + * so cluster and core IDs go back into Aff1 and Aff0 respectively. + * The upper bits are also affected, but plat_rpi3_calc_core_pos() + * does not use them. + */ + if ((read_mpidr() & MPIDR_MT_MASK) != 0) { + if (MPIDR_AFFLVL0_VAL(mpidr) != 0) { + return -1; + } + mpidr >>= MPIDR_AFFINITY_BITS; + } + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) { return -1; } - cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; - cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + cluster_id = MPIDR_AFFLVL1_VAL(mpidr); + cpu_id = MPIDR_AFFLVL0_VAL(mpidr); if (cluster_id >= PLATFORM_CLUSTER_COUNT) { return -1; From f834b64f889c1c4e03e590d44a6a52e3ac79cf42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20B=C4=83l=C4=83nic=C4=83?= Date: Sat, 2 Dec 2023 03:08:02 +0200 Subject: [PATCH 6/6] feat(rpi): add Raspberry Pi 5 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Raspberry Pi 5 is a single-board computer based on BCM2712 that contains four Arm Cortex-A76 cores. This change introduces minimal BL31 support with PSCI that has been validated to boot Linux and a private EDK2 build. It's a drop-in replacement for the custom TF-A armstub now included in the EEPROM images. Change-Id: Id72a0370f54e71ac97c3daa1bacedacb7dec148f Signed-off-by: Mario Bălănică --- changelog.yaml | 3 + docs/plat/index.rst | 1 + docs/plat/rpi5.rst | 78 +++++++++++++++ plat/rpi/rpi5/include/plat.ld.S | 23 +++++ plat/rpi/rpi5/include/platform_def.h | 141 +++++++++++++++++++++++++++ plat/rpi/rpi5/include/rpi_hw.h | 51 ++++++++++ plat/rpi/rpi5/platform.mk | 107 ++++++++++++++++++++ plat/rpi/rpi5/rpi5_setup.c | 12 +++ 8 files changed, 416 insertions(+) create mode 100644 docs/plat/rpi5.rst create mode 100644 plat/rpi/rpi5/include/plat.ld.S create mode 100644 plat/rpi/rpi5/include/platform_def.h create mode 100644 plat/rpi/rpi5/include/rpi_hw.h create mode 100644 plat/rpi/rpi5/platform.mk create mode 100644 plat/rpi/rpi5/rpi5_setup.c diff --git a/changelog.yaml b/changelog.yaml index 35ffaa863..5135d6950 100644 --- a/changelog.yaml +++ b/changelog.yaml @@ -541,6 +541,9 @@ subsections: - title: Raspberry Pi 4 scope: rpi4 + - title: Raspberry Pi 5 + scope: rpi5 + - title: Renesas scope: renesas diff --git a/docs/plat/index.rst b/docs/plat/index.rst index b1ccaa51e..795fb0930 100644 --- a/docs/plat/index.rst +++ b/docs/plat/index.rst @@ -37,6 +37,7 @@ Platform Ports qti-msm8916 rpi3 rpi4 + rpi5 rcar-gen3 rz-g2 rockchip diff --git a/docs/plat/rpi5.rst b/docs/plat/rpi5.rst new file mode 100644 index 000000000..f2e1b9f2d --- /dev/null +++ b/docs/plat/rpi5.rst @@ -0,0 +1,78 @@ +Raspberry Pi 5 +============== + +The `Raspberry Pi 5`_ is a single-board computer that contains four +Arm Cortex-A76 cores. + +This port is a minimal BL31 implementation capable of booting 64-bit EL2 +payloads such as Linux and EDK2. + +**IMPORTANT NOTE**: This port isn't secure. All of the memory used is DRAM, +which is available from both the Non-secure and Secure worlds. The SoC does +not seem to feature a secure memory controller of any kind, so portions of +DRAM can't be protected properly from the Non-secure world. + +Build +------------------ + +To build this platform, run: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi5 DEBUG=1 + +The firmware will be generated at ``build/rpi5/debug/bl31.bin``. + +The following build options are supported: + +- ``RPI3_DIRECT_LINUX_BOOT``: Enabled by default. Allows direct boot of the Linux + kernel from the firmware. + +- ``PRELOADED_BL33_BASE``: Used to specify the fixed address of a BL33 binary + that has been preloaded by earlier boot stages (VPU). Useful for bundling + BL31 and BL33 in the same ``armstub`` image (e.g. TF-A + EDK2). + +- ``RPI3_PRELOADED_DTB_BASE``: This option allows to specify the fixed address of + a DTB in memory. Can only be used if ``device_tree_address=`` is present in + config.txt. + +- ``RPI3_RUNTIME_UART``: Indicates whether TF-A should use the debug UART for + runtime messages or not. ``-1`` (default) disables the option, any other value + enables it. + +Usage +------------------ + +Copy the firmware binary to the first FAT32 partition of a supported boot media +(SD, USB) and append ``armstub=bl31.bin`` to config.txt, or just rename the +file to ``armstub8-2712.bin``. + +No other config options or files are required by the firmware alone, this will +depend on the payload you intend to run. + +For Linux, you must also place an appropriate DTB and kernel in the boot +partition. This has been validated with a copy of Raspberry Pi OS. + +The VPU will preload a BL33 AArch64 image named either ``kernel_2712.img`` or +``kernel8.img``, which can be overridden by adding a ``kernel=filename`` option +to config.txt. + +Kernel and DTB load addresses are also chosen by the VPU and can be changed with +``kernel_address=`` and ``device_tree_address=`` in config.txt. If TF-A was built +with ``PRELOADED_BL33_BASE`` or ``RPI3_PRELOADED_DTB_BASE``, setting those config +options may be necessary. + +By default, all boot stages print messages to the dedicated UART debug port. +Configuration is ``115200 8n1``. + +Design +------------------ + +This port is largely based on the RPi 4 one. + +The boot process is essentially the same, the only notable difference being that +all VPU blobs have been moved into EEPROM (former start4.elf & fixup4.dat). There's +also a custom BL31 TF-A armstub included for PSCI, which can be replaced with this +port. + +.. _Raspberry Pi 5: https://www.raspberrypi.com/products/raspberry-pi-5/ diff --git a/plat/rpi/rpi5/include/plat.ld.S b/plat/rpi/rpi5/include/plat.ld.S new file mode 100644 index 000000000..961c630c6 --- /dev/null +++ b/plat/rpi/rpi5/include/plat.ld.S @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019-2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Stub linker script to provide the armstub8.bin header before the actual + * code. If the GPU firmware finds a magic value at offset 240 in + * armstub8.bin, it will put the DTB and kernel load address in subsequent + * words. We can then read those values to find the proper NS entry point + * and find our DTB more flexibly. + */ + +MEMORY { + PRERAM (rwx): ORIGIN = 0, LENGTH = 4096 +} + +SECTIONS +{ + .armstub8 . : { + *armstub8_header.o(.text*) + KEEP(*(.armstub8)) + } >PRERAM +} diff --git a/plat/rpi/rpi5/include/platform_def.h b/plat/rpi/rpi5/include/platform_def.h new file mode 100644 index 000000000..a4c2f5b9d --- /dev/null +++ b/plat/rpi/rpi5/include/platform_def.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2024, Mario Bălănică + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include + +#include "rpi_hw.h" + +/* Special value used to verify platform parameters from BL2 to BL31 */ +#define RPI3_BL31_PLAT_PARAM_VAL ULL(0x0F1E2D3C4B5A6978) + +#define PLATFORM_STACK_SIZE ULL(0x1000) + +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER +#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT + +#define RPI_PRIMARY_CPU U(0) + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +/* Local power state for power domains in Run state. */ +#define PLAT_LOCAL_STATE_RUN U(0) +/* Local power state for retention. Valid only for CPU power domains */ +#define PLAT_LOCAL_STATE_RET U(1) +/* + * Local power state for OFF/power-down. Valid for CPU and cluster power + * domains. + */ +#define PLAT_LOCAL_STATE_OFF U(2) + +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define PLAT_LOCAL_PSTATE_WIDTH U(4) +#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1) + +/* + * Some data must be aligned on the biggest cache line size in the platform. + * This is known only to the platform as it might have a combination of + * integrated and external caches. + */ +#define CACHE_WRITEBACK_SHIFT U(6) +#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT) + +/* + * I/O registers. + */ +#define DEVICE0_BASE RPI_IO_BASE +#define DEVICE0_SIZE RPI_IO_SIZE + +/* + * Mailbox to control the secondary cores. All secondary cores are held in a + * wait loop in cold boot. To release them perform the following steps (plus + * any additional barriers that may be needed): + * + * uint64_t *entrypoint = (uint64_t *)PLAT_RPI3_TM_ENTRYPOINT; + * *entrypoint = ADDRESS_TO_JUMP_TO; + * + * uint64_t *mbox_entry = (uint64_t *)PLAT_RPI3_TM_HOLD_BASE; + * mbox_entry[cpu_id] = PLAT_RPI3_TM_HOLD_STATE_GO; + * + * sev(); + */ +/* The secure entry point to be used on warm reset by all CPUs. */ +#define PLAT_RPI3_TM_ENTRYPOINT 0x100 +#define PLAT_RPI3_TM_ENTRYPOINT_SIZE ULL(8) + +/* Hold entries for each CPU. */ +#define PLAT_RPI3_TM_HOLD_BASE (PLAT_RPI3_TM_ENTRYPOINT + \ + PLAT_RPI3_TM_ENTRYPOINT_SIZE) +#define PLAT_RPI3_TM_HOLD_ENTRY_SIZE ULL(8) +#define PLAT_RPI3_TM_HOLD_SIZE (PLAT_RPI3_TM_HOLD_ENTRY_SIZE * \ + PLATFORM_CORE_COUNT) + +#define PLAT_RPI3_TRUSTED_MAILBOX_SIZE (PLAT_RPI3_TM_ENTRYPOINT_SIZE + \ + PLAT_RPI3_TM_HOLD_SIZE) + +#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. + * + * Put BL31 at the top of the Trusted SRAM. BL31_BASE is calculated using the + * current BL31 debug size plus a little space for growth. + */ +#define PLAT_MAX_BL31_SIZE ULL(0x80000) + +#define BL31_BASE ULL(0x1000) +#define BL31_LIMIT ULL(0x80000) +#define BL31_PROGBITS_LIMIT ULL(0x80000) + +#define SEC_SRAM_ID 0 +#define SEC_DRAM_ID 1 + +/* + * Other memory-related defines. + */ +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 40) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 40) + +#define MAX_MMAP_REGIONS 8 +#define MAX_XLAT_TABLES 4 + +#define MAX_IO_DEVICES U(3) +#define MAX_IO_HANDLES U(4) + +#define MAX_IO_BLOCK_DEVICES U(1) + +/* + * Serial-related constants. + */ +#define PLAT_RPI_PL011_UART_BASE RPI4_PL011_UART_BASE +#define PLAT_RPI_PL011_UART_CLOCK RPI4_PL011_UART_CLOCK +#define PLAT_RPI_UART_BAUDRATE ULL(115200) +#define PLAT_RPI_CRASH_UART_BASE PLAT_RPI_PL011_UART_BASE + +/* + * System counter + */ +#define SYS_COUNTER_FREQ_IN_TICKS ULL(54000000) + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/rpi/rpi5/include/rpi_hw.h b/plat/rpi/rpi5/include/rpi_hw.h new file mode 100644 index 000000000..384542e66 --- /dev/null +++ b/plat/rpi/rpi5/include/rpi_hw.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016-2024, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2024, Mario Bălănică + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RPI_HW_H +#define RPI_HW_H + +#include + +/* + * Peripherals + */ + +#define RPI_IO_BASE ULL(0x1000000000) +#define RPI_IO_SIZE ULL(0x1000000000) + +/* + * ARM <-> VideoCore mailboxes + */ +#define RPI3_MBOX_BASE (RPI_IO_BASE + ULL(0x7c013880)) + +/* + * Power management, reset controller, watchdog. + */ +#define RPI3_PM_BASE (RPI_IO_BASE + ULL(0x7d200000)) + +/* + * Hardware random number generator. + */ +#define RPI3_RNG_BASE (RPI_IO_BASE + ULL(0x7d208000)) + +/* + * PL011 system serial port + */ +#define RPI4_PL011_UART_BASE (RPI_IO_BASE + ULL(0x7d001000)) +#define RPI4_PL011_UART_CLOCK ULL(44000000) + +/* + * GIC interrupt controller + */ +#define RPI_HAVE_GIC +#define RPI4_GIC_GICD_BASE (RPI_IO_BASE + ULL(0x7fff9000)) +#define RPI4_GIC_GICC_BASE (RPI_IO_BASE + ULL(0x7fffa000)) + +#define RPI4_LOCAL_CONTROL_BASE_ADDRESS (RPI_IO_BASE + ULL(0x7c280000)) +#define RPI4_LOCAL_CONTROL_PRESCALER (RPI_IO_BASE + ULL(0x7c280008)) + +#endif /* RPI_HW_H */ diff --git a/plat/rpi/rpi5/platform.mk b/plat/rpi/rpi5/platform.mk new file mode 100644 index 000000000..81b7dedfb --- /dev/null +++ b/plat/rpi/rpi5/platform.mk @@ -0,0 +1,107 @@ +# +# Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved. +# Copyright (c) 2024, Mario Bălănică +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include lib/xlat_tables_v2/xlat_tables.mk + +include drivers/arm/gic/v2/gicv2.mk + +PLAT_INCLUDES := -Iplat/rpi/common/include \ + -Iplat/rpi/rpi5/include + +PLAT_BL_COMMON_SOURCES := drivers/arm/pl011/aarch64/pl011_console.S \ + plat/rpi/common/rpi3_common.c \ + plat/rpi/common/rpi3_console_pl011.c \ + ${XLAT_TABLES_LIB_SRCS} + +BL31_SOURCES += lib/cpus/aarch64/cortex_a76.S \ + plat/rpi/common/aarch64/plat_helpers.S \ + plat/rpi/common/aarch64/armstub8_header.S \ + drivers/delay_timer/delay_timer.c \ + plat/common/plat_gicv2.c \ + plat/rpi/common/rpi4_bl31_setup.c \ + plat/rpi/rpi5/rpi5_setup.c \ + plat/rpi/common/rpi3_pm.c \ + plat/common/plat_psci_common.c \ + plat/rpi/common/rpi3_topology.c \ + ${GICV2_SOURCES} + +# For now we only support BL31, using the kernel loaded by the GPU firmware. +RESET_TO_BL31 := 1 + +# All CPUs enter armstub8.bin. +COLD_BOOT_SINGLE_CPU := 0 + +# Tune compiler for Cortex-A76 +ifeq ($(notdir $(CC)),armclang) + TF_CFLAGS_aarch64 += -mcpu=cortex-a76 +else ifneq ($(findstring clang,$(notdir $(CC))),) + TF_CFLAGS_aarch64 += -mcpu=cortex-a76 +else + TF_CFLAGS_aarch64 += -mtune=cortex-a76 +endif + +# Add support for platform supplied linker script for BL31 build +$(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) + +# Enable all errata workarounds for Cortex-A76 r4p1 +ERRATA_A76_1946160 := 1 +ERRATA_A76_2743102 := 1 + +# Add new default target when compiling this platform +all: bl31 + +# Build config flags +# ------------------ + +# Disable stack protector by default +ENABLE_STACK_PROTECTOR := 0 + +# Have different sections for code and rodata +SEPARATE_CODE_AND_RODATA := 1 + +# Hardware-managed coherency +HW_ASSISTED_COHERENCY := 1 +USE_COHERENT_MEM := 0 + +# Cortex-A76 is 64-bit only +CTX_INCLUDE_AARCH32_REGS := 0 + +# Platform build flags +# -------------------- + +# There is not much else than a Linux kernel to load at the moment. +RPI3_DIRECT_LINUX_BOOT := 1 + +# BL33 images can only be AArch64 on this platform. +RPI3_BL33_IN_AARCH32 := 0 + +# UART to use at runtime. -1 means the runtime UART is disabled. +# Any other value means the default UART will be used. +RPI3_RUNTIME_UART := 0 + +# Use normal memory mapping for ROM, FIP, SRAM and DRAM +RPI3_USE_UEFI_MAP := 0 + +# Process platform flags +# ---------------------- + +$(eval $(call add_define,RPI3_BL33_IN_AARCH32)) +$(eval $(call add_define,RPI3_DIRECT_LINUX_BOOT)) +ifdef RPI3_PRELOADED_DTB_BASE +$(eval $(call add_define,RPI3_PRELOADED_DTB_BASE)) +endif +$(eval $(call add_define,RPI3_RUNTIME_UART)) +$(eval $(call add_define,RPI3_USE_UEFI_MAP)) + +ifeq (${ARCH},aarch32) + $(error Error: AArch32 not supported on rpi5) +endif + +ifneq ($(ENABLE_STACK_PROTECTOR), 0) +PLAT_BL_COMMON_SOURCES += drivers/rpi3/rng/rpi3_rng.c \ + plat/rpi/common/rpi3_stack_protector.c +endif diff --git a/plat/rpi/rpi5/rpi5_setup.c b/plat/rpi/rpi5/rpi5_setup.c new file mode 100644 index 000000000..de82300de --- /dev/null +++ b/plat/rpi/rpi5/rpi5_setup.c @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2024, Mario Bălănică + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +void plat_rpi_bl31_custom_setup(void) +{ + /* Nothing to do here yet. */ +}