Index: sys/dev/pci/pci_host_generic.c =================================================================== --- sys/dev/pci/pci_host_generic.c +++ sys/dev/pci/pci_host_generic.c @@ -109,6 +109,11 @@ struct ofw_bus_iinfo pci_iinfo; }; +typedef void (*generic_pcie_quirk)(device_t); +struct generic_pcie_quirks { + generic_pcie_quirk cb; +}; + /* Forward prototypes */ static int generic_pcie_probe(device_t dev); @@ -128,6 +133,16 @@ rman_res_t count, u_int flags); static int generic_pcie_release_resource(device_t dev, device_t child, int type, int rid, struct resource *res); +#if defined(__aarch64__) +static void generic_pcie_quirk_thunderx(device_t); +#endif + +struct generic_pcie_quirks g_quirks[] = { +#if defined(__aarch64__) + {generic_pcie_quirk_thunderx}, +#endif + {NULL} +}; static int generic_pcie_probe(device_t dev) @@ -144,10 +159,32 @@ return (ENXIO); } +#if defined(__aarch64__) +#define THUNDER_CFG_BASE_TO_ECAM(x) ((((x) >> 36UL) & 0x3) | (((x) >> 45UL) & 1)) +static void +generic_pcie_quirk_thunderx(device_t dev) +{ + struct generic_pcie_softc *sc; + rman_res_t start; + + /* Check if we're running on Cavium ThunderX */ + if (!CPU_MATCH(CPU_IMPL_MASK | CPU_PART_MASK, + CPU_IMPL_CAVIUM, CPU_PART_THUNDER, 0, 0)) + return; + + sc = device_get_softc(dev); + start = bus_get_resource_start(dev, SYS_RES_MEMORY, 0); + sc->ecam = THUNDER_CFG_BASE_TO_ECAM(start); + + device_printf(dev, "quirk: ThunderX, setting ECAM to %d\n", sc->ecam); +} +#endif + static int generic_pcie_attach(device_t dev) { struct generic_pcie_softc *sc; + struct generic_pcie_quirks *quirk = g_quirks; uint64_t phys_base; uint64_t pci_base; uint64_t size; @@ -220,6 +257,9 @@ ofw_bus_setup_iinfo(ofw_bus_get_node(dev), &sc->pci_iinfo, sizeof(cell_t)); + /* Run quirks */ + for (; quirk->cb != NULL; quirk++) + (*quirk->cb)(dev); device_add_child(dev, "pci", -1); return (bus_generic_attach(dev)); @@ -434,7 +474,8 @@ return (0); } - device_printf(dev, "ERROR: Unknown index.\n"); + if (bootverbose) + device_printf(dev, "ERROR: Unknown index %d.\n", index); return (ENOENT); }