Index | Thread | Search

From:
Gregory Norton <gregory.norton@me.com>
Subject:
ispi_pci: enable support for 9-series pch
To:
tech@openbsd.org
Date:
Wed, 10 Jun 2026 20:25:15 -0400

Download raw body.

Thread
Hi all, first patch so might be rough.

I've added support for the SPI part of the intel 9-series PCH as found 
on the 2015 macbook8,1. When used with the aplhidev patches from Joshua 
Stein, it enables the keyboard and trackpad to function (albeit some 
quirks with backlight).

The 9-series (and 8-series) chipsets didn't yet support a dedicated 
reset register or the ability to check the device's capabilities. 
Referring to the source for intel_spi in FreeBSD, looks like they do a 
similar skip over those checks for older models.

These changes should also open the path for 8-series, braswell, and 
baytrail chipsets if the need arises.

- Greg


diff --git sys/dev/ic/ispivar.h sys/dev/ic/ispivar.h
index 6131616b5..8d44bda97 100644
--- sys/dev/ic/ispivar.h
+++ sys/dev/ic/ispivar.h
@@ -42,6 +42,13 @@
  #define DPRINTF(x)
  #endif

+enum ispi_version {
+	SPI_BAYTRAIL,
+	SPI_BRASWELL,
+	SPI_LYNXPOINT,
+	SPI_SUNRISEPOINT
+};
+
  struct ispi_softc {
  	struct device		sc_dev;

@@ -69,6 +76,7 @@ struct ispi_softc {
  	struct aml_node		*sc_devnode;
  #endif
  	u_int32_t		sc_caps;
+	enum ispi_version	sc_vers;
  };

  void		ispi_init(struct ispi_softc *sc);
diff --git sys/dev/pci/ispi_pci.c sys/dev/pci/ispi_pci.c
index c77e67180..a23946336 100644
--- sys/dev/pci/ispi_pci.c
+++ sys/dev/pci/ispi_pci.c
@@ -44,6 +44,7 @@ const struct cfattach ispi_pci_ca = {
  };

  const struct pci_matchid ispi_pci_ids[] = {
+	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_9SERIES_LP_SPI },
  	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_100SERIES_LP_SPI_3 },
  };

@@ -62,26 +63,34 @@ ispi_pci_attach(struct device *parent, struct device 
*self, void *aux)
  	pci_intr_handle_t ih;
  	const char *intrstr = NULL;
  	uint8_t type;
+	int mtype;

  	memcpy(&sc->sc_paa, pa, sizeof(sc->sc_paa));

  	pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0);

-	if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_MEM_TYPE_64BIT, 0,
+	mtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, PCI_MAPREG_START);
+	if (pci_mapreg_map(pa, PCI_MAPREG_START, mtype, 0,
  	    &sc->sc_iot, &sc->sc_ioh, NULL, &iosize, 0)) {
  		printf(": can't map mem space\n");
  		return;
  	}

-	sc->sc_caps = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LPSS_CAPS);
-	type = (sc->sc_caps & LPSS_CAPS_TYPE_MASK) >> LPSS_CAPS_TYPE_SHIFT;
-	if (type != LPSS_CAPS_TYPE_SPI) {
-		printf(": type %d not supported\n", type);
-		return;
-	}
-
  	switch (PCI_PRODUCT(pa->pa_id)) {
+	case PCI_PRODUCT_INTEL_9SERIES_LP_SPI:
+		sc->sc_vers = SPI_LYNXPOINT;
+
+		/* SPT */
+		sc->sc_lpss_reg_offset = 0x800;
+		sc->sc_reg_cs_ctrl = 0x18;
+		sc->sc_rx_threshold = 2;
+		sc->sc_tx_threshold = 32;
+		sc->sc_tx_threshold_hi = 56;
+		sc->sc_ssp_clk = 9600000;
+		break;
  	case PCI_PRODUCT_INTEL_100SERIES_LP_SPI_3:
+		sc->sc_vers = SPI_SUNRISEPOINT;
+
  		/* SPT */
  		sc->sc_lpss_reg_offset = 0x200;
  		sc->sc_reg_cs_ctrl = 0x24;
@@ -96,9 +105,27 @@ ispi_pci_attach(struct device *parent, struct device 
*self, void *aux)
  		return;
  	}

-	/* un-reset - page 958 */
-	bus_space_write_4(sc->sc_iot, sc->sc_ioh, LPSS_RESETS,
-	    (LPSS_RESETS_FUNC | LPSS_RESETS_IDMA));
+	sc->sc_caps = 0;
+	if (sc->sc_vers == SPI_SUNRISEPOINT) {
+		/*
+		 * sunrise point supports capability validation
+		 * and includes a dedicated reset register
+		 */
+
+		/* validate capabilities */
+		sc->sc_caps = bus_space_read_4(sc->sc_iot, sc->sc_ioh, LPSS_CAPS);
+		type = (sc->sc_caps & LPSS_CAPS_TYPE_MASK) >> LPSS_CAPS_TYPE_SHIFT;
+		if (type != LPSS_CAPS_TYPE_SPI) {
+			printf(": type %d not supported\n", type);
+			bus_space_unmap(sc->sc_iot, sc->sc_ioh, iosize);
+			return;
+		}
+
+		/* un-reset - page 958 */
+		if (sc->sc_vers == SPI_SUNRISEPOINT)
+			bus_space_write_4(sc->sc_iot, sc->sc_ioh, LPSS_RESETS,
+				(LPSS_RESETS_FUNC | LPSS_RESETS_IDMA));
+	}

  	/* install interrupt handler */
  	if (pci_intr_map(&sc->sc_paa, &ih) == 0) {