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
This commit is contained in:
Abdelkader Boudih committed 2026-10-19 16:15:09 +01:00
1 parent b37e8ffbd9
commit 6690cbdc64
3 files changed
+50 -21

No files matched your search

+35
View File
@@ -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_ */
+7 -8
View File
@@ -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);
+8 -13
View File
@@ -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);