summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorBlue Swirl <blauwirbel@gmail.com>2010-04-03 06:17:35 +0000
committerBlue Swirl <blauwirbel@gmail.com>2010-04-03 06:17:35 +0000
commit68fb89a2c07b6ad1e69a9a45f664d533f2662ec6 (patch)
treefda0fe64363a15cf360a440b52d46605b0bf4e26 /hw
parent25da2f343cba4f854f19b2b52817f2e5c851ee17 (diff)
sparc32: improve timer implementation
Timer with zero period (free-run) will never match. Timer counting starts with tick value of 0x200, not from 0, so the period must calculated from one tick less than the limit. Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/slavio_timer.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c
index ef36fe4c99..d7875536b6 100644
--- a/hw/slavio_timer.c
+++ b/hw/slavio_timer.c
@@ -88,8 +88,8 @@ typedef struct TimerContext {
#define TIMER_MAX_COUNT32 0x7ffffe00ULL
#define TIMER_REACHED 0x80000000
#define TIMER_PERIOD 500ULL // 500ns
-#define LIMIT_TO_PERIODS(l) ((l) >> 9)
-#define PERIODS_TO_LIMIT(l) ((l) << 9)
+#define LIMIT_TO_PERIODS(l) (((l) >> 9) - 1)
+#define PERIODS_TO_LIMIT(l) (((l) + 1) << 9)
static int slavio_timer_is_user(TimerContext *tc)
{
@@ -127,7 +127,10 @@ static void slavio_timer_irq(void *opaque)
slavio_timer_get_out(t);
DPRINTF("callback: count %x%08x\n", t->counthigh, t->count);
- t->reached = TIMER_REACHED;
+ /* if limit is 0 (free-run), there will be no match */
+ if (t->limit != 0) {
+ t->reached = TIMER_REACHED;
+ }
/* there is no interrupt if user timer or free-run */
if (!slavio_timer_is_user(tc) && t->limit != 0) {
qemu_irq_raise(t->irq);