Statistics
| Branch: | Revision:

root / hw / integratorcp.c @ 71d9bc50

History | View | Annotate | Download (15.7 kB)

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