xref: /openbmc/qemu/hw/arm/integratorcp.c (revision dccbaf0cc0f1744ffd7562a3dc60e4fc99fd9d44)
153018216SPaolo Bonzini /*
253018216SPaolo Bonzini  * ARM Integrator CP System emulation.
353018216SPaolo Bonzini  *
453018216SPaolo Bonzini  * Copyright (c) 2005-2007 CodeSourcery.
553018216SPaolo Bonzini  * Written by Paul Brook
653018216SPaolo Bonzini  *
753018216SPaolo Bonzini  * This code is licensed under the GPL
853018216SPaolo Bonzini  */
953018216SPaolo Bonzini 
1012b16722SPeter Maydell #include "qemu/osdep.h"
11da34e65cSMarkus Armbruster #include "qapi/error.h"
1253018216SPaolo Bonzini #include "hw/sysbus.h"
13d6454270SMarkus Armbruster #include "migration/vmstate.h"
1453018216SPaolo Bonzini #include "hw/boards.h"
1512ec8bd5SPeter Maydell #include "hw/arm/boot.h"
16b8616055SAlex Bennée #include "hw/misc/arm_integrator_debug.h"
17437cc27dSPhilippe Mathieu-Daudé #include "hw/net/smc91c111.h"
1853018216SPaolo Bonzini #include "net/net.h"
1953018216SPaolo Bonzini #include "exec/address-spaces.h"
2054d31236SMarkus Armbruster #include "sysemu/runstate.h"
2153018216SPaolo Bonzini #include "sysemu/sysemu.h"
229904625fSPhilippe Mathieu-Daudé #include "qemu/log.h"
23223a72f1SGreg Bellows #include "qemu/error-report.h"
24f0d1d2c1Sxiaoqiang zhao #include "hw/char/pl011.h"
25650d103dSMarkus Armbruster #include "hw/hw.h"
2664552b6bSMarkus Armbruster #include "hw/irq.h"
2726c607b8SPhilippe Mathieu-Daudé #include "hw/sd/sd.h"
28db1015e9SEduardo Habkost #include "qom/object.h"
29b8ab0303SMartin Kletzander #include "audio/audio.h"
30d780d056SPhilippe Mathieu-Daudé #include "target/arm/cpu-qom.h"
3153018216SPaolo Bonzini 
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 
4053018216SPaolo Bonzini     MemoryRegion iomem;
4153018216SPaolo Bonzini     uint32_t memsz;
4253018216SPaolo Bonzini     MemoryRegion flash;
4353018216SPaolo Bonzini     uint32_t cm_osc;
4453018216SPaolo Bonzini     uint32_t cm_ctrl;
4553018216SPaolo Bonzini     uint32_t cm_lock;
4653018216SPaolo Bonzini     uint32_t cm_auxosc;
4753018216SPaolo Bonzini     uint32_t cm_sdram;
4853018216SPaolo Bonzini     uint32_t cm_init;
4953018216SPaolo Bonzini     uint32_t cm_flags;
5053018216SPaolo Bonzini     uint32_t cm_nvflags;
51f53977f7SJan Petrous     uint32_t cm_refcnt_offset;
5253018216SPaolo Bonzini     uint32_t int_level;
5353018216SPaolo Bonzini     uint32_t irq_enabled;
5453018216SPaolo Bonzini     uint32_t fiq_enabled;
55db1015e9SEduardo Habkost };
5653018216SPaolo Bonzini 
5753018216SPaolo Bonzini static uint8_t integrator_spd[128] = {
5853018216SPaolo Bonzini    128, 8, 4, 11, 9, 1, 64, 0,  2, 0xa0, 0xa0, 0, 0, 8, 0, 1,
5953018216SPaolo Bonzini    0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
6053018216SPaolo Bonzini };
6153018216SPaolo Bonzini 
6226d32022SPavel Dovgalyuk static const VMStateDescription vmstate_integratorcm = {
6326d32022SPavel Dovgalyuk     .name = "integratorcm",
6426d32022SPavel Dovgalyuk     .version_id = 1,
6526d32022SPavel Dovgalyuk     .minimum_version_id = 1,
66607ef570SRichard Henderson     .fields = (const 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 
integratorcm_read(void * opaque,hwaddr offset,unsigned size)8253018216SPaolo Bonzini static uint64_t integratorcm_read(void *opaque, hwaddr offset,
8353018216SPaolo Bonzini                                   unsigned size)
8453018216SPaolo Bonzini {
85257ec289SAndreas Färber     IntegratorCMState *s = opaque;
8653018216SPaolo Bonzini     if (offset >= 0x100 && offset < 0x200) {
8753018216SPaolo Bonzini         /* CM_SPD */
8853018216SPaolo Bonzini         if (offset >= 0x180)
8953018216SPaolo Bonzini             return 0;
9053018216SPaolo Bonzini         return integrator_spd[offset >> 2];
9153018216SPaolo Bonzini     }
9253018216SPaolo Bonzini     switch (offset >> 2) {
9353018216SPaolo Bonzini     case 0: /* CM_ID */
9453018216SPaolo Bonzini         return 0x411a3001;
9553018216SPaolo Bonzini     case 1: /* CM_PROC */
9653018216SPaolo Bonzini         return 0;
9753018216SPaolo Bonzini     case 2: /* CM_OSC */
9853018216SPaolo Bonzini         return s->cm_osc;
9953018216SPaolo Bonzini     case 3: /* CM_CTRL */
10053018216SPaolo Bonzini         return s->cm_ctrl;
10153018216SPaolo Bonzini     case 4: /* CM_STAT */
10253018216SPaolo Bonzini         return 0x00100000;
10353018216SPaolo Bonzini     case 5: /* CM_LOCK */
10453018216SPaolo Bonzini         if (s->cm_lock == 0xa05f) {
10553018216SPaolo Bonzini             return 0x1a05f;
10653018216SPaolo Bonzini         } else {
10753018216SPaolo Bonzini             return s->cm_lock;
10853018216SPaolo Bonzini         }
10953018216SPaolo Bonzini     case 6: /* CM_LMBUSCNT */
11053018216SPaolo Bonzini         /* ??? High frequency timer.  */
11153018216SPaolo Bonzini         hw_error("integratorcm_read: CM_LMBUSCNT");
11253018216SPaolo Bonzini     case 7: /* CM_AUXOSC */
11353018216SPaolo Bonzini         return s->cm_auxosc;
11453018216SPaolo Bonzini     case 8: /* CM_SDRAM */
11553018216SPaolo Bonzini         return s->cm_sdram;
11653018216SPaolo Bonzini     case 9: /* CM_INIT */
11753018216SPaolo Bonzini         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;
12553018216SPaolo Bonzini     case 12: /* CM_FLAGS */
12653018216SPaolo Bonzini         return s->cm_flags;
12753018216SPaolo Bonzini     case 14: /* CM_NVFLAGS */
12853018216SPaolo Bonzini         return s->cm_nvflags;
12953018216SPaolo Bonzini     case 16: /* CM_IRQ_STAT */
13053018216SPaolo Bonzini         return s->int_level & s->irq_enabled;
13153018216SPaolo Bonzini     case 17: /* CM_IRQ_RSTAT */
13253018216SPaolo Bonzini         return s->int_level;
13353018216SPaolo Bonzini     case 18: /* CM_IRQ_ENSET */
13453018216SPaolo Bonzini         return s->irq_enabled;
13553018216SPaolo Bonzini     case 20: /* CM_SOFT_INTSET */
13653018216SPaolo Bonzini         return s->int_level & 1;
13753018216SPaolo Bonzini     case 24: /* CM_FIQ_STAT */
13853018216SPaolo Bonzini         return s->int_level & s->fiq_enabled;
13953018216SPaolo Bonzini     case 25: /* CM_FIQ_RSTAT */
14053018216SPaolo Bonzini         return s->int_level;
14153018216SPaolo Bonzini     case 26: /* CM_FIQ_ENSET */
14253018216SPaolo Bonzini         return s->fiq_enabled;
14353018216SPaolo Bonzini     case 32: /* CM_VOLTAGE_CTL0 */
14453018216SPaolo Bonzini     case 33: /* CM_VOLTAGE_CTL1 */
14553018216SPaolo Bonzini     case 34: /* CM_VOLTAGE_CTL2 */
14653018216SPaolo Bonzini     case 35: /* CM_VOLTAGE_CTL3 */
14753018216SPaolo Bonzini         /* ??? Voltage control unimplemented.  */
14853018216SPaolo Bonzini         return 0;
14953018216SPaolo Bonzini     default:
1509904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_UNIMP,
1519904625fSPhilippe Mathieu-Daudé                       "%s: Unimplemented offset 0x%" HWADDR_PRIX "\n",
1529904625fSPhilippe Mathieu-Daudé                       __func__, offset);
15353018216SPaolo Bonzini         return 0;
15453018216SPaolo Bonzini     }
15553018216SPaolo Bonzini }
15653018216SPaolo Bonzini 
integratorcm_do_remap(IntegratorCMState * s)157257ec289SAndreas Färber static void integratorcm_do_remap(IntegratorCMState *s)
15853018216SPaolo Bonzini {
15953018216SPaolo Bonzini     /* Sync memory region state with CM_CTRL REMAP bit:
16053018216SPaolo Bonzini      * bit 0 => flash at address 0; bit 1 => RAM
16153018216SPaolo Bonzini      */
16253018216SPaolo Bonzini     memory_region_set_enabled(&s->flash, !(s->cm_ctrl & 4));
16353018216SPaolo Bonzini }
16453018216SPaolo Bonzini 
integratorcm_set_ctrl(IntegratorCMState * s,uint32_t value)165257ec289SAndreas Färber static void integratorcm_set_ctrl(IntegratorCMState *s, uint32_t value)
16653018216SPaolo Bonzini {
16753018216SPaolo Bonzini     if (value & 8) {
168cf83f140SEric Blake         qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
16953018216SPaolo Bonzini     }
17053018216SPaolo Bonzini     if ((s->cm_ctrl ^ value) & 1) {
17153018216SPaolo Bonzini         /* (value & 1) != 0 means the green "MISC LED" is lit.
17253018216SPaolo Bonzini          * We don't have any nice place to display LEDs. printf is a bad
17353018216SPaolo Bonzini          * idea because Linux uses the LED as a heartbeat and the output
17453018216SPaolo Bonzini          * will swamp anything else on the terminal.
17553018216SPaolo Bonzini          */
17653018216SPaolo Bonzini     }
17753018216SPaolo Bonzini     /* Note that the RESET bit [3] always reads as zero */
17853018216SPaolo Bonzini     s->cm_ctrl = (s->cm_ctrl & ~5) | (value & 5);
17953018216SPaolo Bonzini     integratorcm_do_remap(s);
18053018216SPaolo Bonzini }
18153018216SPaolo Bonzini 
integratorcm_update(IntegratorCMState * s)182257ec289SAndreas Färber static void integratorcm_update(IntegratorCMState *s)
18353018216SPaolo Bonzini {
18453018216SPaolo Bonzini     /* ??? The CPU irq/fiq is raised when either the core module or base PIC
18553018216SPaolo Bonzini        are active.  */
18653018216SPaolo Bonzini     if (s->int_level & (s->irq_enabled | s->fiq_enabled))
18753018216SPaolo Bonzini         hw_error("Core module interrupt\n");
18853018216SPaolo Bonzini }
18953018216SPaolo Bonzini 
integratorcm_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)19053018216SPaolo Bonzini static void integratorcm_write(void *opaque, hwaddr offset,
19153018216SPaolo Bonzini                                uint64_t value, unsigned size)
19253018216SPaolo Bonzini {
193257ec289SAndreas Färber     IntegratorCMState *s = opaque;
19453018216SPaolo Bonzini     switch (offset >> 2) {
19553018216SPaolo Bonzini     case 2: /* CM_OSC */
19653018216SPaolo Bonzini         if (s->cm_lock == 0xa05f)
19753018216SPaolo Bonzini             s->cm_osc = value;
19853018216SPaolo Bonzini         break;
19953018216SPaolo Bonzini     case 3: /* CM_CTRL */
20053018216SPaolo Bonzini         integratorcm_set_ctrl(s, value);
20153018216SPaolo Bonzini         break;
20253018216SPaolo Bonzini     case 5: /* CM_LOCK */
20353018216SPaolo Bonzini         s->cm_lock = value & 0xffff;
20453018216SPaolo Bonzini         break;
20553018216SPaolo Bonzini     case 7: /* CM_AUXOSC */
20653018216SPaolo Bonzini         if (s->cm_lock == 0xa05f)
20753018216SPaolo Bonzini             s->cm_auxosc = value;
20853018216SPaolo Bonzini         break;
20953018216SPaolo Bonzini     case 8: /* CM_SDRAM */
21053018216SPaolo Bonzini         s->cm_sdram = value;
21153018216SPaolo Bonzini         break;
21253018216SPaolo Bonzini     case 9: /* CM_INIT */
21353018216SPaolo Bonzini         /* ??? This can change the memory bus frequency.  */
21453018216SPaolo Bonzini         s->cm_init = value;
21553018216SPaolo Bonzini         break;
21653018216SPaolo Bonzini     case 12: /* CM_FLAGSS */
21753018216SPaolo Bonzini         s->cm_flags |= value;
21853018216SPaolo Bonzini         break;
21953018216SPaolo Bonzini     case 13: /* CM_FLAGSC */
22053018216SPaolo Bonzini         s->cm_flags &= ~value;
22153018216SPaolo Bonzini         break;
22253018216SPaolo Bonzini     case 14: /* CM_NVFLAGSS */
22353018216SPaolo Bonzini         s->cm_nvflags |= value;
22453018216SPaolo Bonzini         break;
22553018216SPaolo Bonzini     case 15: /* CM_NVFLAGSS */
22653018216SPaolo Bonzini         s->cm_nvflags &= ~value;
22753018216SPaolo Bonzini         break;
22853018216SPaolo Bonzini     case 18: /* CM_IRQ_ENSET */
22953018216SPaolo Bonzini         s->irq_enabled |= value;
23053018216SPaolo Bonzini         integratorcm_update(s);
23153018216SPaolo Bonzini         break;
23253018216SPaolo Bonzini     case 19: /* CM_IRQ_ENCLR */
23353018216SPaolo Bonzini         s->irq_enabled &= ~value;
23453018216SPaolo Bonzini         integratorcm_update(s);
23553018216SPaolo Bonzini         break;
23653018216SPaolo Bonzini     case 20: /* CM_SOFT_INTSET */
23753018216SPaolo Bonzini         s->int_level |= (value & 1);
23853018216SPaolo Bonzini         integratorcm_update(s);
23953018216SPaolo Bonzini         break;
24053018216SPaolo Bonzini     case 21: /* CM_SOFT_INTCLR */
24153018216SPaolo Bonzini         s->int_level &= ~(value & 1);
24253018216SPaolo Bonzini         integratorcm_update(s);
24353018216SPaolo Bonzini         break;
24453018216SPaolo Bonzini     case 26: /* CM_FIQ_ENSET */
24553018216SPaolo Bonzini         s->fiq_enabled |= value;
24653018216SPaolo Bonzini         integratorcm_update(s);
24753018216SPaolo Bonzini         break;
24853018216SPaolo Bonzini     case 27: /* CM_FIQ_ENCLR */
24953018216SPaolo Bonzini         s->fiq_enabled &= ~value;
25053018216SPaolo Bonzini         integratorcm_update(s);
25153018216SPaolo Bonzini         break;
25253018216SPaolo Bonzini     case 32: /* CM_VOLTAGE_CTL0 */
25353018216SPaolo Bonzini     case 33: /* CM_VOLTAGE_CTL1 */
25453018216SPaolo Bonzini     case 34: /* CM_VOLTAGE_CTL2 */
25553018216SPaolo Bonzini     case 35: /* CM_VOLTAGE_CTL3 */
25653018216SPaolo Bonzini         /* ??? Voltage control unimplemented.  */
25753018216SPaolo Bonzini         break;
25853018216SPaolo Bonzini     default:
2599904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_UNIMP,
2609904625fSPhilippe Mathieu-Daudé                       "%s: Unimplemented offset 0x%" HWADDR_PRIX "\n",
2619904625fSPhilippe Mathieu-Daudé                       __func__, offset);
26253018216SPaolo Bonzini         break;
26353018216SPaolo Bonzini     }
26453018216SPaolo Bonzini }
26553018216SPaolo Bonzini 
26653018216SPaolo Bonzini /* Integrator/CM control registers.  */
26753018216SPaolo Bonzini 
26853018216SPaolo Bonzini static const MemoryRegionOps integratorcm_ops = {
26953018216SPaolo Bonzini     .read = integratorcm_read,
27053018216SPaolo Bonzini     .write = integratorcm_write,
27153018216SPaolo Bonzini     .endianness = DEVICE_NATIVE_ENDIAN,
27253018216SPaolo Bonzini };
27353018216SPaolo Bonzini 
integratorcm_init(Object * obj)274a1f42e0cSxiaoqiang.zhao static void integratorcm_init(Object *obj)
27553018216SPaolo Bonzini {
276a1f42e0cSxiaoqiang.zhao     IntegratorCMState *s = INTEGRATOR_CM(obj);
27753018216SPaolo Bonzini 
27853018216SPaolo Bonzini     s->cm_osc = 0x01000048;
27953018216SPaolo Bonzini     /* ??? What should the high bits of this value be?  */
28053018216SPaolo Bonzini     s->cm_auxosc = 0x0007feff;
28153018216SPaolo Bonzini     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 
integratorcm_realize(DeviceState * d,Error ** errp)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 
2952198f5f0SPhilippe Mathieu-Daudé     if (!memory_region_init_ram(&s->flash, OBJECT(d), "integrator.flash",
2962198f5f0SPhilippe Mathieu-Daudé                                 0x100000, errp)) {
2978720daadSThomas Huth         return;
2988720daadSThomas Huth     }
2998720daadSThomas Huth 
3008720daadSThomas Huth     memory_region_init_io(&s->iomem, OBJECT(d), &integratorcm_ops, s,
3018720daadSThomas Huth                           "integratorcm", 0x00800000);
3028720daadSThomas Huth     sysbus_init_mmio(dev, &s->iomem);
3038720daadSThomas Huth 
3048720daadSThomas Huth     integratorcm_do_remap(s);
305e9d9ee23SJakub Jermar 
30653018216SPaolo Bonzini     if (s->memsz >= 256) {
30753018216SPaolo Bonzini         integrator_spd[31] = 64;
30853018216SPaolo Bonzini         s->cm_sdram |= 0x10;
30953018216SPaolo Bonzini     } else if (s->memsz >= 128) {
31053018216SPaolo Bonzini         integrator_spd[31] = 32;
31153018216SPaolo Bonzini         s->cm_sdram |= 0x0c;
31253018216SPaolo Bonzini     } else if (s->memsz >= 64) {
31353018216SPaolo Bonzini         integrator_spd[31] = 16;
31453018216SPaolo Bonzini         s->cm_sdram |= 0x08;
31553018216SPaolo Bonzini     } else if (s->memsz >= 32) {
31653018216SPaolo Bonzini         integrator_spd[31] = 4;
31753018216SPaolo Bonzini         s->cm_sdram |= 0x04;
31853018216SPaolo Bonzini     } else {
31953018216SPaolo Bonzini         integrator_spd[31] = 2;
32053018216SPaolo Bonzini     }
32153018216SPaolo Bonzini }
32253018216SPaolo Bonzini 
32353018216SPaolo Bonzini /* Integrator/CP hardware emulation.  */
32453018216SPaolo Bonzini /* Primary interrupt controller.  */
32553018216SPaolo Bonzini 
32691b64626SAndreas Färber #define TYPE_INTEGRATOR_PIC "integrator_pic"
3278063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(icp_pic_state, INTEGRATOR_PIC)
32891b64626SAndreas Färber 
329db1015e9SEduardo Habkost struct icp_pic_state {
33091b64626SAndreas Färber     /*< private >*/
33191b64626SAndreas Färber     SysBusDevice parent_obj;
33291b64626SAndreas Färber     /*< public >*/
33391b64626SAndreas Färber 
33453018216SPaolo Bonzini     MemoryRegion iomem;
33553018216SPaolo Bonzini     uint32_t level;
33653018216SPaolo Bonzini     uint32_t irq_enabled;
33753018216SPaolo Bonzini     uint32_t fiq_enabled;
33853018216SPaolo Bonzini     qemu_irq parent_irq;
33953018216SPaolo Bonzini     qemu_irq parent_fiq;
340db1015e9SEduardo Habkost };
34153018216SPaolo Bonzini 
34226d32022SPavel Dovgalyuk static const VMStateDescription vmstate_icp_pic = {
34326d32022SPavel Dovgalyuk     .name = "icp_pic",
34426d32022SPavel Dovgalyuk     .version_id = 1,
34526d32022SPavel Dovgalyuk     .minimum_version_id = 1,
346607ef570SRichard Henderson     .fields = (const VMStateField[]) {
34726d32022SPavel Dovgalyuk         VMSTATE_UINT32(level, icp_pic_state),
34826d32022SPavel Dovgalyuk         VMSTATE_UINT32(irq_enabled, icp_pic_state),
34926d32022SPavel Dovgalyuk         VMSTATE_UINT32(fiq_enabled, icp_pic_state),
35026d32022SPavel Dovgalyuk         VMSTATE_END_OF_LIST()
35126d32022SPavel Dovgalyuk     }
35226d32022SPavel Dovgalyuk };
35326d32022SPavel Dovgalyuk 
icp_pic_update(icp_pic_state * s)35453018216SPaolo Bonzini static void icp_pic_update(icp_pic_state *s)
35553018216SPaolo Bonzini {
35653018216SPaolo Bonzini     uint32_t flags;
35753018216SPaolo Bonzini 
35853018216SPaolo Bonzini     flags = (s->level & s->irq_enabled);
35953018216SPaolo Bonzini     qemu_set_irq(s->parent_irq, flags != 0);
36053018216SPaolo Bonzini     flags = (s->level & s->fiq_enabled);
36153018216SPaolo Bonzini     qemu_set_irq(s->parent_fiq, flags != 0);
36253018216SPaolo Bonzini }
36353018216SPaolo Bonzini 
icp_pic_set_irq(void * opaque,int irq,int level)36453018216SPaolo Bonzini static void icp_pic_set_irq(void *opaque, int irq, int level)
36553018216SPaolo Bonzini {
36653018216SPaolo Bonzini     icp_pic_state *s = (icp_pic_state *)opaque;
36753018216SPaolo Bonzini     if (level)
36853018216SPaolo Bonzini         s->level |= 1 << irq;
36953018216SPaolo Bonzini     else
37053018216SPaolo Bonzini         s->level &= ~(1 << irq);
37153018216SPaolo Bonzini     icp_pic_update(s);
37253018216SPaolo Bonzini }
37353018216SPaolo Bonzini 
icp_pic_read(void * opaque,hwaddr offset,unsigned size)37453018216SPaolo Bonzini static uint64_t icp_pic_read(void *opaque, hwaddr offset,
37553018216SPaolo Bonzini                              unsigned size)
37653018216SPaolo Bonzini {
37753018216SPaolo Bonzini     icp_pic_state *s = (icp_pic_state *)opaque;
37853018216SPaolo Bonzini 
37953018216SPaolo Bonzini     switch (offset >> 2) {
38053018216SPaolo Bonzini     case 0: /* IRQ_STATUS */
38153018216SPaolo Bonzini         return s->level & s->irq_enabled;
38253018216SPaolo Bonzini     case 1: /* IRQ_RAWSTAT */
38353018216SPaolo Bonzini         return s->level;
38453018216SPaolo Bonzini     case 2: /* IRQ_ENABLESET */
38553018216SPaolo Bonzini         return s->irq_enabled;
38653018216SPaolo Bonzini     case 4: /* INT_SOFTSET */
38753018216SPaolo Bonzini         return s->level & 1;
38853018216SPaolo Bonzini     case 8: /* FRQ_STATUS */
38953018216SPaolo Bonzini         return s->level & s->fiq_enabled;
39053018216SPaolo Bonzini     case 9: /* FRQ_RAWSTAT */
39153018216SPaolo Bonzini         return s->level;
39253018216SPaolo Bonzini     case 10: /* FRQ_ENABLESET */
39353018216SPaolo Bonzini         return s->fiq_enabled;
39453018216SPaolo Bonzini     case 3: /* IRQ_ENABLECLR */
39553018216SPaolo Bonzini     case 5: /* INT_SOFTCLR */
39653018216SPaolo Bonzini     case 11: /* FRQ_ENABLECLR */
39753018216SPaolo Bonzini     default:
3989904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
3999904625fSPhilippe Mathieu-Daudé                       __func__, offset);
40053018216SPaolo Bonzini         return 0;
40153018216SPaolo Bonzini     }
40253018216SPaolo Bonzini }
40353018216SPaolo Bonzini 
icp_pic_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)40453018216SPaolo Bonzini static void icp_pic_write(void *opaque, hwaddr offset,
40553018216SPaolo Bonzini                           uint64_t value, unsigned size)
40653018216SPaolo Bonzini {
40753018216SPaolo Bonzini     icp_pic_state *s = (icp_pic_state *)opaque;
40853018216SPaolo Bonzini 
40953018216SPaolo Bonzini     switch (offset >> 2) {
41053018216SPaolo Bonzini     case 2: /* IRQ_ENABLESET */
41153018216SPaolo Bonzini         s->irq_enabled |= value;
41253018216SPaolo Bonzini         break;
41353018216SPaolo Bonzini     case 3: /* IRQ_ENABLECLR */
41453018216SPaolo Bonzini         s->irq_enabled &= ~value;
41553018216SPaolo Bonzini         break;
41653018216SPaolo Bonzini     case 4: /* INT_SOFTSET */
41753018216SPaolo Bonzini         if (value & 1)
41853018216SPaolo Bonzini             icp_pic_set_irq(s, 0, 1);
41953018216SPaolo Bonzini         break;
42053018216SPaolo Bonzini     case 5: /* INT_SOFTCLR */
42153018216SPaolo Bonzini         if (value & 1)
42253018216SPaolo Bonzini             icp_pic_set_irq(s, 0, 0);
42353018216SPaolo Bonzini         break;
42453018216SPaolo Bonzini     case 10: /* FRQ_ENABLESET */
42553018216SPaolo Bonzini         s->fiq_enabled |= value;
42653018216SPaolo Bonzini         break;
42753018216SPaolo Bonzini     case 11: /* FRQ_ENABLECLR */
42853018216SPaolo Bonzini         s->fiq_enabled &= ~value;
42953018216SPaolo Bonzini         break;
43053018216SPaolo Bonzini     case 0: /* IRQ_STATUS */
43153018216SPaolo Bonzini     case 1: /* IRQ_RAWSTAT */
43253018216SPaolo Bonzini     case 8: /* FRQ_STATUS */
43353018216SPaolo Bonzini     case 9: /* FRQ_RAWSTAT */
43453018216SPaolo Bonzini     default:
4359904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
4369904625fSPhilippe Mathieu-Daudé                       __func__, offset);
43753018216SPaolo Bonzini         return;
43853018216SPaolo Bonzini     }
43953018216SPaolo Bonzini     icp_pic_update(s);
44053018216SPaolo Bonzini }
44153018216SPaolo Bonzini 
44253018216SPaolo Bonzini static const MemoryRegionOps icp_pic_ops = {
44353018216SPaolo Bonzini     .read = icp_pic_read,
44453018216SPaolo Bonzini     .write = icp_pic_write,
44553018216SPaolo Bonzini     .endianness = DEVICE_NATIVE_ENDIAN,
44653018216SPaolo Bonzini };
44753018216SPaolo Bonzini 
icp_pic_init(Object * obj)448a1f42e0cSxiaoqiang.zhao static void icp_pic_init(Object *obj)
44953018216SPaolo Bonzini {
450a1f42e0cSxiaoqiang.zhao     DeviceState *dev = DEVICE(obj);
451a1f42e0cSxiaoqiang.zhao     icp_pic_state *s = INTEGRATOR_PIC(obj);
452a1f42e0cSxiaoqiang.zhao     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
45353018216SPaolo Bonzini 
45491b64626SAndreas Färber     qdev_init_gpio_in(dev, icp_pic_set_irq, 32);
45591b64626SAndreas Färber     sysbus_init_irq(sbd, &s->parent_irq);
45691b64626SAndreas Färber     sysbus_init_irq(sbd, &s->parent_fiq);
457a1f42e0cSxiaoqiang.zhao     memory_region_init_io(&s->iomem, obj, &icp_pic_ops, s,
45864bde0f3SPaolo Bonzini                           "icp-pic", 0x00800000);
45991b64626SAndreas Färber     sysbus_init_mmio(sbd, &s->iomem);
46053018216SPaolo Bonzini }
46153018216SPaolo Bonzini 
46253018216SPaolo Bonzini /* CP control registers.  */
46353018216SPaolo Bonzini 
464ffc8542aSJan Kiszka #define TYPE_ICP_CONTROL_REGS "icp-ctrl-regs"
4658063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(ICPCtrlRegsState, ICP_CONTROL_REGS)
466ffc8542aSJan Kiszka 
467db1015e9SEduardo Habkost struct ICPCtrlRegsState {
468ffc8542aSJan Kiszka     /*< private >*/
469ffc8542aSJan Kiszka     SysBusDevice parent_obj;
470ffc8542aSJan Kiszka     /*< public >*/
471ffc8542aSJan Kiszka 
472ffc8542aSJan Kiszka     MemoryRegion iomem;
47383d0cf89SJan Kiszka 
47483d0cf89SJan Kiszka     qemu_irq mmc_irq;
47583d0cf89SJan Kiszka     uint32_t intreg_state;
476db1015e9SEduardo Habkost };
477ffc8542aSJan Kiszka 
47883d0cf89SJan Kiszka #define ICP_GPIO_MMC_WPROT      "mmc-wprot"
47983d0cf89SJan Kiszka #define ICP_GPIO_MMC_CARDIN     "mmc-cardin"
48083d0cf89SJan Kiszka 
48183d0cf89SJan Kiszka #define ICP_INTREG_WPROT        (1 << 0)
48283d0cf89SJan Kiszka #define ICP_INTREG_CARDIN       (1 << 3)
48383d0cf89SJan Kiszka 
48426d32022SPavel Dovgalyuk static const VMStateDescription vmstate_icp_control = {
48526d32022SPavel Dovgalyuk     .name = "icp_control",
48626d32022SPavel Dovgalyuk     .version_id = 1,
48726d32022SPavel Dovgalyuk     .minimum_version_id = 1,
488607ef570SRichard Henderson     .fields = (const VMStateField[]) {
48926d32022SPavel Dovgalyuk         VMSTATE_UINT32(intreg_state, ICPCtrlRegsState),
49026d32022SPavel Dovgalyuk         VMSTATE_END_OF_LIST()
49126d32022SPavel Dovgalyuk     }
49226d32022SPavel Dovgalyuk };
49326d32022SPavel Dovgalyuk 
icp_control_read(void * opaque,hwaddr offset,unsigned size)49453018216SPaolo Bonzini static uint64_t icp_control_read(void *opaque, hwaddr offset,
49553018216SPaolo Bonzini                                  unsigned size)
49653018216SPaolo Bonzini {
49783d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
49883d0cf89SJan Kiszka 
49953018216SPaolo Bonzini     switch (offset >> 2) {
50053018216SPaolo Bonzini     case 0: /* CP_IDFIELD */
50153018216SPaolo Bonzini         return 0x41034003;
50253018216SPaolo Bonzini     case 1: /* CP_FLASHPROG */
50353018216SPaolo Bonzini         return 0;
50453018216SPaolo Bonzini     case 2: /* CP_INTREG */
50583d0cf89SJan Kiszka         return s->intreg_state;
50653018216SPaolo Bonzini     case 3: /* CP_DECODE */
50753018216SPaolo Bonzini         return 0x11;
50853018216SPaolo Bonzini     default:
5099904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
5109904625fSPhilippe Mathieu-Daudé                       __func__, offset);
51153018216SPaolo Bonzini         return 0;
51253018216SPaolo Bonzini     }
51353018216SPaolo Bonzini }
51453018216SPaolo Bonzini 
icp_control_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)51553018216SPaolo Bonzini static void icp_control_write(void *opaque, hwaddr offset,
51653018216SPaolo Bonzini                           uint64_t value, unsigned size)
51753018216SPaolo Bonzini {
51883d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
51983d0cf89SJan Kiszka 
52053018216SPaolo Bonzini     switch (offset >> 2) {
52153018216SPaolo Bonzini     case 2: /* CP_INTREG */
52283d0cf89SJan Kiszka         s->intreg_state &= ~(value & ICP_INTREG_CARDIN);
52383d0cf89SJan Kiszka         qemu_set_irq(s->mmc_irq, !!(s->intreg_state & ICP_INTREG_CARDIN));
52483d0cf89SJan Kiszka         break;
52583d0cf89SJan Kiszka     case 1: /* CP_FLASHPROG */
52653018216SPaolo Bonzini     case 3: /* CP_DECODE */
52753018216SPaolo Bonzini         /* Nothing interesting implemented yet.  */
52853018216SPaolo Bonzini         break;
52953018216SPaolo Bonzini     default:
5309904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
5319904625fSPhilippe Mathieu-Daudé                       __func__, offset);
53253018216SPaolo Bonzini     }
53353018216SPaolo Bonzini }
53453018216SPaolo Bonzini 
53553018216SPaolo Bonzini static const MemoryRegionOps icp_control_ops = {
53653018216SPaolo Bonzini     .read = icp_control_read,
53753018216SPaolo Bonzini     .write = icp_control_write,
53853018216SPaolo Bonzini     .endianness = DEVICE_NATIVE_ENDIAN,
53953018216SPaolo Bonzini };
54053018216SPaolo Bonzini 
icp_control_mmc_wprot(void * opaque,int line,int level)54183d0cf89SJan Kiszka static void icp_control_mmc_wprot(void *opaque, int line, int level)
54283d0cf89SJan Kiszka {
54383d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
54483d0cf89SJan Kiszka 
54583d0cf89SJan Kiszka     s->intreg_state &= ~ICP_INTREG_WPROT;
54683d0cf89SJan Kiszka     if (level) {
54783d0cf89SJan Kiszka         s->intreg_state |= ICP_INTREG_WPROT;
54883d0cf89SJan Kiszka     }
54983d0cf89SJan Kiszka }
55083d0cf89SJan Kiszka 
icp_control_mmc_cardin(void * opaque,int line,int level)55183d0cf89SJan Kiszka static void icp_control_mmc_cardin(void *opaque, int line, int level)
55283d0cf89SJan Kiszka {
55383d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
55483d0cf89SJan Kiszka 
55583d0cf89SJan Kiszka     /* line is released by writing to CP_INTREG */
55683d0cf89SJan Kiszka     if (level) {
55783d0cf89SJan Kiszka         s->intreg_state |= ICP_INTREG_CARDIN;
55883d0cf89SJan Kiszka         qemu_set_irq(s->mmc_irq, 1);
55983d0cf89SJan Kiszka     }
56083d0cf89SJan Kiszka }
56183d0cf89SJan Kiszka 
icp_control_init(Object * obj)562ffc8542aSJan Kiszka static void icp_control_init(Object *obj)
56353018216SPaolo Bonzini {
564ffc8542aSJan Kiszka     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
565ffc8542aSJan Kiszka     ICPCtrlRegsState *s = ICP_CONTROL_REGS(obj);
56683d0cf89SJan Kiszka     DeviceState *dev = DEVICE(obj);
56753018216SPaolo Bonzini 
568ffc8542aSJan Kiszka     memory_region_init_io(&s->iomem, OBJECT(s), &icp_control_ops, s,
569ffc8542aSJan Kiszka                           "icp_ctrl_regs", 0x00800000);
570ffc8542aSJan Kiszka     sysbus_init_mmio(sbd, &s->iomem);
57183d0cf89SJan Kiszka 
57283d0cf89SJan Kiszka     qdev_init_gpio_in_named(dev, icp_control_mmc_wprot, ICP_GPIO_MMC_WPROT, 1);
57383d0cf89SJan Kiszka     qdev_init_gpio_in_named(dev, icp_control_mmc_cardin,
57483d0cf89SJan Kiszka                             ICP_GPIO_MMC_CARDIN, 1);
57583d0cf89SJan Kiszka     sysbus_init_irq(sbd, &s->mmc_irq);
57653018216SPaolo Bonzini }
57753018216SPaolo Bonzini 
57853018216SPaolo Bonzini 
57953018216SPaolo Bonzini /* Board init.  */
58053018216SPaolo Bonzini 
58153018216SPaolo Bonzini static struct arm_boot_info integrator_binfo = {
58253018216SPaolo Bonzini     .loader_start = 0x0,
58353018216SPaolo Bonzini     .board_id = 0x113,
58453018216SPaolo Bonzini };
58553018216SPaolo Bonzini 
integratorcp_init(MachineState * machine)5863ef96221SMarcel Apfelbaum static void integratorcp_init(MachineState *machine)
58753018216SPaolo Bonzini {
5883ef96221SMarcel Apfelbaum     ram_addr_t ram_size = machine->ram_size;
589223a72f1SGreg Bellows     Object *cpuobj;
59053018216SPaolo Bonzini     ARMCPU *cpu;
59153018216SPaolo Bonzini     MemoryRegion *address_space_mem = get_system_memory();
59253018216SPaolo Bonzini     MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
59353018216SPaolo Bonzini     qemu_irq pic[32];
59483d0cf89SJan Kiszka     DeviceState *dev, *sic, *icp;
59526c607b8SPhilippe Mathieu-Daudé     DriveInfo *dinfo;
59653018216SPaolo Bonzini     int i;
59753018216SPaolo Bonzini 
598ba1ba5ccSIgor Mammedov     cpuobj = object_new(machine->cpu_type);
599223a72f1SGreg Bellows 
60061e2f352SGreg Bellows     /* By default ARM1176 CPUs have EL3 enabled.  This board does not
60161e2f352SGreg Bellows      * currently support EL3 so the CPU EL3 property is disabled before
60261e2f352SGreg Bellows      * realization.
60361e2f352SGreg Bellows      */
604efba1595SDaniel P. Berrangé     if (object_property_find(cpuobj, "has_el3")) {
6055325cc34SMarkus Armbruster         object_property_set_bool(cpuobj, "has_el3", false, &error_fatal);
60661e2f352SGreg Bellows     }
60761e2f352SGreg Bellows 
608ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
609223a72f1SGreg Bellows 
610223a72f1SGreg Bellows     cpu = ARM_CPU(cpuobj);
611223a72f1SGreg Bellows 
61253018216SPaolo Bonzini     /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
61353018216SPaolo Bonzini     /* ??? RAM should repeat to fill physical memory space.  */
61453018216SPaolo Bonzini     /* SDRAM at address zero*/
6153f25b3f4SIgor Mammedov     memory_region_add_subregion(address_space_mem, 0, machine->ram);
61653018216SPaolo Bonzini     /* And again at address 0x80000000 */
6173f25b3f4SIgor Mammedov     memory_region_init_alias(ram_alias, NULL, "ram.alias", machine->ram,
6183f25b3f4SIgor Mammedov                              0, ram_size);
61953018216SPaolo Bonzini     memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
62053018216SPaolo Bonzini 
6213e80f690SMarkus Armbruster     dev = qdev_new(TYPE_INTEGRATOR_CM);
62253018216SPaolo Bonzini     qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
6233c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
62453018216SPaolo Bonzini     sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
62553018216SPaolo Bonzini 
62691b64626SAndreas Färber     dev = sysbus_create_varargs(TYPE_INTEGRATOR_PIC, 0x14000000,
62799d228d6SPeter Maydell                                 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ),
62899d228d6SPeter Maydell                                 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ),
62999d228d6SPeter Maydell                                 NULL);
63053018216SPaolo Bonzini     for (i = 0; i < 32; i++) {
63153018216SPaolo Bonzini         pic[i] = qdev_get_gpio_in(dev, i);
63253018216SPaolo Bonzini     }
63383d0cf89SJan Kiszka     sic = sysbus_create_simple(TYPE_INTEGRATOR_PIC, 0xca000000, pic[26]);
63453018216SPaolo Bonzini     sysbus_create_varargs("integrator_pit", 0x13000000,
63553018216SPaolo Bonzini                           pic[5], pic[6], pic[7], NULL);
63653018216SPaolo Bonzini     sysbus_create_simple("pl031", 0x15000000, pic[8]);
6379bca0edbSPeter Maydell     pl011_create(0x16000000, pic[1], serial_hd(0));
6389bca0edbSPeter Maydell     pl011_create(0x17000000, pic[2], serial_hd(1));
63983d0cf89SJan Kiszka     icp = sysbus_create_simple(TYPE_ICP_CONTROL_REGS, 0xcb000000,
64083d0cf89SJan Kiszka                                qdev_get_gpio_in(sic, 3));
64153018216SPaolo Bonzini     sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
64253018216SPaolo Bonzini     sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]);
643b8616055SAlex Bennée     sysbus_create_simple(TYPE_INTEGRATOR_DEBUG, 0x1a000000, 0);
64483d0cf89SJan Kiszka 
64583d0cf89SJan Kiszka     dev = sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL);
64626c5b0f4SPhilippe Mathieu-Daudé     qdev_connect_gpio_out_named(dev, "card-read-only", 0,
64783d0cf89SJan Kiszka                           qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_WPROT, 0));
64826c5b0f4SPhilippe Mathieu-Daudé     qdev_connect_gpio_out_named(dev, "card-inserted", 0,
64983d0cf89SJan Kiszka                           qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_CARDIN, 0));
65064eaa820SMarkus Armbruster     dinfo = drive_get(IF_SD, 0, 0);
65126c607b8SPhilippe Mathieu-Daudé     if (dinfo) {
65226c607b8SPhilippe Mathieu-Daudé         DeviceState *card;
65326c607b8SPhilippe Mathieu-Daudé 
65426c607b8SPhilippe Mathieu-Daudé         card = qdev_new(TYPE_SD_CARD);
65526c607b8SPhilippe Mathieu-Daudé         qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo),
65626c607b8SPhilippe Mathieu-Daudé                                 &error_fatal);
65726c607b8SPhilippe Mathieu-Daudé         qdev_realize_and_unref(card, qdev_get_child_bus(dev, "sd-bus"),
65826c607b8SPhilippe Mathieu-Daudé                                &error_fatal);
65926c607b8SPhilippe Mathieu-Daudé     }
66026c607b8SPhilippe Mathieu-Daudé 
661b8ab0303SMartin Kletzander     dev = qdev_new("pl041");
662b8ab0303SMartin Kletzander     if (machine->audiodev) {
663b8ab0303SMartin Kletzander         qdev_prop_set_string(dev, "audiodev", machine->audiodev);
664b8ab0303SMartin Kletzander     }
665b8ab0303SMartin Kletzander     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
666b8ab0303SMartin Kletzander     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0x1d000000);
667b8ab0303SMartin Kletzander     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[25]);
66883d0cf89SJan Kiszka 
669cd53991dSDavid Woodhouse     if (qemu_find_nic_info("smc91c111", true, NULL)) {
670cd53991dSDavid Woodhouse         smc91c111_init(0xc8000000, pic[27]);
671cd53991dSDavid Woodhouse     }
67253018216SPaolo Bonzini 
67349aff03eSPhilippe Mathieu-Daudé     dev = qdev_new("pl110");
674*c2093660SPhilippe Mathieu-Daudé     object_property_set_link(OBJECT(dev), "framebuffer-memory",
675*c2093660SPhilippe Mathieu-Daudé                              OBJECT(address_space_mem), &error_fatal);
67649aff03eSPhilippe Mathieu-Daudé     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
67749aff03eSPhilippe Mathieu-Daudé     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xc0000000);
67849aff03eSPhilippe Mathieu-Daudé     sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[22]);
67953018216SPaolo Bonzini 
68053018216SPaolo Bonzini     integrator_binfo.ram_size = ram_size;
6812744ece8STao Xu     arm_load_kernel(cpu, machine, &integrator_binfo);
68253018216SPaolo Bonzini }
68353018216SPaolo Bonzini 
integratorcp_machine_init(MachineClass * mc)684e264d29dSEduardo Habkost static void integratorcp_machine_init(MachineClass *mc)
68553018216SPaolo Bonzini {
686e264d29dSEduardo Habkost     mc->desc = "ARM Integrator/CP (ARM926EJ-S)";
687e264d29dSEduardo Habkost     mc->init = integratorcp_init;
6884672cbd7SPeter Maydell     mc->ignore_memory_transaction_failures = true;
689ba1ba5ccSIgor Mammedov     mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926");
6903f25b3f4SIgor Mammedov     mc->default_ram_id = "integrator.ram";
691b8ab0303SMartin Kletzander 
692b8ab0303SMartin Kletzander     machine_add_audiodev_property(mc);
69353018216SPaolo Bonzini }
69453018216SPaolo Bonzini 
695e264d29dSEduardo Habkost DEFINE_MACHINE("integratorcp", integratorcp_machine_init)
69653018216SPaolo Bonzini 
69753018216SPaolo Bonzini static Property core_properties[] = {
698257ec289SAndreas Färber     DEFINE_PROP_UINT32("memsz", IntegratorCMState, memsz, 0),
69953018216SPaolo Bonzini     DEFINE_PROP_END_OF_LIST(),
70053018216SPaolo Bonzini };
70153018216SPaolo Bonzini 
core_class_init(ObjectClass * klass,void * data)70253018216SPaolo Bonzini static void core_class_init(ObjectClass *klass, void *data)
70353018216SPaolo Bonzini {
70453018216SPaolo Bonzini     DeviceClass *dc = DEVICE_CLASS(klass);
70553018216SPaolo Bonzini 
7064f67d30bSMarc-André Lureau     device_class_set_props(dc, core_properties);
707e9d9ee23SJakub Jermar     dc->realize = integratorcm_realize;
70826d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_integratorcm;
70926d32022SPavel Dovgalyuk }
71026d32022SPavel Dovgalyuk 
icp_pic_class_init(ObjectClass * klass,void * data)71126d32022SPavel Dovgalyuk static void icp_pic_class_init(ObjectClass *klass, void *data)
71226d32022SPavel Dovgalyuk {
71326d32022SPavel Dovgalyuk     DeviceClass *dc = DEVICE_CLASS(klass);
71426d32022SPavel Dovgalyuk 
71526d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_icp_pic;
71626d32022SPavel Dovgalyuk }
71726d32022SPavel Dovgalyuk 
icp_control_class_init(ObjectClass * klass,void * data)71826d32022SPavel Dovgalyuk static void icp_control_class_init(ObjectClass *klass, void *data)
71926d32022SPavel Dovgalyuk {
72026d32022SPavel Dovgalyuk     DeviceClass *dc = DEVICE_CLASS(klass);
72126d32022SPavel Dovgalyuk 
72226d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_icp_control;
72353018216SPaolo Bonzini }
72453018216SPaolo Bonzini 
72553018216SPaolo Bonzini static const TypeInfo core_info = {
726257ec289SAndreas Färber     .name          = TYPE_INTEGRATOR_CM,
72753018216SPaolo Bonzini     .parent        = TYPE_SYS_BUS_DEVICE,
728257ec289SAndreas Färber     .instance_size = sizeof(IntegratorCMState),
729a1f42e0cSxiaoqiang.zhao     .instance_init = integratorcm_init,
73053018216SPaolo Bonzini     .class_init    = core_class_init,
73153018216SPaolo Bonzini };
73253018216SPaolo Bonzini 
73353018216SPaolo Bonzini static const TypeInfo icp_pic_info = {
73491b64626SAndreas Färber     .name          = TYPE_INTEGRATOR_PIC,
73553018216SPaolo Bonzini     .parent        = TYPE_SYS_BUS_DEVICE,
73653018216SPaolo Bonzini     .instance_size = sizeof(icp_pic_state),
737a1f42e0cSxiaoqiang.zhao     .instance_init = icp_pic_init,
73826d32022SPavel Dovgalyuk     .class_init    = icp_pic_class_init,
73953018216SPaolo Bonzini };
74053018216SPaolo Bonzini 
741ffc8542aSJan Kiszka static const TypeInfo icp_ctrl_regs_info = {
742ffc8542aSJan Kiszka     .name          = TYPE_ICP_CONTROL_REGS,
743ffc8542aSJan Kiszka     .parent        = TYPE_SYS_BUS_DEVICE,
744ffc8542aSJan Kiszka     .instance_size = sizeof(ICPCtrlRegsState),
745ffc8542aSJan Kiszka     .instance_init = icp_control_init,
74626d32022SPavel Dovgalyuk     .class_init    = icp_control_class_init,
747ffc8542aSJan Kiszka };
748ffc8542aSJan Kiszka 
integratorcp_register_types(void)74953018216SPaolo Bonzini static void integratorcp_register_types(void)
75053018216SPaolo Bonzini {
75153018216SPaolo Bonzini     type_register_static(&icp_pic_info);
75253018216SPaolo Bonzini     type_register_static(&core_info);
753ffc8542aSJan Kiszka     type_register_static(&icp_ctrl_regs_info);
75453018216SPaolo Bonzini }
75553018216SPaolo Bonzini 
75653018216SPaolo Bonzini type_init(integratorcp_register_types)
757