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
28#include "qemu/osdep.h"
29#include "hw/sysbus.h"
30#include "hw/register-dep.h"
31#include "qemu/bitops.h"
32#include "qemu/log.h"
33
34#include "hw/fdt_generic_util.h"
35
36#define TYPE_XILINX_IPI "xlnx.zynqmp_ipi"
37
38#define XILINX_IPI(obj) \
39 OBJECT_CHECK(IPI, (obj), TYPE_XILINX_IPI)
40
41#ifndef XILINX_IPI_ERR_DEBUG
42#define XILINX_IPI_ERR_DEBUG 0
43#endif
44
45#define DB_PRINT_L(lvl, fmt, args...) do {\
46 if (XILINX_IPI_ERR_DEBUG >= lvl) {\
47 qemu_log(TYPE_XILINX_IPI ": %s:" fmt, __func__, ## args);\
48 } \
49} while (0);
50
51#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
52
53DEP_REG32(IPI_TRIG, 0x0)
54 DEP_FIELD(IPI_TRIG, PL_3, 1, 27)
55 DEP_FIELD(IPI_TRIG, PL_2, 1, 26)
56 DEP_FIELD(IPI_TRIG, PL_1, 1, 25)
57 DEP_FIELD(IPI_TRIG, PL_0, 1, 24)
58 DEP_FIELD(IPI_TRIG, PMU_3, 1, 19)
59 DEP_FIELD(IPI_TRIG, PMU_2, 1, 18)
60 DEP_FIELD(IPI_TRIG, PMU_1, 1, 17)
61 DEP_FIELD(IPI_TRIG, PMU_0, 1, 16)
62 DEP_FIELD(IPI_TRIG, RPU_1, 1, 9)
63 DEP_FIELD(IPI_TRIG, RPU_0, 1, 8)
64 DEP_FIELD(IPI_TRIG, APU, 1, 0)
65DEP_REG32(IPI_OBS, 0x4)
66 DEP_FIELD(IPI_OBS, PL_3, 1, 27)
67 DEP_FIELD(IPI_OBS, PL_2, 1, 26)
68 DEP_FIELD(IPI_OBS, PL_1, 1, 25)
69 DEP_FIELD(IPI_OBS, PL_0, 1, 24)
70 DEP_FIELD(IPI_OBS, PMU_3, 1, 19)
71 DEP_FIELD(IPI_OBS, PMU_2, 1, 18)
72 DEP_FIELD(IPI_OBS, PMU_1, 1, 17)
73 DEP_FIELD(IPI_OBS, PMU_0, 1, 16)
74 DEP_FIELD(IPI_OBS, RPU_1, 1, 9)
75 DEP_FIELD(IPI_OBS, RPU_0, 1, 8)
76 DEP_FIELD(IPI_OBS, APU, 1, 0)
77DEP_REG32(IPI_ISR, 0x10)
78 DEP_FIELD(IPI_ISR, PL_3, 1, 27)
79 DEP_FIELD(IPI_ISR, PL_2, 1, 26)
80 DEP_FIELD(IPI_ISR, PL_1, 1, 25)
81 DEP_FIELD(IPI_ISR, PL_0, 1, 24)
82 DEP_FIELD(IPI_ISR, PMU_3, 1, 19)
83 DEP_FIELD(IPI_ISR, PMU_2, 1, 18)
84 DEP_FIELD(IPI_ISR, PMU_1, 1, 17)
85 DEP_FIELD(IPI_ISR, PMU_0, 1, 16)
86 DEP_FIELD(IPI_ISR, RPU_1, 1, 9)
87 DEP_FIELD(IPI_ISR, RPU_0, 1, 8)
88 DEP_FIELD(IPI_ISR, APU, 1, 0)
89DEP_REG32(IPI_IMR, 0x14)
90 DEP_FIELD(IPI_IMR, PL_3, 1, 27)
91 DEP_FIELD(IPI_IMR, PL_2, 1, 26)
92 DEP_FIELD(IPI_IMR, PL_1, 1, 25)
93 DEP_FIELD(IPI_IMR, PL_0, 1, 24)
94 DEP_FIELD(IPI_IMR, PMU_3, 1, 19)
95 DEP_FIELD(IPI_IMR, PMU_2, 1, 18)
96 DEP_FIELD(IPI_IMR, PMU_1, 1, 17)
97 DEP_FIELD(IPI_IMR, PMU_0, 1, 16)
98 DEP_FIELD(IPI_IMR, RPU_1, 1, 9)
99 DEP_FIELD(IPI_IMR, RPU_0, 1, 8)
100 DEP_FIELD(IPI_IMR, APU, 1, 0)
101DEP_REG32(IPI_IER, 0x18)
102 DEP_FIELD(IPI_IER, PL_3, 1, 27)
103 DEP_FIELD(IPI_IER, PL_2, 1, 26)
104 DEP_FIELD(IPI_IER, PL_1, 1, 25)
105 DEP_FIELD(IPI_IER, PL_0, 1, 24)
106 DEP_FIELD(IPI_IER, PMU_3, 1, 19)
107 DEP_FIELD(IPI_IER, PMU_2, 1, 18)
108 DEP_FIELD(IPI_IER, PMU_1, 1, 17)
109 DEP_FIELD(IPI_IER, PMU_0, 1, 16)
110 DEP_FIELD(IPI_IER, RPU_1, 1, 9)
111 DEP_FIELD(IPI_IER, RPU_0, 1, 8)
112 DEP_FIELD(IPI_IER, APU, 1, 0)
113DEP_REG32(IPI_IDR, 0x1c)
114 DEP_FIELD(IPI_IDR, PL_3, 1, 27)
115 DEP_FIELD(IPI_IDR, PL_2, 1, 26)
116 DEP_FIELD(IPI_IDR, PL_1, 1, 25)
117 DEP_FIELD(IPI_IDR, PL_0, 1, 24)
118 DEP_FIELD(IPI_IDR, PMU_3, 1, 19)
119 DEP_FIELD(IPI_IDR, PMU_2, 1, 18)
120 DEP_FIELD(IPI_IDR, PMU_1, 1, 17)
121 DEP_FIELD(IPI_IDR, PMU_0, 1, 16)
122 DEP_FIELD(IPI_IDR, RPU_1, 1, 9)
123 DEP_FIELD(IPI_IDR, RPU_0, 1, 8)
124 DEP_FIELD(IPI_IDR, APU, 1, 0)
125
126#define R_MAX (R_IPI_IDR + 1)
127
128typedef struct IPI {
129 SysBusDevice parent_obj;
130 MemoryRegion iomem;
131 qemu_irq irq;
132
133 uint32_t regs[R_MAX];
134 DepRegisterInfo regs_info[R_MAX];
135} IPI;
136
137static void ipi_update_irq(IPI *s)
138{
139 bool pending = s->regs[R_IPI_ISR] & ~s->regs[R_IPI_IMR];
140 DB_PRINT("%s: irq=%d isr=%x mask=%x\n",
141 object_get_canonical_path(OBJECT(s)),
142 pending, s->regs[R_IPI_ISR], s->regs[R_IPI_IMR]);
143 qemu_set_irq(s->irq, pending);
144}
145
146static void ipi_isr_postw(DepRegisterInfo *reg, uint64_t val64)
147{
148 IPI *s = XILINX_IPI(reg->opaque);
149 ipi_update_irq(s);
150}
151
152static uint64_t ipi_ier_prew(DepRegisterInfo *reg, uint64_t val64)
153{
154 IPI *s = XILINX_IPI(reg->opaque);
155 uint32_t val = val64;
156
157 s->regs[R_IPI_IMR] &= ~val;
158 ipi_update_irq(s);
159 return 0;
160}
161
162static uint64_t ipi_idr_prew(DepRegisterInfo *reg, uint64_t val64)
163{
164 IPI *s = XILINX_IPI(reg->opaque);
165 uint32_t val = val64;
166
167 s->regs[R_IPI_IMR] |= val;
168 ipi_update_irq(s);
169 return 0;
170}
171
172static void ipi_trig_postw(DepRegisterInfo *reg, uint64_t val64) {
173 IPI *s = XILINX_IPI(reg->opaque);
174 uint64_t old_value = s->regs[R_IPI_TRIG];
175
176
177
178 s->regs[R_IPI_TRIG] = 0;
179 dep_register_refresh_gpios(reg, old_value);
180}
181
182#define GPIO_TRIG_OUT(x) \
183 { .name = stringify(x), .bit_pos = R_IPI_TRIG_ ## x ## _SHIFT, .width = 1 }
184
185#define GPIO_OBS_OUT(x) \
186 { .name = "OBS_" stringify(x), .bit_pos = R_IPI_ISR_ ## x ## _SHIFT, .width = 1 }
187
188static DepRegisterAccessInfo ipi_regs_info[] = {
189 { .name = "IPI_TRIG", .decode.addr = A_IPI_TRIG,
190 .rsvd = 0xf0f0fcfe,
191 .ro = 0xf0f0fcfe,
192 .post_write = ipi_trig_postw,
193 .gpios = (DepRegisterGPIOMapping[]) {
194 GPIO_TRIG_OUT(APU),
195 GPIO_TRIG_OUT(RPU_0),
196 GPIO_TRIG_OUT(RPU_1),
197 GPIO_TRIG_OUT(PMU_0),
198 GPIO_TRIG_OUT(PMU_1),
199 GPIO_TRIG_OUT(PMU_2),
200 GPIO_TRIG_OUT(PMU_3),
201 GPIO_TRIG_OUT(PL_0),
202 GPIO_TRIG_OUT(PL_1),
203 GPIO_TRIG_OUT(PL_2),
204 GPIO_TRIG_OUT(PL_3),
205 { },
206 }
207 },{ .name = "IPI_OBS", .decode.addr = A_IPI_OBS,
208 .rsvd = 0xf0f0fcfe,
209 .ro = 0xffffffff,
210 },{ .name = "IPI_ISR", .decode.addr = A_IPI_ISR,
211 .rsvd = 0xf0f0fcfe,
212 .ro = 0xf0f0fcfe,
213 .w1c = 0xf0f0301,
214 .post_write = ipi_isr_postw,
215 .gpios = (DepRegisterGPIOMapping[]) {
216 GPIO_OBS_OUT(APU),
217 GPIO_OBS_OUT(RPU_0),
218 GPIO_OBS_OUT(RPU_1),
219 GPIO_OBS_OUT(PMU_0),
220 GPIO_OBS_OUT(PMU_1),
221 GPIO_OBS_OUT(PMU_2),
222 GPIO_OBS_OUT(PMU_3),
223 GPIO_OBS_OUT(PL_0),
224 GPIO_OBS_OUT(PL_1),
225 GPIO_OBS_OUT(PL_2),
226 GPIO_OBS_OUT(PL_3),
227 { },
228 }
229 },{ .name = "IPI_IMR", .decode.addr = A_IPI_IMR,
230 .reset = 0xf0f0301,
231 .rsvd = 0xf0f0fcfe,
232 .ro = 0xffffffff,
233 },{ .name = "IPI_IER", .decode.addr = A_IPI_IER,
234 .rsvd = 0xf0f0fcfe,
235 .ro = 0xf0f0fcfe,
236 .pre_write = ipi_ier_prew,
237 },{ .name = "IPI_IDR", .decode.addr = A_IPI_IDR,
238 .rsvd = 0xf0f0fcfe,
239 .ro = 0xf0f0fcfe,
240 .pre_write = ipi_idr_prew,
241 }
242};
243
244static void ipi_reset(DeviceState *dev)
245{
246 IPI *s = XILINX_IPI(dev);
247 unsigned int i;
248
249 for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
250 dep_register_reset(&s->regs_info[i]);
251 }
252
253 ipi_update_irq(s);
254}
255
256static void ipi_handler(void *opaque, int n, int level)
257{
258 IPI *s = XILINX_IPI(opaque);
259 DepRegisterInfo *r_isr = &s->regs_info[A_IPI_ISR / 4];
260 uint32_t val = (!!level) << n;
261 uint64_t old_value = s->regs[R_IPI_ISR];
262
263 DB_PRINT("%s: %s: irq[%d]=%d\n", __func__,
264 object_get_canonical_path(OBJECT(s)), n, level);
265
266 s->regs[R_IPI_ISR] |= val;
267 ipi_update_irq(s);
268 dep_register_refresh_gpios(r_isr, old_value);
269}
270
271static void obs_handler(void *opaque, int n, int level)
272{
273 IPI *s = XILINX_IPI(opaque);
274
275 s->regs[R_IPI_OBS] &= ~(1ULL << n);
276 s->regs[R_IPI_OBS] |= (level << n);
277}
278
279static uint64_t ipi_read(void *opaque, hwaddr addr, unsigned size)
280{
281 IPI *s = XILINX_IPI(opaque);
282 DepRegisterInfo *r = &s->regs_info[addr / 4];
283
284 if (!r->data) {
285 qemu_log_mask(LOG_GUEST_ERROR,
286 "%s: Decode error: read from %" HWADDR_PRIx "\n",
287 object_get_canonical_path(OBJECT(s)), addr);
288 return 0;
289 }
290 return dep_register_read(r);
291}
292
293static void ipi_write(void *opaque, hwaddr addr, uint64_t value,
294 unsigned size)
295{
296 IPI *s = XILINX_IPI(opaque);
297 DepRegisterInfo *r = &s->regs_info[addr / 4];
298
299 if (!r->data) {
300 qemu_log_mask(LOG_GUEST_ERROR, "%s: Decode error: write to"
301 " %" HWADDR_PRIx "=%" PRIx64 "\n",
302 object_get_canonical_path(OBJECT(s)), addr, value);
303 return;
304 }
305 dep_register_write(r, value, ~0);
306}
307
308static const MemoryRegionOps ipi_ops = {
309 .read = ipi_read,
310 .write = ipi_write,
311 .endianness = DEVICE_LITTLE_ENDIAN,
312 .valid = {
313 .min_access_size = 4,
314 .max_access_size = 4,
315 },
316};
317
318static void ipi_realize(DeviceState *dev, Error **errp)
319{
320 IPI *s = XILINX_IPI(dev);
321 const char *prefix = object_get_canonical_path(OBJECT(dev));
322 unsigned int i;
323
324 for (i = 0; i < ARRAY_SIZE(ipi_regs_info); ++i) {
325 DepRegisterInfo *r = &s->regs_info[ipi_regs_info[i].decode.addr/4];
326
327 *r = (DepRegisterInfo) {
328 .data = (uint8_t *)&s->regs[
329 ipi_regs_info[i].decode.addr/4],
330 .data_size = sizeof(uint32_t),
331 .access = &ipi_regs_info[i],
332 .debug = XILINX_IPI_ERR_DEBUG,
333 .prefix = prefix,
334 .opaque = s,
335 };
336 dep_register_init(r);
337 qdev_pass_all_gpios(DEVICE(r), dev);
338 }
339
340 qdev_init_gpio_in_named(dev, ipi_handler, "IPI_INPUTS", 32);
341 qdev_init_gpio_in_named(dev, obs_handler, "OBS_INPUTS", 32);
342}
343
344static void ipi_init(Object *obj)
345{
346 IPI *s = XILINX_IPI(obj);
347 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
348
349 memory_region_init_io(&s->iomem, obj, &ipi_ops, s,
350 TYPE_XILINX_IPI, R_MAX * 4);
351 sysbus_init_mmio(sbd, &s->iomem);
352 sysbus_init_irq(sbd, &s->irq);
353}
354
355static const VMStateDescription vmstate_ipi = {
356 .name = TYPE_XILINX_IPI,
357 .version_id = 1,
358 .minimum_version_id = 1,
359 .minimum_version_id_old = 1,
360 .fields = (VMStateField[]) {
361 VMSTATE_UINT32_ARRAY(regs, IPI, R_MAX),
362 VMSTATE_END_OF_LIST(),
363 }
364};
365
366#define GPIO_FDT_TRIG_OUT(x, n) \
367 { \
368 .name = stringify(x), \
369 .fdt_index = n, \
370 }
371
372#define GPIO_FDT_OBS_OUT(x, n) \
373 { \
374 .name = "OBS_" stringify(x), \
375 .fdt_index = n, \
376 }
377
378static const FDTGenericGPIONameSet interrupt_gpios_names = {
379 .propname = "interrupt-gpios",
380 .cells_propname = "#gpio-cells",
381 .names_propname = "gpio-names",
382};
383
384static const FDTGenericGPIOSet ipi_ctrl_gpios[] = {
385 {
386 .names = &fdt_generic_gpio_name_set_gpio,
387 .gpios = (FDTGenericGPIOConnection[]) {
388 { .name = "IPI_INPUTS", .fdt_index = 0, .range = 32 },
389 { .name = "OBS_INPUTS", .fdt_index = 32, .range = 32 },
390 { },
391 },
392 },
393 { },
394};
395
396static const FDTGenericGPIOSet ipi_client_gpios[] = {
397 {
398 .names = &interrupt_gpios_names,
399 .gpios = (FDTGenericGPIOConnection[]) {
400 GPIO_FDT_TRIG_OUT(APU, 0),
401 GPIO_FDT_TRIG_OUT(RPU_0, 1),
402 GPIO_FDT_TRIG_OUT(RPU_1, 2),
403 GPIO_FDT_TRIG_OUT(PMU_0, 3),
404 GPIO_FDT_TRIG_OUT(PMU_1, 4),
405 GPIO_FDT_TRIG_OUT(PMU_2, 5),
406 GPIO_FDT_TRIG_OUT(PMU_3, 6),
407 GPIO_FDT_TRIG_OUT(PL_0, 7),
408 GPIO_FDT_TRIG_OUT(PL_1, 8),
409 GPIO_FDT_TRIG_OUT(PL_2, 9),
410 GPIO_FDT_TRIG_OUT(PL_3, 10),
411 }
412 },
413 {
414 .names = &fdt_generic_gpio_name_set_gpio,
415 .gpios = (FDTGenericGPIOConnection[]) {
416 GPIO_FDT_OBS_OUT(APU, 0),
417 GPIO_FDT_OBS_OUT(RPU_0, 1),
418 GPIO_FDT_OBS_OUT(RPU_1, 2),
419 GPIO_FDT_OBS_OUT(PMU_0, 3),
420 GPIO_FDT_OBS_OUT(PMU_1, 4),
421 GPIO_FDT_OBS_OUT(PMU_2, 5),
422 GPIO_FDT_OBS_OUT(PMU_3, 6),
423 GPIO_FDT_OBS_OUT(PL_0, 7),
424 GPIO_FDT_OBS_OUT(PL_1, 8),
425 GPIO_FDT_OBS_OUT(PL_2, 9),
426 GPIO_FDT_OBS_OUT(PL_3, 10),
427 }
428 },
429 { },
430};
431
432static void ipi_class_init(ObjectClass *klass, void *data)
433{
434 DeviceClass *dc = DEVICE_CLASS(klass);
435 FDTGenericGPIOClass *fggc = FDT_GENERIC_GPIO_CLASS(klass);
436
437 dc->reset = ipi_reset;
438 dc->realize = ipi_realize;
439 dc->vmsd = &vmstate_ipi;
440 fggc->controller_gpios = ipi_ctrl_gpios;
441 fggc->client_gpios = ipi_client_gpios;
442}
443
444static const TypeInfo ipi_info = {
445 .name = TYPE_XILINX_IPI,
446 .parent = TYPE_SYS_BUS_DEVICE,
447 .instance_size = sizeof(IPI),
448 .class_init = ipi_class_init,
449 .instance_init = ipi_init,
450 .interfaces = (InterfaceInfo[]) {
451 { TYPE_FDT_GENERIC_GPIO },
452 { }
453 },
454};
455
456static void ipi_register_types(void)
457{
458 type_register_static(&ipi_info);
459}
460
461type_init(ipi_register_types)
462