summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2023-04-23 00:20:27 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2023-04-23 00:20:27 +0000
commitdab0a5ce68c5fdc2ae6c7a3eac21718d7eb9cf03 (patch)
tree590e6e1e65745d9f430580e41c44ae3b69a88fd8 /sys/dev/pci
parenta4a7cdae255fbb485a0a21acb41acac11da96c2c (diff)
add iosf(4), a driver for the Intel OnChip System Fabric
The OnChip System Fabric is mostly an implementation detail on a bunch of Intel SoC platforms we usually don't care about, except on some of these machines there are devices shared between the kernel and the platform that need to coordinate. The iosf(4) driver allows the kernel to talk via a mailbox interface to take and release a semaphore that the hardware also uses to lock around accesses to some components. There are two ways to talk to the mailbox interface, one via mmio ops on an INT33BD acpi device. The other is via magic pci conf space operations on the pci host device. This provides a generic iosf driver with attachment glue for both acpi and pci so either can be used. According to linux, the pci ops are a lot more reliable and less buggy, so if both acpi and pci are available we will prefer the pci ops after they attach. I found this because I got a Dell Wyse 3040, which is a cherry trail/braswell system that has an acpitz(4) which talks to a tipmic(4) device attached to dwiic(4) on acpi. This box almost always locked up by the time it got to showing the console login prompt, and it turns out one of the reasons for this is because acpitz was touching the tipmic device at the same time the powerunit on the platform was also trying to use it. The tipmic device lists the iosf mailbox as a dependency, and the dwiic controller has a _SEM property, both of which indicate we should use an iosf device to coordinate iic ops when talking to the tipmic. This adds the code, but doesn't wire it into dwiic or the build yet. help from patrick@ jsg@ kettenis@ ok kettenis@ patrick@
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/files.pci6
-rw-r--r--sys/dev/pci/iosf_pci.c157
2 files changed, 162 insertions, 1 deletions
diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci
index 797e07c5b81..101ed502e76 100644
--- a/sys/dev/pci/files.pci
+++ b/sys/dev/pci/files.pci
@@ -1,4 +1,4 @@
-# $OpenBSD: files.pci,v 1.360 2023/03/31 08:19:41 kevlo Exp $
+# $OpenBSD: files.pci,v 1.361 2023/04/23 00:20:26 dlg Exp $
# $NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $
#
# Config file and device description for machine-independent PCI code.
@@ -771,6 +771,10 @@ device gcu
attach gcu at pci
file dev/pci/gcu.c gcu needs-flag
+# Intel OnChip System Fabric
+attach iosf at pci with iosf_pci
+file dev/pci/iosf_pci.c iosf_pci
+
# AMD Geode CS5536 Audio
device auglx: audio, ac97
attach auglx at pci
diff --git a/sys/dev/pci/iosf_pci.c b/sys/dev/pci/iosf_pci.c
new file mode 100644
index 00000000000..886a39c6071
--- /dev/null
+++ b/sys/dev/pci/iosf_pci.c
@@ -0,0 +1,157 @@
+/* $OpenBSD: iosf_pci.c,v 1.1 2023/04/23 00:20:26 dlg Exp $ */
+
+/*
+ * Copyright (c) 2023 David Gwynne <dlg@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/mutex.h>
+#include <sys/rwlock.h>
+
+#include <machine/bus.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <dev/ic/iosfvar.h>
+
+/*
+ * Intel OnChip System Fabric driver
+ */
+
+struct iosf_pci_softc {
+ struct device sc_dev;
+
+ pci_chipset_tag_t sc_pc;
+ pcitag_t sc_pcitag;
+
+ int sc_semaddr;
+
+ struct iosf_mbi sc_mbi;
+};
+
+static int iosf_pci_match(struct device *, void *, void *);
+static void iosf_pci_attach(struct device *, struct device *, void *);
+
+static uint32_t iosf_pci_mbi_mdr_rd(struct iosf_mbi *, uint32_t, uint32_t);
+static void iosf_pci_mbi_mdr_wr(struct iosf_mbi *, uint32_t, uint32_t,
+ uint32_t);
+
+const struct cfattach iosf_pci_ca = {
+ sizeof(struct iosf_pci_softc), iosf_pci_match, iosf_pci_attach
+};
+
+struct iosf_pci_device {
+ struct pci_matchid id_pm;
+ int id_semaddr;
+};
+
+static const struct iosf_pci_device iosf_pci_devices[] = {
+ { { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_BAYTRAIL_HB }, 0x7 },
+ { { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_BSW_HB }, 0x10e },
+ /* Quark X1000, -1 */
+ /* Tangier, -1 */
+};
+
+static const struct iosf_pci_device *
+iosf_pci_device_match(struct pci_attach_args *pa)
+{
+ pci_vendor_id_t vid = PCI_VENDOR(pa->pa_id);
+ pci_product_id_t pid = PCI_PRODUCT(pa->pa_id);
+ const struct iosf_pci_device *id;
+ size_t i;
+
+ for (i = 0; i < nitems(iosf_pci_devices); i++) {
+ id = &iosf_pci_devices[i];
+ if (id->id_pm.pm_vid == vid && id->id_pm.pm_pid == pid)
+ return (id);
+ }
+
+ return (NULL);
+}
+
+static int
+iosf_pci_match(struct device *parent, void *match, void *aux)
+{
+ struct pci_attach_args *pa = aux;
+
+ if (iosf_pci_device_match(pa) != NULL) {
+ /* match higher than pchb(4) */
+ return (2);
+ }
+
+ return (0);
+}
+
+static void
+iosf_pci_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct iosf_pci_softc *sc = (struct iosf_pci_softc *)self;
+ struct pci_attach_args *pa = aux;
+ const struct iosf_pci_device *id = iosf_pci_device_match(pa);
+
+ sc->sc_pc = pa->pa_pc;
+ sc->sc_pcitag = pa->pa_tag;
+
+ printf(": mbi\n");
+
+ sc->sc_mbi.mbi_dev = self;
+ sc->sc_mbi.mbi_prio = 2; /* prefer pci over acpi ops */
+ sc->sc_mbi.mbi_semaddr = id->id_semaddr;
+ sc->sc_mbi.mbi_mdr_rd = iosf_pci_mbi_mdr_rd;
+ sc->sc_mbi.mbi_mdr_wr = iosf_pci_mbi_mdr_wr;
+
+ iosf_mbi_attach(&sc->sc_mbi);
+}
+
+/*
+ * mbi mdr pciconf operations
+ */
+
+#define IOSF_PCI_MBI_MCR 0xd0
+#define IOSF_PCI_MBI_MDR 0xd4
+#define IOSF_PCI_MBI_MCRX 0xd8
+
+static uint32_t
+iosf_pci_mbi_mdr_rd(struct iosf_mbi *mbi, uint32_t mcr, uint32_t mcrx)
+{
+ struct iosf_pci_softc *sc = (struct iosf_pci_softc *)mbi->mbi_dev;
+
+ if (mcrx != 0) {
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag,
+ IOSF_PCI_MBI_MCRX, mcrx);
+ }
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, IOSF_PCI_MBI_MCR, mcr);
+
+ return (pci_conf_read(sc->sc_pc, sc->sc_pcitag, IOSF_PCI_MBI_MDR));
+}
+
+static void
+iosf_pci_mbi_mdr_wr(struct iosf_mbi *mbi, uint32_t mcr, uint32_t mcrx,
+ uint32_t mdr)
+{
+ struct iosf_pci_softc *sc = (struct iosf_pci_softc *)mbi->mbi_dev;
+
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, IOSF_PCI_MBI_MDR, mdr);
+
+ if (mcrx != 0) {
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag,
+ IOSF_PCI_MBI_MCRX, mcrx);
+ }
+
+ pci_conf_write(sc->sc_pc, sc->sc_pcitag, IOSF_PCI_MBI_MCR, mcr);
+}