xref: /qemu/hw/arm/integratorcp.c (revision 06b40d250ecfa1633209c2e431a7a38acfd03a98)
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"
1283c9f4caSPaolo Bonzini #include "hw/sysbus.h"
13d6454270SMarkus Armbruster #include "migration/vmstate.h"
1483c9f4caSPaolo 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"
181422e32dSPaolo Bonzini #include "net/net.h"
19dfc56946SRichard Henderson #include "system/address-spaces.h"
2032cad1ffSPhilippe Mathieu-Daudé #include "system/runstate.h"
2132cad1ffSPhilippe Mathieu-Daudé #include "system/system.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"
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,
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)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 
integratorcm_do_remap(IntegratorCMState * s)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 
integratorcm_set_ctrl(IntegratorCMState * s,uint32_t value)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 
integratorcm_update(IntegratorCMState * s)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 
integratorcm_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)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 
integratorcm_init(Object * obj)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 
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 
306ee6847d1SGerd Hoffmann     if (s->memsz >= 256) {
307b5ff1b31Sbellard         integrator_spd[31] = 64;
308b5ff1b31Sbellard         s->cm_sdram |= 0x10;
309ee6847d1SGerd Hoffmann     } else if (s->memsz >= 128) {
310b5ff1b31Sbellard         integrator_spd[31] = 32;
311b5ff1b31Sbellard         s->cm_sdram |= 0x0c;
312ee6847d1SGerd Hoffmann     } else if (s->memsz >= 64) {
313b5ff1b31Sbellard         integrator_spd[31] = 16;
314b5ff1b31Sbellard         s->cm_sdram |= 0x08;
315ee6847d1SGerd Hoffmann     } else if (s->memsz >= 32) {
316b5ff1b31Sbellard         integrator_spd[31] = 4;
317b5ff1b31Sbellard         s->cm_sdram |= 0x04;
318b5ff1b31Sbellard     } else {
319b5ff1b31Sbellard         integrator_spd[31] = 2;
320b5ff1b31Sbellard     }
321b5ff1b31Sbellard }
322b5ff1b31Sbellard 
323b5ff1b31Sbellard /* Integrator/CP hardware emulation.  */
324b5ff1b31Sbellard /* Primary interrupt controller.  */
325b5ff1b31Sbellard 
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 
33461074e46SBenoît Canet     MemoryRegion iomem;
335b5ff1b31Sbellard     uint32_t level;
336b5ff1b31Sbellard     uint32_t irq_enabled;
337b5ff1b31Sbellard     uint32_t fiq_enabled;
338d537cf6cSpbrook     qemu_irq parent_irq;
339d537cf6cSpbrook     qemu_irq parent_fiq;
340db1015e9SEduardo Habkost };
341b5ff1b31Sbellard 
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)354b5ff1b31Sbellard static void icp_pic_update(icp_pic_state *s)
355b5ff1b31Sbellard {
356b5ff1b31Sbellard     uint32_t flags;
357b5ff1b31Sbellard 
358b5ff1b31Sbellard     flags = (s->level & s->irq_enabled);
359d537cf6cSpbrook     qemu_set_irq(s->parent_irq, flags != 0);
360cdbdb648Spbrook     flags = (s->level & s->fiq_enabled);
361d537cf6cSpbrook     qemu_set_irq(s->parent_fiq, flags != 0);
362b5ff1b31Sbellard }
363b5ff1b31Sbellard 
icp_pic_set_irq(void * opaque,int irq,int level)364cdbdb648Spbrook static void icp_pic_set_irq(void *opaque, int irq, int level)
365b5ff1b31Sbellard {
36680337b66Sbellard     icp_pic_state *s = (icp_pic_state *)opaque;
367b5ff1b31Sbellard     if (level)
36880337b66Sbellard         s->level |= 1 << irq;
369b5ff1b31Sbellard     else
37080337b66Sbellard         s->level &= ~(1 << irq);
371b5ff1b31Sbellard     icp_pic_update(s);
372b5ff1b31Sbellard }
373b5ff1b31Sbellard 
icp_pic_read(void * opaque,hwaddr offset,unsigned size)374a8170e5eSAvi Kivity static uint64_t icp_pic_read(void *opaque, hwaddr offset,
37561074e46SBenoît Canet                              unsigned size)
376b5ff1b31Sbellard {
377b5ff1b31Sbellard     icp_pic_state *s = (icp_pic_state *)opaque;
378b5ff1b31Sbellard 
379b5ff1b31Sbellard     switch (offset >> 2) {
380b5ff1b31Sbellard     case 0: /* IRQ_STATUS */
381b5ff1b31Sbellard         return s->level & s->irq_enabled;
382b5ff1b31Sbellard     case 1: /* IRQ_RAWSTAT */
383b5ff1b31Sbellard         return s->level;
384b5ff1b31Sbellard     case 2: /* IRQ_ENABLESET */
385b5ff1b31Sbellard         return s->irq_enabled;
386b5ff1b31Sbellard     case 4: /* INT_SOFTSET */
387b5ff1b31Sbellard         return s->level & 1;
388b5ff1b31Sbellard     case 8: /* FRQ_STATUS */
389b5ff1b31Sbellard         return s->level & s->fiq_enabled;
390b5ff1b31Sbellard     case 9: /* FRQ_RAWSTAT */
391b5ff1b31Sbellard         return s->level;
392b5ff1b31Sbellard     case 10: /* FRQ_ENABLESET */
393b5ff1b31Sbellard         return s->fiq_enabled;
394b5ff1b31Sbellard     case 3: /* IRQ_ENABLECLR */
395b5ff1b31Sbellard     case 5: /* INT_SOFTCLR */
396b5ff1b31Sbellard     case 11: /* FRQ_ENABLECLR */
397b5ff1b31Sbellard     default:
3989904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
3999904625fSPhilippe Mathieu-Daudé                       __func__, offset);
400b5ff1b31Sbellard         return 0;
401b5ff1b31Sbellard     }
402b5ff1b31Sbellard }
403b5ff1b31Sbellard 
icp_pic_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)404a8170e5eSAvi Kivity static void icp_pic_write(void *opaque, hwaddr offset,
40561074e46SBenoît Canet                           uint64_t value, unsigned size)
406b5ff1b31Sbellard {
407b5ff1b31Sbellard     icp_pic_state *s = (icp_pic_state *)opaque;
408b5ff1b31Sbellard 
409b5ff1b31Sbellard     switch (offset >> 2) {
410b5ff1b31Sbellard     case 2: /* IRQ_ENABLESET */
411b5ff1b31Sbellard         s->irq_enabled |= value;
412b5ff1b31Sbellard         break;
413b5ff1b31Sbellard     case 3: /* IRQ_ENABLECLR */
414b5ff1b31Sbellard         s->irq_enabled &= ~value;
415b5ff1b31Sbellard         break;
416b5ff1b31Sbellard     case 4: /* INT_SOFTSET */
417b5ff1b31Sbellard         if (value & 1)
418d537cf6cSpbrook             icp_pic_set_irq(s, 0, 1);
419b5ff1b31Sbellard         break;
420b5ff1b31Sbellard     case 5: /* INT_SOFTCLR */
421b5ff1b31Sbellard         if (value & 1)
422d537cf6cSpbrook             icp_pic_set_irq(s, 0, 0);
423b5ff1b31Sbellard         break;
424b5ff1b31Sbellard     case 10: /* FRQ_ENABLESET */
425b5ff1b31Sbellard         s->fiq_enabled |= value;
426b5ff1b31Sbellard         break;
427b5ff1b31Sbellard     case 11: /* FRQ_ENABLECLR */
428b5ff1b31Sbellard         s->fiq_enabled &= ~value;
429b5ff1b31Sbellard         break;
430b5ff1b31Sbellard     case 0: /* IRQ_STATUS */
431b5ff1b31Sbellard     case 1: /* IRQ_RAWSTAT */
432b5ff1b31Sbellard     case 8: /* FRQ_STATUS */
433b5ff1b31Sbellard     case 9: /* FRQ_RAWSTAT */
434b5ff1b31Sbellard     default:
4359904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
4369904625fSPhilippe Mathieu-Daudé                       __func__, offset);
437b5ff1b31Sbellard         return;
438b5ff1b31Sbellard     }
439b5ff1b31Sbellard     icp_pic_update(s);
440b5ff1b31Sbellard }
441b5ff1b31Sbellard 
44261074e46SBenoît Canet static const MemoryRegionOps icp_pic_ops = {
44361074e46SBenoît Canet     .read = icp_pic_read,
44461074e46SBenoît Canet     .write = icp_pic_write,
44561074e46SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
446b5ff1b31Sbellard };
447b5ff1b31Sbellard 
icp_pic_init(Object * obj)448a1f42e0cSxiaoqiang.zhao static void icp_pic_init(Object *obj)
449b5ff1b31Sbellard {
450a1f42e0cSxiaoqiang.zhao     DeviceState *dev = DEVICE(obj);
451a1f42e0cSxiaoqiang.zhao     icp_pic_state *s = INTEGRATOR_PIC(obj);
452a1f42e0cSxiaoqiang.zhao     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
453b5ff1b31Sbellard 
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);
460b5ff1b31Sbellard }
461b5ff1b31Sbellard 
462b5ff1b31Sbellard /* CP control registers.  */
4630c36493eSBenoît Canet 
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)494a8170e5eSAvi Kivity static uint64_t icp_control_read(void *opaque, hwaddr offset,
4950c36493eSBenoît Canet                                  unsigned size)
496b5ff1b31Sbellard {
49783d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
49883d0cf89SJan Kiszka 
499b5ff1b31Sbellard     switch (offset >> 2) {
500b5ff1b31Sbellard     case 0: /* CP_IDFIELD */
501b5ff1b31Sbellard         return 0x41034003;
502b5ff1b31Sbellard     case 1: /* CP_FLASHPROG */
503b5ff1b31Sbellard         return 0;
504b5ff1b31Sbellard     case 2: /* CP_INTREG */
50583d0cf89SJan Kiszka         return s->intreg_state;
506b5ff1b31Sbellard     case 3: /* CP_DECODE */
507b5ff1b31Sbellard         return 0x11;
508b5ff1b31Sbellard     default:
5099904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
5109904625fSPhilippe Mathieu-Daudé                       __func__, offset);
511b5ff1b31Sbellard         return 0;
512b5ff1b31Sbellard     }
513b5ff1b31Sbellard }
514b5ff1b31Sbellard 
icp_control_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)515a8170e5eSAvi Kivity static void icp_control_write(void *opaque, hwaddr offset,
5160c36493eSBenoît Canet                           uint64_t value, unsigned size)
517b5ff1b31Sbellard {
51883d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
51983d0cf89SJan Kiszka 
520b5ff1b31Sbellard     switch (offset >> 2) {
521b5ff1b31Sbellard     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 */
526b5ff1b31Sbellard     case 3: /* CP_DECODE */
527b5ff1b31Sbellard         /* Nothing interesting implemented yet.  */
528b5ff1b31Sbellard         break;
529b5ff1b31Sbellard     default:
5309904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
5319904625fSPhilippe Mathieu-Daudé                       __func__, offset);
532b5ff1b31Sbellard     }
533b5ff1b31Sbellard }
5340c36493eSBenoît Canet 
5350c36493eSBenoît Canet static const MemoryRegionOps icp_control_ops = {
5360c36493eSBenoît Canet     .read = icp_control_read,
5370c36493eSBenoît Canet     .write = icp_control_write,
5380c36493eSBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
539b5ff1b31Sbellard };
540b5ff1b31Sbellard 
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)
563b5ff1b31Sbellard {
564ffc8542aSJan Kiszka     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
565ffc8542aSJan Kiszka     ICPCtrlRegsState *s = ICP_CONTROL_REGS(obj);
56683d0cf89SJan Kiszka     DeviceState *dev = DEVICE(obj);
567b5ff1b31Sbellard 
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);
576b5ff1b31Sbellard }
577b5ff1b31Sbellard 
578b5ff1b31Sbellard 
579b5ff1b31Sbellard /* Board init.  */
580b5ff1b31Sbellard 
581f93eb9ffSbalrog static struct arm_boot_info integrator_binfo = {
582f93eb9ffSbalrog     .loader_start = 0x0,
583f93eb9ffSbalrog     .board_id = 0x113,
584f93eb9ffSbalrog };
585f93eb9ffSbalrog 
integratorcp_init(MachineState * machine)5863ef96221SMarcel Apfelbaum static void integratorcp_init(MachineState *machine)
587b5ff1b31Sbellard {
5883ef96221SMarcel Apfelbaum     ram_addr_t ram_size = machine->ram_size;
589223a72f1SGreg Bellows     Object *cpuobj;
590393a9eabSAndreas Färber     ARMCPU *cpu;
591211adf4dSAvi Kivity     MemoryRegion *address_space_mem = get_system_memory();
592211adf4dSAvi Kivity     MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
593a7086888SPaul Brook     qemu_irq pic[32];
59483d0cf89SJan Kiszka     DeviceState *dev, *sic, *icp;
59526c607b8SPhilippe Mathieu-Daudé     DriveInfo *dinfo;
596a7086888SPaul Brook     int i;
597b5ff1b31Sbellard 
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 
612b5ff1b31Sbellard     /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
6131235fc06Sths     /* ??? RAM should repeat to fill physical memory space.  */
614b5ff1b31Sbellard     /* SDRAM at address zero*/
6153f25b3f4SIgor Mammedov     memory_region_add_subregion(address_space_mem, 0, machine->ram);
616b5ff1b31Sbellard     /* And again at address 0x80000000 */
6173f25b3f4SIgor Mammedov     memory_region_init_alias(ram_alias, NULL, "ram.alias", machine->ram,
6183f25b3f4SIgor Mammedov                              0, ram_size);
619211adf4dSAvi Kivity     memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
620b5ff1b31Sbellard 
6213e80f690SMarkus Armbruster     dev = qdev_new(TYPE_INTEGRATOR_CM);
622ee6847d1SGerd Hoffmann     qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
6233c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
624a7086888SPaul Brook     sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
625a7086888SPaul Brook 
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);
630a7086888SPaul Brook     for (i = 0; i < 32; i++) {
631067a3ddcSPaul Brook         pic[i] = qdev_get_gpio_in(dev, i);
632a7086888SPaul Brook     }
63383d0cf89SJan Kiszka     sic = sysbus_create_simple(TYPE_INTEGRATOR_PIC, 0xca000000, pic[26]);
6346a824ec3SPaul Brook     sysbus_create_varargs("integrator_pit", 0x13000000,
6356a824ec3SPaul Brook                           pic[5], pic[6], pic[7], NULL);
636a63bdb31SPaul Brook     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));
64186394e96SPaul Brook     sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
64286394e96SPaul Brook     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     }
6722e9bdce5SPaul Brook 
67349aff03eSPhilippe Mathieu-Daudé     dev = qdev_new("pl110");
674c2093660SPhilippe Mathieu-Daudé     object_property_set_link(OBJECT(dev), "framebuffer-memory",
675c2093660SPhilippe 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]);
679b5ff1b31Sbellard 
680f93eb9ffSbalrog     integrator_binfo.ram_size = ram_size;
6812744ece8STao Xu     arm_load_kernel(cpu, machine, &integrator_binfo);
682b5ff1b31Sbellard }
683b5ff1b31Sbellard 
integratorcp_machine_init(MachineClass * mc)684e264d29dSEduardo Habkost static void integratorcp_machine_init(MachineClass *mc)
685f80f9ec9SAnthony Liguori {
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";
691cdc8d7caSPhilippe Mathieu-Daudé     mc->auto_create_sdcard = true;
692b8ab0303SMartin Kletzander 
693b8ab0303SMartin Kletzander     machine_add_audiodev_property(mc);
694f80f9ec9SAnthony Liguori }
695f80f9ec9SAnthony Liguori 
696e264d29dSEduardo Habkost DEFINE_MACHINE("integratorcp", integratorcp_machine_init)
697f80f9ec9SAnthony Liguori 
698e15bd5ddSRichard Henderson static const Property core_properties[] = {
699257ec289SAndreas Färber     DEFINE_PROP_UINT32("memsz", IntegratorCMState, memsz, 0),
700999e12bbSAnthony Liguori };
701999e12bbSAnthony Liguori 
core_class_init(ObjectClass * klass,const void * data)702*12d1a768SPhilippe Mathieu-Daudé static void core_class_init(ObjectClass *klass, const void *data)
703999e12bbSAnthony Liguori {
70439bffca2SAnthony Liguori     DeviceClass *dc = DEVICE_CLASS(klass);
705999e12bbSAnthony Liguori 
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,const void * data)711*12d1a768SPhilippe Mathieu-Daudé static void icp_pic_class_init(ObjectClass *klass, const 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,const void * data)718*12d1a768SPhilippe Mathieu-Daudé static void icp_control_class_init(ObjectClass *klass, const void *data)
71926d32022SPavel Dovgalyuk {
72026d32022SPavel Dovgalyuk     DeviceClass *dc = DEVICE_CLASS(klass);
72126d32022SPavel Dovgalyuk 
72226d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_icp_control;
723ee6847d1SGerd Hoffmann }
724999e12bbSAnthony Liguori 
7258c43a6f0SAndreas Färber static const TypeInfo core_info = {
726257ec289SAndreas Färber     .name          = TYPE_INTEGRATOR_CM,
72739bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
728257ec289SAndreas Färber     .instance_size = sizeof(IntegratorCMState),
729a1f42e0cSxiaoqiang.zhao     .instance_init = integratorcm_init,
730999e12bbSAnthony Liguori     .class_init    = core_class_init,
731999e12bbSAnthony Liguori };
732999e12bbSAnthony Liguori 
7338c43a6f0SAndreas Färber static const TypeInfo icp_pic_info = {
73491b64626SAndreas Färber     .name          = TYPE_INTEGRATOR_PIC,
73539bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
73639bffca2SAnthony Liguori     .instance_size = sizeof(icp_pic_state),
737a1f42e0cSxiaoqiang.zhao     .instance_init = icp_pic_init,
73826d32022SPavel Dovgalyuk     .class_init    = icp_pic_class_init,
739ee6847d1SGerd Hoffmann };
740ee6847d1SGerd Hoffmann 
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)74983f7d43aSAndreas Färber static void integratorcp_register_types(void)
750a7086888SPaul Brook {
75139bffca2SAnthony Liguori     type_register_static(&icp_pic_info);
75239bffca2SAnthony Liguori     type_register_static(&core_info);
753ffc8542aSJan Kiszka     type_register_static(&icp_ctrl_regs_info);
754a7086888SPaul Brook }
755a7086888SPaul Brook 
75683f7d43aSAndreas Färber type_init(integratorcp_register_types)
757