From e3ec0ab8118602d53078e05ffdeef8484ddd5f98 Mon Sep 17 00:00:00 2001 From: Gedare Bloom Date: Wed, 11 Mar 2026 15:20:53 -0600 Subject: [PATCH] riscv/riscv: refactor FDT helper functions Adds bsp/riscv-fdt.h with new functions for pulling information from the FDT. --- bsps/riscv/include/bsp/riscv-fdt.h | 69 +++++++++++ bsps/riscv/riscv/clock/clockdrv.c | 47 +------- bsps/riscv/shared/fdt/riscv-fdt.c | 147 +++++++++++++++++++++++ bsps/riscv/shared/start/bspgetworkarea.c | 71 +---------- spec/build/bsps/riscv/grp.yml | 1 + spec/build/bsps/riscv/noel/obj.yml | 1 + spec/build/bsps/riscv/riscv/obj.yml | 1 + 7 files changed, 223 insertions(+), 114 deletions(-) create mode 100644 bsps/riscv/include/bsp/riscv-fdt.h create mode 100644 bsps/riscv/shared/fdt/riscv-fdt.c diff --git a/bsps/riscv/include/bsp/riscv-fdt.h b/bsps/riscv/include/bsp/riscv-fdt.h new file mode 100644 index 0000000000..b3e61f01c2 --- /dev/null +++ b/bsps/riscv/include/bsp/riscv-fdt.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSBSPsRISCVShared + * + * @brief This header file provides interfaces for probing the RISC-V ISA + * extensions. + */ + +/* + * Copyright (C) 2026 Gedare Bloom + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _BSP_RISCV_FDT_H +#define _BSP_RISCV_FDT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @brief Finds the end of memory from the @a fdt properties. + * + * @return Returns the last valid address of memory. + */ +void *riscv_fdt_get_end_of_memory(const void *fdt); + +/** + * @brief Finds the timebase frequency from the @a fdt properties. + * + * @return Returns the timebase frequency. + */ +uint32_t riscv_clock_get_timebase_frequency(const void *fdt); + +/** + * @brief Searches for the ISA @a extension within the @a fdt. + */ +bool riscv_has_isa_extension(const void *fdt, const char *extension); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _BSP_RISCV_FDT_H */ diff --git a/bsps/riscv/riscv/clock/clockdrv.c b/bsps/riscv/riscv/clock/clockdrv.c index d7a066447e..ac0c8d3c52 100644 --- a/bsps/riscv/riscv/clock/clockdrv.c +++ b/bsps/riscv/riscv/clock/clockdrv.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -49,7 +50,6 @@ #include #ifdef RISCV_USE_S_MODE -#include #include static bool riscv_has_sstc; @@ -111,30 +111,6 @@ static uint64_t riscv_clock_read_mtime(volatile RISCV_CLINT_timer_reg *mtime) } #endif /* !RISCV_USE_S_MODE */ -#ifdef RISCV_USE_S_MODE -static bool riscv_has_isa_extension(const void *fdt, const char *ext) -{ - int node; - const char *val; - int len = 0; - - node = fdt_path_offset(fdt, "/cpus"); - - val = (const char *) fdt_getprop(fdt, node, "riscv,isa", &len); - - if (val == NULL || len == 0) { - int cpu0 = fdt_subnode_offset(fdt, node, "cpu@0"); - val = (const char *) fdt_getprop(fdt, cpu0, "riscv,isa", &len); - - if (val == NULL || len == 0) { - return false; - } - } - - return strstr( val, ext ) != NULL; -} -#endif - static void riscv_clock_handler_install(rtems_interrupt_handler handler) { rtems_status_code sc; @@ -166,27 +142,6 @@ static uint32_t riscv_clock_get_timecount(struct timecounter *base) return timecount; } -static uint32_t riscv_clock_get_timebase_frequency(const void *fdt) -{ - int node; - const fdt32_t *val; - int len=0; - - node = fdt_path_offset(fdt, "/cpus"); - - val = (fdt32_t *) fdt_getprop(fdt, node, "timebase-frequency", &len); - - if (val == NULL || len < 4) { - int cpu0 = fdt_subnode_offset(fdt, node, "cpu@0"); - val = (fdt32_t *) fdt_getprop(fdt, cpu0, "timebase-frequency", &len); - - if (val == NULL || len < 4) { - bsp_fatal(RISCV_FATAL_NO_TIMEBASE_FREQUENCY_IN_DEVICE_TREE); - } - } - return fdt32_to_cpu(*val); -} - static uint64_t riscv_clock_read_timer(riscv_timecounter *tc) { uint64_t now; diff --git a/bsps/riscv/shared/fdt/riscv-fdt.c b/bsps/riscv/shared/fdt/riscv-fdt.c new file mode 100644 index 0000000000..31580c5092 --- /dev/null +++ b/bsps/riscv/shared/fdt/riscv-fdt.c @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSBSPsRISCVShared + * + * @brief Helpers to probe the RISC-V ISA extensions. + * + */ + +/* + * Copyright (C) 2026 Gedare Bloom + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include + +void *riscv_fdt_get_end_of_memory( const void *fdt ) +{ + const void *val; + int node; + int parent; + int ac; + int sc; + int len; + uintptr_t start; + uintptr_t size; + + node = fdt_path_offset( fdt, "/memory" ); + + if (node < 0) { + return NULL; + } + + parent = fdt_parent_offset(fdt, node); + if (parent < 0) { + return NULL; + } + + ac = fdt_address_cells(fdt, parent); + if (ac != 1 && ac != 2) { + return NULL; + } + + sc = fdt_size_cells(fdt, parent); + if (sc != 1 && sc != 2) { + return NULL; + } + + if (sc > ac) { + return NULL; + } + + val = fdt_getprop(fdt, node, "reg", &len); + if (len < sc + ac) { + return NULL; + } + + if (ac == 1) { + start = fdt32_ld(&((fdt32_t *)val)[0]); + size = fdt32_ld(&((fdt32_t *)val)[1]); + } + + if (ac == 2) { + start = fdt64_ld(&((fdt64_t *)val)[0]); + if (sc == 1) { + size = fdt32_ld(&((fdt32_t *)(val+8))[0]); + } else { + size = fdt64_ld(&((fdt64_t *)val)[1]); + } + } + + return (void*) (start + size); +} + +uint32_t riscv_clock_get_timebase_frequency(const void *fdt) +{ + int node; + const fdt32_t *val; + int len=0; + + node = fdt_path_offset(fdt, "/cpus"); + + val = (fdt32_t *) fdt_getprop(fdt, node, "timebase-frequency", &len); + + if (val == NULL || len < 4) { + int cpu0 = fdt_subnode_offset(fdt, node, "cpu@0"); + val = (fdt32_t *) fdt_getprop(fdt, cpu0, "timebase-frequency", &len); + + if (val == NULL || len < 4) { + bsp_fatal(RISCV_FATAL_NO_TIMEBASE_FREQUENCY_IN_DEVICE_TREE); + } + } + return fdt32_to_cpu(*val); +} + +bool riscv_has_isa_extension(const void *fdt, const char *ext) +{ + int node; + const char *val; + int len = 0; + + node = fdt_path_offset(fdt, "/cpus"); + + if ( node < 0 ) { + return false; + } + + val = (const char *) fdt_getprop(fdt, node, "riscv,isa", &len); + + if (val == NULL || len == 0) { + int cpu0 = fdt_subnode_offset(fdt, node, "cpu@0"); + val = (const char *) fdt_getprop(fdt, cpu0, "riscv,isa", &len); + + if (val == NULL || len == 0) { + return false; + } + } + + return strstr( val, ext ) != NULL; +} diff --git a/bsps/riscv/shared/start/bspgetworkarea.c b/bsps/riscv/shared/start/bspgetworkarea.c index c3dbb43fdf..839fc8839a 100644 --- a/bsps/riscv/shared/start/bspgetworkarea.c +++ b/bsps/riscv/shared/start/bspgetworkarea.c @@ -36,6 +36,7 @@ #include #include +#include #include @@ -49,79 +50,13 @@ extern char RamEnd[]; static Memory_Area _Memory_Areas[ 1 ]; -static const char memory_path[] = "/memory"; - -static void* get_end_of_memory_from_fdt(void) -{ - const void *fdt; - const void *val; - int node; - int parent; - int ac; - int sc; - int len; - uintptr_t start; - uintptr_t size; - - fdt = bsp_fdt_get(); - - node = fdt_path_offset_namelen( - fdt, - memory_path, - (int) sizeof(memory_path) - 1 - ); - - if (node < 0) { - return NULL; - } - - parent = fdt_parent_offset(fdt, node); - if (parent < 0) { - return NULL; - } - - ac = fdt_address_cells(fdt, parent); - if (ac != 1 && ac != 2) { - return NULL; - } - - sc = fdt_size_cells(fdt, parent); - if (sc != 1 && sc != 2) { - return NULL; - } - - if (sc > ac) { - return NULL; - } - - val = fdt_getprop(fdt, node, "reg", &len); - if (len < sc + ac) { - return NULL; - } - - if (ac == 1) { - start = fdt32_ld(&((fdt32_t *)val)[0]); - size = fdt32_ld(&((fdt32_t *)val)[1]); - } - - if (ac == 2) { - start = fdt64_ld(&((fdt64_t *)val)[0]); - if (sc == 1) { - size = fdt32_ld(&((fdt32_t *)(val+8))[0]); - } else { - size = fdt64_ld(&((fdt64_t *)val)[1]); - } - } - - return (void*) (start + size); -} - static void bsp_memory_initialize( void ) { void *end; + const void *fdt = bsp_fdt_get(); /* get end of memory from the "/memory" node in the fdt */ - end = get_end_of_memory_from_fdt(); + end = riscv_fdt_get_end_of_memory(fdt); if (end == NULL) { /* fall back to linker symbol if "/memory" node not found or invalid */ end = RamEnd; diff --git a/spec/build/bsps/riscv/grp.yml b/spec/build/bsps/riscv/grp.yml index 594eda8e6e..75b11b9e14 100644 --- a/spec/build/bsps/riscv/grp.yml +++ b/spec/build/bsps/riscv/grp.yml @@ -12,6 +12,7 @@ install: source: - bsps/include/bsp/linker-symbols.h - bsps/riscv/include/bsp/linker-symbols-arch.h + - bsps/riscv/include/bsp/riscv-fdt.h ldflags: [] links: [] type: build diff --git a/spec/build/bsps/riscv/noel/obj.yml b/spec/build/bsps/riscv/noel/obj.yml index c108a7cbf6..ee508d7ae6 100644 --- a/spec/build/bsps/riscv/noel/obj.yml +++ b/spec/build/bsps/riscv/noel/obj.yml @@ -23,6 +23,7 @@ source: - bsps/riscv/riscv/irq/irq.c - bsps/riscv/noel/start/bsp_fatal_halt.c - bsps/riscv/riscv/start/bspstart.c +- bsps/riscv/shared/fdt/riscv-fdt.c - bsps/riscv/shared/start/bspgetworkarea.c - bsps/shared/cache/nocache.c - bsps/shared/dev/btimer/btimer-cpucounter.c diff --git a/spec/build/bsps/riscv/riscv/obj.yml b/spec/build/bsps/riscv/riscv/obj.yml index 38783f4031..1daa7fe00f 100644 --- a/spec/build/bsps/riscv/riscv/obj.yml +++ b/spec/build/bsps/riscv/riscv/obj.yml @@ -29,6 +29,7 @@ source: - bsps/riscv/riscv/irq/irq.c - bsps/riscv/riscv/start/bsp_fatal_halt.c - bsps/riscv/riscv/start/bspstart.c +- bsps/riscv/shared/fdt/riscv-fdt.c - bsps/riscv/shared/start/bspgetworkarea.c - bsps/shared/cache/nocache.c - bsps/shared/dev/btimer/btimer-cpucounter.c