xref: /qemu/hw/arm/integratorcp.c (revision d6454270575da1f16a8923c7cb240e46ef243f72)
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"
14*d6454270SMarkus 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"
2464552b6bSMarkus Armbruster #include "hw/irq.h"
25b5ff1b31Sbellard 
26257ec289SAndreas Färber #define TYPE_INTEGRATOR_CM "integrator_core"
27257ec289SAndreas Färber #define INTEGRATOR_CM(obj) \
28257ec289SAndreas Färber     OBJECT_CHECK(IntegratorCMState, (obj), TYPE_INTEGRATOR_CM)
29257ec289SAndreas Färber 
30257ec289SAndreas Färber typedef struct IntegratorCMState {
31257ec289SAndreas Färber     /*< private >*/
32257ec289SAndreas Färber     SysBusDevice parent_obj;
33257ec289SAndreas Färber     /*< public >*/
34257ec289SAndreas Färber 
3571d9bc50SBenoît Canet     MemoryRegion iomem;
36ee6847d1SGerd Hoffmann     uint32_t memsz;
37211adf4dSAvi Kivity     MemoryRegion flash;
38b5ff1b31Sbellard     uint32_t cm_osc;
39b5ff1b31Sbellard     uint32_t cm_ctrl;
40b5ff1b31Sbellard     uint32_t cm_lock;
41b5ff1b31Sbellard     uint32_t cm_auxosc;
42b5ff1b31Sbellard     uint32_t cm_sdram;
43b5ff1b31Sbellard     uint32_t cm_init;
44b5ff1b31Sbellard     uint32_t cm_flags;
45b5ff1b31Sbellard     uint32_t cm_nvflags;
46f53977f7SJan Petrous     uint32_t cm_refcnt_offset;
47b5ff1b31Sbellard     uint32_t int_level;
48b5ff1b31Sbellard     uint32_t irq_enabled;
49b5ff1b31Sbellard     uint32_t fiq_enabled;
50257ec289SAndreas Färber } IntegratorCMState;
51b5ff1b31Sbellard 
52b5ff1b31Sbellard static uint8_t integrator_spd[128] = {
53b5ff1b31Sbellard    128, 8, 4, 11, 9, 1, 64, 0,  2, 0xa0, 0xa0, 0, 0, 8, 0, 1,
54b5ff1b31Sbellard    0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
55b5ff1b31Sbellard };
56b5ff1b31Sbellard 
5726d32022SPavel Dovgalyuk static const VMStateDescription vmstate_integratorcm = {
5826d32022SPavel Dovgalyuk     .name = "integratorcm",
5926d32022SPavel Dovgalyuk     .version_id = 1,
6026d32022SPavel Dovgalyuk     .minimum_version_id = 1,
6126d32022SPavel Dovgalyuk     .fields      = (VMStateField[]) {
6226d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_osc, IntegratorCMState),
6326d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_ctrl, IntegratorCMState),
6426d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_lock, IntegratorCMState),
6526d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_auxosc, IntegratorCMState),
6626d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_sdram, IntegratorCMState),
6726d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_init, IntegratorCMState),
6826d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_flags, IntegratorCMState),
6926d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_nvflags, IntegratorCMState),
7026d32022SPavel Dovgalyuk         VMSTATE_UINT32(int_level, IntegratorCMState),
7126d32022SPavel Dovgalyuk         VMSTATE_UINT32(irq_enabled, IntegratorCMState),
7226d32022SPavel Dovgalyuk         VMSTATE_UINT32(fiq_enabled, IntegratorCMState),
7326d32022SPavel Dovgalyuk         VMSTATE_END_OF_LIST()
7426d32022SPavel Dovgalyuk     }
7526d32022SPavel Dovgalyuk };
7626d32022SPavel Dovgalyuk 
77a8170e5eSAvi Kivity static uint64_t integratorcm_read(void *opaque, hwaddr offset,
7871d9bc50SBenoît Canet                                   unsigned size)
79b5ff1b31Sbellard {
80257ec289SAndreas Färber     IntegratorCMState *s = opaque;
81b5ff1b31Sbellard     if (offset >= 0x100 && offset < 0x200) {
82b5ff1b31Sbellard         /* CM_SPD */
83b5ff1b31Sbellard         if (offset >= 0x180)
84b5ff1b31Sbellard             return 0;
85b5ff1b31Sbellard         return integrator_spd[offset >> 2];
86b5ff1b31Sbellard     }
87b5ff1b31Sbellard     switch (offset >> 2) {
88b5ff1b31Sbellard     case 0: /* CM_ID */
89b5ff1b31Sbellard         return 0x411a3001;
90b5ff1b31Sbellard     case 1: /* CM_PROC */
91b5ff1b31Sbellard         return 0;
92b5ff1b31Sbellard     case 2: /* CM_OSC */
93b5ff1b31Sbellard         return s->cm_osc;
94b5ff1b31Sbellard     case 3: /* CM_CTRL */
95b5ff1b31Sbellard         return s->cm_ctrl;
96b5ff1b31Sbellard     case 4: /* CM_STAT */
97b5ff1b31Sbellard         return 0x00100000;
98b5ff1b31Sbellard     case 5: /* CM_LOCK */
99b5ff1b31Sbellard         if (s->cm_lock == 0xa05f) {
100b5ff1b31Sbellard             return 0x1a05f;
101b5ff1b31Sbellard         } else {
102b5ff1b31Sbellard             return s->cm_lock;
103b5ff1b31Sbellard         }
104b5ff1b31Sbellard     case 6: /* CM_LMBUSCNT */
105b5ff1b31Sbellard         /* ??? High frequency timer.  */
1062ac71179SPaul Brook         hw_error("integratorcm_read: CM_LMBUSCNT");
107b5ff1b31Sbellard     case 7: /* CM_AUXOSC */
108b5ff1b31Sbellard         return s->cm_auxosc;
109b5ff1b31Sbellard     case 8: /* CM_SDRAM */
110b5ff1b31Sbellard         return s->cm_sdram;
111b5ff1b31Sbellard     case 9: /* CM_INIT */
112b5ff1b31Sbellard         return s->cm_init;
113f53977f7SJan Petrous     case 10: /* CM_REFCNT */
114f53977f7SJan Petrous         /* This register, CM_REFCNT, provides a 32-bit count value.
115f53977f7SJan Petrous          * The count increments at the fixed reference clock frequency of 24MHz
116f53977f7SJan Petrous          * and can be used as a real-time counter.
117f53977f7SJan Petrous          */
118f53977f7SJan Petrous         return (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24,
119f53977f7SJan Petrous                                   1000) - s->cm_refcnt_offset;
120b5ff1b31Sbellard     case 12: /* CM_FLAGS */
121b5ff1b31Sbellard         return s->cm_flags;
122b5ff1b31Sbellard     case 14: /* CM_NVFLAGS */
123b5ff1b31Sbellard         return s->cm_nvflags;
124b5ff1b31Sbellard     case 16: /* CM_IRQ_STAT */
125b5ff1b31Sbellard         return s->int_level & s->irq_enabled;
126b5ff1b31Sbellard     case 17: /* CM_IRQ_RSTAT */
127b5ff1b31Sbellard         return s->int_level;
128b5ff1b31Sbellard     case 18: /* CM_IRQ_ENSET */
129b5ff1b31Sbellard         return s->irq_enabled;
130b5ff1b31Sbellard     case 20: /* CM_SOFT_INTSET */
131b5ff1b31Sbellard         return s->int_level & 1;
132b5ff1b31Sbellard     case 24: /* CM_FIQ_STAT */
133b5ff1b31Sbellard         return s->int_level & s->fiq_enabled;
134b5ff1b31Sbellard     case 25: /* CM_FIQ_RSTAT */
135b5ff1b31Sbellard         return s->int_level;
136b5ff1b31Sbellard     case 26: /* CM_FIQ_ENSET */
137b5ff1b31Sbellard         return s->fiq_enabled;
138b5ff1b31Sbellard     case 32: /* CM_VOLTAGE_CTL0 */
139b5ff1b31Sbellard     case 33: /* CM_VOLTAGE_CTL1 */
140b5ff1b31Sbellard     case 34: /* CM_VOLTAGE_CTL2 */
141b5ff1b31Sbellard     case 35: /* CM_VOLTAGE_CTL3 */
142b5ff1b31Sbellard         /* ??? Voltage control unimplemented.  */
143b5ff1b31Sbellard         return 0;
144b5ff1b31Sbellard     default:
1452ac71179SPaul Brook         hw_error("integratorcm_read: Unimplemented offset 0x%x\n",
1462ac71179SPaul Brook                  (int)offset);
147b5ff1b31Sbellard         return 0;
148b5ff1b31Sbellard     }
149b5ff1b31Sbellard }
150b5ff1b31Sbellard 
151257ec289SAndreas Färber static void integratorcm_do_remap(IntegratorCMState *s)
152b5ff1b31Sbellard {
153563c2bf3SPeter Maydell     /* Sync memory region state with CM_CTRL REMAP bit:
154563c2bf3SPeter Maydell      * bit 0 => flash at address 0; bit 1 => RAM
155563c2bf3SPeter Maydell      */
156563c2bf3SPeter Maydell     memory_region_set_enabled(&s->flash, !(s->cm_ctrl & 4));
157b5ff1b31Sbellard }
158b5ff1b31Sbellard 
159257ec289SAndreas Färber static void integratorcm_set_ctrl(IntegratorCMState *s, uint32_t value)
160b5ff1b31Sbellard {
161b5ff1b31Sbellard     if (value & 8) {
162cf83f140SEric Blake         qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
163b5ff1b31Sbellard     }
164df3f457bSPeter Maydell     if ((s->cm_ctrl ^ value) & 1) {
165df3f457bSPeter Maydell         /* (value & 1) != 0 means the green "MISC LED" is lit.
166df3f457bSPeter Maydell          * We don't have any nice place to display LEDs. printf is a bad
167df3f457bSPeter Maydell          * idea because Linux uses the LED as a heartbeat and the output
168df3f457bSPeter Maydell          * will swamp anything else on the terminal.
169df3f457bSPeter Maydell          */
170b5ff1b31Sbellard     }
171df3f457bSPeter Maydell     /* Note that the RESET bit [3] always reads as zero */
172df3f457bSPeter Maydell     s->cm_ctrl = (s->cm_ctrl & ~5) | (value & 5);
173563c2bf3SPeter Maydell     integratorcm_do_remap(s);
174b5ff1b31Sbellard }
175b5ff1b31Sbellard 
176257ec289SAndreas Färber static void integratorcm_update(IntegratorCMState *s)
177b5ff1b31Sbellard {
178b5ff1b31Sbellard     /* ??? The CPU irq/fiq is raised when either the core module or base PIC
179b5ff1b31Sbellard        are active.  */
180b5ff1b31Sbellard     if (s->int_level & (s->irq_enabled | s->fiq_enabled))
1812ac71179SPaul Brook         hw_error("Core module interrupt\n");
182b5ff1b31Sbellard }
183b5ff1b31Sbellard 
184a8170e5eSAvi Kivity static void integratorcm_write(void *opaque, hwaddr offset,
18571d9bc50SBenoît Canet                                uint64_t value, unsigned size)
186b5ff1b31Sbellard {
187257ec289SAndreas Färber     IntegratorCMState *s = opaque;
188b5ff1b31Sbellard     switch (offset >> 2) {
189b5ff1b31Sbellard     case 2: /* CM_OSC */
190b5ff1b31Sbellard         if (s->cm_lock == 0xa05f)
191b5ff1b31Sbellard             s->cm_osc = value;
192b5ff1b31Sbellard         break;
193b5ff1b31Sbellard     case 3: /* CM_CTRL */
194b5ff1b31Sbellard         integratorcm_set_ctrl(s, value);
195b5ff1b31Sbellard         break;
196b5ff1b31Sbellard     case 5: /* CM_LOCK */
197b5ff1b31Sbellard         s->cm_lock = value & 0xffff;
198b5ff1b31Sbellard         break;
199b5ff1b31Sbellard     case 7: /* CM_AUXOSC */
200b5ff1b31Sbellard         if (s->cm_lock == 0xa05f)
201b5ff1b31Sbellard             s->cm_auxosc = value;
202b5ff1b31Sbellard         break;
203b5ff1b31Sbellard     case 8: /* CM_SDRAM */
204b5ff1b31Sbellard         s->cm_sdram = value;
205b5ff1b31Sbellard         break;
206b5ff1b31Sbellard     case 9: /* CM_INIT */
207b5ff1b31Sbellard         /* ??? This can change the memory bus frequency.  */
208b5ff1b31Sbellard         s->cm_init = value;
209b5ff1b31Sbellard         break;
210b5ff1b31Sbellard     case 12: /* CM_FLAGSS */
211b5ff1b31Sbellard         s->cm_flags |= value;
212b5ff1b31Sbellard         break;
213b5ff1b31Sbellard     case 13: /* CM_FLAGSC */
214b5ff1b31Sbellard         s->cm_flags &= ~value;
215b5ff1b31Sbellard         break;
216b5ff1b31Sbellard     case 14: /* CM_NVFLAGSS */
217b5ff1b31Sbellard         s->cm_nvflags |= value;
218b5ff1b31Sbellard         break;
219b5ff1b31Sbellard     case 15: /* CM_NVFLAGSS */
220b5ff1b31Sbellard         s->cm_nvflags &= ~value;
221b5ff1b31Sbellard         break;
222b5ff1b31Sbellard     case 18: /* CM_IRQ_ENSET */
223b5ff1b31Sbellard         s->irq_enabled |= value;
224b5ff1b31Sbellard         integratorcm_update(s);
225b5ff1b31Sbellard         break;
226b5ff1b31Sbellard     case 19: /* CM_IRQ_ENCLR */
227b5ff1b31Sbellard         s->irq_enabled &= ~value;
228b5ff1b31Sbellard         integratorcm_update(s);
229b5ff1b31Sbellard         break;
230b5ff1b31Sbellard     case 20: /* CM_SOFT_INTSET */
231b5ff1b31Sbellard         s->int_level |= (value & 1);
232b5ff1b31Sbellard         integratorcm_update(s);
233b5ff1b31Sbellard         break;
234b5ff1b31Sbellard     case 21: /* CM_SOFT_INTCLR */
235b5ff1b31Sbellard         s->int_level &= ~(value & 1);
236b5ff1b31Sbellard         integratorcm_update(s);
237b5ff1b31Sbellard         break;
238b5ff1b31Sbellard     case 26: /* CM_FIQ_ENSET */
239b5ff1b31Sbellard         s->fiq_enabled |= value;
240b5ff1b31Sbellard         integratorcm_update(s);
241b5ff1b31Sbellard         break;
242b5ff1b31Sbellard     case 27: /* CM_FIQ_ENCLR */
243b5ff1b31Sbellard         s->fiq_enabled &= ~value;
244b5ff1b31Sbellard         integratorcm_update(s);
245b5ff1b31Sbellard         break;
246b5ff1b31Sbellard     case 32: /* CM_VOLTAGE_CTL0 */
247b5ff1b31Sbellard     case 33: /* CM_VOLTAGE_CTL1 */
248b5ff1b31Sbellard     case 34: /* CM_VOLTAGE_CTL2 */
249b5ff1b31Sbellard     case 35: /* CM_VOLTAGE_CTL3 */
250b5ff1b31Sbellard         /* ??? Voltage control unimplemented.  */
251b5ff1b31Sbellard         break;
252b5ff1b31Sbellard     default:
2532ac71179SPaul Brook         hw_error("integratorcm_write: Unimplemented offset 0x%x\n",
2542ac71179SPaul Brook                  (int)offset);
255b5ff1b31Sbellard         break;
256b5ff1b31Sbellard     }
257b5ff1b31Sbellard }
258b5ff1b31Sbellard 
259b5ff1b31Sbellard /* Integrator/CM control registers.  */
260b5ff1b31Sbellard 
26171d9bc50SBenoît Canet static const MemoryRegionOps integratorcm_ops = {
26271d9bc50SBenoît Canet     .read = integratorcm_read,
26371d9bc50SBenoît Canet     .write = integratorcm_write,
26471d9bc50SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
265b5ff1b31Sbellard };
266b5ff1b31Sbellard 
267a1f42e0cSxiaoqiang.zhao static void integratorcm_init(Object *obj)
268b5ff1b31Sbellard {
269a1f42e0cSxiaoqiang.zhao     IntegratorCMState *s = INTEGRATOR_CM(obj);
270b5ff1b31Sbellard 
271b5ff1b31Sbellard     s->cm_osc = 0x01000048;
272b5ff1b31Sbellard     /* ??? What should the high bits of this value be?  */
273b5ff1b31Sbellard     s->cm_auxosc = 0x0007feff;
274b5ff1b31Sbellard     s->cm_sdram = 0x00011122;
275e9d9ee23SJakub Jermar     memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
276e9d9ee23SJakub Jermar     s->cm_init = 0x00000112;
277e9d9ee23SJakub Jermar     s->cm_refcnt_offset = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24,
278e9d9ee23SJakub Jermar                                    1000);
279e9d9ee23SJakub Jermar 
280e9d9ee23SJakub Jermar     /* ??? Save/restore.  */
281e9d9ee23SJakub Jermar }
282e9d9ee23SJakub Jermar 
283e9d9ee23SJakub Jermar static void integratorcm_realize(DeviceState *d, Error **errp)
284e9d9ee23SJakub Jermar {
285e9d9ee23SJakub Jermar     IntegratorCMState *s = INTEGRATOR_CM(d);
2868720daadSThomas Huth     SysBusDevice *dev = SYS_BUS_DEVICE(d);
2878720daadSThomas Huth     Error *local_err = NULL;
2888720daadSThomas Huth 
2898720daadSThomas Huth     memory_region_init_ram(&s->flash, OBJECT(d), "integrator.flash", 0x100000,
2908720daadSThomas Huth                            &local_err);
2918720daadSThomas Huth     if (local_err) {
2928720daadSThomas Huth         error_propagate(errp, local_err);
2938720daadSThomas Huth         return;
2948720daadSThomas Huth     }
2958720daadSThomas Huth 
2968720daadSThomas Huth     memory_region_init_io(&s->iomem, OBJECT(d), &integratorcm_ops, s,
2978720daadSThomas Huth                           "integratorcm", 0x00800000);
2988720daadSThomas Huth     sysbus_init_mmio(dev, &s->iomem);
2998720daadSThomas Huth 
3008720daadSThomas Huth     integratorcm_do_remap(s);
301e9d9ee23SJakub Jermar 
302ee6847d1SGerd Hoffmann     if (s->memsz >= 256) {
303b5ff1b31Sbellard         integrator_spd[31] = 64;
304b5ff1b31Sbellard         s->cm_sdram |= 0x10;
305ee6847d1SGerd Hoffmann     } else if (s->memsz >= 128) {
306b5ff1b31Sbellard         integrator_spd[31] = 32;
307b5ff1b31Sbellard         s->cm_sdram |= 0x0c;
308ee6847d1SGerd Hoffmann     } else if (s->memsz >= 64) {
309b5ff1b31Sbellard         integrator_spd[31] = 16;
310b5ff1b31Sbellard         s->cm_sdram |= 0x08;
311ee6847d1SGerd Hoffmann     } else if (s->memsz >= 32) {
312b5ff1b31Sbellard         integrator_spd[31] = 4;
313b5ff1b31Sbellard         s->cm_sdram |= 0x04;
314b5ff1b31Sbellard     } else {
315b5ff1b31Sbellard         integrator_spd[31] = 2;
316b5ff1b31Sbellard     }
317b5ff1b31Sbellard }
318b5ff1b31Sbellard 
319b5ff1b31Sbellard /* Integrator/CP hardware emulation.  */
320b5ff1b31Sbellard /* Primary interrupt controller.  */
321b5ff1b31Sbellard 
32291b64626SAndreas Färber #define TYPE_INTEGRATOR_PIC "integrator_pic"
32391b64626SAndreas Färber #define INTEGRATOR_PIC(obj) \
32491b64626SAndreas Färber    OBJECT_CHECK(icp_pic_state, (obj), TYPE_INTEGRATOR_PIC)
32591b64626SAndreas Färber 
32691b64626SAndreas Färber typedef struct icp_pic_state {
32791b64626SAndreas Färber     /*< private >*/
32891b64626SAndreas Färber     SysBusDevice parent_obj;
32991b64626SAndreas Färber     /*< public >*/
33091b64626SAndreas Färber 
33161074e46SBenoît Canet     MemoryRegion iomem;
332b5ff1b31Sbellard     uint32_t level;
333b5ff1b31Sbellard     uint32_t irq_enabled;
334b5ff1b31Sbellard     uint32_t fiq_enabled;
335d537cf6cSpbrook     qemu_irq parent_irq;
336d537cf6cSpbrook     qemu_irq parent_fiq;
337b5ff1b31Sbellard } icp_pic_state;
338b5ff1b31Sbellard 
33926d32022SPavel Dovgalyuk static const VMStateDescription vmstate_icp_pic = {
34026d32022SPavel Dovgalyuk     .name = "icp_pic",
34126d32022SPavel Dovgalyuk     .version_id = 1,
34226d32022SPavel Dovgalyuk     .minimum_version_id = 1,
34326d32022SPavel Dovgalyuk     .fields      = (VMStateField[]) {
34426d32022SPavel Dovgalyuk         VMSTATE_UINT32(level, icp_pic_state),
34526d32022SPavel Dovgalyuk         VMSTATE_UINT32(irq_enabled, icp_pic_state),
34626d32022SPavel Dovgalyuk         VMSTATE_UINT32(fiq_enabled, icp_pic_state),
34726d32022SPavel Dovgalyuk         VMSTATE_END_OF_LIST()
34826d32022SPavel Dovgalyuk     }
34926d32022SPavel Dovgalyuk };
35026d32022SPavel Dovgalyuk 
351b5ff1b31Sbellard static void icp_pic_update(icp_pic_state *s)
352b5ff1b31Sbellard {
353b5ff1b31Sbellard     uint32_t flags;
354b5ff1b31Sbellard 
355b5ff1b31Sbellard     flags = (s->level & s->irq_enabled);
356d537cf6cSpbrook     qemu_set_irq(s->parent_irq, flags != 0);
357cdbdb648Spbrook     flags = (s->level & s->fiq_enabled);
358d537cf6cSpbrook     qemu_set_irq(s->parent_fiq, flags != 0);
359b5ff1b31Sbellard }
360b5ff1b31Sbellard 
361cdbdb648Spbrook static void icp_pic_set_irq(void *opaque, int irq, int level)
362b5ff1b31Sbellard {
36380337b66Sbellard     icp_pic_state *s = (icp_pic_state *)opaque;
364b5ff1b31Sbellard     if (level)
36580337b66Sbellard         s->level |= 1 << irq;
366b5ff1b31Sbellard     else
36780337b66Sbellard         s->level &= ~(1 << irq);
368b5ff1b31Sbellard     icp_pic_update(s);
369b5ff1b31Sbellard }
370b5ff1b31Sbellard 
371a8170e5eSAvi Kivity static uint64_t icp_pic_read(void *opaque, hwaddr offset,
37261074e46SBenoît Canet                              unsigned size)
373b5ff1b31Sbellard {
374b5ff1b31Sbellard     icp_pic_state *s = (icp_pic_state *)opaque;
375b5ff1b31Sbellard 
376b5ff1b31Sbellard     switch (offset >> 2) {
377b5ff1b31Sbellard     case 0: /* IRQ_STATUS */
378b5ff1b31Sbellard         return s->level & s->irq_enabled;
379b5ff1b31Sbellard     case 1: /* IRQ_RAWSTAT */
380b5ff1b31Sbellard         return s->level;
381b5ff1b31Sbellard     case 2: /* IRQ_ENABLESET */
382b5ff1b31Sbellard         return s->irq_enabled;
383b5ff1b31Sbellard     case 4: /* INT_SOFTSET */
384b5ff1b31Sbellard         return s->level & 1;
385b5ff1b31Sbellard     case 8: /* FRQ_STATUS */
386b5ff1b31Sbellard         return s->level & s->fiq_enabled;
387b5ff1b31Sbellard     case 9: /* FRQ_RAWSTAT */
388b5ff1b31Sbellard         return s->level;
389b5ff1b31Sbellard     case 10: /* FRQ_ENABLESET */
390b5ff1b31Sbellard         return s->fiq_enabled;
391b5ff1b31Sbellard     case 3: /* IRQ_ENABLECLR */
392b5ff1b31Sbellard     case 5: /* INT_SOFTCLR */
393b5ff1b31Sbellard     case 11: /* FRQ_ENABLECLR */
394b5ff1b31Sbellard     default:
39529bfb117Spbrook         printf ("icp_pic_read: Bad register offset 0x%x\n", (int)offset);
396b5ff1b31Sbellard         return 0;
397b5ff1b31Sbellard     }
398b5ff1b31Sbellard }
399b5ff1b31Sbellard 
400a8170e5eSAvi Kivity static void icp_pic_write(void *opaque, hwaddr offset,
40161074e46SBenoît Canet                           uint64_t value, unsigned size)
402b5ff1b31Sbellard {
403b5ff1b31Sbellard     icp_pic_state *s = (icp_pic_state *)opaque;
404b5ff1b31Sbellard 
405b5ff1b31Sbellard     switch (offset >> 2) {
406b5ff1b31Sbellard     case 2: /* IRQ_ENABLESET */
407b5ff1b31Sbellard         s->irq_enabled |= value;
408b5ff1b31Sbellard         break;
409b5ff1b31Sbellard     case 3: /* IRQ_ENABLECLR */
410b5ff1b31Sbellard         s->irq_enabled &= ~value;
411b5ff1b31Sbellard         break;
412b5ff1b31Sbellard     case 4: /* INT_SOFTSET */
413b5ff1b31Sbellard         if (value & 1)
414d537cf6cSpbrook             icp_pic_set_irq(s, 0, 1);
415b5ff1b31Sbellard         break;
416b5ff1b31Sbellard     case 5: /* INT_SOFTCLR */
417b5ff1b31Sbellard         if (value & 1)
418d537cf6cSpbrook             icp_pic_set_irq(s, 0, 0);
419b5ff1b31Sbellard         break;
420b5ff1b31Sbellard     case 10: /* FRQ_ENABLESET */
421b5ff1b31Sbellard         s->fiq_enabled |= value;
422b5ff1b31Sbellard         break;
423b5ff1b31Sbellard     case 11: /* FRQ_ENABLECLR */
424b5ff1b31Sbellard         s->fiq_enabled &= ~value;
425b5ff1b31Sbellard         break;
426b5ff1b31Sbellard     case 0: /* IRQ_STATUS */
427b5ff1b31Sbellard     case 1: /* IRQ_RAWSTAT */
428b5ff1b31Sbellard     case 8: /* FRQ_STATUS */
429b5ff1b31Sbellard     case 9: /* FRQ_RAWSTAT */
430b5ff1b31Sbellard     default:
43129bfb117Spbrook         printf ("icp_pic_write: Bad register offset 0x%x\n", (int)offset);
432b5ff1b31Sbellard         return;
433b5ff1b31Sbellard     }
434b5ff1b31Sbellard     icp_pic_update(s);
435b5ff1b31Sbellard }
436b5ff1b31Sbellard 
43761074e46SBenoît Canet static const MemoryRegionOps icp_pic_ops = {
43861074e46SBenoît Canet     .read = icp_pic_read,
43961074e46SBenoît Canet     .write = icp_pic_write,
44061074e46SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
441b5ff1b31Sbellard };
442b5ff1b31Sbellard 
443a1f42e0cSxiaoqiang.zhao static void icp_pic_init(Object *obj)
444b5ff1b31Sbellard {
445a1f42e0cSxiaoqiang.zhao     DeviceState *dev = DEVICE(obj);
446a1f42e0cSxiaoqiang.zhao     icp_pic_state *s = INTEGRATOR_PIC(obj);
447a1f42e0cSxiaoqiang.zhao     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
448b5ff1b31Sbellard 
44991b64626SAndreas Färber     qdev_init_gpio_in(dev, icp_pic_set_irq, 32);
45091b64626SAndreas Färber     sysbus_init_irq(sbd, &s->parent_irq);
45191b64626SAndreas Färber     sysbus_init_irq(sbd, &s->parent_fiq);
452a1f42e0cSxiaoqiang.zhao     memory_region_init_io(&s->iomem, obj, &icp_pic_ops, s,
45364bde0f3SPaolo Bonzini                           "icp-pic", 0x00800000);
45491b64626SAndreas Färber     sysbus_init_mmio(sbd, &s->iomem);
455b5ff1b31Sbellard }
456b5ff1b31Sbellard 
457b5ff1b31Sbellard /* CP control registers.  */
4580c36493eSBenoît Canet 
459ffc8542aSJan Kiszka #define TYPE_ICP_CONTROL_REGS "icp-ctrl-regs"
460ffc8542aSJan Kiszka #define ICP_CONTROL_REGS(obj) \
461ffc8542aSJan Kiszka     OBJECT_CHECK(ICPCtrlRegsState, (obj), TYPE_ICP_CONTROL_REGS)
462ffc8542aSJan Kiszka 
463ffc8542aSJan Kiszka typedef struct ICPCtrlRegsState {
464ffc8542aSJan Kiszka     /*< private >*/
465ffc8542aSJan Kiszka     SysBusDevice parent_obj;
466ffc8542aSJan Kiszka     /*< public >*/
467ffc8542aSJan Kiszka 
468ffc8542aSJan Kiszka     MemoryRegion iomem;
46983d0cf89SJan Kiszka 
47083d0cf89SJan Kiszka     qemu_irq mmc_irq;
47183d0cf89SJan Kiszka     uint32_t intreg_state;
472ffc8542aSJan Kiszka } ICPCtrlRegsState;
473ffc8542aSJan Kiszka 
47483d0cf89SJan Kiszka #define ICP_GPIO_MMC_WPROT      "mmc-wprot"
47583d0cf89SJan Kiszka #define ICP_GPIO_MMC_CARDIN     "mmc-cardin"
47683d0cf89SJan Kiszka 
47783d0cf89SJan Kiszka #define ICP_INTREG_WPROT        (1 << 0)
47883d0cf89SJan Kiszka #define ICP_INTREG_CARDIN       (1 << 3)
47983d0cf89SJan Kiszka 
48026d32022SPavel Dovgalyuk static const VMStateDescription vmstate_icp_control = {
48126d32022SPavel Dovgalyuk     .name = "icp_control",
48226d32022SPavel Dovgalyuk     .version_id = 1,
48326d32022SPavel Dovgalyuk     .minimum_version_id = 1,
48426d32022SPavel Dovgalyuk     .fields      = (VMStateField[]) {
48526d32022SPavel Dovgalyuk         VMSTATE_UINT32(intreg_state, ICPCtrlRegsState),
48626d32022SPavel Dovgalyuk         VMSTATE_END_OF_LIST()
48726d32022SPavel Dovgalyuk     }
48826d32022SPavel Dovgalyuk };
48926d32022SPavel Dovgalyuk 
490a8170e5eSAvi Kivity static uint64_t icp_control_read(void *opaque, hwaddr offset,
4910c36493eSBenoît Canet                                  unsigned size)
492b5ff1b31Sbellard {
49383d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
49483d0cf89SJan Kiszka 
495b5ff1b31Sbellard     switch (offset >> 2) {
496b5ff1b31Sbellard     case 0: /* CP_IDFIELD */
497b5ff1b31Sbellard         return 0x41034003;
498b5ff1b31Sbellard     case 1: /* CP_FLASHPROG */
499b5ff1b31Sbellard         return 0;
500b5ff1b31Sbellard     case 2: /* CP_INTREG */
50183d0cf89SJan Kiszka         return s->intreg_state;
502b5ff1b31Sbellard     case 3: /* CP_DECODE */
503b5ff1b31Sbellard         return 0x11;
504b5ff1b31Sbellard     default:
5052ac71179SPaul Brook         hw_error("icp_control_read: Bad offset %x\n", (int)offset);
506b5ff1b31Sbellard         return 0;
507b5ff1b31Sbellard     }
508b5ff1b31Sbellard }
509b5ff1b31Sbellard 
510a8170e5eSAvi Kivity static void icp_control_write(void *opaque, hwaddr offset,
5110c36493eSBenoît Canet                           uint64_t value, unsigned size)
512b5ff1b31Sbellard {
51383d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
51483d0cf89SJan Kiszka 
515b5ff1b31Sbellard     switch (offset >> 2) {
516b5ff1b31Sbellard     case 2: /* CP_INTREG */
51783d0cf89SJan Kiszka         s->intreg_state &= ~(value & ICP_INTREG_CARDIN);
51883d0cf89SJan Kiszka         qemu_set_irq(s->mmc_irq, !!(s->intreg_state & ICP_INTREG_CARDIN));
51983d0cf89SJan Kiszka         break;
52083d0cf89SJan Kiszka     case 1: /* CP_FLASHPROG */
521b5ff1b31Sbellard     case 3: /* CP_DECODE */
522b5ff1b31Sbellard         /* Nothing interesting implemented yet.  */
523b5ff1b31Sbellard         break;
524b5ff1b31Sbellard     default:
5252ac71179SPaul Brook         hw_error("icp_control_write: Bad offset %x\n", (int)offset);
526b5ff1b31Sbellard     }
527b5ff1b31Sbellard }
5280c36493eSBenoît Canet 
5290c36493eSBenoît Canet static const MemoryRegionOps icp_control_ops = {
5300c36493eSBenoît Canet     .read = icp_control_read,
5310c36493eSBenoît Canet     .write = icp_control_write,
5320c36493eSBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
533b5ff1b31Sbellard };
534b5ff1b31Sbellard 
53583d0cf89SJan Kiszka static void icp_control_mmc_wprot(void *opaque, int line, int level)
53683d0cf89SJan Kiszka {
53783d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
53883d0cf89SJan Kiszka 
53983d0cf89SJan Kiszka     s->intreg_state &= ~ICP_INTREG_WPROT;
54083d0cf89SJan Kiszka     if (level) {
54183d0cf89SJan Kiszka         s->intreg_state |= ICP_INTREG_WPROT;
54283d0cf89SJan Kiszka     }
54383d0cf89SJan Kiszka }
54483d0cf89SJan Kiszka 
54583d0cf89SJan Kiszka static void icp_control_mmc_cardin(void *opaque, int line, int level)
54683d0cf89SJan Kiszka {
54783d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
54883d0cf89SJan Kiszka 
54983d0cf89SJan Kiszka     /* line is released by writing to CP_INTREG */
55083d0cf89SJan Kiszka     if (level) {
55183d0cf89SJan Kiszka         s->intreg_state |= ICP_INTREG_CARDIN;
55283d0cf89SJan Kiszka         qemu_set_irq(s->mmc_irq, 1);
55383d0cf89SJan Kiszka     }
55483d0cf89SJan Kiszka }
55583d0cf89SJan Kiszka 
556ffc8542aSJan Kiszka static void icp_control_init(Object *obj)
557b5ff1b31Sbellard {
558ffc8542aSJan Kiszka     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
559ffc8542aSJan Kiszka     ICPCtrlRegsState *s = ICP_CONTROL_REGS(obj);
56083d0cf89SJan Kiszka     DeviceState *dev = DEVICE(obj);
561b5ff1b31Sbellard 
562ffc8542aSJan Kiszka     memory_region_init_io(&s->iomem, OBJECT(s), &icp_control_ops, s,
563ffc8542aSJan Kiszka                           "icp_ctrl_regs", 0x00800000);
564ffc8542aSJan Kiszka     sysbus_init_mmio(sbd, &s->iomem);
56583d0cf89SJan Kiszka 
56683d0cf89SJan Kiszka     qdev_init_gpio_in_named(dev, icp_control_mmc_wprot, ICP_GPIO_MMC_WPROT, 1);
56783d0cf89SJan Kiszka     qdev_init_gpio_in_named(dev, icp_control_mmc_cardin,
56883d0cf89SJan Kiszka                             ICP_GPIO_MMC_CARDIN, 1);
56983d0cf89SJan Kiszka     sysbus_init_irq(sbd, &s->mmc_irq);
570b5ff1b31Sbellard }
571b5ff1b31Sbellard 
572b5ff1b31Sbellard 
573b5ff1b31Sbellard /* Board init.  */
574b5ff1b31Sbellard 
575f93eb9ffSbalrog static struct arm_boot_info integrator_binfo = {
576f93eb9ffSbalrog     .loader_start = 0x0,
577f93eb9ffSbalrog     .board_id = 0x113,
578f93eb9ffSbalrog };
579f93eb9ffSbalrog 
5803ef96221SMarcel Apfelbaum static void integratorcp_init(MachineState *machine)
581b5ff1b31Sbellard {
5823ef96221SMarcel Apfelbaum     ram_addr_t ram_size = machine->ram_size;
5833ef96221SMarcel Apfelbaum     const char *kernel_filename = machine->kernel_filename;
5843ef96221SMarcel Apfelbaum     const char *kernel_cmdline = machine->kernel_cmdline;
5853ef96221SMarcel Apfelbaum     const char *initrd_filename = machine->initrd_filename;
586223a72f1SGreg Bellows     Object *cpuobj;
587393a9eabSAndreas Färber     ARMCPU *cpu;
588211adf4dSAvi Kivity     MemoryRegion *address_space_mem = get_system_memory();
589211adf4dSAvi Kivity     MemoryRegion *ram = g_new(MemoryRegion, 1);
590211adf4dSAvi Kivity     MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
591a7086888SPaul Brook     qemu_irq pic[32];
59283d0cf89SJan Kiszka     DeviceState *dev, *sic, *icp;
593a7086888SPaul Brook     int i;
594b5ff1b31Sbellard 
595ba1ba5ccSIgor Mammedov     cpuobj = object_new(machine->cpu_type);
596223a72f1SGreg Bellows 
59761e2f352SGreg Bellows     /* By default ARM1176 CPUs have EL3 enabled.  This board does not
59861e2f352SGreg Bellows      * currently support EL3 so the CPU EL3 property is disabled before
59961e2f352SGreg Bellows      * realization.
60061e2f352SGreg Bellows      */
60161e2f352SGreg Bellows     if (object_property_find(cpuobj, "has_el3", NULL)) {
602007b0657SMarkus Armbruster         object_property_set_bool(cpuobj, false, "has_el3", &error_fatal);
60361e2f352SGreg Bellows     }
60461e2f352SGreg Bellows 
605007b0657SMarkus Armbruster     object_property_set_bool(cpuobj, true, "realized", &error_fatal);
606223a72f1SGreg Bellows 
607223a72f1SGreg Bellows     cpu = ARM_CPU(cpuobj);
608223a72f1SGreg Bellows 
609c8623c02SDirk Müller     memory_region_allocate_system_memory(ram, NULL, "integrator.ram",
610c8623c02SDirk Müller                                          ram_size);
611b5ff1b31Sbellard     /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
6121235fc06Sths     /* ??? RAM should repeat to fill physical memory space.  */
613b5ff1b31Sbellard     /* SDRAM at address zero*/
614211adf4dSAvi Kivity     memory_region_add_subregion(address_space_mem, 0, ram);
615b5ff1b31Sbellard     /* And again at address 0x80000000 */
6162c9b15caSPaolo Bonzini     memory_region_init_alias(ram_alias, NULL, "ram.alias", ram, 0, ram_size);
617211adf4dSAvi Kivity     memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
618b5ff1b31Sbellard 
619257ec289SAndreas Färber     dev = qdev_create(NULL, TYPE_INTEGRATOR_CM);
620ee6847d1SGerd Hoffmann     qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
621e23a1b33SMarkus Armbruster     qdev_init_nofail(dev);
622a7086888SPaul Brook     sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
623a7086888SPaul Brook 
62491b64626SAndreas Färber     dev = sysbus_create_varargs(TYPE_INTEGRATOR_PIC, 0x14000000,
62599d228d6SPeter Maydell                                 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ),
62699d228d6SPeter Maydell                                 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ),
62799d228d6SPeter Maydell                                 NULL);
628a7086888SPaul Brook     for (i = 0; i < 32; i++) {
629067a3ddcSPaul Brook         pic[i] = qdev_get_gpio_in(dev, i);
630a7086888SPaul Brook     }
63183d0cf89SJan Kiszka     sic = sysbus_create_simple(TYPE_INTEGRATOR_PIC, 0xca000000, pic[26]);
6326a824ec3SPaul Brook     sysbus_create_varargs("integrator_pit", 0x13000000,
6336a824ec3SPaul Brook                           pic[5], pic[6], pic[7], NULL);
634a63bdb31SPaul Brook     sysbus_create_simple("pl031", 0x15000000, pic[8]);
6359bca0edbSPeter Maydell     pl011_create(0x16000000, pic[1], serial_hd(0));
6369bca0edbSPeter Maydell     pl011_create(0x17000000, pic[2], serial_hd(1));
63783d0cf89SJan Kiszka     icp = sysbus_create_simple(TYPE_ICP_CONTROL_REGS, 0xcb000000,
63883d0cf89SJan Kiszka                                qdev_get_gpio_in(sic, 3));
63986394e96SPaul Brook     sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
64086394e96SPaul Brook     sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]);
641b8616055SAlex Bennée     sysbus_create_simple(TYPE_INTEGRATOR_DEBUG, 0x1a000000, 0);
64283d0cf89SJan Kiszka 
64383d0cf89SJan Kiszka     dev = sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL);
64483d0cf89SJan Kiszka     qdev_connect_gpio_out(dev, 0,
64583d0cf89SJan Kiszka                           qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_WPROT, 0));
64683d0cf89SJan Kiszka     qdev_connect_gpio_out(dev, 1,
64783d0cf89SJan Kiszka                           qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_CARDIN, 0));
64883d0cf89SJan Kiszka 
649a005d073SStefan Hajnoczi     if (nd_table[0].used)
650d537cf6cSpbrook         smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
6512e9bdce5SPaul Brook 
6522e9bdce5SPaul Brook     sysbus_create_simple("pl110", 0xc0000000, pic[22]);
653b5ff1b31Sbellard 
654f93eb9ffSbalrog     integrator_binfo.ram_size = ram_size;
655f93eb9ffSbalrog     integrator_binfo.kernel_filename = kernel_filename;
656f93eb9ffSbalrog     integrator_binfo.kernel_cmdline = kernel_cmdline;
657f93eb9ffSbalrog     integrator_binfo.initrd_filename = initrd_filename;
6583aaa8dfaSAndreas Färber     arm_load_kernel(cpu, &integrator_binfo);
659b5ff1b31Sbellard }
660b5ff1b31Sbellard 
661e264d29dSEduardo Habkost static void integratorcp_machine_init(MachineClass *mc)
662f80f9ec9SAnthony Liguori {
663e264d29dSEduardo Habkost     mc->desc = "ARM Integrator/CP (ARM926EJ-S)";
664e264d29dSEduardo Habkost     mc->init = integratorcp_init;
6654672cbd7SPeter Maydell     mc->ignore_memory_transaction_failures = true;
666ba1ba5ccSIgor Mammedov     mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926");
667f80f9ec9SAnthony Liguori }
668f80f9ec9SAnthony Liguori 
669e264d29dSEduardo Habkost DEFINE_MACHINE("integratorcp", integratorcp_machine_init)
670f80f9ec9SAnthony Liguori 
671999e12bbSAnthony Liguori static Property core_properties[] = {
672257ec289SAndreas Färber     DEFINE_PROP_UINT32("memsz", IntegratorCMState, memsz, 0),
673bb36f66aSGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
674999e12bbSAnthony Liguori };
675999e12bbSAnthony Liguori 
676999e12bbSAnthony Liguori static void core_class_init(ObjectClass *klass, void *data)
677999e12bbSAnthony Liguori {
67839bffca2SAnthony Liguori     DeviceClass *dc = DEVICE_CLASS(klass);
679999e12bbSAnthony Liguori 
68039bffca2SAnthony Liguori     dc->props = core_properties;
681e9d9ee23SJakub Jermar     dc->realize = integratorcm_realize;
68226d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_integratorcm;
68326d32022SPavel Dovgalyuk }
68426d32022SPavel Dovgalyuk 
68526d32022SPavel Dovgalyuk static void icp_pic_class_init(ObjectClass *klass, void *data)
68626d32022SPavel Dovgalyuk {
68726d32022SPavel Dovgalyuk     DeviceClass *dc = DEVICE_CLASS(klass);
68826d32022SPavel Dovgalyuk 
68926d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_icp_pic;
69026d32022SPavel Dovgalyuk }
69126d32022SPavel Dovgalyuk 
69226d32022SPavel Dovgalyuk static void icp_control_class_init(ObjectClass *klass, void *data)
69326d32022SPavel Dovgalyuk {
69426d32022SPavel Dovgalyuk     DeviceClass *dc = DEVICE_CLASS(klass);
69526d32022SPavel Dovgalyuk 
69626d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_icp_control;
697ee6847d1SGerd Hoffmann }
698999e12bbSAnthony Liguori 
6998c43a6f0SAndreas Färber static const TypeInfo core_info = {
700257ec289SAndreas Färber     .name          = TYPE_INTEGRATOR_CM,
70139bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
702257ec289SAndreas Färber     .instance_size = sizeof(IntegratorCMState),
703a1f42e0cSxiaoqiang.zhao     .instance_init = integratorcm_init,
704999e12bbSAnthony Liguori     .class_init    = core_class_init,
705999e12bbSAnthony Liguori };
706999e12bbSAnthony Liguori 
7078c43a6f0SAndreas Färber static const TypeInfo icp_pic_info = {
70891b64626SAndreas Färber     .name          = TYPE_INTEGRATOR_PIC,
70939bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
71039bffca2SAnthony Liguori     .instance_size = sizeof(icp_pic_state),
711a1f42e0cSxiaoqiang.zhao     .instance_init = icp_pic_init,
71226d32022SPavel Dovgalyuk     .class_init    = icp_pic_class_init,
713ee6847d1SGerd Hoffmann };
714ee6847d1SGerd Hoffmann 
715ffc8542aSJan Kiszka static const TypeInfo icp_ctrl_regs_info = {
716ffc8542aSJan Kiszka     .name          = TYPE_ICP_CONTROL_REGS,
717ffc8542aSJan Kiszka     .parent        = TYPE_SYS_BUS_DEVICE,
718ffc8542aSJan Kiszka     .instance_size = sizeof(ICPCtrlRegsState),
719ffc8542aSJan Kiszka     .instance_init = icp_control_init,
72026d32022SPavel Dovgalyuk     .class_init    = icp_control_class_init,
721ffc8542aSJan Kiszka };
722ffc8542aSJan Kiszka 
72383f7d43aSAndreas Färber static void integratorcp_register_types(void)
724a7086888SPaul Brook {
72539bffca2SAnthony Liguori     type_register_static(&icp_pic_info);
72639bffca2SAnthony Liguori     type_register_static(&core_info);
727ffc8542aSJan Kiszka     type_register_static(&icp_ctrl_regs_info);
728a7086888SPaul Brook }
729a7086888SPaul Brook 
73083f7d43aSAndreas Färber type_init(integratorcp_register_types)
731