/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 2012  MIPS Technologies, Inc.  All rights reserved.
 * Authors: Sanjay Lal <sanjayl@kymasys.com>
 *
 * Copyright (C) 2015 Imagination Technologies
 */

#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/log.h"
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "sysemu/sysemu.h"
#include "hw/misc/mips_cmgcr.h"
#include "hw/misc/mips_cpc.h"
#include "hw/intc/mips_gic.h"

static inline bool is_cpc_connected(MIPSGCRState *s)
{
    return s->cpc_mr != NULL;
}

static inline bool is_gic_connected(MIPSGCRState *s)
{
    return s->gic_mr != NULL;
}

static inline void update_gcr_base(MIPSGCRState *gcr, uint64_t val)
{
    CPUState *cpu;
    MIPSCPU *mips_cpu;

    gcr->gcr_base = val & GCR_BASE_GCRBASE_MSK;
    memory_region_set_address(&gcr->iomem, gcr->gcr_base);

    CPU_FOREACH(cpu) {
        mips_cpu = MIPS_CPU(cpu);
        mips_cpu->env.CP0_CMGCRBase = gcr->gcr_base >> 4;
    }
}

static inline void update_cpc_base(MIPSGCRState *gcr, uint64_t val)
{
    if (is_cpc_connected(gcr)) {
        gcr->cpc_base = val & GCR_CPC_BASE_MSK;
        memory_region_transaction_begin();
        memory_region_set_address(gcr->cpc_mr,
                                  gcr->cpc_base & GCR_CPC_BASE_CPCBASE_MSK);
        memory_region_set_enabled(gcr->cpc_mr,
                                  gcr->cpc_base & GCR_CPC_BASE_CPCEN_MSK);
        memory_region_transaction_commit();
    }
}

static inline void update_gic_base(MIPSGCRState *gcr, uint64_t val)
{
    if (is_gic_connected(gcr)) {
        gcr->gic_base = val & GCR_GIC_BASE_MSK;
        memory_region_transaction_begin();
        memory_region_set_address(gcr->gic_mr,
                                  gcr->gic_base & GCR_GIC_BASE_GICBASE_MSK);
        memory_region_set_enabled(gcr->gic_mr,
                                  gcr->gic_base & GCR_GIC_BASE_GICEN_MSK);
        memory_region_transaction_commit();
    }
}

/* Read GCR registers */
static uint64_t gcr_read(void *opaque, hwaddr addr, unsigned size)
{
    MIPSGCRState *gcr = (MIPSGCRState *) opaque;
    MIPSGCRVPState *current_vps = &gcr->vps[current_cpu->cpu_index];
    MIPSGCRVPState *other_vps = &gcr->vps[current_vps->other];

    switch (addr) {
    /* Global Control Block Register */
    case GCR_CONFIG_OFS:
        /* Set PCORES to 0 */
        return 0;
    case GCR_BASE_OFS:
        return gcr->gcr_base;
    case GCR_REV_OFS:
        return gcr->gcr_rev;
    case GCR_GIC_BASE_OFS:
        return gcr->gic_base;
    case GCR_CPC_BASE_OFS:
        return gcr->cpc_base;
    case GCR_GIC_STATUS_OFS:
        return is_gic_connected(gcr);
    case GCR_CPC_STATUS_OFS:
        return is_cpc_connected(gcr);
    case GCR_L2_CONFIG_OFS:
        /* L2 BYPASS */
        return GCR_L2_CONFIG_BYPASS_MSK;
        /* Core-Local and Core-Other Control Blocks */
    case MIPS_CLCB_OFS + GCR_CL_CONFIG_OFS:
    case MIPS_COCB_OFS + GCR_CL_CONFIG_OFS:
        /* Set PVP to # of VPs - 1 */
        return gcr->num_vps - 1;
    case MIPS_CLCB_OFS + GCR_CL_RESETBASE_OFS:
        return current_vps->reset_base;
    case MIPS_COCB_OFS + GCR_CL_RESETBASE_OFS:
        return other_vps->reset_base;
    case MIPS_CLCB_OFS + GCR_CL_OTHER_OFS:
        return current_vps->other;
    case MIPS_COCB_OFS + GCR_CL_OTHER_OFS:
        return other_vps->other;
    default:
        qemu_log_mask(LOG_UNIMP, "Read %d bytes at GCR offset 0x%" HWADDR_PRIx
                      "\n", size, addr);
        return 0;
    }
    return 0;
}

static inline target_ulong get_exception_base(MIPSGCRVPState *vps)
{
    /* TODO: BEV_BASE and SELECT_BEV */
    return (int32_t)(vps->reset_base & GCR_CL_RESET_BASE_RESETBASE_MSK);
}

/* Write GCR registers */
static void gcr_write(void *opaque, hwaddr addr, uint64_t data, unsigned size)
{
    MIPSGCRState *gcr = (MIPSGCRState *)opaque;
    MIPSGCRVPState *current_vps = &gcr->vps[current_cpu->cpu_index];
    MIPSGCRVPState *other_vps = &gcr->vps[current_vps->other];

    switch (addr) {
    case GCR_BASE_OFS:
        update_gcr_base(gcr, data);
        break;
    case GCR_GIC_BASE_OFS:
        update_gic_base(gcr, data);
        break;
    case GCR_CPC_BASE_OFS:
        update_cpc_base(gcr, data);
        break;
    case MIPS_CLCB_OFS + GCR_CL_RESETBASE_OFS:
        current_vps->reset_base = data & GCR_CL_RESET_BASE_MSK;
        cpu_set_exception_base(current_cpu->cpu_index,
                               get_exception_base(current_vps));
        break;
    case MIPS_COCB_OFS + GCR_CL_RESETBASE_OFS:
        other_vps->reset_base = data & GCR_CL_RESET_BASE_MSK;
        cpu_set_exception_base(current_vps->other,
                               get_exception_base(other_vps));
        break;
    case MIPS_CLCB_OFS + GCR_CL_OTHER_OFS:
        if ((data & GCR_CL_OTHER_MSK) < gcr->num_vps) {
            current_vps->other = data & GCR_CL_OTHER_MSK;
        }
        break;
    case MIPS_COCB_OFS + GCR_CL_OTHER_OFS:
        if ((data & GCR_CL_OTHER_MSK) < gcr->num_vps) {
            other_vps->other = data & GCR_CL_OTHER_MSK;
        }
        break;
    default:
        qemu_log_mask(LOG_UNIMP, "Write %d bytes at GCR offset 0x%" HWADDR_PRIx
                      " 0x%" PRIx64 "\n", size, addr, data);
        break;
    }
}

static const MemoryRegionOps gcr_ops = {
    .read = gcr_read,
    .write = gcr_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
    .impl = {
        .max_access_size = 8,
    },
};

static void mips_gcr_init(Object *obj)
{
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    MIPSGCRState *s = MIPS_GCR(obj);

    object_property_add_link(obj, "gic", TYPE_MEMORY_REGION,
                             (Object **)&s->gic_mr,
                             qdev_prop_allow_set_link_before_realize,
                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
                             &error_abort);

    object_property_add_link(obj, "cpc", TYPE_MEMORY_REGION,
                             (Object **)&s->cpc_mr,
                             qdev_prop_allow_set_link_before_realize,
                             OBJ_PROP_LINK_UNREF_ON_RELEASE,
                             &error_abort);

    memory_region_init_io(&s->iomem, OBJECT(s), &gcr_ops, s,
                          "mips-gcr", GCR_ADDRSPACE_SZ);
    sysbus_init_mmio(sbd, &s->iomem);
}

static void mips_gcr_reset(DeviceState *dev)
{
    MIPSGCRState *s = MIPS_GCR(dev);
    int i;

    update_gic_base(s, 0);
    update_cpc_base(s, 0);

    for (i = 0; i < s->num_vps; i++) {
        s->vps[i].other = 0;
        s->vps[i].reset_base = 0xBFC00000 & GCR_CL_RESET_BASE_MSK;
        cpu_set_exception_base(i, get_exception_base(&s->vps[i]));
    }
}

static const VMStateDescription vmstate_mips_gcr = {
    .name = "mips-gcr",
    .version_id = 0,
    .minimum_version_id = 0,
    .fields = (VMStateField[]) {
        VMSTATE_UINT64(cpc_base, MIPSGCRState),
        VMSTATE_END_OF_LIST()
    },
};

static Property mips_gcr_properties[] = {
    DEFINE_PROP_INT32("num-vp", MIPSGCRState, num_vps, 1),
    DEFINE_PROP_INT32("gcr-rev", MIPSGCRState, gcr_rev, 0x800),
    DEFINE_PROP_UINT64("gcr-base", MIPSGCRState, gcr_base, GCR_BASE_ADDR),
    DEFINE_PROP_END_OF_LIST(),
};

static void mips_gcr_realize(DeviceState *dev, Error **errp)
{
    MIPSGCRState *s = MIPS_GCR(dev);

    /* Create local set of registers for each VP */
    s->vps = g_new(MIPSGCRVPState, s->num_vps);
}

static void mips_gcr_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    dc->props = mips_gcr_properties;
    dc->vmsd = &vmstate_mips_gcr;
    dc->reset = mips_gcr_reset;
    dc->realize = mips_gcr_realize;
}

static const TypeInfo mips_gcr_info = {
    .name          = TYPE_MIPS_GCR,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(MIPSGCRState),
    .instance_init = mips_gcr_init,
    .class_init    = mips_gcr_class_init,
};

static void mips_gcr_register_types(void)
{
    type_register_static(&mips_gcr_info);
}

type_init(mips_gcr_register_types)
