xref: /openbmc/qemu/hw/timer/avr_timer16.c (revision 873ec69a)
1 /*
2  * AVR 16-bit timer
3  *
4  * Copyright (c) 2018 University of Kent
5  * Author: Ed Robbins
6  *
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.
11  *
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.
16  *
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>
20  */
21 
22 /*
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
26  */
27 
28 /*
29  * XXX TODO: Power Reduction Register support
30  *           prescaler pause support
31  *           PWM modes, GPIO, output capture pins, input compare pin
32  */
33 
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"
41 
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
56 
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)
64 
65 #define T16_CRB_CS      0x7
66 #define T16_CRB_WGM23   0x18
67 #define T16_CRB_ICES    0x40
68 #define T16_CRB_ICNC    0x80
69 
70 #define T16_CRC_FOCC    0x20
71 #define T16_CRC_FOCB    0x40
72 #define T16_CRC_FOCA    0x80
73 
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 */
80 
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
90 
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
95 
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)
105 
106 /* Helper macros */
107 #define VAL16(l, h) ((h << 8) | l)
108 #define DB_PRINT(fmt, args...) /* Nothing */
109 
avr_timer16_ns_to_ticks(AVRTimer16State * t16,int64_t t)110 static inline int64_t avr_timer16_ns_to_ticks(AVRTimer16State *t16, int64_t t)
111 {
112     if (t16->period_ns == 0) {
113         return 0;
114     }
115     return t / t16->period_ns;
116 }
117 
avr_timer16_update_cnt(AVRTimer16State * t16)118 static void avr_timer16_update_cnt(AVRTimer16State *t16)
119 {
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);
125 }
126 
avr_timer16_recalc_reset_time(AVRTimer16State * t16)127 static inline void avr_timer16_recalc_reset_time(AVRTimer16State *t16)
128 {
129     t16->reset_time_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
130                          CNT(t16) * t16->period_ns;
131 }
132 
avr_timer16_clock_reset(AVRTimer16State * t16)133 static void avr_timer16_clock_reset(AVRTimer16State *t16)
134 {
135     t16->cntl = 0;
136     t16->cnth = 0;
137     t16->reset_time_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
138 }
139 
avr_timer16_clksrc_update(AVRTimer16State * t16)140 static void avr_timer16_clksrc_update(AVRTimer16State *t16)
141 {
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;
168     }
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));
174     }
175 }
176 
avr_timer16_set_alarm(AVRTimer16State * t16)177 static void avr_timer16_set_alarm(AVRTimer16State *t16)
178 {
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;
184     }
185 
186     uint64_t alarm_offset = 0xffff;
187     enum NextInterrupt next_interrupt = OVERFLOW;
188 
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;
196         }
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;
203         }
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;
210         }
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;
215         }
216         break;
217     default:
218         qemu_log_mask(LOG_UNIMP, "%s: pwm modes are unsupported\n",
219                       __func__);
220         return;
221     }
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;
226     }
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;
231     }
232     alarm_offset -= CNT(t16);
233 
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);
238 
239     trace_avr_timer16_next_alarm(alarm_offset * t16->period_ns);
240 }
241 
avr_timer16_interrupt(void * opaque)242 static void avr_timer16_interrupt(void *opaque)
243 {
244     AVRTimer16State *t16 = opaque;
245     uint8_t mode = MODE(t16);
246 
247     avr_timer16_update_cnt(t16);
248 
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;
254     }
255 
256     trace_avr_timer16_interrupt_count(CNT(t16));
257 
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);
265         }
266     }
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);
271     }
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);
279         }
280     }
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);
285     }
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);
289     }
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);
293     }
294     avr_timer16_set_alarm(t16);
295 }
296 
avr_timer16_reset(DeviceState * dev)297 static void avr_timer16_reset(DeviceState *dev)
298 {
299     AVRTimer16State *t16 = AVR_TIMER16(dev);
300 
301     avr_timer16_clock_reset(t16);
302     avr_timer16_clksrc_update(t16);
303     avr_timer16_set_alarm(t16);
304 
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);
310 }
311 
avr_timer16_read(void * opaque,hwaddr offset,unsigned size)312 static uint64_t avr_timer16_read(void *opaque, hwaddr offset, unsigned size)
313 {
314     assert(size == 1);
315     AVRTimer16State *t16 = opaque;
316     uint8_t retval = 0;
317 
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:
337         /*
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
342          */
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;
369     }
370     trace_avr_timer16_read(offset, retval);
371 
372     return (uint64_t)retval;
373 }
374 
avr_timer16_write(void * opaque,hwaddr offset,uint64_t val64,unsigned size)375 static void avr_timer16_write(void *opaque, hwaddr offset,
376                               uint64_t val64, unsigned size)
377 {
378     assert(size == 1);
379     AVRTimer16State *t16 = opaque;
380     uint8_t val8 = (uint8_t)val64;
381     uint8_t prev_clk_src = CLKSRC(t16);
382 
383     trace_avr_timer16_write(offset, val8);
384 
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__);
391         }
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__);
399         }
400         if (t16->crb & T16_CRB_ICES) {
401             qemu_log_mask(LOG_UNIMP, "%s: input capture unsupported\n",
402                           __func__);
403         }
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);
408             }
409         }
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:
417         /*
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.
420          */
421         /* ICR also has this behaviour, and shares rtmp */
422         /*
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
426          */
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;
439         }
440         break;
441     case T16_ICRH:
442         if (MODE(t16) == T16_MODE_CTC_ICR) {
443             t16->rtmp = val8;
444         }
445         break;
446     case T16_OCRAL:
447         /*
448          * OCRn cause the relevant output compare flag to be raised, and
449          * trigger an interrupt, when CNT is equal to the value here
450          */
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;
470     }
471     avr_timer16_set_alarm(t16);
472 }
473 
avr_timer16_imsk_read(void * opaque,hwaddr offset,unsigned size)474 static uint64_t avr_timer16_imsk_read(void *opaque,
475                                       hwaddr offset,
476                                       unsigned size)
477 {
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;
483     }
484     return t16->imsk;
485 }
486 
avr_timer16_imsk_write(void * opaque,hwaddr offset,uint64_t val64,unsigned size)487 static void avr_timer16_imsk_write(void *opaque, hwaddr offset,
488                                    uint64_t val64, unsigned size)
489 {
490     assert(size == 1);
491     AVRTimer16State *t16 = opaque;
492     trace_avr_timer16_write_imsk(val64);
493     if (offset != 0) {
494         return;
495     }
496     t16->imsk = (uint8_t)val64;
497 }
498 
avr_timer16_ifr_read(void * opaque,hwaddr offset,unsigned size)499 static uint64_t avr_timer16_ifr_read(void *opaque,
500                                      hwaddr offset,
501                                      unsigned size)
502 {
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;
508     }
509     return t16->ifr;
510 }
511 
avr_timer16_ifr_write(void * opaque,hwaddr offset,uint64_t val64,unsigned size)512 static void avr_timer16_ifr_write(void *opaque, hwaddr offset,
513                                   uint64_t val64, unsigned size)
514 {
515     assert(size == 1);
516     AVRTimer16State *t16 = opaque;
517     trace_avr_timer16_write_imsk(val64);
518     if (offset != 0) {
519         return;
520     }
521     t16->ifr = (uint8_t)val64;
522 }
523 
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}
529 };
530 
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}
536 };
537 
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}
543 };
544 
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(),
550 };
551 
avr_timer16_pr(void * opaque,int irq,int level)552 static void avr_timer16_pr(void *opaque, int irq, int level)
553 {
554     AVRTimer16State *s = AVR_TIMER16(opaque);
555 
556     s->enabled = !level;
557 
558     if (!s->enabled) {
559         avr_timer16_reset(DEVICE(s));
560     }
561 }
562 
avr_timer16_init(Object * obj)563 static void avr_timer16_init(Object *obj)
564 {
565     AVRTimer16State *s = AVR_TIMER16(obj);
566 
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);
572 
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);
579 
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);
584 }
585 
avr_timer16_realize(DeviceState * dev,Error ** errp)586 static void avr_timer16_realize(DeviceState *dev, Error **errp)
587 {
588     AVRTimer16State *s = AVR_TIMER16(dev);
589 
590     if (s->cpu_freq_hz == 0) {
591         error_setg(errp, "AVR timer16: cpu-frequency-hz property must be set");
592         return;
593     }
594 
595     s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, avr_timer16_interrupt, s);
596     s->enabled = true;
597 }
598 
avr_timer16_class_init(ObjectClass * klass,void * data)599 static void avr_timer16_class_init(ObjectClass *klass, void *data)
600 {
601     DeviceClass *dc = DEVICE_CLASS(klass);
602 
603     dc->reset = avr_timer16_reset;
604     dc->realize = avr_timer16_realize;
605     device_class_set_props(dc, avr_timer16_properties);
606 }
607 
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,
614 };
615 
avr_timer16_register_types(void)616 static void avr_timer16_register_types(void)
617 {
618     type_register_static(&avr_timer16_info);
619 }
620 
621 type_init(avr_timer16_register_types)
622