Statistics
| Branch: | Revision:

root / hw / integratorcp.c @ cde844fa

History | View | Annotate | Download (15.6 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 61074e46 Benoît Canet
  MemoryRegion iomem;
283 b5ff1b31 bellard
  uint32_t level;
284 b5ff1b31 bellard
  uint32_t irq_enabled;
285 b5ff1b31 bellard
  uint32_t fiq_enabled;
286 d537cf6c pbrook
  qemu_irq parent_irq;
287 d537cf6c pbrook
  qemu_irq parent_fiq;
288 b5ff1b31 bellard
} icp_pic_state;
289 b5ff1b31 bellard
290 b5ff1b31 bellard
static void icp_pic_update(icp_pic_state *s)
291 b5ff1b31 bellard
{
292 cdbdb648 pbrook
    uint32_t flags;
293 b5ff1b31 bellard
294 d537cf6c pbrook
    flags = (s->level & s->irq_enabled);
295 d537cf6c pbrook
    qemu_set_irq(s->parent_irq, flags != 0);
296 d537cf6c pbrook
    flags = (s->level & s->fiq_enabled);
297 d537cf6c pbrook
    qemu_set_irq(s->parent_fiq, flags != 0);
298 b5ff1b31 bellard
}
299 b5ff1b31 bellard
300 cdbdb648 pbrook
static void icp_pic_set_irq(void *opaque, int irq, int level)
301 b5ff1b31 bellard
{
302 80337b66 bellard
    icp_pic_state *s = (icp_pic_state *)opaque;
303 b5ff1b31 bellard
    if (level)
304 80337b66 bellard
        s->level |= 1 << irq;
305 b5ff1b31 bellard
    else
306 80337b66 bellard
        s->level &= ~(1 << irq);
307 b5ff1b31 bellard
    icp_pic_update(s);
308 b5ff1b31 bellard
}
309 b5ff1b31 bellard
310 61074e46 Benoît Canet
static uint64_t icp_pic_read(void *opaque, target_phys_addr_t offset,
311 61074e46 Benoît Canet
                             unsigned size)
312 b5ff1b31 bellard
{
313 b5ff1b31 bellard
    icp_pic_state *s = (icp_pic_state *)opaque;
314 b5ff1b31 bellard
315 b5ff1b31 bellard
    switch (offset >> 2) {
316 b5ff1b31 bellard
    case 0: /* IRQ_STATUS */
317 b5ff1b31 bellard
        return s->level & s->irq_enabled;
318 b5ff1b31 bellard
    case 1: /* IRQ_RAWSTAT */
319 b5ff1b31 bellard
        return s->level;
320 b5ff1b31 bellard
    case 2: /* IRQ_ENABLESET */
321 b5ff1b31 bellard
        return s->irq_enabled;
322 b5ff1b31 bellard
    case 4: /* INT_SOFTSET */
323 b5ff1b31 bellard
        return s->level & 1;
324 b5ff1b31 bellard
    case 8: /* FRQ_STATUS */
325 b5ff1b31 bellard
        return s->level & s->fiq_enabled;
326 b5ff1b31 bellard
    case 9: /* FRQ_RAWSTAT */
327 b5ff1b31 bellard
        return s->level;
328 b5ff1b31 bellard
    case 10: /* FRQ_ENABLESET */
329 b5ff1b31 bellard
        return s->fiq_enabled;
330 b5ff1b31 bellard
    case 3: /* IRQ_ENABLECLR */
331 b5ff1b31 bellard
    case 5: /* INT_SOFTCLR */
332 b5ff1b31 bellard
    case 11: /* FRQ_ENABLECLR */
333 b5ff1b31 bellard
    default:
334 29bfb117 pbrook
        printf ("icp_pic_read: Bad register offset 0x%x\n", (int)offset);
335 b5ff1b31 bellard
        return 0;
336 b5ff1b31 bellard
    }
337 b5ff1b31 bellard
}
338 b5ff1b31 bellard
339 c227f099 Anthony Liguori
static void icp_pic_write(void *opaque, target_phys_addr_t offset,
340 61074e46 Benoît Canet
                          uint64_t value, unsigned size)
341 b5ff1b31 bellard
{
342 b5ff1b31 bellard
    icp_pic_state *s = (icp_pic_state *)opaque;
343 b5ff1b31 bellard
344 b5ff1b31 bellard
    switch (offset >> 2) {
345 b5ff1b31 bellard
    case 2: /* IRQ_ENABLESET */
346 b5ff1b31 bellard
        s->irq_enabled |= value;
347 b5ff1b31 bellard
        break;
348 b5ff1b31 bellard
    case 3: /* IRQ_ENABLECLR */
349 b5ff1b31 bellard
        s->irq_enabled &= ~value;
350 b5ff1b31 bellard
        break;
351 b5ff1b31 bellard
    case 4: /* INT_SOFTSET */
352 b5ff1b31 bellard
        if (value & 1)
353 d537cf6c pbrook
            icp_pic_set_irq(s, 0, 1);
354 b5ff1b31 bellard
        break;
355 b5ff1b31 bellard
    case 5: /* INT_SOFTCLR */
356 b5ff1b31 bellard
        if (value & 1)
357 d537cf6c pbrook
            icp_pic_set_irq(s, 0, 0);
358 b5ff1b31 bellard
        break;
359 b5ff1b31 bellard
    case 10: /* FRQ_ENABLESET */
360 b5ff1b31 bellard
        s->fiq_enabled |= value;
361 b5ff1b31 bellard
        break;
362 b5ff1b31 bellard
    case 11: /* FRQ_ENABLECLR */
363 b5ff1b31 bellard
        s->fiq_enabled &= ~value;
364 b5ff1b31 bellard
        break;
365 b5ff1b31 bellard
    case 0: /* IRQ_STATUS */
366 b5ff1b31 bellard
    case 1: /* IRQ_RAWSTAT */
367 b5ff1b31 bellard
    case 8: /* FRQ_STATUS */
368 b5ff1b31 bellard
    case 9: /* FRQ_RAWSTAT */
369 b5ff1b31 bellard
    default:
370 29bfb117 pbrook
        printf ("icp_pic_write: Bad register offset 0x%x\n", (int)offset);
371 b5ff1b31 bellard
        return;
372 b5ff1b31 bellard
    }
373 b5ff1b31 bellard
    icp_pic_update(s);
374 b5ff1b31 bellard
}
375 b5ff1b31 bellard
376 61074e46 Benoît Canet
static const MemoryRegionOps icp_pic_ops = {
377 61074e46 Benoît Canet
    .read = icp_pic_read,
378 61074e46 Benoît Canet
    .write = icp_pic_write,
379 61074e46 Benoît Canet
    .endianness = DEVICE_NATIVE_ENDIAN,
380 b5ff1b31 bellard
};
381 b5ff1b31 bellard
382 81a322d4 Gerd Hoffmann
static int icp_pic_init(SysBusDevice *dev)
383 b5ff1b31 bellard
{
384 a7086888 Paul Brook
    icp_pic_state *s = FROM_SYSBUS(icp_pic_state, dev);
385 b5ff1b31 bellard
386 067a3ddc Paul Brook
    qdev_init_gpio_in(&dev->qdev, icp_pic_set_irq, 32);
387 a7086888 Paul Brook
    sysbus_init_irq(dev, &s->parent_irq);
388 a7086888 Paul Brook
    sysbus_init_irq(dev, &s->parent_fiq);
389 61074e46 Benoît Canet
    memory_region_init_io(&s->iomem, &icp_pic_ops, s, "icp-pic", 0x00800000);
390 61074e46 Benoît Canet
    sysbus_init_mmio_region(dev, &s->iomem);
391 81a322d4 Gerd Hoffmann
    return 0;
392 b5ff1b31 bellard
}
393 b5ff1b31 bellard
394 b5ff1b31 bellard
/* CP control registers.  */
395 0c36493e Benoît Canet
396 0c36493e Benoît Canet
static uint64_t icp_control_read(void *opaque, target_phys_addr_t offset,
397 0c36493e Benoît Canet
                                 unsigned size)
398 b5ff1b31 bellard
{
399 b5ff1b31 bellard
    switch (offset >> 2) {
400 b5ff1b31 bellard
    case 0: /* CP_IDFIELD */
401 b5ff1b31 bellard
        return 0x41034003;
402 b5ff1b31 bellard
    case 1: /* CP_FLASHPROG */
403 b5ff1b31 bellard
        return 0;
404 b5ff1b31 bellard
    case 2: /* CP_INTREG */
405 b5ff1b31 bellard
        return 0;
406 b5ff1b31 bellard
    case 3: /* CP_DECODE */
407 b5ff1b31 bellard
        return 0x11;
408 b5ff1b31 bellard
    default:
409 2ac71179 Paul Brook
        hw_error("icp_control_read: Bad offset %x\n", (int)offset);
410 b5ff1b31 bellard
        return 0;
411 b5ff1b31 bellard
    }
412 b5ff1b31 bellard
}
413 b5ff1b31 bellard
414 c227f099 Anthony Liguori
static void icp_control_write(void *opaque, target_phys_addr_t offset,
415 0c36493e Benoît Canet
                          uint64_t value, unsigned size)
416 b5ff1b31 bellard
{
417 b5ff1b31 bellard
    switch (offset >> 2) {
418 b5ff1b31 bellard
    case 1: /* CP_FLASHPROG */
419 b5ff1b31 bellard
    case 2: /* CP_INTREG */
420 b5ff1b31 bellard
    case 3: /* CP_DECODE */
421 b5ff1b31 bellard
        /* Nothing interesting implemented yet.  */
422 b5ff1b31 bellard
        break;
423 b5ff1b31 bellard
    default:
424 2ac71179 Paul Brook
        hw_error("icp_control_write: Bad offset %x\n", (int)offset);
425 b5ff1b31 bellard
    }
426 b5ff1b31 bellard
}
427 b5ff1b31 bellard
428 0c36493e Benoît Canet
static const MemoryRegionOps icp_control_ops = {
429 0c36493e Benoît Canet
    .read = icp_control_read,
430 0c36493e Benoît Canet
    .write = icp_control_write,
431 0c36493e Benoît Canet
    .endianness = DEVICE_NATIVE_ENDIAN,
432 b5ff1b31 bellard
};
433 b5ff1b31 bellard
434 0c36493e Benoît Canet
static void icp_control_init(target_phys_addr_t base)
435 b5ff1b31 bellard
{
436 0c36493e Benoît Canet
    MemoryRegion *io;
437 b5ff1b31 bellard
438 0c36493e Benoît Canet
    io = (MemoryRegion *)g_malloc0(sizeof(MemoryRegion));
439 0c36493e Benoît Canet
    memory_region_init_io(io, &icp_control_ops, NULL,
440 0c36493e Benoît Canet
                          "control", 0x00800000);
441 0c36493e Benoît Canet
    memory_region_add_subregion(get_system_memory(), base, io);
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 211adf4d Avi Kivity
    MemoryRegion *address_space_mem = get_system_memory();
460 211adf4d Avi Kivity
    MemoryRegion *ram = g_new(MemoryRegion, 1);
461 211adf4d Avi Kivity
    MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
462 a7086888 Paul Brook
    qemu_irq pic[32];
463 d537cf6c pbrook
    qemu_irq *cpu_pic;
464 a7086888 Paul Brook
    DeviceState *dev;
465 a7086888 Paul Brook
    int i;
466 b5ff1b31 bellard
467 3371d272 pbrook
    if (!cpu_model)
468 3371d272 pbrook
        cpu_model = "arm926";
469 aaed909a bellard
    env = cpu_init(cpu_model);
470 aaed909a bellard
    if (!env) {
471 aaed909a bellard
        fprintf(stderr, "Unable to find CPU definition\n");
472 aaed909a bellard
        exit(1);
473 aaed909a bellard
    }
474 211adf4d Avi Kivity
    memory_region_init_ram(ram, NULL, "integrator.ram", ram_size);
475 b5ff1b31 bellard
    /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
476 1235fc06 ths
    /* ??? RAM should repeat to fill physical memory space.  */
477 b5ff1b31 bellard
    /* SDRAM at address zero*/
478 211adf4d Avi Kivity
    memory_region_add_subregion(address_space_mem, 0, ram);
479 b5ff1b31 bellard
    /* And again at address 0x80000000 */
480 211adf4d Avi Kivity
    memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size);
481 211adf4d Avi Kivity
    memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias);
482 b5ff1b31 bellard
483 a7086888 Paul Brook
    dev = qdev_create(NULL, "integrator_core");
484 ee6847d1 Gerd Hoffmann
    qdev_prop_set_uint32(dev, "memsz", ram_size >> 20);
485 e23a1b33 Markus Armbruster
    qdev_init_nofail(dev);
486 a7086888 Paul Brook
    sysbus_mmio_map((SysBusDevice *)dev, 0, 0x10000000);
487 a7086888 Paul Brook
488 cdbdb648 pbrook
    cpu_pic = arm_pic_init_cpu(env);
489 a7086888 Paul Brook
    dev = sysbus_create_varargs("integrator_pic", 0x14000000,
490 a7086888 Paul Brook
                                cpu_pic[ARM_PIC_CPU_IRQ],
491 a7086888 Paul Brook
                                cpu_pic[ARM_PIC_CPU_FIQ], NULL);
492 a7086888 Paul Brook
    for (i = 0; i < 32; i++) {
493 067a3ddc Paul Brook
        pic[i] = qdev_get_gpio_in(dev, i);
494 a7086888 Paul Brook
    }
495 6a824ec3 Paul Brook
    sysbus_create_simple("integrator_pic", 0xca000000, pic[26]);
496 6a824ec3 Paul Brook
    sysbus_create_varargs("integrator_pit", 0x13000000,
497 6a824ec3 Paul Brook
                          pic[5], pic[6], pic[7], NULL);
498 a63bdb31 Paul Brook
    sysbus_create_simple("pl031", 0x15000000, pic[8]);
499 a7d518a6 Paul Brook
    sysbus_create_simple("pl011", 0x16000000, pic[1]);
500 a7d518a6 Paul Brook
    sysbus_create_simple("pl011", 0x17000000, pic[2]);
501 b5ff1b31 bellard
    icp_control_init(0xcb000000);
502 86394e96 Paul Brook
    sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
503 86394e96 Paul Brook
    sysbus_create_simple("pl050_mouse", 0x19000000, pic[4]);
504 aa9311d8 Paul Brook
    sysbus_create_varargs("pl181", 0x1c000000, pic[23], pic[24], NULL);
505 0ae18cee aliguori
    if (nd_table[0].vlan)
506 0ae18cee aliguori
        smc91c111_init(&nd_table[0], 0xc8000000, pic[27]);
507 2e9bdce5 Paul Brook
508 2e9bdce5 Paul Brook
    sysbus_create_simple("pl110", 0xc0000000, pic[22]);
509 b5ff1b31 bellard
510 f93eb9ff balrog
    integrator_binfo.ram_size = ram_size;
511 f93eb9ff balrog
    integrator_binfo.kernel_filename = kernel_filename;
512 f93eb9ff balrog
    integrator_binfo.kernel_cmdline = kernel_cmdline;
513 f93eb9ff balrog
    integrator_binfo.initrd_filename = initrd_filename;
514 f93eb9ff balrog
    arm_load_kernel(env, &integrator_binfo);
515 b5ff1b31 bellard
}
516 b5ff1b31 bellard
517 f80f9ec9 Anthony Liguori
static QEMUMachine integratorcp_machine = {
518 4b32e168 aliguori
    .name = "integratorcp",
519 4b32e168 aliguori
    .desc = "ARM Integrator/CP (ARM926EJ-S)",
520 4b32e168 aliguori
    .init = integratorcp_init,
521 0c257437 Anthony Liguori
    .is_default = 1,
522 b5ff1b31 bellard
};
523 a7086888 Paul Brook
524 f80f9ec9 Anthony Liguori
static void integratorcp_machine_init(void)
525 f80f9ec9 Anthony Liguori
{
526 f80f9ec9 Anthony Liguori
    qemu_register_machine(&integratorcp_machine);
527 f80f9ec9 Anthony Liguori
}
528 f80f9ec9 Anthony Liguori
529 f80f9ec9 Anthony Liguori
machine_init(integratorcp_machine_init);
530 f80f9ec9 Anthony Liguori
531 ee6847d1 Gerd Hoffmann
static SysBusDeviceInfo core_info = {
532 ee6847d1 Gerd Hoffmann
    .init = integratorcm_init,
533 ee6847d1 Gerd Hoffmann
    .qdev.name  = "integrator_core",
534 ee6847d1 Gerd Hoffmann
    .qdev.size  = sizeof(integratorcm_state),
535 ee6847d1 Gerd Hoffmann
    .qdev.props = (Property[]) {
536 bb36f66a Gerd Hoffmann
        DEFINE_PROP_UINT32("memsz", integratorcm_state, memsz, 0),
537 bb36f66a Gerd Hoffmann
        DEFINE_PROP_END_OF_LIST(),
538 ee6847d1 Gerd Hoffmann
    }
539 ee6847d1 Gerd Hoffmann
};
540 ee6847d1 Gerd Hoffmann
541 a7086888 Paul Brook
static void integratorcp_register_devices(void)
542 a7086888 Paul Brook
{
543 a7086888 Paul Brook
    sysbus_register_dev("integrator_pic", sizeof(icp_pic_state), icp_pic_init);
544 ee6847d1 Gerd Hoffmann
    sysbus_register_withprop(&core_info);
545 a7086888 Paul Brook
}
546 a7086888 Paul Brook
547 a7086888 Paul Brook
device_init(integratorcp_register_devices)