diff options
Diffstat (limited to 'arch/riscv/cpu/cpu.c')
-rw-r--r-- | arch/riscv/cpu/cpu.c | 98 |
1 files changed, 69 insertions, 29 deletions
diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c index d9f820c44c..e662140427 100644 --- a/arch/riscv/cpu/cpu.c +++ b/arch/riscv/cpu/cpu.c @@ -4,7 +4,12 @@ */ #include <common.h> +#include <cpu.h> +#include <dm.h> +#include <log.h> #include <asm/csr.h> +#include <asm/encoding.h> +#include <dm/uclass-internal.h> /* * prior_stage_fdt_address must be stored in the data section since it is used @@ -12,44 +17,79 @@ */ phys_addr_t prior_stage_fdt_address __attribute__((section(".data"))); -enum { - ISA_INVALID = 0, - ISA_32BIT, - ISA_64BIT, - ISA_128BIT -}; - -static const char * const isa_bits[] = { - [ISA_INVALID] = NULL, - [ISA_32BIT] = "32", - [ISA_64BIT] = "64", - [ISA_128BIT] = "128" -}; - static inline bool supports_extension(char ext) { +#ifdef CONFIG_CPU + struct udevice *dev; + char desc[32]; + + uclass_find_first_device(UCLASS_CPU, &dev); + if (!dev) { + debug("unable to find the RISC-V cpu device\n"); + return false; + } + if (!cpu_get_desc(dev, desc, sizeof(desc))) { + /* skip the first 4 characters (rv32|rv64) */ + if (strchr(desc + 4, ext)) + return true; + } + + return false; +#else /* !CONFIG_CPU */ +#ifdef CONFIG_RISCV_MMODE return csr_read(misa) & (1 << (ext - 'a')); +#else /* !CONFIG_RISCV_MMODE */ +#warning "There is no way to determine the available extensions in S-mode." +#warning "Please convert your board to use the RISC-V CPU driver." + return false; +#endif /* CONFIG_RISCV_MMODE */ +#endif /* CONFIG_CPU */ +} + +static int riscv_cpu_probe(void) +{ +#ifdef CONFIG_CPU + int ret; + + /* probe cpus so that RISC-V timer can be bound */ + ret = cpu_probe_all(); + if (ret) + return log_msg_ret("RISC-V cpus probe failed\n", ret); +#endif + + return 0; } -int print_cpuinfo(void) +int arch_cpu_init_dm(void) { - char name[32]; - char *s = name; - int bit; + int ret; + + ret = riscv_cpu_probe(); + if (ret) + return ret; - s += sprintf(name, "rv"); - bit = csr_read(misa) >> (sizeof(long) * 8 - 2); - s += sprintf(s, isa_bits[bit]); + /* Enable FPU */ + if (supports_extension('d') || supports_extension('f')) { + csr_set(MODE_PREFIX(status), MSTATUS_FS); + csr_write(fcsr, 0); + } - supports_extension('i') ? *s++ = 'i' : 'r'; - supports_extension('m') ? *s++ = 'm' : 'i'; - supports_extension('a') ? *s++ = 'a' : 's'; - supports_extension('f') ? *s++ = 'f' : 'c'; - supports_extension('d') ? *s++ = 'd' : '-'; - supports_extension('c') ? *s++ = 'c' : 'v'; - *s++ = '\0'; + if (CONFIG_IS_ENABLED(RISCV_MMODE)) { + /* + * Enable perf counters for cycle, time, + * and instret counters only + */ + csr_write(mcounteren, GENMASK(2, 0)); - printf("CPU: %s\n", name); + /* Disable paging */ + if (supports_extension('s')) + csr_write(satp, 0); + } return 0; } + +int arch_early_init_r(void) +{ + return riscv_cpu_probe(); +} |