xref: /qemu/hw/arm/integratorcp.c (revision 26c5b0f4cbe19ad87d3aaba22cd1a8edc25f7ceb)
1b5ff1b31Sbellard /*
2b5ff1b31Sbellard  * ARM Integrator CP System emulation.
3b5ff1b31Sbellard  *
4a1bb27b1Spbrook  * Copyright (c) 2005-2007 CodeSourcery.
5b5ff1b31Sbellard  * Written by Paul Brook
6b5ff1b31Sbellard  *
78e31bf38SMatthew Fernandez  * This code is licensed under the GPL
8b5ff1b31Sbellard  */
9b5ff1b31Sbellard 
1012b16722SPeter Maydell #include "qemu/osdep.h"
11da34e65cSMarkus Armbruster #include "qapi/error.h"
124771d756SPaolo Bonzini #include "cpu.h"
1383c9f4caSPaolo Bonzini #include "hw/sysbus.h"
14d6454270SMarkus Armbruster #include "migration/vmstate.h"
1583c9f4caSPaolo Bonzini #include "hw/boards.h"
1612ec8bd5SPeter Maydell #include "hw/arm/boot.h"
17b8616055SAlex Bennée #include "hw/misc/arm_integrator_debug.h"
18437cc27dSPhilippe Mathieu-Daudé #include "hw/net/smc91c111.h"
191422e32dSPaolo Bonzini #include "net/net.h"
20022c62cbSPaolo Bonzini #include "exec/address-spaces.h"
2154d31236SMarkus Armbruster #include "sysemu/runstate.h"
229c17d615SPaolo Bonzini #include "sysemu/sysemu.h"
239904625fSPhilippe Mathieu-Daudé #include "qemu/log.h"
24223a72f1SGreg Bellows #include "qemu/error-report.h"
25f0d1d2c1Sxiaoqiang zhao #include "hw/char/pl011.h"
26650d103dSMarkus Armbruster #include "hw/hw.h"
2764552b6bSMarkus Armbruster #include "hw/irq.h"
28b5ff1b31Sbellard 
29257ec289SAndreas Färber #define TYPE_INTEGRATOR_CM "integrator_core"
30257ec289SAndreas Färber #define INTEGRATOR_CM(obj) \
31257ec289SAndreas Färber     OBJECT_CHECK(IntegratorCMState, (obj), TYPE_INTEGRATOR_CM)
32257ec289SAndreas Färber 
33257ec289SAndreas Färber typedef struct IntegratorCMState {
34257ec289SAndreas Färber     /*< private >*/
35257ec289SAndreas Färber     SysBusDevice parent_obj;
36257ec289SAndreas Färber     /*< public >*/
37257ec289SAndreas Färber 
3871d9bc50SBenoît Canet     MemoryRegion iomem;
39ee6847d1SGerd Hoffmann     uint32_t memsz;
40211adf4dSAvi Kivity     MemoryRegion flash;
41b5ff1b31Sbellard     uint32_t cm_osc;
42b5ff1b31Sbellard     uint32_t cm_ctrl;
43b5ff1b31Sbellard     uint32_t cm_lock;
44b5ff1b31Sbellard     uint32_t cm_auxosc;
45b5ff1b31Sbellard     uint32_t cm_sdram;
46b5ff1b31Sbellard     uint32_t cm_init;
47b5ff1b31Sbellard     uint32_t cm_flags;
48b5ff1b31Sbellard     uint32_t cm_nvflags;
49f53977f7SJan Petrous     uint32_t cm_refcnt_offset;
50b5ff1b31Sbellard     uint32_t int_level;
51b5ff1b31Sbellard     uint32_t irq_enabled;
52b5ff1b31Sbellard     uint32_t fiq_enabled;
53257ec289SAndreas Färber } IntegratorCMState;
54b5ff1b31Sbellard 
55b5ff1b31Sbellard static uint8_t integrator_spd[128] = {
56b5ff1b31Sbellard    128, 8, 4, 11, 9, 1, 64, 0,  2, 0xa0, 0xa0, 0, 0, 8, 0, 1,
57b5ff1b31Sbellard    0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
58b5ff1b31Sbellard };
59b5ff1b31Sbellard 
6026d32022SPavel Dovgalyuk static const VMStateDescription vmstate_integratorcm = {
6126d32022SPavel Dovgalyuk     .name = "integratorcm",
6226d32022SPavel Dovgalyuk     .version_id = 1,
6326d32022SPavel Dovgalyuk     .minimum_version_id = 1,
6426d32022SPavel Dovgalyuk     .fields      = (VMStateField[]) {
6526d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_osc, IntegratorCMState),
6626d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_ctrl, IntegratorCMState),
6726d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_lock, IntegratorCMState),
6826d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_auxosc, IntegratorCMState),
6926d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_sdram, IntegratorCMState),
7026d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_init, IntegratorCMState),
7126d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_flags, IntegratorCMState),
7226d32022SPavel Dovgalyuk         VMSTATE_UINT32(cm_nvflags, IntegratorCMState),
7326d32022SPavel Dovgalyuk         VMSTATE_UINT32(int_level, IntegratorCMState),
7426d32022SPavel Dovgalyuk         VMSTATE_UINT32(irq_enabled, IntegratorCMState),
7526d32022SPavel Dovgalyuk         VMSTATE_UINT32(fiq_enabled, IntegratorCMState),
7626d32022SPavel Dovgalyuk         VMSTATE_END_OF_LIST()
7726d32022SPavel Dovgalyuk     }
7826d32022SPavel Dovgalyuk };
7926d32022SPavel Dovgalyuk 
80a8170e5eSAvi Kivity static uint64_t integratorcm_read(void *opaque, hwaddr offset,
8171d9bc50SBenoît Canet                                   unsigned size)
82b5ff1b31Sbellard {
83257ec289SAndreas Färber     IntegratorCMState *s = opaque;
84b5ff1b31Sbellard     if (offset >= 0x100 && offset < 0x200) {
85b5ff1b31Sbellard         /* CM_SPD */
86b5ff1b31Sbellard         if (offset >= 0x180)
87b5ff1b31Sbellard             return 0;
88b5ff1b31Sbellard         return integrator_spd[offset >> 2];
89b5ff1b31Sbellard     }
90b5ff1b31Sbellard     switch (offset >> 2) {
91b5ff1b31Sbellard     case 0: /* CM_ID */
92b5ff1b31Sbellard         return 0x411a3001;
93b5ff1b31Sbellard     case 1: /* CM_PROC */
94b5ff1b31Sbellard         return 0;
95b5ff1b31Sbellard     case 2: /* CM_OSC */
96b5ff1b31Sbellard         return s->cm_osc;
97b5ff1b31Sbellard     case 3: /* CM_CTRL */
98b5ff1b31Sbellard         return s->cm_ctrl;
99b5ff1b31Sbellard     case 4: /* CM_STAT */
100b5ff1b31Sbellard         return 0x00100000;
101b5ff1b31Sbellard     case 5: /* CM_LOCK */
102b5ff1b31Sbellard         if (s->cm_lock == 0xa05f) {
103b5ff1b31Sbellard             return 0x1a05f;
104b5ff1b31Sbellard         } else {
105b5ff1b31Sbellard             return s->cm_lock;
106b5ff1b31Sbellard         }
107b5ff1b31Sbellard     case 6: /* CM_LMBUSCNT */
108b5ff1b31Sbellard         /* ??? High frequency timer.  */
1092ac71179SPaul Brook         hw_error("integratorcm_read: CM_LMBUSCNT");
110b5ff1b31Sbellard     case 7: /* CM_AUXOSC */
111b5ff1b31Sbellard         return s->cm_auxosc;
112b5ff1b31Sbellard     case 8: /* CM_SDRAM */
113b5ff1b31Sbellard         return s->cm_sdram;
114b5ff1b31Sbellard     case 9: /* CM_INIT */
115b5ff1b31Sbellard         return s->cm_init;
116f53977f7SJan Petrous     case 10: /* CM_REFCNT */
117f53977f7SJan Petrous         /* This register, CM_REFCNT, provides a 32-bit count value.
118f53977f7SJan Petrous          * The count increments at the fixed reference clock frequency of 24MHz
119f53977f7SJan Petrous          * and can be used as a real-time counter.
120f53977f7SJan Petrous          */
121f53977f7SJan Petrous         return (uint32_t)muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24,
122f53977f7SJan Petrous                                   1000) - s->cm_refcnt_offset;
123b5ff1b31Sbellard     case 12: /* CM_FLAGS */
124b5ff1b31Sbellard         return s->cm_flags;
125b5ff1b31Sbellard     case 14: /* CM_NVFLAGS */
126b5ff1b31Sbellard         return s->cm_nvflags;
127b5ff1b31Sbellard     case 16: /* CM_IRQ_STAT */
128b5ff1b31Sbellard         return s->int_level & s->irq_enabled;
129b5ff1b31Sbellard     case 17: /* CM_IRQ_RSTAT */
130b5ff1b31Sbellard         return s->int_level;
131b5ff1b31Sbellard     case 18: /* CM_IRQ_ENSET */
132b5ff1b31Sbellard         return s->irq_enabled;
133b5ff1b31Sbellard     case 20: /* CM_SOFT_INTSET */
134b5ff1b31Sbellard         return s->int_level & 1;
135b5ff1b31Sbellard     case 24: /* CM_FIQ_STAT */
136b5ff1b31Sbellard         return s->int_level & s->fiq_enabled;
137b5ff1b31Sbellard     case 25: /* CM_FIQ_RSTAT */
138b5ff1b31Sbellard         return s->int_level;
139b5ff1b31Sbellard     case 26: /* CM_FIQ_ENSET */
140b5ff1b31Sbellard         return s->fiq_enabled;
141b5ff1b31Sbellard     case 32: /* CM_VOLTAGE_CTL0 */
142b5ff1b31Sbellard     case 33: /* CM_VOLTAGE_CTL1 */
143b5ff1b31Sbellard     case 34: /* CM_VOLTAGE_CTL2 */
144b5ff1b31Sbellard     case 35: /* CM_VOLTAGE_CTL3 */
145b5ff1b31Sbellard         /* ??? Voltage control unimplemented.  */
146b5ff1b31Sbellard         return 0;
147b5ff1b31Sbellard     default:
1489904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_UNIMP,
1499904625fSPhilippe Mathieu-Daudé                       "%s: Unimplemented offset 0x%" HWADDR_PRIX "\n",
1509904625fSPhilippe Mathieu-Daudé                       __func__, offset);
151b5ff1b31Sbellard         return 0;
152b5ff1b31Sbellard     }
153b5ff1b31Sbellard }
154b5ff1b31Sbellard 
155257ec289SAndreas Färber static void integratorcm_do_remap(IntegratorCMState *s)
156b5ff1b31Sbellard {
157563c2bf3SPeter Maydell     /* Sync memory region state with CM_CTRL REMAP bit:
158563c2bf3SPeter Maydell      * bit 0 => flash at address 0; bit 1 => RAM
159563c2bf3SPeter Maydell      */
160563c2bf3SPeter Maydell     memory_region_set_enabled(&s->flash, !(s->cm_ctrl & 4));
161b5ff1b31Sbellard }
162b5ff1b31Sbellard 
163257ec289SAndreas Färber static void integratorcm_set_ctrl(IntegratorCMState *s, uint32_t value)
164b5ff1b31Sbellard {
165b5ff1b31Sbellard     if (value & 8) {
166cf83f140SEric Blake         qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
167b5ff1b31Sbellard     }
168df3f457bSPeter Maydell     if ((s->cm_ctrl ^ value) & 1) {
169df3f457bSPeter Maydell         /* (value & 1) != 0 means the green "MISC LED" is lit.
170df3f457bSPeter Maydell          * We don't have any nice place to display LEDs. printf is a bad
171df3f457bSPeter Maydell          * idea because Linux uses the LED as a heartbeat and the output
172df3f457bSPeter Maydell          * will swamp anything else on the terminal.
173df3f457bSPeter Maydell          */
174b5ff1b31Sbellard     }
175df3f457bSPeter Maydell     /* Note that the RESET bit [3] always reads as zero */
176df3f457bSPeter Maydell     s->cm_ctrl = (s->cm_ctrl & ~5) | (value & 5);
177563c2bf3SPeter Maydell     integratorcm_do_remap(s);
178b5ff1b31Sbellard }
179b5ff1b31Sbellard 
180257ec289SAndreas Färber static void integratorcm_update(IntegratorCMState *s)
181b5ff1b31Sbellard {
182b5ff1b31Sbellard     /* ??? The CPU irq/fiq is raised when either the core module or base PIC
183b5ff1b31Sbellard        are active.  */
184b5ff1b31Sbellard     if (s->int_level & (s->irq_enabled | s->fiq_enabled))
1852ac71179SPaul Brook         hw_error("Core module interrupt\n");
186b5ff1b31Sbellard }
187b5ff1b31Sbellard 
188a8170e5eSAvi Kivity static void integratorcm_write(void *opaque, hwaddr offset,
18971d9bc50SBenoît Canet                                uint64_t value, unsigned size)
190b5ff1b31Sbellard {
191257ec289SAndreas Färber     IntegratorCMState *s = opaque;
192b5ff1b31Sbellard     switch (offset >> 2) {
193b5ff1b31Sbellard     case 2: /* CM_OSC */
194b5ff1b31Sbellard         if (s->cm_lock == 0xa05f)
195b5ff1b31Sbellard             s->cm_osc = value;
196b5ff1b31Sbellard         break;
197b5ff1b31Sbellard     case 3: /* CM_CTRL */
198b5ff1b31Sbellard         integratorcm_set_ctrl(s, value);
199b5ff1b31Sbellard         break;
200b5ff1b31Sbellard     case 5: /* CM_LOCK */
201b5ff1b31Sbellard         s->cm_lock = value & 0xffff;
202b5ff1b31Sbellard         break;
203b5ff1b31Sbellard     case 7: /* CM_AUXOSC */
204b5ff1b31Sbellard         if (s->cm_lock == 0xa05f)
205b5ff1b31Sbellard             s->cm_auxosc = value;
206b5ff1b31Sbellard         break;
207b5ff1b31Sbellard     case 8: /* CM_SDRAM */
208b5ff1b31Sbellard         s->cm_sdram = value;
209b5ff1b31Sbellard         break;
210b5ff1b31Sbellard     case 9: /* CM_INIT */
211b5ff1b31Sbellard         /* ??? This can change the memory bus frequency.  */
212b5ff1b31Sbellard         s->cm_init = value;
213b5ff1b31Sbellard         break;
214b5ff1b31Sbellard     case 12: /* CM_FLAGSS */
215b5ff1b31Sbellard         s->cm_flags |= value;
216b5ff1b31Sbellard         break;
217b5ff1b31Sbellard     case 13: /* CM_FLAGSC */
218b5ff1b31Sbellard         s->cm_flags &= ~value;
219b5ff1b31Sbellard         break;
220b5ff1b31Sbellard     case 14: /* CM_NVFLAGSS */
221b5ff1b31Sbellard         s->cm_nvflags |= value;
222b5ff1b31Sbellard         break;
223b5ff1b31Sbellard     case 15: /* CM_NVFLAGSS */
224b5ff1b31Sbellard         s->cm_nvflags &= ~value;
225b5ff1b31Sbellard         break;
226b5ff1b31Sbellard     case 18: /* CM_IRQ_ENSET */
227b5ff1b31Sbellard         s->irq_enabled |= value;
228b5ff1b31Sbellard         integratorcm_update(s);
229b5ff1b31Sbellard         break;
230b5ff1b31Sbellard     case 19: /* CM_IRQ_ENCLR */
231b5ff1b31Sbellard         s->irq_enabled &= ~value;
232b5ff1b31Sbellard         integratorcm_update(s);
233b5ff1b31Sbellard         break;
234b5ff1b31Sbellard     case 20: /* CM_SOFT_INTSET */
235b5ff1b31Sbellard         s->int_level |= (value & 1);
236b5ff1b31Sbellard         integratorcm_update(s);
237b5ff1b31Sbellard         break;
238b5ff1b31Sbellard     case 21: /* CM_SOFT_INTCLR */
239b5ff1b31Sbellard         s->int_level &= ~(value & 1);
240b5ff1b31Sbellard         integratorcm_update(s);
241b5ff1b31Sbellard         break;
242b5ff1b31Sbellard     case 26: /* CM_FIQ_ENSET */
243b5ff1b31Sbellard         s->fiq_enabled |= value;
244b5ff1b31Sbellard         integratorcm_update(s);
245b5ff1b31Sbellard         break;
246b5ff1b31Sbellard     case 27: /* CM_FIQ_ENCLR */
247b5ff1b31Sbellard         s->fiq_enabled &= ~value;
248b5ff1b31Sbellard         integratorcm_update(s);
249b5ff1b31Sbellard         break;
250b5ff1b31Sbellard     case 32: /* CM_VOLTAGE_CTL0 */
251b5ff1b31Sbellard     case 33: /* CM_VOLTAGE_CTL1 */
252b5ff1b31Sbellard     case 34: /* CM_VOLTAGE_CTL2 */
253b5ff1b31Sbellard     case 35: /* CM_VOLTAGE_CTL3 */
254b5ff1b31Sbellard         /* ??? Voltage control unimplemented.  */
255b5ff1b31Sbellard         break;
256b5ff1b31Sbellard     default:
2579904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_UNIMP,
2589904625fSPhilippe Mathieu-Daudé                       "%s: Unimplemented offset 0x%" HWADDR_PRIX "\n",
2599904625fSPhilippe Mathieu-Daudé                       __func__, offset);
260b5ff1b31Sbellard         break;
261b5ff1b31Sbellard     }
262b5ff1b31Sbellard }
263b5ff1b31Sbellard 
264b5ff1b31Sbellard /* Integrator/CM control registers.  */
265b5ff1b31Sbellard 
26671d9bc50SBenoît Canet static const MemoryRegionOps integratorcm_ops = {
26771d9bc50SBenoît Canet     .read = integratorcm_read,
26871d9bc50SBenoît Canet     .write = integratorcm_write,
26971d9bc50SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
270b5ff1b31Sbellard };
271b5ff1b31Sbellard 
272a1f42e0cSxiaoqiang.zhao static void integratorcm_init(Object *obj)
273b5ff1b31Sbellard {
274a1f42e0cSxiaoqiang.zhao     IntegratorCMState *s = INTEGRATOR_CM(obj);
275b5ff1b31Sbellard 
276b5ff1b31Sbellard     s->cm_osc = 0x01000048;
277b5ff1b31Sbellard     /* ??? What should the high bits of this value be?  */
278b5ff1b31Sbellard     s->cm_auxosc = 0x0007feff;
279b5ff1b31Sbellard     s->cm_sdram = 0x00011122;
280e9d9ee23SJakub Jermar     memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
281e9d9ee23SJakub Jermar     s->cm_init = 0x00000112;
282e9d9ee23SJakub Jermar     s->cm_refcnt_offset = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24,
283e9d9ee23SJakub Jermar                                    1000);
284e9d9ee23SJakub Jermar 
285e9d9ee23SJakub Jermar     /* ??? Save/restore.  */
286e9d9ee23SJakub Jermar }
287e9d9ee23SJakub Jermar 
288e9d9ee23SJakub Jermar static void integratorcm_realize(DeviceState *d, Error **errp)
289e9d9ee23SJakub Jermar {
290e9d9ee23SJakub Jermar     IntegratorCMState *s = INTEGRATOR_CM(d);
2918720daadSThomas Huth     SysBusDevice *dev = SYS_BUS_DEVICE(d);
2928720daadSThomas Huth     Error *local_err = NULL;
2938720daadSThomas Huth 
2948720daadSThomas Huth     memory_region_init_ram(&s->flash, OBJECT(d), "integrator.flash", 0x100000,
2958720daadSThomas Huth                            &local_err);
2968720daadSThomas Huth     if (local_err) {
2978720daadSThomas Huth         error_propagate(errp, local_err);
2988720daadSThomas Huth         return;
2998720daadSThomas Huth     }
3008720daadSThomas Huth 
3018720daadSThomas Huth     memory_region_init_io(&s->iomem, OBJECT(d), &integratorcm_ops, s,
3028720daadSThomas Huth                           "integratorcm", 0x00800000);
3038720daadSThomas Huth     sysbus_init_mmio(dev, &s->iomem);
3048720daadSThomas Huth 
3058720daadSThomas Huth     integratorcm_do_remap(s);
306e9d9ee23SJakub Jermar 
307ee6847d1SGerd Hoffmann     if (s->memsz >= 256) {
308b5ff1b31Sbellard         integrator_spd[31] = 64;
309b5ff1b31Sbellard         s->cm_sdram |= 0x10;
310ee6847d1SGerd Hoffmann     } else if (s->memsz >= 128) {
311b5ff1b31Sbellard         integrator_spd[31] = 32;
312b5ff1b31Sbellard         s->cm_sdram |= 0x0c;
313ee6847d1SGerd Hoffmann     } else if (s->memsz >= 64) {
314b5ff1b31Sbellard         integrator_spd[31] = 16;
315b5ff1b31Sbellard         s->cm_sdram |= 0x08;
316ee6847d1SGerd Hoffmann     } else if (s->memsz >= 32) {
317b5ff1b31Sbellard         integrator_spd[31] = 4;
318b5ff1b31Sbellard         s->cm_sdram |= 0x04;
319b5ff1b31Sbellard     } else {
320b5ff1b31Sbellard         integrator_spd[31] = 2;
321b5ff1b31Sbellard     }
322b5ff1b31Sbellard }
323b5ff1b31Sbellard 
324b5ff1b31Sbellard /* Integrator/CP hardware emulation.  */
325b5ff1b31Sbellard /* Primary interrupt controller.  */
326b5ff1b31Sbellard 
32791b64626SAndreas Färber #define TYPE_INTEGRATOR_PIC "integrator_pic"
32891b64626SAndreas Färber #define INTEGRATOR_PIC(obj) \
32991b64626SAndreas Färber    OBJECT_CHECK(icp_pic_state, (obj), TYPE_INTEGRATOR_PIC)
33091b64626SAndreas Färber 
33191b64626SAndreas Färber typedef struct icp_pic_state {
33291b64626SAndreas Färber     /*< private >*/
33391b64626SAndreas Färber     SysBusDevice parent_obj;
33491b64626SAndreas Färber     /*< public >*/
33591b64626SAndreas Färber 
33661074e46SBenoît Canet     MemoryRegion iomem;
337b5ff1b31Sbellard     uint32_t level;
338b5ff1b31Sbellard     uint32_t irq_enabled;
339b5ff1b31Sbellard     uint32_t fiq_enabled;
340d537cf6cSpbrook     qemu_irq parent_irq;
341d537cf6cSpbrook     qemu_irq parent_fiq;
342b5ff1b31Sbellard } icp_pic_state;
343b5ff1b31Sbellard 
34426d32022SPavel Dovgalyuk static const VMStateDescription vmstate_icp_pic = {
34526d32022SPavel Dovgalyuk     .name = "icp_pic",
34626d32022SPavel Dovgalyuk     .version_id = 1,
34726d32022SPavel Dovgalyuk     .minimum_version_id = 1,
34826d32022SPavel Dovgalyuk     .fields      = (VMStateField[]) {
34926d32022SPavel Dovgalyuk         VMSTATE_UINT32(level, icp_pic_state),
35026d32022SPavel Dovgalyuk         VMSTATE_UINT32(irq_enabled, icp_pic_state),
35126d32022SPavel Dovgalyuk         VMSTATE_UINT32(fiq_enabled, icp_pic_state),
35226d32022SPavel Dovgalyuk         VMSTATE_END_OF_LIST()
35326d32022SPavel Dovgalyuk     }
35426d32022SPavel Dovgalyuk };
35526d32022SPavel Dovgalyuk 
356b5ff1b31Sbellard static void icp_pic_update(icp_pic_state *s)
357b5ff1b31Sbellard {
358b5ff1b31Sbellard     uint32_t flags;
359b5ff1b31Sbellard 
360b5ff1b31Sbellard     flags = (s->level & s->irq_enabled);
361d537cf6cSpbrook     qemu_set_irq(s->parent_irq, flags != 0);
362cdbdb648Spbrook     flags = (s->level & s->fiq_enabled);
363d537cf6cSpbrook     qemu_set_irq(s->parent_fiq, flags != 0);
364b5ff1b31Sbellard }
365b5ff1b31Sbellard 
366cdbdb648Spbrook static void icp_pic_set_irq(void *opaque, int irq, int level)
367b5ff1b31Sbellard {
36880337b66Sbellard     icp_pic_state *s = (icp_pic_state *)opaque;
369b5ff1b31Sbellard     if (level)
37080337b66Sbellard         s->level |= 1 << irq;
371b5ff1b31Sbellard     else
37280337b66Sbellard         s->level &= ~(1 << irq);
373b5ff1b31Sbellard     icp_pic_update(s);
374b5ff1b31Sbellard }
375b5ff1b31Sbellard 
376a8170e5eSAvi Kivity static uint64_t icp_pic_read(void *opaque, hwaddr offset,
37761074e46SBenoît Canet                              unsigned size)
378b5ff1b31Sbellard {
379b5ff1b31Sbellard     icp_pic_state *s = (icp_pic_state *)opaque;
380b5ff1b31Sbellard 
381b5ff1b31Sbellard     switch (offset >> 2) {
382b5ff1b31Sbellard     case 0: /* IRQ_STATUS */
383b5ff1b31Sbellard         return s->level & s->irq_enabled;
384b5ff1b31Sbellard     case 1: /* IRQ_RAWSTAT */
385b5ff1b31Sbellard         return s->level;
386b5ff1b31Sbellard     case 2: /* IRQ_ENABLESET */
387b5ff1b31Sbellard         return s->irq_enabled;
388b5ff1b31Sbellard     case 4: /* INT_SOFTSET */
389b5ff1b31Sbellard         return s->level & 1;
390b5ff1b31Sbellard     case 8: /* FRQ_STATUS */
391b5ff1b31Sbellard         return s->level & s->fiq_enabled;
392b5ff1b31Sbellard     case 9: /* FRQ_RAWSTAT */
393b5ff1b31Sbellard         return s->level;
394b5ff1b31Sbellard     case 10: /* FRQ_ENABLESET */
395b5ff1b31Sbellard         return s->fiq_enabled;
396b5ff1b31Sbellard     case 3: /* IRQ_ENABLECLR */
397b5ff1b31Sbellard     case 5: /* INT_SOFTCLR */
398b5ff1b31Sbellard     case 11: /* FRQ_ENABLECLR */
399b5ff1b31Sbellard     default:
4009904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
4019904625fSPhilippe Mathieu-Daudé                       __func__, offset);
402b5ff1b31Sbellard         return 0;
403b5ff1b31Sbellard     }
404b5ff1b31Sbellard }
405b5ff1b31Sbellard 
406a8170e5eSAvi Kivity static void icp_pic_write(void *opaque, hwaddr offset,
40761074e46SBenoît Canet                           uint64_t value, unsigned size)
408b5ff1b31Sbellard {
409b5ff1b31Sbellard     icp_pic_state *s = (icp_pic_state *)opaque;
410b5ff1b31Sbellard 
411b5ff1b31Sbellard     switch (offset >> 2) {
412b5ff1b31Sbellard     case 2: /* IRQ_ENABLESET */
413b5ff1b31Sbellard         s->irq_enabled |= value;
414b5ff1b31Sbellard         break;
415b5ff1b31Sbellard     case 3: /* IRQ_ENABLECLR */
416b5ff1b31Sbellard         s->irq_enabled &= ~value;
417b5ff1b31Sbellard         break;
418b5ff1b31Sbellard     case 4: /* INT_SOFTSET */
419b5ff1b31Sbellard         if (value & 1)
420d537cf6cSpbrook             icp_pic_set_irq(s, 0, 1);
421b5ff1b31Sbellard         break;
422b5ff1b31Sbellard     case 5: /* INT_SOFTCLR */
423b5ff1b31Sbellard         if (value & 1)
424d537cf6cSpbrook             icp_pic_set_irq(s, 0, 0);
425b5ff1b31Sbellard         break;
426b5ff1b31Sbellard     case 10: /* FRQ_ENABLESET */
427b5ff1b31Sbellard         s->fiq_enabled |= value;
428b5ff1b31Sbellard         break;
429b5ff1b31Sbellard     case 11: /* FRQ_ENABLECLR */
430b5ff1b31Sbellard         s->fiq_enabled &= ~value;
431b5ff1b31Sbellard         break;
432b5ff1b31Sbellard     case 0: /* IRQ_STATUS */
433b5ff1b31Sbellard     case 1: /* IRQ_RAWSTAT */
434b5ff1b31Sbellard     case 8: /* FRQ_STATUS */
435b5ff1b31Sbellard     case 9: /* FRQ_RAWSTAT */
436b5ff1b31Sbellard     default:
4379904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
4389904625fSPhilippe Mathieu-Daudé                       __func__, offset);
439b5ff1b31Sbellard         return;
440b5ff1b31Sbellard     }
441b5ff1b31Sbellard     icp_pic_update(s);
442b5ff1b31Sbellard }
443b5ff1b31Sbellard 
44461074e46SBenoît Canet static const MemoryRegionOps icp_pic_ops = {
44561074e46SBenoît Canet     .read = icp_pic_read,
44661074e46SBenoît Canet     .write = icp_pic_write,
44761074e46SBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
448b5ff1b31Sbellard };
449b5ff1b31Sbellard 
450a1f42e0cSxiaoqiang.zhao static void icp_pic_init(Object *obj)
451b5ff1b31Sbellard {
452a1f42e0cSxiaoqiang.zhao     DeviceState *dev = DEVICE(obj);
453a1f42e0cSxiaoqiang.zhao     icp_pic_state *s = INTEGRATOR_PIC(obj);
454a1f42e0cSxiaoqiang.zhao     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
455b5ff1b31Sbellard 
45691b64626SAndreas Färber     qdev_init_gpio_in(dev, icp_pic_set_irq, 32);
45791b64626SAndreas Färber     sysbus_init_irq(sbd, &s->parent_irq);
45891b64626SAndreas Färber     sysbus_init_irq(sbd, &s->parent_fiq);
459a1f42e0cSxiaoqiang.zhao     memory_region_init_io(&s->iomem, obj, &icp_pic_ops, s,
46064bde0f3SPaolo Bonzini                           "icp-pic", 0x00800000);
46191b64626SAndreas Färber     sysbus_init_mmio(sbd, &s->iomem);
462b5ff1b31Sbellard }
463b5ff1b31Sbellard 
464b5ff1b31Sbellard /* CP control registers.  */
4650c36493eSBenoît Canet 
466ffc8542aSJan Kiszka #define TYPE_ICP_CONTROL_REGS "icp-ctrl-regs"
467ffc8542aSJan Kiszka #define ICP_CONTROL_REGS(obj) \
468ffc8542aSJan Kiszka     OBJECT_CHECK(ICPCtrlRegsState, (obj), TYPE_ICP_CONTROL_REGS)
469ffc8542aSJan Kiszka 
470ffc8542aSJan Kiszka typedef struct ICPCtrlRegsState {
471ffc8542aSJan Kiszka     /*< private >*/
472ffc8542aSJan Kiszka     SysBusDevice parent_obj;
473ffc8542aSJan Kiszka     /*< public >*/
474ffc8542aSJan Kiszka 
475ffc8542aSJan Kiszka     MemoryRegion iomem;
47683d0cf89SJan Kiszka 
47783d0cf89SJan Kiszka     qemu_irq mmc_irq;
47883d0cf89SJan Kiszka     uint32_t intreg_state;
479ffc8542aSJan Kiszka } ICPCtrlRegsState;
480ffc8542aSJan Kiszka 
48183d0cf89SJan Kiszka #define ICP_GPIO_MMC_WPROT      "mmc-wprot"
48283d0cf89SJan Kiszka #define ICP_GPIO_MMC_CARDIN     "mmc-cardin"
48383d0cf89SJan Kiszka 
48483d0cf89SJan Kiszka #define ICP_INTREG_WPROT        (1 << 0)
48583d0cf89SJan Kiszka #define ICP_INTREG_CARDIN       (1 << 3)
48683d0cf89SJan Kiszka 
48726d32022SPavel Dovgalyuk static const VMStateDescription vmstate_icp_control = {
48826d32022SPavel Dovgalyuk     .name = "icp_control",
48926d32022SPavel Dovgalyuk     .version_id = 1,
49026d32022SPavel Dovgalyuk     .minimum_version_id = 1,
49126d32022SPavel Dovgalyuk     .fields      = (VMStateField[]) {
49226d32022SPavel Dovgalyuk         VMSTATE_UINT32(intreg_state, ICPCtrlRegsState),
49326d32022SPavel Dovgalyuk         VMSTATE_END_OF_LIST()
49426d32022SPavel Dovgalyuk     }
49526d32022SPavel Dovgalyuk };
49626d32022SPavel Dovgalyuk 
497a8170e5eSAvi Kivity static uint64_t icp_control_read(void *opaque, hwaddr offset,
4980c36493eSBenoît Canet                                  unsigned size)
499b5ff1b31Sbellard {
50083d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
50183d0cf89SJan Kiszka 
502b5ff1b31Sbellard     switch (offset >> 2) {
503b5ff1b31Sbellard     case 0: /* CP_IDFIELD */
504b5ff1b31Sbellard         return 0x41034003;
505b5ff1b31Sbellard     case 1: /* CP_FLASHPROG */
506b5ff1b31Sbellard         return 0;
507b5ff1b31Sbellard     case 2: /* CP_INTREG */
50883d0cf89SJan Kiszka         return s->intreg_state;
509b5ff1b31Sbellard     case 3: /* CP_DECODE */
510b5ff1b31Sbellard         return 0x11;
511b5ff1b31Sbellard     default:
5129904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
5139904625fSPhilippe Mathieu-Daudé                       __func__, offset);
514b5ff1b31Sbellard         return 0;
515b5ff1b31Sbellard     }
516b5ff1b31Sbellard }
517b5ff1b31Sbellard 
518a8170e5eSAvi Kivity static void icp_control_write(void *opaque, hwaddr offset,
5190c36493eSBenoît Canet                           uint64_t value, unsigned size)
520b5ff1b31Sbellard {
52183d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
52283d0cf89SJan Kiszka 
523b5ff1b31Sbellard     switch (offset >> 2) {
524b5ff1b31Sbellard     case 2: /* CP_INTREG */
52583d0cf89SJan Kiszka         s->intreg_state &= ~(value & ICP_INTREG_CARDIN);
52683d0cf89SJan Kiszka         qemu_set_irq(s->mmc_irq, !!(s->intreg_state & ICP_INTREG_CARDIN));
52783d0cf89SJan Kiszka         break;
52883d0cf89SJan Kiszka     case 1: /* CP_FLASHPROG */
529b5ff1b31Sbellard     case 3: /* CP_DECODE */
530b5ff1b31Sbellard         /* Nothing interesting implemented yet.  */
531b5ff1b31Sbellard         break;
532b5ff1b31Sbellard     default:
5339904625fSPhilippe Mathieu-Daudé         qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIX "\n",
5349904625fSPhilippe Mathieu-Daudé                       __func__, offset);
535b5ff1b31Sbellard     }
536b5ff1b31Sbellard }
5370c36493eSBenoît Canet 
5380c36493eSBenoît Canet static const MemoryRegionOps icp_control_ops = {
5390c36493eSBenoît Canet     .read = icp_control_read,
5400c36493eSBenoît Canet     .write = icp_control_write,
5410c36493eSBenoît Canet     .endianness = DEVICE_NATIVE_ENDIAN,
542b5ff1b31Sbellard };
543b5ff1b31Sbellard 
54483d0cf89SJan Kiszka static void icp_control_mmc_wprot(void *opaque, int line, int level)
54583d0cf89SJan Kiszka {
54683d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
54783d0cf89SJan Kiszka 
54883d0cf89SJan Kiszka     s->intreg_state &= ~ICP_INTREG_WPROT;
54983d0cf89SJan Kiszka     if (level) {
55083d0cf89SJan Kiszka         s->intreg_state |= ICP_INTREG_WPROT;
55183d0cf89SJan Kiszka     }
55283d0cf89SJan Kiszka }
55383d0cf89SJan Kiszka 
55483d0cf89SJan Kiszka static void icp_control_mmc_cardin(void *opaque, int line, int level)
55583d0cf89SJan Kiszka {
55683d0cf89SJan Kiszka     ICPCtrlRegsState *s = opaque;
55783d0cf89SJan Kiszka 
55883d0cf89SJan Kiszka     /* line is released by writing to CP_INTREG */
55983d0cf89SJan Kiszka     if (level) {
56083d0cf89SJan Kiszka         s->intreg_state |= ICP_INTREG_CARDIN;
56183d0cf89SJan Kiszka         qemu_set_irq(s->mmc_irq, 1);
56283d0cf89SJan Kiszka     }
56383d0cf89SJan Kiszka }
56483d0cf89SJan Kiszka 
565ffc8542aSJan Kiszka static void icp_control_init(Object *obj)
566b5ff1b31Sbellard {
567ffc8542aSJan Kiszka     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
568ffc8542aSJan Kiszka     ICPCtrlRegsState *s = ICP_CONTROL_REGS(obj);
56983d0cf89SJan Kiszka     DeviceState *dev = DEVICE(obj);
570b5ff1b31Sbellard 
571ffc8542aSJan Kiszka     memory_region_init_io(&s->iomem, OBJECT(s), &icp_control_ops, s,
572ffc8542aSJan Kiszka                           "icp_ctrl_regs", 0x00800000);
573ffc8542aSJan Kiszka     sysbus_init_mmio(sbd, &s->iomem);
57483d0cf89SJan Kiszka 
57583d0cf89SJan Kiszka     qdev_init_gpio_in_named(dev, icp_control_mmc_wprot, ICP_GPIO_MMC_WPROT, 1);
57683d0cf89SJan Kiszka     qdev_init_gpio_in_named(dev, icp_control_mmc_cardin,
57783d0cf89SJan Kiszka                             ICP_GPIO_MMC_CARDIN, 1);
57883d0cf89SJan Kiszka     sysbus_init_irq(sbd, &s->mmc_irq);
579b5ff1b31Sbellard }
580b5ff1b31Sbellard 
581b5ff1b31Sbellard 
582b5ff1b31Sbellard /* Board init.  */
583b5ff1b31Sbellard 
584f93eb9ffSbalrog static struct arm_boot_info integrator_binfo = {
585f93eb9ffSbalrog     .loader_start = 0x0,
586f93eb9ffSbalrog     .board_id = 0x113,
587f93eb9ffSbalrog };
588f93eb9ffSbalrog 
5893ef96221SMarcel Apfelbaum static void integratorcp_init(MachineState *machine)
590b5ff1b31Sbellard {
5913ef96221SMarcel Apfelbaum     ram_addr_t ram_size = machine->ram_size;
592223a72f1SGreg Bellows     Object *cpuobj;
593393a9eabSAndreas Färber     ARMCPU *cpu;
594211adf4dSAvi Kivity     MemoryRegion *address_space_mem = get_system_memory();
595211adf4dSAvi Kivity     MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
596a7086888SPaul Brook     qemu_irq pic[32];
59783d0cf89SJan Kiszka     DeviceState *dev, *sic, *icp;
598a7086888SPaul Brook     int i;
599b5ff1b31Sbellard 
600ba1ba5ccSIgor Mammedov     cpuobj = object_new(machine->cpu_type);
601223a72f1SGreg Bellows 
60261e2f352SGreg Bellows     /* By default ARM1176 CPUs have EL3 enabled.  This board does not
60361e2f352SGreg Bellows      * currently support EL3 so the CPU EL3 property is disabled before
60461e2f352SGreg Bellows      * realization.
60561e2f352SGreg Bellows      */
60661e2f352SGreg Bellows     if (object_property_find(cpuobj, "has_el3", NULL)) {
6075325cc34SMarkus Armbruster         object_property_set_bool(cpuobj, "has_el3", false, &error_fatal);
60861e2f352SGreg Bellows     }
60961e2f352SGreg Bellows 
610ce189ab2SMarkus Armbruster     qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
611223a72f1SGreg Bellows 
612223a72f1SGreg Bellows     cpu = ARM_CPU(cpuobj);
613223a72f1SGreg Bellows 
614b5ff1b31Sbellard     /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
6151235fc06Sths     /* ??? RAM should repeat to fill physical memory space.  */
616b5ff1b31Sbellard     /* SDRAM at address zero*/
6173f25b3f4SIgor Mammedov     memory_region_add_subregion(address_space_mem, 0, machine->ram);
618b5ff1b31Sbellard     /* And again at address 0x80000000 */
6193f25b3f4SIgor Mammedov     memory_region_init_alias(ram_alias, NULL, "ram.alias", machine->ram,
6203f25b3f4SIgor Mammedov                              0, ram_size);
621211adf4dSAvi Kivity     memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
622b5ff1b31Sbellard 
6233e80f690SMarkus Armbruster     dev = qdev_new(TYPE_INTEGRATOR_CM);
624ee6847d1SGerd Hoffmann     qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
6253c6ef471SMarkus Armbruster     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
626a7086888SPaul Brook     sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
627a7086888SPaul Brook 
62891b64626SAndreas Färber     dev = sysbus_create_varargs(TYPE_INTEGRATOR_PIC, 0x14000000,
62999d228d6SPeter Maydell                                 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ),
63099d228d6SPeter Maydell                                 qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ),
63199d228d6SPeter Maydell                                 NULL);
632a7086888SPaul Brook     for (i = 0; i < 32; i++) {
633067a3ddcSPaul Brook         pic[i] = qdev_get_gpio_in(dev, i);
634a7086888SPaul Brook     }
63583d0cf89SJan Kiszka     sic = sysbus_create_simple(TYPE_INTEGRATOR_PIC, 0xca000000, pic[26]);
6366a824ec3SPaul Brook     sysbus_create_varargs("integrator_pit", 0x13000000,
6376a824ec3SPaul Brook                           pic[5], pic[6], pic[7], NULL);
638a63bdb31SPaul Brook     sysbus_create_simple("pl031", 0x15000000, pic[8]);
6399bca0edbSPeter Maydell     pl011_create(0x16000000, pic[1], serial_hd(0));
6409bca0edbSPeter Maydell     pl011_create(0x17000000, pic[2], serial_hd(1));
64183d0cf89SJan Kiszka     icp = sysbus_create_simple(TYPE_ICP_CONTROL_REGS, 0xcb000000,
64283d0cf89SJan Kiszka                                qdev_get_gpio_in(sic, 3));
64386394e96SPaul Brook     sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
64486394e96SPaul Brook     sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]);
645b8616055SAlex Bennée     sysbus_create_simple(TYPE_INTEGRATOR_DEBUG, 0x1a000000, 0);
64683d0cf89SJan Kiszka 
64783d0cf89SJan Kiszka     dev = sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL);
648*26c5b0f4SPhilippe Mathieu-Daudé     qdev_connect_gpio_out_named(dev, "card-read-only", 0,
64983d0cf89SJan Kiszka                           qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_WPROT, 0));
650*26c5b0f4SPhilippe Mathieu-Daudé     qdev_connect_gpio_out_named(dev, "card-inserted", 0,
65183d0cf89SJan Kiszka                           qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_CARDIN, 0));
6525df2cfbcSPhilippe Mathieu-Daudé     sysbus_create_varargs("pl041", 0x1d000000, pic[25], NULL);
65383d0cf89SJan Kiszka 
654a005d073SStefan Hajnoczi     if (nd_table[0].used)
655d537cf6cSpbrook         smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
6562e9bdce5SPaul Brook 
6572e9bdce5SPaul Brook     sysbus_create_simple("pl110", 0xc0000000, pic[22]);
658b5ff1b31Sbellard 
659f93eb9ffSbalrog     integrator_binfo.ram_size = ram_size;
6602744ece8STao Xu     arm_load_kernel(cpu, machine, &integrator_binfo);
661b5ff1b31Sbellard }
662b5ff1b31Sbellard 
663e264d29dSEduardo Habkost static void integratorcp_machine_init(MachineClass *mc)
664f80f9ec9SAnthony Liguori {
665e264d29dSEduardo Habkost     mc->desc = "ARM Integrator/CP (ARM926EJ-S)";
666e264d29dSEduardo Habkost     mc->init = integratorcp_init;
6674672cbd7SPeter Maydell     mc->ignore_memory_transaction_failures = true;
668ba1ba5ccSIgor Mammedov     mc->default_cpu_type = ARM_CPU_TYPE_NAME("arm926");
6693f25b3f4SIgor Mammedov     mc->default_ram_id = "integrator.ram";
670f80f9ec9SAnthony Liguori }
671f80f9ec9SAnthony Liguori 
672e264d29dSEduardo Habkost DEFINE_MACHINE("integratorcp", integratorcp_machine_init)
673f80f9ec9SAnthony Liguori 
674999e12bbSAnthony Liguori static Property core_properties[] = {
675257ec289SAndreas Färber     DEFINE_PROP_UINT32("memsz", IntegratorCMState, memsz, 0),
676bb36f66aSGerd Hoffmann     DEFINE_PROP_END_OF_LIST(),
677999e12bbSAnthony Liguori };
678999e12bbSAnthony Liguori 
679999e12bbSAnthony Liguori static void core_class_init(ObjectClass *klass, void *data)
680999e12bbSAnthony Liguori {
68139bffca2SAnthony Liguori     DeviceClass *dc = DEVICE_CLASS(klass);
682999e12bbSAnthony Liguori 
6834f67d30bSMarc-André Lureau     device_class_set_props(dc, core_properties);
684e9d9ee23SJakub Jermar     dc->realize = integratorcm_realize;
68526d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_integratorcm;
68626d32022SPavel Dovgalyuk }
68726d32022SPavel Dovgalyuk 
68826d32022SPavel Dovgalyuk static void icp_pic_class_init(ObjectClass *klass, void *data)
68926d32022SPavel Dovgalyuk {
69026d32022SPavel Dovgalyuk     DeviceClass *dc = DEVICE_CLASS(klass);
69126d32022SPavel Dovgalyuk 
69226d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_icp_pic;
69326d32022SPavel Dovgalyuk }
69426d32022SPavel Dovgalyuk 
69526d32022SPavel Dovgalyuk static void icp_control_class_init(ObjectClass *klass, void *data)
69626d32022SPavel Dovgalyuk {
69726d32022SPavel Dovgalyuk     DeviceClass *dc = DEVICE_CLASS(klass);
69826d32022SPavel Dovgalyuk 
69926d32022SPavel Dovgalyuk     dc->vmsd = &vmstate_icp_control;
700ee6847d1SGerd Hoffmann }
701999e12bbSAnthony Liguori 
7028c43a6f0SAndreas Färber static const TypeInfo core_info = {
703257ec289SAndreas Färber     .name          = TYPE_INTEGRATOR_CM,
70439bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
705257ec289SAndreas Färber     .instance_size = sizeof(IntegratorCMState),
706a1f42e0cSxiaoqiang.zhao     .instance_init = integratorcm_init,
707999e12bbSAnthony Liguori     .class_init    = core_class_init,
708999e12bbSAnthony Liguori };
709999e12bbSAnthony Liguori 
7108c43a6f0SAndreas Färber static const TypeInfo icp_pic_info = {
71191b64626SAndreas Färber     .name          = TYPE_INTEGRATOR_PIC,
71239bffca2SAnthony Liguori     .parent        = TYPE_SYS_BUS_DEVICE,
71339bffca2SAnthony Liguori     .instance_size = sizeof(icp_pic_state),
714a1f42e0cSxiaoqiang.zhao     .instance_init = icp_pic_init,
71526d32022SPavel Dovgalyuk     .class_init    = icp_pic_class_init,
716ee6847d1SGerd Hoffmann };
717ee6847d1SGerd Hoffmann 
718ffc8542aSJan Kiszka static const TypeInfo icp_ctrl_regs_info = {
719ffc8542aSJan Kiszka     .name          = TYPE_ICP_CONTROL_REGS,
720ffc8542aSJan Kiszka     .parent        = TYPE_SYS_BUS_DEVICE,
721ffc8542aSJan Kiszka     .instance_size = sizeof(ICPCtrlRegsState),
722ffc8542aSJan Kiszka     .instance_init = icp_control_init,
72326d32022SPavel Dovgalyuk     .class_init    = icp_control_class_init,
724ffc8542aSJan Kiszka };
725ffc8542aSJan Kiszka 
72683f7d43aSAndreas Färber static void integratorcp_register_types(void)
727a7086888SPaul Brook {
72839bffca2SAnthony Liguori     type_register_static(&icp_pic_info);
72939bffca2SAnthony Liguori     type_register_static(&core_info);
730ffc8542aSJan Kiszka     type_register_static(&icp_ctrl_regs_info);
731a7086888SPaul Brook }
732a7086888SPaul Brook 
73383f7d43aSAndreas Färber type_init(integratorcp_register_types)
734