Factor out the code that calculates the runtime value of the timer. Updates tb->count to the calculated value. Prepares support for pausing the timer where the timer disable event should sync the counter to its current value.
Signed-off-by: Peter Crosthwaite <crosthwaite.pe...@gmail.com> --- hw/timer/arm_mptimer.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c index 8b93b3c..04dfb63 100644 --- a/hw/timer/arm_mptimer.c +++ b/hw/timer/arm_mptimer.c @@ -72,25 +72,32 @@ static void timerblock_tick(void *opaque) timerblock_update_irq(tb); } +static void timerblock_sync(TimerBlock *tb) +{ + int64_t val; + + if (((tb->control & 1) == 0) || (tb->count == 0)) { + return; + } + /* Slow and ugly, but hopefully won't happen too often. */ + val = tb->tick - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + val /= timerblock_scale(tb); + if (val < 0) { + val = 0; + } + tb->count = val; +} + static uint64_t timerblock_read(void *opaque, hwaddr addr, unsigned size) { TimerBlock *tb = (TimerBlock *)opaque; - int64_t val; switch (addr) { case 0: /* Load */ return tb->load; case 4: /* Counter. */ - if (((tb->control & 1) == 0) || (tb->count == 0)) { - return 0; - } - /* Slow and ugly, but hopefully won't happen too often. */ - val = tb->tick - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); - val /= timerblock_scale(tb); - if (val < 0) { - val = 0; - } - return val; + timerblock_sync(tb); + return tb->count; case 8: /* Control. */ return tb->control; case 12: /* Interrupt status. */ -- 1.9.1