xref: /qemu/hw/arm/integratorcp.c (revision db1015e92e04835c9eb50c29625fe566d1202dbd)
1b5ff1b31Sbellard /*
2b5ff1b31Sbellard  * ARM Integrator CP System emulation.
3b5ff1b31Sbellard  *
4a1bb27b1Spbrook  * Copyright (c) 2005-2007 CodeSourcery.
5b5ff1b31Sbellard  * Written by Paul Brook
6b5ff1b31Sbellard  *
78e31bf38SMatthew Fernandez  * This code is licensed under the GPL
8b5ff1b31Sbellard  */
9b5ff1b31Sbellard 
1012b16722SPeter Maydell #include "qemu/osdep.h"
11da34e65cSMarkus Armbruster #include "qapi/error.h"
124771d756SPaolo Bonzini #include "cpu.h"
1383c9f4caSPaolo Bonzini #include "hw/sysbus.h"
14d6454270SMarkus Armbruster #include "migration/vmstate.h"
1583c9f4caSPaolo Bonzini #include "hw/boards.h"
1612ec8bd5SPeter Maydell #include "hw/arm/boot.h"
17b8616055SAlex Bennée #include "hw/misc/arm_integrator_debug.h"
18437cc27dSPhilippe Mathieu-Daudé #include "hw/net/smc91c111.h"
191422e32dSPaolo Bonzini #include "net/net.h"
20022c62cbSPaolo Bonzini #include "exec/address-spaces.h"
2154d31236SMarkus Armbruster #include "sysemu/runstate.h"
229c17d615SPaolo Bonzini #include "sysemu/sysemu.h"
239904625fSPhilippe Mathieu-Daudé #include "qemu/log.h"
24223a72f1SGreg Bellows #include "qemu/error-report.h"
25f0d1d2c1Sxiaoqiang zhao #include "hw/char/pl011.h"
26650d103dSMarkus Armbruster #include "hw/hw.h"
2764552b6bSMarkus Armbruster #include "hw/irq.h"
2826c607b8SPhilippe Mathieu-Daudé #include "hw/sd/sd.h"
29*db1015e9SEduardo Habkost #include "qom/object.h"
30b5ff1b31Sbellard 
31257ec289SAndreas Färber #define TYPE_INTEGRATOR_CM "integrator_core"
32*db1015e9SEduardo Habkost typedef struct IntegratorCMState IntegratorCMState;
33257ec289SAndreas Färber #define INTEGRATOR_CM(obj) \
34257ec289SAndreas Färber     OBJECT_CHECK(IntegratorCMState, (obj), TYPE_INTEGRATOR_CM)
35257ec289SAndreas Färber 
36*db1015e9SEduardo Habkost struct IntegratorCMState {
37257ec289SAndreas Färber     /*< private >*/
38257ec289SAndreas Färber     SysBusDevice parent_obj;
39257ec289SAndreas Färber     /*< public >*/
40257ec289SAndreas Färber 
4171d9bc50SBenoît Canet     MemoryRegion iomem;
42ee6847d1SGerd Hoffmann     uint32_t memsz;
43211adf4dSAvi Kivity     MemoryRegion flash;
44b5ff1b31Sbellard     uint32_t cm_osc;
45b5ff1b31Sbellard     uint32_t cm_ctrl;
46b5ff1b31Sbellard     uint32_t cm_lock;
47b5ff1b31Sbellard     uint32_t cm_auxosc;
48b5ff1b31Sbellard     uint32_t cm_sdram;
49b5ff1b31Sbellard     uint32_t cm_init;
50b5ff1b31Sbellard     uint32_t cm_flags;
51b5ff1b31Sbellard     uint32_t cm_nvflags;
52f53977f7SJan Petrous     uint32_t cm_refcnt_offset;
53b5ff1b31Sbellard     uint32_t int_level;
54b5ff1b31Sbellard     uint32_t irq_enabled;
55b5ff1b31Sbellard     uint32_t fiq_enabled;
56*db1015e9SEduardo Habkost };
57b5ff1b31Sbellard 
58b5ff1b31Sbellard static uint8_t integrator_spd[128] = {
59b5ff1b31Sbellard    128, 8, 4, 11, 9, 1, 64, 0,  2, 0xa0, 0xa0, 0, 0, 8, 0, 1,
60b5ff1b31Sbellard    0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
61b5ff1b31Sbellard };
62b5ff1b31Sbellard 
6326d32022SPavel Dovgalyuk static const VMStateDescription vmstate_integratorcm = {
6426d32022SPavel Dovgalyuk     .name = "integratorcm",
6526d32022SPavel Dovgalyuk     .version_id = 1,
6626d32022SPavel Dovgalyuk     .minimum_version_id = 1,
6726d32022SPavel Dovgalyuk     .fields      = (VMStateField[]) {
6826d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_osc, IntegratorCMState),
6926d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_ctrl, IntegratorCMState),
7026d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_lock, IntegratorCMState),
7126d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_auxosc, IntegratorCMState),
7226d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_sdram, IntegratorCMState),
7326d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_init, IntegratorCMState),
7426d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_flags, IntegratorCMState),
7526d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_nvflags, IntegratorCMState),
7626d32022SPavel Dovgalyuk         VMSTATE_UINT32(int_level, IntegratorCMState),
7726d32022SPavel Dovgalyuk         VMSTATE_UINT32(irq_enabled, IntegratorCMState),
7826d32022SPavel Dovgalyuk         VMSTATE_UINT32(fiq_enabled, IntegratorCMState),
7926d32022SPavel Dovgalyuk         VMSTATE_END_OF_LIST()
8026d32022SPavel Dovgalyuk     }
8126d32022SPavel Dovgalyuk };
8226d32022SPavel Dovgalyuk 
83a8170e5eSAvi Kivity static uint64_t integratorcm_read(void *opaque, hwaddr offset,
8471d9bc50SBenoît Canet                                   unsigned size)
85b5ff1b31Sbellard {
86257ec289SAndreas Färber     IntegratorCMState *s = opaque;
87b5ff1b31Sbellard     if (offset >= 0x100 && offset < 0x200) {
88b5ff1b31Sbellard         /* CM_SPD */
89b5ff1b31Sbellard         if (offset >= 0x180)
90b5ff1b31Sbellard             return 0;
91b5ff1b31Sbellard         return integrator_spd[offset >> 2];
92b5ff1b31Sbellard     }
93b5ff1b31Sbellard     switch (offset >> 2) {
94b5ff1b31Sbellard     case 0: /* CM_ID */
95b5ff1b31Sbellard         return 0x411a3001;
96b5ff1b31Sbellard     case 1: /* CM_PROC */
97b5ff1b31Sbellard         return 0;
98b5ff1b31Sbellard     case 2: /* CM_OSC */
99b5ff1b31Sbellard         return s->cm_osc;
100b5ff1b31Sbellard     case 3: /* CM_CTRL */
101b5ff1b31Sbellard         return s->cm_ctrl;
102b5ff1b31Sbellard     case 4: /* CM_STAT */
103b5ff1b31Sbellard         return 0x00100000;
104b5ff1b31Sbellard     case 5: /* CM_LOCK */
105b5ff1b31Sbellard         if (s->cm_lock == 0xa05f) {
106b5ff1b31Sbellard             return 0x1a05f;
107b5ff1b31Sbellard         } else {
108b5ff1b31Sbellard             return s->cm_lock;
109b5ff1b31Sbellard         }
110b5ff1b31Sbellard     case 6: /* CM_LMBUSCNT */
111b5ff1b31Sbellard         /* ??? High frequency timer.  */
1122ac71179SPaul Brook         hw_error("integratorcm_read: CM_LMBUSCNT");
113b5ff1b31Sbellard     case 7: /* CM_AUXOSC */
114b5ff1b31Sbellard         return s->cm_auxosc;
115b5ff1b31Sbellard     case 8: /* CM_SDRAM */
116b5ff1b31Sbellard         return s->cm_sdram;
117b5ff1b31Sbellard     case 9: /* CM_INIT */
118b5ff1b31Sbellard         return s->cm_init;
119f53977f7SJan Petrous     case 10: /* CM_REFCNT */
120f53977f7SJan Petrous         /* This register, CM_REFCNT, provides a 32-bit count value.
121f53977f7SJan Petrous          * The count increments at the fixed reference clock frequency of 24MHz
122f53977f7SJan Petrous          * and can be used as a real-time counter.
123f53977f7SJan Petrous          */
124f53977f7SJan Petrous         return (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24,
125f53977f7SJan Petrous                                   1000) - s->cm_refcnt_offset;
126b5ff1b31Sbellard     case 12: /* CM_FLAGS */
127b5ff1b31Sbellard         return s->cm_flags;
128b5ff1b31Sbellard     case 14: /* CM_NVFLAGS */
129b5ff1b31Sbellard         return s->cm_nvflags;
130b5ff1b31Sbellard     case 16: /* CM_IRQ_STAT */
131b5ff1b31Sbellard         return s->int_level & s->irq_enabled;
132b5ff1b31Sbellard     case 17: /* CM_IRQ_RSTAT */
133b5ff1b31Sbellard         return s->int_level;
134b5ff1b31Sbellard     case 18: /* CM_IRQ_ENSET */
135b5ff1b31Sbellard         return s->irq_enabled;
136b5ff1b31Sbellard     case 20: /* CM_SOFT_INTSET */
137b5ff1b31Sbellard         return s->int_level & 1;
138b5ff1b31Sbellard     case 24: /* CM_FIQ_STAT */
139b5ff1b31Sbellard         return s->int_level & s->fiq_enabled;
140b5ff1b31Sbellard     case 25: /* CM_FIQ_RSTAT */
141b5ff1b31Sbellard         return s->int_level;
142b5ff1b31Sbellard     case 26: /* CM_FIQ_ENSET */
143b5ff1b31Sbellard         return s->fiq_enabled;
144b5ff1b31Sbellard     case 32: /* CM_VOLTAGE_CTL0 */
145b5ff1b31Sbellard     case 33: /* CM_VOLTAGE_CTL1 */
146b5ff1b31Sbellard     case 34: /* CM_VOLTAGE_CTL2 */
147b5ff1b31Sbellard     case 35: /* CM_VOLTAGE_CTL3 */
148b5ff1b31Sbellard         /* ??? Voltage control unimplemented.  */
149b5ff1b31Sbellard         return 0;
150b5ff1b31Sbellard     default:
1519904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_UNIMP,
1529904625fSPhilippe Mathieu-Daudé                       "%s: Unimplemented offset 0x%" HWADDR_PRIX "\n",
1539904625fSPhilippe Mathieu-Daudé                       __func__, offset);
154b5ff1b31Sbellard         return 0;
155b5ff1b31Sbellard     }
156b5ff1b31Sbellard }
157b5ff1b31Sbellard 
158257ec289SAndreas Färber static void integratorcm_do_remap(IntegratorCMState *s)
159b5ff1b31Sbellard {
160563c2bf3SPeter Maydell     /* Sync memory region state with CM_CTRL REMAP bit:
161563c2bf3SPeter Maydell      * bit 0 => flash at address 0; bit 1 => RAM
162563c2bf3SPeter Maydell      */
163563c2bf3SPeter Maydell     memory_region_set_enabled(&s->flash, !(s->cm_ctrl & 4));
164b5ff1b31Sbellard }
165b5ff1b31Sbellard 
166257ec289SAndreas Färber static void integratorcm_set_ctrl(IntegratorCMState *s, uint32_t value)
167b5ff1b31Sbellard {
168b5ff1b31Sbellard     if (value & 8) {
169cf83f140SEric Blake         qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
170b5ff1b31Sbellard     }
171df3f457bSPeter Maydell     if ((s->cm_ctrl ^ value) & 1) {
172df3f457bSPeter Maydell         /* (value & 1) != 0 means the green "MISC LED" is lit.
173df3f457bSPeter Maydell          * We don't have any nice place to display LEDs. printf is a bad
174df3f457bSPeter Maydell          * idea because Linux uses the LED as a heartbeat and the output
175df3f457bSPeter Maydell          * will swamp anything else on the terminal.
176df3f457bSPeter Maydell          */
177b5ff1b31Sbellard     }
178df3f457bSPeter Maydell     /* Note that the RESET bit [3] always reads as zero */
179df3f457bSPeter Maydell     s->cm_ctrl = (s->cm_ctrl & ~5) | (value & 5);
180563c2bf3SPeter Maydell     integratorcm_do_remap(s);
181b5ff1b31Sbellard }
182b5ff1b31Sbellard 
183257ec289SAndreas Färber static void integratorcm_update(IntegratorCMState *s)
184b5ff1b31Sbellard {
185b5ff1b31Sbellard     /* ??? The CPU irq/fiq is raised when either the core module or base PIC
186b5ff1b31Sbellard        are active.  */
187b5ff1b31Sbellard     if (s->int_level & (s->irq_enabled | s->fiq_enabled))
1882ac71179SPaul Brook         hw_error("Core module interrupt\n");
189b5ff1b31Sbellard }
190b5ff1b31Sbellard 
191a8170e5eSAvi Kivity static void integratorcm_write(void *opaque, hwaddr offset,
19271d9bc50SBenoît Canet                                uint64_t value, unsigned size)
193b5ff1b31Sbellard {
194257ec289SAndreas Färber     IntegratorCMState *s = opaque;
195b5ff1b31Sbellard     switch (offset >> 2) {
196b5ff1b31Sbellard     case 2: /* CM_OSC */
197b5ff1b31Sbellard         if (s->cm_lock == 0xa05f)
198b5ff1b31Sbellard             s->cm_osc = value;
199b5ff1b31Sbellard         break;
200b5ff1b31Sbellard     case 3: /* CM_CTRL */
201b5ff1b31Sbellard         integratorcm_set_ctrl(s, value);
202b5ff1b31Sbellard         break;
203b5ff1b31Sbellard     case 5: /* CM_LOCK */
204b5ff1b31Sbellard         s->cm_lock = value & 0xffff;
205b5ff1b31Sbellard         break;
206b5ff1b31Sbellard     case 7: /* CM_AUXOSC */
207b5ff1b31Sbellard         if (s->cm_lock == 0xa05f)
208b5ff1b31Sbellard             s->cm_auxosc = value;
209b5ff1b31Sbellard         break;
210b5ff1b31Sbellard     case 8: /* CM_SDRAM */
211b5ff1b31Sbellard         s->cm_sdram = value;
212b5ff1b31Sbellard         break;
213b5ff1b31Sbellard     case 9: /* CM_INIT */
214b5ff1b31Sbellard         /* ??? This can change the memory bus frequency.  */
215b5ff1b31Sbellard         s->cm_init = value;
216b5ff1b31Sbellard         break;
217b5ff1b31Sbellard     case 12: /* CM_FLAGSS */
218b5ff1b31Sbellard         s->cm_flags |= value;
219b5ff1b31Sbellard         break;
220b5ff1b31Sbellard     case 13: /* CM_FLAGSC */
221b5ff1b31Sbellard         s->cm_flags &= ~value;
222b5ff1b31Sbellard         break;
223b5ff1b31Sbellard     case 14: /* CM_NVFLAGSS */
224b5ff1b31Sbellard         s->cm_nvflags |= value;
225b5ff1b31Sbellard         break;
226b5ff1b31Sbellard     case 15: /* CM_NVFLAGSS */
227b5ff1b31Sbellard         s->cm_nvflags &= ~value;
228b5ff1b31Sbellard         break;
229b5ff1b31Sbellard     case 18: /* CM_IRQ_ENSET */
230b5ff1b31Sbellard         s->irq_enabled |= value;
231b5ff1b31Sbellard         integratorcm_update(s);
232b5ff1b31Sbellard         break;
233b5ff1b31Sbellard     case 19: /* CM_IRQ_ENCLR */
234b5ff1b31Sbellard         s->irq_enabled &= ~value;
235b5ff1b31Sbellard         integratorcm_update(s);
236b5ff1b31Sbellard         break;
237b5ff1b31Sbellard     case 20: /* CM_SOFT_INTSET */
238b5ff1b31Sbellard         s->int_level |= (value & 1);
239b5ff1b31Sbellard         integratorcm_update(s);
240b5ff1b31Sbellard         break;
241b5ff1b31Sbellard     case 21: /* CM_SOFT_INTCLR */
242b5ff1b31Sbellard         s->int_level &= ~(value & 1);
243b5ff1b31Sbellard         integratorcm_update(s);
244b5ff1b31Sbellard         break;
245b5ff1b31Sbellard     case 26: /* CM_FIQ_ENSET */
246b5ff1b31Sbellard         s->fiq_enabled |= value;
247b5ff1b31Sbellard         integratorcm_update(s);
248b5ff1b31Sbellard         break;
249b5ff1b31Sbellard     case 27: /* CM_FIQ_ENCLR */
250b5ff1b31Sbellard         s->fiq_enabled &= ~value;
251b5ff1b31Sbellard         integratorcm_update(s);
252b5ff1b31Sbellard         break;
253b5ff1b31Sbellard     case 32: /* CM_VOLTAGE_CTL0 */
254b5ff1b31Sbellard     case 33: /* CM_VOLTAGE_CTL1 */
255b5ff1b31Sbellard     case 34: /* CM_VOLTAGE_CTL2 */
256b5ff1b31Sbellard     case 35: /* CM_VOLTAGE_CTL3 */
257b5ff1b31Sbellard         /* ??? Voltage control unimplemented.  */
258b5ff1b31Sbellard         break;
259b5ff1b31Sbellard     default:
2609904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_UNIMP,
2619904625fSPhilippe Mathieu-Daudé                       "%s: Unimplemented offset 0x%" HWADDR_PRIX "\n",
2629904625fSPhilippe Mathieu-Daudé                       __func__, offset);
263b5ff1b31Sbellard         break;
264b5ff1b31Sbellard     }
265b5ff1b31Sbellard }
266b5ff1b31Sbellard 
267b5ff1b31Sbellard /* Integrator/CM control registers.  */
268b5ff1b31Sbellard 
26971d9bc50SBenoît Canet static const MemoryRegionOps integratorcm_ops = {
27071d9bc50SBenoît Canet     .read = integratorcm_read,
27171d9bc50SBenoît Canet     .write = integratorcm_write,
27271d9bc50SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
273b5ff1b31Sbellard };
274b5ff1b31Sbellard 
275a1f42e0cSxiaoqiang.zhao static void integratorcm_init(Object *obj)
276b5ff1b31Sbellard {
277a1f42e0cSxiaoqiang.zhao     IntegratorCMState *s = INTEGRATOR_CM(obj);
278b5ff1b31Sbellard 
279b5ff1b31Sbellard     s->cm_osc = 0x01000048;
280b5ff1b31Sbellard     /* ??? What should the high bits of this value be?  */
281b5ff1b31Sbellard     s->cm_auxosc = 0x0007feff;
282b5ff1b31Sbellard     s->cm_sdram = 0x00011122;
283e9d9ee23SJakub Jermar     memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
284e9d9ee23SJakub Jermar     s->cm_init = 0x00000112;
285e9d9ee23SJakub Jermar     s->cm_refcnt_offset = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24,
286e9d9ee23SJakub Jermar                                    1000);
287e9d9ee23SJakub Jermar 
288e9d9ee23SJakub Jermar     /* ??? Save/restore.  */
289e9d9ee23SJakub Jermar }
290e9d9ee23SJakub Jermar 
291e9d9ee23SJakub Jermar static void integratorcm_realize(DeviceState *d, Error **errp)
292e9d9ee23SJakub Jermar {
293e9d9ee23SJakub Jermar     IntegratorCMState *s = INTEGRATOR_CM(d);
2948720daadSThomas Huth     SysBusDevice *dev = SYS_BUS_DEVICE(d);
2958720daadSThomas Huth     Error *local_err = NULL;
2968720daadSThomas Huth 
2978720daadSThomas Huth     memory_region_init_ram(&s->flash, OBJECT(d), "integrator.flash", 0x100000,
2988720daadSThomas Huth                            &local_err);
2998720daadSThomas Huth     if (local_err) {
3008720daadSThomas Huth         error_propagate(errp, local_err);
3018720daadSThomas Huth         return;
3028720daadSThomas Huth     }
3038720daadSThomas Huth 
3048720daadSThomas Huth     memory_region_init_io(&s->iomem, OBJECT(d), &integratorcm_ops, s,
3058720daadSThomas Huth                           "integratorcm", 0x00800000);
3068720daadSThomas Huth     sysbus_init_mmio(dev, &s->iomem);
3078720daadSThomas Huth 
3088720daadSThomas Huth     integratorcm_do_remap(s);
309e9d9ee23SJakub Jermar 
310ee6847d1SGerd Hoffmann     if (s->memsz >= 256) {
311b5ff1b31Sbellard         integrator_spd[31] = 64;
312b5ff1b31Sbellard         s->cm_sdram |= 0x10;
313ee6847d1SGerd Hoffmann     } else if (s->memsz >= 128) {
314b5ff1b31Sbellard         integrator_spd[31] = 32;
315b5ff1b31Sbellard         s->cm_sdram |= 0x0c;
316ee6847d1SGerd Hoffmann     } else if (s->memsz >= 64) {
317b5ff1b31Sbellard         integrator_spd[31] = 16;
318b5ff1b31Sbellard         s->cm_sdram |= 0x08;
319ee6847d1SGerd Hoffmann     } else if (s->memsz >= 32) {
320b5ff1b31Sbellard         integrator_spd[31] = 4;
321b5ff1b31Sbellard         s->cm_sdram |= 0x04;
322b5ff1b31Sbellard     } else {
323b5ff1b31Sbellard         integrator_spd[31] = 2;
324b5ff1b31Sbellard     }
325b5ff1b31Sbellard }
326b5ff1b31Sbellard 
327b5ff1b31Sbellard /* Integrator/CP hardware emulation.  */
328b5ff1b31Sbellard /* Primary interrupt controller.  */
329b5ff1b31Sbellard 
33091b64626SAndreas Färber #define TYPE_INTEGRATOR_PIC "integrator_pic"
331*db1015e9SEduardo Habkost typedef struct icp_pic_state icp_pic_state;
33291b64626SAndreas Färber #define INTEGRATOR_PIC(obj) \
33391b64626SAndreas Färber    OBJECT_CHECK(icp_pic_state, (obj), TYPE_INTEGRATOR_PIC)
33491b64626SAndreas Färber 
335*db1015e9SEduardo Habkost struct icp_pic_state {
33691b64626SAndreas Färber     /*< private >*/
33791b64626SAndreas Färber     SysBusDevice parent_obj;
33891b64626SAndreas Färber     /*< public >*/
33991b64626SAndreas Färber 
34061074e46SBenoît Canet     MemoryRegion iomem;
341b5ff1b31Sbellard     uint32_t level;
342b5ff1b31Sbellard     uint32_t irq_enabled;
343b5ff1b31Sbellard     uint32_t fiq_enabled;
344d537cf6cSpbrook     qemu_irq parent_irq;
345d537cf6cSpbrook     qemu_irq parent_fiq;
346*db1015e9SEduardo Habkost };
347b5ff1b31Sbellard 
34826d32022SPavel Dovgalyuk static const VMStateDescription vmstate_icp_pic = {
34926d32022SPavel Dovgalyuk     .name = "icp_pic",
35026d32022SPavel Dovgalyuk     .version_id = 1,
35126d32022SPavel Dovgalyuk     .minimum_version_id = 1,
35226d32022SPavel Dovgalyuk     .fields      = (VMStateField[]) {
35326d32022SPavel Dovgalyuk         VMSTATE_UINT32(level, icp_pic_state),
35426d32022SPavel Dovgalyuk         VMSTATE_UINT32(irq_enabled, icp_pic_state),
35526d32022SPavel Dovgalyuk         VMSTATE_UINT32(fiq_enabled, icp_pic_state),
35626d32022SPavel Dovgalyuk         VMSTATE_END_OF_LIST()
35726d32022SPavel Dovgalyuk     }
35826d32022SPavel Dovgalyuk };
35926d32022SPavel Dovgalyuk 
360b5ff1b31Sbellard static void icp_pic_update(icp_pic_state *s)
361b5ff1b31Sbellard {
362b5ff1b31Sbellard     uint32_t flags;
363b5ff1b31Sbellard 
364b5ff1b31Sbellard     flags = (s->level & s->irq_enabled);
365d537cf6cSpbrook     qemu_set_irq(s->parent_irq, flags != 0);
366cdbdb648Spbrook     flags = (s->level & s->fiq_enabled);
367d537cf6cSpbrook     qemu_set_irq(s->parent_fiq, flags != 0);
368b5ff1b31Sbellard }
369b5ff1b31Sbellard 
370cdbdb648Spbrook static void icp_pic_set_irq(void *opaque, int irq, int level)
371b5ff1b31Sbellard {
37280337b66Sbellard     icp_pic_state *s = (icp_pic_state *)opaque;
373b5ff1b31Sbellard     if (level)
37480337b66Sbellard         s->level |= 1 << irq;
375b5ff1b31Sbellard     else
37680337b66Sbellard         s->level &= ~(1 << irq);
377b5ff1b31Sbellard     icp_pic_update(s);
378b5ff1b31Sbellard }
379b5ff1b31Sbellard 
380a8170e5eSAvi Kivity static uint64_t icp_pic_read(void *opaque, hwaddr offset,
38161074e46SBenoît Canet                              unsigned size)
382b5ff1b31Sbellard {
383b5ff1b31Sbellard     icp_pic_state *s = (icp_pic_state *)opaque;
384b5ff1b31Sbellard 
385b5ff1b31Sbellard     switch (offset >> 2) {
386b5ff1b31Sbellard     case 0: /* IRQ_STATUS */
387b5ff1b31Sbellard         return s->level & s->irq_enabled;
388b5ff1b31Sbellard     case 1: /* IRQ_RAWSTAT */
389b5ff1b31Sbellard         return s->level;
390b5ff1b31Sbellard     case 2: /* IRQ_ENABLESET */
391b5ff1b31Sbellard         return s->irq_enabled;
392b5ff1b31Sbellard     case 4: /* INT_SOFTSET */
393b5ff1b31Sbellard         return s->level & 1;
394b5ff1b31Sbellard     case 8: /* FRQ_STATUS */
395b5ff1b31Sbellard         return s->level & s->fiq_enabled;
396b5ff1b31Sbellard     case 9: /* FRQ_RAWSTAT */
397b5ff1b31Sbellard         return s->level;
398b5ff1b31Sbellard     case 10: /* FRQ_ENABLESET */
399b5ff1b31Sbellard         return s->fiq_enabled;
400b5ff1b31Sbellard     case 3: /* IRQ_ENABLECLR */
401b5ff1b31Sbellard     case 5: /* INT_SOFTCLR */
402b5ff1b31Sbellard     case 11: /* FRQ_ENABLECLR */
403b5ff1b31Sbellard     default:
4049904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
4059904625fSPhilippe Mathieu-Daudé                       __func__, offset);
406b5ff1b31Sbellard         return 0;
407b5ff1b31Sbellard     }
408b5ff1b31Sbellard }
409b5ff1b31Sbellard 
410a8170e5eSAvi Kivity static void icp_pic_write(void *opaque, hwaddr offset,
41161074e46SBenoît Canet                           uint64_t value, unsigned size)
412b5ff1b31Sbellard {
413b5ff1b31Sbellard     icp_pic_state *s = (icp_pic_state *)opaque;
414b5ff1b31Sbellard 
415b5ff1b31Sbellard     switch (offset >> 2) {
416b5ff1b31Sbellard     case 2: /* IRQ_ENABLESET */
417b5ff1b31Sbellard         s->irq_enabled |= value;
418b5ff1b31Sbellard         break;
419b5ff1b31Sbellard     case 3: /* IRQ_ENABLECLR */
420b5ff1b31Sbellard         s->irq_enabled &= ~value;
421b5ff1b31Sbellard         break;
422b5ff1b31Sbellard     case 4: /* INT_SOFTSET */
423b5ff1b31Sbellard         if (value & 1)
424d537cf6cSpbrook             icp_pic_set_irq(s, 0, 1);
425b5ff1b31Sbellard         break;
426b5ff1b31Sbellard     case 5: /* INT_SOFTCLR */
427b5ff1b31Sbellard         if (value & 1)
428d537cf6cSpbrook             icp_pic_set_irq(s, 0, 0);
429b5ff1b31Sbellard         break;
430b5ff1b31Sbellard     case 10: /* FRQ_ENABLESET */
431b5ff1b31Sbellard         s->fiq_enabled |= value;
432b5ff1b31Sbellard         break;
433b5ff1b31Sbellard     case 11: /* FRQ_ENABLECLR */
434b5ff1b31Sbellard         s->fiq_enabled &= ~value;
435b5ff1b31Sbellard         break;
436b5ff1b31Sbellard     case 0: /* IRQ_STATUS */
437b5ff1b31Sbellard     case 1: /* IRQ_RAWSTAT */
438b5ff1b31Sbellard     case 8: /* FRQ_STATUS */
439b5ff1b31Sbellard     case 9: /* FRQ_RAWSTAT */
440b5ff1b31Sbellard     default:
4419904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
4429904625fSPhilippe Mathieu-Daudé                       __func__, offset);
443b5ff1b31Sbellard         return;
444b5ff1b31Sbellard     }
445b5ff1b31Sbellard     icp_pic_update(s);
446b5ff1b31Sbellard }
447b5ff1b31Sbellard 
44861074e46SBenoît Canet static const MemoryRegionOps icp_pic_ops = {
44961074e46SBenoît Canet     .read = icp_pic_read,
45061074e46SBenoît Canet     .write = icp_pic_write,
45161074e46SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
452b5ff1b31Sbellard };
453b5ff1b31Sbellard 
454a1f42e0cSxiaoqiang.zhao static void icp_pic_init(Object *obj)
455b5ff1b31Sbellard {
456a1f42e0cSxiaoqiang.zhao     DeviceState *dev = DEVICE(obj);
457a1f42e0cSxiaoqiang.zhao     icp_pic_state *s = INTEGRATOR_PIC(obj);
458a1f42e0cSxiaoqiang.zhao     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
459b5ff1b31Sbellard 
46091b64626SAndreas Färber     qdev_init_gpio_in(dev, icp_pic_set_irq, 32);
46191b64626SAndreas Färber     sysbus_init_irq(sbd, &s->parent_irq);
46291b64626SAndreas Färber     sysbus_init_irq(sbd, &s->parent_fiq);
463a1f42e0cSxiaoqiang.zhao     memory_region_init_io(&s->iomem, obj, &icp_pic_ops, s,
46464bde0f3SPaolo Bonzini                           "icp-pic", 0x00800000);
46591b64626SAndreas Färber     sysbus_init_mmio(sbd, &s->iomem);
466b5ff1b31Sbellard }
467b5ff1b31Sbellard 
468b5ff1b31Sbellard /* CP control registers.  */
4690c36493eSBenoît Canet 
470ffc8542aSJan Kiszka #define TYPE_ICP_CONTROL_REGS "icp-ctrl-regs"
471*db1015e9SEduardo Habkost typedef struct ICPCtrlRegsState ICPCtrlRegsState;
472ffc8542aSJan Kiszka #define ICP_CONTROL_REGS(obj) \
473ffc8542aSJan Kiszka     OBJECT_CHECK(ICPCtrlRegsState, (obj), TYPE_ICP_CONTROL_REGS)
474ffc8542aSJan Kiszka 
475*db1015e9SEduardo Habkost struct ICPCtrlRegsState {
476ffc8542aSJan Kiszka     /*< private >*/
477ffc8542aSJan Kiszka     SysBusDevice parent_obj;
478ffc8542aSJan Kiszka     /*< public >*/
479ffc8542aSJan Kiszka 
480ffc8542aSJan Kiszka     MemoryRegion iomem;
48183d0cf89SJan Kiszka 
48283d0cf89SJan Kiszka     qemu_irq mmc_irq;
48383d0cf89SJan Kiszka     uint32_t intreg_state;
484*db1015e9SEduardo Habkost };
485ffc8542aSJan Kiszka 
48683d0cf89SJan Kiszka #define ICP_GPIO_MMC_WPROT      "mmc-wprot"
48783d0cf89SJan Kiszka #define ICP_GPIO_MMC_CARDIN     "mmc-cardin"
48883d0cf89SJan Kiszka 
48983d0cf89SJan Kiszka #define ICP_INTREG_WPROT        (1 << 0)
49083d0cf89SJan Kiszka #define ICP_INTREG_CARDIN       (1 << 3)
49183d0cf89SJan Kiszka 
49226d32022SPavel Dovgalyuk static const VMStateDescription vmstate_icp_control = {
49326d32022SPavel Dovgalyuk     .name = "icp_control",
49426d32022SPavel Dovgalyuk     .version_id = 1,
49526d32022SPavel Dovgalyuk     .minimum_version_id = 1,
49626d32022SPavel Dovgalyuk     .fields      = (VMStateField[]) {
49726d32022SPavel Dovgalyuk         VMSTATE_UINT32(intreg_state, ICPCtrlRegsState),
49826d32022SPavel Dovgalyuk         VMSTATE_END_OF_LIST()
49926d32022SPavel Dovgalyuk     }
50026d32022SPavel Dovgalyuk };
50126d32022SPavel Dovgalyuk 
502a8170e5eSAvi Kivity static uint64_t icp_control_read(void *opaque, hwaddr offset,
5030c36493eSBenoît Canet                                  unsigned size)
504b5ff1b31Sbellard {
50583d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
50683d0cf89SJan Kiszka 
507b5ff1b31Sbellard     switch (offset >> 2) {
508b5ff1b31Sbellard     case 0: /* CP_IDFIELD */
509b5ff1b31Sbellard         return 0x41034003;
510b5ff1b31Sbellard     case 1: /* CP_FLASHPROG */
511b5ff1b31Sbellard         return 0;
512b5ff1b31Sbellard     case 2: /* CP_INTREG */
51383d0cf89SJan Kiszka         return s->intreg_state;
514b5ff1b31Sbellard     case 3: /* CP_DECODE */
515b5ff1b31Sbellard         return 0x11;
516b5ff1b31Sbellard     default:
5179904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
5189904625fSPhilippe Mathieu-Daudé                       __func__, offset);
519b5ff1b31Sbellard         return 0;
520b5ff1b31Sbellard     }
521b5ff1b31Sbellard }
522b5ff1b31Sbellard 
523a8170e5eSAvi Kivity static void icp_control_write(void *opaque, hwaddr offset,
5240c36493eSBenoît Canet                           uint64_t value, unsigned size)
525b5ff1b31Sbellard {
52683d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
52783d0cf89SJan Kiszka 
528b5ff1b31Sbellard     switch (offset >> 2) {
529b5ff1b31Sbellard     case 2: /* CP_INTREG */
53083d0cf89SJan Kiszka         s->intreg_state &= ~(value & ICP_INTREG_CARDIN);
53183d0cf89SJan Kiszka         qemu_set_irq(s->mmc_irq, !!(s->intreg_state & ICP_INTREG_CARDIN));
53283d0cf89SJan Kiszka         break;
53383d0cf89SJan Kiszka     case 1: /* CP_FLASHPROG */
534b5ff1b31Sbellard     case 3: /* CP_DECODE */
535b5ff1b31Sbellard         /* Nothing interesting implemented yet.  */
536b5ff1b31Sbellard         break;
537b5ff1b31Sbellard     default:
5389904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
5399904625fSPhilippe Mathieu-Daudé                       __func__, offset);
540b5ff1b31Sbellard     }
541b5ff1b31Sbellard }
5420c36493eSBenoît Canet 
5430c36493eSBenoît Canet static const MemoryRegionOps icp_control_ops = {
5440c36493eSBenoît Canet     .read = icp_control_read,
5450c36493eSBenoît Canet     .write = icp_control_write,
5460c36493eSBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
547b5ff1b31Sbellard };
548b5ff1b31Sbellard 
54983d0cf89SJan Kiszka static void icp_control_mmc_wprot(void *opaque, int line, int level)
55083d0cf89SJan Kiszka {
55183d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
55283d0cf89SJan Kiszka 
55383d0cf89SJan Kiszka     s->intreg_state &= ~ICP_INTREG_WPROT;
55483d0cf89SJan Kiszka     if (level) {
55583d0cf89SJan Kiszka         s->intreg_state |= ICP_INTREG_WPROT;
55683d0cf89SJan Kiszka     }
55783d0cf89SJan Kiszka }
55883d0cf89SJan Kiszka 
55983d0cf89SJan Kiszka static void icp_control_mmc_cardin(void *opaque, int line, int level)
56083d0cf89SJan Kiszka {
56183d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
56283d0cf89SJan Kiszka 
56383d0cf89SJan Kiszka     /* line is released by writing to CP_INTREG */
56483d0cf89SJan Kiszka     if (level) {
56583d0cf89SJan Kiszka         s->intreg_state |= ICP_INTREG_CARDIN;
56683d0cf89SJan Kiszka         qemu_set_irq(s->mmc_irq, 1);
56783d0cf89SJan Kiszka     }
56883d0cf89SJan Kiszka }
56983d0cf89SJan Kiszka 
570ffc8542aSJan Kiszka static void icp_control_init(Object *obj)
571b5ff1b31Sbellard {
572ffc8542aSJan Kiszka     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
573ffc8542aSJan Kiszka     ICPCtrlRegsState *s = ICP_CONTROL_REGS(obj);
57483d0cf89SJan Kiszka     DeviceState *dev = DEVICE(obj);
575b5ff1b31Sbellard 
576ffc8542aSJan Kiszka     memory_region_init_io(&s->iomem, OBJECT(s), &icp_control_ops, s,
577ffc8542aSJan Kiszka                           "icp_ctrl_regs", 0x00800000);
578ffc8542aSJan Kiszka     sysbus_init_mmio(sbd, &s->iomem);
57983d0cf89SJan Kiszka 
58083d0cf89SJan Kiszka     qdev_init_gpio_in_named(dev, icp_control_mmc_wprot, ICP_GPIO_MMC_WPROT, 1);
58183d0cf89SJan Kiszka     qdev_init_gpio_in_named(dev, icp_control_mmc_cardin,
58283d0cf89SJan Kiszka                             ICP_GPIO_MMC_CARDIN, 1);
58383d0cf89SJan Kiszka     sysbus_init_irq(sbd, &s->mmc_irq);
584b5ff1b31Sbellard }
585b5ff1b31Sbellard 
586b5ff1b31Sbellard 
587b5ff1b31Sbellard /* Board init.  */
588b5ff1b31Sbellard 
589f93eb9ffSbalrog static struct arm_boot_info integrator_binfo = {
590f93eb9ffSbalrog     .loader_start = 0x0,
591f93eb9ffSbalrog     .board_id = 0x113,
592f93eb9ffSbalrog };
593f93eb9ffSbalrog 
5943ef96221SMarcel Apfelbaum static void integratorcp_init(MachineState *machine)
595b5ff1b31Sbellard {
5963ef96221SMarcel Apfelbaum     ram_addr_t ram_size = machine->ram_size;
597223a72f1SGreg Bellows     Object *cpuobj;
598393a9eabSAndreas Färber     ARMCPU *cpu;
599211adf4dSAvi Kivity     MemoryRegion *address_space_mem = get_system_memory();
600211adf4dSAvi Kivity     MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
601a7086888SPaul Brook     qemu_irq pic[32];
60283d0cf89SJan Kiszka     DeviceState *dev, *sic, *icp;
60326c607b8SPhilippe Mathieu-Daudé     DriveInfo *dinfo;
604a7086888SPaul Brook     int i;
605b5ff1b31Sbellard 
606ba1ba5ccSIgor Mammedov     cpuobj = object_new(machine->cpu_type);
607223a72f1SGreg Bellows 
60861e2f352SGreg Bellows     /* By default ARM1176 CPUs have EL3 enabled.  This board does not
60961e2f352SGreg Bellows      * currently support EL3 so the CPU EL3 property is disabled before
61061e2f352SGreg Bellows      * realization.
61161e2f352SGreg Bellows      */
61261e2f352SGreg Bellows     if (object_property_find(cpuobj, "has_el3", NULL)) {
6135325cc34SMarkus Armbruster         object_property_set_bool(cpuobj, "has_el3", false, &error_fatal);
61461e2f352SGreg Bellows     }
61561e2f352SGreg Bellows 
616ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
617223a72f1SGreg Bellows 
618223a72f1SGreg Bellows     cpu = ARM_CPU(cpuobj);
619223a72f1SGreg Bellows 
620b5ff1b31Sbellard     /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
6211235fc06Sths     /* ??? RAM should repeat to fill physical memory space.  */
622b5ff1b31Sbellard     /* SDRAM at address zero*/
6233f25b3f4SIgor Mammedov     memory_region_add_subregion(address_space_mem, 0, machine->ram);
624b5ff1b31Sbellard     /* And again at address 0x80000000 */
6253f25b3f4SIgor Mammedov     memory_region_init_alias(ram_alias, NULL, "ram.alias", machine->ram,
6263f25b3f4SIgor Mammedov                              0, ram_size);
627211adf4dSAvi Kivity     memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
628b5ff1b31Sbellard 
6293e80f690SMarkus Armbruster     dev = qdev_new(TYPE_INTEGRATOR_CM);
630ee6847d1SGerd Hoffmann     qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
6313c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
632a7086888SPaul Brook     sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
633a7086888SPaul Brook 
63491b64626SAndreas Färber     dev = sysbus_create_varargs(TYPE_INTEGRATOR_PIC, 0x14000000,
63599d228d6SPeter Maydell                                 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ),
63699d228d6SPeter Maydell                                 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ),
63799d228d6SPeter Maydell                                 NULL);
638a7086888SPaul Brook     for (i = 0; i < 32; i++) {
639067a3ddcSPaul Brook         pic[i] = qdev_get_gpio_in(dev, i);
640a7086888SPaul Brook     }
64183d0cf89SJan Kiszka     sic = sysbus_create_simple(TYPE_INTEGRATOR_PIC, 0xca000000, pic[26]);
6426a824ec3SPaul Brook     sysbus_create_varargs("integrator_pit", 0x13000000,
6436a824ec3SPaul Brook                           pic[5], pic[6], pic[7], NULL);
644a63bdb31SPaul Brook     sysbus_create_simple("pl031", 0x15000000, pic[8]);
6459bca0edbSPeter Maydell     pl011_create(0x16000000, pic[1], serial_hd(0));
6469bca0edbSPeter Maydell     pl011_create(0x17000000, pic[2], serial_hd(1));
64783d0cf89SJan Kiszka     icp = sysbus_create_simple(TYPE_ICP_CONTROL_REGS, 0xcb000000,
64883d0cf89SJan Kiszka                                qdev_get_gpio_in(sic, 3));
64986394e96SPaul Brook     sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
65086394e96SPaul Brook     sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]);
651b8616055SAlex Bennée     sysbus_create_simple(TYPE_INTEGRATOR_DEBUG, 0x1a000000, 0);
65283d0cf89SJan Kiszka 
65383d0cf89SJan Kiszka     dev = sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL);
65426c5b0f4SPhilippe Mathieu-Daudé     qdev_connect_gpio_out_named(dev, "card-read-only", 0,
65583d0cf89SJan Kiszka                           qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_WPROT, 0));
65626c5b0f4SPhilippe Mathieu-Daudé     qdev_connect_gpio_out_named(dev, "card-inserted", 0,
65783d0cf89SJan Kiszka                           qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_CARDIN, 0));
65826c607b8SPhilippe Mathieu-Daudé     dinfo = drive_get_next(IF_SD);
65926c607b8SPhilippe Mathieu-Daudé     if (dinfo) {
66026c607b8SPhilippe Mathieu-Daudé         DeviceState *card;
66126c607b8SPhilippe Mathieu-Daudé 
66226c607b8SPhilippe Mathieu-Daudé         card = qdev_new(TYPE_SD_CARD);
66326c607b8SPhilippe Mathieu-Daudé         qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo),
66426c607b8SPhilippe Mathieu-Daudé                                 &error_fatal);
66526c607b8SPhilippe Mathieu-Daudé         qdev_realize_and_unref(card, qdev_get_child_bus(dev, "sd-bus"),
66626c607b8SPhilippe Mathieu-Daudé                                &error_fatal);
66726c607b8SPhilippe Mathieu-Daudé     }
66826c607b8SPhilippe Mathieu-Daudé 
6695df2cfbcSPhilippe Mathieu-Daudé     sysbus_create_varargs("pl041", 0x1d000000, pic[25], NULL);
67083d0cf89SJan Kiszka 
671a005d073SStefan Hajnoczi     if (nd_table[0].used)
672d537cf6cSpbrook         smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
6732e9bdce5SPaul Brook 
6742e9bdce5SPaul Brook     sysbus_create_simple("pl110", 0xc0000000, pic[22]);
675b5ff1b31Sbellard 
676f93eb9ffSbalrog     integrator_binfo.ram_size = ram_size;
6772744ece8STao Xu     arm_load_kernel(cpu, machine, &integrator_binfo);
678b5ff1b31Sbellard }
679b5ff1b31Sbellard 
680e264d29dSEduardo Habkost static void integratorcp_machine_init(MachineClass *mc)
681f80f9ec9SAnthony Liguori {
682e264d29dSEduardo Habkost     mc->desc = "ARM Integrator/CP (ARM926EJ-S)";
683e264d29dSEduardo Habkost     mc->init = integratorcp_init;
6844672cbd7SPeter Maydell     mc->ignore_memory_transaction_failures = true;
685ba1ba5ccSIgor Mammedov     mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926");
6863f25b3f4SIgor Mammedov     mc->default_ram_id = "integrator.ram";
687f80f9ec9SAnthony Liguori }
688f80f9ec9SAnthony Liguori 
689e264d29dSEduardo Habkost DEFINE_MACHINE("integratorcp", integratorcp_machine_init)
690f80f9ec9SAnthony Liguori 
691999e12bbSAnthony Liguori static Property core_properties[] = {
692257ec289SAndreas Färber     DEFINE_PROP_UINT32("memsz", IntegratorCMState, memsz, 0),
693bb36f66aSGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
694999e12bbSAnthony Liguori };
695999e12bbSAnthony Liguori 
696999e12bbSAnthony Liguori static void core_class_init(ObjectClass *klass, void *data)
697999e12bbSAnthony Liguori {
69839bffca2SAnthony Liguori     DeviceClass *dc = DEVICE_CLASS(klass);
699999e12bbSAnthony Liguori 
7004f67d30bSMarc-André Lureau     device_class_set_props(dc, core_properties);
701e9d9ee23SJakub Jermar     dc->realize = integratorcm_realize;
70226d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_integratorcm;
70326d32022SPavel Dovgalyuk }
70426d32022SPavel Dovgalyuk 
70526d32022SPavel Dovgalyuk static void icp_pic_class_init(ObjectClass *klass, void *data)
70626d32022SPavel Dovgalyuk {
70726d32022SPavel Dovgalyuk     DeviceClass *dc = DEVICE_CLASS(klass);
70826d32022SPavel Dovgalyuk 
70926d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_icp_pic;
71026d32022SPavel Dovgalyuk }
71126d32022SPavel Dovgalyuk 
71226d32022SPavel Dovgalyuk static void icp_control_class_init(ObjectClass *klass, void *data)
71326d32022SPavel Dovgalyuk {
71426d32022SPavel Dovgalyuk     DeviceClass *dc = DEVICE_CLASS(klass);
71526d32022SPavel Dovgalyuk 
71626d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_icp_control;
717ee6847d1SGerd Hoffmann }
718999e12bbSAnthony Liguori 
7198c43a6f0SAndreas Färber static const TypeInfo core_info = {
720257ec289SAndreas Färber     .name          = TYPE_INTEGRATOR_CM,
72139bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
722257ec289SAndreas Färber     .instance_size = sizeof(IntegratorCMState),
723a1f42e0cSxiaoqiang.zhao     .instance_init = integratorcm_init,
724999e12bbSAnthony Liguori     .class_init    = core_class_init,
725999e12bbSAnthony Liguori };
726999e12bbSAnthony Liguori 
7278c43a6f0SAndreas Färber static const TypeInfo icp_pic_info = {
72891b64626SAndreas Färber     .name          = TYPE_INTEGRATOR_PIC,
72939bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
73039bffca2SAnthony Liguori     .instance_size = sizeof(icp_pic_state),
731a1f42e0cSxiaoqiang.zhao     .instance_init = icp_pic_init,
73226d32022SPavel Dovgalyuk     .class_init    = icp_pic_class_init,
733ee6847d1SGerd Hoffmann };
734ee6847d1SGerd Hoffmann 
735ffc8542aSJan Kiszka static const TypeInfo icp_ctrl_regs_info = {
736ffc8542aSJan Kiszka     .name          = TYPE_ICP_CONTROL_REGS,
737ffc8542aSJan Kiszka     .parent        = TYPE_SYS_BUS_DEVICE,
738ffc8542aSJan Kiszka     .instance_size = sizeof(ICPCtrlRegsState),
739ffc8542aSJan Kiszka     .instance_init = icp_control_init,
74026d32022SPavel Dovgalyuk     .class_init    = icp_control_class_init,
741ffc8542aSJan Kiszka };
742ffc8542aSJan Kiszka 
74383f7d43aSAndreas Färber static void integratorcp_register_types(void)
744a7086888SPaul Brook {
74539bffca2SAnthony Liguori     type_register_static(&icp_pic_info);
74639bffca2SAnthony Liguori     type_register_static(&core_info);
747ffc8542aSJan Kiszka     type_register_static(&icp_ctrl_regs_info);
748a7086888SPaul Brook }
749a7086888SPaul Brook 
75083f7d43aSAndreas Färber type_init(integratorcp_register_types)
751