mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-22 23:21:31 +00:00
riscv: Clean up IPI initialization code
The previous IPI code initialized the device whenever the first call was made to a riscv_*_ipi function. This made it difficult to determine when the IPI device was initialized. This patch introduces a new function riscv_init_ipi. It is called once during arch_cpu_init_dm. In SPL, it is called in spl_invoke_opensbi. Before this point, no riscv_*_ipi functions should be called. Signed-off-by: Sean Anderson <seanga2@gmail.com> Reviewed-by: Rick Chen <rick@andestech.com>
This commit is contained in:
parent
9472630337
commit
40686c394e
7 changed files with 89 additions and 86 deletions
|
@ -98,6 +98,12 @@ int arch_cpu_init_dm(void)
|
||||||
csr_write(CSR_SATP, 0);
|
csr_write(CSR_SATP, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
ret = riscv_init_ipi();
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,4 +51,47 @@ void handle_ipi(ulong hart);
|
||||||
*/
|
*/
|
||||||
int smp_call_function(ulong addr, ulong arg0, ulong arg1, int wait);
|
int smp_call_function(ulong addr, ulong arg0, ulong arg1, int wait);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* riscv_init_ipi() - Initialize inter-process interrupt (IPI) driver
|
||||||
|
*
|
||||||
|
* Platform code must provide this function. This function is called once after
|
||||||
|
* the cpu driver is initialized. No other riscv_*_ipi() calls will be made
|
||||||
|
* before this function is called.
|
||||||
|
*
|
||||||
|
* @return 0 if OK, -ve on error
|
||||||
|
*/
|
||||||
|
int riscv_init_ipi(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* riscv_send_ipi() - Send inter-processor interrupt (IPI)
|
||||||
|
*
|
||||||
|
* Platform code must provide this function.
|
||||||
|
*
|
||||||
|
* @hart: Hart ID of receiving hart
|
||||||
|
* @return 0 if OK, -ve on error
|
||||||
|
*/
|
||||||
|
int riscv_send_ipi(int hart);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* riscv_clear_ipi() - Clear inter-processor interrupt (IPI)
|
||||||
|
*
|
||||||
|
* Platform code must provide this function.
|
||||||
|
*
|
||||||
|
* @hart: Hart ID of hart to be cleared
|
||||||
|
* @return 0 if OK, -ve on error
|
||||||
|
*/
|
||||||
|
int riscv_clear_ipi(int hart);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* riscv_get_ipi() - Get status of inter-processor interrupt (IPI)
|
||||||
|
*
|
||||||
|
* Platform code must provide this function.
|
||||||
|
*
|
||||||
|
* @hart: Hart ID of hart to be checked
|
||||||
|
* @pending: Pointer to variable with result of the check,
|
||||||
|
* 1 if IPI is pending, 0 otherwise
|
||||||
|
* @return 0 if OK, -ve on error
|
||||||
|
*/
|
||||||
|
int riscv_get_ipi(int hart, int *pending);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,20 +30,6 @@
|
||||||
#define SEND_IPI_TO_HART(hart) (0x80 >> (hart))
|
#define SEND_IPI_TO_HART(hart) (0x80 >> (hart))
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
static int init_plic(void);
|
|
||||||
|
|
||||||
#define PLIC_BASE_GET(void) \
|
|
||||||
do { \
|
|
||||||
long *ret; \
|
|
||||||
\
|
|
||||||
if (!gd->arch.plic) { \
|
|
||||||
ret = syscon_get_first_range(RISCV_SYSCON_PLIC); \
|
|
||||||
if (IS_ERR(ret)) \
|
|
||||||
return PTR_ERR(ret); \
|
|
||||||
gd->arch.plic = ret; \
|
|
||||||
init_plic(); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
static int enable_ipi(int hart)
|
static int enable_ipi(int hart)
|
||||||
{
|
{
|
||||||
|
@ -93,13 +79,21 @@ static int init_plic(void)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int riscv_init_ipi(void)
|
||||||
|
{
|
||||||
|
long *ret = syscon_get_first_range(RISCV_SYSCON_PLIC);
|
||||||
|
|
||||||
|
if (IS_ERR(ret))
|
||||||
|
return PTR_ERR(ret);
|
||||||
|
gd->arch.plic = ret;
|
||||||
|
|
||||||
|
return init_plic();
|
||||||
|
}
|
||||||
|
|
||||||
int riscv_send_ipi(int hart)
|
int riscv_send_ipi(int hart)
|
||||||
{
|
{
|
||||||
unsigned int ipi;
|
unsigned int ipi = (SEND_IPI_TO_HART(hart) << (8 * gd->arch.boot_hart));
|
||||||
|
|
||||||
PLIC_BASE_GET();
|
|
||||||
|
|
||||||
ipi = (SEND_IPI_TO_HART(hart) << (8 * gd->arch.boot_hart));
|
|
||||||
writel(ipi, (void __iomem *)PENDING_REG(gd->arch.plic,
|
writel(ipi, (void __iomem *)PENDING_REG(gd->arch.plic,
|
||||||
gd->arch.boot_hart));
|
gd->arch.boot_hart));
|
||||||
|
|
||||||
|
@ -110,8 +104,6 @@ int riscv_clear_ipi(int hart)
|
||||||
{
|
{
|
||||||
u32 source_id;
|
u32 source_id;
|
||||||
|
|
||||||
PLIC_BASE_GET();
|
|
||||||
|
|
||||||
source_id = readl((void __iomem *)CLAIM_REG(gd->arch.plic, hart));
|
source_id = readl((void __iomem *)CLAIM_REG(gd->arch.plic, hart));
|
||||||
writel(source_id, (void __iomem *)CLAIM_REG(gd->arch.plic, hart));
|
writel(source_id, (void __iomem *)CLAIM_REG(gd->arch.plic, hart));
|
||||||
|
|
||||||
|
@ -120,8 +112,6 @@ int riscv_clear_ipi(int hart)
|
||||||
|
|
||||||
int riscv_get_ipi(int hart, int *pending)
|
int riscv_get_ipi(int hart, int *pending)
|
||||||
{
|
{
|
||||||
PLIC_BASE_GET();
|
|
||||||
|
|
||||||
*pending = readl((void __iomem *)PENDING_REG(gd->arch.plic,
|
*pending = readl((void __iomem *)PENDING_REG(gd->arch.plic,
|
||||||
gd->arch.boot_hart));
|
gd->arch.boot_hart));
|
||||||
*pending = !!(*pending & SEND_IPI_TO_HART(hart));
|
*pending = !!(*pending & SEND_IPI_TO_HART(hart));
|
||||||
|
|
|
@ -8,6 +8,11 @@
|
||||||
#include <asm/encoding.h>
|
#include <asm/encoding.h>
|
||||||
#include <asm/sbi.h>
|
#include <asm/sbi.h>
|
||||||
|
|
||||||
|
int riscv_init_ipi(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int riscv_send_ipi(int hart)
|
int riscv_send_ipi(int hart)
|
||||||
{
|
{
|
||||||
ulong mask;
|
ulong mask;
|
||||||
|
|
|
@ -24,22 +24,8 @@
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
#define CLINT_BASE_GET(void) \
|
|
||||||
do { \
|
|
||||||
long *ret; \
|
|
||||||
\
|
|
||||||
if (!gd->arch.clint) { \
|
|
||||||
ret = syscon_get_first_range(RISCV_SYSCON_CLINT); \
|
|
||||||
if (IS_ERR(ret)) \
|
|
||||||
return PTR_ERR(ret); \
|
|
||||||
gd->arch.clint = ret; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
int riscv_get_time(u64 *time)
|
int riscv_get_time(u64 *time)
|
||||||
{
|
{
|
||||||
CLINT_BASE_GET();
|
|
||||||
|
|
||||||
*time = readq((void __iomem *)MTIME_REG(gd->arch.clint));
|
*time = readq((void __iomem *)MTIME_REG(gd->arch.clint));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -47,17 +33,24 @@ int riscv_get_time(u64 *time)
|
||||||
|
|
||||||
int riscv_set_timecmp(int hart, u64 cmp)
|
int riscv_set_timecmp(int hart, u64 cmp)
|
||||||
{
|
{
|
||||||
CLINT_BASE_GET();
|
|
||||||
|
|
||||||
writeq(cmp, (void __iomem *)MTIMECMP_REG(gd->arch.clint, hart));
|
writeq(cmp, (void __iomem *)MTIMECMP_REG(gd->arch.clint, hart));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int riscv_init_ipi(void)
|
||||||
|
{
|
||||||
|
long *ret = syscon_get_first_range(RISCV_SYSCON_CLINT);
|
||||||
|
|
||||||
|
if (IS_ERR(ret))
|
||||||
|
return PTR_ERR(ret);
|
||||||
|
gd->arch.clint = ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int riscv_send_ipi(int hart)
|
int riscv_send_ipi(int hart)
|
||||||
{
|
{
|
||||||
CLINT_BASE_GET();
|
|
||||||
|
|
||||||
writel(1, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
|
writel(1, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -65,8 +58,6 @@ int riscv_send_ipi(int hart)
|
||||||
|
|
||||||
int riscv_clear_ipi(int hart)
|
int riscv_clear_ipi(int hart)
|
||||||
{
|
{
|
||||||
CLINT_BASE_GET();
|
|
||||||
|
|
||||||
writel(0, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
|
writel(0, (void __iomem *)MSIP_REG(gd->arch.clint, hart));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -74,8 +65,6 @@ int riscv_clear_ipi(int hart)
|
||||||
|
|
||||||
int riscv_get_ipi(int hart, int *pending)
|
int riscv_get_ipi(int hart, int *pending)
|
||||||
{
|
{
|
||||||
CLINT_BASE_GET();
|
|
||||||
|
|
||||||
*pending = readl((void __iomem *)MSIP_REG(gd->arch.clint, hart));
|
*pending = readl((void __iomem *)MSIP_REG(gd->arch.clint, hart));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -12,38 +12,6 @@
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
/**
|
|
||||||
* riscv_send_ipi() - Send inter-processor interrupt (IPI)
|
|
||||||
*
|
|
||||||
* Platform code must provide this function.
|
|
||||||
*
|
|
||||||
* @hart: Hart ID of receiving hart
|
|
||||||
* @return 0 if OK, -ve on error
|
|
||||||
*/
|
|
||||||
extern int riscv_send_ipi(int hart);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* riscv_clear_ipi() - Clear inter-processor interrupt (IPI)
|
|
||||||
*
|
|
||||||
* Platform code must provide this function.
|
|
||||||
*
|
|
||||||
* @hart: Hart ID of hart to be cleared
|
|
||||||
* @return 0 if OK, -ve on error
|
|
||||||
*/
|
|
||||||
extern int riscv_clear_ipi(int hart);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* riscv_get_ipi() - Get status of inter-processor interrupt (IPI)
|
|
||||||
*
|
|
||||||
* Platform code must provide this function.
|
|
||||||
*
|
|
||||||
* @hart: Hart ID of hart to be checked
|
|
||||||
* @pending: Pointer to variable with result of the check,
|
|
||||||
* 1 if IPI is pending, 0 otherwise
|
|
||||||
* @return 0 if OK, -ve on error
|
|
||||||
*/
|
|
||||||
extern int riscv_get_ipi(int hart, int *pending);
|
|
||||||
|
|
||||||
static int send_ipi_many(struct ipi_data *ipi, int wait)
|
static int send_ipi_many(struct ipi_data *ipi, int wait)
|
||||||
{
|
{
|
||||||
ofnode node, cpus;
|
ofnode node, cpus;
|
||||||
|
@ -124,7 +92,7 @@ void handle_ipi(ulong hart)
|
||||||
*/
|
*/
|
||||||
ret = riscv_clear_ipi(hart);
|
ret = riscv_clear_ipi(hart);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("Cannot clear IPI of hart %ld\n", hart);
|
pr_err("Cannot clear IPI of hart %ld (error %d)\n", hart, ret);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,14 +101,11 @@ void handle_ipi(ulong hart)
|
||||||
|
|
||||||
int smp_call_function(ulong addr, ulong arg0, ulong arg1, int wait)
|
int smp_call_function(ulong addr, ulong arg0, ulong arg1, int wait)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
struct ipi_data ipi = {
|
||||||
struct ipi_data ipi;
|
.addr = addr,
|
||||||
|
.arg0 = arg0,
|
||||||
|
.arg1 = arg1,
|
||||||
|
};
|
||||||
|
|
||||||
ipi.addr = addr;
|
return send_ipi_many(&ipi, wait);
|
||||||
ipi.arg0 = arg0;
|
|
||||||
ipi.arg1 = arg1;
|
|
||||||
|
|
||||||
ret = send_ipi_many(&ipi, wait);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,11 @@ void spl_invoke_opensbi(struct spl_image_info *spl_image)
|
||||||
invalidate_icache_all();
|
invalidate_icache_all();
|
||||||
|
|
||||||
#ifdef CONFIG_SPL_SMP
|
#ifdef CONFIG_SPL_SMP
|
||||||
|
/* Initialize the IPI before we use it */
|
||||||
|
ret = riscv_init_ipi();
|
||||||
|
if (ret)
|
||||||
|
hang();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start OpenSBI on all secondary harts and wait for acknowledgment.
|
* Start OpenSBI on all secondary harts and wait for acknowledgment.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Reference in a new issue