/*
 * ARM11MPCore internal peripheral emulation.
 *
 * Copyright (c) 2006-2007 CodeSourcery.
 * Written by Paul Brook
 *
 * This code is licensed under the GPL.
 */

#include "sysbus.h"
#include "qemu-timer.h"

/* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
   (+ 32 internal).  However my test chip only exposes/reports 32.
   More importantly Linux falls over if more than 32 are present!  */
#define GIC_NIRQ 64

#define NCPU 4

static inline int
gic_get_current_cpu(void)
{
  return cpu_single_env->cpu_index;
}

#include "arm_gic.c"

/* MPCore private memory region.  */

typedef struct mpcore_priv_state {
    gic_state gic;
    uint32_t scu_control;
    int iomemtype;
    uint32_t old_timer_status[8];
    uint32_t num_cpu;
    qemu_irq *timer_irq;
    MemoryRegion iomem;
    MemoryRegion container;
    DeviceState *mptimer;
} mpcore_priv_state;

/* Per-CPU private memory mapped IO.  */

static uint64_t mpcore_scu_read(void *opaque, target_phys_addr_t offset,
                                unsigned size)
{
    mpcore_priv_state *s = (mpcore_priv_state *)opaque;
    int id;
    offset &= 0xff;
    /* SCU */
    switch (offset) {
    case 0x00: /* Control.  */
        return s->scu_control;
    case 0x04: /* Configuration.  */
        id = ((1 << s->num_cpu) - 1) << 4;
        return id | (s->num_cpu - 1);
    case 0x08: /* CPU status.  */
        return 0;
    case 0x0c: /* Invalidate all.  */
        return 0;
    default:
        hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
    }
}

static void mpcore_scu_write(void *opaque, target_phys_addr_t offset,
                             uint64_t value, unsigned size)
{
    mpcore_priv_state *s = (mpcore_priv_state *)opaque;
    offset &= 0xff;
    /* SCU */
    switch (offset) {
    case 0: /* Control register.  */
        s->scu_control = value & 1;
        break;
    case 0x0c: /* Invalidate all.  */
        /* This is a no-op as cache is not emulated.  */
        break;
    default:
        hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
    }
}

static const MemoryRegionOps mpcore_scu_ops = {
    .read = mpcore_scu_read,
    .write = mpcore_scu_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
};

static void mpcore_timer_irq_handler(void *opaque, int irq, int level)
{
    mpcore_priv_state *s = (mpcore_priv_state *)opaque;
    if (level && !s->old_timer_status[irq]) {
        gic_set_pending_private(&s->gic, irq >> 1, 29 + (irq & 1));
    }
    s->old_timer_status[irq] = level;
}

static void mpcore_priv_map_setup(mpcore_priv_state *s)
{
    int i;
    SysBusDevice *busdev = sysbus_from_qdev(s->mptimer);
    memory_region_init(&s->container, "mpcode-priv-container", 0x2000);
    memory_region_init_io(&s->iomem, &mpcore_scu_ops, s, "mpcore-scu", 0x100);
    memory_region_add_subregion(&s->container, 0, &s->iomem);
    /* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs
     * at 0x200, 0x300...
     */
    for (i = 0; i < (s->num_cpu + 1); i++) {
        target_phys_addr_t offset = 0x100 + (i * 0x100);
        memory_region_add_subregion(&s->container, offset, &s->gic.cpuiomem[i]);
    }
    /* Add the regions for timer and watchdog for "current CPU" and
     * for each specific CPU.
     */
    s->timer_irq = qemu_allocate_irqs(mpcore_timer_irq_handler,
                                      s, (s->num_cpu + 1) * 2);
    for (i = 0; i < (s->num_cpu + 1) * 2; i++) {
        /* Timers at 0x600, 0x700, ...; watchdogs at 0x620, 0x720, ... */
        target_phys_addr_t offset = 0x600 + (i >> 1) * 0x100 + (i & 1) * 0x20;
        memory_region_add_subregion(&s->container, offset,
                                    sysbus_mmio_get_region(busdev, i));
    }
    memory_region_add_subregion(&s->container, 0x1000, &s->gic.iomem);
    /* Wire up the interrupt from each watchdog and timer. */
    for (i = 0; i < s->num_cpu * 2; i++) {
        sysbus_connect_irq(busdev, i, s->timer_irq[i]);
    }
}

static int mpcore_priv_init(SysBusDevice *dev)
{
    mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);

    gic_init(&s->gic, s->num_cpu);
    s->mptimer = qdev_create(NULL, "arm_mptimer");
    qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
    qdev_init_nofail(s->mptimer);
    mpcore_priv_map_setup(s);
    sysbus_init_mmio(dev, &s->container);
    return 0;
}

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

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

static void mpcore_rirq_set_irq(void *opaque, int irq, int level)
{
    mpcore_rirq_state *s = (mpcore_rirq_state *)opaque;
    int i;

    for (i = 0; i < 4; i++) {
        qemu_set_irq(s->rvic[i][irq], level);
    }
    if (irq < 32) {
        irq = mpcore_irq_map[irq];
        if (irq >= 0) {
            qemu_set_irq(s->cpuic[irq], level);
        }
    }
}

static int realview_mpcore_init(SysBusDevice *dev)
{
    mpcore_rirq_state *s = FROM_SYSBUS(mpcore_rirq_state, dev);
    DeviceState *gic;
    DeviceState *priv;
    int n;
    int i;

    priv = qdev_create(NULL, "arm11mpcore_priv");
    qdev_prop_set_uint32(priv, "num-cpu", s->num_cpu);
    qdev_init_nofail(priv);
    s->priv = sysbus_from_qdev(priv);
    sysbus_pass_irq(dev, s->priv);
    for (i = 0; i < 32; i++) {
        s->cpuic[i] = qdev_get_gpio_in(priv, i);
    }
    /* ??? IRQ routing is hardcoded to "normal" mode.  */
    for (n = 0; n < 4; n++) {
        gic = sysbus_create_simple("realview_gic", 0x10040000 + n * 0x10000,
                                   s->cpuic[10 + n]);
        for (i = 0; i < 64; i++) {
            s->rvic[n][i] = qdev_get_gpio_in(gic, i);
        }
    }
    qdev_init_gpio_in(&dev->qdev, mpcore_rirq_set_irq, 64);
    sysbus_init_mmio(dev, sysbus_mmio_get_region(s->priv, 0));
    return 0;
}

static SysBusDeviceInfo mpcore_rirq_info = {
    .init = realview_mpcore_init,
    .qdev.name  = "realview_mpcore",
    .qdev.size  = sizeof(mpcore_rirq_state),
    .qdev.props = (Property[]) {
        DEFINE_PROP_UINT32("num-cpu", mpcore_rirq_state, num_cpu, 1),
        DEFINE_PROP_END_OF_LIST(),
    }
};

static SysBusDeviceInfo mpcore_priv_info = {
    .init = mpcore_priv_init,
    .qdev.name  = "arm11mpcore_priv",
    .qdev.size  = sizeof(mpcore_priv_state),
    .qdev.props = (Property[]) {
        DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
        DEFINE_PROP_END_OF_LIST(),
    }
};

static void arm11mpcore_register_devices(void)
{
    sysbus_register_withprop(&mpcore_rirq_info);
    sysbus_register_withprop(&mpcore_priv_info);
}

device_init(arm11mpcore_register_devices)
