qemu/hw/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.h"
  11#include "qemu-timer.h"
  12#include "sysemu.h"
  13#include "pxa.h"
  14#include "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
  63typedef struct PXA2xxTimerInfo PXA2xxTimerInfo;
  64
  65typedef struct {
  66    uint32_t value;
  67    qemu_irq irq;
  68    QEMUTimer *qtimer;
  69    int num;
  70    PXA2xxTimerInfo *info;
  71} PXA2xxTimer0;
  72
  73typedef struct {
  74    PXA2xxTimer0 tm;
  75    int32_t oldclock;
  76    int32_t clock;
  77    uint64_t lastload;
  78    uint32_t freq;
  79    uint32_t control;
  80} PXA2xxTimer4;
  81
  82struct PXA2xxTimerInfo {
  83    SysBusDevice busdev;
  84    MemoryRegion iomem;
  85    uint32_t flags;
  86
  87    int32_t clock;
  88    int32_t oldclock;
  89    uint64_t lastload;
  90    uint32_t freq;
  91    PXA2xxTimer0 timer[4];
  92    uint32_t events;
  93    uint32_t irq_enabled;
  94    uint32_t reset3;
  95    uint32_t snapshot;
  96
  97    qemu_irq irq4;
  98    PXA2xxTimer4 tm4[8];
  99};
 100
 101#define PXA2XX_TIMER_HAVE_TM4   0
 102
 103static inline int pxa2xx_timer_has_tm4(PXA2xxTimerInfo *s)
 104{
 105    return s->flags & (1 << PXA2XX_TIMER_HAVE_TM4);
 106}
 107
 108static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu)
 109{
 110    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
 111    int i;
 112    uint32_t now_vm;
 113    uint64_t new_qemu;
 114
 115    now_vm = s->clock +
 116            muldiv64(now_qemu - s->lastload, s->freq, get_ticks_per_sec());
 117
 118    for (i = 0; i < 4; i ++) {
 119        new_qemu = now_qemu + muldiv64((uint32_t) (s->timer[i].value - now_vm),
 120                        get_ticks_per_sec(), s->freq);
 121        qemu_mod_timer(s->timer[i].qtimer, new_qemu);
 122    }
 123}
 124
 125static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n)
 126{
 127    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
 128    uint32_t now_vm;
 129    uint64_t new_qemu;
 130    static const int counters[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
 131    int counter;
 132
 133    if (s->tm4[n].control & (1 << 7))
 134        counter = n;
 135    else
 136        counter = counters[n];
 137
 138    if (!s->tm4[counter].freq) {
 139        qemu_del_timer(s->tm4[n].tm.qtimer);
 140        return;
 141    }
 142
 143    now_vm = s->tm4[counter].clock + muldiv64(now_qemu -
 144                    s->tm4[counter].lastload,
 145                    s->tm4[counter].freq, get_ticks_per_sec());
 146
 147    new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].tm.value - now_vm),
 148                    get_ticks_per_sec(), s->tm4[counter].freq);
 149    qemu_mod_timer(s->tm4[n].tm.qtimer, new_qemu);
 150}
 151
 152static uint64_t pxa2xx_timer_read(void *opaque, hwaddr offset,
 153                                  unsigned size)
 154{
 155    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
 156    int tm = 0;
 157
 158    switch (offset) {
 159    case OSMR3:  tm ++;
 160    case OSMR2:  tm ++;
 161    case OSMR1:  tm ++;
 162    case OSMR0:
 163        return s->timer[tm].value;
 164    case OSMR11: tm ++;
 165    case OSMR10: tm ++;
 166    case OSMR9:  tm ++;
 167    case OSMR8:  tm ++;
 168    case OSMR7:  tm ++;
 169    case OSMR6:  tm ++;
 170    case OSMR5:  tm ++;
 171    case OSMR4:
 172        if (!pxa2xx_timer_has_tm4(s))
 173            goto badreg;
 174        return s->tm4[tm].tm.value;
 175    case OSCR:
 176        return s->clock + muldiv64(qemu_get_clock_ns(vm_clock) -
 177                        s->lastload, s->freq, get_ticks_per_sec());
 178    case OSCR11: tm ++;
 179    case OSCR10: tm ++;
 180    case OSCR9:  tm ++;
 181    case OSCR8:  tm ++;
 182    case OSCR7:  tm ++;
 183    case OSCR6:  tm ++;
 184    case OSCR5:  tm ++;
 185    case OSCR4:
 186        if (!pxa2xx_timer_has_tm4(s))
 187            goto badreg;
 188
 189        if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) {
 190            if (s->tm4[tm - 1].freq)
 191                s->snapshot = s->tm4[tm - 1].clock + muldiv64(
 192                                qemu_get_clock_ns(vm_clock) -
 193                                s->tm4[tm - 1].lastload,
 194                                s->tm4[tm - 1].freq, get_ticks_per_sec());
 195            else
 196                s->snapshot = s->tm4[tm - 1].clock;
 197        }
 198
 199        if (!s->tm4[tm].freq)
 200            return s->tm4[tm].clock;
 201        return s->tm4[tm].clock + muldiv64(qemu_get_clock_ns(vm_clock) -
 202                        s->tm4[tm].lastload, s->tm4[tm].freq, get_ticks_per_sec());
 203    case OIER:
 204        return s->irq_enabled;
 205    case OSSR:  /* Status register */
 206        return s->events;
 207    case OWER:
 208        return s->reset3;
 209    case OMCR11: tm ++;
 210    case OMCR10: tm ++;
 211    case OMCR9:  tm ++;
 212    case OMCR8:  tm ++;
 213    case OMCR7:  tm ++;
 214    case OMCR6:  tm ++;
 215    case OMCR5:  tm ++;
 216    case OMCR4:
 217        if (!pxa2xx_timer_has_tm4(s))
 218            goto badreg;
 219        return s->tm4[tm].control;
 220    case OSNR:
 221        return s->snapshot;
 222    default:
 223    badreg:
 224        hw_error("pxa2xx_timer_read: Bad offset " REG_FMT "\n", offset);
 225    }
 226
 227    return 0;
 228}
 229
 230static void pxa2xx_timer_write(void *opaque, hwaddr offset,
 231                               uint64_t value, unsigned size)
 232{
 233    int i, tm = 0;
 234    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
 235
 236    switch (offset) {
 237    case OSMR3:  tm ++;
 238    case OSMR2:  tm ++;
 239    case OSMR1:  tm ++;
 240    case OSMR0:
 241        s->timer[tm].value = value;
 242        pxa2xx_timer_update(s, qemu_get_clock_ns(vm_clock));
 243        break;
 244    case OSMR11: tm ++;
 245    case OSMR10: tm ++;
 246    case OSMR9:  tm ++;
 247    case OSMR8:  tm ++;
 248    case OSMR7:  tm ++;
 249    case OSMR6:  tm ++;
 250    case OSMR5:  tm ++;
 251    case OSMR4:
 252        if (!pxa2xx_timer_has_tm4(s))
 253            goto badreg;
 254        s->tm4[tm].tm.value = value;
 255        pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm);
 256        break;
 257    case OSCR:
 258        s->oldclock = s->clock;
 259        s->lastload = qemu_get_clock_ns(vm_clock);
 260        s->clock = value;
 261        pxa2xx_timer_update(s, s->lastload);
 262        break;
 263    case OSCR11: tm ++;
 264    case OSCR10: tm ++;
 265    case OSCR9:  tm ++;
 266    case OSCR8:  tm ++;
 267    case OSCR7:  tm ++;
 268    case OSCR6:  tm ++;
 269    case OSCR5:  tm ++;
 270    case OSCR4:
 271        if (!pxa2xx_timer_has_tm4(s))
 272            goto badreg;
 273        s->tm4[tm].oldclock = s->tm4[tm].clock;
 274        s->tm4[tm].lastload = qemu_get_clock_ns(vm_clock);
 275        s->tm4[tm].clock = value;
 276        pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm);
 277        break;
 278    case OIER:
 279        s->irq_enabled = value & 0xfff;
 280        break;
 281    case OSSR:  /* Status register */
 282        value &= s->events;
 283        s->events &= ~value;
 284        for (i = 0; i < 4; i ++, value >>= 1)
 285            if (value & 1)
 286                qemu_irq_lower(s->timer[i].irq);
 287        if (pxa2xx_timer_has_tm4(s) && !(s->events & 0xff0) && value)
 288            qemu_irq_lower(s->irq4);
 289        break;
 290    case OWER:  /* XXX: Reset on OSMR3 match? */
 291        s->reset3 = value;
 292        break;
 293    case OMCR7:  tm ++;
 294    case OMCR6:  tm ++;
 295    case OMCR5:  tm ++;
 296    case OMCR4:
 297        if (!pxa2xx_timer_has_tm4(s))
 298            goto badreg;
 299        s->tm4[tm].control = value & 0x0ff;
 300        /* XXX Stop if running (shouldn't happen) */
 301        if ((value & (1 << 7)) || tm == 0)
 302            s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7];
 303        else {
 304            s->tm4[tm].freq = 0;
 305            pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm);
 306        }
 307        break;
 308    case OMCR11: tm ++;
 309    case OMCR10: tm ++;
 310    case OMCR9:  tm ++;
 311    case OMCR8:  tm += 4;
 312        if (!pxa2xx_timer_has_tm4(s))
 313            goto badreg;
 314        s->tm4[tm].control = value & 0x3ff;
 315        /* XXX Stop if running (shouldn't happen) */
 316        if ((value & (1 << 7)) || !(tm & 1))
 317            s->tm4[tm].freq =
 318                    pxa2xx_timer4_freq[(value & (1 << 8)) ?  0 : (value & 7)];
 319        else {
 320            s->tm4[tm].freq = 0;
 321            pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm);
 322        }
 323        break;
 324    default:
 325    badreg:
 326        hw_error("pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset);
 327    }
 328}
 329
 330static const MemoryRegionOps pxa2xx_timer_ops = {
 331    .read = pxa2xx_timer_read,
 332    .write = pxa2xx_timer_write,
 333    .endianness = DEVICE_NATIVE_ENDIAN,
 334};
 335
 336static void pxa2xx_timer_tick(void *opaque)
 337{
 338    PXA2xxTimer0 *t = (PXA2xxTimer0 *) opaque;
 339    PXA2xxTimerInfo *i = t->info;
 340
 341    if (i->irq_enabled & (1 << t->num)) {
 342        i->events |= 1 << t->num;
 343        qemu_irq_raise(t->irq);
 344    }
 345
 346    if (t->num == 3)
 347        if (i->reset3 & 1) {
 348            i->reset3 = 0;
 349            qemu_system_reset_request();
 350        }
 351}
 352
 353static void pxa2xx_timer_tick4(void *opaque)
 354{
 355    PXA2xxTimer4 *t = (PXA2xxTimer4 *) opaque;
 356    PXA2xxTimerInfo *i = (PXA2xxTimerInfo *) t->tm.info;
 357
 358    pxa2xx_timer_tick(&t->tm);
 359    if (t->control & (1 << 3))
 360        t->clock = 0;
 361    if (t->control & (1 << 6))
 362        pxa2xx_timer_update4(i, qemu_get_clock_ns(vm_clock), t->tm.num - 4);
 363    if (i->events & 0xff0)
 364        qemu_irq_raise(i->irq4);
 365}
 366
 367static int pxa25x_timer_post_load(void *opaque, int version_id)
 368{
 369    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
 370    int64_t now;
 371    int i;
 372
 373    now = qemu_get_clock_ns(vm_clock);
 374    pxa2xx_timer_update(s, now);
 375
 376    if (pxa2xx_timer_has_tm4(s))
 377        for (i = 0; i < 8; i ++)
 378            pxa2xx_timer_update4(s, now, i);
 379
 380    return 0;
 381}
 382
 383static int pxa2xx_timer_init(SysBusDevice *dev)
 384{
 385    int i;
 386    PXA2xxTimerInfo *s;
 387
 388    s = FROM_SYSBUS(PXA2xxTimerInfo, dev);
 389    s->irq_enabled = 0;
 390    s->oldclock = 0;
 391    s->clock = 0;
 392    s->lastload = qemu_get_clock_ns(vm_clock);
 393    s->reset3 = 0;
 394
 395    for (i = 0; i < 4; i ++) {
 396        s->timer[i].value = 0;
 397        sysbus_init_irq(dev, &s->timer[i].irq);
 398        s->timer[i].info = s;
 399        s->timer[i].num = i;
 400        s->timer[i].qtimer = qemu_new_timer_ns(vm_clock,
 401                        pxa2xx_timer_tick, &s->timer[i]);
 402    }
 403    if (s->flags & (1 << PXA2XX_TIMER_HAVE_TM4)) {
 404        sysbus_init_irq(dev, &s->irq4);
 405
 406        for (i = 0; i < 8; i ++) {
 407            s->tm4[i].tm.value = 0;
 408            s->tm4[i].tm.info = s;
 409            s->tm4[i].tm.num = i + 4;
 410            s->tm4[i].freq = 0;
 411            s->tm4[i].control = 0x0;
 412            s->tm4[i].tm.qtimer = qemu_new_timer_ns(vm_clock,
 413                        pxa2xx_timer_tick4, &s->tm4[i]);
 414        }
 415    }
 416
 417    memory_region_init_io(&s->iomem, &pxa2xx_timer_ops, s,
 418                          "pxa2xx-timer", 0x00001000);
 419    sysbus_init_mmio(dev, &s->iomem);
 420
 421    return 0;
 422}
 423
 424static const VMStateDescription vmstate_pxa2xx_timer0_regs = {
 425    .name = "pxa2xx_timer0",
 426    .version_id = 2,
 427    .minimum_version_id = 2,
 428    .minimum_version_id_old = 2,
 429    .fields = (VMStateField[]) {
 430        VMSTATE_UINT32(value, PXA2xxTimer0),
 431        VMSTATE_END_OF_LIST(),
 432    },
 433};
 434
 435static const VMStateDescription vmstate_pxa2xx_timer4_regs = {
 436    .name = "pxa2xx_timer4",
 437    .version_id = 1,
 438    .minimum_version_id = 1,
 439    .minimum_version_id_old = 1,
 440    .fields = (VMStateField[]) {
 441        VMSTATE_STRUCT(tm, PXA2xxTimer4, 1,
 442                        vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
 443        VMSTATE_INT32(oldclock, PXA2xxTimer4),
 444        VMSTATE_INT32(clock, PXA2xxTimer4),
 445        VMSTATE_UINT64(lastload, PXA2xxTimer4),
 446        VMSTATE_UINT32(freq, PXA2xxTimer4),
 447        VMSTATE_UINT32(control, PXA2xxTimer4),
 448        VMSTATE_END_OF_LIST(),
 449    },
 450};
 451
 452static bool pxa2xx_timer_has_tm4_test(void *opaque, int version_id)
 453{
 454    return pxa2xx_timer_has_tm4(opaque);
 455}
 456
 457static const VMStateDescription vmstate_pxa2xx_timer_regs = {
 458    .name = "pxa2xx_timer",
 459    .version_id = 1,
 460    .minimum_version_id = 1,
 461    .minimum_version_id_old = 1,
 462    .post_load = pxa25x_timer_post_load,
 463    .fields = (VMStateField[]) {
 464        VMSTATE_INT32(clock, PXA2xxTimerInfo),
 465        VMSTATE_INT32(oldclock, PXA2xxTimerInfo),
 466        VMSTATE_UINT64(lastload, PXA2xxTimerInfo),
 467        VMSTATE_STRUCT_ARRAY(timer, PXA2xxTimerInfo, 4, 1,
 468                        vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
 469        VMSTATE_UINT32(events, PXA2xxTimerInfo),
 470        VMSTATE_UINT32(irq_enabled, PXA2xxTimerInfo),
 471        VMSTATE_UINT32(reset3, PXA2xxTimerInfo),
 472        VMSTATE_UINT32(snapshot, PXA2xxTimerInfo),
 473        VMSTATE_STRUCT_ARRAY_TEST(tm4, PXA2xxTimerInfo, 8,
 474                        pxa2xx_timer_has_tm4_test, 0,
 475                        vmstate_pxa2xx_timer4_regs, PXA2xxTimer4),
 476        VMSTATE_END_OF_LIST(),
 477    }
 478};
 479
 480static Property pxa25x_timer_dev_properties[] = {
 481    DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA25X_FREQ),
 482    DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
 483    PXA2XX_TIMER_HAVE_TM4, false),
 484    DEFINE_PROP_END_OF_LIST(),
 485};
 486
 487static void pxa25x_timer_dev_class_init(ObjectClass *klass, void *data)
 488{
 489    DeviceClass *dc = DEVICE_CLASS(klass);
 490    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 491
 492    k->init = pxa2xx_timer_init;
 493    dc->desc = "PXA25x timer";
 494    dc->vmsd = &vmstate_pxa2xx_timer_regs;
 495    dc->props = pxa25x_timer_dev_properties;
 496}
 497
 498static TypeInfo pxa25x_timer_dev_info = {
 499    .name          = "pxa25x-timer",
 500    .parent        = TYPE_SYS_BUS_DEVICE,
 501    .instance_size = sizeof(PXA2xxTimerInfo),
 502    .class_init    = pxa25x_timer_dev_class_init,
 503};
 504
 505static Property pxa27x_timer_dev_properties[] = {
 506    DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA27X_FREQ),
 507    DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
 508    PXA2XX_TIMER_HAVE_TM4, true),
 509    DEFINE_PROP_END_OF_LIST(),
 510};
 511
 512static void pxa27x_timer_dev_class_init(ObjectClass *klass, void *data)
 513{
 514    DeviceClass *dc = DEVICE_CLASS(klass);
 515    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
 516
 517    k->init = pxa2xx_timer_init;
 518    dc->desc = "PXA27x timer";
 519    dc->vmsd = &vmstate_pxa2xx_timer_regs;
 520    dc->props = pxa27x_timer_dev_properties;
 521}
 522
 523static TypeInfo pxa27x_timer_dev_info = {
 524    .name          = "pxa27x-timer",
 525    .parent        = TYPE_SYS_BUS_DEVICE,
 526    .instance_size = sizeof(PXA2xxTimerInfo),
 527    .class_init    = pxa27x_timer_dev_class_init,
 528};
 529
 530static void pxa2xx_timer_register_types(void)
 531{
 532    type_register_static(&pxa25x_timer_dev_info);
 533    type_register_static(&pxa27x_timer_dev_info);
 534}
 535
 536type_init(pxa2xx_timer_register_types)
 537