Merge tag 'seabios-20211203-pull-request' of git://git.kraxel.org/qemu into staging
[qemu.git] / hw / timer / armv7m_systick.c
1 /*
2 * ARMv7M SysTick timer
3 *
4 * Copyright (c) 2006-2007 CodeSourcery.
5 * Written by Paul Brook
6 * Copyright (c) 2017 Linaro Ltd
7 * Written by Peter Maydell
8 *
9 * This code is licensed under the GPL (version 2 or later).
10 */
11
12 #include "qemu/osdep.h"
13 #include "hw/timer/armv7m_systick.h"
14 #include "migration/vmstate.h"
15 #include "hw/irq.h"
16 #include "hw/sysbus.h"
17 #include "qemu/timer.h"
18 #include "qemu/log.h"
19 #include "qemu/module.h"
20 #include "trace.h"
21
22 /* qemu timers run at 1GHz. We want something closer to 1MHz. */
23 #define SYSTICK_SCALE 1000ULL
24
25 #define SYSTICK_ENABLE (1 << 0)
26 #define SYSTICK_TICKINT (1 << 1)
27 #define SYSTICK_CLKSOURCE (1 << 2)
28 #define SYSTICK_COUNTFLAG (1 << 16)
29
30 int system_clock_scale;
31
32 /* Conversion factor from qemu timer to SysTick frequencies. */
33 static inline int64_t systick_scale(SysTickState *s)
34 {
35 if (s->control & SYSTICK_CLKSOURCE) {
36 return system_clock_scale;
37 } else {
38 return 1000;
39 }
40 }
41
42 static void systick_timer_tick(void *opaque)
43 {
44 SysTickState *s = (SysTickState *)opaque;
45
46 trace_systick_timer_tick();
47
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);
52 }
53 if (ptimer_get_limit(s->ptimer) == 0) {
54 /*
55 * Timer expiry with SYST_RVR zero disables the timer
56 * (but doesn't clear SYST_CSR.ENABLE)
57 */
58 ptimer_stop(s->ptimer);
59 }
60 }
61
62 static MemTxResult systick_read(void *opaque, hwaddr addr, uint64_t *data,
63 unsigned size, MemTxAttrs attrs)
64 {
65 SysTickState *s = opaque;
66 uint32_t val;
67
68 if (attrs.user) {
69 /* Generate BusFault for unprivileged accesses */
70 return MEMTX_ERROR;
71 }
72
73 switch (addr) {
74 case 0x0: /* SysTick Control and Status. */
75 val = s->control;
76 s->control &= ~SYSTICK_COUNTFLAG;
77 break;
78 case 0x4: /* SysTick Reload Value. */
79 val = ptimer_get_limit(s->ptimer);
80 break;
81 case 0x8: /* SysTick Current Value. */
82 val = ptimer_get_count(s->ptimer);
83 break;
84 case 0xc: /* SysTick Calibration Value. */
85 val = 10000;
86 break;
87 default:
88 val = 0;
89 qemu_log_mask(LOG_GUEST_ERROR,
90 "SysTick: Bad read offset 0x%" HWADDR_PRIx "\n", addr);
91 break;
92 }
93
94 trace_systick_read(addr, val, size);
95 *data = val;
96 return MEMTX_OK;
97 }
98
99 static MemTxResult systick_write(void *opaque, hwaddr addr,
100 uint64_t value, unsigned size,
101 MemTxAttrs attrs)
102 {
103 SysTickState *s = opaque;
104
105 if (attrs.user) {
106 /* Generate BusFault for unprivileged accesses */
107 return MEMTX_ERROR;
108 }
109
110 trace_systick_write(addr, value, size);
111
112 switch (addr) {
113 case 0x0: /* SysTick Control and Status. */
114 {
115 uint32_t oldval;
116
117 ptimer_transaction_begin(s->ptimer);
118 oldval = s->control;
119 s->control &= 0xfffffff8;
120 s->control |= value & 7;
121
122 if ((oldval ^ value) & SYSTICK_ENABLE) {
123 if (value & SYSTICK_ENABLE) {
124 /*
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.
129 */
130 ptimer_set_period(s->ptimer, systick_scale(s));
131 ptimer_run(s->ptimer, 0);
132 } else {
133 ptimer_stop(s->ptimer);
134 }
135 } else if ((oldval ^ value) & SYSTICK_CLKSOURCE) {
136 ptimer_set_period(s->ptimer, systick_scale(s));
137 }
138 ptimer_transaction_commit(s->ptimer);
139 break;
140 }
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);
145 break;
146 case 0x8: /* SysTick Current Value. */
147 /*
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.
151 */
152 ptimer_transaction_begin(s->ptimer);
153 if (ptimer_get_limit(s->ptimer) == 0) {
154 ptimer_stop(s->ptimer);
155 }
156 ptimer_set_count(s->ptimer, 0);
157 s->control &= ~SYSTICK_COUNTFLAG;
158 ptimer_transaction_commit(s->ptimer);
159 break;
160 default:
161 qemu_log_mask(LOG_GUEST_ERROR,
162 "SysTick: Bad write offset 0x%" HWADDR_PRIx "\n", addr);
163 }
164 return MEMTX_OK;
165 }
166
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,
173 };
174
175 static void systick_reset(DeviceState *dev)
176 {
177 SysTickState *s = SYSTICK(dev);
178
179 /*
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.
184 */
185 assert(system_clock_scale != 0);
186
187 ptimer_transaction_begin(s->ptimer);
188 s->control = 0;
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);
194 }
195
196 static void systick_instance_init(Object *obj)
197 {
198 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
199 SysTickState *s = SYSTICK(obj);
200
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);
204 }
205
206 static void systick_realize(DeviceState *dev, Error **errp)
207 {
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);
214 }
215
216 static const VMStateDescription vmstate_systick = {
217 .name = "armv7m_systick",
218 .version_id = 2,
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()
225 }
226 };
227
228 static void systick_class_init(ObjectClass *klass, void *data)
229 {
230 DeviceClass *dc = DEVICE_CLASS(klass);
231
232 dc->vmsd = &vmstate_systick;
233 dc->reset = systick_reset;
234 dc->realize = systick_realize;
235 }
236
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,
243 };
244
245 static void armv7m_systick_register_types(void)
246 {
247 type_register_static(&armv7m_systick_info);
248 }
249
250 type_init(armv7m_systick_register_types)