Statistics
| Branch: | Revision:

root / hw / integratorcp.c @ 1f0ff2fb

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