/*
 * 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 "qemu/log.h"
#include "qemu/module.h"
#include "hw/sysbus.h"
#include "migration/vmstate.h"
#include "hw/misc/mips_cmgcr.h"
#include "hw/misc/mips_cpc.h"
#include "hw/qdev-properties.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);

    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 = (const VMStateField[]) {
        VMSTATE_UINT64(cpc_base, MIPSGCRState),
        VMSTATE_END_OF_LIST()
    },
};

static Property mips_gcr_properties[] = {
    DEFINE_PROP_UINT32("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_LINK("gic", MIPSGCRState, gic_mr, TYPE_MEMORY_REGION,
                     MemoryRegion *),
    DEFINE_PROP_LINK("cpc", MIPSGCRState, cpc_mr, TYPE_MEMORY_REGION,
                     MemoryRegion *),
    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);
    device_class_set_props(dc, mips_gcr_properties);
    dc->vmsd = &vmstate_mips_gcr;
    device_class_set_legacy_reset(dc, 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)
