summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnup Patel <anup.patel@wdc.com>2019-12-30 09:01:59 +0300
committerAnup Patel <anup@brainfault.org>2020-01-02 06:44:36 +0300
commit46a90d90e7dca6eeb66700b6970171119c51fd66 (patch)
tree1e4c6902a0e8b68277a46e6610a33b898f9391bb
parentfc6bd90457b5553fbb0a17f0b58adb2da28e8db0 (diff)
downloadopensbi-46a90d90e7dca6eeb66700b6970171119c51fd66.tar.xz
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>
-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;
}