2 * Intel XScale PXA255/270 OS Timers.
4 * Copyright (c) 2006 Openedhand Ltd.
5 * Copyright (c) 2006 Thorsten Zitterell
7 * This code is licensed 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
{
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 uint64_t pxa2xx_timer_read(void *opaque
, target_phys_addr_t offset
,
155 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
163 return s
->timer
[tm
].value
;
172 if (!pxa2xx_timer_has_tm4(s
))
174 return s
->tm4
[tm
].tm
.value
;
176 return s
->clock
+ muldiv64(qemu_get_clock_ns(vm_clock
) -
177 s
->lastload
, s
->freq
, get_ticks_per_sec());
186 if (!pxa2xx_timer_has_tm4(s
))
189 if ((tm
== 9 - 4 || tm
== 11 - 4) && (s
->tm4
[tm
].control
& (1 << 9))) {
190 if (s
->tm4
[tm
- 1].freq
)
191 s
->snapshot
= s
->tm4
[tm
- 1].clock
+ muldiv64(
192 qemu_get_clock_ns(vm_clock
) -
193 s
->tm4
[tm
- 1].lastload
,
194 s
->tm4
[tm
- 1].freq
, get_ticks_per_sec());
196 s
->snapshot
= s
->tm4
[tm
- 1].clock
;
199 if (!s
->tm4
[tm
].freq
)
200 return s
->tm4
[tm
].clock
;
201 return s
->tm4
[tm
].clock
+ muldiv64(qemu_get_clock_ns(vm_clock
) -
202 s
->tm4
[tm
].lastload
, s
->tm4
[tm
].freq
, get_ticks_per_sec());
204 return s
->irq_enabled
;
205 case OSSR
: /* Status register */
217 if (!pxa2xx_timer_has_tm4(s
))
219 return s
->tm4
[tm
].control
;
224 hw_error("pxa2xx_timer_read: Bad offset " REG_FMT
"\n", offset
);
230 static void pxa2xx_timer_write(void *opaque
, target_phys_addr_t offset
,
231 uint64_t value
, unsigned size
)
234 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
241 s
->timer
[tm
].value
= value
;
242 pxa2xx_timer_update(s
, qemu_get_clock_ns(vm_clock
));
252 if (!pxa2xx_timer_has_tm4(s
))
254 s
->tm4
[tm
].tm
.value
= value
;
255 pxa2xx_timer_update4(s
, qemu_get_clock_ns(vm_clock
), tm
);
258 s
->oldclock
= s
->clock
;
259 s
->lastload
= qemu_get_clock_ns(vm_clock
);
261 pxa2xx_timer_update(s
, s
->lastload
);
271 if (!pxa2xx_timer_has_tm4(s
))
273 s
->tm4
[tm
].oldclock
= s
->tm4
[tm
].clock
;
274 s
->tm4
[tm
].lastload
= qemu_get_clock_ns(vm_clock
);
275 s
->tm4
[tm
].clock
= value
;
276 pxa2xx_timer_update4(s
, s
->tm4
[tm
].lastload
, tm
);
279 s
->irq_enabled
= value
& 0xfff;
281 case OSSR
: /* Status register */
284 for (i
= 0; i
< 4; i
++, value
>>= 1)
286 qemu_irq_lower(s
->timer
[i
].irq
);
287 if (pxa2xx_timer_has_tm4(s
) && !(s
->events
& 0xff0) && value
)
288 qemu_irq_lower(s
->irq4
);
290 case OWER
: /* XXX: Reset on OSMR3 match? */
297 if (!pxa2xx_timer_has_tm4(s
))
299 s
->tm4
[tm
].control
= value
& 0x0ff;
300 /* XXX Stop if running (shouldn't happen) */
301 if ((value
& (1 << 7)) || tm
== 0)
302 s
->tm4
[tm
].freq
= pxa2xx_timer4_freq
[value
& 7];
305 pxa2xx_timer_update4(s
, qemu_get_clock_ns(vm_clock
), tm
);
312 if (!pxa2xx_timer_has_tm4(s
))
314 s
->tm4
[tm
].control
= value
& 0x3ff;
315 /* XXX Stop if running (shouldn't happen) */
316 if ((value
& (1 << 7)) || !(tm
& 1))
318 pxa2xx_timer4_freq
[(value
& (1 << 8)) ? 0 : (value
& 7)];
321 pxa2xx_timer_update4(s
, qemu_get_clock_ns(vm_clock
), tm
);
326 hw_error("pxa2xx_timer_write: Bad offset " REG_FMT
"\n", offset
);
330 static const MemoryRegionOps pxa2xx_timer_ops
= {
331 .read
= pxa2xx_timer_read
,
332 .write
= pxa2xx_timer_write
,
333 .endianness
= DEVICE_NATIVE_ENDIAN
,
336 static void pxa2xx_timer_tick(void *opaque
)
338 PXA2xxTimer0
*t
= (PXA2xxTimer0
*) opaque
;
339 PXA2xxTimerInfo
*i
= t
->info
;
341 if (i
->irq_enabled
& (1 << t
->num
)) {
342 i
->events
|= 1 << t
->num
;
343 qemu_irq_raise(t
->irq
);
349 qemu_system_reset_request();
353 static void pxa2xx_timer_tick4(void *opaque
)
355 PXA2xxTimer4
*t
= (PXA2xxTimer4
*) opaque
;
356 PXA2xxTimerInfo
*i
= (PXA2xxTimerInfo
*) t
->tm
.info
;
358 pxa2xx_timer_tick(&t
->tm
);
359 if (t
->control
& (1 << 3))
361 if (t
->control
& (1 << 6))
362 pxa2xx_timer_update4(i
, qemu_get_clock_ns(vm_clock
), t
->tm
.num
- 4);
363 if (i
->events
& 0xff0)
364 qemu_irq_raise(i
->irq4
);
367 static int pxa25x_timer_post_load(void *opaque
, int version_id
)
369 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
373 now
= qemu_get_clock_ns(vm_clock
);
374 pxa2xx_timer_update(s
, now
);
376 if (pxa2xx_timer_has_tm4(s
))
377 for (i
= 0; i
< 8; i
++)
378 pxa2xx_timer_update4(s
, now
, i
);
383 static int pxa2xx_timer_init(SysBusDevice
*dev
)
388 s
= FROM_SYSBUS(PXA2xxTimerInfo
, dev
);
392 s
->lastload
= qemu_get_clock_ns(vm_clock
);
395 for (i
= 0; i
< 4; i
++) {
396 s
->timer
[i
].value
= 0;
397 sysbus_init_irq(dev
, &s
->timer
[i
].irq
);
398 s
->timer
[i
].info
= s
;
400 s
->timer
[i
].qtimer
= qemu_new_timer_ns(vm_clock
,
401 pxa2xx_timer_tick
, &s
->timer
[i
]);
403 if (s
->flags
& (1 << PXA2XX_TIMER_HAVE_TM4
)) {
404 sysbus_init_irq(dev
, &s
->irq4
);
406 for (i
= 0; i
< 8; i
++) {
407 s
->tm4
[i
].tm
.value
= 0;
408 s
->tm4
[i
].tm
.info
= s
;
409 s
->tm4
[i
].tm
.num
= i
+ 4;
411 s
->tm4
[i
].control
= 0x0;
412 s
->tm4
[i
].tm
.qtimer
= qemu_new_timer_ns(vm_clock
,
413 pxa2xx_timer_tick4
, &s
->tm4
[i
]);
417 memory_region_init_io(&s
->iomem
, &pxa2xx_timer_ops
, s
,
418 "pxa2xx-timer", 0x00001000);
419 sysbus_init_mmio(dev
, &s
->iomem
);
424 static const VMStateDescription vmstate_pxa2xx_timer0_regs
= {
425 .name
= "pxa2xx_timer0",
427 .minimum_version_id
= 2,
428 .minimum_version_id_old
= 2,
429 .fields
= (VMStateField
[]) {
430 VMSTATE_UINT32(value
, PXA2xxTimer0
),
431 VMSTATE_END_OF_LIST(),
435 static const VMStateDescription vmstate_pxa2xx_timer4_regs
= {
436 .name
= "pxa2xx_timer4",
438 .minimum_version_id
= 1,
439 .minimum_version_id_old
= 1,
440 .fields
= (VMStateField
[]) {
441 VMSTATE_STRUCT(tm
, PXA2xxTimer4
, 1,
442 vmstate_pxa2xx_timer0_regs
, PXA2xxTimer0
),
443 VMSTATE_INT32(oldclock
, PXA2xxTimer4
),
444 VMSTATE_INT32(clock
, PXA2xxTimer4
),
445 VMSTATE_UINT64(lastload
, PXA2xxTimer4
),
446 VMSTATE_UINT32(freq
, PXA2xxTimer4
),
447 VMSTATE_UINT32(control
, PXA2xxTimer4
),
448 VMSTATE_END_OF_LIST(),
452 static bool pxa2xx_timer_has_tm4_test(void *opaque
, int version_id
)
454 return pxa2xx_timer_has_tm4(opaque
);
457 static const VMStateDescription vmstate_pxa2xx_timer_regs
= {
458 .name
= "pxa2xx_timer",
460 .minimum_version_id
= 1,
461 .minimum_version_id_old
= 1,
462 .post_load
= pxa25x_timer_post_load
,
463 .fields
= (VMStateField
[]) {
464 VMSTATE_INT32(clock
, PXA2xxTimerInfo
),
465 VMSTATE_INT32(oldclock
, PXA2xxTimerInfo
),
466 VMSTATE_UINT64(lastload
, PXA2xxTimerInfo
),
467 VMSTATE_STRUCT_ARRAY(timer
, PXA2xxTimerInfo
, 4, 1,
468 vmstate_pxa2xx_timer0_regs
, PXA2xxTimer0
),
469 VMSTATE_UINT32(events
, PXA2xxTimerInfo
),
470 VMSTATE_UINT32(irq_enabled
, PXA2xxTimerInfo
),
471 VMSTATE_UINT32(reset3
, PXA2xxTimerInfo
),
472 VMSTATE_UINT32(snapshot
, PXA2xxTimerInfo
),
473 VMSTATE_STRUCT_ARRAY_TEST(tm4
, PXA2xxTimerInfo
, 8,
474 pxa2xx_timer_has_tm4_test
, 0,
475 vmstate_pxa2xx_timer4_regs
, PXA2xxTimer4
),
476 VMSTATE_END_OF_LIST(),
480 static SysBusDeviceInfo pxa25x_timer_dev_info
= {
481 .init
= pxa2xx_timer_init
,
482 .qdev
.name
= "pxa25x-timer",
483 .qdev
.desc
= "PXA25x timer",
484 .qdev
.size
= sizeof(PXA2xxTimerInfo
),
485 .qdev
.vmsd
= &vmstate_pxa2xx_timer_regs
,
486 .qdev
.props
= (Property
[]) {
487 DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo
, freq
, PXA25X_FREQ
),
488 DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo
, flags
,
489 PXA2XX_TIMER_HAVE_TM4
, false),
490 DEFINE_PROP_END_OF_LIST(),
494 static SysBusDeviceInfo pxa27x_timer_dev_info
= {
495 .init
= pxa2xx_timer_init
,
496 .qdev
.name
= "pxa27x-timer",
497 .qdev
.desc
= "PXA27x timer",
498 .qdev
.size
= sizeof(PXA2xxTimerInfo
),
499 .qdev
.vmsd
= &vmstate_pxa2xx_timer_regs
,
500 .qdev
.props
= (Property
[]) {
501 DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo
, freq
, PXA27X_FREQ
),
502 DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo
, flags
,
503 PXA2XX_TIMER_HAVE_TM4
, true),
504 DEFINE_PROP_END_OF_LIST(),
508 static void pxa2xx_timer_register(void)
510 sysbus_register_withprop(&pxa25x_timer_dev_info
);
511 sysbus_register_withprop(&pxa27x_timer_dev_info
);
513 device_init(pxa2xx_timer_register
);