Statistics
| Branch: | Revision:

root / hw / arm / integratorcp.c @ 9188dbf7

History | View | Annotate | Download (16.3 kB)

1 5fafdf24 ths
/*
2 b5ff1b31 bellard
 * ARM Integrator CP System emulation.
3 b5ff1b31 bellard
 *
4 a1bb27b1 pbrook
 * Copyright (c) 2005-2007 CodeSourcery.
5 b5ff1b31 bellard
 * Written by Paul Brook
6 b5ff1b31 bellard
 *
7 8e31bf38 Matthew Fernandez
 * This code is licensed under the GPL
8 b5ff1b31 bellard
 */
9 b5ff1b31 bellard
10 83c9f4ca Paolo Bonzini
#include "hw/sysbus.h"
11 bd2be150 Peter Maydell
#include "hw/devices.h"
12 83c9f4ca Paolo Bonzini
#include "hw/boards.h"
13 bd2be150 Peter Maydell
#include "hw/arm/arm.h"
14 1422e32d Paolo Bonzini
#include "net/net.h"
15 022c62cb Paolo Bonzini
#include "exec/address-spaces.h"
16 9c17d615 Paolo Bonzini
#include "sysemu/sysemu.h"
17 b5ff1b31 bellard
18 257ec289 Andreas Färber
#define TYPE_INTEGRATOR_CM "integrator_core"
19 257ec289 Andreas Färber
#define INTEGRATOR_CM(obj) \
20 257ec289 Andreas Färber
    OBJECT_CHECK(IntegratorCMState, (obj), TYPE_INTEGRATOR_CM)
21 257ec289 Andreas Färber
22 257ec289 Andreas Färber
typedef struct IntegratorCMState {
23 257ec289 Andreas Färber
    /*< private >*/
24 257ec289 Andreas Färber
    SysBusDevice parent_obj;
25 257ec289 Andreas Färber
    /*< public >*/
26 257ec289 Andreas Färber
27 71d9bc50 Benoît Canet
    MemoryRegion iomem;
28 ee6847d1 Gerd Hoffmann
    uint32_t memsz;
29 211adf4d Avi Kivity
    MemoryRegion flash;
30 b5ff1b31 bellard
    uint32_t cm_osc;
31 b5ff1b31 bellard
    uint32_t cm_ctrl;
32 b5ff1b31 bellard
    uint32_t cm_lock;
33 b5ff1b31 bellard
    uint32_t cm_auxosc;
34 b5ff1b31 bellard
    uint32_t cm_sdram;
35 b5ff1b31 bellard
    uint32_t cm_init;
36 b5ff1b31 bellard
    uint32_t cm_flags;
37 b5ff1b31 bellard
    uint32_t cm_nvflags;
38 b5ff1b31 bellard
    uint32_t int_level;
39 b5ff1b31 bellard
    uint32_t irq_enabled;
40 b5ff1b31 bellard
    uint32_t fiq_enabled;
41 257ec289 Andreas Färber
} IntegratorCMState;
42 b5ff1b31 bellard
43 b5ff1b31 bellard
static uint8_t integrator_spd[128] = {
44 b5ff1b31 bellard
   128, 8, 4, 11, 9, 1, 64, 0,  2, 0xa0, 0xa0, 0, 0, 8, 0, 1,
45 b5ff1b31 bellard
   0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
46 b5ff1b31 bellard
};
47 b5ff1b31 bellard
48 a8170e5e Avi Kivity
static uint64_t integratorcm_read(void *opaque, hwaddr offset,
49 71d9bc50 Benoît Canet
                                  unsigned size)
50 b5ff1b31 bellard
{
51 257ec289 Andreas Färber
    IntegratorCMState *s = opaque;
52 b5ff1b31 bellard
    if (offset >= 0x100 && offset < 0x200) {
53 b5ff1b31 bellard
        /* CM_SPD */
54 b5ff1b31 bellard
        if (offset >= 0x180)
55 b5ff1b31 bellard
            return 0;
56 b5ff1b31 bellard
        return integrator_spd[offset >> 2];
57 b5ff1b31 bellard
    }
58 b5ff1b31 bellard
    switch (offset >> 2) {
59 b5ff1b31 bellard
    case 0: /* CM_ID */
60 b5ff1b31 bellard
        return 0x411a3001;
61 b5ff1b31 bellard
    case 1: /* CM_PROC */
62 b5ff1b31 bellard
        return 0;
63 b5ff1b31 bellard
    case 2: /* CM_OSC */
64 b5ff1b31 bellard
        return s->cm_osc;
65 b5ff1b31 bellard
    case 3: /* CM_CTRL */
66 b5ff1b31 bellard
        return s->cm_ctrl;
67 b5ff1b31 bellard
    case 4: /* CM_STAT */
68 b5ff1b31 bellard
        return 0x00100000;
69 b5ff1b31 bellard
    case 5: /* CM_LOCK */
70 b5ff1b31 bellard
        if (s->cm_lock == 0xa05f) {
71 b5ff1b31 bellard
            return 0x1a05f;
72 b5ff1b31 bellard
        } else {
73 b5ff1b31 bellard
            return s->cm_lock;
74 b5ff1b31 bellard
        }
75 b5ff1b31 bellard
    case 6: /* CM_LMBUSCNT */
76 b5ff1b31 bellard
        /* ??? High frequency timer.  */
77 2ac71179 Paul Brook
        hw_error("integratorcm_read: CM_LMBUSCNT");
78 b5ff1b31 bellard
    case 7: /* CM_AUXOSC */
79 b5ff1b31 bellard
        return s->cm_auxosc;
80 b5ff1b31 bellard
    case 8: /* CM_SDRAM */
81 b5ff1b31 bellard
        return s->cm_sdram;
82 b5ff1b31 bellard
    case 9: /* CM_INIT */
83 b5ff1b31 bellard
        return s->cm_init;
84 b5ff1b31 bellard
    case 10: /* CM_REFCT */
85 b5ff1b31 bellard
        /* ??? High frequency timer.  */
86 2ac71179 Paul Brook
        hw_error("integratorcm_read: CM_REFCT");
87 b5ff1b31 bellard
    case 12: /* CM_FLAGS */
88 b5ff1b31 bellard
        return s->cm_flags;
89 b5ff1b31 bellard
    case 14: /* CM_NVFLAGS */
90 b5ff1b31 bellard
        return s->cm_nvflags;
91 b5ff1b31 bellard
    case 16: /* CM_IRQ_STAT */
92 b5ff1b31 bellard
        return s->int_level & s->irq_enabled;
93 b5ff1b31 bellard
    case 17: /* CM_IRQ_RSTAT */
94 b5ff1b31 bellard
        return s->int_level;
95 b5ff1b31 bellard
    case 18: /* CM_IRQ_ENSET */
96 b5ff1b31 bellard
        return s->irq_enabled;
97 b5ff1b31 bellard
    case 20: /* CM_SOFT_INTSET */
98 b5ff1b31 bellard
        return s->int_level & 1;
99 b5ff1b31 bellard
    case 24: /* CM_FIQ_STAT */
100 b5ff1b31 bellard
        return s->int_level & s->fiq_enabled;
101 b5ff1b31 bellard
    case 25: /* CM_FIQ_RSTAT */
102 b5ff1b31 bellard
        return s->int_level;
103 b5ff1b31 bellard
    case 26: /* CM_FIQ_ENSET */
104 b5ff1b31 bellard
        return s->fiq_enabled;
105 b5ff1b31 bellard
    case 32: /* CM_VOLTAGE_CTL0 */
106 b5ff1b31 bellard
    case 33: /* CM_VOLTAGE_CTL1 */
107 b5ff1b31 bellard
    case 34: /* CM_VOLTAGE_CTL2 */
108 b5ff1b31 bellard
    case 35: /* CM_VOLTAGE_CTL3 */
109 b5ff1b31 bellard
        /* ??? Voltage control unimplemented.  */
110 b5ff1b31 bellard
        return 0;
111 b5ff1b31 bellard
    default:
112 2ac71179 Paul Brook
        hw_error("integratorcm_read: Unimplemented offset 0x%x\n",
113 2ac71179 Paul Brook
                 (int)offset);
114 b5ff1b31 bellard
        return 0;
115 b5ff1b31 bellard
    }
116 b5ff1b31 bellard
}
117 b5ff1b31 bellard
118 257ec289 Andreas Färber
static void integratorcm_do_remap(IntegratorCMState *s)
119 b5ff1b31 bellard
{
120 563c2bf3 Peter Maydell
    /* Sync memory region state with CM_CTRL REMAP bit:
121 563c2bf3 Peter Maydell
     * bit 0 => flash at address 0; bit 1 => RAM
122 563c2bf3 Peter Maydell
     */
123 563c2bf3 Peter Maydell
    memory_region_set_enabled(&s->flash, !(s->cm_ctrl & 4));
124 b5ff1b31 bellard
}
125 b5ff1b31 bellard
126 257ec289 Andreas Färber
static void integratorcm_set_ctrl(IntegratorCMState *s, uint32_t value)
127 b5ff1b31 bellard
{
128 b5ff1b31 bellard
    if (value & 8) {
129 df3f457b Peter Maydell
        qemu_system_reset_request();
130 b5ff1b31 bellard
    }
131 df3f457b Peter Maydell
    if ((s->cm_ctrl ^ value) & 1) {
132 df3f457b Peter Maydell
        /* (value & 1) != 0 means the green "MISC LED" is lit.
133 df3f457b Peter Maydell
         * We don't have any nice place to display LEDs. printf is a bad
134 df3f457b Peter Maydell
         * idea because Linux uses the LED as a heartbeat and the output
135 df3f457b Peter Maydell
         * will swamp anything else on the terminal.
136 df3f457b Peter Maydell
         */
137 b5ff1b31 bellard
    }
138 df3f457b Peter Maydell
    /* Note that the RESET bit [3] always reads as zero */
139 df3f457b Peter Maydell
    s->cm_ctrl = (s->cm_ctrl & ~5) | (value & 5);
140 563c2bf3 Peter Maydell
    integratorcm_do_remap(s);
141 b5ff1b31 bellard
}
142 b5ff1b31 bellard
143 257ec289 Andreas Färber
static void integratorcm_update(IntegratorCMState *s)
144 b5ff1b31 bellard
{
145 b5ff1b31 bellard
    /* ??? The CPU irq/fiq is raised when either the core module or base PIC
146 b5ff1b31 bellard
       are active.  */
147 b5ff1b31 bellard
    if (s->int_level & (s->irq_enabled | s->fiq_enabled))
148 2ac71179 Paul Brook
        hw_error("Core module interrupt\n");
149 b5ff1b31 bellard
}
150 b5ff1b31 bellard
151 a8170e5e Avi Kivity
static void integratorcm_write(void *opaque, hwaddr offset,
152 71d9bc50 Benoît Canet
                               uint64_t value, unsigned size)
153 b5ff1b31 bellard
{
154 257ec289 Andreas Färber
    IntegratorCMState *s = opaque;
155 b5ff1b31 bellard
    switch (offset >> 2) {
156 b5ff1b31 bellard
    case 2: /* CM_OSC */
157 b5ff1b31 bellard
        if (s->cm_lock == 0xa05f)
158 b5ff1b31 bellard
            s->cm_osc = value;
159 b5ff1b31 bellard
        break;
160 b5ff1b31 bellard
    case 3: /* CM_CTRL */
161 b5ff1b31 bellard
        integratorcm_set_ctrl(s, value);
162 b5ff1b31 bellard
        break;
163 b5ff1b31 bellard
    case 5: /* CM_LOCK */
164 b5ff1b31 bellard
        s->cm_lock = value & 0xffff;
165 b5ff1b31 bellard
        break;
166 b5ff1b31 bellard
    case 7: /* CM_AUXOSC */
167 b5ff1b31 bellard
        if (s->cm_lock == 0xa05f)
168 b5ff1b31 bellard
            s->cm_auxosc = value;
169 b5ff1b31 bellard
        break;
170 b5ff1b31 bellard
    case 8: /* CM_SDRAM */
171 b5ff1b31 bellard
        s->cm_sdram = value;
172 b5ff1b31 bellard
        break;
173 b5ff1b31 bellard
    case 9: /* CM_INIT */
174 b5ff1b31 bellard
        /* ??? This can change the memory bus frequency.  */
175 b5ff1b31 bellard
        s->cm_init = value;
176 b5ff1b31 bellard
        break;
177 b5ff1b31 bellard
    case 12: /* CM_FLAGSS */
178 b5ff1b31 bellard
        s->cm_flags |= value;
179 b5ff1b31 bellard
        break;
180 b5ff1b31 bellard
    case 13: /* CM_FLAGSC */
181 b5ff1b31 bellard
        s->cm_flags &= ~value;
182 b5ff1b31 bellard
        break;
183 b5ff1b31 bellard
    case 14: /* CM_NVFLAGSS */
184 b5ff1b31 bellard
        s->cm_nvflags |= value;
185 b5ff1b31 bellard
        break;
186 b5ff1b31 bellard
    case 15: /* CM_NVFLAGSS */
187 b5ff1b31 bellard
        s->cm_nvflags &= ~value;
188 b5ff1b31 bellard
        break;
189 b5ff1b31 bellard
    case 18: /* CM_IRQ_ENSET */
190 b5ff1b31 bellard
        s->irq_enabled |= value;
191 b5ff1b31 bellard
        integratorcm_update(s);
192 b5ff1b31 bellard
        break;
193 b5ff1b31 bellard
    case 19: /* CM_IRQ_ENCLR */
194 b5ff1b31 bellard
        s->irq_enabled &= ~value;
195 b5ff1b31 bellard
        integratorcm_update(s);
196 b5ff1b31 bellard
        break;
197 b5ff1b31 bellard
    case 20: /* CM_SOFT_INTSET */
198 b5ff1b31 bellard
        s->int_level |= (value & 1);
199 b5ff1b31 bellard
        integratorcm_update(s);
200 b5ff1b31 bellard
        break;
201 b5ff1b31 bellard
    case 21: /* CM_SOFT_INTCLR */
202 b5ff1b31 bellard
        s->int_level &= ~(value & 1);
203 b5ff1b31 bellard
        integratorcm_update(s);
204 b5ff1b31 bellard
        break;
205 b5ff1b31 bellard
    case 26: /* CM_FIQ_ENSET */
206 b5ff1b31 bellard
        s->fiq_enabled |= value;
207 b5ff1b31 bellard
        integratorcm_update(s);
208 b5ff1b31 bellard
        break;
209 b5ff1b31 bellard
    case 27: /* CM_FIQ_ENCLR */
210 b5ff1b31 bellard
        s->fiq_enabled &= ~value;
211 b5ff1b31 bellard
        integratorcm_update(s);
212 b5ff1b31 bellard
        break;
213 b5ff1b31 bellard
    case 32: /* CM_VOLTAGE_CTL0 */
214 b5ff1b31 bellard
    case 33: /* CM_VOLTAGE_CTL1 */
215 b5ff1b31 bellard
    case 34: /* CM_VOLTAGE_CTL2 */
216 b5ff1b31 bellard
    case 35: /* CM_VOLTAGE_CTL3 */
217 b5ff1b31 bellard
        /* ??? Voltage control unimplemented.  */
218 b5ff1b31 bellard
        break;
219 b5ff1b31 bellard
    default:
220 2ac71179 Paul Brook
        hw_error("integratorcm_write: Unimplemented offset 0x%x\n",
221 2ac71179 Paul Brook
                 (int)offset);
222 b5ff1b31 bellard
        break;
223 b5ff1b31 bellard
    }
224 b5ff1b31 bellard
}
225 b5ff1b31 bellard
226 b5ff1b31 bellard
/* Integrator/CM control registers.  */
227 b5ff1b31 bellard
228 71d9bc50 Benoît Canet
static const MemoryRegionOps integratorcm_ops = {
229 71d9bc50 Benoît Canet
    .read = integratorcm_read,
230 71d9bc50 Benoît Canet
    .write = integratorcm_write,
231 71d9bc50 Benoît Canet
    .endianness = DEVICE_NATIVE_ENDIAN,
232 b5ff1b31 bellard
};
233 b5ff1b31 bellard
234 81a322d4 Gerd Hoffmann
static int integratorcm_init(SysBusDevice *dev)
235 b5ff1b31 bellard
{
236 257ec289 Andreas Färber
    IntegratorCMState *s = INTEGRATOR_CM(dev);
237 b5ff1b31 bellard
238 b5ff1b31 bellard
    s->cm_osc = 0x01000048;
239 b5ff1b31 bellard
    /* ??? What should the high bits of this value be?  */
240 b5ff1b31 bellard
    s->cm_auxosc = 0x0007feff;
241 b5ff1b31 bellard
    s->cm_sdram = 0x00011122;
242 ee6847d1 Gerd Hoffmann
    if (s->memsz >= 256) {
243 b5ff1b31 bellard
        integrator_spd[31] = 64;
244 b5ff1b31 bellard
        s->cm_sdram |= 0x10;
245 ee6847d1 Gerd Hoffmann
    } else if (s->memsz >= 128) {
246 b5ff1b31 bellard
        integrator_spd[31] = 32;
247 b5ff1b31 bellard
        s->cm_sdram |= 0x0c;
248 ee6847d1 Gerd Hoffmann
    } else if (s->memsz >= 64) {
249 b5ff1b31 bellard
        integrator_spd[31] = 16;
250 b5ff1b31 bellard
        s->cm_sdram |= 0x08;
251 ee6847d1 Gerd Hoffmann
    } else if (s->memsz >= 32) {
252 b5ff1b31 bellard
        integrator_spd[31] = 4;
253 b5ff1b31 bellard
        s->cm_sdram |= 0x04;
254 b5ff1b31 bellard
    } else {
255 b5ff1b31 bellard
        integrator_spd[31] = 2;
256 b5ff1b31 bellard
    }
257 b5ff1b31 bellard
    memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
258 b5ff1b31 bellard
    s->cm_init = 0x00000112;
259 64bde0f3 Paolo Bonzini
    memory_region_init_ram(&s->flash, OBJECT(s), "integrator.flash", 0x100000);
260 c5705a77 Avi Kivity
    vmstate_register_ram_global(&s->flash);
261 b5ff1b31 bellard
262 64bde0f3 Paolo Bonzini
    memory_region_init_io(&s->iomem, OBJECT(s), &integratorcm_ops, s,
263 71d9bc50 Benoît Canet
                          "integratorcm", 0x00800000);
264 750ecd44 Avi Kivity
    sysbus_init_mmio(dev, &s->iomem);
265 71d9bc50 Benoît Canet
266 563c2bf3 Peter Maydell
    integratorcm_do_remap(s);
267 b5ff1b31 bellard
    /* ??? Save/restore.  */
268 81a322d4 Gerd Hoffmann
    return 0;
269 b5ff1b31 bellard
}
270 b5ff1b31 bellard
271 b5ff1b31 bellard
/* Integrator/CP hardware emulation.  */
272 b5ff1b31 bellard
/* Primary interrupt controller.  */
273 b5ff1b31 bellard
274 91b64626 Andreas Färber
#define TYPE_INTEGRATOR_PIC "integrator_pic"
275 91b64626 Andreas Färber
#define INTEGRATOR_PIC(obj) \
276 91b64626 Andreas Färber
   OBJECT_CHECK(icp_pic_state, (obj), TYPE_INTEGRATOR_PIC)
277 91b64626 Andreas Färber
278 91b64626 Andreas Färber
typedef struct icp_pic_state {
279 91b64626 Andreas Färber
    /*< private >*/
280 91b64626 Andreas Färber
    SysBusDevice parent_obj;
281 91b64626 Andreas Färber
    /*< public >*/
282 91b64626 Andreas Färber
283 91b64626 Andreas Färber
    MemoryRegion iomem;
284 91b64626 Andreas Färber
    uint32_t level;
285 91b64626 Andreas Färber
    uint32_t irq_enabled;
286 91b64626 Andreas Färber
    uint32_t fiq_enabled;
287 91b64626 Andreas Färber
    qemu_irq parent_irq;
288 91b64626 Andreas Färber
    qemu_irq parent_fiq;
289 b5ff1b31 bellard
} icp_pic_state;
290 b5ff1b31 bellard
291 b5ff1b31 bellard
static void icp_pic_update(icp_pic_state *s)
292 b5ff1b31 bellard
{
293 cdbdb648 pbrook
    uint32_t flags;
294 b5ff1b31 bellard
295 d537cf6c pbrook
    flags = (s->level & s->irq_enabled);
296 d537cf6c pbrook
    qemu_set_irq(s->parent_irq, flags != 0);
297 d537cf6c pbrook
    flags = (s->level & s->fiq_enabled);
298 d537cf6c pbrook
    qemu_set_irq(s->parent_fiq, flags != 0);
299 b5ff1b31 bellard
}
300 b5ff1b31 bellard
301 cdbdb648 pbrook
static void icp_pic_set_irq(void *opaque, int irq, int level)
302 b5ff1b31 bellard
{
303 80337b66 bellard
    icp_pic_state *s = (icp_pic_state *)opaque;
304 b5ff1b31 bellard
    if (level)
305 80337b66 bellard
        s->level |= 1 << irq;
306 b5ff1b31 bellard
    else
307 80337b66 bellard
        s->level &= ~(1 << irq);
308 b5ff1b31 bellard
    icp_pic_update(s);
309 b5ff1b31 bellard
}
310 b5ff1b31 bellard
311 a8170e5e Avi Kivity
static uint64_t icp_pic_read(void *opaque, hwaddr offset,
312 61074e46 Benoît Canet
                             unsigned size)
313 b5ff1b31 bellard
{
314 b5ff1b31 bellard
    icp_pic_state *s = (icp_pic_state *)opaque;
315 b5ff1b31 bellard
316 b5ff1b31 bellard
    switch (offset >> 2) {
317 b5ff1b31 bellard
    case 0: /* IRQ_STATUS */
318 b5ff1b31 bellard
        return s->level & s->irq_enabled;
319 b5ff1b31 bellard
    case 1: /* IRQ_RAWSTAT */
320 b5ff1b31 bellard
        return s->level;
321 b5ff1b31 bellard
    case 2: /* IRQ_ENABLESET */
322 b5ff1b31 bellard
        return s->irq_enabled;
323 b5ff1b31 bellard
    case 4: /* INT_SOFTSET */
324 b5ff1b31 bellard
        return s->level & 1;
325 b5ff1b31 bellard
    case 8: /* FRQ_STATUS */
326 b5ff1b31 bellard
        return s->level & s->fiq_enabled;
327 b5ff1b31 bellard
    case 9: /* FRQ_RAWSTAT */
328 b5ff1b31 bellard
        return s->level;
329 b5ff1b31 bellard
    case 10: /* FRQ_ENABLESET */
330 b5ff1b31 bellard
        return s->fiq_enabled;
331 b5ff1b31 bellard
    case 3: /* IRQ_ENABLECLR */
332 b5ff1b31 bellard
    case 5: /* INT_SOFTCLR */
333 b5ff1b31 bellard
    case 11: /* FRQ_ENABLECLR */
334 b5ff1b31 bellard
    default:
335 29bfb117 pbrook
        printf ("icp_pic_read: Bad register offset 0x%x\n", (int)offset);
336 b5ff1b31 bellard
        return 0;
337 b5ff1b31 bellard
    }
338 b5ff1b31 bellard
}
339 b5ff1b31 bellard
340 a8170e5e Avi Kivity
static void icp_pic_write(void *opaque, hwaddr offset,
341 61074e46 Benoît Canet
                          uint64_t value, unsigned size)
342 b5ff1b31 bellard
{
343 b5ff1b31 bellard
    icp_pic_state *s = (icp_pic_state *)opaque;
344 b5ff1b31 bellard
345 b5ff1b31 bellard
    switch (offset >> 2) {
346 b5ff1b31 bellard
    case 2: /* IRQ_ENABLESET */
347 b5ff1b31 bellard
        s->irq_enabled |= value;
348 b5ff1b31 bellard
        break;
349 b5ff1b31 bellard
    case 3: /* IRQ_ENABLECLR */
350 b5ff1b31 bellard
        s->irq_enabled &= ~value;
351 b5ff1b31 bellard
        break;
352 b5ff1b31 bellard
    case 4: /* INT_SOFTSET */
353 b5ff1b31 bellard
        if (value & 1)
354 d537cf6c pbrook
            icp_pic_set_irq(s, 0, 1);
355 b5ff1b31 bellard
        break;
356 b5ff1b31 bellard
    case 5: /* INT_SOFTCLR */
357 b5ff1b31 bellard
        if (value & 1)
358 d537cf6c pbrook
            icp_pic_set_irq(s, 0, 0);
359 b5ff1b31 bellard
        break;
360 b5ff1b31 bellard
    case 10: /* FRQ_ENABLESET */
361 b5ff1b31 bellard
        s->fiq_enabled |= value;
362 b5ff1b31 bellard
        break;
363 b5ff1b31 bellard
    case 11: /* FRQ_ENABLECLR */
364 b5ff1b31 bellard
        s->fiq_enabled &= ~value;
365 b5ff1b31 bellard
        break;
366 b5ff1b31 bellard
    case 0: /* IRQ_STATUS */
367 b5ff1b31 bellard
    case 1: /* IRQ_RAWSTAT */
368 b5ff1b31 bellard
    case 8: /* FRQ_STATUS */
369 b5ff1b31 bellard
    case 9: /* FRQ_RAWSTAT */
370 b5ff1b31 bellard
    default:
371 29bfb117 pbrook
        printf ("icp_pic_write: Bad register offset 0x%x\n", (int)offset);
372 b5ff1b31 bellard
        return;
373 b5ff1b31 bellard
    }
374 b5ff1b31 bellard
    icp_pic_update(s);
375 b5ff1b31 bellard
}
376 b5ff1b31 bellard
377 61074e46 Benoît Canet
static const MemoryRegionOps icp_pic_ops = {
378 61074e46 Benoît Canet
    .read = icp_pic_read,
379 61074e46 Benoît Canet
    .write = icp_pic_write,
380 61074e46 Benoît Canet
    .endianness = DEVICE_NATIVE_ENDIAN,
381 b5ff1b31 bellard
};
382 b5ff1b31 bellard
383 91b64626 Andreas Färber
static int icp_pic_init(SysBusDevice *sbd)
384 b5ff1b31 bellard
{
385 91b64626 Andreas Färber
    DeviceState *dev = DEVICE(sbd);
386 91b64626 Andreas Färber
    icp_pic_state *s = INTEGRATOR_PIC(dev);
387 b5ff1b31 bellard
388 91b64626 Andreas Färber
    qdev_init_gpio_in(dev, icp_pic_set_irq, 32);
389 91b64626 Andreas Färber
    sysbus_init_irq(sbd, &s->parent_irq);
390 91b64626 Andreas Färber
    sysbus_init_irq(sbd, &s->parent_fiq);
391 64bde0f3 Paolo Bonzini
    memory_region_init_io(&s->iomem, OBJECT(s), &icp_pic_ops, s,
392 64bde0f3 Paolo Bonzini
                          "icp-pic", 0x00800000);
393 91b64626 Andreas Färber
    sysbus_init_mmio(sbd, &s->iomem);
394 81a322d4 Gerd Hoffmann
    return 0;
395 b5ff1b31 bellard
}
396 b5ff1b31 bellard
397 b5ff1b31 bellard
/* CP control registers.  */
398 0c36493e Benoît Canet
399 a8170e5e Avi Kivity
static uint64_t icp_control_read(void *opaque, hwaddr offset,
400 0c36493e Benoît Canet
                                 unsigned size)
401 b5ff1b31 bellard
{
402 b5ff1b31 bellard
    switch (offset >> 2) {
403 b5ff1b31 bellard
    case 0: /* CP_IDFIELD */
404 b5ff1b31 bellard
        return 0x41034003;
405 b5ff1b31 bellard
    case 1: /* CP_FLASHPROG */
406 b5ff1b31 bellard
        return 0;
407 b5ff1b31 bellard
    case 2: /* CP_INTREG */
408 b5ff1b31 bellard
        return 0;
409 b5ff1b31 bellard
    case 3: /* CP_DECODE */
410 b5ff1b31 bellard
        return 0x11;
411 b5ff1b31 bellard
    default:
412 2ac71179 Paul Brook
        hw_error("icp_control_read: Bad offset %x\n", (int)offset);
413 b5ff1b31 bellard
        return 0;
414 b5ff1b31 bellard
    }
415 b5ff1b31 bellard
}
416 b5ff1b31 bellard
417 a8170e5e Avi Kivity
static void icp_control_write(void *opaque, hwaddr offset,
418 0c36493e Benoît Canet
                          uint64_t value, unsigned size)
419 b5ff1b31 bellard
{
420 b5ff1b31 bellard
    switch (offset >> 2) {
421 b5ff1b31 bellard
    case 1: /* CP_FLASHPROG */
422 b5ff1b31 bellard
    case 2: /* CP_INTREG */
423 b5ff1b31 bellard
    case 3: /* CP_DECODE */
424 b5ff1b31 bellard
        /* Nothing interesting implemented yet.  */
425 b5ff1b31 bellard
        break;
426 b5ff1b31 bellard
    default:
427 2ac71179 Paul Brook
        hw_error("icp_control_write: Bad offset %x\n", (int)offset);
428 b5ff1b31 bellard
    }
429 b5ff1b31 bellard
}
430 b5ff1b31 bellard
431 0c36493e Benoît Canet
static const MemoryRegionOps icp_control_ops = {
432 0c36493e Benoît Canet
    .read = icp_control_read,
433 0c36493e Benoît Canet
    .write = icp_control_write,
434 0c36493e Benoît Canet
    .endianness = DEVICE_NATIVE_ENDIAN,
435 b5ff1b31 bellard
};
436 b5ff1b31 bellard
437 a8170e5e Avi Kivity
static void icp_control_init(hwaddr base)
438 b5ff1b31 bellard
{
439 0c36493e Benoît Canet
    MemoryRegion *io;
440 b5ff1b31 bellard
441 0c36493e Benoît Canet
    io = (MemoryRegion *)g_malloc0(sizeof(MemoryRegion));
442 2c9b15ca Paolo Bonzini
    memory_region_init_io(io, NULL, &icp_control_ops, NULL,
443 0c36493e Benoît Canet
                          "control", 0x00800000);
444 0c36493e Benoît Canet
    memory_region_add_subregion(get_system_memory(), base, io);
445 b5ff1b31 bellard
    /* ??? Save/restore.  */
446 b5ff1b31 bellard
}
447 b5ff1b31 bellard
448 b5ff1b31 bellard
449 b5ff1b31 bellard
/* Board init.  */
450 b5ff1b31 bellard
451 f93eb9ff balrog
static struct arm_boot_info integrator_binfo = {
452 f93eb9ff balrog
    .loader_start = 0x0,
453 f93eb9ff balrog
    .board_id = 0x113,
454 f93eb9ff balrog
};
455 f93eb9ff balrog
456 5f072e1f Eduardo Habkost
static void integratorcp_init(QEMUMachineInitArgs *args)
457 b5ff1b31 bellard
{
458 5f072e1f Eduardo Habkost
    ram_addr_t ram_size = args->ram_size;
459 5f072e1f Eduardo Habkost
    const char *cpu_model = args->cpu_model;
460 5f072e1f Eduardo Habkost
    const char *kernel_filename = args->kernel_filename;
461 5f072e1f Eduardo Habkost
    const char *kernel_cmdline = args->kernel_cmdline;
462 5f072e1f Eduardo Habkost
    const char *initrd_filename = args->initrd_filename;
463 393a9eab Andreas Färber
    ARMCPU *cpu;
464 211adf4d Avi Kivity
    MemoryRegion *address_space_mem = get_system_memory();
465 211adf4d Avi Kivity
    MemoryRegion *ram = g_new(MemoryRegion, 1);
466 211adf4d Avi Kivity
    MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
467 a7086888 Paul Brook
    qemu_irq pic[32];
468 d537cf6c pbrook
    qemu_irq *cpu_pic;
469 a7086888 Paul Brook
    DeviceState *dev;
470 a7086888 Paul Brook
    int i;
471 b5ff1b31 bellard
472 393a9eab Andreas Färber
    if (!cpu_model) {
473 3371d272 pbrook
        cpu_model = "arm926";
474 393a9eab Andreas Färber
    }
475 393a9eab Andreas Färber
    cpu = cpu_arm_init(cpu_model);
476 393a9eab Andreas Färber
    if (!cpu) {
477 aaed909a bellard
        fprintf(stderr, "Unable to find CPU definition\n");
478 aaed909a bellard
        exit(1);
479 aaed909a bellard
    }
480 393a9eab Andreas Färber
481 2c9b15ca Paolo Bonzini
    memory_region_init_ram(ram, NULL, "integrator.ram", ram_size);
482 c5705a77 Avi Kivity
    vmstate_register_ram_global(ram);
483 b5ff1b31 bellard
    /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
484 1235fc06 ths
    /* ??? RAM should repeat to fill physical memory space.  */
485 b5ff1b31 bellard
    /* SDRAM at address zero*/
486 211adf4d Avi Kivity
    memory_region_add_subregion(address_space_mem, 0, ram);
487 b5ff1b31 bellard
    /* And again at address 0x80000000 */
488 2c9b15ca Paolo Bonzini
    memory_region_init_alias(ram_alias, NULL, "ram.alias", ram, 0, ram_size);
489 211adf4d Avi Kivity
    memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
490 b5ff1b31 bellard
491 257ec289 Andreas Färber
    dev = qdev_create(NULL, TYPE_INTEGRATOR_CM);
492 ee6847d1 Gerd Hoffmann
    qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
493 e23a1b33 Markus Armbruster
    qdev_init_nofail(dev);
494 a7086888 Paul Brook
    sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
495 a7086888 Paul Brook
496 4bd74661 Andreas Färber
    cpu_pic = arm_pic_init_cpu(cpu);
497 91b64626 Andreas Färber
    dev = sysbus_create_varargs(TYPE_INTEGRATOR_PIC, 0x14000000,
498 a7086888 Paul Brook
                                cpu_pic[ARM_PIC_CPU_IRQ],
499 a7086888 Paul Brook
                                cpu_pic[ARM_PIC_CPU_FIQ], NULL);
500 a7086888 Paul Brook
    for (i = 0; i < 32; i++) {
501 067a3ddc Paul Brook
        pic[i] = qdev_get_gpio_in(dev, i);
502 a7086888 Paul Brook
    }
503 91b64626 Andreas Färber
    sysbus_create_simple(TYPE_INTEGRATOR_PIC, 0xca000000, pic[26]);
504 6a824ec3 Paul Brook
    sysbus_create_varargs("integrator_pit", 0x13000000,
505 6a824ec3 Paul Brook
                          pic[5], pic[6], pic[7], NULL);
506 a63bdb31 Paul Brook
    sysbus_create_simple("pl031", 0x15000000, pic[8]);
507 a7d518a6 Paul Brook
    sysbus_create_simple("pl011", 0x16000000, pic[1]);
508 a7d518a6 Paul Brook
    sysbus_create_simple("pl011", 0x17000000, pic[2]);
509 b5ff1b31 bellard
    icp_control_init(0xcb000000);
510 86394e96 Paul Brook
    sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
511 86394e96 Paul Brook
    sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]);
512 aa9311d8 Paul Brook
    sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL);
513 a005d073 Stefan Hajnoczi
    if (nd_table[0].used)
514 0ae18cee aliguori
        smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
515 2e9bdce5 Paul Brook
516 2e9bdce5 Paul Brook
    sysbus_create_simple("pl110", 0xc0000000, pic[22]);
517 b5ff1b31 bellard
518 f93eb9ff balrog
    integrator_binfo.ram_size = ram_size;
519 f93eb9ff balrog
    integrator_binfo.kernel_filename = kernel_filename;
520 f93eb9ff balrog
    integrator_binfo.kernel_cmdline = kernel_cmdline;
521 f93eb9ff balrog
    integrator_binfo.initrd_filename = initrd_filename;
522 3aaa8dfa Andreas Färber
    arm_load_kernel(cpu, &integrator_binfo);
523 b5ff1b31 bellard
}
524 b5ff1b31 bellard
525 f80f9ec9 Anthony Liguori
static QEMUMachine integratorcp_machine = {
526 4b32e168 aliguori
    .name = "integratorcp",
527 4b32e168 aliguori
    .desc = "ARM Integrator/CP (ARM926EJ-S)",
528 4b32e168 aliguori
    .init = integratorcp_init,
529 0c257437 Anthony Liguori
    .is_default = 1,
530 e4ada29e Avik Sil
    DEFAULT_MACHINE_OPTIONS,
531 b5ff1b31 bellard
};
532 a7086888 Paul Brook
533 f80f9ec9 Anthony Liguori
static void integratorcp_machine_init(void)
534 f80f9ec9 Anthony Liguori
{
535 f80f9ec9 Anthony Liguori
    qemu_register_machine(&integratorcp_machine);
536 f80f9ec9 Anthony Liguori
}
537 f80f9ec9 Anthony Liguori
538 f80f9ec9 Anthony Liguori
machine_init(integratorcp_machine_init);
539 f80f9ec9 Anthony Liguori
540 999e12bb Anthony Liguori
static Property core_properties[] = {
541 257ec289 Andreas Färber
    DEFINE_PROP_UINT32("memsz", IntegratorCMState, memsz, 0),
542 999e12bb Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
543 999e12bb Anthony Liguori
};
544 999e12bb Anthony Liguori
545 999e12bb Anthony Liguori
static void core_class_init(ObjectClass *klass, void *data)
546 999e12bb Anthony Liguori
{
547 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
548 999e12bb Anthony Liguori
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
549 999e12bb Anthony Liguori
550 999e12bb Anthony Liguori
    k->init = integratorcm_init;
551 39bffca2 Anthony Liguori
    dc->props = core_properties;
552 999e12bb Anthony Liguori
}
553 999e12bb Anthony Liguori
554 8c43a6f0 Andreas Färber
static const TypeInfo core_info = {
555 257ec289 Andreas Färber
    .name          = TYPE_INTEGRATOR_CM,
556 39bffca2 Anthony Liguori
    .parent        = TYPE_SYS_BUS_DEVICE,
557 257ec289 Andreas Färber
    .instance_size = sizeof(IntegratorCMState),
558 39bffca2 Anthony Liguori
    .class_init    = core_class_init,
559 999e12bb Anthony Liguori
};
560 999e12bb Anthony Liguori
561 999e12bb Anthony Liguori
static void icp_pic_class_init(ObjectClass *klass, void *data)
562 999e12bb Anthony Liguori
{
563 999e12bb Anthony Liguori
    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
564 999e12bb Anthony Liguori
565 999e12bb Anthony Liguori
    sdc->init = icp_pic_init;
566 999e12bb Anthony Liguori
}
567 999e12bb Anthony Liguori
568 8c43a6f0 Andreas Färber
static const TypeInfo icp_pic_info = {
569 91b64626 Andreas Färber
    .name          = TYPE_INTEGRATOR_PIC,
570 39bffca2 Anthony Liguori
    .parent        = TYPE_SYS_BUS_DEVICE,
571 39bffca2 Anthony Liguori
    .instance_size = sizeof(icp_pic_state),
572 39bffca2 Anthony Liguori
    .class_init    = icp_pic_class_init,
573 ee6847d1 Gerd Hoffmann
};
574 ee6847d1 Gerd Hoffmann
575 83f7d43a Andreas Färber
static void integratorcp_register_types(void)
576 a7086888 Paul Brook
{
577 39bffca2 Anthony Liguori
    type_register_static(&icp_pic_info);
578 39bffca2 Anthony Liguori
    type_register_static(&core_info);
579 a7086888 Paul Brook
}
580 a7086888 Paul Brook
581 83f7d43a Andreas Färber
type_init(integratorcp_register_types)