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 "qemu-common.h" 134771d756SPaolo Bonzini #include "cpu.h" 1483c9f4caSPaolo Bonzini #include "hw/sysbus.h" 15bd2be150SPeter Maydell #include "hw/devices.h" 1683c9f4caSPaolo Bonzini #include "hw/boards.h" 17bd2be150SPeter Maydell #include "hw/arm/arm.h" 18b8616055SAlex Bennée #include "hw/misc/arm_integrator_debug.h" 191422e32dSPaolo Bonzini #include "net/net.h" 20022c62cbSPaolo Bonzini #include "exec/address-spaces.h" 219c17d615SPaolo Bonzini #include "sysemu/sysemu.h" 22223a72f1SGreg Bellows #include "qemu/error-report.h" 23f0d1d2c1Sxiaoqiang zhao #include "hw/char/pl011.h" 24b5ff1b31Sbellard 25257ec289SAndreas Färber #define TYPE_INTEGRATOR_CM "integrator_core" 26257ec289SAndreas Färber #define INTEGRATOR_CM(obj) \ 27257ec289SAndreas Färber OBJECT_CHECK(IntegratorCMState, (obj), TYPE_INTEGRATOR_CM) 28257ec289SAndreas Färber 29257ec289SAndreas Färber typedef struct IntegratorCMState { 30257ec289SAndreas Färber /*< private >*/ 31257ec289SAndreas Färber SysBusDevice parent_obj; 32257ec289SAndreas Färber /*< public >*/ 33257ec289SAndreas Färber 3471d9bc50SBenoît Canet MemoryRegion iomem; 35ee6847d1SGerd Hoffmann uint32_t memsz; 36211adf4dSAvi Kivity MemoryRegion flash; 37b5ff1b31Sbellard uint32_t cm_osc; 38b5ff1b31Sbellard uint32_t cm_ctrl; 39b5ff1b31Sbellard uint32_t cm_lock; 40b5ff1b31Sbellard uint32_t cm_auxosc; 41b5ff1b31Sbellard uint32_t cm_sdram; 42b5ff1b31Sbellard uint32_t cm_init; 43b5ff1b31Sbellard uint32_t cm_flags; 44b5ff1b31Sbellard uint32_t cm_nvflags; 45f53977f7SJan Petrous uint32_t cm_refcnt_offset; 46b5ff1b31Sbellard uint32_t int_level; 47b5ff1b31Sbellard uint32_t irq_enabled; 48b5ff1b31Sbellard uint32_t fiq_enabled; 49257ec289SAndreas Färber } IntegratorCMState; 50b5ff1b31Sbellard 51b5ff1b31Sbellard static uint8_t integrator_spd[128] = { 52b5ff1b31Sbellard 128, 8, 4, 11, 9, 1, 64, 0, 2, 0xa0, 0xa0, 0, 0, 8, 0, 1, 53b5ff1b31Sbellard 0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40 54b5ff1b31Sbellard }; 55b5ff1b31Sbellard 5626d32022SPavel Dovgalyuk static const VMStateDescription vmstate_integratorcm = { 5726d32022SPavel Dovgalyuk .name = "integratorcm", 5826d32022SPavel Dovgalyuk .version_id = 1, 5926d32022SPavel Dovgalyuk .minimum_version_id = 1, 6026d32022SPavel Dovgalyuk .fields = (VMStateField[]) { 6126d32022SPavel Dovgalyuk VMSTATE_UINT32(cm_osc, IntegratorCMState), 6226d32022SPavel Dovgalyuk VMSTATE_UINT32(cm_ctrl, IntegratorCMState), 6326d32022SPavel Dovgalyuk VMSTATE_UINT32(cm_lock, IntegratorCMState), 6426d32022SPavel Dovgalyuk VMSTATE_UINT32(cm_auxosc, IntegratorCMState), 6526d32022SPavel Dovgalyuk VMSTATE_UINT32(cm_sdram, IntegratorCMState), 6626d32022SPavel Dovgalyuk VMSTATE_UINT32(cm_init, IntegratorCMState), 6726d32022SPavel Dovgalyuk VMSTATE_UINT32(cm_flags, IntegratorCMState), 6826d32022SPavel Dovgalyuk VMSTATE_UINT32(cm_nvflags, IntegratorCMState), 6926d32022SPavel Dovgalyuk VMSTATE_UINT32(int_level, IntegratorCMState), 7026d32022SPavel Dovgalyuk VMSTATE_UINT32(irq_enabled, IntegratorCMState), 7126d32022SPavel Dovgalyuk VMSTATE_UINT32(fiq_enabled, IntegratorCMState), 7226d32022SPavel Dovgalyuk VMSTATE_END_OF_LIST() 7326d32022SPavel Dovgalyuk } 7426d32022SPavel Dovgalyuk }; 7526d32022SPavel Dovgalyuk 76a8170e5eSAvi Kivity static uint64_t integratorcm_read(void *opaque, hwaddr offset, 7771d9bc50SBenoît Canet unsigned size) 78b5ff1b31Sbellard { 79257ec289SAndreas Färber IntegratorCMState *s = opaque; 80b5ff1b31Sbellard if (offset >= 0x100 && offset < 0x200) { 81b5ff1b31Sbellard /* CM_SPD */ 82b5ff1b31Sbellard if (offset >= 0x180) 83b5ff1b31Sbellard return 0; 84b5ff1b31Sbellard return integrator_spd[offset >> 2]; 85b5ff1b31Sbellard } 86b5ff1b31Sbellard switch (offset >> 2) { 87b5ff1b31Sbellard case 0: /* CM_ID */ 88b5ff1b31Sbellard return 0x411a3001; 89b5ff1b31Sbellard case 1: /* CM_PROC */ 90b5ff1b31Sbellard return 0; 91b5ff1b31Sbellard case 2: /* CM_OSC */ 92b5ff1b31Sbellard return s->cm_osc; 93b5ff1b31Sbellard case 3: /* CM_CTRL */ 94b5ff1b31Sbellard return s->cm_ctrl; 95b5ff1b31Sbellard case 4: /* CM_STAT */ 96b5ff1b31Sbellard return 0x00100000; 97b5ff1b31Sbellard case 5: /* CM_LOCK */ 98b5ff1b31Sbellard if (s->cm_lock == 0xa05f) { 99b5ff1b31Sbellard return 0x1a05f; 100b5ff1b31Sbellard } else { 101b5ff1b31Sbellard return s->cm_lock; 102b5ff1b31Sbellard } 103b5ff1b31Sbellard case 6: /* CM_LMBUSCNT */ 104b5ff1b31Sbellard /* ??? High frequency timer. */ 1052ac71179SPaul Brook hw_error("integratorcm_read: CM_LMBUSCNT"); 106b5ff1b31Sbellard case 7: /* CM_AUXOSC */ 107b5ff1b31Sbellard return s->cm_auxosc; 108b5ff1b31Sbellard case 8: /* CM_SDRAM */ 109b5ff1b31Sbellard return s->cm_sdram; 110b5ff1b31Sbellard case 9: /* CM_INIT */ 111b5ff1b31Sbellard return s->cm_init; 112f53977f7SJan Petrous case 10: /* CM_REFCNT */ 113f53977f7SJan Petrous /* This register, CM_REFCNT, provides a 32-bit count value. 114f53977f7SJan Petrous * The count increments at the fixed reference clock frequency of 24MHz 115f53977f7SJan Petrous * and can be used as a real-time counter. 116f53977f7SJan Petrous */ 117f53977f7SJan Petrous return (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24, 118f53977f7SJan Petrous 1000) - s->cm_refcnt_offset; 119b5ff1b31Sbellard case 12: /* CM_FLAGS */ 120b5ff1b31Sbellard return s->cm_flags; 121b5ff1b31Sbellard case 14: /* CM_NVFLAGS */ 122b5ff1b31Sbellard return s->cm_nvflags; 123b5ff1b31Sbellard case 16: /* CM_IRQ_STAT */ 124b5ff1b31Sbellard return s->int_level & s->irq_enabled; 125b5ff1b31Sbellard case 17: /* CM_IRQ_RSTAT */ 126b5ff1b31Sbellard return s->int_level; 127b5ff1b31Sbellard case 18: /* CM_IRQ_ENSET */ 128b5ff1b31Sbellard return s->irq_enabled; 129b5ff1b31Sbellard case 20: /* CM_SOFT_INTSET */ 130b5ff1b31Sbellard return s->int_level & 1; 131b5ff1b31Sbellard case 24: /* CM_FIQ_STAT */ 132b5ff1b31Sbellard return s->int_level & s->fiq_enabled; 133b5ff1b31Sbellard case 25: /* CM_FIQ_RSTAT */ 134b5ff1b31Sbellard return s->int_level; 135b5ff1b31Sbellard case 26: /* CM_FIQ_ENSET */ 136b5ff1b31Sbellard return s->fiq_enabled; 137b5ff1b31Sbellard case 32: /* CM_VOLTAGE_CTL0 */ 138b5ff1b31Sbellard case 33: /* CM_VOLTAGE_CTL1 */ 139b5ff1b31Sbellard case 34: /* CM_VOLTAGE_CTL2 */ 140b5ff1b31Sbellard case 35: /* CM_VOLTAGE_CTL3 */ 141b5ff1b31Sbellard /* ??? Voltage control unimplemented. */ 142b5ff1b31Sbellard return 0; 143b5ff1b31Sbellard default: 1442ac71179SPaul Brook hw_error("integratorcm_read: Unimplemented offset 0x%x\n", 1452ac71179SPaul Brook (int)offset); 146b5ff1b31Sbellard return 0; 147b5ff1b31Sbellard } 148b5ff1b31Sbellard } 149b5ff1b31Sbellard 150257ec289SAndreas Färber static void integratorcm_do_remap(IntegratorCMState *s) 151b5ff1b31Sbellard { 152563c2bf3SPeter Maydell /* Sync memory region state with CM_CTRL REMAP bit: 153563c2bf3SPeter Maydell * bit 0 => flash at address 0; bit 1 => RAM 154563c2bf3SPeter Maydell */ 155563c2bf3SPeter Maydell memory_region_set_enabled(&s->flash, !(s->cm_ctrl & 4)); 156b5ff1b31Sbellard } 157b5ff1b31Sbellard 158257ec289SAndreas Färber static void integratorcm_set_ctrl(IntegratorCMState *s, uint32_t value) 159b5ff1b31Sbellard { 160b5ff1b31Sbellard if (value & 8) { 161cf83f140SEric Blake qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); 162b5ff1b31Sbellard } 163df3f457bSPeter Maydell if ((s->cm_ctrl ^ value) & 1) { 164df3f457bSPeter Maydell /* (value & 1) != 0 means the green "MISC LED" is lit. 165df3f457bSPeter Maydell * We don't have any nice place to display LEDs. printf is a bad 166df3f457bSPeter Maydell * idea because Linux uses the LED as a heartbeat and the output 167df3f457bSPeter Maydell * will swamp anything else on the terminal. 168df3f457bSPeter Maydell */ 169b5ff1b31Sbellard } 170df3f457bSPeter Maydell /* Note that the RESET bit [3] always reads as zero */ 171df3f457bSPeter Maydell s->cm_ctrl = (s->cm_ctrl & ~5) | (value & 5); 172563c2bf3SPeter Maydell integratorcm_do_remap(s); 173b5ff1b31Sbellard } 174b5ff1b31Sbellard 175257ec289SAndreas Färber static void integratorcm_update(IntegratorCMState *s) 176b5ff1b31Sbellard { 177b5ff1b31Sbellard /* ??? The CPU irq/fiq is raised when either the core module or base PIC 178b5ff1b31Sbellard are active. */ 179b5ff1b31Sbellard if (s->int_level & (s->irq_enabled | s->fiq_enabled)) 1802ac71179SPaul Brook hw_error("Core module interrupt\n"); 181b5ff1b31Sbellard } 182b5ff1b31Sbellard 183a8170e5eSAvi Kivity static void integratorcm_write(void *opaque, hwaddr offset, 18471d9bc50SBenoît Canet uint64_t value, unsigned size) 185b5ff1b31Sbellard { 186257ec289SAndreas Färber IntegratorCMState *s = opaque; 187b5ff1b31Sbellard switch (offset >> 2) { 188b5ff1b31Sbellard case 2: /* CM_OSC */ 189b5ff1b31Sbellard if (s->cm_lock == 0xa05f) 190b5ff1b31Sbellard s->cm_osc = value; 191b5ff1b31Sbellard break; 192b5ff1b31Sbellard case 3: /* CM_CTRL */ 193b5ff1b31Sbellard integratorcm_set_ctrl(s, value); 194b5ff1b31Sbellard break; 195b5ff1b31Sbellard case 5: /* CM_LOCK */ 196b5ff1b31Sbellard s->cm_lock = value & 0xffff; 197b5ff1b31Sbellard break; 198b5ff1b31Sbellard case 7: /* CM_AUXOSC */ 199b5ff1b31Sbellard if (s->cm_lock == 0xa05f) 200b5ff1b31Sbellard s->cm_auxosc = value; 201b5ff1b31Sbellard break; 202b5ff1b31Sbellard case 8: /* CM_SDRAM */ 203b5ff1b31Sbellard s->cm_sdram = value; 204b5ff1b31Sbellard break; 205b5ff1b31Sbellard case 9: /* CM_INIT */ 206b5ff1b31Sbellard /* ??? This can change the memory bus frequency. */ 207b5ff1b31Sbellard s->cm_init = value; 208b5ff1b31Sbellard break; 209b5ff1b31Sbellard case 12: /* CM_FLAGSS */ 210b5ff1b31Sbellard s->cm_flags |= value; 211b5ff1b31Sbellard break; 212b5ff1b31Sbellard case 13: /* CM_FLAGSC */ 213b5ff1b31Sbellard s->cm_flags &= ~value; 214b5ff1b31Sbellard break; 215b5ff1b31Sbellard case 14: /* CM_NVFLAGSS */ 216b5ff1b31Sbellard s->cm_nvflags |= value; 217b5ff1b31Sbellard break; 218b5ff1b31Sbellard case 15: /* CM_NVFLAGSS */ 219b5ff1b31Sbellard s->cm_nvflags &= ~value; 220b5ff1b31Sbellard break; 221b5ff1b31Sbellard case 18: /* CM_IRQ_ENSET */ 222b5ff1b31Sbellard s->irq_enabled |= value; 223b5ff1b31Sbellard integratorcm_update(s); 224b5ff1b31Sbellard break; 225b5ff1b31Sbellard case 19: /* CM_IRQ_ENCLR */ 226b5ff1b31Sbellard s->irq_enabled &= ~value; 227b5ff1b31Sbellard integratorcm_update(s); 228b5ff1b31Sbellard break; 229b5ff1b31Sbellard case 20: /* CM_SOFT_INTSET */ 230b5ff1b31Sbellard s->int_level |= (value & 1); 231b5ff1b31Sbellard integratorcm_update(s); 232b5ff1b31Sbellard break; 233b5ff1b31Sbellard case 21: /* CM_SOFT_INTCLR */ 234b5ff1b31Sbellard s->int_level &= ~(value & 1); 235b5ff1b31Sbellard integratorcm_update(s); 236b5ff1b31Sbellard break; 237b5ff1b31Sbellard case 26: /* CM_FIQ_ENSET */ 238b5ff1b31Sbellard s->fiq_enabled |= value; 239b5ff1b31Sbellard integratorcm_update(s); 240b5ff1b31Sbellard break; 241b5ff1b31Sbellard case 27: /* CM_FIQ_ENCLR */ 242b5ff1b31Sbellard s->fiq_enabled &= ~value; 243b5ff1b31Sbellard integratorcm_update(s); 244b5ff1b31Sbellard break; 245b5ff1b31Sbellard case 32: /* CM_VOLTAGE_CTL0 */ 246b5ff1b31Sbellard case 33: /* CM_VOLTAGE_CTL1 */ 247b5ff1b31Sbellard case 34: /* CM_VOLTAGE_CTL2 */ 248b5ff1b31Sbellard case 35: /* CM_VOLTAGE_CTL3 */ 249b5ff1b31Sbellard /* ??? Voltage control unimplemented. */ 250b5ff1b31Sbellard break; 251b5ff1b31Sbellard default: 2522ac71179SPaul Brook hw_error("integratorcm_write: Unimplemented offset 0x%x\n", 2532ac71179SPaul Brook (int)offset); 254b5ff1b31Sbellard break; 255b5ff1b31Sbellard } 256b5ff1b31Sbellard } 257b5ff1b31Sbellard 258b5ff1b31Sbellard /* Integrator/CM control registers. */ 259b5ff1b31Sbellard 26071d9bc50SBenoît Canet static const MemoryRegionOps integratorcm_ops = { 26171d9bc50SBenoît Canet .read = integratorcm_read, 26271d9bc50SBenoît Canet .write = integratorcm_write, 26371d9bc50SBenoît Canet .endianness = DEVICE_NATIVE_ENDIAN, 264b5ff1b31Sbellard }; 265b5ff1b31Sbellard 266a1f42e0cSxiaoqiang.zhao static void integratorcm_init(Object *obj) 267b5ff1b31Sbellard { 268a1f42e0cSxiaoqiang.zhao IntegratorCMState *s = INTEGRATOR_CM(obj); 269b5ff1b31Sbellard 270b5ff1b31Sbellard s->cm_osc = 0x01000048; 271b5ff1b31Sbellard /* ??? What should the high bits of this value be? */ 272b5ff1b31Sbellard s->cm_auxosc = 0x0007feff; 273b5ff1b31Sbellard s->cm_sdram = 0x00011122; 274e9d9ee23SJakub Jermar memcpy(integrator_spd + 73, "QEMU-MEMORY", 11); 275e9d9ee23SJakub Jermar s->cm_init = 0x00000112; 276e9d9ee23SJakub Jermar s->cm_refcnt_offset = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24, 277e9d9ee23SJakub Jermar 1000); 278e9d9ee23SJakub Jermar 279e9d9ee23SJakub Jermar /* ??? Save/restore. */ 280e9d9ee23SJakub Jermar } 281e9d9ee23SJakub Jermar 282e9d9ee23SJakub Jermar static void integratorcm_realize(DeviceState *d, Error **errp) 283e9d9ee23SJakub Jermar { 284e9d9ee23SJakub Jermar IntegratorCMState *s = INTEGRATOR_CM(d); 2858720daadSThomas Huth SysBusDevice *dev = SYS_BUS_DEVICE(d); 2868720daadSThomas Huth Error *local_err = NULL; 2878720daadSThomas Huth 2888720daadSThomas Huth memory_region_init_ram(&s->flash, OBJECT(d), "integrator.flash", 0x100000, 2898720daadSThomas Huth &local_err); 2908720daadSThomas Huth if (local_err) { 2918720daadSThomas Huth error_propagate(errp, local_err); 2928720daadSThomas Huth return; 2938720daadSThomas Huth } 2948720daadSThomas Huth 2958720daadSThomas Huth memory_region_init_io(&s->iomem, OBJECT(d), &integratorcm_ops, s, 2968720daadSThomas Huth "integratorcm", 0x00800000); 2978720daadSThomas Huth sysbus_init_mmio(dev, &s->iomem); 2988720daadSThomas Huth 2998720daadSThomas Huth integratorcm_do_remap(s); 300e9d9ee23SJakub Jermar 301ee6847d1SGerd Hoffmann if (s->memsz >= 256) { 302b5ff1b31Sbellard integrator_spd[31] = 64; 303b5ff1b31Sbellard s->cm_sdram |= 0x10; 304ee6847d1SGerd Hoffmann } else if (s->memsz >= 128) { 305b5ff1b31Sbellard integrator_spd[31] = 32; 306b5ff1b31Sbellard s->cm_sdram |= 0x0c; 307ee6847d1SGerd Hoffmann } else if (s->memsz >= 64) { 308b5ff1b31Sbellard integrator_spd[31] = 16; 309b5ff1b31Sbellard s->cm_sdram |= 0x08; 310ee6847d1SGerd Hoffmann } else if (s->memsz >= 32) { 311b5ff1b31Sbellard integrator_spd[31] = 4; 312b5ff1b31Sbellard s->cm_sdram |= 0x04; 313b5ff1b31Sbellard } else { 314b5ff1b31Sbellard integrator_spd[31] = 2; 315b5ff1b31Sbellard } 316b5ff1b31Sbellard } 317b5ff1b31Sbellard 318b5ff1b31Sbellard /* Integrator/CP hardware emulation. */ 319b5ff1b31Sbellard /* Primary interrupt controller. */ 320b5ff1b31Sbellard 32191b64626SAndreas Färber #define TYPE_INTEGRATOR_PIC "integrator_pic" 32291b64626SAndreas Färber #define INTEGRATOR_PIC(obj) \ 32391b64626SAndreas Färber OBJECT_CHECK(icp_pic_state, (obj), TYPE_INTEGRATOR_PIC) 32491b64626SAndreas Färber 32591b64626SAndreas Färber typedef struct icp_pic_state { 32691b64626SAndreas Färber /*< private >*/ 32791b64626SAndreas Färber SysBusDevice parent_obj; 32891b64626SAndreas Färber /*< public >*/ 32991b64626SAndreas Färber 33061074e46SBenoît Canet MemoryRegion iomem; 331b5ff1b31Sbellard uint32_t level; 332b5ff1b31Sbellard uint32_t irq_enabled; 333b5ff1b31Sbellard uint32_t fiq_enabled; 334d537cf6cSpbrook qemu_irq parent_irq; 335d537cf6cSpbrook qemu_irq parent_fiq; 336b5ff1b31Sbellard } icp_pic_state; 337b5ff1b31Sbellard 33826d32022SPavel Dovgalyuk static const VMStateDescription vmstate_icp_pic = { 33926d32022SPavel Dovgalyuk .name = "icp_pic", 34026d32022SPavel Dovgalyuk .version_id = 1, 34126d32022SPavel Dovgalyuk .minimum_version_id = 1, 34226d32022SPavel Dovgalyuk .fields = (VMStateField[]) { 34326d32022SPavel Dovgalyuk VMSTATE_UINT32(level, icp_pic_state), 34426d32022SPavel Dovgalyuk VMSTATE_UINT32(irq_enabled, icp_pic_state), 34526d32022SPavel Dovgalyuk VMSTATE_UINT32(fiq_enabled, icp_pic_state), 34626d32022SPavel Dovgalyuk VMSTATE_END_OF_LIST() 34726d32022SPavel Dovgalyuk } 34826d32022SPavel Dovgalyuk }; 34926d32022SPavel Dovgalyuk 350b5ff1b31Sbellard static void icp_pic_update(icp_pic_state *s) 351b5ff1b31Sbellard { 352b5ff1b31Sbellard uint32_t flags; 353b5ff1b31Sbellard 354b5ff1b31Sbellard flags = (s->level & s->irq_enabled); 355d537cf6cSpbrook qemu_set_irq(s->parent_irq, flags != 0); 356cdbdb648Spbrook flags = (s->level & s->fiq_enabled); 357d537cf6cSpbrook qemu_set_irq(s->parent_fiq, flags != 0); 358b5ff1b31Sbellard } 359b5ff1b31Sbellard 360cdbdb648Spbrook static void icp_pic_set_irq(void *opaque, int irq, int level) 361b5ff1b31Sbellard { 36280337b66Sbellard icp_pic_state *s = (icp_pic_state *)opaque; 363b5ff1b31Sbellard if (level) 36480337b66Sbellard s->level |= 1 << irq; 365b5ff1b31Sbellard else 36680337b66Sbellard s->level &= ~(1 << irq); 367b5ff1b31Sbellard icp_pic_update(s); 368b5ff1b31Sbellard } 369b5ff1b31Sbellard 370a8170e5eSAvi Kivity static uint64_t icp_pic_read(void *opaque, hwaddr offset, 37161074e46SBenoît Canet unsigned size) 372b5ff1b31Sbellard { 373b5ff1b31Sbellard icp_pic_state *s = (icp_pic_state *)opaque; 374b5ff1b31Sbellard 375b5ff1b31Sbellard switch (offset >> 2) { 376b5ff1b31Sbellard case 0: /* IRQ_STATUS */ 377b5ff1b31Sbellard return s->level & s->irq_enabled; 378b5ff1b31Sbellard case 1: /* IRQ_RAWSTAT */ 379b5ff1b31Sbellard return s->level; 380b5ff1b31Sbellard case 2: /* IRQ_ENABLESET */ 381b5ff1b31Sbellard return s->irq_enabled; 382b5ff1b31Sbellard case 4: /* INT_SOFTSET */ 383b5ff1b31Sbellard return s->level & 1; 384b5ff1b31Sbellard case 8: /* FRQ_STATUS */ 385b5ff1b31Sbellard return s->level & s->fiq_enabled; 386b5ff1b31Sbellard case 9: /* FRQ_RAWSTAT */ 387b5ff1b31Sbellard return s->level; 388b5ff1b31Sbellard case 10: /* FRQ_ENABLESET */ 389b5ff1b31Sbellard return s->fiq_enabled; 390b5ff1b31Sbellard case 3: /* IRQ_ENABLECLR */ 391b5ff1b31Sbellard case 5: /* INT_SOFTCLR */ 392b5ff1b31Sbellard case 11: /* FRQ_ENABLECLR */ 393b5ff1b31Sbellard default: 39429bfb117Spbrook printf ("icp_pic_read: Bad register offset 0x%x\n", (int)offset); 395b5ff1b31Sbellard return 0; 396b5ff1b31Sbellard } 397b5ff1b31Sbellard } 398b5ff1b31Sbellard 399a8170e5eSAvi Kivity static void icp_pic_write(void *opaque, hwaddr offset, 40061074e46SBenoît Canet uint64_t value, unsigned size) 401b5ff1b31Sbellard { 402b5ff1b31Sbellard icp_pic_state *s = (icp_pic_state *)opaque; 403b5ff1b31Sbellard 404b5ff1b31Sbellard switch (offset >> 2) { 405b5ff1b31Sbellard case 2: /* IRQ_ENABLESET */ 406b5ff1b31Sbellard s->irq_enabled |= value; 407b5ff1b31Sbellard break; 408b5ff1b31Sbellard case 3: /* IRQ_ENABLECLR */ 409b5ff1b31Sbellard s->irq_enabled &= ~value; 410b5ff1b31Sbellard break; 411b5ff1b31Sbellard case 4: /* INT_SOFTSET */ 412b5ff1b31Sbellard if (value & 1) 413d537cf6cSpbrook icp_pic_set_irq(s, 0, 1); 414b5ff1b31Sbellard break; 415b5ff1b31Sbellard case 5: /* INT_SOFTCLR */ 416b5ff1b31Sbellard if (value & 1) 417d537cf6cSpbrook icp_pic_set_irq(s, 0, 0); 418b5ff1b31Sbellard break; 419b5ff1b31Sbellard case 10: /* FRQ_ENABLESET */ 420b5ff1b31Sbellard s->fiq_enabled |= value; 421b5ff1b31Sbellard break; 422b5ff1b31Sbellard case 11: /* FRQ_ENABLECLR */ 423b5ff1b31Sbellard s->fiq_enabled &= ~value; 424b5ff1b31Sbellard break; 425b5ff1b31Sbellard case 0: /* IRQ_STATUS */ 426b5ff1b31Sbellard case 1: /* IRQ_RAWSTAT */ 427b5ff1b31Sbellard case 8: /* FRQ_STATUS */ 428b5ff1b31Sbellard case 9: /* FRQ_RAWSTAT */ 429b5ff1b31Sbellard default: 43029bfb117Spbrook printf ("icp_pic_write: Bad register offset 0x%x\n", (int)offset); 431b5ff1b31Sbellard return; 432b5ff1b31Sbellard } 433b5ff1b31Sbellard icp_pic_update(s); 434b5ff1b31Sbellard } 435b5ff1b31Sbellard 43661074e46SBenoît Canet static const MemoryRegionOps icp_pic_ops = { 43761074e46SBenoît Canet .read = icp_pic_read, 43861074e46SBenoît Canet .write = icp_pic_write, 43961074e46SBenoît Canet .endianness = DEVICE_NATIVE_ENDIAN, 440b5ff1b31Sbellard }; 441b5ff1b31Sbellard 442a1f42e0cSxiaoqiang.zhao static void icp_pic_init(Object *obj) 443b5ff1b31Sbellard { 444a1f42e0cSxiaoqiang.zhao DeviceState *dev = DEVICE(obj); 445a1f42e0cSxiaoqiang.zhao icp_pic_state *s = INTEGRATOR_PIC(obj); 446a1f42e0cSxiaoqiang.zhao SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 447b5ff1b31Sbellard 44891b64626SAndreas Färber qdev_init_gpio_in(dev, icp_pic_set_irq, 32); 44991b64626SAndreas Färber sysbus_init_irq(sbd, &s->parent_irq); 45091b64626SAndreas Färber sysbus_init_irq(sbd, &s->parent_fiq); 451a1f42e0cSxiaoqiang.zhao memory_region_init_io(&s->iomem, obj, &icp_pic_ops, s, 45264bde0f3SPaolo Bonzini "icp-pic", 0x00800000); 45391b64626SAndreas Färber sysbus_init_mmio(sbd, &s->iomem); 454b5ff1b31Sbellard } 455b5ff1b31Sbellard 456b5ff1b31Sbellard /* CP control registers. */ 4570c36493eSBenoît Canet 458ffc8542aSJan Kiszka #define TYPE_ICP_CONTROL_REGS "icp-ctrl-regs" 459ffc8542aSJan Kiszka #define ICP_CONTROL_REGS(obj) \ 460ffc8542aSJan Kiszka OBJECT_CHECK(ICPCtrlRegsState, (obj), TYPE_ICP_CONTROL_REGS) 461ffc8542aSJan Kiszka 462ffc8542aSJan Kiszka typedef struct ICPCtrlRegsState { 463ffc8542aSJan Kiszka /*< private >*/ 464ffc8542aSJan Kiszka SysBusDevice parent_obj; 465ffc8542aSJan Kiszka /*< public >*/ 466ffc8542aSJan Kiszka 467ffc8542aSJan Kiszka MemoryRegion iomem; 46883d0cf89SJan Kiszka 46983d0cf89SJan Kiszka qemu_irq mmc_irq; 47083d0cf89SJan Kiszka uint32_t intreg_state; 471ffc8542aSJan Kiszka } ICPCtrlRegsState; 472ffc8542aSJan Kiszka 47383d0cf89SJan Kiszka #define ICP_GPIO_MMC_WPROT "mmc-wprot" 47483d0cf89SJan Kiszka #define ICP_GPIO_MMC_CARDIN "mmc-cardin" 47583d0cf89SJan Kiszka 47683d0cf89SJan Kiszka #define ICP_INTREG_WPROT (1 << 0) 47783d0cf89SJan Kiszka #define ICP_INTREG_CARDIN (1 << 3) 47883d0cf89SJan Kiszka 47926d32022SPavel Dovgalyuk static const VMStateDescription vmstate_icp_control = { 48026d32022SPavel Dovgalyuk .name = "icp_control", 48126d32022SPavel Dovgalyuk .version_id = 1, 48226d32022SPavel Dovgalyuk .minimum_version_id = 1, 48326d32022SPavel Dovgalyuk .fields = (VMStateField[]) { 48426d32022SPavel Dovgalyuk VMSTATE_UINT32(intreg_state, ICPCtrlRegsState), 48526d32022SPavel Dovgalyuk VMSTATE_END_OF_LIST() 48626d32022SPavel Dovgalyuk } 48726d32022SPavel Dovgalyuk }; 48826d32022SPavel Dovgalyuk 489a8170e5eSAvi Kivity static uint64_t icp_control_read(void *opaque, hwaddr offset, 4900c36493eSBenoît Canet unsigned size) 491b5ff1b31Sbellard { 49283d0cf89SJan Kiszka ICPCtrlRegsState *s = opaque; 49383d0cf89SJan Kiszka 494b5ff1b31Sbellard switch (offset >> 2) { 495b5ff1b31Sbellard case 0: /* CP_IDFIELD */ 496b5ff1b31Sbellard return 0x41034003; 497b5ff1b31Sbellard case 1: /* CP_FLASHPROG */ 498b5ff1b31Sbellard return 0; 499b5ff1b31Sbellard case 2: /* CP_INTREG */ 50083d0cf89SJan Kiszka return s->intreg_state; 501b5ff1b31Sbellard case 3: /* CP_DECODE */ 502b5ff1b31Sbellard return 0x11; 503b5ff1b31Sbellard default: 5042ac71179SPaul Brook hw_error("icp_control_read: Bad offset %x\n", (int)offset); 505b5ff1b31Sbellard return 0; 506b5ff1b31Sbellard } 507b5ff1b31Sbellard } 508b5ff1b31Sbellard 509a8170e5eSAvi Kivity static void icp_control_write(void *opaque, hwaddr offset, 5100c36493eSBenoît Canet uint64_t value, unsigned size) 511b5ff1b31Sbellard { 51283d0cf89SJan Kiszka ICPCtrlRegsState *s = opaque; 51383d0cf89SJan Kiszka 514b5ff1b31Sbellard switch (offset >> 2) { 515b5ff1b31Sbellard case 2: /* CP_INTREG */ 51683d0cf89SJan Kiszka s->intreg_state &= ~(value & ICP_INTREG_CARDIN); 51783d0cf89SJan Kiszka qemu_set_irq(s->mmc_irq, !!(s->intreg_state & ICP_INTREG_CARDIN)); 51883d0cf89SJan Kiszka break; 51983d0cf89SJan Kiszka case 1: /* CP_FLASHPROG */ 520b5ff1b31Sbellard case 3: /* CP_DECODE */ 521b5ff1b31Sbellard /* Nothing interesting implemented yet. */ 522b5ff1b31Sbellard break; 523b5ff1b31Sbellard default: 5242ac71179SPaul Brook hw_error("icp_control_write: Bad offset %x\n", (int)offset); 525b5ff1b31Sbellard } 526b5ff1b31Sbellard } 5270c36493eSBenoît Canet 5280c36493eSBenoît Canet static const MemoryRegionOps icp_control_ops = { 5290c36493eSBenoît Canet .read = icp_control_read, 5300c36493eSBenoît Canet .write = icp_control_write, 5310c36493eSBenoît Canet .endianness = DEVICE_NATIVE_ENDIAN, 532b5ff1b31Sbellard }; 533b5ff1b31Sbellard 53483d0cf89SJan Kiszka static void icp_control_mmc_wprot(void *opaque, int line, int level) 53583d0cf89SJan Kiszka { 53683d0cf89SJan Kiszka ICPCtrlRegsState *s = opaque; 53783d0cf89SJan Kiszka 53883d0cf89SJan Kiszka s->intreg_state &= ~ICP_INTREG_WPROT; 53983d0cf89SJan Kiszka if (level) { 54083d0cf89SJan Kiszka s->intreg_state |= ICP_INTREG_WPROT; 54183d0cf89SJan Kiszka } 54283d0cf89SJan Kiszka } 54383d0cf89SJan Kiszka 54483d0cf89SJan Kiszka static void icp_control_mmc_cardin(void *opaque, int line, int level) 54583d0cf89SJan Kiszka { 54683d0cf89SJan Kiszka ICPCtrlRegsState *s = opaque; 54783d0cf89SJan Kiszka 54883d0cf89SJan Kiszka /* line is released by writing to CP_INTREG */ 54983d0cf89SJan Kiszka if (level) { 55083d0cf89SJan Kiszka s->intreg_state |= ICP_INTREG_CARDIN; 55183d0cf89SJan Kiszka qemu_set_irq(s->mmc_irq, 1); 55283d0cf89SJan Kiszka } 55383d0cf89SJan Kiszka } 55483d0cf89SJan Kiszka 555ffc8542aSJan Kiszka static void icp_control_init(Object *obj) 556b5ff1b31Sbellard { 557ffc8542aSJan Kiszka SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 558ffc8542aSJan Kiszka ICPCtrlRegsState *s = ICP_CONTROL_REGS(obj); 55983d0cf89SJan Kiszka DeviceState *dev = DEVICE(obj); 560b5ff1b31Sbellard 561ffc8542aSJan Kiszka memory_region_init_io(&s->iomem, OBJECT(s), &icp_control_ops, s, 562ffc8542aSJan Kiszka "icp_ctrl_regs", 0x00800000); 563ffc8542aSJan Kiszka sysbus_init_mmio(sbd, &s->iomem); 56483d0cf89SJan Kiszka 56583d0cf89SJan Kiszka qdev_init_gpio_in_named(dev, icp_control_mmc_wprot, ICP_GPIO_MMC_WPROT, 1); 56683d0cf89SJan Kiszka qdev_init_gpio_in_named(dev, icp_control_mmc_cardin, 56783d0cf89SJan Kiszka ICP_GPIO_MMC_CARDIN, 1); 56883d0cf89SJan Kiszka sysbus_init_irq(sbd, &s->mmc_irq); 569b5ff1b31Sbellard } 570b5ff1b31Sbellard 571b5ff1b31Sbellard 572b5ff1b31Sbellard /* Board init. */ 573b5ff1b31Sbellard 574f93eb9ffSbalrog static struct arm_boot_info integrator_binfo = { 575f93eb9ffSbalrog .loader_start = 0x0, 576f93eb9ffSbalrog .board_id = 0x113, 577f93eb9ffSbalrog }; 578f93eb9ffSbalrog 5793ef96221SMarcel Apfelbaum static void integratorcp_init(MachineState *machine) 580b5ff1b31Sbellard { 5813ef96221SMarcel Apfelbaum ram_addr_t ram_size = machine->ram_size; 5823ef96221SMarcel Apfelbaum const char *kernel_filename = machine->kernel_filename; 5833ef96221SMarcel Apfelbaum const char *kernel_cmdline = machine->kernel_cmdline; 5843ef96221SMarcel Apfelbaum const char *initrd_filename = machine->initrd_filename; 585223a72f1SGreg Bellows Object *cpuobj; 586393a9eabSAndreas Färber ARMCPU *cpu; 587211adf4dSAvi Kivity MemoryRegion *address_space_mem = get_system_memory(); 588211adf4dSAvi Kivity MemoryRegion *ram = g_new(MemoryRegion, 1); 589211adf4dSAvi Kivity MemoryRegion *ram_alias = g_new(MemoryRegion, 1); 590a7086888SPaul Brook qemu_irq pic[32]; 59183d0cf89SJan Kiszka DeviceState *dev, *sic, *icp; 592a7086888SPaul Brook int i; 593b5ff1b31Sbellard 594ba1ba5ccSIgor Mammedov cpuobj = object_new(machine->cpu_type); 595223a72f1SGreg Bellows 59661e2f352SGreg Bellows /* By default ARM1176 CPUs have EL3 enabled. This board does not 59761e2f352SGreg Bellows * currently support EL3 so the CPU EL3 property is disabled before 59861e2f352SGreg Bellows * realization. 59961e2f352SGreg Bellows */ 60061e2f352SGreg Bellows if (object_property_find(cpuobj, "has_el3", NULL)) { 601007b0657SMarkus Armbruster object_property_set_bool(cpuobj, false, "has_el3", &error_fatal); 60261e2f352SGreg Bellows } 60361e2f352SGreg Bellows 604007b0657SMarkus Armbruster object_property_set_bool(cpuobj, true, "realized", &error_fatal); 605223a72f1SGreg Bellows 606223a72f1SGreg Bellows cpu = ARM_CPU(cpuobj); 607223a72f1SGreg Bellows 608c8623c02SDirk Müller memory_region_allocate_system_memory(ram, NULL, "integrator.ram", 609c8623c02SDirk Müller ram_size); 610b5ff1b31Sbellard /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash. */ 6111235fc06Sths /* ??? RAM should repeat to fill physical memory space. */ 612b5ff1b31Sbellard /* SDRAM at address zero*/ 613211adf4dSAvi Kivity memory_region_add_subregion(address_space_mem, 0, ram); 614b5ff1b31Sbellard /* And again at address 0x80000000 */ 6152c9b15caSPaolo Bonzini memory_region_init_alias(ram_alias, NULL, "ram.alias", ram, 0, ram_size); 616211adf4dSAvi Kivity memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias); 617b5ff1b31Sbellard 618257ec289SAndreas Färber dev = qdev_create(NULL, TYPE_INTEGRATOR_CM); 619ee6847d1SGerd Hoffmann qdev_prop_set_uint32(dev, "memsz", ram_size >> 20); 620e23a1b33SMarkus Armbruster qdev_init_nofail(dev); 621a7086888SPaul Brook sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000); 622a7086888SPaul Brook 62391b64626SAndreas Färber dev = sysbus_create_varargs(TYPE_INTEGRATOR_PIC, 0x14000000, 62499d228d6SPeter Maydell qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ), 62599d228d6SPeter Maydell qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ), 62699d228d6SPeter Maydell NULL); 627a7086888SPaul Brook for (i = 0; i < 32; i++) { 628067a3ddcSPaul Brook pic[i] = qdev_get_gpio_in(dev, i); 629a7086888SPaul Brook } 63083d0cf89SJan Kiszka sic = sysbus_create_simple(TYPE_INTEGRATOR_PIC, 0xca000000, pic[26]); 6316a824ec3SPaul Brook sysbus_create_varargs("integrator_pit", 0x13000000, 6326a824ec3SPaul Brook pic[5], pic[6], pic[7], NULL); 633a63bdb31SPaul Brook sysbus_create_simple("pl031", 0x15000000, pic[8]); 634*9bca0edbSPeter Maydell pl011_create(0x16000000, pic[1], serial_hd(0)); 635*9bca0edbSPeter Maydell pl011_create(0x17000000, pic[2], serial_hd(1)); 63683d0cf89SJan Kiszka icp = sysbus_create_simple(TYPE_ICP_CONTROL_REGS, 0xcb000000, 63783d0cf89SJan Kiszka qdev_get_gpio_in(sic, 3)); 63886394e96SPaul Brook sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]); 63986394e96SPaul Brook sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]); 640b8616055SAlex Bennée sysbus_create_simple(TYPE_INTEGRATOR_DEBUG, 0x1a000000, 0); 64183d0cf89SJan Kiszka 64283d0cf89SJan Kiszka dev = sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL); 64383d0cf89SJan Kiszka qdev_connect_gpio_out(dev, 0, 64483d0cf89SJan Kiszka qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_WPROT, 0)); 64583d0cf89SJan Kiszka qdev_connect_gpio_out(dev, 1, 64683d0cf89SJan Kiszka qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_CARDIN, 0)); 64783d0cf89SJan Kiszka 648a005d073SStefan Hajnoczi if (nd_table[0].used) 649d537cf6cSpbrook smc91c111_init(&nd_table[0], 0xc8000000, pic[27]); 6502e9bdce5SPaul Brook 6512e9bdce5SPaul Brook sysbus_create_simple("pl110", 0xc0000000, pic[22]); 652b5ff1b31Sbellard 653f93eb9ffSbalrog integrator_binfo.ram_size = ram_size; 654f93eb9ffSbalrog integrator_binfo.kernel_filename = kernel_filename; 655f93eb9ffSbalrog integrator_binfo.kernel_cmdline = kernel_cmdline; 656f93eb9ffSbalrog integrator_binfo.initrd_filename = initrd_filename; 6573aaa8dfaSAndreas Färber arm_load_kernel(cpu, &integrator_binfo); 658b5ff1b31Sbellard } 659b5ff1b31Sbellard 660e264d29dSEduardo Habkost static void integratorcp_machine_init(MachineClass *mc) 661f80f9ec9SAnthony Liguori { 662e264d29dSEduardo Habkost mc->desc = "ARM Integrator/CP (ARM926EJ-S)"; 663e264d29dSEduardo Habkost mc->init = integratorcp_init; 6644672cbd7SPeter Maydell mc->ignore_memory_transaction_failures = true; 665ba1ba5ccSIgor Mammedov mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926"); 666f80f9ec9SAnthony Liguori } 667f80f9ec9SAnthony Liguori 668e264d29dSEduardo Habkost DEFINE_MACHINE("integratorcp", integratorcp_machine_init) 669f80f9ec9SAnthony Liguori 670999e12bbSAnthony Liguori static Property core_properties[] = { 671257ec289SAndreas Färber DEFINE_PROP_UINT32("memsz", IntegratorCMState, memsz, 0), 672bb36f66aSGerd Hoffmann DEFINE_PROP_END_OF_LIST(), 673999e12bbSAnthony Liguori }; 674999e12bbSAnthony Liguori 675999e12bbSAnthony Liguori static void core_class_init(ObjectClass *klass, void *data) 676999e12bbSAnthony Liguori { 67739bffca2SAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 678999e12bbSAnthony Liguori 67939bffca2SAnthony Liguori dc->props = core_properties; 680e9d9ee23SJakub Jermar dc->realize = integratorcm_realize; 68126d32022SPavel Dovgalyuk dc->vmsd = &vmstate_integratorcm; 68226d32022SPavel Dovgalyuk } 68326d32022SPavel Dovgalyuk 68426d32022SPavel Dovgalyuk static void icp_pic_class_init(ObjectClass *klass, void *data) 68526d32022SPavel Dovgalyuk { 68626d32022SPavel Dovgalyuk DeviceClass *dc = DEVICE_CLASS(klass); 68726d32022SPavel Dovgalyuk 68826d32022SPavel Dovgalyuk dc->vmsd = &vmstate_icp_pic; 68926d32022SPavel Dovgalyuk } 69026d32022SPavel Dovgalyuk 69126d32022SPavel Dovgalyuk static void icp_control_class_init(ObjectClass *klass, void *data) 69226d32022SPavel Dovgalyuk { 69326d32022SPavel Dovgalyuk DeviceClass *dc = DEVICE_CLASS(klass); 69426d32022SPavel Dovgalyuk 69526d32022SPavel Dovgalyuk dc->vmsd = &vmstate_icp_control; 696ee6847d1SGerd Hoffmann } 697999e12bbSAnthony Liguori 6988c43a6f0SAndreas Färber static const TypeInfo core_info = { 699257ec289SAndreas Färber .name = TYPE_INTEGRATOR_CM, 70039bffca2SAnthony Liguori .parent = TYPE_SYS_BUS_DEVICE, 701257ec289SAndreas Färber .instance_size = sizeof(IntegratorCMState), 702a1f42e0cSxiaoqiang.zhao .instance_init = integratorcm_init, 703999e12bbSAnthony Liguori .class_init = core_class_init, 704999e12bbSAnthony Liguori }; 705999e12bbSAnthony Liguori 7068c43a6f0SAndreas Färber static const TypeInfo icp_pic_info = { 70791b64626SAndreas Färber .name = TYPE_INTEGRATOR_PIC, 70839bffca2SAnthony Liguori .parent = TYPE_SYS_BUS_DEVICE, 70939bffca2SAnthony Liguori .instance_size = sizeof(icp_pic_state), 710a1f42e0cSxiaoqiang.zhao .instance_init = icp_pic_init, 71126d32022SPavel Dovgalyuk .class_init = icp_pic_class_init, 712ee6847d1SGerd Hoffmann }; 713ee6847d1SGerd Hoffmann 714ffc8542aSJan Kiszka static const TypeInfo icp_ctrl_regs_info = { 715ffc8542aSJan Kiszka .name = TYPE_ICP_CONTROL_REGS, 716ffc8542aSJan Kiszka .parent = TYPE_SYS_BUS_DEVICE, 717ffc8542aSJan Kiszka .instance_size = sizeof(ICPCtrlRegsState), 718ffc8542aSJan Kiszka .instance_init = icp_control_init, 71926d32022SPavel Dovgalyuk .class_init = icp_control_class_init, 720ffc8542aSJan Kiszka }; 721ffc8542aSJan Kiszka 72283f7d43aSAndreas Färber static void integratorcp_register_types(void) 723a7086888SPaul Brook { 72439bffca2SAnthony Liguori type_register_static(&icp_pic_info); 72539bffca2SAnthony Liguori type_register_static(&core_info); 726ffc8542aSJan Kiszka type_register_static(&icp_ctrl_regs_info); 727a7086888SPaul Brook } 728a7086888SPaul Brook 72983f7d43aSAndreas Färber type_init(integratorcp_register_types) 730