This implements the prescaler and source fields of the timer control register as described in the A10 user manual.
Signed-off-by: Beniamino Galvani <b.galv...@gmail.com> --- hw/timer/allwinner-a10-pit.c | 30 +++++++++++++++++++++++++++++- include/hw/timer/allwinner-a10-pit.h | 8 ++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/hw/timer/allwinner-a10-pit.c b/hw/timer/allwinner-a10-pit.c index f8c9236..a448689 100644 --- a/hw/timer/allwinner-a10-pit.c +++ b/hw/timer/allwinner-a10-pit.c @@ -74,6 +74,34 @@ 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; + uint32_t source_freq = AW_A10_PIT_OSC24M_FREQ; + + prescaler = 1 << extract32(s->control[index], 4, 3); + source = extract32(s->control[index], 2, 2); + + switch (source) { + case AW_A10_PIT_SOURCE_LS_OSC: + source_freq = AW_A10_PIT_LS_OSC_FREQ; + break; + case AW_A10_PIT_SOURCE_OSC24M: + source_freq = AW_A10_PIT_OSC24M_FREQ; + break; + case AW_A10_PIT_SOURCE_PLL6: + qemu_log_mask(LOG_UNIMP, "%s: unimplemented clock source %u", __func__, + source); + break; + case AW_A10_PIT_SOURCE_UNDEF: + qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid clock source %u", __func__, + source); + break; + } + + ptimer_set_freq(s->timer[index], source_freq / prescaler); +} + static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { @@ -96,6 +124,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]); } @@ -239,7 +268,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); } } diff --git a/include/hw/timer/allwinner-a10-pit.h b/include/hw/timer/allwinner-a10-pit.h index a48d3c7..37a2662 100644 --- a/include/hw/timer/allwinner-a10-pit.h +++ b/include/hw/timer/allwinner-a10-pit.h @@ -33,6 +33,14 @@ #define AW_A10_PIT_TIMER_BASE_END \ (AW_A10_PIT_TIMER_BASE * 6 + AW_A10_PIT_TIMER_COUNT) +#define AW_A10_PIT_SOURCE_LS_OSC 0 +#define AW_A10_PIT_SOURCE_OSC24M 1 +#define AW_A10_PIT_SOURCE_PLL6 2 +#define AW_A10_PIT_SOURCE_UNDEF 3 + +#define AW_A10_PIT_LS_OSC_FREQ 32768 +#define AW_A10_PIT_OSC24M_FREQ 24000000 + #define AW_A10_PIT_DEFAULT_CLOCK 0x4 typedef struct AwA10PITState AwA10PITState; -- 1.7.10.4