1 /*
2 * ARM CMSDK APB dual-timer emulation
3 *
4 * Copyright (c) 2018 Linaro Limited
5 * Written by Peter Maydell
6 *
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.
10 */
11
12 /*
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
17 */
18
19 #include "qemu/osdep.h"
20 #include "qemu/log.h"
21 #include "trace.h"
22 #include "qapi/error.h"
23 #include "qemu/module.h"
24 #include "hw/sysbus.h"
25 #include "hw/irq.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"
31
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)
63 REG32(PID4, 0xfd0)
64 REG32(PID5, 0xfd4)
65 REG32(PID6, 0xfd8)
66 REG32(PID7, 0xfdc)
67 REG32(PID0, 0xfe0)
68 REG32(PID1, 0xfe4)
69 REG32(PID2, 0xfe8)
70 REG32(PID3, 0xfec)
71 REG32(CID0, 0xff0)
72 REG32(CID1, 0xff4)
73 REG32(CID2, 0xff8)
74 REG32(CID3, 0xffc)
75
76 /* PID/CID values */
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 */
81 };
82
cmsdk_dualtimermod_intstatus(CMSDKAPBDualTimerModule * m)83 static bool cmsdk_dualtimermod_intstatus(CMSDKAPBDualTimerModule *m)
84 {
85 /* Return masked interrupt status for the timer module */
86 return m->intstatus && (m->control & R_CONTROL_INTEN_MASK);
87 }
88
cmsdk_apb_dualtimer_update(CMSDKAPBDualTimer * s)89 static void cmsdk_apb_dualtimer_update(CMSDKAPBDualTimer *s)
90 {
91 bool timint1, timint2, timintc;
92
93 if (s->timeritcr) {
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;
97 } else {
98 timint1 = cmsdk_dualtimermod_intstatus(&s->timermod[0]);
99 timint2 = cmsdk_dualtimermod_intstatus(&s->timermod[1]);
100 }
101
102 timintc = timint1 || timint2;
103
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);
107 }
108
cmsdk_dualtimermod_divisor(CMSDKAPBDualTimerModule * m)109 static int cmsdk_dualtimermod_divisor(CMSDKAPBDualTimerModule *m)
110 {
111 /* Return the divisor set by the current CONTROL.PRESCALE value */
112 switch (FIELD_EX32(m->control, CONTROL, PRESCALE)) {
113 case 0:
114 return 1;
115 case 1:
116 return 16;
117 case 2:
118 case 3: /* UNDEFINED, we treat like 2 (and complained when it was set) */
119 return 256;
120 default:
121 g_assert_not_reached();
122 }
123 }
124
cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule * m,uint32_t newctrl)125 static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
126 uint32_t newctrl)
127 {
128 /* Handle a write to the CONTROL register */
129 uint32_t changed;
130
131 ptimer_transaction_begin(m->timer);
132
133 newctrl &= R_CONTROL_VALID_MASK;
134
135 changed = m->control ^ newctrl;
136
137 if (changed & ~newctrl & R_CONTROL_ENABLE_MASK) {
138 /* ENABLE cleared, stop timer before any further changes */
139 ptimer_stop(m->timer);
140 }
141
142 if (changed & R_CONTROL_PRESCALE_MASK) {
143 int divisor;
144
145 switch (FIELD_EX32(newctrl, CONTROL, PRESCALE)) {
146 case 0:
147 divisor = 1;
148 break;
149 case 1:
150 divisor = 16;
151 break;
152 case 2:
153 divisor = 256;
154 break;
155 case 3:
156 /* UNDEFINED; complain, and arbitrarily treat like 2 */
157 qemu_log_mask(LOG_GUEST_ERROR,
158 "CMSDK APB dual-timer: CONTROL.PRESCALE==0b11"
159 " is undefined behaviour\n");
160 divisor = 256;
161 break;
162 default:
163 g_assert_not_reached();
164 }
165 ptimer_set_period_from_clock(m->timer, m->parent->timclk, divisor);
166 }
167
168 if (changed & R_CONTROL_MODE_MASK) {
169 uint32_t load;
170 if (newctrl & R_CONTROL_MODE_MASK) {
171 /* Periodic: the limit is the LOAD register value */
172 load = m->load;
173 } else {
174 /* Free-running: counter wraps around */
175 load = ptimer_get_limit(m->timer);
176 if (!(m->control & R_CONTROL_SIZE_MASK)) {
177 load = deposit32(m->load, 0, 16, load);
178 }
179 m->load = load;
180 load = 0xffffffff;
181 }
182 if (!(m->control & R_CONTROL_SIZE_MASK)) {
183 load &= 0xffff;
184 }
185 ptimer_set_limit(m->timer, load, 0);
186 }
187
188 if (changed & R_CONTROL_SIZE_MASK) {
189 /* Timer switched between 16 and 32 bit count */
190 uint32_t value, load;
191
192 value = ptimer_get_count(m->timer);
193 load = ptimer_get_limit(m->timer);
194 if (newctrl & R_CONTROL_SIZE_MASK) {
195 /* 16 -> 32, top half of VALUE is in struct field */
196 value = deposit32(m->value, 0, 16, value);
197 } else {
198 /* 32 -> 16: save top half to struct field and truncate */
199 m->value = value;
200 value &= 0xffff;
201 }
202
203 if (newctrl & R_CONTROL_MODE_MASK) {
204 /* Periodic, timer limit has LOAD value */
205 if (newctrl & R_CONTROL_SIZE_MASK) {
206 load = deposit32(m->load, 0, 16, load);
207 } else {
208 m->load = load;
209 load &= 0xffff;
210 }
211 } else {
212 /* Free-running, timer limit is set to give wraparound */
213 if (newctrl & R_CONTROL_SIZE_MASK) {
214 load = 0xffffffff;
215 } else {
216 load = 0xffff;
217 }
218 }
219 ptimer_set_count(m->timer, value);
220 ptimer_set_limit(m->timer, load, 0);
221 }
222
223 if (newctrl & R_CONTROL_ENABLE_MASK) {
224 /*
225 * ENABLE is set; start the timer after all other changes.
226 * We start it even if the ENABLE bit didn't actually change,
227 * in case the timer was an expired one-shot timer that has
228 * now been changed into a free-running or periodic timer.
229 */
230 ptimer_run(m->timer, !!(newctrl & R_CONTROL_ONESHOT_MASK));
231 }
232
233 m->control = newctrl;
234
235 ptimer_transaction_commit(m->timer);
236 }
237
cmsdk_apb_dualtimer_read(void * opaque,hwaddr offset,unsigned size)238 static uint64_t cmsdk_apb_dualtimer_read(void *opaque, hwaddr offset,
239 unsigned size)
240 {
241 CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
242 uint64_t r;
243
244 if (offset >= A_TIMERITCR) {
245 switch (offset) {
246 case A_TIMERITCR:
247 r = s->timeritcr;
248 break;
249 case A_PID4 ... A_CID3:
250 r = timer_id[(offset - A_PID4) / 4];
251 break;
252 default:
253 bad_offset:
254 qemu_log_mask(LOG_GUEST_ERROR,
255 "CMSDK APB dual-timer read: bad offset %x\n",
256 (int) offset);
257 r = 0;
258 break;
259 }
260 } else {
261 int timer = offset >> 5;
262 CMSDKAPBDualTimerModule *m;
263
264 if (timer >= ARRAY_SIZE(s->timermod)) {
265 goto bad_offset;
266 }
267
268 m = &s->timermod[timer];
269
270 switch (offset & 0x1F) {
271 case A_TIMER1LOAD:
272 case A_TIMER1BGLOAD:
273 if (m->control & R_CONTROL_MODE_MASK) {
274 /*
275 * Periodic: the ptimer limit is the LOAD register value, (or
276 * just the low 16 bits of it if the timer is in 16-bit mode)
277 */
278 r = ptimer_get_limit(m->timer);
279 if (!(m->control & R_CONTROL_SIZE_MASK)) {
280 r = deposit32(m->load, 0, 16, r);
281 }
282 } else {
283 /* Free-running: LOAD register value is just in m->load */
284 r = m->load;
285 }
286 break;
287 case A_TIMER1VALUE:
288 r = ptimer_get_count(m->timer);
289 if (!(m->control & R_CONTROL_SIZE_MASK)) {
290 r = deposit32(m->value, 0, 16, r);
291 }
292 break;
293 case A_TIMER1CONTROL:
294 r = m->control;
295 break;
296 case A_TIMER1RIS:
297 r = m->intstatus;
298 break;
299 case A_TIMER1MIS:
300 r = cmsdk_dualtimermod_intstatus(m);
301 break;
302 default:
303 goto bad_offset;
304 }
305 }
306
307 trace_cmsdk_apb_dualtimer_read(offset, r, size);
308 return r;
309 }
310
cmsdk_apb_dualtimer_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)311 static void cmsdk_apb_dualtimer_write(void *opaque, hwaddr offset,
312 uint64_t value, unsigned size)
313 {
314 CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
315
316 trace_cmsdk_apb_dualtimer_write(offset, value, size);
317
318 if (offset >= A_TIMERITCR) {
319 switch (offset) {
320 case A_TIMERITCR:
321 s->timeritcr = value & R_TIMERITCR_VALID_MASK;
322 cmsdk_apb_dualtimer_update(s);
323 break;
324 case A_TIMERITOP:
325 s->timeritop = value & R_TIMERITOP_VALID_MASK;
326 cmsdk_apb_dualtimer_update(s);
327 break;
328 default:
329 bad_offset:
330 qemu_log_mask(LOG_GUEST_ERROR,
331 "CMSDK APB dual-timer write: bad offset %x\n",
332 (int) offset);
333 break;
334 }
335 } else {
336 int timer = offset >> 5;
337 CMSDKAPBDualTimerModule *m;
338
339 if (timer >= ARRAY_SIZE(s->timermod)) {
340 goto bad_offset;
341 }
342
343 m = &s->timermod[timer];
344
345 switch (offset & 0x1F) {
346 case A_TIMER1LOAD:
347 /* Set the limit, and immediately reload the count from it */
348 m->load = value;
349 m->value = value;
350 if (!(m->control & R_CONTROL_SIZE_MASK)) {
351 value &= 0xffff;
352 }
353 ptimer_transaction_begin(m->timer);
354 if (!(m->control & R_CONTROL_MODE_MASK)) {
355 /*
356 * In free-running mode this won't set the limit but will
357 * still change the current count value.
358 */
359 ptimer_set_count(m->timer, value);
360 } else {
361 if (!value) {
362 ptimer_stop(m->timer);
363 }
364 ptimer_set_limit(m->timer, value, 1);
365 if (value && (m->control & R_CONTROL_ENABLE_MASK)) {
366 /* Force possibly-expired oneshot timer to restart */
367 ptimer_run(m->timer, 1);
368 }
369 }
370 ptimer_transaction_commit(m->timer);
371 break;
372 case A_TIMER1BGLOAD:
373 /* Set the limit, but not the current count */
374 m->load = value;
375 if (!(m->control & R_CONTROL_MODE_MASK)) {
376 /* In free-running mode there is no limit */
377 break;
378 }
379 if (!(m->control & R_CONTROL_SIZE_MASK)) {
380 value &= 0xffff;
381 }
382 ptimer_transaction_begin(m->timer);
383 ptimer_set_limit(m->timer, value, 0);
384 ptimer_transaction_commit(m->timer);
385 break;
386 case A_TIMER1CONTROL:
387 cmsdk_dualtimermod_write_control(m, value);
388 cmsdk_apb_dualtimer_update(s);
389 break;
390 case A_TIMER1INTCLR:
391 m->intstatus = 0;
392 cmsdk_apb_dualtimer_update(s);
393 break;
394 default:
395 goto bad_offset;
396 }
397 }
398 }
399
400 static const MemoryRegionOps cmsdk_apb_dualtimer_ops = {
401 .read = cmsdk_apb_dualtimer_read,
402 .write = cmsdk_apb_dualtimer_write,
403 .endianness = DEVICE_LITTLE_ENDIAN,
404 /* byte/halfword accesses are just zero-padded on reads and writes */
405 .impl.min_access_size = 4,
406 .impl.max_access_size = 4,
407 .valid.min_access_size = 1,
408 .valid.max_access_size = 4,
409 };
410
cmsdk_dualtimermod_tick(void * opaque)411 static void cmsdk_dualtimermod_tick(void *opaque)
412 {
413 CMSDKAPBDualTimerModule *m = opaque;
414
415 m->intstatus = 1;
416 cmsdk_apb_dualtimer_update(m->parent);
417 }
418
cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule * m)419 static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m)
420 {
421 m->control = R_CONTROL_INTEN_MASK;
422 m->intstatus = 0;
423 m->load = 0;
424 m->value = 0xffffffff;
425 ptimer_transaction_begin(m->timer);
426 ptimer_stop(m->timer);
427 /*
428 * We start in free-running mode, with VALUE at 0xffffffff, and
429 * in 16-bit counter mode. This means that the ptimer count and
430 * limit must both be set to 0xffff, so we wrap at 16 bits.
431 */
432 ptimer_set_limit(m->timer, 0xffff, 1);
433 ptimer_set_period_from_clock(m->timer, m->parent->timclk,
434 cmsdk_dualtimermod_divisor(m));
435 ptimer_transaction_commit(m->timer);
436 }
437
cmsdk_apb_dualtimer_reset(DeviceState * dev)438 static void cmsdk_apb_dualtimer_reset(DeviceState *dev)
439 {
440 CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
441 int i;
442
443 trace_cmsdk_apb_dualtimer_reset();
444
445 for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
446 cmsdk_dualtimermod_reset(&s->timermod[i]);
447 }
448 s->timeritcr = 0;
449 s->timeritop = 0;
450 }
451
cmsdk_apb_dualtimer_clk_update(void * opaque,ClockEvent event)452 static void cmsdk_apb_dualtimer_clk_update(void *opaque, ClockEvent event)
453 {
454 CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
455 int i;
456
457 for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
458 CMSDKAPBDualTimerModule *m = &s->timermod[i];
459 ptimer_transaction_begin(m->timer);
460 ptimer_set_period_from_clock(m->timer, m->parent->timclk,
461 cmsdk_dualtimermod_divisor(m));
462 ptimer_transaction_commit(m->timer);
463 }
464 }
465
cmsdk_apb_dualtimer_init(Object * obj)466 static void cmsdk_apb_dualtimer_init(Object *obj)
467 {
468 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
469 CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(obj);
470 int i;
471
472 memory_region_init_io(&s->iomem, obj, &cmsdk_apb_dualtimer_ops,
473 s, "cmsdk-apb-dualtimer", 0x1000);
474 sysbus_init_mmio(sbd, &s->iomem);
475 sysbus_init_irq(sbd, &s->timerintc);
476
477 for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
478 sysbus_init_irq(sbd, &s->timermod[i].timerint);
479 }
480 s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK",
481 cmsdk_apb_dualtimer_clk_update, s,
482 ClockUpdate);
483 }
484
cmsdk_apb_dualtimer_realize(DeviceState * dev,Error ** errp)485 static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
486 {
487 CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
488 int i;
489
490 if (!clock_has_source(s->timclk)) {
491 error_setg(errp, "CMSDK APB dualtimer: TIMCLK clock must be connected");
492 return;
493 }
494
495 for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
496 CMSDKAPBDualTimerModule *m = &s->timermod[i];
497
498 m->parent = s;
499 m->timer = ptimer_init(cmsdk_dualtimermod_tick, m,
500 PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
501 PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
502 PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
503 PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
504 }
505 }
506
507 static const VMStateDescription cmsdk_dualtimermod_vmstate = {
508 .name = "cmsdk-apb-dualtimer-module",
509 .version_id = 1,
510 .minimum_version_id = 1,
511 .fields = (const VMStateField[]) {
512 VMSTATE_PTIMER(timer, CMSDKAPBDualTimerModule),
513 VMSTATE_UINT32(load, CMSDKAPBDualTimerModule),
514 VMSTATE_UINT32(value, CMSDKAPBDualTimerModule),
515 VMSTATE_UINT32(control, CMSDKAPBDualTimerModule),
516 VMSTATE_UINT32(intstatus, CMSDKAPBDualTimerModule),
517 VMSTATE_END_OF_LIST()
518 }
519 };
520
521 static const VMStateDescription cmsdk_apb_dualtimer_vmstate = {
522 .name = "cmsdk-apb-dualtimer",
523 .version_id = 2,
524 .minimum_version_id = 2,
525 .fields = (const VMStateField[]) {
526 VMSTATE_CLOCK(timclk, CMSDKAPBDualTimer),
527 VMSTATE_STRUCT_ARRAY(timermod, CMSDKAPBDualTimer,
528 CMSDK_APB_DUALTIMER_NUM_MODULES,
529 1, cmsdk_dualtimermod_vmstate,
530 CMSDKAPBDualTimerModule),
531 VMSTATE_UINT32(timeritcr, CMSDKAPBDualTimer),
532 VMSTATE_UINT32(timeritop, CMSDKAPBDualTimer),
533 VMSTATE_END_OF_LIST()
534 }
535 };
536
cmsdk_apb_dualtimer_class_init(ObjectClass * klass,void * data)537 static void cmsdk_apb_dualtimer_class_init(ObjectClass *klass, void *data)
538 {
539 DeviceClass *dc = DEVICE_CLASS(klass);
540
541 dc->realize = cmsdk_apb_dualtimer_realize;
542 dc->vmsd = &cmsdk_apb_dualtimer_vmstate;
543 dc->reset = cmsdk_apb_dualtimer_reset;
544 }
545
546 static const TypeInfo cmsdk_apb_dualtimer_info = {
547 .name = TYPE_CMSDK_APB_DUALTIMER,
548 .parent = TYPE_SYS_BUS_DEVICE,
549 .instance_size = sizeof(CMSDKAPBDualTimer),
550 .instance_init = cmsdk_apb_dualtimer_init,
551 .class_init = cmsdk_apb_dualtimer_class_init,
552 };
553
cmsdk_apb_dualtimer_register_types(void)554 static void cmsdk_apb_dualtimer_register_types(void)
555 {
556 type_register_static(&cmsdk_apb_dualtimer_info);
557 }
558
559 type_init(cmsdk_apb_dualtimer_register_types);
560