Module Name: src Committed By: jmcneill Date: Mon Oct 14 00:16:29 UTC 2019
Modified Files: src/sys/arch/arm/acpi: acpi_pci_machdep.c acpi_pci_machdep.h acpipchb.c Log Message: Add quirks for Amazon Graviton PCIe root ports. Configuration space for the root port is found in a child AMZN0001 resource, not the MCFG table. To generate a diff of this commit: cvs rdiff -u -r1.9 -r1.10 src/sys/arch/arm/acpi/acpi_pci_machdep.c \ src/sys/arch/arm/acpi/acpipchb.c cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/acpi/acpi_pci_machdep.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/acpi/acpi_pci_machdep.c diff -u src/sys/arch/arm/acpi/acpi_pci_machdep.c:1.9 src/sys/arch/arm/acpi/acpi_pci_machdep.c:1.10 --- src/sys/arch/arm/acpi/acpi_pci_machdep.c:1.9 Sat Dec 8 15:04:40 2018 +++ src/sys/arch/arm/acpi/acpi_pci_machdep.c Mon Oct 14 00:16:29 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_pci_machdep.c,v 1.9 2018/12/08 15:04:40 jmcneill Exp $ */ +/* $NetBSD: acpi_pci_machdep.c,v 1.10 2019/10/14 00:16:29 jmcneill Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_pci_machdep.c,v 1.9 2018/12/08 15:04:40 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_pci_machdep.c,v 1.10 2019/10/14 00:16:29 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -60,6 +60,120 @@ __KERNEL_RCSID(0, "$NetBSD: acpi_pci_mac #include <arm/pci/pci_msi_machdep.h> +static int +acpi_pci_amazon_graviton_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t *data) +{ + struct acpi_pci_context *ap = pc->pc_conf_v; + bus_size_t off; + int b, d, f; + + pci_decompose_tag(pc, tag, &b, &d, &f); + + if (ap->ap_bus == b) { + if (d > 0) { + *data = -1; + return EINVAL; + } + off = f * PCI_EXTCONF_SIZE + reg; + *data = bus_space_read_4(ap->ap_bst, ap->ap_conf_bsh, off); + return 0; + } + + return acpimcfg_conf_read(pc, tag, reg, data); +} + +static int +acpi_pci_amazon_graviton_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) +{ + struct acpi_pci_context *ap = pc->pc_conf_v; + bus_size_t off; + int b, d, f; + + pci_decompose_tag(pc, tag, &b, &d, &f); + + if (ap->ap_bus == b) { + if (d > 0) { + return EINVAL; + } + off = f * PCI_EXTCONF_SIZE + reg; + bus_space_write_4(ap->ap_bst, ap->ap_conf_bsh, off, data); + return 0; + } + + return acpimcfg_conf_write(pc, tag, reg, data); +} + +static ACPI_STATUS +acpi_pci_amazon_graviton_map(ACPI_HANDLE handle, UINT32 level, void *ctx, void **retval) +{ + struct acpi_pci_context *ap = ctx; + struct acpi_resources res; + struct acpi_mem *mem; + ACPI_STATUS rv; + int error; + + rv = acpi_resource_parse(ap->ap_dev, handle, "_CRS", &res, &acpi_resource_parse_ops_quiet); + if (ACPI_FAILURE(rv)) + return rv; + + mem = acpi_res_mem(&res, 0); + if (mem == NULL) { + acpi_resource_cleanup(&res); + return AE_NOT_FOUND; + } + + error = bus_space_map(ap->ap_bst, mem->ar_base, mem->ar_length, 0, &ap->ap_conf_bsh); + if (error != 0) + return AE_NO_MEMORY; + + return AE_CTRL_TERMINATE; +} + +static void +acpi_pci_amazon_graviton_init(struct pcibus_attach_args *pba) +{ + struct acpi_pci_context *ap = pba->pba_pc->pc_conf_v; + ACPI_STATUS rv; + + rv = AcpiGetDevices(__UNCONST("AMZN0001"), acpi_pci_amazon_graviton_map, ap, NULL); + if (ACPI_FAILURE(rv)) + return; + + ap->ap_conf_read = acpi_pci_amazon_graviton_conf_read; + ap->ap_conf_write = acpi_pci_amazon_graviton_conf_write; +} + +static const struct acpi_pci_quirk { + const char q_oemid[ACPI_OEM_ID_SIZE+1]; + const char q_oemtableid[ACPI_OEM_TABLE_ID_SIZE+1]; + uint32_t q_oemrevision; + void (*q_init)(struct pcibus_attach_args *); +} acpi_pci_quirks[] = { + { "AMAZON", "GRAVITON", 0, acpi_pci_amazon_graviton_init }, +}; + +static const struct acpi_pci_quirk * +acpi_pci_find_quirk(void) +{ + ACPI_STATUS rv; + ACPI_TABLE_MCFG *mcfg; + u_int n; + + rv = AcpiGetTable(ACPI_SIG_MCFG, 0, (ACPI_TABLE_HEADER **)&mcfg); + if (ACPI_FAILURE(rv)) + return NULL; + + for (n = 0; n < __arraycount(acpi_pci_quirks); n++) { + const struct acpi_pci_quirk *q = &acpi_pci_quirks[n]; + if (memcmp(q->q_oemid, mcfg->Header.OemId, ACPI_OEM_ID_SIZE) == 0 && + memcmp(q->q_oemtableid, mcfg->Header.OemTableId, ACPI_OEM_TABLE_ID_SIZE) == 0 && + q->q_oemrevision == mcfg->Header.OemRevision) + return q; + } + + return NULL; +} + struct acpi_pci_prt { u_int prt_segment; u_int prt_bus; @@ -160,6 +274,7 @@ acpi_pci_md_attach_hook(device_t parent, { struct acpi_pci_context *ap = pba->pba_pc->pc_conf_v; struct acpi_pci_prt *prt, *prtp; + const struct acpi_pci_quirk *q; struct acpi_devnode *ad; ACPI_HANDLE handle; int seg, bus, dev, func; @@ -202,6 +317,10 @@ acpi_pci_md_attach_hook(device_t parent, TAILQ_INSERT_TAIL(&acpi_pci_irq_routes, prt, prt_list); } + q = acpi_pci_find_quirk(); + if (q != NULL) + q->q_init(pba); + acpimcfg_map_bus(self, pba->pba_pc, pba->pba_bus); if (ad != NULL) { @@ -260,7 +379,10 @@ acpi_pci_md_conf_read(void *v, pcitag_t if (offset < 0 || offset >= PCI_EXTCONF_SIZE) return (pcireg_t) -1; - acpimcfg_conf_read(&ap->ap_pc, tag, offset, &val); + if (ap->ap_conf_read != NULL) + ap->ap_conf_read(&ap->ap_pc, tag, offset, &val); + else + acpimcfg_conf_read(&ap->ap_pc, tag, offset, &val); return val; } @@ -273,7 +395,10 @@ acpi_pci_md_conf_write(void *v, pcitag_t if (offset < 0 || offset >= PCI_EXTCONF_SIZE) return; - acpimcfg_conf_write(&ap->ap_pc, tag, offset, val); + if (ap->ap_conf_write != NULL) + ap->ap_conf_write(&ap->ap_pc, tag, offset, val); + else + acpimcfg_conf_write(&ap->ap_pc, tag, offset, val); } static int Index: src/sys/arch/arm/acpi/acpipchb.c diff -u src/sys/arch/arm/acpi/acpipchb.c:1.9 src/sys/arch/arm/acpi/acpipchb.c:1.10 --- src/sys/arch/arm/acpi/acpipchb.c:1.9 Tue Jun 25 22:23:39 2019 +++ src/sys/arch/arm/acpi/acpipchb.c Mon Oct 14 00:16:29 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: acpipchb.c,v 1.9 2019/06/25 22:23:39 jmcneill Exp $ */ +/* $NetBSD: acpipchb.c,v 1.10 2019/10/14 00:16:29 jmcneill Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpipchb.c,v 1.9 2019/06/25 22:23:39 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpipchb.c,v 1.10 2019/10/14 00:16:29 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -144,9 +144,12 @@ acpipchb_attach(device_t parent, device_ if (cca == 0) sc->sc_dmat._nranges = 0; + sc->sc_ap.ap_dev = self; sc->sc_ap.ap_pc = *aa->aa_pc; sc->sc_ap.ap_pc.pc_conf_v = &sc->sc_ap; sc->sc_ap.ap_seg = seg; + sc->sc_ap.ap_bus = sc->sc_bus; + sc->sc_ap.ap_bst = sc->sc_memt; if (acpi_pci_ignore_boot_config(sc->sc_handle)) { if (acpimcfg_configure_bus(self, &sc->sc_ap.ap_pc, sc->sc_handle, sc->sc_bus, PCIHOST_CACHELINE_SIZE) != 0) Index: src/sys/arch/arm/acpi/acpi_pci_machdep.h diff -u src/sys/arch/arm/acpi/acpi_pci_machdep.h:1.2 src/sys/arch/arm/acpi/acpi_pci_machdep.h:1.3 --- src/sys/arch/arm/acpi/acpi_pci_machdep.h:1.2 Fri Oct 19 11:40:27 2018 +++ src/sys/arch/arm/acpi/acpi_pci_machdep.h Mon Oct 14 00:16:29 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_pci_machdep.h,v 1.2 2018/10/19 11:40:27 jmcneill Exp $ */ +/* $NetBSD: acpi_pci_machdep.h,v 1.3 2019/10/14 00:16:29 jmcneill Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -36,7 +36,13 @@ extern struct arm32_pci_chipset arm_acpi struct acpi_pci_context { struct arm32_pci_chipset ap_pc; + device_t ap_dev; u_int ap_seg; + int ap_bus; + bus_space_tag_t ap_bst; + bus_space_handle_t ap_conf_bsh; + int (*ap_conf_read)(pci_chipset_tag_t, pcitag_t, int, pcireg_t *); + int (*ap_conf_write)(pci_chipset_tag_t, pcitag_t, int, pcireg_t); }; #endif /* !_ARM_ACPI_PCI_MACHDEP_H */