qemu/hw/timer/arm_timer.c
<<
>>
Prefs
   1/*
   2 * ARM PrimeCell Timer modules.
   3 *
   4 * Copyright (c) 2005-2006 CodeSourcery.
   5 * Written by Paul Brook
   6 *
   7 * This code is licensed under the GPL.
   8 */
   9
  10#include "qemu/osdep.h"
  11#include "hw/sysbus.h"
  12#include "migration/vmstate.h"
  13#include "qemu/timer.h"
  14#include "hw/irq.h"
  15#include "hw/ptimer.h"
  16#include "hw/qdev-properties.h"
  17#include "qemu/module.h"
  18#include "qemu/log.h"
  19#include "qom/object.h"
  20
  21/* Common timer implementation.  */
  22
  23#define TIMER_CTRL_ONESHOT      (1 << 0)
  24#define TIMER_CTRL_32BIT        (1 << 1)
  25#define TIMER_CTRL_DIV1         (0 << 2)
  26#define TIMER_CTRL_DIV16        (1 << 2)
  27#define TIMER_CTRL_DIV256       (2 << 2)
  28#define TIMER_CTRL_IE           (1 << 5)
  29#define TIMER_CTRL_PERIODIC     (1 << 6)
  30#define TIMER_CTRL_ENABLE       (1 << 7)
  31
  32typedef struct {
  33    ptimer_state *timer;
  34    uint32_t control;
  35    uint32_t limit;
  36    int freq;
  37    int int_level;
  38    qemu_irq irq;
  39} arm_timer_state;
  40
  41/* Check all active timers, and schedule the next timer interrupt.  */
  42
  43static void arm_timer_update(arm_timer_state *s)
  44{
  45    /* Update interrupts.  */
  46    if (s->int_level && (s->control & TIMER_CTRL_IE)) {
  47        qemu_irq_raise(s->irq);
  48    } else {
  49        qemu_irq_lower(s->irq);
  50    }
  51}
  52
  53static uint32_t arm_timer_read(void *opaque, hwaddr offset)
  54{
  55    arm_timer_state *s = (arm_timer_state *)opaque;
  56
  57    switch (offset >> 2) {
  58    case 0: /* TimerLoad */
  59    case 6: /* TimerBGLoad */
  60        return s->limit;
  61    case 1: /* TimerValue */
  62        return ptimer_get_count(s->timer);
  63    case 2: /* TimerControl */
  64        return s->control;
  65    case 4: /* TimerRIS */
  66        return s->int_level;
  67    case 5: /* TimerMIS */
  68        if ((s->control & TIMER_CTRL_IE) == 0)
  69            return 0;
  70        return s->int_level;
  71    default:
  72        qemu_log_mask(LOG_GUEST_ERROR,
  73                      "%s: Bad offset %x\n", __func__, (int)offset);
  74        return 0;
  75    }
  76}
  77
  78/*
  79 * Reset the timer limit after settings have changed.
  80 * May only be called from inside a ptimer transaction block.
  81 */
  82static void arm_timer_recalibrate(arm_timer_state *s, int reload)
  83{
  84    uint32_t limit;
  85
  86    if ((s->control & (TIMER_CTRL_PERIODIC | TIMER_CTRL_ONESHOT)) == 0) {
  87        /* Free running.  */
  88        if (s->control & TIMER_CTRL_32BIT)
  89            limit = 0xffffffff;
  90        else
  91            limit = 0xffff;
  92    } else {
  93          /* Periodic.  */
  94          limit = s->limit;
  95    }
  96    ptimer_set_limit(s->timer, limit, reload);
  97}
  98
  99static void arm_timer_write(void *opaque, hwaddr offset,
 100                            uint32_t value)
 101{
 102    arm_timer_state *s = (arm_timer_state *)opaque;
 103    int freq;
 104
 105    switch (offset >> 2) {
 106    case 0: /* TimerLoad */
 107        s->limit = value;
 108        ptimer_transaction_begin(s->timer);
 109        arm_timer_recalibrate(s, 1);
 110        ptimer_transaction_commit(s->timer);
 111        break;
 112    case 1: /* TimerValue */
 113        /* ??? Linux seems to want to write to this readonly register.
 114           Ignore it.  */
 115        break;
 116    case 2: /* TimerControl */
 117        ptimer_transaction_begin(s->timer);
 118        if (s->control & TIMER_CTRL_ENABLE) {
 119            /* Pause the timer if it is running.  This may cause some
 120               inaccuracy dure to rounding, but avoids a whole lot of other
 121               messyness.  */
 122            ptimer_stop(s->timer);
 123        }
 124        s->control = value;
 125        freq = s->freq;
 126        /* ??? Need to recalculate expiry time after changing divisor.  */
 127        switch ((value >> 2) & 3) {
 128        case 1: freq >>= 4; break;
 129        case 2: freq >>= 8; break;
 130        }
 131        arm_timer_recalibrate(s, s->control & TIMER_CTRL_ENABLE);
 132        ptimer_set_freq(s->timer, freq);
 133        if (s->control & TIMER_CTRL_ENABLE) {
 134            /* Restart the timer if still enabled.  */
 135            ptimer_run(s->timer, (s->control & TIMER_CTRL_ONESHOT) != 0);
 136        }
 137        ptimer_transaction_commit(s->timer);
 138        break;
 139    case 3: /* TimerIntClr */
 140        s->int_level = 0;
 141        break;
 142    case 6: /* TimerBGLoad */
 143        s->limit = value;
 144        ptimer_transaction_begin(s->timer);
 145        arm_timer_recalibrate(s, 0);
 146        ptimer_transaction_commit(s->timer);
 147        break;
 148    default:
 149        qemu_log_mask(LOG_GUEST_ERROR,
 150                      "%s: Bad offset %x\n", __func__, (int)offset);
 151    }
 152    arm_timer_update(s);
 153}
 154
 155static void arm_timer_tick(void *opaque)
 156{
 157    arm_timer_state *s = (arm_timer_state *)opaque;
 158    s->int_level = 1;
 159    arm_timer_update(s);
 160}
 161
 162static const VMStateDescription vmstate_arm_timer = {
 163    .name = "arm_timer",
 164    .version_id = 1,
 165    .minimum_version_id = 1,
 166    .fields = (VMStateField[]) {
 167        VMSTATE_UINT32(control, arm_timer_state),
 168        VMSTATE_UINT32(limit, arm_timer_state),
 169        VMSTATE_INT32(int_level, arm_timer_state),
 170        VMSTATE_PTIMER(timer, arm_timer_state),
 171        VMSTATE_END_OF_LIST()
 172    }
 173};
 174
 175static arm_timer_state *arm_timer_init(uint32_t freq)
 176{
 177    arm_timer_state *s;
 178
 179    s = (arm_timer_state *)g_malloc0(sizeof(arm_timer_state));
 180    s->freq = freq;
 181    s->control = TIMER_CTRL_IE;
 182
 183    s->timer = ptimer_init(arm_timer_tick, s, PTIMER_POLICY_DEFAULT);
 184    vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY, &vmstate_arm_timer, s);
 185    return s;
 186}
 187
 188/*
 189 * ARM PrimeCell SP804 dual timer module.
 190 * Docs at
 191 * https://developer.arm.com/documentation/ddi0271/latest/
 192 */
 193
 194#define TYPE_SP804 "sp804"
 195OBJECT_DECLARE_SIMPLE_TYPE(SP804State, SP804)
 196
 197struct SP804State {
 198    SysBusDevice parent_obj;
 199
 200    MemoryRegion iomem;
 201    arm_timer_state *timer[2];
 202    uint32_t freq0, freq1;
 203    int level[2];
 204    qemu_irq irq;
 205};
 206
 207static const uint8_t sp804_ids[] = {
 208    /* Timer ID */
 209    0x04, 0x18, 0x14, 0,
 210    /* PrimeCell ID */
 211    0xd, 0xf0, 0x05, 0xb1
 212};
 213
 214/* Merge the IRQs from the two component devices.  */
 215static void sp804_set_irq(void *opaque, int irq, int level)
 216{
 217    SP804State *s = (SP804State *)opaque;
 218
 219    s->level[irq] = level;
 220    qemu_set_irq(s->irq, s->level[0] || s->level[1]);
 221}
 222
 223static uint64_t sp804_read(void *opaque, hwaddr offset,
 224                           unsigned size)
 225{
 226    SP804State *s = (SP804State *)opaque;
 227
 228    if (offset < 0x20) {
 229        return arm_timer_read(s->timer[0], offset);
 230    }
 231    if (offset < 0x40) {
 232        return arm_timer_read(s->timer[1], offset - 0x20);
 233    }
 234
 235    /* TimerPeriphID */
 236    if (offset >= 0xfe0 && offset <= 0xffc) {
 237        return sp804_ids[(offset - 0xfe0) >> 2];
 238    }
 239
 240    switch (offset) {
 241    /* Integration Test control registers, which we won't support */
 242    case 0xf00: /* TimerITCR */
 243    case 0xf04: /* TimerITOP (strictly write only but..) */
 244        qemu_log_mask(LOG_UNIMP,
 245                      "%s: integration test registers unimplemented\n",
 246                      __func__);
 247        return 0;
 248    }
 249
 250    qemu_log_mask(LOG_GUEST_ERROR,
 251                  "%s: Bad offset %x\n", __func__, (int)offset);
 252    return 0;
 253}
 254
 255static void sp804_write(void *opaque, hwaddr offset,
 256                        uint64_t value, unsigned size)
 257{
 258    SP804State *s = (SP804State *)opaque;
 259
 260    if (offset < 0x20) {
 261        arm_timer_write(s->timer[0], offset, value);
 262        return;
 263    }
 264
 265    if (offset < 0x40) {
 266        arm_timer_write(s->timer[1], offset - 0x20, value);
 267        return;
 268    }
 269
 270    /* Technically we could be writing to the Test Registers, but not likely */
 271    qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %x\n",
 272                  __func__, (int)offset);
 273}
 274
 275static const MemoryRegionOps sp804_ops = {
 276    .read = sp804_read,
 277    .write = sp804_write,
 278    .endianness = DEVICE_NATIVE_ENDIAN,
 279};
 280
 281static const VMStateDescription vmstate_sp804 = {
 282    .name = "sp804",
 283    .version_id = 1,
 284    .minimum_version_id = 1,
 285    .fields = (VMStateField[]) {
 286        VMSTATE_INT32_ARRAY(level, SP804State, 2),
 287        VMSTATE_END_OF_LIST()
 288    }
 289};
 290
 291static void sp804_init(Object *obj)
 292{
 293    SP804State *s = SP804(obj);
 294    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 295
 296    sysbus_init_irq(sbd, &s->irq);
 297    memory_region_init_io(&s->iomem, obj, &sp804_ops, s,
 298                          "sp804", 0x1000);
 299    sysbus_init_mmio(sbd, &s->iomem);
 300}
 301
 302static void sp804_realize(DeviceState *dev, Error **errp)
 303{
 304    SP804State *s = SP804(dev);
 305
 306    s->timer[0] = arm_timer_init(s->freq0);
 307    s->timer[1] = arm_timer_init(s->freq1);
 308    s->timer[0]->irq = qemu_allocate_irq(sp804_set_irq, s, 0);
 309    s->timer[1]->irq = qemu_allocate_irq(sp804_set_irq, s, 1);
 310}
 311
 312/* Integrator/CP timer module.  */
 313
 314#define TYPE_INTEGRATOR_PIT "integrator_pit"
 315OBJECT_DECLARE_SIMPLE_TYPE(icp_pit_state, INTEGRATOR_PIT)
 316
 317struct icp_pit_state {
 318    SysBusDevice parent_obj;
 319
 320    MemoryRegion iomem;
 321    arm_timer_state *timer[3];
 322};
 323
 324static uint64_t icp_pit_read(void *opaque, hwaddr offset,
 325                             unsigned size)
 326{
 327    icp_pit_state *s = (icp_pit_state *)opaque;
 328    int n;
 329
 330    /* ??? Don't know the PrimeCell ID for this device.  */
 331    n = offset >> 8;
 332    if (n > 2) {
 333        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad timer %d\n", __func__, n);
 334        return 0;
 335    }
 336
 337    return arm_timer_read(s->timer[n], offset & 0xff);
 338}
 339
 340static void icp_pit_write(void *opaque, hwaddr offset,
 341                          uint64_t value, unsigned size)
 342{
 343    icp_pit_state *s = (icp_pit_state *)opaque;
 344    int n;
 345
 346    n = offset >> 8;
 347    if (n > 2) {
 348        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad timer %d\n", __func__, n);
 349        return;
 350    }
 351
 352    arm_timer_write(s->timer[n], offset & 0xff, value);
 353}
 354
 355static const MemoryRegionOps icp_pit_ops = {
 356    .read = icp_pit_read,
 357    .write = icp_pit_write,
 358    .endianness = DEVICE_NATIVE_ENDIAN,
 359};
 360
 361static void icp_pit_init(Object *obj)
 362{
 363    icp_pit_state *s = INTEGRATOR_PIT(obj);
 364    SysBusDevice *dev = SYS_BUS_DEVICE(obj);
 365
 366    /* Timer 0 runs at the system clock speed (40MHz).  */
 367    s->timer[0] = arm_timer_init(40000000);
 368    /* The other two timers run at 1MHz.  */
 369    s->timer[1] = arm_timer_init(1000000);
 370    s->timer[2] = arm_timer_init(1000000);
 371
 372    sysbus_init_irq(dev, &s->timer[0]->irq);
 373    sysbus_init_irq(dev, &s->timer[1]->irq);
 374    sysbus_init_irq(dev, &s->timer[2]->irq);
 375
 376    memory_region_init_io(&s->iomem, obj, &icp_pit_ops, s,
 377                          "icp_pit", 0x1000);
 378    sysbus_init_mmio(dev, &s->iomem);
 379    /* This device has no state to save/restore.  The component timers will
 380       save themselves.  */
 381}
 382
 383static const TypeInfo icp_pit_info = {
 384    .name          = TYPE_INTEGRATOR_PIT,
 385    .parent        = TYPE_SYS_BUS_DEVICE,
 386    .instance_size = sizeof(icp_pit_state),
 387    .instance_init = icp_pit_init,
 388};
 389
 390static Property sp804_properties[] = {
 391    DEFINE_PROP_UINT32("freq0", SP804State, freq0, 1000000),
 392    DEFINE_PROP_UINT32("freq1", SP804State, freq1, 1000000),
 393    DEFINE_PROP_END_OF_LIST(),
 394};
 395
 396static void sp804_class_init(ObjectClass *klass, void *data)
 397{
 398    DeviceClass *k = DEVICE_CLASS(klass);
 399
 400    k->realize = sp804_realize;
 401    device_class_set_props(k, sp804_properties);
 402    k->vmsd = &vmstate_sp804;
 403}
 404
 405static const TypeInfo sp804_info = {
 406    .name          = TYPE_SP804,
 407    .parent        = TYPE_SYS_BUS_DEVICE,
 408    .instance_size = sizeof(SP804State),
 409    .instance_init = sp804_init,
 410    .class_init    = sp804_class_init,
 411};
 412
 413static void arm_timer_register_types(void)
 414{
 415    type_register_static(&icp_pit_info);
 416    type_register_static(&sp804_info);
 417}
 418
 419type_init(arm_timer_register_types)
 420