Statistics
| Branch: | Revision:

root / hw / pxa2xx_timer.c @ b79e1752

History | View | Annotate | Download (13.3 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
struct pxa2xx_timer0_s {
63
    uint32_t value;
64
    int level;
65
    qemu_irq irq;
66
    QEMUTimer *qtimer;
67
    int num;
68
    void *info;
69
};
70

    
71
struct pxa2xx_timer4_s {
72
    struct pxa2xx_timer0_s tm;
73
    int32_t oldclock;
74
    int32_t clock;
75
    uint64_t lastload;
76
    uint32_t freq;
77
    uint32_t control;
78
};
79

    
80
typedef struct {
81
    int32_t clock;
82
    int32_t oldclock;
83
    uint64_t lastload;
84
    uint32_t freq;
85
    struct pxa2xx_timer0_s timer[4];
86
    struct pxa2xx_timer4_s *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, 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
                        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, ticks_per_sec);
131

    
132
    new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].tm.value - now_vm),
133
                    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, 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, 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, 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
        cpu_abort(cpu_single_env, "pxa2xx_timer_read: Bad offset "
209
                        REG_FMT "\n", offset);
210
    }
211

    
212
    return 0;
213
}
214

    
215
static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
216
                uint32_t value)
217
{
218
    int i, tm = 0;
219
    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
220

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

    
323
static CPUReadMemoryFunc *pxa2xx_timer_readfn[] = {
324
    pxa2xx_timer_read,
325
    pxa2xx_timer_read,
326
    pxa2xx_timer_read,
327
};
328

    
329
static CPUWriteMemoryFunc *pxa2xx_timer_writefn[] = {
330
    pxa2xx_timer_write,
331
    pxa2xx_timer_write,
332
    pxa2xx_timer_write,
333
};
334

    
335
static void pxa2xx_timer_tick(void *opaque)
336
{
337
    struct pxa2xx_timer0_s *t = (struct pxa2xx_timer0_s *) opaque;
338
    pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->info;
339

    
340
    if (i->irq_enabled & (1 << t->num)) {
341
        t->level = 1;
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
    struct pxa2xx_timer4_s *t = (struct pxa2xx_timer4_s *) opaque;
356
    pxa2xx_timer_info *i = (pxa2xx_timer_info *) 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(vm_clock), t->tm.num - 4);
363
}
364

    
365
static void pxa2xx_timer_save(QEMUFile *f, void *opaque)
366
{
367
    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
368
    int i;
369

    
370
    qemu_put_be32s(f, (uint32_t *) &s->clock);
371
    qemu_put_be32s(f, (uint32_t *) &s->oldclock);
372
    qemu_put_be64s(f, &s->lastload);
373

    
374
    for (i = 0; i < 4; i ++) {
375
        qemu_put_be32s(f, &s->timer[i].value);
376
        qemu_put_be32(f, s->timer[i].level);
377
    }
378
    if (s->tm4)
379
        for (i = 0; i < 8; i ++) {
380
            qemu_put_be32s(f, &s->tm4[i].tm.value);
381
            qemu_put_be32(f, s->tm4[i].tm.level);
382
            qemu_put_sbe32s(f, &s->tm4[i].oldclock);
383
            qemu_put_sbe32s(f, &s->tm4[i].clock);
384
            qemu_put_be64s(f, &s->tm4[i].lastload);
385
            qemu_put_be32s(f, &s->tm4[i].freq);
386
            qemu_put_be32s(f, &s->tm4[i].control);
387
        }
388

    
389
    qemu_put_be32s(f, &s->events);
390
    qemu_put_be32s(f, &s->irq_enabled);
391
    qemu_put_be32s(f, &s->reset3);
392
    qemu_put_be32s(f, &s->snapshot);
393
}
394

    
395
static int pxa2xx_timer_load(QEMUFile *f, void *opaque, int version_id)
396
{
397
    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
398
    int64_t now;
399
    int i;
400

    
401
    qemu_get_be32s(f, (uint32_t *) &s->clock);
402
    qemu_get_be32s(f, (uint32_t *) &s->oldclock);
403
    qemu_get_be64s(f, &s->lastload);
404

    
405
    now = qemu_get_clock(vm_clock);
406
    for (i = 0; i < 4; i ++) {
407
        qemu_get_be32s(f, &s->timer[i].value);
408
        s->timer[i].level = qemu_get_be32(f);
409
    }
410
    pxa2xx_timer_update(s, now);
411

    
412
    if (s->tm4)
413
        for (i = 0; i < 8; i ++) {
414
            qemu_get_be32s(f, &s->tm4[i].tm.value);
415
            s->tm4[i].tm.level = qemu_get_be32(f);
416
            qemu_get_sbe32s(f, &s->tm4[i].oldclock);
417
            qemu_get_sbe32s(f, &s->tm4[i].clock);
418
            qemu_get_be64s(f, &s->tm4[i].lastload);
419
            qemu_get_be32s(f, &s->tm4[i].freq);
420
            qemu_get_be32s(f, &s->tm4[i].control);
421
            pxa2xx_timer_update4(s, now, i);
422
        }
423

    
424
    qemu_get_be32s(f, &s->events);
425
    qemu_get_be32s(f, &s->irq_enabled);
426
    qemu_get_be32s(f, &s->reset3);
427
    qemu_get_be32s(f, &s->snapshot);
428

    
429
    return 0;
430
}
431

    
432
static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
433
                qemu_irq *irqs)
434
{
435
    int i;
436
    int iomemtype;
437
    pxa2xx_timer_info *s;
438

    
439
    s = (pxa2xx_timer_info *) qemu_mallocz(sizeof(pxa2xx_timer_info));
440
    s->irq_enabled = 0;
441
    s->oldclock = 0;
442
    s->clock = 0;
443
    s->lastload = qemu_get_clock(vm_clock);
444
    s->reset3 = 0;
445

    
446
    for (i = 0; i < 4; i ++) {
447
        s->timer[i].value = 0;
448
        s->timer[i].irq = irqs[i];
449
        s->timer[i].info = s;
450
        s->timer[i].num = i;
451
        s->timer[i].level = 0;
452
        s->timer[i].qtimer = qemu_new_timer(vm_clock,
453
                        pxa2xx_timer_tick, &s->timer[i]);
454
    }
455

    
456
    iomemtype = cpu_register_io_memory(0, pxa2xx_timer_readfn,
457
                    pxa2xx_timer_writefn, s);
458
    cpu_register_physical_memory(base, 0x00001000, iomemtype);
459

    
460
    register_savevm("pxa2xx_timer", 0, 0,
461
                    pxa2xx_timer_save, pxa2xx_timer_load, s);
462

    
463
    return s;
464
}
465

    
466
void pxa25x_timer_init(target_phys_addr_t base, qemu_irq *irqs)
467
{
468
    pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs);
469
    s->freq = PXA25X_FREQ;
470
    s->tm4 = 0;
471
}
472

    
473
void pxa27x_timer_init(target_phys_addr_t base,
474
                qemu_irq *irqs, qemu_irq irq4)
475
{
476
    pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs);
477
    int i;
478
    s->freq = PXA27X_FREQ;
479
    s->tm4 = (struct pxa2xx_timer4_s *) qemu_mallocz(8 *
480
                    sizeof(struct pxa2xx_timer4_s));
481
    for (i = 0; i < 8; i ++) {
482
        s->tm4[i].tm.value = 0;
483
        s->tm4[i].tm.irq = irq4;
484
        s->tm4[i].tm.info = s;
485
        s->tm4[i].tm.num = i + 4;
486
        s->tm4[i].tm.level = 0;
487
        s->tm4[i].freq = 0;
488
        s->tm4[i].control = 0x0;
489
        s->tm4[i].tm.qtimer = qemu_new_timer(vm_clock,
490
                        pxa2xx_timer_tick4, &s->tm4[i]);
491
    }
492
}