/*
 * QEMU PowerPC PowerNV Interrupt Control Presenter (ICP) model
 *
 * Copyright (c) 2017, IBM Corporation.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */

#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/log.h"
#include "qemu/module.h"
#include "hw/ppc/xics.h"

#define ICP_XIRR_POLL    0 /* 1 byte (CPRR) or 4 bytes */
#define ICP_XIRR         4 /* 1 byte (CPRR) or 4 bytes */
#define ICP_MFRR        12 /* 1 byte access only */

#define ICP_LINKA       16 /* unused */
#define ICP_LINKB       20 /* unused */
#define ICP_LINKC       24 /* unused */

static uint64_t pnv_icp_read(void *opaque, hwaddr addr, unsigned width)
{
    ICPState *icp = ICP(opaque);
    PnvICPState *picp = PNV_ICP(opaque);
    bool byte0 = (width == 1 && (addr & 0x3) == 0);
    uint64_t val = 0xffffffff;

    switch (addr & 0xffc) {
    case ICP_XIRR_POLL:
        val = icp_ipoll(icp, NULL);
        if (byte0) {
            val >>= 24;
        } else if (width != 4) {
            goto bad_access;
        }
        break;
    case ICP_XIRR:
        if (byte0) {
            val = icp_ipoll(icp, NULL) >> 24;
        } else if (width == 4) {
            val = icp_accept(icp);
        } else {
            goto bad_access;
        }
        break;
    case ICP_MFRR:
        if (byte0) {
            val = icp->mfrr;
        } else {
            goto bad_access;
        }
        break;
    case ICP_LINKA:
        if (width == 4) {
            val = picp->links[0];
        } else {
            goto bad_access;
        }
        break;
    case ICP_LINKB:
        if (width == 4) {
            val = picp->links[1];
        } else {
            goto bad_access;
        }
        break;
    case ICP_LINKC:
        if (width == 4) {
            val = picp->links[2];
        } else {
            goto bad_access;
        }
        break;
    default:
bad_access:
        qemu_log_mask(LOG_GUEST_ERROR, "XICS: Bad ICP access 0x%"
                      HWADDR_PRIx"/%d\n", addr, width);
    }

    return val;
}

static void pnv_icp_write(void *opaque, hwaddr addr, uint64_t val,
                              unsigned width)
{
    ICPState *icp = ICP(opaque);
    PnvICPState *picp = PNV_ICP(opaque);
    bool byte0 = (width == 1 && (addr & 0x3) == 0);

    switch (addr & 0xffc) {
    case ICP_XIRR:
        if (byte0) {
            icp_set_cppr(icp, val);
        } else if (width == 4) {
            icp_eoi(icp, val);
        } else {
            goto bad_access;
        }
        break;
    case ICP_MFRR:
        if (byte0) {
            icp_set_mfrr(icp, val);
        } else {
            goto bad_access;
        }
        break;
    case ICP_LINKA:
        if (width == 4) {
            picp->links[0] = val;
        } else {
            goto bad_access;
        }
        break;
    case ICP_LINKB:
        if (width == 4) {
            picp->links[1] = val;
        } else {
            goto bad_access;
        }
        break;
    case ICP_LINKC:
        if (width == 4) {
            picp->links[2] = val;
        } else {
            goto bad_access;
        }
        break;
    default:
bad_access:
        qemu_log_mask(LOG_GUEST_ERROR, "XICS: Bad ICP access 0x%"
                      HWADDR_PRIx"/%d\n", addr, width);
    }
}

static const MemoryRegionOps pnv_icp_ops = {
    .read = pnv_icp_read,
    .write = pnv_icp_write,
    .endianness = DEVICE_BIG_ENDIAN,
    .valid = {
        .min_access_size = 1,
        .max_access_size = 4,
    },
    .impl = {
        .min_access_size = 1,
        .max_access_size = 4,
    },
};

static void pnv_icp_realize(DeviceState *dev, Error **errp)
{
    ICPState *icp = ICP(dev);
    PnvICPState *pnv_icp = PNV_ICP(icp);
    ICPStateClass *icpc = ICP_GET_CLASS(icp);
    Error *local_err = NULL;

    icpc->parent_realize(dev, &local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        return;
    }

    memory_region_init_io(&pnv_icp->mmio, OBJECT(icp), &pnv_icp_ops,
                          icp, "icp-thread", 0x1000);
}

static void pnv_icp_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    ICPStateClass *icpc = ICP_CLASS(klass);

    device_class_set_parent_realize(dc, pnv_icp_realize,
                                    &icpc->parent_realize);
    dc->desc = "PowerNV ICP";
}

static const TypeInfo pnv_icp_info = {
    .name          = TYPE_PNV_ICP,
    .parent        = TYPE_ICP,
    .instance_size = sizeof(PnvICPState),
    .class_init    = pnv_icp_class_init,
    .class_size    = sizeof(ICPStateClass),
};

static void pnv_icp_register_types(void)
{
    type_register_static(&pnv_icp_info);
}

type_init(pnv_icp_register_types)
