diff options
-rw-r--r-- | include/sbi_utils/sys/clint.h | 3 | ||||
-rw-r--r-- | lib/utils/sys/clint.c | 88 | ||||
-rw-r--r-- | platform/ariane-fpga/platform.c | 2 | ||||
-rw-r--r-- | platform/kendryte/k210/platform.c | 2 | ||||
-rw-r--r-- | platform/qemu/sifive_u/platform.c | 2 | ||||
-rw-r--r-- | platform/qemu/virt/platform.c | 3 | ||||
-rw-r--r-- | platform/sifive/fu540/platform.c | 3 | ||||
-rw-r--r-- | platform/template/platform.c | 2 |
8 files changed, 60 insertions, 45 deletions
diff --git a/include/sbi_utils/sys/clint.h b/include/sbi_utils/sys/clint.h index 78e1209..5749d46 100644 --- a/include/sbi_utils/sys/clint.h +++ b/include/sbi_utils/sys/clint.h @@ -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 diff --git a/lib/utils/sys/clint.c b/lib/utils/sys/clint.c index 802d419..ec85507 100644 --- a/lib/utils/sys/clint.c +++ b/lib/utils/sys/clint.c @@ -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); -#endif + /* 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) +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); + 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; } diff --git a/platform/ariane-fpga/platform.c b/platform/ariane-fpga/platform.c index daeb9cd..5ebbff8 100644 --- a/platform/ariane-fpga/platform.c +++ b/platform/ariane-fpga/platform.c @@ -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; } diff --git a/platform/kendryte/k210/platform.c b/platform/kendryte/k210/platform.c index 39771e3..8ad1bf8 100644 --- a/platform/kendryte/k210/platform.c +++ b/platform/kendryte/k210/platform.c @@ -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; } diff --git a/platform/qemu/sifive_u/platform.c b/platform/qemu/sifive_u/platform.c index 40d6584..b021ca2 100644 --- a/platform/qemu/sifive_u/platform.c +++ b/platform/qemu/sifive_u/platform.c @@ -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; } diff --git a/platform/qemu/virt/platform.c b/platform/qemu/virt/platform.c index 6ef6a19..883555c 100644 --- a/platform/qemu/virt/platform.c +++ b/platform/qemu/virt/platform.c @@ -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; } diff --git a/platform/sifive/fu540/platform.c b/platform/sifive/fu540/platform.c index 81e8e8d..c8ead9d 100644 --- a/platform/sifive/fu540/platform.c +++ b/platform/sifive/fu540/platform.c @@ -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; } diff --git a/platform/template/platform.c b/platform/template/platform.c index d36af48..20ae579 100644 --- a/platform/template/platform.c +++ b/platform/template/platform.c @@ -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; } |