xref: /openbmc/qemu/hw/timer/aspeed_timer.c (revision b917da4c)
1 /*
2  * ASPEED AST2400 Timer
3  *
4  * Andrew Jeffery <andrew@aj.id.au>
5  *
6  * Copyright (C) 2016 IBM Corp.
7  *
8  * This code is licensed under the GPL version 2 or later.  See
9  * the COPYING file in the top-level directory.
10  */
11 
12 #include "qemu/osdep.h"
13 #include "hw/ptimer.h"
14 #include "hw/sysbus.h"
15 #include "hw/timer/aspeed_timer.h"
16 #include "qemu-common.h"
17 #include "qemu/bitops.h"
18 #include "qemu/main-loop.h"
19 #include "qemu/timer.h"
20 #include "trace.h"
21 
22 #define TIMER_NR_REGS 4
23 
24 #define TIMER_CTRL_BITS 4
25 #define TIMER_CTRL_MASK ((1 << TIMER_CTRL_BITS) - 1)
26 
27 #define TIMER_CLOCK_USE_EXT true
28 #define TIMER_CLOCK_EXT_HZ 1000000
29 #define TIMER_CLOCK_USE_APB false
30 #define TIMER_CLOCK_APB_HZ 24000000
31 
32 #define TIMER_REG_STATUS 0
33 #define TIMER_REG_RELOAD 1
34 #define TIMER_REG_MATCH_FIRST 2
35 #define TIMER_REG_MATCH_SECOND 3
36 
37 #define TIMER_FIRST_CAP_PULSE 4
38 
39 enum timer_ctrl_op {
40     op_enable = 0,
41     op_external_clock,
42     op_overflow_interrupt,
43     op_pulse_enable
44 };
45 
46 /**
47  * Avoid mutual references between AspeedTimerCtrlState and AspeedTimer
48  * structs, as it's a waste of memory. The ptimer BH callback needs to know
49  * whether a specific AspeedTimer is enabled, but this information is held in
50  * AspeedTimerCtrlState. So, provide a helper to hoist ourselves from an
51  * arbitrary AspeedTimer to AspeedTimerCtrlState.
52  */
53 static inline AspeedTimerCtrlState *timer_to_ctrl(AspeedTimer *t)
54 {
55     const AspeedTimer (*timers)[] = (void *)t - (t->id * sizeof(*t));
56     return container_of(timers, AspeedTimerCtrlState, timers);
57 }
58 
59 static inline bool timer_ctrl_status(AspeedTimer *t, enum timer_ctrl_op op)
60 {
61     return !!(timer_to_ctrl(t)->ctrl & BIT(t->id * TIMER_CTRL_BITS + op));
62 }
63 
64 static inline bool timer_enabled(AspeedTimer *t)
65 {
66     return timer_ctrl_status(t, op_enable);
67 }
68 
69 static inline bool timer_overflow_interrupt(AspeedTimer *t)
70 {
71     return timer_ctrl_status(t, op_overflow_interrupt);
72 }
73 
74 static inline bool timer_can_pulse(AspeedTimer *t)
75 {
76     return t->id >= TIMER_FIRST_CAP_PULSE;
77 }
78 
79 static void aspeed_timer_expire(void *opaque)
80 {
81     AspeedTimer *t = opaque;
82 
83     /* Only support interrupts on match values of zero for the moment - this is
84      * sufficient to boot an aspeed_defconfig Linux kernel.
85      *
86      * TODO: matching on arbitrary values (see e.g. hw/timer/a9gtimer.c)
87      */
88     bool match = !(t->match[0] && t->match[1]);
89     bool interrupt = timer_overflow_interrupt(t) || match;
90     if (timer_enabled(t) && interrupt) {
91         t->level = !t->level;
92         qemu_set_irq(t->irq, t->level);
93     }
94 }
95 
96 static uint64_t aspeed_timer_get_value(AspeedTimer *t, int reg)
97 {
98     uint64_t value;
99 
100     switch (reg) {
101     case TIMER_REG_STATUS:
102         value = ptimer_get_count(t->timer);
103         break;
104     case TIMER_REG_RELOAD:
105         value = t->reload;
106         break;
107     case TIMER_REG_MATCH_FIRST:
108     case TIMER_REG_MATCH_SECOND:
109         value = t->match[reg - 2];
110         break;
111     default:
112         qemu_log_mask(LOG_UNIMP, "%s: Programming error: unexpected reg: %d\n",
113                       __func__, reg);
114         value = 0;
115         break;
116     }
117     return value;
118 }
119 
120 static uint64_t aspeed_timer_read(void *opaque, hwaddr offset, unsigned size)
121 {
122     AspeedTimerCtrlState *s = opaque;
123     const int reg = (offset & 0xf) / 4;
124     uint64_t value;
125 
126     switch (offset) {
127     case 0x30: /* Control Register */
128         value = s->ctrl;
129         break;
130     case 0x34: /* Control Register 2 */
131         value = s->ctrl2;
132         break;
133     case 0x00 ... 0x2c: /* Timers 1 - 4 */
134         value = aspeed_timer_get_value(&s->timers[(offset >> 4)], reg);
135         break;
136     case 0x40 ... 0x8c: /* Timers 5 - 8 */
137         value = aspeed_timer_get_value(&s->timers[(offset >> 4) - 1], reg);
138         break;
139     /* Illegal */
140     case 0x38:
141     case 0x3C:
142     default:
143         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
144                 __func__, offset);
145         value = 0;
146         break;
147     }
148     trace_aspeed_timer_read(offset, size, value);
149     return value;
150 }
151 
152 static void aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg,
153                                    uint32_t value)
154 {
155     AspeedTimer *t;
156 
157     trace_aspeed_timer_set_value(timer, reg, value);
158     t = &s->timers[timer];
159     switch (reg) {
160     case TIMER_REG_STATUS:
161         if (timer_enabled(t)) {
162             ptimer_set_count(t->timer, value);
163         }
164         break;
165     case TIMER_REG_RELOAD:
166         t->reload = value;
167         ptimer_set_limit(t->timer, value, 1);
168         break;
169     case TIMER_REG_MATCH_FIRST:
170     case TIMER_REG_MATCH_SECOND:
171         if (value) {
172             /* Non-zero match values are unsupported. As such an interrupt will
173              * always be triggered when the timer reaches zero even if the
174              * overflow interrupt control bit is clear.
175              */
176             qemu_log_mask(LOG_UNIMP, "%s: Match value unsupported by device: "
177                     "0x%" PRIx32 "\n", __func__, value);
178         } else {
179             t->match[reg - 2] = value;
180         }
181         break;
182     default:
183         qemu_log_mask(LOG_UNIMP, "%s: Programming error: unexpected reg: %d\n",
184                       __func__, reg);
185         break;
186     }
187 }
188 
189 /* Control register operations are broken out into helpers that can be
190  * explictly called on aspeed_timer_reset(), but also from
191  * aspeed_timer_ctrl_op().
192  */
193 
194 static void aspeed_timer_ctrl_enable(AspeedTimer *t, bool enable)
195 {
196     trace_aspeed_timer_ctrl_enable(t->id, enable);
197     if (enable) {
198         ptimer_run(t->timer, 0);
199     } else {
200         ptimer_stop(t->timer);
201         ptimer_set_limit(t->timer, t->reload, 1);
202     }
203 }
204 
205 static void aspeed_timer_ctrl_external_clock(AspeedTimer *t, bool enable)
206 {
207     trace_aspeed_timer_ctrl_external_clock(t->id, enable);
208     if (enable) {
209         ptimer_set_freq(t->timer, TIMER_CLOCK_EXT_HZ);
210     } else {
211         ptimer_set_freq(t->timer, TIMER_CLOCK_APB_HZ);
212     }
213 }
214 
215 static void aspeed_timer_ctrl_overflow_interrupt(AspeedTimer *t, bool enable)
216 {
217     trace_aspeed_timer_ctrl_overflow_interrupt(t->id, enable);
218 }
219 
220 static void aspeed_timer_ctrl_pulse_enable(AspeedTimer *t, bool enable)
221 {
222     if (timer_can_pulse(t)) {
223         trace_aspeed_timer_ctrl_pulse_enable(t->id, enable);
224     } else {
225         qemu_log_mask(LOG_GUEST_ERROR,
226                 "%s: Timer does not support pulse mode\n", __func__);
227     }
228 }
229 
230 /**
231  * Given the actions are fixed in number and completely described in helper
232  * functions, dispatch with a lookup table rather than manage control flow with
233  * a switch statement.
234  */
235 static void (*const ctrl_ops[])(AspeedTimer *, bool) = {
236     [op_enable] = aspeed_timer_ctrl_enable,
237     [op_external_clock] = aspeed_timer_ctrl_external_clock,
238     [op_overflow_interrupt] = aspeed_timer_ctrl_overflow_interrupt,
239     [op_pulse_enable] = aspeed_timer_ctrl_pulse_enable,
240 };
241 
242 /**
243  * Conditionally affect changes chosen by a timer's control bit.
244  *
245  * The aspeed_timer_ctrl_op() interface is convenient for the
246  * aspeed_timer_set_ctrl() function as the "no change" early exit can be
247  * calculated for all operations, which cleans up the caller code. However the
248  * interface isn't convenient for the reset function where we want to enter a
249  * specific state without artificially constructing old and new values that
250  * will fall through the change guard (and motivates extracting the actions
251  * out to helper functions).
252  *
253  * @t: The timer to manipulate
254  * @op: The type of operation to be performed
255  * @old: The old state of the timer's control bits
256  * @new: The incoming state for the timer's control bits
257  */
258 static void aspeed_timer_ctrl_op(AspeedTimer *t, enum timer_ctrl_op op,
259                                  uint8_t old, uint8_t new)
260 {
261     const uint8_t mask = BIT(op);
262     const bool enable = !!(new & mask);
263     const bool changed = ((old ^ new) & mask);
264     if (!changed) {
265         return;
266     }
267     ctrl_ops[op](t, enable);
268 }
269 
270 static void aspeed_timer_set_ctrl(AspeedTimerCtrlState *s, uint32_t reg)
271 {
272     int i;
273     int shift;
274     uint8_t t_old, t_new;
275     AspeedTimer *t;
276     const uint8_t enable_mask = BIT(op_enable);
277 
278     /* Handle a dependency between the 'enable' and remaining three
279      * configuration bits - i.e. if more than one bit in the control set has
280      * changed, including the 'enable' bit, then we want either disable the
281      * timer and perform configuration, or perform configuration and then
282      * enable the timer
283      */
284     for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
285         t = &s->timers[i];
286         shift = (i * TIMER_CTRL_BITS);
287         t_old = (s->ctrl >> shift) & TIMER_CTRL_MASK;
288         t_new = (reg >> shift) & TIMER_CTRL_MASK;
289 
290         /* If we are disabling, do so first */
291         if ((t_old & enable_mask) && !(t_new & enable_mask)) {
292             aspeed_timer_ctrl_enable(t, false);
293         }
294         aspeed_timer_ctrl_op(t, op_external_clock, t_old, t_new);
295         aspeed_timer_ctrl_op(t, op_overflow_interrupt, t_old, t_new);
296         aspeed_timer_ctrl_op(t, op_pulse_enable, t_old, t_new);
297         /* If we are enabling, do so last */
298         if (!(t_old & enable_mask) && (t_new & enable_mask)) {
299             aspeed_timer_ctrl_enable(t, true);
300         }
301     }
302     s->ctrl = reg;
303 }
304 
305 static void aspeed_timer_set_ctrl2(AspeedTimerCtrlState *s, uint32_t value)
306 {
307     trace_aspeed_timer_set_ctrl2(value);
308 }
309 
310 static void aspeed_timer_write(void *opaque, hwaddr offset, uint64_t value,
311                                unsigned size)
312 {
313     const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF);
314     const int reg = (offset & 0xf) / 4;
315     AspeedTimerCtrlState *s = opaque;
316 
317     switch (offset) {
318     /* Control Registers */
319     case 0x30:
320         aspeed_timer_set_ctrl(s, tv);
321         break;
322     case 0x34:
323         aspeed_timer_set_ctrl2(s, tv);
324         break;
325     /* Timer Registers */
326     case 0x00 ... 0x2c:
327         aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS), reg, tv);
328         break;
329     case 0x40 ... 0x8c:
330         aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS) - 1, reg, tv);
331         break;
332     /* Illegal */
333     case 0x38:
334     case 0x3C:
335     default:
336         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
337                 __func__, offset);
338         break;
339     }
340 }
341 
342 static const MemoryRegionOps aspeed_timer_ops = {
343     .read = aspeed_timer_read,
344     .write = aspeed_timer_write,
345     .endianness = DEVICE_LITTLE_ENDIAN,
346     .valid.min_access_size = 4,
347     .valid.max_access_size = 4,
348     .valid.unaligned = false,
349 };
350 
351 static void aspeed_init_one_timer(AspeedTimerCtrlState *s, uint8_t id)
352 {
353     QEMUBH *bh;
354     AspeedTimer *t = &s->timers[id];
355 
356     t->id = id;
357     bh = qemu_bh_new(aspeed_timer_expire, t);
358     t->timer = ptimer_init(bh);
359 }
360 
361 static void aspeed_timer_realize(DeviceState *dev, Error **errp)
362 {
363     int i;
364     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
365     AspeedTimerCtrlState *s = ASPEED_TIMER(dev);
366 
367     for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
368         aspeed_init_one_timer(s, i);
369         sysbus_init_irq(sbd, &s->timers[i].irq);
370     }
371     memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_timer_ops, s,
372                           TYPE_ASPEED_TIMER, 0x1000);
373     sysbus_init_mmio(sbd, &s->iomem);
374 }
375 
376 static void aspeed_timer_reset(DeviceState *dev)
377 {
378     int i;
379     AspeedTimerCtrlState *s = ASPEED_TIMER(dev);
380 
381     for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
382         AspeedTimer *t = &s->timers[i];
383         /* Explictly call helpers to avoid any conditional behaviour through
384          * aspeed_timer_set_ctrl().
385          */
386         aspeed_timer_ctrl_enable(t, false);
387         aspeed_timer_ctrl_external_clock(t, TIMER_CLOCK_USE_APB);
388         aspeed_timer_ctrl_overflow_interrupt(t, false);
389         aspeed_timer_ctrl_pulse_enable(t, false);
390         t->level = 0;
391         t->reload = 0;
392         t->match[0] = 0;
393         t->match[1] = 0;
394     }
395     s->ctrl = 0;
396     s->ctrl2 = 0;
397 }
398 
399 static const VMStateDescription vmstate_aspeed_timer = {
400     .name = "aspeed.timer",
401     .version_id = 1,
402     .minimum_version_id = 1,
403     .fields = (VMStateField[]) {
404         VMSTATE_UINT8(id, AspeedTimer),
405         VMSTATE_INT32(level, AspeedTimer),
406         VMSTATE_PTIMER(timer, AspeedTimer),
407         VMSTATE_UINT32(reload, AspeedTimer),
408         VMSTATE_UINT32_ARRAY(match, AspeedTimer, 2),
409         VMSTATE_END_OF_LIST()
410     }
411 };
412 
413 static const VMStateDescription vmstate_aspeed_timer_state = {
414     .name = "aspeed.timerctrl",
415     .version_id = 1,
416     .minimum_version_id = 1,
417     .fields = (VMStateField[]) {
418         VMSTATE_UINT32(ctrl, AspeedTimerCtrlState),
419         VMSTATE_UINT32(ctrl2, AspeedTimerCtrlState),
420         VMSTATE_STRUCT_ARRAY(timers, AspeedTimerCtrlState,
421                              ASPEED_TIMER_NR_TIMERS, 1, vmstate_aspeed_timer,
422                              AspeedTimer),
423         VMSTATE_END_OF_LIST()
424     }
425 };
426 
427 static void timer_class_init(ObjectClass *klass, void *data)
428 {
429     DeviceClass *dc = DEVICE_CLASS(klass);
430 
431     dc->realize = aspeed_timer_realize;
432     dc->reset = aspeed_timer_reset;
433     dc->desc = "ASPEED Timer";
434     dc->vmsd = &vmstate_aspeed_timer_state;
435 }
436 
437 static const TypeInfo aspeed_timer_info = {
438     .name = TYPE_ASPEED_TIMER,
439     .parent = TYPE_SYS_BUS_DEVICE,
440     .instance_size = sizeof(AspeedTimerCtrlState),
441     .class_init = timer_class_init,
442 };
443 
444 static void aspeed_timer_register_types(void)
445 {
446     type_register_static(&aspeed_timer_info);
447 }
448 
449 type_init(aspeed_timer_register_types)
450