aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorNick Dyer <nick.dyer@itdev.co.uk>2014-07-23 15:45:49 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2014-07-23 17:42:11 -0400
commit8efaa5e5a95170fa126798c7a48f0747fdb29862 (patch)
treec625d942dc85eb4301221703a5f8cf7de827c32e /drivers/input
parent44a0bab2154f07d6cb7ec6d929f6875a1f768f41 (diff)
Input: atmel_mxt_ts - recover from bootloader on probe
The MXT device may be in bootloader mode on probe, due to: 1) APP CRC failure, either: a) flash corruption b) bad power or other intermittent problem while checking CRC 2) If the device has been reset 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. There is an additional complexity: we have to try two possible bootloader addresses because the mapping is not one-to-one and we don't know the exact model yet. Signed-off-by: Nick Dyer <nick.dyer@itdev.co.uk> Acked-by: Yufeng Shen <miletus@chromium.org> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c67
1 files changed, 50 insertions, 17 deletions
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index dc8133d6b914..869065c2df83 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -379,7 +379,7 @@ static int mxt_bootloader_write(struct mxt_data *data,
379 return ret; 379 return ret;
380} 380}
381 381
382static int mxt_lookup_bootloader_address(struct mxt_data *data) 382static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry)
383{ 383{
384 u8 appmode = data->client->addr; 384 u8 appmode = data->client->addr;
385 u8 bootloader; 385 u8 bootloader;
@@ -388,7 +388,7 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data)
388 case 0x4a: 388 case 0x4a:
389 case 0x4b: 389 case 0x4b:
390 /* Chips after 1664S use different scheme */ 390 /* Chips after 1664S use different scheme */
391 if (data->info.family_id >= 0xa2) { 391 if (retry || data->info.family_id >= 0xa2) {
392 bootloader = appmode - 0x24; 392 bootloader = appmode - 0x24;
393 break; 393 break;
394 } 394 }
@@ -410,14 +410,14 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data)
410 return 0; 410 return 0;
411} 411}
412 412
413static int mxt_probe_bootloader(struct mxt_data *data) 413static int mxt_probe_bootloader(struct mxt_data *data, bool retry)
414{ 414{
415 struct device *dev = &data->client->dev; 415 struct device *dev = &data->client->dev;
416 int ret; 416 int ret;
417 u8 val; 417 u8 val;
418 bool crc_failure; 418 bool crc_failure;
419 419
420 ret = mxt_lookup_bootloader_address(data); 420 ret = mxt_lookup_bootloader_address(data, retry);
421 if (ret) 421 if (ret)
422 return ret; 422 return ret;
423 423
@@ -518,13 +518,18 @@ recheck:
518 return 0; 518 return 0;
519} 519}
520 520
521static int mxt_unlock_bootloader(struct mxt_data *data) 521static int mxt_send_bootloader_cmd(struct mxt_data *data, bool unlock)
522{ 522{
523 int ret; 523 int ret;
524 u8 buf[2]; 524 u8 buf[2];
525 525
526 buf[0] = MXT_UNLOCK_CMD_LSB; 526 if (unlock) {
527 buf[1] = MXT_UNLOCK_CMD_MSB; 527 buf[0] = MXT_UNLOCK_CMD_LSB;
528 buf[1] = MXT_UNLOCK_CMD_MSB;
529 } else {
530 buf[0] = 0x01;
531 buf[1] = 0x01;
532 }
528 533
529 ret = mxt_bootloader_write(data, buf, 2); 534 ret = mxt_bootloader_write(data, buf, 2);
530 if (ret) 535 if (ret)
@@ -1481,15 +1486,40 @@ static int mxt_initialize(struct mxt_data *data)
1481{ 1486{
1482 struct i2c_client *client = data->client; 1487 struct i2c_client *client = data->client;
1483 int error; 1488 int error;
1489 bool alt_bootloader_addr = false;
1490 bool retry = false;
1484 1491
1492retry_info:
1485 error = mxt_get_info(data); 1493 error = mxt_get_info(data);
1486 if (error) { 1494 if (error) {
1487 error = mxt_probe_bootloader(data); 1495retry_bootloader:
1488 if (error) 1496 error = mxt_probe_bootloader(data, alt_bootloader_addr);
1489 return error; 1497 if (error) {
1498 if (alt_bootloader_addr) {
1499 /* Chip is not in appmode or bootloader mode */
1500 return error;
1501 }
1490 1502
1491 data->in_bootloader = true; 1503 dev_info(&client->dev, "Trying alternate bootloader address\n");
1492 return 0; 1504 alt_bootloader_addr = true;
1505 goto retry_bootloader;
1506 } else {
1507 if (retry) {
1508 dev_err(&client->dev, "Could not recover from bootloader mode\n");
1509 /*
1510 * We can reflash from this state, so do not
1511 * abort init
1512 */
1513 data->in_bootloader = true;
1514 return 0;
1515 }
1516
1517 /* Attempt to exit bootloader into app mode */
1518 mxt_send_bootloader_cmd(data, false);
1519 msleep(MXT_FW_RESET_TIME);
1520 retry = true;
1521 goto retry_info;
1522 }
1493 } 1523 }
1494 1524
1495 /* Get object table information */ 1525 /* Get object table information */
@@ -1664,10 +1694,6 @@ static int mxt_load_fw(struct device *dev, const char *fn)
1664 if (ret) 1694 if (ret)
1665 goto release_firmware; 1695 goto release_firmware;
1666 1696
1667 ret = mxt_lookup_bootloader_address(data);
1668 if (ret)
1669 goto release_firmware;
1670
1671 if (!data->in_bootloader) { 1697 if (!data->in_bootloader) {
1672 /* Change to the bootloader mode */ 1698 /* Change to the bootloader mode */
1673 data->in_bootloader = true; 1699 data->in_bootloader = true;
@@ -1678,6 +1704,13 @@ static int mxt_load_fw(struct device *dev, const char *fn)
1678 goto release_firmware; 1704 goto release_firmware;
1679 1705
1680 msleep(MXT_RESET_TIME); 1706 msleep(MXT_RESET_TIME);
1707
1708 /* Do not need to scan since we know family ID */
1709 ret = mxt_lookup_bootloader_address(data, 0);
1710 if (ret)
1711 goto release_firmware;
1712 } else {
1713 enable_irq(data->irq);
1681 } 1714 }
1682 1715
1683 mxt_free_object_table(data); 1716 mxt_free_object_table(data);
@@ -1693,7 +1726,7 @@ static int mxt_load_fw(struct device *dev, const char *fn)
1693 dev_info(dev, "Unlocking bootloader\n"); 1726 dev_info(dev, "Unlocking bootloader\n");
1694 1727
1695 /* Unlock bootloader */ 1728 /* Unlock bootloader */
1696 ret = mxt_unlock_bootloader(data); 1729 ret = mxt_send_bootloader_cmd(data, true);
1697 if (ret) 1730 if (ret)
1698 goto disable_irq; 1731 goto disable_irq;
1699 } 1732 }