/*
 * QEMU PowerPC N1 chiplet model
 *
 * Copyright (c) 2023, IBM Corporation.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include "qemu/osdep.h"
#include "qemu/log.h"
#include "hw/qdev-properties.h"
#include "hw/ppc/pnv.h"
#include "hw/ppc/pnv_xscom.h"
#include "hw/ppc/pnv_n1_chiplet.h"
#include "hw/ppc/pnv_nest_pervasive.h"

/*
 * The n1 chiplet contains chiplet control unit,
 * PowerBus/RaceTrack/Bridge logic, nest Memory Management Unit(nMMU)
 * and more.
 *
 * In this model Nest1 chiplet control registers are modelled via common
 * nest pervasive model and few PowerBus racetrack registers are modelled.
 */

#define PB_SCOM_EQ0_HP_MODE2_CURR      0xe
#define PB_SCOM_ES3_MODE               0x8a

static uint64_t pnv_n1_chiplet_pb_scom_eq_read(void *opaque, hwaddr addr,
                                                  unsigned size)
{
    PnvN1Chiplet *n1_chiplet = PNV_N1_CHIPLET(opaque);
    uint32_t reg = addr >> 3;
    uint64_t val = ~0ull;

    switch (reg) {
    case PB_SCOM_EQ0_HP_MODE2_CURR:
        val = n1_chiplet->eq[0].hp_mode2_curr;
        break;
    default:
        qemu_log_mask(LOG_UNIMP, "%s: Invalid xscom read at 0x%" PRIx32 "\n",
                      __func__, reg);
    }
    return val;
}

static void pnv_n1_chiplet_pb_scom_eq_write(void *opaque, hwaddr addr,
                                               uint64_t val, unsigned size)
{
    PnvN1Chiplet *n1_chiplet = PNV_N1_CHIPLET(opaque);
    uint32_t reg = addr >> 3;

    switch (reg) {
    case PB_SCOM_EQ0_HP_MODE2_CURR:
        n1_chiplet->eq[0].hp_mode2_curr = val;
        break;
    default:
        qemu_log_mask(LOG_UNIMP, "%s: Invalid xscom write at 0x%" PRIx32 "\n",
                      __func__, reg);
    }
}

static const MemoryRegionOps pnv_n1_chiplet_pb_scom_eq_ops = {
    .read = pnv_n1_chiplet_pb_scom_eq_read,
    .write = pnv_n1_chiplet_pb_scom_eq_write,
    .valid.min_access_size = 8,
    .valid.max_access_size = 8,
    .impl.min_access_size = 8,
    .impl.max_access_size = 8,
    .endianness = DEVICE_BIG_ENDIAN,
};

static uint64_t pnv_n1_chiplet_pb_scom_es_read(void *opaque, hwaddr addr,
                                          unsigned size)
{
    PnvN1Chiplet *n1_chiplet = PNV_N1_CHIPLET(opaque);
    uint32_t reg = addr >> 3;
    uint64_t val = ~0ull;

    switch (reg) {
    case PB_SCOM_ES3_MODE:
        val = n1_chiplet->es[3].mode;
        break;
    default:
        qemu_log_mask(LOG_UNIMP, "%s: Invalid xscom read at 0x%" PRIx32 "\n",
                      __func__, reg);
    }
    return val;
}

static void pnv_n1_chiplet_pb_scom_es_write(void *opaque, hwaddr addr,
                                               uint64_t val, unsigned size)
{
    PnvN1Chiplet *n1_chiplet = PNV_N1_CHIPLET(opaque);
    uint32_t reg = addr >> 3;

    switch (reg) {
    case PB_SCOM_ES3_MODE:
        n1_chiplet->es[3].mode = val;
        break;
    default:
        qemu_log_mask(LOG_UNIMP, "%s: Invalid xscom write at 0x%" PRIx32 "\n",
                      __func__, reg);
    }
}

static const MemoryRegionOps pnv_n1_chiplet_pb_scom_es_ops = {
    .read = pnv_n1_chiplet_pb_scom_es_read,
    .write = pnv_n1_chiplet_pb_scom_es_write,
    .valid.min_access_size = 8,
    .valid.max_access_size = 8,
    .impl.min_access_size = 8,
    .impl.max_access_size = 8,
    .endianness = DEVICE_BIG_ENDIAN,
};

static void pnv_n1_chiplet_realize(DeviceState *dev, Error **errp)
{
    PnvN1Chiplet *n1_chiplet = PNV_N1_CHIPLET(dev);

    /* Realize nest pervasive common chiplet model */
    if (!qdev_realize(DEVICE(&n1_chiplet->nest_pervasive), NULL, errp)) {
        return;
    }

    /* Nest1 chiplet power bus EQ xscom region */
    pnv_xscom_region_init(&n1_chiplet->xscom_pb_eq_mr, OBJECT(n1_chiplet),
                          &pnv_n1_chiplet_pb_scom_eq_ops, n1_chiplet,
                          "xscom-n1-chiplet-pb-scom-eq",
                          PNV10_XSCOM_N1_PB_SCOM_EQ_SIZE);

    /* Nest1 chiplet power bus ES xscom region */
    pnv_xscom_region_init(&n1_chiplet->xscom_pb_es_mr, OBJECT(n1_chiplet),
                          &pnv_n1_chiplet_pb_scom_es_ops, n1_chiplet,
                          "xscom-n1-chiplet-pb-scom-es",
                          PNV10_XSCOM_N1_PB_SCOM_ES_SIZE);
}

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

    dc->desc = "PowerNV n1 chiplet";
    dc->realize = pnv_n1_chiplet_realize;
}

static void pnv_n1_chiplet_instance_init(Object *obj)
{
    PnvN1Chiplet *n1_chiplet = PNV_N1_CHIPLET(obj);

    object_initialize_child(OBJECT(n1_chiplet), "nest-pervasive-common",
                            &n1_chiplet->nest_pervasive,
                            TYPE_PNV_NEST_CHIPLET_PERVASIVE);
}

static const TypeInfo pnv_n1_chiplet_info = {
    .name          = TYPE_PNV_N1_CHIPLET,
    .parent        = TYPE_DEVICE,
    .instance_init = pnv_n1_chiplet_instance_init,
    .instance_size = sizeof(PnvN1Chiplet),
    .class_init    = pnv_n1_chiplet_class_init,
    .interfaces    = (InterfaceInfo[]) {
        { TYPE_PNV_XSCOM_INTERFACE },
        { }
    }
};

static void pnv_n1_chiplet_register_types(void)
{
    type_register_static(&pnv_n1_chiplet_info);
}

type_init(pnv_n1_chiplet_register_types);
