qemu/hw/timer/cmsdk-apb-dualtimer.c
<<
>>
Prefs
   1/*
   2 * ARM CMSDK APB dual-timer emulation
   3 *
   4 * Copyright (c) 2018 Linaro Limited
   5 * Written by Peter Maydell
   6 *
   7 *  This program is free software; you can redistribute it and/or modify
   8 *  it under the terms of the GNU General Public License version 2 or
   9 *  (at your option) any later version.
  10 */
  11
  12/*
  13 * This is a model of the "APB dual-input timer" which is part of the Cortex-M
  14 * System Design Kit (CMSDK) and documented in the Cortex-M System
  15 * Design Kit Technical Reference Manual (ARM DDI0479C):
  16 * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
  17 */
  18
  19#include "qemu/osdep.h"
  20#include "qemu/log.h"
  21#include "trace.h"
  22#include "qapi/error.h"
  23#include "qemu/module.h"
  24#include "hw/sysbus.h"
  25#include "hw/irq.h"
  26#include "hw/qdev-properties.h"
  27#include "hw/registerfields.h"
  28#include "hw/qdev-clock.h"
  29#include "hw/timer/cmsdk-apb-dualtimer.h"
  30#include "migration/vmstate.h"
  31
  32REG32(TIMER1LOAD, 0x0)
  33REG32(TIMER1VALUE, 0x4)
  34REG32(TIMER1CONTROL, 0x8)
  35    FIELD(CONTROL, ONESHOT, 0, 1)
  36    FIELD(CONTROL, SIZE, 1, 1)
  37    FIELD(CONTROL, PRESCALE, 2, 2)
  38    FIELD(CONTROL, INTEN, 5, 1)
  39    FIELD(CONTROL, MODE, 6, 1)
  40    FIELD(CONTROL, ENABLE, 7, 1)
  41#define R_CONTROL_VALID_MASK (R_CONTROL_ONESHOT_MASK | R_CONTROL_SIZE_MASK | \
  42                              R_CONTROL_PRESCALE_MASK | R_CONTROL_INTEN_MASK | \
  43                              R_CONTROL_MODE_MASK | R_CONTROL_ENABLE_MASK)
  44REG32(TIMER1INTCLR, 0xc)
  45REG32(TIMER1RIS, 0x10)
  46REG32(TIMER1MIS, 0x14)
  47REG32(TIMER1BGLOAD, 0x18)
  48REG32(TIMER2LOAD, 0x20)
  49REG32(TIMER2VALUE, 0x24)
  50REG32(TIMER2CONTROL, 0x28)
  51REG32(TIMER2INTCLR, 0x2c)
  52REG32(TIMER2RIS, 0x30)
  53REG32(TIMER2MIS, 0x34)
  54REG32(TIMER2BGLOAD, 0x38)
  55REG32(TIMERITCR, 0xf00)
  56    FIELD(TIMERITCR, ENABLE, 0, 1)
  57#define R_TIMERITCR_VALID_MASK R_TIMERITCR_ENABLE_MASK
  58REG32(TIMERITOP, 0xf04)
  59    FIELD(TIMERITOP, TIMINT1, 0, 1)
  60    FIELD(TIMERITOP, TIMINT2, 1, 1)
  61#define R_TIMERITOP_VALID_MASK (R_TIMERITOP_TIMINT1_MASK | \
  62                                R_TIMERITOP_TIMINT2_MASK)
  63REG32(PID4, 0xfd0)
  64REG32(PID5, 0xfd4)
  65REG32(PID6, 0xfd8)
  66REG32(PID7, 0xfdc)
  67REG32(PID0, 0xfe0)
  68REG32(PID1, 0xfe4)
  69REG32(PID2, 0xfe8)
  70REG32(PID3, 0xfec)
  71REG32(CID0, 0xff0)
  72REG32(CID1, 0xff4)
  73REG32(CID2, 0xff8)
  74REG32(CID3, 0xffc)
  75
  76/* PID/CID values */
  77static const int timer_id[] = {
  78    0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
  79    0x23, 0xb8, 0x1b, 0x00, /* PID0..PID3 */
  80    0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
  81};
  82
  83static bool cmsdk_dualtimermod_intstatus(CMSDKAPBDualTimerModule *m)
  84{
  85    /* Return masked interrupt status for the timer module */
  86    return m->intstatus && (m->control & R_CONTROL_INTEN_MASK);
  87}
  88
  89static void cmsdk_apb_dualtimer_update(CMSDKAPBDualTimer *s)
  90{
  91    bool timint1, timint2, timintc;
  92
  93    if (s->timeritcr) {
  94        /* Integration test mode: outputs driven directly from TIMERITOP bits */
  95        timint1 = s->timeritop & R_TIMERITOP_TIMINT1_MASK;
  96        timint2 = s->timeritop & R_TIMERITOP_TIMINT2_MASK;
  97    } else {
  98        timint1 = cmsdk_dualtimermod_intstatus(&s->timermod[0]);
  99        timint2 = cmsdk_dualtimermod_intstatus(&s->timermod[1]);
 100    }
 101
 102    timintc = timint1 || timint2;
 103
 104    qemu_set_irq(s->timermod[0].timerint, timint1);
 105    qemu_set_irq(s->timermod[1].timerint, timint2);
 106    qemu_set_irq(s->timerintc, timintc);
 107}
 108
 109static int cmsdk_dualtimermod_divisor(CMSDKAPBDualTimerModule *m)
 110{
 111    /* Return the divisor set by the current CONTROL.PRESCALE value */
 112    switch (FIELD_EX32(m->control, CONTROL, PRESCALE)) {
 113    case 0:
 114        return 1;
 115    case 1:
 116        return 16;
 117    case 2:
 118    case 3: /* UNDEFINED, we treat like 2 (and complained when it was set) */
 119        return 256;
 120    default:
 121        g_assert_not_reached();
 122    }
 123}
 124
 125static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
 126                                             uint32_t newctrl)
 127{
 128    /* Handle a write to the CONTROL register */
 129    uint32_t changed;
 130
 131    ptimer_transaction_begin(m->timer);
 132
 133    newctrl &= R_CONTROL_VALID_MASK;
 134
 135    changed = m->control ^ newctrl;
 136
 137    if (changed & ~newctrl & R_CONTROL_ENABLE_MASK) {
 138        /* ENABLE cleared, stop timer before any further changes */
 139        ptimer_stop(m->timer);
 140    }
 141
 142    if (changed & R_CONTROL_PRESCALE_MASK) {
 143        int divisor;
 144
 145        switch (FIELD_EX32(newctrl, CONTROL, PRESCALE)) {
 146        case 0:
 147            divisor = 1;
 148            break;
 149        case 1:
 150            divisor = 16;
 151            break;
 152        case 2:
 153            divisor = 256;
 154            break;
 155        case 3:
 156            /* UNDEFINED; complain, and arbitrarily treat like 2 */
 157            qemu_log_mask(LOG_GUEST_ERROR,
 158                          "CMSDK APB dual-timer: CONTROL.PRESCALE==0b11"
 159                          " is undefined behaviour\n");
 160            divisor = 256;
 161            break;
 162        default:
 163            g_assert_not_reached();
 164        }
 165        ptimer_set_period_from_clock(m->timer, m->parent->timclk, divisor);
 166    }
 167
 168    if (changed & R_CONTROL_MODE_MASK) {
 169        uint32_t load;
 170        if (newctrl & R_CONTROL_MODE_MASK) {
 171            /* Periodic: the limit is the LOAD register value */
 172            load = m->load;
 173        } else {
 174            /* Free-running: counter wraps around */
 175            load = ptimer_get_limit(m->timer);
 176            if (!(m->control & R_CONTROL_SIZE_MASK)) {
 177                load = deposit32(m->load, 0, 16, load);
 178            }
 179            m->load = load;
 180            load = 0xffffffff;
 181        }
 182        if (!(m->control & R_CONTROL_SIZE_MASK)) {
 183            load &= 0xffff;
 184        }
 185        ptimer_set_limit(m->timer, load, 0);
 186    }
 187
 188    if (changed & R_CONTROL_SIZE_MASK) {
 189        /* Timer switched between 16 and 32 bit count */
 190        uint32_t value, load;
 191
 192        value = ptimer_get_count(m->timer);
 193        load = ptimer_get_limit(m->timer);
 194        if (newctrl & R_CONTROL_SIZE_MASK) {
 195            /* 16 -> 32, top half of VALUE is in struct field */
 196            value = deposit32(m->value, 0, 16, value);
 197        } else {
 198            /* 32 -> 16: save top half to struct field and truncate */
 199            m->value = value;
 200            value &= 0xffff;
 201        }
 202
 203        if (newctrl & R_CONTROL_MODE_MASK) {
 204            /* Periodic, timer limit has LOAD value */
 205            if (newctrl & R_CONTROL_SIZE_MASK) {
 206                load = deposit32(m->load, 0, 16, load);
 207            } else {
 208                m->load = load;
 209                load &= 0xffff;
 210            }
 211        } else {
 212            /* Free-running, timer limit is set to give wraparound */
 213            if (newctrl & R_CONTROL_SIZE_MASK) {
 214                load = 0xffffffff;
 215            } else {
 216                load = 0xffff;
 217            }
 218        }
 219        ptimer_set_count(m->timer, value);
 220        ptimer_set_limit(m->timer, load, 0);
 221    }
 222
 223    if (newctrl & R_CONTROL_ENABLE_MASK) {
 224        /*
 225         * ENABLE is set; start the timer after all other changes.
 226         * We start it even if the ENABLE bit didn't actually change,
 227         * in case the timer was an expired one-shot timer that has
 228         * now been changed into a free-running or periodic timer.
 229         */
 230        ptimer_run(m->timer, !!(newctrl & R_CONTROL_ONESHOT_MASK));
 231    }
 232
 233    m->control = newctrl;
 234
 235    ptimer_transaction_commit(m->timer);
 236}
 237
 238static uint64_t cmsdk_apb_dualtimer_read(void *opaque, hwaddr offset,
 239                                          unsigned size)
 240{
 241    CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
 242    uint64_t r;
 243
 244    if (offset >= A_TIMERITCR) {
 245        switch (offset) {
 246        case A_TIMERITCR:
 247            r = s->timeritcr;
 248            break;
 249        case A_PID4 ... A_CID3:
 250            r = timer_id[(offset - A_PID4) / 4];
 251            break;
 252        default:
 253        bad_offset:
 254            qemu_log_mask(LOG_GUEST_ERROR,
 255                          "CMSDK APB dual-timer read: bad offset %x\n",
 256                          (int) offset);
 257            r = 0;
 258            break;
 259        }
 260    } else {
 261        int timer = offset >> 5;
 262        CMSDKAPBDualTimerModule *m;
 263
 264        if (timer >= ARRAY_SIZE(s->timermod)) {
 265            goto bad_offset;
 266        }
 267
 268        m = &s->timermod[timer];
 269
 270        switch (offset & 0x1F) {
 271        case A_TIMER1LOAD:
 272        case A_TIMER1BGLOAD:
 273            if (m->control & R_CONTROL_MODE_MASK) {
 274                /*
 275                 * Periodic: the ptimer limit is the LOAD register value, (or
 276                 * just the low 16 bits of it if the timer is in 16-bit mode)
 277                 */
 278                r = ptimer_get_limit(m->timer);
 279                if (!(m->control & R_CONTROL_SIZE_MASK)) {
 280                    r = deposit32(m->load, 0, 16, r);
 281                }
 282            } else {
 283                /* Free-running: LOAD register value is just in m->load */
 284                r = m->load;
 285            }
 286            break;
 287        case A_TIMER1VALUE:
 288            r = ptimer_get_count(m->timer);
 289            if (!(m->control & R_CONTROL_SIZE_MASK)) {
 290                r = deposit32(m->value, 0, 16, r);
 291            }
 292            break;
 293        case A_TIMER1CONTROL:
 294            r = m->control;
 295            break;
 296        case A_TIMER1RIS:
 297            r = m->intstatus;
 298            break;
 299        case A_TIMER1MIS:
 300            r = cmsdk_dualtimermod_intstatus(m);
 301            break;
 302        default:
 303            goto bad_offset;
 304        }
 305    }
 306
 307    trace_cmsdk_apb_dualtimer_read(offset, r, size);
 308    return r;
 309}
 310
 311static void cmsdk_apb_dualtimer_write(void *opaque, hwaddr offset,
 312                                       uint64_t value, unsigned size)
 313{
 314    CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
 315
 316    trace_cmsdk_apb_dualtimer_write(offset, value, size);
 317
 318    if (offset >= A_TIMERITCR) {
 319        switch (offset) {
 320        case A_TIMERITCR:
 321            s->timeritcr = value & R_TIMERITCR_VALID_MASK;
 322            cmsdk_apb_dualtimer_update(s);
 323            break;
 324        case A_TIMERITOP:
 325            s->timeritop = value & R_TIMERITOP_VALID_MASK;
 326            cmsdk_apb_dualtimer_update(s);
 327            break;
 328        default:
 329        bad_offset:
 330            qemu_log_mask(LOG_GUEST_ERROR,
 331                          "CMSDK APB dual-timer write: bad offset %x\n",
 332                          (int) offset);
 333            break;
 334        }
 335    } else {
 336        int timer = offset >> 5;
 337        CMSDKAPBDualTimerModule *m;
 338
 339        if (timer >= ARRAY_SIZE(s->timermod)) {
 340            goto bad_offset;
 341        }
 342
 343        m = &s->timermod[timer];
 344
 345        switch (offset & 0x1F) {
 346        case A_TIMER1LOAD:
 347            /* Set the limit, and immediately reload the count from it */
 348            m->load = value;
 349            m->value = value;
 350            if (!(m->control & R_CONTROL_SIZE_MASK)) {
 351                value &= 0xffff;
 352            }
 353            ptimer_transaction_begin(m->timer);
 354            if (!(m->control & R_CONTROL_MODE_MASK)) {
 355                /*
 356                 * In free-running mode this won't set the limit but will
 357                 * still change the current count value.
 358                 */
 359                ptimer_set_count(m->timer, value);
 360            } else {
 361                if (!value) {
 362                    ptimer_stop(m->timer);
 363                }
 364                ptimer_set_limit(m->timer, value, 1);
 365                if (value && (m->control & R_CONTROL_ENABLE_MASK)) {
 366                    /* Force possibly-expired oneshot timer to restart */
 367                    ptimer_run(m->timer, 1);
 368                }
 369            }
 370            ptimer_transaction_commit(m->timer);
 371            break;
 372        case A_TIMER1BGLOAD:
 373            /* Set the limit, but not the current count */
 374            m->load = value;
 375            if (!(m->control & R_CONTROL_MODE_MASK)) {
 376                /* In free-running mode there is no limit */
 377                break;
 378            }
 379            if (!(m->control & R_CONTROL_SIZE_MASK)) {
 380                value &= 0xffff;
 381            }
 382            ptimer_transaction_begin(m->timer);
 383            ptimer_set_limit(m->timer, value, 0);
 384            ptimer_transaction_commit(m->timer);
 385            break;
 386        case A_TIMER1CONTROL:
 387            cmsdk_dualtimermod_write_control(m, value);
 388            cmsdk_apb_dualtimer_update(s);
 389            break;
 390        case A_TIMER1INTCLR:
 391            m->intstatus = 0;
 392            cmsdk_apb_dualtimer_update(s);
 393            break;
 394        default:
 395            goto bad_offset;
 396        }
 397    }
 398}
 399
 400static const MemoryRegionOps cmsdk_apb_dualtimer_ops = {
 401    .read = cmsdk_apb_dualtimer_read,
 402    .write = cmsdk_apb_dualtimer_write,
 403    .endianness = DEVICE_LITTLE_ENDIAN,
 404    /* byte/halfword accesses are just zero-padded on reads and writes */
 405    .impl.min_access_size = 4,
 406    .impl.max_access_size = 4,
 407    .valid.min_access_size = 1,
 408    .valid.max_access_size = 4,
 409};
 410
 411static void cmsdk_dualtimermod_tick(void *opaque)
 412{
 413    CMSDKAPBDualTimerModule *m = opaque;
 414
 415    m->intstatus = 1;
 416    cmsdk_apb_dualtimer_update(m->parent);
 417}
 418
 419static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m)
 420{
 421    m->control = R_CONTROL_INTEN_MASK;
 422    m->intstatus = 0;
 423    m->load = 0;
 424    m->value = 0xffffffff;
 425    ptimer_transaction_begin(m->timer);
 426    ptimer_stop(m->timer);
 427    /*
 428     * We start in free-running mode, with VALUE at 0xffffffff, and
 429     * in 16-bit counter mode. This means that the ptimer count and
 430     * limit must both be set to 0xffff, so we wrap at 16 bits.
 431     */
 432    ptimer_set_limit(m->timer, 0xffff, 1);
 433    ptimer_set_period_from_clock(m->timer, m->parent->timclk,
 434                                 cmsdk_dualtimermod_divisor(m));
 435    ptimer_transaction_commit(m->timer);
 436}
 437
 438static void cmsdk_apb_dualtimer_reset(DeviceState *dev)
 439{
 440    CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
 441    int i;
 442
 443    trace_cmsdk_apb_dualtimer_reset();
 444
 445    for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
 446        cmsdk_dualtimermod_reset(&s->timermod[i]);
 447    }
 448    s->timeritcr = 0;
 449    s->timeritop = 0;
 450}
 451
 452static void cmsdk_apb_dualtimer_clk_update(void *opaque, ClockEvent event)
 453{
 454    CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(opaque);
 455    int i;
 456
 457    for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
 458        CMSDKAPBDualTimerModule *m = &s->timermod[i];
 459        ptimer_transaction_begin(m->timer);
 460        ptimer_set_period_from_clock(m->timer, m->parent->timclk,
 461                                     cmsdk_dualtimermod_divisor(m));
 462        ptimer_transaction_commit(m->timer);
 463    }
 464}
 465
 466static void cmsdk_apb_dualtimer_init(Object *obj)
 467{
 468    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 469    CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(obj);
 470    int i;
 471
 472    memory_region_init_io(&s->iomem, obj, &cmsdk_apb_dualtimer_ops,
 473                          s, "cmsdk-apb-dualtimer", 0x1000);
 474    sysbus_init_mmio(sbd, &s->iomem);
 475    sysbus_init_irq(sbd, &s->timerintc);
 476
 477    for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
 478        sysbus_init_irq(sbd, &s->timermod[i].timerint);
 479    }
 480    s->timclk = qdev_init_clock_in(DEVICE(s), "TIMCLK",
 481                                   cmsdk_apb_dualtimer_clk_update, s,
 482                                   ClockUpdate);
 483}
 484
 485static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
 486{
 487    CMSDKAPBDualTimer *s = CMSDK_APB_DUALTIMER(dev);
 488    int i;
 489
 490    if (!clock_has_source(s->timclk)) {
 491        error_setg(errp, "CMSDK APB dualtimer: TIMCLK clock must be connected");
 492        return;
 493    }
 494
 495    for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
 496        CMSDKAPBDualTimerModule *m = &s->timermod[i];
 497
 498        m->parent = s;
 499        m->timer = ptimer_init(cmsdk_dualtimermod_tick, m,
 500                               PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
 501                               PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
 502                               PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
 503                               PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
 504    }
 505}
 506
 507static const VMStateDescription cmsdk_dualtimermod_vmstate = {
 508    .name = "cmsdk-apb-dualtimer-module",
 509    .version_id = 1,
 510    .minimum_version_id = 1,
 511    .fields = (VMStateField[]) {
 512        VMSTATE_PTIMER(timer, CMSDKAPBDualTimerModule),
 513        VMSTATE_UINT32(load, CMSDKAPBDualTimerModule),
 514        VMSTATE_UINT32(value, CMSDKAPBDualTimerModule),
 515        VMSTATE_UINT32(control, CMSDKAPBDualTimerModule),
 516        VMSTATE_UINT32(intstatus, CMSDKAPBDualTimerModule),
 517        VMSTATE_END_OF_LIST()
 518    }
 519};
 520
 521static const VMStateDescription cmsdk_apb_dualtimer_vmstate = {
 522    .name = "cmsdk-apb-dualtimer",
 523    .version_id = 2,
 524    .minimum_version_id = 2,
 525    .fields = (VMStateField[]) {
 526        VMSTATE_CLOCK(timclk, CMSDKAPBDualTimer),
 527        VMSTATE_STRUCT_ARRAY(timermod, CMSDKAPBDualTimer,
 528                             CMSDK_APB_DUALTIMER_NUM_MODULES,
 529                             1, cmsdk_dualtimermod_vmstate,
 530                             CMSDKAPBDualTimerModule),
 531        VMSTATE_UINT32(timeritcr, CMSDKAPBDualTimer),
 532        VMSTATE_UINT32(timeritop, CMSDKAPBDualTimer),
 533        VMSTATE_END_OF_LIST()
 534    }
 535};
 536
 537static void cmsdk_apb_dualtimer_class_init(ObjectClass *klass, void *data)
 538{
 539    DeviceClass *dc = DEVICE_CLASS(klass);
 540
 541    dc->realize = cmsdk_apb_dualtimer_realize;
 542    dc->vmsd = &cmsdk_apb_dualtimer_vmstate;
 543    dc->reset = cmsdk_apb_dualtimer_reset;
 544}
 545
 546static const TypeInfo cmsdk_apb_dualtimer_info = {
 547    .name = TYPE_CMSDK_APB_DUALTIMER,
 548    .parent = TYPE_SYS_BUS_DEVICE,
 549    .instance_size = sizeof(CMSDKAPBDualTimer),
 550    .instance_init = cmsdk_apb_dualtimer_init,
 551    .class_init = cmsdk_apb_dualtimer_class_init,
 552};
 553
 554static void cmsdk_apb_dualtimer_register_types(void)
 555{
 556    type_register_static(&cmsdk_apb_dualtimer_info);
 557}
 558
 559type_init(cmsdk_apb_dualtimer_register_types);
 560