Embedded PowerPC Device Control Registers infrastructure.
[qemu] / hw / arm_timer.c
1 /* 
2  * ARM PrimeCell Timer modules.
3  *
4  * Copyright (c) 2005-2006 CodeSourcery.
5  * Written by Paul Brook
6  *
7  * This code is licenced under the GPL.
8  */
9
10 #include "vl.h"
11 #include "arm_pic.h"
12
13 /* Common timer implementation.  */
14
15 #define TIMER_CTRL_ONESHOT      (1 << 0)
16 #define TIMER_CTRL_32BIT        (1 << 1)
17 #define TIMER_CTRL_DIV1         (0 << 2)
18 #define TIMER_CTRL_DIV16        (1 << 2)
19 #define TIMER_CTRL_DIV256       (2 << 2)
20 #define TIMER_CTRL_IE           (1 << 5)
21 #define TIMER_CTRL_PERIODIC     (1 << 6)
22 #define TIMER_CTRL_ENABLE       (1 << 7)
23
24 typedef struct {
25     int64_t next_time;
26     int64_t expires;
27     int64_t loaded;
28     QEMUTimer *timer;
29     uint32_t control;
30     uint32_t count;
31     uint32_t limit;
32     int raw_freq;
33     int freq;
34     int int_level;
35     qemu_irq irq;
36 } arm_timer_state;
37
38 /* Calculate the new expiry time of the given timer.  */
39
40 static void arm_timer_reload(arm_timer_state *s)
41 {
42     int64_t delay;
43
44     s->loaded = s->expires;
45     delay = muldiv64(s->count, ticks_per_sec, s->freq);
46     if (delay == 0)
47         delay = 1;
48     s->expires += delay;
49 }
50
51 /* Check all active timers, and schedule the next timer interrupt.  */
52
53 static void arm_timer_update(arm_timer_state *s, int64_t now)
54 {
55     int64_t next;
56
57     /* Ignore disabled timers.  */
58     if ((s->control & TIMER_CTRL_ENABLE) == 0)
59         return;
60     /* Ignore expired one-shot timers.  */
61     if (s->count == 0 && (s->control & TIMER_CTRL_ONESHOT))
62         return;
63     if (s->expires - now <= 0) {
64         /* Timer has expired.  */
65         s->int_level = 1;
66         if (s->control & TIMER_CTRL_ONESHOT) {
67             /* One-shot.  */
68             s->count = 0;
69         } else {
70             if ((s->control & TIMER_CTRL_PERIODIC) == 0) {
71                 /* Free running.  */
72                 if (s->control & TIMER_CTRL_32BIT)
73                     s->count = 0xffffffff;
74                 else
75                     s->count = 0xffff;
76             } else {
77                   /* Periodic.  */
78                   s->count = s->limit;
79             }
80         }
81     }
82     while (s->expires - now <= 0) {
83         arm_timer_reload(s);
84     }
85     /* Update interrupts.  */
86     if (s->int_level && (s->control & TIMER_CTRL_IE)) {
87         qemu_irq_raise(s->irq);
88     } else {
89         qemu_irq_lower(s->irq);
90     }
91
92     next = now;
93     if (next - s->expires < 0)
94         next = s->expires;
95
96     /* Schedule the next timer interrupt.  */
97     if (next == now) {
98         qemu_del_timer(s->timer);
99         s->next_time = 0;
100     } else if (next != s->next_time) {
101         qemu_mod_timer(s->timer, next);
102         s->next_time = next;
103     }
104 }
105
106 /* Return the current value of the timer.  */
107 static uint32_t arm_timer_getcount(arm_timer_state *s, int64_t now)
108 {
109     int64_t left;
110     int64_t period;
111
112     if (s->count == 0)
113         return 0;
114     if ((s->control & TIMER_CTRL_ENABLE) == 0)
115         return s->count;
116     left = s->expires - now;
117     period = s->expires - s->loaded;
118     /* If the timer should have expired then return 0.  This can happen
119        when the host timer signal doesnt occur immediately.  It's better to
120        have a timer appear to sit at zero for a while than have it wrap
121        around before the guest interrupt is raised.  */
122     /* ??? Could we trigger the interrupt here?  */
123     if (left < 0)
124         return 0;
125     /* We need to calculate count * elapsed / period without overfowing.
126        Scale both elapsed and period so they fit in a 32-bit int.  */
127     while (period != (int32_t)period) {
128         period >>= 1;
129         left >>= 1;
130     }
131     return ((uint64_t)s->count * (uint64_t)(int32_t)left)
132             / (int32_t)period;
133 }
134
135 uint32_t arm_timer_read(void *opaque, target_phys_addr_t offset)
136 {
137     arm_timer_state *s = (arm_timer_state *)opaque;
138
139     switch (offset >> 2) {
140     case 0: /* TimerLoad */
141     case 6: /* TimerBGLoad */
142         return s->limit;
143     case 1: /* TimerValue */
144         return arm_timer_getcount(s, qemu_get_clock(vm_clock));
145     case 2: /* TimerControl */
146         return s->control;
147     case 4: /* TimerRIS */
148         return s->int_level;
149     case 5: /* TimerMIS */
150         if ((s->control & TIMER_CTRL_IE) == 0)
151             return 0;
152         return s->int_level;
153     default:
154         cpu_abort (cpu_single_env, "arm_timer_read: Bad offset %x\n", offset);
155         return 0;
156     }
157 }
158
159 static void arm_timer_write(void *opaque, target_phys_addr_t offset,
160                             uint32_t value)
161 {
162     arm_timer_state *s = (arm_timer_state *)opaque;
163     int64_t now;
164
165     now = qemu_get_clock(vm_clock);
166     switch (offset >> 2) {
167     case 0: /* TimerLoad */
168         s->limit = value;
169         s->count = value;
170         s->expires = now;
171         arm_timer_reload(s);
172         break;
173     case 1: /* TimerValue */
174         /* ??? Linux seems to want to write to this readonly register.
175            Ignore it.  */
176         break;
177     case 2: /* TimerControl */
178         if (s->control & TIMER_CTRL_ENABLE) {
179             /* Pause the timer if it is running.  This may cause some
180                inaccuracy dure to rounding, but avoids a whole lot of other
181                messyness.  */
182             s->count = arm_timer_getcount(s, now);
183         }
184         s->control = value;
185         s->freq = s->raw_freq;
186         /* ??? Need to recalculate expiry time after changing divisor.  */
187         switch ((value >> 2) & 3) {
188         case 1: s->freq >>= 4; break;
189         case 2: s->freq >>= 8; break;
190         }
191         if (s->control & TIMER_CTRL_ENABLE) {
192             /* Restart the timer if still enabled.  */
193             s->expires = now;
194             arm_timer_reload(s);
195         }
196         break;
197     case 3: /* TimerIntClr */
198         s->int_level = 0;
199         break;
200     case 6: /* TimerBGLoad */
201         s->limit = value;
202         break;
203     default:
204         cpu_abort (cpu_single_env, "arm_timer_write: Bad offset %x\n", offset);
205     }
206     arm_timer_update(s, now);
207 }
208
209 static void arm_timer_tick(void *opaque)
210 {
211     int64_t now;
212
213     now = qemu_get_clock(vm_clock);
214     arm_timer_update((arm_timer_state *)opaque, now);
215 }
216
217 static void *arm_timer_init(uint32_t freq, qemu_irq irq)
218 {
219     arm_timer_state *s;
220
221     s = (arm_timer_state *)qemu_mallocz(sizeof(arm_timer_state));
222     s->irq = irq;
223     s->raw_freq = s->freq = 1000000;
224     s->control = TIMER_CTRL_IE;
225     s->count = 0xffffffff;
226
227     s->timer = qemu_new_timer(vm_clock, arm_timer_tick, s);
228     /* ??? Save/restore.  */
229     return s;
230 }
231
232 /* ARM PrimeCell SP804 dual timer module.
233    Docs for this device don't seem to be publicly available.  This
234    implementation is based on guesswork, the linux kernel sources and the
235    Integrator/CP timer modules.  */
236
237 typedef struct {
238     void *timer[2];
239     int level[2];
240     uint32_t base;
241     qemu_irq irq;
242 } sp804_state;
243
244 /* Merge the IRQs from the two component devices.  */
245 static void sp804_set_irq(void *opaque, int irq, int level)
246 {
247     sp804_state *s = (sp804_state *)opaque;
248
249     s->level[irq] = level;
250     qemu_set_irq(s->irq, s->level[0] || s->level[1]);
251 }
252
253 static uint32_t sp804_read(void *opaque, target_phys_addr_t offset)
254 {
255     sp804_state *s = (sp804_state *)opaque;
256
257     /* ??? Don't know the PrimeCell ID for this device.  */
258     offset -= s->base;
259     if (offset < 0x20) {
260         return arm_timer_read(s->timer[0], offset);
261     } else {
262         return arm_timer_read(s->timer[1], offset - 0x20);
263     }
264 }
265
266 static void sp804_write(void *opaque, target_phys_addr_t offset,
267                         uint32_t value)
268 {
269     sp804_state *s = (sp804_state *)opaque;
270
271     offset -= s->base;
272     if (offset < 0x20) {
273         arm_timer_write(s->timer[0], offset, value);
274     } else {
275         arm_timer_write(s->timer[1], offset - 0x20, value);
276     }
277 }
278
279 static CPUReadMemoryFunc *sp804_readfn[] = {
280    sp804_read,
281    sp804_read,
282    sp804_read
283 };
284
285 static CPUWriteMemoryFunc *sp804_writefn[] = {
286    sp804_write,
287    sp804_write,
288    sp804_write
289 };
290
291 void sp804_init(uint32_t base, qemu_irq irq)
292 {
293     int iomemtype;
294     sp804_state *s;
295     qemu_irq *qi;
296
297     s = (sp804_state *)qemu_mallocz(sizeof(sp804_state));
298     qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
299     s->base = base;
300     s->irq = irq;
301     /* ??? The timers are actually configurable between 32kHz and 1MHz, but
302        we don't implement that.  */
303     s->timer[0] = arm_timer_init(1000000, qi[0]);
304     s->timer[1] = arm_timer_init(1000000, qi[1]);
305     iomemtype = cpu_register_io_memory(0, sp804_readfn,
306                                        sp804_writefn, s);
307     cpu_register_physical_memory(base, 0x00000fff, iomemtype);
308     /* ??? Save/restore.  */
309 }
310
311
312 /* Integrator/CP timer module.  */
313
314 typedef struct {
315     void *timer[3];
316     uint32_t base;
317 } icp_pit_state;
318
319 static uint32_t icp_pit_read(void *opaque, target_phys_addr_t offset)
320 {
321     icp_pit_state *s = (icp_pit_state *)opaque;
322     int n;
323
324     /* ??? Don't know the PrimeCell ID for this device.  */
325     offset -= s->base;
326     n = offset >> 8;
327     if (n > 3)
328         cpu_abort(cpu_single_env, "sp804_read: Bad timer %d\n", n);
329
330     return arm_timer_read(s->timer[n], offset & 0xff);
331 }
332
333 static void icp_pit_write(void *opaque, target_phys_addr_t offset,
334                           uint32_t value)
335 {
336     icp_pit_state *s = (icp_pit_state *)opaque;
337     int n;
338
339     offset -= s->base;
340     n = offset >> 8;
341     if (n > 3)
342         cpu_abort(cpu_single_env, "sp804_write: Bad timer %d\n", n);
343
344     arm_timer_write(s->timer[n], offset & 0xff, value);
345 }
346
347
348 static CPUReadMemoryFunc *icp_pit_readfn[] = {
349    icp_pit_read,
350    icp_pit_read,
351    icp_pit_read
352 };
353
354 static CPUWriteMemoryFunc *icp_pit_writefn[] = {
355    icp_pit_write,
356    icp_pit_write,
357    icp_pit_write
358 };
359
360 void icp_pit_init(uint32_t base, qemu_irq *pic, int irq)
361 {
362     int iomemtype;
363     icp_pit_state *s;
364
365     s = (icp_pit_state *)qemu_mallocz(sizeof(icp_pit_state));
366     s->base = base;
367     /* Timer 0 runs at the system clock speed (40MHz).  */
368     s->timer[0] = arm_timer_init(40000000, pic[irq]);
369     /* The other two timers run at 1MHz.  */
370     s->timer[1] = arm_timer_init(1000000, pic[irq + 1]);
371     s->timer[2] = arm_timer_init(1000000, pic[irq + 2]);
372
373     iomemtype = cpu_register_io_memory(0, icp_pit_readfn,
374                                        icp_pit_writefn, s);
375     cpu_register_physical_memory(base, 0x00000fff, iomemtype);
376     /* ??? Save/restore.  */
377 }
378