qapi: Improve specificity of type/member descriptions
[qemu/armbru.git] / hw / timer / avr_timer16.c
blobc48555da5254370efb069460b0ee805430902e2e
1 /*
2 * AVR 16-bit timer
4 * Copyright (c) 2018 University of Kent
5 * Author: Ed Robbins
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see
19 * <http://www.gnu.org/licenses/lgpl-2.1.html>
23 * Driver for 16 bit timers on 8 bit AVR devices.
24 * Note:
25 * ATmega640/V-1280/V-1281/V-2560/V-2561/V timers 1, 3, 4 and 5 are 16 bit
29 * XXX TODO: Power Reduction Register support
30 * prescaler pause support
31 * PWM modes, GPIO, output capture pins, input compare pin
34 #include "qemu/osdep.h"
35 #include "qapi/error.h"
36 #include "qemu/log.h"
37 #include "hw/irq.h"
38 #include "hw/qdev-properties.h"
39 #include "hw/timer/avr_timer16.h"
40 #include "trace.h"
42 /* Register offsets */
43 #define T16_CRA 0x0
44 #define T16_CRB 0x1
45 #define T16_CRC 0x2
46 #define T16_CNTL 0x4
47 #define T16_CNTH 0x5
48 #define T16_ICRL 0x6
49 #define T16_ICRH 0x7
50 #define T16_OCRAL 0x8
51 #define T16_OCRAH 0x9
52 #define T16_OCRBL 0xa
53 #define T16_OCRBH 0xb
54 #define T16_OCRCL 0xc
55 #define T16_OCRCH 0xd
57 /* Field masks */
58 #define T16_CRA_WGM01 0x3
59 #define T16_CRA_COMC 0xc
60 #define T16_CRA_COMB 0x30
61 #define T16_CRA_COMA 0xc0
62 #define T16_CRA_OC_CONF \
63 (T16_CRA_COMA | T16_CRA_COMB | T16_CRA_COMC)
65 #define T16_CRB_CS 0x7
66 #define T16_CRB_WGM23 0x18
67 #define T16_CRB_ICES 0x40
68 #define T16_CRB_ICNC 0x80
70 #define T16_CRC_FOCC 0x20
71 #define T16_CRC_FOCB 0x40
72 #define T16_CRC_FOCA 0x80
74 /* Fields masks both TIMSK and TIFR (interrupt mask/flag registers) */
75 #define T16_INT_TOV 0x1 /* Timer overflow */
76 #define T16_INT_OCA 0x2 /* Output compare A */
77 #define T16_INT_OCB 0x4 /* Output compare B */
78 #define T16_INT_OCC 0x8 /* Output compare C */
79 #define T16_INT_IC 0x20 /* Input capture */
81 /* Clock source values */
82 #define T16_CLKSRC_STOPPED 0
83 #define T16_CLKSRC_DIV1 1
84 #define T16_CLKSRC_DIV8 2
85 #define T16_CLKSRC_DIV64 3
86 #define T16_CLKSRC_DIV256 4
87 #define T16_CLKSRC_DIV1024 5
88 #define T16_CLKSRC_EXT_FALLING 6
89 #define T16_CLKSRC_EXT_RISING 7
91 /* Timer mode values (not including PWM modes) */
92 #define T16_MODE_NORMAL 0
93 #define T16_MODE_CTC_OCRA 4
94 #define T16_MODE_CTC_ICR 12
96 /* Accessors */
97 #define CLKSRC(t16) (t16->crb & T16_CRB_CS)
98 #define MODE(t16) (((t16->crb & T16_CRB_WGM23) >> 1) | \
99 (t16->cra & T16_CRA_WGM01))
100 #define CNT(t16) VAL16(t16->cntl, t16->cnth)
101 #define OCRA(t16) VAL16(t16->ocral, t16->ocrah)
102 #define OCRB(t16) VAL16(t16->ocrbl, t16->ocrbh)
103 #define OCRC(t16) VAL16(t16->ocrcl, t16->ocrch)
104 #define ICR(t16) VAL16(t16->icrl, t16->icrh)
106 /* Helper macros */
107 #define VAL16(l, h) ((h << 8) | l)
108 #define DB_PRINT(fmt, args...) /* Nothing */
110 static inline int64_t avr_timer16_ns_to_ticks(AVRTimer16State *t16, int64_t t)
112 if (t16->period_ns == 0) {
113 return 0;
115 return t / t16->period_ns;
118 static void avr_timer16_update_cnt(AVRTimer16State *t16)
120 uint16_t cnt;
121 cnt = avr_timer16_ns_to_ticks(t16, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
122 t16->reset_time_ns);
123 t16->cntl = (uint8_t)(cnt & 0xff);
124 t16->cnth = (uint8_t)((cnt & 0xff00) >> 8);
127 static inline void avr_timer16_recalc_reset_time(AVRTimer16State *t16)
129 t16->reset_time_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
130 CNT(t16) * t16->period_ns;
133 static void avr_timer16_clock_reset(AVRTimer16State *t16)
135 t16->cntl = 0;
136 t16->cnth = 0;
137 t16->reset_time_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
140 static void avr_timer16_clksrc_update(AVRTimer16State *t16)
142 uint16_t divider = 0;
143 switch (CLKSRC(t16)) {
144 case T16_CLKSRC_EXT_FALLING:
145 case T16_CLKSRC_EXT_RISING:
146 qemu_log_mask(LOG_UNIMP, "%s: external clock source unsupported\n",
147 __func__);
148 break;
149 case T16_CLKSRC_STOPPED:
150 break;
151 case T16_CLKSRC_DIV1:
152 divider = 1;
153 break;
154 case T16_CLKSRC_DIV8:
155 divider = 8;
156 break;
157 case T16_CLKSRC_DIV64:
158 divider = 64;
159 break;
160 case T16_CLKSRC_DIV256:
161 divider = 256;
162 break;
163 case T16_CLKSRC_DIV1024:
164 divider = 1024;
165 break;
166 default:
167 break;
169 if (divider) {
170 t16->freq_hz = t16->cpu_freq_hz / divider;
171 t16->period_ns = NANOSECONDS_PER_SECOND / t16->freq_hz;
172 trace_avr_timer16_clksrc_update(t16->freq_hz, t16->period_ns,
173 (uint64_t)(1e6 / t16->freq_hz));
177 static void avr_timer16_set_alarm(AVRTimer16State *t16)
179 if (CLKSRC(t16) == T16_CLKSRC_EXT_FALLING ||
180 CLKSRC(t16) == T16_CLKSRC_EXT_RISING ||
181 CLKSRC(t16) == T16_CLKSRC_STOPPED) {
182 /* Timer is disabled or set to external clock source (unsupported) */
183 return;
186 uint64_t alarm_offset = 0xffff;
187 enum NextInterrupt next_interrupt = OVERFLOW;
189 switch (MODE(t16)) {
190 case T16_MODE_NORMAL:
191 /* Normal mode */
192 if (OCRA(t16) < alarm_offset && OCRA(t16) > CNT(t16) &&
193 (t16->imsk & T16_INT_OCA)) {
194 alarm_offset = OCRA(t16);
195 next_interrupt = COMPA;
197 break;
198 case T16_MODE_CTC_OCRA:
199 /* CTC mode, top = ocra */
200 if (OCRA(t16) < alarm_offset && OCRA(t16) > CNT(t16)) {
201 alarm_offset = OCRA(t16);
202 next_interrupt = COMPA;
204 break;
205 case T16_MODE_CTC_ICR:
206 /* CTC mode, top = icr */
207 if (ICR(t16) < alarm_offset && ICR(t16) > CNT(t16)) {
208 alarm_offset = ICR(t16);
209 next_interrupt = CAPT;
211 if (OCRA(t16) < alarm_offset && OCRA(t16) > CNT(t16) &&
212 (t16->imsk & T16_INT_OCA)) {
213 alarm_offset = OCRA(t16);
214 next_interrupt = COMPA;
216 break;
217 default:
218 qemu_log_mask(LOG_UNIMP, "%s: pwm modes are unsupported\n",
219 __func__);
220 return;
222 if (OCRB(t16) < alarm_offset && OCRB(t16) > CNT(t16) &&
223 (t16->imsk & T16_INT_OCB)) {
224 alarm_offset = OCRB(t16);
225 next_interrupt = COMPB;
227 if (OCRC(t16) < alarm_offset && OCRB(t16) > CNT(t16) &&
228 (t16->imsk & T16_INT_OCC)) {
229 alarm_offset = OCRB(t16);
230 next_interrupt = COMPC;
232 alarm_offset -= CNT(t16);
234 t16->next_interrupt = next_interrupt;
235 uint64_t alarm_ns =
236 t16->reset_time_ns + ((CNT(t16) + alarm_offset) * t16->period_ns);
237 timer_mod(t16->timer, alarm_ns);
239 trace_avr_timer16_next_alarm(alarm_offset * t16->period_ns);
242 static void avr_timer16_interrupt(void *opaque)
244 AVRTimer16State *t16 = opaque;
245 uint8_t mode = MODE(t16);
247 avr_timer16_update_cnt(t16);
249 if (CLKSRC(t16) == T16_CLKSRC_EXT_FALLING ||
250 CLKSRC(t16) == T16_CLKSRC_EXT_RISING ||
251 CLKSRC(t16) == T16_CLKSRC_STOPPED) {
252 /* Timer is disabled or set to external clock source (unsupported) */
253 return;
256 trace_avr_timer16_interrupt_count(CNT(t16));
258 /* Counter overflow */
259 if (t16->next_interrupt == OVERFLOW) {
260 trace_avr_timer16_interrupt_overflow("counter 0xffff");
261 avr_timer16_clock_reset(t16);
262 if (t16->imsk & T16_INT_TOV) {
263 t16->ifr |= T16_INT_TOV;
264 qemu_set_irq(t16->ovf_irq, 1);
267 /* Check for ocra overflow in CTC mode */
268 if (mode == T16_MODE_CTC_OCRA && t16->next_interrupt == COMPA) {
269 trace_avr_timer16_interrupt_overflow("CTC OCRA");
270 avr_timer16_clock_reset(t16);
272 /* Check for icr overflow in CTC mode */
273 if (mode == T16_MODE_CTC_ICR && t16->next_interrupt == CAPT) {
274 trace_avr_timer16_interrupt_overflow("CTC ICR");
275 avr_timer16_clock_reset(t16);
276 if (t16->imsk & T16_INT_IC) {
277 t16->ifr |= T16_INT_IC;
278 qemu_set_irq(t16->capt_irq, 1);
281 /* Check for output compare interrupts */
282 if (t16->imsk & T16_INT_OCA && t16->next_interrupt == COMPA) {
283 t16->ifr |= T16_INT_OCA;
284 qemu_set_irq(t16->compa_irq, 1);
286 if (t16->imsk & T16_INT_OCB && t16->next_interrupt == COMPB) {
287 t16->ifr |= T16_INT_OCB;
288 qemu_set_irq(t16->compb_irq, 1);
290 if (t16->imsk & T16_INT_OCC && t16->next_interrupt == COMPC) {
291 t16->ifr |= T16_INT_OCC;
292 qemu_set_irq(t16->compc_irq, 1);
294 avr_timer16_set_alarm(t16);
297 static void avr_timer16_reset(DeviceState *dev)
299 AVRTimer16State *t16 = AVR_TIMER16(dev);
301 avr_timer16_clock_reset(t16);
302 avr_timer16_clksrc_update(t16);
303 avr_timer16_set_alarm(t16);
305 qemu_set_irq(t16->capt_irq, 0);
306 qemu_set_irq(t16->compa_irq, 0);
307 qemu_set_irq(t16->compb_irq, 0);
308 qemu_set_irq(t16->compc_irq, 0);
309 qemu_set_irq(t16->ovf_irq, 0);
312 static uint64_t avr_timer16_read(void *opaque, hwaddr offset, unsigned size)
314 assert(size == 1);
315 AVRTimer16State *t16 = opaque;
316 uint8_t retval = 0;
318 switch (offset) {
319 case T16_CRA:
320 retval = t16->cra;
321 break;
322 case T16_CRB:
323 retval = t16->crb;
324 break;
325 case T16_CRC:
326 retval = t16->crc;
327 break;
328 case T16_CNTL:
329 avr_timer16_update_cnt(t16);
330 t16->rtmp = t16->cnth;
331 retval = t16->cntl;
332 break;
333 case T16_CNTH:
334 retval = t16->rtmp;
335 break;
336 case T16_ICRL:
338 * The timer copies cnt to icr when the input capture pin changes
339 * state or when the analog comparator has a match. We don't
340 * emulate this behaviour. We do support it's use for defining a
341 * TOP value in T16_MODE_CTC_ICR
343 t16->rtmp = t16->icrh;
344 retval = t16->icrl;
345 break;
346 case T16_ICRH:
347 retval = t16->rtmp;
348 break;
349 case T16_OCRAL:
350 retval = t16->ocral;
351 break;
352 case T16_OCRAH:
353 retval = t16->ocrah;
354 break;
355 case T16_OCRBL:
356 retval = t16->ocrbl;
357 break;
358 case T16_OCRBH:
359 retval = t16->ocrbh;
360 break;
361 case T16_OCRCL:
362 retval = t16->ocrcl;
363 break;
364 case T16_OCRCH:
365 retval = t16->ocrch;
366 break;
367 default:
368 break;
370 trace_avr_timer16_read(offset, retval);
372 return (uint64_t)retval;
375 static void avr_timer16_write(void *opaque, hwaddr offset,
376 uint64_t val64, unsigned size)
378 assert(size == 1);
379 AVRTimer16State *t16 = opaque;
380 uint8_t val8 = (uint8_t)val64;
381 uint8_t prev_clk_src = CLKSRC(t16);
383 trace_avr_timer16_write(offset, val8);
385 switch (offset) {
386 case T16_CRA:
387 t16->cra = val8;
388 if (t16->cra & T16_CRA_OC_CONF) {
389 qemu_log_mask(LOG_UNIMP, "%s: output compare pins unsupported\n",
390 __func__);
392 break;
393 case T16_CRB:
394 t16->crb = val8;
395 if (t16->crb & T16_CRB_ICNC) {
396 qemu_log_mask(LOG_UNIMP,
397 "%s: input capture noise canceller unsupported\n",
398 __func__);
400 if (t16->crb & T16_CRB_ICES) {
401 qemu_log_mask(LOG_UNIMP, "%s: input capture unsupported\n",
402 __func__);
404 if (CLKSRC(t16) != prev_clk_src) {
405 avr_timer16_clksrc_update(t16);
406 if (prev_clk_src == T16_CLKSRC_STOPPED) {
407 t16->reset_time_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
410 break;
411 case T16_CRC:
412 t16->crc = val8;
413 qemu_log_mask(LOG_UNIMP, "%s: output compare pins unsupported\n",
414 __func__);
415 break;
416 case T16_CNTL:
418 * CNT is the 16-bit counter value, it must be read/written via
419 * a temporary register (rtmp) to make the read/write atomic.
421 /* ICR also has this behaviour, and shares rtmp */
423 * Writing CNT blocks compare matches for one clock cycle.
424 * Writing CNT to TOP or to an OCR value (if in use) will
425 * skip the relevant interrupt
427 t16->cntl = val8;
428 t16->cnth = t16->rtmp;
429 avr_timer16_recalc_reset_time(t16);
430 break;
431 case T16_CNTH:
432 t16->rtmp = val8;
433 break;
434 case T16_ICRL:
435 /* ICR can only be written in mode T16_MODE_CTC_ICR */
436 if (MODE(t16) == T16_MODE_CTC_ICR) {
437 t16->icrl = val8;
438 t16->icrh = t16->rtmp;
440 break;
441 case T16_ICRH:
442 if (MODE(t16) == T16_MODE_CTC_ICR) {
443 t16->rtmp = val8;
445 break;
446 case T16_OCRAL:
448 * OCRn cause the relevant output compare flag to be raised, and
449 * trigger an interrupt, when CNT is equal to the value here
451 t16->ocral = val8;
452 break;
453 case T16_OCRAH:
454 t16->ocrah = val8;
455 break;
456 case T16_OCRBL:
457 t16->ocrbl = val8;
458 break;
459 case T16_OCRBH:
460 t16->ocrbh = val8;
461 break;
462 case T16_OCRCL:
463 t16->ocrcl = val8;
464 break;
465 case T16_OCRCH:
466 t16->ocrch = val8;
467 break;
468 default:
469 break;
471 avr_timer16_set_alarm(t16);
474 static uint64_t avr_timer16_imsk_read(void *opaque,
475 hwaddr offset,
476 unsigned size)
478 assert(size == 1);
479 AVRTimer16State *t16 = opaque;
480 trace_avr_timer16_read_imsk(offset ? 0 : t16->imsk);
481 if (offset != 0) {
482 return 0;
484 return t16->imsk;
487 static void avr_timer16_imsk_write(void *opaque, hwaddr offset,
488 uint64_t val64, unsigned size)
490 assert(size == 1);
491 AVRTimer16State *t16 = opaque;
492 trace_avr_timer16_write_imsk(val64);
493 if (offset != 0) {
494 return;
496 t16->imsk = (uint8_t)val64;
499 static uint64_t avr_timer16_ifr_read(void *opaque,
500 hwaddr offset,
501 unsigned size)
503 assert(size == 1);
504 AVRTimer16State *t16 = opaque;
505 trace_avr_timer16_read_ifr(offset ? 0 : t16->ifr);
506 if (offset != 0) {
507 return 0;
509 return t16->ifr;
512 static void avr_timer16_ifr_write(void *opaque, hwaddr offset,
513 uint64_t val64, unsigned size)
515 assert(size == 1);
516 AVRTimer16State *t16 = opaque;
517 trace_avr_timer16_write_imsk(val64);
518 if (offset != 0) {
519 return;
521 t16->ifr = (uint8_t)val64;
524 static const MemoryRegionOps avr_timer16_ops = {
525 .read = avr_timer16_read,
526 .write = avr_timer16_write,
527 .endianness = DEVICE_NATIVE_ENDIAN,
528 .impl = {.max_access_size = 1}
531 static const MemoryRegionOps avr_timer16_imsk_ops = {
532 .read = avr_timer16_imsk_read,
533 .write = avr_timer16_imsk_write,
534 .endianness = DEVICE_NATIVE_ENDIAN,
535 .impl = {.max_access_size = 1}
538 static const MemoryRegionOps avr_timer16_ifr_ops = {
539 .read = avr_timer16_ifr_read,
540 .write = avr_timer16_ifr_write,
541 .endianness = DEVICE_NATIVE_ENDIAN,
542 .impl = {.max_access_size = 1}
545 static Property avr_timer16_properties[] = {
546 DEFINE_PROP_UINT8("id", struct AVRTimer16State, id, 0),
547 DEFINE_PROP_UINT64("cpu-frequency-hz", struct AVRTimer16State,
548 cpu_freq_hz, 0),
549 DEFINE_PROP_END_OF_LIST(),
552 static void avr_timer16_pr(void *opaque, int irq, int level)
554 AVRTimer16State *s = AVR_TIMER16(opaque);
556 s->enabled = !level;
558 if (!s->enabled) {
559 avr_timer16_reset(DEVICE(s));
563 static void avr_timer16_init(Object *obj)
565 AVRTimer16State *s = AVR_TIMER16(obj);
567 sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->capt_irq);
568 sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->compa_irq);
569 sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->compb_irq);
570 sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->compc_irq);
571 sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->ovf_irq);
573 memory_region_init_io(&s->iomem, obj, &avr_timer16_ops,
574 s, "avr-timer16", 0xe);
575 memory_region_init_io(&s->imsk_iomem, obj, &avr_timer16_imsk_ops,
576 s, "avr-timer16-intmask", 0x1);
577 memory_region_init_io(&s->ifr_iomem, obj, &avr_timer16_ifr_ops,
578 s, "avr-timer16-intflag", 0x1);
580 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
581 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->imsk_iomem);
582 sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->ifr_iomem);
583 qdev_init_gpio_in(DEVICE(s), avr_timer16_pr, 1);
586 static void avr_timer16_realize(DeviceState *dev, Error **errp)
588 AVRTimer16State *s = AVR_TIMER16(dev);
590 if (s->cpu_freq_hz == 0) {
591 error_setg(errp, "AVR timer16: cpu-frequency-hz property must be set");
592 return;
595 s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, avr_timer16_interrupt, s);
596 s->enabled = true;
599 static void avr_timer16_class_init(ObjectClass *klass, void *data)
601 DeviceClass *dc = DEVICE_CLASS(klass);
603 dc->reset = avr_timer16_reset;
604 dc->realize = avr_timer16_realize;
605 device_class_set_props(dc, avr_timer16_properties);
608 static const TypeInfo avr_timer16_info = {
609 .name = TYPE_AVR_TIMER16,
610 .parent = TYPE_SYS_BUS_DEVICE,
611 .instance_size = sizeof(AVRTimer16State),
612 .instance_init = avr_timer16_init,
613 .class_init = avr_timer16_class_init,
616 static void avr_timer16_register_types(void)
618 type_register_static(&avr_timer16_info);
621 type_init(avr_timer16_register_types)