diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2023-04-23 00:20:27 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2023-04-23 00:20:27 +0000 |
commit | dab0a5ce68c5fdc2ae6c7a3eac21718d7eb9cf03 (patch) | |
tree | 590e6e1e65745d9f430580e41c44ae3b69a88fd8 /sys/dev/pci | |
parent | a4a7cdae255fbb485a0a21acb41acac11da96c2c (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.pci | 6 | ||||
-rw-r--r-- | sys/dev/pci/iosf_pci.c | 157 |
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); +} |