/*
 * Raspberry Pi emulation (c) 2012 Gregory Estrade
 * Refactoring for Pi2 Copyright (c) 2015, Microsoft. Written by Andrew Baumann.
 * This code is licensed under the GNU GPLv2 and later.
 * Heavily based on pl190.c, copyright terms below:
 *
 * Arm PrimeCell PL190 Vector Interrupt Controller
 *
 * Copyright (c) 2006 CodeSourcery.
 * Written by Paul Brook
 *
 * This code is licensed under the GPL.
 */

#include "qemu/osdep.h"
#include "hw/intc/bcm2835_ic.h"

#define GPU_IRQS 64
#define ARM_IRQS 8

#define IRQ_PENDING_BASIC       0x00 /* IRQ basic pending */
#define IRQ_PENDING_1           0x04 /* IRQ pending 1 */
#define IRQ_PENDING_2           0x08 /* IRQ pending 2 */
#define FIQ_CONTROL             0x0C /* FIQ register */
#define IRQ_ENABLE_1            0x10 /* Interrupt enable register 1 */
#define IRQ_ENABLE_2            0x14 /* Interrupt enable register 2 */
#define IRQ_ENABLE_BASIC        0x18 /* Base interrupt enable register */
#define IRQ_DISABLE_1           0x1C /* Interrupt disable register 1 */
#define IRQ_DISABLE_2           0x20 /* Interrupt disable register 2 */
#define IRQ_DISABLE_BASIC       0x24 /* Base interrupt disable register */

/* Update interrupts.  */
static void bcm2835_ic_update(BCM2835ICState *s)
{
    bool set = false;

    if (s->fiq_enable) {
        if (s->fiq_select >= GPU_IRQS) {
            /* ARM IRQ */
            set = extract32(s->arm_irq_level, s->fiq_select - GPU_IRQS, 1);
        } else {
            set = extract64(s->gpu_irq_level, s->fiq_select, 1);
        }
    }
    qemu_set_irq(s->fiq, set);

    set = (s->gpu_irq_level & s->gpu_irq_enable)
        || (s->arm_irq_level & s->arm_irq_enable);
    qemu_set_irq(s->irq, set);

}

static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
{
    BCM2835ICState *s = opaque;

    assert(irq >= 0 && irq < 64);
    s->gpu_irq_level = deposit64(s->gpu_irq_level, irq, 1, level != 0);
    bcm2835_ic_update(s);
}

static void bcm2835_ic_set_arm_irq(void *opaque, int irq, int level)
{
    BCM2835ICState *s = opaque;

    assert(irq >= 0 && irq < 8);
    s->arm_irq_level = deposit32(s->arm_irq_level, irq, 1, level != 0);
    bcm2835_ic_update(s);
}

static const int irq_dups[] = { 7, 9, 10, 18, 19, 53, 54, 55, 56, 57, 62 };

static uint64_t bcm2835_ic_read(void *opaque, hwaddr offset, unsigned size)
{
    BCM2835ICState *s = opaque;
    uint32_t res = 0;
    uint64_t gpu_pending = s->gpu_irq_level & s->gpu_irq_enable;
    int i;

    switch (offset) {
    case IRQ_PENDING_BASIC:
        /* bits 0-7: ARM irqs */
        res = s->arm_irq_level & s->arm_irq_enable;

        /* bits 8 & 9: pending registers 1 & 2 */
        res |= (((uint32_t)gpu_pending) != 0) << 8;
        res |= ((gpu_pending >> 32) != 0) << 9;

        /* bits 10-20: selected GPU IRQs */
        for (i = 0; i < ARRAY_SIZE(irq_dups); i++) {
            res |= extract64(gpu_pending, irq_dups[i], 1) << (i + 10);
        }
        break;
    case IRQ_PENDING_1:
        res = gpu_pending;
        break;
    case IRQ_PENDING_2:
        res = gpu_pending >> 32;
        break;
    case FIQ_CONTROL:
        res = (s->fiq_enable << 7) | s->fiq_select;
        break;
    case IRQ_ENABLE_1:
        res = s->gpu_irq_enable;
        break;
    case IRQ_ENABLE_2:
        res = s->gpu_irq_enable >> 32;
        break;
    case IRQ_ENABLE_BASIC:
        res = s->arm_irq_enable;
        break;
    case IRQ_DISABLE_1:
        res = ~s->gpu_irq_enable;
        break;
    case IRQ_DISABLE_2:
        res = ~s->gpu_irq_enable >> 32;
        break;
    case IRQ_DISABLE_BASIC:
        res = ~s->arm_irq_enable;
        break;
    default:
        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
                      __func__, offset);
        return 0;
    }

    return res;
}

static void bcm2835_ic_write(void *opaque, hwaddr offset, uint64_t val,
                             unsigned size)
{
    BCM2835ICState *s = opaque;

    switch (offset) {
    case FIQ_CONTROL:
        s->fiq_select = extract32(val, 0, 7);
        s->fiq_enable = extract32(val, 7, 1);
        break;
    case IRQ_ENABLE_1:
        s->gpu_irq_enable |= val;
        break;
    case IRQ_ENABLE_2:
        s->gpu_irq_enable |= val << 32;
        break;
    case IRQ_ENABLE_BASIC:
        s->arm_irq_enable |= val & 0xff;
        break;
    case IRQ_DISABLE_1:
        s->gpu_irq_enable &= ~val;
        break;
    case IRQ_DISABLE_2:
        s->gpu_irq_enable &= ~(val << 32);
        break;
    case IRQ_DISABLE_BASIC:
        s->arm_irq_enable &= ~val & 0xff;
        break;
    default:
        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
                      __func__, offset);
        return;
    }
    bcm2835_ic_update(s);
}

static const MemoryRegionOps bcm2835_ic_ops = {
    .read = bcm2835_ic_read,
    .write = bcm2835_ic_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
    .valid.min_access_size = 4,
    .valid.max_access_size = 4,
};

static void bcm2835_ic_reset(DeviceState *d)
{
    BCM2835ICState *s = BCM2835_IC(d);

    s->gpu_irq_enable = 0;
    s->arm_irq_enable = 0;
    s->fiq_enable = false;
    s->fiq_select = 0;
}

static void bcm2835_ic_init(Object *obj)
{
    BCM2835ICState *s = BCM2835_IC(obj);

    memory_region_init_io(&s->iomem, obj, &bcm2835_ic_ops, s, TYPE_BCM2835_IC,
                          0x200);
    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);

    qdev_init_gpio_in_named(DEVICE(s), bcm2835_ic_set_gpu_irq,
                            BCM2835_IC_GPU_IRQ, GPU_IRQS);
    qdev_init_gpio_in_named(DEVICE(s), bcm2835_ic_set_arm_irq,
                            BCM2835_IC_ARM_IRQ, ARM_IRQS);

    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->fiq);
}

static const VMStateDescription vmstate_bcm2835_ic = {
    .name = TYPE_BCM2835_IC,
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT64(gpu_irq_level, BCM2835ICState),
        VMSTATE_UINT64(gpu_irq_enable, BCM2835ICState),
        VMSTATE_UINT8(arm_irq_level, BCM2835ICState),
        VMSTATE_UINT8(arm_irq_enable, BCM2835ICState),
        VMSTATE_BOOL(fiq_enable, BCM2835ICState),
        VMSTATE_UINT8(fiq_select, BCM2835ICState),
        VMSTATE_END_OF_LIST()
    }
};

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

    dc->reset = bcm2835_ic_reset;
    dc->vmsd = &vmstate_bcm2835_ic;
}

static TypeInfo bcm2835_ic_info = {
    .name          = TYPE_BCM2835_IC,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(BCM2835ICState),
    .class_init    = bcm2835_ic_class_init,
    .instance_init = bcm2835_ic_init,
};

static void bcm2835_ic_register_types(void)
{
    type_register_static(&bcm2835_ic_info);
}

type_init(bcm2835_ic_register_types)
