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 licenced under the GPL.
   8 */
   9
  10#include "hw.h"
  11#include "qemu-timer.h"
  12#include "sysemu.h"
  13#include "pxa.h"
  14
  15#define OSMR0   0x00
  16#define OSMR1   0x04
  17#define OSMR2   0x08
  18#define OSMR3   0x0c
  19#define OSMR4   0x80
  20#define OSMR5   0x84
  21#define OSMR6   0x88
  22#define OSMR7   0x8c
  23#define OSMR8   0x90
  24#define OSMR9   0x94
  25#define OSMR10  0x98
  26#define OSMR11  0x9c
  27#define OSCR    0x10    /* OS Timer Count */
  28#define OSCR4   0x40
  29#define OSCR5   0x44
  30#define OSCR6   0x48
  31#define OSCR7   0x4c
  32#define OSCR8   0x50
  33#define OSCR9   0x54
  34#define OSCR10  0x58
  35#define OSCR11  0x5c
  36#define OSSR    0x14    /* Timer status register */
  37#define OWER    0x18
  38#define OIER    0x1c    /* Interrupt enable register  3-0 to E3-E0 */
  39#define OMCR4   0xc0    /* OS Match Control registers */
  40#define OMCR5   0xc4
  41#define OMCR6   0xc8
  42#define OMCR7   0xcc
  43#define OMCR8   0xd0
  44#define OMCR9   0xd4
  45#define OMCR10  0xd8
  46#define OMCR11  0xdc
  47#define OSNR    0x20
  48
  49#define PXA25X_FREQ     3686400 /* 3.6864 MHz */
  50#define PXA27X_FREQ     3250000 /* 3.25 MHz */
  51
  52static int pxa2xx_timer4_freq[8] = {
  53    [0] = 0,
  54    [1] = 32768,
  55    [2] = 1000,
  56    [3] = 1,
  57    [4] = 1000000,
  58    /* [5] is the "Externally supplied clock".  Assign if necessary.  */
  59    [5 ... 7] = 0,
  60};
  61
  62typedef struct {
  63    uint32_t value;
  64    int level;
  65    qemu_irq irq;
  66    QEMUTimer *qtimer;
  67    int num;
  68    void *info;
  69} PXA2xxTimer0;
  70
  71typedef struct {
  72    PXA2xxTimer0 tm;
  73    int32_t oldclock;
  74    int32_t clock;
  75    uint64_t lastload;
  76    uint32_t freq;
  77    uint32_t control;
  78} PXA2xxTimer4;
  79
  80typedef struct {
  81    int32_t clock;
  82    int32_t oldclock;
  83    uint64_t lastload;
  84    uint32_t freq;
  85    PXA2xxTimer0 timer[4];
  86    PXA2xxTimer4 *tm4;
  87    uint32_t events;
  88    uint32_t irq_enabled;
  89    uint32_t reset3;
  90    uint32_t snapshot;
  91} pxa2xx_timer_info;
  92
  93static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu)
  94{
  95    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
  96    int i;
  97    uint32_t now_vm;
  98    uint64_t new_qemu;
  99
 100    now_vm = s->clock +
 101            muldiv64(now_qemu - s->lastload, s->freq, get_ticks_per_sec());
 102
 103    for (i = 0; i < 4; i ++) {
 104        new_qemu = now_qemu + muldiv64((uint32_t) (s->timer[i].value - now_vm),
 105                        get_ticks_per_sec(), s->freq);
 106        qemu_mod_timer(s->timer[i].qtimer, new_qemu);
 107    }
 108}
 109
 110static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n)
 111{
 112    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
 113    uint32_t now_vm;
 114    uint64_t new_qemu;
 115    static const int counters[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
 116    int counter;
 117
 118    if (s->tm4[n].control & (1 << 7))
 119        counter = n;
 120    else
 121        counter = counters[n];
 122
 123    if (!s->tm4[counter].freq) {
 124        qemu_del_timer(s->tm4[n].tm.qtimer);
 125        return;
 126    }
 127
 128    now_vm = s->tm4[counter].clock + muldiv64(now_qemu -
 129                    s->tm4[counter].lastload,
 130                    s->tm4[counter].freq, get_ticks_per_sec());
 131
 132    new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].tm.value - now_vm),
 133                    get_ticks_per_sec(), s->tm4[counter].freq);
 134    qemu_mod_timer(s->tm4[n].tm.qtimer, new_qemu);
 135}
 136
 137static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
 138{
 139    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
 140    int tm = 0;
 141
 142    switch (offset) {
 143    case OSMR3:  tm ++;
 144    case OSMR2:  tm ++;
 145    case OSMR1:  tm ++;
 146    case OSMR0:
 147        return s->timer[tm].value;
 148    case OSMR11: tm ++;
 149    case OSMR10: tm ++;
 150    case OSMR9:  tm ++;
 151    case OSMR8:  tm ++;
 152    case OSMR7:  tm ++;
 153    case OSMR6:  tm ++;
 154    case OSMR5:  tm ++;
 155    case OSMR4:
 156        if (!s->tm4)
 157            goto badreg;
 158        return s->tm4[tm].tm.value;
 159    case OSCR:
 160        return s->clock + muldiv64(qemu_get_clock(vm_clock) -
 161                        s->lastload, s->freq, get_ticks_per_sec());
 162    case OSCR11: tm ++;
 163    case OSCR10: tm ++;
 164    case OSCR9:  tm ++;
 165    case OSCR8:  tm ++;
 166    case OSCR7:  tm ++;
 167    case OSCR6:  tm ++;
 168    case OSCR5:  tm ++;
 169    case OSCR4:
 170        if (!s->tm4)
 171            goto badreg;
 172
 173        if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) {
 174            if (s->tm4[tm - 1].freq)
 175                s->snapshot = s->tm4[tm - 1].clock + muldiv64(
 176                                qemu_get_clock(vm_clock) -
 177                                s->tm4[tm - 1].lastload,
 178                                s->tm4[tm - 1].freq, get_ticks_per_sec());
 179            else
 180                s->snapshot = s->tm4[tm - 1].clock;
 181        }
 182
 183        if (!s->tm4[tm].freq)
 184            return s->tm4[tm].clock;
 185        return s->tm4[tm].clock + muldiv64(qemu_get_clock(vm_clock) -
 186                        s->tm4[tm].lastload, s->tm4[tm].freq, get_ticks_per_sec());
 187    case OIER:
 188        return s->irq_enabled;
 189    case OSSR:  /* Status register */
 190        return s->events;
 191    case OWER:
 192        return s->reset3;
 193    case OMCR11: tm ++;
 194    case OMCR10: tm ++;
 195    case OMCR9:  tm ++;
 196    case OMCR8:  tm ++;
 197    case OMCR7:  tm ++;
 198    case OMCR6:  tm ++;
 199    case OMCR5:  tm ++;
 200    case OMCR4:
 201        if (!s->tm4)
 202            goto badreg;
 203        return s->tm4[tm].control;
 204    case OSNR:
 205        return s->snapshot;
 206    default:
 207    badreg:
 208        hw_error("pxa2xx_timer_read: Bad offset " REG_FMT "\n", offset);
 209    }
 210
 211    return 0;
 212}
 213
 214static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
 215                uint32_t value)
 216{
 217    int i, tm = 0;
 218    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
 219
 220    switch (offset) {
 221    case OSMR3:  tm ++;
 222    case OSMR2:  tm ++;
 223    case OSMR1:  tm ++;
 224    case OSMR0:
 225        s->timer[tm].value = value;
 226        pxa2xx_timer_update(s, qemu_get_clock(vm_clock));
 227        break;
 228    case OSMR11: tm ++;
 229    case OSMR10: tm ++;
 230    case OSMR9:  tm ++;
 231    case OSMR8:  tm ++;
 232    case OSMR7:  tm ++;
 233    case OSMR6:  tm ++;
 234    case OSMR5:  tm ++;
 235    case OSMR4:
 236        if (!s->tm4)
 237            goto badreg;
 238        s->tm4[tm].tm.value = value;
 239        pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
 240        break;
 241    case OSCR:
 242        s->oldclock = s->clock;
 243        s->lastload = qemu_get_clock(vm_clock);
 244        s->clock = value;
 245        pxa2xx_timer_update(s, s->lastload);
 246        break;
 247    case OSCR11: tm ++;
 248    case OSCR10: tm ++;
 249    case OSCR9:  tm ++;
 250    case OSCR8:  tm ++;
 251    case OSCR7:  tm ++;
 252    case OSCR6:  tm ++;
 253    case OSCR5:  tm ++;
 254    case OSCR4:
 255        if (!s->tm4)
 256            goto badreg;
 257        s->tm4[tm].oldclock = s->tm4[tm].clock;
 258        s->tm4[tm].lastload = qemu_get_clock(vm_clock);
 259        s->tm4[tm].clock = value;
 260        pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm);
 261        break;
 262    case OIER:
 263        s->irq_enabled = value & 0xfff;
 264        break;
 265    case OSSR:  /* Status register */
 266        s->events &= ~value;
 267        for (i = 0; i < 4; i ++, value >>= 1) {
 268            if (s->timer[i].level && (value & 1)) {
 269                s->timer[i].level = 0;
 270                qemu_irq_lower(s->timer[i].irq);
 271            }
 272        }
 273        if (s->tm4) {
 274            for (i = 0; i < 8; i ++, value >>= 1)
 275                if (s->tm4[i].tm.level && (value & 1))
 276                    s->tm4[i].tm.level = 0;
 277            if (!(s->events & 0xff0))
 278                qemu_irq_lower(s->tm4->tm.irq);
 279        }
 280        break;
 281    case OWER:  /* XXX: Reset on OSMR3 match? */
 282        s->reset3 = value;
 283        break;
 284    case OMCR7:  tm ++;
 285    case OMCR6:  tm ++;
 286    case OMCR5:  tm ++;
 287    case OMCR4:
 288        if (!s->tm4)
 289            goto badreg;
 290        s->tm4[tm].control = value & 0x0ff;
 291        /* XXX Stop if running (shouldn't happen) */
 292        if ((value & (1 << 7)) || tm == 0)
 293            s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7];
 294        else {
 295            s->tm4[tm].freq = 0;
 296            pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
 297        }
 298        break;
 299    case OMCR11: tm ++;
 300    case OMCR10: tm ++;
 301    case OMCR9:  tm ++;
 302    case OMCR8:  tm += 4;
 303        if (!s->tm4)
 304            goto badreg;
 305        s->tm4[tm].control = value & 0x3ff;
 306        /* XXX Stop if running (shouldn't happen) */
 307        if ((value & (1 << 7)) || !(tm & 1))
 308            s->tm4[tm].freq =
 309                    pxa2xx_timer4_freq[(value & (1 << 8)) ?  0 : (value & 7)];
 310        else {
 311            s->tm4[tm].freq = 0;
 312            pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
 313        }
 314        break;
 315    default:
 316    badreg:
 317        hw_error("pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset);
 318    }
 319}
 320
 321static CPUReadMemoryFunc * const pxa2xx_timer_readfn[] = {
 322    pxa2xx_timer_read,
 323    pxa2xx_timer_read,
 324    pxa2xx_timer_read,
 325};
 326
 327static CPUWriteMemoryFunc * const pxa2xx_timer_writefn[] = {
 328    pxa2xx_timer_write,
 329    pxa2xx_timer_write,
 330    pxa2xx_timer_write,
 331};
 332
 333static void pxa2xx_timer_tick(void *opaque)
 334{
 335    PXA2xxTimer0 *t = (PXA2xxTimer0 *) opaque;
 336    pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->info;
 337
 338    if (i->irq_enabled & (1 << t->num)) {
 339        t->level = 1;
 340        i->events |= 1 << t->num;
 341        qemu_irq_raise(t->irq);
 342    }
 343
 344    if (t->num == 3)
 345        if (i->reset3 & 1) {
 346            i->reset3 = 0;
 347            qemu_system_reset_request();
 348        }
 349}
 350
 351static void pxa2xx_timer_tick4(void *opaque)
 352{
 353    PXA2xxTimer4 *t = (PXA2xxTimer4 *) opaque;
 354    pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->tm.info;
 355
 356    pxa2xx_timer_tick(&t->tm);
 357    if (t->control & (1 << 3))
 358        t->clock = 0;
 359    if (t->control & (1 << 6))
 360        pxa2xx_timer_update4(i, qemu_get_clock(vm_clock), t->tm.num - 4);
 361}
 362
 363static void pxa2xx_timer_save(QEMUFile *f, void *opaque)
 364{
 365    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
 366    int i;
 367
 368    qemu_put_be32s(f, (uint32_t *) &s->clock);
 369    qemu_put_be32s(f, (uint32_t *) &s->oldclock);
 370    qemu_put_be64s(f, &s->lastload);
 371
 372    for (i = 0; i < 4; i ++) {
 373        qemu_put_be32s(f, &s->timer[i].value);
 374        qemu_put_be32(f, s->timer[i].level);
 375    }
 376    if (s->tm4)
 377        for (i = 0; i < 8; i ++) {
 378            qemu_put_be32s(f, &s->tm4[i].tm.value);
 379            qemu_put_be32(f, s->tm4[i].tm.level);
 380            qemu_put_sbe32s(f, &s->tm4[i].oldclock);
 381            qemu_put_sbe32s(f, &s->tm4[i].clock);
 382            qemu_put_be64s(f, &s->tm4[i].lastload);
 383            qemu_put_be32s(f, &s->tm4[i].freq);
 384            qemu_put_be32s(f, &s->tm4[i].control);
 385        }
 386
 387    qemu_put_be32s(f, &s->events);
 388    qemu_put_be32s(f, &s->irq_enabled);
 389    qemu_put_be32s(f, &s->reset3);
 390    qemu_put_be32s(f, &s->snapshot);
 391}
 392
 393static int pxa2xx_timer_load(QEMUFile *f, void *opaque, int version_id)
 394{
 395    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
 396    int64_t now;
 397    int i;
 398
 399    qemu_get_be32s(f, (uint32_t *) &s->clock);
 400    qemu_get_be32s(f, (uint32_t *) &s->oldclock);
 401    qemu_get_be64s(f, &s->lastload);
 402
 403    now = qemu_get_clock(vm_clock);
 404    for (i = 0; i < 4; i ++) {
 405        qemu_get_be32s(f, &s->timer[i].value);
 406        s->timer[i].level = qemu_get_be32(f);
 407    }
 408    pxa2xx_timer_update(s, now);
 409
 410    if (s->tm4)
 411        for (i = 0; i < 8; i ++) {
 412            qemu_get_be32s(f, &s->tm4[i].tm.value);
 413            s->tm4[i].tm.level = qemu_get_be32(f);
 414            qemu_get_sbe32s(f, &s->tm4[i].oldclock);
 415            qemu_get_sbe32s(f, &s->tm4[i].clock);
 416            qemu_get_be64s(f, &s->tm4[i].lastload);
 417            qemu_get_be32s(f, &s->tm4[i].freq);
 418            qemu_get_be32s(f, &s->tm4[i].control);
 419            pxa2xx_timer_update4(s, now, i);
 420        }
 421
 422    qemu_get_be32s(f, &s->events);
 423    qemu_get_be32s(f, &s->irq_enabled);
 424    qemu_get_be32s(f, &s->reset3);
 425    qemu_get_be32s(f, &s->snapshot);
 426
 427    return 0;
 428}
 429
 430static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
 431                qemu_irq *irqs)
 432{
 433    int i;
 434    int iomemtype;
 435    pxa2xx_timer_info *s;
 436
 437    s = (pxa2xx_timer_info *) qemu_mallocz(sizeof(pxa2xx_timer_info));
 438    s->irq_enabled = 0;
 439    s->oldclock = 0;
 440    s->clock = 0;
 441    s->lastload = qemu_get_clock(vm_clock);
 442    s->reset3 = 0;
 443
 444    for (i = 0; i < 4; i ++) {
 445        s->timer[i].value = 0;
 446        s->timer[i].irq = irqs[i];
 447        s->timer[i].info = s;
 448        s->timer[i].num = i;
 449        s->timer[i].level = 0;
 450        s->timer[i].qtimer = qemu_new_timer(vm_clock,
 451                        pxa2xx_timer_tick, &s->timer[i]);
 452    }
 453
 454    iomemtype = cpu_register_io_memory(pxa2xx_timer_readfn,
 455                    pxa2xx_timer_writefn, s, DEVICE_NATIVE_ENDIAN);
 456    cpu_register_physical_memory(base, 0x00001000, iomemtype);
 457
 458    register_savevm(NULL, "pxa2xx_timer", 0, 0,
 459                    pxa2xx_timer_save, pxa2xx_timer_load, s);
 460
 461    return s;
 462}
 463
 464void pxa25x_timer_init(target_phys_addr_t base, qemu_irq *irqs)
 465{
 466    pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs);
 467    s->freq = PXA25X_FREQ;
 468    s->tm4 = NULL;
 469}
 470
 471void pxa27x_timer_init(target_phys_addr_t base,
 472                qemu_irq *irqs, qemu_irq irq4)
 473{
 474    pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs);
 475    int i;
 476    s->freq = PXA27X_FREQ;
 477    s->tm4 = (PXA2xxTimer4 *) qemu_mallocz(8 *
 478                    sizeof(PXA2xxTimer4));
 479    for (i = 0; i < 8; i ++) {
 480        s->tm4[i].tm.value = 0;
 481        s->tm4[i].tm.irq = irq4;
 482        s->tm4[i].tm.info = s;
 483        s->tm4[i].tm.num = i + 4;
 484        s->tm4[i].tm.level = 0;
 485        s->tm4[i].freq = 0;
 486        s->tm4[i].control = 0x0;
 487        s->tm4[i].tm.qtimer = qemu_new_timer(vm_clock,
 488                        pxa2xx_timer_tick4, &s->tm4[i]);
 489    }
 490}
 491