#include "sun4m.h"
#include "qemu-timer.h"
+#include "ptimer.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 {
+ MemoryRegion iomem;
SLAVIO_TIMERState *s;
unsigned int timer_index; /* 0 for system, 1 ... MAX_CPUS for CPU timers */
} TimerContext;
}
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);
+ 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;
}
}
-static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
+static uint64_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr,
+ unsigned size)
{
TimerContext *tc = opaque;
SLAVIO_TIMERState *s = tc->s;
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;
}
static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr,
- uint32_t val)
+ uint64_t val, unsigned size)
{
TimerContext *tc = opaque;
SLAVIO_TIMERState *s = tc->s;
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 CPUReadMemoryFunc * const slavio_timer_mem_read[3] = {
- NULL,
- NULL,
- slavio_timer_mem_readl,
-};
-
-static CPUWriteMemoryFunc * const slavio_timer_mem_write[3] = {
- NULL,
- NULL,
- slavio_timer_mem_writel,
+static const MemoryRegionOps slavio_timer_mem_ops = {
+ .read = slavio_timer_mem_readl,
+ .write = slavio_timer_mem_writel,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
};
static const VMStateDescription vmstate_timer = {
static int slavio_timer_init1(SysBusDevice *dev)
{
- int io;
SLAVIO_TIMERState *s = FROM_SYSBUS(SLAVIO_TIMERState, dev);
QEMUBH *bh;
unsigned int i;
TimerContext *tc;
for (i = 0; i <= MAX_CPUS; i++) {
- tc = qemu_mallocz(sizeof(TimerContext));
+ uint64_t size;
+ char timer_name[20];
+
+ tc = g_malloc0(sizeof(TimerContext));
tc->s = s;
tc->timer_index = i;
s->cputimer[i].timer = ptimer_init(bh);
ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD);
- io = cpu_register_io_memory(slavio_timer_mem_read,
- slavio_timer_mem_write, tc);
- if (i == 0) {
- sysbus_init_mmio(dev, SYS_TIMER_SIZE, io);
- } else {
- sysbus_init_mmio(dev, CPU_TIMER_SIZE, io);
- }
+ size = i == 0 ? SYS_TIMER_SIZE : CPU_TIMER_SIZE;
+ snprintf(timer_name, sizeof(timer_name), "timer-%i", i);
+ memory_region_init_io(&tc->iomem, &slavio_timer_mem_ops, tc,
+ timer_name, size);
+ sysbus_init_mmio(dev, &tc->iomem);
sysbus_init_irq(dev, &s->cputimer[i].irq);
}
return 0;
}
-static SysBusDeviceInfo slavio_timer_info = {
- .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(),
- }
+static Property slavio_timer_properties[] = {
+ DEFINE_PROP_UINT32("num_cpus", SLAVIO_TIMERState, num_cpus, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void slavio_timer_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = slavio_timer_init1;
+ dc->reset = slavio_timer_reset;
+ dc->vmsd = &vmstate_slavio_timer;
+ dc->props = slavio_timer_properties;
+}
+
+static TypeInfo slavio_timer_info = {
+ .name = "slavio_timer",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SLAVIO_TIMERState),
+ .class_init = slavio_timer_class_init,
};
static void slavio_timer_register_devices(void)
{
- sysbus_register_withprop(&slavio_timer_info);
+ type_register_static(&slavio_timer_info);
}
device_init(slavio_timer_register_devices)