Revision f7c70325 hw/mpcore.c

b/hw/mpcore.c
1 1
/*
2
 * ARM MPCore internal peripheral emulation.
2
 * ARM MPCore internal peripheral emulation (common code).
3 3
 *
4 4
 * Copyright (c) 2006-2007 CodeSourcery.
5 5
 * Written by Paul Brook
......
10 10
#include "sysbus.h"
11 11
#include "qemu-timer.h"
12 12

  
13
#define MPCORE_PRIV_BASE  0x10100000
14 13
#define NCPU 4
15
/* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
16
   (+ 32 internal).  However my test chip only exposes/reports 32.
17
   More importantly Linux falls over if more than 32 are present!  */
18
#define GIC_NIRQ 64
19 14

  
20 15
static inline int
21 16
gic_get_current_cpu(void)
......
288 283
    }
289 284
    return 0;
290 285
}
291

  
292
/* Dummy PIC to route IRQ lines.  The baseboard has 4 independent IRQ
293
   controllers.  The output of these, plus some of the raw input lines
294
   are fed into a single SMP-aware interrupt controller on the CPU.  */
295
typedef struct {
296
    SysBusDevice busdev;
297
    qemu_irq cpuic[32];
298
    qemu_irq rvic[4][64];
299
    uint32_t num_cpu;
300
} mpcore_rirq_state;
301

  
302
/* Map baseboard IRQs onto CPU IRQ lines.  */
303
static const int mpcore_irq_map[32] = {
304
    -1, -1, -1, -1,  1,  2, -1, -1,
305
    -1, -1,  6, -1,  4,  5, -1, -1,
306
    -1, 14, 15,  0,  7,  8, -1, -1,
307
    -1, -1, -1, -1,  9,  3, -1, -1,
308
};
309

  
310
static void mpcore_rirq_set_irq(void *opaque, int irq, int level)
311
{
312
    mpcore_rirq_state *s = (mpcore_rirq_state *)opaque;
313
    int i;
314

  
315
    for (i = 0; i < 4; i++) {
316
        qemu_set_irq(s->rvic[i][irq], level);
317
    }
318
    if (irq < 32) {
319
        irq = mpcore_irq_map[irq];
320
        if (irq >= 0) {
321
            qemu_set_irq(s->cpuic[irq], level);
322
        }
323
    }
324
}
325

  
326
static int realview_mpcore_init(SysBusDevice *dev)
327
{
328
    mpcore_rirq_state *s = FROM_SYSBUS(mpcore_rirq_state, dev);
329
    DeviceState *gic;
330
    DeviceState *priv;
331
    SysBusDevice *bus_priv;
332
    int n;
333
    int i;
334

  
335
    priv = qdev_create(NULL, "arm11mpcore_priv");
336
    qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu);
337
    qdev_init_nofail(priv);
338
    bus_priv = sysbus_from_qdev(priv);
339
    sysbus_mmio_map(bus_priv, 0, MPCORE_PRIV_BASE);
340
    sysbus_pass_irq(dev, bus_priv);
341
    for (i = 0; i < 32; i++) {
342
        s->cpuic[i] = qdev_get_gpio_in(priv, i);
343
    }
344
    /* ??? IRQ routing is hardcoded to "normal" mode.  */
345
    for (n = 0; n < 4; n++) {
346
        gic = sysbus_create_simple("realview_gic", 0x10040000 + n * 0x10000,
347
                                   s->cpuic[10 + n]);
348
        for (i = 0; i < 64; i++) {
349
            s->rvic[n][i] = qdev_get_gpio_in(gic, i);
350
        }
351
    }
352
    qdev_init_gpio_in(&dev->qdev, mpcore_rirq_set_irq, 64);
353
    return 0;
354
}
355

  
356
static SysBusDeviceInfo mpcore_rirq_info = {
357
    .init = realview_mpcore_init,
358
    .qdev.name  = "realview_mpcore",
359
    .qdev.size  = sizeof(mpcore_rirq_state),
360
    .qdev.props = (Property[]) {
361
        DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1),
362
        DEFINE_PROP_END_OF_LIST(),
363
    }
364
};
365

  
366
static SysBusDeviceInfo mpcore_priv_info = {
367
    .init = mpcore_priv_init,
368
    .qdev.name  = "arm11mpcore_priv",
369
    .qdev.size  = sizeof(mpcore_priv_state),
370
    .qdev.props = (Property[]) {
371
        DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
372
        DEFINE_PROP_END_OF_LIST(),
373
    }
374
};
375

  
376
static void mpcore_register_devices(void)
377
{
378
    sysbus_register_withprop(&mpcore_rirq_info);
379
    sysbus_register_withprop(&mpcore_priv_info);
380
}
381

  
382
device_init(mpcore_register_devices)

Also available in: Unified diff