10c69996eSAndrew Jeffery /*
20c69996eSAndrew Jeffery * ASPEED Interrupt Controller (New)
30c69996eSAndrew Jeffery *
40c69996eSAndrew Jeffery * Andrew Jeffery <andrew@aj.id.au>
50c69996eSAndrew Jeffery *
60c69996eSAndrew Jeffery * Copyright 2015, 2016 IBM Corp.
70c69996eSAndrew Jeffery *
80c69996eSAndrew Jeffery * This code is licensed under the GPL version 2 or later. See
90c69996eSAndrew Jeffery * the COPYING file in the top-level directory.
100c69996eSAndrew Jeffery */
110c69996eSAndrew Jeffery
120c69996eSAndrew Jeffery /* The hardware exposes two register sets, a legacy set and a 'new' set. The
130c69996eSAndrew Jeffery * model implements the 'new' register set, and logs warnings on accesses to
140c69996eSAndrew Jeffery * the legacy IO space.
150c69996eSAndrew Jeffery *
160c69996eSAndrew Jeffery * The hardware uses 32bit registers to manage 51 IRQs, with low and high
170c69996eSAndrew Jeffery * registers for each conceptual register. The device model's implementation
180c69996eSAndrew Jeffery * uses 64bit data types to store both low and high register values (in the one
190c69996eSAndrew Jeffery * member), but must cope with access offset values in multiples of 4 passed to
200c69996eSAndrew Jeffery * the callbacks. As such the read() and write() implementations process the
210c69996eSAndrew Jeffery * provided offset to understand whether the access is requesting the lower or
220c69996eSAndrew Jeffery * upper 32 bits of the 64bit member.
230c69996eSAndrew Jeffery *
240c69996eSAndrew Jeffery * Additionally, the "Interrupt Enable", "Edge Status" and "Software Interrupt"
250c69996eSAndrew Jeffery * fields have separate "enable"/"status" and "clear" registers, where set bits
260c69996eSAndrew Jeffery * are written to one or the other to change state (avoiding a
270c69996eSAndrew Jeffery * read-modify-write sequence).
280c69996eSAndrew Jeffery */
290c69996eSAndrew Jeffery
300c69996eSAndrew Jeffery #include "qemu/osdep.h"
310c69996eSAndrew Jeffery #include "hw/intc/aspeed_vic.h"
3264552b6bSMarkus Armbruster #include "hw/irq.h"
33d6454270SMarkus Armbruster #include "migration/vmstate.h"
340c69996eSAndrew Jeffery #include "qemu/bitops.h"
3522b31af2SPaolo Bonzini #include "qemu/log.h"
360b8fa32fSMarkus Armbruster #include "qemu/module.h"
370c69996eSAndrew Jeffery #include "trace.h"
380c69996eSAndrew Jeffery
390c69996eSAndrew Jeffery #define AVIC_NEW_BASE_OFFSET 0x80
400c69996eSAndrew Jeffery
410c69996eSAndrew Jeffery #define AVIC_L_MASK 0xFFFFFFFFU
420c69996eSAndrew Jeffery #define AVIC_H_MASK 0x0007FFFFU
430c69996eSAndrew Jeffery #define AVIC_EVENT_W_MASK (0x78000ULL << 32)
440c69996eSAndrew Jeffery
aspeed_vic_update(AspeedVICState * s)450c69996eSAndrew Jeffery static void aspeed_vic_update(AspeedVICState *s)
460c69996eSAndrew Jeffery {
470c69996eSAndrew Jeffery uint64_t new = (s->raw & s->enable);
480c69996eSAndrew Jeffery uint64_t flags;
490c69996eSAndrew Jeffery
500c69996eSAndrew Jeffery flags = new & s->select;
510c69996eSAndrew Jeffery trace_aspeed_vic_update_fiq(!!flags);
520c69996eSAndrew Jeffery qemu_set_irq(s->fiq, !!flags);
530c69996eSAndrew Jeffery
540c69996eSAndrew Jeffery flags = new & ~s->select;
550c69996eSAndrew Jeffery trace_aspeed_vic_update_irq(!!flags);
560c69996eSAndrew Jeffery qemu_set_irq(s->irq, !!flags);
570c69996eSAndrew Jeffery }
580c69996eSAndrew Jeffery
aspeed_vic_set_irq(void * opaque,int irq,int level)590c69996eSAndrew Jeffery static void aspeed_vic_set_irq(void *opaque, int irq, int level)
600c69996eSAndrew Jeffery {
610c69996eSAndrew Jeffery uint64_t irq_mask;
620c69996eSAndrew Jeffery bool raise;
630c69996eSAndrew Jeffery AspeedVICState *s = (AspeedVICState *)opaque;
640c69996eSAndrew Jeffery
650c69996eSAndrew Jeffery if (irq > ASPEED_VIC_NR_IRQS) {
660c69996eSAndrew Jeffery qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid interrupt number: %d\n",
670c69996eSAndrew Jeffery __func__, irq);
680c69996eSAndrew Jeffery return;
690c69996eSAndrew Jeffery }
700c69996eSAndrew Jeffery
710c69996eSAndrew Jeffery trace_aspeed_vic_set_irq(irq, level);
720c69996eSAndrew Jeffery
730c69996eSAndrew Jeffery irq_mask = BIT(irq);
740c69996eSAndrew Jeffery if (s->sense & irq_mask) {
750c69996eSAndrew Jeffery /* level-triggered */
760c69996eSAndrew Jeffery if (s->event & irq_mask) {
770c69996eSAndrew Jeffery /* high-sensitive */
780c69996eSAndrew Jeffery raise = level;
790c69996eSAndrew Jeffery } else {
800c69996eSAndrew Jeffery /* low-sensitive */
810c69996eSAndrew Jeffery raise = !level;
820c69996eSAndrew Jeffery }
830c69996eSAndrew Jeffery s->raw = deposit64(s->raw, irq, 1, raise);
840c69996eSAndrew Jeffery } else {
850c69996eSAndrew Jeffery uint64_t old_level = s->level & irq_mask;
860c69996eSAndrew Jeffery
870c69996eSAndrew Jeffery /* edge-triggered */
880c69996eSAndrew Jeffery if (s->dual_edge & irq_mask) {
890c69996eSAndrew Jeffery raise = (!!old_level) != (!!level);
900c69996eSAndrew Jeffery } else {
910c69996eSAndrew Jeffery if (s->event & irq_mask) {
920c69996eSAndrew Jeffery /* rising-sensitive */
930c69996eSAndrew Jeffery raise = !old_level && level;
940c69996eSAndrew Jeffery } else {
950c69996eSAndrew Jeffery /* falling-sensitive */
960c69996eSAndrew Jeffery raise = old_level && !level;
970c69996eSAndrew Jeffery }
980c69996eSAndrew Jeffery }
990c69996eSAndrew Jeffery if (raise) {
1000c69996eSAndrew Jeffery s->raw = deposit64(s->raw, irq, 1, raise);
1010c69996eSAndrew Jeffery }
1020c69996eSAndrew Jeffery }
1030c69996eSAndrew Jeffery s->level = deposit64(s->level, irq, 1, level);
1040c69996eSAndrew Jeffery aspeed_vic_update(s);
1050c69996eSAndrew Jeffery }
1060c69996eSAndrew Jeffery
aspeed_vic_read(void * opaque,hwaddr offset,unsigned size)1070c69996eSAndrew Jeffery static uint64_t aspeed_vic_read(void *opaque, hwaddr offset, unsigned size)
1080c69996eSAndrew Jeffery {
1090c69996eSAndrew Jeffery AspeedVICState *s = (AspeedVICState *)opaque;
110ebd205c0SAndrew Jeffery hwaddr n_offset;
111ebd205c0SAndrew Jeffery uint64_t val;
112ebd205c0SAndrew Jeffery bool high;
1130c69996eSAndrew Jeffery
1140c69996eSAndrew Jeffery if (offset < AVIC_NEW_BASE_OFFSET) {
115ebd205c0SAndrew Jeffery high = false;
116ebd205c0SAndrew Jeffery n_offset = offset;
117ebd205c0SAndrew Jeffery } else {
118ebd205c0SAndrew Jeffery high = !!(offset & 0x4);
119ebd205c0SAndrew Jeffery n_offset = (offset & ~0x4);
1200c69996eSAndrew Jeffery }
1210c69996eSAndrew Jeffery
1220c69996eSAndrew Jeffery switch (n_offset) {
123ebd205c0SAndrew Jeffery case 0x80: /* IRQ Status */
124ebd205c0SAndrew Jeffery case 0x00:
1250c69996eSAndrew Jeffery val = s->raw & ~s->select & s->enable;
1260c69996eSAndrew Jeffery break;
127ebd205c0SAndrew Jeffery case 0x88: /* FIQ Status */
128ebd205c0SAndrew Jeffery case 0x04:
1290c69996eSAndrew Jeffery val = s->raw & s->select & s->enable;
1300c69996eSAndrew Jeffery break;
131ebd205c0SAndrew Jeffery case 0x90: /* Raw Interrupt Status */
132ebd205c0SAndrew Jeffery case 0x08:
1330c69996eSAndrew Jeffery val = s->raw;
1340c69996eSAndrew Jeffery break;
135ebd205c0SAndrew Jeffery case 0x98: /* Interrupt Selection */
136ebd205c0SAndrew Jeffery case 0x0c:
1370c69996eSAndrew Jeffery val = s->select;
1380c69996eSAndrew Jeffery break;
139ebd205c0SAndrew Jeffery case 0xa0: /* Interrupt Enable */
140ebd205c0SAndrew Jeffery case 0x10:
1410c69996eSAndrew Jeffery val = s->enable;
1420c69996eSAndrew Jeffery break;
143ebd205c0SAndrew Jeffery case 0xb0: /* Software Interrupt */
144ebd205c0SAndrew Jeffery case 0x18:
1450c69996eSAndrew Jeffery val = s->trigger;
1460c69996eSAndrew Jeffery break;
147ebd205c0SAndrew Jeffery case 0xc0: /* Interrupt Sensitivity */
148ebd205c0SAndrew Jeffery case 0x24:
1490c69996eSAndrew Jeffery val = s->sense;
1500c69996eSAndrew Jeffery break;
151ebd205c0SAndrew Jeffery case 0xc8: /* Interrupt Both Edge Trigger Control */
152ebd205c0SAndrew Jeffery case 0x28:
1530c69996eSAndrew Jeffery val = s->dual_edge;
1540c69996eSAndrew Jeffery break;
155ebd205c0SAndrew Jeffery case 0xd0: /* Interrupt Event */
156ebd205c0SAndrew Jeffery case 0x2c:
1570c69996eSAndrew Jeffery val = s->event;
1580c69996eSAndrew Jeffery break;
159ebd205c0SAndrew Jeffery case 0xe0: /* Edge Triggered Interrupt Status */
1600c69996eSAndrew Jeffery val = s->raw & ~s->sense;
1610c69996eSAndrew Jeffery break;
1620c69996eSAndrew Jeffery /* Illegal */
163ebd205c0SAndrew Jeffery case 0xa8: /* Interrupt Enable Clear */
164ebd205c0SAndrew Jeffery case 0xb8: /* Software Interrupt Clear */
165ebd205c0SAndrew Jeffery case 0xd8: /* Edge Triggered Interrupt Clear */
1660c69996eSAndrew Jeffery qemu_log_mask(LOG_GUEST_ERROR,
1670c69996eSAndrew Jeffery "%s: Read of write-only register with offset 0x%"
1680c69996eSAndrew Jeffery HWADDR_PRIx "\n", __func__, offset);
1690c69996eSAndrew Jeffery val = 0;
1700c69996eSAndrew Jeffery break;
1710c69996eSAndrew Jeffery default:
1720c69996eSAndrew Jeffery qemu_log_mask(LOG_GUEST_ERROR,
1730c69996eSAndrew Jeffery "%s: Bad register at offset 0x%" HWADDR_PRIx "\n",
1740c69996eSAndrew Jeffery __func__, offset);
1750c69996eSAndrew Jeffery val = 0;
1760c69996eSAndrew Jeffery break;
1770c69996eSAndrew Jeffery }
1780c69996eSAndrew Jeffery if (high) {
1790c69996eSAndrew Jeffery val = extract64(val, 32, 19);
180ebd205c0SAndrew Jeffery } else {
181ebd205c0SAndrew Jeffery val = extract64(val, 0, 32);
1820c69996eSAndrew Jeffery }
1830c69996eSAndrew Jeffery trace_aspeed_vic_read(offset, size, val);
1840c69996eSAndrew Jeffery return val;
1850c69996eSAndrew Jeffery }
1860c69996eSAndrew Jeffery
aspeed_vic_write(void * opaque,hwaddr offset,uint64_t data,unsigned size)1870c69996eSAndrew Jeffery static void aspeed_vic_write(void *opaque, hwaddr offset, uint64_t data,
1880c69996eSAndrew Jeffery unsigned size)
1890c69996eSAndrew Jeffery {
1900c69996eSAndrew Jeffery AspeedVICState *s = (AspeedVICState *)opaque;
191ebd205c0SAndrew Jeffery hwaddr n_offset;
192ebd205c0SAndrew Jeffery bool high;
1930c69996eSAndrew Jeffery
1940c69996eSAndrew Jeffery if (offset < AVIC_NEW_BASE_OFFSET) {
195ebd205c0SAndrew Jeffery high = false;
196ebd205c0SAndrew Jeffery n_offset = offset;
197ebd205c0SAndrew Jeffery } else {
198ebd205c0SAndrew Jeffery high = !!(offset & 0x4);
199ebd205c0SAndrew Jeffery n_offset = (offset & ~0x4);
2000c69996eSAndrew Jeffery }
2010c69996eSAndrew Jeffery
2020c69996eSAndrew Jeffery trace_aspeed_vic_write(offset, size, data);
2030c69996eSAndrew Jeffery
2040c69996eSAndrew Jeffery /* Given we have members using separate enable/clear registers, deposit64()
2050c69996eSAndrew Jeffery * isn't quite the tool for the job. Instead, relocate the incoming bits to
2060c69996eSAndrew Jeffery * the required bit offset based on the provided access address
2070c69996eSAndrew Jeffery */
2080c69996eSAndrew Jeffery if (high) {
2090c69996eSAndrew Jeffery data &= AVIC_H_MASK;
2100c69996eSAndrew Jeffery data <<= 32;
2110c69996eSAndrew Jeffery } else {
2120c69996eSAndrew Jeffery data &= AVIC_L_MASK;
2130c69996eSAndrew Jeffery }
2140c69996eSAndrew Jeffery
2150c69996eSAndrew Jeffery switch (n_offset) {
216ebd205c0SAndrew Jeffery case 0x98: /* Interrupt Selection */
217ebd205c0SAndrew Jeffery case 0x0c:
2180c69996eSAndrew Jeffery /* Register has deposit64() semantics - overwrite requested 32 bits */
2190c69996eSAndrew Jeffery if (high) {
2200c69996eSAndrew Jeffery s->select &= AVIC_L_MASK;
2210c69996eSAndrew Jeffery } else {
2220c69996eSAndrew Jeffery s->select &= ((uint64_t) AVIC_H_MASK) << 32;
2230c69996eSAndrew Jeffery }
2240c69996eSAndrew Jeffery s->select |= data;
2250c69996eSAndrew Jeffery break;
226ebd205c0SAndrew Jeffery case 0xa0: /* Interrupt Enable */
227ebd205c0SAndrew Jeffery case 0x10:
2280c69996eSAndrew Jeffery s->enable |= data;
2290c69996eSAndrew Jeffery break;
230ebd205c0SAndrew Jeffery case 0xa8: /* Interrupt Enable Clear */
231ebd205c0SAndrew Jeffery case 0x14:
2320c69996eSAndrew Jeffery s->enable &= ~data;
2330c69996eSAndrew Jeffery break;
234ebd205c0SAndrew Jeffery case 0xb0: /* Software Interrupt */
235ebd205c0SAndrew Jeffery case 0x18:
2360c69996eSAndrew Jeffery qemu_log_mask(LOG_UNIMP, "%s: Software interrupts unavailable. "
2370c69996eSAndrew Jeffery "IRQs requested: 0x%016" PRIx64 "\n", __func__, data);
2380c69996eSAndrew Jeffery break;
239ebd205c0SAndrew Jeffery case 0xb8: /* Software Interrupt Clear */
240ebd205c0SAndrew Jeffery case 0x1c:
2410c69996eSAndrew Jeffery qemu_log_mask(LOG_UNIMP, "%s: Software interrupts unavailable. "
2420c69996eSAndrew Jeffery "IRQs to be cleared: 0x%016" PRIx64 "\n", __func__, data);
2430c69996eSAndrew Jeffery break;
244ebd205c0SAndrew Jeffery case 0xd0: /* Interrupt Event */
2450c69996eSAndrew Jeffery /* Register has deposit64() semantics - overwrite the top four valid
2460c69996eSAndrew Jeffery * IRQ bits, as only the top four IRQs (GPIOs) can change their event
2470c69996eSAndrew Jeffery * type */
2480c69996eSAndrew Jeffery if (high) {
2490c69996eSAndrew Jeffery s->event &= ~AVIC_EVENT_W_MASK;
2500c69996eSAndrew Jeffery s->event |= (data & AVIC_EVENT_W_MASK);
2510c69996eSAndrew Jeffery } else {
2520c69996eSAndrew Jeffery qemu_log_mask(LOG_GUEST_ERROR,
2530c69996eSAndrew Jeffery "Ignoring invalid write to interrupt event register");
2540c69996eSAndrew Jeffery }
2550c69996eSAndrew Jeffery break;
256ebd205c0SAndrew Jeffery case 0xd8: /* Edge Triggered Interrupt Clear */
257ebd205c0SAndrew Jeffery case 0x38:
2580c69996eSAndrew Jeffery s->raw &= ~(data & ~s->sense);
2590c69996eSAndrew Jeffery break;
260ebd205c0SAndrew Jeffery case 0x80: /* IRQ Status */
261ebd205c0SAndrew Jeffery case 0x00:
262ebd205c0SAndrew Jeffery case 0x88: /* FIQ Status */
263ebd205c0SAndrew Jeffery case 0x04:
264ebd205c0SAndrew Jeffery case 0x90: /* Raw Interrupt Status */
265ebd205c0SAndrew Jeffery case 0x08:
266ebd205c0SAndrew Jeffery case 0xc0: /* Interrupt Sensitivity */
267ebd205c0SAndrew Jeffery case 0x24:
268ebd205c0SAndrew Jeffery case 0xc8: /* Interrupt Both Edge Trigger Control */
269ebd205c0SAndrew Jeffery case 0x28:
270ebd205c0SAndrew Jeffery case 0xe0: /* Edge Triggered Interrupt Status */
2710c69996eSAndrew Jeffery qemu_log_mask(LOG_GUEST_ERROR,
2720c69996eSAndrew Jeffery "%s: Write of read-only register with offset 0x%"
2730c69996eSAndrew Jeffery HWADDR_PRIx "\n", __func__, offset);
2740c69996eSAndrew Jeffery break;
2750c69996eSAndrew Jeffery
2760c69996eSAndrew Jeffery default:
2770c69996eSAndrew Jeffery qemu_log_mask(LOG_GUEST_ERROR,
2780c69996eSAndrew Jeffery "%s: Bad register at offset 0x%" HWADDR_PRIx "\n",
2790c69996eSAndrew Jeffery __func__, offset);
2800c69996eSAndrew Jeffery break;
2810c69996eSAndrew Jeffery }
2820c69996eSAndrew Jeffery aspeed_vic_update(s);
2830c69996eSAndrew Jeffery }
2840c69996eSAndrew Jeffery
2850c69996eSAndrew Jeffery static const MemoryRegionOps aspeed_vic_ops = {
2860c69996eSAndrew Jeffery .read = aspeed_vic_read,
2870c69996eSAndrew Jeffery .write = aspeed_vic_write,
2880c69996eSAndrew Jeffery .endianness = DEVICE_LITTLE_ENDIAN,
289*d34fea6cSJoel Stanley .valid.min_access_size = 1,
2900c69996eSAndrew Jeffery .valid.max_access_size = 4,
2910c69996eSAndrew Jeffery .valid.unaligned = false,
2920c69996eSAndrew Jeffery };
2930c69996eSAndrew Jeffery
aspeed_vic_reset(DeviceState * dev)2940c69996eSAndrew Jeffery static void aspeed_vic_reset(DeviceState *dev)
2950c69996eSAndrew Jeffery {
2960c69996eSAndrew Jeffery AspeedVICState *s = ASPEED_VIC(dev);
2970c69996eSAndrew Jeffery
2980c69996eSAndrew Jeffery s->level = 0;
2990c69996eSAndrew Jeffery s->raw = 0;
3000c69996eSAndrew Jeffery s->select = 0;
3010c69996eSAndrew Jeffery s->enable = 0;
3020c69996eSAndrew Jeffery s->trigger = 0;
3030c69996eSAndrew Jeffery s->sense = 0x1F07FFF8FFFFULL;
3040c69996eSAndrew Jeffery s->dual_edge = 0xF800070000ULL;
3050c69996eSAndrew Jeffery s->event = 0x5F07FFF8FFFFULL;
3060c69996eSAndrew Jeffery }
3070c69996eSAndrew Jeffery
3080c69996eSAndrew Jeffery #define AVIC_IO_REGION_SIZE 0x20000
3090c69996eSAndrew Jeffery
aspeed_vic_realize(DeviceState * dev,Error ** errp)3100c69996eSAndrew Jeffery static void aspeed_vic_realize(DeviceState *dev, Error **errp)
3110c69996eSAndrew Jeffery {
3120c69996eSAndrew Jeffery SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
3130c69996eSAndrew Jeffery AspeedVICState *s = ASPEED_VIC(dev);
3140c69996eSAndrew Jeffery
3150c69996eSAndrew Jeffery memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_vic_ops, s,
3160c69996eSAndrew Jeffery TYPE_ASPEED_VIC, AVIC_IO_REGION_SIZE);
3170c69996eSAndrew Jeffery
3180c69996eSAndrew Jeffery sysbus_init_mmio(sbd, &s->iomem);
3190c69996eSAndrew Jeffery
3200c69996eSAndrew Jeffery qdev_init_gpio_in(dev, aspeed_vic_set_irq, ASPEED_VIC_NR_IRQS);
3210c69996eSAndrew Jeffery sysbus_init_irq(sbd, &s->irq);
3220c69996eSAndrew Jeffery sysbus_init_irq(sbd, &s->fiq);
3230c69996eSAndrew Jeffery }
3240c69996eSAndrew Jeffery
3250c69996eSAndrew Jeffery static const VMStateDescription vmstate_aspeed_vic = {
3260c69996eSAndrew Jeffery .name = "aspeed.new-vic",
3270c69996eSAndrew Jeffery .version_id = 1,
3280c69996eSAndrew Jeffery .minimum_version_id = 1,
32945b1f81dSRichard Henderson .fields = (const VMStateField[]) {
3300c69996eSAndrew Jeffery VMSTATE_UINT64(level, AspeedVICState),
3310c69996eSAndrew Jeffery VMSTATE_UINT64(raw, AspeedVICState),
3320c69996eSAndrew Jeffery VMSTATE_UINT64(select, AspeedVICState),
3330c69996eSAndrew Jeffery VMSTATE_UINT64(enable, AspeedVICState),
3340c69996eSAndrew Jeffery VMSTATE_UINT64(trigger, AspeedVICState),
3350c69996eSAndrew Jeffery VMSTATE_UINT64(sense, AspeedVICState),
3360c69996eSAndrew Jeffery VMSTATE_UINT64(dual_edge, AspeedVICState),
3370c69996eSAndrew Jeffery VMSTATE_UINT64(event, AspeedVICState),
3380c69996eSAndrew Jeffery VMSTATE_END_OF_LIST()
3390c69996eSAndrew Jeffery }
3400c69996eSAndrew Jeffery };
3410c69996eSAndrew Jeffery
aspeed_vic_class_init(ObjectClass * klass,void * data)3420c69996eSAndrew Jeffery static void aspeed_vic_class_init(ObjectClass *klass, void *data)
3430c69996eSAndrew Jeffery {
3440c69996eSAndrew Jeffery DeviceClass *dc = DEVICE_CLASS(klass);
3450c69996eSAndrew Jeffery dc->realize = aspeed_vic_realize;
346e3d08143SPeter Maydell device_class_set_legacy_reset(dc, aspeed_vic_reset);
3470c69996eSAndrew Jeffery dc->desc = "ASPEED Interrupt Controller (New)";
3480c69996eSAndrew Jeffery dc->vmsd = &vmstate_aspeed_vic;
3490c69996eSAndrew Jeffery }
3500c69996eSAndrew Jeffery
3510c69996eSAndrew Jeffery static const TypeInfo aspeed_vic_info = {
3520c69996eSAndrew Jeffery .name = TYPE_ASPEED_VIC,
3530c69996eSAndrew Jeffery .parent = TYPE_SYS_BUS_DEVICE,
3540c69996eSAndrew Jeffery .instance_size = sizeof(AspeedVICState),
3550c69996eSAndrew Jeffery .class_init = aspeed_vic_class_init,
3560c69996eSAndrew Jeffery };
3570c69996eSAndrew Jeffery
aspeed_vic_register_types(void)3580c69996eSAndrew Jeffery static void aspeed_vic_register_types(void)
3590c69996eSAndrew Jeffery {
3600c69996eSAndrew Jeffery type_register_static(&aspeed_vic_info);
3610c69996eSAndrew Jeffery }
3620c69996eSAndrew Jeffery
3630c69996eSAndrew Jeffery type_init(aspeed_vic_register_types);
364