|
|
1.1 root 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:
1.1.1.2 ! root 370: qemu_put_be32s(f, (uint32_t *) &s->clock);
! 371: qemu_put_be32s(f, (uint32_t *) &s->oldclock);
1.1 root 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);
1.1.1.2 ! root 382: qemu_put_sbe32s(f, &s->tm4[i].oldclock);
! 383: qemu_put_sbe32s(f, &s->tm4[i].clock);
1.1 root 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:
1.1.1.2 ! root 401: qemu_get_be32s(f, (uint32_t *) &s->clock);
! 402: qemu_get_be32s(f, (uint32_t *) &s->oldclock);
1.1 root 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);
1.1.1.2 ! root 416: qemu_get_sbe32s(f, &s->tm4[i].oldclock);
! 417: qemu_get_sbe32s(f, &s->tm4[i].clock);
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.