]> Git Repo - qemu.git/blob - hw/pxa2xx_timer.c
pxa2xx_pic: update to use qdev
[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 "hw.h"
11 #include "qemu-timer.h"
12 #include "sysemu.h"
13 #include "qdev.h"
14 #include "pxa.h"
15
16 #define OSMR0   0x00
17 #define OSMR1   0x04
18 #define OSMR2   0x08
19 #define OSMR3   0x0c
20 #define OSMR4   0x80
21 #define OSMR5   0x84
22 #define OSMR6   0x88
23 #define OSMR7   0x8c
24 #define OSMR8   0x90
25 #define OSMR9   0x94
26 #define OSMR10  0x98
27 #define OSMR11  0x9c
28 #define OSCR    0x10    /* OS Timer Count */
29 #define OSCR4   0x40
30 #define OSCR5   0x44
31 #define OSCR6   0x48
32 #define OSCR7   0x4c
33 #define OSCR8   0x50
34 #define OSCR9   0x54
35 #define OSCR10  0x58
36 #define OSCR11  0x5c
37 #define OSSR    0x14    /* Timer status register */
38 #define OWER    0x18
39 #define OIER    0x1c    /* Interrupt enable register  3-0 to E3-E0 */
40 #define OMCR4   0xc0    /* OS Match Control registers */
41 #define OMCR5   0xc4
42 #define OMCR6   0xc8
43 #define OMCR7   0xcc
44 #define OMCR8   0xd0
45 #define OMCR9   0xd4
46 #define OMCR10  0xd8
47 #define OMCR11  0xdc
48 #define OSNR    0x20
49
50 #define PXA25X_FREQ     3686400 /* 3.6864 MHz */
51 #define PXA27X_FREQ     3250000 /* 3.25 MHz */
52
53 static int pxa2xx_timer4_freq[8] = {
54     [0] = 0,
55     [1] = 32768,
56     [2] = 1000,
57     [3] = 1,
58     [4] = 1000000,
59     /* [5] is the "Externally supplied clock".  Assign if necessary.  */
60     [5 ... 7] = 0,
61 };
62
63 typedef struct {
64     uint32_t value;
65     int level;
66     qemu_irq irq;
67     QEMUTimer *qtimer;
68     int num;
69     void *info;
70 } PXA2xxTimer0;
71
72 typedef struct {
73     PXA2xxTimer0 tm;
74     int32_t oldclock;
75     int32_t clock;
76     uint64_t lastload;
77     uint32_t freq;
78     uint32_t control;
79 } PXA2xxTimer4;
80
81 typedef struct {
82     int32_t clock;
83     int32_t oldclock;
84     uint64_t lastload;
85     uint32_t freq;
86     PXA2xxTimer0 timer[4];
87     PXA2xxTimer4 *tm4;
88     uint32_t events;
89     uint32_t irq_enabled;
90     uint32_t reset3;
91     uint32_t snapshot;
92 } pxa2xx_timer_info;
93
94 static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu)
95 {
96     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
97     int i;
98     uint32_t now_vm;
99     uint64_t new_qemu;
100
101     now_vm = s->clock +
102             muldiv64(now_qemu - s->lastload, s->freq, get_ticks_per_sec());
103
104     for (i = 0; i < 4; i ++) {
105         new_qemu = now_qemu + muldiv64((uint32_t) (s->timer[i].value - now_vm),
106                         get_ticks_per_sec(), s->freq);
107         qemu_mod_timer(s->timer[i].qtimer, new_qemu);
108     }
109 }
110
111 static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n)
112 {
113     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
114     uint32_t now_vm;
115     uint64_t new_qemu;
116     static const int counters[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
117     int counter;
118
119     if (s->tm4[n].control & (1 << 7))
120         counter = n;
121     else
122         counter = counters[n];
123
124     if (!s->tm4[counter].freq) {
125         qemu_del_timer(s->tm4[n].tm.qtimer);
126         return;
127     }
128
129     now_vm = s->tm4[counter].clock + muldiv64(now_qemu -
130                     s->tm4[counter].lastload,
131                     s->tm4[counter].freq, get_ticks_per_sec());
132
133     new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].tm.value - now_vm),
134                     get_ticks_per_sec(), s->tm4[counter].freq);
135     qemu_mod_timer(s->tm4[n].tm.qtimer, new_qemu);
136 }
137
138 static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
139 {
140     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
141     int tm = 0;
142
143     switch (offset) {
144     case OSMR3:  tm ++;
145     case OSMR2:  tm ++;
146     case OSMR1:  tm ++;
147     case OSMR0:
148         return s->timer[tm].value;
149     case OSMR11: tm ++;
150     case OSMR10: tm ++;
151     case OSMR9:  tm ++;
152     case OSMR8:  tm ++;
153     case OSMR7:  tm ++;
154     case OSMR6:  tm ++;
155     case OSMR5:  tm ++;
156     case OSMR4:
157         if (!s->tm4)
158             goto badreg;
159         return s->tm4[tm].tm.value;
160     case OSCR:
161         return s->clock + muldiv64(qemu_get_clock(vm_clock) -
162                         s->lastload, s->freq, get_ticks_per_sec());
163     case OSCR11: tm ++;
164     case OSCR10: tm ++;
165     case OSCR9:  tm ++;
166     case OSCR8:  tm ++;
167     case OSCR7:  tm ++;
168     case OSCR6:  tm ++;
169     case OSCR5:  tm ++;
170     case OSCR4:
171         if (!s->tm4)
172             goto badreg;
173
174         if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) {
175             if (s->tm4[tm - 1].freq)
176                 s->snapshot = s->tm4[tm - 1].clock + muldiv64(
177                                 qemu_get_clock(vm_clock) -
178                                 s->tm4[tm - 1].lastload,
179                                 s->tm4[tm - 1].freq, get_ticks_per_sec());
180             else
181                 s->snapshot = s->tm4[tm - 1].clock;
182         }
183
184         if (!s->tm4[tm].freq)
185             return s->tm4[tm].clock;
186         return s->tm4[tm].clock + muldiv64(qemu_get_clock(vm_clock) -
187                         s->tm4[tm].lastload, s->tm4[tm].freq, get_ticks_per_sec());
188     case OIER:
189         return s->irq_enabled;
190     case OSSR:  /* Status register */
191         return s->events;
192     case OWER:
193         return s->reset3;
194     case OMCR11: tm ++;
195     case OMCR10: tm ++;
196     case OMCR9:  tm ++;
197     case OMCR8:  tm ++;
198     case OMCR7:  tm ++;
199     case OMCR6:  tm ++;
200     case OMCR5:  tm ++;
201     case OMCR4:
202         if (!s->tm4)
203             goto badreg;
204         return s->tm4[tm].control;
205     case OSNR:
206         return s->snapshot;
207     default:
208     badreg:
209         hw_error("pxa2xx_timer_read: Bad offset " 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         hw_error("pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset);
319     }
320 }
321
322 static CPUReadMemoryFunc * const pxa2xx_timer_readfn[] = {
323     pxa2xx_timer_read,
324     pxa2xx_timer_read,
325     pxa2xx_timer_read,
326 };
327
328 static CPUWriteMemoryFunc * const pxa2xx_timer_writefn[] = {
329     pxa2xx_timer_write,
330     pxa2xx_timer_write,
331     pxa2xx_timer_write,
332 };
333
334 static void pxa2xx_timer_tick(void *opaque)
335 {
336     PXA2xxTimer0 *t = (PXA2xxTimer0 *) opaque;
337     pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->info;
338
339     if (i->irq_enabled & (1 << t->num)) {
340         t->level = 1;
341         i->events |= 1 << t->num;
342         qemu_irq_raise(t->irq);
343     }
344
345     if (t->num == 3)
346         if (i->reset3 & 1) {
347             i->reset3 = 0;
348             qemu_system_reset_request();
349         }
350 }
351
352 static void pxa2xx_timer_tick4(void *opaque)
353 {
354     PXA2xxTimer4 *t = (PXA2xxTimer4 *) opaque;
355     pxa2xx_timer_info *i = (pxa2xx_timer_info *) t->tm.info;
356
357     pxa2xx_timer_tick(&t->tm);
358     if (t->control & (1 << 3))
359         t->clock = 0;
360     if (t->control & (1 << 6))
361         pxa2xx_timer_update4(i, qemu_get_clock(vm_clock), t->tm.num - 4);
362 }
363
364 static void pxa2xx_timer_save(QEMUFile *f, void *opaque)
365 {
366     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
367     int i;
368
369     qemu_put_be32s(f, (uint32_t *) &s->clock);
370     qemu_put_be32s(f, (uint32_t *) &s->oldclock);
371     qemu_put_be64s(f, &s->lastload);
372
373     for (i = 0; i < 4; i ++) {
374         qemu_put_be32s(f, &s->timer[i].value);
375         qemu_put_be32(f, s->timer[i].level);
376     }
377     if (s->tm4)
378         for (i = 0; i < 8; i ++) {
379             qemu_put_be32s(f, &s->tm4[i].tm.value);
380             qemu_put_be32(f, s->tm4[i].tm.level);
381             qemu_put_sbe32s(f, &s->tm4[i].oldclock);
382             qemu_put_sbe32s(f, &s->tm4[i].clock);
383             qemu_put_be64s(f, &s->tm4[i].lastload);
384             qemu_put_be32s(f, &s->tm4[i].freq);
385             qemu_put_be32s(f, &s->tm4[i].control);
386         }
387
388     qemu_put_be32s(f, &s->events);
389     qemu_put_be32s(f, &s->irq_enabled);
390     qemu_put_be32s(f, &s->reset3);
391     qemu_put_be32s(f, &s->snapshot);
392 }
393
394 static int pxa2xx_timer_load(QEMUFile *f, void *opaque, int version_id)
395 {
396     pxa2xx_timer_info *s = (pxa2xx_timer_info *) opaque;
397     int64_t now;
398     int i;
399
400     qemu_get_be32s(f, (uint32_t *) &s->clock);
401     qemu_get_be32s(f, (uint32_t *) &s->oldclock);
402     qemu_get_be64s(f, &s->lastload);
403
404     now = qemu_get_clock(vm_clock);
405     for (i = 0; i < 4; i ++) {
406         qemu_get_be32s(f, &s->timer[i].value);
407         s->timer[i].level = qemu_get_be32(f);
408     }
409     pxa2xx_timer_update(s, now);
410
411     if (s->tm4)
412         for (i = 0; i < 8; i ++) {
413             qemu_get_be32s(f, &s->tm4[i].tm.value);
414             s->tm4[i].tm.level = qemu_get_be32(f);
415             qemu_get_sbe32s(f, &s->tm4[i].oldclock);
416             qemu_get_sbe32s(f, &s->tm4[i].clock);
417             qemu_get_be64s(f, &s->tm4[i].lastload);
418             qemu_get_be32s(f, &s->tm4[i].freq);
419             qemu_get_be32s(f, &s->tm4[i].control);
420             pxa2xx_timer_update4(s, now, i);
421         }
422
423     qemu_get_be32s(f, &s->events);
424     qemu_get_be32s(f, &s->irq_enabled);
425     qemu_get_be32s(f, &s->reset3);
426     qemu_get_be32s(f, &s->snapshot);
427
428     return 0;
429 }
430
431 static pxa2xx_timer_info *pxa2xx_timer_init(target_phys_addr_t base,
432                 DeviceState *pic)
433 {
434     int i;
435     int iomemtype;
436     pxa2xx_timer_info *s;
437
438     s = (pxa2xx_timer_info *) qemu_mallocz(sizeof(pxa2xx_timer_info));
439     s->irq_enabled = 0;
440     s->oldclock = 0;
441     s->clock = 0;
442     s->lastload = qemu_get_clock(vm_clock);
443     s->reset3 = 0;
444
445     for (i = 0; i < 4; i ++) {
446         s->timer[i].value = 0;
447         s->timer[i].irq = qdev_get_gpio_in(pic, PXA2XX_PIC_OST_0 + i);
448         s->timer[i].info = s;
449         s->timer[i].num = i;
450         s->timer[i].level = 0;
451         s->timer[i].qtimer = qemu_new_timer(vm_clock,
452                         pxa2xx_timer_tick, &s->timer[i]);
453     }
454
455     iomemtype = cpu_register_io_memory(pxa2xx_timer_readfn,
456                     pxa2xx_timer_writefn, s, DEVICE_NATIVE_ENDIAN);
457     cpu_register_physical_memory(base, 0x00001000, iomemtype);
458
459     register_savevm(NULL, "pxa2xx_timer", 0, 0,
460                     pxa2xx_timer_save, pxa2xx_timer_load, s);
461
462     return s;
463 }
464
465 void pxa25x_timer_init(target_phys_addr_t base, DeviceState *pic)
466 {
467     pxa2xx_timer_info *s = pxa2xx_timer_init(base, pic);
468     s->freq = PXA25X_FREQ;
469     s->tm4 = NULL;
470 }
471
472 void pxa27x_timer_init(target_phys_addr_t base, DeviceState *pic)
473 {
474     pxa2xx_timer_info *s = pxa2xx_timer_init(base, pic);
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 = qdev_get_gpio_in(pic, PXA27X_PIC_OST_4_11);
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 }
This page took 0.053951 seconds and 4 git commands to generate.