/*
 * ITS base class for a GICv3-based system
 *
 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
 * Written by Pavel Fedin
 *
 * 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 <http://www.gnu.org/licenses/>.
 */

#include "qemu/osdep.h"
#include "hw/pci/msi.h"
#include "hw/intc/arm_gicv3_its_common.h"
#include "qemu/log.h"

static void gicv3_its_pre_save(void *opaque)
{
    GICv3ITSState *s = (GICv3ITSState *)opaque;
    GICv3ITSCommonClass *c = ARM_GICV3_ITS_COMMON_GET_CLASS(s);

    if (c->pre_save) {
        c->pre_save(s);
    }
}

static int gicv3_its_post_load(void *opaque, int version_id)
{
    GICv3ITSState *s = (GICv3ITSState *)opaque;
    GICv3ITSCommonClass *c = ARM_GICV3_ITS_COMMON_GET_CLASS(s);

    if (c->post_load) {
        c->post_load(s);
    }
    return 0;
}

static const VMStateDescription vmstate_its = {
    .name = "arm_gicv3_its",
    .pre_save = gicv3_its_pre_save,
    .post_load = gicv3_its_post_load,
    .unmigratable = true,
};

static MemTxResult gicv3_its_trans_read(void *opaque, hwaddr offset,
                                        uint64_t *data, unsigned size,
                                        MemTxAttrs attrs)
{
    qemu_log_mask(LOG_GUEST_ERROR, "ITS read at offset 0x%"PRIx64"\n", offset);
    return MEMTX_ERROR;
}

static MemTxResult gicv3_its_trans_write(void *opaque, hwaddr offset,
                                         uint64_t value, unsigned size,
                                         MemTxAttrs attrs)
{
    if (offset == 0x0040 && ((size == 2) || (size == 4))) {
        GICv3ITSState *s = ARM_GICV3_ITS_COMMON(opaque);
        GICv3ITSCommonClass *c = ARM_GICV3_ITS_COMMON_GET_CLASS(s);
        int ret = c->send_msi(s, le64_to_cpu(value), attrs.requester_id);

        if (ret <= 0) {
            qemu_log_mask(LOG_GUEST_ERROR,
                          "ITS: Error sending MSI: %s\n", strerror(-ret));
            return MEMTX_DECODE_ERROR;
        }

        return MEMTX_OK;
    } else {
        qemu_log_mask(LOG_GUEST_ERROR,
                      "ITS write at bad offset 0x%"PRIx64"\n", offset);
        return MEMTX_DECODE_ERROR;
    }
}

static const MemoryRegionOps gicv3_its_trans_ops = {
    .read_with_attrs = gicv3_its_trans_read,
    .write_with_attrs = gicv3_its_trans_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
};

void gicv3_its_init_mmio(GICv3ITSState *s, const MemoryRegionOps *ops)
{
    SysBusDevice *sbd = SYS_BUS_DEVICE(s);

    memory_region_init_io(&s->iomem_its_cntrl, OBJECT(s), ops, s,
                          "control", ITS_CONTROL_SIZE);
    memory_region_init_io(&s->iomem_its_translation, OBJECT(s),
                          &gicv3_its_trans_ops, s,
                          "translation", ITS_TRANS_SIZE);

    /* Our two regions are always adjacent, therefore we now combine them
     * into a single one in order to make our users' life easier.
     */
    memory_region_init(&s->iomem_main, OBJECT(s), "gicv3_its", ITS_SIZE);
    memory_region_add_subregion(&s->iomem_main, 0, &s->iomem_its_cntrl);
    memory_region_add_subregion(&s->iomem_main, ITS_CONTROL_SIZE,
                                &s->iomem_its_translation);
    sysbus_init_mmio(sbd, &s->iomem_main);

    msi_nonbroken = true;
}

static void gicv3_its_common_reset(DeviceState *dev)
{
    GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);

    s->ctlr = 0;
    s->cbaser = 0;
    s->cwriter = 0;
    s->creadr = 0;
    memset(&s->baser, 0, sizeof(s->baser));

    gicv3_its_post_load(s, 0);
}

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

    dc->reset = gicv3_its_common_reset;
    dc->vmsd = &vmstate_its;
}

static const TypeInfo gicv3_its_common_info = {
    .name = TYPE_ARM_GICV3_ITS_COMMON,
    .parent = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(GICv3ITSState),
    .class_size = sizeof(GICv3ITSCommonClass),
    .class_init = gicv3_its_common_class_init,
    .abstract = true,
};

static void gicv3_its_common_register_types(void)
{
    type_register_static(&gicv3_its_common_info);
}

type_init(gicv3_its_common_register_types)
