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_timer_tick(void *opaque
)
44 SysTickState
*s
= (SysTickState
*)opaque
;
46 trace_systick_timer_tick();
48 s
->control
|= SYSTICK_COUNTFLAG
;
49 if (s
->control
& SYSTICK_TICKINT
) {
50 /* Tell the NVIC to pend the SysTick exception */
51 qemu_irq_pulse(s
->irq
);
53 if (ptimer_get_limit(s
->ptimer
) == 0) {
55 * Timer expiry with SYST_RVR zero disables the timer
56 * (but doesn't clear SYST_CSR.ENABLE)
58 ptimer_stop(s
->ptimer
);
62 static MemTxResult
systick_read(void *opaque
, hwaddr addr
, uint64_t *data
,
63 unsigned size
, MemTxAttrs attrs
)
65 SysTickState
*s
= opaque
;
69 /* Generate BusFault for unprivileged accesses */
74 case 0x0: /* SysTick Control and Status. */
76 s
->control
&= ~SYSTICK_COUNTFLAG
;
78 case 0x4: /* SysTick Reload Value. */
79 val
= ptimer_get_limit(s
->ptimer
);
81 case 0x8: /* SysTick Current Value. */
82 val
= ptimer_get_count(s
->ptimer
);
84 case 0xc: /* SysTick Calibration Value. */
89 qemu_log_mask(LOG_GUEST_ERROR
,
90 "SysTick: Bad read offset 0x%" HWADDR_PRIx
"\n", addr
);
94 trace_systick_read(addr
, val
, size
);
99 static MemTxResult
systick_write(void *opaque
, hwaddr addr
,
100 uint64_t value
, unsigned size
,
103 SysTickState
*s
= opaque
;
106 /* Generate BusFault for unprivileged accesses */
110 trace_systick_write(addr
, value
, size
);
113 case 0x0: /* SysTick Control and Status. */
117 ptimer_transaction_begin(s
->ptimer
);
119 s
->control
&= 0xfffffff8;
120 s
->control
|= value
& 7;
122 if ((oldval
^ value
) & SYSTICK_ENABLE
) {
123 if (value
& SYSTICK_ENABLE
) {
125 * Always reload the period in case board code has
126 * changed system_clock_scale. If we ever replace that
127 * global with a more sensible API then we might be able
128 * to set the period only when it actually changes.
130 ptimer_set_period(s
->ptimer
, systick_scale(s
));
131 ptimer_run(s
->ptimer
, 0);
133 ptimer_stop(s
->ptimer
);
135 } else if ((oldval
^ value
) & SYSTICK_CLKSOURCE
) {
136 ptimer_set_period(s
->ptimer
, systick_scale(s
));
138 ptimer_transaction_commit(s
->ptimer
);
141 case 0x4: /* SysTick Reload Value. */
142 ptimer_transaction_begin(s
->ptimer
);
143 ptimer_set_limit(s
->ptimer
, value
& 0xffffff, 0);
144 ptimer_transaction_commit(s
->ptimer
);
146 case 0x8: /* SysTick Current Value. */
148 * Writing any value clears SYST_CVR to zero and clears
149 * SYST_CSR.COUNTFLAG. The counter will then reload from SYST_RVR
150 * on the next clock edge unless SYST_RVR is zero.
152 ptimer_transaction_begin(s
->ptimer
);
153 if (ptimer_get_limit(s
->ptimer
) == 0) {
154 ptimer_stop(s
->ptimer
);
156 ptimer_set_count(s
->ptimer
, 0);
157 s
->control
&= ~SYSTICK_COUNTFLAG
;
158 ptimer_transaction_commit(s
->ptimer
);
161 qemu_log_mask(LOG_GUEST_ERROR
,
162 "SysTick: Bad write offset 0x%" HWADDR_PRIx
"\n", addr
);
167 static const MemoryRegionOps systick_ops
= {
168 .read_with_attrs
= systick_read
,
169 .write_with_attrs
= systick_write
,
170 .endianness
= DEVICE_NATIVE_ENDIAN
,
171 .valid
.min_access_size
= 4,
172 .valid
.max_access_size
= 4,
175 static void systick_reset(DeviceState
*dev
)
177 SysTickState
*s
= SYSTICK(dev
);
180 * Forgetting to set system_clock_scale is always a board code
181 * bug. We can't check this earlier because for some boards
182 * (like stellaris) it is not yet configured at the point where
183 * the systick device is realized.
185 assert(system_clock_scale
!= 0);
187 ptimer_transaction_begin(s
->ptimer
);
189 ptimer_stop(s
->ptimer
);
190 ptimer_set_count(s
->ptimer
, 0);
191 ptimer_set_limit(s
->ptimer
, 0, 0);
192 ptimer_set_period(s
->ptimer
, systick_scale(s
));
193 ptimer_transaction_commit(s
->ptimer
);
196 static void systick_instance_init(Object
*obj
)
198 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
199 SysTickState
*s
= SYSTICK(obj
);
201 memory_region_init_io(&s
->iomem
, obj
, &systick_ops
, s
, "systick", 0xe0);
202 sysbus_init_mmio(sbd
, &s
->iomem
);
203 sysbus_init_irq(sbd
, &s
->irq
);
206 static void systick_realize(DeviceState
*dev
, Error
**errp
)
208 SysTickState
*s
= SYSTICK(dev
);
209 s
->ptimer
= ptimer_init(systick_timer_tick
, s
,
210 PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD
|
211 PTIMER_POLICY_NO_COUNTER_ROUND_DOWN
|
212 PTIMER_POLICY_NO_IMMEDIATE_RELOAD
|
213 PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT
);
216 static const VMStateDescription vmstate_systick
= {
217 .name
= "armv7m_systick",
219 .minimum_version_id
= 2,
220 .fields
= (VMStateField
[]) {
221 VMSTATE_UINT32(control
, SysTickState
),
222 VMSTATE_INT64(tick
, SysTickState
),
223 VMSTATE_PTIMER(ptimer
, SysTickState
),
224 VMSTATE_END_OF_LIST()
228 static void systick_class_init(ObjectClass
*klass
, void *data
)
230 DeviceClass
*dc
= DEVICE_CLASS(klass
);
232 dc
->vmsd
= &vmstate_systick
;
233 dc
->reset
= systick_reset
;
234 dc
->realize
= systick_realize
;
237 static const TypeInfo armv7m_systick_info
= {
238 .name
= TYPE_SYSTICK
,
239 .parent
= TYPE_SYS_BUS_DEVICE
,
240 .instance_init
= systick_instance_init
,
241 .instance_size
= sizeof(SysTickState
),
242 .class_init
= systick_class_init
,
245 static void armv7m_systick_register_types(void)
247 type_register_static(&armv7m_systick_info
);
250 type_init(armv7m_systick_register_types
)