#include "sun4m.h"
#include "qemu-timer.h"
#include "sysbus.h"
-
-//#define DEBUG_TIMER
-
-#ifdef DEBUG_TIMER
-#define DPRINTF(fmt, ...) \
- do { printf("TIMER: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while (0)
-#endif
+#include "trace.h"
/*
* Registers of hardware timer in sun4m.
qemu_irq irq;
ptimer_state *timer;
uint32_t count, counthigh, reached;
- uint64_t limit;
- // processor only
+ /* processor only */
uint32_t running;
+ uint64_t limit;
} CPUTimerState;
typedef struct SLAVIO_TIMERState {
SysBusDevice busdev;
uint32_t num_cpus;
- CPUTimerState cputimer[MAX_CPUS + 1];
uint32_t cputimer_mode;
+ CPUTimerState cputimer[MAX_CPUS + 1];
} SLAVIO_TIMERState;
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)
{
}
count = limit - PERIODS_TO_LIMIT(ptimer_get_count(t->timer));
- DPRINTF("get_out: limit %" PRIx64 " count %x%08x\n", t->limit, t->counthigh,
- t->count);
+ trace_slavio_timer_get_out(t->limit, t->counthigh, t->count);
t->count = count & TIMER_COUNT_MASK32;
t->counthigh = count >> 32;
}
CPUTimerState *t = &s->cputimer[tc->timer_index];
slavio_timer_get_out(t);
- DPRINTF("callback: count %x%08x\n", t->counthigh, t->count);
- t->reached = TIMER_REACHED;
- if (!slavio_timer_is_user(tc)) {
+ trace_slavio_timer_irq(t->counthigh, t->count);
+ /* 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);
}
}
ret = s->cputimer_mode;
break;
default:
- DPRINTF("invalid read address " TARGET_FMT_plx "\n", addr);
+ trace_slavio_timer_mem_readl_invalid(addr);
ret = 0;
break;
}
- DPRINTF("read " TARGET_FMT_plx " = %08x\n", addr, ret);
-
+ trace_slavio_timer_mem_readl(addr, ret);
return ret;
}
unsigned int timer_index = tc->timer_index;
CPUTimerState *t = &s->cputimer[timer_index];
- DPRINTF("write " TARGET_FMT_plx " %08x\n", addr, val);
+ trace_slavio_timer_mem_writel(addr, val);
saddr = addr >> 2;
switch (saddr) {
case TIMER_LIMIT:
t->counthigh = val & (TIMER_MAX_COUNT64 >> 32);
t->reached = 0;
count = ((uint64_t)t->counthigh << 32) | t->count;
- DPRINTF("processor %d user timer set to %016" PRIx64 "\n",
- timer_index, count);
+ trace_slavio_timer_mem_writel_limit(timer_index, count);
ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count));
} else {
// set limit, reset counter
t->count = val & TIMER_MAX_COUNT64;
t->reached = 0;
count = ((uint64_t)t->counthigh) << 32 | t->count;
- DPRINTF("processor %d user timer set to %016" PRIx64 "\n",
- timer_index, count);
+ trace_slavio_timer_mem_writel_limit(timer_index, count);
ptimer_set_count(t->timer, LIMIT_TO_PERIODS(t->limit - count));
- } else
- DPRINTF("not user timer\n");
+ } else {
+ trace_slavio_timer_mem_writel_counter_invalid();
+ }
break;
case TIMER_COUNTER_NORST:
// set limit without resetting counter
if (slavio_timer_is_user(tc)) {
// start/stop user counter
if ((val & 1) && !t->running) {
- DPRINTF("processor %d user timer started\n",
- timer_index);
+ trace_slavio_timer_mem_writel_status_start(timer_index);
ptimer_run(t->timer, 0);
t->running = 1;
} else if (!(val & 1) && t->running) {
- DPRINTF("processor %d user timer stopped\n",
- timer_index);
+ trace_slavio_timer_mem_writel_status_stop(timer_index);
ptimer_stop(t->timer);
t->running = 0;
}
// set this processors user timer bit in config
// register
s->cputimer_mode |= processor;
- DPRINTF("processor %d changed from counter to user "
- "timer\n", timer_index);
+ trace_slavio_timer_mem_writel_mode_user(timer_index);
} else { // user timer -> counter
// stop the user timer if it is running
if (curr_timer->running) {
// clear this processors user timer bit in config
// register
s->cputimer_mode &= ~processor;
- DPRINTF("processor %d changed from user timer to "
- "counter\n", timer_index);
+ trace_slavio_timer_mem_writel_mode_counter(timer_index);
}
}
}
} else {
- DPRINTF("not system timer\n");
+ trace_slavio_timer_mem_writel_mode_invalid();
}
break;
default:
- DPRINTF("invalid write address " TARGET_FMT_plx "\n", addr);
+ trace_slavio_timer_mem_writel_invalid(addr);
break;
}
}
}
};
-static void slavio_timer_reset(void *opaque)
+static void slavio_timer_reset(DeviceState *d)
{
- SLAVIO_TIMERState *s = opaque;
+ SLAVIO_TIMERState *s = container_of(d, SLAVIO_TIMERState, busdev.qdev);
unsigned int i;
CPUTimerState *curr_timer;
curr_timer->limit = 0;
curr_timer->count = 0;
curr_timer->reached = 0;
- if (i < s->num_cpus) {
+ if (i <= s->num_cpus) {
ptimer_set_limit(curr_timer->timer,
LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
ptimer_run(curr_timer->timer, 0);
+ curr_timer->running = 1;
}
- curr_timer->running = 1;
}
s->cputimer_mode = 0;
}
TimerContext *tc;
for (i = 0; i <= MAX_CPUS; i++) {
- tc = qemu_mallocz(sizeof(TimerContext));
+ tc = g_malloc0(sizeof(TimerContext));
tc->s = s;
tc->timer_index = i;
ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD);
io = cpu_register_io_memory(slavio_timer_mem_read,
- slavio_timer_mem_write, tc);
+ slavio_timer_mem_write, tc,
+ DEVICE_NATIVE_ENDIAN);
if (i == 0) {
sysbus_init_mmio(dev, SYS_TIMER_SIZE, io);
} else {
sysbus_init_irq(dev, &s->cputimer[i].irq);
}
- vmstate_register(-1, &vmstate_slavio_timer, s);
- qemu_register_reset(slavio_timer_reset, s);
- slavio_timer_reset(s);
return 0;
}
.init = slavio_timer_init1,
.qdev.name = "slavio_timer",
.qdev.size = sizeof(SLAVIO_TIMERState),
+ .qdev.vmsd = &vmstate_slavio_timer,
+ .qdev.reset = slavio_timer_reset,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("num_cpus", SLAVIO_TIMERState, num_cpus, 0),
DEFINE_PROP_END_OF_LIST(),