xref: /qemu/hw/arm/integratorcp.c (revision 3f25b3f4e88f5df1b0eb5e9cb59567aa4ffc80fe)
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"
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"
27b5ff1b31Sbellard 
28257ec289SAndreas Färber #define TYPE_INTEGRATOR_CM "integrator_core"
29257ec289SAndreas Färber #define INTEGRATOR_CM(obj) \
30257ec289SAndreas Färber     OBJECT_CHECK(IntegratorCMState, (obj), TYPE_INTEGRATOR_CM)
31257ec289SAndreas Färber 
32257ec289SAndreas Färber typedef struct IntegratorCMState {
33257ec289SAndreas Färber     /*< private >*/
34257ec289SAndreas Färber     SysBusDevice parent_obj;
35257ec289SAndreas Färber     /*< public >*/
36257ec289SAndreas Färber 
3771d9bc50SBenoît Canet     MemoryRegion iomem;
38ee6847d1SGerd Hoffmann     uint32_t memsz;
39211adf4dSAvi Kivity     MemoryRegion flash;
40b5ff1b31Sbellard     uint32_t cm_osc;
41b5ff1b31Sbellard     uint32_t cm_ctrl;
42b5ff1b31Sbellard     uint32_t cm_lock;
43b5ff1b31Sbellard     uint32_t cm_auxosc;
44b5ff1b31Sbellard     uint32_t cm_sdram;
45b5ff1b31Sbellard     uint32_t cm_init;
46b5ff1b31Sbellard     uint32_t cm_flags;
47b5ff1b31Sbellard     uint32_t cm_nvflags;
48f53977f7SJan Petrous     uint32_t cm_refcnt_offset;
49b5ff1b31Sbellard     uint32_t int_level;
50b5ff1b31Sbellard     uint32_t irq_enabled;
51b5ff1b31Sbellard     uint32_t fiq_enabled;
52257ec289SAndreas Färber } IntegratorCMState;
53b5ff1b31Sbellard 
54b5ff1b31Sbellard static uint8_t integrator_spd[128] = {
55b5ff1b31Sbellard    128, 8, 4, 11, 9, 1, 64, 0,  2, 0xa0, 0xa0, 0, 0, 8, 0, 1,
56b5ff1b31Sbellard    0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
57b5ff1b31Sbellard };
58b5ff1b31Sbellard 
5926d32022SPavel Dovgalyuk static const VMStateDescription vmstate_integratorcm = {
6026d32022SPavel Dovgalyuk     .name = "integratorcm",
6126d32022SPavel Dovgalyuk     .version_id = 1,
6226d32022SPavel Dovgalyuk     .minimum_version_id = 1,
6326d32022SPavel Dovgalyuk     .fields      = (VMStateField[]) {
6426d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_osc, IntegratorCMState),
6526d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_ctrl, IntegratorCMState),
6626d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_lock, IntegratorCMState),
6726d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_auxosc, IntegratorCMState),
6826d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_sdram, IntegratorCMState),
6926d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_init, IntegratorCMState),
7026d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_flags, IntegratorCMState),
7126d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_nvflags, IntegratorCMState),
7226d32022SPavel Dovgalyuk         VMSTATE_UINT32(int_level, IntegratorCMState),
7326d32022SPavel Dovgalyuk         VMSTATE_UINT32(irq_enabled, IntegratorCMState),
7426d32022SPavel Dovgalyuk         VMSTATE_UINT32(fiq_enabled, IntegratorCMState),
7526d32022SPavel Dovgalyuk         VMSTATE_END_OF_LIST()
7626d32022SPavel Dovgalyuk     }
7726d32022SPavel Dovgalyuk };
7826d32022SPavel Dovgalyuk 
79a8170e5eSAvi Kivity static uint64_t integratorcm_read(void *opaque, hwaddr offset,
8071d9bc50SBenoît Canet                                   unsigned size)
81b5ff1b31Sbellard {
82257ec289SAndreas Färber     IntegratorCMState *s = opaque;
83b5ff1b31Sbellard     if (offset >= 0x100 && offset < 0x200) {
84b5ff1b31Sbellard         /* CM_SPD */
85b5ff1b31Sbellard         if (offset >= 0x180)
86b5ff1b31Sbellard             return 0;
87b5ff1b31Sbellard         return integrator_spd[offset >> 2];
88b5ff1b31Sbellard     }
89b5ff1b31Sbellard     switch (offset >> 2) {
90b5ff1b31Sbellard     case 0: /* CM_ID */
91b5ff1b31Sbellard         return 0x411a3001;
92b5ff1b31Sbellard     case 1: /* CM_PROC */
93b5ff1b31Sbellard         return 0;
94b5ff1b31Sbellard     case 2: /* CM_OSC */
95b5ff1b31Sbellard         return s->cm_osc;
96b5ff1b31Sbellard     case 3: /* CM_CTRL */
97b5ff1b31Sbellard         return s->cm_ctrl;
98b5ff1b31Sbellard     case 4: /* CM_STAT */
99b5ff1b31Sbellard         return 0x00100000;
100b5ff1b31Sbellard     case 5: /* CM_LOCK */
101b5ff1b31Sbellard         if (s->cm_lock == 0xa05f) {
102b5ff1b31Sbellard             return 0x1a05f;
103b5ff1b31Sbellard         } else {
104b5ff1b31Sbellard             return s->cm_lock;
105b5ff1b31Sbellard         }
106b5ff1b31Sbellard     case 6: /* CM_LMBUSCNT */
107b5ff1b31Sbellard         /* ??? High frequency timer.  */
1082ac71179SPaul Brook         hw_error("integratorcm_read: CM_LMBUSCNT");
109b5ff1b31Sbellard     case 7: /* CM_AUXOSC */
110b5ff1b31Sbellard         return s->cm_auxosc;
111b5ff1b31Sbellard     case 8: /* CM_SDRAM */
112b5ff1b31Sbellard         return s->cm_sdram;
113b5ff1b31Sbellard     case 9: /* CM_INIT */
114b5ff1b31Sbellard         return s->cm_init;
115f53977f7SJan Petrous     case 10: /* CM_REFCNT */
116f53977f7SJan Petrous         /* This register, CM_REFCNT, provides a 32-bit count value.
117f53977f7SJan Petrous          * The count increments at the fixed reference clock frequency of 24MHz
118f53977f7SJan Petrous          * and can be used as a real-time counter.
119f53977f7SJan Petrous          */
120f53977f7SJan Petrous         return (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24,
121f53977f7SJan Petrous                                   1000) - s->cm_refcnt_offset;
122b5ff1b31Sbellard     case 12: /* CM_FLAGS */
123b5ff1b31Sbellard         return s->cm_flags;
124b5ff1b31Sbellard     case 14: /* CM_NVFLAGS */
125b5ff1b31Sbellard         return s->cm_nvflags;
126b5ff1b31Sbellard     case 16: /* CM_IRQ_STAT */
127b5ff1b31Sbellard         return s->int_level & s->irq_enabled;
128b5ff1b31Sbellard     case 17: /* CM_IRQ_RSTAT */
129b5ff1b31Sbellard         return s->int_level;
130b5ff1b31Sbellard     case 18: /* CM_IRQ_ENSET */
131b5ff1b31Sbellard         return s->irq_enabled;
132b5ff1b31Sbellard     case 20: /* CM_SOFT_INTSET */
133b5ff1b31Sbellard         return s->int_level & 1;
134b5ff1b31Sbellard     case 24: /* CM_FIQ_STAT */
135b5ff1b31Sbellard         return s->int_level & s->fiq_enabled;
136b5ff1b31Sbellard     case 25: /* CM_FIQ_RSTAT */
137b5ff1b31Sbellard         return s->int_level;
138b5ff1b31Sbellard     case 26: /* CM_FIQ_ENSET */
139b5ff1b31Sbellard         return s->fiq_enabled;
140b5ff1b31Sbellard     case 32: /* CM_VOLTAGE_CTL0 */
141b5ff1b31Sbellard     case 33: /* CM_VOLTAGE_CTL1 */
142b5ff1b31Sbellard     case 34: /* CM_VOLTAGE_CTL2 */
143b5ff1b31Sbellard     case 35: /* CM_VOLTAGE_CTL3 */
144b5ff1b31Sbellard         /* ??? Voltage control unimplemented.  */
145b5ff1b31Sbellard         return 0;
146b5ff1b31Sbellard     default:
1472ac71179SPaul Brook         hw_error("integratorcm_read: Unimplemented offset 0x%x\n",
1482ac71179SPaul Brook                  (int)offset);
149b5ff1b31Sbellard         return 0;
150b5ff1b31Sbellard     }
151b5ff1b31Sbellard }
152b5ff1b31Sbellard 
153257ec289SAndreas Färber static void integratorcm_do_remap(IntegratorCMState *s)
154b5ff1b31Sbellard {
155563c2bf3SPeter Maydell     /* Sync memory region state with CM_CTRL REMAP bit:
156563c2bf3SPeter Maydell      * bit 0 => flash at address 0; bit 1 => RAM
157563c2bf3SPeter Maydell      */
158563c2bf3SPeter Maydell     memory_region_set_enabled(&s->flash, !(s->cm_ctrl & 4));
159b5ff1b31Sbellard }
160b5ff1b31Sbellard 
161257ec289SAndreas Färber static void integratorcm_set_ctrl(IntegratorCMState *s, uint32_t value)
162b5ff1b31Sbellard {
163b5ff1b31Sbellard     if (value & 8) {
164cf83f140SEric Blake         qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
165b5ff1b31Sbellard     }
166df3f457bSPeter Maydell     if ((s->cm_ctrl ^ value) & 1) {
167df3f457bSPeter Maydell         /* (value & 1) != 0 means the green "MISC LED" is lit.
168df3f457bSPeter Maydell          * We don't have any nice place to display LEDs. printf is a bad
169df3f457bSPeter Maydell          * idea because Linux uses the LED as a heartbeat and the output
170df3f457bSPeter Maydell          * will swamp anything else on the terminal.
171df3f457bSPeter Maydell          */
172b5ff1b31Sbellard     }
173df3f457bSPeter Maydell     /* Note that the RESET bit [3] always reads as zero */
174df3f457bSPeter Maydell     s->cm_ctrl = (s->cm_ctrl & ~5) | (value & 5);
175563c2bf3SPeter Maydell     integratorcm_do_remap(s);
176b5ff1b31Sbellard }
177b5ff1b31Sbellard 
178257ec289SAndreas Färber static void integratorcm_update(IntegratorCMState *s)
179b5ff1b31Sbellard {
180b5ff1b31Sbellard     /* ??? The CPU irq/fiq is raised when either the core module or base PIC
181b5ff1b31Sbellard        are active.  */
182b5ff1b31Sbellard     if (s->int_level & (s->irq_enabled | s->fiq_enabled))
1832ac71179SPaul Brook         hw_error("Core module interrupt\n");
184b5ff1b31Sbellard }
185b5ff1b31Sbellard 
186a8170e5eSAvi Kivity static void integratorcm_write(void *opaque, hwaddr offset,
18771d9bc50SBenoît Canet                                uint64_t value, unsigned size)
188b5ff1b31Sbellard {
189257ec289SAndreas Färber     IntegratorCMState *s = opaque;
190b5ff1b31Sbellard     switch (offset >> 2) {
191b5ff1b31Sbellard     case 2: /* CM_OSC */
192b5ff1b31Sbellard         if (s->cm_lock == 0xa05f)
193b5ff1b31Sbellard             s->cm_osc = value;
194b5ff1b31Sbellard         break;
195b5ff1b31Sbellard     case 3: /* CM_CTRL */
196b5ff1b31Sbellard         integratorcm_set_ctrl(s, value);
197b5ff1b31Sbellard         break;
198b5ff1b31Sbellard     case 5: /* CM_LOCK */
199b5ff1b31Sbellard         s->cm_lock = value & 0xffff;
200b5ff1b31Sbellard         break;
201b5ff1b31Sbellard     case 7: /* CM_AUXOSC */
202b5ff1b31Sbellard         if (s->cm_lock == 0xa05f)
203b5ff1b31Sbellard             s->cm_auxosc = value;
204b5ff1b31Sbellard         break;
205b5ff1b31Sbellard     case 8: /* CM_SDRAM */
206b5ff1b31Sbellard         s->cm_sdram = value;
207b5ff1b31Sbellard         break;
208b5ff1b31Sbellard     case 9: /* CM_INIT */
209b5ff1b31Sbellard         /* ??? This can change the memory bus frequency.  */
210b5ff1b31Sbellard         s->cm_init = value;
211b5ff1b31Sbellard         break;
212b5ff1b31Sbellard     case 12: /* CM_FLAGSS */
213b5ff1b31Sbellard         s->cm_flags |= value;
214b5ff1b31Sbellard         break;
215b5ff1b31Sbellard     case 13: /* CM_FLAGSC */
216b5ff1b31Sbellard         s->cm_flags &= ~value;
217b5ff1b31Sbellard         break;
218b5ff1b31Sbellard     case 14: /* CM_NVFLAGSS */
219b5ff1b31Sbellard         s->cm_nvflags |= value;
220b5ff1b31Sbellard         break;
221b5ff1b31Sbellard     case 15: /* CM_NVFLAGSS */
222b5ff1b31Sbellard         s->cm_nvflags &= ~value;
223b5ff1b31Sbellard         break;
224b5ff1b31Sbellard     case 18: /* CM_IRQ_ENSET */
225b5ff1b31Sbellard         s->irq_enabled |= value;
226b5ff1b31Sbellard         integratorcm_update(s);
227b5ff1b31Sbellard         break;
228b5ff1b31Sbellard     case 19: /* CM_IRQ_ENCLR */
229b5ff1b31Sbellard         s->irq_enabled &= ~value;
230b5ff1b31Sbellard         integratorcm_update(s);
231b5ff1b31Sbellard         break;
232b5ff1b31Sbellard     case 20: /* CM_SOFT_INTSET */
233b5ff1b31Sbellard         s->int_level |= (value & 1);
234b5ff1b31Sbellard         integratorcm_update(s);
235b5ff1b31Sbellard         break;
236b5ff1b31Sbellard     case 21: /* CM_SOFT_INTCLR */
237b5ff1b31Sbellard         s->int_level &= ~(value & 1);
238b5ff1b31Sbellard         integratorcm_update(s);
239b5ff1b31Sbellard         break;
240b5ff1b31Sbellard     case 26: /* CM_FIQ_ENSET */
241b5ff1b31Sbellard         s->fiq_enabled |= value;
242b5ff1b31Sbellard         integratorcm_update(s);
243b5ff1b31Sbellard         break;
244b5ff1b31Sbellard     case 27: /* CM_FIQ_ENCLR */
245b5ff1b31Sbellard         s->fiq_enabled &= ~value;
246b5ff1b31Sbellard         integratorcm_update(s);
247b5ff1b31Sbellard         break;
248b5ff1b31Sbellard     case 32: /* CM_VOLTAGE_CTL0 */
249b5ff1b31Sbellard     case 33: /* CM_VOLTAGE_CTL1 */
250b5ff1b31Sbellard     case 34: /* CM_VOLTAGE_CTL2 */
251b5ff1b31Sbellard     case 35: /* CM_VOLTAGE_CTL3 */
252b5ff1b31Sbellard         /* ??? Voltage control unimplemented.  */
253b5ff1b31Sbellard         break;
254b5ff1b31Sbellard     default:
2552ac71179SPaul Brook         hw_error("integratorcm_write: Unimplemented offset 0x%x\n",
2562ac71179SPaul Brook                  (int)offset);
257b5ff1b31Sbellard         break;
258b5ff1b31Sbellard     }
259b5ff1b31Sbellard }
260b5ff1b31Sbellard 
261b5ff1b31Sbellard /* Integrator/CM control registers.  */
262b5ff1b31Sbellard 
26371d9bc50SBenoît Canet static const MemoryRegionOps integratorcm_ops = {
26471d9bc50SBenoît Canet     .read = integratorcm_read,
26571d9bc50SBenoît Canet     .write = integratorcm_write,
26671d9bc50SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
267b5ff1b31Sbellard };
268b5ff1b31Sbellard 
269a1f42e0cSxiaoqiang.zhao static void integratorcm_init(Object *obj)
270b5ff1b31Sbellard {
271a1f42e0cSxiaoqiang.zhao     IntegratorCMState *s = INTEGRATOR_CM(obj);
272b5ff1b31Sbellard 
273b5ff1b31Sbellard     s->cm_osc = 0x01000048;
274b5ff1b31Sbellard     /* ??? What should the high bits of this value be?  */
275b5ff1b31Sbellard     s->cm_auxosc = 0x0007feff;
276b5ff1b31Sbellard     s->cm_sdram = 0x00011122;
277e9d9ee23SJakub Jermar     memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
278e9d9ee23SJakub Jermar     s->cm_init = 0x00000112;
279e9d9ee23SJakub Jermar     s->cm_refcnt_offset = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24,
280e9d9ee23SJakub Jermar                                    1000);
281e9d9ee23SJakub Jermar 
282e9d9ee23SJakub Jermar     /* ??? Save/restore.  */
283e9d9ee23SJakub Jermar }
284e9d9ee23SJakub Jermar 
285e9d9ee23SJakub Jermar static void integratorcm_realize(DeviceState *d, Error **errp)
286e9d9ee23SJakub Jermar {
287e9d9ee23SJakub Jermar     IntegratorCMState *s = INTEGRATOR_CM(d);
2888720daadSThomas Huth     SysBusDevice *dev = SYS_BUS_DEVICE(d);
2898720daadSThomas Huth     Error *local_err = NULL;
2908720daadSThomas Huth 
2918720daadSThomas Huth     memory_region_init_ram(&s->flash, OBJECT(d), "integrator.flash", 0x100000,
2928720daadSThomas Huth                            &local_err);
2938720daadSThomas Huth     if (local_err) {
2948720daadSThomas Huth         error_propagate(errp, local_err);
2958720daadSThomas Huth         return;
2968720daadSThomas Huth     }
2978720daadSThomas Huth 
2988720daadSThomas Huth     memory_region_init_io(&s->iomem, OBJECT(d), &integratorcm_ops, s,
2998720daadSThomas Huth                           "integratorcm", 0x00800000);
3008720daadSThomas Huth     sysbus_init_mmio(dev, &s->iomem);
3018720daadSThomas Huth 
3028720daadSThomas Huth     integratorcm_do_remap(s);
303e9d9ee23SJakub Jermar 
304ee6847d1SGerd Hoffmann     if (s->memsz >= 256) {
305b5ff1b31Sbellard         integrator_spd[31] = 64;
306b5ff1b31Sbellard         s->cm_sdram |= 0x10;
307ee6847d1SGerd Hoffmann     } else if (s->memsz >= 128) {
308b5ff1b31Sbellard         integrator_spd[31] = 32;
309b5ff1b31Sbellard         s->cm_sdram |= 0x0c;
310ee6847d1SGerd Hoffmann     } else if (s->memsz >= 64) {
311b5ff1b31Sbellard         integrator_spd[31] = 16;
312b5ff1b31Sbellard         s->cm_sdram |= 0x08;
313ee6847d1SGerd Hoffmann     } else if (s->memsz >= 32) {
314b5ff1b31Sbellard         integrator_spd[31] = 4;
315b5ff1b31Sbellard         s->cm_sdram |= 0x04;
316b5ff1b31Sbellard     } else {
317b5ff1b31Sbellard         integrator_spd[31] = 2;
318b5ff1b31Sbellard     }
319b5ff1b31Sbellard }
320b5ff1b31Sbellard 
321b5ff1b31Sbellard /* Integrator/CP hardware emulation.  */
322b5ff1b31Sbellard /* Primary interrupt controller.  */
323b5ff1b31Sbellard 
32491b64626SAndreas Färber #define TYPE_INTEGRATOR_PIC "integrator_pic"
32591b64626SAndreas Färber #define INTEGRATOR_PIC(obj) \
32691b64626SAndreas Färber    OBJECT_CHECK(icp_pic_state, (obj), TYPE_INTEGRATOR_PIC)
32791b64626SAndreas Färber 
32891b64626SAndreas Färber typedef struct icp_pic_state {
32991b64626SAndreas Färber     /*< private >*/
33091b64626SAndreas Färber     SysBusDevice parent_obj;
33191b64626SAndreas Färber     /*< public >*/
33291b64626SAndreas Färber 
33361074e46SBenoît Canet     MemoryRegion iomem;
334b5ff1b31Sbellard     uint32_t level;
335b5ff1b31Sbellard     uint32_t irq_enabled;
336b5ff1b31Sbellard     uint32_t fiq_enabled;
337d537cf6cSpbrook     qemu_irq parent_irq;
338d537cf6cSpbrook     qemu_irq parent_fiq;
339b5ff1b31Sbellard } icp_pic_state;
340b5ff1b31Sbellard 
34126d32022SPavel Dovgalyuk static const VMStateDescription vmstate_icp_pic = {
34226d32022SPavel Dovgalyuk     .name = "icp_pic",
34326d32022SPavel Dovgalyuk     .version_id = 1,
34426d32022SPavel Dovgalyuk     .minimum_version_id = 1,
34526d32022SPavel Dovgalyuk     .fields      = (VMStateField[]) {
34626d32022SPavel Dovgalyuk         VMSTATE_UINT32(level, icp_pic_state),
34726d32022SPavel Dovgalyuk         VMSTATE_UINT32(irq_enabled, icp_pic_state),
34826d32022SPavel Dovgalyuk         VMSTATE_UINT32(fiq_enabled, icp_pic_state),
34926d32022SPavel Dovgalyuk         VMSTATE_END_OF_LIST()
35026d32022SPavel Dovgalyuk     }
35126d32022SPavel Dovgalyuk };
35226d32022SPavel Dovgalyuk 
353b5ff1b31Sbellard static void icp_pic_update(icp_pic_state *s)
354b5ff1b31Sbellard {
355b5ff1b31Sbellard     uint32_t flags;
356b5ff1b31Sbellard 
357b5ff1b31Sbellard     flags = (s->level & s->irq_enabled);
358d537cf6cSpbrook     qemu_set_irq(s->parent_irq, flags != 0);
359cdbdb648Spbrook     flags = (s->level & s->fiq_enabled);
360d537cf6cSpbrook     qemu_set_irq(s->parent_fiq, flags != 0);
361b5ff1b31Sbellard }
362b5ff1b31Sbellard 
363cdbdb648Spbrook static void icp_pic_set_irq(void *opaque, int irq, int level)
364b5ff1b31Sbellard {
36580337b66Sbellard     icp_pic_state *s = (icp_pic_state *)opaque;
366b5ff1b31Sbellard     if (level)
36780337b66Sbellard         s->level |= 1 << irq;
368b5ff1b31Sbellard     else
36980337b66Sbellard         s->level &= ~(1 << irq);
370b5ff1b31Sbellard     icp_pic_update(s);
371b5ff1b31Sbellard }
372b5ff1b31Sbellard 
373a8170e5eSAvi Kivity static uint64_t icp_pic_read(void *opaque, hwaddr offset,
37461074e46SBenoît Canet                              unsigned size)
375b5ff1b31Sbellard {
376b5ff1b31Sbellard     icp_pic_state *s = (icp_pic_state *)opaque;
377b5ff1b31Sbellard 
378b5ff1b31Sbellard     switch (offset >> 2) {
379b5ff1b31Sbellard     case 0: /* IRQ_STATUS */
380b5ff1b31Sbellard         return s->level & s->irq_enabled;
381b5ff1b31Sbellard     case 1: /* IRQ_RAWSTAT */
382b5ff1b31Sbellard         return s->level;
383b5ff1b31Sbellard     case 2: /* IRQ_ENABLESET */
384b5ff1b31Sbellard         return s->irq_enabled;
385b5ff1b31Sbellard     case 4: /* INT_SOFTSET */
386b5ff1b31Sbellard         return s->level & 1;
387b5ff1b31Sbellard     case 8: /* FRQ_STATUS */
388b5ff1b31Sbellard         return s->level & s->fiq_enabled;
389b5ff1b31Sbellard     case 9: /* FRQ_RAWSTAT */
390b5ff1b31Sbellard         return s->level;
391b5ff1b31Sbellard     case 10: /* FRQ_ENABLESET */
392b5ff1b31Sbellard         return s->fiq_enabled;
393b5ff1b31Sbellard     case 3: /* IRQ_ENABLECLR */
394b5ff1b31Sbellard     case 5: /* INT_SOFTCLR */
395b5ff1b31Sbellard     case 11: /* FRQ_ENABLECLR */
396b5ff1b31Sbellard     default:
39729bfb117Spbrook         printf ("icp_pic_read: Bad register offset 0x%x\n", (int)offset);
398b5ff1b31Sbellard         return 0;
399b5ff1b31Sbellard     }
400b5ff1b31Sbellard }
401b5ff1b31Sbellard 
402a8170e5eSAvi Kivity static void icp_pic_write(void *opaque, hwaddr offset,
40361074e46SBenoît Canet                           uint64_t value, unsigned size)
404b5ff1b31Sbellard {
405b5ff1b31Sbellard     icp_pic_state *s = (icp_pic_state *)opaque;
406b5ff1b31Sbellard 
407b5ff1b31Sbellard     switch (offset >> 2) {
408b5ff1b31Sbellard     case 2: /* IRQ_ENABLESET */
409b5ff1b31Sbellard         s->irq_enabled |= value;
410b5ff1b31Sbellard         break;
411b5ff1b31Sbellard     case 3: /* IRQ_ENABLECLR */
412b5ff1b31Sbellard         s->irq_enabled &= ~value;
413b5ff1b31Sbellard         break;
414b5ff1b31Sbellard     case 4: /* INT_SOFTSET */
415b5ff1b31Sbellard         if (value & 1)
416d537cf6cSpbrook             icp_pic_set_irq(s, 0, 1);
417b5ff1b31Sbellard         break;
418b5ff1b31Sbellard     case 5: /* INT_SOFTCLR */
419b5ff1b31Sbellard         if (value & 1)
420d537cf6cSpbrook             icp_pic_set_irq(s, 0, 0);
421b5ff1b31Sbellard         break;
422b5ff1b31Sbellard     case 10: /* FRQ_ENABLESET */
423b5ff1b31Sbellard         s->fiq_enabled |= value;
424b5ff1b31Sbellard         break;
425b5ff1b31Sbellard     case 11: /* FRQ_ENABLECLR */
426b5ff1b31Sbellard         s->fiq_enabled &= ~value;
427b5ff1b31Sbellard         break;
428b5ff1b31Sbellard     case 0: /* IRQ_STATUS */
429b5ff1b31Sbellard     case 1: /* IRQ_RAWSTAT */
430b5ff1b31Sbellard     case 8: /* FRQ_STATUS */
431b5ff1b31Sbellard     case 9: /* FRQ_RAWSTAT */
432b5ff1b31Sbellard     default:
43329bfb117Spbrook         printf ("icp_pic_write: Bad register offset 0x%x\n", (int)offset);
434b5ff1b31Sbellard         return;
435b5ff1b31Sbellard     }
436b5ff1b31Sbellard     icp_pic_update(s);
437b5ff1b31Sbellard }
438b5ff1b31Sbellard 
43961074e46SBenoît Canet static const MemoryRegionOps icp_pic_ops = {
44061074e46SBenoît Canet     .read = icp_pic_read,
44161074e46SBenoît Canet     .write = icp_pic_write,
44261074e46SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
443b5ff1b31Sbellard };
444b5ff1b31Sbellard 
445a1f42e0cSxiaoqiang.zhao static void icp_pic_init(Object *obj)
446b5ff1b31Sbellard {
447a1f42e0cSxiaoqiang.zhao     DeviceState *dev = DEVICE(obj);
448a1f42e0cSxiaoqiang.zhao     icp_pic_state *s = INTEGRATOR_PIC(obj);
449a1f42e0cSxiaoqiang.zhao     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
450b5ff1b31Sbellard 
45191b64626SAndreas Färber     qdev_init_gpio_in(dev, icp_pic_set_irq, 32);
45291b64626SAndreas Färber     sysbus_init_irq(sbd, &s->parent_irq);
45391b64626SAndreas Färber     sysbus_init_irq(sbd, &s->parent_fiq);
454a1f42e0cSxiaoqiang.zhao     memory_region_init_io(&s->iomem, obj, &icp_pic_ops, s,
45564bde0f3SPaolo Bonzini                           "icp-pic", 0x00800000);
45691b64626SAndreas Färber     sysbus_init_mmio(sbd, &s->iomem);
457b5ff1b31Sbellard }
458b5ff1b31Sbellard 
459b5ff1b31Sbellard /* CP control registers.  */
4600c36493eSBenoît Canet 
461ffc8542aSJan Kiszka #define TYPE_ICP_CONTROL_REGS "icp-ctrl-regs"
462ffc8542aSJan Kiszka #define ICP_CONTROL_REGS(obj) \
463ffc8542aSJan Kiszka     OBJECT_CHECK(ICPCtrlRegsState, (obj), TYPE_ICP_CONTROL_REGS)
464ffc8542aSJan Kiszka 
465ffc8542aSJan Kiszka typedef struct ICPCtrlRegsState {
466ffc8542aSJan Kiszka     /*< private >*/
467ffc8542aSJan Kiszka     SysBusDevice parent_obj;
468ffc8542aSJan Kiszka     /*< public >*/
469ffc8542aSJan Kiszka 
470ffc8542aSJan Kiszka     MemoryRegion iomem;
47183d0cf89SJan Kiszka 
47283d0cf89SJan Kiszka     qemu_irq mmc_irq;
47383d0cf89SJan Kiszka     uint32_t intreg_state;
474ffc8542aSJan Kiszka } ICPCtrlRegsState;
475ffc8542aSJan Kiszka 
47683d0cf89SJan Kiszka #define ICP_GPIO_MMC_WPROT      "mmc-wprot"
47783d0cf89SJan Kiszka #define ICP_GPIO_MMC_CARDIN     "mmc-cardin"
47883d0cf89SJan Kiszka 
47983d0cf89SJan Kiszka #define ICP_INTREG_WPROT        (1 << 0)
48083d0cf89SJan Kiszka #define ICP_INTREG_CARDIN       (1 << 3)
48183d0cf89SJan Kiszka 
48226d32022SPavel Dovgalyuk static const VMStateDescription vmstate_icp_control = {
48326d32022SPavel Dovgalyuk     .name = "icp_control",
48426d32022SPavel Dovgalyuk     .version_id = 1,
48526d32022SPavel Dovgalyuk     .minimum_version_id = 1,
48626d32022SPavel Dovgalyuk     .fields      = (VMStateField[]) {
48726d32022SPavel Dovgalyuk         VMSTATE_UINT32(intreg_state, ICPCtrlRegsState),
48826d32022SPavel Dovgalyuk         VMSTATE_END_OF_LIST()
48926d32022SPavel Dovgalyuk     }
49026d32022SPavel Dovgalyuk };
49126d32022SPavel Dovgalyuk 
492a8170e5eSAvi Kivity static uint64_t icp_control_read(void *opaque, hwaddr offset,
4930c36493eSBenoît Canet                                  unsigned size)
494b5ff1b31Sbellard {
49583d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
49683d0cf89SJan Kiszka 
497b5ff1b31Sbellard     switch (offset >> 2) {
498b5ff1b31Sbellard     case 0: /* CP_IDFIELD */
499b5ff1b31Sbellard         return 0x41034003;
500b5ff1b31Sbellard     case 1: /* CP_FLASHPROG */
501b5ff1b31Sbellard         return 0;
502b5ff1b31Sbellard     case 2: /* CP_INTREG */
50383d0cf89SJan Kiszka         return s->intreg_state;
504b5ff1b31Sbellard     case 3: /* CP_DECODE */
505b5ff1b31Sbellard         return 0x11;
506b5ff1b31Sbellard     default:
5072ac71179SPaul Brook         hw_error("icp_control_read: Bad offset %x\n", (int)offset);
508b5ff1b31Sbellard         return 0;
509b5ff1b31Sbellard     }
510b5ff1b31Sbellard }
511b5ff1b31Sbellard 
512a8170e5eSAvi Kivity static void icp_control_write(void *opaque, hwaddr offset,
5130c36493eSBenoît Canet                           uint64_t value, unsigned size)
514b5ff1b31Sbellard {
51583d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
51683d0cf89SJan Kiszka 
517b5ff1b31Sbellard     switch (offset >> 2) {
518b5ff1b31Sbellard     case 2: /* CP_INTREG */
51983d0cf89SJan Kiszka         s->intreg_state &= ~(value & ICP_INTREG_CARDIN);
52083d0cf89SJan Kiszka         qemu_set_irq(s->mmc_irq, !!(s->intreg_state & ICP_INTREG_CARDIN));
52183d0cf89SJan Kiszka         break;
52283d0cf89SJan Kiszka     case 1: /* CP_FLASHPROG */
523b5ff1b31Sbellard     case 3: /* CP_DECODE */
524b5ff1b31Sbellard         /* Nothing interesting implemented yet.  */
525b5ff1b31Sbellard         break;
526b5ff1b31Sbellard     default:
5272ac71179SPaul Brook         hw_error("icp_control_write: Bad offset %x\n", (int)offset);
528b5ff1b31Sbellard     }
529b5ff1b31Sbellard }
5300c36493eSBenoît Canet 
5310c36493eSBenoît Canet static const MemoryRegionOps icp_control_ops = {
5320c36493eSBenoît Canet     .read = icp_control_read,
5330c36493eSBenoît Canet     .write = icp_control_write,
5340c36493eSBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
535b5ff1b31Sbellard };
536b5ff1b31Sbellard 
53783d0cf89SJan Kiszka static void icp_control_mmc_wprot(void *opaque, int line, int level)
53883d0cf89SJan Kiszka {
53983d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
54083d0cf89SJan Kiszka 
54183d0cf89SJan Kiszka     s->intreg_state &= ~ICP_INTREG_WPROT;
54283d0cf89SJan Kiszka     if (level) {
54383d0cf89SJan Kiszka         s->intreg_state |= ICP_INTREG_WPROT;
54483d0cf89SJan Kiszka     }
54583d0cf89SJan Kiszka }
54683d0cf89SJan Kiszka 
54783d0cf89SJan Kiszka static void icp_control_mmc_cardin(void *opaque, int line, int level)
54883d0cf89SJan Kiszka {
54983d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
55083d0cf89SJan Kiszka 
55183d0cf89SJan Kiszka     /* line is released by writing to CP_INTREG */
55283d0cf89SJan Kiszka     if (level) {
55383d0cf89SJan Kiszka         s->intreg_state |= ICP_INTREG_CARDIN;
55483d0cf89SJan Kiszka         qemu_set_irq(s->mmc_irq, 1);
55583d0cf89SJan Kiszka     }
55683d0cf89SJan Kiszka }
55783d0cf89SJan Kiszka 
558ffc8542aSJan Kiszka static void icp_control_init(Object *obj)
559b5ff1b31Sbellard {
560ffc8542aSJan Kiszka     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
561ffc8542aSJan Kiszka     ICPCtrlRegsState *s = ICP_CONTROL_REGS(obj);
56283d0cf89SJan Kiszka     DeviceState *dev = DEVICE(obj);
563b5ff1b31Sbellard 
564ffc8542aSJan Kiszka     memory_region_init_io(&s->iomem, OBJECT(s), &icp_control_ops, s,
565ffc8542aSJan Kiszka                           "icp_ctrl_regs", 0x00800000);
566ffc8542aSJan Kiszka     sysbus_init_mmio(sbd, &s->iomem);
56783d0cf89SJan Kiszka 
56883d0cf89SJan Kiszka     qdev_init_gpio_in_named(dev, icp_control_mmc_wprot, ICP_GPIO_MMC_WPROT, 1);
56983d0cf89SJan Kiszka     qdev_init_gpio_in_named(dev, icp_control_mmc_cardin,
57083d0cf89SJan Kiszka                             ICP_GPIO_MMC_CARDIN, 1);
57183d0cf89SJan Kiszka     sysbus_init_irq(sbd, &s->mmc_irq);
572b5ff1b31Sbellard }
573b5ff1b31Sbellard 
574b5ff1b31Sbellard 
575b5ff1b31Sbellard /* Board init.  */
576b5ff1b31Sbellard 
577f93eb9ffSbalrog static struct arm_boot_info integrator_binfo = {
578f93eb9ffSbalrog     .loader_start = 0x0,
579f93eb9ffSbalrog     .board_id = 0x113,
580f93eb9ffSbalrog };
581f93eb9ffSbalrog 
5823ef96221SMarcel Apfelbaum static void integratorcp_init(MachineState *machine)
583b5ff1b31Sbellard {
5843ef96221SMarcel Apfelbaum     ram_addr_t ram_size = machine->ram_size;
585223a72f1SGreg Bellows     Object *cpuobj;
586393a9eabSAndreas Färber     ARMCPU *cpu;
587211adf4dSAvi Kivity     MemoryRegion *address_space_mem = get_system_memory();
588211adf4dSAvi Kivity     MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
589a7086888SPaul Brook     qemu_irq pic[32];
59083d0cf89SJan Kiszka     DeviceState *dev, *sic, *icp;
591a7086888SPaul Brook     int i;
592b5ff1b31Sbellard 
593ba1ba5ccSIgor Mammedov     cpuobj = object_new(machine->cpu_type);
594223a72f1SGreg Bellows 
59561e2f352SGreg Bellows     /* By default ARM1176 CPUs have EL3 enabled.  This board does not
59661e2f352SGreg Bellows      * currently support EL3 so the CPU EL3 property is disabled before
59761e2f352SGreg Bellows      * realization.
59861e2f352SGreg Bellows      */
59961e2f352SGreg Bellows     if (object_property_find(cpuobj, "has_el3", NULL)) {
600007b0657SMarkus Armbruster         object_property_set_bool(cpuobj, false, "has_el3", &error_fatal);
60161e2f352SGreg Bellows     }
60261e2f352SGreg Bellows 
603007b0657SMarkus Armbruster     object_property_set_bool(cpuobj, true, "realized", &error_fatal);
604223a72f1SGreg Bellows 
605223a72f1SGreg Bellows     cpu = ARM_CPU(cpuobj);
606223a72f1SGreg Bellows 
607b5ff1b31Sbellard     /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
6081235fc06Sths     /* ??? RAM should repeat to fill physical memory space.  */
609b5ff1b31Sbellard     /* SDRAM at address zero*/
610*3f25b3f4SIgor Mammedov     memory_region_add_subregion(address_space_mem, 0, machine->ram);
611b5ff1b31Sbellard     /* And again at address 0x80000000 */
612*3f25b3f4SIgor Mammedov     memory_region_init_alias(ram_alias, NULL, "ram.alias", machine->ram,
613*3f25b3f4SIgor Mammedov                              0, ram_size);
614211adf4dSAvi Kivity     memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
615b5ff1b31Sbellard 
616257ec289SAndreas Färber     dev = qdev_create(NULL, TYPE_INTEGRATOR_CM);
617ee6847d1SGerd Hoffmann     qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
618e23a1b33SMarkus Armbruster     qdev_init_nofail(dev);
619a7086888SPaul Brook     sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
620a7086888SPaul Brook 
62191b64626SAndreas Färber     dev = sysbus_create_varargs(TYPE_INTEGRATOR_PIC, 0x14000000,
62299d228d6SPeter Maydell                                 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ),
62399d228d6SPeter Maydell                                 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ),
62499d228d6SPeter Maydell                                 NULL);
625a7086888SPaul Brook     for (i = 0; i < 32; i++) {
626067a3ddcSPaul Brook         pic[i] = qdev_get_gpio_in(dev, i);
627a7086888SPaul Brook     }
62883d0cf89SJan Kiszka     sic = sysbus_create_simple(TYPE_INTEGRATOR_PIC, 0xca000000, pic[26]);
6296a824ec3SPaul Brook     sysbus_create_varargs("integrator_pit", 0x13000000,
6306a824ec3SPaul Brook                           pic[5], pic[6], pic[7], NULL);
631a63bdb31SPaul Brook     sysbus_create_simple("pl031", 0x15000000, pic[8]);
6329bca0edbSPeter Maydell     pl011_create(0x16000000, pic[1], serial_hd(0));
6339bca0edbSPeter Maydell     pl011_create(0x17000000, pic[2], serial_hd(1));
63483d0cf89SJan Kiszka     icp = sysbus_create_simple(TYPE_ICP_CONTROL_REGS, 0xcb000000,
63583d0cf89SJan Kiszka                                qdev_get_gpio_in(sic, 3));
63686394e96SPaul Brook     sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
63786394e96SPaul Brook     sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]);
638b8616055SAlex Bennée     sysbus_create_simple(TYPE_INTEGRATOR_DEBUG, 0x1a000000, 0);
63983d0cf89SJan Kiszka 
64083d0cf89SJan Kiszka     dev = sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL);
64183d0cf89SJan Kiszka     qdev_connect_gpio_out(dev, 0,
64283d0cf89SJan Kiszka                           qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_WPROT, 0));
64383d0cf89SJan Kiszka     qdev_connect_gpio_out(dev, 1,
64483d0cf89SJan Kiszka                           qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_CARDIN, 0));
64583d0cf89SJan Kiszka 
646a005d073SStefan Hajnoczi     if (nd_table[0].used)
647d537cf6cSpbrook         smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
6482e9bdce5SPaul Brook 
6492e9bdce5SPaul Brook     sysbus_create_simple("pl110", 0xc0000000, pic[22]);
650b5ff1b31Sbellard 
651f93eb9ffSbalrog     integrator_binfo.ram_size = ram_size;
6522744ece8STao Xu     arm_load_kernel(cpu, machine, &integrator_binfo);
653b5ff1b31Sbellard }
654b5ff1b31Sbellard 
655e264d29dSEduardo Habkost static void integratorcp_machine_init(MachineClass *mc)
656f80f9ec9SAnthony Liguori {
657e264d29dSEduardo Habkost     mc->desc = "ARM Integrator/CP (ARM926EJ-S)";
658e264d29dSEduardo Habkost     mc->init = integratorcp_init;
6594672cbd7SPeter Maydell     mc->ignore_memory_transaction_failures = true;
660ba1ba5ccSIgor Mammedov     mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926");
661*3f25b3f4SIgor Mammedov     mc->default_ram_id = "integrator.ram";
662f80f9ec9SAnthony Liguori }
663f80f9ec9SAnthony Liguori 
664e264d29dSEduardo Habkost DEFINE_MACHINE("integratorcp", integratorcp_machine_init)
665f80f9ec9SAnthony Liguori 
666999e12bbSAnthony Liguori static Property core_properties[] = {
667257ec289SAndreas Färber     DEFINE_PROP_UINT32("memsz", IntegratorCMState, memsz, 0),
668bb36f66aSGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
669999e12bbSAnthony Liguori };
670999e12bbSAnthony Liguori 
671999e12bbSAnthony Liguori static void core_class_init(ObjectClass *klass, void *data)
672999e12bbSAnthony Liguori {
67339bffca2SAnthony Liguori     DeviceClass *dc = DEVICE_CLASS(klass);
674999e12bbSAnthony Liguori 
6754f67d30bSMarc-André Lureau     device_class_set_props(dc, core_properties);
676e9d9ee23SJakub Jermar     dc->realize = integratorcm_realize;
67726d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_integratorcm;
67826d32022SPavel Dovgalyuk }
67926d32022SPavel Dovgalyuk 
68026d32022SPavel Dovgalyuk static void icp_pic_class_init(ObjectClass *klass, void *data)
68126d32022SPavel Dovgalyuk {
68226d32022SPavel Dovgalyuk     DeviceClass *dc = DEVICE_CLASS(klass);
68326d32022SPavel Dovgalyuk 
68426d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_icp_pic;
68526d32022SPavel Dovgalyuk }
68626d32022SPavel Dovgalyuk 
68726d32022SPavel Dovgalyuk static void icp_control_class_init(ObjectClass *klass, void *data)
68826d32022SPavel Dovgalyuk {
68926d32022SPavel Dovgalyuk     DeviceClass *dc = DEVICE_CLASS(klass);
69026d32022SPavel Dovgalyuk 
69126d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_icp_control;
692ee6847d1SGerd Hoffmann }
693999e12bbSAnthony Liguori 
6948c43a6f0SAndreas Färber static const TypeInfo core_info = {
695257ec289SAndreas Färber     .name          = TYPE_INTEGRATOR_CM,
69639bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
697257ec289SAndreas Färber     .instance_size = sizeof(IntegratorCMState),
698a1f42e0cSxiaoqiang.zhao     .instance_init = integratorcm_init,
699999e12bbSAnthony Liguori     .class_init    = core_class_init,
700999e12bbSAnthony Liguori };
701999e12bbSAnthony Liguori 
7028c43a6f0SAndreas Färber static const TypeInfo icp_pic_info = {
70391b64626SAndreas Färber     .name          = TYPE_INTEGRATOR_PIC,
70439bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
70539bffca2SAnthony Liguori     .instance_size = sizeof(icp_pic_state),
706a1f42e0cSxiaoqiang.zhao     .instance_init = icp_pic_init,
70726d32022SPavel Dovgalyuk     .class_init    = icp_pic_class_init,
708ee6847d1SGerd Hoffmann };
709ee6847d1SGerd Hoffmann 
710ffc8542aSJan Kiszka static const TypeInfo icp_ctrl_regs_info = {
711ffc8542aSJan Kiszka     .name          = TYPE_ICP_CONTROL_REGS,
712ffc8542aSJan Kiszka     .parent        = TYPE_SYS_BUS_DEVICE,
713ffc8542aSJan Kiszka     .instance_size = sizeof(ICPCtrlRegsState),
714ffc8542aSJan Kiszka     .instance_init = icp_control_init,
71526d32022SPavel Dovgalyuk     .class_init    = icp_control_class_init,
716ffc8542aSJan Kiszka };
717ffc8542aSJan Kiszka 
71883f7d43aSAndreas Färber static void integratorcp_register_types(void)
719a7086888SPaul Brook {
72039bffca2SAnthony Liguori     type_register_static(&icp_pic_info);
72139bffca2SAnthony Liguori     type_register_static(&core_info);
722ffc8542aSJan Kiszka     type_register_static(&icp_ctrl_regs_info);
723a7086888SPaul Brook }
724a7086888SPaul Brook 
72583f7d43aSAndreas Färber type_init(integratorcp_register_types)
726