Statistics
| Branch: | Revision:

root / hw / integratorcp.c @ c2ff060f

History | View | Annotate | Download (17.7 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
#define KERNEL_ARGS_ADDR 0x100
14 b5ff1b31 bellard
#define KERNEL_LOAD_ADDR 0x00010000
15 b5ff1b31 bellard
#define INITRD_LOAD_ADDR 0x00800000
16 b5ff1b31 bellard
17 b5ff1b31 bellard
void DMA_run (void)
18 b5ff1b31 bellard
{
19 b5ff1b31 bellard
}
20 b5ff1b31 bellard
21 b5ff1b31 bellard
typedef struct {
22 b5ff1b31 bellard
    uint32_t flash_offset;
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 b5ff1b31 bellard
static uint32_t integratorcm_read(void *opaque, target_phys_addr_t offset)
42 b5ff1b31 bellard
{
43 b5ff1b31 bellard
    integratorcm_state *s = (integratorcm_state *)opaque;
44 b5ff1b31 bellard
    offset -= 0x10000000;
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 b5ff1b31 bellard
        cpu_abort(cpu_single_env, "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 b5ff1b31 bellard
        cpu_abort(cpu_single_env, "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 b5ff1b31 bellard
        cpu_abort (cpu_single_env,
106 b5ff1b31 bellard
            "integratorcm_read: Unimplemented offset 0x%x\n", offset);
107 b5ff1b31 bellard
        return 0;
108 b5ff1b31 bellard
    }
109 b5ff1b31 bellard
}
110 b5ff1b31 bellard
111 b5ff1b31 bellard
static void integratorcm_do_remap(integratorcm_state *s, int flash)
112 b5ff1b31 bellard
{
113 b5ff1b31 bellard
    if (flash) {
114 b5ff1b31 bellard
        cpu_register_physical_memory(0, 0x100000, IO_MEM_RAM);
115 b5ff1b31 bellard
    } else {
116 b5ff1b31 bellard
        cpu_register_physical_memory(0, 0x100000, s->flash_offset | IO_MEM_RAM);
117 b5ff1b31 bellard
    }
118 b5ff1b31 bellard
    //??? tlb_flush (cpu_single_env, 1);
119 b5ff1b31 bellard
}
120 b5ff1b31 bellard
121 b5ff1b31 bellard
static void integratorcm_set_ctrl(integratorcm_state *s, uint32_t value)
122 b5ff1b31 bellard
{
123 b5ff1b31 bellard
    if (value & 8) {
124 b5ff1b31 bellard
        cpu_abort(cpu_single_env, "Board reset\n");
125 b5ff1b31 bellard
    }
126 b5ff1b31 bellard
    if ((s->cm_init ^ value) & 4) {
127 b5ff1b31 bellard
        integratorcm_do_remap(s, (value & 4) == 0);
128 b5ff1b31 bellard
    }
129 b5ff1b31 bellard
    if ((s->cm_init ^ value) & 1) {
130 b5ff1b31 bellard
        printf("Green LED %s\n", (value & 1) ? "on" : "off");
131 b5ff1b31 bellard
    }
132 b5ff1b31 bellard
    s->cm_init = (s->cm_init & ~ 5) | (value ^ 5);
133 b5ff1b31 bellard
}
134 b5ff1b31 bellard
135 b5ff1b31 bellard
static void integratorcm_update(integratorcm_state *s)
136 b5ff1b31 bellard
{
137 b5ff1b31 bellard
    /* ??? The CPU irq/fiq is raised when either the core module or base PIC
138 b5ff1b31 bellard
       are active.  */
139 b5ff1b31 bellard
    if (s->int_level & (s->irq_enabled | s->fiq_enabled))
140 b5ff1b31 bellard
        cpu_abort(cpu_single_env, "Core module interrupt\n");
141 b5ff1b31 bellard
}
142 b5ff1b31 bellard
143 b5ff1b31 bellard
static void integratorcm_write(void *opaque, target_phys_addr_t offset,
144 b5ff1b31 bellard
                               uint32_t value)
145 b5ff1b31 bellard
{
146 b5ff1b31 bellard
    integratorcm_state *s = (integratorcm_state *)opaque;
147 b5ff1b31 bellard
    offset -= 0x10000000;
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 b5ff1b31 bellard
        cpu_abort (cpu_single_env,
214 b5ff1b31 bellard
            "integratorcm_write: Unimplemented offset 0x%x\n", 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 b5ff1b31 bellard
static CPUReadMemoryFunc *integratorcm_readfn[] = {
222 b5ff1b31 bellard
   integratorcm_read,
223 b5ff1b31 bellard
   integratorcm_read,
224 b5ff1b31 bellard
   integratorcm_read
225 b5ff1b31 bellard
};
226 b5ff1b31 bellard
227 b5ff1b31 bellard
static CPUWriteMemoryFunc *integratorcm_writefn[] = {
228 b5ff1b31 bellard
   integratorcm_write,
229 b5ff1b31 bellard
   integratorcm_write,
230 b5ff1b31 bellard
   integratorcm_write
231 b5ff1b31 bellard
};
232 b5ff1b31 bellard
233 b5ff1b31 bellard
static void integratorcm_init(int memsz, uint32_t flash_offset)
234 b5ff1b31 bellard
{
235 b5ff1b31 bellard
    int iomemtype;
236 b5ff1b31 bellard
    integratorcm_state *s;
237 b5ff1b31 bellard
238 b5ff1b31 bellard
    s = (integratorcm_state *)qemu_mallocz(sizeof(integratorcm_state));
239 b5ff1b31 bellard
    s->cm_osc = 0x01000048;
240 b5ff1b31 bellard
    /* ??? What should the high bits of this value be?  */
241 b5ff1b31 bellard
    s->cm_auxosc = 0x0007feff;
242 b5ff1b31 bellard
    s->cm_sdram = 0x00011122;
243 b5ff1b31 bellard
    if (memsz >= 256) {
244 b5ff1b31 bellard
        integrator_spd[31] = 64;
245 b5ff1b31 bellard
        s->cm_sdram |= 0x10;
246 b5ff1b31 bellard
    } else if (memsz >= 128) {
247 b5ff1b31 bellard
        integrator_spd[31] = 32;
248 b5ff1b31 bellard
        s->cm_sdram |= 0x0c;
249 b5ff1b31 bellard
    } else if (memsz >= 64) {
250 b5ff1b31 bellard
        integrator_spd[31] = 16;
251 b5ff1b31 bellard
        s->cm_sdram |= 0x08;
252 b5ff1b31 bellard
    } else if (memsz >= 32) {
253 b5ff1b31 bellard
        integrator_spd[31] = 4;
254 b5ff1b31 bellard
        s->cm_sdram |= 0x04;
255 b5ff1b31 bellard
    } else {
256 b5ff1b31 bellard
        integrator_spd[31] = 2;
257 b5ff1b31 bellard
    }
258 b5ff1b31 bellard
    memcpy(integrator_spd + 73, "QEMU-MEMORY", 11);
259 b5ff1b31 bellard
    s->cm_init = 0x00000112;
260 b5ff1b31 bellard
    s->flash_offset = flash_offset;
261 b5ff1b31 bellard
262 b5ff1b31 bellard
    iomemtype = cpu_register_io_memory(0, integratorcm_readfn,
263 b5ff1b31 bellard
                                       integratorcm_writefn, s);
264 b5ff1b31 bellard
    cpu_register_physical_memory(0x10000000, 0x007fffff, iomemtype);
265 b5ff1b31 bellard
    integratorcm_do_remap(s, 1);
266 b5ff1b31 bellard
    /* ??? Save/restore.  */
267 b5ff1b31 bellard
}
268 b5ff1b31 bellard
269 b5ff1b31 bellard
/* Integrator/CP hardware emulation.  */
270 b5ff1b31 bellard
/* Primary interrupt controller.  */
271 b5ff1b31 bellard
272 b5ff1b31 bellard
typedef struct icp_pic_state
273 b5ff1b31 bellard
{
274 cdbdb648 pbrook
  arm_pic_handler handler;
275 b5ff1b31 bellard
  uint32_t base;
276 b5ff1b31 bellard
  uint32_t level;
277 b5ff1b31 bellard
  uint32_t irq_enabled;
278 b5ff1b31 bellard
  uint32_t fiq_enabled;
279 b5ff1b31 bellard
  void *parent;
280 b5ff1b31 bellard
  int parent_irq;
281 cdbdb648 pbrook
  int parent_fiq;
282 b5ff1b31 bellard
} icp_pic_state;
283 b5ff1b31 bellard
284 b5ff1b31 bellard
static void icp_pic_update(icp_pic_state *s)
285 b5ff1b31 bellard
{
286 cdbdb648 pbrook
    uint32_t flags;
287 b5ff1b31 bellard
288 cdbdb648 pbrook
    if (s->parent_irq != -1) {
289 b5ff1b31 bellard
        flags = (s->level & s->irq_enabled);
290 cdbdb648 pbrook
        pic_set_irq_new(s->parent, s->parent_irq, flags != 0);
291 b5ff1b31 bellard
    }
292 cdbdb648 pbrook
    if (s->parent_fiq != -1) {
293 cdbdb648 pbrook
        flags = (s->level & s->fiq_enabled);
294 cdbdb648 pbrook
        pic_set_irq_new(s->parent, s->parent_fiq, flags != 0);
295 b5ff1b31 bellard
    }
296 b5ff1b31 bellard
}
297 b5ff1b31 bellard
298 cdbdb648 pbrook
static void icp_pic_set_irq(void *opaque, int irq, int level)
299 b5ff1b31 bellard
{
300 80337b66 bellard
    icp_pic_state *s = (icp_pic_state *)opaque;
301 b5ff1b31 bellard
    if (level)
302 80337b66 bellard
        s->level |= 1 << irq;
303 b5ff1b31 bellard
    else
304 80337b66 bellard
        s->level &= ~(1 << irq);
305 b5ff1b31 bellard
    icp_pic_update(s);
306 b5ff1b31 bellard
}
307 b5ff1b31 bellard
308 b5ff1b31 bellard
static uint32_t icp_pic_read(void *opaque, target_phys_addr_t offset)
309 b5ff1b31 bellard
{
310 b5ff1b31 bellard
    icp_pic_state *s = (icp_pic_state *)opaque;
311 b5ff1b31 bellard
312 b5ff1b31 bellard
    offset -= s->base;
313 b5ff1b31 bellard
    switch (offset >> 2) {
314 b5ff1b31 bellard
    case 0: /* IRQ_STATUS */
315 b5ff1b31 bellard
        return s->level & s->irq_enabled;
316 b5ff1b31 bellard
    case 1: /* IRQ_RAWSTAT */
317 b5ff1b31 bellard
        return s->level;
318 b5ff1b31 bellard
    case 2: /* IRQ_ENABLESET */
319 b5ff1b31 bellard
        return s->irq_enabled;
320 b5ff1b31 bellard
    case 4: /* INT_SOFTSET */
321 b5ff1b31 bellard
        return s->level & 1;
322 b5ff1b31 bellard
    case 8: /* FRQ_STATUS */
323 b5ff1b31 bellard
        return s->level & s->fiq_enabled;
324 b5ff1b31 bellard
    case 9: /* FRQ_RAWSTAT */
325 b5ff1b31 bellard
        return s->level;
326 b5ff1b31 bellard
    case 10: /* FRQ_ENABLESET */
327 b5ff1b31 bellard
        return s->fiq_enabled;
328 b5ff1b31 bellard
    case 3: /* IRQ_ENABLECLR */
329 b5ff1b31 bellard
    case 5: /* INT_SOFTCLR */
330 b5ff1b31 bellard
    case 11: /* FRQ_ENABLECLR */
331 b5ff1b31 bellard
    default:
332 b5ff1b31 bellard
        printf ("icp_pic_read: Bad register offset 0x%x\n", offset);
333 b5ff1b31 bellard
        return 0;
334 b5ff1b31 bellard
    }
335 b5ff1b31 bellard
}
336 b5ff1b31 bellard
337 b5ff1b31 bellard
static void icp_pic_write(void *opaque, target_phys_addr_t offset,
338 b5ff1b31 bellard
                          uint32_t value)
339 b5ff1b31 bellard
{
340 b5ff1b31 bellard
    icp_pic_state *s = (icp_pic_state *)opaque;
341 b5ff1b31 bellard
    offset -= s->base;
342 b5ff1b31 bellard
343 b5ff1b31 bellard
    switch (offset >> 2) {
344 b5ff1b31 bellard
    case 2: /* IRQ_ENABLESET */
345 b5ff1b31 bellard
        s->irq_enabled |= value;
346 b5ff1b31 bellard
        break;
347 b5ff1b31 bellard
    case 3: /* IRQ_ENABLECLR */
348 b5ff1b31 bellard
        s->irq_enabled &= ~value;
349 b5ff1b31 bellard
        break;
350 b5ff1b31 bellard
    case 4: /* INT_SOFTSET */
351 b5ff1b31 bellard
        if (value & 1)
352 80337b66 bellard
            pic_set_irq_new(s, 0, 1);
353 b5ff1b31 bellard
        break;
354 b5ff1b31 bellard
    case 5: /* INT_SOFTCLR */
355 b5ff1b31 bellard
        if (value & 1)
356 80337b66 bellard
            pic_set_irq_new(s, 0, 0);
357 b5ff1b31 bellard
        break;
358 b5ff1b31 bellard
    case 10: /* FRQ_ENABLESET */
359 b5ff1b31 bellard
        s->fiq_enabled |= value;
360 b5ff1b31 bellard
        break;
361 b5ff1b31 bellard
    case 11: /* FRQ_ENABLECLR */
362 b5ff1b31 bellard
        s->fiq_enabled &= ~value;
363 b5ff1b31 bellard
        break;
364 b5ff1b31 bellard
    case 0: /* IRQ_STATUS */
365 b5ff1b31 bellard
    case 1: /* IRQ_RAWSTAT */
366 b5ff1b31 bellard
    case 8: /* FRQ_STATUS */
367 b5ff1b31 bellard
    case 9: /* FRQ_RAWSTAT */
368 b5ff1b31 bellard
    default:
369 b5ff1b31 bellard
        printf ("icp_pic_write: Bad register offset 0x%x\n", offset);
370 b5ff1b31 bellard
        return;
371 b5ff1b31 bellard
    }
372 b5ff1b31 bellard
    icp_pic_update(s);
373 b5ff1b31 bellard
}
374 b5ff1b31 bellard
375 b5ff1b31 bellard
static CPUReadMemoryFunc *icp_pic_readfn[] = {
376 b5ff1b31 bellard
   icp_pic_read,
377 b5ff1b31 bellard
   icp_pic_read,
378 b5ff1b31 bellard
   icp_pic_read
379 b5ff1b31 bellard
};
380 b5ff1b31 bellard
381 b5ff1b31 bellard
static CPUWriteMemoryFunc *icp_pic_writefn[] = {
382 b5ff1b31 bellard
   icp_pic_write,
383 b5ff1b31 bellard
   icp_pic_write,
384 b5ff1b31 bellard
   icp_pic_write
385 b5ff1b31 bellard
};
386 b5ff1b31 bellard
387 b5ff1b31 bellard
static icp_pic_state *icp_pic_init(uint32_t base, void *parent,
388 cdbdb648 pbrook
                                   int parent_irq, int parent_fiq)
389 b5ff1b31 bellard
{
390 b5ff1b31 bellard
    icp_pic_state *s;
391 b5ff1b31 bellard
    int iomemtype;
392 b5ff1b31 bellard
393 b5ff1b31 bellard
    s = (icp_pic_state *)qemu_mallocz(sizeof(icp_pic_state));
394 b5ff1b31 bellard
    if (!s)
395 b5ff1b31 bellard
        return NULL;
396 cdbdb648 pbrook
    s->handler = icp_pic_set_irq;
397 b5ff1b31 bellard
    s->base = base;
398 b5ff1b31 bellard
    s->parent = parent;
399 b5ff1b31 bellard
    s->parent_irq = parent_irq;
400 cdbdb648 pbrook
    s->parent_fiq = parent_fiq;
401 b5ff1b31 bellard
    iomemtype = cpu_register_io_memory(0, icp_pic_readfn,
402 b5ff1b31 bellard
                                       icp_pic_writefn, s);
403 b5ff1b31 bellard
    cpu_register_physical_memory(base, 0x007fffff, iomemtype);
404 b5ff1b31 bellard
    /* ??? Save/restore.  */
405 b5ff1b31 bellard
    return s;
406 b5ff1b31 bellard
}
407 b5ff1b31 bellard
408 b5ff1b31 bellard
/* CP control registers.  */
409 b5ff1b31 bellard
typedef struct {
410 b5ff1b31 bellard
    uint32_t base;
411 b5ff1b31 bellard
} icp_control_state;
412 b5ff1b31 bellard
413 b5ff1b31 bellard
static uint32_t icp_control_read(void *opaque, target_phys_addr_t offset)
414 b5ff1b31 bellard
{
415 b5ff1b31 bellard
    icp_control_state *s = (icp_control_state *)opaque;
416 b5ff1b31 bellard
    offset -= s->base;
417 b5ff1b31 bellard
    switch (offset >> 2) {
418 b5ff1b31 bellard
    case 0: /* CP_IDFIELD */
419 b5ff1b31 bellard
        return 0x41034003;
420 b5ff1b31 bellard
    case 1: /* CP_FLASHPROG */
421 b5ff1b31 bellard
        return 0;
422 b5ff1b31 bellard
    case 2: /* CP_INTREG */
423 b5ff1b31 bellard
        return 0;
424 b5ff1b31 bellard
    case 3: /* CP_DECODE */
425 b5ff1b31 bellard
        return 0x11;
426 b5ff1b31 bellard
    default:
427 b5ff1b31 bellard
        cpu_abort (cpu_single_env, "icp_control_read: Bad offset %x\n", offset);
428 b5ff1b31 bellard
        return 0;
429 b5ff1b31 bellard
    }
430 b5ff1b31 bellard
}
431 b5ff1b31 bellard
432 b5ff1b31 bellard
static void icp_control_write(void *opaque, target_phys_addr_t offset,
433 b5ff1b31 bellard
                          uint32_t value)
434 b5ff1b31 bellard
{
435 b5ff1b31 bellard
    icp_control_state *s = (icp_control_state *)opaque;
436 b5ff1b31 bellard
    offset -= s->base;
437 b5ff1b31 bellard
    switch (offset >> 2) {
438 b5ff1b31 bellard
    case 1: /* CP_FLASHPROG */
439 b5ff1b31 bellard
    case 2: /* CP_INTREG */
440 b5ff1b31 bellard
    case 3: /* CP_DECODE */
441 b5ff1b31 bellard
        /* Nothing interesting implemented yet.  */
442 b5ff1b31 bellard
        break;
443 b5ff1b31 bellard
    default:
444 b5ff1b31 bellard
        cpu_abort (cpu_single_env, "icp_control_write: Bad offset %x\n", offset);
445 b5ff1b31 bellard
    }
446 b5ff1b31 bellard
}
447 b5ff1b31 bellard
static CPUReadMemoryFunc *icp_control_readfn[] = {
448 b5ff1b31 bellard
   icp_control_read,
449 b5ff1b31 bellard
   icp_control_read,
450 b5ff1b31 bellard
   icp_control_read
451 b5ff1b31 bellard
};
452 b5ff1b31 bellard
453 b5ff1b31 bellard
static CPUWriteMemoryFunc *icp_control_writefn[] = {
454 b5ff1b31 bellard
   icp_control_write,
455 b5ff1b31 bellard
   icp_control_write,
456 b5ff1b31 bellard
   icp_control_write
457 b5ff1b31 bellard
};
458 b5ff1b31 bellard
459 b5ff1b31 bellard
static void icp_control_init(uint32_t base)
460 b5ff1b31 bellard
{
461 b5ff1b31 bellard
    int iomemtype;
462 b5ff1b31 bellard
    icp_control_state *s;
463 b5ff1b31 bellard
464 b5ff1b31 bellard
    s = (icp_control_state *)qemu_mallocz(sizeof(icp_control_state));
465 b5ff1b31 bellard
    iomemtype = cpu_register_io_memory(0, icp_control_readfn,
466 b5ff1b31 bellard
                                       icp_control_writefn, s);
467 b5ff1b31 bellard
    cpu_register_physical_memory(base, 0x007fffff, iomemtype);
468 b5ff1b31 bellard
    s->base = base;
469 b5ff1b31 bellard
    /* ??? Save/restore.  */
470 b5ff1b31 bellard
}
471 b5ff1b31 bellard
472 b5ff1b31 bellard
473 b5ff1b31 bellard
/* The worlds second smallest bootloader.  Set r0-r2, then jump to kernel.  */
474 b5ff1b31 bellard
static uint32_t bootloader[] = {
475 b5ff1b31 bellard
  0xe3a00000, /* mov     r0, #0 */
476 b5ff1b31 bellard
  0xe3a01013, /* mov     r1, #0x13 */
477 b5ff1b31 bellard
  0xe3811c01, /* orr     r1, r1, #0x100 */
478 b5ff1b31 bellard
  0xe59f2000, /* ldr     r2, [pc, #0] */
479 b5ff1b31 bellard
  0xe59ff000, /* ldr     pc, [pc, #0] */
480 b5ff1b31 bellard
  0, /* Address of kernel args.  Set by integratorcp_init.  */
481 b5ff1b31 bellard
  0  /* Kernel entry point.  Set by integratorcp_init.  */
482 b5ff1b31 bellard
};
483 b5ff1b31 bellard
484 b5ff1b31 bellard
static void set_kernel_args(uint32_t ram_size, int initrd_size,
485 b5ff1b31 bellard
                            const char *kernel_cmdline)
486 b5ff1b31 bellard
{
487 b5ff1b31 bellard
    uint32_t *p;
488 b5ff1b31 bellard
489 b5ff1b31 bellard
    p = (uint32_t *)(phys_ram_base + KERNEL_ARGS_ADDR);
490 b5ff1b31 bellard
    /* ATAG_CORE */
491 24201115 pbrook
    stl_raw(p++, 5);
492 24201115 pbrook
    stl_raw(p++, 0x54410001);
493 24201115 pbrook
    stl_raw(p++, 1);
494 24201115 pbrook
    stl_raw(p++, 0x1000);
495 24201115 pbrook
    stl_raw(p++, 0);
496 b5ff1b31 bellard
    /* ATAG_MEM */
497 24201115 pbrook
    stl_raw(p++, 4);
498 24201115 pbrook
    stl_raw(p++, 0x54410002);
499 24201115 pbrook
    stl_raw(p++, ram_size);
500 24201115 pbrook
    stl_raw(p++, 0);
501 b5ff1b31 bellard
    if (initrd_size) {
502 b5ff1b31 bellard
        /* ATAG_INITRD2 */
503 24201115 pbrook
        stl_raw(p++, 4);
504 24201115 pbrook
        stl_raw(p++, 0x54420005);
505 24201115 pbrook
        stl_raw(p++, INITRD_LOAD_ADDR);
506 24201115 pbrook
        stl_raw(p++, initrd_size);
507 b5ff1b31 bellard
    }
508 b5ff1b31 bellard
    if (kernel_cmdline && *kernel_cmdline) {
509 b5ff1b31 bellard
        /* ATAG_CMDLINE */
510 b5ff1b31 bellard
        int cmdline_size;
511 b5ff1b31 bellard
512 b5ff1b31 bellard
        cmdline_size = strlen(kernel_cmdline);
513 b5ff1b31 bellard
        memcpy (p + 2, kernel_cmdline, cmdline_size + 1);
514 b5ff1b31 bellard
        cmdline_size = (cmdline_size >> 2) + 1;
515 24201115 pbrook
        stl_raw(p++, cmdline_size + 2);
516 24201115 pbrook
        stl_raw(p++, 0x54410009);
517 b5ff1b31 bellard
        p += cmdline_size;
518 b5ff1b31 bellard
    }
519 b5ff1b31 bellard
    /* ATAG_END */
520 24201115 pbrook
    stl_raw(p++, 0);
521 24201115 pbrook
    stl_raw(p++, 0);
522 b5ff1b31 bellard
}
523 b5ff1b31 bellard
524 b5ff1b31 bellard
/* Board init.  */
525 b5ff1b31 bellard
526 b5ff1b31 bellard
static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device,
527 b5ff1b31 bellard
                     DisplayState *ds, const char **fd_filename, int snapshot,
528 b5ff1b31 bellard
                     const char *kernel_filename, const char *kernel_cmdline,
529 40f137e1 pbrook
                     const char *initrd_filename, uint32_t cpuid)
530 b5ff1b31 bellard
{
531 b5ff1b31 bellard
    CPUState *env;
532 b5ff1b31 bellard
    uint32_t bios_offset;
533 b5ff1b31 bellard
    icp_pic_state *pic;
534 cdbdb648 pbrook
    void *cpu_pic;
535 b5ff1b31 bellard
    int kernel_size;
536 b5ff1b31 bellard
    int initrd_size;
537 24201115 pbrook
    int n;
538 b5ff1b31 bellard
539 b5ff1b31 bellard
    env = cpu_init();
540 40f137e1 pbrook
    cpu_arm_set_model(env, cpuid);
541 b5ff1b31 bellard
    bios_offset = ram_size + vga_ram_size;
542 b5ff1b31 bellard
    /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
543 b5ff1b31 bellard
    /* ??? RAM shoud repeat to fill physical memory space.  */
544 b5ff1b31 bellard
    /* SDRAM at address zero*/
545 b5ff1b31 bellard
    cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
546 b5ff1b31 bellard
    /* And again at address 0x80000000 */
547 b5ff1b31 bellard
    cpu_register_physical_memory(0x80000000, ram_size, IO_MEM_RAM);
548 b5ff1b31 bellard
549 b5ff1b31 bellard
    integratorcm_init(ram_size >> 20, bios_offset);
550 cdbdb648 pbrook
    cpu_pic = arm_pic_init_cpu(env);
551 cdbdb648 pbrook
    pic = icp_pic_init(0x14000000, cpu_pic, ARM_PIC_CPU_IRQ, ARM_PIC_CPU_FIQ);
552 cdbdb648 pbrook
    icp_pic_init(0xca000000, pic, 26, -1);
553 cdbdb648 pbrook
    icp_pit_init(0x13000000, pic, 5);
554 b5ff1b31 bellard
    pl011_init(0x16000000, pic, 1, serial_hds[0]);
555 b5ff1b31 bellard
    pl011_init(0x17000000, pic, 2, serial_hds[1]);
556 b5ff1b31 bellard
    icp_control_init(0xcb000000);
557 cdbdb648 pbrook
    pl050_init(0x18000000, pic, 3, 0);
558 cdbdb648 pbrook
    pl050_init(0x19000000, pic, 4, 1);
559 a41b2ff2 pbrook
    if (nd_table[0].vlan) {
560 a41b2ff2 pbrook
        if (nd_table[0].model == NULL
561 a41b2ff2 pbrook
            || strcmp(nd_table[0].model, "smc91c111") == 0) {
562 a41b2ff2 pbrook
            smc91c111_init(&nd_table[0], 0xc8000000, pic, 27);
563 a41b2ff2 pbrook
        } else {
564 a41b2ff2 pbrook
            fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
565 a41b2ff2 pbrook
            exit (1);
566 a41b2ff2 pbrook
        }
567 a41b2ff2 pbrook
    }
568 95219897 pbrook
    pl110_init(ds, 0xc0000000, pic, 22, 0);
569 b5ff1b31 bellard
570 b5ff1b31 bellard
    /* Load the kernel.  */
571 b5ff1b31 bellard
    if (!kernel_filename) {
572 b5ff1b31 bellard
        fprintf(stderr, "Kernel image must be specified\n");
573 b5ff1b31 bellard
        exit(1);
574 b5ff1b31 bellard
    }
575 b5ff1b31 bellard
    kernel_size = load_image(kernel_filename,
576 b5ff1b31 bellard
                             phys_ram_base + KERNEL_LOAD_ADDR);
577 b5ff1b31 bellard
    if (kernel_size < 0) {
578 b5ff1b31 bellard
        fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
579 b5ff1b31 bellard
        exit(1);
580 b5ff1b31 bellard
    }
581 b5ff1b31 bellard
    if (initrd_filename) {
582 b5ff1b31 bellard
        initrd_size = load_image(initrd_filename,
583 b5ff1b31 bellard
                                 phys_ram_base + INITRD_LOAD_ADDR);
584 b5ff1b31 bellard
        if (initrd_size < 0) {
585 b5ff1b31 bellard
            fprintf(stderr, "qemu: could not load initrd '%s'\n",
586 b5ff1b31 bellard
                    initrd_filename);
587 b5ff1b31 bellard
            exit(1);
588 b5ff1b31 bellard
        }
589 b5ff1b31 bellard
    } else {
590 b5ff1b31 bellard
        initrd_size = 0;
591 b5ff1b31 bellard
    }
592 b5ff1b31 bellard
    bootloader[5] = KERNEL_ARGS_ADDR;
593 b5ff1b31 bellard
    bootloader[6] = KERNEL_LOAD_ADDR;
594 24201115 pbrook
    for (n = 0; n < sizeof(bootloader) / 4; n++)
595 24201115 pbrook
        stl_raw(phys_ram_base + (n * 4), bootloader[n]);
596 b5ff1b31 bellard
    set_kernel_args(ram_size, initrd_size, kernel_cmdline);
597 b5ff1b31 bellard
}
598 b5ff1b31 bellard
599 40f137e1 pbrook
static void integratorcp926_init(int ram_size, int vga_ram_size,
600 40f137e1 pbrook
    int boot_device, DisplayState *ds, const char **fd_filename, int snapshot,
601 40f137e1 pbrook
    const char *kernel_filename, const char *kernel_cmdline,
602 40f137e1 pbrook
    const char *initrd_filename)
603 40f137e1 pbrook
{
604 40f137e1 pbrook
    integratorcp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
605 40f137e1 pbrook
                      snapshot, kernel_filename, kernel_cmdline,
606 40f137e1 pbrook
                      initrd_filename, ARM_CPUID_ARM926);
607 40f137e1 pbrook
}
608 40f137e1 pbrook
609 40f137e1 pbrook
static void integratorcp1026_init(int ram_size, int vga_ram_size,
610 40f137e1 pbrook
    int boot_device, DisplayState *ds, const char **fd_filename, int snapshot,
611 40f137e1 pbrook
    const char *kernel_filename, const char *kernel_cmdline,
612 40f137e1 pbrook
    const char *initrd_filename)
613 40f137e1 pbrook
{
614 40f137e1 pbrook
    integratorcp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
615 40f137e1 pbrook
                      snapshot, kernel_filename, kernel_cmdline,
616 40f137e1 pbrook
                      initrd_filename, ARM_CPUID_ARM1026);
617 40f137e1 pbrook
}
618 40f137e1 pbrook
619 40f137e1 pbrook
QEMUMachine integratorcp926_machine = {
620 40f137e1 pbrook
    "integratorcp926",
621 40f137e1 pbrook
    "ARM Integrator/CP (ARM926EJ-S)",
622 40f137e1 pbrook
    integratorcp926_init,
623 40f137e1 pbrook
};
624 40f137e1 pbrook
625 40f137e1 pbrook
QEMUMachine integratorcp1026_machine = {
626 40f137e1 pbrook
    "integratorcp1026",
627 40f137e1 pbrook
    "ARM Integrator/CP (ARM1026EJ-S)",
628 40f137e1 pbrook
    integratorcp1026_init,
629 b5ff1b31 bellard
};