/*
 * INTC device simulation in PKUnity SoC
 *
 * Copyright (C) 2010-2012 Guan Xuetao
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation, or any later version.
 * See the COPYING file in the top-level directory.
 */
#include "hw/sysbus.h"

#undef DEBUG_PUV3
#include "hw/unicore32/puv3.h"

typedef struct {
    SysBusDevice busdev;
    MemoryRegion iomem;
    qemu_irq parent_irq;

    uint32_t reg_ICMR;
    uint32_t reg_ICPR;
} PUV3INTCState;

/* Update interrupt status after enabled or pending bits have been changed.  */
static void puv3_intc_update(PUV3INTCState *s)
{
    if (s->reg_ICMR & s->reg_ICPR) {
        qemu_irq_raise(s->parent_irq);
    } else {
        qemu_irq_lower(s->parent_irq);
    }
}

/* Process a change in an external INTC input. */
static void puv3_intc_handler(void *opaque, int irq, int level)
{
    PUV3INTCState *s = opaque;

    DPRINTF("irq 0x%x, level 0x%x\n", irq, level);
    if (level) {
        s->reg_ICPR |= (1 << irq);
    } else {
        s->reg_ICPR &= ~(1 << irq);
    }
    puv3_intc_update(s);
}

static uint64_t puv3_intc_read(void *opaque, hwaddr offset,
        unsigned size)
{
    PUV3INTCState *s = opaque;
    uint32_t ret = 0;

    switch (offset) {
    case 0x04: /* INTC_ICMR */
        ret = s->reg_ICMR;
        break;
    case 0x0c: /* INTC_ICIP */
        ret = s->reg_ICPR; /* the same value with ICPR */
        break;
    default:
        DPRINTF("Bad offset %x\n", (int)offset);
    }
    DPRINTF("offset 0x%x, value 0x%x\n", offset, ret);
    return ret;
}

static void puv3_intc_write(void *opaque, hwaddr offset,
        uint64_t value, unsigned size)
{
    PUV3INTCState *s = opaque;

    DPRINTF("offset 0x%x, value 0x%x\n", offset, value);
    switch (offset) {
    case 0x00: /* INTC_ICLR */
    case 0x14: /* INTC_ICCR */
        break;
    case 0x04: /* INTC_ICMR */
        s->reg_ICMR = value;
        break;
    default:
        DPRINTF("Bad offset 0x%x\n", (int)offset);
        return;
    }
    puv3_intc_update(s);
}

static const MemoryRegionOps puv3_intc_ops = {
    .read = puv3_intc_read,
    .write = puv3_intc_write,
    .impl = {
        .min_access_size = 4,
        .max_access_size = 4,
    },
    .endianness = DEVICE_NATIVE_ENDIAN,
};

static int puv3_intc_init(SysBusDevice *dev)
{
    PUV3INTCState *s = FROM_SYSBUS(PUV3INTCState, dev);

    qdev_init_gpio_in(&s->busdev.qdev, puv3_intc_handler, PUV3_IRQS_NR);
    sysbus_init_irq(&s->busdev, &s->parent_irq);

    s->reg_ICMR = 0;
    s->reg_ICPR = 0;

    memory_region_init_io(&s->iomem, &puv3_intc_ops, s, "puv3_intc",
            PUV3_REGS_OFFSET);
    sysbus_init_mmio(dev, &s->iomem);

    return 0;
}

static void puv3_intc_class_init(ObjectClass *klass, void *data)
{
    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);

    sdc->init = puv3_intc_init;
}

static const TypeInfo puv3_intc_info = {
    .name = "puv3_intc",
    .parent = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(PUV3INTCState),
    .class_init = puv3_intc_class_init,
};

static void puv3_intc_register_type(void)
{
    type_register_static(&puv3_intc_info);
}

type_init(puv3_intc_register_type)
