4 * Copyright (c) 2006-2007 CodeSourcery.
5 * Written by Paul Brook
6 * Copyright (c) 2017 Linaro Ltd
7 * Written by Peter Maydell
9 * This code is licensed under the GPL (version 2 or later).
12 #include "qemu/osdep.h"
13 #include "hw/timer/armv7m_systick.h"
14 #include "qemu-common.h"
15 #include "hw/sysbus.h"
16 #include "qemu/timer.h"
20 /* qemu timers run at 1GHz. We want something closer to 1MHz. */
21 #define SYSTICK_SCALE 1000ULL
23 #define SYSTICK_ENABLE (1 << 0)
24 #define SYSTICK_TICKINT (1 << 1)
25 #define SYSTICK_CLKSOURCE (1 << 2)
26 #define SYSTICK_COUNTFLAG (1 << 16)
28 int system_clock_scale
;
30 /* Conversion factor from qemu timer to SysTick frequencies. */
31 static inline int64_t systick_scale(SysTickState
*s
)
33 if (s
->control
& SYSTICK_CLKSOURCE
) {
34 return system_clock_scale
;
40 static void systick_reload(SysTickState
*s
, int reset
)
42 /* The Cortex-M3 Devices Generic User Guide says that "When the
43 * ENABLE bit is set to 1, the counter loads the RELOAD value from the
44 * SYST RVR register and then counts down". So, we need to check the
45 * ENABLE bit before reloading the value.
47 trace_systick_reload();
49 if ((s
->control
& SYSTICK_ENABLE
) == 0) {
54 s
->tick
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
56 s
->tick
+= (s
->reload
+ 1) * systick_scale(s
);
57 timer_mod(s
->timer
, s
->tick
);
60 static void systick_timer_tick(void *opaque
)
62 SysTickState
*s
= (SysTickState
*)opaque
;
64 trace_systick_timer_tick();
66 s
->control
|= SYSTICK_COUNTFLAG
;
67 if (s
->control
& SYSTICK_TICKINT
) {
68 /* Tell the NVIC to pend the SysTick exception */
69 qemu_irq_pulse(s
->irq
);
72 s
->control
&= ~SYSTICK_ENABLE
;
78 static uint64_t systick_read(void *opaque
, hwaddr addr
, unsigned size
)
80 SysTickState
*s
= opaque
;
84 case 0x0: /* SysTick Control and Status. */
86 s
->control
&= ~SYSTICK_COUNTFLAG
;
88 case 0x4: /* SysTick Reload Value. */
91 case 0x8: /* SysTick Current Value. */
95 if ((s
->control
& SYSTICK_ENABLE
) == 0) {
99 t
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
104 val
= ((s
->tick
- (t
+ 1)) / systick_scale(s
)) + 1;
105 /* The interrupt in triggered when the timer reaches zero.
106 However the counter is not reloaded until the next clock
107 tick. This is a hack to return zero during the first tick. */
108 if (val
> s
->reload
) {
113 case 0xc: /* SysTick Calibration Value. */
118 qemu_log_mask(LOG_GUEST_ERROR
,
119 "SysTick: Bad read offset 0x%" HWADDR_PRIx
"\n", addr
);
123 trace_systick_read(addr
, val
, size
);
127 static void systick_write(void *opaque
, hwaddr addr
,
128 uint64_t value
, unsigned size
)
130 SysTickState
*s
= opaque
;
132 trace_systick_write(addr
, value
, size
);
135 case 0x0: /* SysTick Control and Status. */
137 uint32_t oldval
= s
->control
;
139 s
->control
&= 0xfffffff8;
140 s
->control
|= value
& 7;
141 if ((oldval
^ value
) & SYSTICK_ENABLE
) {
142 int64_t now
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
143 if (value
& SYSTICK_ENABLE
) {
146 timer_mod(s
->timer
, s
->tick
);
148 systick_reload(s
, 1);
157 } else if ((oldval
^ value
) & SYSTICK_CLKSOURCE
) {
158 /* This is a hack. Force the timer to be reloaded
159 when the reference clock is changed. */
160 systick_reload(s
, 1);
164 case 0x4: /* SysTick Reload Value. */
167 case 0x8: /* SysTick Current Value. Writes reload the timer. */
168 systick_reload(s
, 1);
169 s
->control
&= ~SYSTICK_COUNTFLAG
;
172 qemu_log_mask(LOG_GUEST_ERROR
,
173 "SysTick: Bad write offset 0x%" HWADDR_PRIx
"\n", addr
);
177 static const MemoryRegionOps systick_ops
= {
178 .read
= systick_read
,
179 .write
= systick_write
,
180 .endianness
= DEVICE_NATIVE_ENDIAN
,
181 .valid
.min_access_size
= 4,
182 .valid
.max_access_size
= 4,
185 static void systick_reset(DeviceState
*dev
)
187 SysTickState
*s
= SYSTICK(dev
);
195 static void systick_instance_init(Object
*obj
)
197 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
198 SysTickState
*s
= SYSTICK(obj
);
200 memory_region_init_io(&s
->iomem
, obj
, &systick_ops
, s
, "systick", 0xe0);
201 sysbus_init_mmio(sbd
, &s
->iomem
);
202 sysbus_init_irq(sbd
, &s
->irq
);
203 s
->timer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
, systick_timer_tick
, s
);
206 static const VMStateDescription vmstate_systick
= {
207 .name
= "armv7m_systick",
209 .minimum_version_id
= 1,
210 .fields
= (VMStateField
[]) {
211 VMSTATE_UINT32(control
, SysTickState
),
212 VMSTATE_UINT32(reload
, SysTickState
),
213 VMSTATE_INT64(tick
, SysTickState
),
214 VMSTATE_TIMER_PTR(timer
, SysTickState
),
215 VMSTATE_END_OF_LIST()
219 static void systick_class_init(ObjectClass
*klass
, void *data
)
221 DeviceClass
*dc
= DEVICE_CLASS(klass
);
223 dc
->vmsd
= &vmstate_systick
;
224 dc
->reset
= systick_reset
;
227 static const TypeInfo armv7m_systick_info
= {
228 .name
= TYPE_SYSTICK
,
229 .parent
= TYPE_SYS_BUS_DEVICE
,
230 .instance_init
= systick_instance_init
,
231 .instance_size
= sizeof(SysTickState
),
232 .class_init
= systick_class_init
,
235 static void armv7m_systick_register_types(void)
237 type_register_static(&armv7m_systick_info
);
240 type_init(armv7m_systick_register_types
)