Statistics
| Branch: | Revision:

root / hw / pxa2xx_timer.c @ 74475455

History | View | Annotate | Download (14.2 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
    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
    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
    uint32_t events;
92
    uint32_t irq_enabled;
93
    uint32_t reset3;
94
    uint32_t snapshot;
95

    
96
    qemu_irq irq4;
97
    PXA2xxTimer4 tm4[8];
98
};
99

    
100
#define PXA2XX_TIMER_HAVE_TM4        0
101

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

    
107
static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu)
108
{
109
    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
110
    int i;
111
    uint32_t now_vm;
112
    uint64_t new_qemu;
113

    
114
    now_vm = s->clock +
115
            muldiv64(now_qemu - s->lastload, s->freq, get_ticks_per_sec());
116

    
117
    for (i = 0; i < 4; i ++) {
118
        new_qemu = now_qemu + muldiv64((uint32_t) (s->timer[i].value - now_vm),
119
                        get_ticks_per_sec(), s->freq);
120
        qemu_mod_timer(s->timer[i].qtimer, new_qemu);
121
    }
122
}
123

    
124
static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n)
125
{
126
    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
127
    uint32_t now_vm;
128
    uint64_t new_qemu;
129
    static const int counters[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
130
    int counter;
131

    
132
    if (s->tm4[n].control & (1 << 7))
133
        counter = n;
134
    else
135
        counter = counters[n];
136

    
137
    if (!s->tm4[counter].freq) {
138
        qemu_del_timer(s->tm4[n].tm.qtimer);
139
        return;
140
    }
141

    
142
    now_vm = s->tm4[counter].clock + muldiv64(now_qemu -
143
                    s->tm4[counter].lastload,
144
                    s->tm4[counter].freq, get_ticks_per_sec());
145

    
146
    new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].tm.value - now_vm),
147
                    get_ticks_per_sec(), s->tm4[counter].freq);
148
    qemu_mod_timer(s->tm4[n].tm.qtimer, new_qemu);
149
}
150

    
151
static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
152
{
153
    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
154
    int tm = 0;
155

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

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

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

    
225
    return 0;
226
}
227

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

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

    
328
static CPUReadMemoryFunc * const pxa2xx_timer_readfn[] = {
329
    pxa2xx_timer_read,
330
    pxa2xx_timer_read,
331
    pxa2xx_timer_read,
332
};
333

    
334
static CPUWriteMemoryFunc * const pxa2xx_timer_writefn[] = {
335
    pxa2xx_timer_write,
336
    pxa2xx_timer_write,
337
    pxa2xx_timer_write,
338
};
339

    
340
static void pxa2xx_timer_tick(void *opaque)
341
{
342
    PXA2xxTimer0 *t = (PXA2xxTimer0 *) opaque;
343
    PXA2xxTimerInfo *i = t->info;
344

    
345
    if (i->irq_enabled & (1 << t->num)) {
346
        i->events |= 1 << t->num;
347
        qemu_irq_raise(t->irq);
348
    }
349

    
350
    if (t->num == 3)
351
        if (i->reset3 & 1) {
352
            i->reset3 = 0;
353
            qemu_system_reset_request();
354
        }
355
}
356

    
357
static void pxa2xx_timer_tick4(void *opaque)
358
{
359
    PXA2xxTimer4 *t = (PXA2xxTimer4 *) opaque;
360
    PXA2xxTimerInfo *i = (PXA2xxTimerInfo *) t->tm.info;
361

    
362
    pxa2xx_timer_tick(&t->tm);
363
    if (t->control & (1 << 3))
364
        t->clock = 0;
365
    if (t->control & (1 << 6))
366
        pxa2xx_timer_update4(i, qemu_get_clock_ns(vm_clock), t->tm.num - 4);
367
    if (i->events & 0xff0)
368
        qemu_irq_raise(i->irq4);
369
}
370

    
371
static int pxa25x_timer_post_load(void *opaque, int version_id)
372
{
373
    PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
374
    int64_t now;
375
    int i;
376

    
377
    now = qemu_get_clock_ns(vm_clock);
378
    pxa2xx_timer_update(s, now);
379

    
380
    if (pxa2xx_timer_has_tm4(s))
381
        for (i = 0; i < 8; i ++)
382
            pxa2xx_timer_update4(s, now, i);
383

    
384
    return 0;
385
}
386

    
387
static int pxa2xx_timer_init(SysBusDevice *dev)
388
{
389
    int i;
390
    int iomemtype;
391
    PXA2xxTimerInfo *s;
392

    
393
    s = FROM_SYSBUS(PXA2xxTimerInfo, dev);
394
    s->irq_enabled = 0;
395
    s->oldclock = 0;
396
    s->clock = 0;
397
    s->lastload = qemu_get_clock_ns(vm_clock);
398
    s->reset3 = 0;
399

    
400
    for (i = 0; i < 4; i ++) {
401
        s->timer[i].value = 0;
402
        sysbus_init_irq(dev, &s->timer[i].irq);
403
        s->timer[i].info = s;
404
        s->timer[i].num = i;
405
        s->timer[i].qtimer = qemu_new_timer_ns(vm_clock,
406
                        pxa2xx_timer_tick, &s->timer[i]);
407
    }
408
    if (s->flags & (1 << PXA2XX_TIMER_HAVE_TM4)) {
409
        sysbus_init_irq(dev, &s->irq4);
410

    
411
        for (i = 0; i < 8; i ++) {
412
            s->tm4[i].tm.value = 0;
413
            s->tm4[i].tm.info = s;
414
            s->tm4[i].tm.num = i + 4;
415
            s->tm4[i].freq = 0;
416
            s->tm4[i].control = 0x0;
417
            s->tm4[i].tm.qtimer = qemu_new_timer_ns(vm_clock,
418
                        pxa2xx_timer_tick4, &s->tm4[i]);
419
        }
420
    }
421

    
422
    iomemtype = cpu_register_io_memory(pxa2xx_timer_readfn,
423
                    pxa2xx_timer_writefn, s, DEVICE_NATIVE_ENDIAN);
424
    sysbus_init_mmio(dev, 0x00001000, iomemtype);
425

    
426
    return 0;
427
}
428

    
429
static const VMStateDescription vmstate_pxa2xx_timer0_regs = {
430
    .name = "pxa2xx_timer0",
431
    .version_id = 2,
432
    .minimum_version_id = 2,
433
    .minimum_version_id_old = 2,
434
    .fields = (VMStateField[]) {
435
        VMSTATE_UINT32(value, PXA2xxTimer0),
436
        VMSTATE_END_OF_LIST(),
437
    },
438
};
439

    
440
static const VMStateDescription vmstate_pxa2xx_timer4_regs = {
441
    .name = "pxa2xx_timer4",
442
    .version_id = 1,
443
    .minimum_version_id = 1,
444
    .minimum_version_id_old = 1,
445
    .fields = (VMStateField[]) {
446
        VMSTATE_STRUCT(tm, PXA2xxTimer4, 1,
447
                        vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
448
        VMSTATE_INT32(oldclock, PXA2xxTimer4),
449
        VMSTATE_INT32(clock, PXA2xxTimer4),
450
        VMSTATE_UINT64(lastload, PXA2xxTimer4),
451
        VMSTATE_UINT32(freq, PXA2xxTimer4),
452
        VMSTATE_UINT32(control, PXA2xxTimer4),
453
        VMSTATE_END_OF_LIST(),
454
    },
455
};
456

    
457
static bool pxa2xx_timer_has_tm4_test(void *opaque, int version_id)
458
{
459
    return pxa2xx_timer_has_tm4(opaque);
460
}
461

    
462
static const VMStateDescription vmstate_pxa2xx_timer_regs = {
463
    .name = "pxa2xx_timer",
464
    .version_id = 1,
465
    .minimum_version_id = 1,
466
    .minimum_version_id_old = 1,
467
    .post_load = pxa25x_timer_post_load,
468
    .fields = (VMStateField[]) {
469
        VMSTATE_INT32(clock, PXA2xxTimerInfo),
470
        VMSTATE_INT32(oldclock, PXA2xxTimerInfo),
471
        VMSTATE_UINT64(lastload, PXA2xxTimerInfo),
472
        VMSTATE_STRUCT_ARRAY(timer, PXA2xxTimerInfo, 4, 1,
473
                        vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
474
        VMSTATE_UINT32(events, PXA2xxTimerInfo),
475
        VMSTATE_UINT32(irq_enabled, PXA2xxTimerInfo),
476
        VMSTATE_UINT32(reset3, PXA2xxTimerInfo),
477
        VMSTATE_UINT32(snapshot, PXA2xxTimerInfo),
478
        VMSTATE_STRUCT_ARRAY_TEST(tm4, PXA2xxTimerInfo, 8,
479
                        pxa2xx_timer_has_tm4_test, 0,
480
                        vmstate_pxa2xx_timer4_regs, PXA2xxTimer4),
481
        VMSTATE_END_OF_LIST(),
482
    }
483
};
484

    
485
static SysBusDeviceInfo pxa25x_timer_dev_info = {
486
    .init       = pxa2xx_timer_init,
487
    .qdev.name  = "pxa25x-timer",
488
    .qdev.desc  = "PXA25x timer",
489
    .qdev.size  = sizeof(PXA2xxTimerInfo),
490
    .qdev.vmsd  = &vmstate_pxa2xx_timer_regs,
491
    .qdev.props = (Property[]) {
492
        DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA25X_FREQ),
493
        DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
494
                        PXA2XX_TIMER_HAVE_TM4, false),
495
        DEFINE_PROP_END_OF_LIST(),
496
    },
497
};
498

    
499
static SysBusDeviceInfo pxa27x_timer_dev_info = {
500
    .init       = pxa2xx_timer_init,
501
    .qdev.name  = "pxa27x-timer",
502
    .qdev.desc  = "PXA27x timer",
503
    .qdev.size  = sizeof(PXA2xxTimerInfo),
504
    .qdev.vmsd  = &vmstate_pxa2xx_timer_regs,
505
    .qdev.props = (Property[]) {
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

    
513
static void pxa2xx_timer_register(void)
514
{
515
    sysbus_register_withprop(&pxa25x_timer_dev_info);
516
    sysbus_register_withprop(&pxa27x_timer_dev_info);
517
};
518
device_init(pxa2xx_timer_register);