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];
101 #define PXA2XX_TIMER_HAVE_TM4 0
103 static inline int pxa2xx_timer_has_tm4(PXA2xxTimerInfo
*s
)
105 return s
->flags
& (1 << PXA2XX_TIMER_HAVE_TM4
);
108 static void pxa2xx_timer_update(void *opaque
, uint64_t now_qemu
)
110 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
116 muldiv64(now_qemu
- s
->lastload
, s
->freq
, get_ticks_per_sec());
118 for (i
= 0; i
< 4; i
++) {
119 new_qemu
= now_qemu
+ muldiv64((uint32_t) (s
->timer
[i
].value
- now_vm
),
120 get_ticks_per_sec(), s
->freq
);
121 qemu_mod_timer(s
->timer
[i
].qtimer
, new_qemu
);
125 static void pxa2xx_timer_update4(void *opaque
, uint64_t now_qemu
, int n
)
127 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
130 static const int counters
[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
133 if (s
->tm4
[n
].control
& (1 << 7))
136 counter
= counters
[n
];
138 if (!s
->tm4
[counter
].freq
) {
139 qemu_del_timer(s
->tm4
[n
].tm
.qtimer
);
143 now_vm
= s
->tm4
[counter
].clock
+ muldiv64(now_qemu
-
144 s
->tm4
[counter
].lastload
,
145 s
->tm4
[counter
].freq
, get_ticks_per_sec());
147 new_qemu
= now_qemu
+ muldiv64((uint32_t) (s
->tm4
[n
].tm
.value
- now_vm
),
148 get_ticks_per_sec(), s
->tm4
[counter
].freq
);
149 qemu_mod_timer(s
->tm4
[n
].tm
.qtimer
, new_qemu
);
152 static uint32_t pxa2xx_timer_read(void *opaque
, target_phys_addr_t offset
)
154 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
162 return s
->timer
[tm
].value
;
171 if (!pxa2xx_timer_has_tm4(s
))
173 return s
->tm4
[tm
].tm
.value
;
175 return s
->clock
+ muldiv64(qemu_get_clock(vm_clock
) -
176 s
->lastload
, s
->freq
, get_ticks_per_sec());
185 if (!pxa2xx_timer_has_tm4(s
))
188 if ((tm
== 9 - 4 || tm
== 11 - 4) && (s
->tm4
[tm
].control
& (1 << 9))) {
189 if (s
->tm4
[tm
- 1].freq
)
190 s
->snapshot
= s
->tm4
[tm
- 1].clock
+ muldiv64(
191 qemu_get_clock(vm_clock
) -
192 s
->tm4
[tm
- 1].lastload
,
193 s
->tm4
[tm
- 1].freq
, get_ticks_per_sec());
195 s
->snapshot
= s
->tm4
[tm
- 1].clock
;
198 if (!s
->tm4
[tm
].freq
)
199 return s
->tm4
[tm
].clock
;
200 return s
->tm4
[tm
].clock
+ muldiv64(qemu_get_clock(vm_clock
) -
201 s
->tm4
[tm
].lastload
, s
->tm4
[tm
].freq
, get_ticks_per_sec());
203 return s
->irq_enabled
;
204 case OSSR
: /* Status register */
216 if (!pxa2xx_timer_has_tm4(s
))
218 return s
->tm4
[tm
].control
;
223 hw_error("pxa2xx_timer_read: Bad offset " REG_FMT
"\n", offset
);
229 static void pxa2xx_timer_write(void *opaque
, target_phys_addr_t offset
,
233 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
240 s
->timer
[tm
].value
= value
;
241 pxa2xx_timer_update(s
, qemu_get_clock(vm_clock
));
251 if (!pxa2xx_timer_has_tm4(s
))
253 s
->tm4
[tm
].tm
.value
= value
;
254 pxa2xx_timer_update4(s
, qemu_get_clock(vm_clock
), tm
);
257 s
->oldclock
= s
->clock
;
258 s
->lastload
= qemu_get_clock(vm_clock
);
260 pxa2xx_timer_update(s
, s
->lastload
);
270 if (!pxa2xx_timer_has_tm4(s
))
272 s
->tm4
[tm
].oldclock
= s
->tm4
[tm
].clock
;
273 s
->tm4
[tm
].lastload
= qemu_get_clock(vm_clock
);
274 s
->tm4
[tm
].clock
= value
;
275 pxa2xx_timer_update4(s
, s
->tm4
[tm
].lastload
, tm
);
278 s
->irq_enabled
= value
& 0xfff;
280 case OSSR
: /* Status register */
282 for (i
= 0; i
< 4; i
++, value
>>= 1) {
283 if (s
->timer
[i
].level
&& (value
& 1)) {
284 s
->timer
[i
].level
= 0;
285 qemu_irq_lower(s
->timer
[i
].irq
);
288 if (pxa2xx_timer_has_tm4(s
)) {
289 for (i
= 0; i
< 8; i
++, value
>>= 1)
290 if (s
->tm4
[i
].tm
.level
&& (value
& 1))
291 s
->tm4
[i
].tm
.level
= 0;
292 if (!(s
->events
& 0xff0))
293 qemu_irq_lower(s
->irq4
);
296 case OWER
: /* XXX: Reset on OSMR3 match? */
303 if (!pxa2xx_timer_has_tm4(s
))
305 s
->tm4
[tm
].control
= value
& 0x0ff;
306 /* XXX Stop if running (shouldn't happen) */
307 if ((value
& (1 << 7)) || tm
== 0)
308 s
->tm4
[tm
].freq
= pxa2xx_timer4_freq
[value
& 7];
311 pxa2xx_timer_update4(s
, qemu_get_clock(vm_clock
), tm
);
318 if (!pxa2xx_timer_has_tm4(s
))
320 s
->tm4
[tm
].control
= value
& 0x3ff;
321 /* XXX Stop if running (shouldn't happen) */
322 if ((value
& (1 << 7)) || !(tm
& 1))
324 pxa2xx_timer4_freq
[(value
& (1 << 8)) ? 0 : (value
& 7)];
327 pxa2xx_timer_update4(s
, qemu_get_clock(vm_clock
), tm
);
332 hw_error("pxa2xx_timer_write: Bad offset " REG_FMT
"\n", offset
);
336 static CPUReadMemoryFunc
* const pxa2xx_timer_readfn
[] = {
342 static CPUWriteMemoryFunc
* const pxa2xx_timer_writefn
[] = {
348 static void pxa2xx_timer_tick(void *opaque
)
350 PXA2xxTimer0
*t
= (PXA2xxTimer0
*) opaque
;
351 PXA2xxTimerInfo
*i
= t
->info
;
353 if (i
->irq_enabled
& (1 << t
->num
)) {
355 i
->events
|= 1 << t
->num
;
356 qemu_irq_raise(t
->irq
);
362 qemu_system_reset_request();
366 static void pxa2xx_timer_tick4(void *opaque
)
368 PXA2xxTimer4
*t
= (PXA2xxTimer4
*) opaque
;
369 PXA2xxTimerInfo
*i
= (PXA2xxTimerInfo
*) t
->tm
.info
;
371 pxa2xx_timer_tick(&t
->tm
);
372 if (t
->control
& (1 << 3))
374 if (t
->control
& (1 << 6))
375 pxa2xx_timer_update4(i
, qemu_get_clock(vm_clock
), t
->tm
.num
- 4);
376 if (i
->events
& 0xff0)
377 qemu_irq_raise(i
->irq4
);
380 static int pxa25x_timer_post_load(void *opaque
, int version_id
)
382 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
386 now
= qemu_get_clock(vm_clock
);
387 pxa2xx_timer_update(s
, now
);
389 if (pxa2xx_timer_has_tm4(s
))
390 for (i
= 0; i
< 8; i
++)
391 pxa2xx_timer_update4(s
, now
, i
);
396 static int pxa2xx_timer_init(SysBusDevice
*dev
)
402 s
= FROM_SYSBUS(PXA2xxTimerInfo
, dev
);
406 s
->lastload
= qemu_get_clock(vm_clock
);
409 for (i
= 0; i
< 4; i
++) {
410 s
->timer
[i
].value
= 0;
411 sysbus_init_irq(dev
, &s
->timer
[i
].irq
);
412 s
->timer
[i
].info
= s
;
414 s
->timer
[i
].level
= 0;
415 s
->timer
[i
].qtimer
= qemu_new_timer(vm_clock
,
416 pxa2xx_timer_tick
, &s
->timer
[i
]);
418 if (s
->flags
& (1 << PXA2XX_TIMER_HAVE_TM4
)) {
419 sysbus_init_irq(dev
, &s
->irq4
);
421 for (i
= 0; i
< 8; i
++) {
422 s
->tm4
[i
].tm
.value
= 0;
423 s
->tm4
[i
].tm
.info
= s
;
424 s
->tm4
[i
].tm
.num
= i
+ 4;
425 s
->tm4
[i
].tm
.level
= 0;
427 s
->tm4
[i
].control
= 0x0;
428 s
->tm4
[i
].tm
.qtimer
= qemu_new_timer(vm_clock
,
429 pxa2xx_timer_tick4
, &s
->tm4
[i
]);
433 iomemtype
= cpu_register_io_memory(pxa2xx_timer_readfn
,
434 pxa2xx_timer_writefn
, s
, DEVICE_NATIVE_ENDIAN
);
435 sysbus_init_mmio(dev
, 0x00001000, iomemtype
);
440 static const VMStateDescription vmstate_pxa2xx_timer0_regs
= {
441 .name
= "pxa2xx_timer0",
443 .minimum_version_id
= 1,
444 .minimum_version_id_old
= 1,
445 .fields
= (VMStateField
[]) {
446 VMSTATE_UINT32(value
, PXA2xxTimer0
),
447 VMSTATE_INT32(level
, PXA2xxTimer0
),
448 VMSTATE_END_OF_LIST(),
452 static const VMStateDescription vmstate_pxa2xx_timer4_regs
= {
453 .name
= "pxa2xx_timer4",
455 .minimum_version_id
= 1,
456 .minimum_version_id_old
= 1,
457 .fields
= (VMStateField
[]) {
458 VMSTATE_STRUCT(tm
, PXA2xxTimer4
, 1,
459 vmstate_pxa2xx_timer0_regs
, PXA2xxTimer0
),
460 VMSTATE_INT32(oldclock
, PXA2xxTimer4
),
461 VMSTATE_INT32(clock
, PXA2xxTimer4
),
462 VMSTATE_UINT64(lastload
, PXA2xxTimer4
),
463 VMSTATE_UINT32(freq
, PXA2xxTimer4
),
464 VMSTATE_UINT32(control
, PXA2xxTimer4
),
465 VMSTATE_END_OF_LIST(),
469 static bool pxa2xx_timer_has_tm4_test(void *opaque
, int version_id
)
471 return pxa2xx_timer_has_tm4(opaque
);
474 static const VMStateDescription vmstate_pxa2xx_timer_regs
= {
475 .name
= "pxa2xx_timer",
477 .minimum_version_id
= 1,
478 .minimum_version_id_old
= 1,
479 .post_load
= pxa25x_timer_post_load
,
480 .fields
= (VMStateField
[]) {
481 VMSTATE_INT32(clock
, PXA2xxTimerInfo
),
482 VMSTATE_INT32(oldclock
, PXA2xxTimerInfo
),
483 VMSTATE_UINT64(lastload
, PXA2xxTimerInfo
),
484 VMSTATE_STRUCT_ARRAY(timer
, PXA2xxTimerInfo
, 4, 1,
485 vmstate_pxa2xx_timer0_regs
, PXA2xxTimer0
),
486 VMSTATE_UINT32(events
, PXA2xxTimerInfo
),
487 VMSTATE_UINT32(irq_enabled
, PXA2xxTimerInfo
),
488 VMSTATE_UINT32(reset3
, PXA2xxTimerInfo
),
489 VMSTATE_UINT32(snapshot
, PXA2xxTimerInfo
),
490 VMSTATE_STRUCT_ARRAY_TEST(tm4
, PXA2xxTimerInfo
, 8,
491 pxa2xx_timer_has_tm4_test
, 0,
492 vmstate_pxa2xx_timer4_regs
, PXA2xxTimer4
),
493 VMSTATE_END_OF_LIST(),
497 static SysBusDeviceInfo pxa25x_timer_dev_info
= {
498 .init
= pxa2xx_timer_init
,
499 .qdev
.name
= "pxa25x-timer",
500 .qdev
.desc
= "PXA25x timer",
501 .qdev
.size
= sizeof(PXA2xxTimerInfo
),
502 .qdev
.vmsd
= &vmstate_pxa2xx_timer_regs
,
503 .qdev
.props
= (Property
[]) {
504 DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo
, freq
, PXA25X_FREQ
),
505 DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo
, flags
,
506 PXA2XX_TIMER_HAVE_TM4
, false),
507 DEFINE_PROP_END_OF_LIST(),
511 static SysBusDeviceInfo pxa27x_timer_dev_info
= {
512 .init
= pxa2xx_timer_init
,
513 .qdev
.name
= "pxa27x-timer",
514 .qdev
.desc
= "PXA27x timer",
515 .qdev
.size
= sizeof(PXA2xxTimerInfo
),
516 .qdev
.vmsd
= &vmstate_pxa2xx_timer_regs
,
517 .qdev
.props
= (Property
[]) {
518 DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo
, freq
, PXA27X_FREQ
),
519 DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo
, flags
,
520 PXA2XX_TIMER_HAVE_TM4
, true),
521 DEFINE_PROP_END_OF_LIST(),
525 static void pxa2xx_timer_register(void)
527 sysbus_register_withprop(&pxa25x_timer_dev_info
);
528 sysbus_register_withprop(&pxa27x_timer_dev_info
);
530 device_init(pxa2xx_timer_register
);