qemu/hw/timer/avr_timer16.c
<<
>>
Prefs
   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
 110static 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
 118static 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
 127static 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
 133static 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
 140static 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
 177static 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
 242static 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
 297static 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
 312static 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
 375static 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
 474static 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
 487static 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
 499static 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
 512static 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
 524static 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
 531static 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
 538static 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
 545static 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
 552static 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
 563static 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
 586static 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
 599static 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
 608static 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
 616static void avr_timer16_register_types(void)
 617{
 618    type_register_static(&avr_timer16_info);
 619}
 620
 621type_init(avr_timer16_register_types)
 622