qemu/hw/cpu/realview_mpcore.c
<<
>>
Prefs
   1/*
   2 * RealView ARM11MPCore internal peripheral emulation
   3 *
   4 * Copyright (c) 2006-2007 CodeSourcery.
   5 * Copyright (c) 2013 SUSE LINUX Products GmbH
   6 * Written by Paul Brook and Andreas Färber
   7 *
   8 * This code is licensed under the GPL.
   9 */
  10
  11#include "hw/cpu/arm11mpcore.h"
  12#include "hw/intc/realview_gic.h"
  13
  14#define TYPE_REALVIEW_MPCORE_RIRQ "realview_mpcore"
  15#define REALVIEW_MPCORE_RIRQ(obj) \
  16    OBJECT_CHECK(mpcore_rirq_state, (obj), TYPE_REALVIEW_MPCORE_RIRQ)
  17
  18/* Dummy PIC to route IRQ lines.  The baseboard has 4 independent IRQ
  19   controllers.  The output of these, plus some of the raw input lines
  20   are fed into a single SMP-aware interrupt controller on the CPU.  */
  21typedef struct {
  22    SysBusDevice parent_obj;
  23
  24    qemu_irq cpuic[32];
  25    qemu_irq rvic[4][64];
  26    uint32_t num_cpu;
  27
  28    ARM11MPCorePriveState priv;
  29    RealViewGICState gic[4];
  30} mpcore_rirq_state;
  31
  32/* Map baseboard IRQs onto CPU IRQ lines.  */
  33static const int mpcore_irq_map[32] = {
  34    -1, -1, -1, -1,  1,  2, -1, -1,
  35    -1, -1,  6, -1,  4,  5, -1, -1,
  36    -1, 14, 15,  0,  7,  8, -1, -1,
  37    -1, -1, -1, -1,  9,  3, -1, -1,
  38};
  39
  40static void mpcore_rirq_set_irq(void *opaque, int irq, int level)
  41{
  42    mpcore_rirq_state *s = (mpcore_rirq_state *)opaque;
  43    int i;
  44
  45    for (i = 0; i < 4; i++) {
  46        qemu_set_irq(s->rvic[i][irq], level);
  47    }
  48    if (irq < 32) {
  49        irq = mpcore_irq_map[irq];
  50        if (irq >= 0) {
  51            qemu_set_irq(s->cpuic[irq], level);
  52        }
  53    }
  54}
  55
  56static void realview_mpcore_realize(DeviceState *dev, Error **errp)
  57{
  58    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
  59    mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(dev);
  60    DeviceState *priv = DEVICE(&s->priv);
  61    DeviceState *gic;
  62    SysBusDevice *gicbusdev;
  63    Error *err = NULL;
  64    int n;
  65    int i;
  66
  67    qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu);
  68    object_property_set_bool(OBJECT(&s->priv), true, "realized", &err);
  69    if (err != NULL) {
  70        error_propagate(errp, err);
  71        return;
  72    }
  73    sysbus_pass_irq(sbd, SYS_BUS_DEVICE(&s->priv));
  74    for (i = 0; i < 32; i++) {
  75        s->cpuic[i] = qdev_get_gpio_in(priv, i);
  76    }
  77    /* ??? IRQ routing is hardcoded to "normal" mode.  */
  78    for (n = 0; n < 4; n++) {
  79        object_property_set_bool(OBJECT(&s->gic[n]), true, "realized", &err);
  80        if (err != NULL) {
  81            error_propagate(errp, err);
  82            return;
  83        }
  84        gic = DEVICE(&s->gic[n]);
  85        gicbusdev = SYS_BUS_DEVICE(&s->gic[n]);
  86        sysbus_mmio_map(gicbusdev, 0, 0x10040000 + n * 0x10000);
  87        sysbus_connect_irq(gicbusdev, 0, s->cpuic[10 + n]);
  88        for (i = 0; i < 64; i++) {
  89            s->rvic[n][i] = qdev_get_gpio_in(gic, i);
  90        }
  91    }
  92    qdev_init_gpio_in(dev, mpcore_rirq_set_irq, 64);
  93}
  94
  95static void mpcore_rirq_init(Object *obj)
  96{
  97    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
  98    mpcore_rirq_state *s = REALVIEW_MPCORE_RIRQ(obj);
  99    SysBusDevice *privbusdev;
 100    int i;
 101
 102    object_initialize(&s->priv, sizeof(s->priv), TYPE_ARM11MPCORE_PRIV);
 103    qdev_set_parent_bus(DEVICE(&s->priv), sysbus_get_default());
 104    privbusdev = SYS_BUS_DEVICE(&s->priv);
 105    sysbus_init_mmio(sbd, sysbus_mmio_get_region(privbusdev, 0));
 106
 107    for (i = 0; i < 4; i++) {
 108        object_initialize(&s->gic[i], sizeof(s->gic[i]), TYPE_REALVIEW_GIC);
 109        qdev_set_parent_bus(DEVICE(&s->gic[i]), sysbus_get_default());
 110    }
 111}
 112
 113static Property mpcore_rirq_properties[] = {
 114    DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1),
 115    DEFINE_PROP_END_OF_LIST(),
 116};
 117
 118static void mpcore_rirq_class_init(ObjectClass *klass, void *data)
 119{
 120    DeviceClass *dc = DEVICE_CLASS(klass);
 121
 122    dc->realize = realview_mpcore_realize;
 123    dc->props = mpcore_rirq_properties;
 124}
 125
 126static const TypeInfo mpcore_rirq_info = {
 127    .name          = TYPE_REALVIEW_MPCORE_RIRQ,
 128    .parent        = TYPE_SYS_BUS_DEVICE,
 129    .instance_size = sizeof(mpcore_rirq_state),
 130    .instance_init = mpcore_rirq_init,
 131    .class_init    = mpcore_rirq_class_init,
 132};
 133
 134static void realview_mpcore_register_types(void)
 135{
 136    type_register_static(&mpcore_rirq_info);
 137}
 138
 139type_init(realview_mpcore_register_types)
 140