[rtems commit] bsp/riscv: Fix clock driver

Sebastian Huber sebh at rtems.org
Wed Aug 1 09:18:25 UTC 2018


Module:    rtems
Branch:    master
Commit:    48cbd63c84d26ecb51b6d06c04ef096100f9004d
Changeset: http://git.rtems.org/rtems/commit/?id=48cbd63c84d26ecb51b6d06c04ef096100f9004d

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Tue Jul 31 07:19:33 2018 +0200

bsp/riscv: Fix clock driver

Do not assume that mtime is zero at boot time.

Update #3433.

---

 bsps/riscv/riscv/clock/clockdrv.c | 66 +++++++++++++++++++++++++++++----------
 1 file changed, 49 insertions(+), 17 deletions(-)

diff --git a/bsps/riscv/riscv/clock/clockdrv.c b/bsps/riscv/riscv/clock/clockdrv.c
index 4278a10..30a894f 100644
--- a/bsps/riscv/riscv/clock/clockdrv.c
+++ b/bsps/riscv/riscv/clock/clockdrv.c
@@ -50,29 +50,55 @@ void Clock_isr(void *arg);
 typedef struct {
   struct timecounter base;
   volatile RISCV_CLINT_regs *clint;
+  uint32_t interval;
 } riscv_timecounter;
 
 static riscv_timecounter riscv_clock_tc;
 
-static uint32_t riscv_clock_interval;
+static void riscv_clock_write_mtimecmp(
+  volatile RISCV_CLINT_timer_reg *mtimecmp,
+  uint64_t value
+)
+{
+#if __riscv_xlen == 32
+  mtimecmp->val_32[0] = 0xffffffff;
+  mtimecmp->val_32[1] = (uint32_t) (value >> 32);
+  mtimecmp->val_32[0] = (uint32_t) value;
+#elif __riscv_xlen == 64
+  mtimecmp->val_64 = value;
+#endif
+}
+
+static uint64_t riscv_clock_read_mtime(volatile RISCV_CLINT_timer_reg *mtime)
+{
+#if __riscv_xlen == 32
+  uint32_t low;
+  uint32_t high_0;
+  uint32_t high_1;
+
+  do {
+    high_0 = mtime->val_32[1];
+    low = mtime->val_32[0];
+    high_1 = mtime->val_32[1];
+  } while (high_0 != high_1);
+
+  return (((uint64_t) high_0) << 32) | low;
+#elif __riscv_xlen == 64
+  return mtime->val_64;
+#endif
+}
 
 static void riscv_clock_at_tick(riscv_timecounter *tc)
 {
   volatile RISCV_CLINT_regs *clint;
-  uint64_t cmp;
+  uint64_t value;
 
   clint = tc->clint;
 
-  cmp = clint->mtimecmp[0].val_64;
-  cmp += riscv_clock_interval;
+  value = clint->mtimecmp[0].val_64;
+  value += tc->interval;
 
-#if __riscv_xlen == 32
-  clint->mtimecmp[0].val_32[0] = 0xffffffff;
-  clint->mtimecmp[0].val_32[1] = (uint32_t) (cmp >> 32);
-  clint->mtimecmp[0].val_32[0] = (uint32_t) cmp;
-#elif __riscv_xlen == 64
-  clint->mtimecmp[0].val_64 = cmp;
-#endif
+  riscv_clock_write_mtimecmp(&clint->mtimecmp[0], value);
 }
 
 static void riscv_clock_handler_install(void)
@@ -120,19 +146,25 @@ static void riscv_clock_initialize(void)
 {
   const char *fdt;
   riscv_timecounter *tc;
+  volatile RISCV_CLINT_regs *clint;
   uint32_t tb_freq;
   uint64_t us_per_tick;
+  uint32_t interval;
 
   fdt = bsp_fdt_get();
-
-  tc = &riscv_clock_tc;
-  tc->clint = riscv_clint;
-
   tb_freq = riscv_clock_get_timebase_frequency(fdt);
   us_per_tick = rtems_configuration_get_microseconds_per_tick();
-  riscv_clock_interval = (uint32_t) ((tb_freq * us_per_tick) / 1000000);
+  interval = (uint32_t) ((tb_freq * us_per_tick) / 1000000);
+  clint = riscv_clint;
+  tc = &riscv_clock_tc;
 
-  riscv_clock_at_tick(tc);
+  tc->clint = clint;
+  tc->interval = interval;
+
+  riscv_clock_write_mtimecmp(
+    &clint->mtimecmp[0],
+    riscv_clock_read_mtime(&clint->mtime) + interval
+  );
 
   /* Enable mtimer interrupts */
   set_csr(mie, MIP_MTIP);



More information about the vc mailing list