/*
 * QEMU Loongson Local I/O interrupt controler.
 *
 * Copyright (c) 2020 Jiaxun Yang <jiaxun.yang@flygoat.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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 *
 */

#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "qemu/module.h"
#include "hw/irq.h"
#include "hw/qdev-properties.h"
#include "qom/object.h"

#define D(x)

#define NUM_IRQS                32

#define NUM_CORES               4
#define NUM_IPS                 4
#define NUM_PARENTS             (NUM_CORES * NUM_IPS)
#define PARENT_COREx_IPy(x, y)  (NUM_IPS * x + y)

#define R_MAPPER_START          0x0
#define R_MAPPER_END            0x20
#define R_ISR                   R_MAPPER_END
#define R_IEN                   0x24
#define R_IEN_SET               0x28
#define R_IEN_CLR               0x2c
#define R_PERCORE_ISR(x)        (0x40 + 0x8 * x)
#define R_END                   0x64

#define TYPE_LOONGSON_LIOINTC "loongson.liointc"
DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC,
                         TYPE_LOONGSON_LIOINTC)

struct loongson_liointc {
    SysBusDevice parent_obj;

    MemoryRegion mmio;
    qemu_irq parent_irq[NUM_PARENTS];

    uint8_t mapper[NUM_IRQS]; /* 0:3 for core, 4:7 for IP */
    uint32_t isr;
    uint32_t ien;
    uint32_t per_core_isr[NUM_CORES];

    /* state of the interrupt input pins */
    uint32_t pin_state;
    bool parent_state[NUM_PARENTS];
};

static void update_irq(struct loongson_liointc *p)
{
    uint32_t irq, core, ip;
    uint32_t per_ip_isr[NUM_IPS] = {0};

    /* level triggered interrupt */
    p->isr = p->pin_state;

    /* Clear disabled IRQs */
    p->isr &= p->ien;

    /* Clear per_core_isr */
    for (core = 0; core < NUM_CORES; core++) {
        p->per_core_isr[core] = 0;
    }

    /* Update per_core_isr and per_ip_isr */
    for (irq = 0; irq < NUM_IRQS; irq++) {
        if (!(p->isr & (1 << irq))) {
            continue;
        }

        for (core = 0; core < NUM_CORES; core++) {
            if ((p->mapper[irq] & (1 << core))) {
                p->per_core_isr[core] |= (1 << irq);
            }
        }

        for (ip = 0; ip < NUM_IPS; ip++) {
            if ((p->mapper[irq] & (1 << (ip + 4)))) {
                per_ip_isr[ip] |= (1 << irq);
            }
        }
    }

    /* Emit IRQ to parent! */
    for (core = 0; core < NUM_CORES; core++) {
        for (ip = 0; ip < NUM_IPS; ip++) {
            int parent = PARENT_COREx_IPy(core, ip);
            if (p->parent_state[parent] !=
                (!!p->per_core_isr[core] && !!per_ip_isr[ip])) {
                p->parent_state[parent] = !p->parent_state[parent];
                qemu_set_irq(p->parent_irq[parent], p->parent_state[parent]);
            }
        }
    }
}

static uint64_t
liointc_read(void *opaque, hwaddr addr, unsigned int size)
{
    struct loongson_liointc *p = opaque;
    uint32_t r = 0;

    /* Mapper is 1 byte */
    if (size == 1 && addr < R_MAPPER_END) {
        r = p->mapper[addr];
        goto out;
    }

    /* Rest is 4 byte */
    if (size != 4 || (addr % 4)) {
        goto out;
    }

    if (addr >= R_PERCORE_ISR(0) &&
        addr < R_PERCORE_ISR(NUM_CORES)) {
        int core = (addr - R_PERCORE_ISR(0)) / 4;
        r = p->per_core_isr[core];
        goto out;
    }

    switch (addr) {
    case R_ISR:
        r = p->isr;
        break;
    case R_IEN:
        r = p->ien;
        break;
    default:
        break;
    }

out:
    D(qemu_log("%s: size=%d addr=%lx val=%x\n", __func__, size, addr, r));
    return r;
}

static void
liointc_write(void *opaque, hwaddr addr,
          uint64_t val64, unsigned int size)
{
    struct loongson_liointc *p = opaque;
    uint32_t value = val64;

    D(qemu_log("%s: size=%d, addr=%lx val=%x\n", __func__, size, addr, value));

    /* Mapper is 1 byte */
    if (size == 1 && addr < R_MAPPER_END) {
        p->mapper[addr] = value;
        goto out;
    }

    /* Rest is 4 byte */
    if (size != 4 || (addr % 4)) {
        goto out;
    }

    if (addr >= R_PERCORE_ISR(0) &&
        addr < R_PERCORE_ISR(NUM_CORES)) {
        int core = (addr - R_PERCORE_ISR(0)) / 4;
        p->per_core_isr[core] = value;
        goto out;
    }

    switch (addr) {
    case R_IEN_SET:
        p->ien |= value;
        break;
    case R_IEN_CLR:
        p->ien &= ~value;
        break;
    default:
        break;
    }

out:
    update_irq(p);
}

static const MemoryRegionOps pic_ops = {
    .read = liointc_read,
    .write = liointc_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
    .valid = {
        .min_access_size = 1,
        .max_access_size = 4
    }
};

static void irq_handler(void *opaque, int irq, int level)
{
    struct loongson_liointc *p = opaque;

    p->pin_state &= ~(1 << irq);
    p->pin_state |= level << irq;
    update_irq(p);
}

static void loongson_liointc_init(Object *obj)
{
    struct loongson_liointc *p = LOONGSON_LIOINTC(obj);
    int i;

    qdev_init_gpio_in(DEVICE(obj), irq_handler, 32);

    for (i = 0; i < NUM_PARENTS; i++) {
        sysbus_init_irq(SYS_BUS_DEVICE(obj), &p->parent_irq[i]);
    }

    memory_region_init_io(&p->mmio, obj, &pic_ops, p,
                         "loongson.liointc", R_END);
    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &p->mmio);
}

static const TypeInfo loongson_liointc_info = {
    .name          = TYPE_LOONGSON_LIOINTC,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(struct loongson_liointc),
    .instance_init = loongson_liointc_init,
};

static void loongson_liointc_register_types(void)
{
    type_register_static(&loongson_liointc_info);
}

type_init(loongson_liointc_register_types)
