diff --git a/boards/arm64/qemu/qemu-armv8a/src/qemu_bringup.c b/boards/arm64/qemu/qemu-armv8a/src/qemu_bringup.c index d5fdea9342..799551b545 100644 --- a/boards/arm64/qemu/qemu-armv8a/src/qemu_bringup.c +++ b/boards/arm64/qemu/qemu-armv8a/src/qemu_bringup.c @@ -30,6 +30,7 @@ #include #include #include +#include #ifdef CONFIG_LIBC_FDT # include @@ -45,6 +46,12 @@ #define QEMU_SPI_IRQ_BASE 32 #endif +#define FDT_PCI_TYPE_IO 0x01000000 +#define FDT_PCI_TYPE_MEM32 0x02000000 +#define FDT_PCI_TYPE_MEM64 0x03000000 +#define FDT_PCI_TYPE_MASK 0x03000000 +#define FDT_PCI_PREFTCH 0x40000000 + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -81,6 +88,90 @@ static void register_virtio_devices_from_fdt(const void *fdt) #endif +/**************************************************************************** + * Name: register_pci_host_from_fdt + ****************************************************************************/ + +#ifdef CONFIG_PCI +static void register_pci_host_from_fdt(const void *fdt) +{ + struct pci_resource_s prefetch; + struct pci_resource_s cfg; + struct pci_resource_s mem; + struct pci_resource_s io; + const fdt32_t *ranges; + int offset; + + /* #address-size must be 3 + * defined in the PCI Bus Binding to IEEE Std 1275-1994 : + * Bit# + * + * phys.hi cell: npt000ss bbbbbbbb dddddfff rrrrrrrr + * phys.mid cell: hhhhhhhh hhhhhhhh hhhhhhhh hhhhhhhh + * phys.lo cell: llllllll llllllll llllllll llllllll + */ + + const int na = 3; + + /* #size-cells must be 2 */ + + const int ns = 2; + int rlen; + int pna; + + memset(&prefetch, 0, sizeof(prefetch)); + memset(&cfg, 0, sizeof(cfg)); + memset(&mem, 0, sizeof(mem)); + memset(&io, 0, sizeof(io)); + + offset = fdt_node_offset_by_compatible(fdt, -1, + "pci-host-ecam-generic"); + if (offset < 0) + { + return; + } + + /* Get the reg address, 64 or 32 */ + + cfg.start = fdt_get_reg_base(fdt, offset); + cfg.end = cfg.start + fdt_get_reg_size(fdt, offset); + + /* Get the ranges address */ + + ranges = fdt_getprop(fdt, offset, "ranges", &rlen); + if (ranges < 0) + { + return; + } + + pna = fdt_get_parent_address_cells(fdt, offset); + + for (rlen /= 4; (rlen -= na + pna + ns) >= 0; ranges += na + pna + ns) + { + uint32_t type = fdt32_ld(ranges); + + if ((type & FDT_PCI_TYPE_MASK) == FDT_PCI_TYPE_IO) + { + io.start = fdt_ld_by_cells(ranges + na, pna); + io.end = io.start + fdt_ld_by_cells(ranges + na + pna, ns); + } + else if ((type & FDT_PCI_PREFTCH) == FDT_PCI_PREFTCH) + { + prefetch.start = fdt_ld_by_cells(ranges + na, pna); + prefetch.end = prefetch.start + + fdt_ld_by_cells(ranges + na + pna, ns); + } + else + { + mem.start = fdt_ld_by_cells(ranges + na, pna); + mem.end = mem.start + fdt_ld_by_cells(ranges + na + pna, ns); + } + } + + pci_ecam_register(&cfg, &io, &mem, NULL); +} +#endif + /**************************************************************************** * Name: register_devices_from_fdt ****************************************************************************/ @@ -97,6 +188,10 @@ static void register_devices_from_fdt(void) #ifdef CONFIG_DRIVERS_VIRTIO_MMIO register_virtio_devices_from_fdt(fdt); #endif + +#ifdef CONFIG_PCI + register_pci_host_from_fdt(fdt); +#endif } #endif