Statistics
| Branch: | Revision:

root / hw / integratorcp.c @ 0986ac3b

History | View | Annotate | Download (15.2 kB)

1 b5ff1b31 bellard
/* 
2 b5ff1b31 bellard
 * ARM Integrator CP System emulation.
3 b5ff1b31 bellard
 *
4 cdbdb648 pbrook
 * Copyright (c) 2005-2006 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 cdbdb648 pbrook
#include "vl.h"
11 cdbdb648 pbrook
#include "arm_pic.h"
12 b5ff1b31 bellard
13 b5ff1b31 bellard
void DMA_run (void)
14 b5ff1b31 bellard
{
15 b5ff1b31 bellard
}
16 b5ff1b31 bellard
17 b5ff1b31 bellard
typedef struct {
18 b5ff1b31 bellard
    uint32_t flash_offset;
19 b5ff1b31 bellard
    uint32_t cm_osc;
20 b5ff1b31 bellard
    uint32_t cm_ctrl;
21 b5ff1b31 bellard
    uint32_t cm_lock;
22 b5ff1b31 bellard
    uint32_t cm_auxosc;
23 b5ff1b31 bellard
    uint32_t cm_sdram;
24 b5ff1b31 bellard
    uint32_t cm_init;
25 b5ff1b31 bellard
    uint32_t cm_flags;
26 b5ff1b31 bellard
    uint32_t cm_nvflags;
27 b5ff1b31 bellard
    uint32_t int_level;
28 b5ff1b31 bellard
    uint32_t irq_enabled;
29 b5ff1b31 bellard
    uint32_t fiq_enabled;
30 b5ff1b31 bellard
} integratorcm_state;
31 b5ff1b31 bellard
32 b5ff1b31 bellard
static uint8_t integrator_spd[128] = {
33 b5ff1b31 bellard
   128, 8, 4, 11, 9, 1, 64, 0,  2, 0xa0, 0xa0, 0, 0, 8, 0, 1,
34 b5ff1b31 bellard
   0xe, 4, 0x1c, 1, 2, 0x20, 0xc0, 0, 0, 0, 0, 0x30, 0x28, 0x30, 0x28, 0x40
35 b5ff1b31 bellard
};
36 b5ff1b31 bellard
37 b5ff1b31 bellard
static uint32_t integratorcm_read(void *opaque, target_phys_addr_t offset)
38 b5ff1b31 bellard
{
39 b5ff1b31 bellard
    integratorcm_state *s = (integratorcm_state *)opaque;
40 b5ff1b31 bellard
    offset -= 0x10000000;
41 b5ff1b31 bellard
    if (offset >= 0x100 && offset < 0x200) {
42 b5ff1b31 bellard
        /* CM_SPD */
43 b5ff1b31 bellard
        if (offset >= 0x180)
44 b5ff1b31 bellard
            return 0;
45 b5ff1b31 bellard
        return integrator_spd[offset >> 2];
46 b5ff1b31 bellard
    }
47 b5ff1b31 bellard
    switch (offset >> 2) {
48 b5ff1b31 bellard
    case 0: /* CM_ID */
49 b5ff1b31 bellard
        return 0x411a3001;
50 b5ff1b31 bellard
    case 1: /* CM_PROC */
51 b5ff1b31 bellard
        return 0;
52 b5ff1b31 bellard
    case 2: /* CM_OSC */
53 b5ff1b31 bellard
        return s->cm_osc;
54 b5ff1b31 bellard
    case 3: /* CM_CTRL */
55 b5ff1b31 bellard
        return s->cm_ctrl;
56 b5ff1b31 bellard
    case 4: /* CM_STAT */
57 b5ff1b31 bellard
        return 0x00100000;
58 b5ff1b31 bellard
    case 5: /* CM_LOCK */
59 b5ff1b31 bellard
        if (s->cm_lock == 0xa05f) {
60 b5ff1b31 bellard
            return 0x1a05f;
61 b5ff1b31 bellard
        } else {
62 b5ff1b31 bellard
            return s->cm_lock;
63 b5ff1b31 bellard
        }
64 b5ff1b31 bellard
    case 6: /* CM_LMBUSCNT */
65 b5ff1b31 bellard
        /* ??? High frequency timer.  */
66 b5ff1b31 bellard
        cpu_abort(cpu_single_env, "integratorcm_read: CM_LMBUSCNT");
67 b5ff1b31 bellard
    case 7: /* CM_AUXOSC */
68 b5ff1b31 bellard
        return s->cm_auxosc;
69 b5ff1b31 bellard
    case 8: /* CM_SDRAM */
70 b5ff1b31 bellard
        return s->cm_sdram;
71 b5ff1b31 bellard
    case 9: /* CM_INIT */
72 b5ff1b31 bellard
        return s->cm_init;
73 b5ff1b31 bellard
    case 10: /* CM_REFCT */
74 b5ff1b31 bellard
        /* ??? High frequency timer.  */
75 b5ff1b31 bellard
        cpu_abort(cpu_single_env, "integratorcm_read: CM_REFCT");
76 b5ff1b31 bellard
    case 12: /* CM_FLAGS */
77 b5ff1b31 bellard
        return s->cm_flags;
78 b5ff1b31 bellard
    case 14: /* CM_NVFLAGS */
79 b5ff1b31 bellard
        return s->cm_nvflags;
80 b5ff1b31 bellard
    case 16: /* CM_IRQ_STAT */
81 b5ff1b31 bellard
        return s->int_level & s->irq_enabled;
82 b5ff1b31 bellard
    case 17: /* CM_IRQ_RSTAT */
83 b5ff1b31 bellard
        return s->int_level;
84 b5ff1b31 bellard
    case 18: /* CM_IRQ_ENSET */
85 b5ff1b31 bellard
        return s->irq_enabled;
86 b5ff1b31 bellard
    case 20: /* CM_SOFT_INTSET */
87 b5ff1b31 bellard
        return s->int_level & 1;
88 b5ff1b31 bellard
    case 24: /* CM_FIQ_STAT */
89 b5ff1b31 bellard
        return s->int_level & s->fiq_enabled;
90 b5ff1b31 bellard
    case 25: /* CM_FIQ_RSTAT */
91 b5ff1b31 bellard
        return s->int_level;
92 b5ff1b31 bellard
    case 26: /* CM_FIQ_ENSET */
93 b5ff1b31 bellard
        return s->fiq_enabled;
94 b5ff1b31 bellard
    case 32: /* CM_VOLTAGE_CTL0 */
95 b5ff1b31 bellard
    case 33: /* CM_VOLTAGE_CTL1 */
96 b5ff1b31 bellard
    case 34: /* CM_VOLTAGE_CTL2 */
97 b5ff1b31 bellard
    case 35: /* CM_VOLTAGE_CTL3 */
98 b5ff1b31 bellard
        /* ??? Voltage control unimplemented.  */
99 b5ff1b31 bellard
        return 0;
100 b5ff1b31 bellard
    default:
101 b5ff1b31 bellard
        cpu_abort (cpu_single_env,
102 b5ff1b31 bellard
            "integratorcm_read: Unimplemented offset 0x%x\n", offset);
103 b5ff1b31 bellard
        return 0;
104 b5ff1b31 bellard
    }
105 b5ff1b31 bellard
}
106 b5ff1b31 bellard
107 b5ff1b31 bellard
static void integratorcm_do_remap(integratorcm_state *s, int flash)
108 b5ff1b31 bellard
{
109 b5ff1b31 bellard
    if (flash) {
110 b5ff1b31 bellard
        cpu_register_physical_memory(0, 0x100000, IO_MEM_RAM);
111 b5ff1b31 bellard
    } else {
112 b5ff1b31 bellard
        cpu_register_physical_memory(0, 0x100000, s->flash_offset | IO_MEM_RAM);
113 b5ff1b31 bellard
    }
114 b5ff1b31 bellard
    //??? tlb_flush (cpu_single_env, 1);
115 b5ff1b31 bellard
}
116 b5ff1b31 bellard
117 b5ff1b31 bellard
static void integratorcm_set_ctrl(integratorcm_state *s, uint32_t value)
118 b5ff1b31 bellard
{
119 b5ff1b31 bellard
    if (value & 8) {
120 b5ff1b31 bellard
        cpu_abort(cpu_single_env, "Board reset\n");
121 b5ff1b31 bellard
    }
122 b5ff1b31 bellard
    if ((s->cm_init ^ value) & 4) {
123 b5ff1b31 bellard
        integratorcm_do_remap(s, (value & 4) == 0);
124 b5ff1b31 bellard
    }
125 b5ff1b31 bellard
    if ((s->cm_init ^ value) & 1) {
126 b5ff1b31 bellard
        printf("Green LED %s\n", (value & 1) ? "on" : "off");
127 b5ff1b31 bellard
    }
128 b5ff1b31 bellard
    s->cm_init = (s->cm_init & ~ 5) | (value ^ 5);
129 b5ff1b31 bellard
}
130 b5ff1b31 bellard
131 b5ff1b31 bellard
static void integratorcm_update(integratorcm_state *s)
132 b5ff1b31 bellard
{
133 b5ff1b31 bellard
    /* ??? The CPU irq/fiq is raised when either the core module or base PIC
134 b5ff1b31 bellard
       are active.  */
135 b5ff1b31 bellard
    if (s->int_level & (s->irq_enabled | s->fiq_enabled))
136 b5ff1b31 bellard
        cpu_abort(cpu_single_env, "Core module interrupt\n");
137 b5ff1b31 bellard
}
138 b5ff1b31 bellard
139 b5ff1b31 bellard
static void integratorcm_write(void *opaque, target_phys_addr_t offset,
140 b5ff1b31 bellard
                               uint32_t value)
141 b5ff1b31 bellard
{
142 b5ff1b31 bellard
    integratorcm_state *s = (integratorcm_state *)opaque;
143 b5ff1b31 bellard
    offset -= 0x10000000;
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 b5ff1b31 bellard
        cpu_abort (cpu_single_env,
210 b5ff1b31 bellard
            "integratorcm_write: Unimplemented offset 0x%x\n", 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 b5ff1b31 bellard
static CPUReadMemoryFunc *integratorcm_readfn[] = {
218 b5ff1b31 bellard
   integratorcm_read,
219 b5ff1b31 bellard
   integratorcm_read,
220 b5ff1b31 bellard
   integratorcm_read
221 b5ff1b31 bellard
};
222 b5ff1b31 bellard
223 b5ff1b31 bellard
static CPUWriteMemoryFunc *integratorcm_writefn[] = {
224 b5ff1b31 bellard
   integratorcm_write,
225 b5ff1b31 bellard
   integratorcm_write,
226 b5ff1b31 bellard
   integratorcm_write
227 b5ff1b31 bellard
};
228 b5ff1b31 bellard
229 b5ff1b31 bellard
static void integratorcm_init(int memsz, uint32_t flash_offset)
230 b5ff1b31 bellard
{
231 b5ff1b31 bellard
    int iomemtype;
232 b5ff1b31 bellard
    integratorcm_state *s;
233 b5ff1b31 bellard
234 b5ff1b31 bellard
    s = (integratorcm_state *)qemu_mallocz(sizeof(integratorcm_state));
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 b5ff1b31 bellard
    if (memsz >= 256) {
240 b5ff1b31 bellard
        integrator_spd[31] = 64;
241 b5ff1b31 bellard
        s->cm_sdram |= 0x10;
242 b5ff1b31 bellard
    } else if (memsz >= 128) {
243 b5ff1b31 bellard
        integrator_spd[31] = 32;
244 b5ff1b31 bellard
        s->cm_sdram |= 0x0c;
245 b5ff1b31 bellard
    } else if (memsz >= 64) {
246 b5ff1b31 bellard
        integrator_spd[31] = 16;
247 b5ff1b31 bellard
        s->cm_sdram |= 0x08;
248 b5ff1b31 bellard
    } else if (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 b5ff1b31 bellard
    s->flash_offset = flash_offset;
257 b5ff1b31 bellard
258 b5ff1b31 bellard
    iomemtype = cpu_register_io_memory(0, integratorcm_readfn,
259 b5ff1b31 bellard
                                       integratorcm_writefn, s);
260 b5ff1b31 bellard
    cpu_register_physical_memory(0x10000000, 0x007fffff, iomemtype);
261 b5ff1b31 bellard
    integratorcm_do_remap(s, 1);
262 b5ff1b31 bellard
    /* ??? Save/restore.  */
263 b5ff1b31 bellard
}
264 b5ff1b31 bellard
265 b5ff1b31 bellard
/* Integrator/CP hardware emulation.  */
266 b5ff1b31 bellard
/* Primary interrupt controller.  */
267 b5ff1b31 bellard
268 b5ff1b31 bellard
typedef struct icp_pic_state
269 b5ff1b31 bellard
{
270 cdbdb648 pbrook
  arm_pic_handler handler;
271 b5ff1b31 bellard
  uint32_t base;
272 b5ff1b31 bellard
  uint32_t level;
273 b5ff1b31 bellard
  uint32_t irq_enabled;
274 b5ff1b31 bellard
  uint32_t fiq_enabled;
275 b5ff1b31 bellard
  void *parent;
276 b5ff1b31 bellard
  int parent_irq;
277 cdbdb648 pbrook
  int 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 cdbdb648 pbrook
    if (s->parent_irq != -1) {
285 b5ff1b31 bellard
        flags = (s->level & s->irq_enabled);
286 cdbdb648 pbrook
        pic_set_irq_new(s->parent, s->parent_irq, flags != 0);
287 b5ff1b31 bellard
    }
288 cdbdb648 pbrook
    if (s->parent_fiq != -1) {
289 cdbdb648 pbrook
        flags = (s->level & s->fiq_enabled);
290 cdbdb648 pbrook
        pic_set_irq_new(s->parent, s->parent_fiq, flags != 0);
291 b5ff1b31 bellard
    }
292 b5ff1b31 bellard
}
293 b5ff1b31 bellard
294 cdbdb648 pbrook
static void icp_pic_set_irq(void *opaque, int irq, int level)
295 b5ff1b31 bellard
{
296 80337b66 bellard
    icp_pic_state *s = (icp_pic_state *)opaque;
297 b5ff1b31 bellard
    if (level)
298 80337b66 bellard
        s->level |= 1 << irq;
299 b5ff1b31 bellard
    else
300 80337b66 bellard
        s->level &= ~(1 << irq);
301 b5ff1b31 bellard
    icp_pic_update(s);
302 b5ff1b31 bellard
}
303 b5ff1b31 bellard
304 b5ff1b31 bellard
static uint32_t icp_pic_read(void *opaque, target_phys_addr_t offset)
305 b5ff1b31 bellard
{
306 b5ff1b31 bellard
    icp_pic_state *s = (icp_pic_state *)opaque;
307 b5ff1b31 bellard
308 b5ff1b31 bellard
    offset -= s->base;
309 b5ff1b31 bellard
    switch (offset >> 2) {
310 b5ff1b31 bellard
    case 0: /* IRQ_STATUS */
311 b5ff1b31 bellard
        return s->level & s->irq_enabled;
312 b5ff1b31 bellard
    case 1: /* IRQ_RAWSTAT */
313 b5ff1b31 bellard
        return s->level;
314 b5ff1b31 bellard
    case 2: /* IRQ_ENABLESET */
315 b5ff1b31 bellard
        return s->irq_enabled;
316 b5ff1b31 bellard
    case 4: /* INT_SOFTSET */
317 b5ff1b31 bellard
        return s->level & 1;
318 b5ff1b31 bellard
    case 8: /* FRQ_STATUS */
319 b5ff1b31 bellard
        return s->level & s->fiq_enabled;
320 b5ff1b31 bellard
    case 9: /* FRQ_RAWSTAT */
321 b5ff1b31 bellard
        return s->level;
322 b5ff1b31 bellard
    case 10: /* FRQ_ENABLESET */
323 b5ff1b31 bellard
        return s->fiq_enabled;
324 b5ff1b31 bellard
    case 3: /* IRQ_ENABLECLR */
325 b5ff1b31 bellard
    case 5: /* INT_SOFTCLR */
326 b5ff1b31 bellard
    case 11: /* FRQ_ENABLECLR */
327 b5ff1b31 bellard
    default:
328 b5ff1b31 bellard
        printf ("icp_pic_read: Bad register offset 0x%x\n", offset);
329 b5ff1b31 bellard
        return 0;
330 b5ff1b31 bellard
    }
331 b5ff1b31 bellard
}
332 b5ff1b31 bellard
333 b5ff1b31 bellard
static void icp_pic_write(void *opaque, target_phys_addr_t offset,
334 b5ff1b31 bellard
                          uint32_t value)
335 b5ff1b31 bellard
{
336 b5ff1b31 bellard
    icp_pic_state *s = (icp_pic_state *)opaque;
337 b5ff1b31 bellard
    offset -= s->base;
338 b5ff1b31 bellard
339 b5ff1b31 bellard
    switch (offset >> 2) {
340 b5ff1b31 bellard
    case 2: /* IRQ_ENABLESET */
341 b5ff1b31 bellard
        s->irq_enabled |= value;
342 b5ff1b31 bellard
        break;
343 b5ff1b31 bellard
    case 3: /* IRQ_ENABLECLR */
344 b5ff1b31 bellard
        s->irq_enabled &= ~value;
345 b5ff1b31 bellard
        break;
346 b5ff1b31 bellard
    case 4: /* INT_SOFTSET */
347 b5ff1b31 bellard
        if (value & 1)
348 80337b66 bellard
            pic_set_irq_new(s, 0, 1);
349 b5ff1b31 bellard
        break;
350 b5ff1b31 bellard
    case 5: /* INT_SOFTCLR */
351 b5ff1b31 bellard
        if (value & 1)
352 80337b66 bellard
            pic_set_irq_new(s, 0, 0);
353 b5ff1b31 bellard
        break;
354 b5ff1b31 bellard
    case 10: /* FRQ_ENABLESET */
355 b5ff1b31 bellard
        s->fiq_enabled |= value;
356 b5ff1b31 bellard
        break;
357 b5ff1b31 bellard
    case 11: /* FRQ_ENABLECLR */
358 b5ff1b31 bellard
        s->fiq_enabled &= ~value;
359 b5ff1b31 bellard
        break;
360 b5ff1b31 bellard
    case 0: /* IRQ_STATUS */
361 b5ff1b31 bellard
    case 1: /* IRQ_RAWSTAT */
362 b5ff1b31 bellard
    case 8: /* FRQ_STATUS */
363 b5ff1b31 bellard
    case 9: /* FRQ_RAWSTAT */
364 b5ff1b31 bellard
    default:
365 b5ff1b31 bellard
        printf ("icp_pic_write: Bad register offset 0x%x\n", offset);
366 b5ff1b31 bellard
        return;
367 b5ff1b31 bellard
    }
368 b5ff1b31 bellard
    icp_pic_update(s);
369 b5ff1b31 bellard
}
370 b5ff1b31 bellard
371 b5ff1b31 bellard
static CPUReadMemoryFunc *icp_pic_readfn[] = {
372 b5ff1b31 bellard
   icp_pic_read,
373 b5ff1b31 bellard
   icp_pic_read,
374 b5ff1b31 bellard
   icp_pic_read
375 b5ff1b31 bellard
};
376 b5ff1b31 bellard
377 b5ff1b31 bellard
static CPUWriteMemoryFunc *icp_pic_writefn[] = {
378 b5ff1b31 bellard
   icp_pic_write,
379 b5ff1b31 bellard
   icp_pic_write,
380 b5ff1b31 bellard
   icp_pic_write
381 b5ff1b31 bellard
};
382 b5ff1b31 bellard
383 b5ff1b31 bellard
static icp_pic_state *icp_pic_init(uint32_t base, void *parent,
384 cdbdb648 pbrook
                                   int parent_irq, int parent_fiq)
385 b5ff1b31 bellard
{
386 b5ff1b31 bellard
    icp_pic_state *s;
387 b5ff1b31 bellard
    int iomemtype;
388 b5ff1b31 bellard
389 b5ff1b31 bellard
    s = (icp_pic_state *)qemu_mallocz(sizeof(icp_pic_state));
390 b5ff1b31 bellard
    if (!s)
391 b5ff1b31 bellard
        return NULL;
392 cdbdb648 pbrook
    s->handler = icp_pic_set_irq;
393 b5ff1b31 bellard
    s->base = base;
394 b5ff1b31 bellard
    s->parent = parent;
395 b5ff1b31 bellard
    s->parent_irq = parent_irq;
396 cdbdb648 pbrook
    s->parent_fiq = parent_fiq;
397 b5ff1b31 bellard
    iomemtype = cpu_register_io_memory(0, icp_pic_readfn,
398 b5ff1b31 bellard
                                       icp_pic_writefn, s);
399 b5ff1b31 bellard
    cpu_register_physical_memory(base, 0x007fffff, iomemtype);
400 b5ff1b31 bellard
    /* ??? Save/restore.  */
401 b5ff1b31 bellard
    return s;
402 b5ff1b31 bellard
}
403 b5ff1b31 bellard
404 b5ff1b31 bellard
/* CP control registers.  */
405 b5ff1b31 bellard
typedef struct {
406 b5ff1b31 bellard
    uint32_t base;
407 b5ff1b31 bellard
} icp_control_state;
408 b5ff1b31 bellard
409 b5ff1b31 bellard
static uint32_t icp_control_read(void *opaque, target_phys_addr_t offset)
410 b5ff1b31 bellard
{
411 b5ff1b31 bellard
    icp_control_state *s = (icp_control_state *)opaque;
412 b5ff1b31 bellard
    offset -= s->base;
413 b5ff1b31 bellard
    switch (offset >> 2) {
414 b5ff1b31 bellard
    case 0: /* CP_IDFIELD */
415 b5ff1b31 bellard
        return 0x41034003;
416 b5ff1b31 bellard
    case 1: /* CP_FLASHPROG */
417 b5ff1b31 bellard
        return 0;
418 b5ff1b31 bellard
    case 2: /* CP_INTREG */
419 b5ff1b31 bellard
        return 0;
420 b5ff1b31 bellard
    case 3: /* CP_DECODE */
421 b5ff1b31 bellard
        return 0x11;
422 b5ff1b31 bellard
    default:
423 b5ff1b31 bellard
        cpu_abort (cpu_single_env, "icp_control_read: Bad offset %x\n", offset);
424 b5ff1b31 bellard
        return 0;
425 b5ff1b31 bellard
    }
426 b5ff1b31 bellard
}
427 b5ff1b31 bellard
428 b5ff1b31 bellard
static void icp_control_write(void *opaque, target_phys_addr_t offset,
429 b5ff1b31 bellard
                          uint32_t value)
430 b5ff1b31 bellard
{
431 b5ff1b31 bellard
    icp_control_state *s = (icp_control_state *)opaque;
432 b5ff1b31 bellard
    offset -= s->base;
433 b5ff1b31 bellard
    switch (offset >> 2) {
434 b5ff1b31 bellard
    case 1: /* CP_FLASHPROG */
435 b5ff1b31 bellard
    case 2: /* CP_INTREG */
436 b5ff1b31 bellard
    case 3: /* CP_DECODE */
437 b5ff1b31 bellard
        /* Nothing interesting implemented yet.  */
438 b5ff1b31 bellard
        break;
439 b5ff1b31 bellard
    default:
440 b5ff1b31 bellard
        cpu_abort (cpu_single_env, "icp_control_write: Bad offset %x\n", offset);
441 b5ff1b31 bellard
    }
442 b5ff1b31 bellard
}
443 b5ff1b31 bellard
static CPUReadMemoryFunc *icp_control_readfn[] = {
444 b5ff1b31 bellard
   icp_control_read,
445 b5ff1b31 bellard
   icp_control_read,
446 b5ff1b31 bellard
   icp_control_read
447 b5ff1b31 bellard
};
448 b5ff1b31 bellard
449 b5ff1b31 bellard
static CPUWriteMemoryFunc *icp_control_writefn[] = {
450 b5ff1b31 bellard
   icp_control_write,
451 b5ff1b31 bellard
   icp_control_write,
452 b5ff1b31 bellard
   icp_control_write
453 b5ff1b31 bellard
};
454 b5ff1b31 bellard
455 b5ff1b31 bellard
static void icp_control_init(uint32_t base)
456 b5ff1b31 bellard
{
457 b5ff1b31 bellard
    int iomemtype;
458 b5ff1b31 bellard
    icp_control_state *s;
459 b5ff1b31 bellard
460 b5ff1b31 bellard
    s = (icp_control_state *)qemu_mallocz(sizeof(icp_control_state));
461 b5ff1b31 bellard
    iomemtype = cpu_register_io_memory(0, icp_control_readfn,
462 b5ff1b31 bellard
                                       icp_control_writefn, s);
463 b5ff1b31 bellard
    cpu_register_physical_memory(base, 0x007fffff, iomemtype);
464 b5ff1b31 bellard
    s->base = base;
465 b5ff1b31 bellard
    /* ??? Save/restore.  */
466 b5ff1b31 bellard
}
467 b5ff1b31 bellard
468 b5ff1b31 bellard
469 b5ff1b31 bellard
/* Board init.  */
470 b5ff1b31 bellard
471 b5ff1b31 bellard
static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device,
472 b5ff1b31 bellard
                     DisplayState *ds, const char **fd_filename, int snapshot,
473 b5ff1b31 bellard
                     const char *kernel_filename, const char *kernel_cmdline,
474 40f137e1 pbrook
                     const char *initrd_filename, uint32_t cpuid)
475 b5ff1b31 bellard
{
476 b5ff1b31 bellard
    CPUState *env;
477 b5ff1b31 bellard
    uint32_t bios_offset;
478 b5ff1b31 bellard
    icp_pic_state *pic;
479 cdbdb648 pbrook
    void *cpu_pic;
480 b5ff1b31 bellard
481 b5ff1b31 bellard
    env = cpu_init();
482 40f137e1 pbrook
    cpu_arm_set_model(env, cpuid);
483 b5ff1b31 bellard
    bios_offset = ram_size + vga_ram_size;
484 b5ff1b31 bellard
    /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
485 b5ff1b31 bellard
    /* ??? RAM shoud repeat to fill physical memory space.  */
486 b5ff1b31 bellard
    /* SDRAM at address zero*/
487 b5ff1b31 bellard
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
488 b5ff1b31 bellard
    /* And again at address 0x80000000 */
489 b5ff1b31 bellard
    cpu_register_physical_memory(0x80000000, ram_size, IO_MEM_RAM);
490 b5ff1b31 bellard
491 b5ff1b31 bellard
    integratorcm_init(ram_size >> 20, bios_offset);
492 cdbdb648 pbrook
    cpu_pic = arm_pic_init_cpu(env);
493 cdbdb648 pbrook
    pic = icp_pic_init(0x14000000, cpu_pic, ARM_PIC_CPU_IRQ, ARM_PIC_CPU_FIQ);
494 cdbdb648 pbrook
    icp_pic_init(0xca000000, pic, 26, -1);
495 cdbdb648 pbrook
    icp_pit_init(0x13000000, pic, 5);
496 b5ff1b31 bellard
    pl011_init(0x16000000, pic, 1, serial_hds[0]);
497 b5ff1b31 bellard
    pl011_init(0x17000000, pic, 2, serial_hds[1]);
498 b5ff1b31 bellard
    icp_control_init(0xcb000000);
499 cdbdb648 pbrook
    pl050_init(0x18000000, pic, 3, 0);
500 cdbdb648 pbrook
    pl050_init(0x19000000, pic, 4, 1);
501 a41b2ff2 pbrook
    if (nd_table[0].vlan) {
502 a41b2ff2 pbrook
        if (nd_table[0].model == NULL
503 a41b2ff2 pbrook
            || strcmp(nd_table[0].model, "smc91c111") == 0) {
504 a41b2ff2 pbrook
            smc91c111_init(&nd_table[0], 0xc8000000, pic, 27);
505 a41b2ff2 pbrook
        } else {
506 a41b2ff2 pbrook
            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
507 a41b2ff2 pbrook
            exit (1);
508 a41b2ff2 pbrook
        }
509 a41b2ff2 pbrook
    }
510 95219897 pbrook
    pl110_init(ds, 0xc0000000, pic, 22, 0);
511 b5ff1b31 bellard
512 16406950 pbrook
    arm_load_kernel(ram_size, kernel_filename, kernel_cmdline,
513 16406950 pbrook
                    initrd_filename, 0x113);
514 b5ff1b31 bellard
}
515 b5ff1b31 bellard
516 40f137e1 pbrook
static void integratorcp926_init(int ram_size, int vga_ram_size,
517 40f137e1 pbrook
    int boot_device, DisplayState *ds, const char **fd_filename, int snapshot,
518 40f137e1 pbrook
    const char *kernel_filename, const char *kernel_cmdline,
519 40f137e1 pbrook
    const char *initrd_filename)
520 40f137e1 pbrook
{
521 40f137e1 pbrook
    integratorcp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
522 40f137e1 pbrook
                      snapshot, kernel_filename, kernel_cmdline,
523 40f137e1 pbrook
                      initrd_filename, ARM_CPUID_ARM926);
524 40f137e1 pbrook
}
525 40f137e1 pbrook
526 40f137e1 pbrook
static void integratorcp1026_init(int ram_size, int vga_ram_size,
527 40f137e1 pbrook
    int boot_device, DisplayState *ds, const char **fd_filename, int snapshot,
528 40f137e1 pbrook
    const char *kernel_filename, const char *kernel_cmdline,
529 40f137e1 pbrook
    const char *initrd_filename)
530 40f137e1 pbrook
{
531 40f137e1 pbrook
    integratorcp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
532 40f137e1 pbrook
                      snapshot, kernel_filename, kernel_cmdline,
533 40f137e1 pbrook
                      initrd_filename, ARM_CPUID_ARM1026);
534 40f137e1 pbrook
}
535 40f137e1 pbrook
536 40f137e1 pbrook
QEMUMachine integratorcp926_machine = {
537 40f137e1 pbrook
    "integratorcp926",
538 40f137e1 pbrook
    "ARM Integrator/CP (ARM926EJ-S)",
539 40f137e1 pbrook
    integratorcp926_init,
540 40f137e1 pbrook
};
541 40f137e1 pbrook
542 40f137e1 pbrook
QEMUMachine integratorcp1026_machine = {
543 40f137e1 pbrook
    "integratorcp1026",
544 40f137e1 pbrook
    "ARM Integrator/CP (ARM1026EJ-S)",
545 40f137e1 pbrook
    integratorcp1026_init,
546 b5ff1b31 bellard
};