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.
10 #include "qemu/osdep.h"
12 #include "qemu/timer.h"
13 #include "sysemu/sysemu.h"
14 #include "hw/arm/pxa.h"
15 #include "hw/sysbus.h"
29 #define OSCR 0x10 /* OS Timer Count */
38 #define OSSR 0x14 /* Timer status register */
40 #define OIER 0x1c /* Interrupt enable register 3-0 to E3-E0 */
41 #define OMCR4 0xc0 /* OS Match Control registers */
51 #define PXA25X_FREQ 3686400 /* 3.6864 MHz */
52 #define PXA27X_FREQ 3250000 /* 3.25 MHz */
54 static int pxa2xx_timer4_freq
[8] = {
60 /* [5] is the "Externally supplied clock". Assign if necessary. */
64 #define TYPE_PXA2XX_TIMER "pxa2xx-timer"
65 #define PXA2XX_TIMER(obj) \
66 OBJECT_CHECK(PXA2xxTimerInfo, (obj), TYPE_PXA2XX_TIMER)
68 typedef struct PXA2xxTimerInfo PXA2xxTimerInfo
;
75 PXA2xxTimerInfo
*info
;
87 struct PXA2xxTimerInfo
{
88 SysBusDevice parent_obj
;
97 PXA2xxTimer0 timer
[4];
107 #define PXA2XX_TIMER_HAVE_TM4 0
109 static inline int pxa2xx_timer_has_tm4(PXA2xxTimerInfo
*s
)
111 return s
->flags
& (1 << PXA2XX_TIMER_HAVE_TM4
);
114 static void pxa2xx_timer_update(void *opaque
, uint64_t now_qemu
)
116 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
122 muldiv64(now_qemu
- s
->lastload
, s
->freq
, NANOSECONDS_PER_SECOND
);
124 for (i
= 0; i
< 4; i
++) {
125 new_qemu
= now_qemu
+ muldiv64((uint32_t) (s
->timer
[i
].value
- now_vm
),
126 NANOSECONDS_PER_SECOND
, s
->freq
);
127 timer_mod(s
->timer
[i
].qtimer
, new_qemu
);
131 static void pxa2xx_timer_update4(void *opaque
, uint64_t now_qemu
, int n
)
133 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
136 static const int counters
[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
139 if (s
->tm4
[n
].control
& (1 << 7))
142 counter
= counters
[n
];
144 if (!s
->tm4
[counter
].freq
) {
145 timer_del(s
->tm4
[n
].tm
.qtimer
);
149 now_vm
= s
->tm4
[counter
].clock
+ muldiv64(now_qemu
-
150 s
->tm4
[counter
].lastload
,
151 s
->tm4
[counter
].freq
, NANOSECONDS_PER_SECOND
);
153 new_qemu
= now_qemu
+ muldiv64((uint32_t) (s
->tm4
[n
].tm
.value
- now_vm
),
154 NANOSECONDS_PER_SECOND
, s
->tm4
[counter
].freq
);
155 timer_mod(s
->tm4
[n
].tm
.qtimer
, new_qemu
);
158 static uint64_t pxa2xx_timer_read(void *opaque
, hwaddr offset
,
161 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
172 return s
->timer
[tm
].value
;
188 if (!pxa2xx_timer_has_tm4(s
))
190 return s
->tm4
[tm
].tm
.value
;
192 return s
->clock
+ muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
) -
193 s
->lastload
, s
->freq
, NANOSECONDS_PER_SECOND
);
209 if (!pxa2xx_timer_has_tm4(s
))
212 if ((tm
== 9 - 4 || tm
== 11 - 4) && (s
->tm4
[tm
].control
& (1 << 9))) {
213 if (s
->tm4
[tm
- 1].freq
)
214 s
->snapshot
= s
->tm4
[tm
- 1].clock
+ muldiv64(
215 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
) -
216 s
->tm4
[tm
- 1].lastload
,
217 s
->tm4
[tm
- 1].freq
, NANOSECONDS_PER_SECOND
);
219 s
->snapshot
= s
->tm4
[tm
- 1].clock
;
222 if (!s
->tm4
[tm
].freq
)
223 return s
->tm4
[tm
].clock
;
224 return s
->tm4
[tm
].clock
+
225 muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
) -
226 s
->tm4
[tm
].lastload
, s
->tm4
[tm
].freq
,
227 NANOSECONDS_PER_SECOND
);
229 return s
->irq_enabled
;
230 case OSSR
: /* Status register */
249 if (!pxa2xx_timer_has_tm4(s
))
251 return s
->tm4
[tm
].control
;
256 hw_error("pxa2xx_timer_read: Bad offset " REG_FMT
"\n", offset
);
262 static void pxa2xx_timer_write(void *opaque
, hwaddr offset
,
263 uint64_t value
, unsigned size
)
266 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
276 s
->timer
[tm
].value
= value
;
277 pxa2xx_timer_update(s
, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
));
294 if (!pxa2xx_timer_has_tm4(s
))
296 s
->tm4
[tm
].tm
.value
= value
;
297 pxa2xx_timer_update4(s
, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
), tm
);
300 s
->oldclock
= s
->clock
;
301 s
->lastload
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
303 pxa2xx_timer_update(s
, s
->lastload
);
320 if (!pxa2xx_timer_has_tm4(s
))
322 s
->tm4
[tm
].oldclock
= s
->tm4
[tm
].clock
;
323 s
->tm4
[tm
].lastload
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
324 s
->tm4
[tm
].clock
= value
;
325 pxa2xx_timer_update4(s
, s
->tm4
[tm
].lastload
, tm
);
328 s
->irq_enabled
= value
& 0xfff;
330 case OSSR
: /* Status register */
333 for (i
= 0; i
< 4; i
++, value
>>= 1)
335 qemu_irq_lower(s
->timer
[i
].irq
);
336 if (pxa2xx_timer_has_tm4(s
) && !(s
->events
& 0xff0) && value
)
337 qemu_irq_lower(s
->irq4
);
339 case OWER
: /* XXX: Reset on OSMR3 match? */
349 if (!pxa2xx_timer_has_tm4(s
))
351 s
->tm4
[tm
].control
= value
& 0x0ff;
352 /* XXX Stop if running (shouldn't happen) */
353 if ((value
& (1 << 7)) || tm
== 0)
354 s
->tm4
[tm
].freq
= pxa2xx_timer4_freq
[value
& 7];
357 pxa2xx_timer_update4(s
, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
), tm
);
367 if (!pxa2xx_timer_has_tm4(s
))
369 s
->tm4
[tm
].control
= value
& 0x3ff;
370 /* XXX Stop if running (shouldn't happen) */
371 if ((value
& (1 << 7)) || !(tm
& 1))
373 pxa2xx_timer4_freq
[(value
& (1 << 8)) ? 0 : (value
& 7)];
376 pxa2xx_timer_update4(s
, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
), tm
);
381 hw_error("pxa2xx_timer_write: Bad offset " REG_FMT
"\n", offset
);
385 static const MemoryRegionOps pxa2xx_timer_ops
= {
386 .read
= pxa2xx_timer_read
,
387 .write
= pxa2xx_timer_write
,
388 .endianness
= DEVICE_NATIVE_ENDIAN
,
391 static void pxa2xx_timer_tick(void *opaque
)
393 PXA2xxTimer0
*t
= (PXA2xxTimer0
*) opaque
;
394 PXA2xxTimerInfo
*i
= t
->info
;
396 if (i
->irq_enabled
& (1 << t
->num
)) {
397 i
->events
|= 1 << t
->num
;
398 qemu_irq_raise(t
->irq
);
404 qemu_system_reset_request();
408 static void pxa2xx_timer_tick4(void *opaque
)
410 PXA2xxTimer4
*t
= (PXA2xxTimer4
*) opaque
;
411 PXA2xxTimerInfo
*i
= (PXA2xxTimerInfo
*) t
->tm
.info
;
413 pxa2xx_timer_tick(&t
->tm
);
414 if (t
->control
& (1 << 3))
416 if (t
->control
& (1 << 6))
417 pxa2xx_timer_update4(i
, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
), t
->tm
.num
- 4);
418 if (i
->events
& 0xff0)
419 qemu_irq_raise(i
->irq4
);
422 static int pxa25x_timer_post_load(void *opaque
, int version_id
)
424 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
428 now
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
429 pxa2xx_timer_update(s
, now
);
431 if (pxa2xx_timer_has_tm4(s
))
432 for (i
= 0; i
< 8; i
++)
433 pxa2xx_timer_update4(s
, now
, i
);
438 static void pxa2xx_timer_init(Object
*obj
)
440 PXA2xxTimerInfo
*s
= PXA2XX_TIMER(obj
);
441 SysBusDevice
*dev
= SYS_BUS_DEVICE(obj
);
446 s
->lastload
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
449 memory_region_init_io(&s
->iomem
, obj
, &pxa2xx_timer_ops
, s
,
450 "pxa2xx-timer", 0x00001000);
451 sysbus_init_mmio(dev
, &s
->iomem
);
454 static void pxa2xx_timer_realize(DeviceState
*dev
, Error
**errp
)
456 PXA2xxTimerInfo
*s
= PXA2XX_TIMER(dev
);
457 SysBusDevice
*sbd
= SYS_BUS_DEVICE(dev
);
460 for (i
= 0; i
< 4; i
++) {
461 s
->timer
[i
].value
= 0;
462 sysbus_init_irq(sbd
, &s
->timer
[i
].irq
);
463 s
->timer
[i
].info
= s
;
465 s
->timer
[i
].qtimer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
,
466 pxa2xx_timer_tick
, &s
->timer
[i
]);
469 if (s
->flags
& (1 << PXA2XX_TIMER_HAVE_TM4
)) {
470 sysbus_init_irq(sbd
, &s
->irq4
);
472 for (i
= 0; i
< 8; i
++) {
473 s
->tm4
[i
].tm
.value
= 0;
474 s
->tm4
[i
].tm
.info
= s
;
475 s
->tm4
[i
].tm
.num
= i
+ 4;
477 s
->tm4
[i
].control
= 0x0;
478 s
->tm4
[i
].tm
.qtimer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
,
479 pxa2xx_timer_tick4
, &s
->tm4
[i
]);
484 static const VMStateDescription vmstate_pxa2xx_timer0_regs
= {
485 .name
= "pxa2xx_timer0",
487 .minimum_version_id
= 2,
488 .fields
= (VMStateField
[]) {
489 VMSTATE_UINT32(value
, PXA2xxTimer0
),
490 VMSTATE_END_OF_LIST(),
494 static const VMStateDescription vmstate_pxa2xx_timer4_regs
= {
495 .name
= "pxa2xx_timer4",
497 .minimum_version_id
= 1,
498 .fields
= (VMStateField
[]) {
499 VMSTATE_STRUCT(tm
, PXA2xxTimer4
, 1,
500 vmstate_pxa2xx_timer0_regs
, PXA2xxTimer0
),
501 VMSTATE_INT32(oldclock
, PXA2xxTimer4
),
502 VMSTATE_INT32(clock
, PXA2xxTimer4
),
503 VMSTATE_UINT64(lastload
, PXA2xxTimer4
),
504 VMSTATE_UINT32(freq
, PXA2xxTimer4
),
505 VMSTATE_UINT32(control
, PXA2xxTimer4
),
506 VMSTATE_END_OF_LIST(),
510 static bool pxa2xx_timer_has_tm4_test(void *opaque
, int version_id
)
512 return pxa2xx_timer_has_tm4(opaque
);
515 static const VMStateDescription vmstate_pxa2xx_timer_regs
= {
516 .name
= "pxa2xx_timer",
518 .minimum_version_id
= 1,
519 .post_load
= pxa25x_timer_post_load
,
520 .fields
= (VMStateField
[]) {
521 VMSTATE_INT32(clock
, PXA2xxTimerInfo
),
522 VMSTATE_INT32(oldclock
, PXA2xxTimerInfo
),
523 VMSTATE_UINT64(lastload
, PXA2xxTimerInfo
),
524 VMSTATE_STRUCT_ARRAY(timer
, PXA2xxTimerInfo
, 4, 1,
525 vmstate_pxa2xx_timer0_regs
, PXA2xxTimer0
),
526 VMSTATE_UINT32(events
, PXA2xxTimerInfo
),
527 VMSTATE_UINT32(irq_enabled
, PXA2xxTimerInfo
),
528 VMSTATE_UINT32(reset3
, PXA2xxTimerInfo
),
529 VMSTATE_UINT32(snapshot
, PXA2xxTimerInfo
),
530 VMSTATE_STRUCT_ARRAY_TEST(tm4
, PXA2xxTimerInfo
, 8,
531 pxa2xx_timer_has_tm4_test
, 0,
532 vmstate_pxa2xx_timer4_regs
, PXA2xxTimer4
),
533 VMSTATE_END_OF_LIST(),
537 static Property pxa25x_timer_dev_properties
[] = {
538 DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo
, freq
, PXA25X_FREQ
),
539 DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo
, flags
,
540 PXA2XX_TIMER_HAVE_TM4
, false),
541 DEFINE_PROP_END_OF_LIST(),
544 static void pxa25x_timer_dev_class_init(ObjectClass
*klass
, void *data
)
546 DeviceClass
*dc
= DEVICE_CLASS(klass
);
548 dc
->desc
= "PXA25x timer";
549 dc
->props
= pxa25x_timer_dev_properties
;
552 static const TypeInfo pxa25x_timer_dev_info
= {
553 .name
= "pxa25x-timer",
554 .parent
= TYPE_PXA2XX_TIMER
,
555 .instance_size
= sizeof(PXA2xxTimerInfo
),
556 .class_init
= pxa25x_timer_dev_class_init
,
559 static Property pxa27x_timer_dev_properties
[] = {
560 DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo
, freq
, PXA27X_FREQ
),
561 DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo
, flags
,
562 PXA2XX_TIMER_HAVE_TM4
, true),
563 DEFINE_PROP_END_OF_LIST(),
566 static void pxa27x_timer_dev_class_init(ObjectClass
*klass
, void *data
)
568 DeviceClass
*dc
= DEVICE_CLASS(klass
);
570 dc
->desc
= "PXA27x timer";
571 dc
->props
= pxa27x_timer_dev_properties
;
574 static const TypeInfo pxa27x_timer_dev_info
= {
575 .name
= "pxa27x-timer",
576 .parent
= TYPE_PXA2XX_TIMER
,
577 .instance_size
= sizeof(PXA2xxTimerInfo
),
578 .class_init
= pxa27x_timer_dev_class_init
,
581 static void pxa2xx_timer_class_init(ObjectClass
*oc
, void *data
)
583 DeviceClass
*dc
= DEVICE_CLASS(oc
);
585 dc
->realize
= pxa2xx_timer_realize
;
586 dc
->vmsd
= &vmstate_pxa2xx_timer_regs
;
589 static const TypeInfo pxa2xx_timer_type_info
= {
590 .name
= TYPE_PXA2XX_TIMER
,
591 .parent
= TYPE_SYS_BUS_DEVICE
,
592 .instance_size
= sizeof(PXA2xxTimerInfo
),
593 .instance_init
= pxa2xx_timer_init
,
595 .class_init
= pxa2xx_timer_class_init
,
598 static void pxa2xx_timer_register_types(void)
600 type_register_static(&pxa2xx_timer_type_info
);
601 type_register_static(&pxa25x_timer_dev_info
);
602 type_register_static(&pxa27x_timer_dev_info
);
605 type_init(pxa2xx_timer_register_types
)