|
@@ -109,37 +109,40 @@ static inline uint64_t calculate_time(struct AspeedTimer *t, uint32_t ticks)
|
|
|
|
|
|
static uint64_t calculate_next(struct AspeedTimer *t)
|
|
|
{
|
|
|
- uint64_t next = 0;
|
|
|
- uint32_t rate = calculate_rate(t);
|
|
|
+ uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
|
|
+ uint64_t next;
|
|
|
|
|
|
- while (!next) {
|
|
|
- /* We don't know the relationship between the values in the match
|
|
|
- * registers, so sort using MAX/MIN/zero. We sort in that order as the
|
|
|
- * timer counts down to zero. */
|
|
|
- uint64_t seq[] = {
|
|
|
- calculate_time(t, MAX(t->match[0], t->match[1])),
|
|
|
- calculate_time(t, MIN(t->match[0], t->match[1])),
|
|
|
- calculate_time(t, 0),
|
|
|
- };
|
|
|
- uint64_t reload_ns;
|
|
|
- uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
|
|
-
|
|
|
- if (now < seq[0]) {
|
|
|
- next = seq[0];
|
|
|
- } else if (now < seq[1]) {
|
|
|
- next = seq[1];
|
|
|
- } else if (now < seq[2]) {
|
|
|
- next = seq[2];
|
|
|
- } else if (t->reload) {
|
|
|
- reload_ns = muldiv64(t->reload, NANOSECONDS_PER_SECOND, rate);
|
|
|
- t->start = now - ((now - t->start) % reload_ns);
|
|
|
- } else {
|
|
|
- /* no reload value, return 0 */
|
|
|
- break;
|
|
|
- }
|
|
|
+ /*
|
|
|
+ * We don't know the relationship between the values in the match
|
|
|
+ * registers, so sort using MAX/MIN/zero. We sort in that order as
|
|
|
+ * the timer counts down to zero.
|
|
|
+ */
|
|
|
+
|
|
|
+ next = calculate_time(t, MAX(t->match[0], t->match[1]));
|
|
|
+ if (now < next) {
|
|
|
+ return next;
|
|
|
+ }
|
|
|
+
|
|
|
+ next = calculate_time(t, MIN(t->match[0], t->match[1]));
|
|
|
+ if (now < next) {
|
|
|
+ return next;
|
|
|
+ }
|
|
|
+
|
|
|
+ next = calculate_time(t, 0);
|
|
|
+ if (now < next) {
|
|
|
+ return next;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* We've missed all deadlines, fire interrupt and try again */
|
|
|
+ timer_del(&t->timer);
|
|
|
+
|
|
|
+ if (timer_overflow_interrupt(t)) {
|
|
|
+ t->level = !t->level;
|
|
|
+ qemu_set_irq(t->irq, t->level);
|
|
|
}
|
|
|
|
|
|
- return next;
|
|
|
+ t->start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
|
|
+ return calculate_time(t, MAX(MAX(t->match[0], t->match[1]), 0));
|
|
|
}
|
|
|
|
|
|
static void aspeed_timer_mod(AspeedTimer *t)
|