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"
12 #include "sysemu/sysemu.h"
14 #include "hw/sysbus.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
, hwaddr offset
,
155 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
166 return s
->timer
[tm
].value
;
182 if (!pxa2xx_timer_has_tm4(s
))
184 return s
->tm4
[tm
].tm
.value
;
186 return s
->clock
+ muldiv64(qemu_get_clock_ns(vm_clock
) -
187 s
->lastload
, s
->freq
, get_ticks_per_sec());
203 if (!pxa2xx_timer_has_tm4(s
))
206 if ((tm
== 9 - 4 || tm
== 11 - 4) && (s
->tm4
[tm
].control
& (1 << 9))) {
207 if (s
->tm4
[tm
- 1].freq
)
208 s
->snapshot
= s
->tm4
[tm
- 1].clock
+ muldiv64(
209 qemu_get_clock_ns(vm_clock
) -
210 s
->tm4
[tm
- 1].lastload
,
211 s
->tm4
[tm
- 1].freq
, get_ticks_per_sec());
213 s
->snapshot
= s
->tm4
[tm
- 1].clock
;
216 if (!s
->tm4
[tm
].freq
)
217 return s
->tm4
[tm
].clock
;
218 return s
->tm4
[tm
].clock
+ muldiv64(qemu_get_clock_ns(vm_clock
) -
219 s
->tm4
[tm
].lastload
, s
->tm4
[tm
].freq
, get_ticks_per_sec());
221 return s
->irq_enabled
;
222 case OSSR
: /* Status register */
241 if (!pxa2xx_timer_has_tm4(s
))
243 return s
->tm4
[tm
].control
;
248 hw_error("pxa2xx_timer_read: Bad offset " REG_FMT
"\n", offset
);
254 static void pxa2xx_timer_write(void *opaque
, hwaddr offset
,
255 uint64_t value
, unsigned size
)
258 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
268 s
->timer
[tm
].value
= value
;
269 pxa2xx_timer_update(s
, qemu_get_clock_ns(vm_clock
));
286 if (!pxa2xx_timer_has_tm4(s
))
288 s
->tm4
[tm
].tm
.value
= value
;
289 pxa2xx_timer_update4(s
, qemu_get_clock_ns(vm_clock
), tm
);
292 s
->oldclock
= s
->clock
;
293 s
->lastload
= qemu_get_clock_ns(vm_clock
);
295 pxa2xx_timer_update(s
, s
->lastload
);
312 if (!pxa2xx_timer_has_tm4(s
))
314 s
->tm4
[tm
].oldclock
= s
->tm4
[tm
].clock
;
315 s
->tm4
[tm
].lastload
= qemu_get_clock_ns(vm_clock
);
316 s
->tm4
[tm
].clock
= value
;
317 pxa2xx_timer_update4(s
, s
->tm4
[tm
].lastload
, tm
);
320 s
->irq_enabled
= value
& 0xfff;
322 case OSSR
: /* Status register */
325 for (i
= 0; i
< 4; i
++, value
>>= 1)
327 qemu_irq_lower(s
->timer
[i
].irq
);
328 if (pxa2xx_timer_has_tm4(s
) && !(s
->events
& 0xff0) && value
)
329 qemu_irq_lower(s
->irq4
);
331 case OWER
: /* XXX: Reset on OSMR3 match? */
341 if (!pxa2xx_timer_has_tm4(s
))
343 s
->tm4
[tm
].control
= value
& 0x0ff;
344 /* XXX Stop if running (shouldn't happen) */
345 if ((value
& (1 << 7)) || tm
== 0)
346 s
->tm4
[tm
].freq
= pxa2xx_timer4_freq
[value
& 7];
349 pxa2xx_timer_update4(s
, qemu_get_clock_ns(vm_clock
), tm
);
359 if (!pxa2xx_timer_has_tm4(s
))
361 s
->tm4
[tm
].control
= value
& 0x3ff;
362 /* XXX Stop if running (shouldn't happen) */
363 if ((value
& (1 << 7)) || !(tm
& 1))
365 pxa2xx_timer4_freq
[(value
& (1 << 8)) ? 0 : (value
& 7)];
368 pxa2xx_timer_update4(s
, qemu_get_clock_ns(vm_clock
), tm
);
373 hw_error("pxa2xx_timer_write: Bad offset " REG_FMT
"\n", offset
);
377 static const MemoryRegionOps pxa2xx_timer_ops
= {
378 .read
= pxa2xx_timer_read
,
379 .write
= pxa2xx_timer_write
,
380 .endianness
= DEVICE_NATIVE_ENDIAN
,
383 static void pxa2xx_timer_tick(void *opaque
)
385 PXA2xxTimer0
*t
= (PXA2xxTimer0
*) opaque
;
386 PXA2xxTimerInfo
*i
= t
->info
;
388 if (i
->irq_enabled
& (1 << t
->num
)) {
389 i
->events
|= 1 << t
->num
;
390 qemu_irq_raise(t
->irq
);
396 qemu_system_reset_request();
400 static void pxa2xx_timer_tick4(void *opaque
)
402 PXA2xxTimer4
*t
= (PXA2xxTimer4
*) opaque
;
403 PXA2xxTimerInfo
*i
= (PXA2xxTimerInfo
*) t
->tm
.info
;
405 pxa2xx_timer_tick(&t
->tm
);
406 if (t
->control
& (1 << 3))
408 if (t
->control
& (1 << 6))
409 pxa2xx_timer_update4(i
, qemu_get_clock_ns(vm_clock
), t
->tm
.num
- 4);
410 if (i
->events
& 0xff0)
411 qemu_irq_raise(i
->irq4
);
414 static int pxa25x_timer_post_load(void *opaque
, int version_id
)
416 PXA2xxTimerInfo
*s
= (PXA2xxTimerInfo
*) opaque
;
420 now
= qemu_get_clock_ns(vm_clock
);
421 pxa2xx_timer_update(s
, now
);
423 if (pxa2xx_timer_has_tm4(s
))
424 for (i
= 0; i
< 8; i
++)
425 pxa2xx_timer_update4(s
, now
, i
);
430 static int pxa2xx_timer_init(SysBusDevice
*dev
)
435 s
= FROM_SYSBUS(PXA2xxTimerInfo
, dev
);
439 s
->lastload
= qemu_get_clock_ns(vm_clock
);
442 for (i
= 0; i
< 4; i
++) {
443 s
->timer
[i
].value
= 0;
444 sysbus_init_irq(dev
, &s
->timer
[i
].irq
);
445 s
->timer
[i
].info
= s
;
447 s
->timer
[i
].qtimer
= qemu_new_timer_ns(vm_clock
,
448 pxa2xx_timer_tick
, &s
->timer
[i
]);
450 if (s
->flags
& (1 << PXA2XX_TIMER_HAVE_TM4
)) {
451 sysbus_init_irq(dev
, &s
->irq4
);
453 for (i
= 0; i
< 8; i
++) {
454 s
->tm4
[i
].tm
.value
= 0;
455 s
->tm4
[i
].tm
.info
= s
;
456 s
->tm4
[i
].tm
.num
= i
+ 4;
458 s
->tm4
[i
].control
= 0x0;
459 s
->tm4
[i
].tm
.qtimer
= qemu_new_timer_ns(vm_clock
,
460 pxa2xx_timer_tick4
, &s
->tm4
[i
]);
464 memory_region_init_io(&s
->iomem
, &pxa2xx_timer_ops
, s
,
465 "pxa2xx-timer", 0x00001000);
466 sysbus_init_mmio(dev
, &s
->iomem
);
471 static const VMStateDescription vmstate_pxa2xx_timer0_regs
= {
472 .name
= "pxa2xx_timer0",
474 .minimum_version_id
= 2,
475 .minimum_version_id_old
= 2,
476 .fields
= (VMStateField
[]) {
477 VMSTATE_UINT32(value
, PXA2xxTimer0
),
478 VMSTATE_END_OF_LIST(),
482 static const VMStateDescription vmstate_pxa2xx_timer4_regs
= {
483 .name
= "pxa2xx_timer4",
485 .minimum_version_id
= 1,
486 .minimum_version_id_old
= 1,
487 .fields
= (VMStateField
[]) {
488 VMSTATE_STRUCT(tm
, PXA2xxTimer4
, 1,
489 vmstate_pxa2xx_timer0_regs
, PXA2xxTimer0
),
490 VMSTATE_INT32(oldclock
, PXA2xxTimer4
),
491 VMSTATE_INT32(clock
, PXA2xxTimer4
),
492 VMSTATE_UINT64(lastload
, PXA2xxTimer4
),
493 VMSTATE_UINT32(freq
, PXA2xxTimer4
),
494 VMSTATE_UINT32(control
, PXA2xxTimer4
),
495 VMSTATE_END_OF_LIST(),
499 static bool pxa2xx_timer_has_tm4_test(void *opaque
, int version_id
)
501 return pxa2xx_timer_has_tm4(opaque
);
504 static const VMStateDescription vmstate_pxa2xx_timer_regs
= {
505 .name
= "pxa2xx_timer",
507 .minimum_version_id
= 1,
508 .minimum_version_id_old
= 1,
509 .post_load
= pxa25x_timer_post_load
,
510 .fields
= (VMStateField
[]) {
511 VMSTATE_INT32(clock
, PXA2xxTimerInfo
),
512 VMSTATE_INT32(oldclock
, PXA2xxTimerInfo
),
513 VMSTATE_UINT64(lastload
, PXA2xxTimerInfo
),
514 VMSTATE_STRUCT_ARRAY(timer
, PXA2xxTimerInfo
, 4, 1,
515 vmstate_pxa2xx_timer0_regs
, PXA2xxTimer0
),
516 VMSTATE_UINT32(events
, PXA2xxTimerInfo
),
517 VMSTATE_UINT32(irq_enabled
, PXA2xxTimerInfo
),
518 VMSTATE_UINT32(reset3
, PXA2xxTimerInfo
),
519 VMSTATE_UINT32(snapshot
, PXA2xxTimerInfo
),
520 VMSTATE_STRUCT_ARRAY_TEST(tm4
, PXA2xxTimerInfo
, 8,
521 pxa2xx_timer_has_tm4_test
, 0,
522 vmstate_pxa2xx_timer4_regs
, PXA2xxTimer4
),
523 VMSTATE_END_OF_LIST(),
527 static Property pxa25x_timer_dev_properties
[] = {
528 DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo
, freq
, PXA25X_FREQ
),
529 DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo
, flags
,
530 PXA2XX_TIMER_HAVE_TM4
, false),
531 DEFINE_PROP_END_OF_LIST(),
534 static void pxa25x_timer_dev_class_init(ObjectClass
*klass
, void *data
)
536 DeviceClass
*dc
= DEVICE_CLASS(klass
);
537 SysBusDeviceClass
*k
= SYS_BUS_DEVICE_CLASS(klass
);
539 k
->init
= pxa2xx_timer_init
;
540 dc
->desc
= "PXA25x timer";
541 dc
->vmsd
= &vmstate_pxa2xx_timer_regs
;
542 dc
->props
= pxa25x_timer_dev_properties
;
545 static const TypeInfo pxa25x_timer_dev_info
= {
546 .name
= "pxa25x-timer",
547 .parent
= TYPE_SYS_BUS_DEVICE
,
548 .instance_size
= sizeof(PXA2xxTimerInfo
),
549 .class_init
= pxa25x_timer_dev_class_init
,
552 static Property pxa27x_timer_dev_properties
[] = {
553 DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo
, freq
, PXA27X_FREQ
),
554 DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo
, flags
,
555 PXA2XX_TIMER_HAVE_TM4
, true),
556 DEFINE_PROP_END_OF_LIST(),
559 static void pxa27x_timer_dev_class_init(ObjectClass
*klass
, void *data
)
561 DeviceClass
*dc
= DEVICE_CLASS(klass
);
562 SysBusDeviceClass
*k
= SYS_BUS_DEVICE_CLASS(klass
);
564 k
->init
= pxa2xx_timer_init
;
565 dc
->desc
= "PXA27x timer";
566 dc
->vmsd
= &vmstate_pxa2xx_timer_regs
;
567 dc
->props
= pxa27x_timer_dev_properties
;
570 static const TypeInfo pxa27x_timer_dev_info
= {
571 .name
= "pxa27x-timer",
572 .parent
= TYPE_SYS_BUS_DEVICE
,
573 .instance_size
= sizeof(PXA2xxTimerInfo
),
574 .class_init
= pxa27x_timer_dev_class_init
,
577 static void pxa2xx_timer_register_types(void)
579 type_register_static(&pxa25x_timer_dev_info
);
580 type_register_static(&pxa27x_timer_dev_info
);
583 type_init(pxa2xx_timer_register_types
)