mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-06 13:14:27 +00:00
a0018fc820
Commit40686c394e
("riscv: Clean up IPI initialization code") caused U-Boot failed to boot on SiFive HiFive Unleashed board. The codes inside arch_cpu_init_dm() may call U-Boot timer APIs before the call to riscv_init_ipi(). At that time the timer register base (e.g.: the SiFive CLINT device in this case) is unknown yet. It might be the name riscv_init_ipi() that misleads people to only consider it is related to IPI, but in fact the timer capability is provided by the same SiFive CLINT device that provides the IPI. Timer capability is needed for both UP and SMP. Considering that the original refactor does have benefits, that it makes the IPI code more similar to U-Boot initialization idioms. It also removes some quite ugly macros. Let's do the minimal revert instead of a complete revert, plus a fixes to arch_cpu_init_dm() to consider the SPL case. Fixes:40686c394e
("riscv: Clean up IPI initialization code") Signed-off-by: Bin Meng <bin.meng@windriver.com> Reviewed-by: Sean Anderson <seanga2@gmail.com> Tested-by: Leo Liang <ycliang@andestech.com>
122 lines
2.6 KiB
C
122 lines
2.6 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <cpu.h>
|
|
#include <dm.h>
|
|
#include <init.h>
|
|
#include <log.h>
|
|
#include <asm/encoding.h>
|
|
#include <dm/uclass-internal.h>
|
|
#include <linux/bitops.h>
|
|
|
|
/*
|
|
* The variables here must be stored in the data section since they are used
|
|
* before the bss section is available.
|
|
*/
|
|
#ifdef CONFIG_OF_PRIOR_STAGE
|
|
phys_addr_t prior_stage_fdt_address __attribute__((section(".data")));
|
|
#endif
|
|
#ifndef CONFIG_XIP
|
|
u32 hart_lottery __attribute__((section(".data"))) = 0;
|
|
|
|
/*
|
|
* The main hart running U-Boot has acquired available_harts_lock until it has
|
|
* finished initialization of global data.
|
|
*/
|
|
u32 available_harts_lock = 1;
|
|
#endif
|
|
|
|
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 */
|
|
#if CONFIG_IS_ENABLED(RISCV_MMODE)
|
|
return csr_read(CSR_MISA) & (1 << (ext - 'a'));
|
|
#else /* !CONFIG_IS_ENABLED(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_IS_ENABLED(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 arch_cpu_init_dm(void)
|
|
{
|
|
int ret;
|
|
|
|
ret = riscv_cpu_probe();
|
|
if (ret)
|
|
return ret;
|
|
|
|
/* Enable FPU */
|
|
if (supports_extension('d') || supports_extension('f')) {
|
|
csr_set(MODE_PREFIX(status), MSTATUS_FS);
|
|
csr_write(CSR_FCSR, 0);
|
|
}
|
|
|
|
if (CONFIG_IS_ENABLED(RISCV_MMODE)) {
|
|
/*
|
|
* Enable perf counters for cycle, time,
|
|
* and instret counters only
|
|
*/
|
|
#ifdef CONFIG_RISCV_PRIV_1_9
|
|
csr_write(CSR_MSCOUNTEREN, GENMASK(2, 0));
|
|
csr_write(CSR_MUCOUNTEREN, GENMASK(2, 0));
|
|
#else
|
|
csr_write(CSR_MCOUNTEREN, GENMASK(2, 0));
|
|
#endif
|
|
|
|
/* Disable paging */
|
|
if (supports_extension('s'))
|
|
#ifdef CONFIG_RISCV_PRIV_1_9
|
|
csr_read_clear(CSR_MSTATUS, SR_VM);
|
|
#else
|
|
csr_write(CSR_SATP, 0);
|
|
#endif
|
|
}
|
|
|
|
#if CONFIG_IS_ENABLED(SMP)
|
|
ret = riscv_init_ipi();
|
|
if (ret)
|
|
return ret;
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
int arch_early_init_r(void)
|
|
{
|
|
return riscv_cpu_probe();
|
|
}
|