xref: /qemu/hw/arm/integratorcp.c (revision 650d103d3ea959212f826acb9d3fe80cf30e347b)
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"
219c17d615SPaolo Bonzini #include "sysemu/sysemu.h"
22223a72f1SGreg Bellows #include "qemu/error-report.h"
23f0d1d2c1Sxiaoqiang zhao #include "hw/char/pl011.h"
24*650d103dSMarkus Armbruster #include "hw/hw.h"
2564552b6bSMarkus Armbruster #include "hw/irq.h"
26b5ff1b31Sbellard 
27257ec289SAndreas Färber #define TYPE_INTEGRATOR_CM "integrator_core"
28257ec289SAndreas Färber #define INTEGRATOR_CM(obj) \
29257ec289SAndreas Färber     OBJECT_CHECK(IntegratorCMState, (obj), TYPE_INTEGRATOR_CM)
30257ec289SAndreas Färber 
31257ec289SAndreas Färber typedef struct IntegratorCMState {
32257ec289SAndreas Färber     /*< private >*/
33257ec289SAndreas Färber     SysBusDevice parent_obj;
34257ec289SAndreas Färber     /*< public >*/
35257ec289SAndreas Färber 
3671d9bc50SBenoît Canet     MemoryRegion iomem;
37ee6847d1SGerd Hoffmann     uint32_t memsz;
38211adf4dSAvi Kivity     MemoryRegion flash;
39b5ff1b31Sbellard     uint32_t cm_osc;
40b5ff1b31Sbellard     uint32_t cm_ctrl;
41b5ff1b31Sbellard     uint32_t cm_lock;
42b5ff1b31Sbellard     uint32_t cm_auxosc;
43b5ff1b31Sbellard     uint32_t cm_sdram;
44b5ff1b31Sbellard     uint32_t cm_init;
45b5ff1b31Sbellard     uint32_t cm_flags;
46b5ff1b31Sbellard     uint32_t cm_nvflags;
47f53977f7SJan Petrous     uint32_t cm_refcnt_offset;
48b5ff1b31Sbellard     uint32_t int_level;
49b5ff1b31Sbellard     uint32_t irq_enabled;
50b5ff1b31Sbellard     uint32_t fiq_enabled;
51257ec289SAndreas Färber } IntegratorCMState;
52b5ff1b31Sbellard 
53b5ff1b31Sbellard static uint8_t integrator_spd[128] = {
54b5ff1b31Sbellard    128, 8, 4, 11, 9, 1, 64, 0,  2, 0xa0, 0xa0, 0, 0, 8, 0, 1,
55b5ff1b31Sbellard    0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
56b5ff1b31Sbellard };
57b5ff1b31Sbellard 
5826d32022SPavel Dovgalyuk static const VMStateDescription vmstate_integratorcm = {
5926d32022SPavel Dovgalyuk     .name = "integratorcm",
6026d32022SPavel Dovgalyuk     .version_id = 1,
6126d32022SPavel Dovgalyuk     .minimum_version_id = 1,
6226d32022SPavel Dovgalyuk     .fields      = (VMStateField[]) {
6326d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_osc, IntegratorCMState),
6426d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_ctrl, IntegratorCMState),
6526d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_lock, IntegratorCMState),
6626d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_auxosc, IntegratorCMState),
6726d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_sdram, IntegratorCMState),
6826d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_init, IntegratorCMState),
6926d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_flags, IntegratorCMState),
7026d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_nvflags, IntegratorCMState),
7126d32022SPavel Dovgalyuk         VMSTATE_UINT32(int_level, IntegratorCMState),
7226d32022SPavel Dovgalyuk         VMSTATE_UINT32(irq_enabled, IntegratorCMState),
7326d32022SPavel Dovgalyuk         VMSTATE_UINT32(fiq_enabled, IntegratorCMState),
7426d32022SPavel Dovgalyuk         VMSTATE_END_OF_LIST()
7526d32022SPavel Dovgalyuk     }
7626d32022SPavel Dovgalyuk };
7726d32022SPavel Dovgalyuk 
78a8170e5eSAvi Kivity static uint64_t integratorcm_read(void *opaque, hwaddr offset,
7971d9bc50SBenoît Canet                                   unsigned size)
80b5ff1b31Sbellard {
81257ec289SAndreas Färber     IntegratorCMState *s = opaque;
82b5ff1b31Sbellard     if (offset >= 0x100 && offset < 0x200) {
83b5ff1b31Sbellard         /* CM_SPD */
84b5ff1b31Sbellard         if (offset >= 0x180)
85b5ff1b31Sbellard             return 0;
86b5ff1b31Sbellard         return integrator_spd[offset >> 2];
87b5ff1b31Sbellard     }
88b5ff1b31Sbellard     switch (offset >> 2) {
89b5ff1b31Sbellard     case 0: /* CM_ID */
90b5ff1b31Sbellard         return 0x411a3001;
91b5ff1b31Sbellard     case 1: /* CM_PROC */
92b5ff1b31Sbellard         return 0;
93b5ff1b31Sbellard     case 2: /* CM_OSC */
94b5ff1b31Sbellard         return s->cm_osc;
95b5ff1b31Sbellard     case 3: /* CM_CTRL */
96b5ff1b31Sbellard         return s->cm_ctrl;
97b5ff1b31Sbellard     case 4: /* CM_STAT */
98b5ff1b31Sbellard         return 0x00100000;
99b5ff1b31Sbellard     case 5: /* CM_LOCK */
100b5ff1b31Sbellard         if (s->cm_lock == 0xa05f) {
101b5ff1b31Sbellard             return 0x1a05f;
102b5ff1b31Sbellard         } else {
103b5ff1b31Sbellard             return s->cm_lock;
104b5ff1b31Sbellard         }
105b5ff1b31Sbellard     case 6: /* CM_LMBUSCNT */
106b5ff1b31Sbellard         /* ??? High frequency timer.  */
1072ac71179SPaul Brook         hw_error("integratorcm_read: CM_LMBUSCNT");
108b5ff1b31Sbellard     case 7: /* CM_AUXOSC */
109b5ff1b31Sbellard         return s->cm_auxosc;
110b5ff1b31Sbellard     case 8: /* CM_SDRAM */
111b5ff1b31Sbellard         return s->cm_sdram;
112b5ff1b31Sbellard     case 9: /* CM_INIT */
113b5ff1b31Sbellard         return s->cm_init;
114f53977f7SJan Petrous     case 10: /* CM_REFCNT */
115f53977f7SJan Petrous         /* This register, CM_REFCNT, provides a 32-bit count value.
116f53977f7SJan Petrous          * The count increments at the fixed reference clock frequency of 24MHz
117f53977f7SJan Petrous          * and can be used as a real-time counter.
118f53977f7SJan Petrous          */
119f53977f7SJan Petrous         return (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24,
120f53977f7SJan Petrous                                   1000) - s->cm_refcnt_offset;
121b5ff1b31Sbellard     case 12: /* CM_FLAGS */
122b5ff1b31Sbellard         return s->cm_flags;
123b5ff1b31Sbellard     case 14: /* CM_NVFLAGS */
124b5ff1b31Sbellard         return s->cm_nvflags;
125b5ff1b31Sbellard     case 16: /* CM_IRQ_STAT */
126b5ff1b31Sbellard         return s->int_level & s->irq_enabled;
127b5ff1b31Sbellard     case 17: /* CM_IRQ_RSTAT */
128b5ff1b31Sbellard         return s->int_level;
129b5ff1b31Sbellard     case 18: /* CM_IRQ_ENSET */
130b5ff1b31Sbellard         return s->irq_enabled;
131b5ff1b31Sbellard     case 20: /* CM_SOFT_INTSET */
132b5ff1b31Sbellard         return s->int_level & 1;
133b5ff1b31Sbellard     case 24: /* CM_FIQ_STAT */
134b5ff1b31Sbellard         return s->int_level & s->fiq_enabled;
135b5ff1b31Sbellard     case 25: /* CM_FIQ_RSTAT */
136b5ff1b31Sbellard         return s->int_level;
137b5ff1b31Sbellard     case 26: /* CM_FIQ_ENSET */
138b5ff1b31Sbellard         return s->fiq_enabled;
139b5ff1b31Sbellard     case 32: /* CM_VOLTAGE_CTL0 */
140b5ff1b31Sbellard     case 33: /* CM_VOLTAGE_CTL1 */
141b5ff1b31Sbellard     case 34: /* CM_VOLTAGE_CTL2 */
142b5ff1b31Sbellard     case 35: /* CM_VOLTAGE_CTL3 */
143b5ff1b31Sbellard         /* ??? Voltage control unimplemented.  */
144b5ff1b31Sbellard         return 0;
145b5ff1b31Sbellard     default:
1462ac71179SPaul Brook         hw_error("integratorcm_read: Unimplemented offset 0x%x\n",
1472ac71179SPaul Brook                  (int)offset);
148b5ff1b31Sbellard         return 0;
149b5ff1b31Sbellard     }
150b5ff1b31Sbellard }
151b5ff1b31Sbellard 
152257ec289SAndreas Färber static void integratorcm_do_remap(IntegratorCMState *s)
153b5ff1b31Sbellard {
154563c2bf3SPeter Maydell     /* Sync memory region state with CM_CTRL REMAP bit:
155563c2bf3SPeter Maydell      * bit 0 => flash at address 0; bit 1 => RAM
156563c2bf3SPeter Maydell      */
157563c2bf3SPeter Maydell     memory_region_set_enabled(&s->flash, !(s->cm_ctrl & 4));
158b5ff1b31Sbellard }
159b5ff1b31Sbellard 
160257ec289SAndreas Färber static void integratorcm_set_ctrl(IntegratorCMState *s, uint32_t value)
161b5ff1b31Sbellard {
162b5ff1b31Sbellard     if (value & 8) {
163cf83f140SEric Blake         qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
164b5ff1b31Sbellard     }
165df3f457bSPeter Maydell     if ((s->cm_ctrl ^ value) & 1) {
166df3f457bSPeter Maydell         /* (value & 1) != 0 means the green "MISC LED" is lit.
167df3f457bSPeter Maydell          * We don't have any nice place to display LEDs. printf is a bad
168df3f457bSPeter Maydell          * idea because Linux uses the LED as a heartbeat and the output
169df3f457bSPeter Maydell          * will swamp anything else on the terminal.
170df3f457bSPeter Maydell          */
171b5ff1b31Sbellard     }
172df3f457bSPeter Maydell     /* Note that the RESET bit [3] always reads as zero */
173df3f457bSPeter Maydell     s->cm_ctrl = (s->cm_ctrl & ~5) | (value & 5);
174563c2bf3SPeter Maydell     integratorcm_do_remap(s);
175b5ff1b31Sbellard }
176b5ff1b31Sbellard 
177257ec289SAndreas Färber static void integratorcm_update(IntegratorCMState *s)
178b5ff1b31Sbellard {
179b5ff1b31Sbellard     /* ??? The CPU irq/fiq is raised when either the core module or base PIC
180b5ff1b31Sbellard        are active.  */
181b5ff1b31Sbellard     if (s->int_level & (s->irq_enabled | s->fiq_enabled))
1822ac71179SPaul Brook         hw_error("Core module interrupt\n");
183b5ff1b31Sbellard }
184b5ff1b31Sbellard 
185a8170e5eSAvi Kivity static void integratorcm_write(void *opaque, hwaddr offset,
18671d9bc50SBenoît Canet                                uint64_t value, unsigned size)
187b5ff1b31Sbellard {
188257ec289SAndreas Färber     IntegratorCMState *s = opaque;
189b5ff1b31Sbellard     switch (offset >> 2) {
190b5ff1b31Sbellard     case 2: /* CM_OSC */
191b5ff1b31Sbellard         if (s->cm_lock == 0xa05f)
192b5ff1b31Sbellard             s->cm_osc = value;
193b5ff1b31Sbellard         break;
194b5ff1b31Sbellard     case 3: /* CM_CTRL */
195b5ff1b31Sbellard         integratorcm_set_ctrl(s, value);
196b5ff1b31Sbellard         break;
197b5ff1b31Sbellard     case 5: /* CM_LOCK */
198b5ff1b31Sbellard         s->cm_lock = value & 0xffff;
199b5ff1b31Sbellard         break;
200b5ff1b31Sbellard     case 7: /* CM_AUXOSC */
201b5ff1b31Sbellard         if (s->cm_lock == 0xa05f)
202b5ff1b31Sbellard             s->cm_auxosc = value;
203b5ff1b31Sbellard         break;
204b5ff1b31Sbellard     case 8: /* CM_SDRAM */
205b5ff1b31Sbellard         s->cm_sdram = value;
206b5ff1b31Sbellard         break;
207b5ff1b31Sbellard     case 9: /* CM_INIT */
208b5ff1b31Sbellard         /* ??? This can change the memory bus frequency.  */
209b5ff1b31Sbellard         s->cm_init = value;
210b5ff1b31Sbellard         break;
211b5ff1b31Sbellard     case 12: /* CM_FLAGSS */
212b5ff1b31Sbellard         s->cm_flags |= value;
213b5ff1b31Sbellard         break;
214b5ff1b31Sbellard     case 13: /* CM_FLAGSC */
215b5ff1b31Sbellard         s->cm_flags &= ~value;
216b5ff1b31Sbellard         break;
217b5ff1b31Sbellard     case 14: /* CM_NVFLAGSS */
218b5ff1b31Sbellard         s->cm_nvflags |= value;
219b5ff1b31Sbellard         break;
220b5ff1b31Sbellard     case 15: /* CM_NVFLAGSS */
221b5ff1b31Sbellard         s->cm_nvflags &= ~value;
222b5ff1b31Sbellard         break;
223b5ff1b31Sbellard     case 18: /* CM_IRQ_ENSET */
224b5ff1b31Sbellard         s->irq_enabled |= value;
225b5ff1b31Sbellard         integratorcm_update(s);
226b5ff1b31Sbellard         break;
227b5ff1b31Sbellard     case 19: /* CM_IRQ_ENCLR */
228b5ff1b31Sbellard         s->irq_enabled &= ~value;
229b5ff1b31Sbellard         integratorcm_update(s);
230b5ff1b31Sbellard         break;
231b5ff1b31Sbellard     case 20: /* CM_SOFT_INTSET */
232b5ff1b31Sbellard         s->int_level |= (value & 1);
233b5ff1b31Sbellard         integratorcm_update(s);
234b5ff1b31Sbellard         break;
235b5ff1b31Sbellard     case 21: /* CM_SOFT_INTCLR */
236b5ff1b31Sbellard         s->int_level &= ~(value & 1);
237b5ff1b31Sbellard         integratorcm_update(s);
238b5ff1b31Sbellard         break;
239b5ff1b31Sbellard     case 26: /* CM_FIQ_ENSET */
240b5ff1b31Sbellard         s->fiq_enabled |= value;
241b5ff1b31Sbellard         integratorcm_update(s);
242b5ff1b31Sbellard         break;
243b5ff1b31Sbellard     case 27: /* CM_FIQ_ENCLR */
244b5ff1b31Sbellard         s->fiq_enabled &= ~value;
245b5ff1b31Sbellard         integratorcm_update(s);
246b5ff1b31Sbellard         break;
247b5ff1b31Sbellard     case 32: /* CM_VOLTAGE_CTL0 */
248b5ff1b31Sbellard     case 33: /* CM_VOLTAGE_CTL1 */
249b5ff1b31Sbellard     case 34: /* CM_VOLTAGE_CTL2 */
250b5ff1b31Sbellard     case 35: /* CM_VOLTAGE_CTL3 */
251b5ff1b31Sbellard         /* ??? Voltage control unimplemented.  */
252b5ff1b31Sbellard         break;
253b5ff1b31Sbellard     default:
2542ac71179SPaul Brook         hw_error("integratorcm_write: Unimplemented offset 0x%x\n",
2552ac71179SPaul Brook                  (int)offset);
256b5ff1b31Sbellard         break;
257b5ff1b31Sbellard     }
258b5ff1b31Sbellard }
259b5ff1b31Sbellard 
260b5ff1b31Sbellard /* Integrator/CM control registers.  */
261b5ff1b31Sbellard 
26271d9bc50SBenoît Canet static const MemoryRegionOps integratorcm_ops = {
26371d9bc50SBenoît Canet     .read = integratorcm_read,
26471d9bc50SBenoît Canet     .write = integratorcm_write,
26571d9bc50SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
266b5ff1b31Sbellard };
267b5ff1b31Sbellard 
268a1f42e0cSxiaoqiang.zhao static void integratorcm_init(Object *obj)
269b5ff1b31Sbellard {
270a1f42e0cSxiaoqiang.zhao     IntegratorCMState *s = INTEGRATOR_CM(obj);
271b5ff1b31Sbellard 
272b5ff1b31Sbellard     s->cm_osc = 0x01000048;
273b5ff1b31Sbellard     /* ??? What should the high bits of this value be?  */
274b5ff1b31Sbellard     s->cm_auxosc = 0x0007feff;
275b5ff1b31Sbellard     s->cm_sdram = 0x00011122;
276e9d9ee23SJakub Jermar     memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
277e9d9ee23SJakub Jermar     s->cm_init = 0x00000112;
278e9d9ee23SJakub Jermar     s->cm_refcnt_offset = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24,
279e9d9ee23SJakub Jermar                                    1000);
280e9d9ee23SJakub Jermar 
281e9d9ee23SJakub Jermar     /* ??? Save/restore.  */
282e9d9ee23SJakub Jermar }
283e9d9ee23SJakub Jermar 
284e9d9ee23SJakub Jermar static void integratorcm_realize(DeviceState *d, Error **errp)
285e9d9ee23SJakub Jermar {
286e9d9ee23SJakub Jermar     IntegratorCMState *s = INTEGRATOR_CM(d);
2878720daadSThomas Huth     SysBusDevice *dev = SYS_BUS_DEVICE(d);
2888720daadSThomas Huth     Error *local_err = NULL;
2898720daadSThomas Huth 
2908720daadSThomas Huth     memory_region_init_ram(&s->flash, OBJECT(d), "integrator.flash", 0x100000,
2918720daadSThomas Huth                            &local_err);
2928720daadSThomas Huth     if (local_err) {
2938720daadSThomas Huth         error_propagate(errp, local_err);
2948720daadSThomas Huth         return;
2958720daadSThomas Huth     }
2968720daadSThomas Huth 
2978720daadSThomas Huth     memory_region_init_io(&s->iomem, OBJECT(d), &integratorcm_ops, s,
2988720daadSThomas Huth                           "integratorcm", 0x00800000);
2998720daadSThomas Huth     sysbus_init_mmio(dev, &s->iomem);
3008720daadSThomas Huth 
3018720daadSThomas Huth     integratorcm_do_remap(s);
302e9d9ee23SJakub Jermar 
303ee6847d1SGerd Hoffmann     if (s->memsz >= 256) {
304b5ff1b31Sbellard         integrator_spd[31] = 64;
305b5ff1b31Sbellard         s->cm_sdram |= 0x10;
306ee6847d1SGerd Hoffmann     } else if (s->memsz >= 128) {
307b5ff1b31Sbellard         integrator_spd[31] = 32;
308b5ff1b31Sbellard         s->cm_sdram |= 0x0c;
309ee6847d1SGerd Hoffmann     } else if (s->memsz >= 64) {
310b5ff1b31Sbellard         integrator_spd[31] = 16;
311b5ff1b31Sbellard         s->cm_sdram |= 0x08;
312ee6847d1SGerd Hoffmann     } else if (s->memsz >= 32) {
313b5ff1b31Sbellard         integrator_spd[31] = 4;
314b5ff1b31Sbellard         s->cm_sdram |= 0x04;
315b5ff1b31Sbellard     } else {
316b5ff1b31Sbellard         integrator_spd[31] = 2;
317b5ff1b31Sbellard     }
318b5ff1b31Sbellard }
319b5ff1b31Sbellard 
320b5ff1b31Sbellard /* Integrator/CP hardware emulation.  */
321b5ff1b31Sbellard /* Primary interrupt controller.  */
322b5ff1b31Sbellard 
32391b64626SAndreas Färber #define TYPE_INTEGRATOR_PIC "integrator_pic"
32491b64626SAndreas Färber #define INTEGRATOR_PIC(obj) \
32591b64626SAndreas Färber    OBJECT_CHECK(icp_pic_state, (obj), TYPE_INTEGRATOR_PIC)
32691b64626SAndreas Färber 
32791b64626SAndreas Färber typedef struct icp_pic_state {
32891b64626SAndreas Färber     /*< private >*/
32991b64626SAndreas Färber     SysBusDevice parent_obj;
33091b64626SAndreas Färber     /*< public >*/
33191b64626SAndreas Färber 
33261074e46SBenoît Canet     MemoryRegion iomem;
333b5ff1b31Sbellard     uint32_t level;
334b5ff1b31Sbellard     uint32_t irq_enabled;
335b5ff1b31Sbellard     uint32_t fiq_enabled;
336d537cf6cSpbrook     qemu_irq parent_irq;
337d537cf6cSpbrook     qemu_irq parent_fiq;
338b5ff1b31Sbellard } icp_pic_state;
339b5ff1b31Sbellard 
34026d32022SPavel Dovgalyuk static const VMStateDescription vmstate_icp_pic = {
34126d32022SPavel Dovgalyuk     .name = "icp_pic",
34226d32022SPavel Dovgalyuk     .version_id = 1,
34326d32022SPavel Dovgalyuk     .minimum_version_id = 1,
34426d32022SPavel Dovgalyuk     .fields      = (VMStateField[]) {
34526d32022SPavel Dovgalyuk         VMSTATE_UINT32(level, icp_pic_state),
34626d32022SPavel Dovgalyuk         VMSTATE_UINT32(irq_enabled, icp_pic_state),
34726d32022SPavel Dovgalyuk         VMSTATE_UINT32(fiq_enabled, icp_pic_state),
34826d32022SPavel Dovgalyuk         VMSTATE_END_OF_LIST()
34926d32022SPavel Dovgalyuk     }
35026d32022SPavel Dovgalyuk };
35126d32022SPavel Dovgalyuk 
352b5ff1b31Sbellard static void icp_pic_update(icp_pic_state *s)
353b5ff1b31Sbellard {
354b5ff1b31Sbellard     uint32_t flags;
355b5ff1b31Sbellard 
356b5ff1b31Sbellard     flags = (s->level & s->irq_enabled);
357d537cf6cSpbrook     qemu_set_irq(s->parent_irq, flags != 0);
358cdbdb648Spbrook     flags = (s->level & s->fiq_enabled);
359d537cf6cSpbrook     qemu_set_irq(s->parent_fiq, flags != 0);
360b5ff1b31Sbellard }
361b5ff1b31Sbellard 
362cdbdb648Spbrook static void icp_pic_set_irq(void *opaque, int irq, int level)
363b5ff1b31Sbellard {
36480337b66Sbellard     icp_pic_state *s = (icp_pic_state *)opaque;
365b5ff1b31Sbellard     if (level)
36680337b66Sbellard         s->level |= 1 << irq;
367b5ff1b31Sbellard     else
36880337b66Sbellard         s->level &= ~(1 << irq);
369b5ff1b31Sbellard     icp_pic_update(s);
370b5ff1b31Sbellard }
371b5ff1b31Sbellard 
372a8170e5eSAvi Kivity static uint64_t icp_pic_read(void *opaque, hwaddr offset,
37361074e46SBenoît Canet                              unsigned size)
374b5ff1b31Sbellard {
375b5ff1b31Sbellard     icp_pic_state *s = (icp_pic_state *)opaque;
376b5ff1b31Sbellard 
377b5ff1b31Sbellard     switch (offset >> 2) {
378b5ff1b31Sbellard     case 0: /* IRQ_STATUS */
379b5ff1b31Sbellard         return s->level & s->irq_enabled;
380b5ff1b31Sbellard     case 1: /* IRQ_RAWSTAT */
381b5ff1b31Sbellard         return s->level;
382b5ff1b31Sbellard     case 2: /* IRQ_ENABLESET */
383b5ff1b31Sbellard         return s->irq_enabled;
384b5ff1b31Sbellard     case 4: /* INT_SOFTSET */
385b5ff1b31Sbellard         return s->level & 1;
386b5ff1b31Sbellard     case 8: /* FRQ_STATUS */
387b5ff1b31Sbellard         return s->level & s->fiq_enabled;
388b5ff1b31Sbellard     case 9: /* FRQ_RAWSTAT */
389b5ff1b31Sbellard         return s->level;
390b5ff1b31Sbellard     case 10: /* FRQ_ENABLESET */
391b5ff1b31Sbellard         return s->fiq_enabled;
392b5ff1b31Sbellard     case 3: /* IRQ_ENABLECLR */
393b5ff1b31Sbellard     case 5: /* INT_SOFTCLR */
394b5ff1b31Sbellard     case 11: /* FRQ_ENABLECLR */
395b5ff1b31Sbellard     default:
39629bfb117Spbrook         printf ("icp_pic_read: Bad register offset 0x%x\n", (int)offset);
397b5ff1b31Sbellard         return 0;
398b5ff1b31Sbellard     }
399b5ff1b31Sbellard }
400b5ff1b31Sbellard 
401a8170e5eSAvi Kivity static void icp_pic_write(void *opaque, hwaddr offset,
40261074e46SBenoît Canet                           uint64_t value, unsigned size)
403b5ff1b31Sbellard {
404b5ff1b31Sbellard     icp_pic_state *s = (icp_pic_state *)opaque;
405b5ff1b31Sbellard 
406b5ff1b31Sbellard     switch (offset >> 2) {
407b5ff1b31Sbellard     case 2: /* IRQ_ENABLESET */
408b5ff1b31Sbellard         s->irq_enabled |= value;
409b5ff1b31Sbellard         break;
410b5ff1b31Sbellard     case 3: /* IRQ_ENABLECLR */
411b5ff1b31Sbellard         s->irq_enabled &= ~value;
412b5ff1b31Sbellard         break;
413b5ff1b31Sbellard     case 4: /* INT_SOFTSET */
414b5ff1b31Sbellard         if (value & 1)
415d537cf6cSpbrook             icp_pic_set_irq(s, 0, 1);
416b5ff1b31Sbellard         break;
417b5ff1b31Sbellard     case 5: /* INT_SOFTCLR */
418b5ff1b31Sbellard         if (value & 1)
419d537cf6cSpbrook             icp_pic_set_irq(s, 0, 0);
420b5ff1b31Sbellard         break;
421b5ff1b31Sbellard     case 10: /* FRQ_ENABLESET */
422b5ff1b31Sbellard         s->fiq_enabled |= value;
423b5ff1b31Sbellard         break;
424b5ff1b31Sbellard     case 11: /* FRQ_ENABLECLR */
425b5ff1b31Sbellard         s->fiq_enabled &= ~value;
426b5ff1b31Sbellard         break;
427b5ff1b31Sbellard     case 0: /* IRQ_STATUS */
428b5ff1b31Sbellard     case 1: /* IRQ_RAWSTAT */
429b5ff1b31Sbellard     case 8: /* FRQ_STATUS */
430b5ff1b31Sbellard     case 9: /* FRQ_RAWSTAT */
431b5ff1b31Sbellard     default:
43229bfb117Spbrook         printf ("icp_pic_write: Bad register offset 0x%x\n", (int)offset);
433b5ff1b31Sbellard         return;
434b5ff1b31Sbellard     }
435b5ff1b31Sbellard     icp_pic_update(s);
436b5ff1b31Sbellard }
437b5ff1b31Sbellard 
43861074e46SBenoît Canet static const MemoryRegionOps icp_pic_ops = {
43961074e46SBenoît Canet     .read = icp_pic_read,
44061074e46SBenoît Canet     .write = icp_pic_write,
44161074e46SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
442b5ff1b31Sbellard };
443b5ff1b31Sbellard 
444a1f42e0cSxiaoqiang.zhao static void icp_pic_init(Object *obj)
445b5ff1b31Sbellard {
446a1f42e0cSxiaoqiang.zhao     DeviceState *dev = DEVICE(obj);
447a1f42e0cSxiaoqiang.zhao     icp_pic_state *s = INTEGRATOR_PIC(obj);
448a1f42e0cSxiaoqiang.zhao     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
449b5ff1b31Sbellard 
45091b64626SAndreas Färber     qdev_init_gpio_in(dev, icp_pic_set_irq, 32);
45191b64626SAndreas Färber     sysbus_init_irq(sbd, &s->parent_irq);
45291b64626SAndreas Färber     sysbus_init_irq(sbd, &s->parent_fiq);
453a1f42e0cSxiaoqiang.zhao     memory_region_init_io(&s->iomem, obj, &icp_pic_ops, s,
45464bde0f3SPaolo Bonzini                           "icp-pic", 0x00800000);
45591b64626SAndreas Färber     sysbus_init_mmio(sbd, &s->iomem);
456b5ff1b31Sbellard }
457b5ff1b31Sbellard 
458b5ff1b31Sbellard /* CP control registers.  */
4590c36493eSBenoît Canet 
460ffc8542aSJan Kiszka #define TYPE_ICP_CONTROL_REGS "icp-ctrl-regs"
461ffc8542aSJan Kiszka #define ICP_CONTROL_REGS(obj) \
462ffc8542aSJan Kiszka     OBJECT_CHECK(ICPCtrlRegsState, (obj), TYPE_ICP_CONTROL_REGS)
463ffc8542aSJan Kiszka 
464ffc8542aSJan Kiszka typedef struct ICPCtrlRegsState {
465ffc8542aSJan Kiszka     /*< private >*/
466ffc8542aSJan Kiszka     SysBusDevice parent_obj;
467ffc8542aSJan Kiszka     /*< public >*/
468ffc8542aSJan Kiszka 
469ffc8542aSJan Kiszka     MemoryRegion iomem;
47083d0cf89SJan Kiszka 
47183d0cf89SJan Kiszka     qemu_irq mmc_irq;
47283d0cf89SJan Kiszka     uint32_t intreg_state;
473ffc8542aSJan Kiszka } ICPCtrlRegsState;
474ffc8542aSJan Kiszka 
47583d0cf89SJan Kiszka #define ICP_GPIO_MMC_WPROT      "mmc-wprot"
47683d0cf89SJan Kiszka #define ICP_GPIO_MMC_CARDIN     "mmc-cardin"
47783d0cf89SJan Kiszka 
47883d0cf89SJan Kiszka #define ICP_INTREG_WPROT        (1 << 0)
47983d0cf89SJan Kiszka #define ICP_INTREG_CARDIN       (1 << 3)
48083d0cf89SJan Kiszka 
48126d32022SPavel Dovgalyuk static const VMStateDescription vmstate_icp_control = {
48226d32022SPavel Dovgalyuk     .name = "icp_control",
48326d32022SPavel Dovgalyuk     .version_id = 1,
48426d32022SPavel Dovgalyuk     .minimum_version_id = 1,
48526d32022SPavel Dovgalyuk     .fields      = (VMStateField[]) {
48626d32022SPavel Dovgalyuk         VMSTATE_UINT32(intreg_state, ICPCtrlRegsState),
48726d32022SPavel Dovgalyuk         VMSTATE_END_OF_LIST()
48826d32022SPavel Dovgalyuk     }
48926d32022SPavel Dovgalyuk };
49026d32022SPavel Dovgalyuk 
491a8170e5eSAvi Kivity static uint64_t icp_control_read(void *opaque, hwaddr offset,
4920c36493eSBenoît Canet                                  unsigned size)
493b5ff1b31Sbellard {
49483d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
49583d0cf89SJan Kiszka 
496b5ff1b31Sbellard     switch (offset >> 2) {
497b5ff1b31Sbellard     case 0: /* CP_IDFIELD */
498b5ff1b31Sbellard         return 0x41034003;
499b5ff1b31Sbellard     case 1: /* CP_FLASHPROG */
500b5ff1b31Sbellard         return 0;
501b5ff1b31Sbellard     case 2: /* CP_INTREG */
50283d0cf89SJan Kiszka         return s->intreg_state;
503b5ff1b31Sbellard     case 3: /* CP_DECODE */
504b5ff1b31Sbellard         return 0x11;
505b5ff1b31Sbellard     default:
5062ac71179SPaul Brook         hw_error("icp_control_read: Bad offset %x\n", (int)offset);
507b5ff1b31Sbellard         return 0;
508b5ff1b31Sbellard     }
509b5ff1b31Sbellard }
510b5ff1b31Sbellard 
511a8170e5eSAvi Kivity static void icp_control_write(void *opaque, hwaddr offset,
5120c36493eSBenoît Canet                           uint64_t value, unsigned size)
513b5ff1b31Sbellard {
51483d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
51583d0cf89SJan Kiszka 
516b5ff1b31Sbellard     switch (offset >> 2) {
517b5ff1b31Sbellard     case 2: /* CP_INTREG */
51883d0cf89SJan Kiszka         s->intreg_state &= ~(value & ICP_INTREG_CARDIN);
51983d0cf89SJan Kiszka         qemu_set_irq(s->mmc_irq, !!(s->intreg_state & ICP_INTREG_CARDIN));
52083d0cf89SJan Kiszka         break;
52183d0cf89SJan Kiszka     case 1: /* CP_FLASHPROG */
522b5ff1b31Sbellard     case 3: /* CP_DECODE */
523b5ff1b31Sbellard         /* Nothing interesting implemented yet.  */
524b5ff1b31Sbellard         break;
525b5ff1b31Sbellard     default:
5262ac71179SPaul Brook         hw_error("icp_control_write: Bad offset %x\n", (int)offset);
527b5ff1b31Sbellard     }
528b5ff1b31Sbellard }
5290c36493eSBenoît Canet 
5300c36493eSBenoît Canet static const MemoryRegionOps icp_control_ops = {
5310c36493eSBenoît Canet     .read = icp_control_read,
5320c36493eSBenoît Canet     .write = icp_control_write,
5330c36493eSBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
534b5ff1b31Sbellard };
535b5ff1b31Sbellard 
53683d0cf89SJan Kiszka static void icp_control_mmc_wprot(void *opaque, int line, int level)
53783d0cf89SJan Kiszka {
53883d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
53983d0cf89SJan Kiszka 
54083d0cf89SJan Kiszka     s->intreg_state &= ~ICP_INTREG_WPROT;
54183d0cf89SJan Kiszka     if (level) {
54283d0cf89SJan Kiszka         s->intreg_state |= ICP_INTREG_WPROT;
54383d0cf89SJan Kiszka     }
54483d0cf89SJan Kiszka }
54583d0cf89SJan Kiszka 
54683d0cf89SJan Kiszka static void icp_control_mmc_cardin(void *opaque, int line, int level)
54783d0cf89SJan Kiszka {
54883d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
54983d0cf89SJan Kiszka 
55083d0cf89SJan Kiszka     /* line is released by writing to CP_INTREG */
55183d0cf89SJan Kiszka     if (level) {
55283d0cf89SJan Kiszka         s->intreg_state |= ICP_INTREG_CARDIN;
55383d0cf89SJan Kiszka         qemu_set_irq(s->mmc_irq, 1);
55483d0cf89SJan Kiszka     }
55583d0cf89SJan Kiszka }
55683d0cf89SJan Kiszka 
557ffc8542aSJan Kiszka static void icp_control_init(Object *obj)
558b5ff1b31Sbellard {
559ffc8542aSJan Kiszka     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
560ffc8542aSJan Kiszka     ICPCtrlRegsState *s = ICP_CONTROL_REGS(obj);
56183d0cf89SJan Kiszka     DeviceState *dev = DEVICE(obj);
562b5ff1b31Sbellard 
563ffc8542aSJan Kiszka     memory_region_init_io(&s->iomem, OBJECT(s), &icp_control_ops, s,
564ffc8542aSJan Kiszka                           "icp_ctrl_regs", 0x00800000);
565ffc8542aSJan Kiszka     sysbus_init_mmio(sbd, &s->iomem);
56683d0cf89SJan Kiszka 
56783d0cf89SJan Kiszka     qdev_init_gpio_in_named(dev, icp_control_mmc_wprot, ICP_GPIO_MMC_WPROT, 1);
56883d0cf89SJan Kiszka     qdev_init_gpio_in_named(dev, icp_control_mmc_cardin,
56983d0cf89SJan Kiszka                             ICP_GPIO_MMC_CARDIN, 1);
57083d0cf89SJan Kiszka     sysbus_init_irq(sbd, &s->mmc_irq);
571b5ff1b31Sbellard }
572b5ff1b31Sbellard 
573b5ff1b31Sbellard 
574b5ff1b31Sbellard /* Board init.  */
575b5ff1b31Sbellard 
576f93eb9ffSbalrog static struct arm_boot_info integrator_binfo = {
577f93eb9ffSbalrog     .loader_start = 0x0,
578f93eb9ffSbalrog     .board_id = 0x113,
579f93eb9ffSbalrog };
580f93eb9ffSbalrog 
5813ef96221SMarcel Apfelbaum static void integratorcp_init(MachineState *machine)
582b5ff1b31Sbellard {
5833ef96221SMarcel Apfelbaum     ram_addr_t ram_size = machine->ram_size;
5843ef96221SMarcel Apfelbaum     const char *kernel_filename = machine->kernel_filename;
5853ef96221SMarcel Apfelbaum     const char *kernel_cmdline = machine->kernel_cmdline;
5863ef96221SMarcel Apfelbaum     const char *initrd_filename = machine->initrd_filename;
587223a72f1SGreg Bellows     Object *cpuobj;
588393a9eabSAndreas Färber     ARMCPU *cpu;
589211adf4dSAvi Kivity     MemoryRegion *address_space_mem = get_system_memory();
590211adf4dSAvi Kivity     MemoryRegion *ram = g_new(MemoryRegion, 1);
591211adf4dSAvi Kivity     MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
592a7086888SPaul Brook     qemu_irq pic[32];
59383d0cf89SJan Kiszka     DeviceState *dev, *sic, *icp;
594a7086888SPaul Brook     int i;
595b5ff1b31Sbellard 
596ba1ba5ccSIgor Mammedov     cpuobj = object_new(machine->cpu_type);
597223a72f1SGreg Bellows 
59861e2f352SGreg Bellows     /* By default ARM1176 CPUs have EL3 enabled.  This board does not
59961e2f352SGreg Bellows      * currently support EL3 so the CPU EL3 property is disabled before
60061e2f352SGreg Bellows      * realization.
60161e2f352SGreg Bellows      */
60261e2f352SGreg Bellows     if (object_property_find(cpuobj, "has_el3", NULL)) {
603007b0657SMarkus Armbruster         object_property_set_bool(cpuobj, false, "has_el3", &error_fatal);
60461e2f352SGreg Bellows     }
60561e2f352SGreg Bellows 
606007b0657SMarkus Armbruster     object_property_set_bool(cpuobj, true, "realized", &error_fatal);
607223a72f1SGreg Bellows 
608223a72f1SGreg Bellows     cpu = ARM_CPU(cpuobj);
609223a72f1SGreg Bellows 
610c8623c02SDirk Müller     memory_region_allocate_system_memory(ram, NULL, "integrator.ram",
611c8623c02SDirk Müller                                          ram_size);
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*/
615211adf4dSAvi Kivity     memory_region_add_subregion(address_space_mem, 0, ram);
616b5ff1b31Sbellard     /* And again at address 0x80000000 */
6172c9b15caSPaolo Bonzini     memory_region_init_alias(ram_alias, NULL, "ram.alias", ram, 0, ram_size);
618211adf4dSAvi Kivity     memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
619b5ff1b31Sbellard 
620257ec289SAndreas Färber     dev = qdev_create(NULL, TYPE_INTEGRATOR_CM);
621ee6847d1SGerd Hoffmann     qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
622e23a1b33SMarkus Armbruster     qdev_init_nofail(dev);
623a7086888SPaul Brook     sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
624a7086888SPaul Brook 
62591b64626SAndreas Färber     dev = sysbus_create_varargs(TYPE_INTEGRATOR_PIC, 0x14000000,
62699d228d6SPeter Maydell                                 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ),
62799d228d6SPeter Maydell                                 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ),
62899d228d6SPeter Maydell                                 NULL);
629a7086888SPaul Brook     for (i = 0; i < 32; i++) {
630067a3ddcSPaul Brook         pic[i] = qdev_get_gpio_in(dev, i);
631a7086888SPaul Brook     }
63283d0cf89SJan Kiszka     sic = sysbus_create_simple(TYPE_INTEGRATOR_PIC, 0xca000000, pic[26]);
6336a824ec3SPaul Brook     sysbus_create_varargs("integrator_pit", 0x13000000,
6346a824ec3SPaul Brook                           pic[5], pic[6], pic[7], NULL);
635a63bdb31SPaul Brook     sysbus_create_simple("pl031", 0x15000000, pic[8]);
6369bca0edbSPeter Maydell     pl011_create(0x16000000, pic[1], serial_hd(0));
6379bca0edbSPeter Maydell     pl011_create(0x17000000, pic[2], serial_hd(1));
63883d0cf89SJan Kiszka     icp = sysbus_create_simple(TYPE_ICP_CONTROL_REGS, 0xcb000000,
63983d0cf89SJan Kiszka                                qdev_get_gpio_in(sic, 3));
64086394e96SPaul Brook     sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
64186394e96SPaul Brook     sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]);
642b8616055SAlex Bennée     sysbus_create_simple(TYPE_INTEGRATOR_DEBUG, 0x1a000000, 0);
64383d0cf89SJan Kiszka 
64483d0cf89SJan Kiszka     dev = sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL);
64583d0cf89SJan Kiszka     qdev_connect_gpio_out(dev, 0,
64683d0cf89SJan Kiszka                           qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_WPROT, 0));
64783d0cf89SJan Kiszka     qdev_connect_gpio_out(dev, 1,
64883d0cf89SJan Kiszka                           qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_CARDIN, 0));
64983d0cf89SJan Kiszka 
650a005d073SStefan Hajnoczi     if (nd_table[0].used)
651d537cf6cSpbrook         smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
6522e9bdce5SPaul Brook 
6532e9bdce5SPaul Brook     sysbus_create_simple("pl110", 0xc0000000, pic[22]);
654b5ff1b31Sbellard 
655f93eb9ffSbalrog     integrator_binfo.ram_size = ram_size;
656f93eb9ffSbalrog     integrator_binfo.kernel_filename = kernel_filename;
657f93eb9ffSbalrog     integrator_binfo.kernel_cmdline = kernel_cmdline;
658f93eb9ffSbalrog     integrator_binfo.initrd_filename = initrd_filename;
6593aaa8dfaSAndreas Färber     arm_load_kernel(cpu, &integrator_binfo);
660b5ff1b31Sbellard }
661b5ff1b31Sbellard 
662e264d29dSEduardo Habkost static void integratorcp_machine_init(MachineClass *mc)
663f80f9ec9SAnthony Liguori {
664e264d29dSEduardo Habkost     mc->desc = "ARM Integrator/CP (ARM926EJ-S)";
665e264d29dSEduardo Habkost     mc->init = integratorcp_init;
6664672cbd7SPeter Maydell     mc->ignore_memory_transaction_failures = true;
667ba1ba5ccSIgor Mammedov     mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926");
668f80f9ec9SAnthony Liguori }
669f80f9ec9SAnthony Liguori 
670e264d29dSEduardo Habkost DEFINE_MACHINE("integratorcp", integratorcp_machine_init)
671f80f9ec9SAnthony Liguori 
672999e12bbSAnthony Liguori static Property core_properties[] = {
673257ec289SAndreas Färber     DEFINE_PROP_UINT32("memsz", IntegratorCMState, memsz, 0),
674bb36f66aSGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
675999e12bbSAnthony Liguori };
676999e12bbSAnthony Liguori 
677999e12bbSAnthony Liguori static void core_class_init(ObjectClass *klass, void *data)
678999e12bbSAnthony Liguori {
67939bffca2SAnthony Liguori     DeviceClass *dc = DEVICE_CLASS(klass);
680999e12bbSAnthony Liguori 
68139bffca2SAnthony Liguori     dc->props = core_properties;
682e9d9ee23SJakub Jermar     dc->realize = integratorcm_realize;
68326d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_integratorcm;
68426d32022SPavel Dovgalyuk }
68526d32022SPavel Dovgalyuk 
68626d32022SPavel Dovgalyuk static void icp_pic_class_init(ObjectClass *klass, void *data)
68726d32022SPavel Dovgalyuk {
68826d32022SPavel Dovgalyuk     DeviceClass *dc = DEVICE_CLASS(klass);
68926d32022SPavel Dovgalyuk 
69026d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_icp_pic;
69126d32022SPavel Dovgalyuk }
69226d32022SPavel Dovgalyuk 
69326d32022SPavel Dovgalyuk static void icp_control_class_init(ObjectClass *klass, void *data)
69426d32022SPavel Dovgalyuk {
69526d32022SPavel Dovgalyuk     DeviceClass *dc = DEVICE_CLASS(klass);
69626d32022SPavel Dovgalyuk 
69726d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_icp_control;
698ee6847d1SGerd Hoffmann }
699999e12bbSAnthony Liguori 
7008c43a6f0SAndreas Färber static const TypeInfo core_info = {
701257ec289SAndreas Färber     .name          = TYPE_INTEGRATOR_CM,
70239bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
703257ec289SAndreas Färber     .instance_size = sizeof(IntegratorCMState),
704a1f42e0cSxiaoqiang.zhao     .instance_init = integratorcm_init,
705999e12bbSAnthony Liguori     .class_init    = core_class_init,
706999e12bbSAnthony Liguori };
707999e12bbSAnthony Liguori 
7088c43a6f0SAndreas Färber static const TypeInfo icp_pic_info = {
70991b64626SAndreas Färber     .name          = TYPE_INTEGRATOR_PIC,
71039bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
71139bffca2SAnthony Liguori     .instance_size = sizeof(icp_pic_state),
712a1f42e0cSxiaoqiang.zhao     .instance_init = icp_pic_init,
71326d32022SPavel Dovgalyuk     .class_init    = icp_pic_class_init,
714ee6847d1SGerd Hoffmann };
715ee6847d1SGerd Hoffmann 
716ffc8542aSJan Kiszka static const TypeInfo icp_ctrl_regs_info = {
717ffc8542aSJan Kiszka     .name          = TYPE_ICP_CONTROL_REGS,
718ffc8542aSJan Kiszka     .parent        = TYPE_SYS_BUS_DEVICE,
719ffc8542aSJan Kiszka     .instance_size = sizeof(ICPCtrlRegsState),
720ffc8542aSJan Kiszka     .instance_init = icp_control_init,
72126d32022SPavel Dovgalyuk     .class_init    = icp_control_class_init,
722ffc8542aSJan Kiszka };
723ffc8542aSJan Kiszka 
72483f7d43aSAndreas Färber static void integratorcp_register_types(void)
725a7086888SPaul Brook {
72639bffca2SAnthony Liguori     type_register_static(&icp_pic_info);
72739bffca2SAnthony Liguori     type_register_static(&core_info);
728ffc8542aSJan Kiszka     type_register_static(&icp_ctrl_regs_info);
729a7086888SPaul Brook }
730a7086888SPaul Brook 
73183f7d43aSAndreas Färber type_init(integratorcp_register_types)
732