xref: /qemu/hw/timer/cmsdk-apb-dualtimer.c (revision 55fd0f84)
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 
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 
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 
109 static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
110                                              uint32_t newctrl)
111 {
112     /* Handle a write to the CONTROL register */
113     uint32_t changed;
114 
115     ptimer_transaction_begin(m->timer);
116 
117     newctrl &= R_CONTROL_VALID_MASK;
118 
119     changed = m->control ^ newctrl;
120 
121     if (changed & ~newctrl & R_CONTROL_ENABLE_MASK) {
122         /* ENABLE cleared, stop timer before any further changes */
123         ptimer_stop(m->timer);
124     }
125 
126     if (changed & R_CONTROL_PRESCALE_MASK) {
127         int divisor;
128 
129         switch (FIELD_EX32(newctrl, CONTROL, PRESCALE)) {
130         case 0:
131             divisor = 1;
132             break;
133         case 1:
134             divisor = 16;
135             break;
136         case 2:
137             divisor = 256;
138             break;
139         case 3:
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");
144             divisor = 256;
145             break;
146         default:
147             g_assert_not_reached();
148         }
149         ptimer_set_freq(m->timer, m->parent->pclk_frq / divisor);
150     }
151 
152     if (changed & R_CONTROL_MODE_MASK) {
153         uint32_t load;
154         if (newctrl & R_CONTROL_MODE_MASK) {
155             /* Periodic: the limit is the LOAD register value */
156             load = m->load;
157         } else {
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);
162             }
163             m->load = load;
164             load = 0xffffffff;
165         }
166         if (!(m->control & R_CONTROL_SIZE_MASK)) {
167             load &= 0xffff;
168         }
169         ptimer_set_limit(m->timer, load, 0);
170     }
171 
172     if (changed & R_CONTROL_SIZE_MASK) {
173         /* Timer switched between 16 and 32 bit count */
174         uint32_t value, load;
175 
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);
181         } else {
182             /* 32 -> 16: save top half to struct field and truncate */
183             m->value = value;
184             value &= 0xffff;
185         }
186 
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);
191             } else {
192                 m->load = load;
193                 load &= 0xffff;
194             }
195         } else {
196             /* Free-running, timer limit is set to give wraparound */
197             if (newctrl & R_CONTROL_SIZE_MASK) {
198                 load = 0xffffffff;
199             } else {
200                 load = 0xffff;
201             }
202         }
203         ptimer_set_count(m->timer, value);
204         ptimer_set_limit(m->timer, load, 0);
205     }
206 
207     if (newctrl & R_CONTROL_ENABLE_MASK) {
208         /*
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.
213          */
214         ptimer_run(m->timer, !!(newctrl & R_CONTROL_ONESHOT_MASK));
215     }
216 
217     m->control = newctrl;
218 
219     ptimer_transaction_commit(m->timer);
220 }
221 
222 static uint64_t cmsdk_apb_dualtimer_read(void *opaque, hwaddr offset,
223                                           unsigned size)
224 {
225     CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
226     uint64_t r;
227 
228     if (offset >= A_TIMERITCR) {
229         switch (offset) {
230         case A_TIMERITCR:
231             r = s->timeritcr;
232             break;
233         case A_PID4 ... A_CID3:
234             r = timer_id[(offset - A_PID4) / 4];
235             break;
236         default:
237         bad_offset:
238             qemu_log_mask(LOG_GUEST_ERROR,
239                           "CMSDK APB dual-timer read: bad offset %x\n",
240                           (int) offset);
241             r = 0;
242             break;
243         }
244     } else {
245         int timer = offset >> 5;
246         CMSDKAPBDualTimerModule *m;
247 
248         if (timer >= ARRAY_SIZE(s->timermod)) {
249             goto bad_offset;
250         }
251 
252         m = &s->timermod[timer];
253 
254         switch (offset & 0x1F) {
255         case A_TIMER1LOAD:
256         case A_TIMER1BGLOAD:
257             if (m->control & R_CONTROL_MODE_MASK) {
258                 /*
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)
261                  */
262                 r = ptimer_get_limit(m->timer);
263                 if (!(m->control & R_CONTROL_SIZE_MASK)) {
264                     r = deposit32(m->load, 0, 16, r);
265                 }
266             } else {
267                 /* Free-running: LOAD register value is just in m->load */
268                 r = m->load;
269             }
270             break;
271         case A_TIMER1VALUE:
272             r = ptimer_get_count(m->timer);
273             if (!(m->control & R_CONTROL_SIZE_MASK)) {
274                 r = deposit32(m->value, 0, 16, r);
275             }
276             break;
277         case A_TIMER1CONTROL:
278             r = m->control;
279             break;
280         case A_TIMER1RIS:
281             r = m->intstatus;
282             break;
283         case A_TIMER1MIS:
284             r = cmsdk_dualtimermod_intstatus(m);
285             break;
286         default:
287             goto bad_offset;
288         }
289     }
290 
291     trace_cmsdk_apb_dualtimer_read(offset, r, size);
292     return r;
293 }
294 
295 static void cmsdk_apb_dualtimer_write(void *opaque, hwaddr offset,
296                                        uint64_t value, unsigned size)
297 {
298     CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
299 
300     trace_cmsdk_apb_dualtimer_write(offset, value, size);
301 
302     if (offset >= A_TIMERITCR) {
303         switch (offset) {
304         case A_TIMERITCR:
305             s->timeritcr = value & R_TIMERITCR_VALID_MASK;
306             cmsdk_apb_dualtimer_update(s);
307             break;
308         case A_TIMERITOP:
309             s->timeritop = value & R_TIMERITOP_VALID_MASK;
310             cmsdk_apb_dualtimer_update(s);
311             break;
312         default:
313         bad_offset:
314             qemu_log_mask(LOG_GUEST_ERROR,
315                           "CMSDK APB dual-timer write: bad offset %x\n",
316                           (int) offset);
317             break;
318         }
319     } else {
320         int timer = offset >> 5;
321         CMSDKAPBDualTimerModule *m;
322 
323         if (timer >= ARRAY_SIZE(s->timermod)) {
324             goto bad_offset;
325         }
326 
327         m = &s->timermod[timer];
328 
329         switch (offset & 0x1F) {
330         case A_TIMER1LOAD:
331             /* Set the limit, and immediately reload the count from it */
332             m->load = value;
333             m->value = value;
334             if (!(m->control & R_CONTROL_SIZE_MASK)) {
335                 value &= 0xffff;
336             }
337             ptimer_transaction_begin(m->timer);
338             if (!(m->control & R_CONTROL_MODE_MASK)) {
339                 /*
340                  * In free-running mode this won't set the limit but will
341                  * still change the current count value.
342                  */
343                 ptimer_set_count(m->timer, value);
344             } else {
345                 if (!value) {
346                     ptimer_stop(m->timer);
347                 }
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);
352                 }
353             }
354             ptimer_transaction_commit(m->timer);
355             break;
356         case A_TIMER1BGLOAD:
357             /* Set the limit, but not the current count */
358             m->load = value;
359             if (!(m->control & R_CONTROL_MODE_MASK)) {
360                 /* In free-running mode there is no limit */
361                 break;
362             }
363             if (!(m->control & R_CONTROL_SIZE_MASK)) {
364                 value &= 0xffff;
365             }
366             ptimer_transaction_begin(m->timer);
367             ptimer_set_limit(m->timer, value, 0);
368             ptimer_transaction_commit(m->timer);
369             break;
370         case A_TIMER1CONTROL:
371             cmsdk_dualtimermod_write_control(m, value);
372             cmsdk_apb_dualtimer_update(s);
373             break;
374         case A_TIMER1INTCLR:
375             m->intstatus = 0;
376             cmsdk_apb_dualtimer_update(s);
377             break;
378         default:
379             goto bad_offset;
380         }
381     }
382 }
383 
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,
393 };
394 
395 static void cmsdk_dualtimermod_tick(void *opaque)
396 {
397     CMSDKAPBDualTimerModule *m = opaque;
398 
399     m->intstatus = 1;
400     cmsdk_apb_dualtimer_update(m->parent);
401 }
402 
403 static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m)
404 {
405     m->control = R_CONTROL_INTEN_MASK;
406     m->intstatus = 0;
407     m->load = 0;
408     m->value = 0xffffffff;
409     ptimer_transaction_begin(m->timer);
410     ptimer_stop(m->timer);
411     /*
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.
415      */
416     ptimer_set_limit(m->timer, 0xffff, 1);
417     ptimer_set_freq(m->timer, m->parent->pclk_frq);
418     ptimer_transaction_commit(m->timer);
419 }
420 
421 static void cmsdk_apb_dualtimer_reset(DeviceState *dev)
422 {
423     CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
424     int i;
425 
426     trace_cmsdk_apb_dualtimer_reset();
427 
428     for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
429         cmsdk_dualtimermod_reset(&s->timermod[i]);
430     }
431     s->timeritcr = 0;
432     s->timeritop = 0;
433 }
434 
435 static void cmsdk_apb_dualtimer_init(Object *obj)
436 {
437     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
438     CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(obj);
439     int i;
440 
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);
445 
446     for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
447         sysbus_init_irq(sbd, &s->timermod[i].timerint);
448     }
449     s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK", NULL, NULL);
450 }
451 
452 static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
453 {
454     CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
455     int i;
456 
457     if (s->pclk_frq == 0) {
458         error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
459         return;
460     }
461 
462     for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
463         CMSDKAPBDualTimerModule *m = &s->timermod[i];
464 
465         m->parent = s;
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);
471     }
472 }
473 
474 static const VMStateDescription cmsdk_dualtimermod_vmstate = {
475     .name = "cmsdk-apb-dualtimer-module",
476     .version_id = 1,
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()
485     }
486 };
487 
488 static const VMStateDescription cmsdk_apb_dualtimer_vmstate = {
489     .name = "cmsdk-apb-dualtimer",
490     .version_id = 2,
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()
501     }
502 };
503 
504 static Property cmsdk_apb_dualtimer_properties[] = {
505     DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBDualTimer, pclk_frq, 0),
506     DEFINE_PROP_END_OF_LIST(),
507 };
508 
509 static void cmsdk_apb_dualtimer_class_init(ObjectClass *klass, void *data)
510 {
511     DeviceClass *dc = DEVICE_CLASS(klass);
512 
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);
517 }
518 
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,
525 };
526 
527 static void cmsdk_apb_dualtimer_register_types(void)
528 {
529     type_register_static(&cmsdk_apb_dualtimer_info);
530 }
531 
532 type_init(cmsdk_apb_dualtimer_register_types);
533