/*
 * Allwinner A10 interrupt controller device emulation
 *
 * Copyright (C) 2013 Li Guang
 * Written by Li Guang <lig.fnst@cn.fujitsu.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
 * for more details.
 */

#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "migration/vmstate.h"
#include "hw/intc/allwinner-a10-pic.h"
#include "hw/irq.h"
#include "qemu/log.h"
#include "qemu/module.h"

static void aw_a10_pic_update(AwA10PICState *s)
{
    uint8_t i;
    int irq = 0, fiq = 0, zeroes;

    s->vector = 0;

    for (i = 0; i < AW_A10_PIC_REG_NUM; i++) {
        irq |= s->irq_pending[i] & ~s->mask[i];
        fiq |= s->select[i] & s->irq_pending[i] & ~s->mask[i];

        if (!s->vector) {
            zeroes = ctz32(s->irq_pending[i] & ~s->mask[i]);
            if (zeroes != 32) {
                s->vector = (i * 32 + zeroes) * 4;
            }
        }
    }

    qemu_set_irq(s->parent_irq, !!irq);
    qemu_set_irq(s->parent_fiq, !!fiq);
}

static void aw_a10_pic_set_irq(void *opaque, int irq, int level)
{
    AwA10PICState *s = opaque;
    uint32_t *pending_reg = &s->irq_pending[irq / 32];

    *pending_reg = deposit32(*pending_reg, irq % 32, 1, level);
    aw_a10_pic_update(s);
}

static uint64_t aw_a10_pic_read(void *opaque, hwaddr offset, unsigned size)
{
    AwA10PICState *s = opaque;
    uint8_t index = (offset & 0xc) / 4;

    switch (offset) {
    case AW_A10_PIC_VECTOR:
        return s->vector;
    case AW_A10_PIC_BASE_ADDR:
        return s->base_addr;
    case AW_A10_PIC_PROTECT:
        return s->protect;
    case AW_A10_PIC_NMI:
        return s->nmi;
    case AW_A10_PIC_IRQ_PENDING ... AW_A10_PIC_IRQ_PENDING + 8:
        return s->irq_pending[index];
    case AW_A10_PIC_FIQ_PENDING ... AW_A10_PIC_FIQ_PENDING + 8:
        return s->fiq_pending[index];
    case AW_A10_PIC_SELECT ... AW_A10_PIC_SELECT + 8:
        return s->select[index];
    case AW_A10_PIC_ENABLE ... AW_A10_PIC_ENABLE + 8:
        return s->enable[index];
    case AW_A10_PIC_MASK ... AW_A10_PIC_MASK + 8:
        return s->mask[index];
    default:
        qemu_log_mask(LOG_GUEST_ERROR,
                      "%s: Bad offset 0x%x\n",  __func__, (int)offset);
        break;
    }

    return 0;
}

static void aw_a10_pic_write(void *opaque, hwaddr offset, uint64_t value,
                             unsigned size)
{
    AwA10PICState *s = opaque;
    uint8_t index = (offset & 0xc) / 4;

    switch (offset) {
    case AW_A10_PIC_BASE_ADDR:
        s->base_addr = value & ~0x3;
        break;
    case AW_A10_PIC_PROTECT:
        s->protect = value;
        break;
    case AW_A10_PIC_NMI:
        s->nmi = value;
        break;
    case AW_A10_PIC_IRQ_PENDING ... AW_A10_PIC_IRQ_PENDING + 8:
        /*
         * The register is read-only; nevertheless, Linux (including
         * the version originally shipped by Allwinner) pretends to
         * write to the register. Just ignore it.
         */
        break;
    case AW_A10_PIC_FIQ_PENDING ... AW_A10_PIC_FIQ_PENDING + 8:
        s->fiq_pending[index] &= ~value;
        break;
    case AW_A10_PIC_SELECT ... AW_A10_PIC_SELECT + 8:
        s->select[index] = value;
        break;
    case AW_A10_PIC_ENABLE ... AW_A10_PIC_ENABLE + 8:
        s->enable[index] = value;
        break;
    case AW_A10_PIC_MASK ... AW_A10_PIC_MASK + 8:
        s->mask[index] = value;
        break;
    default:
        qemu_log_mask(LOG_GUEST_ERROR,
                      "%s: Bad offset 0x%x\n",  __func__, (int)offset);
        break;
    }

    aw_a10_pic_update(s);
}

static const MemoryRegionOps aw_a10_pic_ops = {
    .read = aw_a10_pic_read,
    .write = aw_a10_pic_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
};

static const VMStateDescription vmstate_aw_a10_pic = {
    .name = "a10.pic",
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT32(vector, AwA10PICState),
        VMSTATE_UINT32(base_addr, AwA10PICState),
        VMSTATE_UINT32(protect, AwA10PICState),
        VMSTATE_UINT32(nmi, AwA10PICState),
        VMSTATE_UINT32_ARRAY(irq_pending, AwA10PICState, AW_A10_PIC_REG_NUM),
        VMSTATE_UINT32_ARRAY(fiq_pending, AwA10PICState, AW_A10_PIC_REG_NUM),
        VMSTATE_UINT32_ARRAY(enable, AwA10PICState, AW_A10_PIC_REG_NUM),
        VMSTATE_UINT32_ARRAY(select, AwA10PICState, AW_A10_PIC_REG_NUM),
        VMSTATE_UINT32_ARRAY(mask, AwA10PICState, AW_A10_PIC_REG_NUM),
        VMSTATE_END_OF_LIST()
    }
};

static void aw_a10_pic_init(Object *obj)
{
    AwA10PICState *s = AW_A10_PIC(obj);
    SysBusDevice *dev = SYS_BUS_DEVICE(obj);

     qdev_init_gpio_in(DEVICE(dev), aw_a10_pic_set_irq, AW_A10_PIC_INT_NR);
     sysbus_init_irq(dev, &s->parent_irq);
     sysbus_init_irq(dev, &s->parent_fiq);
     memory_region_init_io(&s->iomem, OBJECT(s), &aw_a10_pic_ops, s,
                           TYPE_AW_A10_PIC, 0x400);
     sysbus_init_mmio(dev, &s->iomem);
}

static void aw_a10_pic_reset(DeviceState *d)
{
    AwA10PICState *s = AW_A10_PIC(d);
    uint8_t i;

    s->base_addr = 0;
    s->protect = 0;
    s->nmi = 0;
    s->vector = 0;
    for (i = 0; i < AW_A10_PIC_REG_NUM; i++) {
        s->irq_pending[i] = 0;
        s->fiq_pending[i] = 0;
        s->select[i] = 0;
        s->enable[i] = 0;
        s->mask[i] = 0;
    }
}

static void aw_a10_pic_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);

    dc->reset = aw_a10_pic_reset;
    dc->desc = "allwinner a10 pic";
    dc->vmsd = &vmstate_aw_a10_pic;
 }

static const TypeInfo aw_a10_pic_info = {
    .name = TYPE_AW_A10_PIC,
    .parent = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(AwA10PICState),
    .instance_init = aw_a10_pic_init,
    .class_init = aw_a10_pic_class_init,
};

static void aw_a10_register_types(void)
{
    type_register_static(&aw_a10_pic_info);
}

type_init(aw_a10_register_types);
