2 * ARM PrimeCell Timer modules.
4 * Copyright (c) 2005-2006 CodeSourcery.
5 * Written by Paul Brook
7 * This code is licenced under the GPL.
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)
38 /* Calculate the new expiry time of the given timer. */
40 static void arm_timer_reload(arm_timer_state *s)
44 s->loaded = s->expires;
45 delay = muldiv64(s->count, ticks_per_sec, s->freq);
51 /* Check all active timers, and schedule the next timer interrupt. */
53 static void arm_timer_update(arm_timer_state *s, int64_t now)
57 /* Ignore disabled timers. */
58 if ((s->control & TIMER_CTRL_ENABLE) == 0)
60 /* Ignore expired one-shot timers. */
61 if (s->count == 0 && (s->control & TIMER_CTRL_ONESHOT))
63 if (s->expires - now <= 0) {
64 /* Timer has expired. */
66 if (s->control & TIMER_CTRL_ONESHOT) {
70 if ((s->control & TIMER_CTRL_PERIODIC) == 0) {
72 if (s->control & TIMER_CTRL_32BIT)
73 s->count = 0xffffffff;
82 while (s->expires - now <= 0) {
85 /* Update interrupts. */
86 if (s->int_level && (s->control & TIMER_CTRL_IE)) {
87 qemu_irq_raise(s->irq);
89 qemu_irq_lower(s->irq);
93 if (next - s->expires < 0)
96 /* Schedule the next timer interrupt. */
98 qemu_del_timer(s->timer);
100 } else if (next != s->next_time) {
101 qemu_mod_timer(s->timer, next);
106 /* Return the current value of the timer. */
107 static uint32_t arm_timer_getcount(arm_timer_state *s, int64_t now)
114 if ((s->control & TIMER_CTRL_ENABLE) == 0)
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? */
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) {
131 return ((uint64_t)s->count * (uint64_t)(int32_t)left)
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 */
143 case 1: /* TimerValue */
144 return arm_timer_getcount(s, qemu_get_clock(vm_clock));
145 case 2: /* TimerControl */
147 case 4: /* TimerRIS */
149 case 5: /* TimerMIS */
150 if ((s->control & TIMER_CTRL_IE) == 0)
154 cpu_abort (cpu_single_env, "arm_timer_read: Bad offset %x\n", offset);
159 static void arm_timer_write(void *opaque, target_phys_addr_t offset,
162 arm_timer_state *s = (arm_timer_state *)opaque;
165 now = qemu_get_clock(vm_clock);
166 switch (offset >> 2) {
167 case 0: /* TimerLoad */
173 case 1: /* TimerValue */
174 /* ??? Linux seems to want to write to this readonly register.
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
182 s->count = arm_timer_getcount(s, now);
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. */
197 case 3: /* TimerIntClr */
200 case 6: /* TimerBGLoad */
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)
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)
221 s = (arm_timer_state *)qemu_mallocz(sizeof(arm_timer_state));
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. */
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. */
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. */
260 return arm_timer_read(s->timer[0], offset);
262 return arm_timer_read(s->timer[1], offset - 0x20);
266 static void sp804_write(void *opaque, target_phys_addr_t offset,
269 sp804_state *s = (sp804_state *)opaque;
273 arm_timer_write(s->timer[0], offset, value);
275 arm_timer_write(s->timer[1], offset - 0x20, value);
279 static CPUReadMemoryFunc *sp804_readfn[] = {
285 static CPUWriteMemoryFunc *sp804_writefn[] = {
291 void sp804_init(uint32_t base, qemu_irq irq)
297 s = (sp804_state *)qemu_mallocz(sizeof(sp804_state));
298 qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
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,
307 cpu_register_physical_memory(base, 0x00000fff, iomemtype);
308 /* ??? Save/restore. */
312 /* Integrator/CP timer module. */
319 static uint32_t icp_pit_read(void *opaque, target_phys_addr_t offset)
321 icp_pit_state *s = (icp_pit_state *)opaque;
324 /* ??? Don't know the PrimeCell ID for this device. */
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,
336 icp_pit_state *s = (icp_pit_state *)opaque;
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[] = {
354 static CPUWriteMemoryFunc *icp_pit_writefn[] = {
360 void icp_pit_init(uint32_t base, qemu_irq *pic, int irq)
365 s = (icp_pit_state *)qemu_mallocz(sizeof(icp_pit_state));
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,
375 cpu_register_physical_memory(base, 0x00000fff, iomemtype);
376 /* ??? Save/restore. */