Statistics
| Branch: | Revision:

root / hw / pxa2xx_timer.c @ 797e9542

History | View | Annotate | Download (14.5 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 licenced 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
    int level;
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
    uint32_t flags;
85

    
86
    int32_t clock;
87
    int32_t oldclock;
88
    uint64_t lastload;
89
    uint32_t freq;
90
    PXA2xxTimer0 timer[4];
91
    qemu_irq irqs[5];
92
    uint32_t events;
93
    uint32_t irq_enabled;
94
    uint32_t reset3;
95
    uint32_t snapshot;
96

    
97
    PXA2xxTimer4 tm4[8];
98
    qemu_irq irq4;
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 uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
153
{
154
    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
155
    int tm = 0;
156

    
157
    switch (offset) {
158
    case OSMR3:  tm ++;
159
    case OSMR2:  tm ++;
160
    case OSMR1:  tm ++;
161
    case OSMR0:
162
        return s->timer[tm].value;
163
    case OSMR11: tm ++;
164
    case OSMR10: tm ++;
165
    case OSMR9:  tm ++;
166
    case OSMR8:  tm ++;
167
    case OSMR7:  tm ++;
168
    case OSMR6:  tm ++;
169
    case OSMR5:  tm ++;
170
    case OSMR4:
171
        if (!pxa2xx_timer_has_tm4(s))
172
            goto badreg;
173
        return s->tm4[tm].tm.value;
174
    case OSCR:
175
        return s->clock + muldiv64(qemu_get_clock(vm_clock) -
176
                        s->lastload, s->freq, get_ticks_per_sec());
177
    case OSCR11: tm ++;
178
    case OSCR10: tm ++;
179
    case OSCR9:  tm ++;
180
    case OSCR8:  tm ++;
181
    case OSCR7:  tm ++;
182
    case OSCR6:  tm ++;
183
    case OSCR5:  tm ++;
184
    case OSCR4:
185
        if (!pxa2xx_timer_has_tm4(s))
186
            goto badreg;
187

    
188
        if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) {
189
            if (s->tm4[tm - 1].freq)
190
                s->snapshot = s->tm4[tm - 1].clock + muldiv64(
191
                                qemu_get_clock(vm_clock) -
192
                                s->tm4[tm - 1].lastload,
193
                                s->tm4[tm - 1].freq, get_ticks_per_sec());
194
            else
195
                s->snapshot = s->tm4[tm - 1].clock;
196
        }
197

    
198
        if (!s->tm4[tm].freq)
199
            return s->tm4[tm].clock;
200
        return s->tm4[tm].clock + muldiv64(qemu_get_clock(vm_clock) -
201
                        s->tm4[tm].lastload, s->tm4[tm].freq, get_ticks_per_sec());
202
    case OIER:
203
        return s->irq_enabled;
204
    case OSSR:        /* Status register */
205
        return s->events;
206
    case OWER:
207
        return s->reset3;
208
    case OMCR11: tm ++;
209
    case OMCR10: tm ++;
210
    case OMCR9:  tm ++;
211
    case OMCR8:  tm ++;
212
    case OMCR7:  tm ++;
213
    case OMCR6:  tm ++;
214
    case OMCR5:  tm ++;
215
    case OMCR4:
216
        if (!pxa2xx_timer_has_tm4(s))
217
            goto badreg;
218
        return s->tm4[tm].control;
219
    case OSNR:
220
        return s->snapshot;
221
    default:
222
    badreg:
223
        hw_error("pxa2xx_timer_read: Bad offset " REG_FMT "\n", offset);
224
    }
225

    
226
    return 0;
227
}
228

    
229
static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
230
                uint32_t value)
231
{
232
    int i, tm = 0;
233
    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
234

    
235
    switch (offset) {
236
    case OSMR3:  tm ++;
237
    case OSMR2:  tm ++;
238
    case OSMR1:  tm ++;
239
    case OSMR0:
240
        s->timer[tm].value = value;
241
        pxa2xx_timer_update(s, qemu_get_clock(vm_clock));
242
        break;
243
    case OSMR11: tm ++;
244
    case OSMR10: tm ++;
245
    case OSMR9:  tm ++;
246
    case OSMR8:  tm ++;
247
    case OSMR7:  tm ++;
248
    case OSMR6:  tm ++;
249
    case OSMR5:  tm ++;
250
    case OSMR4:
251
        if (!pxa2xx_timer_has_tm4(s))
252
            goto badreg;
253
        s->tm4[tm].tm.value = value;
254
        pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
255
        break;
256
    case OSCR:
257
        s->oldclock = s->clock;
258
        s->lastload = qemu_get_clock(vm_clock);
259
        s->clock = value;
260
        pxa2xx_timer_update(s, s->lastload);
261
        break;
262
    case OSCR11: tm ++;
263
    case OSCR10: tm ++;
264
    case OSCR9:  tm ++;
265
    case OSCR8:  tm ++;
266
    case OSCR7:  tm ++;
267
    case OSCR6:  tm ++;
268
    case OSCR5:  tm ++;
269
    case OSCR4:
270
        if (!pxa2xx_timer_has_tm4(s))
271
            goto badreg;
272
        s->tm4[tm].oldclock = s->tm4[tm].clock;
273
        s->tm4[tm].lastload = qemu_get_clock(vm_clock);
274
        s->tm4[tm].clock = value;
275
        pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm);
276
        break;
277
    case OIER:
278
        s->irq_enabled = value & 0xfff;
279
        break;
280
    case OSSR:        /* Status register */
281
        s->events &= ~value;
282
        for (i = 0; i < 4; i ++, value >>= 1) {
283
            if (s->timer[i].level && (value & 1)) {
284
                s->timer[i].level = 0;
285
                qemu_irq_lower(s->irqs[i]);
286
            }
287
        }
288
        if (pxa2xx_timer_has_tm4(s)) {
289
            for (i = 0; i < 8; i ++, value >>= 1)
290
                if (s->tm4[i].tm.level && (value & 1))
291
                    s->tm4[i].tm.level = 0;
292
            if (!(s->events & 0xff0))
293
                qemu_irq_lower(s->irq4);
294
        }
295
        break;
296
    case OWER:        /* XXX: Reset on OSMR3 match? */
297
        s->reset3 = value;
298
        break;
299
    case OMCR7:  tm ++;
300
    case OMCR6:  tm ++;
301
    case OMCR5:  tm ++;
302
    case OMCR4:
303
        if (!pxa2xx_timer_has_tm4(s))
304
            goto badreg;
305
        s->tm4[tm].control = value & 0x0ff;
306
        /* XXX Stop if running (shouldn't happen) */
307
        if ((value & (1 << 7)) || tm == 0)
308
            s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7];
309
        else {
310
            s->tm4[tm].freq = 0;
311
            pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
312
        }
313
        break;
314
    case OMCR11: tm ++;
315
    case OMCR10: tm ++;
316
    case OMCR9:  tm ++;
317
    case OMCR8:  tm += 4;
318
        if (!pxa2xx_timer_has_tm4(s))
319
            goto badreg;
320
        s->tm4[tm].control = value & 0x3ff;
321
        /* XXX Stop if running (shouldn't happen) */
322
        if ((value & (1 << 7)) || !(tm & 1))
323
            s->tm4[tm].freq =
324
                    pxa2xx_timer4_freq[(value & (1 << 8)) ?  0 : (value & 7)];
325
        else {
326
            s->tm4[tm].freq = 0;
327
            pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
328
        }
329
        break;
330
    default:
331
    badreg:
332
        hw_error("pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset);
333
    }
334
}
335

    
336
static CPUReadMemoryFunc * const pxa2xx_timer_readfn[] = {
337
    pxa2xx_timer_read,
338
    pxa2xx_timer_read,
339
    pxa2xx_timer_read,
340
};
341

    
342
static CPUWriteMemoryFunc * const pxa2xx_timer_writefn[] = {
343
    pxa2xx_timer_write,
344
    pxa2xx_timer_write,
345
    pxa2xx_timer_write,
346
};
347

    
348
static void pxa2xx_timer_tick(void *opaque)
349
{
350
    PXA2xxTimer0 *t = (PXA2xxTimer0 *) opaque;
351
    PXA2xxTimerInfo *i = t->info;
352

    
353
    if (i->irq_enabled & (1 << t->num)) {
354
        t->level = 1;
355
        i->events |= 1 << t->num;
356
        qemu_irq_raise(t->num < 4 ? i->irqs[t->num] : i->irq4);
357
    }
358

    
359
    if (t->num == 3)
360
        if (i->reset3 & 1) {
361
            i->reset3 = 0;
362
            qemu_system_reset_request();
363
        }
364
}
365

    
366
static void pxa2xx_timer_tick4(void *opaque)
367
{
368
    PXA2xxTimer4 *t = (PXA2xxTimer4 *) opaque;
369
    PXA2xxTimerInfo *i = (PXA2xxTimerInfo *) t->tm.info;
370

    
371
    pxa2xx_timer_tick(&t->tm);
372
    if (t->control & (1 << 3))
373
        t->clock = 0;
374
    if (t->control & (1 << 6))
375
        pxa2xx_timer_update4(i, qemu_get_clock(vm_clock), t->tm.num - 4);
376
}
377

    
378
static int pxa25x_timer_post_load(void *opaque, int version_id)
379
{
380
    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
381
    int64_t now;
382
    int i;
383

    
384
    now = qemu_get_clock(vm_clock);
385
    pxa2xx_timer_update(s, now);
386

    
387
    if (pxa2xx_timer_has_tm4(s))
388
        for (i = 0; i < 8; i ++)
389
            pxa2xx_timer_update4(s, now, i);
390

    
391
    return 0;
392
}
393

    
394
static int pxa2xx_timer_init(SysBusDevice *dev)
395
{
396
    int i;
397
    int iomemtype;
398
    PXA2xxTimerInfo *s;
399

    
400
    s = FROM_SYSBUS(PXA2xxTimerInfo, dev);
401
    s->irq_enabled = 0;
402
    s->oldclock = 0;
403
    s->clock = 0;
404
    s->lastload = qemu_get_clock(vm_clock);
405
    s->reset3 = 0;
406

    
407
    for (i = 0; i < 4; i ++) {
408
        s->timer[i].value = 0;
409
        sysbus_init_irq(dev, &s->irqs[i]);
410
        s->timer[i].info = s;
411
        s->timer[i].num = i;
412
        s->timer[i].level = 0;
413
        s->timer[i].qtimer = qemu_new_timer(vm_clock,
414
                        pxa2xx_timer_tick, &s->timer[i]);
415
    }
416
    if (s->flags & (1 << PXA2XX_TIMER_HAVE_TM4)) {
417
        sysbus_init_irq(dev, &s->irq4);
418

    
419
        for (i = 0; i < 8; i ++) {
420
            s->tm4[i].tm.value = 0;
421
            s->tm4[i].tm.info = s;
422
            s->tm4[i].tm.num = i + 4;
423
            s->tm4[i].tm.level = 0;
424
            s->tm4[i].freq = 0;
425
            s->tm4[i].control = 0x0;
426
            s->tm4[i].tm.qtimer = qemu_new_timer(vm_clock,
427
                        pxa2xx_timer_tick4, &s->tm4[i]);
428
        }
429
    }
430

    
431
    iomemtype = cpu_register_io_memory(pxa2xx_timer_readfn,
432
                    pxa2xx_timer_writefn, s, DEVICE_NATIVE_ENDIAN);
433
    sysbus_init_mmio(dev, 0x00001000, iomemtype);
434

    
435
    return 0;
436
}
437

    
438
static const VMStateDescription vmstate_pxa2xx_timer0_regs = {
439
    .name = "pxa2xx_timer0",
440
    .version_id = 1,
441
    .minimum_version_id = 1,
442
    .minimum_version_id_old = 1,
443
    .fields = (VMStateField[]) {
444
        VMSTATE_UINT32(value, PXA2xxTimer0),
445
        VMSTATE_INT32(level, PXA2xxTimer0),
446
        VMSTATE_END_OF_LIST(),
447
    },
448
};
449

    
450
static const VMStateDescription vmstate_pxa2xx_timer4_regs = {
451
    .name = "pxa2xx_timer4",
452
    .version_id = 1,
453
    .minimum_version_id = 1,
454
    .minimum_version_id_old = 1,
455
    .fields = (VMStateField[]) {
456
        VMSTATE_STRUCT(tm, PXA2xxTimer4, 1,
457
                        vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
458
        VMSTATE_INT32(oldclock, PXA2xxTimer4),
459
        VMSTATE_INT32(clock, PXA2xxTimer4),
460
        VMSTATE_UINT64(lastload, PXA2xxTimer4),
461
        VMSTATE_UINT32(freq, PXA2xxTimer4),
462
        VMSTATE_UINT32(control, PXA2xxTimer4),
463
        VMSTATE_END_OF_LIST(),
464
    },
465
};
466

    
467
static bool pxa2xx_timer_has_tm4_test(void *opaque, int version_id)
468
{
469
    return pxa2xx_timer_has_tm4(opaque);
470
}
471

    
472
static const VMStateDescription vmstate_pxa2xx_timer_regs = {
473
    .name = "pxa2xx_timer",
474
    .version_id = 1,
475
    .minimum_version_id = 1,
476
    .minimum_version_id_old = 1,
477
    .post_load = pxa25x_timer_post_load,
478
    .fields = (VMStateField[]) {
479
        VMSTATE_INT32(clock, PXA2xxTimerInfo),
480
        VMSTATE_INT32(oldclock, PXA2xxTimerInfo),
481
        VMSTATE_UINT64(lastload, PXA2xxTimerInfo),
482
        VMSTATE_STRUCT_ARRAY(timer, PXA2xxTimerInfo, 4, 1,
483
                        vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
484
        VMSTATE_UINT32(events, PXA2xxTimerInfo),
485
        VMSTATE_UINT32(irq_enabled, PXA2xxTimerInfo),
486
        VMSTATE_UINT32(reset3, PXA2xxTimerInfo),
487
        VMSTATE_UINT32(snapshot, PXA2xxTimerInfo),
488
        VMSTATE_STRUCT_ARRAY_TEST(tm4, PXA2xxTimerInfo, 8,
489
                        pxa2xx_timer_has_tm4_test, 0,
490
                        vmstate_pxa2xx_timer4_regs, PXA2xxTimer4),
491
        VMSTATE_END_OF_LIST(),
492
    }
493
};
494

    
495
static SysBusDeviceInfo pxa25x_timer_dev_info = {
496
    .init       = pxa2xx_timer_init,
497
    .qdev.name  = "pxa25x-timer",
498
    .qdev.desc  = "PXA25x timer",
499
    .qdev.size  = sizeof(PXA2xxTimerInfo),
500
    .qdev.vmsd  = &vmstate_pxa2xx_timer_regs,
501
    .qdev.props = (Property[]) {
502
        DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA25X_FREQ),
503
        DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
504
                        PXA2XX_TIMER_HAVE_TM4, false),
505
        DEFINE_PROP_END_OF_LIST(),
506
    },
507
};
508

    
509
static SysBusDeviceInfo pxa27x_timer_dev_info = {
510
    .init       = pxa2xx_timer_init,
511
    .qdev.name  = "pxa27x-timer",
512
    .qdev.desc  = "PXA27x timer",
513
    .qdev.size  = sizeof(PXA2xxTimerInfo),
514
    .qdev.vmsd  = &vmstate_pxa2xx_timer_regs,
515
    .qdev.props = (Property[]) {
516
        DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA27X_FREQ),
517
        DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
518
                        PXA2XX_TIMER_HAVE_TM4, true),
519
        DEFINE_PROP_END_OF_LIST(),
520
    },
521
};
522

    
523
static void pxa2xx_timer_register(void)
524
{
525
    sysbus_register_withprop(&pxa25x_timer_dev_info);
526
    sysbus_register_withprop(&pxa27x_timer_dev_info);
527
};
528
device_init(pxa2xx_timer_register);