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;
        }