Add the root bus, configuration apertures, I/O window, PEM register access and interrupt routing. Leave guest PCI memory transactions to a separate patch.
Signed-off-by: Kirill A. Korinsky <[email protected]> --- hw/mips/Kconfig | 3 + hw/mips/octeon.c | 69 ++++++- hw/mips/octeon_internal.h | 13 ++ hw/pci-bridge/meson.build | 5 + hw/pci-bridge/octeon_pci.c | 356 +++++++++++++++++++++++++++++++++++++ 5 files changed, 444 insertions(+), 2 deletions(-) create mode 100644 hw/pci-bridge/octeon_pci.c diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig index 2566df6da6..54ce3cafbd 100644 --- a/hw/mips/Kconfig +++ b/hw/mips/Kconfig @@ -71,6 +71,9 @@ config MIPS_OCTEON bool default y depends on MIPS64 && TARGET_BIG_ENDIAN + imply E1000_PCI + imply PCI_DEVICES + select PCI select PFLASH_CFI02 select SERIAL_MM select USB_DWC3 diff --git a/hw/mips/octeon.c b/hw/mips/octeon.c index 94717b6c89..19d1451464 100644 --- a/hw/mips/octeon.c +++ b/hw/mips/octeon.c @@ -94,6 +94,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_CSR_BANK) #define OCTEON_CIU_FUSE 0x728 #define OCTEON_CIU_SUM_IPI 0x0000000100000000ULL #define OCTEON_CIU_SUM_UART 0x0000000800000000ULL +#define OCTEON_CIU_SUM_PCI 0x0000001000000000ULL #define OCTEON_CIU_ENABLE0 0x88006f1800000000ULL #define OCTEON_CIU_IPI_SUM_BASE 0x008 #define OCTEON_CIU_IPI_SUM_STRIDE 0x10 @@ -137,6 +138,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_CSR_BANK) #define OCTEON_CIU3_SRC_RAW 0x00000002U #define OCTEON_CIU3_NINTSN (1U << 20) #define OCTEON_CIU3_ISC_SIZE (OCTEON_CIU3_NINTSN * 8) +#define OCTEON_CIU3_PEM_INTSN_INTA(port) (((0xc0 + (port)) << 12) + 60) #define OCTEON_CIU3_MBOX_INTSN(cpu) ((cpu) + 0x4000U) #define OCTEON_CIU3_UART0_INTSN 0x8000 #define OCTEON_CSR_BASE 0x1180000000000ULL @@ -304,6 +306,18 @@ OBJECT_DECLARE_SIMPLE_TYPE(OcteonCsrBankState, OCTEON_CSR_BANK) #define OCTEON_CVMSEG_SIZE 0x4000 #define OCTEON_CVMSEG_TOTAL_SIZE (OCTEON_MAX_CPUS * OCTEON_CVMSEG_SIZE) +#define OCTEON_GSERX_CFG0 0x90000080 +#define OCTEON_GSERX_QLM_STAT0 0x900000a0 +#define OCTEON_RST_CTLX0 0x6001640 +#define OCTEON_RST_SOFT_PRSTX0 0x60016c0 +#define OCTEON_PEMX_CFG_RD0 0xc0000030 +#define OCTEON_PEMX_CFG_WR0 0xc0000028 +#define OCTEON_PEMX_BIST_STATUS0 0xc0000440 +#define OCTEON_PEMX_ON0 0xc0000420 +#define OCTEON_PEMX_STRAP0 0xc0000408 + +#define OCTEON_RST_CTL_HOST_MODE (1ULL << 6) +#define OCTEON_RST_CTL_RST_DONE (1ULL << 8) #define OCTEON_FLASH_BASE 0x1f400000ULL #define OCTEON_FLASH_RESET_BASE 0x1fc00000ULL #define OCTEON_FLASH_RESET_SIZE (4 * MiB) @@ -385,6 +399,7 @@ struct OcteonIntcState { uint64_t ciu_gpio_tx; uint64_t ciu_gpio_bit_cfg[OCTEON_CIU_GPIO_COUNT]; bool uart_pending; + bool pci_pending; uint64_t ciu3_pp_rst; uint32_t ciu3_src_state[OCTEON_CIU3_SRC_COUNT]; uint64_t ciu3_src_ctl[OCTEON_CIU3_SRC_COUNT]; @@ -517,7 +532,8 @@ bool octeon_csr_lookup(OcteonState *s, uint64_t reg, uint64_t *value) if (octeon_mio_emm_decode(reg, &ereg)) { return octeon_reg_lookup(s->emm->regs, ereg, value); } - if (reg == OCTEON_RST_SOFT_RST) { + if (reg == OCTEON_RST_CTLX0 || reg == OCTEON_RST_SOFT_PRSTX0 || + reg == OCTEON_RST_SOFT_RST) { return octeon_reg_lookup(s->rst->regs, reg, value); } return octeon_reg_lookup(s->csr_bank->values, reg, value); @@ -531,7 +547,8 @@ static void octeon_csr_store(OcteonState *s, uint64_t reg, uint64_t value) octeon_reg_store(s->emm->regs, ereg, value); return; } - if (reg == OCTEON_RST_SOFT_RST) { + if (reg == OCTEON_RST_CTLX0 || reg == OCTEON_RST_SOFT_PRSTX0 || + reg == OCTEON_RST_SOFT_RST) { octeon_reg_store(s->rst->regs, reg, value); return; } @@ -1031,6 +1048,10 @@ static void octeon_lmc_write(OcteonLmcState *lmc, hwaddr reg, static bool octeon_ciu3_source_from_intsn(uint32_t intsn, unsigned int *source) { + if (intsn == OCTEON_CIU3_PEM_INTSN_INTA(0)) { + *source = OCTEON_CIU3_SRC_PCI_INTA; + return true; + } if (intsn == OCTEON_CIU3_UART0_INTSN) { *source = OCTEON_CIU3_SRC_UART0; return true; @@ -1057,6 +1078,8 @@ static bool octeon_ciu3_source_from_intsn(uint32_t intsn, static uint32_t octeon_ciu3_source_intsn(unsigned int source) { switch (source) { + case OCTEON_CIU3_SRC_PCI_INTA: + return OCTEON_CIU3_PEM_INTSN_INTA(0); case OCTEON_CIU3_SRC_UART0: return OCTEON_CIU3_UART0_INTSN; case OCTEON_CIU3_SRC_USB0: @@ -1076,6 +1099,7 @@ static uint32_t octeon_ciu3_source_intsn(unsigned int source) static bool octeon_ciu3_source_is_level(unsigned int source) { switch (source) { + case OCTEON_CIU3_SRC_PCI_INTA: case OCTEON_CIU3_SRC_UART0: case OCTEON_CIU3_SRC_USB0: case OCTEON_CIU3_SRC_USB1: @@ -1395,6 +1419,9 @@ static uint64_t octeon_ciu_read(void *opaque, hwaddr addr, unsigned size) if (qatomic_read(&s->intc->uart_pending)) { value |= OCTEON_CIU_SUM_UART; } + if (qatomic_read(&s->intc->pci_pending)) { + value |= OCTEON_CIU_SUM_PCI; + } octeon_intc_request_cpu_update(s, 0); return octeon_read64(value, addr, size); } @@ -1883,6 +1910,29 @@ static uint64_t octeon_csr_read(void *opaque, hwaddr addr, unsigned size) return octeon_read64(value, addr, size); case OCTEON_RST_PP_POWER: return octeon_read64(s->rst->rst_pp_power, addr, size); + case OCTEON_GSERX_CFG0: + return octeon_read64(1, addr, size); + case OCTEON_GSERX_QLM_STAT0: + return octeon_read64(3, addr, size); + case OCTEON_RST_CTLX0: + if (!octeon_csr_lookup(s, reg, &value)) { + value = OCTEON_RST_CTL_HOST_MODE | OCTEON_RST_CTL_RST_DONE; + } + return octeon_read64(value, addr, size); + case OCTEON_RST_SOFT_PRSTX0: + if (!octeon_csr_lookup(s, reg, &value)) { + value = 1; + } + return octeon_read64(value, addr, size); + case OCTEON_PEMX_CFG_RD0: + case OCTEON_PEMX_CFG_WR0: + return octeon_pci_pem_read(s, reg, addr, size); + case OCTEON_PEMX_BIST_STATUS0: + return 0; + case OCTEON_PEMX_ON0: + return octeon_read64(3, addr, size); + case OCTEON_PEMX_STRAP0: + return octeon_read64(3, addr, size); default: break; } @@ -1963,6 +2013,11 @@ static void octeon_csr_write(void *opaque, hwaddr addr, return; } + if (reg == OCTEON_PEMX_CFG_RD0 || reg == OCTEON_PEMX_CFG_WR0) { + octeon_pci_pem_write(s, reg, addr, value, size); + return; + } + if (reg >= OCTEON_MIO_BOOT_REG_CFGX(0) && reg < OCTEON_MIO_BOOT_REG_CFGX(OCTEON_MIO_BOOT_REG_CFG_COUNT)) { unsigned int index = OCTEON_MIO_BOOT_REG_CFG_INDEX(reg); @@ -2174,6 +2229,13 @@ void octeon_irq_set(void *opaque, int irq, int level) } qatomic_set(&s->intc->uart_pending, level); break; + case OCTEON_IRQ_PCI: + src = OCTEON_CIU3_SRC_PCI_INTA; + if (!octeon_ciu3_set_level(s, src, level)) { + return; + } + qatomic_set(&s->intc->pci_pending, level); + break; case OCTEON_IRQ_USB0: src = OCTEON_CIU3_SRC_USB0; if (!octeon_ciu3_set_level(s, src, level)) { @@ -2550,6 +2612,7 @@ static void octeon_intc_reset_hold(Object *obj, ResetType type) qatomic_set(&intc->ciu_gpio_tx, 0); memset(intc->ciu_gpio_bit_cfg, 0, sizeof(intc->ciu_gpio_bit_cfg)); qatomic_set(&intc->uart_pending, false); + qatomic_set(&intc->pci_pending, false); qatomic_set(&intc->ciu3_pp_rst, octeon_secondary_cpu_mask(s)); memset(intc->ciu3_src_state, 0, sizeof(intc->ciu3_src_state)); memset(intc->ciu3_src_ctl, 0, sizeof(intc->ciu3_src_ctl)); @@ -2822,6 +2885,7 @@ static void mips_octeon_init(MachineState *machine) &s->pow); octeon_init_usb(s); + octeon_init_pci(s); octeon_realize_peripherals(s); } @@ -2877,6 +2941,7 @@ static void octeon_machine_class_init(ObjectClass *oc, const void *data) mc->default_ram_size = OCTEON_DEFAULT_RAM_SIZE; mc->default_ram_id = "octeon.ram"; mc->max_cpus = OCTEON_MAX_CPUS; + mc->pci_allow_0_address = true; } static const TypeInfo octeon_machine_types[] = { diff --git a/hw/mips/octeon_internal.h b/hw/mips/octeon_internal.h index 6c93c957de..c2a88dac46 100644 --- a/hw/mips/octeon_internal.h +++ b/hw/mips/octeon_internal.h @@ -30,12 +30,14 @@ typedef enum OcteonIRQ { OCTEON_IRQ_UART, + OCTEON_IRQ_PCI, OCTEON_IRQ_USB0, OCTEON_IRQ_USB1, OCTEON_IRQ_COUNT, } OcteonIRQ; typedef enum OcteonCiu3Source { + OCTEON_CIU3_SRC_PCI_INTA, OCTEON_CIU3_SRC_UART0, OCTEON_CIU3_SRC_USB0, OCTEON_CIU3_SRC_USB1, @@ -93,6 +95,12 @@ struct OcteonState { MemoryRegion uart_alias; MemoryRegion uart_tx; MemoryRegion uart_alias_tx; + MemoryRegion pcie_cfg; + MemoryRegion pcie_sli_cfg; + MemoryRegion pcie0_io; + + DeviceState *pci_host; + PCIBus *pci_bus; }; guint octeon_uint64_hash(gconstpointer v); @@ -109,5 +117,10 @@ void octeon_validate_ram_size(uint64_t ram_size); void octeon_init_spd(OcteonState *s); void octeon_init_twsi(OcteonState *s); void octeon_init_usb(OcteonState *s); +void octeon_init_pci(OcteonState *s); +uint64_t octeon_pci_pem_read(OcteonState *s, hwaddr reg, + hwaddr addr, unsigned size); +void octeon_pci_pem_write(OcteonState *s, hwaddr reg, hwaddr addr, + uint64_t value, unsigned size); #endif diff --git a/hw/pci-bridge/meson.build b/hw/pci-bridge/meson.build index 073aeacf7f..65ec2087c2 100644 --- a/hw/pci-bridge/meson.build +++ b/hw/pci-bridge/meson.build @@ -9,6 +9,11 @@ stub_ss.add(files('pci_expander_bridge_stubs.c')) pci_ss.add(when: 'CONFIG_XIO3130', if_true: files('xio3130_upstream.c', 'xio3130_downstream.c')) pci_ss.add(when: 'CONFIG_CXL', if_true: files('cxl_root_port.c', 'cxl_upstream.c', 'cxl_downstream.c')) +if 'CONFIG_TCG' in config_all_accel + mips_ss.add(when: 'CONFIG_MIPS_OCTEON', + if_true: files('octeon_pci.c')) +endif + # Sun4u pci_ss.add(when: 'CONFIG_SIMBA', if_true: files('simba.c')) diff --git a/hw/pci-bridge/octeon_pci.c b/hw/pci-bridge/octeon_pci.c new file mode 100644 index 0000000000..e2f856e164 --- /dev/null +++ b/hw/pci-bridge/octeon_pci.c @@ -0,0 +1,356 @@ +/* + * QEMU Cavium Octeon PCI host bridge model. + * + * Copyright (c) 2026 Kirill A. Korinsky + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/core/resettable.h" +#include "hw/core/sysbus.h" +#include "hw/mips/octeon_internal.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_host.h" +#include "qemu/module.h" +#include "system/memory.h" + +#define TYPE_OCTEON_PCI_HOST "octeon-pci-host" +OBJECT_DECLARE_TYPE(OcteonPCIHostState, OcteonPCIHostClass, + OCTEON_PCI_HOST) + +#define OCTEON_PCIE_CFG_BASE 0x1190400000000ULL +#define OCTEON_PCIE_CFG_SIZE 0x20000000ULL +#define OCTEON_PCIE_SLI_CFG_BASE 0x1190c00000000ULL +#define OCTEON_PCIE_SLI_CFG_PORTS 4 +#define OCTEON_PCIE_SLI_CFG_PORT_SIZE (1ULL << 32) +#define OCTEON_PCIE_SLI_CFG_SIZE \ + (OCTEON_PCIE_SLI_CFG_PORTS * OCTEON_PCIE_SLI_CFG_PORT_SIZE) +#define OCTEON_PCIE0_IO_BASE 0x11a0400000000ULL +#define OCTEON_PCIE0_IO_SIZE (1ULL << 32) +#define OCTEON_PCIE0_MEM_SIZE (1ULL << 32) +#define OCTEON_PCIE0_ENDPOINT_DEVFN PCI_DEVFN(0x0b, 0) +#define OCTEON_PEMX_CFG_WR0 0xc0000028 +#define OCTEON_PEMX_CFG_RD0 0xc0000030 +#define OCTEON_PCIE_CFG006 0x018 +#define OCTEON_PCIE_CFG031 0x07c +#define OCTEON_PCIE_CFG032 0x080 +#define OCTEON_PCIE_CFG068 0x110 + +struct OcteonPCIHostState { + PCIHostState parent_obj; + MemoryRegion mem; + MemoryRegion io; + uint32_t pem_cfg_rd_addr; + uint64_t pem_cfg_wr; + GHashTable *root_cfg; +}; + +struct OcteonPCIHostClass { + PCIHostBridgeClass parent_class; + ResettablePhases parent_phases; +}; + +static void octeon_pci_host_reset_hold(Object *obj, ResetType type) +{ + OcteonPCIHostState *host = OCTEON_PCI_HOST(obj); + OcteonPCIHostClass *opc = OCTEON_PCI_HOST_GET_CLASS(obj); + + if (opc->parent_phases.hold) { + opc->parent_phases.hold(obj, type); + } + + host->pem_cfg_rd_addr = 0; + host->pem_cfg_wr = 0; + g_hash_table_remove_all(host->root_cfg); +} + +static OcteonPCIHostState *octeon_pci_host(OcteonState *s) +{ + return OCTEON_PCI_HOST(s->pci_host); +} + +static uint32_t octeon_pcie_root_cfg_default(uint32_t reg) +{ + switch (reg) { + case OCTEON_PCIE_CFG006: + return 0x00010101; + case OCTEON_PCIE_CFG031: + return 0x00000011; + case OCTEON_PCIE_CFG032: + return 0x20110000; + default: + return 0; + } +} + +static uint32_t octeon_pcie_root_cfg_read(OcteonPCIHostState *host, + uint32_t reg) +{ + uint64_t value; + + reg &= ~3U; + switch (reg) { + case OCTEON_PCIE_CFG006: + case OCTEON_PCIE_CFG031: + case OCTEON_PCIE_CFG032: + return octeon_pcie_root_cfg_default(reg); + default: + break; + } + + if (octeon_reg_lookup(host->root_cfg, reg, &value)) { + return value; + } + + return octeon_pcie_root_cfg_default(reg); +} + +static void octeon_pcie_root_cfg_write(OcteonPCIHostState *host, + uint32_t reg, uint32_t value) +{ + reg &= ~3U; + if (reg == OCTEON_PCIE_CFG068) { + value = 0; + } + + octeon_reg_store(host->root_cfg, reg, value); +} + +uint64_t octeon_pci_pem_read(OcteonState *s, hwaddr reg, + hwaddr addr, unsigned size) +{ + OcteonPCIHostState *host = octeon_pci_host(s); + uint64_t value; + + switch (reg) { + case OCTEON_PEMX_CFG_RD0: + value = ((uint64_t)octeon_pcie_root_cfg_read( + host, host->pem_cfg_rd_addr) << 32) | + host->pem_cfg_rd_addr; + break; + case OCTEON_PEMX_CFG_WR0: + value = host->pem_cfg_wr; + break; + default: + g_assert_not_reached(); + } + + return octeon_read64(value, addr, size); +} + +void octeon_pci_pem_write(OcteonState *s, hwaddr reg, hwaddr addr, + uint64_t value, unsigned size) +{ + OcteonPCIHostState *host = octeon_pci_host(s); + + switch (reg) { + case OCTEON_PEMX_CFG_RD0: + value = octeon_write64(0, addr, value, size); + host->pem_cfg_rd_addr = value; + break; + case OCTEON_PEMX_CFG_WR0: + value = octeon_write64(host->pem_cfg_wr, addr, value, size); + octeon_pcie_root_cfg_write(host, value, value >> 32); + host->pem_cfg_wr = value; + break; + default: + g_assert_not_reached(); + } +} + +static uint64_t octeon_pci_absent(unsigned size) +{ + return size == 1 ? 0xff : size == 2 ? 0xffff : 0xffffffffU; +} + +static bool octeon_pcie_config_addr(hwaddr addr, uint32_t *pci_addr, + bool sli_cfg) +{ + unsigned int bus = (addr >> 20) & 0xff; + unsigned int dev = (addr >> 15) & 0x1f; + unsigned int fn = (addr >> 12) & 0x7; + unsigned int reg = addr & 0xfff; + + if (sli_cfg) { + if (addr >= OCTEON_PCIE_SLI_CFG_PORT_SIZE || + bus != 0 || dev != 0 || fn != 0 || + reg >= PCI_CONFIG_SPACE_SIZE) { + return false; + } + } else if (bus != 1 || dev != 0 || fn != 0 || + reg >= PCI_CONFIG_SPACE_SIZE) { + return false; + } + + *pci_addr = 0x80000000U | (OCTEON_PCIE0_ENDPOINT_DEVFN << 8) | reg; + return true; +} + +static uint64_t octeon_pcie_cfg_read(void *opaque, hwaddr addr, + unsigned size) +{ + OcteonState *s = opaque; + uint32_t pci_addr; + + if (!octeon_pcie_config_addr(addr, &pci_addr, false)) { + return octeon_pci_absent(size); + } + + return pci_data_read(s->pci_bus, pci_addr, size); +} + +static void octeon_pcie_cfg_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + OcteonState *s = opaque; + uint32_t pci_addr; + + if (octeon_pcie_config_addr(addr, &pci_addr, false)) { + pci_data_write(s->pci_bus, pci_addr, value, size); + } +} + +static const MemoryRegionOps octeon_pcie_cfg_ops = { + .read = octeon_pcie_cfg_read, + .write = octeon_pcie_cfg_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 4, + }, +}; + +static uint64_t octeon_pcie_sli_cfg_read(void *opaque, hwaddr addr, + unsigned size) +{ + OcteonState *s = opaque; + uint32_t pci_addr; + + if (!octeon_pcie_config_addr(addr, &pci_addr, true)) { + return octeon_pci_absent(size); + } + + return pci_data_read(s->pci_bus, pci_addr, size); +} + +static void octeon_pcie_sli_cfg_write(void *opaque, hwaddr addr, + uint64_t value, unsigned size) +{ + OcteonState *s = opaque; + uint32_t pci_addr; + + if (octeon_pcie_config_addr(addr, &pci_addr, true)) { + pci_data_write(s->pci_bus, pci_addr, value, size); + } +} + +static const MemoryRegionOps octeon_pcie_sli_cfg_ops = { + .read = octeon_pcie_sli_cfg_read, + .write = octeon_pcie_sli_cfg_write, + .endianness = DEVICE_BIG_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 4, + }, +}; + +static int octeon_pci_map_irq(PCIDevice *pci_dev, int irq_num) +{ + return 0; +} + +static void octeon_pci_set_irq(void *opaque, int irq_num, int level) +{ + octeon_irq_set(opaque, OCTEON_IRQ_PCI, level); +} + +static void octeon_pci_host_init(Object *obj) +{ + OcteonPCIHostState *host = OCTEON_PCI_HOST(obj); + + host->root_cfg = g_hash_table_new_full(octeon_uint64_hash, + octeon_uint64_equal, + g_free, g_free); +} + +static void octeon_pci_host_finalize(Object *obj) +{ + OcteonPCIHostState *host = OCTEON_PCI_HOST(obj); + + g_hash_table_destroy(host->root_cfg); +} + +static void octeon_pci_host_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + OcteonPCIHostClass *opc = OCTEON_PCI_HOST_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); + + dc->fw_name = "pci"; + dc->user_creatable = false; + resettable_class_set_parent_phases(rc, NULL, + octeon_pci_host_reset_hold, NULL, + &opc->parent_phases); +} + +static const TypeInfo octeon_pci_host_info = { + .name = TYPE_OCTEON_PCI_HOST, + .parent = TYPE_PCI_HOST_BRIDGE, + .instance_size = sizeof(OcteonPCIHostState), + .instance_init = octeon_pci_host_init, + .instance_finalize = octeon_pci_host_finalize, + .class_size = sizeof(OcteonPCIHostClass), + .class_init = octeon_pci_host_class_init, +}; + +static void octeon_pci_host_register_types(void) +{ + type_register_static(&octeon_pci_host_info); +} + +type_init(octeon_pci_host_register_types) + +void octeon_init_pci(OcteonState *s) +{ + DeviceState *dev; + OcteonPCIHostState *host; + PCIHostState *phb; + + dev = qdev_new(TYPE_OCTEON_PCI_HOST); + host = OCTEON_PCI_HOST(dev); + s->pci_host = dev; + phb = PCI_HOST_BRIDGE(dev); + + memory_region_init(&host->mem, OBJECT(dev), "octeon.pci-mem", + OCTEON_PCIE0_MEM_SIZE); + memory_region_init(&host->io, OBJECT(dev), "octeon.pci-io", + OCTEON_PCIE0_IO_SIZE); + + phb->bus = pci_root_bus_new(dev, "pci", &host->mem, &host->io, + OCTEON_PCIE0_ENDPOINT_DEVFN, TYPE_PCI_BUS); + s->pci_bus = phb->bus; + pci_bus_irqs(s->pci_bus, octeon_pci_set_irq, s, 1); + pci_bus_map_irqs(s->pci_bus, octeon_pci_map_irq); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + memory_region_init_io(&s->pcie_cfg, NULL, &octeon_pcie_cfg_ops, s, + "octeon.pcie-config", OCTEON_PCIE_CFG_SIZE); + memory_region_add_subregion(get_system_memory(), OCTEON_PCIE_CFG_BASE, + &s->pcie_cfg); + + memory_region_init_io(&s->pcie_sli_cfg, NULL, &octeon_pcie_sli_cfg_ops, + s, "octeon.pcie-sli-config", + OCTEON_PCIE_SLI_CFG_SIZE); + memory_region_add_subregion(get_system_memory(), + OCTEON_PCIE_SLI_CFG_BASE, + &s->pcie_sli_cfg); + + memory_region_init_alias(&s->pcie0_io, NULL, "octeon.pcie0-io", + &host->io, 0, + OCTEON_PCIE0_IO_SIZE); + memory_region_add_subregion(get_system_memory(), OCTEON_PCIE0_IO_BASE, + &s->pcie0_io); + +} -- 2.56.0
