Statistics
| Branch: | Revision:

root / hw / integratorcp.c @ 00914b7d

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