Statistics
| Branch: | Revision:

root / hw / pxa2xx_timer.c @ 43ad7e3e

History | View | Annotate | Download (13.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

    
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

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

    
62
typedef struct {
63
    uint32_t value;
64
    int level;
65
    qemu_irq irq;
66
    QEMUTimer *qtimer;
67
    int num;
68
    void *info;
69
} PXA2xxTimer0;
70

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

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

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

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

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

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

    
321
static CPUReadMemoryFunc * const pxa2xx_timer_readfn[] = {
322
    pxa2xx_timer_read,
323
    pxa2xx_timer_read,
324
    pxa2xx_timer_read,
325
};
326

    
327
static CPUWriteMemoryFunc * const pxa2xx_timer_writefn[] = {
328
    pxa2xx_timer_write,
329
    pxa2xx_timer_write,
330
    pxa2xx_timer_write,
331
};
332

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

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

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

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

    
430
static 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);
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

    
464
void 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

    
471
void 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
}