Skip to content

Commit 0ffd6c1

Browse files
committed
HID: Intel-thc-hid: Intel-quicki2c: Enhance QuickI2C reset flow
JIRA: https://issues.redhat.com/browse/RHEL-65754 Upstream Status: 6.16-rc Tested: sanity tested only Conflicts: commit 5f60d5f ("move asm/unaligned.h to linux/unaligned.h") is not in RHEL 9 (it was reverted), so make use of the old path commit 73f3a74 Author: Even Xu <even.xu@intel.com> Date: Wed May 14 14:26:38 2025 +0800 HID: Intel-thc-hid: Intel-quicki2c: Enhance QuickI2C reset flow During customer board enabling, it was found: some touch devices prepared reset response, but either forgot sending interrupt or THC missed reset interrupt because of timing issue. THC QuickI2C driver depends on interrupt to read reset response, in this case, it will cause driver waiting timeout. This patch enhances the flow by adding manually reset response reading after waiting for reset interrupt timeout. Signed-off-by: Even Xu <even.xu@intel.com> Tested-by: Chong Han <chong.han@intel.com> Fixes: 66b59bf ("HID: intel-thc-hid: intel-quicki2c: Complete THC QuickI2C driver") Signed-off-by: Jiri Kosina <jkosina@suse.com> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
1 parent 6314574 commit 0ffd6c1

File tree

1 file changed

+25
-1
lines changed

1 file changed

+25
-1
lines changed

drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <linux/bitfield.h>
55
#include <linux/hid.h>
66
#include <linux/hid-over-i2c.h>
7+
#include <asm/unaligned.h>
78

89
#include "intel-thc-dev.h"
910
#include "intel-thc-dma.h"
@@ -200,6 +201,9 @@ int quicki2c_set_report(struct quicki2c_device *qcdev, u8 report_type,
200201

201202
int quicki2c_reset(struct quicki2c_device *qcdev)
202203
{
204+
u16 input_reg = le16_to_cpu(qcdev->dev_desc.input_reg);
205+
size_t read_len = HIDI2C_LENGTH_LEN;
206+
u32 prd_len = read_len;
203207
int ret;
204208

205209
qcdev->reset_ack = false;
@@ -213,12 +217,32 @@ int quicki2c_reset(struct quicki2c_device *qcdev)
213217

214218
ret = wait_event_interruptible_timeout(qcdev->reset_ack_wq, qcdev->reset_ack,
215219
HIDI2C_RESET_TIMEOUT * HZ);
216-
if (ret <= 0 || !qcdev->reset_ack) {
220+
if (qcdev->reset_ack)
221+
return 0;
222+
223+
/*
224+
* Manually read reset response if it wasn't received, in case reset interrupt
225+
* was missed by touch device or THC hardware.
226+
*/
227+
ret = thc_tic_pio_read(qcdev->thc_hw, input_reg, read_len, &prd_len,
228+
(u32 *)qcdev->input_buf);
229+
if (ret) {
230+
dev_err_once(qcdev->dev, "Read Reset Response failed, ret %d\n", ret);
231+
return ret;
232+
}
233+
234+
/*
235+
* Check response packet length, it's first 16 bits of packet.
236+
* If response packet length is zero, it's reset response, otherwise not.
237+
*/
238+
if (get_unaligned_le16(qcdev->input_buf)) {
217239
dev_err_once(qcdev->dev,
218240
"Wait reset response timed out ret:%d timeout:%ds\n",
219241
ret, HIDI2C_RESET_TIMEOUT);
220242
return -ETIMEDOUT;
221243
}
222244

245+
qcdev->reset_ack = true;
246+
223247
return 0;
224248
}

0 commit comments

Comments
 (0)