]> xenbits.xensource.com Git - people/aperard/linux-chromebook.git/commitdiff
CHROMIUM: Input: cyapa - More reliable cyapa_get_state.
authorBenson Leung <bleung@chromium.org>
Tue, 20 Nov 2012 07:16:54 +0000 (23:16 -0800)
committerGerrit <chrome-bot@google.com>
Wed, 5 Dec 2012 07:55:06 +0000 (23:55 -0800)
In cyapa_get_state, add an additional check for OP_STATUS_SRC bit
in REG_OP_STATUS. This bit should only be set when in operational
mode.

Under some conditions, the REG_OP_STATUS may return 0x89,
with the device status bits being 0b01, indicating the operational
mode firmware is busy executing a command from the host. Handle this
status and return state CYAPA_STATE_OP if we are not in bootloader based
on OP_STATUS_SRC.

Signed-off-by: Benson Leung <bleung@chromium.org>
BUG=chrome-os-partner:16217
TEST=Test Lumpy (Samsung Series 5 550) and Snow (Samsung Chromebook ARM)
using this driver.
1. Cold boot the system (power on the system from full on)
2. Warm reboot the system (reboot the system using command sudo reboot)
Check that the touchpad is detected in both cases and is functional.
3. Force a firmware update and check that it succeeds.
/opt/google/touchpad/firmware/chromeos_touch_firmwareupdate -d cyapa -f

Furthermore, see crosbug.com/p/16217 for detailed repro steps.
System with this patch should survive the suspend/resume test
with a grounded metal probe touching the touchpad generating activity.
suspend_stress_test --wake_min 0 --wake_max 0 --backup_rtc

Change-Id: Ie2d513a3a868c6914776355222fad21935af88a5
Reviewed-on: https://gerrit.chromium.org/gerrit/38364
Reviewed-by: Daniel Kurtz <djkurtz@chromium.org>
Reviewed-by: Dudley Du <dudl@cypress.com>
Commit-Ready: Benson Leung <bleung@chromium.org>
Tested-by: Benson Leung <bleung@chromium.org>
drivers/input/mouse/cyapa.c

index 1bd05dcc4721a0609c71981dae37842d25c093e7..a05a4a17dcad5cc3d4960b76fb08410936c2c22a 100644 (file)
  * Other values indicate device is in an abnormal state and must be reset.
  */
 #define CYAPA_DEV_NORMAL  0x03
+#define CYAPA_DEV_BUSY    0x01
 
 enum cyapa_state {
        CYAPA_STATE_OP,
@@ -578,32 +579,56 @@ static int cyapa_get_state(struct cyapa *cyapa)
        }
 
        if (ret != BL_STATUS_SIZE)
-               return (ret < 0) ? ret : -EAGAIN;
+               goto error;
 
        cyapa->status[REG_OP_STATUS] = status[REG_OP_STATUS];
        cyapa->status[REG_BL_STATUS] = status[REG_BL_STATUS];
        cyapa->status[REG_BL_ERROR] = status[REG_BL_ERROR];
-       if ((status[REG_OP_STATUS] & OP_STATUS_DEV) == CYAPA_DEV_NORMAL) {
-               cyapa_dbg(cyapa, "device state: operational mode\n");
-               cyapa->state = CYAPA_STATE_OP;
-       } else if (status[REG_BL_STATUS] & BL_STATUS_BUSY) {
-               cyapa_dbg(cyapa, "device state: bootloader busy\n");
-               cyapa->state = CYAPA_STATE_BL_BUSY;
-       } else if (status[REG_BL_ERROR] & BL_ERROR_BOOTLOADING) {
-               cyapa_dbg(cyapa, "device state: bootloader active\n");
-               cyapa->state = CYAPA_STATE_BL_ACTIVE;
+       if ((status[REG_OP_STATUS] & OP_STATUS_SRC) == OP_STATUS_SRC) {
+               switch (status[REG_OP_STATUS] & OP_STATUS_DEV) {
+               case CYAPA_DEV_NORMAL:
+                       cyapa_dbg(cyapa, "device state: operational mode\n");
+                       cyapa->state = CYAPA_STATE_OP;
+                       break;
+               case CYAPA_DEV_BUSY:
+                       cyapa_dbg(cyapa, "device state: operational busy\n");
+                       cyapa->state = CYAPA_STATE_OP;
+                       break;
+               default:
+                       cyapa->debug = true;
+                       cyapa_dbg(cyapa, "device state: unknown\n");
+                       cyapa_dbg(cyapa, "status[REG_OP_STATUS] = 0x%02x\n",
+                                 status[REG_OP_STATUS]);
+                       cyapa_dbg(cyapa, "status[REG_BL_STATUS] = 0x%02x\n",
+                                 status[REG_BL_STATUS]);
+                       cyapa_dbg(cyapa, "status[REG_BL_ERROR] = 0x%02x\n",
+                                 status[REG_BL_ERROR]);
+                       cyapa->state = CYAPA_STATE_NO_DEVICE;
+                       ret = -EAGAIN;
+                       goto error;
+               }
        } else {
-               cyapa_dbg(cyapa, "device state: bootloader idle\n");
-               cyapa_dbg(cyapa, "status[REG_OP_STATUS] = 0x%02x\n",
-                         status[REG_OP_STATUS]);
-               cyapa_dbg(cyapa, "status[REG_BL_STATUS] = 0x%02x\n",
-                         status[REG_BL_STATUS]);
-               cyapa_dbg(cyapa, "status[REG_BL_ERROR] = 0x%02x\n",
-                         status[REG_BL_ERROR]);
-               cyapa->state = CYAPA_STATE_BL_IDLE;
+               if (status[REG_BL_STATUS] & BL_STATUS_BUSY) {
+                       cyapa_dbg(cyapa, "device state: bootloader busy\n");
+                       cyapa->state = CYAPA_STATE_BL_BUSY;
+               } else if (status[REG_BL_ERROR] & BL_ERROR_BOOTLOADING) {
+                       cyapa_dbg(cyapa, "device state: bootloader active\n");
+                       cyapa->state = CYAPA_STATE_BL_ACTIVE;
+               } else {
+                       cyapa_dbg(cyapa, "device state: bootloader idle\n");
+                       cyapa_dbg(cyapa, "status[REG_OP_STATUS] = 0x%02x\n",
+                                 status[REG_OP_STATUS]);
+                       cyapa_dbg(cyapa, "status[REG_BL_STATUS] = 0x%02x\n",
+                                 status[REG_BL_STATUS]);
+                       cyapa_dbg(cyapa, "status[REG_BL_ERROR] = 0x%02x\n",
+                                 status[REG_BL_ERROR]);
+                       cyapa->state = CYAPA_STATE_BL_IDLE;
+               }
        }
 
        return 0;
+error:
+       return (ret < 0) ? ret : -EAGAIN;
 }
 
 /*