@@ -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}
@@ -56,14 +56,16 @@ void send_movement_packet(void)
5656 int max = 3 ;
5757 int timeout = 0 ;
5858
59-
6059 if (five_button_mode )
6160 max = 4 ;
6261 /* sometimes the host will get behind */
63- while (aux_buffer_available () < max && timeout ++ < 25 )
62+ while (aux_buffer_available () < max && timeout ++ < AUX_BUFFER_FULL_RETRIES &&
63+ (* task_get_event_bitmap (emumouse_task_id ) & PS2MOUSE_EVT_AUX_DATA ) == 0 ) {
6464 usleep (10 * MSEC );
65+ }
6566
66- if (timeout == 25 ) {
67+ if (timeout == AUX_BUFFER_FULL_RETRIES ||
68+ (* task_get_event_bitmap (emumouse_task_id ) & PS2MOUSE_EVT_AUX_DATA )) {
6769 CPRINTS ("PS2M Dropping" );
6870 /*drop mouse packet - host is too far behind */
6971 return ;
@@ -328,15 +330,28 @@ void read_touchpad_in_report(void)
328330 int xfer_len = 0 ;
329331 int16_t x , y ;
330332 uint8_t response_byte = 0x08 ;
333+
334+ /* Make sure report id is set to an invalid value */
335+ data [2 ] = 0 ;
336+
337+ if (power_get_state () == POWER_S5 )
338+ return ;
339+
331340 /*dont trigger disable state during our own transactions*/
332341 gpio_disable_interrupt (GPIO_EC_I2C_3_SDA );
342+ i2c_set_timeout (I2C_PORT_TOUCHPAD , 25 * MSEC );
333343 i2c_lock (I2C_PORT_TOUCHPAD , 1 );
334344 rv = i2c_xfer_unlocked (I2C_PORT_TOUCHPAD ,
335345 TOUCHPAD_I2C_HID_EP | I2C_FLAG_ADDR16_LITTLE_ENDIAN ,
336346 NULL , 0 , data , 2 , I2C_XFER_START );
337347 if (rv != EC_SUCCESS )
338348 goto read_failed ;
339349 xfer_len = (data [1 ]<<8 ) + data [0 ];
350+ if (xfer_len == 0 ) {
351+ /* touchpad has reset per i2c-hid-protocol 7.3 */
352+ CPRINTS ("PS2M Touchpad Reset" );
353+ goto read_failed ;
354+ }
340355 xfer_len = MIN (126 , xfer_len - 2 );
341356 rv = i2c_xfer_unlocked (I2C_PORT_TOUCHPAD ,
342357 TOUCHPAD_I2C_HID_EP | I2C_FLAG_ADDR16_LITTLE_ENDIAN ,
@@ -353,7 +368,13 @@ void read_touchpad_in_report(void)
353368 /* try again some other time later if the TP keeps interrupting us */
354369 detected_host_packet = true;
355370 inreport_retries = 0 ;
356- CPRINTS ("PS2M Too many retries" );
371+ usleep (10 * MSEC );
372+ /*The EC SMB controller sometimes gets in a bad state, so try to recover */
373+ MCHP_I2C_CTRL (MCHP_I2C_CTRL4 ) = BIT (7 ) |
374+ BIT (6 ) |
375+ BIT (3 ) |
376+ BIT (0 );
377+ CPRINTS ("PS2M %d Too many retries" , rv );
357378 } else {
358379 hook_call_deferred (& retry_tp_read_evt_deferred_data , 25 * MSEC );
359380 }
@@ -400,6 +421,7 @@ void read_touchpad_in_report(void)
400421 setup_touchpad ();
401422 }
402423 }
424+
403425}
404426/*
405427 * Looking at timing it takes the SOC about 2ms to grab a tp packet from start of
@@ -410,6 +432,7 @@ void mouse_interrupt_handler_task(void *p)
410432{
411433 int power_state = 0 ;
412434 int evt ;
435+ int i ;
413436
414437 emumouse_task_id = task_get_current ();
415438 while (1 ) {
@@ -431,19 +454,20 @@ void mouse_interrupt_handler_task(void *p)
431454 if (ec_mode_disabled == false) {
432455 if (evt & PS2MOUSE_EVT_AUX_DATA ) {
433456 process_request (aux_data );
434- }
435-
436- if (evt & PS2MOUSE_EVT_INTERRUPT ) {
437- usleep (4 * MSEC );
457+ } else if (evt & PS2MOUSE_EVT_INTERRUPT ) {
438458 /* at the expensive of a slight additional latency
439459 * check to see if the soc has grabbed this out from under us
440460 */
441- if (gpio_get_level (GPIO_SOC_TP_INT_L ) == 1 ) {
442- CPRINTS ("PS2M Detected host packet during interrupt handling" );
443- detected_host_packet = true;
444- } else {
445- read_touchpad_in_report ();
461+ for (i = 0 ; i < 4 ; i ++ ) {
462+ usleep (MSEC );
463+ if (gpio_get_level (GPIO_SOC_TP_INT_L ) == 1 ) {
464+ CPRINTS ("PS2M Detected host pkt during int" );
465+ detected_host_packet = true;
466+ break ;
467+ }
446468 }
469+ if (detected_host_packet != true)
470+ read_touchpad_in_report ();
447471 }
448472
449473 if (evt & PS2MOUSE_EVT_I2C_INTERRUPT ) {
@@ -468,7 +492,7 @@ void mouse_interrupt_handler_task(void *p)
468492 if ((power_state == POWER_S3S0 ) && gpio_get_level (GPIO_SOC_TP_INT_L ) == 0 ) {
469493 read_touchpad_in_report ();
470494 }
471- if (power_state == POWER_S0S3 ) {
495+ if (power_state == POWER_S0S3 || power_state == POWER_S5 ) {
472496 /* Power Down */
473497 gpio_disable_interrupt (GPIO_SOC_TP_INT_L );
474498 gpio_disable_interrupt (GPIO_EC_I2C_3_SDA );
0 commit comments