/*
 * 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;

    if (level) {
        set_bit(irq % 32, (void *)&s->irq_pending[irq / 32]);
    } else {
        clear_bit(irq % 32, (void *)&s->irq_pending[irq / 32]);
    }
    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);
