diff --git a/libplatsupport/CMakeLists.txt b/libplatsupport/CMakeLists.txt index 375066e71..ceeca248a 100644 --- a/libplatsupport/CMakeLists.txt +++ b/libplatsupport/CMakeLists.txt @@ -71,7 +71,7 @@ config_option( mark_as_advanced(LibPlatSupportHaveTimer) set(LibPlatSupportMach "") -if(KernelPlatformRpi3 OR KernelPlatformRpi4) +if(KernelPlatformRpi3 OR KernelPlatformRpi4 OR KernelPlatformRpi5) set(LibPlatSupportMach "bcm") elseif(KernelPlatformCheshire OR KernelPlatformAriane) set(LibPlatSupportMach "cva6") diff --git a/libplatsupport/include/platsupport/fdt.h b/libplatsupport/include/platsupport/fdt.h index 6060b6e11..505e62609 100644 --- a/libplatsupport/include/platsupport/fdt.h +++ b/libplatsupport/include/platsupport/fdt.h @@ -15,8 +15,8 @@ * RISCV does have 128 bits but there are no platforms that use that bit length (yet) */ #define READ_CELL32(addr) fdt32_ld(addr) #define READ_CELL64(addr) fdt64_ld(addr) -#define READ_CELL(size, addr, offset) (size == 2 ? READ_CELL64(addr + (offset * sizeof(uint32_t))) : \ - READ_CELL32(addr + (offset * sizeof(uint32_t)))) +#define READ_CELL(size, addr, offset) (size == 2 ? READ_CELL64((addr) + ((offset) * sizeof(uint32_t))) : \ + READ_CELL32((addr) + ((offset) * sizeof(uint32_t)))) /* * Type of the callback function that is called for each device register instance diff --git a/libplatsupport/plat_include/bcm2712/platsupport/plat/clock.h b/libplatsupport/plat_include/bcm2712/platsupport/plat/clock.h new file mode 100644 index 000000000..0f5085c3e --- /dev/null +++ b/libplatsupport/plat_include/bcm2712/platsupport/plat/clock.h @@ -0,0 +1,17 @@ +/* + * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) + * Copyright (C) 2021, Hensoldt Cyber GmbH + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#pragma once + +enum clk_id { + CLK_MASTER, + /* ----- */ + NCLOCKS, +}; + +enum clock_gate { + NCLKGATES +}; diff --git a/libplatsupport/plat_include/bcm2712/platsupport/plat/gpio.h b/libplatsupport/plat_include/bcm2712/platsupport/plat/gpio.h new file mode 100644 index 000000000..464677185 --- /dev/null +++ b/libplatsupport/plat_include/bcm2712/platsupport/plat/gpio.h @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2021, HENSOLDT Cyber GmbH + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include diff --git a/libplatsupport/plat_include/bcm2712/platsupport/plat/i2c.h b/libplatsupport/plat_include/bcm2712/platsupport/plat/i2c.h new file mode 100644 index 000000000..91bc9c978 --- /dev/null +++ b/libplatsupport/plat_include/bcm2712/platsupport/plat/i2c.h @@ -0,0 +1,11 @@ +/* + * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) + * Copyright (C) 2021, Hensoldt Cyber GmbH + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#pragma once + +enum i2c_id { + NI2C +}; diff --git a/libplatsupport/plat_include/bcm2712/platsupport/plat/mailbox.h b/libplatsupport/plat_include/bcm2712/platsupport/plat/mailbox.h new file mode 100644 index 000000000..74f80199d --- /dev/null +++ b/libplatsupport/plat_include/bcm2712/platsupport/plat/mailbox.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2021, HENSOLDT Cyber GmbH + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +#define MAILBOX_PADDR 0x107c013880 +#define MAILBOX_SIZE 0x1000 diff --git a/libplatsupport/plat_include/bcm2712/platsupport/plat/serial.h b/libplatsupport/plat_include/bcm2712/platsupport/plat/serial.h new file mode 100644 index 000000000..c2b7a84b3 --- /dev/null +++ b/libplatsupport/plat_include/bcm2712/platsupport/plat/serial.h @@ -0,0 +1,34 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +/* Corresponds to the Device Tree node '/soc@107c000000/serial@7d001000' */ +#define PL011_UART_BASE 0x107d001000 + +#define UART0_OFFSET 0x0 // UART0: PL011 + +#define UART0_PADDR (PL011_UART_BASE) + +#define UART0_IRQ 153 + +#define DEFAULT_SERIAL_PADDR UART0_PADDR +#define DEFAULT_SERIAL_INTERRUPT UART0_IRQ + +enum chardev_id { + BCM2xxx_UART0, + + NUM_CHARDEV, + + /* Aliases */ + PS_SERIAL0 = BCM2xxx_UART0, + + /* Defaults */ + PS_SERIAL_DEFAULT = BCM2xxx_UART0 +}; diff --git a/libplatsupport/plat_include/bcm2712/platsupport/plat/system_timer.h b/libplatsupport/plat_include/bcm2712/platsupport/plat/system_timer.h new file mode 100644 index 000000000..48bc3b986 --- /dev/null +++ b/libplatsupport/plat_include/bcm2712/platsupport/plat/system_timer.h @@ -0,0 +1,19 @@ +/* + * Copyright 2025, UNSW + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#pragma once + +#include + +/* + * The Device Tree by default for BCM2712 will contain the timer IRQs + * for each channel. Channels 0 and 2 are used by the VideoCore, so + * we use 1 instead. + */ +#define BCM_SYSTEM_TIMER_CHANNEL (1) +#define BCM_SYSTEM_TIMER_FREQ (MHZ) +#define BCM_SYSTEM_TIMER_FDT_PATH "/soc@107c000000/timer@7c003000" +#define BCM_SYSTEM_TIMER_REG_CHOICE (0) +#define BCM_SYSTEM_TIMER_IRQ_CHOICE (1) diff --git a/libplatsupport/src/fdt.c b/libplatsupport/src/fdt.c index f5078d40a..c80dacf70 100644 --- a/libplatsupport/src/fdt.c +++ b/libplatsupport/src/fdt.c @@ -116,6 +116,20 @@ int ps_fdt_walk_registers(ps_io_fdt_t *io_fdt, ps_fdt_cookie_t *cookie, reg_walk } int total_cells = prop_len / sizeof(uint32_t); + int parent_ranges_prop_len = 0; + const uint32_t *parent_ranges_prop = fdt_getprop(dtb_blob, parent_offset, "ranges", &parent_ranges_prop_len); + bool parent_has_ranges = parent_ranges_prop != NULL; + + int num_parent_bus_address_cells = 0; + if (parent_has_ranges) { + int parent_bus_node_offset = fdt_parent_offset(dtb_blob, parent_offset); + /* If the parent has the ranges field, it should have its own parent node. */ + if (parent_bus_node_offset < 0) { + return parent_bus_node_offset; + } + num_parent_bus_address_cells = fdt_address_cells(dtb_blob, parent_bus_node_offset); + } + /* sanity check */ assert(total_cells % (num_address_cells + num_size_cells) == 0); @@ -128,6 +142,23 @@ int ps_fdt_walk_registers(ps_io_fdt_t *io_fdt, ps_fdt_cookie_t *cookie, reg_walk curr_pmem.type = PMEM_TYPE_DEVICE; curr_pmem.base_addr = READ_CELL(num_address_cells, curr, 0); curr_pmem.length = READ_CELL(num_size_cells, curr, num_address_cells); + + if (parent_has_ranges) { + assert(num_parent_bus_address_cells != 0); + int parent_ranges_cells = parent_ranges_prop_len / sizeof(uint32_t); + int num_ranges = parent_ranges_cells / (num_parent_bus_address_cells + num_address_cells + num_size_cells); + for (int j = 0; j < num_ranges; j++) { + const void *curr_range = (const void *)(&parent_ranges_prop[j]); + uint64_t child_bus_addr = READ_CELL(num_address_cells, curr_range, 0); + uint64_t parent_bus_addr = READ_CELL(num_parent_bus_address_cells, curr_range, num_address_cells); + uint64_t range_length = READ_CELL(num_size_cells, curr_range, num_address_cells + num_parent_bus_address_cells); + if (child_bus_addr <= curr_pmem.base_addr && child_bus_addr + range_length > curr_pmem.base_addr) { + uint64_t offset = curr_pmem.base_addr - child_bus_addr; + curr_pmem.base_addr = parent_bus_addr + offset; + } + } + } + int error = callback(curr_pmem, i, num_regs, token); if (error) { return error; diff --git a/libplatsupport/src/mach/bcm/bcm_uart.c b/libplatsupport/src/mach/bcm/bcm_uart.c index 5c56cc6e3..b19824ad5 100644 --- a/libplatsupport/src/mach/bcm/bcm_uart.c +++ b/libplatsupport/src/mach/bcm/bcm_uart.c @@ -121,9 +121,16 @@ int bcm_uart_init(const struct dev_defn *defn, const ps_io_ops_t *ops, ps_charde uint32_t addr_offset = 0; switch (defn->id) { +#if defined(CONFIG_PLAT_BCM2711) || defined(CONFIG_PLAT_BCM2837) case 1: addr_offset = UART1_OFFSET; break; +#elif defined (CONFIG_PLAT_BCM2712) + /* BCM UART is not supported on BCM2712 as it is on the PCIe bus rather + * than the SoC itself. */ +#else +#error "bcm_uart_init: unknown platform" +#endif default: ZF_LOGE("Mini-UART with ID %d does not exist!", defn->id); return -1; diff --git a/libplatsupport/src/mach/bcm/chardev.c b/libplatsupport/src/mach/bcm/chardev.c index e13324178..f0b9093dd 100644 --- a/libplatsupport/src/mach/bcm/chardev.c +++ b/libplatsupport/src/mach/bcm/chardev.c @@ -44,6 +44,14 @@ static const struct dev_defn dev_defn[] = { UART_DEFN(5) }; +#elif defined(CONFIG_PLAT_BCM2712) + +static const int uart_irqs_0[] = { UART0_IRQ, -1 }; + +static const struct dev_defn dev_defn[] = { + UART_DEFN(0), +}; + #elif defined(CONFIG_PLAT_BCM2837) static const int uart_irqs_0[] = { UART0_IRQ, -1 }; diff --git a/libplatsupport/src/mach/bcm/pl011_uart.c b/libplatsupport/src/mach/bcm/pl011_uart.c index 9463728aa..029c24835 100644 --- a/libplatsupport/src/mach/bcm/pl011_uart.c +++ b/libplatsupport/src/mach/bcm/pl011_uart.c @@ -277,6 +277,17 @@ int pl011_uart_init(const struct dev_defn *defn, const ps_io_ops_t *ops, ps_char return -1; } +#elif defined(CONFIG_PLAT_BCM2712) + + switch (defn->id) { + case BCM2xxx_UART0: + addr_offset = UART0_OFFSET; + break; + default: + ZF_LOGE("PL011 UART with ID %d does not exist!", defn->id); + return -1; + } + #elif defined(CONFIG_PLAT_BCM2837) switch (defn->id) { diff --git a/libplatsupport/src/mach/bcm/serial.c b/libplatsupport/src/mach/bcm/serial.c index 0091c15f7..37a7921da 100644 --- a/libplatsupport/src/mach/bcm/serial.c +++ b/libplatsupport/src/mach/bcm/serial.c @@ -45,6 +45,10 @@ static const uart_gpio_defn_t gpio_defs[NUM_CHARDEV] = { UART_GPIO_DEFN(BCM2xxx_UART5, 12, 13, BCM2711_GPIO_FSEL_ALT4) // UART 5 uses GPIO pins 12-13 }; +#elif defined(CONFIG_PLAT_BCM2712) + +/* GPIO is not supported on BCM2712. */ + #elif defined(CONFIG_PLAT_BCM2837) static const uart_gpio_defn_t gpio_defs[NUM_CHARDEV] = { @@ -96,6 +100,7 @@ int uart_gpio_configure(enum chardev_id id, const ps_io_ops_t *o) // control (CTS/RTS pins) for now. uart_gpio_defn_t pindef = { -1, -1, -1, -1 }; +#ifndef CONFIG_PLAT_BCM2712 for (int i = 0; i < NUM_CHARDEV; i++) { if (id == gpio_defs[i].uart_id) { pindef = gpio_defs[i]; @@ -137,6 +142,8 @@ int uart_gpio_configure(enum chardev_id id, const ps_io_ops_t *o) #else #error "Unknown BCM2xxx platform!" +#endif + #endif return 0; @@ -163,6 +170,13 @@ int uart_init(const struct dev_defn *defn, const ps_io_ops_t *ops, ps_chardevice uart_funcs.uart_putchar = &pl011_uart_putchar; break; +#elif defined(CONFIG_PLAT_BCM2712) + case BCM2xxx_UART0: + uart_funcs.uart_init = &pl011_uart_init; + uart_funcs.uart_getchar = &pl011_uart_getchar; + uart_funcs.uart_putchar = &pl011_uart_putchar; + break; + #elif defined(CONFIG_PLAT_BCM2837) case 0: