xref: /openbmc/qemu/hw/timer/cmsdk-apb-dualtimer.c (revision ba324b3f)
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