summaryrefslogtreecommitdiff
path: root/drivers/input/touchscreen/atmel_mxt_ts.c
diff options
context:
space:
mode:
authorNick Dyer <nick.dyer@itdev.co.uk>2012-08-15 12:39:31 +0100
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 12:37:51 -0700
commitea2d0270bb563b856947254997ff0d66391e06ea (patch)
tree6d535296fcef682c8942c664f701c6391d0ec47a /drivers/input/touchscreen/atmel_mxt_ts.c
parent7234d797ff083cb52dfd33e1808a126e9bc27e79 (diff)
Input: atmel_mxt_ts - recover from bootloader on probe
The MXT device may be in bootloader mode on probe, for two reasons 1) APP CRC failure, which is either due to a) flash corruption b) bad power or other intermittent problem in checking CRC 2) If the power has been cycled 10 or more times without accessing comms 3) Warm probe, device was in bootloader mode already This code attempts to recover from 1(b) and 3. Signed-off-by: Nick Dyer <nick.dyer@itdev.co.uk> Rebase-Id: R2c0a6fd26a6de00bc235d39d667907a739ab3281
Diffstat (limited to 'drivers/input/touchscreen/atmel_mxt_ts.c')
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c35
1 files changed, 28 insertions, 7 deletions
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index aed1310e2e54..4eea8b0b311d 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -516,13 +516,18 @@ recheck:
return 0;
}
-static int mxt_unlock_bootloader(struct mxt_data *data)
+static int mxt_send_bootloader_cmd(struct mxt_data *data, bool unlock)
{
int ret;
u8 buf[2];
- buf[0] = MXT_UNLOCK_CMD_LSB;
- buf[1] = MXT_UNLOCK_CMD_MSB;
+ if (unlock) {
+ buf[0] = MXT_UNLOCK_CMD_LSB;
+ buf[1] = MXT_UNLOCK_CMD_MSB;
+ } else {
+ buf[0] = 0x01;
+ buf[1] = 0x01;
+ }
ret = mxt_bootloader_write(data, buf, 2);
if (ret) {
@@ -1734,16 +1739,32 @@ static int mxt_initialize(struct mxt_data *data)
struct i2c_client *client = data->client;
struct mxt_info *info = &data->info;
int error;
+ u8 retry_count = 0;
+retry_probe:
+ /* Read info block */
error = mxt_read_reg(client, 0, sizeof(*info), info);
if (error) {
error = mxt_probe_bootloader(data);
-
if (error) {
+ /* Chip is not in appmode or bootloader mode */
return error;
} else {
- data->state = BOOTLOADER;
- return 0;
+ if (++retry_count > 10) {
+ dev_err(&client->dev,
+ "Could not recover device from "
+ "bootloader mode\n");
+ data->state = BOOTLOADER;
+ /* this is not an error state, we can reflash
+ * from here */
+ return 0;
+ }
+
+ /* Tell bootloader to enter app mode. Ignore errors
+ * since we're in a retry loop */
+ mxt_send_bootloader_cmd(data, false);
+ msleep(MXT_FWRESET_TIME);
+ goto retry_probe;
}
}
@@ -1860,7 +1881,7 @@ static int mxt_load_fw(struct device *dev, const char *fn)
dev_info(dev, "Unlocking bootloader\n");
/* Unlock bootloader */
- ret = mxt_unlock_bootloader(data);
+ ret = mxt_send_bootloader_cmd(data, true);
if (ret) {
data->state = FAILED;
goto release_firmware;