Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/acpi arm: acpi: Add support for SMCCC based PCI...



details:   https://anonhg.NetBSD.org/src/rev/e2ad19453254
branches:  trunk
changeset: 985088:e2ad19453254
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sat Aug 07 21:27:53 2021 +0000

description:
arm: acpi: Add support for SMCCC based PCI config access.

diffstat:

 sys/arch/arm/acpi/acpi_pci_machdep.c |   34 +++++++-
 sys/arch/arm/acpi/acpi_pci_machdep.h |    6 +-
 sys/arch/arm/acpi/acpi_pci_smccc.c   |  129 +++++++++++++++++++++++++++++++++++
 sys/arch/arm/acpi/acpipchb.c         |   50 +++++++++++--
 sys/arch/arm/acpi/files.acpi         |    3 +-
 5 files changed, 205 insertions(+), 17 deletions(-)

diffs (truncated from 360 to 300 lines):

diff -r f472da6da7fe -r e2ad19453254 sys/arch/arm/acpi/acpi_pci_machdep.c
--- a/sys/arch/arm/acpi/acpi_pci_machdep.c      Sat Aug 07 21:24:56 2021 +0000
+++ b/sys/arch/arm/acpi/acpi_pci_machdep.c      Sat Aug 07 21:27:53 2021 +0000
@@ -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 @@
 #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 @@
 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 @@
        { "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 @@
        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 @@
                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);
diff -r f472da6da7fe -r e2ad19453254 sys/arch/arm/acpi/acpi_pci_machdep.h
--- a/sys/arch/arm/acpi/acpi_pci_machdep.h      Sat Aug 07 21:24:56 2021 +0000
+++ b/sys/arch/arm/acpi/acpi_pci_machdep.h      Sat Aug 07 21:27:53 2021 +0000
@@ -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 @@
        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 @@
 
 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 *);
diff -r f472da6da7fe -r e2ad19453254 sys/arch/arm/acpi/acpi_pci_smccc.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/acpi/acpi_pci_smccc.c        Sat Aug 07 21:27:53 2021 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
+ * 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;
+}
diff -r f472da6da7fe -r e2ad19453254 sys/arch/arm/acpi/acpipchb.c
--- a/sys/arch/arm/acpi/acpipchb.c      Sat Aug 07 21:24:56 2021 +0000
+++ b/sys/arch/arm/acpi/acpipchb.c      Sat Aug 07 21:27:53 2021 +0000
@@ -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 @@
 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 @@
 
        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_setup_ranges(sc, &pba);
        acpipchb_setup_quirks(sc, &pba);
 
+       acpipchb_configure_bus(sc, &pba);
+



Home | Main Index | Thread Index | Old Index