Statistics
| Branch: | Revision:

root / hw / pxa2xx_timer.c @ a171fe39

History | View | Annotate | Download (11.4 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 "vl.h"
11

    
12
#define OSMR0        0x00
13
#define OSMR1        0x04
14
#define OSMR2        0x08
15
#define OSMR3        0x0c
16
#define OSMR4        0x80
17
#define OSMR5        0x84
18
#define OSMR6        0x88
19
#define OSMR7        0x8c
20
#define OSMR8        0x90
21
#define OSMR9        0x94
22
#define OSMR10        0x98
23
#define OSMR11        0x9c
24
#define OSCR        0x10        /* OS Timer Count */
25
#define OSCR4        0x40
26
#define OSCR5        0x44
27
#define OSCR6        0x48
28
#define OSCR7        0x4c
29
#define OSCR8        0x50
30
#define OSCR9        0x54
31
#define OSCR10        0x58
32
#define OSCR11        0x5c
33
#define OSSR        0x14        /* Timer status register */
34
#define OWER        0x18
35
#define OIER        0x1c        /* Interrupt enable register  3-0 to E3-E0 */
36
#define OMCR4        0xc0        /* OS Match Control registers */
37
#define OMCR5        0xc4
38
#define OMCR6        0xc8
39
#define OMCR7        0xcc
40
#define OMCR8        0xd0
41
#define OMCR9        0xd4
42
#define OMCR10        0xd8
43
#define OMCR11        0xdc
44
#define OSNR        0x20
45

    
46
#define PXA25X_FREQ        3686400        /* 3.6864 MHz */
47
#define PXA27X_FREQ        3250000        /* 3.25 MHz */
48

    
49
static int pxa2xx_timer4_freq[8] = {
50
    [0] = 0,
51
    [1] = 32768,
52
    [2] = 1000,
53
    [3] = 1,
54
    [4] = 1000000,
55
    /* [5] is the "Externally supplied clock".  Assign if necessary.  */
56
    [5 ... 7] = 0,
57
};
58

    
59
struct pxa2xx_timer0_s {
60
    uint32_t value;
61
    int level;
62
    qemu_irq irq;
63
    QEMUTimer *qtimer;
64
    int num;
65
    void *info;
66
};
67

    
68
struct pxa2xx_timer4_s {
69
    uint32_t value;
70
    int level;
71
    qemu_irq irq;
72
    QEMUTimer *qtimer;
73
    int num;
74
    void *info;
75
    int32_t oldclock;
76
    int32_t clock;
77
    uint64_t lastload;
78
    uint32_t freq;
79
    uint32_t control;
80
};
81

    
82
typedef struct {
83
    uint32_t base;
84
    int32_t clock;
85
    int32_t oldclock;
86
    uint64_t lastload;
87
    uint32_t freq;
88
    struct pxa2xx_timer0_s timer[4];
89
    struct pxa2xx_timer4_s *tm4;
90
    uint32_t events;
91
    uint32_t irq_enabled;
92
    uint32_t reset3;
93
    CPUState *cpustate;
94
    int64_t qemu_ticks;
95
    uint32_t snapshot;
96
} pxa2xx_timer_info;
97

    
98
static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu)
99
{
100
    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
101
    int i;
102
    uint32_t now_vm;
103
    uint64_t new_qemu;
104

    
105
    now_vm = s->clock +
106
            muldiv64(now_qemu - s->lastload, s->freq, ticks_per_sec);
107

    
108
    for (i = 0; i < 4; i ++) {
109
        new_qemu = now_qemu + muldiv64((uint32_t) (s->timer[i].value - now_vm),
110
                        ticks_per_sec, s->freq);
111
        qemu_mod_timer(s->timer[i].qtimer, new_qemu);
112
    }
113
}
114

    
115
static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n)
116
{
117
    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
118
    uint32_t now_vm;
119
    uint64_t new_qemu;
120
    static const int counters[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
121
    int counter;
122

    
123
    if (s->tm4[n].control & (1 << 7))
124
        counter = n;
125
    else
126
        counter = counters[n];
127

    
128
    if (!s->tm4[counter].freq) {
129
        qemu_del_timer(s->timer[n].qtimer);
130
        return;
131
    }
132

    
133
    now_vm = s->tm4[counter].clock + muldiv64(now_qemu -
134
                    s->tm4[counter].lastload,
135
                    s->tm4[counter].freq, ticks_per_sec);
136

    
137
    new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].value - now_vm),
138
                    ticks_per_sec, s->tm4[counter].freq);
139
    qemu_mod_timer(s->timer[n].qtimer, new_qemu);
140
}
141

    
142
static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
143
{
144
    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
145
    int tm = 0;
146

    
147
    offset -= s->base;
148

    
149
    switch (offset) {
150
    case OSMR3:  tm ++;
151
    case OSMR2:  tm ++;
152
    case OSMR1:  tm ++;
153
    case OSMR0:
154
        return s->timer[tm].value;
155
    case OSMR11: tm ++;
156
    case OSMR10: tm ++;
157
    case OSMR9:  tm ++;
158
    case OSMR8:  tm ++;
159
    case OSMR7:  tm ++;
160
    case OSMR6:  tm ++;
161
    case OSMR5:  tm ++;
162
    case OSMR4:
163
        if (!s->tm4)
164
            goto badreg;
165
        return s->tm4[tm].value;
166
    case OSCR:
167
        return s->clock + muldiv64(qemu_get_clock(vm_clock) -
168
                        s->lastload, s->freq, ticks_per_sec);
169
    case OSCR11: tm ++;
170
    case OSCR10: tm ++;
171
    case OSCR9:  tm ++;
172
    case OSCR8:  tm ++;
173
    case OSCR7:  tm ++;
174
    case OSCR6:  tm ++;
175
    case OSCR5:  tm ++;
176
    case OSCR4:
177
        if (!s->tm4)
178
            goto badreg;
179

    
180
        if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) {
181
            if (s->tm4[tm - 1].freq)
182
                s->snapshot = s->tm4[tm - 1].clock + muldiv64(
183
                                qemu_get_clock(vm_clock) -
184
                                s->tm4[tm - 1].lastload,
185
                                s->tm4[tm - 1].freq, ticks_per_sec);
186
            else
187
                s->snapshot = s->tm4[tm - 1].clock;
188
        }
189

    
190
        if (!s->tm4[tm].freq)
191
            return s->tm4[tm].clock;
192
        return s->tm4[tm].clock + muldiv64(qemu_get_clock(vm_clock) -
193
                        s->tm4[tm].lastload, s->tm4[tm].freq, ticks_per_sec);
194
    case OIER:
195
        return s->irq_enabled;
196
    case OSSR:        /* Status register */
197
        return s->events;
198
    case OWER:
199
        return s->reset3;
200
    case OMCR11: tm ++;
201
    case OMCR10: tm ++;
202
    case OMCR9:  tm ++;
203
    case OMCR8:  tm ++;
204
    case OMCR7:  tm ++;
205
    case OMCR6:  tm ++;
206
    case OMCR5:  tm ++;
207
    case OMCR4:
208
        if (!s->tm4)
209
            goto badreg;
210
        return s->tm4[tm].control;
211
    case OSNR:
212
        return s->snapshot;
213
    default:
214
    badreg:
215
        cpu_abort(cpu_single_env, "pxa2xx_timer_read: Bad offset "
216
                        REG_FMT "\n", offset);
217
    }
218

    
219
    return 0;
220
}
221

    
222
static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
223
                uint32_t value)
224
{
225
    int i, tm = 0;
226
    pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
227

    
228
    offset -= s->base;
229

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

    
332
static CPUReadMemoryFunc *pxa2xx_timer_readfn[] = {
333
    pxa2xx_timer_read,
334
    pxa2xx_timer_read,
335
    pxa2xx_timer_read,
336
};
337

    
338
static CPUWriteMemoryFunc *pxa2xx_timer_writefn[] = {
339
    pxa2xx_timer_write,
340
    pxa2xx_timer_write,
341
    pxa2xx_timer_write,
342
};
343

    
344
static void pxa2xx_timer_tick(void *opaque)
345
{
346
    struct pxa2xx_timer0_s *t = (struct pxa2xx_timer0_s *) opaque;
347
    pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->info;
348

    
349
    if (i->irq_enabled & (1 << t->num)) {
350
        t->level = 1;
351
        i->events |= 1 << t->num;
352
        qemu_irq_raise(t->irq);
353
    }
354

    
355
    if (t->num == 3)
356
        if (i->reset3 & 1) {
357
            i->reset3 = 0;
358
            cpu_reset(i->cpustate);
359
        }
360
}
361

    
362
static void pxa2xx_timer_tick4(void *opaque)
363
{
364
    struct pxa2xx_timer4_s *t = (struct pxa2xx_timer4_s *) opaque;
365
    pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->info;
366

    
367
    pxa2xx_timer_tick4(opaque);
368
    if (t->control & (1 << 3))
369
        t->clock = 0;
370
    if (t->control & (1 << 6))
371
        pxa2xx_timer_update4(i, qemu_get_clock(vm_clock), t->num - 4);
372
}
373

    
374
static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
375
                qemu_irq *irqs, CPUState *cpustate)
376
{
377
    int i;
378
    int iomemtype;
379
    pxa2xx_timer_info *s;
380

    
381
    s = (pxa2xx_timer_info *) qemu_mallocz(sizeof(pxa2xx_timer_info));
382
    s->base = base;
383
    s->irq_enabled = 0;
384
    s->oldclock = 0;
385
    s->clock = 0;
386
    s->lastload = qemu_get_clock(vm_clock);
387
    s->reset3 = 0;
388
    s->cpustate = cpustate;
389

    
390
    for (i = 0; i < 4; i ++) {
391
        s->timer[i].value = 0;
392
        s->timer[i].irq = irqs[i];
393
        s->timer[i].info = s;
394
        s->timer[i].num = i;
395
        s->timer[i].level = 0;
396
        s->timer[i].qtimer = qemu_new_timer(vm_clock,
397
                        pxa2xx_timer_tick, &s->timer[i]);
398
    }
399

    
400
    iomemtype = cpu_register_io_memory(0, pxa2xx_timer_readfn,
401
                    pxa2xx_timer_writefn, s);
402
    cpu_register_physical_memory(base, 0x00000fff, iomemtype);
403
    return s;
404
}
405

    
406
void pxa25x_timer_init(target_phys_addr_t base,
407
                qemu_irq *irqs, CPUState *cpustate)
408
{
409
    pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs, cpustate);
410
    s->freq = PXA25X_FREQ;
411
    s->tm4 = 0;
412
}
413

    
414
void pxa27x_timer_init(target_phys_addr_t base,
415
                qemu_irq *irqs, qemu_irq irq4, CPUState *cpustate)
416
{
417
    pxa2xx_timer_info *s = pxa2xx_timer_init(base, irqs, cpustate);
418
    int i;
419
    s->freq = PXA27X_FREQ;
420
    s->tm4 = (struct pxa2xx_timer4_s *) qemu_mallocz(8 *
421
                    sizeof(struct pxa2xx_timer4_s));
422
    for (i = 0; i < 8; i ++) {
423
        s->tm4[i].value = 0;
424
        s->tm4[i].irq = irq4;
425
        s->tm4[i].info = s;
426
        s->tm4[i].num = i + 4;
427
        s->tm4[i].level = 0;
428
        s->tm4[i].freq = 0;
429
        s->tm4[i].control = 0x0;
430
        s->tm4[i].qtimer = qemu_new_timer(vm_clock,
431
                        pxa2xx_timer_tick4, &s->tm4[i]);
432
    }
433
}