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 "migration/vmstate.h"
16 #include "hw/sysbus.h"
17 #include "qemu/timer.h"
19 #include "qemu/module.h"
22 /* qemu timers run at 1GHz. We want something closer to 1MHz. */
23 #define SYSTICK_SCALE 1000ULL
25 #define SYSTICK_ENABLE (1 << 0)
26 #define SYSTICK_TICKINT (1 << 1)
27 #define SYSTICK_CLKSOURCE (1 << 2)
28 #define SYSTICK_COUNTFLAG (1 << 16)
30 int system_clock_scale
;
32 /* Conversion factor from qemu timer to SysTick frequencies. */
33 static inline int64_t systick_scale(SysTickState
*s
)
35 if (s
->control
& SYSTICK_CLKSOURCE
) {
36 return system_clock_scale
;
42 static void systick_reload(SysTickState
*s
, int reset
)
44 /* The Cortex-M3 Devices Generic User Guide says that "When the
45 * ENABLE bit is set to 1, the counter loads the RELOAD value from the
46 * SYST RVR register and then counts down". So, we need to check the
47 * ENABLE bit before reloading the value.
49 trace_systick_reload();
51 if ((s
->control
& SYSTICK_ENABLE
) == 0) {
56 s
->tick
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
58 s
->tick
+= (s
->reload
+ 1) * systick_scale(s
);
59 timer_mod(s
->timer
, s
->tick
);
62 static void systick_timer_tick(void *opaque
)
64 SysTickState
*s
= (SysTickState
*)opaque
;
66 trace_systick_timer_tick();
68 s
->control
|= SYSTICK_COUNTFLAG
;
69 if (s
->control
& SYSTICK_TICKINT
) {
70 /* Tell the NVIC to pend the SysTick exception */
71 qemu_irq_pulse(s
->irq
);
74 s
->control
&= ~SYSTICK_ENABLE
;
80 static MemTxResult
systick_read(void *opaque
, hwaddr addr
, uint64_t *data
,
81 unsigned size
, MemTxAttrs attrs
)
83 SysTickState
*s
= opaque
;
87 /* Generate BusFault for unprivileged accesses */
92 case 0x0: /* SysTick Control and Status. */
94 s
->control
&= ~SYSTICK_COUNTFLAG
;
96 case 0x4: /* SysTick Reload Value. */
99 case 0x8: /* SysTick Current Value. */
103 if ((s
->control
& SYSTICK_ENABLE
) == 0) {
107 t
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
112 val
= ((s
->tick
- (t
+ 1)) / systick_scale(s
)) + 1;
113 /* The interrupt in triggered when the timer reaches zero.
114 However the counter is not reloaded until the next clock
115 tick. This is a hack to return zero during the first tick. */
116 if (val
> s
->reload
) {
121 case 0xc: /* SysTick Calibration Value. */
126 qemu_log_mask(LOG_GUEST_ERROR
,
127 "SysTick: Bad read offset 0x%" HWADDR_PRIx
"\n", addr
);
131 trace_systick_read(addr
, val
, size
);
136 static MemTxResult
systick_write(void *opaque
, hwaddr addr
,
137 uint64_t value
, unsigned size
,
140 SysTickState
*s
= opaque
;
143 /* Generate BusFault for unprivileged accesses */
147 trace_systick_write(addr
, value
, size
);
150 case 0x0: /* SysTick Control and Status. */
152 uint32_t oldval
= s
->control
;
154 s
->control
&= 0xfffffff8;
155 s
->control
|= value
& 7;
156 if ((oldval
^ value
) & SYSTICK_ENABLE
) {
157 int64_t now
= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
158 if (value
& SYSTICK_ENABLE
) {
161 timer_mod(s
->timer
, s
->tick
);
163 systick_reload(s
, 1);
172 } else if ((oldval
^ value
) & SYSTICK_CLKSOURCE
) {
173 /* This is a hack. Force the timer to be reloaded
174 when the reference clock is changed. */
175 systick_reload(s
, 1);
179 case 0x4: /* SysTick Reload Value. */
182 case 0x8: /* SysTick Current Value. Writes reload the timer. */
183 systick_reload(s
, 1);
184 s
->control
&= ~SYSTICK_COUNTFLAG
;
187 qemu_log_mask(LOG_GUEST_ERROR
,
188 "SysTick: Bad write offset 0x%" HWADDR_PRIx
"\n", addr
);
193 static const MemoryRegionOps systick_ops
= {
194 .read_with_attrs
= systick_read
,
195 .write_with_attrs
= systick_write
,
196 .endianness
= DEVICE_NATIVE_ENDIAN
,
197 .valid
.min_access_size
= 4,
198 .valid
.max_access_size
= 4,
201 static void systick_reset(DeviceState
*dev
)
203 SysTickState
*s
= SYSTICK(dev
);
211 static void systick_instance_init(Object
*obj
)
213 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
214 SysTickState
*s
= SYSTICK(obj
);
216 memory_region_init_io(&s
->iomem
, obj
, &systick_ops
, s
, "systick", 0xe0);
217 sysbus_init_mmio(sbd
, &s
->iomem
);
218 sysbus_init_irq(sbd
, &s
->irq
);
219 s
->timer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
, systick_timer_tick
, s
);
222 static const VMStateDescription vmstate_systick
= {
223 .name
= "armv7m_systick",
225 .minimum_version_id
= 1,
226 .fields
= (VMStateField
[]) {
227 VMSTATE_UINT32(control
, SysTickState
),
228 VMSTATE_UINT32(reload
, SysTickState
),
229 VMSTATE_INT64(tick
, SysTickState
),
230 VMSTATE_TIMER_PTR(timer
, SysTickState
),
231 VMSTATE_END_OF_LIST()
235 static void systick_class_init(ObjectClass
*klass
, void *data
)
237 DeviceClass
*dc
= DEVICE_CLASS(klass
);
239 dc
->vmsd
= &vmstate_systick
;
240 dc
->reset
= systick_reset
;
243 static const TypeInfo armv7m_systick_info
= {
244 .name
= TYPE_SYSTICK
,
245 .parent
= TYPE_SYS_BUS_DEVICE
,
246 .instance_init
= systick_instance_init
,
247 .instance_size
= sizeof(SysTickState
),
248 .class_init
= systick_class_init
,
251 static void armv7m_systick_register_types(void)
253 type_register_static(&armv7m_systick_info
);
256 type_init(armv7m_systick_register_types
)