qemu/hw/timer/pxa2xx_timer.c
<<
>>
Prefs
   1/*
   2 * Intel XScale PXA255/270 OS Timers.
   3 *
   4 * Copyright (c) 2006 Openedhand Ltd.
   5 * Copyright (c) 2006 Thorsten Zitterell
   6 *
   7 * This code is licensed under the GPL.
   8 */
   9
  10#include "hw/hw.h"
  11#include "qemu/timer.h"
  12#include "sysemu/sysemu.h"
  13#include "hw/arm/pxa.h"
  14#include "hw/sysbus.h"
  15
  16#define OSMR0   0x00
  17#define OSMR1   0x04
  18#define OSMR2   0x08
  19#define OSMR3   0x0c
  20#define OSMR4   0x80
  21#define OSMR5   0x84
  22#define OSMR6   0x88
  23#define OSMR7   0x8c
  24#define OSMR8   0x90
  25#define OSMR9   0x94
  26#define OSMR10  0x98
  27#define OSMR11  0x9c
  28#define OSCR    0x10    /* OS Timer Count */
  29#define OSCR4   0x40
  30#define OSCR5   0x44
  31#define OSCR6   0x48
  32#define OSCR7   0x4c
  33#define OSCR8   0x50
  34#define OSCR9   0x54
  35#define OSCR10  0x58
  36#define OSCR11  0x5c
  37#define OSSR    0x14    /* Timer status register */
  38#define OWER    0x18
  39#define OIER    0x1c    /* Interrupt enable register  3-0 to E3-E0 */
  40#define OMCR4   0xc0    /* OS Match Control registers */
  41#define OMCR5   0xc4
  42#define OMCR6   0xc8
  43#define OMCR7   0xcc
  44#define OMCR8   0xd0
  45#define OMCR9   0xd4
  46#define OMCR10  0xd8
  47#define OMCR11  0xdc
  48#define OSNR    0x20
  49
  50#define PXA25X_FREQ     3686400 /* 3.6864 MHz */
  51#define PXA27X_FREQ     3250000 /* 3.25 MHz */
  52
  53static int pxa2xx_timer4_freq[8] = {
  54    [0] = 0,
  55    [1] = 32768,
  56    [2] = 1000,
  57    [3] = 1,
  58    [4] = 1000000,
  59    /* [5] is the "Externally supplied clock".  Assign if necessary.  */
  60    [5 ... 7] = 0,
  61};
  62
  63#define TYPE_PXA2XX_TIMER "pxa2xx-timer"
  64#define PXA2XX_TIMER(obj) \
  65    OBJECT_CHECK(PXA2xxTimerInfo, (obj), TYPE_PXA2XX_TIMER)
  66
  67typedef struct PXA2xxTimerInfo PXA2xxTimerInfo;
  68
  69typedef struct {
  70    uint32_t value;
  71    qemu_irq irq;
  72    QEMUTimer *qtimer;
  73    int num;
  74    PXA2xxTimerInfo *info;
  75} PXA2xxTimer0;
  76
  77typedef struct {
  78    PXA2xxTimer0 tm;
  79    int32_t oldclock;
  80    int32_t clock;
  81    uint64_t lastload;
  82    uint32_t freq;
  83    uint32_t control;
  84} PXA2xxTimer4;
  85
  86struct PXA2xxTimerInfo {
  87    SysBusDevice parent_obj;
  88
  89    MemoryRegion iomem;
  90    uint32_t flags;
  91
  92    int32_t clock;
  93    int32_t oldclock;
  94    uint64_t lastload;
  95    uint32_t freq;
  96    PXA2xxTimer0 timer[4];
  97    uint32_t events;
  98    uint32_t irq_enabled;
  99    uint32_t reset3;
 100    uint32_t snapshot;
 101
 102    qemu_irq irq4;
 103    PXA2xxTimer4 tm4[8];
 104};
 105
 106#define PXA2XX_TIMER_HAVE_TM4   0
 107
 108static inline int pxa2xx_timer_has_tm4(PXA2xxTimerInfo *s)
 109{
 110    return s->flags & (1 << PXA2XX_TIMER_HAVE_TM4);
 111}
 112
 113static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu)
 114{
 115    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
 116    int i;
 117    uint32_t now_vm;
 118    uint64_t new_qemu;
 119
 120    now_vm = s->clock +
 121            muldiv64(now_qemu - s->lastload, s->freq, get_ticks_per_sec());
 122
 123    for (i = 0; i < 4; i ++) {
 124        new_qemu = now_qemu + muldiv64((uint32_t) (s->timer[i].value - now_vm),
 125                        get_ticks_per_sec(), s->freq);
 126        qemu_mod_timer(s->timer[i].qtimer, new_qemu);
 127    }
 128}
 129
 130static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n)
 131{
 132    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
 133    uint32_t now_vm;
 134    uint64_t new_qemu;
 135    static const int counters[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
 136    int counter;
 137
 138    if (s->tm4[n].control & (1 << 7))
 139        counter = n;
 140    else
 141        counter = counters[n];
 142
 143    if (!s->tm4[counter].freq) {
 144        qemu_del_timer(s->tm4[n].tm.qtimer);
 145        return;
 146    }
 147
 148    now_vm = s->tm4[counter].clock + muldiv64(now_qemu -
 149                    s->tm4[counter].lastload,
 150                    s->tm4[counter].freq, get_ticks_per_sec());
 151
 152    new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].tm.value - now_vm),
 153                    get_ticks_per_sec(), s->tm4[counter].freq);
 154    qemu_mod_timer(s->tm4[n].tm.qtimer, new_qemu);
 155}
 156
 157static uint64_t pxa2xx_timer_read(void *opaque, hwaddr offset,
 158                                  unsigned size)
 159{
 160    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
 161    int tm = 0;
 162
 163    switch (offset) {
 164    case OSMR3:  tm ++;
 165        /* fall through */
 166    case OSMR2:  tm ++;
 167        /* fall through */
 168    case OSMR1:  tm ++;
 169        /* fall through */
 170    case OSMR0:
 171        return s->timer[tm].value;
 172    case OSMR11: tm ++;
 173        /* fall through */
 174    case OSMR10: tm ++;
 175        /* fall through */
 176    case OSMR9:  tm ++;
 177        /* fall through */
 178    case OSMR8:  tm ++;
 179        /* fall through */
 180    case OSMR7:  tm ++;
 181        /* fall through */
 182    case OSMR6:  tm ++;
 183        /* fall through */
 184    case OSMR5:  tm ++;
 185        /* fall through */
 186    case OSMR4:
 187        if (!pxa2xx_timer_has_tm4(s))
 188            goto badreg;
 189        return s->tm4[tm].tm.value;
 190    case OSCR:
 191        return s->clock + muldiv64(qemu_get_clock_ns(vm_clock) -
 192                        s->lastload, s->freq, get_ticks_per_sec());
 193    case OSCR11: tm ++;
 194        /* fall through */
 195    case OSCR10: tm ++;
 196        /* fall through */
 197    case OSCR9:  tm ++;
 198        /* fall through */
 199    case OSCR8:  tm ++;
 200        /* fall through */
 201    case OSCR7:  tm ++;
 202        /* fall through */
 203    case OSCR6:  tm ++;
 204        /* fall through */
 205    case OSCR5:  tm ++;
 206        /* fall through */
 207    case OSCR4:
 208        if (!pxa2xx_timer_has_tm4(s))
 209            goto badreg;
 210
 211        if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) {
 212            if (s->tm4[tm - 1].freq)
 213                s->snapshot = s->tm4[tm - 1].clock + muldiv64(
 214                                qemu_get_clock_ns(vm_clock) -
 215                                s->tm4[tm - 1].lastload,
 216                                s->tm4[tm - 1].freq, get_ticks_per_sec());
 217            else
 218                s->snapshot = s->tm4[tm - 1].clock;
 219        }
 220
 221        if (!s->tm4[tm].freq)
 222            return s->tm4[tm].clock;
 223        return s->tm4[tm].clock + muldiv64(qemu_get_clock_ns(vm_clock) -
 224                        s->tm4[tm].lastload, s->tm4[tm].freq, get_ticks_per_sec());
 225    case OIER:
 226        return s->irq_enabled;
 227    case OSSR:  /* Status register */
 228        return s->events;
 229    case OWER:
 230        return s->reset3;
 231    case OMCR11: tm ++;
 232        /* fall through */
 233    case OMCR10: tm ++;
 234        /* fall through */
 235    case OMCR9:  tm ++;
 236        /* fall through */
 237    case OMCR8:  tm ++;
 238        /* fall through */
 239    case OMCR7:  tm ++;
 240        /* fall through */
 241    case OMCR6:  tm ++;
 242        /* fall through */
 243    case OMCR5:  tm ++;
 244        /* fall through */
 245    case OMCR4:
 246        if (!pxa2xx_timer_has_tm4(s))
 247            goto badreg;
 248        return s->tm4[tm].control;
 249    case OSNR:
 250        return s->snapshot;
 251    default:
 252    badreg:
 253        hw_error("pxa2xx_timer_read: Bad offset " REG_FMT "\n", offset);
 254    }
 255
 256    return 0;
 257}
 258
 259static void pxa2xx_timer_write(void *opaque, hwaddr offset,
 260                               uint64_t value, unsigned size)
 261{
 262    int i, tm = 0;
 263    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
 264
 265    switch (offset) {
 266    case OSMR3:  tm ++;
 267        /* fall through */
 268    case OSMR2:  tm ++;
 269        /* fall through */
 270    case OSMR1:  tm ++;
 271        /* fall through */
 272    case OSMR0:
 273        s->timer[tm].value = value;
 274        pxa2xx_timer_update(s, qemu_get_clock_ns(vm_clock));
 275        break;
 276    case OSMR11: tm ++;
 277        /* fall through */
 278    case OSMR10: tm ++;
 279        /* fall through */
 280    case OSMR9:  tm ++;
 281        /* fall through */
 282    case OSMR8:  tm ++;
 283        /* fall through */
 284    case OSMR7:  tm ++;
 285        /* fall through */
 286    case OSMR6:  tm ++;
 287        /* fall through */
 288    case OSMR5:  tm ++;
 289        /* fall through */
 290    case OSMR4:
 291        if (!pxa2xx_timer_has_tm4(s))
 292            goto badreg;
 293        s->tm4[tm].tm.value = value;
 294        pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm);
 295        break;
 296    case OSCR:
 297        s->oldclock = s->clock;
 298        s->lastload = qemu_get_clock_ns(vm_clock);
 299        s->clock = value;
 300        pxa2xx_timer_update(s, s->lastload);
 301        break;
 302    case OSCR11: tm ++;
 303        /* fall through */
 304    case OSCR10: tm ++;
 305        /* fall through */
 306    case OSCR9:  tm ++;
 307        /* fall through */
 308    case OSCR8:  tm ++;
 309        /* fall through */
 310    case OSCR7:  tm ++;
 311        /* fall through */
 312    case OSCR6:  tm ++;
 313        /* fall through */
 314    case OSCR5:  tm ++;
 315        /* fall through */
 316    case OSCR4:
 317        if (!pxa2xx_timer_has_tm4(s))
 318            goto badreg;
 319        s->tm4[tm].oldclock = s->tm4[tm].clock;
 320        s->tm4[tm].lastload = qemu_get_clock_ns(vm_clock);
 321        s->tm4[tm].clock = value;
 322        pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm);
 323        break;
 324    case OIER:
 325        s->irq_enabled = value & 0xfff;
 326        break;
 327    case OSSR:  /* Status register */
 328        value &= s->events;
 329        s->events &= ~value;
 330        for (i = 0; i < 4; i ++, value >>= 1)
 331            if (value & 1)
 332                qemu_irq_lower(s->timer[i].irq);
 333        if (pxa2xx_timer_has_tm4(s) && !(s->events & 0xff0) && value)
 334            qemu_irq_lower(s->irq4);
 335        break;
 336    case OWER:  /* XXX: Reset on OSMR3 match? */
 337        s->reset3 = value;
 338        break;
 339    case OMCR7:  tm ++;
 340        /* fall through */
 341    case OMCR6:  tm ++;
 342        /* fall through */
 343    case OMCR5:  tm ++;
 344        /* fall through */
 345    case OMCR4:
 346        if (!pxa2xx_timer_has_tm4(s))
 347            goto badreg;
 348        s->tm4[tm].control = value & 0x0ff;
 349        /* XXX Stop if running (shouldn't happen) */
 350        if ((value & (1 << 7)) || tm == 0)
 351            s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7];
 352        else {
 353            s->tm4[tm].freq = 0;
 354            pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm);
 355        }
 356        break;
 357    case OMCR11: tm ++;
 358        /* fall through */
 359    case OMCR10: tm ++;
 360        /* fall through */
 361    case OMCR9:  tm ++;
 362        /* fall through */
 363    case OMCR8:  tm += 4;
 364        if (!pxa2xx_timer_has_tm4(s))
 365            goto badreg;
 366        s->tm4[tm].control = value & 0x3ff;
 367        /* XXX Stop if running (shouldn't happen) */
 368        if ((value & (1 << 7)) || !(tm & 1))
 369            s->tm4[tm].freq =
 370                    pxa2xx_timer4_freq[(value & (1 << 8)) ?  0 : (value & 7)];
 371        else {
 372            s->tm4[tm].freq = 0;
 373            pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm);
 374        }
 375        break;
 376    default:
 377    badreg:
 378        hw_error("pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset);
 379    }
 380}
 381
 382static const MemoryRegionOps pxa2xx_timer_ops = {
 383    .read = pxa2xx_timer_read,
 384    .write = pxa2xx_timer_write,
 385    .endianness = DEVICE_NATIVE_ENDIAN,
 386};
 387
 388static void pxa2xx_timer_tick(void *opaque)
 389{
 390    PXA2xxTimer0 *t = (PXA2xxTimer0 *) opaque;
 391    PXA2xxTimerInfo *i = t->info;
 392
 393    if (i->irq_enabled & (1 << t->num)) {
 394        i->events |= 1 << t->num;
 395        qemu_irq_raise(t->irq);
 396    }
 397
 398    if (t->num == 3)
 399        if (i->reset3 & 1) {
 400            i->reset3 = 0;
 401            qemu_system_reset_request();
 402        }
 403}
 404
 405static void pxa2xx_timer_tick4(void *opaque)
 406{
 407    PXA2xxTimer4 *t = (PXA2xxTimer4 *) opaque;
 408    PXA2xxTimerInfo *i = (PXA2xxTimerInfo *) t->tm.info;
 409
 410    pxa2xx_timer_tick(&t->tm);
 411    if (t->control & (1 << 3))
 412        t->clock = 0;
 413    if (t->control & (1 << 6))
 414        pxa2xx_timer_update4(i, qemu_get_clock_ns(vm_clock), t->tm.num - 4);
 415    if (i->events & 0xff0)
 416        qemu_irq_raise(i->irq4);
 417}
 418
 419static int pxa25x_timer_post_load(void *opaque, int version_id)
 420{
 421    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
 422    int64_t now;
 423    int i;
 424
 425    now = qemu_get_clock_ns(vm_clock);
 426    pxa2xx_timer_update(s, now);
 427
 428    if (pxa2xx_timer_has_tm4(s))
 429        for (i = 0; i < 8; i ++)
 430            pxa2xx_timer_update4(s, now, i);
 431
 432    return 0;
 433}
 434
 435static int pxa2xx_timer_init(SysBusDevice *dev)
 436{
 437    PXA2xxTimerInfo *s = PXA2XX_TIMER(dev);
 438    int i;
 439
 440    s->irq_enabled = 0;
 441    s->oldclock = 0;
 442    s->clock = 0;
 443    s->lastload = qemu_get_clock_ns(vm_clock);
 444    s->reset3 = 0;
 445
 446    for (i = 0; i < 4; i ++) {
 447        s->timer[i].value = 0;
 448        sysbus_init_irq(dev, &s->timer[i].irq);
 449        s->timer[i].info = s;
 450        s->timer[i].num = i;
 451        s->timer[i].qtimer = qemu_new_timer_ns(vm_clock,
 452                        pxa2xx_timer_tick, &s->timer[i]);
 453    }
 454    if (s->flags & (1 << PXA2XX_TIMER_HAVE_TM4)) {
 455        sysbus_init_irq(dev, &s->irq4);
 456
 457        for (i = 0; i < 8; i ++) {
 458            s->tm4[i].tm.value = 0;
 459            s->tm4[i].tm.info = s;
 460            s->tm4[i].tm.num = i + 4;
 461            s->tm4[i].freq = 0;
 462            s->tm4[i].control = 0x0;
 463            s->tm4[i].tm.qtimer = qemu_new_timer_ns(vm_clock,
 464                        pxa2xx_timer_tick4, &s->tm4[i]);
 465        }
 466    }
 467
 468    memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_timer_ops, s,
 469                          "pxa2xx-timer", 0x00001000);
 470    sysbus_init_mmio(dev, &s->iomem);
 471
 472    return 0;
 473}
 474
 475static const VMStateDescription vmstate_pxa2xx_timer0_regs = {
 476    .name = "pxa2xx_timer0",
 477    .version_id = 2,
 478    .minimum_version_id = 2,
 479    .minimum_version_id_old = 2,
 480    .fields = (VMStateField[]) {
 481        VMSTATE_UINT32(value, PXA2xxTimer0),
 482        VMSTATE_END_OF_LIST(),
 483    },
 484};
 485
 486static const VMStateDescription vmstate_pxa2xx_timer4_regs = {
 487    .name = "pxa2xx_timer4",
 488    .version_id = 1,
 489    .minimum_version_id = 1,
 490    .minimum_version_id_old = 1,
 491    .fields = (VMStateField[]) {
 492        VMSTATE_STRUCT(tm, PXA2xxTimer4, 1,
 493                        vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
 494        VMSTATE_INT32(oldclock, PXA2xxTimer4),
 495        VMSTATE_INT32(clock, PXA2xxTimer4),
 496        VMSTATE_UINT64(lastload, PXA2xxTimer4),
 497        VMSTATE_UINT32(freq, PXA2xxTimer4),
 498        VMSTATE_UINT32(control, PXA2xxTimer4),
 499        VMSTATE_END_OF_LIST(),
 500    },
 501};
 502
 503static bool pxa2xx_timer_has_tm4_test(void *opaque, int version_id)
 504{
 505    return pxa2xx_timer_has_tm4(opaque);
 506}
 507
 508static const VMStateDescription vmstate_pxa2xx_timer_regs = {
 509    .name = "pxa2xx_timer",
 510    .version_id = 1,
 511    .minimum_version_id = 1,
 512    .minimum_version_id_old = 1,
 513    .post_load = pxa25x_timer_post_load,
 514    .fields = (VMStateField[]) {
 515        VMSTATE_INT32(clock, PXA2xxTimerInfo),
 516        VMSTATE_INT32(oldclock, PXA2xxTimerInfo),
 517        VMSTATE_UINT64(lastload, PXA2xxTimerInfo),
 518        VMSTATE_STRUCT_ARRAY(timer, PXA2xxTimerInfo, 4, 1,
 519                        vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
 520        VMSTATE_UINT32(events, PXA2xxTimerInfo),
 521        VMSTATE_UINT32(irq_enabled, PXA2xxTimerInfo),
 522        VMSTATE_UINT32(reset3, PXA2xxTimerInfo),
 523        VMSTATE_UINT32(snapshot, PXA2xxTimerInfo),
 524        VMSTATE_STRUCT_ARRAY_TEST(tm4, PXA2xxTimerInfo, 8,
 525                        pxa2xx_timer_has_tm4_test, 0,
 526                        vmstate_pxa2xx_timer4_regs, PXA2xxTimer4),
 527        VMSTATE_END_OF_LIST(),
 528    }
 529};
 530
 531static Property pxa25x_timer_dev_properties[] = {
 532    DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA25X_FREQ),
 533    DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
 534                    PXA2XX_TIMER_HAVE_TM4, false),
 535    DEFINE_PROP_END_OF_LIST(),
 536};
 537
 538static void pxa25x_timer_dev_class_init(ObjectClass *klass, void *data)
 539{
 540    DeviceClass *dc = DEVICE_CLASS(klass);
 541
 542    dc->desc = "PXA25x timer";
 543    dc->props = pxa25x_timer_dev_properties;
 544}
 545
 546static const TypeInfo pxa25x_timer_dev_info = {
 547    .name          = "pxa25x-timer",
 548    .parent        = TYPE_PXA2XX_TIMER,
 549    .instance_size = sizeof(PXA2xxTimerInfo),
 550    .class_init    = pxa25x_timer_dev_class_init,
 551};
 552
 553static Property pxa27x_timer_dev_properties[] = {
 554    DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA27X_FREQ),
 555    DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
 556                    PXA2XX_TIMER_HAVE_TM4, true),
 557    DEFINE_PROP_END_OF_LIST(),
 558};
 559
 560static void pxa27x_timer_dev_class_init(ObjectClass *klass, void *data)
 561{
 562    DeviceClass *dc = DEVICE_CLASS(klass);
 563
 564    dc->desc = "PXA27x timer";
 565    dc->props = pxa27x_timer_dev_properties;
 566}
 567
 568static const TypeInfo pxa27x_timer_dev_info = {
 569    .name          = "pxa27x-timer",
 570    .parent        = TYPE_PXA2XX_TIMER,
 571    .instance_size = sizeof(PXA2xxTimerInfo),
 572    .class_init    = pxa27x_timer_dev_class_init,
 573};
 574
 575static void pxa2xx_timer_class_init(ObjectClass *oc, void *data)
 576{
 577    DeviceClass *dc = DEVICE_CLASS(oc);
 578    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(oc);
 579
 580    sdc->init = pxa2xx_timer_init;
 581    dc->vmsd = &vmstate_pxa2xx_timer_regs;
 582}
 583
 584static const TypeInfo pxa2xx_timer_type_info = {
 585    .name          = TYPE_PXA2XX_TIMER,
 586    .parent        = TYPE_SYS_BUS_DEVICE,
 587    .instance_size = sizeof(PXA2xxTimerInfo),
 588    .abstract      = true,
 589    .class_init    = pxa2xx_timer_class_init,
 590};
 591
 592static void pxa2xx_timer_register_types(void)
 593{
 594    type_register_static(&pxa2xx_timer_type_info);
 595    type_register_static(&pxa25x_timer_dev_info);
 596    type_register_static(&pxa27x_timer_dev_info);
 597}
 598
 599type_init(pxa2xx_timer_register_types)
 600