/*
 * QEMU Allwinner AHCI Emulation
 *
 * 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
 * of the License, or (at your option) any later version.
 *
 * 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/error-report.h"
#include "qemu/module.h"
#include "sysemu/dma.h"
#include "hw/ide/internal.h"
#include "migration/vmstate.h"
#include "ahci_internal.h"

#include "trace.h"

#define ALLWINNER_AHCI(obj) \
        OBJECT_CHECK(AllwinnerAHCIState, (obj), TYPE_ALLWINNER_AHCI)

#define ALLWINNER_AHCI_BISTAFR    ((0xa0 - ALLWINNER_AHCI_MMIO_OFF) / 4)
#define ALLWINNER_AHCI_BISTCR     ((0xa4 - ALLWINNER_AHCI_MMIO_OFF) / 4)
#define ALLWINNER_AHCI_BISTFCTR   ((0xa8 - ALLWINNER_AHCI_MMIO_OFF) / 4)
#define ALLWINNER_AHCI_BISTSR     ((0xac - ALLWINNER_AHCI_MMIO_OFF) / 4)
#define ALLWINNER_AHCI_BISTDECR   ((0xb0 - ALLWINNER_AHCI_MMIO_OFF) / 4)
#define ALLWINNER_AHCI_DIAGNR0    ((0xb4 - ALLWINNER_AHCI_MMIO_OFF) / 4)
#define ALLWINNER_AHCI_DIAGNR1    ((0xb8 - ALLWINNER_AHCI_MMIO_OFF) / 4)
#define ALLWINNER_AHCI_OOBR       ((0xbc - ALLWINNER_AHCI_MMIO_OFF) / 4)
#define ALLWINNER_AHCI_PHYCS0R    ((0xc0 - ALLWINNER_AHCI_MMIO_OFF) / 4)
#define ALLWINNER_AHCI_PHYCS1R    ((0xc4 - ALLWINNER_AHCI_MMIO_OFF) / 4)
#define ALLWINNER_AHCI_PHYCS2R    ((0xc8 - ALLWINNER_AHCI_MMIO_OFF) / 4)
#define ALLWINNER_AHCI_TIMER1MS   ((0xe0 - ALLWINNER_AHCI_MMIO_OFF) / 4)
#define ALLWINNER_AHCI_GPARAM1R   ((0xe8 - ALLWINNER_AHCI_MMIO_OFF) / 4)
#define ALLWINNER_AHCI_GPARAM2R   ((0xec - ALLWINNER_AHCI_MMIO_OFF) / 4)
#define ALLWINNER_AHCI_PPARAMR    ((0xf0 - ALLWINNER_AHCI_MMIO_OFF) / 4)
#define ALLWINNER_AHCI_TESTR      ((0xf4 - ALLWINNER_AHCI_MMIO_OFF) / 4)
#define ALLWINNER_AHCI_VERSIONR   ((0xf8 - ALLWINNER_AHCI_MMIO_OFF) / 4)
#define ALLWINNER_AHCI_IDR        ((0xfc - ALLWINNER_AHCI_MMIO_OFF) / 4)
#define ALLWINNER_AHCI_RWCR       ((0xfc - ALLWINNER_AHCI_MMIO_OFF) / 4)

static uint64_t allwinner_ahci_mem_read(void *opaque, hwaddr addr,
                                        unsigned size)
{
    AllwinnerAHCIState *a = opaque;
    AHCIState *s = &(SYSBUS_AHCI(a)->ahci);
    uint64_t val = a->regs[addr / 4];

    switch (addr / 4) {
    case ALLWINNER_AHCI_PHYCS0R:
        val |= 0x2 << 28;
        break;
    case ALLWINNER_AHCI_PHYCS2R:
        val &= ~(0x1 << 24);
        break;
    }
    trace_allwinner_ahci_mem_read(s, a, addr, val, size);
    return  val;
}

static void allwinner_ahci_mem_write(void *opaque, hwaddr addr,
                                     uint64_t val, unsigned size)
{
    AllwinnerAHCIState *a = opaque;
    AHCIState *s = &(SYSBUS_AHCI(a)->ahci);

    trace_allwinner_ahci_mem_write(s, a, addr, val, size);
    a->regs[addr / 4] = val;
}

static const MemoryRegionOps allwinner_ahci_mem_ops = {
    .read = allwinner_ahci_mem_read,
    .write = allwinner_ahci_mem_write,
    .valid.min_access_size = 4,
    .valid.max_access_size = 4,
    .endianness = DEVICE_LITTLE_ENDIAN,
};

static void allwinner_ahci_init(Object *obj)
{
    SysbusAHCIState *s = SYSBUS_AHCI(obj);
    AllwinnerAHCIState *a = ALLWINNER_AHCI(obj);

    memory_region_init_io(&a->mmio, obj, &allwinner_ahci_mem_ops, a,
                          "allwinner-ahci", ALLWINNER_AHCI_MMIO_SIZE);
    memory_region_add_subregion(&s->ahci.mem, ALLWINNER_AHCI_MMIO_OFF,
                                &a->mmio);
}

static const VMStateDescription vmstate_allwinner_ahci = {
    .name = "allwinner-ahci",
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT32_ARRAY(regs, AllwinnerAHCIState,
                             ALLWINNER_AHCI_MMIO_SIZE / 4),
        VMSTATE_END_OF_LIST()
    }
};

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

    dc->vmsd = &vmstate_allwinner_ahci;
}

static const TypeInfo allwinner_ahci_info = {
    .name          = TYPE_ALLWINNER_AHCI,
    .parent        = TYPE_SYSBUS_AHCI,
    .instance_size = sizeof(AllwinnerAHCIState),
    .instance_init = allwinner_ahci_init,
    .class_init    = allwinner_ahci_class_init,
};

static void sysbus_ahci_register_types(void)
{
    type_register_static(&allwinner_ahci_info);
}

type_init(sysbus_ahci_register_types)
