Skip to content

Commit e86a88d

Browse files
committed
fix dropped interrupt from touchpad
This fixes an issue where the ps2mouse task will sometimes not process an interrupt from the touchpad, and the task will get 2 interrupt events on top of each other causing the task to get touchpad data after the touchpad has deasserted the interrupt line. I think the smbus controller is still getting in a state and hitting the 100ms timeout, which happens right on top of the touchpad 100ms interrupt retry logic. So the touchpad task gets a 2nd interrupt while it is servicing the first interrupt. But the touchpad only responds one time Signed-off-by: Kieran Levin <[email protected]>
1 parent 30216a3 commit e86a88d

File tree

2 files changed

+27
-10
lines changed

2 files changed

+27
-10
lines changed

board/hx20/ps2mouse.c

+25-10
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ void send_data_byte(uint8_t data) {
4646
int timeout = 0;
4747

4848
/* sometimes the host will get behind */
49-
while (aux_buffer_available() < 1 && timeout++ < 25)
49+
while (aux_buffer_available() < 1 && timeout++ < AUX_BUFFER_FULL_RETRIES)
5050
usleep(10*MSEC);
5151
send_aux_data_to_host_interrupt(data);
5252
}
@@ -59,12 +59,13 @@ void send_movement_packet(void)
5959
if (five_button_mode)
6060
max = 4;
6161
/* sometimes the host will get behind */
62-
while (aux_buffer_available() < max && timeout++ < 25 &&
62+
while (aux_buffer_available() < max && timeout++ < AUX_BUFFER_FULL_RETRIES &&
6363
(*task_get_event_bitmap(emumouse_task_id) & PS2MOUSE_EVT_AUX_DATA) == 0) {
6464
usleep(10*MSEC);
6565
}
6666

67-
if (timeout == 25 || (*task_get_event_bitmap(emumouse_task_id) & PS2MOUSE_EVT_AUX_DATA)) {
67+
if (timeout == AUX_BUFFER_FULL_RETRIES ||
68+
(*task_get_event_bitmap(emumouse_task_id) & PS2MOUSE_EVT_AUX_DATA)) {
6869
CPRINTS("PS2M Dropping");
6970
/*drop mouse packet - host is too far behind */
7071
return;
@@ -332,8 +333,14 @@ void read_touchpad_in_report(void)
332333

333334
/* Make sure report id is set to an invalid value */
334335
data[2] = 0;
336+
337+
if (power_get_state() == POWER_S5) {
338+
return;
339+
}
340+
335341
/*dont trigger disable state during our own transactions*/
336342
gpio_disable_interrupt(GPIO_EC_I2C_3_SDA);
343+
i2c_set_timeout(I2C_PORT_TOUCHPAD, 25*MSEC);
337344
i2c_lock(I2C_PORT_TOUCHPAD, 1);
338345
rv = i2c_xfer_unlocked(I2C_PORT_TOUCHPAD,
339346
TOUCHPAD_I2C_HID_EP | I2C_FLAG_ADDR16_LITTLE_ENDIAN,
@@ -362,11 +369,13 @@ void read_touchpad_in_report(void)
362369
/* try again some other time later if the TP keeps interrupting us */
363370
detected_host_packet = true;
364371
inreport_retries = 0;
372+
usleep(10*MSEC);
373+
/*The EC SMB controller sometimes gets in a bad state, so try to recover */
365374
MCHP_I2C_CTRL(MCHP_I2C_CTRL4) = BIT(7) |
366375
BIT(6) |
367376
BIT(3) |
368377
BIT(0);
369-
CPRINTS("PS2M Too many retries");
378+
CPRINTS("PS2M %d Too many retries", rv);
370379
} else {
371380
hook_call_deferred(&retry_tp_read_evt_deferred_data, 25*MSEC);
372381
}
@@ -413,6 +422,7 @@ void read_touchpad_in_report(void)
413422
setup_touchpad();
414423
}
415424
}
425+
416426
}
417427
/*
418428
* Looking at timing it takes the SOC about 2ms to grab a tp packet from start of
@@ -423,6 +433,7 @@ void mouse_interrupt_handler_task(void *p)
423433
{
424434
int power_state = 0;
425435
int evt;
436+
int i;
426437

427438
emumouse_task_id = task_get_current();
428439
while (1) {
@@ -445,14 +456,18 @@ void mouse_interrupt_handler_task(void *p)
445456
if (evt & PS2MOUSE_EVT_AUX_DATA) {
446457
process_request(aux_data);
447458
} else if (evt & PS2MOUSE_EVT_INTERRUPT) {
448-
usleep(4*MSEC);
449459
/* at the expensive of a slight additional latency
450460
* check to see if the soc has grabbed this out from under us
451461
*/
452-
if (gpio_get_level(GPIO_SOC_TP_INT_L) == 1) {
453-
CPRINTS("PS2M Detected host packet during interrupt handling");
454-
detected_host_packet = true;
455-
} else {
462+
for (i = 0; i < 4; i++) {
463+
usleep(MSEC);
464+
if (gpio_get_level(GPIO_SOC_TP_INT_L) == 1) {
465+
CPRINTS("PS2M Detected host packet during interrupt handling");
466+
detected_host_packet = true;
467+
break;
468+
}
469+
}
470+
if (detected_host_packet != true) {
456471
read_touchpad_in_report();
457472
}
458473
}
@@ -479,7 +494,7 @@ void mouse_interrupt_handler_task(void *p)
479494
if ((power_state == POWER_S3S0) && gpio_get_level(GPIO_SOC_TP_INT_L) == 0) {
480495
read_touchpad_in_report();
481496
}
482-
if (power_state == POWER_S0S3) {
497+
if (power_state == POWER_S0S3 || power_state == POWER_S5) {
483498
/* Power Down */
484499
gpio_disable_interrupt(GPIO_SOC_TP_INT_L);
485500
gpio_disable_interrupt(GPIO_EC_I2C_3_SDA);

board/hx20/ps2mouse.h

+2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ enum ps2_mouse_task_evt {
7070

7171
#define TOUCHPAD_I2C_RETRY_COUNT_TO_RENABLE 6
7272

73+
#define AUX_BUFFER_FULL_RETRIES 25
74+
7375
enum pixart_pct3854_regs {
7476
PCT3854_DESCRIPTOR = 0x0020,
7577
PCT3854_REPORT_DESC = 0x0021,

0 commit comments

Comments
 (0)