Constification
[qemu/qemu_0_9_1_stable.git] / hw / arm_timer.c
blob3c6c0d23946c8b71bf6fc76f669a03cb378e1012
1 /*
2 * ARM PrimeCell Timer modules.
4 * Copyright (c) 2005-2006 CodeSourcery.
5 * Written by Paul Brook
7 * This code is licenced under the GPL.
8 */
10 #include "vl.h"
11 #include "arm_pic.h"
13 /* Common timer implementation. */
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)
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;
38 /* Calculate the new expiry time of the given timer. */
40 static void arm_timer_reload(arm_timer_state *s)
42 int64_t delay;
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;
51 /* Check all active timers, and schedule the next timer interrupt. */
53 static void arm_timer_update(arm_timer_state *s, int64_t now)
55 int64_t next;
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;
82 while (s->expires - now <= 0) {
83 arm_timer_reload(s);
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);
92 next = now;
93 if (next - s->expires < 0)
94 next = s->expires;
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;
106 /* Return the current value of the timer. */
107 static uint32_t arm_timer_getcount(arm_timer_state *s, int64_t now)
109 int64_t left;
110 int64_t period;
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;
131 return ((uint64_t)s->count * (uint64_t)(int32_t)left)
132 / (int32_t)period;
135 uint32_t arm_timer_read(void *opaque, target_phys_addr_t offset)
137 arm_timer_state *s = (arm_timer_state *)opaque;
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;
159 static void arm_timer_write(void *opaque, target_phys_addr_t offset,
160 uint32_t value)
162 arm_timer_state *s = (arm_timer_state *)opaque;
163 int64_t now;
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);
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;
191 if (s->control & TIMER_CTRL_ENABLE) {
192 /* Restart the timer if still enabled. */
193 s->expires = now;
194 arm_timer_reload(s);
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);
206 arm_timer_update(s, now);
209 static void arm_timer_tick(void *opaque)
211 int64_t now;
213 now = qemu_get_clock(vm_clock);
214 arm_timer_update((arm_timer_state *)opaque, now);
217 static void *arm_timer_init(uint32_t freq, qemu_irq irq)
219 arm_timer_state *s;
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;
227 s->timer = qemu_new_timer(vm_clock, arm_timer_tick, s);
228 /* ??? Save/restore. */
229 return s;
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. */
237 typedef struct {
238 void *timer[2];
239 int level[2];
240 uint32_t base;
241 qemu_irq irq;
242 } sp804_state;
244 /* Merge the IRQs from the two component devices. */
245 static void sp804_set_irq(void *opaque, int irq, int level)
247 sp804_state *s = (sp804_state *)opaque;
249 s->level[irq] = level;
250 qemu_set_irq(s->irq, s->level[0] || s->level[1]);
253 static uint32_t sp804_read(void *opaque, target_phys_addr_t offset)
255 sp804_state *s = (sp804_state *)opaque;
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);
266 static void sp804_write(void *opaque, target_phys_addr_t offset,
267 uint32_t value)
269 sp804_state *s = (sp804_state *)opaque;
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);
279 static CPUReadMemoryFunc *sp804_readfn[] = {
280 sp804_read,
281 sp804_read,
282 sp804_read
285 static CPUWriteMemoryFunc *sp804_writefn[] = {
286 sp804_write,
287 sp804_write,
288 sp804_write
291 void sp804_init(uint32_t base, qemu_irq irq)
293 int iomemtype;
294 sp804_state *s;
295 qemu_irq *qi;
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. */
312 /* Integrator/CP timer module. */
314 typedef struct {
315 void *timer[3];
316 uint32_t base;
317 } icp_pit_state;
319 static uint32_t icp_pit_read(void *opaque, target_phys_addr_t offset)
321 icp_pit_state *s = (icp_pit_state *)opaque;
322 int n;
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);
330 return arm_timer_read(s->timer[n], offset & 0xff);
333 static void icp_pit_write(void *opaque, target_phys_addr_t offset,
334 uint32_t value)
336 icp_pit_state *s = (icp_pit_state *)opaque;
337 int n;
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);
344 arm_timer_write(s->timer[n], offset & 0xff, value);
348 static CPUReadMemoryFunc *icp_pit_readfn[] = {
349 icp_pit_read,
350 icp_pit_read,
351 icp_pit_read
354 static CPUWriteMemoryFunc *icp_pit_writefn[] = {
355 icp_pit_write,
356 icp_pit_write,
357 icp_pit_write
360 void icp_pit_init(uint32_t base, qemu_irq *pic, int irq)
362 int iomemtype;
363 icp_pit_state *s;
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]);
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. */