return ret;
}
-static int mxt_lookup_bootloader_address(struct mxt_data *data)
+static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry)
{
u8 appmode = data->client->addr;
u8 bootloader;
case 0x4a:
case 0x4b:
/* Chips after 1664S use different scheme */
- if (data->info.family_id >= 0xa2) {
+ if (retry || data->info.family_id >= 0xa2) {
bootloader = appmode - 0x24;
break;
}
return 0;
}
-static int mxt_probe_bootloader(struct mxt_data *data)
+static int mxt_probe_bootloader(struct mxt_data *data, bool retry)
{
struct device *dev = &data->client->dev;
int ret;
u8 val;
bool crc_failure;
- ret = mxt_lookup_bootloader_address(data);
+ ret = mxt_lookup_bootloader_address(data, retry);
if (ret)
return ret;
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)
{
struct i2c_client *client = data->client;
int error;
+ bool alt_bootloader_addr = false;
+ bool retry = false;
+retry_info:
error = mxt_get_info(data);
if (error) {
- error = mxt_probe_bootloader(data);
- if (error)
- return error;
+retry_bootloader:
+ error = mxt_probe_bootloader(data, alt_bootloader_addr);
+ if (error) {
+ if (alt_bootloader_addr) {
+ /* Chip is not in appmode or bootloader mode */
+ return error;
+ }
- data->in_bootloader = true;
- return 0;
+ dev_info(&client->dev, "Trying alternate bootloader address\n");
+ alt_bootloader_addr = true;
+ goto retry_bootloader;
+ } else {
+ if (retry) {
+ dev_err(&client->dev, "Could not recover from bootloader mode\n");
+ /*
+ * We can reflash from this state, so do not
+ * abort init
+ */
+ data->in_bootloader = true;
+ return 0;
+ }
+
+ /* Attempt to exit bootloader into app mode */
+ mxt_send_bootloader_cmd(data, false);
+ msleep(MXT_FW_RESET_TIME);
+ retry = true;
+ goto retry_info;
+ }
}
/* Get object table information */
if (ret)
goto release_firmware;
- ret = mxt_lookup_bootloader_address(data);
- if (ret)
- goto release_firmware;
-
if (!data->in_bootloader) {
/* Change to the bootloader mode */
data->in_bootloader = true;
goto release_firmware;
msleep(MXT_RESET_TIME);
+
+ /* Do not need to scan since we know family ID */
+ ret = mxt_lookup_bootloader_address(data, 0);
+ if (ret)
+ goto release_firmware;
+ } else {
+ enable_irq(data->irq);
}
mxt_free_object_table(data);
dev_info(dev, "Unlocking bootloader\n");
/* Unlock bootloader */
- ret = mxt_unlock_bootloader(data);
+ ret = mxt_send_bootloader_cmd(data, true);
if (ret)
goto disable_irq;
}