xref: /qemu/hw/intc/aspeed_vic.c (revision 0c69996e22e22b85d2e2cdb98e7be5dd83ec5113)
1*0c69996eSAndrew Jeffery /*
2*0c69996eSAndrew Jeffery  * ASPEED Interrupt Controller (New)
3*0c69996eSAndrew Jeffery  *
4*0c69996eSAndrew Jeffery  * Andrew Jeffery <andrew@aj.id.au>
5*0c69996eSAndrew Jeffery  *
6*0c69996eSAndrew Jeffery  * Copyright 2015, 2016 IBM Corp.
7*0c69996eSAndrew Jeffery  *
8*0c69996eSAndrew Jeffery  * This code is licensed under the GPL version 2 or later.  See
9*0c69996eSAndrew Jeffery  * the COPYING file in the top-level directory.
10*0c69996eSAndrew Jeffery  */
11*0c69996eSAndrew Jeffery 
12*0c69996eSAndrew Jeffery /* The hardware exposes two register sets, a legacy set and a 'new' set. The
13*0c69996eSAndrew Jeffery  * model implements the 'new' register set, and logs warnings on accesses to
14*0c69996eSAndrew Jeffery  * the legacy IO space.
15*0c69996eSAndrew Jeffery  *
16*0c69996eSAndrew Jeffery  * The hardware uses 32bit registers to manage 51 IRQs, with low and high
17*0c69996eSAndrew Jeffery  * registers for each conceptual register. The device model's implementation
18*0c69996eSAndrew Jeffery  * uses 64bit data types to store both low and high register values (in the one
19*0c69996eSAndrew Jeffery  * member), but must cope with access offset values in multiples of 4 passed to
20*0c69996eSAndrew Jeffery  * the callbacks. As such the read() and write() implementations process the
21*0c69996eSAndrew Jeffery  * provided offset to understand whether the access is requesting the lower or
22*0c69996eSAndrew Jeffery  * upper 32 bits of the 64bit member.
23*0c69996eSAndrew Jeffery  *
24*0c69996eSAndrew Jeffery  * Additionally, the "Interrupt Enable", "Edge Status" and "Software Interrupt"
25*0c69996eSAndrew Jeffery  * fields have separate "enable"/"status" and "clear" registers, where set bits
26*0c69996eSAndrew Jeffery  * are written to one or the other to change state (avoiding a
27*0c69996eSAndrew Jeffery  * read-modify-write sequence).
28*0c69996eSAndrew Jeffery  */
29*0c69996eSAndrew Jeffery 
30*0c69996eSAndrew Jeffery #include "qemu/osdep.h"
31*0c69996eSAndrew Jeffery #include <inttypes.h>
32*0c69996eSAndrew Jeffery #include "hw/intc/aspeed_vic.h"
33*0c69996eSAndrew Jeffery #include "qemu/bitops.h"
34*0c69996eSAndrew Jeffery #include "trace.h"
35*0c69996eSAndrew Jeffery 
36*0c69996eSAndrew Jeffery #define AVIC_NEW_BASE_OFFSET 0x80
37*0c69996eSAndrew Jeffery 
38*0c69996eSAndrew Jeffery #define AVIC_L_MASK 0xFFFFFFFFU
39*0c69996eSAndrew Jeffery #define AVIC_H_MASK 0x0007FFFFU
40*0c69996eSAndrew Jeffery #define AVIC_EVENT_W_MASK (0x78000ULL << 32)
41*0c69996eSAndrew Jeffery 
42*0c69996eSAndrew Jeffery static void aspeed_vic_update(AspeedVICState *s)
43*0c69996eSAndrew Jeffery {
44*0c69996eSAndrew Jeffery     uint64_t new = (s->raw & s->enable);
45*0c69996eSAndrew Jeffery     uint64_t flags;
46*0c69996eSAndrew Jeffery 
47*0c69996eSAndrew Jeffery     flags = new & s->select;
48*0c69996eSAndrew Jeffery     trace_aspeed_vic_update_fiq(!!flags);
49*0c69996eSAndrew Jeffery     qemu_set_irq(s->fiq, !!flags);
50*0c69996eSAndrew Jeffery 
51*0c69996eSAndrew Jeffery     flags = new & ~s->select;
52*0c69996eSAndrew Jeffery     trace_aspeed_vic_update_irq(!!flags);
53*0c69996eSAndrew Jeffery     qemu_set_irq(s->irq, !!flags);
54*0c69996eSAndrew Jeffery }
55*0c69996eSAndrew Jeffery 
56*0c69996eSAndrew Jeffery static void aspeed_vic_set_irq(void *opaque, int irq, int level)
57*0c69996eSAndrew Jeffery {
58*0c69996eSAndrew Jeffery     uint64_t irq_mask;
59*0c69996eSAndrew Jeffery     bool raise;
60*0c69996eSAndrew Jeffery     AspeedVICState *s = (AspeedVICState *)opaque;
61*0c69996eSAndrew Jeffery 
62*0c69996eSAndrew Jeffery     if (irq > ASPEED_VIC_NR_IRQS) {
63*0c69996eSAndrew Jeffery         qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
64*0c69996eSAndrew Jeffery                       __func__, irq);
65*0c69996eSAndrew Jeffery         return;
66*0c69996eSAndrew Jeffery     }
67*0c69996eSAndrew Jeffery 
68*0c69996eSAndrew Jeffery     trace_aspeed_vic_set_irq(irq, level);
69*0c69996eSAndrew Jeffery 
70*0c69996eSAndrew Jeffery     irq_mask = BIT(irq);
71*0c69996eSAndrew Jeffery     if (s->sense & irq_mask) {
72*0c69996eSAndrew Jeffery         /* level-triggered */
73*0c69996eSAndrew Jeffery         if (s->event & irq_mask) {
74*0c69996eSAndrew Jeffery             /* high-sensitive */
75*0c69996eSAndrew Jeffery             raise = level;
76*0c69996eSAndrew Jeffery         } else {
77*0c69996eSAndrew Jeffery             /* low-sensitive */
78*0c69996eSAndrew Jeffery             raise = !level;
79*0c69996eSAndrew Jeffery         }
80*0c69996eSAndrew Jeffery         s->raw = deposit64(s->raw, irq, 1, raise);
81*0c69996eSAndrew Jeffery     } else {
82*0c69996eSAndrew Jeffery         uint64_t old_level = s->level & irq_mask;
83*0c69996eSAndrew Jeffery 
84*0c69996eSAndrew Jeffery         /* edge-triggered */
85*0c69996eSAndrew Jeffery         if (s->dual_edge & irq_mask) {
86*0c69996eSAndrew Jeffery             raise = (!!old_level) != (!!level);
87*0c69996eSAndrew Jeffery         } else {
88*0c69996eSAndrew Jeffery             if (s->event & irq_mask) {
89*0c69996eSAndrew Jeffery                 /* rising-sensitive */
90*0c69996eSAndrew Jeffery                 raise = !old_level && level;
91*0c69996eSAndrew Jeffery             } else {
92*0c69996eSAndrew Jeffery                 /* falling-sensitive */
93*0c69996eSAndrew Jeffery                 raise = old_level && !level;
94*0c69996eSAndrew Jeffery             }
95*0c69996eSAndrew Jeffery         }
96*0c69996eSAndrew Jeffery         if (raise) {
97*0c69996eSAndrew Jeffery             s->raw = deposit64(s->raw, irq, 1, raise);
98*0c69996eSAndrew Jeffery         }
99*0c69996eSAndrew Jeffery     }
100*0c69996eSAndrew Jeffery     s->level = deposit64(s->level, irq, 1, level);
101*0c69996eSAndrew Jeffery     aspeed_vic_update(s);
102*0c69996eSAndrew Jeffery }
103*0c69996eSAndrew Jeffery 
104*0c69996eSAndrew Jeffery static uint64_t aspeed_vic_read(void *opaque, hwaddr offset, unsigned size)
105*0c69996eSAndrew Jeffery {
106*0c69996eSAndrew Jeffery     uint64_t val;
107*0c69996eSAndrew Jeffery     const bool high = !!(offset & 0x4);
108*0c69996eSAndrew Jeffery     hwaddr n_offset = (offset & ~0x4);
109*0c69996eSAndrew Jeffery     AspeedVICState *s = (AspeedVICState *)opaque;
110*0c69996eSAndrew Jeffery 
111*0c69996eSAndrew Jeffery     if (offset < AVIC_NEW_BASE_OFFSET) {
112*0c69996eSAndrew Jeffery         qemu_log_mask(LOG_UNIMP, "%s: Ignoring read from legacy registers "
113*0c69996eSAndrew Jeffery                       "at 0x%" HWADDR_PRIx "[%u]\n", __func__, offset, size);
114*0c69996eSAndrew Jeffery         return 0;
115*0c69996eSAndrew Jeffery     }
116*0c69996eSAndrew Jeffery 
117*0c69996eSAndrew Jeffery     n_offset -= AVIC_NEW_BASE_OFFSET;
118*0c69996eSAndrew Jeffery 
119*0c69996eSAndrew Jeffery     switch (n_offset) {
120*0c69996eSAndrew Jeffery     case 0x0: /* IRQ Status */
121*0c69996eSAndrew Jeffery         val = s->raw & ~s->select & s->enable;
122*0c69996eSAndrew Jeffery         break;
123*0c69996eSAndrew Jeffery     case 0x08: /* FIQ Status */
124*0c69996eSAndrew Jeffery         val = s->raw & s->select & s->enable;
125*0c69996eSAndrew Jeffery         break;
126*0c69996eSAndrew Jeffery     case 0x10: /* Raw Interrupt Status */
127*0c69996eSAndrew Jeffery         val = s->raw;
128*0c69996eSAndrew Jeffery         break;
129*0c69996eSAndrew Jeffery     case 0x18: /* Interrupt Selection */
130*0c69996eSAndrew Jeffery         val = s->select;
131*0c69996eSAndrew Jeffery         break;
132*0c69996eSAndrew Jeffery     case 0x20: /* Interrupt Enable */
133*0c69996eSAndrew Jeffery         val = s->enable;
134*0c69996eSAndrew Jeffery         break;
135*0c69996eSAndrew Jeffery     case 0x30: /* Software Interrupt */
136*0c69996eSAndrew Jeffery         val = s->trigger;
137*0c69996eSAndrew Jeffery         break;
138*0c69996eSAndrew Jeffery     case 0x40: /* Interrupt Sensitivity */
139*0c69996eSAndrew Jeffery         val = s->sense;
140*0c69996eSAndrew Jeffery         break;
141*0c69996eSAndrew Jeffery     case 0x48: /* Interrupt Both Edge Trigger Control */
142*0c69996eSAndrew Jeffery         val = s->dual_edge;
143*0c69996eSAndrew Jeffery         break;
144*0c69996eSAndrew Jeffery     case 0x50: /* Interrupt Event */
145*0c69996eSAndrew Jeffery         val = s->event;
146*0c69996eSAndrew Jeffery         break;
147*0c69996eSAndrew Jeffery     case 0x60: /* Edge Triggered Interrupt Status */
148*0c69996eSAndrew Jeffery         val = s->raw & ~s->sense;
149*0c69996eSAndrew Jeffery         break;
150*0c69996eSAndrew Jeffery         /* Illegal */
151*0c69996eSAndrew Jeffery     case 0x28: /* Interrupt Enable Clear */
152*0c69996eSAndrew Jeffery     case 0x38: /* Software Interrupt Clear */
153*0c69996eSAndrew Jeffery     case 0x58: /* Edge Triggered Interrupt Clear */
154*0c69996eSAndrew Jeffery         qemu_log_mask(LOG_GUEST_ERROR,
155*0c69996eSAndrew Jeffery                       "%s: Read of write-only register with offset 0x%"
156*0c69996eSAndrew Jeffery                       HWADDR_PRIx "\n", __func__, offset);
157*0c69996eSAndrew Jeffery         val = 0;
158*0c69996eSAndrew Jeffery         break;
159*0c69996eSAndrew Jeffery     default:
160*0c69996eSAndrew Jeffery         qemu_log_mask(LOG_GUEST_ERROR,
161*0c69996eSAndrew Jeffery                       "%s: Bad register at offset 0x%" HWADDR_PRIx "\n",
162*0c69996eSAndrew Jeffery                       __func__, offset);
163*0c69996eSAndrew Jeffery         val = 0;
164*0c69996eSAndrew Jeffery         break;
165*0c69996eSAndrew Jeffery     }
166*0c69996eSAndrew Jeffery     if (high) {
167*0c69996eSAndrew Jeffery         val = extract64(val, 32, 19);
168*0c69996eSAndrew Jeffery     }
169*0c69996eSAndrew Jeffery     trace_aspeed_vic_read(offset, size, val);
170*0c69996eSAndrew Jeffery     return val;
171*0c69996eSAndrew Jeffery }
172*0c69996eSAndrew Jeffery 
173*0c69996eSAndrew Jeffery static void aspeed_vic_write(void *opaque, hwaddr offset, uint64_t data,
174*0c69996eSAndrew Jeffery                              unsigned size)
175*0c69996eSAndrew Jeffery {
176*0c69996eSAndrew Jeffery     const bool high = !!(offset & 0x4);
177*0c69996eSAndrew Jeffery     hwaddr n_offset = (offset & ~0x4);
178*0c69996eSAndrew Jeffery     AspeedVICState *s = (AspeedVICState *)opaque;
179*0c69996eSAndrew Jeffery 
180*0c69996eSAndrew Jeffery     if (offset < AVIC_NEW_BASE_OFFSET) {
181*0c69996eSAndrew Jeffery         qemu_log_mask(LOG_UNIMP,
182*0c69996eSAndrew Jeffery                       "%s: Ignoring write to legacy registers at 0x%"
183*0c69996eSAndrew Jeffery                       HWADDR_PRIx "[%u] <- 0x%" PRIx64 "\n", __func__, offset,
184*0c69996eSAndrew Jeffery                       size, data);
185*0c69996eSAndrew Jeffery         return;
186*0c69996eSAndrew Jeffery     }
187*0c69996eSAndrew Jeffery 
188*0c69996eSAndrew Jeffery     n_offset -= AVIC_NEW_BASE_OFFSET;
189*0c69996eSAndrew Jeffery     trace_aspeed_vic_write(offset, size, data);
190*0c69996eSAndrew Jeffery 
191*0c69996eSAndrew Jeffery     /* Given we have members using separate enable/clear registers, deposit64()
192*0c69996eSAndrew Jeffery      * isn't quite the tool for the job. Instead, relocate the incoming bits to
193*0c69996eSAndrew Jeffery      * the required bit offset based on the provided access address
194*0c69996eSAndrew Jeffery      */
195*0c69996eSAndrew Jeffery     if (high) {
196*0c69996eSAndrew Jeffery         data &= AVIC_H_MASK;
197*0c69996eSAndrew Jeffery         data <<= 32;
198*0c69996eSAndrew Jeffery     } else {
199*0c69996eSAndrew Jeffery         data &= AVIC_L_MASK;
200*0c69996eSAndrew Jeffery     }
201*0c69996eSAndrew Jeffery 
202*0c69996eSAndrew Jeffery     switch (n_offset) {
203*0c69996eSAndrew Jeffery     case 0x18: /* Interrupt Selection */
204*0c69996eSAndrew Jeffery         /* Register has deposit64() semantics - overwrite requested 32 bits */
205*0c69996eSAndrew Jeffery         if (high) {
206*0c69996eSAndrew Jeffery             s->select &= AVIC_L_MASK;
207*0c69996eSAndrew Jeffery         } else {
208*0c69996eSAndrew Jeffery             s->select &= ((uint64_t) AVIC_H_MASK) << 32;
209*0c69996eSAndrew Jeffery         }
210*0c69996eSAndrew Jeffery         s->select |= data;
211*0c69996eSAndrew Jeffery         break;
212*0c69996eSAndrew Jeffery     case 0x20: /* Interrupt Enable */
213*0c69996eSAndrew Jeffery         s->enable |= data;
214*0c69996eSAndrew Jeffery         break;
215*0c69996eSAndrew Jeffery     case 0x28: /* Interrupt Enable Clear */
216*0c69996eSAndrew Jeffery         s->enable &= ~data;
217*0c69996eSAndrew Jeffery         break;
218*0c69996eSAndrew Jeffery     case 0x30: /* Software Interrupt */
219*0c69996eSAndrew Jeffery         qemu_log_mask(LOG_UNIMP, "%s: Software interrupts unavailable. "
220*0c69996eSAndrew Jeffery                       "IRQs requested: 0x%016" PRIx64 "\n", __func__, data);
221*0c69996eSAndrew Jeffery         break;
222*0c69996eSAndrew Jeffery     case 0x38: /* Software Interrupt Clear */
223*0c69996eSAndrew Jeffery         qemu_log_mask(LOG_UNIMP, "%s: Software interrupts unavailable. "
224*0c69996eSAndrew Jeffery                       "IRQs to be cleared: 0x%016" PRIx64 "\n", __func__, data);
225*0c69996eSAndrew Jeffery         break;
226*0c69996eSAndrew Jeffery     case 0x50: /* Interrupt Event */
227*0c69996eSAndrew Jeffery         /* Register has deposit64() semantics - overwrite the top four valid
228*0c69996eSAndrew Jeffery          * IRQ bits, as only the top four IRQs (GPIOs) can change their event
229*0c69996eSAndrew Jeffery          * type */
230*0c69996eSAndrew Jeffery         if (high) {
231*0c69996eSAndrew Jeffery             s->event &= ~AVIC_EVENT_W_MASK;
232*0c69996eSAndrew Jeffery             s->event |= (data & AVIC_EVENT_W_MASK);
233*0c69996eSAndrew Jeffery         } else {
234*0c69996eSAndrew Jeffery             qemu_log_mask(LOG_GUEST_ERROR,
235*0c69996eSAndrew Jeffery                           "Ignoring invalid write to interrupt event register");
236*0c69996eSAndrew Jeffery         }
237*0c69996eSAndrew Jeffery         break;
238*0c69996eSAndrew Jeffery     case 0x58: /* Edge Triggered Interrupt Clear */
239*0c69996eSAndrew Jeffery         s->raw &= ~(data & ~s->sense);
240*0c69996eSAndrew Jeffery         break;
241*0c69996eSAndrew Jeffery     case 0x00: /* IRQ Status */
242*0c69996eSAndrew Jeffery     case 0x08: /* FIQ Status */
243*0c69996eSAndrew Jeffery     case 0x10: /* Raw Interrupt Status */
244*0c69996eSAndrew Jeffery     case 0x40: /* Interrupt Sensitivity */
245*0c69996eSAndrew Jeffery     case 0x48: /* Interrupt Both Edge Trigger Control */
246*0c69996eSAndrew Jeffery     case 0x60: /* Edge Triggered Interrupt Status */
247*0c69996eSAndrew Jeffery         qemu_log_mask(LOG_GUEST_ERROR,
248*0c69996eSAndrew Jeffery                       "%s: Write of read-only register with offset 0x%"
249*0c69996eSAndrew Jeffery                       HWADDR_PRIx "\n", __func__, offset);
250*0c69996eSAndrew Jeffery         break;
251*0c69996eSAndrew Jeffery 
252*0c69996eSAndrew Jeffery     default:
253*0c69996eSAndrew Jeffery         qemu_log_mask(LOG_GUEST_ERROR,
254*0c69996eSAndrew Jeffery                       "%s: Bad register at offset 0x%" HWADDR_PRIx "\n",
255*0c69996eSAndrew Jeffery                       __func__, offset);
256*0c69996eSAndrew Jeffery         break;
257*0c69996eSAndrew Jeffery     }
258*0c69996eSAndrew Jeffery     aspeed_vic_update(s);
259*0c69996eSAndrew Jeffery }
260*0c69996eSAndrew Jeffery 
261*0c69996eSAndrew Jeffery static const MemoryRegionOps aspeed_vic_ops = {
262*0c69996eSAndrew Jeffery     .read = aspeed_vic_read,
263*0c69996eSAndrew Jeffery     .write = aspeed_vic_write,
264*0c69996eSAndrew Jeffery     .endianness = DEVICE_LITTLE_ENDIAN,
265*0c69996eSAndrew Jeffery     .valid.min_access_size = 4,
266*0c69996eSAndrew Jeffery     .valid.max_access_size = 4,
267*0c69996eSAndrew Jeffery     .valid.unaligned = false,
268*0c69996eSAndrew Jeffery };
269*0c69996eSAndrew Jeffery 
270*0c69996eSAndrew Jeffery static void aspeed_vic_reset(DeviceState *dev)
271*0c69996eSAndrew Jeffery {
272*0c69996eSAndrew Jeffery     AspeedVICState *s = ASPEED_VIC(dev);
273*0c69996eSAndrew Jeffery 
274*0c69996eSAndrew Jeffery     s->level = 0;
275*0c69996eSAndrew Jeffery     s->raw = 0;
276*0c69996eSAndrew Jeffery     s->select = 0;
277*0c69996eSAndrew Jeffery     s->enable = 0;
278*0c69996eSAndrew Jeffery     s->trigger = 0;
279*0c69996eSAndrew Jeffery     s->sense = 0x1F07FFF8FFFFULL;
280*0c69996eSAndrew Jeffery     s->dual_edge = 0xF800070000ULL;
281*0c69996eSAndrew Jeffery     s->event = 0x5F07FFF8FFFFULL;
282*0c69996eSAndrew Jeffery }
283*0c69996eSAndrew Jeffery 
284*0c69996eSAndrew Jeffery #define AVIC_IO_REGION_SIZE 0x20000
285*0c69996eSAndrew Jeffery 
286*0c69996eSAndrew Jeffery static void aspeed_vic_realize(DeviceState *dev, Error **errp)
287*0c69996eSAndrew Jeffery {
288*0c69996eSAndrew Jeffery     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
289*0c69996eSAndrew Jeffery     AspeedVICState *s = ASPEED_VIC(dev);
290*0c69996eSAndrew Jeffery 
291*0c69996eSAndrew Jeffery     memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_vic_ops, s,
292*0c69996eSAndrew Jeffery                           TYPE_ASPEED_VIC, AVIC_IO_REGION_SIZE);
293*0c69996eSAndrew Jeffery 
294*0c69996eSAndrew Jeffery     sysbus_init_mmio(sbd, &s->iomem);
295*0c69996eSAndrew Jeffery 
296*0c69996eSAndrew Jeffery     qdev_init_gpio_in(dev, aspeed_vic_set_irq, ASPEED_VIC_NR_IRQS);
297*0c69996eSAndrew Jeffery     sysbus_init_irq(sbd, &s->irq);
298*0c69996eSAndrew Jeffery     sysbus_init_irq(sbd, &s->fiq);
299*0c69996eSAndrew Jeffery }
300*0c69996eSAndrew Jeffery 
301*0c69996eSAndrew Jeffery static const VMStateDescription vmstate_aspeed_vic = {
302*0c69996eSAndrew Jeffery     .name = "aspeed.new-vic",
303*0c69996eSAndrew Jeffery     .version_id = 1,
304*0c69996eSAndrew Jeffery     .minimum_version_id = 1,
305*0c69996eSAndrew Jeffery     .fields = (VMStateField[]) {
306*0c69996eSAndrew Jeffery         VMSTATE_UINT64(level, AspeedVICState),
307*0c69996eSAndrew Jeffery         VMSTATE_UINT64(raw, AspeedVICState),
308*0c69996eSAndrew Jeffery         VMSTATE_UINT64(select, AspeedVICState),
309*0c69996eSAndrew Jeffery         VMSTATE_UINT64(enable, AspeedVICState),
310*0c69996eSAndrew Jeffery         VMSTATE_UINT64(trigger, AspeedVICState),
311*0c69996eSAndrew Jeffery         VMSTATE_UINT64(sense, AspeedVICState),
312*0c69996eSAndrew Jeffery         VMSTATE_UINT64(dual_edge, AspeedVICState),
313*0c69996eSAndrew Jeffery         VMSTATE_UINT64(event, AspeedVICState),
314*0c69996eSAndrew Jeffery         VMSTATE_END_OF_LIST()
315*0c69996eSAndrew Jeffery     }
316*0c69996eSAndrew Jeffery };
317*0c69996eSAndrew Jeffery 
318*0c69996eSAndrew Jeffery static void aspeed_vic_class_init(ObjectClass *klass, void *data)
319*0c69996eSAndrew Jeffery {
320*0c69996eSAndrew Jeffery     DeviceClass *dc = DEVICE_CLASS(klass);
321*0c69996eSAndrew Jeffery     dc->realize = aspeed_vic_realize;
322*0c69996eSAndrew Jeffery     dc->reset = aspeed_vic_reset;
323*0c69996eSAndrew Jeffery     dc->desc = "ASPEED Interrupt Controller (New)";
324*0c69996eSAndrew Jeffery     dc->vmsd = &vmstate_aspeed_vic;
325*0c69996eSAndrew Jeffery }
326*0c69996eSAndrew Jeffery 
327*0c69996eSAndrew Jeffery static const TypeInfo aspeed_vic_info = {
328*0c69996eSAndrew Jeffery     .name = TYPE_ASPEED_VIC,
329*0c69996eSAndrew Jeffery     .parent = TYPE_SYS_BUS_DEVICE,
330*0c69996eSAndrew Jeffery     .instance_size = sizeof(AspeedVICState),
331*0c69996eSAndrew Jeffery     .class_init = aspeed_vic_class_init,
332*0c69996eSAndrew Jeffery };
333*0c69996eSAndrew Jeffery 
334*0c69996eSAndrew Jeffery static void aspeed_vic_register_types(void)
335*0c69996eSAndrew Jeffery {
336*0c69996eSAndrew Jeffery     type_register_static(&aspeed_vic_info);
337*0c69996eSAndrew Jeffery }
338*0c69996eSAndrew Jeffery 
339*0c69996eSAndrew Jeffery type_init(aspeed_vic_register_types);
340