2 * ARM CMSDK APB dual-timer emulation
4 * Copyright (c) 2018 Linaro Limited
5 * Written by Peter Maydell
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 or
9 * (at your option) any later version.
13 * This is a model of the "APB dual-input timer" which is part of the Cortex-M
14 * System Design Kit (CMSDK) and documented in the Cortex-M System
15 * Design Kit Technical Reference Manual (ARM DDI0479C):
16 * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
19 #include "qemu/osdep.h"
22 #include "qapi/error.h"
23 #include "qemu/module.h"
24 #include "hw/sysbus.h"
26 #include "hw/qdev-properties.h"
27 #include "hw/registerfields.h"
28 #include "hw/qdev-clock.h"
29 #include "hw/timer/cmsdk-apb-dualtimer.h"
30 #include "migration/vmstate.h"
32 REG32(TIMER1LOAD
, 0x0)
33 REG32(TIMER1VALUE
, 0x4)
34 REG32(TIMER1CONTROL
, 0x8)
35 FIELD(CONTROL
, ONESHOT
, 0, 1)
36 FIELD(CONTROL
, SIZE
, 1, 1)
37 FIELD(CONTROL
, PRESCALE
, 2, 2)
38 FIELD(CONTROL
, INTEN
, 5, 1)
39 FIELD(CONTROL
, MODE
, 6, 1)
40 FIELD(CONTROL
, ENABLE
, 7, 1)
41 #define R_CONTROL_VALID_MASK (R_CONTROL_ONESHOT_MASK | R_CONTROL_SIZE_MASK | \
42 R_CONTROL_PRESCALE_MASK | R_CONTROL_INTEN_MASK | \
43 R_CONTROL_MODE_MASK | R_CONTROL_ENABLE_MASK)
44 REG32(TIMER1INTCLR
, 0xc)
45 REG32(TIMER1RIS
, 0x10)
46 REG32(TIMER1MIS
, 0x14)
47 REG32(TIMER1BGLOAD
, 0x18)
48 REG32(TIMER2LOAD
, 0x20)
49 REG32(TIMER2VALUE
, 0x24)
50 REG32(TIMER2CONTROL
, 0x28)
51 REG32(TIMER2INTCLR
, 0x2c)
52 REG32(TIMER2RIS
, 0x30)
53 REG32(TIMER2MIS
, 0x34)
54 REG32(TIMER2BGLOAD
, 0x38)
55 REG32(TIMERITCR
, 0xf00)
56 FIELD(TIMERITCR
, ENABLE
, 0, 1)
57 #define R_TIMERITCR_VALID_MASK R_TIMERITCR_ENABLE_MASK
58 REG32(TIMERITOP
, 0xf04)
59 FIELD(TIMERITOP
, TIMINT1
, 0, 1)
60 FIELD(TIMERITOP
, TIMINT2
, 1, 1)
61 #define R_TIMERITOP_VALID_MASK (R_TIMERITOP_TIMINT1_MASK | \
62 R_TIMERITOP_TIMINT2_MASK)
77 static const int timer_id
[] = {
78 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
79 0x23, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
80 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
83 static bool cmsdk_dualtimermod_intstatus(CMSDKAPBDualTimerModule
*m
)
85 /* Return masked interrupt status for the timer module */
86 return m
->intstatus
&& (m
->control
& R_CONTROL_INTEN_MASK
);
89 static void cmsdk_apb_dualtimer_update(CMSDKAPBDualTimer
*s
)
91 bool timint1
, timint2
, timintc
;
94 /* Integration test mode: outputs driven directly from TIMERITOP bits */
95 timint1
= s
->timeritop
& R_TIMERITOP_TIMINT1_MASK
;
96 timint2
= s
->timeritop
& R_TIMERITOP_TIMINT2_MASK
;
98 timint1
= cmsdk_dualtimermod_intstatus(&s
->timermod
[0]);
99 timint2
= cmsdk_dualtimermod_intstatus(&s
->timermod
[1]);
102 timintc
= timint1
|| timint2
;
104 qemu_set_irq(s
->timermod
[0].timerint
, timint1
);
105 qemu_set_irq(s
->timermod
[1].timerint
, timint2
);
106 qemu_set_irq(s
->timerintc
, timintc
);
109 static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule
*m
,
112 /* Handle a write to the CONTROL register */
115 ptimer_transaction_begin(m
->timer
);
117 newctrl
&= R_CONTROL_VALID_MASK
;
119 changed
= m
->control
^ newctrl
;
121 if (changed
& ~newctrl
& R_CONTROL_ENABLE_MASK
) {
122 /* ENABLE cleared, stop timer before any further changes */
123 ptimer_stop(m
->timer
);
126 if (changed
& R_CONTROL_PRESCALE_MASK
) {
129 switch (FIELD_EX32(newctrl
, CONTROL
, PRESCALE
)) {
140 /* UNDEFINED; complain, and arbitrarily treat like 2 */
141 qemu_log_mask(LOG_GUEST_ERROR
,
142 "CMSDK APB dual-timer: CONTROL.PRESCALE==0b11"
143 " is undefined behaviour\n");
147 g_assert_not_reached();
149 ptimer_set_freq(m
->timer
, m
->parent
->pclk_frq
/ divisor
);
152 if (changed
& R_CONTROL_MODE_MASK
) {
154 if (newctrl
& R_CONTROL_MODE_MASK
) {
155 /* Periodic: the limit is the LOAD register value */
158 /* Free-running: counter wraps around */
159 load
= ptimer_get_limit(m
->timer
);
160 if (!(m
->control
& R_CONTROL_SIZE_MASK
)) {
161 load
= deposit32(m
->load
, 0, 16, load
);
166 if (!(m
->control
& R_CONTROL_SIZE_MASK
)) {
169 ptimer_set_limit(m
->timer
, load
, 0);
172 if (changed
& R_CONTROL_SIZE_MASK
) {
173 /* Timer switched between 16 and 32 bit count */
174 uint32_t value
, load
;
176 value
= ptimer_get_count(m
->timer
);
177 load
= ptimer_get_limit(m
->timer
);
178 if (newctrl
& R_CONTROL_SIZE_MASK
) {
179 /* 16 -> 32, top half of VALUE is in struct field */
180 value
= deposit32(m
->value
, 0, 16, value
);
182 /* 32 -> 16: save top half to struct field and truncate */
187 if (newctrl
& R_CONTROL_MODE_MASK
) {
188 /* Periodic, timer limit has LOAD value */
189 if (newctrl
& R_CONTROL_SIZE_MASK
) {
190 load
= deposit32(m
->load
, 0, 16, load
);
196 /* Free-running, timer limit is set to give wraparound */
197 if (newctrl
& R_CONTROL_SIZE_MASK
) {
203 ptimer_set_count(m
->timer
, value
);
204 ptimer_set_limit(m
->timer
, load
, 0);
207 if (newctrl
& R_CONTROL_ENABLE_MASK
) {
209 * ENABLE is set; start the timer after all other changes.
210 * We start it even if the ENABLE bit didn't actually change,
211 * in case the timer was an expired one-shot timer that has
212 * now been changed into a free-running or periodic timer.
214 ptimer_run(m
->timer
, !!(newctrl
& R_CONTROL_ONESHOT_MASK
));
217 m
->control
= newctrl
;
219 ptimer_transaction_commit(m
->timer
);
222 static uint64_t cmsdk_apb_dualtimer_read(void *opaque
, hwaddr offset
,
225 CMSDKAPBDualTimer
*s
= CMSDK_APB_DUALTIMER(opaque
);
228 if (offset
>= A_TIMERITCR
) {
233 case A_PID4
... A_CID3
:
234 r
= timer_id
[(offset
- A_PID4
) / 4];
238 qemu_log_mask(LOG_GUEST_ERROR
,
239 "CMSDK APB dual-timer read: bad offset %x\n",
245 int timer
= offset
>> 5;
246 CMSDKAPBDualTimerModule
*m
;
248 if (timer
>= ARRAY_SIZE(s
->timermod
)) {
252 m
= &s
->timermod
[timer
];
254 switch (offset
& 0x1F) {
257 if (m
->control
& R_CONTROL_MODE_MASK
) {
259 * Periodic: the ptimer limit is the LOAD register value, (or
260 * just the low 16 bits of it if the timer is in 16-bit mode)
262 r
= ptimer_get_limit(m
->timer
);
263 if (!(m
->control
& R_CONTROL_SIZE_MASK
)) {
264 r
= deposit32(m
->load
, 0, 16, r
);
267 /* Free-running: LOAD register value is just in m->load */
272 r
= ptimer_get_count(m
->timer
);
273 if (!(m
->control
& R_CONTROL_SIZE_MASK
)) {
274 r
= deposit32(m
->value
, 0, 16, r
);
277 case A_TIMER1CONTROL
:
284 r
= cmsdk_dualtimermod_intstatus(m
);
291 trace_cmsdk_apb_dualtimer_read(offset
, r
, size
);
295 static void cmsdk_apb_dualtimer_write(void *opaque
, hwaddr offset
,
296 uint64_t value
, unsigned size
)
298 CMSDKAPBDualTimer
*s
= CMSDK_APB_DUALTIMER(opaque
);
300 trace_cmsdk_apb_dualtimer_write(offset
, value
, size
);
302 if (offset
>= A_TIMERITCR
) {
305 s
->timeritcr
= value
& R_TIMERITCR_VALID_MASK
;
306 cmsdk_apb_dualtimer_update(s
);
309 s
->timeritop
= value
& R_TIMERITOP_VALID_MASK
;
310 cmsdk_apb_dualtimer_update(s
);
314 qemu_log_mask(LOG_GUEST_ERROR
,
315 "CMSDK APB dual-timer write: bad offset %x\n",
320 int timer
= offset
>> 5;
321 CMSDKAPBDualTimerModule
*m
;
323 if (timer
>= ARRAY_SIZE(s
->timermod
)) {
327 m
= &s
->timermod
[timer
];
329 switch (offset
& 0x1F) {
331 /* Set the limit, and immediately reload the count from it */
334 if (!(m
->control
& R_CONTROL_SIZE_MASK
)) {
337 ptimer_transaction_begin(m
->timer
);
338 if (!(m
->control
& R_CONTROL_MODE_MASK
)) {
340 * In free-running mode this won't set the limit but will
341 * still change the current count value.
343 ptimer_set_count(m
->timer
, value
);
346 ptimer_stop(m
->timer
);
348 ptimer_set_limit(m
->timer
, value
, 1);
349 if (value
&& (m
->control
& R_CONTROL_ENABLE_MASK
)) {
350 /* Force possibly-expired oneshot timer to restart */
351 ptimer_run(m
->timer
, 1);
354 ptimer_transaction_commit(m
->timer
);
357 /* Set the limit, but not the current count */
359 if (!(m
->control
& R_CONTROL_MODE_MASK
)) {
360 /* In free-running mode there is no limit */
363 if (!(m
->control
& R_CONTROL_SIZE_MASK
)) {
366 ptimer_transaction_begin(m
->timer
);
367 ptimer_set_limit(m
->timer
, value
, 0);
368 ptimer_transaction_commit(m
->timer
);
370 case A_TIMER1CONTROL
:
371 cmsdk_dualtimermod_write_control(m
, value
);
372 cmsdk_apb_dualtimer_update(s
);
376 cmsdk_apb_dualtimer_update(s
);
384 static const MemoryRegionOps cmsdk_apb_dualtimer_ops
= {
385 .read
= cmsdk_apb_dualtimer_read
,
386 .write
= cmsdk_apb_dualtimer_write
,
387 .endianness
= DEVICE_LITTLE_ENDIAN
,
388 /* byte/halfword accesses are just zero-padded on reads and writes */
389 .impl
.min_access_size
= 4,
390 .impl
.max_access_size
= 4,
391 .valid
.min_access_size
= 1,
392 .valid
.max_access_size
= 4,
395 static void cmsdk_dualtimermod_tick(void *opaque
)
397 CMSDKAPBDualTimerModule
*m
= opaque
;
400 cmsdk_apb_dualtimer_update(m
->parent
);
403 static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule
*m
)
405 m
->control
= R_CONTROL_INTEN_MASK
;
408 m
->value
= 0xffffffff;
409 ptimer_transaction_begin(m
->timer
);
410 ptimer_stop(m
->timer
);
412 * We start in free-running mode, with VALUE at 0xffffffff, and
413 * in 16-bit counter mode. This means that the ptimer count and
414 * limit must both be set to 0xffff, so we wrap at 16 bits.
416 ptimer_set_limit(m
->timer
, 0xffff, 1);
417 ptimer_set_freq(m
->timer
, m
->parent
->pclk_frq
);
418 ptimer_transaction_commit(m
->timer
);
421 static void cmsdk_apb_dualtimer_reset(DeviceState
*dev
)
423 CMSDKAPBDualTimer
*s
= CMSDK_APB_DUALTIMER(dev
);
426 trace_cmsdk_apb_dualtimer_reset();
428 for (i
= 0; i
< ARRAY_SIZE(s
->timermod
); i
++) {
429 cmsdk_dualtimermod_reset(&s
->timermod
[i
]);
435 static void cmsdk_apb_dualtimer_init(Object
*obj
)
437 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
438 CMSDKAPBDualTimer
*s
= CMSDK_APB_DUALTIMER(obj
);
441 memory_region_init_io(&s
->iomem
, obj
, &cmsdk_apb_dualtimer_ops
,
442 s
, "cmsdk-apb-dualtimer", 0x1000);
443 sysbus_init_mmio(sbd
, &s
->iomem
);
444 sysbus_init_irq(sbd
, &s
->timerintc
);
446 for (i
= 0; i
< ARRAY_SIZE(s
->timermod
); i
++) {
447 sysbus_init_irq(sbd
, &s
->timermod
[i
].timerint
);
449 s
->timclk
= qdev_init_clock_in(DEVICE(s
), "TIMCLK", NULL
, NULL
);
452 static void cmsdk_apb_dualtimer_realize(DeviceState
*dev
, Error
**errp
)
454 CMSDKAPBDualTimer
*s
= CMSDK_APB_DUALTIMER(dev
);
457 if (s
->pclk_frq
== 0) {
458 error_setg(errp
, "CMSDK APB timer: pclk-frq property must be set");
462 for (i
= 0; i
< ARRAY_SIZE(s
->timermod
); i
++) {
463 CMSDKAPBDualTimerModule
*m
= &s
->timermod
[i
];
466 m
->timer
= ptimer_init(cmsdk_dualtimermod_tick
, m
,
467 PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD
|
468 PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT
|
469 PTIMER_POLICY_NO_IMMEDIATE_RELOAD
|
470 PTIMER_POLICY_NO_COUNTER_ROUND_DOWN
);
474 static const VMStateDescription cmsdk_dualtimermod_vmstate
= {
475 .name
= "cmsdk-apb-dualtimer-module",
477 .minimum_version_id
= 1,
478 .fields
= (VMStateField
[]) {
479 VMSTATE_PTIMER(timer
, CMSDKAPBDualTimerModule
),
480 VMSTATE_UINT32(load
, CMSDKAPBDualTimerModule
),
481 VMSTATE_UINT32(value
, CMSDKAPBDualTimerModule
),
482 VMSTATE_UINT32(control
, CMSDKAPBDualTimerModule
),
483 VMSTATE_UINT32(intstatus
, CMSDKAPBDualTimerModule
),
484 VMSTATE_END_OF_LIST()
488 static const VMStateDescription cmsdk_apb_dualtimer_vmstate
= {
489 .name
= "cmsdk-apb-dualtimer",
491 .minimum_version_id
= 2,
492 .fields
= (VMStateField
[]) {
493 VMSTATE_CLOCK(timclk
, CMSDKAPBDualTimer
),
494 VMSTATE_STRUCT_ARRAY(timermod
, CMSDKAPBDualTimer
,
495 CMSDK_APB_DUALTIMER_NUM_MODULES
,
496 1, cmsdk_dualtimermod_vmstate
,
497 CMSDKAPBDualTimerModule
),
498 VMSTATE_UINT32(timeritcr
, CMSDKAPBDualTimer
),
499 VMSTATE_UINT32(timeritop
, CMSDKAPBDualTimer
),
500 VMSTATE_END_OF_LIST()
504 static Property cmsdk_apb_dualtimer_properties
[] = {
505 DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBDualTimer
, pclk_frq
, 0),
506 DEFINE_PROP_END_OF_LIST(),
509 static void cmsdk_apb_dualtimer_class_init(ObjectClass
*klass
, void *data
)
511 DeviceClass
*dc
= DEVICE_CLASS(klass
);
513 dc
->realize
= cmsdk_apb_dualtimer_realize
;
514 dc
->vmsd
= &cmsdk_apb_dualtimer_vmstate
;
515 dc
->reset
= cmsdk_apb_dualtimer_reset
;
516 device_class_set_props(dc
, cmsdk_apb_dualtimer_properties
);
519 static const TypeInfo cmsdk_apb_dualtimer_info
= {
520 .name
= TYPE_CMSDK_APB_DUALTIMER
,
521 .parent
= TYPE_SYS_BUS_DEVICE
,
522 .instance_size
= sizeof(CMSDKAPBDualTimer
),
523 .instance_init
= cmsdk_apb_dualtimer_init
,
524 .class_init
= cmsdk_apb_dualtimer_class_init
,
527 static void cmsdk_apb_dualtimer_register_types(void)
529 type_register_static(&cmsdk_apb_dualtimer_info
);
532 type_init(cmsdk_apb_dualtimer_register_types
);