Skip to content

Commit 73f3a74

Browse files
EvenxfJiri Kosina
authored andcommitted
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 <[email protected]> Tested-by: Chong Han <[email protected]> Fixes: 66b59bf ("HID: intel-thc-hid: intel-quicki2c: Complete THC QuickI2C driver") Signed-off-by: Jiri Kosina <[email protected]>
1 parent 4a03810 commit 73f3a74

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 <linux/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)