/*
 * Aspeed SD Host Controller
 * Eddie James <eajames@linux.ibm.com>
 *
 * Copyright (C) 2019 IBM Corp
 * SPDX-License-Identifer: GPL-2.0-or-later
 */

#include "qemu/osdep.h"
#include "qemu/log.h"
#include "qemu/error-report.h"
#include "hw/sd/aspeed_sdhci.h"
#include "qapi/error.h"
#include "hw/irq.h"
#include "migration/vmstate.h"
#include "hw/qdev-properties.h"

#define ASPEED_SDHCI_INFO            0x00
#define  ASPEED_SDHCI_INFO_RESET     0x00030000
#define ASPEED_SDHCI_DEBOUNCE        0x04
#define  ASPEED_SDHCI_DEBOUNCE_RESET 0x00000005
#define ASPEED_SDHCI_BUS             0x08
#define ASPEED_SDHCI_SDIO_140        0x10
#define ASPEED_SDHCI_SDIO_148        0x18
#define ASPEED_SDHCI_SDIO_240        0x20
#define ASPEED_SDHCI_SDIO_248        0x28
#define ASPEED_SDHCI_WP_POL          0xec
#define ASPEED_SDHCI_CARD_DET        0xf0
#define ASPEED_SDHCI_IRQ_STAT        0xfc

#define TO_REG(addr) ((addr) / sizeof(uint32_t))

static uint64_t aspeed_sdhci_read(void *opaque, hwaddr addr, unsigned int size)
{
    uint32_t val = 0;
    AspeedSDHCIState *sdhci = opaque;

    switch (addr) {
    case ASPEED_SDHCI_SDIO_140:
        val = (uint32_t)sdhci->slots[0].capareg;
        break;
    case ASPEED_SDHCI_SDIO_148:
        val = (uint32_t)sdhci->slots[0].maxcurr;
        break;
    case ASPEED_SDHCI_SDIO_240:
        val = (uint32_t)sdhci->slots[1].capareg;
        break;
    case ASPEED_SDHCI_SDIO_248:
        val = (uint32_t)sdhci->slots[1].maxcurr;
        break;
    default:
        if (addr < ASPEED_SDHCI_REG_SIZE) {
            val = sdhci->regs[TO_REG(addr)];
        } else {
            qemu_log_mask(LOG_GUEST_ERROR,
                          "%s: Out-of-bounds read at 0x%" HWADDR_PRIx "\n",
                          __func__, addr);
        }
    }

    return (uint64_t)val;
}

static void aspeed_sdhci_write(void *opaque, hwaddr addr, uint64_t val,
                               unsigned int size)
{
    AspeedSDHCIState *sdhci = opaque;

    switch (addr) {
    case ASPEED_SDHCI_SDIO_140:
        sdhci->slots[0].capareg = (uint64_t)(uint32_t)val;
        break;
    case ASPEED_SDHCI_SDIO_148:
        sdhci->slots[0].maxcurr = (uint64_t)(uint32_t)val;
        break;
    case ASPEED_SDHCI_SDIO_240:
        sdhci->slots[1].capareg = (uint64_t)(uint32_t)val;
        break;
    case ASPEED_SDHCI_SDIO_248:
        sdhci->slots[1].maxcurr = (uint64_t)(uint32_t)val;
        break;
    default:
        if (addr < ASPEED_SDHCI_REG_SIZE) {
            sdhci->regs[TO_REG(addr)] = (uint32_t)val;
        } else {
            qemu_log_mask(LOG_GUEST_ERROR,
                          "%s: Out-of-bounds write at 0x%" HWADDR_PRIx "\n",
                          __func__, addr);
        }
    }
}

static const MemoryRegionOps aspeed_sdhci_ops = {
    .read = aspeed_sdhci_read,
    .write = aspeed_sdhci_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
    .valid.min_access_size = 4,
    .valid.max_access_size = 4,
};

static void aspeed_sdhci_set_irq(void *opaque, int n, int level)
{
    AspeedSDHCIState *sdhci = opaque;

    if (level) {
        sdhci->regs[TO_REG(ASPEED_SDHCI_IRQ_STAT)] |= BIT(n);

        qemu_irq_raise(sdhci->irq);
    } else {
        sdhci->regs[TO_REG(ASPEED_SDHCI_IRQ_STAT)] &= ~BIT(n);

        qemu_irq_lower(sdhci->irq);
    }
}

static void aspeed_sdhci_realize(DeviceState *dev, Error **errp)
{
    Error *err = NULL;
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
    AspeedSDHCIState *sdhci = ASPEED_SDHCI(dev);

    /* Create input irqs for the slots */
    qdev_init_gpio_in_named_with_opaque(DEVICE(sbd), aspeed_sdhci_set_irq,
                                        sdhci, NULL, sdhci->num_slots);

    sysbus_init_irq(sbd, &sdhci->irq);
    memory_region_init_io(&sdhci->iomem, OBJECT(sdhci), &aspeed_sdhci_ops,
                          sdhci, TYPE_ASPEED_SDHCI, 0x1000);
    sysbus_init_mmio(sbd, &sdhci->iomem);

    for (int i = 0; i < sdhci->num_slots; ++i) {
        Object *sdhci_slot = OBJECT(&sdhci->slots[i]);
        SysBusDevice *sbd_slot = SYS_BUS_DEVICE(&sdhci->slots[i]);

        object_property_set_int(sdhci_slot, 2, "sd-spec-version", &err);
        if (err) {
            error_propagate(errp, err);
            return;
        }

        object_property_set_uint(sdhci_slot, ASPEED_SDHCI_CAPABILITIES,
                                 "capareg", &err);
        if (err) {
            error_propagate(errp, err);
            return;
        }

        object_property_set_bool(sdhci_slot, true, "realized", &err);
        if (err) {
            error_propagate(errp, err);
            return;
        }

        sysbus_connect_irq(sbd_slot, 0, qdev_get_gpio_in(DEVICE(sbd), i));
        memory_region_add_subregion(&sdhci->iomem, (i + 1) * 0x100,
                                    &sdhci->slots[i].iomem);
    }
}

static void aspeed_sdhci_reset(DeviceState *dev)
{
    AspeedSDHCIState *sdhci = ASPEED_SDHCI(dev);

    memset(sdhci->regs, 0, ASPEED_SDHCI_REG_SIZE);
    sdhci->regs[TO_REG(ASPEED_SDHCI_INFO)] = ASPEED_SDHCI_INFO_RESET;
    sdhci->regs[TO_REG(ASPEED_SDHCI_DEBOUNCE)] = ASPEED_SDHCI_DEBOUNCE_RESET;
}

static const VMStateDescription vmstate_aspeed_sdhci = {
    .name = TYPE_ASPEED_SDHCI,
    .version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT32_ARRAY(regs, AspeedSDHCIState, ASPEED_SDHCI_NUM_REGS),
        VMSTATE_END_OF_LIST(),
    },
};

static Property aspeed_sdhci_properties[] = {
    DEFINE_PROP_UINT8("num-slots", AspeedSDHCIState, num_slots, 0),
    DEFINE_PROP_END_OF_LIST(),
};

static void aspeed_sdhci_class_init(ObjectClass *classp, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(classp);

    dc->realize = aspeed_sdhci_realize;
    dc->reset = aspeed_sdhci_reset;
    dc->vmsd = &vmstate_aspeed_sdhci;
    device_class_set_props(dc, aspeed_sdhci_properties);
}

static TypeInfo aspeed_sdhci_info = {
    .name          = TYPE_ASPEED_SDHCI,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(AspeedSDHCIState),
    .class_init    = aspeed_sdhci_class_init,
};

static void aspeed_sdhci_register_types(void)
{
    type_register_static(&aspeed_sdhci_info);
}

type_init(aspeed_sdhci_register_types)
