Statistics
| Branch: | Revision:

root / hw / pxa2xx_timer.c @ 0d09e41a

History | View | Annotate | Download (15.9 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/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

    
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
        /* fall through */
161
    case OSMR2:  tm ++;
162
        /* fall through */
163
    case OSMR1:  tm ++;
164
        /* fall through */
165
    case OSMR0:
166
        return s->timer[tm].value;
167
    case OSMR11: tm ++;
168
        /* fall through */
169
    case OSMR10: tm ++;
170
        /* fall through */
171
    case OSMR9:  tm ++;
172
        /* fall through */
173
    case OSMR8:  tm ++;
174
        /* fall through */
175
    case OSMR7:  tm ++;
176
        /* fall through */
177
    case OSMR6:  tm ++;
178
        /* fall through */
179
    case OSMR5:  tm ++;
180
        /* fall through */
181
    case OSMR4:
182
        if (!pxa2xx_timer_has_tm4(s))
183
            goto badreg;
184
        return s->tm4[tm].tm.value;
185
    case OSCR:
186
        return s->clock + muldiv64(qemu_get_clock_ns(vm_clock) -
187
                        s->lastload, s->freq, get_ticks_per_sec());
188
    case OSCR11: tm ++;
189
        /* fall through */
190
    case OSCR10: tm ++;
191
        /* fall through */
192
    case OSCR9:  tm ++;
193
        /* fall through */
194
    case OSCR8:  tm ++;
195
        /* fall through */
196
    case OSCR7:  tm ++;
197
        /* fall through */
198
    case OSCR6:  tm ++;
199
        /* fall through */
200
    case OSCR5:  tm ++;
201
        /* fall through */
202
    case OSCR4:
203
        if (!pxa2xx_timer_has_tm4(s))
204
            goto badreg;
205

    
206
        if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) {
207
            if (s->tm4[tm - 1].freq)
208
                s->snapshot = s->tm4[tm - 1].clock + muldiv64(
209
                                qemu_get_clock_ns(vm_clock) -
210
                                s->tm4[tm - 1].lastload,
211
                                s->tm4[tm - 1].freq, get_ticks_per_sec());
212
            else
213
                s->snapshot = s->tm4[tm - 1].clock;
214
        }
215

    
216
        if (!s->tm4[tm].freq)
217
            return s->tm4[tm].clock;
218
        return s->tm4[tm].clock + muldiv64(qemu_get_clock_ns(vm_clock) -
219
                        s->tm4[tm].lastload, s->tm4[tm].freq, get_ticks_per_sec());
220
    case OIER:
221
        return s->irq_enabled;
222
    case OSSR:        /* Status register */
223
        return s->events;
224
    case OWER:
225
        return s->reset3;
226
    case OMCR11: tm ++;
227
        /* fall through */
228
    case OMCR10: tm ++;
229
        /* fall through */
230
    case OMCR9:  tm ++;
231
        /* fall through */
232
    case OMCR8:  tm ++;
233
        /* fall through */
234
    case OMCR7:  tm ++;
235
        /* fall through */
236
    case OMCR6:  tm ++;
237
        /* fall through */
238
    case OMCR5:  tm ++;
239
        /* fall through */
240
    case OMCR4:
241
        if (!pxa2xx_timer_has_tm4(s))
242
            goto badreg;
243
        return s->tm4[tm].control;
244
    case OSNR:
245
        return s->snapshot;
246
    default:
247
    badreg:
248
        hw_error("pxa2xx_timer_read: Bad offset " REG_FMT "\n", offset);
249
    }
250

    
251
    return 0;
252
}
253

    
254
static void pxa2xx_timer_write(void *opaque, hwaddr offset,
255
                               uint64_t value, unsigned size)
256
{
257
    int i, tm = 0;
258
    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
259

    
260
    switch (offset) {
261
    case OSMR3:  tm ++;
262
        /* fall through */
263
    case OSMR2:  tm ++;
264
        /* fall through */
265
    case OSMR1:  tm ++;
266
        /* fall through */
267
    case OSMR0:
268
        s->timer[tm].value = value;
269
        pxa2xx_timer_update(s, qemu_get_clock_ns(vm_clock));
270
        break;
271
    case OSMR11: tm ++;
272
        /* fall through */
273
    case OSMR10: tm ++;
274
        /* fall through */
275
    case OSMR9:  tm ++;
276
        /* fall through */
277
    case OSMR8:  tm ++;
278
        /* fall through */
279
    case OSMR7:  tm ++;
280
        /* fall through */
281
    case OSMR6:  tm ++;
282
        /* fall through */
283
    case OSMR5:  tm ++;
284
        /* fall through */
285
    case OSMR4:
286
        if (!pxa2xx_timer_has_tm4(s))
287
            goto badreg;
288
        s->tm4[tm].tm.value = value;
289
        pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm);
290
        break;
291
    case OSCR:
292
        s->oldclock = s->clock;
293
        s->lastload = qemu_get_clock_ns(vm_clock);
294
        s->clock = value;
295
        pxa2xx_timer_update(s, s->lastload);
296
        break;
297
    case OSCR11: tm ++;
298
        /* fall through */
299
    case OSCR10: tm ++;
300
        /* fall through */
301
    case OSCR9:  tm ++;
302
        /* fall through */
303
    case OSCR8:  tm ++;
304
        /* fall through */
305
    case OSCR7:  tm ++;
306
        /* fall through */
307
    case OSCR6:  tm ++;
308
        /* fall through */
309
    case OSCR5:  tm ++;
310
        /* fall through */
311
    case OSCR4:
312
        if (!pxa2xx_timer_has_tm4(s))
313
            goto badreg;
314
        s->tm4[tm].oldclock = s->tm4[tm].clock;
315
        s->tm4[tm].lastload = qemu_get_clock_ns(vm_clock);
316
        s->tm4[tm].clock = value;
317
        pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm);
318
        break;
319
    case OIER:
320
        s->irq_enabled = value & 0xfff;
321
        break;
322
    case OSSR:        /* Status register */
323
        value &= s->events;
324
        s->events &= ~value;
325
        for (i = 0; i < 4; i ++, value >>= 1)
326
            if (value & 1)
327
                qemu_irq_lower(s->timer[i].irq);
328
        if (pxa2xx_timer_has_tm4(s) && !(s->events & 0xff0) && value)
329
            qemu_irq_lower(s->irq4);
330
        break;
331
    case OWER:        /* XXX: Reset on OSMR3 match? */
332
        s->reset3 = value;
333
        break;
334
    case OMCR7:  tm ++;
335
        /* fall through */
336
    case OMCR6:  tm ++;
337
        /* fall through */
338
    case OMCR5:  tm ++;
339
        /* fall through */
340
    case OMCR4:
341
        if (!pxa2xx_timer_has_tm4(s))
342
            goto badreg;
343
        s->tm4[tm].control = value & 0x0ff;
344
        /* XXX Stop if running (shouldn't happen) */
345
        if ((value & (1 << 7)) || tm == 0)
346
            s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7];
347
        else {
348
            s->tm4[tm].freq = 0;
349
            pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm);
350
        }
351
        break;
352
    case OMCR11: tm ++;
353
        /* fall through */
354
    case OMCR10: tm ++;
355
        /* fall through */
356
    case OMCR9:  tm ++;
357
        /* fall through */
358
    case OMCR8:  tm += 4;
359
        if (!pxa2xx_timer_has_tm4(s))
360
            goto badreg;
361
        s->tm4[tm].control = value & 0x3ff;
362
        /* XXX Stop if running (shouldn't happen) */
363
        if ((value & (1 << 7)) || !(tm & 1))
364
            s->tm4[tm].freq =
365
                    pxa2xx_timer4_freq[(value & (1 << 8)) ?  0 : (value & 7)];
366
        else {
367
            s->tm4[tm].freq = 0;
368
            pxa2xx_timer_update4(s, qemu_get_clock_ns(vm_clock), tm);
369
        }
370
        break;
371
    default:
372
    badreg:
373
        hw_error("pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset);
374
    }
375
}
376

    
377
static const MemoryRegionOps pxa2xx_timer_ops = {
378
    .read = pxa2xx_timer_read,
379
    .write = pxa2xx_timer_write,
380
    .endianness = DEVICE_NATIVE_ENDIAN,
381
};
382

    
383
static void pxa2xx_timer_tick(void *opaque)
384
{
385
    PXA2xxTimer0 *t = (PXA2xxTimer0 *) opaque;
386
    PXA2xxTimerInfo *i = t->info;
387

    
388
    if (i->irq_enabled & (1 << t->num)) {
389
        i->events |= 1 << t->num;
390
        qemu_irq_raise(t->irq);
391
    }
392

    
393
    if (t->num == 3)
394
        if (i->reset3 & 1) {
395
            i->reset3 = 0;
396
            qemu_system_reset_request();
397
        }
398
}
399

    
400
static void pxa2xx_timer_tick4(void *opaque)
401
{
402
    PXA2xxTimer4 *t = (PXA2xxTimer4 *) opaque;
403
    PXA2xxTimerInfo *i = (PXA2xxTimerInfo *) t->tm.info;
404

    
405
    pxa2xx_timer_tick(&t->tm);
406
    if (t->control & (1 << 3))
407
        t->clock = 0;
408
    if (t->control & (1 << 6))
409
        pxa2xx_timer_update4(i, qemu_get_clock_ns(vm_clock), t->tm.num - 4);
410
    if (i->events & 0xff0)
411
        qemu_irq_raise(i->irq4);
412
}
413

    
414
static int pxa25x_timer_post_load(void *opaque, int version_id)
415
{
416
    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
417
    int64_t now;
418
    int i;
419

    
420
    now = qemu_get_clock_ns(vm_clock);
421
    pxa2xx_timer_update(s, now);
422

    
423
    if (pxa2xx_timer_has_tm4(s))
424
        for (i = 0; i < 8; i ++)
425
            pxa2xx_timer_update4(s, now, i);
426

    
427
    return 0;
428
}
429

    
430
static int pxa2xx_timer_init(SysBusDevice *dev)
431
{
432
    int i;
433
    PXA2xxTimerInfo *s;
434

    
435
    s = FROM_SYSBUS(PXA2xxTimerInfo, dev);
436
    s->irq_enabled = 0;
437
    s->oldclock = 0;
438
    s->clock = 0;
439
    s->lastload = qemu_get_clock_ns(vm_clock);
440
    s->reset3 = 0;
441

    
442
    for (i = 0; i < 4; i ++) {
443
        s->timer[i].value = 0;
444
        sysbus_init_irq(dev, &s->timer[i].irq);
445
        s->timer[i].info = s;
446
        s->timer[i].num = i;
447
        s->timer[i].qtimer = qemu_new_timer_ns(vm_clock,
448
                        pxa2xx_timer_tick, &s->timer[i]);
449
    }
450
    if (s->flags & (1 << PXA2XX_TIMER_HAVE_TM4)) {
451
        sysbus_init_irq(dev, &s->irq4);
452

    
453
        for (i = 0; i < 8; i ++) {
454
            s->tm4[i].tm.value = 0;
455
            s->tm4[i].tm.info = s;
456
            s->tm4[i].tm.num = i + 4;
457
            s->tm4[i].freq = 0;
458
            s->tm4[i].control = 0x0;
459
            s->tm4[i].tm.qtimer = qemu_new_timer_ns(vm_clock,
460
                        pxa2xx_timer_tick4, &s->tm4[i]);
461
        }
462
    }
463

    
464
    memory_region_init_io(&s->iomem, &pxa2xx_timer_ops, s,
465
                          "pxa2xx-timer", 0x00001000);
466
    sysbus_init_mmio(dev, &s->iomem);
467

    
468
    return 0;
469
}
470

    
471
static const VMStateDescription vmstate_pxa2xx_timer0_regs = {
472
    .name = "pxa2xx_timer0",
473
    .version_id = 2,
474
    .minimum_version_id = 2,
475
    .minimum_version_id_old = 2,
476
    .fields = (VMStateField[]) {
477
        VMSTATE_UINT32(value, PXA2xxTimer0),
478
        VMSTATE_END_OF_LIST(),
479
    },
480
};
481

    
482
static const VMStateDescription vmstate_pxa2xx_timer4_regs = {
483
    .name = "pxa2xx_timer4",
484
    .version_id = 1,
485
    .minimum_version_id = 1,
486
    .minimum_version_id_old = 1,
487
    .fields = (VMStateField[]) {
488
        VMSTATE_STRUCT(tm, PXA2xxTimer4, 1,
489
                        vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
490
        VMSTATE_INT32(oldclock, PXA2xxTimer4),
491
        VMSTATE_INT32(clock, PXA2xxTimer4),
492
        VMSTATE_UINT64(lastload, PXA2xxTimer4),
493
        VMSTATE_UINT32(freq, PXA2xxTimer4),
494
        VMSTATE_UINT32(control, PXA2xxTimer4),
495
        VMSTATE_END_OF_LIST(),
496
    },
497
};
498

    
499
static bool pxa2xx_timer_has_tm4_test(void *opaque, int version_id)
500
{
501
    return pxa2xx_timer_has_tm4(opaque);
502
}
503

    
504
static const VMStateDescription vmstate_pxa2xx_timer_regs = {
505
    .name = "pxa2xx_timer",
506
    .version_id = 1,
507
    .minimum_version_id = 1,
508
    .minimum_version_id_old = 1,
509
    .post_load = pxa25x_timer_post_load,
510
    .fields = (VMStateField[]) {
511
        VMSTATE_INT32(clock, PXA2xxTimerInfo),
512
        VMSTATE_INT32(oldclock, PXA2xxTimerInfo),
513
        VMSTATE_UINT64(lastload, PXA2xxTimerInfo),
514
        VMSTATE_STRUCT_ARRAY(timer, PXA2xxTimerInfo, 4, 1,
515
                        vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
516
        VMSTATE_UINT32(events, PXA2xxTimerInfo),
517
        VMSTATE_UINT32(irq_enabled, PXA2xxTimerInfo),
518
        VMSTATE_UINT32(reset3, PXA2xxTimerInfo),
519
        VMSTATE_UINT32(snapshot, PXA2xxTimerInfo),
520
        VMSTATE_STRUCT_ARRAY_TEST(tm4, PXA2xxTimerInfo, 8,
521
                        pxa2xx_timer_has_tm4_test, 0,
522
                        vmstate_pxa2xx_timer4_regs, PXA2xxTimer4),
523
        VMSTATE_END_OF_LIST(),
524
    }
525
};
526

    
527
static Property pxa25x_timer_dev_properties[] = {
528
    DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA25X_FREQ),
529
    DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
530
    PXA2XX_TIMER_HAVE_TM4, false),
531
    DEFINE_PROP_END_OF_LIST(),
532
};
533

    
534
static void pxa25x_timer_dev_class_init(ObjectClass *klass, void *data)
535
{
536
    DeviceClass *dc = DEVICE_CLASS(klass);
537
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
538

    
539
    k->init = pxa2xx_timer_init;
540
    dc->desc = "PXA25x timer";
541
    dc->vmsd = &vmstate_pxa2xx_timer_regs;
542
    dc->props = pxa25x_timer_dev_properties;
543
}
544

    
545
static const TypeInfo pxa25x_timer_dev_info = {
546
    .name          = "pxa25x-timer",
547
    .parent        = TYPE_SYS_BUS_DEVICE,
548
    .instance_size = sizeof(PXA2xxTimerInfo),
549
    .class_init    = pxa25x_timer_dev_class_init,
550
};
551

    
552
static Property pxa27x_timer_dev_properties[] = {
553
    DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA27X_FREQ),
554
    DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
555
    PXA2XX_TIMER_HAVE_TM4, true),
556
    DEFINE_PROP_END_OF_LIST(),
557
};
558

    
559
static void pxa27x_timer_dev_class_init(ObjectClass *klass, void *data)
560
{
561
    DeviceClass *dc = DEVICE_CLASS(klass);
562
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
563

    
564
    k->init = pxa2xx_timer_init;
565
    dc->desc = "PXA27x timer";
566
    dc->vmsd = &vmstate_pxa2xx_timer_regs;
567
    dc->props = pxa27x_timer_dev_properties;
568
}
569

    
570
static const TypeInfo pxa27x_timer_dev_info = {
571
    .name          = "pxa27x-timer",
572
    .parent        = TYPE_SYS_BUS_DEVICE,
573
    .instance_size = sizeof(PXA2xxTimerInfo),
574
    .class_init    = pxa27x_timer_dev_class_init,
575
};
576

    
577
static void pxa2xx_timer_register_types(void)
578
{
579
    type_register_static(&pxa25x_timer_dev_info);
580
    type_register_static(&pxa27x_timer_dev_info);
581
}
582

    
583
type_init(pxa2xx_timer_register_types)