hw/timer/cmsdk-apb-dualtimer: Convert to use Clock input

Switch the CMSDK APB dualtimer device over to using its Clock input;
the pclk-frq property is now ignored.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Luc Michel <luc@lmichel.fr>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20210128114145.20536-20-peter.maydell@linaro.org
Message-id: 20210121190622.22000-20-peter.maydell@linaro.org
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
This commit is contained in:
Peter Maydell 2021-01-28 11:41:39 +00:00
parent 5e066562f5
commit 7208aafb6c

View file

@ -106,6 +106,22 @@ static void cmsdk_apb_dualtimer_update(CMSDKAPBDualTimer *s)
qemu_set_irq(s->timerintc, timintc); qemu_set_irq(s->timerintc, timintc);
} }
static int cmsdk_dualtimermod_divisor(CMSDKAPBDualTimerModule *m)
{
/* Return the divisor set by the current CONTROL.PRESCALE value */
switch (FIELD_EX32(m->control, CONTROL, PRESCALE)) {
case 0:
return 1;
case 1:
return 16;
case 2:
case 3: /* UNDEFINED, we treat like 2 (and complained when it was set) */
return 256;
default:
g_assert_not_reached();
}
}
static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m, static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
uint32_t newctrl) uint32_t newctrl)
{ {
@ -146,7 +162,7 @@ static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
default: default:
g_assert_not_reached(); g_assert_not_reached();
} }
ptimer_set_freq(m->timer, m->parent->pclk_frq / divisor); ptimer_set_period_from_clock(m->timer, m->parent->timclk, divisor);
} }
if (changed & R_CONTROL_MODE_MASK) { if (changed & R_CONTROL_MODE_MASK) {
@ -414,7 +430,8 @@ static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m)
* limit must both be set to 0xffff, so we wrap at 16 bits. * limit must both be set to 0xffff, so we wrap at 16 bits.
*/ */
ptimer_set_limit(m->timer, 0xffff, 1); ptimer_set_limit(m->timer, 0xffff, 1);
ptimer_set_freq(m->timer, m->parent->pclk_frq); ptimer_set_period_from_clock(m->timer, m->parent->timclk,
cmsdk_dualtimermod_divisor(m));
ptimer_transaction_commit(m->timer); ptimer_transaction_commit(m->timer);
} }
@ -432,6 +449,20 @@ static void cmsdk_apb_dualtimer_reset(DeviceState *dev)
s->timeritop = 0; s->timeritop = 0;
} }
static void cmsdk_apb_dualtimer_clk_update(void *opaque)
{
CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
int i;
for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
CMSDKAPBDualTimerModule *m = &s->timermod[i];
ptimer_transaction_begin(m->timer);
ptimer_set_period_from_clock(m->timer, m->parent->timclk,
cmsdk_dualtimermod_divisor(m));
ptimer_transaction_commit(m->timer);
}
}
static void cmsdk_apb_dualtimer_init(Object *obj) static void cmsdk_apb_dualtimer_init(Object *obj)
{ {
SysBusDevice *sbd = SYS_BUS_DEVICE(obj); SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
@ -446,7 +477,8 @@ static void cmsdk_apb_dualtimer_init(Object *obj)
for (i = 0; i < ARRAY_SIZE(s->timermod); i++) { for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
sysbus_init_irq(sbd, &s->timermod[i].timerint); sysbus_init_irq(sbd, &s->timermod[i].timerint);
} }
s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK", NULL, NULL); s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK",
cmsdk_apb_dualtimer_clk_update, s);
} }
static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp) static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
@ -454,8 +486,8 @@ static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev); CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
int i; int i;
if (s->pclk_frq == 0) { if (!clock_has_source(s->timclk)) {
error_setg(errp, "CMSDK APB timer: pclk-frq property must be set"); error_setg(errp, "CMSDK APB dualtimer: TIMCLK clock must be connected");
return; return;
} }