diff options
author | Anup Patel <anup.patel@wdc.com> | 2020-03-19 11:23:41 +0530 |
---|---|---|
committer | Anup Patel <anup@brainfault.org> | 2020-03-28 13:31:50 +0530 |
commit | 160c88535f07084051ebba97689fc4a7b2e9037c (patch) | |
tree | 593e42dc4a3165d5fcb8740f192be2ee4ebd631b /lib/utils/fdt | |
parent | 550ba88db1950d448f25cf71457ed89a91c401f7 (diff) |
lib: utils: Improve fdt_cpu_fixup() implementation
Currently, the fdt_cpu_fixup() implementation assumes:
1. We have one CPU DT for each HART under /cpus DT node
2. The CPU DT nodes are named sequentially (i.e cpu@0,
cpu@1, ...) which is not true for discontinuous and
sparse HART ids (i.e. cpu@0, cpu@4, cpu@5). Generally,
CPU DT node are named based on HART id and not HART
index
If any of the above assumptions are violated then the
fdt_cpu_fixup() will not work.
This improves fdt_cpu_fixup() implementation and makes
it independent of above assumptions.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Atish Patra <atish.patra@wdc.com>
Diffstat (limited to 'lib/utils/fdt')
-rw-r--r-- | lib/utils/fdt/fdt_fixup.c | 35 |
1 files changed, 24 insertions, 11 deletions
diff --git a/lib/utils/fdt/fdt_fixup.c b/lib/utils/fdt/fdt_fixup.c index b91e95f..d6e4cc1 100644 --- a/lib/utils/fdt/fdt_fixup.c +++ b/lib/utils/fdt/fdt_fixup.c @@ -12,30 +12,43 @@ #include <sbi/sbi_console.h> #include <sbi/sbi_platform.h> #include <sbi/sbi_scratch.h> +#include <sbi/sbi_string.h> void fdt_cpu_fixup(void *fdt) { struct sbi_scratch *scratch = sbi_scratch_thishart_ptr(); const struct sbi_platform *plat = sbi_platform_ptr(scratch); - char cpu_node[32] = ""; - int cpu_offset; - int err; - u32 i; + int err, len, cpu_offset, cpus_offset; + const fdt32_t *val; + const void *prop; + u32 hartid; err = fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + 32); if (err < 0) return; - /* assume hart ids are continuous */ - for (i = 0; i < sbi_platform_hart_count(plat); i++) { - sbi_sprintf(cpu_node, "/cpus/cpu@%d", i); - cpu_offset = fdt_path_offset(fdt, cpu_node); + cpus_offset = fdt_path_offset(fdt, "/cpus"); + if (cpus_offset < 0) + return; + + fdt_for_each_subnode(cpu_offset, fdt, cpus_offset) { + prop = fdt_getprop(fdt, cpu_offset, "device_type", &len); + if (!prop || !len) + continue; + if (sbi_strcmp(prop, "cpu")) + continue; - if (sbi_platform_hart_invalid(plat, i)) + val = fdt_getprop(fdt, cpu_offset, "reg", &len); + if (!val || len < sizeof(fdt32_t)) + continue; + + if (len > sizeof(fdt32_t)) + val++; + hartid = fdt32_to_cpu(*val); + + if (sbi_platform_hart_invalid(plat, hartid)) fdt_setprop_string(fdt, cpu_offset, "status", "disabled"); - - memset(cpu_node, 0, sizeof(cpu_node)); } } |