allwinner-a10-pit: implement prescaler and source selection
This implements the prescaler and source fields of the timer control register. The source for each timer can be selected among 4 clock inputs whose frequencies are set through model properties. Signed-off-by: Beniamino Galvani <b.galvani@gmail.com> Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com> Message-id: 1395771730-16882-6-git-send-email-b.galvani@gmail.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
a63f9f85e3
commit
286226a479
@ -43,6 +43,19 @@ static void cubieboard_init(QEMUMachineInitArgs *args)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
object_property_set_int(OBJECT(&s->a10->timer), 32768, "clk0-freq", &err);
|
||||
if (err != NULL) {
|
||||
error_report("Couldn't set clk0 frequency: %s", error_get_pretty(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
object_property_set_int(OBJECT(&s->a10->timer), 24000000, "clk1-freq",
|
||||
&err);
|
||||
if (err != NULL) {
|
||||
error_report("Couldn't set clk1 frequency: %s", error_get_pretty(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
object_property_set_bool(OBJECT(s->a10), true, "realized", &err);
|
||||
if (err != NULL) {
|
||||
error_report("Couldn't realize Allwinner A10: %s",
|
||||
|
@ -74,6 +74,22 @@ static uint64_t a10_pit_read(void *opaque, hwaddr offset, unsigned size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void a10_pit_set_freq(AwA10PITState *s, int index)
|
||||
{
|
||||
uint32_t prescaler, source, source_freq;
|
||||
|
||||
prescaler = 1 << extract32(s->control[index], 4, 3);
|
||||
source = extract32(s->control[index], 2, 2);
|
||||
source_freq = s->clk_freq[source];
|
||||
|
||||
if (source_freq) {
|
||||
ptimer_set_freq(s->timer[index], source_freq / prescaler);
|
||||
} else {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid clock source %u\n",
|
||||
__func__, source);
|
||||
}
|
||||
}
|
||||
|
||||
static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
|
||||
unsigned size)
|
||||
{
|
||||
@ -96,6 +112,7 @@ static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
|
||||
switch (offset & 0x0f) {
|
||||
case AW_A10_PIT_TIMER_CONTROL:
|
||||
s->control[index] = value;
|
||||
a10_pit_set_freq(s, index);
|
||||
if (s->control[index] & AW_A10_PIT_TIMER_RELOAD) {
|
||||
ptimer_set_count(s->timer[index], s->interval[index]);
|
||||
}
|
||||
@ -161,6 +178,14 @@ static const MemoryRegionOps a10_pit_ops = {
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static Property a10_pit_properties[] = {
|
||||
DEFINE_PROP_UINT32("clk0-freq", AwA10PITState, clk_freq[0], 0),
|
||||
DEFINE_PROP_UINT32("clk1-freq", AwA10PITState, clk_freq[1], 0),
|
||||
DEFINE_PROP_UINT32("clk2-freq", AwA10PITState, clk_freq[2], 0),
|
||||
DEFINE_PROP_UINT32("clk3-freq", AwA10PITState, clk_freq[3], 0),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_a10_pit = {
|
||||
.name = "a10.pit",
|
||||
.version_id = 1,
|
||||
@ -196,6 +221,7 @@ static void a10_pit_reset(DeviceState *dev)
|
||||
s->interval[i] = 0;
|
||||
s->count[i] = 0;
|
||||
ptimer_stop(s->timer[i]);
|
||||
a10_pit_set_freq(s, i);
|
||||
}
|
||||
s->watch_dog_mode = 0;
|
||||
s->watch_dog_control = 0;
|
||||
@ -241,7 +267,6 @@ static void a10_pit_init(Object *obj)
|
||||
tc->index = i;
|
||||
bh[i] = qemu_bh_new(a10_pit_timer_cb, tc);
|
||||
s->timer[i] = ptimer_init(bh[i]);
|
||||
ptimer_set_freq(s->timer[i], 240000);
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,6 +275,7 @@ static void a10_pit_class_init(ObjectClass *klass, void *data)
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->reset = a10_pit_reset;
|
||||
dc->props = a10_pit_properties;
|
||||
dc->desc = "allwinner a10 timer";
|
||||
dc->vmsd = &vmstate_a10_pit;
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ struct AwA10PITState {
|
||||
ptimer_state * timer[AW_A10_PIT_TIMER_NR];
|
||||
AwA10TimerContext timer_context[AW_A10_PIT_TIMER_NR];
|
||||
MemoryRegion iomem;
|
||||
uint32_t clk_freq[4];
|
||||
|
||||
uint32_t irq_enable;
|
||||
uint32_t irq_status;
|
||||
|
Loading…
Reference in New Issue
Block a user