/*
 * Aspeed PECI Controller
 *
 * Copyright (c) Meta Platforms, Inc. and affiliates. (http://www.meta.com)
 *
 * This code is licensed under the GPL version 2 or later. See the COPYING
 * file in the top-level directory.
 */

#include "qemu/osdep.h"
#include "qemu/log.h"
#include "hw/irq.h"
#include "hw/misc/aspeed_peci.h"
#include "hw/registerfields.h"
#include "trace.h"

#define ASPEED_PECI_CC_RSP_SUCCESS (0x40U)

/* Command Register */
REG32(PECI_CMD, 0x08)
    FIELD(PECI_CMD, FIRE, 0, 1)

/* Interrupt Control Register */
REG32(PECI_INT_CTRL, 0x18)

/* Interrupt Status Register */
REG32(PECI_INT_STS, 0x1C)
    FIELD(PECI_INT_STS, CMD_DONE, 0, 1)

/* Rx/Tx Data Buffer Registers */
REG32(PECI_WR_DATA0, 0x20)
REG32(PECI_RD_DATA0, 0x30)

static void aspeed_peci_raise_interrupt(AspeedPECIState *s, uint32_t status)
{
    trace_aspeed_peci_raise_interrupt(s->regs[R_PECI_INT_CTRL], status);

    s->regs[R_PECI_INT_STS] = s->regs[R_PECI_INT_CTRL] & status;
    if (!s->regs[R_PECI_INT_STS]) {
        return;
    }
    qemu_irq_raise(s->irq);
}

static uint64_t aspeed_peci_read(void *opaque, hwaddr offset, unsigned size)
{
    AspeedPECIState *s = ASPEED_PECI(opaque);
    uint64_t data;

    if (offset >= ASPEED_PECI_NR_REGS << 2) {
        qemu_log_mask(LOG_GUEST_ERROR,
                      "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
                      __func__, offset);
        return 0;
    }
    data = s->regs[offset >> 2];

    trace_aspeed_peci_read(offset, data);
    return data;
}

static void aspeed_peci_write(void *opaque, hwaddr offset, uint64_t data,
                              unsigned size)
{
    AspeedPECIState *s = ASPEED_PECI(opaque);

    trace_aspeed_peci_write(offset, data);

    if (offset >= ASPEED_PECI_NR_REGS << 2) {
        qemu_log_mask(LOG_GUEST_ERROR,
                      "%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
                      __func__, offset);
        return;
    }

    switch (offset) {
    case A_PECI_INT_STS:
        s->regs[R_PECI_INT_STS] &= ~data;
        if (!s->regs[R_PECI_INT_STS]) {
            qemu_irq_lower(s->irq);
        }
        break;
    case A_PECI_CMD:
        /*
         * Only the FIRE bit is writable. Once the command is complete, it
         * should be cleared. Since we complete the command immediately, the
         * value is not stored in the register array.
         */
        if (!FIELD_EX32(data, PECI_CMD, FIRE)) {
            break;
        }
        if (s->regs[R_PECI_INT_STS]) {
            qemu_log_mask(LOG_GUEST_ERROR, "%s: Interrupt status must be "
                          "cleared before firing another command: 0x%08x\n",
                          __func__, s->regs[R_PECI_INT_STS]);
            break;
        }
        s->regs[R_PECI_RD_DATA0] = ASPEED_PECI_CC_RSP_SUCCESS;
        s->regs[R_PECI_WR_DATA0] = ASPEED_PECI_CC_RSP_SUCCESS;
        aspeed_peci_raise_interrupt(s,
                                    FIELD_DP32(0, PECI_INT_STS, CMD_DONE, 1));
        break;
    default:
        s->regs[offset / sizeof(s->regs[0])] = data;
        break;
    }
}

static const MemoryRegionOps aspeed_peci_ops = {
    .read = aspeed_peci_read,
    .write = aspeed_peci_write,
    .endianness = DEVICE_LITTLE_ENDIAN,
};

static void aspeed_peci_realize(DeviceState *dev, Error **errp)
{
    AspeedPECIState *s = ASPEED_PECI(dev);
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);

    memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_peci_ops, s,
                          TYPE_ASPEED_PECI, 0x1000);
    sysbus_init_mmio(sbd, &s->mmio);
    sysbus_init_irq(sbd, &s->irq);
}

static void aspeed_peci_reset(DeviceState *dev)
{
    AspeedPECIState *s = ASPEED_PECI(dev);

    memset(s->regs, 0, sizeof(s->regs));
}

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

    dc->realize = aspeed_peci_realize;
    device_class_set_legacy_reset(dc, aspeed_peci_reset);
    dc->desc = "Aspeed PECI Controller";
}

static const TypeInfo aspeed_peci_types[] = {
    {
        .name = TYPE_ASPEED_PECI,
        .parent = TYPE_SYS_BUS_DEVICE,
        .instance_size = sizeof(AspeedPECIState),
        .class_init = aspeed_peci_class_init,
        .abstract = false,
    },
};

DEFINE_TYPES(aspeed_peci_types);
