2 * Raspberry Pi emulation (c) 2012 Gregory Estrade
3 * This code is licensed under the GNU GPLv2 and later.
6 #include "qemu/osdep.h"
8 #include "hw/timer/bcm2835_timer.h"
9 #include "qemu/main-loop.h"
11 #define SYSCLOCK_FREQ (252000000)
12 #define APBCLOCK_FREQ (126000000)
14 #define CTRL_FRC_EN (1 << 9)
15 #define CTRL_TIMER_EN (1 << 7)
16 #define CTRL_IRQ_EN (1 << 5)
17 #define CTRL_PS_MASK (3 << 2)
18 #define CTRL_PS_SHIFT 2
19 #define CTRL_CNT_32 (1 << 1)
20 #define CTRL_FRC_PS_MASK (0xff << 16)
21 #define CTRL_FRC_PS_SHIFT 16
23 static void timer_tick(void *opaque
)
25 BCM2835TimerState
*s
= (BCM2835TimerState
*)opaque
;
27 if (s
->control
& CTRL_IRQ_EN
) {
28 qemu_set_irq(s
->irq
, 1);
31 static void frc_timer_tick(void *opaque
)
33 BCM2835TimerState
*s
= (BCM2835TimerState
*)opaque
;
37 static uint64_t bcm2835_timer_read(void *opaque
, hwaddr offset
,
40 BCM2835TimerState
*s
= (BCM2835TimerState
*)opaque
;
50 res
= ptimer_get_count(s
->timer
);
62 if (s
->control
& CTRL_IRQ_EN
) {
76 qemu_log_mask(LOG_GUEST_ERROR
,
77 "bcm2835_timer_read: Bad offset %x\n", (int)offset
);
84 static void bcm2835_timer_write(void *opaque
, hwaddr offset
,
85 uint64_t value
, unsigned size
)
87 BCM2835TimerState
*s
= (BCM2835TimerState
*)opaque
;
95 ptimer_set_limit(s
->timer
, s
->load
, 1);
100 if (s
->control
& CTRL_FRC_EN
) {
101 ptimer_stop(s
->frc_timer
);
103 if (s
->control
& CTRL_TIMER_EN
) {
104 ptimer_stop(s
->timer
);
106 s
->control
= value
& 0x00ff03ae;
108 freq
= SYSCLOCK_FREQ
;
109 ptimer_set_freq(s
->frc_timer
, freq
);
110 ptimer_set_limit(s
->frc_timer
,
111 ((s
->control
& CTRL_FRC_PS_MASK
) >> CTRL_FRC_PS_SHIFT
) + 1,
112 s
->control
& CTRL_FRC_EN
);
114 freq
= APBCLOCK_FREQ
;
115 freq
/= s
->prediv
+ 1;
116 switch ((s
->control
& CTRL_PS_MASK
) >> CTRL_PS_SHIFT
) {
126 ptimer_set_freq(s
->timer
, freq
);
127 ptimer_set_limit(s
->timer
, s
->load
, s
->control
& CTRL_TIMER_EN
);
129 if (s
->control
& CTRL_TIMER_EN
) {
130 ptimer_run(s
->timer
, 0);
132 if (s
->control
& CTRL_FRC_EN
) {
134 ptimer_run(s
->frc_timer
, 0);
139 qemu_set_irq(s
->irq
, 0);
146 ptimer_set_limit(s
->timer
, s
->load
, 0);
149 s
->prediv
= value
& 0x3ff;
154 qemu_log_mask(LOG_GUEST_ERROR
,
155 "bcm2835_timer_write: Bad offset %x\n", (int)offset
);
160 static const MemoryRegionOps bcm2835_timer_ops
= {
161 .read
= bcm2835_timer_read
,
162 .write
= bcm2835_timer_write
,
163 .endianness
= DEVICE_NATIVE_ENDIAN
,
166 static const VMStateDescription vmstate_bcm2835_timer
= {
167 .name
= TYPE_BCM2835_TIMER
,
169 .minimum_version_id
= 1,
170 .minimum_version_id_old
= 1,
171 .fields
= (VMStateField
[]) {
172 VMSTATE_END_OF_LIST()
176 static void bcm2835_timer_init(Object
*obj
)
178 BCM2835TimerState
*s
= BCM2835_TIMER(obj
);
180 memory_region_init_io(&s
->iomem
, obj
, &bcm2835_timer_ops
, s
,
181 TYPE_BCM2835_TIMER
, 0x100);
182 sysbus_init_mmio(SYS_BUS_DEVICE(s
), &s
->iomem
);
183 sysbus_init_irq(SYS_BUS_DEVICE(s
), &s
->irq
);
186 static void bcm2835_timer_realize(DeviceState
*dev
, Error
**errp
)
188 BCM2835TimerState
*s
= BCM2835_TIMER(dev
);
192 s
->control
= 0x3e << 16;
196 bh
= qemu_bh_new(timer_tick
, s
);
197 s
->timer
= ptimer_init(bh
, PTIMER_POLICY_DEFAULT
);
199 bh
= qemu_bh_new(frc_timer_tick
, s
);
200 s
->frc_timer
= ptimer_init(bh
, PTIMER_POLICY_DEFAULT
);
203 static void bcm2835_timer_class_init(ObjectClass
*klass
, void *data
)
205 DeviceClass
*dc
= DEVICE_CLASS(klass
);
207 dc
->realize
= bcm2835_timer_realize
;
208 dc
->vmsd
= &vmstate_bcm2835_timer
;
211 static TypeInfo bcm2835_timer_info
= {
212 .name
= TYPE_BCM2835_TIMER
,
213 .parent
= TYPE_SYS_BUS_DEVICE
,
214 .instance_size
= sizeof(BCM2835TimerState
),
215 .class_init
= bcm2835_timer_class_init
,
216 .instance_init
= bcm2835_timer_init
,
219 static void bcm2835_timer_register_types(void)
221 type_register_static(&bcm2835_timer_info
);
224 type_init(bcm2835_timer_register_types
)