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. */
63 typedef struct PXA2xxTimerInfo PXA2xxTimerInfo
;
70 PXA2xxTimerInfo
*info
;
82 struct PXA2xxTimerInfo
{
90 PXA2xxTimer0 timer
[4];
100 #define PXA2XX_TIMER_HAVE_TM4 0
102 static inline int pxa2xx_timer_has_tm4(PXA2xxTimerInfo
*s
)
104 return s
->flags
& (1 << PXA2XX_TIMER_HAVE_TM4
);
107 static void pxa2xx_timer_update(void *opaque
, uint64_t now_qemu
)
109 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
115 muldiv64(now_qemu
- s
->lastload
, s
->freq
, get_ticks_per_sec());
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
);
124 static void pxa2xx_timer_update4(void *opaque
, uint64_t now_qemu
, int n
)
126 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
129 static const int counters
[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
132 if (s
->tm4
[n
].control
& (1 << 7))
135 counter
= counters
[n
];
137 if (!s
->tm4
[counter
].freq
) {
138 qemu_del_timer(s
->tm4
[n
].tm
.qtimer
);
142 now_vm
= s
->tm4
[counter
].clock
+ muldiv64(now_qemu
-
143 s
->tm4
[counter
].lastload
,
144 s
->tm4
[counter
].freq
, get_ticks_per_sec());
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
);
151 static uint32_t pxa2xx_timer_read(void *opaque
, target_phys_addr_t offset
)
153 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
161 return s
->timer
[tm
].value
;
170 if (!pxa2xx_timer_has_tm4(s
))
172 return s
->tm4
[tm
].tm
.value
;
174 return s
->clock
+ muldiv64(qemu_get_clock_ns(vm_clock
) -
175 s
->lastload
, s
->freq
, get_ticks_per_sec());
184 if (!pxa2xx_timer_has_tm4(s
))
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_ns(vm_clock
) -
191 s
->tm4
[tm
- 1].lastload
,
192 s
->tm4
[tm
- 1].freq
, get_ticks_per_sec());
194 s
->snapshot
= s
->tm4
[tm
- 1].clock
;
197 if (!s
->tm4
[tm
].freq
)
198 return s
->tm4
[tm
].clock
;
199 return s
->tm4
[tm
].clock
+ muldiv64(qemu_get_clock_ns(vm_clock
) -
200 s
->tm4
[tm
].lastload
, s
->tm4
[tm
].freq
, get_ticks_per_sec());
202 return s
->irq_enabled
;
203 case OSSR
: /* Status register */
215 if (!pxa2xx_timer_has_tm4(s
))
217 return s
->tm4
[tm
].control
;
222 hw_error("pxa2xx_timer_read: Bad offset " REG_FMT
"\n", offset
);
228 static void pxa2xx_timer_write(void *opaque
, target_phys_addr_t offset
,
232 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
239 s
->timer
[tm
].value
= value
;
240 pxa2xx_timer_update(s
, qemu_get_clock_ns(vm_clock
));
250 if (!pxa2xx_timer_has_tm4(s
))
252 s
->tm4
[tm
].tm
.value
= value
;
253 pxa2xx_timer_update4(s
, qemu_get_clock_ns(vm_clock
), tm
);
256 s
->oldclock
= s
->clock
;
257 s
->lastload
= qemu_get_clock_ns(vm_clock
);
259 pxa2xx_timer_update(s
, s
->lastload
);
269 if (!pxa2xx_timer_has_tm4(s
))
271 s
->tm4
[tm
].oldclock
= s
->tm4
[tm
].clock
;
272 s
->tm4
[tm
].lastload
= qemu_get_clock_ns(vm_clock
);
273 s
->tm4
[tm
].clock
= value
;
274 pxa2xx_timer_update4(s
, s
->tm4
[tm
].lastload
, tm
);
277 s
->irq_enabled
= value
& 0xfff;
279 case OSSR
: /* Status register */
282 for (i
= 0; i
< 4; i
++, 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
);
288 case OWER
: /* XXX: Reset on OSMR3 match? */
295 if (!pxa2xx_timer_has_tm4(s
))
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];
303 pxa2xx_timer_update4(s
, qemu_get_clock_ns(vm_clock
), tm
);
310 if (!pxa2xx_timer_has_tm4(s
))
312 s
->tm4
[tm
].control
= value
& 0x3ff;
313 /* XXX Stop if running (shouldn't happen) */
314 if ((value
& (1 << 7)) || !(tm
& 1))
316 pxa2xx_timer4_freq
[(value
& (1 << 8)) ? 0 : (value
& 7)];
319 pxa2xx_timer_update4(s
, qemu_get_clock_ns(vm_clock
), tm
);
324 hw_error("pxa2xx_timer_write: Bad offset " REG_FMT
"\n", offset
);
328 static CPUReadMemoryFunc
* const pxa2xx_timer_readfn
[] = {
334 static CPUWriteMemoryFunc
* const pxa2xx_timer_writefn
[] = {
340 static void pxa2xx_timer_tick(void *opaque
)
342 PXA2xxTimer0
*t
= (PXA2xxTimer0
*) opaque
;
343 PXA2xxTimerInfo
*i
= t
->info
;
345 if (i
->irq_enabled
& (1 << t
->num
)) {
346 i
->events
|= 1 << t
->num
;
347 qemu_irq_raise(t
->irq
);
353 qemu_system_reset_request();
357 static void pxa2xx_timer_tick4(void *opaque
)
359 PXA2xxTimer4
*t
= (PXA2xxTimer4
*) opaque
;
360 PXA2xxTimerInfo
*i
= (PXA2xxTimerInfo
*) t
->tm
.info
;
362 pxa2xx_timer_tick(&t
->tm
);
363 if (t
->control
& (1 << 3))
365 if (t
->control
& (1 << 6))
366 pxa2xx_timer_update4(i
, qemu_get_clock_ns(vm_clock
), t
->tm
.num
- 4);
367 if (i
->events
& 0xff0)
368 qemu_irq_raise(i
->irq4
);
371 static int pxa25x_timer_post_load(void *opaque
, int version_id
)
373 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
377 now
= qemu_get_clock_ns(vm_clock
);
378 pxa2xx_timer_update(s
, now
);
380 if (pxa2xx_timer_has_tm4(s
))
381 for (i
= 0; i
< 8; i
++)
382 pxa2xx_timer_update4(s
, now
, i
);
387 static int pxa2xx_timer_init(SysBusDevice
*dev
)
393 s
= FROM_SYSBUS(PXA2xxTimerInfo
, dev
);
397 s
->lastload
= qemu_get_clock_ns(vm_clock
);
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
;
405 s
->timer
[i
].qtimer
= qemu_new_timer_ns(vm_clock
,
406 pxa2xx_timer_tick
, &s
->timer
[i
]);
408 if (s
->flags
& (1 << PXA2XX_TIMER_HAVE_TM4
)) {
409 sysbus_init_irq(dev
, &s
->irq4
);
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;
416 s
->tm4
[i
].control
= 0x0;
417 s
->tm4
[i
].tm
.qtimer
= qemu_new_timer_ns(vm_clock
,
418 pxa2xx_timer_tick4
, &s
->tm4
[i
]);
422 iomemtype
= cpu_register_io_memory(pxa2xx_timer_readfn
,
423 pxa2xx_timer_writefn
, s
, DEVICE_NATIVE_ENDIAN
);
424 sysbus_init_mmio(dev
, 0x00001000, iomemtype
);
429 static const VMStateDescription vmstate_pxa2xx_timer0_regs
= {
430 .name
= "pxa2xx_timer0",
432 .minimum_version_id
= 2,
433 .minimum_version_id_old
= 2,
434 .fields
= (VMStateField
[]) {
435 VMSTATE_UINT32(value
, PXA2xxTimer0
),
436 VMSTATE_END_OF_LIST(),
440 static const VMStateDescription vmstate_pxa2xx_timer4_regs
= {
441 .name
= "pxa2xx_timer4",
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(),
457 static bool pxa2xx_timer_has_tm4_test(void *opaque
, int version_id
)
459 return pxa2xx_timer_has_tm4(opaque
);
462 static const VMStateDescription vmstate_pxa2xx_timer_regs
= {
463 .name
= "pxa2xx_timer",
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(),
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(),
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(),
513 static void pxa2xx_timer_register(void)
515 sysbus_register_withprop(&pxa25x_timer_dev_info
);
516 sysbus_register_withprop(&pxa27x_timer_dev_info
);
518 device_init(pxa2xx_timer_register
);