https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=298558

            Bug ID: 298558
           Summary: ig4(4): ACPI-enumerated Intel LPSS I2C controllers
                    never work on Haswell/Broadwell (D3 at attach, wrong
                    version, gated functional clock)
           Product: Base System
           Version: 15.1-RELEASE
          Hardware: amd64
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: kern
          Assignee: [email protected]
          Reporter: [email protected]

Created attachment 274793
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=274793&action=edit
ig4: bring ACPI-enumerated LPSS controllers out of D3 and ungate their clock

On Haswell/Broadwell laptops whose LPSS is enumerated through ACPI rather
than PCI, ig4iic never attaches, so every device behind those I2C buses is
lost. On a Dell XPS 13 9343 this hides the I2C HID touchpad (DLL0665,
Synaptics 06CB:76AD), leaving only the PS/2 fallback, which does not
survive S3 resume.

Three independent defects, all on the ACPI attach path.


1. THE CONTROLLER IS LEFT IN D3

ig4iic_acpi_attach() never runs _PS0. Firmware on this machine leaves both
LPSS I2C functions in D3hot, so all registers read as 0xffffffff and attach
fails:

    ig4iic0: <Designware I2C Controller> iomem 0xfe103000-0xfe103fff irq 7 on
acpi0
    ig4iic0: controller error during attach-1
    device_attach: ig4iic0 attach returned 6

PCI config space of the I2C1 function (8086:9ce2, mapped at 0xfe106000),
PMCSR at offset 0x84, read from /dev/mem right after boot:

    0xfe106000+0x000 = 0x9ce28086
    0xfe106000+0x084 = 0x0000000b      /* PowerState = D3hot */

Clearing the low two bits, which is what the DSDT _PS0 -> LPD0 does, makes
the registers readable and ig4iic_attach() succeed. The PCI attach path
does not need this, which is why the gap survived.


2. BROADWELL IS TREATED AS AN ATOM SOC

ig4iic_acpi_attach() assigns IG4_ATOM to every HID except APMC0D0F:

    if (strcmp(str, "APMC0D0F") == 0) {
            sc->version = IG4_EMAG;
    } else {
            /* All the other HIDs matched are Atom SOCs. */
            sc->version = IG4_ATOM;
    }

INT33C2/INT33C3 (Lynx Point-LP) and INT3432/INT3433 (Wildcat Point-LP) are
the same hardware that ig4_pci.c maps to IG4_HASWELL:

    { PCI_CHIP_LYNXPT_LP_I2C_1, "Intel Lynx Point-LP I2C Controller-1",
IG4_HASWELL},
    { PCI_CHIP_LYNXPT_LP_I2C_2, "Intel Lynx Point-LP I2C Controller-2",
IG4_HASWELL},

The version selects, among other things, whether IG4_GENERAL_SWMODE is
programmed and which FIFO and timing parameters are used.


3. THE LPSS FUNCTIONAL CLOCK IS LEFT GATED

Nothing in the driver sets bit 0 of IG4_REG_CLK_PARMS (0x800). With the
clock gated the controller accepts writes into the TX FIFO but never drives
the bus, so every transfer ends in IIC_ETIMEOUT and iichid probe fails
silently. Registers with the controller enabled, target address programmed
and a transfer pending:

    0xfe105000+0x070 (IC_STATUS)      = 0x00000000   /* no activity */
    0xfe105000+0x074 (TXFLR)          = 0x00000020   /* TX FIFO full */
    0xfe105000+0x034 (RAW_INTR_STAT)  = 0x00000000
    0xfe105000+0x800 (CLK_PARMS)      = 0x00000000

After setting bit 0 of CLK_PARMS, with nothing else changed:

    0xfe105000+0x070 = 0x0000000e
    0xfe105000+0x074 = 0x00000000     /* FIFO drained */
    0xfe105000+0x034 = 0x00000714     /* STOP_DET, ACTIVITY, TX_EMPTY, RX_FULL
*/

and the touchpad answers a HID-over-I2C descriptor read at 0x2c:

    1e 00 00 01 09 02 21 00 24 00 3c 00 25 00 17 00 22 00 23 00 cb 06 ad 76
    06 00 00 00 00 00
    wHIDDescLength=30 bcdVersion=0x0100 wReportDescLength=521
    wMaxInputLength=60 VID=0x06cb PID=0x76ad

Linux does the same ungating for these parts in drivers/acpi/acpi_lpss.c
(lpt_i2c_dev_desc, LPSS_CLK_GATE, prv_offset = 0x800):
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/acpi/acpi_lpss.c

A side effect of the gated clock: the controller raises no interrupts at
all. Before the patch vmstat -i reported "irq7: ig4iic0+ 0"; transfers on
the bus that did attach only made progress because wait_intr() re-reads the
status registers every 10 ms. After the patch the counter increases
normally. This also explains intermittent "codec: I2C read failed: 60"
errors from an out-of-tree Intel SST audio driver sharing I2C0 on the same
machine.


STEPS TO REPRODUCE

1. Boot FreeBSD 15.1 on a Broadwell-U laptop whose LPSS is in ACPI mode
   (Dell XPS 13 9343, BIOS A20; INT3432 and INT3433 present in the DSDT).
2. dmesg shows "controller error during attach-1" for both controllers.
3. No iicbus is created, so the I2C HID touchpad (_SB.PCI0.I2C1.TPD8,
   _HID DLL0665, _CID PNP0C50, address 0x2c) is never probed.


FIX

Attached patch, against sys/dev/ichiic:

- ig4_acpi.c: call acpi_set_powerstate(dev, ACPI_STATE_D0) before mapping
  the registers, and map INT33C2, INT33C3, INT3432 and INT3433 to
  IG4_HASWELL instead of IG4_ATOM.
- ig4_iic.c: in ig4iic_set_config(), ungate the functional clock for
  IG4_HASWELL by setting bit 0 of IG4_REG_CLK_PARMS when clear. Doing it
  there also covers the resume path.
- ig4_reg.h: add IG4_CLK_PARMS_EN.


TEST RESULT

Same machine, patched module, no manual steps:

    ig4iic1: <Designware I2C Controller> iomem 0xfe105000-0xfe105fff irq 7 on
acpi0
    iicbus7: <Philips I2C bus (ACPI-hinted)> on ig4iic1
    iicbus7: <unknown card> at addr 0x2c
    iichid0: <DLL0665:00 06CB:76AD I2C HID device> at addr 0x2c irq 39 on
iicbus7
    hidbus1: <HID bus> on iichid0
    hmt1: <DLL0665:00 06CB:76AD TouchPad> on hidbus1
    hmt1: Multitouch touchpad with 0 external buttons, click-pad
    hmt1: 3 contacts with [C] properties. Report range [0:0] - [1216:680]
    hms0: <DLL0665:00 06CB:76AD Mouse> on hidbus1

The touchpad works, multi-touch included, and keeps working across an S3
suspend/resume cycle. The PS/2 path on this machine does not:

    atkbdc0: resume: selftest=1 cmdbyte=0x47 auxcmd=1 auxport=0 reset=0
tries=60
    psm0: failed to enable the aux device.
    psm0: the aux device has gone! (reinitialize).

Tested only on Broadwell-U (INT3432, INT3433). The INT33C2/INT33C3 mapping
follows the PCI table but was not verified on hardware.


RELATED

bug 275115 (ig4(4): Intel Ice Lake I2C not recognized), and the older
bug 245654 and bug 240485, report the same user-visible symptom - a
touchpad missing because ig4 does not bring up the controller - but a
different cause: the controller ID was not in the driver's tables, so it
never probed. Here the controller probes and attaches, and fails
afterwards. The _PS0 part of this patch does not depend on the generation
and may matter on those machines too, since ACPI enumeration is where the
D3 assumption breaks.


UNRELATED OBSERVATION

atkbdc(4) has no device_resume method; it relies on bus_generic_resume, so
the i8042 is never reconfigured after S3 while its children immediately
start talking to it. Not the cause of this bug and not touched by this
patch, but worth a separate report.

-- 
You are receiving this mail because:
You are the assignee for the bug.

Reply via email to