mirror of
https://github.com/riscv-software-src/opensbi.git
synced 2025-08-24 15:31:22 +01:00
lib: utils: Support CLINT with 32bit MMIO access on RV64 system
It is possible to have a CLINT implementation which supports only 32bit MMIO accesses on RV64 system so this patch extends our CLINT driver such that platform code can specify whether CLINT supports 64bit MMIO access. Signed-off-by: Anup Patel <anup.patel@wdc.com> Reviewed-by: Atish Patra<atish.patra@wdc.com> Reviewed-by: Zong Li <zong.li@sifive.com>
This commit is contained in:
@@ -30,6 +30,7 @@ void clint_timer_event_start(u64 next_event);
|
||||
|
||||
int clint_warm_timer_init(void);
|
||||
|
||||
int clint_cold_timer_init(unsigned long base, u32 hart_count);
|
||||
int clint_cold_timer_init(unsigned long base, u32 hart_count,
|
||||
bool has_64bit_mmio);
|
||||
|
||||
#endif
|
||||
|
@@ -62,25 +62,45 @@ static volatile void *clint_time_base;
|
||||
static volatile u64 *clint_time_val;
|
||||
static volatile u64 *clint_time_cmp;
|
||||
|
||||
static inline u32 clint_time_read_hi()
|
||||
#if __riscv_xlen != 32
|
||||
static u64 clint_time_rd64(volatile u64 *addr)
|
||||
{
|
||||
return readl_relaxed((u32 *)clint_time_val + 1);
|
||||
return readq_relaxed(addr);
|
||||
}
|
||||
|
||||
u64 clint_timer_value(void)
|
||||
static void clint_time_wr64(u64 value, volatile u64 *addr)
|
||||
{
|
||||
writeq_relaxed(value, addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static u64 clint_time_rd32(volatile u64 *addr)
|
||||
{
|
||||
#if __riscv_xlen == 64
|
||||
return readq_relaxed(clint_time_val);
|
||||
#else
|
||||
u32 lo, hi;
|
||||
|
||||
do {
|
||||
hi = clint_time_read_hi();
|
||||
lo = readl_relaxed(clint_time_val);
|
||||
} while (hi != clint_time_read_hi());
|
||||
hi = readl_relaxed((u32 *)addr + 1);
|
||||
lo = readl_relaxed((u32 *)addr);
|
||||
} while (hi != readl_relaxed((u32 *)addr + 1));
|
||||
|
||||
return ((u64)hi << 32) | (u64)lo;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void clint_time_wr32(u64 value, volatile u64 *addr)
|
||||
{
|
||||
u32 mask = -1U;
|
||||
|
||||
writel_relaxed(value & mask, (void *)(addr));
|
||||
writel_relaxed(value >> 32, (void *)(addr) + 0x04);
|
||||
}
|
||||
|
||||
static u64 (*clint_time_rd)(volatile u64 *addr) = clint_time_rd32;
|
||||
static void (*clint_time_wr)(u64 value, volatile u64 *addr) = clint_time_wr32;
|
||||
|
||||
u64 clint_timer_value(void)
|
||||
{
|
||||
/* Read CLINT Time Value */
|
||||
return clint_time_rd(clint_time_val);
|
||||
}
|
||||
|
||||
void clint_timer_event_stop(void)
|
||||
@@ -90,13 +110,8 @@ void clint_timer_event_stop(void)
|
||||
if (clint_time_hart_count <= target_hart)
|
||||
return;
|
||||
|
||||
/* Clear CLINT Time Compare */
|
||||
#if __riscv_xlen == 64
|
||||
writeq_relaxed(-1ULL, &clint_time_cmp[target_hart]);
|
||||
#else
|
||||
writel_relaxed(-1UL, &clint_time_cmp[target_hart]);
|
||||
writel_relaxed(-1UL, (void *)(&clint_time_cmp[target_hart]) + 0x04);
|
||||
#endif
|
||||
/* Clear CLINT Time Compare */
|
||||
clint_time_wr(-1ULL, &clint_time_cmp[target_hart]);
|
||||
}
|
||||
|
||||
void clint_timer_event_start(u64 next_event)
|
||||
@@ -106,15 +121,8 @@ void clint_timer_event_start(u64 next_event)
|
||||
if (clint_time_hart_count <= target_hart)
|
||||
return;
|
||||
|
||||
/* Program CLINT Time Compare */
|
||||
#if __riscv_xlen == 64
|
||||
writeq_relaxed(next_event, &clint_time_cmp[target_hart]);
|
||||
#else
|
||||
u32 mask = -1UL;
|
||||
writel_relaxed(next_event & mask, &clint_time_cmp[target_hart]);
|
||||
writel_relaxed(next_event >> 32,
|
||||
(void *)(&clint_time_cmp[target_hart]) + 0x04);
|
||||
#endif
|
||||
/* Program CLINT Time Compare */
|
||||
clint_time_wr(next_event, &clint_time_cmp[target_hart]);
|
||||
}
|
||||
|
||||
int clint_warm_timer_init(void)
|
||||
@@ -124,24 +132,28 @@ int clint_warm_timer_init(void)
|
||||
if (clint_time_hart_count <= target_hart || !clint_time_base)
|
||||
return -1;
|
||||
|
||||
/* Clear CLINT Time Compare */
|
||||
#if __riscv_xlen == 64
|
||||
writeq_relaxed(-1ULL, &clint_time_cmp[target_hart]);
|
||||
#else
|
||||
writel_relaxed(-1UL, &clint_time_cmp[target_hart]);
|
||||
writel_relaxed(-1UL, (void *)(&clint_time_cmp[target_hart]) + 0x04);
|
||||
/* Clear CLINT Time Compare */
|
||||
clint_time_wr(-1ULL, &clint_time_cmp[target_hart]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_cold_timer_init(unsigned long base, u32 hart_count,
|
||||
bool has_64bit_mmio)
|
||||
{
|
||||
/* Figure-out CLINT Time register address */
|
||||
clint_time_hart_count = hart_count;
|
||||
clint_time_base = (void *)base;
|
||||
clint_time_val = (u64 *)(clint_time_base + 0xbff8);
|
||||
clint_time_cmp = (u64 *)(clint_time_base + 0x4000);
|
||||
|
||||
/* Override read/write accessors for 64bit MMIO */
|
||||
#if __riscv_xlen != 32
|
||||
if (has_64bit_mmio) {
|
||||
clint_time_rd = clint_time_rd64;
|
||||
clint_time_wr = clint_time_wr64;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clint_cold_timer_init(unsigned long base, u32 hart_count)
|
||||
{
|
||||
/* Figure-out CLINT Time register address */
|
||||
clint_time_hart_count = hart_count;
|
||||
clint_time_base = (void *)base;
|
||||
clint_time_val = (u64 *)(clint_time_base + 0xbff8);
|
||||
clint_time_cmp = (u64 *)(clint_time_base + 0x4000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -145,7 +145,7 @@ static int ariane_timer_init(bool cold_boot)
|
||||
|
||||
if (cold_boot) {
|
||||
ret = clint_cold_timer_init(ARIANE_CLINT_ADDR,
|
||||
ARIANE_HART_COUNT);
|
||||
ARIANE_HART_COUNT, TRUE);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@@ -88,7 +88,7 @@ static int k210_timer_init(bool cold_boot)
|
||||
|
||||
if (cold_boot) {
|
||||
rc = clint_cold_timer_init(K210_CLINT_BASE_ADDR,
|
||||
K210_HART_COUNT);
|
||||
K210_HART_COUNT, TRUE);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
@@ -113,7 +113,7 @@ static int sifive_u_timer_init(bool cold_boot)
|
||||
|
||||
if (cold_boot) {
|
||||
rc = clint_cold_timer_init(SIFIVE_U_CLINT_ADDR,
|
||||
SIFIVE_U_HART_COUNT);
|
||||
SIFIVE_U_HART_COUNT, TRUE);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
@@ -114,7 +114,8 @@ static int virt_timer_init(bool cold_boot)
|
||||
int rc;
|
||||
|
||||
if (cold_boot) {
|
||||
rc = clint_cold_timer_init(VIRT_CLINT_ADDR, VIRT_HART_COUNT);
|
||||
rc = clint_cold_timer_init(VIRT_CLINT_ADDR,
|
||||
VIRT_HART_COUNT, TRUE);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
@@ -176,7 +176,8 @@ static int fu540_timer_init(bool cold_boot)
|
||||
int rc;
|
||||
|
||||
if (cold_boot) {
|
||||
rc = clint_cold_timer_init(FU540_CLINT_ADDR, FU540_HART_COUNT);
|
||||
rc = clint_cold_timer_init(FU540_CLINT_ADDR,
|
||||
FU540_HART_COUNT, TRUE);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
@@ -143,7 +143,7 @@ static int platform_timer_init(bool cold_boot)
|
||||
/* Example if the generic CLINT driver is used */
|
||||
if (cold_boot) {
|
||||
ret = clint_cold_timer_init(PLATFORM_CLINT_ADDR,
|
||||
PLATFORM_HART_COUNT);
|
||||
PLATFORM_HART_COUNT, TRUE);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user