Statistics
| Branch: | Revision:

root / hw / arm / integratorcp.c @ f487b677

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