git: e75f61962ca4 - main - ig4(4): fix attach of ACPI-enumerated LPSS controllers
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 17 Sep 2026 09:10:09 UTC
The branch main has been updated by wulf:
URL: https://cgit.FreeBSD.org/src/commit/?id=e75f61962ca47f0b0ae4aed89c8416e6544d9845
commit e75f61962ca47f0b0ae4aed89c8416e6544d9845
Author: Please <please@forget.me.uk>
AuthorDate: 2026-09-17 09:08:43 +0000
Commit: Vladimir Kondratyev <wulf@FreeBSD.org>
CommitDate: 2026-09-17 09:08:43 +0000
ig4(4): fix attach of ACPI-enumerated LPSS controllers
Intel LPSS I2C controllers enumerated through ACPI rather than PCI never
attach on Haswell and Broadwell, so every device behind those buses is
lost. On a Dell XPS 13 9343 that hides the I2C HID touchpad and leaves
only the PS/2 fallback, which the firmware does not restore after S3.
Three causes, all on the ACPI path:
Firmware may leave an LPSS function in D3, where its registers read as
all-ones and set_controller() fails with "controller error during
attach-1". Run _PS0 before mapping them. The PCI path does not need
this, which is why the gap went unnoticed.
INT33C2, INT33C3, INT3432 and INT3433 are Lynx Point-LP and Wildcat
Point-LP, which ig4_pci.c already classifies as IG4_HASWELL; the ACPI
path called everything but APMC0D0F an Atom SoC.
The functional clock stays gated until bit 0 of IG4_REG_CLK_PARMS is
set. Until then the controller accepts writes into the TX FIFO, never
drives the bus, raises no interrupts, and every transfer ends in
IIC_ETIMEOUT. Linux ungates the same bit in acpi_lpss.c. Doing it in
ig4iic_set_config() covers resume as well as attach.
With all three in place the touchpad attaches as iichid0/hmt1 with
multi-touch and survives suspend and resume.
PR: 298558
Tested by: Please (XPS 13 9343, Broadwell-U, 15.1-RELEASE-p3)
Reviewed by: wulf
MFC after: 1 week
---
sys/dev/ichiic/ig4_acpi.c | 10 ++++++++++
sys/dev/ichiic/ig4_iic.c | 11 +++++++++++
sys/dev/ichiic/ig4_reg.h | 1 +
3 files changed, 22 insertions(+)
diff --git a/sys/dev/ichiic/ig4_acpi.c b/sys/dev/ichiic/ig4_acpi.c
index 1275790a4412..10540d2bd889 100644
--- a/sys/dev/ichiic/ig4_acpi.c
+++ b/sys/dev/ichiic/ig4_acpi.c
@@ -95,10 +95,20 @@ ig4iic_acpi_attach(device_t dev)
return (error);
if (strcmp(str, "APMC0D0F") == 0) {
sc->version = IG4_EMAG;
+ } else if (strcmp(str, "INT33C2") == 0 || strcmp(str, "INT33C3") == 0 ||
+ strcmp(str, "INT3432") == 0 || strcmp(str, "INT3433") == 0) {
+ /* Lynx Point-LP / Wildcat Point-LP LPSS in ACPI mode. */
+ sc->version = IG4_HASWELL;
} else {
/* All the other HIDs matched are Atom SOCs. */
sc->version = IG4_ATOM;
}
+ /*
+ * Firmware may leave LPSS functions in D3 (e.g. Dell XPS 13 9343):
+ * the registers then read as all-ones and attach fails. Run _PS0.
+ */
+ acpi_set_powerstate(dev, ACPI_STATE_D0);
+
sc->regs_rid = 0;
sc->regs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&sc->regs_rid, RF_ACTIVE);
diff --git a/sys/dev/ichiic/ig4_iic.c b/sys/dev/ichiic/ig4_iic.c
index 161a940c5e7a..a326d487e1d9 100644
--- a/sys/dev/ichiic/ig4_iic.c
+++ b/sys/dev/ichiic/ig4_iic.c
@@ -933,6 +933,17 @@ ig4iic_set_config(ig4iic_softc_t *sc, bool reset, bool force_restore)
reset = true;
}
+ /*
+ * Haswell/Broadwell LPSS in ACPI mode can come up with the functional
+ * clock gated. The controller then accepts FIFO writes but never
+ * drives the bus and every transfer times out.
+ */
+ if (sc->version == IG4_HASWELL) {
+ v = reg_read(sc, IG4_REG_CLK_PARMS);
+ if ((v & IG4_CLK_PARMS_EN) == 0)
+ reg_write(sc, IG4_REG_CLK_PARMS, v | IG4_CLK_PARMS_EN);
+ }
+
if ((sc->version == IG4_HASWELL || sc->version == IG4_ATOM) && reset) {
reg_write(sc, IG4_REG_RESETS_HSW, IG4_RESETS_ASSERT_HSW);
reg_write(sc, IG4_REG_RESETS_HSW, IG4_RESETS_DEASSERT_HSW);
diff --git a/sys/dev/ichiic/ig4_reg.h b/sys/dev/ichiic/ig4_reg.h
index 35342f7d79aa..435475465e6f 100644
--- a/sys/dev/ichiic/ig4_reg.h
+++ b/sys/dev/ichiic/ig4_reg.h
@@ -124,6 +124,7 @@
#define IG4_REG_DEVIDLE_CTRL 0x024C /* RW Device Control */
/* Available at least on Atom SoCs */
#define IG4_REG_CLK_PARMS 0x0800 /* RW Clock Parameters */
+#define IG4_CLK_PARMS_EN 0x00000001 /* functional clock ungated */
/* Available at least on Atom SoCs and Haswell mobile */
#define IG4_REG_RESETS_HSW 0x0804 /* RW Reset Register */
#define IG4_REG_GENERAL 0x0808 /* RW General Register */