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
;
71 PXA2xxTimerInfo
*info
;
83 struct PXA2xxTimerInfo
{
91 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(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(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(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(vm_clock
));
250 if (!pxa2xx_timer_has_tm4(s
))
252 s
->tm4
[tm
].tm
.value
= value
;
253 pxa2xx_timer_update4(s
, qemu_get_clock(vm_clock
), tm
);
256 s
->oldclock
= s
->clock
;
257 s
->lastload
= qemu_get_clock(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(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 */
281 for (i
= 0; i
< 4; i
++, value
>>= 1) {
282 if (s
->timer
[i
].level
&& (value
& 1)) {
283 s
->timer
[i
].level
= 0;
284 qemu_irq_lower(s
->timer
[i
].irq
);
287 if (pxa2xx_timer_has_tm4(s
)) {
288 for (i
= 0; i
< 8; i
++, value
>>= 1)
289 if (s
->tm4
[i
].tm
.level
&& (value
& 1))
290 s
->tm4
[i
].tm
.level
= 0;
291 if (!(s
->events
& 0xff0))
292 qemu_irq_lower(s
->tm4
->tm
.irq
);
295 case OWER
: /* XXX: Reset on OSMR3 match? */
302 if (!pxa2xx_timer_has_tm4(s
))
304 s
->tm4
[tm
].control
= value
& 0x0ff;
305 /* XXX Stop if running (shouldn't happen) */
306 if ((value
& (1 << 7)) || tm
== 0)
307 s
->tm4
[tm
].freq
= pxa2xx_timer4_freq
[value
& 7];
310 pxa2xx_timer_update4(s
, qemu_get_clock(vm_clock
), tm
);
317 if (!pxa2xx_timer_has_tm4(s
))
319 s
->tm4
[tm
].control
= value
& 0x3ff;
320 /* XXX Stop if running (shouldn't happen) */
321 if ((value
& (1 << 7)) || !(tm
& 1))
323 pxa2xx_timer4_freq
[(value
& (1 << 8)) ? 0 : (value
& 7)];
326 pxa2xx_timer_update4(s
, qemu_get_clock(vm_clock
), tm
);
331 hw_error("pxa2xx_timer_write: Bad offset " REG_FMT
"\n", offset
);
335 static CPUReadMemoryFunc
* const pxa2xx_timer_readfn
[] = {
341 static CPUWriteMemoryFunc
* const pxa2xx_timer_writefn
[] = {
347 static void pxa2xx_timer_tick(void *opaque
)
349 PXA2xxTimer0
*t
= (PXA2xxTimer0
*) opaque
;
350 PXA2xxTimerInfo
*i
= t
->info
;
352 if (i
->irq_enabled
& (1 << t
->num
)) {
354 i
->events
|= 1 << t
->num
;
355 qemu_irq_raise(t
->irq
);
361 qemu_system_reset_request();
365 static void pxa2xx_timer_tick4(void *opaque
)
367 PXA2xxTimer4
*t
= (PXA2xxTimer4
*) opaque
;
368 PXA2xxTimerInfo
*i
= (PXA2xxTimerInfo
*) t
->tm
.info
;
370 pxa2xx_timer_tick(&t
->tm
);
371 if (t
->control
& (1 << 3))
373 if (t
->control
& (1 << 6))
374 pxa2xx_timer_update4(i
, qemu_get_clock(vm_clock
), t
->tm
.num
- 4);
377 static int pxa25x_timer_post_load(void *opaque
, int version_id
)
379 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
383 now
= qemu_get_clock(vm_clock
);
384 pxa2xx_timer_update(s
, now
);
386 if (pxa2xx_timer_has_tm4(s
))
387 for (i
= 0; i
< 8; i
++)
388 pxa2xx_timer_update4(s
, now
, i
);
393 static int pxa2xx_timer_init(SysBusDevice
*dev
)
400 s
= FROM_SYSBUS(PXA2xxTimerInfo
, dev
);
404 s
->lastload
= qemu_get_clock(vm_clock
);
407 for (i
= 0; i
< 4; i
++) {
408 s
->timer
[i
].value
= 0;
409 sysbus_init_irq(dev
, &s
->timer
[i
].irq
);
410 s
->timer
[i
].info
= s
;
412 s
->timer
[i
].level
= 0;
413 s
->timer
[i
].qtimer
= qemu_new_timer(vm_clock
,
414 pxa2xx_timer_tick
, &s
->timer
[i
]);
416 if (s
->flags
& (1 << PXA2XX_TIMER_HAVE_TM4
)) {
417 sysbus_init_irq(dev
, &irq4
);
419 for (i
= 0; i
< 8; i
++) {
420 s
->tm4
[i
].tm
.value
= 0;
421 s
->tm4
[i
].tm
.info
= s
;
422 s
->tm4
[i
].tm
.num
= i
+ 4;
423 s
->tm4
[i
].tm
.level
= 0;
425 s
->tm4
[i
].control
= 0x0;
426 s
->tm4
[i
].tm
.qtimer
= qemu_new_timer(vm_clock
,
427 pxa2xx_timer_tick4
, &s
->tm4
[i
]);
428 s
->tm4
[i
].tm
.irq
= irq4
;
432 iomemtype
= cpu_register_io_memory(pxa2xx_timer_readfn
,
433 pxa2xx_timer_writefn
, s
, DEVICE_NATIVE_ENDIAN
);
434 sysbus_init_mmio(dev
, 0x00001000, iomemtype
);
439 static const VMStateDescription vmstate_pxa2xx_timer0_regs
= {
440 .name
= "pxa2xx_timer0",
442 .minimum_version_id
= 1,
443 .minimum_version_id_old
= 1,
444 .fields
= (VMStateField
[]) {
445 VMSTATE_UINT32(value
, PXA2xxTimer0
),
446 VMSTATE_INT32(level
, PXA2xxTimer0
),
447 VMSTATE_END_OF_LIST(),
451 static const VMStateDescription vmstate_pxa2xx_timer4_regs
= {
452 .name
= "pxa2xx_timer4",
454 .minimum_version_id
= 1,
455 .minimum_version_id_old
= 1,
456 .fields
= (VMStateField
[]) {
457 VMSTATE_STRUCT(tm
, PXA2xxTimer4
, 1,
458 vmstate_pxa2xx_timer0_regs
, PXA2xxTimer0
),
459 VMSTATE_INT32(oldclock
, PXA2xxTimer4
),
460 VMSTATE_INT32(clock
, PXA2xxTimer4
),
461 VMSTATE_UINT64(lastload
, PXA2xxTimer4
),
462 VMSTATE_UINT32(freq
, PXA2xxTimer4
),
463 VMSTATE_UINT32(control
, PXA2xxTimer4
),
464 VMSTATE_END_OF_LIST(),
468 static bool pxa2xx_timer_has_tm4_test(void *opaque
, int version_id
)
470 return pxa2xx_timer_has_tm4(opaque
);
473 static const VMStateDescription vmstate_pxa2xx_timer_regs
= {
474 .name
= "pxa2xx_timer",
476 .minimum_version_id
= 1,
477 .minimum_version_id_old
= 1,
478 .post_load
= pxa25x_timer_post_load
,
479 .fields
= (VMStateField
[]) {
480 VMSTATE_INT32(clock
, PXA2xxTimerInfo
),
481 VMSTATE_INT32(oldclock
, PXA2xxTimerInfo
),
482 VMSTATE_UINT64(lastload
, PXA2xxTimerInfo
),
483 VMSTATE_STRUCT_ARRAY(timer
, PXA2xxTimerInfo
, 4, 1,
484 vmstate_pxa2xx_timer0_regs
, PXA2xxTimer0
),
485 VMSTATE_UINT32(events
, PXA2xxTimerInfo
),
486 VMSTATE_UINT32(irq_enabled
, PXA2xxTimerInfo
),
487 VMSTATE_UINT32(reset3
, PXA2xxTimerInfo
),
488 VMSTATE_UINT32(snapshot
, PXA2xxTimerInfo
),
489 VMSTATE_STRUCT_ARRAY_TEST(tm4
, PXA2xxTimerInfo
, 8,
490 pxa2xx_timer_has_tm4_test
, 0,
491 vmstate_pxa2xx_timer4_regs
, PXA2xxTimer4
),
492 VMSTATE_END_OF_LIST(),
496 static SysBusDeviceInfo pxa25x_timer_dev_info
= {
497 .init
= pxa2xx_timer_init
,
498 .qdev
.name
= "pxa25x-timer",
499 .qdev
.desc
= "PXA25x timer",
500 .qdev
.size
= sizeof(PXA2xxTimerInfo
),
501 .qdev
.vmsd
= &vmstate_pxa2xx_timer_regs
,
502 .qdev
.props
= (Property
[]) {
503 DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo
, freq
, PXA25X_FREQ
),
504 DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo
, flags
,
505 PXA2XX_TIMER_HAVE_TM4
, false),
506 DEFINE_PROP_END_OF_LIST(),
510 static SysBusDeviceInfo pxa27x_timer_dev_info
= {
511 .init
= pxa2xx_timer_init
,
512 .qdev
.name
= "pxa27x-timer",
513 .qdev
.desc
= "PXA27x timer",
514 .qdev
.size
= sizeof(PXA2xxTimerInfo
),
515 .qdev
.vmsd
= &vmstate_pxa2xx_timer_regs
,
516 .qdev
.props
= (Property
[]) {
517 DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo
, freq
, PXA27X_FREQ
),
518 DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo
, flags
,
519 PXA2XX_TIMER_HAVE_TM4
, true),
520 DEFINE_PROP_END_OF_LIST(),
524 static void pxa2xx_timer_register(void)
526 sysbus_register_withprop(&pxa25x_timer_dev_info
);
527 sysbus_register_withprop(&pxa27x_timer_dev_info
);
529 device_init(pxa2xx_timer_register
);