summaryrefslogtreecommitdiff
path: root/lib/utils/sys
diff options
context:
space:
mode:
authorAtish Patra <atish.patra@wdc.com>2019-08-30 01:19:11 +0300
committerAnup Patel <anup@brainfault.org>2019-08-31 10:43:12 +0300
commit2e5cc9051b5daf0b164f0454e28e08c2b952089a (patch)
treef4f019563b5e6b6e79f30fd22eddcb1ac6571e4a /lib/utils/sys
parentffa6c5f457527a2e71f2e7bd643ed0dce383506d (diff)
downloadopensbi-2e5cc9051b5daf0b164f0454e28e08c2b952089a.tar.xz
lib: Fix timer for 32 bit
To read 64bit time in 32 bit we have to read lower & upper half separately and 'or' them together. However, upper half time may have changed by the time we read lower half. Thus, the resultant 64 bit time may not be accurate. Consider lower half time value only if upper half time value has not changed. Signed-off-by: Atish Patra <atish.patra@wdc.com> Reviewed-by: Anup Patel <anup.patel@wdc.com>
Diffstat (limited to 'lib/utils/sys')
-rw-r--r--lib/utils/sys/clint.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/lib/utils/sys/clint.c b/lib/utils/sys/clint.c
index d58e4e6..802d419 100644
--- a/lib/utils/sys/clint.c
+++ b/lib/utils/sys/clint.c
@@ -62,16 +62,24 @@ 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()
+{
+ return readl_relaxed((u32 *)clint_time_val + 1);
+}
+
u64 clint_timer_value(void)
{
#if __riscv_xlen == 64
return readq_relaxed(clint_time_val);
#else
- u64 tmp;
- tmp = readl_relaxed((void *)clint_time_val + 0x04);
- tmp <<= 32;
- tmp |= readl_relaxed(clint_time_val);
- return tmp;
+ u32 lo, hi;
+
+ do {
+ hi = clint_time_read_hi();
+ lo = readl_relaxed(clint_time_val);
+ } while (hi != clint_time_read_hi());
+
+ return ((u64)hi << 32) | (u64)lo;
#endif
}