xref: /openbmc/qemu/hw/timer/cmsdk-apb-dualtimer.c (revision 6a0acfff)
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/main-loop.h"
24 #include "qemu/module.h"
25 #include "hw/sysbus.h"
26 #include "hw/irq.h"
27 #include "hw/registerfields.h"
28 #include "hw/timer/cmsdk-apb-dualtimer.h"
29 
30 REG32(TIMER1LOAD, 0x0)
31 REG32(TIMER1VALUE, 0x4)
32 REG32(TIMER1CONTROL, 0x8)
33     FIELD(CONTROL, ONESHOT, 0, 1)
34     FIELD(CONTROL, SIZE, 1, 1)
35     FIELD(CONTROL, PRESCALE, 2, 2)
36     FIELD(CONTROL, INTEN, 5, 1)
37     FIELD(CONTROL, MODE, 6, 1)
38     FIELD(CONTROL, ENABLE, 7, 1)
39 #define R_CONTROL_VALID_MASK (R_CONTROL_ONESHOT_MASK | R_CONTROL_SIZE_MASK | \
40                               R_CONTROL_PRESCALE_MASK | R_CONTROL_INTEN_MASK | \
41                               R_CONTROL_MODE_MASK | R_CONTROL_ENABLE_MASK)
42 REG32(TIMER1INTCLR, 0xc)
43 REG32(TIMER1RIS, 0x10)
44 REG32(TIMER1MIS, 0x14)
45 REG32(TIMER1BGLOAD, 0x18)
46 REG32(TIMER2LOAD, 0x20)
47 REG32(TIMER2VALUE, 0x24)
48 REG32(TIMER2CONTROL, 0x28)
49 REG32(TIMER2INTCLR, 0x2c)
50 REG32(TIMER2RIS, 0x30)
51 REG32(TIMER2MIS, 0x34)
52 REG32(TIMER2BGLOAD, 0x38)
53 REG32(TIMERITCR, 0xf00)
54     FIELD(TIMERITCR, ENABLE, 0, 1)
55 #define R_TIMERITCR_VALID_MASK R_TIMERITCR_ENABLE_MASK
56 REG32(TIMERITOP, 0xf04)
57     FIELD(TIMERITOP, TIMINT1, 0, 1)
58     FIELD(TIMERITOP, TIMINT2, 1, 1)
59 #define R_TIMERITOP_VALID_MASK (R_TIMERITOP_TIMINT1_MASK | \
60                                 R_TIMERITOP_TIMINT2_MASK)
61 REG32(PID4, 0xfd0)
62 REG32(PID5, 0xfd4)
63 REG32(PID6, 0xfd8)
64 REG32(PID7, 0xfdc)
65 REG32(PID0, 0xfe0)
66 REG32(PID1, 0xfe4)
67 REG32(PID2, 0xfe8)
68 REG32(PID3, 0xfec)
69 REG32(CID0, 0xff0)
70 REG32(CID1, 0xff4)
71 REG32(CID2, 0xff8)
72 REG32(CID3, 0xffc)
73 
74 /* PID/CID values */
75 static const int timer_id[] = {
76     0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
77     0x23, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
78     0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
79 };
80 
81 static bool cmsdk_dualtimermod_intstatus(CMSDKAPBDualTimerModule *m)
82 {
83     /* Return masked interrupt status for the timer module */
84     return m->intstatus && (m->control & R_CONTROL_INTEN_MASK);
85 }
86 
87 static void cmsdk_apb_dualtimer_update(CMSDKAPBDualTimer *s)
88 {
89     bool timint1, timint2, timintc;
90 
91     if (s->timeritcr) {
92         /* Integration test mode: outputs driven directly from TIMERITOP bits */
93         timint1 = s->timeritop & R_TIMERITOP_TIMINT1_MASK;
94         timint2 = s->timeritop & R_TIMERITOP_TIMINT2_MASK;
95     } else {
96         timint1 = cmsdk_dualtimermod_intstatus(&s->timermod[0]);
97         timint2 = cmsdk_dualtimermod_intstatus(&s->timermod[1]);
98     }
99 
100     timintc = timint1 || timint2;
101 
102     qemu_set_irq(s->timermod[0].timerint, timint1);
103     qemu_set_irq(s->timermod[1].timerint, timint2);
104     qemu_set_irq(s->timerintc, timintc);
105 }
106 
107 static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
108                                              uint32_t newctrl)
109 {
110     /* Handle a write to the CONTROL register */
111     uint32_t changed;
112 
113     newctrl &= R_CONTROL_VALID_MASK;
114 
115     changed = m->control ^ newctrl;
116 
117     if (changed & ~newctrl & R_CONTROL_ENABLE_MASK) {
118         /* ENABLE cleared, stop timer before any further changes */
119         ptimer_stop(m->timer);
120     }
121 
122     if (changed & R_CONTROL_PRESCALE_MASK) {
123         int divisor;
124 
125         switch (FIELD_EX32(newctrl, CONTROL, PRESCALE)) {
126         case 0:
127             divisor = 1;
128             break;
129         case 1:
130             divisor = 16;
131             break;
132         case 2:
133             divisor = 256;
134             break;
135         case 3:
136             /* UNDEFINED; complain, and arbitrarily treat like 2 */
137             qemu_log_mask(LOG_GUEST_ERROR,
138                           "CMSDK APB dual-timer: CONTROL.PRESCALE==0b11"
139                           " is undefined behaviour\n");
140             divisor = 256;
141             break;
142         default:
143             g_assert_not_reached();
144         }
145         ptimer_set_freq(m->timer, m->parent->pclk_frq / divisor);
146     }
147 
148     if (changed & R_CONTROL_MODE_MASK) {
149         uint32_t load;
150         if (newctrl & R_CONTROL_MODE_MASK) {
151             /* Periodic: the limit is the LOAD register value */
152             load = m->load;
153         } else {
154             /* Free-running: counter wraps around */
155             load = ptimer_get_limit(m->timer);
156             if (!(m->control & R_CONTROL_SIZE_MASK)) {
157                 load = deposit32(m->load, 0, 16, load);
158             }
159             m->load = load;
160             load = 0xffffffff;
161         }
162         if (!(m->control & R_CONTROL_SIZE_MASK)) {
163             load &= 0xffff;
164         }
165         ptimer_set_limit(m->timer, load, 0);
166     }
167 
168     if (changed & R_CONTROL_SIZE_MASK) {
169         /* Timer switched between 16 and 32 bit count */
170         uint32_t value, load;
171 
172         value = ptimer_get_count(m->timer);
173         load = ptimer_get_limit(m->timer);
174         if (newctrl & R_CONTROL_SIZE_MASK) {
175             /* 16 -> 32, top half of VALUE is in struct field */
176             value = deposit32(m->value, 0, 16, value);
177         } else {
178             /* 32 -> 16: save top half to struct field and truncate */
179             m->value = value;
180             value &= 0xffff;
181         }
182 
183         if (newctrl & R_CONTROL_MODE_MASK) {
184             /* Periodic, timer limit has LOAD value */
185             if (newctrl & R_CONTROL_SIZE_MASK) {
186                 load = deposit32(m->load, 0, 16, load);
187             } else {
188                 m->load = load;
189                 load &= 0xffff;
190             }
191         } else {
192             /* Free-running, timer limit is set to give wraparound */
193             if (newctrl & R_CONTROL_SIZE_MASK) {
194                 load = 0xffffffff;
195             } else {
196                 load = 0xffff;
197             }
198         }
199         ptimer_set_count(m->timer, value);
200         ptimer_set_limit(m->timer, load, 0);
201     }
202 
203     if (newctrl & R_CONTROL_ENABLE_MASK) {
204         /*
205          * ENABLE is set; start the timer after all other changes.
206          * We start it even if the ENABLE bit didn't actually change,
207          * in case the timer was an expired one-shot timer that has
208          * now been changed into a free-running or periodic timer.
209          */
210         ptimer_run(m->timer, !!(newctrl & R_CONTROL_ONESHOT_MASK));
211     }
212 
213     m->control = newctrl;
214 }
215 
216 static uint64_t cmsdk_apb_dualtimer_read(void *opaque, hwaddr offset,
217                                           unsigned size)
218 {
219     CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
220     uint64_t r;
221 
222     if (offset >= A_TIMERITCR) {
223         switch (offset) {
224         case A_TIMERITCR:
225             r = s->timeritcr;
226             break;
227         case A_PID4 ... A_CID3:
228             r = timer_id[(offset - A_PID4) / 4];
229             break;
230         default:
231         bad_offset:
232             qemu_log_mask(LOG_GUEST_ERROR,
233                           "CMSDK APB dual-timer read: bad offset %x\n",
234                           (int) offset);
235             r = 0;
236             break;
237         }
238     } else {
239         int timer = offset >> 5;
240         CMSDKAPBDualTimerModule *m;
241 
242         if (timer >= ARRAY_SIZE(s->timermod)) {
243             goto bad_offset;
244         }
245 
246         m = &s->timermod[timer];
247 
248         switch (offset & 0x1F) {
249         case A_TIMER1LOAD:
250         case A_TIMER1BGLOAD:
251             if (m->control & R_CONTROL_MODE_MASK) {
252                 /*
253                  * Periodic: the ptimer limit is the LOAD register value, (or
254                  * just the low 16 bits of it if the timer is in 16-bit mode)
255                  */
256                 r = ptimer_get_limit(m->timer);
257                 if (!(m->control & R_CONTROL_SIZE_MASK)) {
258                     r = deposit32(m->load, 0, 16, r);
259                 }
260             } else {
261                 /* Free-running: LOAD register value is just in m->load */
262                 r = m->load;
263             }
264             break;
265         case A_TIMER1VALUE:
266             r = ptimer_get_count(m->timer);
267             if (!(m->control & R_CONTROL_SIZE_MASK)) {
268                 r = deposit32(m->value, 0, 16, r);
269             }
270             break;
271         case A_TIMER1CONTROL:
272             r = m->control;
273             break;
274         case A_TIMER1RIS:
275             r = m->intstatus;
276             break;
277         case A_TIMER1MIS:
278             r = cmsdk_dualtimermod_intstatus(m);
279             break;
280         default:
281             goto bad_offset;
282         }
283     }
284 
285     trace_cmsdk_apb_dualtimer_read(offset, r, size);
286     return r;
287 }
288 
289 static void cmsdk_apb_dualtimer_write(void *opaque, hwaddr offset,
290                                        uint64_t value, unsigned size)
291 {
292     CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
293 
294     trace_cmsdk_apb_dualtimer_write(offset, value, size);
295 
296     if (offset >= A_TIMERITCR) {
297         switch (offset) {
298         case A_TIMERITCR:
299             s->timeritcr = value & R_TIMERITCR_VALID_MASK;
300             cmsdk_apb_dualtimer_update(s);
301             break;
302         case A_TIMERITOP:
303             s->timeritop = value & R_TIMERITOP_VALID_MASK;
304             cmsdk_apb_dualtimer_update(s);
305             break;
306         default:
307         bad_offset:
308             qemu_log_mask(LOG_GUEST_ERROR,
309                           "CMSDK APB dual-timer write: bad offset %x\n",
310                           (int) offset);
311             break;
312         }
313     } else {
314         int timer = offset >> 5;
315         CMSDKAPBDualTimerModule *m;
316 
317         if (timer >= ARRAY_SIZE(s->timermod)) {
318             goto bad_offset;
319         }
320 
321         m = &s->timermod[timer];
322 
323         switch (offset & 0x1F) {
324         case A_TIMER1LOAD:
325             /* Set the limit, and immediately reload the count from it */
326             m->load = value;
327             m->value = value;
328             if (!(m->control & R_CONTROL_SIZE_MASK)) {
329                 value &= 0xffff;
330             }
331             if (!(m->control & R_CONTROL_MODE_MASK)) {
332                 /*
333                  * In free-running mode this won't set the limit but will
334                  * still change the current count value.
335                  */
336                 ptimer_set_count(m->timer, value);
337             } else {
338                 if (!value) {
339                     ptimer_stop(m->timer);
340                 }
341                 ptimer_set_limit(m->timer, value, 1);
342                 if (value && (m->control & R_CONTROL_ENABLE_MASK)) {
343                     /* Force possibly-expired oneshot timer to restart */
344                     ptimer_run(m->timer, 1);
345                 }
346             }
347             break;
348         case A_TIMER1BGLOAD:
349             /* Set the limit, but not the current count */
350             m->load = value;
351             if (!(m->control & R_CONTROL_MODE_MASK)) {
352                 /* In free-running mode there is no limit */
353                 break;
354             }
355             if (!(m->control & R_CONTROL_SIZE_MASK)) {
356                 value &= 0xffff;
357             }
358             ptimer_set_limit(m->timer, value, 0);
359             break;
360         case A_TIMER1CONTROL:
361             cmsdk_dualtimermod_write_control(m, value);
362             cmsdk_apb_dualtimer_update(s);
363             break;
364         case A_TIMER1INTCLR:
365             m->intstatus = 0;
366             cmsdk_apb_dualtimer_update(s);
367             break;
368         default:
369             goto bad_offset;
370         }
371     }
372 }
373 
374 static const MemoryRegionOps cmsdk_apb_dualtimer_ops = {
375     .read = cmsdk_apb_dualtimer_read,
376     .write = cmsdk_apb_dualtimer_write,
377     .endianness = DEVICE_LITTLE_ENDIAN,
378     /* byte/halfword accesses are just zero-padded on reads and writes */
379     .impl.min_access_size = 4,
380     .impl.max_access_size = 4,
381     .valid.min_access_size = 1,
382     .valid.max_access_size = 4,
383 };
384 
385 static void cmsdk_dualtimermod_tick(void *opaque)
386 {
387     CMSDKAPBDualTimerModule *m = opaque;
388 
389     m->intstatus = 1;
390     cmsdk_apb_dualtimer_update(m->parent);
391 }
392 
393 static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m)
394 {
395     m->control = R_CONTROL_INTEN_MASK;
396     m->intstatus = 0;
397     m->load = 0;
398     m->value = 0xffffffff;
399     ptimer_stop(m->timer);
400     /*
401      * We start in free-running mode, with VALUE at 0xffffffff, and
402      * in 16-bit counter mode. This means that the ptimer count and
403      * limit must both be set to 0xffff, so we wrap at 16 bits.
404      */
405     ptimer_set_limit(m->timer, 0xffff, 1);
406     ptimer_set_freq(m->timer, m->parent->pclk_frq);
407 }
408 
409 static void cmsdk_apb_dualtimer_reset(DeviceState *dev)
410 {
411     CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
412     int i;
413 
414     trace_cmsdk_apb_dualtimer_reset();
415 
416     for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
417         cmsdk_dualtimermod_reset(&s->timermod[i]);
418     }
419     s->timeritcr = 0;
420     s->timeritop = 0;
421 }
422 
423 static void cmsdk_apb_dualtimer_init(Object *obj)
424 {
425     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
426     CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(obj);
427     int i;
428 
429     memory_region_init_io(&s->iomem, obj, &cmsdk_apb_dualtimer_ops,
430                           s, "cmsdk-apb-dualtimer", 0x1000);
431     sysbus_init_mmio(sbd, &s->iomem);
432     sysbus_init_irq(sbd, &s->timerintc);
433 
434     for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
435         sysbus_init_irq(sbd, &s->timermod[i].timerint);
436     }
437 }
438 
439 static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
440 {
441     CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
442     int i;
443 
444     if (s->pclk_frq == 0) {
445         error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
446         return;
447     }
448 
449     for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
450         CMSDKAPBDualTimerModule *m = &s->timermod[i];
451         QEMUBH *bh = qemu_bh_new(cmsdk_dualtimermod_tick, m);
452 
453         m->parent = s;
454         m->timer = ptimer_init(bh,
455                                PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
456                                PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
457                                PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
458                                PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
459     }
460 }
461 
462 static const VMStateDescription cmsdk_dualtimermod_vmstate = {
463     .name = "cmsdk-apb-dualtimer-module",
464     .version_id = 1,
465     .minimum_version_id = 1,
466     .fields = (VMStateField[]) {
467         VMSTATE_PTIMER(timer, CMSDKAPBDualTimerModule),
468         VMSTATE_UINT32(load, CMSDKAPBDualTimerModule),
469         VMSTATE_UINT32(value, CMSDKAPBDualTimerModule),
470         VMSTATE_UINT32(control, CMSDKAPBDualTimerModule),
471         VMSTATE_UINT32(intstatus, CMSDKAPBDualTimerModule),
472         VMSTATE_END_OF_LIST()
473     }
474 };
475 
476 static const VMStateDescription cmsdk_apb_dualtimer_vmstate = {
477     .name = "cmsdk-apb-dualtimer",
478     .version_id = 1,
479     .minimum_version_id = 1,
480     .fields = (VMStateField[]) {
481         VMSTATE_STRUCT_ARRAY(timermod, CMSDKAPBDualTimer,
482                              CMSDK_APB_DUALTIMER_NUM_MODULES,
483                              1, cmsdk_dualtimermod_vmstate,
484                              CMSDKAPBDualTimerModule),
485         VMSTATE_UINT32(timeritcr, CMSDKAPBDualTimer),
486         VMSTATE_UINT32(timeritop, CMSDKAPBDualTimer),
487         VMSTATE_END_OF_LIST()
488     }
489 };
490 
491 static Property cmsdk_apb_dualtimer_properties[] = {
492     DEFINE_PROP_UINT32("pclk-frq", CMSDKAPBDualTimer, pclk_frq, 0),
493     DEFINE_PROP_END_OF_LIST(),
494 };
495 
496 static void cmsdk_apb_dualtimer_class_init(ObjectClass *klass, void *data)
497 {
498     DeviceClass *dc = DEVICE_CLASS(klass);
499 
500     dc->realize = cmsdk_apb_dualtimer_realize;
501     dc->vmsd = &cmsdk_apb_dualtimer_vmstate;
502     dc->reset = cmsdk_apb_dualtimer_reset;
503     dc->props = cmsdk_apb_dualtimer_properties;
504 }
505 
506 static const TypeInfo cmsdk_apb_dualtimer_info = {
507     .name = TYPE_CMSDK_APB_DUALTIMER,
508     .parent = TYPE_SYS_BUS_DEVICE,
509     .instance_size = sizeof(CMSDKAPBDualTimer),
510     .instance_init = cmsdk_apb_dualtimer_init,
511     .class_init = cmsdk_apb_dualtimer_class_init,
512 };
513 
514 static void cmsdk_apb_dualtimer_register_types(void)
515 {
516     type_register_static(&cmsdk_apb_dualtimer_info);
517 }
518 
519 type_init(cmsdk_apb_dualtimer_register_types);
520