git: 6690cbdc649e - main - intel: add a shared header for the LPSS private registers

From: Abdelkader Boudih <seuros_at_FreeBSD.org>
Date: Mon, 19 Oct 2026 15:15:27 UTC
The branch main has been updated by seuros:

URL: https://cgit.FreeBSD.org/src/commit/?id=6690cbdc649e7d0b23d96e1490b72068fc791a95

commit 6690cbdc649e7d0b23d96e1490b72068fc791a95
Author:     Abdelkader Boudih <seuros@FreeBSD.org>
AuthorDate: 2026-10-19 15:15:09 +0000
Commit:     Abdelkader Boudih <seuros@FreeBSD.org>
CommitDate: 2026-10-19 15:15:09 +0000

    intel: add a shared header for the LPSS private registers
    
    The Intel Low Power Subsystem wraps its I2C, SPI and UART functions in a
    block of private registers that control the functional clock and the
    function and DMA resets.
    
    Refactored to use a single header
    
    Reviewed by:    imp, adrian
    Differential Revision:  https://reviews.freebsd.org/D60859
---
 sys/dev/intel/lpss.h        | 35 +++++++++++++++++++++++++++++++++++
 sys/dev/intel/spi.c         | 15 +++++++--------
 sys/dev/uart/uart_bus_pci.c | 21 ++++++++-------------
 3 files changed, 50 insertions(+), 21 deletions(-)

diff --git a/sys/dev/intel/lpss.h b/sys/dev/intel/lpss.h
new file mode 100644
index 000000000000..688195048cb6
--- /dev/null
+++ b/sys/dev/intel/lpss.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2026 Abdelkader Boudih <seuros@FreeBSD.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef _DEV_INTEL_LPSS_H_
+#define	_DEV_INTEL_LPSS_H_
+
+/*
+ * Intel LPSS private registers, shared by the I2C, SPI and UART functions.
+ * Offsets are relative to the private block, which sits at one of these
+ * bases in the function's first memory BAR.
+ */
+#define	LPSS_PRIV_LPT		0x800	/* Lynx Point, Atom SoCs */
+#define	LPSS_PRIV_BYT		0x400	/* Bay Trail, Braswell */
+#define	LPSS_PRIV_SPT		0x200	/* Sunrise Point and later */
+
+/* CLK - functional clock gate and M/N divider; rate is reference * M / N. */
+#define	LPSS_PRIV_CLK		0x00
+#define	 LPSS_PRIV_CLK_EN		(1U << 0)
+#define	 LPSS_PRIV_CLK_M_SHIFT		1
+#define	 LPSS_PRIV_CLK_N_SHIFT		16
+#define	 LPSS_PRIV_CLK_MN_MASK		0x7fff
+#define	 LPSS_PRIV_CLK_UPDATE		(1U << 31)	/* latch M and N */
+#define	 LPSS_PRIV_CLK_MN(m, n)						\
+	((((n) & LPSS_PRIV_CLK_MN_MASK) << LPSS_PRIV_CLK_N_SHIFT) |	\
+	 (((m) & LPSS_PRIV_CLK_MN_MASK) << LPSS_PRIV_CLK_M_SHIFT))
+
+/* RESETS - function and DMA resets; polarity is inverted from SPT onwards. */
+#define	LPSS_PRIV_RESETS	0x04
+#define	 LPSS_PRIV_RESETS_FUNC		0x3
+#define	 LPSS_PRIV_RESETS_IDMA		(1U << 2)
+
+#endif /* _DEV_INTEL_LPSS_H_ */
diff --git a/sys/dev/intel/spi.c b/sys/dev/intel/spi.c
index 9a0d4305227d..fca74b2f96cc 100644
--- a/sys/dev/intel/spi.c
+++ b/sys/dev/intel/spi.c
@@ -42,6 +42,7 @@
 #include <dev/spibus/spi.h>
 #include <dev/spibus/spibusvar.h>
 
+#include <dev/intel/lpss.h>
 #include <dev/intel/spi.h>
 
 /**
@@ -123,9 +124,7 @@
 #define	 SPI_CS_CTRL_HW_MODE			(1 << 0)
 #define	 SPI_CS_CTRL_CS_HIGH			(1 << 1)
 
-#define	INTELSPI_RESETS			0x204
-#define	 INTELSPI_RESET_HOST			(1 << 0) | (1 << 1)
-#define	 INTELSPI_RESET_DMA			(1 << 2)
+#define	INTELSPI_RESETS			(LPSS_PRIV_SPT + LPSS_PRIV_RESETS)
 
 /* Same order as intelspi_vers */
 static const struct intelspi_info {
@@ -133,19 +132,19 @@ static const struct intelspi_info {
 	uint32_t reg_cs_ctrl;
 } intelspi_infos[] = {
 	[SPI_BAYTRAIL] = {
-		.reg_lpss_base = 0x400,
+		.reg_lpss_base = LPSS_PRIV_BYT,
 		.reg_cs_ctrl = 0x18,
 	},
 	[SPI_BRASWELL] = {
-		.reg_lpss_base = 0x400,
+		.reg_lpss_base = LPSS_PRIV_BYT,
 		.reg_cs_ctrl = 0x18,
 	},
 	[SPI_LYNXPOINT] = {
-		.reg_lpss_base = 0x800,
+		.reg_lpss_base = LPSS_PRIV_LPT,
 		.reg_cs_ctrl = 0x18,
 	},
 	[SPI_SUNRISEPOINT] = {
-		.reg_lpss_base = 0x200,
+		.reg_lpss_base = LPSS_PRIV_SPT,
 		.reg_cs_ctrl = 0x24,
 	},
 };
@@ -509,7 +508,7 @@ intelspi_attach(device_t dev)
 	/* Release LPSS reset */
 	if (sc->sc_vers == SPI_SUNRISEPOINT)
 		INTELSPI_WRITE(sc, INTELSPI_RESETS,
-		    (INTELSPI_RESET_HOST | INTELSPI_RESET_DMA));
+		    LPSS_PRIV_RESETS_FUNC | LPSS_PRIV_RESETS_IDMA);
 
 	sc->sc_irq_res = bus_alloc_resource_any(sc->sc_dev,
 	    SYS_RES_IRQ, &sc->sc_irq_rid, RF_ACTIVE | RF_SHAREABLE);
diff --git a/sys/dev/uart/uart_bus_pci.c b/sys/dev/uart/uart_bus_pci.c
index 39d3b1323bed..bb7e58a19f99 100644
--- a/sys/dev/uart/uart_bus_pci.c
+++ b/sys/dev/uart/uart_bus_pci.c
@@ -35,6 +35,7 @@
 #include <sys/rman.h>
 #include <machine/resource.h>
 
+#include <dev/intel/lpss.h>
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcireg.h>
 
@@ -85,12 +86,8 @@ struct pci_unique_id {
 #define PCI_INTEL_LPSS	0x20000000
 #define PCI_RID_MASK	0x0000ffff
 
-/* Intel LPSS private registers, relative to BAR0. */
-#define LPSS_CLK	0x200
-#define LPSS_CLK_EN		(1U << 0)
-#define LPSS_CLK_UPDATE		(1U << 31)
-#define LPSS_RESETS	0x204
-#define LPSS_RESETS_FUNC	0x3
+#define LPSS_CLK	(LPSS_PRIV_SPT + LPSS_PRIV_CLK)
+#define LPSS_RESETS	(LPSS_PRIV_SPT + LPSS_PRIV_RESETS)
 
 static const struct pci_id pci_ns8250_ids[] = {
 { 0x1028, 0x0008, 0xffff, 0, "Dell Remote Access Card III", 0x14,
@@ -258,19 +255,17 @@ uart_pci_lpss_setup(struct resource *res)
 		return (ENXIO);
 
 	resets = bus_read_4(res, LPSS_RESETS);
-	bus_write_4(res, LPSS_RESETS, resets | LPSS_RESETS_FUNC);
+	bus_write_4(res, LPSS_RESETS, resets | LPSS_PRIV_RESETS_FUNC);
 	bus_barrier(res, LPSS_RESETS, sizeof(uint32_t),
 	    BUS_SPACE_BARRIER_WRITE);
 
-	/*
-	 * Divide the 100 MHz reference clock down to 44.2368 MHz.  Bits
-	 * 15:1 hold M and bits 30:16 hold N, giving a rate of ref * M / N.
-	 */
-	clk = (15625U << 16) | (6912U << 1);
+	/* Divide the 100 MHz reference clock down to 44.2368 MHz. */
+	clk = LPSS_PRIV_CLK_MN(6912, 15625);
 	bus_write_4(res, LPSS_CLK, clk);
 	bus_barrier(res, LPSS_CLK, sizeof(uint32_t),
 	    BUS_SPACE_BARRIER_WRITE);
-	bus_write_4(res, LPSS_CLK, clk | LPSS_CLK_EN | LPSS_CLK_UPDATE);
+	bus_write_4(res, LPSS_CLK,
+	    clk | LPSS_PRIV_CLK_EN | LPSS_PRIV_CLK_UPDATE);
 	(void)bus_read_4(res, LPSS_CLK);
 
 	return (0);