2 * Intel XScale PXA255/270 OS Timers.
4 * Copyright (c) 2006 Openedhand Ltd.
5 * Copyright (c) 2006 Thorsten Zitterell
7 * This code is licenced under the GPL.
11 #include "qemu-timer.h"
28 #define OSCR 0x10 /* OS Timer Count */
37 #define OSSR 0x14 /* Timer status register */
39 #define OIER 0x1c /* Interrupt enable register 3-0 to E3-E0 */
40 #define OMCR4 0xc0 /* OS Match Control registers */
50 #define PXA25X_FREQ 3686400 /* 3.6864 MHz */
51 #define PXA27X_FREQ 3250000 /* 3.25 MHz */
53 static int pxa2xx_timer4_freq
[8] = {
59 /* [5] is the "Externally supplied clock". Assign if necessary. */
86 PXA2xxTimer0 timer
[4];
94 static void pxa2xx_timer_update(void *opaque
, uint64_t now_qemu
)
96 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
102 muldiv64(now_qemu
- s
->lastload
, s
->freq
, get_ticks_per_sec());
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
);
111 static void pxa2xx_timer_update4(void *opaque
, uint64_t now_qemu
, int n
)
113 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
116 static const int counters
[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
119 if (s
->tm4
[n
].control
& (1 << 7))
122 counter
= counters
[n
];
124 if (!s
->tm4
[counter
].freq
) {
125 qemu_del_timer(s
->tm4
[n
].tm
.qtimer
);
129 now_vm
= s
->tm4
[counter
].clock
+ muldiv64(now_qemu
-
130 s
->tm4
[counter
].lastload
,
131 s
->tm4
[counter
].freq
, get_ticks_per_sec());
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
);
138 static uint32_t pxa2xx_timer_read(void *opaque
, target_phys_addr_t offset
)
140 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
148 return s
->timer
[tm
].value
;
159 return s
->tm4
[tm
].tm
.value
;
161 return s
->clock
+ muldiv64(qemu_get_clock(vm_clock
) -
162 s
->lastload
, s
->freq
, get_ticks_per_sec());
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());
181 s
->snapshot
= s
->tm4
[tm
- 1].clock
;
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());
189 return s
->irq_enabled
;
190 case OSSR
: /* Status register */
204 return s
->tm4
[tm
].control
;
209 hw_error("pxa2xx_timer_read: Bad offset " REG_FMT
"\n", offset
);
215 static void pxa2xx_timer_write(void *opaque
, target_phys_addr_t offset
,
219 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
226 s
->timer
[tm
].value
= value
;
227 pxa2xx_timer_update(s
, qemu_get_clock(vm_clock
));
239 s
->tm4
[tm
].tm
.value
= value
;
240 pxa2xx_timer_update4(s
, qemu_get_clock(vm_clock
), tm
);
243 s
->oldclock
= s
->clock
;
244 s
->lastload
= qemu_get_clock(vm_clock
);
246 pxa2xx_timer_update(s
, s
->lastload
);
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
);
264 s
->irq_enabled
= value
& 0xfff;
266 case OSSR
: /* Status register */
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
);
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
);
282 case OWER
: /* XXX: Reset on OSMR3 match? */
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];
297 pxa2xx_timer_update4(s
, qemu_get_clock(vm_clock
), tm
);
306 s
->tm4
[tm
].control
= value
& 0x3ff;
307 /* XXX Stop if running (shouldn't happen) */
308 if ((value
& (1 << 7)) || !(tm
& 1))
310 pxa2xx_timer4_freq
[(value
& (1 << 8)) ? 0 : (value
& 7)];
313 pxa2xx_timer_update4(s
, qemu_get_clock(vm_clock
), tm
);
318 hw_error("pxa2xx_timer_write: Bad offset " REG_FMT
"\n", offset
);
322 static CPUReadMemoryFunc
* const pxa2xx_timer_readfn
[] = {
328 static CPUWriteMemoryFunc
* const pxa2xx_timer_writefn
[] = {
334 static void pxa2xx_timer_tick(void *opaque
)
336 PXA2xxTimer0
*t
= (PXA2xxTimer0
*) opaque
;
337 PXA2xxTimerInfo
*i
= (PXA2xxTimerInfo
*) t
->info
;
339 if (i
->irq_enabled
& (1 << t
->num
)) {
341 i
->events
|= 1 << t
->num
;
342 qemu_irq_raise(t
->irq
);
348 qemu_system_reset_request();
352 static void pxa2xx_timer_tick4(void *opaque
)
354 PXA2xxTimer4
*t
= (PXA2xxTimer4
*) opaque
;
355 PXA2xxTimerInfo
*i
= (PXA2xxTimerInfo
*) t
->tm
.info
;
357 pxa2xx_timer_tick(&t
->tm
);
358 if (t
->control
& (1 << 3))
360 if (t
->control
& (1 << 6))
361 pxa2xx_timer_update4(i
, qemu_get_clock(vm_clock
), t
->tm
.num
- 4);
364 static void pxa2xx_timer_save(QEMUFile
*f
, void *opaque
)
366 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
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
);
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
);
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
);
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
);
394 static int pxa2xx_timer_load(QEMUFile
*f
, void *opaque
, int version_id
)
396 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
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
);
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
);
409 pxa2xx_timer_update(s
, now
);
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
);
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
);
431 static PXA2xxTimerInfo
*pxa2xx_timer_init(target_phys_addr_t base
,
438 s
= (PXA2xxTimerInfo
*) qemu_mallocz(sizeof(PXA2xxTimerInfo
));
442 s
->lastload
= qemu_get_clock(vm_clock
);
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
;
450 s
->timer
[i
].level
= 0;
451 s
->timer
[i
].qtimer
= qemu_new_timer(vm_clock
,
452 pxa2xx_timer_tick
, &s
->timer
[i
]);
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
);
459 register_savevm(NULL
, "pxa2xx_timer", 0, 0,
460 pxa2xx_timer_save
, pxa2xx_timer_load
, s
);
465 void pxa25x_timer_init(target_phys_addr_t base
, DeviceState
*pic
)
467 PXA2xxTimerInfo
*s
= pxa2xx_timer_init(base
, pic
);
468 s
->freq
= PXA25X_FREQ
;
472 void pxa27x_timer_init(target_phys_addr_t base
, DeviceState
*pic
)
474 PXA2xxTimerInfo
*s
= pxa2xx_timer_init(base
, pic
);
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;
486 s
->tm4
[i
].control
= 0x0;
487 s
->tm4
[i
].tm
.qtimer
= qemu_new_timer(vm_clock
,
488 pxa2xx_timer_tick4
, &s
->tm4
[i
]);