/*
 * Microchip PolarFire SoC MMUART emulation
 *
 * Copyright (c) 2020 Wind River Systems, Inc.
 *
 * Author:
 *   Bin Meng <bin.meng@windriver.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 or
 * (at your option) version 3 of the License.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#include "qemu/osdep.h"
#include "qemu/log.h"
#include "qapi/error.h"
#include "migration/vmstate.h"
#include "hw/char/mchp_pfsoc_mmuart.h"
#include "hw/qdev-properties.h"

#define REGS_OFFSET 0x20

static uint64_t mchp_pfsoc_mmuart_read(void *opaque, hwaddr addr, unsigned size)
{
    MchpPfSoCMMUartState *s = opaque;

    addr >>= 2;
    if (addr >= MCHP_PFSOC_MMUART_REG_COUNT) {
        qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%" HWADDR_PRIx "\n",
                      __func__, addr << 2);
        return 0;
    }

    return s->reg[addr];
}

static void mchp_pfsoc_mmuart_write(void *opaque, hwaddr addr,
                                    uint64_t value, unsigned size)
{
    MchpPfSoCMMUartState *s = opaque;
    uint32_t val32 = (uint32_t)value;

    addr >>= 2;
    if (addr >= MCHP_PFSOC_MMUART_REG_COUNT) {
        qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx
                      " v=0x%x\n", __func__, addr << 2, val32);
        return;
    }

    s->reg[addr] = val32;
}

static const MemoryRegionOps mchp_pfsoc_mmuart_ops = {
    .read = mchp_pfsoc_mmuart_read,
    .write = mchp_pfsoc_mmuart_write,
    .endianness = DEVICE_LITTLE_ENDIAN,
    .impl = {
        .min_access_size = 4,
        .max_access_size = 4,
    },
};

static void mchp_pfsoc_mmuart_reset(DeviceState *dev)
{
    MchpPfSoCMMUartState *s = MCHP_PFSOC_UART(dev);

    memset(s->reg, 0, sizeof(s->reg));
    device_cold_reset(DEVICE(&s->serial_mm));
}

static void mchp_pfsoc_mmuart_init(Object *obj)
{
    MchpPfSoCMMUartState *s = MCHP_PFSOC_UART(obj);

    object_initialize_child(obj, "serial-mm", &s->serial_mm, TYPE_SERIAL_MM);
    object_property_add_alias(obj, "chardev", OBJECT(&s->serial_mm), "chardev");
}

static void mchp_pfsoc_mmuart_realize(DeviceState *dev, Error **errp)
{
    MchpPfSoCMMUartState *s = MCHP_PFSOC_UART(dev);

    qdev_prop_set_uint8(DEVICE(&s->serial_mm), "regshift", 2);
    qdev_prop_set_uint32(DEVICE(&s->serial_mm), "baudbase", 399193);
    qdev_prop_set_uint8(DEVICE(&s->serial_mm), "endianness",
                        DEVICE_LITTLE_ENDIAN);
    if (!sysbus_realize(SYS_BUS_DEVICE(&s->serial_mm), errp)) {
        return;
    }

    sysbus_pass_irq(SYS_BUS_DEVICE(dev), SYS_BUS_DEVICE(&s->serial_mm));

    memory_region_init(&s->container, OBJECT(s), "mchp.pfsoc.mmuart", 0x1000);
    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container);

    memory_region_add_subregion(&s->container, 0,
                    sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->serial_mm), 0));

    memory_region_init_io(&s->iomem, OBJECT(s), &mchp_pfsoc_mmuart_ops, s,
                          "mchp.pfsoc.mmuart.regs", 0x1000 - REGS_OFFSET);
    memory_region_add_subregion(&s->container, REGS_OFFSET, &s->iomem);
}

static const VMStateDescription mchp_pfsoc_mmuart_vmstate = {
    .name = "mchp.pfsoc.uart",
    .version_id = 0,
    .minimum_version_id = 0,
    .fields = (const VMStateField[]) {
        VMSTATE_UINT32_ARRAY(reg, MchpPfSoCMMUartState,
                             MCHP_PFSOC_MMUART_REG_COUNT),
        VMSTATE_END_OF_LIST()
    }
};

static void mchp_pfsoc_mmuart_class_init(ObjectClass *oc, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(oc);

    dc->realize = mchp_pfsoc_mmuart_realize;
    device_class_set_legacy_reset(dc, mchp_pfsoc_mmuart_reset);
    dc->vmsd = &mchp_pfsoc_mmuart_vmstate;
    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}

static const TypeInfo mchp_pfsoc_mmuart_info = {
    .name          = TYPE_MCHP_PFSOC_UART,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(MchpPfSoCMMUartState),
    .instance_init = mchp_pfsoc_mmuart_init,
    .class_init    = mchp_pfsoc_mmuart_class_init,
};

static void mchp_pfsoc_mmuart_register_types(void)
{
    type_register_static(&mchp_pfsoc_mmuart_info);
}

type_init(mchp_pfsoc_mmuart_register_types)

MchpPfSoCMMUartState *mchp_pfsoc_mmuart_create(MemoryRegion *sysmem,
                                               hwaddr base,
                                               qemu_irq irq, Chardev *chr)
{
    DeviceState *dev = qdev_new(TYPE_MCHP_PFSOC_UART);
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);

    qdev_prop_set_chr(dev, "chardev", chr);
    sysbus_realize(sbd, &error_fatal);

    memory_region_add_subregion(sysmem, base, sysbus_mmio_get_region(sbd, 0));
    sysbus_connect_irq(sbd, 0, irq);

    return MCHP_PFSOC_UART(dev);
}
