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 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 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 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 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, 2890c69996eSAndrew Jeffery .valid.min_access_size = 4, 2900c69996eSAndrew Jeffery .valid.max_access_size = 4, 2910c69996eSAndrew Jeffery .valid.unaligned = false, 2920c69996eSAndrew Jeffery }; 2930c69996eSAndrew Jeffery 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 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 342*12d1a768SPhilippe Mathieu-Daudé static void aspeed_vic_class_init(ObjectClass *klass, const 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 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