1b5ff1b31Sbellard /* 2b5ff1b31Sbellard * ARM Integrator CP System emulation. 3b5ff1b31Sbellard * 4a1bb27b1Spbrook * Copyright (c) 2005-2007 CodeSourcery. 5b5ff1b31Sbellard * Written by Paul Brook 6b5ff1b31Sbellard * 78e31bf38SMatthew Fernandez * This code is licensed under the GPL 8b5ff1b31Sbellard */ 9b5ff1b31Sbellard 1012b16722SPeter Maydell #include "qemu/osdep.h" 11da34e65cSMarkus Armbruster #include "qapi/error.h" 124771d756SPaolo Bonzini #include "cpu.h" 1383c9f4caSPaolo Bonzini #include "hw/sysbus.h" 14d6454270SMarkus Armbruster #include "migration/vmstate.h" 1583c9f4caSPaolo Bonzini #include "hw/boards.h" 1612ec8bd5SPeter Maydell #include "hw/arm/boot.h" 17b8616055SAlex Bennée #include "hw/misc/arm_integrator_debug.h" 18437cc27dSPhilippe Mathieu-Daudé #include "hw/net/smc91c111.h" 191422e32dSPaolo Bonzini #include "net/net.h" 20022c62cbSPaolo Bonzini #include "exec/address-spaces.h" 2154d31236SMarkus Armbruster #include "sysemu/runstate.h" 229c17d615SPaolo Bonzini #include "sysemu/sysemu.h" 239904625fSPhilippe Mathieu-Daudé #include "qemu/log.h" 24223a72f1SGreg Bellows #include "qemu/error-report.h" 25f0d1d2c1Sxiaoqiang zhao #include "hw/char/pl011.h" 26650d103dSMarkus Armbruster #include "hw/hw.h" 2764552b6bSMarkus Armbruster #include "hw/irq.h" 2826c607b8SPhilippe Mathieu-Daudé #include "hw/sd/sd.h" 29db1015e9SEduardo Habkost #include "qom/object.h" 30*b8ab0303SMartin Kletzander #include "audio/audio.h" 31b5ff1b31Sbellard 32257ec289SAndreas Färber #define TYPE_INTEGRATOR_CM "integrator_core" 338063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(IntegratorCMState, INTEGRATOR_CM) 34257ec289SAndreas Färber 35db1015e9SEduardo Habkost struct IntegratorCMState { 36257ec289SAndreas Färber /*< private >*/ 37257ec289SAndreas Färber SysBusDevice parent_obj; 38257ec289SAndreas Färber /*< public >*/ 39257ec289SAndreas Färber 4071d9bc50SBenoît Canet MemoryRegion iomem; 41ee6847d1SGerd Hoffmann uint32_t memsz; 42211adf4dSAvi Kivity MemoryRegion flash; 43b5ff1b31Sbellard uint32_t cm_osc; 44b5ff1b31Sbellard uint32_t cm_ctrl; 45b5ff1b31Sbellard uint32_t cm_lock; 46b5ff1b31Sbellard uint32_t cm_auxosc; 47b5ff1b31Sbellard uint32_t cm_sdram; 48b5ff1b31Sbellard uint32_t cm_init; 49b5ff1b31Sbellard uint32_t cm_flags; 50b5ff1b31Sbellard uint32_t cm_nvflags; 51f53977f7SJan Petrous uint32_t cm_refcnt_offset; 52b5ff1b31Sbellard uint32_t int_level; 53b5ff1b31Sbellard uint32_t irq_enabled; 54b5ff1b31Sbellard uint32_t fiq_enabled; 55db1015e9SEduardo Habkost }; 56b5ff1b31Sbellard 57b5ff1b31Sbellard static uint8_t integrator_spd[128] = { 58b5ff1b31Sbellard 128, 8, 4, 11, 9, 1, 64, 0, 2, 0xa0, 0xa0, 0, 0, 8, 0, 1, 59b5ff1b31Sbellard 0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40 60b5ff1b31Sbellard }; 61b5ff1b31Sbellard 6226d32022SPavel Dovgalyuk static const VMStateDescription vmstate_integratorcm = { 6326d32022SPavel Dovgalyuk .name = "integratorcm", 6426d32022SPavel Dovgalyuk .version_id = 1, 6526d32022SPavel Dovgalyuk .minimum_version_id = 1, 6626d32022SPavel Dovgalyuk .fields = (VMStateField[]) { 6726d32022SPavel Dovgalyuk VMSTATE_UINT32(cm_osc, IntegratorCMState), 6826d32022SPavel Dovgalyuk VMSTATE_UINT32(cm_ctrl, IntegratorCMState), 6926d32022SPavel Dovgalyuk VMSTATE_UINT32(cm_lock, IntegratorCMState), 7026d32022SPavel Dovgalyuk VMSTATE_UINT32(cm_auxosc, IntegratorCMState), 7126d32022SPavel Dovgalyuk VMSTATE_UINT32(cm_sdram, IntegratorCMState), 7226d32022SPavel Dovgalyuk VMSTATE_UINT32(cm_init, IntegratorCMState), 7326d32022SPavel Dovgalyuk VMSTATE_UINT32(cm_flags, IntegratorCMState), 7426d32022SPavel Dovgalyuk VMSTATE_UINT32(cm_nvflags, IntegratorCMState), 7526d32022SPavel Dovgalyuk VMSTATE_UINT32(int_level, IntegratorCMState), 7626d32022SPavel Dovgalyuk VMSTATE_UINT32(irq_enabled, IntegratorCMState), 7726d32022SPavel Dovgalyuk VMSTATE_UINT32(fiq_enabled, IntegratorCMState), 7826d32022SPavel Dovgalyuk VMSTATE_END_OF_LIST() 7926d32022SPavel Dovgalyuk } 8026d32022SPavel Dovgalyuk }; 8126d32022SPavel Dovgalyuk 82a8170e5eSAvi Kivity static uint64_t integratorcm_read(void *opaque, hwaddr offset, 8371d9bc50SBenoît Canet unsigned size) 84b5ff1b31Sbellard { 85257ec289SAndreas Färber IntegratorCMState *s = opaque; 86b5ff1b31Sbellard if (offset >= 0x100 && offset < 0x200) { 87b5ff1b31Sbellard /* CM_SPD */ 88b5ff1b31Sbellard if (offset >= 0x180) 89b5ff1b31Sbellard return 0; 90b5ff1b31Sbellard return integrator_spd[offset >> 2]; 91b5ff1b31Sbellard } 92b5ff1b31Sbellard switch (offset >> 2) { 93b5ff1b31Sbellard case 0: /* CM_ID */ 94b5ff1b31Sbellard return 0x411a3001; 95b5ff1b31Sbellard case 1: /* CM_PROC */ 96b5ff1b31Sbellard return 0; 97b5ff1b31Sbellard case 2: /* CM_OSC */ 98b5ff1b31Sbellard return s->cm_osc; 99b5ff1b31Sbellard case 3: /* CM_CTRL */ 100b5ff1b31Sbellard return s->cm_ctrl; 101b5ff1b31Sbellard case 4: /* CM_STAT */ 102b5ff1b31Sbellard return 0x00100000; 103b5ff1b31Sbellard case 5: /* CM_LOCK */ 104b5ff1b31Sbellard if (s->cm_lock == 0xa05f) { 105b5ff1b31Sbellard return 0x1a05f; 106b5ff1b31Sbellard } else { 107b5ff1b31Sbellard return s->cm_lock; 108b5ff1b31Sbellard } 109b5ff1b31Sbellard case 6: /* CM_LMBUSCNT */ 110b5ff1b31Sbellard /* ??? High frequency timer. */ 1112ac71179SPaul Brook hw_error("integratorcm_read: CM_LMBUSCNT"); 112b5ff1b31Sbellard case 7: /* CM_AUXOSC */ 113b5ff1b31Sbellard return s->cm_auxosc; 114b5ff1b31Sbellard case 8: /* CM_SDRAM */ 115b5ff1b31Sbellard return s->cm_sdram; 116b5ff1b31Sbellard case 9: /* CM_INIT */ 117b5ff1b31Sbellard return s->cm_init; 118f53977f7SJan Petrous case 10: /* CM_REFCNT */ 119f53977f7SJan Petrous /* This register, CM_REFCNT, provides a 32-bit count value. 120f53977f7SJan Petrous * The count increments at the fixed reference clock frequency of 24MHz 121f53977f7SJan Petrous * and can be used as a real-time counter. 122f53977f7SJan Petrous */ 123f53977f7SJan Petrous return (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24, 124f53977f7SJan Petrous 1000) - s->cm_refcnt_offset; 125b5ff1b31Sbellard case 12: /* CM_FLAGS */ 126b5ff1b31Sbellard return s->cm_flags; 127b5ff1b31Sbellard case 14: /* CM_NVFLAGS */ 128b5ff1b31Sbellard return s->cm_nvflags; 129b5ff1b31Sbellard case 16: /* CM_IRQ_STAT */ 130b5ff1b31Sbellard return s->int_level & s->irq_enabled; 131b5ff1b31Sbellard case 17: /* CM_IRQ_RSTAT */ 132b5ff1b31Sbellard return s->int_level; 133b5ff1b31Sbellard case 18: /* CM_IRQ_ENSET */ 134b5ff1b31Sbellard return s->irq_enabled; 135b5ff1b31Sbellard case 20: /* CM_SOFT_INTSET */ 136b5ff1b31Sbellard return s->int_level & 1; 137b5ff1b31Sbellard case 24: /* CM_FIQ_STAT */ 138b5ff1b31Sbellard return s->int_level & s->fiq_enabled; 139b5ff1b31Sbellard case 25: /* CM_FIQ_RSTAT */ 140b5ff1b31Sbellard return s->int_level; 141b5ff1b31Sbellard case 26: /* CM_FIQ_ENSET */ 142b5ff1b31Sbellard return s->fiq_enabled; 143b5ff1b31Sbellard case 32: /* CM_VOLTAGE_CTL0 */ 144b5ff1b31Sbellard case 33: /* CM_VOLTAGE_CTL1 */ 145b5ff1b31Sbellard case 34: /* CM_VOLTAGE_CTL2 */ 146b5ff1b31Sbellard case 35: /* CM_VOLTAGE_CTL3 */ 147b5ff1b31Sbellard /* ??? Voltage control unimplemented. */ 148b5ff1b31Sbellard return 0; 149b5ff1b31Sbellard default: 1509904625fSPhilippe Mathieu-Daudé qemu_log_mask(LOG_UNIMP, 1519904625fSPhilippe Mathieu-Daudé "%s: Unimplemented offset 0x%" HWADDR_PRIX "\n", 1529904625fSPhilippe Mathieu-Daudé __func__, offset); 153b5ff1b31Sbellard return 0; 154b5ff1b31Sbellard } 155b5ff1b31Sbellard } 156b5ff1b31Sbellard 157257ec289SAndreas Färber static void integratorcm_do_remap(IntegratorCMState *s) 158b5ff1b31Sbellard { 159563c2bf3SPeter Maydell /* Sync memory region state with CM_CTRL REMAP bit: 160563c2bf3SPeter Maydell * bit 0 => flash at address 0; bit 1 => RAM 161563c2bf3SPeter Maydell */ 162563c2bf3SPeter Maydell memory_region_set_enabled(&s->flash, !(s->cm_ctrl & 4)); 163b5ff1b31Sbellard } 164b5ff1b31Sbellard 165257ec289SAndreas Färber static void integratorcm_set_ctrl(IntegratorCMState *s, uint32_t value) 166b5ff1b31Sbellard { 167b5ff1b31Sbellard if (value & 8) { 168cf83f140SEric Blake qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 169b5ff1b31Sbellard } 170df3f457bSPeter Maydell if ((s->cm_ctrl ^ value) & 1) { 171df3f457bSPeter Maydell /* (value & 1) != 0 means the green "MISC LED" is lit. 172df3f457bSPeter Maydell * We don't have any nice place to display LEDs. printf is a bad 173df3f457bSPeter Maydell * idea because Linux uses the LED as a heartbeat and the output 174df3f457bSPeter Maydell * will swamp anything else on the terminal. 175df3f457bSPeter Maydell */ 176b5ff1b31Sbellard } 177df3f457bSPeter Maydell /* Note that the RESET bit [3] always reads as zero */ 178df3f457bSPeter Maydell s->cm_ctrl = (s->cm_ctrl & ~5) | (value & 5); 179563c2bf3SPeter Maydell integratorcm_do_remap(s); 180b5ff1b31Sbellard } 181b5ff1b31Sbellard 182257ec289SAndreas Färber static void integratorcm_update(IntegratorCMState *s) 183b5ff1b31Sbellard { 184b5ff1b31Sbellard /* ??? The CPU irq/fiq is raised when either the core module or base PIC 185b5ff1b31Sbellard are active. */ 186b5ff1b31Sbellard if (s->int_level & (s->irq_enabled | s->fiq_enabled)) 1872ac71179SPaul Brook hw_error("Core module interrupt\n"); 188b5ff1b31Sbellard } 189b5ff1b31Sbellard 190a8170e5eSAvi Kivity static void integratorcm_write(void *opaque, hwaddr offset, 19171d9bc50SBenoît Canet uint64_t value, unsigned size) 192b5ff1b31Sbellard { 193257ec289SAndreas Färber IntegratorCMState *s = opaque; 194b5ff1b31Sbellard switch (offset >> 2) { 195b5ff1b31Sbellard case 2: /* CM_OSC */ 196b5ff1b31Sbellard if (s->cm_lock == 0xa05f) 197b5ff1b31Sbellard s->cm_osc = value; 198b5ff1b31Sbellard break; 199b5ff1b31Sbellard case 3: /* CM_CTRL */ 200b5ff1b31Sbellard integratorcm_set_ctrl(s, value); 201b5ff1b31Sbellard break; 202b5ff1b31Sbellard case 5: /* CM_LOCK */ 203b5ff1b31Sbellard s->cm_lock = value & 0xffff; 204b5ff1b31Sbellard break; 205b5ff1b31Sbellard case 7: /* CM_AUXOSC */ 206b5ff1b31Sbellard if (s->cm_lock == 0xa05f) 207b5ff1b31Sbellard s->cm_auxosc = value; 208b5ff1b31Sbellard break; 209b5ff1b31Sbellard case 8: /* CM_SDRAM */ 210b5ff1b31Sbellard s->cm_sdram = value; 211b5ff1b31Sbellard break; 212b5ff1b31Sbellard case 9: /* CM_INIT */ 213b5ff1b31Sbellard /* ??? This can change the memory bus frequency. */ 214b5ff1b31Sbellard s->cm_init = value; 215b5ff1b31Sbellard break; 216b5ff1b31Sbellard case 12: /* CM_FLAGSS */ 217b5ff1b31Sbellard s->cm_flags |= value; 218b5ff1b31Sbellard break; 219b5ff1b31Sbellard case 13: /* CM_FLAGSC */ 220b5ff1b31Sbellard s->cm_flags &= ~value; 221b5ff1b31Sbellard break; 222b5ff1b31Sbellard case 14: /* CM_NVFLAGSS */ 223b5ff1b31Sbellard s->cm_nvflags |= value; 224b5ff1b31Sbellard break; 225b5ff1b31Sbellard case 15: /* CM_NVFLAGSS */ 226b5ff1b31Sbellard s->cm_nvflags &= ~value; 227b5ff1b31Sbellard break; 228b5ff1b31Sbellard case 18: /* CM_IRQ_ENSET */ 229b5ff1b31Sbellard s->irq_enabled |= value; 230b5ff1b31Sbellard integratorcm_update(s); 231b5ff1b31Sbellard break; 232b5ff1b31Sbellard case 19: /* CM_IRQ_ENCLR */ 233b5ff1b31Sbellard s->irq_enabled &= ~value; 234b5ff1b31Sbellard integratorcm_update(s); 235b5ff1b31Sbellard break; 236b5ff1b31Sbellard case 20: /* CM_SOFT_INTSET */ 237b5ff1b31Sbellard s->int_level |= (value & 1); 238b5ff1b31Sbellard integratorcm_update(s); 239b5ff1b31Sbellard break; 240b5ff1b31Sbellard case 21: /* CM_SOFT_INTCLR */ 241b5ff1b31Sbellard s->int_level &= ~(value & 1); 242b5ff1b31Sbellard integratorcm_update(s); 243b5ff1b31Sbellard break; 244b5ff1b31Sbellard case 26: /* CM_FIQ_ENSET */ 245b5ff1b31Sbellard s->fiq_enabled |= value; 246b5ff1b31Sbellard integratorcm_update(s); 247b5ff1b31Sbellard break; 248b5ff1b31Sbellard case 27: /* CM_FIQ_ENCLR */ 249b5ff1b31Sbellard s->fiq_enabled &= ~value; 250b5ff1b31Sbellard integratorcm_update(s); 251b5ff1b31Sbellard break; 252b5ff1b31Sbellard case 32: /* CM_VOLTAGE_CTL0 */ 253b5ff1b31Sbellard case 33: /* CM_VOLTAGE_CTL1 */ 254b5ff1b31Sbellard case 34: /* CM_VOLTAGE_CTL2 */ 255b5ff1b31Sbellard case 35: /* CM_VOLTAGE_CTL3 */ 256b5ff1b31Sbellard /* ??? Voltage control unimplemented. */ 257b5ff1b31Sbellard break; 258b5ff1b31Sbellard default: 2599904625fSPhilippe Mathieu-Daudé qemu_log_mask(LOG_UNIMP, 2609904625fSPhilippe Mathieu-Daudé "%s: Unimplemented offset 0x%" HWADDR_PRIX "\n", 2619904625fSPhilippe Mathieu-Daudé __func__, offset); 262b5ff1b31Sbellard break; 263b5ff1b31Sbellard } 264b5ff1b31Sbellard } 265b5ff1b31Sbellard 266b5ff1b31Sbellard /* Integrator/CM control registers. */ 267b5ff1b31Sbellard 26871d9bc50SBenoît Canet static const MemoryRegionOps integratorcm_ops = { 26971d9bc50SBenoît Canet .read = integratorcm_read, 27071d9bc50SBenoît Canet .write = integratorcm_write, 27171d9bc50SBenoît Canet .endianness = DEVICE_NATIVE_ENDIAN, 272b5ff1b31Sbellard }; 273b5ff1b31Sbellard 274a1f42e0cSxiaoqiang.zhao static void integratorcm_init(Object *obj) 275b5ff1b31Sbellard { 276a1f42e0cSxiaoqiang.zhao IntegratorCMState *s = INTEGRATOR_CM(obj); 277b5ff1b31Sbellard 278b5ff1b31Sbellard s->cm_osc = 0x01000048; 279b5ff1b31Sbellard /* ??? What should the high bits of this value be? */ 280b5ff1b31Sbellard s->cm_auxosc = 0x0007feff; 281b5ff1b31Sbellard s->cm_sdram = 0x00011122; 282e9d9ee23SJakub Jermar memcpy(integrator_spd + 73, "QEMU-MEMORY", 11); 283e9d9ee23SJakub Jermar s->cm_init = 0x00000112; 284e9d9ee23SJakub Jermar s->cm_refcnt_offset = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24, 285e9d9ee23SJakub Jermar 1000); 286e9d9ee23SJakub Jermar 287e9d9ee23SJakub Jermar /* ??? Save/restore. */ 288e9d9ee23SJakub Jermar } 289e9d9ee23SJakub Jermar 290e9d9ee23SJakub Jermar static void integratorcm_realize(DeviceState *d, Error **errp) 291e9d9ee23SJakub Jermar { 292e9d9ee23SJakub Jermar IntegratorCMState *s = INTEGRATOR_CM(d); 2938720daadSThomas Huth SysBusDevice *dev = SYS_BUS_DEVICE(d); 2948720daadSThomas Huth Error *local_err = NULL; 2958720daadSThomas Huth 2968720daadSThomas Huth memory_region_init_ram(&s->flash, OBJECT(d), "integrator.flash", 0x100000, 2978720daadSThomas Huth &local_err); 2988720daadSThomas Huth if (local_err) { 2998720daadSThomas Huth error_propagate(errp, local_err); 3008720daadSThomas Huth return; 3018720daadSThomas Huth } 3028720daadSThomas Huth 3038720daadSThomas Huth memory_region_init_io(&s->iomem, OBJECT(d), &integratorcm_ops, s, 3048720daadSThomas Huth "integratorcm", 0x00800000); 3058720daadSThomas Huth sysbus_init_mmio(dev, &s->iomem); 3068720daadSThomas Huth 3078720daadSThomas Huth integratorcm_do_remap(s); 308e9d9ee23SJakub Jermar 309ee6847d1SGerd Hoffmann if (s->memsz >= 256) { 310b5ff1b31Sbellard integrator_spd[31] = 64; 311b5ff1b31Sbellard s->cm_sdram |= 0x10; 312ee6847d1SGerd Hoffmann } else if (s->memsz >= 128) { 313b5ff1b31Sbellard integrator_spd[31] = 32; 314b5ff1b31Sbellard s->cm_sdram |= 0x0c; 315ee6847d1SGerd Hoffmann } else if (s->memsz >= 64) { 316b5ff1b31Sbellard integrator_spd[31] = 16; 317b5ff1b31Sbellard s->cm_sdram |= 0x08; 318ee6847d1SGerd Hoffmann } else if (s->memsz >= 32) { 319b5ff1b31Sbellard integrator_spd[31] = 4; 320b5ff1b31Sbellard s->cm_sdram |= 0x04; 321b5ff1b31Sbellard } else { 322b5ff1b31Sbellard integrator_spd[31] = 2; 323b5ff1b31Sbellard } 324b5ff1b31Sbellard } 325b5ff1b31Sbellard 326b5ff1b31Sbellard /* Integrator/CP hardware emulation. */ 327b5ff1b31Sbellard /* Primary interrupt controller. */ 328b5ff1b31Sbellard 32991b64626SAndreas Färber #define TYPE_INTEGRATOR_PIC "integrator_pic" 3308063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(icp_pic_state, INTEGRATOR_PIC) 33191b64626SAndreas Färber 332db1015e9SEduardo Habkost struct icp_pic_state { 33391b64626SAndreas Färber /*< private >*/ 33491b64626SAndreas Färber SysBusDevice parent_obj; 33591b64626SAndreas Färber /*< public >*/ 33691b64626SAndreas Färber 33761074e46SBenoît Canet MemoryRegion iomem; 338b5ff1b31Sbellard uint32_t level; 339b5ff1b31Sbellard uint32_t irq_enabled; 340b5ff1b31Sbellard uint32_t fiq_enabled; 341d537cf6cSpbrook qemu_irq parent_irq; 342d537cf6cSpbrook qemu_irq parent_fiq; 343db1015e9SEduardo Habkost }; 344b5ff1b31Sbellard 34526d32022SPavel Dovgalyuk static const VMStateDescription vmstate_icp_pic = { 34626d32022SPavel Dovgalyuk .name = "icp_pic", 34726d32022SPavel Dovgalyuk .version_id = 1, 34826d32022SPavel Dovgalyuk .minimum_version_id = 1, 34926d32022SPavel Dovgalyuk .fields = (VMStateField[]) { 35026d32022SPavel Dovgalyuk VMSTATE_UINT32(level, icp_pic_state), 35126d32022SPavel Dovgalyuk VMSTATE_UINT32(irq_enabled, icp_pic_state), 35226d32022SPavel Dovgalyuk VMSTATE_UINT32(fiq_enabled, icp_pic_state), 35326d32022SPavel Dovgalyuk VMSTATE_END_OF_LIST() 35426d32022SPavel Dovgalyuk } 35526d32022SPavel Dovgalyuk }; 35626d32022SPavel Dovgalyuk 357b5ff1b31Sbellard static void icp_pic_update(icp_pic_state *s) 358b5ff1b31Sbellard { 359b5ff1b31Sbellard uint32_t flags; 360b5ff1b31Sbellard 361b5ff1b31Sbellard flags = (s->level & s->irq_enabled); 362d537cf6cSpbrook qemu_set_irq(s->parent_irq, flags != 0); 363cdbdb648Spbrook flags = (s->level & s->fiq_enabled); 364d537cf6cSpbrook qemu_set_irq(s->parent_fiq, flags != 0); 365b5ff1b31Sbellard } 366b5ff1b31Sbellard 367cdbdb648Spbrook static void icp_pic_set_irq(void *opaque, int irq, int level) 368b5ff1b31Sbellard { 36980337b66Sbellard icp_pic_state *s = (icp_pic_state *)opaque; 370b5ff1b31Sbellard if (level) 37180337b66Sbellard s->level |= 1 << irq; 372b5ff1b31Sbellard else 37380337b66Sbellard s->level &= ~(1 << irq); 374b5ff1b31Sbellard icp_pic_update(s); 375b5ff1b31Sbellard } 376b5ff1b31Sbellard 377a8170e5eSAvi Kivity static uint64_t icp_pic_read(void *opaque, hwaddr offset, 37861074e46SBenoît Canet unsigned size) 379b5ff1b31Sbellard { 380b5ff1b31Sbellard icp_pic_state *s = (icp_pic_state *)opaque; 381b5ff1b31Sbellard 382b5ff1b31Sbellard switch (offset >> 2) { 383b5ff1b31Sbellard case 0: /* IRQ_STATUS */ 384b5ff1b31Sbellard return s->level & s->irq_enabled; 385b5ff1b31Sbellard case 1: /* IRQ_RAWSTAT */ 386b5ff1b31Sbellard return s->level; 387b5ff1b31Sbellard case 2: /* IRQ_ENABLESET */ 388b5ff1b31Sbellard return s->irq_enabled; 389b5ff1b31Sbellard case 4: /* INT_SOFTSET */ 390b5ff1b31Sbellard return s->level & 1; 391b5ff1b31Sbellard case 8: /* FRQ_STATUS */ 392b5ff1b31Sbellard return s->level & s->fiq_enabled; 393b5ff1b31Sbellard case 9: /* FRQ_RAWSTAT */ 394b5ff1b31Sbellard return s->level; 395b5ff1b31Sbellard case 10: /* FRQ_ENABLESET */ 396b5ff1b31Sbellard return s->fiq_enabled; 397b5ff1b31Sbellard case 3: /* IRQ_ENABLECLR */ 398b5ff1b31Sbellard case 5: /* INT_SOFTCLR */ 399b5ff1b31Sbellard case 11: /* FRQ_ENABLECLR */ 400b5ff1b31Sbellard default: 4019904625fSPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", 4029904625fSPhilippe Mathieu-Daudé __func__, offset); 403b5ff1b31Sbellard return 0; 404b5ff1b31Sbellard } 405b5ff1b31Sbellard } 406b5ff1b31Sbellard 407a8170e5eSAvi Kivity static void icp_pic_write(void *opaque, hwaddr offset, 40861074e46SBenoît Canet uint64_t value, unsigned size) 409b5ff1b31Sbellard { 410b5ff1b31Sbellard icp_pic_state *s = (icp_pic_state *)opaque; 411b5ff1b31Sbellard 412b5ff1b31Sbellard switch (offset >> 2) { 413b5ff1b31Sbellard case 2: /* IRQ_ENABLESET */ 414b5ff1b31Sbellard s->irq_enabled |= value; 415b5ff1b31Sbellard break; 416b5ff1b31Sbellard case 3: /* IRQ_ENABLECLR */ 417b5ff1b31Sbellard s->irq_enabled &= ~value; 418b5ff1b31Sbellard break; 419b5ff1b31Sbellard case 4: /* INT_SOFTSET */ 420b5ff1b31Sbellard if (value & 1) 421d537cf6cSpbrook icp_pic_set_irq(s, 0, 1); 422b5ff1b31Sbellard break; 423b5ff1b31Sbellard case 5: /* INT_SOFTCLR */ 424b5ff1b31Sbellard if (value & 1) 425d537cf6cSpbrook icp_pic_set_irq(s, 0, 0); 426b5ff1b31Sbellard break; 427b5ff1b31Sbellard case 10: /* FRQ_ENABLESET */ 428b5ff1b31Sbellard s->fiq_enabled |= value; 429b5ff1b31Sbellard break; 430b5ff1b31Sbellard case 11: /* FRQ_ENABLECLR */ 431b5ff1b31Sbellard s->fiq_enabled &= ~value; 432b5ff1b31Sbellard break; 433b5ff1b31Sbellard case 0: /* IRQ_STATUS */ 434b5ff1b31Sbellard case 1: /* IRQ_RAWSTAT */ 435b5ff1b31Sbellard case 8: /* FRQ_STATUS */ 436b5ff1b31Sbellard case 9: /* FRQ_RAWSTAT */ 437b5ff1b31Sbellard default: 4389904625fSPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", 4399904625fSPhilippe Mathieu-Daudé __func__, offset); 440b5ff1b31Sbellard return; 441b5ff1b31Sbellard } 442b5ff1b31Sbellard icp_pic_update(s); 443b5ff1b31Sbellard } 444b5ff1b31Sbellard 44561074e46SBenoît Canet static const MemoryRegionOps icp_pic_ops = { 44661074e46SBenoît Canet .read = icp_pic_read, 44761074e46SBenoît Canet .write = icp_pic_write, 44861074e46SBenoît Canet .endianness = DEVICE_NATIVE_ENDIAN, 449b5ff1b31Sbellard }; 450b5ff1b31Sbellard 451a1f42e0cSxiaoqiang.zhao static void icp_pic_init(Object *obj) 452b5ff1b31Sbellard { 453a1f42e0cSxiaoqiang.zhao DeviceState *dev = DEVICE(obj); 454a1f42e0cSxiaoqiang.zhao icp_pic_state *s = INTEGRATOR_PIC(obj); 455a1f42e0cSxiaoqiang.zhao SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 456b5ff1b31Sbellard 45791b64626SAndreas Färber qdev_init_gpio_in(dev, icp_pic_set_irq, 32); 45891b64626SAndreas Färber sysbus_init_irq(sbd, &s->parent_irq); 45991b64626SAndreas Färber sysbus_init_irq(sbd, &s->parent_fiq); 460a1f42e0cSxiaoqiang.zhao memory_region_init_io(&s->iomem, obj, &icp_pic_ops, s, 46164bde0f3SPaolo Bonzini "icp-pic", 0x00800000); 46291b64626SAndreas Färber sysbus_init_mmio(sbd, &s->iomem); 463b5ff1b31Sbellard } 464b5ff1b31Sbellard 465b5ff1b31Sbellard /* CP control registers. */ 4660c36493eSBenoît Canet 467ffc8542aSJan Kiszka #define TYPE_ICP_CONTROL_REGS "icp-ctrl-regs" 4688063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(ICPCtrlRegsState, ICP_CONTROL_REGS) 469ffc8542aSJan Kiszka 470db1015e9SEduardo Habkost struct ICPCtrlRegsState { 471ffc8542aSJan Kiszka /*< private >*/ 472ffc8542aSJan Kiszka SysBusDevice parent_obj; 473ffc8542aSJan Kiszka /*< public >*/ 474ffc8542aSJan Kiszka 475ffc8542aSJan Kiszka MemoryRegion iomem; 47683d0cf89SJan Kiszka 47783d0cf89SJan Kiszka qemu_irq mmc_irq; 47883d0cf89SJan Kiszka uint32_t intreg_state; 479db1015e9SEduardo Habkost }; 480ffc8542aSJan Kiszka 48183d0cf89SJan Kiszka #define ICP_GPIO_MMC_WPROT "mmc-wprot" 48283d0cf89SJan Kiszka #define ICP_GPIO_MMC_CARDIN "mmc-cardin" 48383d0cf89SJan Kiszka 48483d0cf89SJan Kiszka #define ICP_INTREG_WPROT (1 << 0) 48583d0cf89SJan Kiszka #define ICP_INTREG_CARDIN (1 << 3) 48683d0cf89SJan Kiszka 48726d32022SPavel Dovgalyuk static const VMStateDescription vmstate_icp_control = { 48826d32022SPavel Dovgalyuk .name = "icp_control", 48926d32022SPavel Dovgalyuk .version_id = 1, 49026d32022SPavel Dovgalyuk .minimum_version_id = 1, 49126d32022SPavel Dovgalyuk .fields = (VMStateField[]) { 49226d32022SPavel Dovgalyuk VMSTATE_UINT32(intreg_state, ICPCtrlRegsState), 49326d32022SPavel Dovgalyuk VMSTATE_END_OF_LIST() 49426d32022SPavel Dovgalyuk } 49526d32022SPavel Dovgalyuk }; 49626d32022SPavel Dovgalyuk 497a8170e5eSAvi Kivity static uint64_t icp_control_read(void *opaque, hwaddr offset, 4980c36493eSBenoît Canet unsigned size) 499b5ff1b31Sbellard { 50083d0cf89SJan Kiszka ICPCtrlRegsState *s = opaque; 50183d0cf89SJan Kiszka 502b5ff1b31Sbellard switch (offset >> 2) { 503b5ff1b31Sbellard case 0: /* CP_IDFIELD */ 504b5ff1b31Sbellard return 0x41034003; 505b5ff1b31Sbellard case 1: /* CP_FLASHPROG */ 506b5ff1b31Sbellard return 0; 507b5ff1b31Sbellard case 2: /* CP_INTREG */ 50883d0cf89SJan Kiszka return s->intreg_state; 509b5ff1b31Sbellard case 3: /* CP_DECODE */ 510b5ff1b31Sbellard return 0x11; 511b5ff1b31Sbellard default: 5129904625fSPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", 5139904625fSPhilippe Mathieu-Daudé __func__, offset); 514b5ff1b31Sbellard return 0; 515b5ff1b31Sbellard } 516b5ff1b31Sbellard } 517b5ff1b31Sbellard 518a8170e5eSAvi Kivity static void icp_control_write(void *opaque, hwaddr offset, 5190c36493eSBenoît Canet uint64_t value, unsigned size) 520b5ff1b31Sbellard { 52183d0cf89SJan Kiszka ICPCtrlRegsState *s = opaque; 52283d0cf89SJan Kiszka 523b5ff1b31Sbellard switch (offset >> 2) { 524b5ff1b31Sbellard case 2: /* CP_INTREG */ 52583d0cf89SJan Kiszka s->intreg_state &= ~(value & ICP_INTREG_CARDIN); 52683d0cf89SJan Kiszka qemu_set_irq(s->mmc_irq, !!(s->intreg_state & ICP_INTREG_CARDIN)); 52783d0cf89SJan Kiszka break; 52883d0cf89SJan Kiszka case 1: /* CP_FLASHPROG */ 529b5ff1b31Sbellard case 3: /* CP_DECODE */ 530b5ff1b31Sbellard /* Nothing interesting implemented yet. */ 531b5ff1b31Sbellard break; 532b5ff1b31Sbellard default: 5339904625fSPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n", 5349904625fSPhilippe Mathieu-Daudé __func__, offset); 535b5ff1b31Sbellard } 536b5ff1b31Sbellard } 5370c36493eSBenoît Canet 5380c36493eSBenoît Canet static const MemoryRegionOps icp_control_ops = { 5390c36493eSBenoît Canet .read = icp_control_read, 5400c36493eSBenoît Canet .write = icp_control_write, 5410c36493eSBenoît Canet .endianness = DEVICE_NATIVE_ENDIAN, 542b5ff1b31Sbellard }; 543b5ff1b31Sbellard 54483d0cf89SJan Kiszka static void icp_control_mmc_wprot(void *opaque, int line, int level) 54583d0cf89SJan Kiszka { 54683d0cf89SJan Kiszka ICPCtrlRegsState *s = opaque; 54783d0cf89SJan Kiszka 54883d0cf89SJan Kiszka s->intreg_state &= ~ICP_INTREG_WPROT; 54983d0cf89SJan Kiszka if (level) { 55083d0cf89SJan Kiszka s->intreg_state |= ICP_INTREG_WPROT; 55183d0cf89SJan Kiszka } 55283d0cf89SJan Kiszka } 55383d0cf89SJan Kiszka 55483d0cf89SJan Kiszka static void icp_control_mmc_cardin(void *opaque, int line, int level) 55583d0cf89SJan Kiszka { 55683d0cf89SJan Kiszka ICPCtrlRegsState *s = opaque; 55783d0cf89SJan Kiszka 55883d0cf89SJan Kiszka /* line is released by writing to CP_INTREG */ 55983d0cf89SJan Kiszka if (level) { 56083d0cf89SJan Kiszka s->intreg_state |= ICP_INTREG_CARDIN; 56183d0cf89SJan Kiszka qemu_set_irq(s->mmc_irq, 1); 56283d0cf89SJan Kiszka } 56383d0cf89SJan Kiszka } 56483d0cf89SJan Kiszka 565ffc8542aSJan Kiszka static void icp_control_init(Object *obj) 566b5ff1b31Sbellard { 567ffc8542aSJan Kiszka SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 568ffc8542aSJan Kiszka ICPCtrlRegsState *s = ICP_CONTROL_REGS(obj); 56983d0cf89SJan Kiszka DeviceState *dev = DEVICE(obj); 570b5ff1b31Sbellard 571ffc8542aSJan Kiszka memory_region_init_io(&s->iomem, OBJECT(s), &icp_control_ops, s, 572ffc8542aSJan Kiszka "icp_ctrl_regs", 0x00800000); 573ffc8542aSJan Kiszka sysbus_init_mmio(sbd, &s->iomem); 57483d0cf89SJan Kiszka 57583d0cf89SJan Kiszka qdev_init_gpio_in_named(dev, icp_control_mmc_wprot, ICP_GPIO_MMC_WPROT, 1); 57683d0cf89SJan Kiszka qdev_init_gpio_in_named(dev, icp_control_mmc_cardin, 57783d0cf89SJan Kiszka ICP_GPIO_MMC_CARDIN, 1); 57883d0cf89SJan Kiszka sysbus_init_irq(sbd, &s->mmc_irq); 579b5ff1b31Sbellard } 580b5ff1b31Sbellard 581b5ff1b31Sbellard 582b5ff1b31Sbellard /* Board init. */ 583b5ff1b31Sbellard 584f93eb9ffSbalrog static struct arm_boot_info integrator_binfo = { 585f93eb9ffSbalrog .loader_start = 0x0, 586f93eb9ffSbalrog .board_id = 0x113, 587f93eb9ffSbalrog }; 588f93eb9ffSbalrog 5893ef96221SMarcel Apfelbaum static void integratorcp_init(MachineState *machine) 590b5ff1b31Sbellard { 5913ef96221SMarcel Apfelbaum ram_addr_t ram_size = machine->ram_size; 592223a72f1SGreg Bellows Object *cpuobj; 593393a9eabSAndreas Färber ARMCPU *cpu; 594211adf4dSAvi Kivity MemoryRegion *address_space_mem = get_system_memory(); 595211adf4dSAvi Kivity MemoryRegion *ram_alias = g_new(MemoryRegion, 1); 596a7086888SPaul Brook qemu_irq pic[32]; 59783d0cf89SJan Kiszka DeviceState *dev, *sic, *icp; 59826c607b8SPhilippe Mathieu-Daudé DriveInfo *dinfo; 599a7086888SPaul Brook int i; 600b5ff1b31Sbellard 601ba1ba5ccSIgor Mammedov cpuobj = object_new(machine->cpu_type); 602223a72f1SGreg Bellows 60361e2f352SGreg Bellows /* By default ARM1176 CPUs have EL3 enabled. This board does not 60461e2f352SGreg Bellows * currently support EL3 so the CPU EL3 property is disabled before 60561e2f352SGreg Bellows * realization. 60661e2f352SGreg Bellows */ 607efba1595SDaniel P. Berrangé if (object_property_find(cpuobj, "has_el3")) { 6085325cc34SMarkus Armbruster object_property_set_bool(cpuobj, "has_el3", false, &error_fatal); 60961e2f352SGreg Bellows } 61061e2f352SGreg Bellows 611ce189ab2SMarkus Armbruster qdev_realize(DEVICE(cpuobj), NULL, &error_fatal); 612223a72f1SGreg Bellows 613223a72f1SGreg Bellows cpu = ARM_CPU(cpuobj); 614223a72f1SGreg Bellows 615b5ff1b31Sbellard /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash. */ 6161235fc06Sths /* ??? RAM should repeat to fill physical memory space. */ 617b5ff1b31Sbellard /* SDRAM at address zero*/ 6183f25b3f4SIgor Mammedov memory_region_add_subregion(address_space_mem, 0, machine->ram); 619b5ff1b31Sbellard /* And again at address 0x80000000 */ 6203f25b3f4SIgor Mammedov memory_region_init_alias(ram_alias, NULL, "ram.alias", machine->ram, 6213f25b3f4SIgor Mammedov 0, ram_size); 622211adf4dSAvi Kivity memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias); 623b5ff1b31Sbellard 6243e80f690SMarkus Armbruster dev = qdev_new(TYPE_INTEGRATOR_CM); 625ee6847d1SGerd Hoffmann qdev_prop_set_uint32(dev, "memsz", ram_size >> 20); 6263c6ef471SMarkus Armbruster sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); 627a7086888SPaul Brook sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000); 628a7086888SPaul Brook 62991b64626SAndreas Färber dev = sysbus_create_varargs(TYPE_INTEGRATOR_PIC, 0x14000000, 63099d228d6SPeter Maydell qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ), 63199d228d6SPeter Maydell qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ), 63299d228d6SPeter Maydell NULL); 633a7086888SPaul Brook for (i = 0; i < 32; i++) { 634067a3ddcSPaul Brook pic[i] = qdev_get_gpio_in(dev, i); 635a7086888SPaul Brook } 63683d0cf89SJan Kiszka sic = sysbus_create_simple(TYPE_INTEGRATOR_PIC, 0xca000000, pic[26]); 6376a824ec3SPaul Brook sysbus_create_varargs("integrator_pit", 0x13000000, 6386a824ec3SPaul Brook pic[5], pic[6], pic[7], NULL); 639a63bdb31SPaul Brook sysbus_create_simple("pl031", 0x15000000, pic[8]); 6409bca0edbSPeter Maydell pl011_create(0x16000000, pic[1], serial_hd(0)); 6419bca0edbSPeter Maydell pl011_create(0x17000000, pic[2], serial_hd(1)); 64283d0cf89SJan Kiszka icp = sysbus_create_simple(TYPE_ICP_CONTROL_REGS, 0xcb000000, 64383d0cf89SJan Kiszka qdev_get_gpio_in(sic, 3)); 64486394e96SPaul Brook sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]); 64586394e96SPaul Brook sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]); 646b8616055SAlex Bennée sysbus_create_simple(TYPE_INTEGRATOR_DEBUG, 0x1a000000, 0); 64783d0cf89SJan Kiszka 64883d0cf89SJan Kiszka dev = sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL); 64926c5b0f4SPhilippe Mathieu-Daudé qdev_connect_gpio_out_named(dev, "card-read-only", 0, 65083d0cf89SJan Kiszka qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_WPROT, 0)); 65126c5b0f4SPhilippe Mathieu-Daudé qdev_connect_gpio_out_named(dev, "card-inserted", 0, 65283d0cf89SJan Kiszka qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_CARDIN, 0)); 65364eaa820SMarkus Armbruster dinfo = drive_get(IF_SD, 0, 0); 65426c607b8SPhilippe Mathieu-Daudé if (dinfo) { 65526c607b8SPhilippe Mathieu-Daudé DeviceState *card; 65626c607b8SPhilippe Mathieu-Daudé 65726c607b8SPhilippe Mathieu-Daudé card = qdev_new(TYPE_SD_CARD); 65826c607b8SPhilippe Mathieu-Daudé qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo), 65926c607b8SPhilippe Mathieu-Daudé &error_fatal); 66026c607b8SPhilippe Mathieu-Daudé qdev_realize_and_unref(card, qdev_get_child_bus(dev, "sd-bus"), 66126c607b8SPhilippe Mathieu-Daudé &error_fatal); 66226c607b8SPhilippe Mathieu-Daudé } 66326c607b8SPhilippe Mathieu-Daudé 664*b8ab0303SMartin Kletzander dev = qdev_new("pl041"); 665*b8ab0303SMartin Kletzander if (machine->audiodev) { 666*b8ab0303SMartin Kletzander qdev_prop_set_string(dev, "audiodev", machine->audiodev); 667*b8ab0303SMartin Kletzander } 668*b8ab0303SMartin Kletzander sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); 669*b8ab0303SMartin Kletzander sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x1d000000); 670*b8ab0303SMartin Kletzander sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[25]); 67183d0cf89SJan Kiszka 672a005d073SStefan Hajnoczi if (nd_table[0].used) 673d537cf6cSpbrook smc91c111_init(&nd_table[0], 0xc8000000, pic[27]); 6742e9bdce5SPaul Brook 6752e9bdce5SPaul Brook sysbus_create_simple("pl110", 0xc0000000, pic[22]); 676b5ff1b31Sbellard 677f93eb9ffSbalrog integrator_binfo.ram_size = ram_size; 6782744ece8STao Xu arm_load_kernel(cpu, machine, &integrator_binfo); 679b5ff1b31Sbellard } 680b5ff1b31Sbellard 681e264d29dSEduardo Habkost static void integratorcp_machine_init(MachineClass *mc) 682f80f9ec9SAnthony Liguori { 683e264d29dSEduardo Habkost mc->desc = "ARM Integrator/CP (ARM926EJ-S)"; 684e264d29dSEduardo Habkost mc->init = integratorcp_init; 6854672cbd7SPeter Maydell mc->ignore_memory_transaction_failures = true; 686ba1ba5ccSIgor Mammedov mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926"); 6873f25b3f4SIgor Mammedov mc->default_ram_id = "integrator.ram"; 688*b8ab0303SMartin Kletzander 689*b8ab0303SMartin Kletzander machine_add_audiodev_property(mc); 690f80f9ec9SAnthony Liguori } 691f80f9ec9SAnthony Liguori 692e264d29dSEduardo Habkost DEFINE_MACHINE("integratorcp", integratorcp_machine_init) 693f80f9ec9SAnthony Liguori 694999e12bbSAnthony Liguori static Property core_properties[] = { 695257ec289SAndreas Färber DEFINE_PROP_UINT32("memsz", IntegratorCMState, memsz, 0), 696bb36f66aSGerd Hoffmann DEFINE_PROP_END_OF_LIST(), 697999e12bbSAnthony Liguori }; 698999e12bbSAnthony Liguori 699999e12bbSAnthony Liguori static void core_class_init(ObjectClass *klass, void *data) 700999e12bbSAnthony Liguori { 70139bffca2SAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 702999e12bbSAnthony Liguori 7034f67d30bSMarc-André Lureau device_class_set_props(dc, core_properties); 704e9d9ee23SJakub Jermar dc->realize = integratorcm_realize; 70526d32022SPavel Dovgalyuk dc->vmsd = &vmstate_integratorcm; 70626d32022SPavel Dovgalyuk } 70726d32022SPavel Dovgalyuk 70826d32022SPavel Dovgalyuk static void icp_pic_class_init(ObjectClass *klass, void *data) 70926d32022SPavel Dovgalyuk { 71026d32022SPavel Dovgalyuk DeviceClass *dc = DEVICE_CLASS(klass); 71126d32022SPavel Dovgalyuk 71226d32022SPavel Dovgalyuk dc->vmsd = &vmstate_icp_pic; 71326d32022SPavel Dovgalyuk } 71426d32022SPavel Dovgalyuk 71526d32022SPavel Dovgalyuk static void icp_control_class_init(ObjectClass *klass, void *data) 71626d32022SPavel Dovgalyuk { 71726d32022SPavel Dovgalyuk DeviceClass *dc = DEVICE_CLASS(klass); 71826d32022SPavel Dovgalyuk 71926d32022SPavel Dovgalyuk dc->vmsd = &vmstate_icp_control; 720ee6847d1SGerd Hoffmann } 721999e12bbSAnthony Liguori 7228c43a6f0SAndreas Färber static const TypeInfo core_info = { 723257ec289SAndreas Färber .name = TYPE_INTEGRATOR_CM, 72439bffca2SAnthony Liguori .parent = TYPE_SYS_BUS_DEVICE, 725257ec289SAndreas Färber .instance_size = sizeof(IntegratorCMState), 726a1f42e0cSxiaoqiang.zhao .instance_init = integratorcm_init, 727999e12bbSAnthony Liguori .class_init = core_class_init, 728999e12bbSAnthony Liguori }; 729999e12bbSAnthony Liguori 7308c43a6f0SAndreas Färber static const TypeInfo icp_pic_info = { 73191b64626SAndreas Färber .name = TYPE_INTEGRATOR_PIC, 73239bffca2SAnthony Liguori .parent = TYPE_SYS_BUS_DEVICE, 73339bffca2SAnthony Liguori .instance_size = sizeof(icp_pic_state), 734a1f42e0cSxiaoqiang.zhao .instance_init = icp_pic_init, 73526d32022SPavel Dovgalyuk .class_init = icp_pic_class_init, 736ee6847d1SGerd Hoffmann }; 737ee6847d1SGerd Hoffmann 738ffc8542aSJan Kiszka static const TypeInfo icp_ctrl_regs_info = { 739ffc8542aSJan Kiszka .name = TYPE_ICP_CONTROL_REGS, 740ffc8542aSJan Kiszka .parent = TYPE_SYS_BUS_DEVICE, 741ffc8542aSJan Kiszka .instance_size = sizeof(ICPCtrlRegsState), 742ffc8542aSJan Kiszka .instance_init = icp_control_init, 74326d32022SPavel Dovgalyuk .class_init = icp_control_class_init, 744ffc8542aSJan Kiszka }; 745ffc8542aSJan Kiszka 74683f7d43aSAndreas Färber static void integratorcp_register_types(void) 747a7086888SPaul Brook { 74839bffca2SAnthony Liguori type_register_static(&icp_pic_info); 74939bffca2SAnthony Liguori type_register_static(&core_info); 750ffc8542aSJan Kiszka type_register_static(&icp_ctrl_regs_info); 751a7086888SPaul Brook } 752a7086888SPaul Brook 75383f7d43aSAndreas Färber type_init(integratorcp_register_types) 754