* [PATCH 1/2] pinctrl-amd: enable IRQ for WACF2200 touchscreen on Lenovo Yoga 7 14AGP11
2026-05-12 7:31 [PATCH " Hardik Prakash
@ 2026-05-12 7:31 ` Hardik Prakash
2026-05-12 8:47 ` Linus Walleij
` (2 more replies)
0 siblings, 3 replies; 15+ messages in thread
From: Hardik Prakash @ 2026-05-12 7:31 UTC (permalink / raw)
To: linux-gpio, linux-i2c; +Cc: linus.walleij, wsa, Hardik Prakash
On Lenovo Yoga 7 14AGP11 (83TD), the WACF2200 touchscreen controller
is wired via I2C2 (AMDI0010:02) with its interrupt on GPIO pin 157
(confirmed via ACPI _CRS GpioInt decode). After amd_gpio_irq_init()
clears all GPIO interrupts at boot, pin 157 is never re-enabled,
preventing the touchscreen from signalling the driver.
Windows keeps GPIO 157 INTERRUPT_ENABLE (bit 11) and INTERRUPT_MASK
(bit 12) set after initialisation. Add a DMI quirk to restore these
bits after amd_gpio_irq_init() on this hardware.
Signed-off-by: Hardik Prakash <hardikprakash.official@gmail.com>
---
drivers/pinctrl/pinctrl-amd.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index e3128b0045d22..64315b0edf2a6 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/pinctrl/pinconf.h>
+#include <linux/dmi.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/string_choices.h>
@@ -39,6 +40,39 @@
static struct amd_gpio *pinctrl_dev;
#endif
+static const struct dmi_system_id amd_gpio_quirk_yoga7_14agp11[] = {
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "83TD"),
+ DMI_MATCH(DMI_BOARD_NAME, "LNVNB161216"),
+ },
+ },
+ { }
+};
+
+static void amd_gpio_apply_quirks(struct amd_gpio *gpio_dev)
+{
+ const unsigned int pin = 157; /* WACF2200 GpioInt per ACPI _CRS */
+ unsigned long flags;
+ u32 reg;
+
+ if (!dmi_check_system(amd_gpio_quirk_yoga7_14agp11))
+ return;
+ if (pin >= gpio_dev->gc.ngpio)
+ return;
+
+ raw_spin_lock_irqsave(&gpio_dev->lock, flags);
+ reg = readl(gpio_dev->base + pin * 4);
+ reg |= BIT(INTERRUPT_ENABLE_OFF) | BIT(INTERRUPT_MASK_OFF);
+ writel(reg, gpio_dev->base + pin * 4);
+ raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
+
+ dev_info(&gpio_dev->pdev->dev,
+ "Enabled IRQ for GPIO %u (Yoga 7 14AGP11 touchscreen)\n",
+ pin);
+}
+
static int amd_gpio_get_direction(struct gpio_chip *gc, unsigned offset)
{
unsigned long flags;
@@ -1219,6 +1253,7 @@ static int amd_gpio_probe(struct platform_device *pdev)
/* Disable and mask interrupts */
amd_gpio_irq_init(gpio_dev);
+ amd_gpio_apply_quirks(gpio_dev);
girq = &gpio_dev->gc.irq;
gpio_irq_chip_set_chip(girq, &amd_gpio_irqchip);
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] pinctrl-amd: enable IRQ for WACF2200 touchscreen on Lenovo Yoga 7 14AGP11
2026-05-12 7:31 ` [PATCH 1/2] pinctrl-amd: enable IRQ for " Hardik Prakash
@ 2026-05-12 8:47 ` Linus Walleij
2026-05-12 10:46 ` Andy Shevchenko
2026-05-13 7:33 ` Linus Walleij
2 siblings, 0 replies; 15+ messages in thread
From: Linus Walleij @ 2026-05-12 8:47 UTC (permalink / raw)
To: Hardik Prakash, Andy Shevchenko, Rafael J. Wysocki,
Mika Westerberg
Cc: linux-gpio, linux-i2c, linus.walleij, wsa
On Tue, May 12, 2026 at 9:32 AM Hardik Prakash
<hardikprakash.official@gmail.com> wrote:
> On Lenovo Yoga 7 14AGP11 (83TD), the WACF2200 touchscreen controller
> is wired via I2C2 (AMDI0010:02) with its interrupt on GPIO pin 157
> (confirmed via ACPI _CRS GpioInt decode). After amd_gpio_irq_init()
> clears all GPIO interrupts at boot, pin 157 is never re-enabled,
> preventing the touchscreen from signalling the driver.
>
> Windows keeps GPIO 157 INTERRUPT_ENABLE (bit 11) and INTERRUPT_MASK
> (bit 12) set after initialisation. Add a DMI quirk to restore these
> bits after amd_gpio_irq_init() on this hardware.
>
> Signed-off-by: Hardik Prakash <hardikprakash.official@gmail.com>
I don't understand DMI quirks.
Andy, Rafael or Mika has to ACK this if I should merge it, otherwise it
looks superficially good.
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] pinctrl-amd: enable IRQ for WACF2200 touchscreen on Lenovo Yoga 7 14AGP11
2026-05-12 7:31 ` [PATCH 1/2] pinctrl-amd: enable IRQ for " Hardik Prakash
2026-05-12 8:47 ` Linus Walleij
@ 2026-05-12 10:46 ` Andy Shevchenko
2026-05-13 7:33 ` Linus Walleij
2 siblings, 0 replies; 15+ messages in thread
From: Andy Shevchenko @ 2026-05-12 10:46 UTC (permalink / raw)
To: Hardik Prakash; +Cc: linux-gpio, linux-i2c, linus.walleij, wsa
On Tue, May 12, 2026 at 01:01:38PM +0530, Hardik Prakash wrote:
> On Lenovo Yoga 7 14AGP11 (83TD), the WACF2200 touchscreen controller
> is wired via I2C2 (AMDI0010:02) with its interrupt on GPIO pin 157
> (confirmed via ACPI _CRS GpioInt decode). After amd_gpio_irq_init()
> clears all GPIO interrupts at boot, pin 157 is never re-enabled,
> preventing the touchscreen from signalling the driver.
>
> Windows keeps GPIO 157 INTERRUPT_ENABLE (bit 11) and INTERRUPT_MASK
> (bit 12) set after initialisation. Add a DMI quirk to restore these
> bits after amd_gpio_irq_init() on this hardware.
Acked-by: Andy Shevchenko <andriy.shevchenko@intel.com>
...
> /* Disable and mask interrupts */
> amd_gpio_irq_init(gpio_dev);
Ideally this should be done as a GPIO driver callback (we have something
like .init_hw() IIRC). But since it's an original code, it may be an exercise
for another day.
> + amd_gpio_apply_quirks(gpio_dev);
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 0/2] Fix WACF2200 touchscreen on Lenovo Yoga 7 14AGP11
@ 2026-05-13 6:13 Hardik Prakash
2026-05-13 6:13 ` [PATCH 1/2] pinctrl-amd: enable IRQ for " Hardik Prakash
` (2 more replies)
0 siblings, 3 replies; 15+ messages in thread
From: Hardik Prakash @ 2026-05-13 6:13 UTC (permalink / raw)
To: linux-gpio, linux-i2c
Cc: linus.walleij, wsa, andriy.shevchenko, Hardik Prakash
The Wacom WACF2200 touchscreen on the Lenovo Yoga 7 14AGP11 (83TD) is
completely non-functional on Linux. The I2C bus (AMDI0010:02) fails with
repeated lost arbitration errors at boot before any driver can probe the
device. The touchscreen works correctly in UEFI and Windows.
Investigation using ACPI _CRS decode and Windows/Linux GPIO register
comparison identified two bugs:
1. GPIO 157 (WACF2200 GpioInt per ACPI _CRS) has INTERRUPT_ENABLE and
INTERRUPT_MASK cleared by amd_gpio_irq_init() and never restored,
preventing the device from signalling the driver. Windows keeps both
bits set after initialisation.
2. i2c_designware probes AMDI0010:02 before pinctrl-amd's probe
completes. A DMI-matched deferral is added to correctly enforce
ordering using device_is_bound() under device_lock().
Patch 1 adds a DMI quirk in pinctrl-amd to restore GPIO 157 interrupt
bits after amd_gpio_irq_init().
Patch 2 adds a probe deferral in i2c-designware-platdrv that correctly
waits for pinctrl-amd to fully complete before AMDI0010:02 is probed,
using acpi_dev_get_first_match_dev() and acpi_get_first_physical_node()
for robust device lookup.
Both patches tested on Lenovo Yoga 7 14AGP11 (83TD), Fedora 44, kernel
7.1.0-rc2+. Touch and stylus fully functional across 4 stable reboots.
v2:
- Patch 2: replace custom HID/UID lookup helpers with
acpi_dev_get_first_match_dev() (Andy Shevchenko)
- Patch 2: use acpi_get_first_physical_node() to get the platform
device for correct device_is_bound() check
- Patch 2: use device_is_bound() under device_lock() with explanatory
comments (Andy Shevchenko)
- Patch 2: fix dev_warn to use dev_name() instead of hardcoded suffix
(Andy Shevchenko)
- Patch 2: fix commit message (removed incorrect "existing" reference)
- Both patches: add Assisted-by tags per coding-assistants.rst
- Patch 1: no functional changes (Acked-by: Andy Shevchenko)
Kernel bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=221494
Related: https://bugzilla.kernel.org/show_bug.cgi?id=221454
drivers/i2c/busses/i2c-designware-platdrv.c | 75 +++++++++++++++++++++
drivers/pinctrl/pinctrl-amd.c | 35 ++++++++++
2 files changed, 110 insertions(+)
--
2.54.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/2] pinctrl-amd: enable IRQ for WACF2200 touchscreen on Lenovo Yoga 7 14AGP11
2026-05-13 6:13 [PATCH v2 0/2] Fix WACF2200 touchscreen on Lenovo Yoga 7 14AGP11 Hardik Prakash
@ 2026-05-13 6:13 ` Hardik Prakash
2026-05-13 7:36 ` Linus Walleij
2026-05-13 17:23 ` Mario Limonciello
2026-05-13 6:13 ` [PATCH 2/2] i2c: designware: fix probe ordering for AMD GPIO " Hardik Prakash
2026-05-13 17:03 ` [PATCH v2 0/2] Fix WACF2200 touchscreen " Andy Shevchenko
2 siblings, 2 replies; 15+ messages in thread
From: Hardik Prakash @ 2026-05-13 6:13 UTC (permalink / raw)
To: linux-gpio, linux-i2c
Cc: linus.walleij, wsa, andriy.shevchenko, Hardik Prakash
On Lenovo Yoga 7 14AGP11 (83TD), the WACF2200 touchscreen controller
is wired via I2C2 (AMDI0010:02) with its interrupt on GPIO pin 157
(confirmed via ACPI _CRS GpioInt decode). After amd_gpio_irq_init()
clears all GPIO interrupts at boot, pin 157 is never re-enabled,
preventing the touchscreen from signalling the driver.
Windows keeps GPIO 157 INTERRUPT_ENABLE (bit 11) and INTERRUPT_MASK
(bit 12) set after initialisation. Add a DMI quirk to restore these
bits after amd_gpio_irq_init() on this hardware.
Signed-off-by: Hardik Prakash <hardikprakash.official@gmail.com>
Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: GPT-Codex:gpt-5.2-codex
---
drivers/pinctrl/pinctrl-amd.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index e3128b0045d22..64315b0edf2a6 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/pinctrl/pinconf.h>
+#include <linux/dmi.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/string_choices.h>
@@ -39,6 +40,39 @@
static struct amd_gpio *pinctrl_dev;
#endif
+static const struct dmi_system_id amd_gpio_quirk_yoga7_14agp11[] = {
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "83TD"),
+ DMI_MATCH(DMI_BOARD_NAME, "LNVNB161216"),
+ },
+ },
+ { }
+};
+
+static void amd_gpio_apply_quirks(struct amd_gpio *gpio_dev)
+{
+ const unsigned int pin = 157; /* WACF2200 GpioInt per ACPI _CRS */
+ unsigned long flags;
+ u32 reg;
+
+ if (!dmi_check_system(amd_gpio_quirk_yoga7_14agp11))
+ return;
+ if (pin >= gpio_dev->gc.ngpio)
+ return;
+
+ raw_spin_lock_irqsave(&gpio_dev->lock, flags);
+ reg = readl(gpio_dev->base + pin * 4);
+ reg |= BIT(INTERRUPT_ENABLE_OFF) | BIT(INTERRUPT_MASK_OFF);
+ writel(reg, gpio_dev->base + pin * 4);
+ raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
+
+ dev_info(&gpio_dev->pdev->dev,
+ "Enabled IRQ for GPIO %u (Yoga 7 14AGP11 touchscreen)\n",
+ pin);
+}
+
static int amd_gpio_get_direction(struct gpio_chip *gc, unsigned offset)
{
unsigned long flags;
@@ -1219,6 +1253,7 @@ static int amd_gpio_probe(struct platform_device *pdev)
/* Disable and mask interrupts */
amd_gpio_irq_init(gpio_dev);
+ amd_gpio_apply_quirks(gpio_dev);
girq = &gpio_dev->gc.irq;
gpio_irq_chip_set_chip(girq, &amd_gpio_irqchip);
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 2/2] i2c: designware: fix probe ordering for AMD GPIO on Lenovo Yoga 7 14AGP11
2026-05-13 6:13 [PATCH v2 0/2] Fix WACF2200 touchscreen on Lenovo Yoga 7 14AGP11 Hardik Prakash
2026-05-13 6:13 ` [PATCH 1/2] pinctrl-amd: enable IRQ for " Hardik Prakash
@ 2026-05-13 6:13 ` Hardik Prakash
2026-05-13 17:12 ` Andy Shevchenko
2026-05-13 17:03 ` [PATCH v2 0/2] Fix WACF2200 touchscreen " Andy Shevchenko
2 siblings, 1 reply; 15+ messages in thread
From: Hardik Prakash @ 2026-05-13 6:13 UTC (permalink / raw)
To: linux-gpio, linux-i2c
Cc: linus.walleij, wsa, andriy.shevchenko, Hardik Prakash
On Lenovo Yoga 7 14AGP11 (83TD), the WACF2200 touchscreen fails with
lost arbitration errors on AMDI0010:02 at boot. The root cause is a
probe ordering issue: i2c_designware probes AMDI0010:02 before
pinctrl-amd has finished initialising, so the GPIO 157 interrupt
needed by the touchscreen is not yet enabled.
Add a DMI-matched deferral in dw_i2c_plat_probe() that uses
device_is_bound() under device_lock() to correctly wait until
pinctrl-amd's probe has fully completed. Use acpi_dev_get_first_match_dev()
for robust HID/UID-based GPIO controller lookup instead of string
name matching.
Signed-off-by: Hardik Prakash <hardikprakash.official@gmail.com>
Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: GPT-Codex:gpt-5.2-codex
---
drivers/i2c/busses/i2c-designware-platdrv.c | 75 +++++++++++++++++++++
1 file changed, 75 insertions(+)
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 3351c4a9ef118..35fa4bcafc7ad 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -8,6 +8,7 @@
* Copyright (C) 2007 MontaVista Software Inc.
* Copyright (C) 2009 Provigent Ltd.
*/
+#include <linux/acpi.h>
#include <linux/clk-provider.h>
#include <linux/clk.h>
#include <linux/delay.h>
@@ -86,6 +87,76 @@ static const struct dmi_system_id dw_i2c_hwmon_class_dmi[] = {
{ } /* terminate list */
};
+static const struct dmi_system_id dw_i2c_amd_gpio_defer_dmi[] = {
+ {
+ .ident = "Lenovo Yoga 7 14AGP11",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "83TD"),
+ DMI_MATCH(DMI_BOARD_NAME, "LNVNB161216"),
+ },
+ },
+ { } /* terminate list */
+};
+
+static bool dw_i2c_needs_amd_gpio_dep(struct device *device)
+{
+ struct acpi_device *adev = ACPI_COMPANION(device);
+
+ if (!dmi_check_system(dw_i2c_amd_gpio_defer_dmi))
+ return false;
+ if (!adev)
+ return false;
+
+ return acpi_dev_hid_uid_match(adev, "AMDI0010", "2");
+}
+
+static int dw_i2c_defer_for_amd_gpio(struct device *device)
+{
+ struct acpi_device *gpio_adev;
+ struct device *gpio_dev;
+
+ if (!dw_i2c_needs_amd_gpio_dep(device))
+ return 0;
+
+ /*
+ * Find the AMD GPIO controller by HID/UID and get its physical
+ * platform device. We need the platform device (not the ACPI device)
+ * because that is what gets bound by the amd_gpio driver.
+ */
+ gpio_adev = acpi_dev_get_first_match_dev("AMDI0030", "0", -1);
+ if (!gpio_adev)
+ return -EPROBE_DEFER;
+
+ gpio_dev = acpi_get_first_physical_node(gpio_adev);
+ acpi_dev_put(gpio_adev);
+ if (!gpio_dev)
+ return -EPROBE_DEFER;
+
+ /*
+ * Check that amd_gpio probe has fully completed, not just that the
+ * driver pointer is set. The driver pointer is assigned before probe
+ * finishes, so checking it would allow i2c_designware to probe before
+ * the GPIO IRQ quirk in amd_gpio_probe() has run.
+ */
+ device_lock(gpio_dev);
+ if (!device_is_bound(gpio_dev)) {
+ device_unlock(gpio_dev);
+ return -EPROBE_DEFER;
+ }
+ device_unlock(gpio_dev);
+
+ /*
+ * Create a device link so the driver core enforces probe/remove
+ * ordering between this I2C controller and the GPIO controller.
+ */
+ if (!device_link_add(device, gpio_dev, DL_FLAG_AUTOREMOVE_CONSUMER))
+ dev_warn(device, "failed to add device link to %s\n",
+ dev_name(gpio_dev));
+
+ return 0;
+}
+
static const struct i2c_dw_semaphore_callbacks i2c_dw_semaphore_cb_table[] = {
#ifdef CONFIG_I2C_DESIGNWARE_BAYTRAIL
{
@@ -138,6 +209,10 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
struct dw_i2c_dev *dev;
int irq, ret;
+ ret = dw_i2c_defer_for_amd_gpio(device);
+ if (ret)
+ return ret;
+
irq = platform_get_irq_optional(pdev, 0);
if (irq == -ENXIO)
flags |= ACCESS_POLLING;
--
2.54.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] pinctrl-amd: enable IRQ for WACF2200 touchscreen on Lenovo Yoga 7 14AGP11
2026-05-12 7:31 ` [PATCH 1/2] pinctrl-amd: enable IRQ for " Hardik Prakash
2026-05-12 8:47 ` Linus Walleij
2026-05-12 10:46 ` Andy Shevchenko
@ 2026-05-13 7:33 ` Linus Walleij
2 siblings, 0 replies; 15+ messages in thread
From: Linus Walleij @ 2026-05-13 7:33 UTC (permalink / raw)
To: Hardik Prakash; +Cc: linux-gpio, linux-i2c, linus.walleij, wsa
On Tue, May 12, 2026 at 9:32 AM Hardik Prakash
<hardikprakash.official@gmail.com> wrote:
> On Lenovo Yoga 7 14AGP11 (83TD), the WACF2200 touchscreen controller
> is wired via I2C2 (AMDI0010:02) with its interrupt on GPIO pin 157
> (confirmed via ACPI _CRS GpioInt decode). After amd_gpio_irq_init()
> clears all GPIO interrupts at boot, pin 157 is never re-enabled,
> preventing the touchscreen from signalling the driver.
>
> Windows keeps GPIO 157 INTERRUPT_ENABLE (bit 11) and INTERRUPT_MASK
> (bit 12) set after initialisation. Add a DMI quirk to restore these
> bits after amd_gpio_irq_init() on this hardware.
>
> Signed-off-by: Hardik Prakash <hardikprakash.official@gmail.com>
This patch 1/2 applied to the pinctrl fixes for v7.1.
Thanks Hardik & Andy!
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] pinctrl-amd: enable IRQ for WACF2200 touchscreen on Lenovo Yoga 7 14AGP11
2026-05-13 6:13 ` [PATCH 1/2] pinctrl-amd: enable IRQ for " Hardik Prakash
@ 2026-05-13 7:36 ` Linus Walleij
2026-05-13 17:23 ` Mario Limonciello
1 sibling, 0 replies; 15+ messages in thread
From: Linus Walleij @ 2026-05-13 7:36 UTC (permalink / raw)
To: Hardik Prakash
Cc: linux-gpio, linux-i2c, linus.walleij, wsa, andriy.shevchenko
On Wed, May 13, 2026 at 8:14 AM Hardik Prakash
<hardikprakash.official@gmail.com> wrote:
> On Lenovo Yoga 7 14AGP11 (83TD), the WACF2200 touchscreen controller
> is wired via I2C2 (AMDI0010:02) with its interrupt on GPIO pin 157
> (confirmed via ACPI _CRS GpioInt decode). After amd_gpio_irq_init()
> clears all GPIO interrupts at boot, pin 157 is never re-enabled,
> preventing the touchscreen from signalling the driver.
>
> Windows keeps GPIO 157 INTERRUPT_ENABLE (bit 11) and INTERRUPT_MASK
> (bit 12) set after initialisation. Add a DMI quirk to restore these
> bits after amd_gpio_irq_init() on this hardware.
>
> Signed-off-by: Hardik Prakash <hardikprakash.official@gmail.com>
> Assisted-by: Claude:claude-sonnet-4-6
> Assisted-by: GPT-Codex:gpt-5.2-codex
You forgot to carry over Andy's ACK!
I see that the only real change was the addition of the two AI tags so I
just added these to the commit already in my tree.
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 0/2] Fix WACF2200 touchscreen on Lenovo Yoga 7 14AGP11
2026-05-13 6:13 [PATCH v2 0/2] Fix WACF2200 touchscreen on Lenovo Yoga 7 14AGP11 Hardik Prakash
2026-05-13 6:13 ` [PATCH 1/2] pinctrl-amd: enable IRQ for " Hardik Prakash
2026-05-13 6:13 ` [PATCH 2/2] i2c: designware: fix probe ordering for AMD GPIO " Hardik Prakash
@ 2026-05-13 17:03 ` Andy Shevchenko
2 siblings, 0 replies; 15+ messages in thread
From: Andy Shevchenko @ 2026-05-13 17:03 UTC (permalink / raw)
To: Hardik Prakash; +Cc: linux-gpio, linux-i2c, linus.walleij, wsa
On Wed, May 13, 2026 at 11:43:36AM +0530, Hardik Prakash wrote:
> The Wacom WACF2200 touchscreen on the Lenovo Yoga 7 14AGP11 (83TD) is
> completely non-functional on Linux. The I2C bus (AMDI0010:02) fails with
> repeated lost arbitration errors at boot before any driver can probe the
> device. The touchscreen works correctly in UEFI and Windows.
>
> Investigation using ACPI _CRS decode and Windows/Linux GPIO register
> comparison identified two bugs:
>
> 1. GPIO 157 (WACF2200 GpioInt per ACPI _CRS) has INTERRUPT_ENABLE and
> INTERRUPT_MASK cleared by amd_gpio_irq_init() and never restored,
> preventing the device from signalling the driver. Windows keeps both
> bits set after initialisation.
>
> 2. i2c_designware probes AMDI0010:02 before pinctrl-amd's probe
> completes. A DMI-matched deferral is added to correctly enforce
> ordering using device_is_bound() under device_lock().
>
> Patch 1 adds a DMI quirk in pinctrl-amd to restore GPIO 157 interrupt
> bits after amd_gpio_irq_init().
>
> Patch 2 adds a probe deferral in i2c-designware-platdrv that correctly
> waits for pinctrl-amd to fully complete before AMDI0010:02 is probed,
> using acpi_dev_get_first_match_dev() and acpi_get_first_physical_node()
> for robust device lookup.
>
> Both patches tested on Lenovo Yoga 7 14AGP11 (83TD), Fedora 44, kernel
> 7.1.0-rc2+. Touch and stylus fully functional across 4 stable reboots.
The Subject in the patches misses versioning, use
git format-patch -v<N> --cover-letter ...
where <N> is the version, to get proper format in the Subject.
Also link to the bugzilla makes sense as BugLink tag in the patch(es):
BugLink: $URL
Or simple Link.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] i2c: designware: fix probe ordering for AMD GPIO on Lenovo Yoga 7 14AGP11
2026-05-13 6:13 ` [PATCH 2/2] i2c: designware: fix probe ordering for AMD GPIO " Hardik Prakash
@ 2026-05-13 17:12 ` Andy Shevchenko
2026-05-13 17:28 ` Mario Limonciello
0 siblings, 1 reply; 15+ messages in thread
From: Andy Shevchenko @ 2026-05-13 17:12 UTC (permalink / raw)
To: Hardik Prakash, Mario Limonciello, Bartosz Golaszewski
Cc: linux-gpio, linux-i2c, linus.walleij, wsa
Please, Cc AMD people on the AMD related stuff.
+Cc: Mario
+Cc: Bart
(the GPIO enumeration and checks, smells like it might be done differently).
On Wed, May 13, 2026 at 11:43:38AM +0530, Hardik Prakash wrote:
> On Lenovo Yoga 7 14AGP11 (83TD), the WACF2200 touchscreen fails with
> lost arbitration errors on AMDI0010:02 at boot. The root cause is a
> probe ordering issue: i2c_designware probes AMDI0010:02 before
> pinctrl-amd has finished initialising, so the GPIO 157 interrupt
> needed by the touchscreen is not yet enabled.
>
> Add a DMI-matched deferral in dw_i2c_plat_probe() that uses
> device_is_bound() under device_lock() to correctly wait until
> pinctrl-amd's probe has fully completed. Use acpi_dev_get_first_match_dev()
> for robust HID/UID-based GPIO controller lookup instead of string
> name matching.
...
> +static bool dw_i2c_needs_amd_gpio_dep(struct device *device)
> +{
> + struct acpi_device *adev = ACPI_COMPANION(device);
Split hard-to-maintain definition and assignment that's going to be validated.
> + if (!dmi_check_system(dw_i2c_amd_gpio_defer_dmi))
> + return false;
> + if (!adev)
> + return false;
struct acpi_device *adev;
if (!dmi_check_system(dw_i2c_amd_gpio_defer_dmi))
return false;
adev = ACPI_COMPANION(device);
if (!adev)
return false;
> + return acpi_dev_hid_uid_match(adev, "AMDI0010", "2");
> +}
...
> +static int dw_i2c_defer_for_amd_gpio(struct device *device)
> +{
> + struct acpi_device *gpio_adev;
> + struct device *gpio_dev;
> +
> + if (!dw_i2c_needs_amd_gpio_dep(device))
> + return 0;
> +
> + /*
> + * Find the AMD GPIO controller by HID/UID and get its physical
> + * platform device. We need the platform device (not the ACPI device)
> + * because that is what gets bound by the amd_gpio driver.
> + */
> + gpio_adev = acpi_dev_get_first_match_dev("AMDI0030", "0", -1);
> + if (!gpio_adev)
> + return -EPROBE_DEFER;
Hmm... This is interesting case, smells like something similar to what we had
with x86 Android quirk driver. Cc'ed to Bart to briefly look at this.
> + gpio_dev = acpi_get_first_physical_node(gpio_adev);
> + acpi_dev_put(gpio_adev);
> + if (!gpio_dev)
> + return -EPROBE_DEFER;
> +
> + /*
> + * Check that amd_gpio probe has fully completed, not just that the
> + * driver pointer is set. The driver pointer is assigned before probe
> + * finishes, so checking it would allow i2c_designware to probe before
> + * the GPIO IRQ quirk in amd_gpio_probe() has run.
> + */
> + device_lock(gpio_dev);
> + if (!device_is_bound(gpio_dev)) {
> + device_unlock(gpio_dev);
> + return -EPROBE_DEFER;
> + }
> + device_unlock(gpio_dev);
> +
> + /*
> + * Create a device link so the driver core enforces probe/remove
> + * ordering between this I2C controller and the GPIO controller.
> + */
> + if (!device_link_add(device, gpio_dev, DL_FLAG_AUTOREMOVE_CONSUMER))
> + dev_warn(device, "failed to add device link to %s\n",
> + dev_name(gpio_dev));
> +
> + return 0;
> +}
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] pinctrl-amd: enable IRQ for WACF2200 touchscreen on Lenovo Yoga 7 14AGP11
2026-05-13 6:13 ` [PATCH 1/2] pinctrl-amd: enable IRQ for " Hardik Prakash
2026-05-13 7:36 ` Linus Walleij
@ 2026-05-13 17:23 ` Mario Limonciello
[not found] ` <CANTFpSUr7KWMA5D7wh48f5-Ty9hDo7U7Ydsob32YZuZ83dRiiw@mail.gmail.com>
1 sibling, 1 reply; 15+ messages in thread
From: Mario Limonciello @ 2026-05-13 17:23 UTC (permalink / raw)
To: Hardik Prakash, linux-gpio, linux-i2c
Cc: linus.walleij, wsa, andriy.shevchenko, Natikar, Basavaraj
++
On 5/13/26 01:13, Hardik Prakash wrote:
> On Lenovo Yoga 7 14AGP11 (83TD), the WACF2200 touchscreen controller
> is wired via I2C2 (AMDI0010:02) with its interrupt on GPIO pin 157
> (confirmed via ACPI _CRS GpioInt decode). After amd_gpio_irq_init()
> clears all GPIO interrupts at boot, pin 157 is never re-enabled,
> preventing the touchscreen from signalling the driver.
>
> Windows keeps GPIO 157 INTERRUPT_ENABLE (bit 11) and INTERRUPT_MASK
> (bit 12) set after initialisation. Add a DMI quirk to restore these
> bits after amd_gpio_irq_init() on this hardware.
>
> Signed-off-by: Hardik Prakash <hardikprakash.official@gmail.com>
> Assisted-by: Claude:claude-sonnet-4-6
> Assisted-by: GPT-Codex:gpt-5.2-codex
> ---
> drivers/pinctrl/pinctrl-amd.c | 35 +++++++++++++++++++++++++++++++++++
> 1 file changed, 35 insertions(+)
>
> diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
> index e3128b0045d22..64315b0edf2a6 100644
> --- a/drivers/pinctrl/pinctrl-amd.c
> +++ b/drivers/pinctrl/pinctrl-amd.c
> @@ -26,6 +26,7 @@
> #include <linux/interrupt.h>
> #include <linux/bitops.h>
> #include <linux/pinctrl/pinconf.h>
> +#include <linux/dmi.h>
> #include <linux/pinctrl/pinconf-generic.h>
> #include <linux/pinctrl/pinmux.h>
> #include <linux/string_choices.h>
> @@ -39,6 +40,39 @@
> static struct amd_gpio *pinctrl_dev;
> #endif
>
> +static const struct dmi_system_id amd_gpio_quirk_yoga7_14agp11[] = {
> + {
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
> + DMI_MATCH(DMI_PRODUCT_NAME, "83TD"),
> + DMI_MATCH(DMI_BOARD_NAME, "LNVNB161216"),
> + },
> + },
> + { }
> +};
> +
> +static void amd_gpio_apply_quirks(struct amd_gpio *gpio_dev)
> +{
> + const unsigned int pin = 157; /* WACF2200 GpioInt per ACPI _CRS */
> + unsigned long flags;
> + u32 reg;
> +
> + if (!dmi_check_system(amd_gpio_quirk_yoga7_14agp11))
> + return;
> + if (pin >= gpio_dev->gc.ngpio)
> + return;
> +
> + raw_spin_lock_irqsave(&gpio_dev->lock, flags);
> + reg = readl(gpio_dev->base + pin * 4);
> + reg |= BIT(INTERRUPT_ENABLE_OFF) | BIT(INTERRUPT_MASK_OFF);
> + writel(reg, gpio_dev->base + pin * 4);
> + raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
> +
> + dev_info(&gpio_dev->pdev->dev,
> + "Enabled IRQ for GPIO %u (Yoga 7 14AGP11 touchscreen)\n",
> + pin);
I don't understand. Our design is that the interrupt is disabled
initially when driver loads (we don't trust state of the GPIO
configuration pre-boot), and then when i2c-hid loads later it is
re-enabled via amd_gpio_irq_enable().
Why isn't that flow working on this system?
> +}
> +
> static int amd_gpio_get_direction(struct gpio_chip *gc, unsigned offset)
> {
> unsigned long flags;
> @@ -1219,6 +1253,7 @@ static int amd_gpio_probe(struct platform_device *pdev)
>
> /* Disable and mask interrupts */
> amd_gpio_irq_init(gpio_dev);
> + amd_gpio_apply_quirks(gpio_dev);
>
> girq = &gpio_dev->gc.irq;
> gpio_irq_chip_set_chip(girq, &amd_gpio_irqchip);
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] i2c: designware: fix probe ordering for AMD GPIO on Lenovo Yoga 7 14AGP11
2026-05-13 17:12 ` Andy Shevchenko
@ 2026-05-13 17:28 ` Mario Limonciello
[not found] ` <CANTFpSU=94RuX1uFf4UitRyzLPvu=cTF_S5khjjJNQUU1T_PtA@mail.gmail.com>
0 siblings, 1 reply; 15+ messages in thread
From: Mario Limonciello @ 2026-05-13 17:28 UTC (permalink / raw)
To: Andy Shevchenko, Hardik Prakash, Bartosz Golaszewski
Cc: linux-gpio, linux-i2c, linus.walleij, wsa, Natikar, Basavaraj
++
On 5/13/26 12:12, Andy Shevchenko wrote:
> Please, Cc AMD people on the AMD related stuff.
> +Cc: Mario
>
> +Cc: Bart
> (the GPIO enumeration and checks, smells like it might be done differently).
Yeah; I tend to think doing this with a quirk is hiding a bug.
Are you sure this isn't a case of two masters on the bus?
[ 2.286838] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
arbitration
[ 2.286887] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
arbitration
[ 2.286923] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
arbitration
[ 2.286964] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
arbitration
[ 2.287521] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
arbitration
[ 2.287569] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
arbitration
[ 2.287616] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
arbitration
[ 2.287658] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
arbitration
I saw something really similar on a Dell platform last year; but around S4.
It ended up being a situation that the EC had way to act as I2C master
and until the right method from I2C-HID was called it thought it was
still I2C master.
https://git.kernel.org/torvalds/c/7d62beb102d6f
Could this be something similar that really calling the _DSM is the
missing link?
>
> On Wed, May 13, 2026 at 11:43:38AM +0530, Hardik Prakash wrote:
>> On Lenovo Yoga 7 14AGP11 (83TD), the WACF2200 touchscreen fails with
>> lost arbitration errors on AMDI0010:02 at boot. The root cause is a
>> probe ordering issue: i2c_designware probes AMDI0010:02 before
>> pinctrl-amd has finished initialising, so the GPIO 157 interrupt
>> needed by the touchscreen is not yet enabled.
>>
>> Add a DMI-matched deferral in dw_i2c_plat_probe() that uses
>> device_is_bound() under device_lock() to correctly wait until
>> pinctrl-amd's probe has fully completed. Use acpi_dev_get_first_match_dev()
>> for robust HID/UID-based GPIO controller lookup instead of string
>> name matching.
>
> ...
>
>> +static bool dw_i2c_needs_amd_gpio_dep(struct device *device)
>> +{
>> + struct acpi_device *adev = ACPI_COMPANION(device);
>
> Split hard-to-maintain definition and assignment that's going to be validated.
>
>> + if (!dmi_check_system(dw_i2c_amd_gpio_defer_dmi))
>> + return false;
>> + if (!adev)
>> + return false;
>
> struct acpi_device *adev;
>
> if (!dmi_check_system(dw_i2c_amd_gpio_defer_dmi))
> return false;
>
> adev = ACPI_COMPANION(device);
> if (!adev)
> return false;
>
>> + return acpi_dev_hid_uid_match(adev, "AMDI0010", "2");
>> +}
>
> ...
>
>> +static int dw_i2c_defer_for_amd_gpio(struct device *device)
>> +{
>> + struct acpi_device *gpio_adev;
>> + struct device *gpio_dev;
>> +
>> + if (!dw_i2c_needs_amd_gpio_dep(device))
>> + return 0;
>> +
>> + /*
>> + * Find the AMD GPIO controller by HID/UID and get its physical
>> + * platform device. We need the platform device (not the ACPI device)
>> + * because that is what gets bound by the amd_gpio driver.
>> + */
>> + gpio_adev = acpi_dev_get_first_match_dev("AMDI0030", "0", -1);
>> + if (!gpio_adev)
>> + return -EPROBE_DEFER;
>
> Hmm... This is interesting case, smells like something similar to what we had
> with x86 Android quirk driver. Cc'ed to Bart to briefly look at this.
>
>> + gpio_dev = acpi_get_first_physical_node(gpio_adev);
>> + acpi_dev_put(gpio_adev);
>> + if (!gpio_dev)
>> + return -EPROBE_DEFER;
>> +
>> + /*
>> + * Check that amd_gpio probe has fully completed, not just that the
>> + * driver pointer is set. The driver pointer is assigned before probe
>> + * finishes, so checking it would allow i2c_designware to probe before
>> + * the GPIO IRQ quirk in amd_gpio_probe() has run.
>> + */
>> + device_lock(gpio_dev);
>> + if (!device_is_bound(gpio_dev)) {
>> + device_unlock(gpio_dev);
>> + return -EPROBE_DEFER;
>> + }
>> + device_unlock(gpio_dev);
>> +
>> + /*
>> + * Create a device link so the driver core enforces probe/remove
>> + * ordering between this I2C controller and the GPIO controller.
>> + */
>> + if (!device_link_add(device, gpio_dev, DL_FLAG_AUTOREMOVE_CONSUMER))
>> + dev_warn(device, "failed to add device link to %s\n",
>> + dev_name(gpio_dev));
>> +
>> + return 0;
>> +}
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] pinctrl-amd: enable IRQ for WACF2200 touchscreen on Lenovo Yoga 7 14AGP11
[not found] ` <CANTFpSUr7KWMA5D7wh48f5-Ty9hDo7U7Ydsob32YZuZ83dRiiw@mail.gmail.com>
@ 2026-05-14 5:12 ` Hardik Prakash
0 siblings, 0 replies; 15+ messages in thread
From: Hardik Prakash @ 2026-05-14 5:12 UTC (permalink / raw)
To: Mario Limonciello, linux-gpio, linux-i2c
Cc: Andy Shevchenko, wsa, linus.walleij, basavaraj.natikar
(Resending with full Cc list — apologies for the missed recipients.)
On Wed, May 13, 2026 at 22:53, Mario Limonciello wrote:
> I don't understand. Our design is that the interrupt is disabled
> initially when driver loads (we don't trust state of the GPIO
> configuration pre-boot), and then when i2c-hid loads later it is
> re-enabled via amd_gpio_irq_enable().
>
> Why isn't that flow working on this system?
The flow breaks because i2c-hid never gets to probe. The lost
arbitration errors happen on AMDI0010:02 at ~2.3s after boot, before
any driver reaches the HID layer. Without the probe ordering fix,
i2c_designware probes the bus while pinctrl-amd is still initialising
and GPIO 157 (the WACF2200 GpioInt per ACPI _CRS) has its interrupt
bits cleared. The bus transaction fails immediately, the device never
appears in /sys/bus/hid/devices/, and i2c-hid has nothing to bind to.
With patch 1 alone (GPIO IRQ fix), the interrupt is enabled but the
probe ordering race still causes arbitration failures. With both patches
applied, the bus comes up cleanly and i2c-hid probes successfully.
However, see my reply on the 2/2 thread — there may be a deeper cause
related to _DSM.
Thanks,
Hardik
On Thu, 14 May 2026 at 10:36, Hardik Prakash
<hardikprakash.official@gmail.com> wrote:
>
> On Wed, May 13, 2026 at 22:53, Mario Limonciello wrote:
> > I don't understand. Our design is that the interrupt is disabled
> > initially when driver loads (we don't trust state of the GPIO
> > configuration pre-boot), and then when i2c-hid loads later it is
> > re-enabled via amd_gpio_irq_enable().
> >
> > Why isn't that flow working on this system?
>
> The flow breaks because i2c-hid never gets to probe. The lost
> arbitration errors happen on AMDI0010:02 at ~2.3s after boot, before
> any driver reaches the HID layer. Without the probe ordering fix,
> i2c_designware probes the bus while pinctrl-amd is still initialising
> and GPIO 157 (the WACF2200 GpioInt per ACPI _CRS) has its interrupt
> bits cleared. The bus transaction fails immediately, the device never
> appears in /sys/bus/hid/devices/, and i2c-hid has nothing to bind to.
>
> With patch 1 alone (GPIO IRQ fix), the interrupt is enabled but the
> probe ordering race still causes arbitration failures. With both patches
> applied, the bus comes up cleanly and i2c-hid probes successfully.
>
> However, see my reply on the 2/2 thread — there may be a deeper cause
> related to _DSM.
>
> Thanks,
> Hardik
>
> On Wed, 13 May 2026 at 22:53, Mario Limonciello <superm1@kernel.org> wrote:
> >
> > ++
> >
> > On 5/13/26 01:13, Hardik Prakash wrote:
> > > On Lenovo Yoga 7 14AGP11 (83TD), the WACF2200 touchscreen controller
> > > is wired via I2C2 (AMDI0010:02) with its interrupt on GPIO pin 157
> > > (confirmed via ACPI _CRS GpioInt decode). After amd_gpio_irq_init()
> > > clears all GPIO interrupts at boot, pin 157 is never re-enabled,
> > > preventing the touchscreen from signalling the driver.
> > >
> > > Windows keeps GPIO 157 INTERRUPT_ENABLE (bit 11) and INTERRUPT_MASK
> > > (bit 12) set after initialisation. Add a DMI quirk to restore these
> > > bits after amd_gpio_irq_init() on this hardware.
> > >
> > > Signed-off-by: Hardik Prakash <hardikprakash.official@gmail.com>
> > > Assisted-by: Claude:claude-sonnet-4-6
> > > Assisted-by: GPT-Codex:gpt-5.2-codex
> > > ---
> > > drivers/pinctrl/pinctrl-amd.c | 35 +++++++++++++++++++++++++++++++++++
> > > 1 file changed, 35 insertions(+)
> > >
> > > diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
> > > index e3128b0045d22..64315b0edf2a6 100644
> > > --- a/drivers/pinctrl/pinctrl-amd.c
> > > +++ b/drivers/pinctrl/pinctrl-amd.c
> > > @@ -26,6 +26,7 @@
> > > #include <linux/interrupt.h>
> > > #include <linux/bitops.h>
> > > #include <linux/pinctrl/pinconf.h>
> > > +#include <linux/dmi.h>
> > > #include <linux/pinctrl/pinconf-generic.h>
> > > #include <linux/pinctrl/pinmux.h>
> > > #include <linux/string_choices.h>
> > > @@ -39,6 +40,39 @@
> > > static struct amd_gpio *pinctrl_dev;
> > > #endif
> > >
> > > +static const struct dmi_system_id amd_gpio_quirk_yoga7_14agp11[] = {
> > > + {
> > > + .matches = {
> > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
> > > + DMI_MATCH(DMI_PRODUCT_NAME, "83TD"),
> > > + DMI_MATCH(DMI_BOARD_NAME, "LNVNB161216"),
> > > + },
> > > + },
> > > + { }
> > > +};
> > > +
> > > +static void amd_gpio_apply_quirks(struct amd_gpio *gpio_dev)
> > > +{
> > > + const unsigned int pin = 157; /* WACF2200 GpioInt per ACPI _CRS */
> > > + unsigned long flags;
> > > + u32 reg;
> > > +
> > > + if (!dmi_check_system(amd_gpio_quirk_yoga7_14agp11))
> > > + return;
> > > + if (pin >= gpio_dev->gc.ngpio)
> > > + return;
> > > +
> > > + raw_spin_lock_irqsave(&gpio_dev->lock, flags);
> > > + reg = readl(gpio_dev->base + pin * 4);
> > > + reg |= BIT(INTERRUPT_ENABLE_OFF) | BIT(INTERRUPT_MASK_OFF);
> > > + writel(reg, gpio_dev->base + pin * 4);
> > > + raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
> > > +
> > > + dev_info(&gpio_dev->pdev->dev,
> > > + "Enabled IRQ for GPIO %u (Yoga 7 14AGP11 touchscreen)\n",
> > > + pin);
> >
> > I don't understand. Our design is that the interrupt is disabled
> > initially when driver loads (we don't trust state of the GPIO
> > configuration pre-boot), and then when i2c-hid loads later it is
> > re-enabled via amd_gpio_irq_enable().
> >
> > Why isn't that flow working on this system?
> >
> > > +}
> > > +
> > > static int amd_gpio_get_direction(struct gpio_chip *gc, unsigned offset)
> > > {
> > > unsigned long flags;
> > > @@ -1219,6 +1253,7 @@ static int amd_gpio_probe(struct platform_device *pdev)
> > >
> > > /* Disable and mask interrupts */
> > > amd_gpio_irq_init(gpio_dev);
> > > + amd_gpio_apply_quirks(gpio_dev);
> > >
> > > girq = &gpio_dev->gc.irq;
> > > gpio_irq_chip_set_chip(girq, &amd_gpio_irqchip);
> >
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] i2c: designware: fix probe ordering for AMD GPIO on Lenovo Yoga 7 14AGP11
[not found] ` <CANTFpSU=94RuX1uFf4UitRyzLPvu=cTF_S5khjjJNQUU1T_PtA@mail.gmail.com>
@ 2026-05-14 5:14 ` Hardik Prakash
2026-05-14 5:43 ` Hardik Prakash
0 siblings, 1 reply; 15+ messages in thread
From: Hardik Prakash @ 2026-05-14 5:14 UTC (permalink / raw)
To: Mario Limonciello, Andy Shevchenko, brgl
Cc: linux-gpio, linux-i2c, linus.walleij, wsa, basavaraj.natikar
(Resending with full Cc list — apologies for the missed recipients.)
On Wed, May 13, 2026 at 22:58, Mario Limonciello wrote:
> Yeah; I tend to think doing this with a quirk is hiding a bug.
>
> Are you sure this isn't a case of two masters on the bus?
I looked into this after your email. The DSDT for TPNL (WACF2200) does
have a _DSM with UUID 3cdff6f7-4267-4555-ad05-b30a3d8938de (HID I2C
Device). So yes — this could be the same mechanism you saw on Dell.
> Could this be something similar that really calling the _DSM is the
> missing link?
Possibly. With my current patches applied, the probe ordering fix
ensures i2c_designware initialises AMDI0010:02 cleanly, i2c-hid
subsequently probes, and presumably calls the _DSM at that point —
which may be what finally releases the bus. Without the patches,
i2c-hid never gets that far.
The question I can't answer yet is whether the _DSM needs to be called
*before* the first I2C bus transaction attempt, rather than at i2c-hid
probe time. If the firmware is acting as I2C master until the _DSM is
called, then the arbitration errors at 2.3s would be explained entirely
by the missing _DSM call, independent of the GPIO IRQ state.
I'm investigating the _DSM content further. If you believe the correct
fix is an earlier _DSM call (similar to what 7d62beb did for S4), I'm
happy to test a patch for that approach and report back.
Thanks,
Hardik
On Thu, 14 May 2026 at 10:37, Hardik Prakash
<hardikprakash.official@gmail.com> wrote:
>
> On Wed, May 13, 2026 at 22:58, Mario Limonciello wrote:
> > Yeah; I tend to think doing this with a quirk is hiding a bug.
> >
> > Are you sure this isn't a case of two masters on the bus?
>
> I looked into this after your email. The DSDT for TPNL (WACF2200) does
> have a _DSM with UUID 3cdff6f7-4267-4555-ad05-b30a3d8938de (HID I2C
> Device). So yes — this could be the same mechanism you saw on Dell.
>
> > Could this be something similar that really calling the _DSM is the
> > missing link?
>
> Possibly. With my current patches applied, the probe ordering fix
> ensures i2c_designware initialises AMDI0010:02 cleanly, i2c-hid
> subsequently probes, and presumably calls the _DSM at that point —
> which may be what finally releases the bus. Without the patches,
> i2c-hid never gets that far.
>
> The question I can't answer yet is whether the _DSM needs to be called
> *before* the first I2C bus transaction attempt, rather than at i2c-hid
> probe time. If the firmware is acting as I2C master until the _DSM is
> called, then the arbitration errors at 2.3s would be explained entirely
> by the missing _DSM call, independent of the GPIO IRQ state.
>
> I'm investigating the _DSM content further. If you believe the correct
> fix is an earlier _DSM call (similar to what 7d62beb did for S4), I'm
> happy to test a patch for that approach and report back.
>
> Thanks,
> Hardik
>
> On Wed, 13 May 2026 at 22:58, Mario Limonciello <superm1@kernel.org> wrote:
> >
> > ++
> >
> > On 5/13/26 12:12, Andy Shevchenko wrote:
> > > Please, Cc AMD people on the AMD related stuff.
> > > +Cc: Mario
> > >
> > > +Cc: Bart
> > > (the GPIO enumeration and checks, smells like it might be done differently).
> >
> > Yeah; I tend to think doing this with a quirk is hiding a bug.
> >
> > Are you sure this isn't a case of two masters on the bus?
> >
> > [ 2.286838] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
> > arbitration
> > [ 2.286887] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
> > arbitration
> > [ 2.286923] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
> > arbitration
> > [ 2.286964] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
> > arbitration
> > [ 2.287521] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
> > arbitration
> > [ 2.287569] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
> > arbitration
> > [ 2.287616] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
> > arbitration
> > [ 2.287658] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
> > arbitration
> >
> > I saw something really similar on a Dell platform last year; but around S4.
> >
> > It ended up being a situation that the EC had way to act as I2C master
> > and until the right method from I2C-HID was called it thought it was
> > still I2C master.
> >
> > https://git.kernel.org/torvalds/c/7d62beb102d6f
> >
> > Could this be something similar that really calling the _DSM is the
> > missing link?
> >
> > >
> > > On Wed, May 13, 2026 at 11:43:38AM +0530, Hardik Prakash wrote:
> > >> On Lenovo Yoga 7 14AGP11 (83TD), the WACF2200 touchscreen fails with
> > >> lost arbitration errors on AMDI0010:02 at boot. The root cause is a
> > >> probe ordering issue: i2c_designware probes AMDI0010:02 before
> > >> pinctrl-amd has finished initialising, so the GPIO 157 interrupt
> > >> needed by the touchscreen is not yet enabled.
> > >>
> > >> Add a DMI-matched deferral in dw_i2c_plat_probe() that uses
> > >> device_is_bound() under device_lock() to correctly wait until
> > >> pinctrl-amd's probe has fully completed. Use acpi_dev_get_first_match_dev()
> > >> for robust HID/UID-based GPIO controller lookup instead of string
> > >> name matching.
> > >
> > > ...
> > >
> > >> +static bool dw_i2c_needs_amd_gpio_dep(struct device *device)
> > >> +{
> > >> + struct acpi_device *adev = ACPI_COMPANION(device);
> > >
> > > Split hard-to-maintain definition and assignment that's going to be validated.
> > >
> > >> + if (!dmi_check_system(dw_i2c_amd_gpio_defer_dmi))
> > >> + return false;
> > >> + if (!adev)
> > >> + return false;
> > >
> > > struct acpi_device *adev;
> > >
> > > if (!dmi_check_system(dw_i2c_amd_gpio_defer_dmi))
> > > return false;
> > >
> > > adev = ACPI_COMPANION(device);
> > > if (!adev)
> > > return false;
> > >
> > >> + return acpi_dev_hid_uid_match(adev, "AMDI0010", "2");
> > >> +}
> > >
> > > ...
> > >
> > >> +static int dw_i2c_defer_for_amd_gpio(struct device *device)
> > >> +{
> > >> + struct acpi_device *gpio_adev;
> > >> + struct device *gpio_dev;
> > >> +
> > >> + if (!dw_i2c_needs_amd_gpio_dep(device))
> > >> + return 0;
> > >> +
> > >> + /*
> > >> + * Find the AMD GPIO controller by HID/UID and get its physical
> > >> + * platform device. We need the platform device (not the ACPI device)
> > >> + * because that is what gets bound by the amd_gpio driver.
> > >> + */
> > >> + gpio_adev = acpi_dev_get_first_match_dev("AMDI0030", "0", -1);
> > >> + if (!gpio_adev)
> > >> + return -EPROBE_DEFER;
> > >
> > > Hmm... This is interesting case, smells like something similar to what we had
> > > with x86 Android quirk driver. Cc'ed to Bart to briefly look at this.
> > >
> > >> + gpio_dev = acpi_get_first_physical_node(gpio_adev);
> > >> + acpi_dev_put(gpio_adev);
> > >> + if (!gpio_dev)
> > >> + return -EPROBE_DEFER;
> > >> +
> > >> + /*
> > >> + * Check that amd_gpio probe has fully completed, not just that the
> > >> + * driver pointer is set. The driver pointer is assigned before probe
> > >> + * finishes, so checking it would allow i2c_designware to probe before
> > >> + * the GPIO IRQ quirk in amd_gpio_probe() has run.
> > >> + */
> > >> + device_lock(gpio_dev);
> > >> + if (!device_is_bound(gpio_dev)) {
> > >> + device_unlock(gpio_dev);
> > >> + return -EPROBE_DEFER;
> > >> + }
> > >> + device_unlock(gpio_dev);
> > >> +
> > >> + /*
> > >> + * Create a device link so the driver core enforces probe/remove
> > >> + * ordering between this I2C controller and the GPIO controller.
> > >> + */
> > >> + if (!device_link_add(device, gpio_dev, DL_FLAG_AUTOREMOVE_CONSUMER))
> > >> + dev_warn(device, "failed to add device link to %s\n",
> > >> + dev_name(gpio_dev));
> > >> +
> > >> + return 0;
> > >> +}
> > >
> >
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] i2c: designware: fix probe ordering for AMD GPIO on Lenovo Yoga 7 14AGP11
2026-05-14 5:14 ` Hardik Prakash
@ 2026-05-14 5:43 ` Hardik Prakash
0 siblings, 0 replies; 15+ messages in thread
From: Hardik Prakash @ 2026-05-14 5:43 UTC (permalink / raw)
To: Mario Limonciello, Andy Shevchenko, brgl
Cc: linux-gpio, linux-i2c, linus.walleij, wsa, basavaraj.natikar
On Wed, May 13, 2026 at 22:58, Mario Limonciello wrote:
> Could this be something similar that really calling the _DSM is the
> missing link?
Correction to my previous reply — I've now disassembled the DSDT and
looked at the _DSM content directly.
TPNL's _DSM (UUID 3cdff6f7-4267-4555-ad05-b30a3d8938de):
Function 0 (revision 1): returns 0x03 (functions 0 and 1 supported)
Function 1: returns integer 1 (HID descriptor address)
All other functions: return 0
There are no side effects — no power sequencing, no GPIO operations,
no bus ownership transfer. It is a pure query method that returns a
constant HID descriptor address. This makes the dual-master scenario
less likely for this hardware than it was for the Dell case.
Based on the DSDT, I don't see evidence that the firmware is acting as
a secondary I2C master, or that calling the _DSM earlier would change
the bus arbitration behaviour. The arbitration errors on this system
appear to be explained by the GPIO IRQ not being enabled (patch 1) and
the probe ordering race (patch 2).
That said, I could be wrong — if you see something in the DSDT or
elsewhere that suggests otherwise, I'm happy to test a different
approach.
Thanks,
Hardik
On Thu, 14 May 2026 at 10:44, Hardik Prakash
<hardikprakash.official@gmail.com> wrote:
>
> (Resending with full Cc list — apologies for the missed recipients.)
>
> On Wed, May 13, 2026 at 22:58, Mario Limonciello wrote:
> > Yeah; I tend to think doing this with a quirk is hiding a bug.
> >
> > Are you sure this isn't a case of two masters on the bus?
>
> I looked into this after your email. The DSDT for TPNL (WACF2200) does
> have a _DSM with UUID 3cdff6f7-4267-4555-ad05-b30a3d8938de (HID I2C
> Device). So yes — this could be the same mechanism you saw on Dell.
>
> > Could this be something similar that really calling the _DSM is the
> > missing link?
>
> Possibly. With my current patches applied, the probe ordering fix
> ensures i2c_designware initialises AMDI0010:02 cleanly, i2c-hid
> subsequently probes, and presumably calls the _DSM at that point —
> which may be what finally releases the bus. Without the patches,
> i2c-hid never gets that far.
>
> The question I can't answer yet is whether the _DSM needs to be called
> *before* the first I2C bus transaction attempt, rather than at i2c-hid
> probe time. If the firmware is acting as I2C master until the _DSM is
> called, then the arbitration errors at 2.3s would be explained entirely
> by the missing _DSM call, independent of the GPIO IRQ state.
>
> I'm investigating the _DSM content further. If you believe the correct
> fix is an earlier _DSM call (similar to what 7d62beb did for S4), I'm
> happy to test a patch for that approach and report back.
>
> Thanks,
> Hardik
>
> On Thu, 14 May 2026 at 10:37, Hardik Prakash
> <hardikprakash.official@gmail.com> wrote:
> >
> > On Wed, May 13, 2026 at 22:58, Mario Limonciello wrote:
> > > Yeah; I tend to think doing this with a quirk is hiding a bug.
> > >
> > > Are you sure this isn't a case of two masters on the bus?
> >
> > I looked into this after your email. The DSDT for TPNL (WACF2200) does
> > have a _DSM with UUID 3cdff6f7-4267-4555-ad05-b30a3d8938de (HID I2C
> > Device). So yes — this could be the same mechanism you saw on Dell.
> >
> > > Could this be something similar that really calling the _DSM is the
> > > missing link?
> >
> > Possibly. With my current patches applied, the probe ordering fix
> > ensures i2c_designware initialises AMDI0010:02 cleanly, i2c-hid
> > subsequently probes, and presumably calls the _DSM at that point —
> > which may be what finally releases the bus. Without the patches,
> > i2c-hid never gets that far.
> >
> > The question I can't answer yet is whether the _DSM needs to be called
> > *before* the first I2C bus transaction attempt, rather than at i2c-hid
> > probe time. If the firmware is acting as I2C master until the _DSM is
> > called, then the arbitration errors at 2.3s would be explained entirely
> > by the missing _DSM call, independent of the GPIO IRQ state.
> >
> > I'm investigating the _DSM content further. If you believe the correct
> > fix is an earlier _DSM call (similar to what 7d62beb did for S4), I'm
> > happy to test a patch for that approach and report back.
> >
> > Thanks,
> > Hardik
> >
> > On Wed, 13 May 2026 at 22:58, Mario Limonciello <superm1@kernel.org> wrote:
> > >
> > > ++
> > >
> > > On 5/13/26 12:12, Andy Shevchenko wrote:
> > > > Please, Cc AMD people on the AMD related stuff.
> > > > +Cc: Mario
> > > >
> > > > +Cc: Bart
> > > > (the GPIO enumeration and checks, smells like it might be done differently).
> > >
> > > Yeah; I tend to think doing this with a quirk is hiding a bug.
> > >
> > > Are you sure this isn't a case of two masters on the bus?
> > >
> > > [ 2.286838] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
> > > arbitration
> > > [ 2.286887] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
> > > arbitration
> > > [ 2.286923] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
> > > arbitration
> > > [ 2.286964] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
> > > arbitration
> > > [ 2.287521] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
> > > arbitration
> > > [ 2.287569] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
> > > arbitration
> > > [ 2.287616] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
> > > arbitration
> > > [ 2.287658] i2c_designware AMDI0010:02: i2c_dw_handle_tx_abort: lost
> > > arbitration
> > >
> > > I saw something really similar on a Dell platform last year; but around S4.
> > >
> > > It ended up being a situation that the EC had way to act as I2C master
> > > and until the right method from I2C-HID was called it thought it was
> > > still I2C master.
> > >
> > > https://git.kernel.org/torvalds/c/7d62beb102d6f
> > >
> > > Could this be something similar that really calling the _DSM is the
> > > missing link?
> > >
> > > >
> > > > On Wed, May 13, 2026 at 11:43:38AM +0530, Hardik Prakash wrote:
> > > >> On Lenovo Yoga 7 14AGP11 (83TD), the WACF2200 touchscreen fails with
> > > >> lost arbitration errors on AMDI0010:02 at boot. The root cause is a
> > > >> probe ordering issue: i2c_designware probes AMDI0010:02 before
> > > >> pinctrl-amd has finished initialising, so the GPIO 157 interrupt
> > > >> needed by the touchscreen is not yet enabled.
> > > >>
> > > >> Add a DMI-matched deferral in dw_i2c_plat_probe() that uses
> > > >> device_is_bound() under device_lock() to correctly wait until
> > > >> pinctrl-amd's probe has fully completed. Use acpi_dev_get_first_match_dev()
> > > >> for robust HID/UID-based GPIO controller lookup instead of string
> > > >> name matching.
> > > >
> > > > ...
> > > >
> > > >> +static bool dw_i2c_needs_amd_gpio_dep(struct device *device)
> > > >> +{
> > > >> + struct acpi_device *adev = ACPI_COMPANION(device);
> > > >
> > > > Split hard-to-maintain definition and assignment that's going to be validated.
> > > >
> > > >> + if (!dmi_check_system(dw_i2c_amd_gpio_defer_dmi))
> > > >> + return false;
> > > >> + if (!adev)
> > > >> + return false;
> > > >
> > > > struct acpi_device *adev;
> > > >
> > > > if (!dmi_check_system(dw_i2c_amd_gpio_defer_dmi))
> > > > return false;
> > > >
> > > > adev = ACPI_COMPANION(device);
> > > > if (!adev)
> > > > return false;
> > > >
> > > >> + return acpi_dev_hid_uid_match(adev, "AMDI0010", "2");
> > > >> +}
> > > >
> > > > ...
> > > >
> > > >> +static int dw_i2c_defer_for_amd_gpio(struct device *device)
> > > >> +{
> > > >> + struct acpi_device *gpio_adev;
> > > >> + struct device *gpio_dev;
> > > >> +
> > > >> + if (!dw_i2c_needs_amd_gpio_dep(device))
> > > >> + return 0;
> > > >> +
> > > >> + /*
> > > >> + * Find the AMD GPIO controller by HID/UID and get its physical
> > > >> + * platform device. We need the platform device (not the ACPI device)
> > > >> + * because that is what gets bound by the amd_gpio driver.
> > > >> + */
> > > >> + gpio_adev = acpi_dev_get_first_match_dev("AMDI0030", "0", -1);
> > > >> + if (!gpio_adev)
> > > >> + return -EPROBE_DEFER;
> > > >
> > > > Hmm... This is interesting case, smells like something similar to what we had
> > > > with x86 Android quirk driver. Cc'ed to Bart to briefly look at this.
> > > >
> > > >> + gpio_dev = acpi_get_first_physical_node(gpio_adev);
> > > >> + acpi_dev_put(gpio_adev);
> > > >> + if (!gpio_dev)
> > > >> + return -EPROBE_DEFER;
> > > >> +
> > > >> + /*
> > > >> + * Check that amd_gpio probe has fully completed, not just that the
> > > >> + * driver pointer is set. The driver pointer is assigned before probe
> > > >> + * finishes, so checking it would allow i2c_designware to probe before
> > > >> + * the GPIO IRQ quirk in amd_gpio_probe() has run.
> > > >> + */
> > > >> + device_lock(gpio_dev);
> > > >> + if (!device_is_bound(gpio_dev)) {
> > > >> + device_unlock(gpio_dev);
> > > >> + return -EPROBE_DEFER;
> > > >> + }
> > > >> + device_unlock(gpio_dev);
> > > >> +
> > > >> + /*
> > > >> + * Create a device link so the driver core enforces probe/remove
> > > >> + * ordering between this I2C controller and the GPIO controller.
> > > >> + */
> > > >> + if (!device_link_add(device, gpio_dev, DL_FLAG_AUTOREMOVE_CONSUMER))
> > > >> + dev_warn(device, "failed to add device link to %s\n",
> > > >> + dev_name(gpio_dev));
> > > >> +
> > > >> + return 0;
> > > >> +}
> > > >
> > >
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-05-14 5:43 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-13 6:13 [PATCH v2 0/2] Fix WACF2200 touchscreen on Lenovo Yoga 7 14AGP11 Hardik Prakash
2026-05-13 6:13 ` [PATCH 1/2] pinctrl-amd: enable IRQ for " Hardik Prakash
2026-05-13 7:36 ` Linus Walleij
2026-05-13 17:23 ` Mario Limonciello
[not found] ` <CANTFpSUr7KWMA5D7wh48f5-Ty9hDo7U7Ydsob32YZuZ83dRiiw@mail.gmail.com>
2026-05-14 5:12 ` Hardik Prakash
2026-05-13 6:13 ` [PATCH 2/2] i2c: designware: fix probe ordering for AMD GPIO " Hardik Prakash
2026-05-13 17:12 ` Andy Shevchenko
2026-05-13 17:28 ` Mario Limonciello
[not found] ` <CANTFpSU=94RuX1uFf4UitRyzLPvu=cTF_S5khjjJNQUU1T_PtA@mail.gmail.com>
2026-05-14 5:14 ` Hardik Prakash
2026-05-14 5:43 ` Hardik Prakash
2026-05-13 17:03 ` [PATCH v2 0/2] Fix WACF2200 touchscreen " Andy Shevchenko
-- strict thread matches above, loose matches on Subject: below --
2026-05-12 7:31 [PATCH " Hardik Prakash
2026-05-12 7:31 ` [PATCH 1/2] pinctrl-amd: enable IRQ for " Hardik Prakash
2026-05-12 8:47 ` Linus Walleij
2026-05-12 10:46 ` Andy Shevchenko
2026-05-13 7:33 ` Linus Walleij
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox