Skip to content

Commit

Permalink
allwinner-a10-pit: implement prescaler and source selection
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
bengal authored and pm215 committed Apr 17, 2014
1 parent a63f9f8 commit 286226a
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 1 deletion.
13 changes: 13 additions & 0 deletions hw/arm/cubieboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
28 changes: 27 additions & 1 deletion hw/timer/allwinner-a10-pit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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]);
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions include/hw/timer/allwinner-a10-pit.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 286226a

Please sign in to comment.