Statistics
| Branch: | Revision:

root / hw / integratorcp.c @ f76e1d81

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