Module Name:    src
Committed By:   jmcneill
Date:           Fri Jan 17 17:06:33 UTC 2020

Modified Files:
        src/sys/arch/arm/acpi: acpi_pci_machdep.c acpi_pci_machdep.h acpipchb.c
            files.acpi
        src/sys/arch/arm/fdt: acpi_fdt.c
        src/sys/arch/x86/x86: mpacpi.c
        src/sys/dev/acpi: acpi.c acpi_pci.c acpi_pci.h acpi_pci_link.c
            acpivar.h
        src/sys/dev/acpi/acpica: OsdHardware.c
Added Files:
        src/sys/arch/arm/acpi: acpi_pci_graviton.c acpi_pci_n1sdp.c

Log Message:
Add support for Arm N1 SDP PCIe host controller.

The N1 SDP has a few bugs that we need to work around:
 - PCIe root port config space lives in a non-standard location.
 - Access to PCIe config space of devices that do not exist results in
   an sync SError. Firmware creates a "known devices" table at a fixed
   physical address that we use to filter PCI conf access to only known
   devices.

This change splits the Arm ACPI PCI quirks into separate files for each
host controller, and allows per-segment quirks to be applied.

These changes exposed some bugs in the MI ACPI layer related to
multi-segment support. The MI ACPI PCI code was using a shared PCI
chipset tag to access devices, and these accesses can happen before our
PCI host bridge drivers are attached! The global chipset tag is now gone,
and an MD callback can provide a custom tag on a per-segment basis.


To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/acpi/acpi_pci_graviton.c \
    src/sys/arch/arm/acpi/acpi_pci_n1sdp.c
cvs rdiff -u -r1.12 -r1.13 src/sys/arch/arm/acpi/acpi_pci_machdep.c
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/acpi/acpi_pci_machdep.h
cvs rdiff -u -r1.15 -r1.16 src/sys/arch/arm/acpi/acpipchb.c
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/arm/acpi/files.acpi
cvs rdiff -u -r1.13 -r1.14 src/sys/arch/arm/fdt/acpi_fdt.c
cvs rdiff -u -r1.103 -r1.104 src/sys/arch/x86/x86/mpacpi.c
cvs rdiff -u -r1.282 -r1.283 src/sys/dev/acpi/acpi.c
cvs rdiff -u -r1.26 -r1.27 src/sys/dev/acpi/acpi_pci.c
cvs rdiff -u -r1.10 -r1.11 src/sys/dev/acpi/acpi_pci.h
cvs rdiff -u -r1.25 -r1.26 src/sys/dev/acpi/acpi_pci_link.c
cvs rdiff -u -r1.81 -r1.82 src/sys/dev/acpi/acpivar.h
cvs rdiff -u -r1.11 -r1.12 src/sys/dev/acpi/acpica/OsdHardware.c

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.12 src/sys/arch/arm/acpi/acpi_pci_machdep.c:1.13
--- src/sys/arch/arm/acpi/acpi_pci_machdep.c:1.12	Tue Oct 15 13:27:50 2019
+++ src/sys/arch/arm/acpi/acpi_pci_machdep.c	Fri Jan 17 17:06:33 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_pci_machdep.c,v 1.12 2019/10/15 13:27:50 jmcneill Exp $ */
+/* $NetBSD: acpi_pci_machdep.c,v 1.13 2020/01/17 17:06:33 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.12 2019/10/15 13:27:50 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_pci_machdep.c,v 1.13 2020/01/17 17:06:33 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -70,6 +70,23 @@ struct acpi_pci_prt {
 static TAILQ_HEAD(, acpi_pci_prt) acpi_pci_irq_routes =
     TAILQ_HEAD_INITIALIZER(acpi_pci_irq_routes);
 
+struct acpi_pci_pct {
+	struct acpi_pci_context		pct_ap;
+	TAILQ_ENTRY(acpi_pci_pct)	pct_list;
+};
+
+static TAILQ_HEAD(, acpi_pci_pct) acpi_pci_chipset_tags =
+    TAILQ_HEAD_INITIALIZER(acpi_pci_chipset_tags);
+
+static const struct acpi_pci_quirk acpi_pci_quirks[] = {
+	/* OEM ID	OEM Table ID	Revision	Seg	Func */
+	{ "AMAZON",	"GRAVITON",	0,		-1,	acpi_pci_graviton_init },
+	{ "ARMLTD",	"ARMN1SDP",	0x20181101,	0,	acpi_pci_n1sdp_init },
+	{ "ARMLTD",	"ARMN1SDP",	0x20181101,	1,	acpi_pci_n1sdp_init },
+};
+
+pci_chipset_tag_t acpi_pci_md_get_chipset_tag(struct acpi_softc *, int, int);
+
 static void	acpi_pci_md_attach_hook(device_t, device_t,
 				       struct pcibus_attach_args *);
 static int	acpi_pci_md_bus_maxdevs(void *, int);
@@ -115,7 +132,7 @@ struct arm32_pci_chipset arm_acpi_pci_ch
 };
 
 static ACPI_STATUS
-acpi_pci_md_pci_link(ACPI_HANDLE handle, int bus)
+acpi_pci_md_pci_link(ACPI_HANDLE handle, pci_chipset_tag_t pc, int bus)
 {
 	ACPI_PCI_ROUTING_TABLE *prt;
 	ACPI_HANDLE linksrc;
@@ -144,7 +161,7 @@ acpi_pci_md_pci_link(ACPI_HANDLE handle,
 			}
 
 			linkdev = acpi_pci_link_devbyhandle(linksrc);
-			acpi_pci_link_add_reference(linkdev, 0, bus, dev, prt->Pin & 3);
+			acpi_pci_link_add_reference(linkdev, pc, 0, bus, dev, prt->Pin & 3);
 		} else {
 			aprint_debug("ACPI: %s dev %u INT%c on globint %d\n",
 			    acpi_name(handle), dev, 'A' + (prt->Pin & 3), prt->SourceIndex);
@@ -208,7 +225,7 @@ acpi_pci_md_attach_hook(device_t parent,
 		/*
 		 * This is a new ACPI managed bus. Add PCI link references.
 		 */
-		acpi_pci_md_pci_link(ad->ad_handle, pba->pba_bus);
+		acpi_pci_md_pci_link(ad->ad_handle, pba->pba_pc, pba->pba_bus);
 	}
 }
 
@@ -343,7 +360,8 @@ acpi_pci_md_intr_map(const struct pci_at
 				if (ACPI_FAILURE(AcpiGetHandle(ACPI_ROOT_OBJECT, tab->Source, &linksrc)))
 					goto done;
 				linkdev = acpi_pci_link_devbyhandle(linksrc);
-				*ih = acpi_pci_link_route_interrupt(linkdev, tab->SourceIndex,
+				*ih = acpi_pci_link_route_interrupt(linkdev,
+				    pa->pa_pc, tab->SourceIndex,
 				    &line, &pol, &trig);
 				error = 0;
 				goto done;
@@ -417,3 +435,58 @@ acpi_pci_md_intr_disestablish(void *v, v
 {
 	intr_disestablish(vih);
 }
+
+const struct acpi_pci_quirk *
+acpi_pci_md_find_quirk(int seg)
+{
+	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 &&
+		    (q->q_segment == -1 || q->q_segment == seg))
+			return q;
+	}
+
+	return NULL;
+}
+
+pci_chipset_tag_t
+acpi_pci_md_get_chipset_tag(struct acpi_softc *sc, int seg, int bbn)
+{
+	struct acpi_pci_pct *pct = NULL, *pctp;
+	const struct acpi_pci_quirk *q;
+
+	TAILQ_FOREACH(pctp, &acpi_pci_chipset_tags, pct_list)
+		if (pctp->pct_ap.ap_seg == seg) {
+			pct = pctp;
+			break;
+		}
+
+	if (pct == NULL) {
+		pct = kmem_zalloc(sizeof(*pct), KM_SLEEP);
+		pct->pct_ap.ap_dev = sc->sc_dev;
+		pct->pct_ap.ap_pc = arm_acpi_pci_chipset;
+		pct->pct_ap.ap_pc.pc_conf_v = &pct->pct_ap;
+		pct->pct_ap.ap_seg = seg;
+		pct->pct_ap.ap_bus = bbn;
+		pct->pct_ap.ap_bst = acpi_softc->sc_memt;
+
+		q = acpi_pci_md_find_quirk(seg);
+		if (q != NULL)
+			q->q_init(&pct->pct_ap);
+
+		TAILQ_INSERT_TAIL(&acpi_pci_chipset_tags, pct, pct_list);
+	}
+
+	return &pct->pct_ap.ap_pc;
+}
+__strong_alias(acpi_get_pci_chipset_tag,acpi_pci_md_get_chipset_tag);

Index: src/sys/arch/arm/acpi/acpi_pci_machdep.h
diff -u src/sys/arch/arm/acpi/acpi_pci_machdep.h:1.5 src/sys/arch/arm/acpi/acpi_pci_machdep.h:1.6
--- src/sys/arch/arm/acpi/acpi_pci_machdep.h:1.5	Tue Oct 15 13:27:50 2019
+++ src/sys/arch/arm/acpi/acpi_pci_machdep.h	Fri Jan 17 17:06:33 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_pci_machdep.h,v 1.5 2019/10/15 13:27:50 jmcneill Exp $ */
+/* $NetBSD: acpi_pci_machdep.h,v 1.6 2020/01/17 17:06:33 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -39,11 +39,24 @@ struct acpi_pci_context {
 	device_t ap_dev;
 	u_int ap_seg;
 	int ap_bus;
-	ACPI_HANDLE ap_handle;
 	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);
+	int ap_pciflags_clear;
 };
 
+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;
+	int				q_segment;
+	void				(*q_init)(struct acpi_pci_context *);
+};
+
+const struct acpi_pci_quirk *	acpi_pci_md_find_quirk(int);
+
+void	acpi_pci_graviton_init(struct acpi_pci_context *);
+void	acpi_pci_n1sdp_init(struct acpi_pci_context *);
+
 #endif /* !_ARM_ACPI_PCI_MACHDEP_H */

Index: src/sys/arch/arm/acpi/acpipchb.c
diff -u src/sys/arch/arm/acpi/acpipchb.c:1.15 src/sys/arch/arm/acpi/acpipchb.c:1.16
--- src/sys/arch/arm/acpi/acpipchb.c:1.15	Sun Dec 29 23:47:56 2019
+++ src/sys/arch/arm/acpi/acpipchb.c	Fri Jan 17 17:06:33 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: acpipchb.c,v 1.15 2019/12/29 23:47:56 jmcneill Exp $ */
+/* $NetBSD: acpipchb.c,v 1.16 2020/01/17 17:06:33 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.15 2019/12/29 23:47:56 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpipchb.c,v 1.16 2020/01/17 17:06:33 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -85,7 +85,6 @@ struct acpipchb_softc {
 	bus_space_tag_t		sc_memt;
 
 	struct arm32_bus_dma_tag sc_dmat;
-	struct acpi_pci_context sc_ap;
 
 	ACPI_HANDLE		sc_handle;
 	ACPI_INTEGER		sc_bus;
@@ -94,127 +93,11 @@ struct acpipchb_softc {
 	struct acpipchb_bus_space sc_pciio_bst;
 };
 
-static int
-acpipchb_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;
-	int b, d, f;
-
-	pci_decompose_tag(pc, tag, &b, &d, &f);
-
-	if (ap->ap_bus == b) {
-		if (d > 0 || f > 0) {
-			*data = -1;
-			return EINVAL;
-		}
-		*data = bus_space_read_4(ap->ap_bst, ap->ap_conf_bsh, reg);
-		return 0;
-	}
-	
-	return acpimcfg_conf_read(pc, tag, reg, data);
-}
-
-static int
-acpipchb_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;
-	int b, d, f;
-
-	pci_decompose_tag(pc, tag, &b, &d, &f);
-
-	if (ap->ap_bus == b) {
-		if (d > 0 || f > 0) {
-			return EINVAL;
-		}
-		bus_space_write_4(ap->ap_bst, ap->ap_conf_bsh, reg, data);
-		return 0;
-	}
-	
-	return acpimcfg_conf_write(pc, tag, reg, data);
-}
-
-static ACPI_STATUS
-acpipchb_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_HANDLE parent;
-	ACPI_STATUS rv;
-	int error;
-
-	rv = AcpiGetParent(handle, &parent);
-	if (ACPI_FAILURE(rv))
-		return rv;
-	if (ap->ap_handle != parent)
-		return AE_OK;
-
-	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,
-	    _ARM_BUS_SPACE_MAP_STRONGLY_ORDERED, &ap->ap_conf_bsh);
-	if (error != 0)
-		return AE_NO_MEMORY;
-
-	ap->ap_conf_read = acpipchb_amazon_graviton_conf_read;
-	ap->ap_conf_write = acpipchb_amazon_graviton_conf_write;
-
-	return AE_CTRL_TERMINATE;
-}
-
-static void
-acpipchb_amazon_graviton_init(struct acpi_pci_context *ap)
-{
-	ACPI_STATUS rv;
-
-	rv = AcpiGetDevices(__UNCONST("AMZN0001"), acpipchb_amazon_graviton_map, ap, NULL);
-	if (ACPI_FAILURE(rv))
-		return;
-}
-
-static const struct acpipchb_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 acpi_pci_context *);
-} acpipchb_quirks[] = {
-	{ "AMAZON",	"GRAVITON",	0,	acpipchb_amazon_graviton_init },
-};
-
-static const struct acpipchb_quirk *
-acpipchb_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(acpipchb_quirks); n++) {
-		const struct acpipchb_quirk *q = &acpipchb_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;
-}
-
 static int	acpipchb_match(device_t, cfdata_t, void *);
 static void	acpipchb_attach(device_t, device_t, void *);
 
 static void	acpipchb_setup_ranges(struct acpipchb_softc *, struct pcibus_attach_args *);
+static void	acpipchb_setup_quirks(struct acpipchb_softc *, struct pcibus_attach_args *);
 
 CFATTACH_DECL_NEW(acpipchb, sizeof(struct acpipchb_softc),
 	acpipchb_match, acpipchb_attach, NULL, NULL);
@@ -241,7 +124,6 @@ acpipchb_attach(device_t parent, device_
 	struct acpipchb_softc * const sc = device_private(self);
 	struct acpi_attach_args *aa = aux;
 	struct pcibus_attach_args pba;
-	const struct acpipchb_quirk *q;
 	ACPI_INTEGER seg;
 
 	sc->sc_dev = self;
@@ -259,20 +141,8 @@ acpipchb_attach(device_t parent, device_
 
 	sc->sc_dmat = *aa->aa_dmat;
 
-	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_handle = sc->sc_handle;
-	sc->sc_ap.ap_bus = sc->sc_bus;
-	sc->sc_ap.ap_bst = sc->sc_memt;
-
-	q = acpipchb_find_quirk();
-	if (q != NULL)
-		q->q_init(&sc->sc_ap);
-
 	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)
+		if (acpimcfg_configure_bus(self, aa->aa_pc, sc->sc_handle, sc->sc_bus, PCIHOST_CACHELINE_SIZE) != 0)
 			aprint_error_dev(self, "failed to configure bus\n");
 	}
 
@@ -284,10 +154,11 @@ acpipchb_attach(device_t parent, device_
 #ifdef _PCI_HAVE_DMA64
 	pba.pba_dmat64 = &sc->sc_dmat;
 #endif
-	pba.pba_pc = &sc->sc_ap.ap_pc;
+	pba.pba_pc = aa->aa_pc;
 	pba.pba_bus = sc->sc_bus;
 
 	acpipchb_setup_ranges(sc, &pba);
+	acpipchb_setup_quirks(sc, &pba);
 
 	config_found_ia(self, "pcibus", &pba, pcibusprint);
 }
@@ -402,3 +273,12 @@ acpipchb_setup_ranges(struct acpipchb_so
 
 	AcpiWalkResources(sc->sc_handle, "_CRS", acpipchb_setup_ranges_cb, &args);
 }
+
+static void
+acpipchb_setup_quirks(struct acpipchb_softc *sc, struct pcibus_attach_args *pba)
+{
+	struct arm32_pci_chipset *md_pc = (struct arm32_pci_chipset *)pba->pba_pc;
+	struct acpi_pci_context *ap = md_pc->pc_conf_v;
+
+	pba->pba_flags &= ~ap->ap_pciflags_clear;
+}

Index: src/sys/arch/arm/acpi/files.acpi
diff -u src/sys/arch/arm/acpi/files.acpi:1.8 src/sys/arch/arm/acpi/files.acpi:1.9
--- src/sys/arch/arm/acpi/files.acpi:1.8	Mon Oct 14 11:00:13 2019
+++ src/sys/arch/arm/acpi/files.acpi	Fri Jan 17 17:06:33 2020
@@ -1,4 +1,4 @@
-#	$NetBSD: files.acpi,v 1.8 2019/10/14 11:00:13 jmcneill Exp $
+#	$NetBSD: files.acpi,v 1.9 2020/01/17 17:06:33 jmcneill Exp $
 #
 # Configuration info for ACPI compliant ARM boards.
 #
@@ -13,6 +13,8 @@ include "dev/acpi/files.acpi"
 file	arch/arm/acpi/acpi_iort.c		acpi
 file	arch/arm/acpi/acpi_machdep.c		acpi
 file	arch/arm/acpi/acpi_pci_machdep.c	acpi & pci
+file	arch/arm/acpi/acpi_pci_graviton.c	acpi & pci
+file	arch/arm/acpi/acpi_pci_n1sdp.c		acpi & pci
 file	arch/arm/acpi/acpi_platform.c		acpi
 file	arch/arm/acpi/acpi_simplefb.c		acpi & wsdisplay & genfb
 file	arch/arm/acpi/acpi_table.c		acpi

Index: src/sys/arch/arm/fdt/acpi_fdt.c
diff -u src/sys/arch/arm/fdt/acpi_fdt.c:1.13 src/sys/arch/arm/fdt/acpi_fdt.c:1.14
--- src/sys/arch/arm/fdt/acpi_fdt.c:1.13	Sun Dec 29 23:47:56 2019
+++ src/sys/arch/arm/fdt/acpi_fdt.c	Fri Jan 17 17:06:33 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_fdt.c,v 1.13 2019/12/29 23:47:56 jmcneill Exp $ */
+/* $NetBSD: acpi_fdt.c,v 1.14 2020/01/17 17:06:33 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015-2017 Jared McNeill <jmcne...@invisible.ca>
@@ -30,7 +30,7 @@
 #include "opt_efi.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_fdt.c,v 1.13 2019/12/29 23:47:56 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_fdt.c,v 1.14 2020/01/17 17:06:33 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -72,10 +72,6 @@ static void	acpi_fdt_sysctl_init(void);
 
 extern struct arm32_bus_dma_tag acpi_coherent_dma_tag;
 
-#if NPCI > 0
-static struct acpi_pci_context acpi_fdt_pci_context;
-#endif
-
 static uint64_t smbios_table = 0;
 
 #ifdef EFI_RUNTIME
@@ -122,9 +118,6 @@ acpi_fdt_attach(device_t parent, device_
 
 	memset(&aa, 0, sizeof(aa));
 #if NPCI > 0
-	acpi_fdt_pci_context.ap_pc = arm_acpi_pci_chipset;
-	acpi_fdt_pci_context.ap_pc.pc_conf_v = &acpi_fdt_pci_context;
-	acpi_fdt_pci_context.ap_seg = 0;
 	aa.aa_pciflags =
 	    /*PCI_FLAGS_IO_OKAY |*/ PCI_FLAGS_MEM_OKAY |
 	    PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | 
@@ -132,7 +125,6 @@ acpi_fdt_attach(device_t parent, device_
 #ifdef __HAVE_PCI_MSI_MSIX
 	aa.aa_pciflags |= PCI_FLAGS_MSI_OKAY | PCI_FLAGS_MSIX_OKAY;
 #endif
-	aa.aa_pc = &acpi_fdt_pci_context.ap_pc;
 #endif
 
 	aa.aa_memt = faa->faa_bst;

Index: src/sys/arch/x86/x86/mpacpi.c
diff -u src/sys/arch/x86/x86/mpacpi.c:1.103 src/sys/arch/x86/x86/mpacpi.c:1.104
--- src/sys/arch/x86/x86/mpacpi.c:1.103	Thu Jun  1 02:45:08 2017
+++ src/sys/arch/x86/x86/mpacpi.c	Fri Jan 17 17:06:32 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: mpacpi.c,v 1.103 2017/06/01 02:45:08 chs Exp $	*/
+/*	$NetBSD: mpacpi.c,v 1.104 2020/01/17 17:06:32 jmcneill Exp $	*/
 
 /*
  * Copyright (c) 2003 Wasabi Systems, Inc.
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mpacpi.c,v 1.103 2017/06/01 02:45:08 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mpacpi.c,v 1.104 2020/01/17 17:06:32 jmcneill Exp $");
 
 #include "acpica.h"
 #include "opt_acpi.h"
@@ -633,7 +633,7 @@ mpacpi_pciroute(struct mpacpi_pcibus *mp
 			/* acpi_allocate_resources(linkdev); */
 			mpi->ioapic_pin = -1;
 			mpi->linkdev = acpi_pci_link_devbyhandle(linkdev);
-			acpi_pci_link_add_reference(mpi->linkdev, 0,
+			acpi_pci_link_add_reference(mpi->linkdev, NULL, 0,
 			    mpr->mpr_bus, dev, ptrp->Pin & 3);
 			mpi->ioapic = NULL;
 			mpi->flags = MPS_INTPO_ACTLO | (MPS_INTTR_LEVEL << 2);
@@ -1009,8 +1009,8 @@ mpacpi_findintr_linkdev(struct mp_intr_m
 	if (mip->linkdev == NULL)
 		return ENOENT;
 
-	irq = acpi_pci_link_route_interrupt(mip->linkdev, mip->sourceindex,
-	    &line, &pol, &trig);
+	irq = acpi_pci_link_route_interrupt(mip->linkdev, NULL,
+	    mip->sourceindex, &line, &pol, &trig);
 	if (mp_verbose)
 		printf("linkdev %s returned ACPI global irq %d, line %d\n",
 		    acpi_pci_link_name(mip->linkdev), irq, line);

Index: src/sys/dev/acpi/acpi.c
diff -u src/sys/dev/acpi/acpi.c:1.282 src/sys/dev/acpi/acpi.c:1.283
--- src/sys/dev/acpi/acpi.c:1.282	Tue Dec 31 12:27:50 2019
+++ src/sys/dev/acpi/acpi.c	Fri Jan 17 17:06:32 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: acpi.c,v 1.282 2019/12/31 12:27:50 jmcneill Exp $	*/
+/*	$NetBSD: acpi.c,v 1.283 2020/01/17 17:06:32 jmcneill Exp $	*/
 
 /*-
  * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc.
@@ -100,7 +100,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.282 2019/12/31 12:27:50 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.283 2020/01/17 17:06:32 jmcneill Exp $");
 
 #include "pci.h"
 #include "opt_acpi.h"
@@ -241,6 +241,7 @@ void (*acpi_print_dev)(const char *) = a
 
 bus_dma_tag_t		acpi_default_dma_tag(struct acpi_softc *, struct acpi_devnode *);
 bus_dma_tag_t		acpi_default_dma64_tag(struct acpi_softc *, struct acpi_devnode *);
+pci_chipset_tag_t	acpi_default_pci_chipset_tag(struct acpi_softc *, int, int);
 
 CFATTACH_DECL2_NEW(acpi, sizeof(struct acpi_softc),
     acpi_match, acpi_attach, acpi_detach, NULL, acpi_rescan, acpi_childdet);
@@ -461,7 +462,6 @@ acpi_attach(device_t parent, device_t se
 
 	sc->sc_iot = aa->aa_iot;
 	sc->sc_memt = aa->aa_memt;
-	sc->sc_pc = aa->aa_pc;
 	sc->sc_pciflags = aa->aa_pciflags;
 	sc->sc_ic = aa->aa_ic;
 	sc->sc_dmat = aa->aa_dmat;
@@ -849,6 +849,13 @@ acpi_default_dma64_tag(struct acpi_softc
 }
 __weak_alias(acpi_get_dma64_tag,acpi_default_dma64_tag);
 
+pci_chipset_tag_t
+acpi_default_pci_chipset_tag(struct acpi_softc *sc, int seg, int bbn)
+{
+	return NULL;
+}
+__weak_alias(acpi_get_pci_chipset_tag,acpi_default_pci_chipset_tag);
+
 /*
  * Device attachment.
  */
@@ -915,8 +922,10 @@ acpi_rescan_early(struct acpi_softc *sc)
 		aa.aa_node = ad;
 		aa.aa_iot = sc->sc_iot;
 		aa.aa_memt = sc->sc_memt;
-		aa.aa_pc = sc->sc_pc;
-		aa.aa_pciflags = sc->sc_pciflags;
+		if (ad->ad_pciinfo != NULL) {
+			aa.aa_pc = ad->ad_pciinfo->ap_pc;
+			aa.aa_pciflags = sc->sc_pciflags;
+		}
 		aa.aa_ic = sc->sc_ic;
 		aa.aa_dmat = ad->ad_dmat;
 		aa.aa_dmat64 = ad->ad_dmat64;
@@ -977,8 +986,10 @@ acpi_rescan_nodes(struct acpi_softc *sc)
 		aa.aa_node = ad;
 		aa.aa_iot = sc->sc_iot;
 		aa.aa_memt = sc->sc_memt;
-		aa.aa_pc = sc->sc_pc;
-		aa.aa_pciflags = sc->sc_pciflags;
+		if (ad->ad_pciinfo != NULL) {
+			aa.aa_pc = ad->ad_pciinfo->ap_pc;
+			aa.aa_pciflags = sc->sc_pciflags;
+		}
 		aa.aa_ic = sc->sc_ic;
 		aa.aa_dmat = ad->ad_dmat;
 		aa.aa_dmat64 = ad->ad_dmat64;

Index: src/sys/dev/acpi/acpi_pci.c
diff -u src/sys/dev/acpi/acpi_pci.c:1.26 src/sys/dev/acpi/acpi_pci.c:1.27
--- src/sys/dev/acpi/acpi_pci.c:1.26	Fri Mar  1 09:26:00 2019
+++ src/sys/dev/acpi/acpi_pci.c	Fri Jan 17 17:06:32 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_pci.c,v 1.26 2019/03/01 09:26:00 msaitoh Exp $ */
+/* $NetBSD: acpi_pci.c,v 1.27 2020/01/17 17:06:32 jmcneill Exp $ */
 
 /*
  * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc.
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_pci.c,v 1.26 2019/03/01 09:26:00 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_pci.c,v 1.27 2020/01/17 17:06:32 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -230,6 +230,8 @@ acpi_pcidev_scan(struct acpi_devnode *ad
 
 		ap->ap_flags |= ACPI_PCI_INFO_BRIDGE;
 
+		ap->ap_pc = acpi_get_pci_chipset_tag(acpi_softc, ap->ap_segment, ap->ap_downbus);
+
 		/*
 		 * This ACPI node denotes a PCI root bridge, but it may also
 		 * denote a PCI device on the bridge's downstream bus segment.
@@ -266,6 +268,7 @@ acpi_pcidev_scan(struct acpi_devnode *ad
 		 */
 		ap = kmem_zalloc(sizeof(*ap), KM_SLEEP);
 
+		ap->ap_pc = ad->ad_parent->ad_pciinfo->ap_pc;
 		ap->ap_segment = ad->ad_parent->ad_pciinfo->ap_segment;
 		ap->ap_bus = ad->ad_parent->ad_pciinfo->ap_downbus;
 
@@ -292,8 +295,10 @@ acpi_pcidev_scan(struct acpi_devnode *ad
 			 * Check whether this device is a PCI-to-PCI
 			 * bridge and get its secondary bus number.
 			 */
-			rv = acpi_pcidev_ppb_downbus(ap->ap_segment, ap->ap_bus,
-			    ap->ap_device, ap->ap_function, &ap->ap_downbus);
+			rv = acpi_pcidev_ppb_downbus(
+			    ad->ad_parent->ad_pciinfo->ap_pc,
+			    ap->ap_segment, ap->ap_bus, ap->ap_device,
+			    ap->ap_function, &ap->ap_downbus);
 
 			if (ACPI_SUCCESS(rv))
 				ap->ap_flags |= ACPI_PCI_INFO_BRIDGE;
@@ -325,19 +330,15 @@ rec:
  * XXX	Need to deal with PCI segment groups (see also acpica/OsdHardware.c).
  */
 ACPI_STATUS
-acpi_pcidev_ppb_downbus(uint16_t segment, uint16_t bus, uint16_t device,
-    uint16_t function, uint16_t *downbus)
+acpi_pcidev_ppb_downbus(pci_chipset_tag_t pc, uint16_t segment, uint16_t bus,
+    uint16_t device, uint16_t function, uint16_t *downbus)
 {
-	struct acpi_softc *sc = acpi_softc;
-	pci_chipset_tag_t pc;
 	pcitag_t tag;
 	pcireg_t val;
 
 	if (bus > 255 || device > 31 || function > 7)
 		return AE_BAD_PARAMETER;
 
-	pc = sc->sc_pc;
-
 	tag = pci_make_tag(pc, bus, device, function);
 
 	/* Check that this device exists. */
@@ -392,6 +393,24 @@ acpi_pcidev_find(uint16_t segment, uint1
 }
 
 /*
+ * acpi_pcidev_get_tag:
+ *
+ *	Returns a PCI chipset tag for a PCI device in the ACPI name space.
+ */
+pci_chipset_tag_t
+acpi_pcidev_get_tag(uint16_t segment, uint16_t bus,
+    uint16_t device, uint16_t function)
+{
+	struct acpi_devnode *ad;
+
+	ad = acpi_pcidev_find(segment, bus, device, function);
+	if (ad == NULL || ad->ad_pciinfo == NULL)
+		return NULL;
+
+	return ad->ad_pciinfo->ap_pc;
+}
+
+/*
  * acpi_pciroot_find:
  *
  *	Finds a PCI root bridge in the ACPI name space.

Index: src/sys/dev/acpi/acpi_pci.h
diff -u src/sys/dev/acpi/acpi_pci.h:1.10 src/sys/dev/acpi/acpi_pci.h:1.11
--- src/sys/dev/acpi/acpi_pci.h:1.10	Sun Oct 21 11:04:26 2018
+++ src/sys/dev/acpi/acpi_pci.h	Fri Jan 17 17:06:32 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_pci.h,v 1.10 2018/10/21 11:04:26 jmcneill Exp $ */
+/* $NetBSD: acpi_pci.h,v 1.11 2020/01/17 17:06:32 jmcneill Exp $ */
 
 /*
  * Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -32,10 +32,13 @@
 #define _SYS_DEV_ACPI_ACPI_PCI_H
 
 ACPI_STATUS		 acpi_pcidev_scan(struct acpi_devnode *);
-ACPI_STATUS		 acpi_pcidev_ppb_downbus(uint16_t, uint16_t, uint16_t,
+ACPI_STATUS		 acpi_pcidev_ppb_downbus(pci_chipset_tag_t,
+						 uint16_t, uint16_t, uint16_t,
 						 uint16_t, uint16_t *);
 struct acpi_devnode	*acpi_pcidev_find(uint16_t, uint16_t,
 					  uint16_t, uint16_t);
+pci_chipset_tag_t	 acpi_pcidev_get_tag(uint16_t, uint16_t,
+					     uint16_t, uint16_t);
 device_t		 acpi_pcidev_find_dev(struct acpi_devnode *);
 struct acpi_devnode	*acpi_pciroot_find(uint16_t, uint16_t);
 ACPI_INTEGER		 acpi_pci_ignore_boot_config(ACPI_HANDLE);

Index: src/sys/dev/acpi/acpi_pci_link.c
diff -u src/sys/dev/acpi/acpi_pci_link.c:1.25 src/sys/dev/acpi/acpi_pci_link.c:1.26
--- src/sys/dev/acpi/acpi_pci_link.c:1.25	Mon Jan 13 00:19:43 2020
+++ src/sys/dev/acpi/acpi_pci_link.c	Fri Jan 17 17:06:32 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: acpi_pci_link.c,v 1.25 2020/01/13 00:19:43 chs Exp $	*/
+/*	$NetBSD: acpi_pci_link.c,v 1.26 2020/01/17 17:06:32 jmcneill Exp $	*/
 
 /*-
  * Copyright (c) 2002 Mitsuru IWASAKI <iwas...@jp.freebsd.org>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_pci_link.c,v 1.25 2020/01/13 00:19:43 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_pci_link.c,v 1.26 2020/01/17 17:06:32 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/malloc.h>
@@ -142,8 +142,8 @@ static ACPI_STATUS link_add_prs(ACPI_RES
 static int link_valid_irq(struct link *, int);
 static void acpi_pci_link_dump(struct acpi_pci_link_softc *);
 static int acpi_pci_link_attach(struct acpi_pci_link_softc *);
-static uint8_t acpi_pci_link_search_irq(struct acpi_pci_link_softc *, int, int,
-					int);
+static uint8_t acpi_pci_link_search_irq(struct acpi_pci_link_softc *,
+					pci_chipset_tag_t, int, int, int);
 static struct link *acpi_pci_link_lookup(struct acpi_pci_link_softc *, int);
 static ACPI_STATUS acpi_pci_link_srs(struct acpi_pci_link_softc *,
 				     ACPI_BUFFER *);
@@ -560,15 +560,15 @@ fail:
 
 static void
 acpi_pci_link_add_functions(struct acpi_pci_link_softc *sc, struct link *link,
-    int bus, int device, int pin)
+    pci_chipset_tag_t pc, int bus, int device, int pin)
 {
 	uint32_t value;
 	uint8_t func, maxfunc, ipin;
 	pcitag_t tag;
 
-	tag = pci_make_tag(acpi_softc->sc_pc, bus, device, 0);
+	tag = pci_make_tag(pc, bus, device, 0);
 	/* See if we have a valid device at function 0. */
-	value = pci_conf_read(acpi_softc->sc_pc, tag,  PCI_BHLC_REG);
+	value = pci_conf_read(pc, tag,  PCI_BHLC_REG);
 	if (PCI_HDRTYPE_TYPE(value) > PCI_HDRTYPE_PCB)
 		return;
 	if (PCI_HDRTYPE_MULTIFN(value))
@@ -578,11 +578,11 @@ acpi_pci_link_add_functions(struct acpi_
 
 	/* Scan all possible functions at this device. */
 	for (func = 0; func <= maxfunc; func++) {
-		tag = pci_make_tag(acpi_softc->sc_pc, bus, device, func);
-		value = pci_conf_read(acpi_softc->sc_pc, tag, PCI_ID_REG);
+		tag = pci_make_tag(pc, bus, device, func);
+		value = pci_conf_read(pc, tag, PCI_ID_REG);
 		if (PCI_VENDOR(value) == 0xffff)
 			continue;
-		value = pci_conf_read(acpi_softc->sc_pc, tag,
+		value = pci_conf_read(pc, tag,
 		    PCI_INTERRUPT_REG);
 		ipin = PCI_INTERRUPT_PIN(value);
 		/*
@@ -602,16 +602,16 @@ acpi_pci_link_add_functions(struct acpi_
 }
 
 static uint8_t
-acpi_pci_link_search_irq(struct acpi_pci_link_softc *sc, int bus, int device,
-			 int pin)
+acpi_pci_link_search_irq(struct acpi_pci_link_softc *sc, pci_chipset_tag_t pc,
+    int bus, int device, int pin)
 {
 	uint32_t value;
 	uint8_t func, maxfunc, ipin, iline;
 	pcitag_t tag;
 
-	tag = pci_make_tag(acpi_softc->sc_pc, bus, device, 0);
+	tag = pci_make_tag(pc, bus, device, 0);
 	/* See if we have a valid device at function 0. */
-	value = pci_conf_read(acpi_softc->sc_pc, tag,  PCI_BHLC_REG);
+	value = pci_conf_read(pc, tag,  PCI_BHLC_REG);
 	if (PCI_HDRTYPE_TYPE(value) > PCI_HDRTYPE_PCB)
 		return (PCI_INVALID_IRQ);
 	if (PCI_HDRTYPE_MULTIFN(value))
@@ -621,11 +621,11 @@ acpi_pci_link_search_irq(struct acpi_pci
 
 	/* Scan all possible functions at this device. */
 	for (func = 0; func <= maxfunc; func++) {
-		tag = pci_make_tag(acpi_softc->sc_pc, bus, device, func);
-		value = pci_conf_read(acpi_softc->sc_pc, tag, PCI_ID_REG);
+		tag = pci_make_tag(pc, bus, device, func);
+		value = pci_conf_read(pc, tag, PCI_ID_REG);
 		if (PCI_VENDOR(value) == 0xffff)
 			continue;
-		value = pci_conf_read(acpi_softc->sc_pc, tag,
+		value = pci_conf_read(pc, tag,
 		    PCI_INTERRUPT_REG);
 		ipin = PCI_INTERRUPT_PIN(value);
 		iline = PCI_INTERRUPT_LINE(value);
@@ -663,7 +663,8 @@ acpi_pci_link_lookup(struct acpi_pci_lin
 }
 
 void
-acpi_pci_link_add_reference(void *v, int index, int bus, int slot, int pin)
+acpi_pci_link_add_reference(void *v, pci_chipset_tag_t pc, int index,
+    int bus, int slot, int pin)
 {
 	struct acpi_pci_link_softc *sc = v;
 	struct link *link;
@@ -678,7 +679,7 @@ acpi_pci_link_add_reference(void *v, int
 		return;
 	}
 	link->l_references++;
-	acpi_pci_link_add_functions(sc, link, bus, slot, pin);
+	acpi_pci_link_add_functions(sc, link, pc, bus, slot, pin);
 	if (link->l_routed)
 		pci_link_interrupt_weights[link->l_irq]++;
 
@@ -703,7 +704,7 @@ acpi_pci_link_add_reference(void *v, int
 	}
 
 	/* Try to find a BIOS IRQ setting from any matching devices. */
-	bios_irq = acpi_pci_link_search_irq(sc, bus, slot, pin);
+	bios_irq = acpi_pci_link_search_irq(sc, pc, bus, slot, pin);
 	if (!PCI_INTERRUPT_VALID(bios_irq)) {
 		ACPI_SERIAL_END(pci_link);
 		return;
@@ -1022,7 +1023,8 @@ acpi_pci_link_choose_irq(struct acpi_pci
 }
 
 int
-acpi_pci_link_route_interrupt(void *v, int index, int *irq, int *pol, int *trig)
+acpi_pci_link_route_interrupt(void *v, pci_chipset_tag_t pc, int index,
+    int *irq, int *pol, int *trig)
 {
 	struct acpi_pci_link_softc *sc = v;
 	struct link *link;
@@ -1073,11 +1075,11 @@ acpi_pci_link_route_interrupt(void *v, i
 	link->l_pol = *pol;
 	link->l_trig = *trig;
 	for (i = 0; i < link->l_dev_count; ++i) {
-		reg = pci_conf_read(acpi_softc->sc_pc, link->l_devices[i],
+		reg = pci_conf_read(pc, link->l_devices[i],
 		    PCI_INTERRUPT_REG);
 		reg &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
 		reg |= link->l_irq << PCI_INTERRUPT_LINE_SHIFT;
-		pci_conf_write(acpi_softc->sc_pc, link->l_devices[i],
+		pci_conf_write(pc, link->l_devices[i],
 		    PCI_INTERRUPT_REG, reg);
 	}
 

Index: src/sys/dev/acpi/acpivar.h
diff -u src/sys/dev/acpi/acpivar.h:1.81 src/sys/dev/acpi/acpivar.h:1.82
--- src/sys/dev/acpi/acpivar.h:1.81	Tue Dec 31 17:26:04 2019
+++ src/sys/dev/acpi/acpivar.h	Fri Jan 17 17:06:32 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: acpivar.h,v 1.81 2019/12/31 17:26:04 jmcneill Exp $	*/
+/*	$NetBSD: acpivar.h,v 1.82 2020/01/17 17:06:32 jmcneill Exp $	*/
 
 /*
  * Copyright 2001 Wasabi Systems, Inc.
@@ -87,6 +87,7 @@ struct acpibus_attach_args {
  * functions on a PCI device (ACPI 4.0a, p. 200).
  */
 struct acpi_pci_info {
+	pci_chipset_tag_t	 ap_pc;		/* PCI chipset tag */
 	uint16_t		 ap_flags;	/* Flags (cf. below) */
 	uint16_t		 ap_segment;	/* PCI segment group */
 	uint16_t		 ap_bus;	/* PCI bus */
@@ -160,7 +161,6 @@ struct acpi_softc {
 
 	bus_space_tag_t		 sc_iot;	/* PCI I/O space tag */
 	bus_space_tag_t		 sc_memt;	/* PCI MEM space tag */
-	pci_chipset_tag_t	 sc_pc;		/* PCI chipset tag */
 	int			 sc_pciflags;	/* PCI bus flags */
 	int			 sc_pci_bus;	/* internal PCI fixup */
 	isa_chipset_tag_t	 sc_ic;		/* ISA chipset tag */
@@ -322,8 +322,10 @@ void		acpi_resource_print(device_t, stru
 void		acpi_resource_cleanup(struct acpi_resources *);
 
 void *		acpi_pci_link_devbyhandle(ACPI_HANDLE);
-void		acpi_pci_link_add_reference(void *, int, int, int, int);
-int		acpi_pci_link_route_interrupt(void *, int, int *, int *, int *);
+void		acpi_pci_link_add_reference(void *, pci_chipset_tag_t, int,
+		    int, int, int);
+int		acpi_pci_link_route_interrupt(void *, pci_chipset_tag_t, int,
+		    int *, int *, int *);
 char *		acpi_pci_link_name(void *);
 ACPI_HANDLE	acpi_pci_link_handle(void *);
 void		acpi_pci_link_state(void);
@@ -389,6 +391,7 @@ void	acpi_debug_init(void);
 
 bus_dma_tag_t	acpi_get_dma_tag(struct acpi_softc *, struct acpi_devnode *);
 bus_dma_tag_t	acpi_get_dma64_tag(struct acpi_softc *, struct acpi_devnode *);
+pci_chipset_tag_t acpi_get_pci_chipset_tag(struct acpi_softc *, int, int);
 
 /*
  * Misc routines with vectors updated by acpiverbose module.

Index: src/sys/dev/acpi/acpica/OsdHardware.c
diff -u src/sys/dev/acpi/acpica/OsdHardware.c:1.11 src/sys/dev/acpi/acpica/OsdHardware.c:1.12
--- src/sys/dev/acpi/acpica/OsdHardware.c:1.11	Fri Feb 15 20:48:57 2019
+++ src/sys/dev/acpi/acpica/OsdHardware.c	Fri Jan 17 17:06:33 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: OsdHardware.c,v 1.11 2019/02/15 20:48:57 kamil Exp $	*/
+/*	$NetBSD: OsdHardware.c,v 1.12 2020/01/17 17:06:33 jmcneill Exp $	*/
 
 /*
  * Copyright 2001 Wasabi Systems, Inc.
@@ -44,7 +44,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: OsdHardware.c,v 1.11 2019/02/15 20:48:57 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: OsdHardware.c,v 1.12 2020/01/17 17:06:33 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -210,15 +210,15 @@ ACPI_STATUS
 AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register, UINT64 *Value,
     UINT32 Width)
 {
+	pci_chipset_tag_t pc;
 	pcitag_t tag;
 	pcireg_t tmp;
-	pci_chipset_tag_t pc = acpi_softc ? acpi_softc->sc_pc : NULL;
-
-	/* XXX Need to deal with "segment" ("hose" in Alpha terminology). */
 
 	if (PciId->Bus >= 256 || PciId->Device >= 32 || PciId->Function >= 8)
 		return AE_BAD_PARAMETER;
 
+	pc = acpi_pcidev_get_tag(PciId->Segment, PciId->Bus, PciId->Device, PciId->Function);
+
 	tag = pci_make_tag(pc, PciId->Bus, PciId->Device, PciId->Function);
 	tmp = pci_conf_read(pc, tag, Register & ~3);
 
@@ -251,12 +251,11 @@ ACPI_STATUS
 AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Register,
     ACPI_INTEGER Value, UINT32 Width)
 {
+	pci_chipset_tag_t pc;
 	pcitag_t tag;
 	pcireg_t tmp;
-	pci_chipset_tag_t pc = acpi_softc ? acpi_softc->sc_pc : NULL;
-
-	/* XXX Need to deal with "segment" ("hose" in Alpha terminology). */
 
+	pc = acpi_pcidev_get_tag(PciId->Segment, PciId->Bus, PciId->Device, PciId->Function);
 	tag = pci_make_tag(pc, PciId->Bus, PciId->Device, PciId->Function);
 
 	switch (Width) {

Added files:

Index: src/sys/arch/arm/acpi/acpi_pci_graviton.c
diff -u /dev/null src/sys/arch/arm/acpi/acpi_pci_graviton.c:1.1
--- /dev/null	Fri Jan 17 17:06:33 2020
+++ src/sys/arch/arm/acpi/acpi_pci_graviton.c	Fri Jan 17 17:06:33 2020
@@ -0,0 +1,144 @@
+/* $NetBSD: acpi_pci_graviton.c,v 1.1 2020/01/17 17:06:33 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jared McNeill <jmcne...@invisible.ca>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: acpi_pci_graviton.c,v 1.1 2020/01/17 17:06:33 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/extent.h>
+#include <sys/kmem.h>
+
+#include <machine/cpu.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pciconf.h>
+
+#include <dev/acpi/acpivar.h>
+#include <dev/acpi/acpi_pci.h>
+#include <dev/acpi/acpi_mcfg.h>
+
+#include <arm/acpi/acpi_pci_machdep.h>
+
+static int
+acpi_pci_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;
+	int b, d, f;
+
+	pci_decompose_tag(pc, tag, &b, &d, &f);
+
+	if (ap->ap_bus == b) {
+		if (d > 0 || f > 0) {
+			*data = -1;
+			return EINVAL;
+		}
+		*data = bus_space_read_4(ap->ap_bst, ap->ap_conf_bsh, reg);
+		return 0;
+	}
+	
+	return acpimcfg_conf_read(pc, tag, reg, data);
+}
+
+static int
+acpi_pci_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;
+	int b, d, f;
+
+	pci_decompose_tag(pc, tag, &b, &d, &f);
+
+	if (ap->ap_bus == b) {
+		if (d > 0 || f > 0) {
+			return EINVAL;
+		}
+		bus_space_write_4(ap->ap_bst, ap->ap_conf_bsh, reg, data);
+		return 0;
+	}
+	
+	return acpimcfg_conf_write(pc, tag, reg, data);
+}
+
+static ACPI_STATUS
+acpi_pci_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_HANDLE parent;
+	ACPI_INTEGER seg;
+	ACPI_STATUS rv;
+	int error;
+
+	rv = AcpiGetParent(handle, &parent);
+	if (ACPI_FAILURE(rv))
+		return rv;
+	rv = acpi_eval_integer(parent, "_SEG", &seg);
+	if (ACPI_FAILURE(rv))
+		seg = 0;
+	if (ap->ap_seg != seg)
+		return AE_OK;
+
+	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,
+	    _ARM_BUS_SPACE_MAP_STRONGLY_ORDERED, &ap->ap_conf_bsh);
+	if (error != 0)
+		return AE_NO_MEMORY;
+
+	ap->ap_conf_read = acpi_pci_graviton_conf_read;
+	ap->ap_conf_write = acpi_pci_graviton_conf_write;
+
+	return AE_CTRL_TERMINATE;
+}
+
+void
+acpi_pci_graviton_init(struct acpi_pci_context *ap)
+{
+	ACPI_STATUS rv;
+
+	rv = AcpiGetDevices(__UNCONST("AMZN0001"), acpi_pci_graviton_map, ap, NULL);
+	if (ACPI_FAILURE(rv))
+		return;
+}
Index: src/sys/arch/arm/acpi/acpi_pci_n1sdp.c
diff -u /dev/null src/sys/arch/arm/acpi/acpi_pci_n1sdp.c:1.1
--- /dev/null	Fri Jan 17 17:06:33 2020
+++ src/sys/arch/arm/acpi/acpi_pci_n1sdp.c	Fri Jan 17 17:06:33 2020
@@ -0,0 +1,193 @@
+/* $NetBSD: acpi_pci_n1sdp.c,v 1.1 2020/01/17 17:06:33 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2020 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jared McNeill <jmcne...@invisible.ca>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: acpi_pci_n1sdp.c,v 1.1 2020/01/17 17:06:33 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/extent.h>
+#include <sys/kmem.h>
+
+#include <machine/cpu.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pciconf.h>
+
+#include <dev/acpi/acpivar.h>
+#include <dev/acpi/acpi_pci.h>
+#include <dev/acpi/acpi_mcfg.h>
+
+#include <arm/acpi/acpi_pci_machdep.h>
+
+extern struct bus_space arm_generic_bs_tag;
+
+/* Shared memory location written by the SCP at boot */
+#define	N1SDP_SHARED_MEM_BASE	0x06000000
+
+#define	N1SDP_NSEGS		2
+#define	N1SDP_TABLE_SIZE	0x4000
+
+#define	N1SDP_BUS_SHIFT		20
+#define	N1SDP_DEV_SHIFT		15
+#define	N1SDP_FUNC_SHIFT	12
+
+struct n1sdp_pcie_discovery_data {
+	uint32_t	rc_base_addr;
+	uint32_t	nr_bdfs;
+	uint32_t	valid_bdfs[0];
+};
+
+static struct n1sdp_pcie_discovery_data *n1sdp_data[N1SDP_NSEGS];
+
+static bool
+acpi_pci_n1sdp_valid(pci_chipset_tag_t pc, pcitag_t tag)
+{
+	struct acpi_pci_context *ap = pc->pc_conf_v;
+	u_int n, bdfaddr;
+	int b, d, f;
+
+	if (ap->ap_seg >= N1SDP_NSEGS || n1sdp_data[ap->ap_seg] == NULL)
+		return false;
+
+	pci_decompose_tag(pc, tag, &b, &d, &f);
+
+	bdfaddr = (b << N1SDP_BUS_SHIFT) + 
+		  (d << N1SDP_DEV_SHIFT) +
+		  (f << N1SDP_FUNC_SHIFT);
+
+	for (n = 0; n < n1sdp_data[ap->ap_seg]->nr_bdfs; n++) {
+		if (n1sdp_data[ap->ap_seg]->valid_bdfs[n] == bdfaddr)
+			return true;
+	}
+
+	return false;
+}
+
+static int
+acpi_pci_n1sdp_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t *data)
+{
+	struct acpi_pci_context *ap = pc->pc_conf_v;
+	int b, d, f;
+
+	pci_decompose_tag(pc, tag, &b, &d, &f);
+
+	if (ap->ap_bus == b) {
+		if (d > 0 || f > 0 || reg >= PCI_EXTCONF_SIZE) {
+			*data = -1;
+			return EINVAL;
+		}
+		*data = bus_space_read_4(ap->ap_bst, ap->ap_conf_bsh, reg);
+		return 0;
+	}
+
+	if (!acpi_pci_n1sdp_valid(pc, tag)) {
+		*data = -1;
+		return 0;
+	}
+	
+	return acpimcfg_conf_read(pc, tag, reg, data);
+}
+
+static int
+acpi_pci_n1sdp_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data)
+{
+	struct acpi_pci_context *ap = pc->pc_conf_v;
+	int b, d, f;
+
+	pci_decompose_tag(pc, tag, &b, &d, &f);
+
+	if (ap->ap_bus == b) {
+		if (d > 0 || f > 0 || reg >= PCI_EXTCONF_SIZE) {
+			return EINVAL;
+		}
+		bus_space_write_4(ap->ap_bst, ap->ap_conf_bsh, reg, data);
+		return 0;
+	}
+
+	if (!acpi_pci_n1sdp_valid(pc, tag))
+		return 0;
+	
+	return acpimcfg_conf_write(pc, tag, reg, data);
+}
+
+void
+acpi_pci_n1sdp_init(struct acpi_pci_context *ap)
+{
+	bus_space_tag_t bst = &arm_generic_bs_tag;
+	bus_space_handle_t bsh;
+	paddr_t pa;
+	int error;
+	u_int n;
+
+	if (ap->ap_seg >= N1SDP_NSEGS)
+		return;
+
+	if (n1sdp_data[ap->ap_seg] == NULL) {
+		aprint_normal_dev(ap->ap_dev, "applying N1SDP quirk for segment %d\n", ap->ap_seg);
+
+		pa = N1SDP_SHARED_MEM_BASE + ap->ap_seg * N1SDP_TABLE_SIZE;
+		if (bus_space_map(bst, pa, N1SDP_TABLE_SIZE, BUS_SPACE_MAP_LINEAR, &bsh) != 0)
+			panic("acpi_pci_n1sdp_init: couldn't map PCIe discovery table");
+
+		n1sdp_data[ap->ap_seg] = bus_space_vaddr(bst, bsh);
+		if (n1sdp_data[ap->ap_seg] == NULL)
+			panic("acpi_pci_n1sdp_init: couldn't get PCIe discovery table VA");
+
+		error = bus_space_map(bst, n1sdp_data[ap->ap_seg]->rc_base_addr, PCI_EXTCONF_SIZE,
+		    _ARM_BUS_SPACE_MAP_STRONGLY_ORDERED, &ap->ap_conf_bsh);
+		if (error != 0)
+			panic("acpi_pci_n1sdp_init: couldn't map segment %d", ap->ap_seg);
+
+		aprint_debug_dev(ap->ap_dev, "N1SDP: RC @ 0x%08x, %d devices\n",
+		    n1sdp_data[ap->ap_seg]->rc_base_addr, n1sdp_data[ap->ap_seg]->nr_bdfs);
+		for (n = 0; n < n1sdp_data[ap->ap_seg]->nr_bdfs; n++) {
+			const uint32_t bdf = n1sdp_data[ap->ap_seg]->valid_bdfs[n];
+			const int b = (bdf >> N1SDP_BUS_SHIFT) & 0xff;
+			const int d = (bdf >> N1SDP_DEV_SHIFT) & 0x1f;
+			const int f = (bdf >> N1SDP_FUNC_SHIFT) & 0x7;
+			aprint_debug_dev(ap->ap_dev, "N1SDP: %02x:%02x.%x (%08x)\n", b, d, f, bdf);
+		}
+	}
+
+	ap->ap_conf_read = acpi_pci_n1sdp_conf_read;
+	ap->ap_conf_write = acpi_pci_n1sdp_conf_write;
+
+	/* IO space access and MSI seems to cause async SErrors, so disable for now */
+	ap->ap_pciflags_clear = PCI_FLAGS_IO_OKAY |
+				PCI_FLAGS_MSI_OKAY |
+				PCI_FLAGS_MSIX_OKAY;
+}

Reply via email to