Module Name: src Committed By: jmcneill Date: Sat Aug 7 21:27:53 UTC 2021
Modified Files: src/sys/arch/arm/acpi: acpi_pci_machdep.c acpi_pci_machdep.h acpipchb.c files.acpi Added Files: src/sys/arch/arm/acpi: acpi_pci_smccc.c Log Message: arm: acpi: Add support for SMCCC based PCI config access. To generate a diff of this commit: cvs rdiff -u -r1.18 -r1.19 src/sys/arch/arm/acpi/acpi_pci_machdep.c cvs rdiff -u -r1.7 -r1.8 src/sys/arch/arm/acpi/acpi_pci_machdep.h cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/acpi/acpi_pci_smccc.c cvs rdiff -u -r1.26 -r1.27 src/sys/arch/arm/acpi/acpipchb.c cvs rdiff -u -r1.12 -r1.13 src/sys/arch/arm/acpi/files.acpi 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.18 src/sys/arch/arm/acpi/acpi_pci_machdep.c:1.19 --- src/sys/arch/arm/acpi/acpi_pci_machdep.c:1.18 Wed Jun 17 06:45:09 2020 +++ src/sys/arch/arm/acpi/acpi_pci_machdep.c Sat Aug 7 21:27:53 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_pci_machdep.c,v 1.18 2020/06/17 06:45:09 thorpej Exp $ */ +/* $NetBSD: acpi_pci_machdep.c,v 1.19 2021/08/07 21:27:53 jmcneill Exp $ */ /*- * Copyright (c) 2018, 2020 The NetBSD Foundation, Inc. @@ -29,10 +29,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include "opt_pci.h" + #define _INTR_PRIVATE #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_pci_machdep.c,v 1.18 2020/06/17 06:45:09 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_pci_machdep.c,v 1.19 2021/08/07 21:27:53 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -60,6 +62,10 @@ __KERNEL_RCSID(0, "$NetBSD: acpi_pci_mac #include <arm/acpi/acpi_iort.h> #include <arm/acpi/acpi_pci_machdep.h> +#ifdef PCI_SMCCC +#include <arm/pci/pci_smccc.h> +#endif + #include <arm/pci/pci_msi_machdep.h> struct acpi_pci_prt { @@ -94,7 +100,7 @@ struct acpi_pci_intr { static TAILQ_HEAD(, acpi_pci_intr) acpi_pci_intrs = TAILQ_HEAD_INITIALIZER(acpi_pci_intrs); -static const struct acpi_pci_quirk acpi_pci_quirks[] = { +static const struct acpi_pci_quirk acpi_pci_mcfg_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 }, @@ -102,6 +108,13 @@ static const struct acpi_pci_quirk acpi_ { "NXP ", "LX2160 ", 0, -1, acpi_pci_layerscape_gen4_init }, }; +#ifdef PCI_SMCCC +static const struct acpi_pci_quirk acpi_pci_smccc_quirk = { + .q_segment = -1, + .q_init = acpi_pci_smccc_init, +}; +#endif + 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, @@ -554,11 +567,19 @@ acpi_pci_md_find_quirk(int seg) u_int n; rv = AcpiGetTable(ACPI_SIG_MCFG, 0, (ACPI_TABLE_HEADER **)&mcfg); - if (ACPI_FAILURE(rv)) + if (ACPI_FAILURE(rv)) { +#ifdef PCI_SMCCC + uint32_t ver = pci_smccc_version(); + aprint_debug("%s: SMCCC version %#x\n", __func__, ver); + if (PCI_SMCCC_SUCCESS(ver)) { + return &acpi_pci_smccc_quirk; + } +#endif return NULL; + } - for (n = 0; n < __arraycount(acpi_pci_quirks); n++) { - const struct acpi_pci_quirk *q = &acpi_pci_quirks[n]; + for (n = 0; n < __arraycount(acpi_pci_mcfg_quirks); n++) { + const struct acpi_pci_quirk *q = &acpi_pci_mcfg_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 && @@ -589,6 +610,7 @@ acpi_pci_md_get_chipset_tag(struct acpi_ pct->pct_ap.ap_pc.pc_intr_v = &pct->pct_ap; pct->pct_ap.ap_seg = seg; pct->pct_ap.ap_bus = bbn; + pct->pct_ap.ap_maxbus = -1; pct->pct_ap.ap_bst = acpi_softc->sc_memt; q = acpi_pci_md_find_quirk(seg); Index: src/sys/arch/arm/acpi/acpi_pci_machdep.h diff -u src/sys/arch/arm/acpi/acpi_pci_machdep.h:1.7 src/sys/arch/arm/acpi/acpi_pci_machdep.h:1.8 --- src/sys/arch/arm/acpi/acpi_pci_machdep.h:1.7 Sat Feb 1 13:26:43 2020 +++ src/sys/arch/arm/acpi/acpi_pci_machdep.h Sat Aug 7 21:27:53 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_pci_machdep.h,v 1.7 2020/02/01 13:26:43 jmcneill Exp $ */ +/* $NetBSD: acpi_pci_machdep.h,v 1.8 2021/08/07 21:27:53 jmcneill Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -39,12 +39,15 @@ struct acpi_pci_context { device_t ap_dev; u_int ap_seg; int ap_bus; + int ap_maxbus; 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); void *ap_conf_priv; int ap_pciflags_clear; + u_int ap_flags; +#define ACPI_PCI_FLAG_NO_MCFG __BIT(0) /* ignore MCFG table */ }; struct acpi_pci_quirk { @@ -57,6 +60,7 @@ struct acpi_pci_quirk { const struct acpi_pci_quirk * acpi_pci_md_find_quirk(int); +void acpi_pci_smccc_init(struct acpi_pci_context *); void acpi_pci_graviton_init(struct acpi_pci_context *); void acpi_pci_layerscape_gen4_init(struct acpi_pci_context *); void acpi_pci_n1sdp_init(struct acpi_pci_context *); Index: src/sys/arch/arm/acpi/acpipchb.c diff -u src/sys/arch/arm/acpi/acpipchb.c:1.26 src/sys/arch/arm/acpi/acpipchb.c:1.27 --- src/sys/arch/arm/acpi/acpipchb.c:1.26 Sat Aug 7 16:18:42 2021 +++ src/sys/arch/arm/acpi/acpipchb.c Sat Aug 7 21:27:53 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: acpipchb.c,v 1.26 2021/08/07 16:18:42 thorpej Exp $ */ +/* $NetBSD: acpipchb.c,v 1.27 2021/08/07 21:27:53 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.26 2021/08/07 16:18:42 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpipchb.c,v 1.27 2021/08/07 21:27:53 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -92,6 +92,7 @@ struct acpipchb_softc { static int acpipchb_match(device_t, cfdata_t, void *); static void acpipchb_attach(device_t, device_t, void *); +static void acpipchb_configure_bus(struct acpipchb_softc *, struct pcibus_attach_args *); static void acpipchb_setup_ranges(struct acpipchb_softc *, struct pcibus_attach_args *); static void acpipchb_setup_quirks(struct acpipchb_softc *, @@ -152,13 +153,6 @@ acpipchb_attach(device_t parent, device_ acpi_claim_childdevs(self, aa->aa_node); - if (acpi_pci_ignore_boot_config(sc->sc_handle)) { - 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"); - } - } - memset(&pba, 0, sizeof(pba)); pba.pba_flags = aa->aa_pciflags & ~(PCI_FLAGS_MEM_OKAY | PCI_FLAGS_IO_OKAY); @@ -174,10 +168,48 @@ acpipchb_attach(device_t parent, device_ acpipchb_setup_ranges(sc, &pba); acpipchb_setup_quirks(sc, &pba); + acpipchb_configure_bus(sc, &pba); + config_found(self, &pba, pcibusprint, CFARGS(.devhandle = device_handle(self))); } +static void +acpipchb_configure_bus(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; + struct pciconf_resources *pcires; + ACPI_STATUS rv; + int error; + + if (!acpi_pci_ignore_boot_config(sc->sc_handle)) { + return; + } + + if ((ap->ap_flags & ACPI_PCI_FLAG_NO_MCFG) != 0) { + pcires = pciconf_resource_init(); + rv = AcpiWalkResources(sc->sc_handle, "_CRS", + acpimcfg_configure_bus_cb, pcires); + if (ACPI_FAILURE(rv)) { + error = ENXIO; + } else { + error = pci_configure_bus(pba->pba_pc, pcires, ap->ap_bus, + PCIHOST_CACHELINE_SIZE); + } + pciconf_resource_fini(pcires); + } else { + error = acpimcfg_configure_bus(sc->sc_dev, pba->pba_pc, sc->sc_handle, + sc->sc_bus, PCIHOST_CACHELINE_SIZE); + } + + if (error != 0) { + aprint_error_dev(sc->sc_dev, "failed to configure bus, error %d\n", + error); + } +} + struct acpipchb_setup_ranges_args { struct acpipchb_softc *sc; struct pcibus_attach_args *pba; Index: src/sys/arch/arm/acpi/files.acpi diff -u src/sys/arch/arm/acpi/files.acpi:1.12 src/sys/arch/arm/acpi/files.acpi:1.13 --- src/sys/arch/arm/acpi/files.acpi:1.12 Mon Dec 7 10:57:41 2020 +++ src/sys/arch/arm/acpi/files.acpi Sat Aug 7 21:27:53 2021 @@ -1,4 +1,4 @@ -# $NetBSD: files.acpi,v 1.12 2020/12/07 10:57:41 jmcneill Exp $ +# $NetBSD: files.acpi,v 1.13 2021/08/07 21:27:53 jmcneill Exp $ # # Configuration info for ACPI compliant ARM boards. # @@ -16,6 +16,7 @@ file arch/arm/acpi/acpi_pci_machdep.c ac file arch/arm/acpi/acpi_pci_graviton.c acpi & pci file arch/arm/acpi/acpi_pci_layerscape_gen4.c acpi & pci file arch/arm/acpi/acpi_pci_n1sdp.c acpi & pci +file arch/arm/acpi/acpi_pci_smccc.c acpi & pci & pci_smccc file arch/arm/acpi/acpi_platform.c acpi file arch/arm/acpi/acpi_table.c acpi Added files: Index: src/sys/arch/arm/acpi/acpi_pci_smccc.c diff -u /dev/null src/sys/arch/arm/acpi/acpi_pci_smccc.c:1.1 --- /dev/null Sat Aug 7 21:27:53 2021 +++ src/sys/arch/arm/acpi/acpi_pci_smccc.c Sat Aug 7 21:27:53 2021 @@ -0,0 +1,129 @@ +/* $NetBSD: acpi_pci_smccc.c,v 1.1 2021/08/07 21:27:53 jmcneill Exp $ */ + +/*- + * Copyright (c) 2021 Jared McNeill <jmcne...@invisible.ca> + * All rights reserved. + * + * 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 AUTHOR ``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 AUTHOR 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_smccc.c,v 1.1 2021/08/07 21:27:53 jmcneill Exp $"); + +#include <sys/param.h> +#include <sys/kernel.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> + +#include <arm/pci/pci_smccc.h> + +static int +acpi_pci_smccc_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; + int status; + + pci_decompose_tag(pc, tag, &b, &d, &f); + + if (b < ap->ap_bus || b > ap->ap_maxbus) { + *data = -1; + return EINVAL; + } + + status = pci_smccc_read(PCI_SMCCC_SBDF(ap->ap_seg, b, d, f), reg, + PCI_SMCCC_ACCESS_32BIT, data); + if (!PCI_SMCCC_SUCCESS(status)) { + *data = -1; + return EINVAL; + } + + return 0; +} + +static int +acpi_pci_smccc_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; + int status; + + pci_decompose_tag(pc, tag, &b, &d, &f); + + if (b < ap->ap_bus || b > ap->ap_maxbus) { + return EINVAL; + } + + status = pci_smccc_write(PCI_SMCCC_SBDF(ap->ap_seg, b, d, f), reg, + PCI_SMCCC_ACCESS_32BIT, data); + if (!PCI_SMCCC_SUCCESS(status)) { + return EINVAL; + } + + return 0; +} + + +void +acpi_pci_smccc_init(struct acpi_pci_context *ap) +{ + int status, ver; + uint8_t bus_start, bus_end; + uint16_t next_seg; + + ver = pci_smccc_version(); + if (!PCI_SMCCC_SUCCESS(ver)) { + aprint_error_dev(ap->ap_dev, + "SMCCC: PCI_VERSION call failed, status %#x\n", ver); + return; + } + aprint_normal_dev(ap->ap_dev, "SMCCC: PCI impl. version %u.%u\n", + (ver >> 16) & 0x7fff, ver & 0xffff); + + status = pci_smccc_get_seg_info(ap->ap_seg, &bus_start, &bus_end, + &next_seg); + if (!PCI_SMCCC_SUCCESS(status)) { + aprint_error_dev(ap->ap_dev, + "SMCCC: No info for segment %u, status %#x\n", + ap->ap_seg, status); + return; + } + aprint_normal_dev(ap->ap_dev, "SMCCC: segment %u, bus %u-%u\n", + ap->ap_seg, bus_start, bus_end); + + ap->ap_bus = bus_start; + ap->ap_maxbus = bus_end; + ap->ap_conf_read = acpi_pci_smccc_conf_read; + ap->ap_conf_write = acpi_pci_smccc_conf_write; + ap->ap_flags |= ACPI_PCI_FLAG_NO_MCFG; + ap->ap_pciflags_clear = PCI_FLAGS_MSI_OKAY | PCI_FLAGS_MSIX_OKAY; +}