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#include "qemu/osdep.h"
27#include "hw/sysbus.h"
28#include "hw/register-dep.h"
29#include "qemu/log.h"
30#include "hw/fdt_generic_util.h"
31
32#ifndef XILINX_IO_MODULE_INTC_ERR_DEBUG
33#define XILINX_IO_MODULE_INTC_ERR_DEBUG 0
34#endif
35
36#define TYPE_XILINX_IO_MODULE_INTC "xlnx.io_intc"
37
38#define XILINX_IO_MODULE_INTC(obj) \
39 OBJECT_CHECK(XilinxIntC, (obj), TYPE_XILINX_IO_MODULE_INTC)
40
41#define DB_PRINT_L(lvl, fmt, args...) do {\
42 if (XILINX_IO_MODULE_INTC_ERR_DEBUG >= (lvl)) {\
43 qemu_log(TYPE_XILINX_IO_MODULE_INTC ": %s: " fmt, __func__, ## args);\
44 } \
45} while (0);
46
47#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
48
49
50#define R_IOM_IRQ_MODE (0x00 / 4)
51
52#define R_MAX_0 (1)
53
54#define R_IOM_IRQ_STATUS (0x00 / 4)
55#define R_IOM_IRQ_PENDING (0x04 / 4)
56#define R_IOM_IRQ_ENABLE (0x08 / 4)
57#define R_IOM_IRQ_ACK (0x0C / 4)
58
59#define IOM_IRQF_PIT1_SHIFT 3
60#define IOM_IRQF_PIT2_SHIFT 4
61#define IOM_IRQF_PIT3_SHIFT 5
62#define IOM_IRQF_PIT4_SHIFT 6
63
64#define IOM_IRQF_UART_ERR (1 << 0)
65#define IOM_IRQF_UART_TX (1 << 1)
66#define IOM_IRQF_UART_RX (1 << 2)
67#define IOM_IRQF_PIT1 (1 << IOM_IRQF_PIT1_SHIFT)
68#define IOM_IRQF_PIT2 (1 << IOM_IRQF_PIT2_SHIFT)
69#define IOM_IRQF_PIT3 (1 << IOM_IRQF_PIT3_SHIFT)
70#define IOM_IRQF_PIT4 (1 << IOM_IRQF_PIT4_SHIFT)
71#define IOM_IRQF_FIT1 (1 << 7)
72#define IOM_IRQF_FIT2 (1 << 8)
73#define IOM_IRQF_FIT3 (1 << 9)
74#define IOM_IRQF_FIT4 (1 << 10)
75#define IOM_IRQF_GPI1 (1 << 11)
76#define IOM_IRQF_GPI2 (1 << 12)
77#define IOM_IRQF_GPI3 (1 << 13)
78#define IOM_IRQF_GPI4 (1 << 14)
79#define IOM_IRQF_EXT0 (1 << 16)
80
81#define R_MAX_1 (R_IOM_IRQ_ACK + 1)
82
83#define R_IOM_IRQ_VECTOR0 (0x00 / 4)
84#define R_IOM_IRQ_VECTOR1 (0x04 / 4)
85#define R_IOM_IRQ_VECTOR2 (0x08 / 4)
86#define R_IOM_IRQ_VECTOR3 (0x0C / 4)
87#define R_IOM_IRQ_VECTOR4 (0x10 / 4)
88#define R_IOM_IRQ_VECTOR5 (0x14 / 4)
89#define R_IOM_IRQ_VECTOR6 (0x18 / 4)
90#define R_IOM_IRQ_VECTOR7 (0x1C / 4)
91#define R_IOM_IRQ_VECTOR8 (0x20 / 4)
92#define R_IOM_IRQ_VECTOR9 (0x24 / 4)
93#define R_IOM_IRQ_VECTOR10 (0x28 / 4)
94#define R_IOM_IRQ_VECTOR11 (0x2C / 4)
95#define R_IOM_IRQ_VECTOR12 (0x30 / 4)
96#define R_IOM_IRQ_VECTOR13 (0x34 / 4)
97#define R_IOM_IRQ_VECTOR14 (0x38 / 4)
98#define R_IOM_IRQ_VECTOR15 (0x3C / 4)
99#define R_IOM_IRQ_VECTOR16 (0x40 / 4)
100#define R_IOM_IRQ_VECTOR17 (0x44 / 4)
101#define R_IOM_IRQ_VECTOR18 (0x48 / 4)
102#define R_IOM_IRQ_VECTOR19 (0x4C / 4)
103#define R_IOM_IRQ_VECTOR20 (0x50 / 4)
104#define R_IOM_IRQ_VECTOR21 (0x54 / 4)
105#define R_IOM_IRQ_VECTOR22 (0x58 / 4)
106#define R_IOM_IRQ_VECTOR23 (0x5C / 4)
107#define R_IOM_IRQ_VECTOR24 (0x60 / 4)
108#define R_IOM_IRQ_VECTOR25 (0x64 / 4)
109#define R_IOM_IRQ_VECTOR26 (0x68 / 4)
110#define R_IOM_IRQ_VECTOR27 (0x6C / 4)
111#define R_IOM_IRQ_VECTOR28 (0x70 / 4)
112#define R_IOM_IRQ_VECTOR29 (0x74 / 4)
113#define R_IOM_IRQ_VECTOR30 (0x78 / 4)
114#define R_IOM_IRQ_VECTOR31 (0x7C / 4)
115
116#define R_MAX_2 (0x80 / 4)
117
118typedef struct XilinxIntC {
119 SysBusDevice parent_obj;
120 MemoryRegion iomem[3];
121 qemu_irq parent_irq;
122
123 struct {
124 bool use_ext_intr;
125 uint32_t intr_size;
126 uint32_t level_edge;
127 uint32_t positive;
128 bool has_fast;
129 uint32_t addr_width;
130 uint32_t base_vectors;
131 } cfg;
132
133 uint32_t irq_raw;
134 uint32_t irq_mode;
135 uint32_t regs[R_MAX_1];
136 uint32_t vectors[R_MAX_1];
137 DepRegisterInfo regs_info0[R_MAX_0];
138 DepRegisterInfo regs_info1[R_MAX_1];
139 DepRegisterInfo regs_info2[R_MAX_2];
140 DepRegisterInfo *regs_infos[3];
141 const char *prefix;
142
143 bool irq_output;
144} XilinxIntC;
145
146static Property xlx_iom_properties[] = {
147 DEFINE_PROP_BOOL("intc-use-ext-intr", XilinxIntC, cfg.use_ext_intr, 0),
148 DEFINE_PROP_UINT32("intc-intr-size", XilinxIntC, cfg.intr_size, 0),
149 DEFINE_PROP_UINT32("intc-level-edge", XilinxIntC, cfg.level_edge, 0),
150 DEFINE_PROP_UINT32("intc-positive", XilinxIntC, cfg.positive, 0),
151 DEFINE_PROP_BOOL("intc-has-fast", XilinxIntC, cfg.has_fast, 0),
152 DEFINE_PROP_UINT32("intc-addr-width", XilinxIntC, cfg.addr_width, 32),
153 DEFINE_PROP_UINT32("intc-base-vectors", XilinxIntC, cfg.base_vectors, 0),
154 DEFINE_PROP_END_OF_LIST(),
155};
156
157static void iom_intc_irq_ack(DepRegisterInfo *reg, uint64_t val64);
158static void iom_intc_update(DepRegisterInfo *reg, uint64_t val64);
159
160static void xlx_iom_irq_update(XilinxIntC *s)
161{
162 bool old_state = s->irq_output;
163
164 s->regs[R_IOM_IRQ_PENDING] = s->regs[R_IOM_IRQ_STATUS];
165 s->regs[R_IOM_IRQ_PENDING] &= s->regs[R_IOM_IRQ_ENABLE];
166 s->irq_output = s->regs[R_IOM_IRQ_PENDING];
167 DB_PRINT_L(s->irq_output != old_state ? 1 : 2, "Setting IRQ output = %d\n",
168 (int)s->irq_output);
169 qemu_set_irq(s->parent_irq, s->irq_output);
170}
171
172static void iom_intc_irq_ack(DepRegisterInfo *reg, uint64_t val64)
173{
174 XilinxIntC *s = XILINX_IO_MODULE_INTC(reg->opaque);
175 uint32_t val = val64;
176
177 val &= s->regs[R_IOM_IRQ_STATUS];
178 s->regs[R_IOM_IRQ_STATUS] ^= val;
179
180
181 s->regs[R_IOM_IRQ_STATUS] |= s->irq_raw & ~s->cfg.level_edge;
182
183 xlx_iom_irq_update(s);
184}
185
186static void iom_intc_update(DepRegisterInfo *reg, uint64_t val64)
187{
188 XilinxIntC *s = XILINX_IO_MODULE_INTC(reg->opaque);
189 xlx_iom_irq_update(s);
190}
191
192static const MemoryRegionOps iom_intc_ops = {
193 .read = dep_register_read_memory_le,
194 .write = dep_register_write_memory_le,
195 .endianness = DEVICE_LITTLE_ENDIAN,
196 .valid = {
197 .min_access_size = 4,
198 .max_access_size = 4,
199 },
200};
201
202static void irq_handler(void *opaque, int irq, int level)
203{
204 XilinxIntC *s = XILINX_IO_MODULE_INTC(opaque);
205 uint32_t mask = 1 << irq;
206 uint32_t flip = (~s->cfg.positive) & mask;
207 uint32_t prev = s->irq_raw;
208 uint32_t p;
209
210 s->irq_raw &= ~(1 << irq);
211 s->irq_raw |= (!!level) << irq;
212
213
214 s->irq_raw ^= flip;
215
216 DB_PRINT_L(prev ^ s->irq_raw ? 1 : 2, "Input irq %d = %d\n", irq, level);
217
218 if (s->cfg.level_edge & (1 << irq)) {
219
220 p = (prev ^ s->irq_raw) & s->irq_raw & mask;
221 } else {
222
223 p = s->irq_raw & mask;
224 }
225 s->regs[R_IOM_IRQ_STATUS] |= p;
226 xlx_iom_irq_update(s);
227}
228
229static const DepRegisterAccessInfo intc_regs_info0[] = {
230 [R_IOM_IRQ_MODE] = { .name = "IRQ_MODE" },
231};
232
233static const DepRegisterAccessInfo intc_regs_info1[] = {
234 [R_IOM_IRQ_STATUS] = { .name = "IRQ_STATUS", .ro = ~0 },
235 [R_IOM_IRQ_PENDING] = { .name = "IRQ_PENDING" , .ro = ~0 },
236 [R_IOM_IRQ_ENABLE] = { .name = "IRQ_ENABLE",
237 .post_write = iom_intc_update },
238 [R_IOM_IRQ_ACK] = { .name = "IRQ_ACK", .post_write = iom_intc_irq_ack },
239};
240
241static const DepRegisterAccessInfo intc_regs_info2[] = {
242#define REG_VECTOR(n) [R_IOM_IRQ_VECTOR ## n] = \
243 { .name = "IRQ_VECTOR" #n, \
244 .ui1 = (DepRegisterAccessError[]) { \
245 { .mask = ~0, .reason = "IRQ Vectors not implemented" }, {} } }
246
247 REG_VECTOR(0),
248 REG_VECTOR(1),
249 REG_VECTOR(2),
250 REG_VECTOR(3),
251 REG_VECTOR(4),
252 REG_VECTOR(5),
253 REG_VECTOR(6),
254 REG_VECTOR(7),
255 REG_VECTOR(8),
256 REG_VECTOR(9),
257 REG_VECTOR(10),
258 REG_VECTOR(11),
259 REG_VECTOR(12),
260 REG_VECTOR(13),
261 REG_VECTOR(14),
262 REG_VECTOR(15),
263 REG_VECTOR(16),
264 REG_VECTOR(17),
265 REG_VECTOR(18),
266 REG_VECTOR(19),
267 REG_VECTOR(20),
268 REG_VECTOR(21),
269 REG_VECTOR(22),
270 REG_VECTOR(23),
271 REG_VECTOR(24),
272 REG_VECTOR(25),
273 REG_VECTOR(26),
274 REG_VECTOR(27),
275 REG_VECTOR(28),
276 REG_VECTOR(29),
277 REG_VECTOR(30),
278 REG_VECTOR(31),
279};
280
281static const DepRegisterAccessInfo *intc_reginfos[] = {
282 &intc_regs_info0[0], &intc_regs_info1[0], &intc_regs_info2[0]
283};
284
285static const unsigned int intc_reginfo_sizes[] = {
286 ARRAY_SIZE(intc_regs_info0),
287 ARRAY_SIZE(intc_regs_info1),
288 ARRAY_SIZE(intc_regs_info2),
289};
290
291
292static void iom_intc_reset(DeviceState *dev)
293{
294 XilinxIntC *s = XILINX_IO_MODULE_INTC(dev);
295 unsigned int i;
296 unsigned int rmap;
297
298 for (rmap = 0; rmap < ARRAY_SIZE(intc_reginfos); rmap++) {
299 for (i = 0; i < intc_reginfo_sizes[rmap]; ++i) {
300 dep_register_reset(&s->regs_infos[rmap][i]);
301 }
302 }
303}
304
305static void xlx_iom_realize(DeviceState *dev, Error **errp)
306{
307 XilinxIntC *s = XILINX_IO_MODULE_INTC(dev);
308 unsigned int i;
309 unsigned int rmap;
310 uint32_t *regmaps[3] = {
311 &s->irq_mode, &s->regs[0], &s->vectors[0]
312 };
313 s->prefix = object_get_canonical_path(OBJECT(dev));
314
315 s->cfg.level_edge <<= 16;
316 s->cfg.level_edge |= 0xffff;
317
318 s->cfg.positive <<= 16;
319 s->cfg.positive |= 0xffff;
320
321 assert(s->cfg.intr_size <= 16);
322
323 for (rmap = 0; rmap < ARRAY_SIZE(intc_reginfos); rmap++) {
324 for (i = 0; i < intc_reginfo_sizes[rmap]; ++i) {
325 DepRegisterInfo *r = &s->regs_infos[rmap][i];
326
327 *r = (DepRegisterInfo) {
328 .data = (uint8_t *)®maps[rmap][i],
329 .data_size = sizeof(uint32_t),
330 .access = &intc_reginfos[rmap][i],
331 .debug = XILINX_IO_MODULE_INTC_ERR_DEBUG,
332 .prefix = s->prefix,
333 .opaque = s,
334 };
335 memory_region_init_io(&r->mem, OBJECT(dev), &iom_intc_ops, r,
336 r->access->name, 4);
337 memory_region_add_subregion(&s->iomem[rmap], i * 4, &r->mem);
338 }
339 }
340 qdev_init_gpio_in(dev, irq_handler, 16 + s->cfg.intr_size);
341}
342
343static void xlx_iom_init(Object *obj)
344{
345 XilinxIntC *s = XILINX_IO_MODULE_INTC(obj);
346 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
347 unsigned int i;
348
349 s->regs_infos[0] = s->regs_info0;
350 s->regs_infos[1] = s->regs_info1;
351 s->regs_infos[2] = s->regs_info2;
352
353 for (i = 0; i < ARRAY_SIZE(s->iomem); i++) {
354 char *region_name = g_strdup_printf("%s-%d", TYPE_XILINX_IO_MODULE_INTC,
355 i);
356 memory_region_init_io(&s->iomem[i], obj, &iom_intc_ops, s,
357 region_name, intc_reginfo_sizes[i] * 4);
358 g_free(region_name);
359 sysbus_init_mmio(sbd, &s->iomem[i]);
360 }
361 qdev_init_gpio_out(DEVICE(obj), &s->parent_irq, 1);
362}
363
364static int xilinx_iom_fdt_get_irq(FDTGenericIntc *obj, qemu_irq *irqs,
365 uint32_t *cells, int ncells, int max,
366 Error **errp)
367{
368
369 (*irqs) = qdev_get_gpio_in(DEVICE(obj), cells[0]);
370 return 1;
371};
372
373static const VMStateDescription vmstate_xlx_iom = {
374 .name = TYPE_XILINX_IO_MODULE_INTC,
375 .version_id = 1,
376 .minimum_version_id = 1,
377 .minimum_version_id_old = 1,
378 .fields = (VMStateField[]) {
379 VMSTATE_END_OF_LIST(),
380 }
381};
382
383static void xlx_iom_class_init(ObjectClass *klass, void *data)
384{
385 DeviceClass *dc = DEVICE_CLASS(klass);
386 FDTGenericIntcClass *fgic = FDT_GENERIC_INTC_CLASS(klass);
387
388 dc->reset = iom_intc_reset;
389 dc->realize = xlx_iom_realize;
390 dc->props = xlx_iom_properties;
391 dc->vmsd = &vmstate_xlx_iom;
392 fgic->get_irq = xilinx_iom_fdt_get_irq;
393}
394
395static const TypeInfo xlx_iom_info = {
396 .name = TYPE_XILINX_IO_MODULE_INTC,
397 .parent = TYPE_SYS_BUS_DEVICE,
398 .instance_size = sizeof(XilinxIntC),
399 .class_init = xlx_iom_class_init,
400 .instance_init = xlx_iom_init,
401 .interfaces = (InterfaceInfo[]) {
402 { TYPE_FDT_GENERIC_INTC },
403 { }
404 },
405};
406
407static void xlx_iom_register_types(void)
408{
409 type_register_static(&xlx_iom_info);
410}
411
412type_init(xlx_iom_register_types)
413