]> git.proxmox.com Git - qemu.git/blob - hw/pxa2xx_timer.c
Set OOK when OON is set in OSCC register (thanks to BobOfDoom). Correct a fatal...
[qemu.git] / hw / pxa2xx_timer.c
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_tick(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 }