Hi, On Wed, Oct 31, 2018 at 6:22 AM Alistair Francis <alistair.fran...@wdc.com> wrote: > > Connect the gpex PCIe device based on the device tree included in the > HiFive Unleashed ROM. > > Signed-off-by: Alistair Francis <alistair.fran...@wdc.com> > --- > default-configs/riscv32-softmmu.mak | 6 +- > default-configs/riscv64-softmmu.mak | 6 +- > hw/riscv/virt.c | 111 ++++++++++++++++++++++++++++ > include/hw/riscv/virt.h | 8 +- > 4 files changed, 127 insertions(+), 4 deletions(-) > > diff --git a/default-configs/riscv32-softmmu.mak > b/default-configs/riscv32-softmmu.mak > index 7937c69e22..3e3d195f37 100644 > --- a/default-configs/riscv32-softmmu.mak > +++ b/default-configs/riscv32-softmmu.mak > @@ -1,7 +1,11 @@ > # Default configuration for riscv-softmmu > > +include pci.mak > + > CONFIG_SERIAL=y > CONFIG_VIRTIO_MMIO=y > -include virtio.mak > > CONFIG_CADENCE=y > + > +CONFIG_PCI_GENERIC=y > +CONFIG_PCI_XILINX=y > diff --git a/default-configs/riscv64-softmmu.mak > b/default-configs/riscv64-softmmu.mak > index 7937c69e22..3e3d195f37 100644 > --- a/default-configs/riscv64-softmmu.mak > +++ b/default-configs/riscv64-softmmu.mak > @@ -1,7 +1,11 @@ > # Default configuration for riscv-softmmu > > +include pci.mak > + > CONFIG_SERIAL=y > CONFIG_VIRTIO_MMIO=y > -include virtio.mak > > CONFIG_CADENCE=y > + > +CONFIG_PCI_GENERIC=y > +CONFIG_PCI_XILINX=y > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c > index 4a137a503c..2fbe58ba4b 100644 > --- a/hw/riscv/virt.c > +++ b/hw/riscv/virt.c > @@ -39,6 +39,8 @@ > #include "sysemu/arch_init.h" > #include "sysemu/device_tree.h" > #include "exec/address-spaces.h" > +#include "hw/pci/pci.h" > +#include "hw/pci-host/gpex.h" > #include "elf.h" > > #include <libfdt.h> > @@ -55,6 +57,10 @@ static const struct MemmapEntry { > [VIRT_UART0] = { 0x10000000, 0x100 }, > [VIRT_VIRTIO] = { 0x10001000, 0x1000 }, > [VIRT_DRAM] = { 0x80000000, 0x0 }, > + [VIRT_PCIE_MMIO] = { 0x2000000000, 0x4000000 },
Does this work with RV32? > + [VIRT_PCIE_PIO] = { 0x2010000, 0x40000000 }, > + [VIRT_PCIE_ECAM] = { 0x40000000, 0x20000000 }, > + > }; > > static uint64_t load_kernel(const char *kernel_filename) > @@ -98,6 +104,37 @@ static hwaddr load_initrd(const char *filename, uint64_t > mem_size, > return *start + size; > } > > +#define INTERREUPT_MAP_WIDTH 7 > + > +static void create_pcie_irq_map(void *fdt, char *nodename, > + uint32_t plic_phandle) > +{ > + int pin; > + uint32_t full_irq_map[GPEX_NUM_IRQS * INTERREUPT_MAP_WIDTH] = { 0 }; > + uint32_t *irq_map = full_irq_map; > + > + for (pin = 0; pin < GPEX_NUM_IRQS; pin++) { > + int irq_nr = PCIE_IRQ + (pin % PCI_NUM_PINS); > + int i; > + > + uint32_t map[] = { > + 0, 0, 0, > + pin + 1, plic_phandle, 0, irq_nr}; > + > + /* Convert map to big endian */ > + for (i = 0; i < INTERREUPT_MAP_WIDTH; i++) { > + irq_map[i] = cpu_to_be32(map[i]); > + } > + irq_map += INTERREUPT_MAP_WIDTH; > + } > + > + qemu_fdt_setprop(fdt, nodename, "interrupt-map", > + full_irq_map, sizeof(full_irq_map)); > + > + qemu_fdt_setprop_cells(fdt, nodename, "interrupt-map-mask", > + 0, 0, 0, 0x7); > +} > + > static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, > uint64_t mem_size, const char *cmdline) > { > @@ -233,6 +270,31 @@ static void *create_fdt(RISCVVirtState *s, const struct > MemmapEntry *memmap, > g_free(nodename); > } > > + nodename = g_strdup_printf("/pci@%lx", > + (long) memmap[VIRT_PCIE_MMIO].base); > + qemu_fdt_add_subnode(fdt, nodename); > + qemu_fdt_setprop_cells(fdt, nodename, "#address-cells", 0x3); > + qemu_fdt_setprop_cells(fdt, nodename, "#interrupt-cells", 0x1); > + qemu_fdt_setprop_cells(fdt, nodename, "#size-cells", 0x2); > + qemu_fdt_setprop_string(fdt, nodename, "compatible", > + "pci-host-ecam-generic"); > + qemu_fdt_setprop_string(fdt, nodename, "device_type", "pci"); > + qemu_fdt_setprop_cell(fdt, nodename, "linux,pci-domain", 0); > + qemu_fdt_setprop_cells(fdt, nodename, "bus-range", 0, > + memmap[VIRT_PCIE_ECAM].base / > + PCIE_MMCFG_SIZE_MIN - 1); > + qemu_fdt_setprop(fdt, nodename, "dma-coherent", NULL, 0); > + qemu_fdt_setprop_cells(fdt, nodename, "reg", 0x20, 0, > + 0, memmap[VIRT_PCIE_ECAM].size); > + qemu_fdt_setprop_cells(fdt, nodename, "ranges", > + memmap[VIRT_PCIE_PIO].base, > + 0, memmap[VIRT_PCIE_PIO].size, > + 0, memmap[VIRT_PCIE_MMIO].base, > + 0, memmap[VIRT_PCIE_MMIO].size); This does not conform with the PCI bus ranges encoding. > + qemu_fdt_setprop_cells(fdt, nodename, "interrupt-parent", plic_phandle); > + qemu_fdt_setprop_cells(fdt, nodename, "interrupts", PCIE_IRQ); > + create_pcie_irq_map(fdt, nodename, plic_phandle); > + > nodename = g_strdup_printf("/test@%lx", > (long)memmap[VIRT_TEST].base); > qemu_fdt_add_subnode(fdt, nodename); > @@ -262,6 +324,47 @@ static void *create_fdt(RISCVVirtState *s, const struct > MemmapEntry *memmap, > return fdt; > } > [snip] Regards, Bin