1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include "qemu/osdep.h"
28#include "hw/sysbus.h"
29#include "hw/register.h"
30#include "hw/irq.h"
31#include "qemu/timer.h"
32#include "qemu/bitops.h"
33#include "qapi/error.h"
34#include "qemu/log.h"
35#include "migration/vmstate.h"
36#include "hw/qdev-properties.h"
37#include "hw/fdt_generic_util.h"
38
39#include "qapi/qmp/qerror.h"
40
41#ifndef XLNX_SWDT_ERR_DEBUG
42#define XLNX_SWDT_ERR_DEBUG 0
43#endif
44
45#define TYPE_XLNX_SWDT "xlnx.swdt"
46
47#define XLNX_SWDT(obj) \
48 OBJECT_CHECK(SWDTState, (obj), TYPE_XLNX_SWDT)
49
50REG32(MODE, 0x0)
51 FIELD(MODE, ZKEY, 12, 12)
52 FIELD(MODE, IRQLN, 7, 2)
53 FIELD(MODE, RSTLN, 4, 3)
54 FIELD(MODE, IRQEN, 2, 1)
55 FIELD(MODE, RSTEN, 1, 1)
56 FIELD(MODE, WDEN, 0, 1)
57REG32(CONTROL, 0x4)
58 FIELD(CONTROL, CKEY, 14, 12)
59 FIELD(CONTROL, CRV, 2, 12)
60 FIELD(CONTROL, CLKSEL, 0, 2)
61REG32(RESTART, 0x8)
62 FIELD(RESTART, RSTKEY, 0, 16)
63REG32(STATUS, 0xc)
64 FIELD(STATUS, WDZ, 0, 1)
65
66#define SWDT_R_MAX (R_STATUS + 1)
67
68typedef struct SWDTState {
69 SysBusDevice parent_obj;
70 MemoryRegion iomem;
71 qemu_irq irq;
72 qemu_irq rst;
73 qemu_irq wdt_timeout_irq;
74 QEMUTimer *timer;
75
76 QEMUTimer *irq_done_timer;
77 QEMUTimer *rst_done_timer;
78
79 uint64_t pclk;
80 uint32_t current_mode;
81 uint32_t current_control;
82 uint32_t regs[SWDT_R_MAX];
83 RegisterInfo regs_info[SWDT_R_MAX];
84} SWDTState;
85
86static void swdt_done_irq_update(SWDTState *s)
87{
88 uint64_t irqln = muldiv64(1000000000,
89 4 << ARRAY_FIELD_EX32(s->regs, MODE, IRQLN),
90 s->pclk);
91
92 qemu_set_irq(s->irq, 1);
93 timer_mod(s->irq_done_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + irqln);
94}
95
96static void swdt_reset_irq_update(SWDTState *s)
97{
98 uint64_t rstln = muldiv64(1000000000,
99 2 << ARRAY_FIELD_EX32(s->regs, MODE, RSTLN),
100 s->pclk);
101
102 qemu_set_irq(s->rst, 1);
103 timer_mod(s->rst_done_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + rstln);
104}
105
106static void swdt_irq_done(void *opaque)
107{
108 SWDTState *s = XLNX_SWDT(opaque);
109
110 qemu_set_irq(s->irq, 0);
111}
112
113static void swdt_reset_done(void *opaque)
114{
115 SWDTState *s = XLNX_SWDT(opaque);
116
117 qemu_set_irq(s->rst, 0);
118}
119
120static void swdt_time_elapsed(void *opaque)
121{
122 SWDTState *s = XLNX_SWDT(opaque);
123 bool do_a_reset = ARRAY_FIELD_EX32(s->regs, MODE, RSTEN);
124 bool do_an_irq = ARRAY_FIELD_EX32(s->regs, MODE, IRQEN);
125
126 s->regs[R_STATUS] = 1;
127 qemu_set_irq(s->wdt_timeout_irq, 1);
128
129 if (do_a_reset) {
130 swdt_reset_irq_update(s);
131 }
132 if (do_an_irq) {
133 swdt_done_irq_update(s);
134 }
135}
136
137static uint32_t swdt_reload_value(SWDTState *s)
138{
139 return (ARRAY_FIELD_EX32(s->regs, CONTROL, CRV) << 12) + 0xFFF;
140}
141
142static uint64_t swdt_next_trigger(SWDTState *s)
143{
144 uint64_t clksel = muldiv64(1000000000,
145 8 << (3 * ARRAY_FIELD_EX32(s->regs,
146 CONTROL, CLKSEL)),
147 s->pclk);
148
149 return (clksel * swdt_reload_value(s)) +
150 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
151}
152
153
154static void swdt_counter_reload(SWDTState *s)
155{
156 bool watchdog_enabled = ARRAY_FIELD_EX32(s->regs, MODE, WDEN);
157
158 if (watchdog_enabled) {
159 s->regs[R_STATUS] = 0;
160 timer_mod(s->timer, swdt_next_trigger(s));
161 } else {
162 timer_del(s->timer);
163 }
164}
165
166static void swdt_mode_postw(RegisterInfo *reg, uint64_t val64)
167{
168 SWDTState *s = XLNX_SWDT(reg->opaque);
169 bool valid = (ARRAY_FIELD_EX32(s->regs, MODE, ZKEY) == 0xABC);
170
171 if (!valid) {
172
173
174 s->regs[R_MODE] = s->current_mode;
175 return;
176 }
177
178 s->current_mode = s->regs[R_MODE];
179
180 swdt_counter_reload(s);
181}
182
183static uint64_t swdt_mode_postr(RegisterInfo *reg, uint64_t val)
184{
185 SWDTState *s = XLNX_SWDT(reg->opaque);
186
187
188 return s->regs[R_MODE] & ~R_MODE_ZKEY_MASK;
189}
190
191static void swdt_control_postw(RegisterInfo *reg, uint64_t val64)
192{
193 SWDTState *s = XLNX_SWDT(reg->opaque);
194 bool valid = (ARRAY_FIELD_EX32(s->regs, CONTROL, CKEY) == 0x248);
195
196 if (!valid) {
197
198
199 s->regs[R_CONTROL] = s->current_control;
200 return;
201 }
202
203
204 s->current_control = s->regs[R_CONTROL];
205}
206
207static void swdt_restart_key_postw(RegisterInfo *reg, uint64_t val64)
208{
209 SWDTState *s = XLNX_SWDT(reg->opaque);
210 bool valid = (ARRAY_FIELD_EX32(s->regs, RESTART, RSTKEY) == 0x1999);
211
212 if (valid) {
213 swdt_counter_reload(s);
214 }
215
216
217 s->regs[R_RESTART] = 0x0000;
218}
219
220static const RegisterAccessInfo swdt_regs_info[] = {
221 { .name = "MODE", .addr = A_MODE,
222 .reset = 0x1c2,
223 .rsvd = 0xe08,
224 .post_write = swdt_mode_postw,
225 .post_read = swdt_mode_postr,
226 },{ .name = "CONTROL", .addr = A_CONTROL,
227 .reset = 0x3ffc,
228 .post_write = swdt_control_postw,
229 },{ .name = "RESTART", .addr = A_RESTART,
230 .post_write = swdt_restart_key_postw,
231 },{ .name = "STATUS", .addr = A_STATUS,
232 .ro = 0x1,
233 }
234};
235
236static void swdt_reset(DeviceState *dev)
237{
238 SWDTState *s = XLNX_SWDT(dev);
239 unsigned int i;
240
241
242
243
244
245 s->current_mode = 0x000001C2;
246 s->current_control = 0x00003FFC;
247
248 for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
249 register_reset(&s->regs_info[i]);
250 }
251
252 swdt_counter_reload(s);
253 swdt_irq_done(s);
254 swdt_reset_done(s);
255}
256
257static const MemoryRegionOps swdt_ops = {
258 .read = register_read_memory,
259 .write = register_write_memory,
260 .endianness = DEVICE_LITTLE_ENDIAN,
261 .valid = {
262 .min_access_size = 4,
263 .max_access_size = 4,
264 },
265};
266
267static void swdt_realize(DeviceState *dev, Error **errp)
268{
269 SWDTState *s = XLNX_SWDT(dev);
270
271 if (!s->pclk) {
272 error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, "pclk");
273 return;
274 }
275}
276
277static void swdt_init(Object *obj)
278{
279 SWDTState *s = XLNX_SWDT(obj);
280 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
281 RegisterInfoArray *reg_array;
282
283 memory_region_init(&s->iomem, obj, TYPE_XLNX_SWDT, SWDT_R_MAX * 4);
284 reg_array =
285 register_init_block32(DEVICE(obj), swdt_regs_info,
286 ARRAY_SIZE(swdt_regs_info),
287 s->regs_info, s->regs,
288 &swdt_ops,
289 XLNX_SWDT_ERR_DEBUG,
290 SWDT_R_MAX * 4);
291 memory_region_add_subregion(&s->iomem,
292 0x0,
293 ®_array->mem);
294 sysbus_init_mmio(sbd, &s->iomem);
295 sysbus_init_irq(sbd, &s->irq);
296
297 qdev_init_gpio_out_named(DEVICE(obj), &s->wdt_timeout_irq,
298 "wdt_timeout_error_out", 1);
299
300 s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, swdt_time_elapsed, s);
301 s->irq_done_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, swdt_irq_done, s);
302 s->rst_done_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, swdt_reset_done, s);
303}
304
305static Property swdt_properties[] = {
306
307 DEFINE_PROP_UINT64("pclk", SWDTState, pclk, 0),
308 DEFINE_PROP_END_OF_LIST(),
309};
310
311static const FDTGenericGPIOSet wdt_client_gpios[] = {
312 {
313 .names = &fdt_generic_gpio_name_set_gpio,
314 .gpios = (FDTGenericGPIOConnection[]) {
315 { .name = "wdt_timeout_error_out", .fdt_index = 0, .range = 1 },
316 { },
317 }
318 },
319 { },
320};
321
322static const VMStateDescription vmstate_swdt = {
323 .name = TYPE_XLNX_SWDT,
324 .version_id = 1,
325 .minimum_version_id = 1,
326 .fields = (VMStateField[]) {
327 VMSTATE_UINT32_ARRAY(regs, SWDTState, SWDT_R_MAX),
328 VMSTATE_END_OF_LIST(),
329 }
330};
331
332static void swdt_class_init(ObjectClass *klass, void *data)
333{
334 DeviceClass *dc = DEVICE_CLASS(klass);
335 FDTGenericGPIOClass *fggc = FDT_GENERIC_GPIO_CLASS(klass);
336
337 dc->reset = swdt_reset;
338 dc->realize = swdt_realize;
339 dc->vmsd = &vmstate_swdt;
340 device_class_set_props(dc, swdt_properties);
341 fggc->client_gpios = wdt_client_gpios;
342}
343
344static const TypeInfo swdt_info = {
345 .name = TYPE_XLNX_SWDT,
346 .parent = TYPE_SYS_BUS_DEVICE,
347 .instance_size = sizeof(SWDTState),
348 .class_init = swdt_class_init,
349 .instance_init = swdt_init,
350 .interfaces = (InterfaceInfo[]) {
351 { TYPE_FDT_GENERIC_GPIO },
352 { }
353 },
354};
355
356static void swdt_register_types(void)
357{
358 type_register_static(&swdt_info);
359}
360
361type_init(swdt_register_types)
362