aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sbi_utils/sys/clint.h3
-rw-r--r--lib/utils/sys/clint.c88
-rw-r--r--platform/ariane-fpga/platform.c2
-rw-r--r--platform/kendryte/k210/platform.c2
-rw-r--r--platform/qemu/sifive_u/platform.c2
-rw-r--r--platform/qemu/virt/platform.c3
-rw-r--r--platform/sifive/fu540/platform.c3
-rw-r--r--platform/template/platform.c2
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;
}