mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 07:43:54 -06:00
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:
parent
5e066562f5
commit
7208aafb6c
1 changed files with 37 additions and 5 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue