]> Git Repo - qemu.git/blob - hw/pxa2xx_timer.c
pxa2xx_timer: Get rid of .level in PXA2xxTimer0.
[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 "pxa.h"
14 #include "sysbus.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 PXA2xxTimerInfo PXA2xxTimerInfo;
64
65 typedef struct {
66     uint32_t value;
67     qemu_irq irq;
68     QEMUTimer *qtimer;
69     int num;
70     PXA2xxTimerInfo *info;
71 } PXA2xxTimer0;
72
73 typedef struct {
74     PXA2xxTimer0 tm;
75     int32_t oldclock;
76     int32_t clock;
77     uint64_t lastload;
78     uint32_t freq;
79     uint32_t control;
80 } PXA2xxTimer4;
81
82 struct PXA2xxTimerInfo {
83     SysBusDevice busdev;
84     uint32_t flags;
85
86     int32_t clock;
87     int32_t oldclock;
88     uint64_t lastload;
89     uint32_t freq;
90     PXA2xxTimer0 timer[4];
91     uint32_t events;
92     uint32_t irq_enabled;
93     uint32_t reset3;
94     uint32_t snapshot;
95
96     qemu_irq irq4;
97     PXA2xxTimer4 tm4[8];
98 };
99
100 #define PXA2XX_TIMER_HAVE_TM4   0
101
102 static inline int pxa2xx_timer_has_tm4(PXA2xxTimerInfo *s)
103 {
104     return s->flags & (1 << PXA2XX_TIMER_HAVE_TM4);
105 }
106
107 static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu)
108 {
109     PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
110     int i;
111     uint32_t now_vm;
112     uint64_t new_qemu;
113
114     now_vm = s->clock +
115             muldiv64(now_qemu - s->lastload, s->freq, get_ticks_per_sec());
116
117     for (i = 0; i < 4; i ++) {
118         new_qemu = now_qemu + muldiv64((uint32_t) (s->timer[i].value - now_vm),
119                         get_ticks_per_sec(), s->freq);
120         qemu_mod_timer(s->timer[i].qtimer, new_qemu);
121     }
122 }
123
124 static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n)
125 {
126     PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
127     uint32_t now_vm;
128     uint64_t new_qemu;
129     static const int counters[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
130     int counter;
131
132     if (s->tm4[n].control & (1 << 7))
133         counter = n;
134     else
135         counter = counters[n];
136
137     if (!s->tm4[counter].freq) {
138         qemu_del_timer(s->tm4[n].tm.qtimer);
139         return;
140     }
141
142     now_vm = s->tm4[counter].clock + muldiv64(now_qemu -
143                     s->tm4[counter].lastload,
144                     s->tm4[counter].freq, get_ticks_per_sec());
145
146     new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].tm.value - now_vm),
147                     get_ticks_per_sec(), s->tm4[counter].freq);
148     qemu_mod_timer(s->tm4[n].tm.qtimer, new_qemu);
149 }
150
151 static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
152 {
153     PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
154     int tm = 0;
155
156     switch (offset) {
157     case OSMR3:  tm ++;
158     case OSMR2:  tm ++;
159     case OSMR1:  tm ++;
160     case OSMR0:
161         return s->timer[tm].value;
162     case OSMR11: tm ++;
163     case OSMR10: tm ++;
164     case OSMR9:  tm ++;
165     case OSMR8:  tm ++;
166     case OSMR7:  tm ++;
167     case OSMR6:  tm ++;
168     case OSMR5:  tm ++;
169     case OSMR4:
170         if (!pxa2xx_timer_has_tm4(s))
171             goto badreg;
172         return s->tm4[tm].tm.value;
173     case OSCR:
174         return s->clock + muldiv64(qemu_get_clock(vm_clock) -
175                         s->lastload, s->freq, get_ticks_per_sec());
176     case OSCR11: tm ++;
177     case OSCR10: tm ++;
178     case OSCR9:  tm ++;
179     case OSCR8:  tm ++;
180     case OSCR7:  tm ++;
181     case OSCR6:  tm ++;
182     case OSCR5:  tm ++;
183     case OSCR4:
184         if (!pxa2xx_timer_has_tm4(s))
185             goto badreg;
186
187         if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) {
188             if (s->tm4[tm - 1].freq)
189                 s->snapshot = s->tm4[tm - 1].clock + muldiv64(
190                                 qemu_get_clock(vm_clock) -
191                                 s->tm4[tm - 1].lastload,
192                                 s->tm4[tm - 1].freq, get_ticks_per_sec());
193             else
194                 s->snapshot = s->tm4[tm - 1].clock;
195         }
196
197         if (!s->tm4[tm].freq)
198             return s->tm4[tm].clock;
199         return s->tm4[tm].clock + muldiv64(qemu_get_clock(vm_clock) -
200                         s->tm4[tm].lastload, s->tm4[tm].freq, get_ticks_per_sec());
201     case OIER:
202         return s->irq_enabled;
203     case OSSR:  /* Status register */
204         return s->events;
205     case OWER:
206         return s->reset3;
207     case OMCR11: tm ++;
208     case OMCR10: tm ++;
209     case OMCR9:  tm ++;
210     case OMCR8:  tm ++;
211     case OMCR7:  tm ++;
212     case OMCR6:  tm ++;
213     case OMCR5:  tm ++;
214     case OMCR4:
215         if (!pxa2xx_timer_has_tm4(s))
216             goto badreg;
217         return s->tm4[tm].control;
218     case OSNR:
219         return s->snapshot;
220     default:
221     badreg:
222         hw_error("pxa2xx_timer_read: Bad offset " REG_FMT "\n", offset);
223     }
224
225     return 0;
226 }
227
228 static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
229                 uint32_t value)
230 {
231     int i, tm = 0;
232     PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
233
234     switch (offset) {
235     case OSMR3:  tm ++;
236     case OSMR2:  tm ++;
237     case OSMR1:  tm ++;
238     case OSMR0:
239         s->timer[tm].value = value;
240         pxa2xx_timer_update(s, qemu_get_clock(vm_clock));
241         break;
242     case OSMR11: tm ++;
243     case OSMR10: tm ++;
244     case OSMR9:  tm ++;
245     case OSMR8:  tm ++;
246     case OSMR7:  tm ++;
247     case OSMR6:  tm ++;
248     case OSMR5:  tm ++;
249     case OSMR4:
250         if (!pxa2xx_timer_has_tm4(s))
251             goto badreg;
252         s->tm4[tm].tm.value = value;
253         pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
254         break;
255     case OSCR:
256         s->oldclock = s->clock;
257         s->lastload = qemu_get_clock(vm_clock);
258         s->clock = value;
259         pxa2xx_timer_update(s, s->lastload);
260         break;
261     case OSCR11: tm ++;
262     case OSCR10: tm ++;
263     case OSCR9:  tm ++;
264     case OSCR8:  tm ++;
265     case OSCR7:  tm ++;
266     case OSCR6:  tm ++;
267     case OSCR5:  tm ++;
268     case OSCR4:
269         if (!pxa2xx_timer_has_tm4(s))
270             goto badreg;
271         s->tm4[tm].oldclock = s->tm4[tm].clock;
272         s->tm4[tm].lastload = qemu_get_clock(vm_clock);
273         s->tm4[tm].clock = value;
274         pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm);
275         break;
276     case OIER:
277         s->irq_enabled = value & 0xfff;
278         break;
279     case OSSR:  /* Status register */
280         value &= s->events;
281         s->events &= ~value;
282         for (i = 0; i < 4; i ++, value >>= 1)
283             if (value & 1)
284                 qemu_irq_lower(s->timer[i].irq);
285         if (pxa2xx_timer_has_tm4(s) && !(s->events & 0xff0) && value)
286             qemu_irq_lower(s->irq4);
287         break;
288     case OWER:  /* XXX: Reset on OSMR3 match? */
289         s->reset3 = value;
290         break;
291     case OMCR7:  tm ++;
292     case OMCR6:  tm ++;
293     case OMCR5:  tm ++;
294     case OMCR4:
295         if (!pxa2xx_timer_has_tm4(s))
296             goto badreg;
297         s->tm4[tm].control = value & 0x0ff;
298         /* XXX Stop if running (shouldn't happen) */
299         if ((value & (1 << 7)) || tm == 0)
300             s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7];
301         else {
302             s->tm4[tm].freq = 0;
303             pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
304         }
305         break;
306     case OMCR11: tm ++;
307     case OMCR10: tm ++;
308     case OMCR9:  tm ++;
309     case OMCR8:  tm += 4;
310         if (!pxa2xx_timer_has_tm4(s))
311             goto badreg;
312         s->tm4[tm].control = value & 0x3ff;
313         /* XXX Stop if running (shouldn't happen) */
314         if ((value & (1 << 7)) || !(tm & 1))
315             s->tm4[tm].freq =
316                     pxa2xx_timer4_freq[(value & (1 << 8)) ?  0 : (value & 7)];
317         else {
318             s->tm4[tm].freq = 0;
319             pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm);
320         }
321         break;
322     default:
323     badreg:
324         hw_error("pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset);
325     }
326 }
327
328 static CPUReadMemoryFunc * const pxa2xx_timer_readfn[] = {
329     pxa2xx_timer_read,
330     pxa2xx_timer_read,
331     pxa2xx_timer_read,
332 };
333
334 static CPUWriteMemoryFunc * const pxa2xx_timer_writefn[] = {
335     pxa2xx_timer_write,
336     pxa2xx_timer_write,
337     pxa2xx_timer_write,
338 };
339
340 static void pxa2xx_timer_tick(void *opaque)
341 {
342     PXA2xxTimer0 *t = (PXA2xxTimer0 *) opaque;
343     PXA2xxTimerInfo *i = t->info;
344
345     if (i->irq_enabled & (1 << t->num)) {
346         i->events |= 1 << t->num;
347         qemu_irq_raise(t->irq);
348     }
349
350     if (t->num == 3)
351         if (i->reset3 & 1) {
352             i->reset3 = 0;
353             qemu_system_reset_request();
354         }
355 }
356
357 static void pxa2xx_timer_tick4(void *opaque)
358 {
359     PXA2xxTimer4 *t = (PXA2xxTimer4 *) opaque;
360     PXA2xxTimerInfo *i = (PXA2xxTimerInfo *) t->tm.info;
361
362     pxa2xx_timer_tick(&t->tm);
363     if (t->control & (1 << 3))
364         t->clock = 0;
365     if (t->control & (1 << 6))
366         pxa2xx_timer_update4(i, qemu_get_clock(vm_clock), t->tm.num - 4);
367     if (i->events & 0xff0)
368         qemu_irq_raise(i->irq4);
369 }
370
371 static int pxa25x_timer_post_load(void *opaque, int version_id)
372 {
373     PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
374     int64_t now;
375     int i;
376
377     now = qemu_get_clock(vm_clock);
378     pxa2xx_timer_update(s, now);
379
380     if (pxa2xx_timer_has_tm4(s))
381         for (i = 0; i < 8; i ++)
382             pxa2xx_timer_update4(s, now, i);
383
384     return 0;
385 }
386
387 static int pxa2xx_timer_init(SysBusDevice *dev)
388 {
389     int i;
390     int iomemtype;
391     PXA2xxTimerInfo *s;
392
393     s = FROM_SYSBUS(PXA2xxTimerInfo, dev);
394     s->irq_enabled = 0;
395     s->oldclock = 0;
396     s->clock = 0;
397     s->lastload = qemu_get_clock(vm_clock);
398     s->reset3 = 0;
399
400     for (i = 0; i < 4; i ++) {
401         s->timer[i].value = 0;
402         sysbus_init_irq(dev, &s->timer[i].irq);
403         s->timer[i].info = s;
404         s->timer[i].num = i;
405         s->timer[i].qtimer = qemu_new_timer(vm_clock,
406                         pxa2xx_timer_tick, &s->timer[i]);
407     }
408     if (s->flags & (1 << PXA2XX_TIMER_HAVE_TM4)) {
409         sysbus_init_irq(dev, &s->irq4);
410
411         for (i = 0; i < 8; i ++) {
412             s->tm4[i].tm.value = 0;
413             s->tm4[i].tm.info = s;
414             s->tm4[i].tm.num = i + 4;
415             s->tm4[i].freq = 0;
416             s->tm4[i].control = 0x0;
417             s->tm4[i].tm.qtimer = qemu_new_timer(vm_clock,
418                         pxa2xx_timer_tick4, &s->tm4[i]);
419         }
420     }
421
422     iomemtype = cpu_register_io_memory(pxa2xx_timer_readfn,
423                     pxa2xx_timer_writefn, s, DEVICE_NATIVE_ENDIAN);
424     sysbus_init_mmio(dev, 0x00001000, iomemtype);
425
426     return 0;
427 }
428
429 static const VMStateDescription vmstate_pxa2xx_timer0_regs = {
430     .name = "pxa2xx_timer0",
431     .version_id = 2,
432     .minimum_version_id = 2,
433     .minimum_version_id_old = 2,
434     .fields = (VMStateField[]) {
435         VMSTATE_UINT32(value, PXA2xxTimer0),
436         VMSTATE_END_OF_LIST(),
437     },
438 };
439
440 static const VMStateDescription vmstate_pxa2xx_timer4_regs = {
441     .name = "pxa2xx_timer4",
442     .version_id = 1,
443     .minimum_version_id = 1,
444     .minimum_version_id_old = 1,
445     .fields = (VMStateField[]) {
446         VMSTATE_STRUCT(tm, PXA2xxTimer4, 1,
447                         vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
448         VMSTATE_INT32(oldclock, PXA2xxTimer4),
449         VMSTATE_INT32(clock, PXA2xxTimer4),
450         VMSTATE_UINT64(lastload, PXA2xxTimer4),
451         VMSTATE_UINT32(freq, PXA2xxTimer4),
452         VMSTATE_UINT32(control, PXA2xxTimer4),
453         VMSTATE_END_OF_LIST(),
454     },
455 };
456
457 static bool pxa2xx_timer_has_tm4_test(void *opaque, int version_id)
458 {
459     return pxa2xx_timer_has_tm4(opaque);
460 }
461
462 static const VMStateDescription vmstate_pxa2xx_timer_regs = {
463     .name = "pxa2xx_timer",
464     .version_id = 1,
465     .minimum_version_id = 1,
466     .minimum_version_id_old = 1,
467     .post_load = pxa25x_timer_post_load,
468     .fields = (VMStateField[]) {
469         VMSTATE_INT32(clock, PXA2xxTimerInfo),
470         VMSTATE_INT32(oldclock, PXA2xxTimerInfo),
471         VMSTATE_UINT64(lastload, PXA2xxTimerInfo),
472         VMSTATE_STRUCT_ARRAY(timer, PXA2xxTimerInfo, 4, 1,
473                         vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
474         VMSTATE_UINT32(events, PXA2xxTimerInfo),
475         VMSTATE_UINT32(irq_enabled, PXA2xxTimerInfo),
476         VMSTATE_UINT32(reset3, PXA2xxTimerInfo),
477         VMSTATE_UINT32(snapshot, PXA2xxTimerInfo),
478         VMSTATE_STRUCT_ARRAY_TEST(tm4, PXA2xxTimerInfo, 8,
479                         pxa2xx_timer_has_tm4_test, 0,
480                         vmstate_pxa2xx_timer4_regs, PXA2xxTimer4),
481         VMSTATE_END_OF_LIST(),
482     }
483 };
484
485 static SysBusDeviceInfo pxa25x_timer_dev_info = {
486     .init       = pxa2xx_timer_init,
487     .qdev.name  = "pxa25x-timer",
488     .qdev.desc  = "PXA25x timer",
489     .qdev.size  = sizeof(PXA2xxTimerInfo),
490     .qdev.vmsd  = &vmstate_pxa2xx_timer_regs,
491     .qdev.props = (Property[]) {
492         DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA25X_FREQ),
493         DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
494                         PXA2XX_TIMER_HAVE_TM4, false),
495         DEFINE_PROP_END_OF_LIST(),
496     },
497 };
498
499 static SysBusDeviceInfo pxa27x_timer_dev_info = {
500     .init       = pxa2xx_timer_init,
501     .qdev.name  = "pxa27x-timer",
502     .qdev.desc  = "PXA27x timer",
503     .qdev.size  = sizeof(PXA2xxTimerInfo),
504     .qdev.vmsd  = &vmstate_pxa2xx_timer_regs,
505     .qdev.props = (Property[]) {
506         DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA27X_FREQ),
507         DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
508                         PXA2XX_TIMER_HAVE_TM4, true),
509         DEFINE_PROP_END_OF_LIST(),
510     },
511 };
512
513 static void pxa2xx_timer_register(void)
514 {
515     sysbus_register_withprop(&pxa25x_timer_dev_info);
516     sysbus_register_withprop(&pxa27x_timer_dev_info);
517 };
518 device_init(pxa2xx_timer_register);
This page took 0.053809 seconds and 4 git commands to generate.