/*
 * QEMU Ultrasparc Sabre PCI host (PBM)
 *
 * Copyright (c) 2006 Fabrice Bellard
 * Copyright (c) 2012,2013 Artyom Tarasenko
 * Copyright (c) 2018 Mark Cave-Ayland
 *
 * 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/pci/pci.h"
#include "hw/pci/pci_host.h"
#include "hw/qdev-properties.h"
#include "hw/pci/pci_bridge.h"
#include "hw/pci/pci_bus.h"
#include "hw/irq.h"
#include "hw/pci-bridge/simba.h"
#include "hw/pci-host/sabre.h"
#include "qapi/error.h"
#include "qemu/log.h"
#include "qemu/module.h"
#include "sysemu/runstate.h"
#include "trace.h"

/*
 * Chipset docs:
 * PBM: "UltraSPARC IIi User's Manual",
 * https://web.archive.org/web/20030403110020/http://www.sun.com/processors/manuals/805-0087.pdf
 */

#define PBM_PCI_IMR_MASK    0x7fffffff
#define PBM_PCI_IMR_ENABLED 0x80000000

#define POR          (1U << 31)
#define SOFT_POR     (1U << 30)
#define SOFT_XIR     (1U << 29)
#define BTN_POR      (1U << 28)
#define BTN_XIR      (1U << 27)
#define RESET_MASK   0xf8000000
#define RESET_WCMASK 0x98000000
#define RESET_WMASK  0x60000000

#define NO_IRQ_REQUEST (MAX_IVEC + 1)

static inline void sabre_set_request(SabreState *s, unsigned int irq_num)
{
    trace_sabre_set_request(irq_num);
    s->irq_request = irq_num;
    qemu_set_irq(s->ivec_irqs[irq_num], 1);
}

static inline void sabre_check_irqs(SabreState *s)
{
    unsigned int i;

    /* Previous request is not acknowledged, resubmit */
    if (s->irq_request != NO_IRQ_REQUEST) {
        sabre_set_request(s, s->irq_request);
        return;
    }
    /* no request pending */
    if (s->pci_irq_in == 0ULL) {
        return;
    }
    for (i = 0; i < 32; i++) {
        if (s->pci_irq_in & (1ULL << i)) {
            if (s->pci_irq_map[i >> 2] & PBM_PCI_IMR_ENABLED) {
                sabre_set_request(s, i);
                return;
            }
        }
    }
    for (i = 32; i < 64; i++) {
        if (s->pci_irq_in & (1ULL << i)) {
            if (s->obio_irq_map[i - 32] & PBM_PCI_IMR_ENABLED) {
                sabre_set_request(s, i);
                break;
            }
        }
    }
}

static inline void sabre_clear_request(SabreState *s, unsigned int irq_num)
{
    trace_sabre_clear_request(irq_num);
    qemu_set_irq(s->ivec_irqs[irq_num], 0);
    s->irq_request = NO_IRQ_REQUEST;
}

static AddressSpace *sabre_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
{
    IOMMUState *is = opaque;

    return &is->iommu_as;
}

static void sabre_config_write(void *opaque, hwaddr addr,
                               uint64_t val, unsigned size)
{
    SabreState *s = opaque;

    trace_sabre_config_write(addr, val);

    switch (addr) {
    case 0x30 ... 0x4f: /* DMA error registers */
        /* XXX: not implemented yet */
        break;
    case 0xc00 ... 0xc3f: /* PCI interrupt control */
        if (addr & 4) {
            unsigned int ino = (addr & 0x3f) >> 3;
            s->pci_irq_map[ino] &= PBM_PCI_IMR_MASK;
            s->pci_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
            if ((s->irq_request == ino) && !(val & ~PBM_PCI_IMR_MASK)) {
                sabre_clear_request(s, ino);
            }
            sabre_check_irqs(s);
        }
        break;
    case 0x1000 ... 0x107f: /* OBIO interrupt control */
        if (addr & 4) {
            unsigned int ino = ((addr & 0xff) >> 3);
            s->obio_irq_map[ino] &= PBM_PCI_IMR_MASK;
            s->obio_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
            if ((s->irq_request == (ino | 0x20))
                 && !(val & ~PBM_PCI_IMR_MASK)) {
                sabre_clear_request(s, ino | 0x20);
            }
            sabre_check_irqs(s);
        }
        break;
    case 0x1400 ... 0x14ff: /* PCI interrupt clear */
        if (addr & 4) {
            unsigned int ino = (addr & 0xff) >> 5;
            if ((s->irq_request / 4)  == ino) {
                sabre_clear_request(s, s->irq_request);
                sabre_check_irqs(s);
            }
        }
        break;
    case 0x1800 ... 0x1860: /* OBIO interrupt clear */
        if (addr & 4) {
            unsigned int ino = ((addr & 0xff) >> 3) | 0x20;
            if (s->irq_request == ino) {
                sabre_clear_request(s, ino);
                sabre_check_irqs(s);
            }
        }
        break;
    case 0x2000 ... 0x202f: /* PCI control */
        s->pci_control[(addr & 0x3f) >> 2] = val;
        break;
    case 0xf020 ... 0xf027: /* Reset control */
        if (addr & 4) {
            val &= RESET_MASK;
            s->reset_control &= ~(val & RESET_WCMASK);
            s->reset_control |= val & RESET_WMASK;
            if (val & SOFT_POR) {
                s->nr_resets = 0;
                qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
            } else if (val & SOFT_XIR) {
                qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
            }
        }
        break;
    case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
    case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
    case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
    case 0xf000 ... 0xf01f: /* FFB config, memory control */
        /* we don't care */
    default:
        break;
    }
}

static uint64_t sabre_config_read(void *opaque,
                                  hwaddr addr, unsigned size)
{
    SabreState *s = opaque;
    uint32_t val = 0;

    switch (addr) {
    case 0x30 ... 0x4f: /* DMA error registers */
        /* XXX: not implemented yet */
        break;
    case 0xc00 ... 0xc3f: /* PCI interrupt control */
        if (addr & 4) {
            val = s->pci_irq_map[(addr & 0x3f) >> 3];
        }
        break;
    case 0x1000 ... 0x107f: /* OBIO interrupt control */
        if (addr & 4) {
            val = s->obio_irq_map[(addr & 0xff) >> 3];
        }
        break;
    case 0x1080 ... 0x108f: /* PCI bus error */
        if (addr & 4) {
            val = s->pci_err_irq_map[(addr & 0xf) >> 3];
        }
        break;
    case 0x2000 ... 0x202f: /* PCI control */
        val = s->pci_control[(addr & 0x3f) >> 2];
        break;
    case 0xf020 ... 0xf027: /* Reset control */
        if (addr & 4) {
            val = s->reset_control;
        }
        break;
    case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
    case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
    case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
    case 0xf000 ... 0xf01f: /* FFB config, memory control */
        /* we don't care */
    default:
        break;
    }
    trace_sabre_config_read(addr, val);

    return val;
}

static const MemoryRegionOps sabre_config_ops = {
    .read = sabre_config_read,
    .write = sabre_config_write,
    .endianness = DEVICE_BIG_ENDIAN,
};

static void sabre_pci_config_write(void *opaque, hwaddr addr,
                                   uint64_t val, unsigned size)
{
    SabreState *s = opaque;
    PCIHostState *phb = PCI_HOST_BRIDGE(s);

    trace_sabre_pci_config_write(addr, val);
    pci_data_write(phb->bus, addr, val, size);
}

static uint64_t sabre_pci_config_read(void *opaque, hwaddr addr,
                                      unsigned size)
{
    uint32_t ret;
    SabreState *s = opaque;
    PCIHostState *phb = PCI_HOST_BRIDGE(s);

    ret = pci_data_read(phb->bus, addr, size);
    trace_sabre_pci_config_read(addr, ret);
    return ret;
}

/* The sabre host has an IRQ line for each IRQ line of each slot.  */
static int pci_sabre_map_irq(PCIDevice *pci_dev, int irq_num)
{
    /* Return the irq as swizzled by the PBM */
    return irq_num;
}

static int pci_simbaA_map_irq(PCIDevice *pci_dev, int irq_num)
{
    /* The on-board devices have fixed (legacy) OBIO intnos */
    switch (PCI_SLOT(pci_dev->devfn)) {
    case 1:
        /* Onboard NIC */
        return OBIO_NIC_IRQ;
    case 3:
        /* Onboard IDE */
        return OBIO_HDD_IRQ;
    default:
        /* Normal intno, fall through */
        break;
    }

    return ((PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f;
}

static int pci_simbaB_map_irq(PCIDevice *pci_dev, int irq_num)
{
    return (0x10 + (PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f;
}

static void pci_sabre_set_irq(void *opaque, int irq_num, int level)
{
    SabreState *s = opaque;

    trace_sabre_pci_set_irq(irq_num, level);

    /* PCI IRQ map onto the first 32 INO.  */
    if (irq_num < 32) {
        if (level) {
            s->pci_irq_in |= 1ULL << irq_num;
            if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
                sabre_set_request(s, irq_num);
            }
        } else {
            s->pci_irq_in &= ~(1ULL << irq_num);
        }
    } else {
        /* OBIO IRQ map onto the next 32 INO.  */
        if (level) {
            trace_sabre_pci_set_obio_irq(irq_num, level);
            s->pci_irq_in |= 1ULL << irq_num;
            if ((s->irq_request == NO_IRQ_REQUEST)
                && (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED)) {
                sabre_set_request(s, irq_num);
            }
        } else {
            s->pci_irq_in &= ~(1ULL << irq_num);
        }
    }
}

static void sabre_reset(DeviceState *d)
{
    SabreState *s = SABRE(d);
    PCIDevice *pci_dev;
    unsigned int i;
    uint16_t cmd;

    for (i = 0; i < 8; i++) {
        s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
    }
    for (i = 0; i < 32; i++) {
        s->obio_irq_map[i] &= PBM_PCI_IMR_MASK;
    }

    s->irq_request = NO_IRQ_REQUEST;
    s->pci_irq_in = 0ULL;

    if (s->nr_resets++ == 0) {
        /* Power on reset */
        s->reset_control = POR;
    }

    /* As this is the busA PCI bridge which contains the on-board devices
     * attached to the ebus, ensure that we initially allow IO transactions
     * so that we get the early serial console until OpenBIOS can properly
     * configure the PCI bridge itself */
    pci_dev = PCI_DEVICE(s->bridgeA);
    cmd = pci_get_word(pci_dev->config + PCI_COMMAND);
    pci_set_word(pci_dev->config + PCI_COMMAND, cmd | PCI_COMMAND_IO);
    pci_bridge_update_mappings(PCI_BRIDGE(pci_dev));
}

static const MemoryRegionOps pci_config_ops = {
    .read = sabre_pci_config_read,
    .write = sabre_pci_config_write,
    .endianness = DEVICE_LITTLE_ENDIAN,
};

static void sabre_realize(DeviceState *dev, Error **errp)
{
    SabreState *s = SABRE(dev);
    PCIHostState *phb = PCI_HOST_BRIDGE(dev);
    PCIDevice *pci_dev;

    memory_region_init(&s->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL);
    memory_region_add_subregion(get_system_memory(), s->mem_base,
                                &s->pci_mmio);

    phb->bus = pci_register_root_bus(dev, "pci",
                                     pci_sabre_set_irq, pci_sabre_map_irq, s,
                                     &s->pci_mmio,
                                     &s->pci_ioport,
                                     0, 0x40, TYPE_PCI_BUS);

    pci_create_simple(phb->bus, 0, TYPE_SABRE_PCI_DEVICE);

    /* IOMMU */
    memory_region_add_subregion_overlap(&s->sabre_config, 0x200,
                    sysbus_mmio_get_region(SYS_BUS_DEVICE(s->iommu), 0), 1);
    pci_setup_iommu(phb->bus, sabre_pci_dma_iommu, s->iommu);

    /* APB secondary busses */
    pci_dev = pci_new_multifunction(PCI_DEVFN(1, 0), true,
                                    TYPE_SIMBA_PCI_BRIDGE);
    s->bridgeB = PCI_BRIDGE(pci_dev);
    pci_bridge_map_irq(s->bridgeB, "pciB", pci_simbaB_map_irq);
    pci_realize_and_unref(pci_dev, phb->bus, &error_fatal);

    pci_dev = pci_new_multifunction(PCI_DEVFN(1, 1), true,
                                    TYPE_SIMBA_PCI_BRIDGE);
    s->bridgeA = PCI_BRIDGE(pci_dev);
    pci_bridge_map_irq(s->bridgeA, "pciA", pci_simbaA_map_irq);
    pci_realize_and_unref(pci_dev, phb->bus, &error_fatal);
}

static void sabre_init(Object *obj)
{
    SabreState *s = SABRE(obj);
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    unsigned int i;

    for (i = 0; i < 8; i++) {
        s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
    }
    for (i = 0; i < 2; i++) {
        s->pci_err_irq_map[i] = (0x1f << 6) | 0x30;
    }
    for (i = 0; i < 32; i++) {
        s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i;
    }
    qdev_init_gpio_in_named(DEVICE(s), pci_sabre_set_irq, "pbm-irq", MAX_IVEC);
    qdev_init_gpio_out_named(DEVICE(s), s->ivec_irqs, "ivec-irq", MAX_IVEC);
    s->irq_request = NO_IRQ_REQUEST;
    s->pci_irq_in = 0ULL;

    /* IOMMU */
    object_property_add_link(obj, "iommu", TYPE_SUN4U_IOMMU,
                             (Object **) &s->iommu,
                             qdev_prop_allow_set_link_before_realize,
                             0);

    /* sabre_config */
    memory_region_init_io(&s->sabre_config, OBJECT(s), &sabre_config_ops, s,
                          "sabre-config", 0x10000);
    /* at region 0 */
    sysbus_init_mmio(sbd, &s->sabre_config);

    memory_region_init_io(&s->pci_config, OBJECT(s), &pci_config_ops, s,
                          "sabre-pci-config", 0x1000000);
    /* at region 1 */
    sysbus_init_mmio(sbd, &s->pci_config);

    /* pci_ioport */
    memory_region_init(&s->pci_ioport, OBJECT(s), "sabre-pci-ioport",
                       0x1000000);

    /* at region 2 */
    sysbus_init_mmio(sbd, &s->pci_ioport);
}

static void sabre_pci_realize(PCIDevice *d, Error **errp)
{
    pci_set_word(d->config + PCI_COMMAND,
                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
    pci_set_word(d->config + PCI_STATUS,
                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
                 PCI_STATUS_DEVSEL_MEDIUM);
}

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

    k->realize = sabre_pci_realize;
    k->vendor_id = PCI_VENDOR_ID_SUN;
    k->device_id = PCI_DEVICE_ID_SUN_SABRE;
    k->class_id = PCI_CLASS_BRIDGE_HOST;
    /*
     * 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 sabre_pci_info = {
    .name          = TYPE_SABRE_PCI_DEVICE,
    .parent        = TYPE_PCI_DEVICE,
    .instance_size = sizeof(SabrePCIState),
    .class_init    = sabre_pci_class_init,
    .interfaces = (InterfaceInfo[]) {
        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
        { },
    },
};

static char *sabre_ofw_unit_address(const SysBusDevice *dev)
{
    SabreState *s = SABRE(dev);

    return g_strdup_printf("%x,%x",
               (uint32_t)((s->special_base >> 32) & 0xffffffff),
               (uint32_t)(s->special_base & 0xffffffff));
}

static Property sabre_properties[] = {
    DEFINE_PROP_UINT64("special-base", SabreState, special_base, 0),
    DEFINE_PROP_UINT64("mem-base", SabreState, mem_base, 0),
    DEFINE_PROP_END_OF_LIST(),
};

static void sabre_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);

    dc->realize = sabre_realize;
    dc->reset = sabre_reset;
    device_class_set_props(dc, sabre_properties);
    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
    dc->fw_name = "pci";
    sbc->explicit_ofw_unit_address = sabre_ofw_unit_address;
}

static const TypeInfo sabre_info = {
    .name          = TYPE_SABRE,
    .parent        = TYPE_PCI_HOST_BRIDGE,
    .instance_size = sizeof(SabreState),
    .instance_init = sabre_init,
    .class_init    = sabre_class_init,
};

static void sabre_register_types(void)
{
    type_register_static(&sabre_info);
    type_register_static(&sabre_pci_info);
}

type_init(sabre_register_types)
