Statistics
| Branch: | Revision:

root / hw / pxa2xx_timer.c @ 1de7afc9

History | View | Annotate | Download (14.7 kB)

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

    
53
static 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
typedef struct PXA2xxTimerInfo PXA2xxTimerInfo;
64

    
65
typedef struct {
66
    uint32_t value;
67
    qemu_irq irq;
68
    QEMUTimer *qtimer;
69
    int num;
70
    PXA2xxTimerInfo *info;
71
} PXA2xxTimer0;
72

    
73
typedef 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

    
82
struct 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

    
103
static inline int pxa2xx_timer_has_tm4(PXA2xxTimerInfo *s)
104
{
105
    return s->flags & (1 << PXA2XX_TIMER_HAVE_TM4);
106
}
107

    
108
static 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

    
125
static 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

    
152
static 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

    
230
static 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

    
330
static const MemoryRegionOps pxa2xx_timer_ops = {
331
    .read = pxa2xx_timer_read,
332
    .write = pxa2xx_timer_write,
333
    .endianness = DEVICE_NATIVE_ENDIAN,
334
};
335

    
336
static 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

    
353
static 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

    
367
static 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

    
383
static 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

    
424
static 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

    
435
static 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

    
452
static bool pxa2xx_timer_has_tm4_test(void *opaque, int version_id)
453
{
454
    return pxa2xx_timer_has_tm4(opaque);
455
}
456

    
457
static 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

    
480
static 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

    
487
static 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

    
498
static 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

    
505
static 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

    
512
static 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

    
523
static 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

    
530
static 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

    
536
type_init(pxa2xx_timer_register_types)