/*
 * SuperH on-chip PCIC emulation.
 *
 * Copyright (c) 2008 Takashi YOSHII
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "hw/sh4/sh.h"
#include "hw/pci/pci.h"
#include "hw/pci/pci_host.h"
#include "qemu/bswap.h"
#include "exec/address-spaces.h"

#define TYPE_SH_PCI_HOST_BRIDGE "sh_pci"

#define SH_PCI_HOST_BRIDGE(obj) \
    OBJECT_CHECK(SHPCIState, (obj), TYPE_SH_PCI_HOST_BRIDGE)

typedef struct SHPCIState {
    PCIHostState parent_obj;

    PCIDevice *dev;
    qemu_irq irq[4];
    MemoryRegion memconfig_p4;
    MemoryRegion memconfig_a7;
    MemoryRegion isa;
    uint32_t par;
    uint32_t mbr;
    uint32_t iobr;
} SHPCIState;

static void sh_pci_reg_write (void *p, hwaddr addr, uint64_t val,
                              unsigned size)
{
    SHPCIState *pcic = p;
    PCIHostState *phb = PCI_HOST_BRIDGE(pcic);

    switch(addr) {
    case 0 ... 0xfc:
        stl_le_p(pcic->dev->config + addr, val);
        break;
    case 0x1c0:
        pcic->par = val;
        break;
    case 0x1c4:
        pcic->mbr = val & 0xff000001;
        break;
    case 0x1c8:
        if ((val & 0xfffc0000) != (pcic->iobr & 0xfffc0000)) {
            memory_region_del_subregion(get_system_memory(), &pcic->isa);
            pcic->iobr = val & 0xfffc0001;
            memory_region_add_subregion(get_system_memory(),
                                        pcic->iobr & 0xfffc0000, &pcic->isa);
        }
        break;
    case 0x220:
        pci_data_write(phb->bus, pcic->par, val, 4);
        break;
    }
}

static uint64_t sh_pci_reg_read (void *p, hwaddr addr,
                                 unsigned size)
{
    SHPCIState *pcic = p;
    PCIHostState *phb = PCI_HOST_BRIDGE(pcic);

    switch(addr) {
    case 0 ... 0xfc:
        return ldl_le_p(pcic->dev->config + addr);
    case 0x1c0:
        return pcic->par;
    case 0x1c4:
        return pcic->mbr;
    case 0x1c8:
        return pcic->iobr;
    case 0x220:
        return pci_data_read(phb->bus, pcic->par, 4);
    }
    return 0;
}

static const MemoryRegionOps sh_pci_reg_ops = {
    .read = sh_pci_reg_read,
    .write = sh_pci_reg_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
    .valid = {
        .min_access_size = 4,
        .max_access_size = 4,
    },
};

static int sh_pci_map_irq(PCIDevice *d, int irq_num)
{
    return (d->devfn >> 3);
}

static void sh_pci_set_irq(void *opaque, int irq_num, int level)
{
    qemu_irq *pic = opaque;

    qemu_set_irq(pic[irq_num], level);
}

static void sh_pci_device_realize(DeviceState *dev, Error **errp)
{
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
    SHPCIState *s = SH_PCI_HOST_BRIDGE(dev);
    PCIHostState *phb = PCI_HOST_BRIDGE(s);
    int i;

    for (i = 0; i < 4; i++) {
        sysbus_init_irq(sbd, &s->irq[i]);
    }
    phb->bus = pci_register_root_bus(DEVICE(dev), "pci",
                                     sh_pci_set_irq, sh_pci_map_irq,
                                     s->irq,
                                     get_system_memory(),
                                     get_system_io(),
                                     PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS);
    memory_region_init_io(&s->memconfig_p4, OBJECT(s), &sh_pci_reg_ops, s,
                          "sh_pci", 0x224);
    memory_region_init_alias(&s->memconfig_a7, OBJECT(s), "sh_pci.2",
                             &s->memconfig_p4, 0, 0x224);
    memory_region_init_alias(&s->isa, OBJECT(s), "sh_pci.isa",
                             get_system_io(), 0, 0x40000);
    sysbus_init_mmio(sbd, &s->memconfig_p4);
    sysbus_init_mmio(sbd, &s->memconfig_a7);
    s->iobr = 0xfe240000;
    memory_region_add_subregion(get_system_memory(), s->iobr, &s->isa);

    s->dev = pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "sh_pci_host");
}

static void sh_pci_host_realize(PCIDevice *d, Error **errp)
{
    pci_set_word(d->config + PCI_COMMAND, PCI_COMMAND_WAIT);
    pci_set_word(d->config + PCI_STATUS, PCI_STATUS_CAP_LIST |
                 PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
}

static void sh_pci_host_class_init(ObjectClass *klass, void *data)
{
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
    DeviceClass *dc = DEVICE_CLASS(klass);

    k->realize = sh_pci_host_realize;
    k->vendor_id = PCI_VENDOR_ID_HITACHI;
    k->device_id = PCI_DEVICE_ID_HITACHI_SH7751R;
    /*
     * PCI-facing part of the host bridge, not usable without the
     * host-facing part, which can't be device_add'ed, yet.
     */
    dc->user_creatable = false;
}

static const TypeInfo sh_pci_host_info = {
    .name          = "sh_pci_host",
    .parent        = TYPE_PCI_DEVICE,
    .instance_size = sizeof(PCIDevice),
    .class_init    = sh_pci_host_class_init,
    .interfaces = (InterfaceInfo[]) {
        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
        { },
    },
};

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

    dc->realize = sh_pci_device_realize;
}

static const TypeInfo sh_pci_device_info = {
    .name          = TYPE_SH_PCI_HOST_BRIDGE,
    .parent        = TYPE_PCI_HOST_BRIDGE,
    .instance_size = sizeof(SHPCIState),
    .class_init    = sh_pci_device_class_init,
};

static void sh_pci_register_types(void)
{
    type_register_static(&sh_pci_device_info);
    type_register_static(&sh_pci_host_info);
}

type_init(sh_pci_register_types)
