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 "qapi/error.h"
14#include "hw/irq.h"
15#include "hw/sysbus.h"
16#include "hw/timer/aspeed_timer.h"
17#include "migration/vmstate.h"
18#include "qemu/bitops.h"
19#include "qemu/timer.h"
20#include "qemu/log.h"
21#include "qemu/module.h"
22#include "trace.h"
23
24#define TIMER_NR_REGS 4
25
26#define TIMER_CTRL_BITS 4
27#define TIMER_CTRL_MASK ((1 << TIMER_CTRL_BITS) - 1)
28
29#define TIMER_CLOCK_USE_EXT true
30#define TIMER_CLOCK_EXT_HZ 1000000
31#define TIMER_CLOCK_USE_APB false
32
33#define TIMER_REG_STATUS 0
34#define TIMER_REG_RELOAD 1
35#define TIMER_REG_MATCH_FIRST 2
36#define TIMER_REG_MATCH_SECOND 3
37
38#define TIMER_FIRST_CAP_PULSE 4
39
40enum timer_ctrl_op {
41 op_enable = 0,
42 op_external_clock,
43 op_overflow_interrupt,
44 op_pulse_enable
45};
46
47/*
48 * Minimum value of the reload register to filter out short period
49 * timers which have a noticeable impact in emulation. 5us should be
50 * enough, use 20us for "safety".
51 */
52#define TIMER_MIN_NS (20 * SCALE_US)
53
54/**
55 * Avoid mutual references between AspeedTimerCtrlState and AspeedTimer
56 * structs, as it's a waste of memory. The ptimer BH callback needs to know
57 * whether a specific AspeedTimer is enabled, but this information is held in
58 * AspeedTimerCtrlState. So, provide a helper to hoist ourselves from an
59 * arbitrary AspeedTimer to AspeedTimerCtrlState.
60 */
61static inline AspeedTimerCtrlState *timer_to_ctrl(AspeedTimer *t)
62{
63 const AspeedTimer (*timers)[] = (void *)t - (t->id * sizeof(*t));
64 return container_of(timers, AspeedTimerCtrlState, timers);
65}
66
67static inline bool timer_ctrl_status(AspeedTimer *t, enum timer_ctrl_op op)
68{
69 return !!(timer_to_ctrl(t)->ctrl & BIT(t->id * TIMER_CTRL_BITS + op));
70}
71
72static inline bool timer_enabled(AspeedTimer *t)
73{
74 return timer_ctrl_status(t, op_enable);
75}
76
77static inline bool timer_overflow_interrupt(AspeedTimer *t)
78{
79 return timer_ctrl_status(t, op_overflow_interrupt);
80}
81
82static inline bool timer_can_pulse(AspeedTimer *t)
83{
84 return t->id >= TIMER_FIRST_CAP_PULSE;
85}
86
87static inline bool timer_external_clock(AspeedTimer *t)
88{
89 return timer_ctrl_status(t, op_external_clock);
90}
91
92static inline uint32_t calculate_rate(struct AspeedTimer *t)
93{
94 AspeedTimerCtrlState *s = timer_to_ctrl(t);
95
96 return timer_external_clock(t) ? TIMER_CLOCK_EXT_HZ : s->scu->apb_freq;
97}
98
99static inline uint32_t calculate_ticks(struct AspeedTimer *t, uint64_t now_ns)
100{
101 uint64_t delta_ns = now_ns - MIN(now_ns, t->start);
102 uint32_t rate = calculate_rate(t);
103 uint64_t ticks = muldiv64(delta_ns, rate, NANOSECONDS_PER_SECOND);
104
105 return t->reload - MIN(t->reload, ticks);
106}
107
108static uint32_t calculate_min_ticks(AspeedTimer *t, uint32_t value)
109{
110 uint32_t rate = calculate_rate(t);
111 uint32_t min_ticks = muldiv64(TIMER_MIN_NS, rate, NANOSECONDS_PER_SECOND);
112
113 return value < min_ticks ? min_ticks : value;
114}
115
116static inline uint64_t calculate_time(struct AspeedTimer *t, uint32_t ticks)
117{
118 uint64_t delta_ns;
119 uint64_t delta_ticks;
120
121 delta_ticks = t->reload - MIN(t->reload, ticks);
122 delta_ns = muldiv64(delta_ticks, NANOSECONDS_PER_SECOND, calculate_rate(t));
123
124 return t->start + delta_ns;
125}
126
127static inline uint32_t calculate_match(struct AspeedTimer *t, int i)
128{
129 return t->match[i] < t->reload ? t->match[i] : 0;
130}
131
132static uint64_t calculate_next(struct AspeedTimer *t)
133{
134 uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
135 uint64_t next;
136
137 /*
138 * We don't know the relationship between the values in the match
139 * registers, so sort using MAX/MIN/zero. We sort in that order as
140 * the timer counts down to zero.
141 */
142
143 next = calculate_time(t, MAX(calculate_match(t, 0), calculate_match(t, 1)));
144 if (now < next) {
145 return next;
146 }
147
148 next = calculate_time(t, MIN(calculate_match(t, 0), calculate_match(t, 1)));
149 if (now < next) {
150 return next;
151 }
152
153 next = calculate_time(t, 0);
154 if (now < next) {
155 return next;
156 }
157
158 /* We've missed all deadlines, fire interrupt and try again */
159 timer_del(&t->timer);
160
161 if (timer_overflow_interrupt(t)) {
162 t->level = !t->level;
163 qemu_set_irq(t->irq, t->level);
164 }
165
166 next = MAX(MAX(calculate_match(t, 0), calculate_match(t, 1)), 0);
167 t->start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
168
169 return calculate_time(t, next);
170}
171
172static void aspeed_timer_mod(AspeedTimer *t)
173{
174 uint64_t next = calculate_next(t);
175 if (next) {
176 timer_mod(&t->timer, next);
177 }
178}
179
180static void aspeed_timer_expire(void *opaque)
181{
182 AspeedTimer *t = opaque;
183 bool interrupt = false;
184 uint32_t ticks;
185
186 if (!timer_enabled(t)) {
187 return;
188 }
189
190 ticks = calculate_ticks(t, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
191
192 if (!ticks) {
193 interrupt = timer_overflow_interrupt(t) || !t->match[0] || !t->match[1];
194 } else if (ticks <= MIN(t->match[0], t->match[1])) {
195 interrupt = true;
196 } else if (ticks <= MAX(t->match[0], t->match[1])) {
197 interrupt = true;
198 }
199
200 if (interrupt) {
201 t->level = !t->level;
202 qemu_set_irq(t->irq, t->level);
203 }
204
205 aspeed_timer_mod(t);
206}
207
208static uint64_t aspeed_timer_get_value(AspeedTimer *t, int reg)
209{
210 uint64_t value;
211
212 switch (reg) {
213 case TIMER_REG_STATUS:
214 if (timer_enabled(t)) {
215 value = calculate_ticks(t, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
216 } else {
217 value = t->reload;
218 }
219 break;
220 case TIMER_REG_RELOAD:
221 value = t->reload;
222 break;
223 case TIMER_REG_MATCH_FIRST:
224 case TIMER_REG_MATCH_SECOND:
225 value = t->match[reg - 2];
226 break;
227 default:
228 qemu_log_mask(LOG_UNIMP, "%s: Programming error: unexpected reg: %d\n",
229 __func__, reg);
230 value = 0;
231 break;
232 }
233 return value;
234}
235
236static uint64_t aspeed_timer_read(void *opaque, hwaddr offset, unsigned size)
237{
238 AspeedTimerCtrlState *s = opaque;
239 const int reg = (offset & 0xf) / 4;
240 uint64_t value;
241
242 switch (offset) {
243 case 0x30: /* Control Register */
244 value = s->ctrl;
245 break;
246 case 0x34: /* Control Register 2 */
247 value = s->ctrl2;
248 break;
249 case 0x00 ... 0x2c: /* Timers 1 - 4 */
250 value = aspeed_timer_get_value(&s->timers[(offset >> 4)], reg);
251 break;
252 case 0x40 ... 0x8c: /* Timers 5 - 8 */
253 value = aspeed_timer_get_value(&s->timers[(offset >> 4) - 1], reg);
254 break;
255 /* Illegal */
256 case 0x38:
257 case 0x3C:
258 default:
259 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
260 __func__, offset);
261 value = 0;
262 break;
263 }
264 trace_aspeed_timer_read(offset, size, value);
265 return value;
266}
267
268static void aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg,
269 uint32_t value)
270{
271 AspeedTimer *t;
272 uint32_t old_reload;
273
274 trace_aspeed_timer_set_value(timer, reg, value);
275 t = &s->timers[timer];
276 switch (reg) {
277 case TIMER_REG_RELOAD:
278 old_reload = t->reload;
279 t->reload = calculate_min_ticks(t, value);
280
281 /* If the reload value was not previously set, or zero, and
282 * the current value is valid, try to start the timer if it is
283 * enabled.
284 */
285 if (old_reload || !t->reload) {
286 break;
287 }
288
289 case TIMER_REG_STATUS:
290 if (timer_enabled(t)) {
291 uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
292 int64_t delta = (int64_t) value - (int64_t) calculate_ticks(t, now);
293 uint32_t rate = calculate_rate(t);
294
295 if (delta >= 0) {
296 t->start += muldiv64(delta, NANOSECONDS_PER_SECOND, rate);
297 } else {
298 t->start -= muldiv64(-delta, NANOSECONDS_PER_SECOND, rate);
299 }
300 aspeed_timer_mod(t);
301 }
302 break;
303 case TIMER_REG_MATCH_FIRST:
304 case TIMER_REG_MATCH_SECOND:
305 t->match[reg - 2] = value;
306 if (timer_enabled(t)) {
307 aspeed_timer_mod(t);
308 }
309 break;
310 default:
311 qemu_log_mask(LOG_UNIMP, "%s: Programming error: unexpected reg: %d\n",
312 __func__, reg);
313 break;
314 }
315}
316
317/* Control register operations are broken out into helpers that can be
318 * explicitly called on aspeed_timer_reset(), but also from
319 * aspeed_timer_ctrl_op().
320 */
321
322static void aspeed_timer_ctrl_enable(AspeedTimer *t, bool enable)
323{
324 trace_aspeed_timer_ctrl_enable(t->id, enable);
325 if (enable) {
326 t->start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
327 aspeed_timer_mod(t);
328 } else {
329 timer_del(&t->timer);
330 }
331}
332
333static void aspeed_timer_ctrl_external_clock(AspeedTimer *t, bool enable)
334{
335 trace_aspeed_timer_ctrl_external_clock(t->id, enable);
336}
337
338static void aspeed_timer_ctrl_overflow_interrupt(AspeedTimer *t, bool enable)
339{
340 trace_aspeed_timer_ctrl_overflow_interrupt(t->id, enable);
341}
342
343static void aspeed_timer_ctrl_pulse_enable(AspeedTimer *t, bool enable)
344{
345 if (timer_can_pulse(t)) {
346 trace_aspeed_timer_ctrl_pulse_enable(t->id, enable);
347 } else {
348 qemu_log_mask(LOG_GUEST_ERROR,
349 "%s: Timer does not support pulse mode\n", __func__);
350 }
351}
352
353/**
354 * Given the actions are fixed in number and completely described in helper
355 * functions, dispatch with a lookup table rather than manage control flow with
356 * a switch statement.
357 */
358static void (*const ctrl_ops[])(AspeedTimer *, bool) = {
359 [op_enable] = aspeed_timer_ctrl_enable,
360 [op_external_clock] = aspeed_timer_ctrl_external_clock,
361 [op_overflow_interrupt] = aspeed_timer_ctrl_overflow_interrupt,
362 [op_pulse_enable] = aspeed_timer_ctrl_pulse_enable,
363};
364
365/**
366 * Conditionally affect changes chosen by a timer's control bit.
367 *
368 * The aspeed_timer_ctrl_op() interface is convenient for the
369 * aspeed_timer_set_ctrl() function as the "no change" early exit can be
370 * calculated for all operations, which cleans up the caller code. However the
371 * interface isn't convenient for the reset function where we want to enter a
372 * specific state without artificially constructing old and new values that
373 * will fall through the change guard (and motivates extracting the actions
374 * out to helper functions).
375 *
376 * @t: The timer to manipulate
377 * @op: The type of operation to be performed
378 * @old: The old state of the timer's control bits
379 * @new: The incoming state for the timer's control bits
380 */
381static void aspeed_timer_ctrl_op(AspeedTimer *t, enum timer_ctrl_op op,
382 uint8_t old, uint8_t new)
383{
384 const uint8_t mask = BIT(op);
385 const bool enable = !!(new & mask);
386 const bool changed = ((old ^ new) & mask);
387 if (!changed) {
388 return;
389 }
390 ctrl_ops[op](t, enable);
391}
392
393static void aspeed_timer_set_ctrl(AspeedTimerCtrlState *s, uint32_t reg)
394{
395 int i;
396 int shift;
397 uint8_t t_old, t_new;
398 AspeedTimer *t;
399 const uint8_t enable_mask = BIT(op_enable);
400
401 /* Handle a dependency between the 'enable' and remaining three
402 * configuration bits - i.e. if more than one bit in the control set has
403 * changed, including the 'enable' bit, then we want either disable the
404 * timer and perform configuration, or perform configuration and then
405 * enable the timer
406 */
407 for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
408 t = &s->timers[i];
409 shift = (i * TIMER_CTRL_BITS);
410 t_old = (s->ctrl >> shift) & TIMER_CTRL_MASK;
411 t_new = (reg >> shift) & TIMER_CTRL_MASK;
412
413 /* If we are disabling, do so first */
414 if ((t_old & enable_mask) && !(t_new & enable_mask)) {
415 aspeed_timer_ctrl_enable(t, false);
416 }
417 aspeed_timer_ctrl_op(t, op_external_clock, t_old, t_new);
418 aspeed_timer_ctrl_op(t, op_overflow_interrupt, t_old, t_new);
419 aspeed_timer_ctrl_op(t, op_pulse_enable, t_old, t_new);
420 /* If we are enabling, do so last */
421 if (!(t_old & enable_mask) && (t_new & enable_mask)) {
422 aspeed_timer_ctrl_enable(t, true);
423 }
424 }
425 s->ctrl = reg;
426}
427
428static void aspeed_timer_set_ctrl2(AspeedTimerCtrlState *s, uint32_t value)
429{
430 trace_aspeed_timer_set_ctrl2(value);
431}
432
433static void aspeed_timer_write(void *opaque, hwaddr offset, uint64_t value,
434 unsigned size)
435{
436 const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF);
437 const int reg = (offset & 0xf) / 4;
438 AspeedTimerCtrlState *s = opaque;
439
440 switch (offset) {
441 /* Control Registers */
442 case 0x30:
443 aspeed_timer_set_ctrl(s, tv);
444 break;
445 case 0x34:
446 aspeed_timer_set_ctrl2(s, tv);
447 break;
448 /* Timer Registers */
449 case 0x00 ... 0x2c:
450 aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS), reg, tv);
451 break;
452 case 0x40 ... 0x8c:
453 aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS) - 1, reg, tv);
454 break;
455 /* Illegal */
456 case 0x38:
457 case 0x3C:
458 default:
459 qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
460 __func__, offset);
461 break;
462 }
463}
464
465static const MemoryRegionOps aspeed_timer_ops = {
466 .read = aspeed_timer_read,
467 .write = aspeed_timer_write,
468 .endianness = DEVICE_LITTLE_ENDIAN,
469 .valid.min_access_size = 4,
470 .valid.max_access_size = 4,
471 .valid.unaligned = false,
472};
473
474static void aspeed_init_one_timer(AspeedTimerCtrlState *s, uint8_t id)
475{
476 AspeedTimer *t = &s->timers[id];
477
478 t->id = id;
479 timer_init_ns(&t->timer, QEMU_CLOCK_VIRTUAL, aspeed_timer_expire, t);
480}
481
482static void aspeed_timer_realize(DeviceState *dev, Error **errp)
483{
484 int i;
485 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
486 AspeedTimerCtrlState *s = ASPEED_TIMER(dev);
487 Object *obj;
488 Error *err = NULL;
489
490 obj = object_property_get_link(OBJECT(dev), "scu", &err);
491 if (!obj) {
492 error_propagate_prepend(errp, err, "required link 'scu' not found: ");
493 return;
494 }
495 s->scu = ASPEED_SCU(obj);
496
497 for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
498 aspeed_init_one_timer(s, i);
499 sysbus_init_irq(sbd, &s->timers[i].irq);
500 }
501 memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_timer_ops, s,
502 TYPE_ASPEED_TIMER, 0x1000);
503 sysbus_init_mmio(sbd, &s->iomem);
504}
505
506static void aspeed_timer_reset(DeviceState *dev)
507{
508 int i;
509 AspeedTimerCtrlState *s = ASPEED_TIMER(dev);
510
511 for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
512 AspeedTimer *t = &s->timers[i];
513 /* Explicitly call helpers to avoid any conditional behaviour through
514 * aspeed_timer_set_ctrl().
515 */
516 aspeed_timer_ctrl_enable(t, false);
517 aspeed_timer_ctrl_external_clock(t, TIMER_CLOCK_USE_APB);
518 aspeed_timer_ctrl_overflow_interrupt(t, false);
519 aspeed_timer_ctrl_pulse_enable(t, false);
520 t->level = 0;
521 t->reload = 0;
522 t->match[0] = 0;
523 t->match[1] = 0;
524 }
525 s->ctrl = 0;
526 s->ctrl2 = 0;
527}
528
529static const VMStateDescription vmstate_aspeed_timer = {
530 .name = "aspeed.timer",
531 .version_id = 2,
532 .minimum_version_id = 2,
533 .fields = (VMStateField[]) {
534 VMSTATE_UINT8(id, AspeedTimer),
535 VMSTATE_INT32(level, AspeedTimer),
536 VMSTATE_TIMER(timer, AspeedTimer),
537 VMSTATE_UINT32(reload, AspeedTimer),
538 VMSTATE_UINT32_ARRAY(match, AspeedTimer, 2),
539 VMSTATE_END_OF_LIST()
540 }
541};
542
543static const VMStateDescription vmstate_aspeed_timer_state = {
544 .name = "aspeed.timerctrl",
545 .version_id = 1,
546 .minimum_version_id = 1,
547 .fields = (VMStateField[]) {
548 VMSTATE_UINT32(ctrl, AspeedTimerCtrlState),
549 VMSTATE_UINT32(ctrl2, AspeedTimerCtrlState),
550 VMSTATE_STRUCT_ARRAY(timers, AspeedTimerCtrlState,
551 ASPEED_TIMER_NR_TIMERS, 1, vmstate_aspeed_timer,
552 AspeedTimer),
553 VMSTATE_END_OF_LIST()
554 }
555};
556
557static void timer_class_init(ObjectClass *klass, void *data)
558{
559 DeviceClass *dc = DEVICE_CLASS(klass);
560
561 dc->realize = aspeed_timer_realize;
562 dc->reset = aspeed_timer_reset;
563 dc->desc = "ASPEED Timer";
564 dc->vmsd = &vmstate_aspeed_timer_state;
565}
566
567static const TypeInfo aspeed_timer_info = {
568 .name = TYPE_ASPEED_TIMER,
569 .parent = TYPE_SYS_BUS_DEVICE,
570 .instance_size = sizeof(AspeedTimerCtrlState),
571 .class_init = timer_class_init,
572};
573
574static void aspeed_timer_register_types(void)
575{
576 type_register_static(&aspeed_timer_info);
577}
578
579type_init(aspeed_timer_register_types)
580