#define MXT_BACKUP_TIME                50      /* msec */
 #define MXT_RESET_TIME         200     /* msec */
 #define MXT_RESET_TIMEOUT      3000    /* msec */
+#define MXT_CRC_TIMEOUT                1000    /* msec */
 #define MXT_FW_RESET_TIME      3000    /* msec */
 #define MXT_FW_CHG_TIMEOUT     300     /* msec */
 
        unsigned int max_x;
        unsigned int max_y;
        bool in_bootloader;
+       u32 config_crc;
 
        /* Cached parameters from object table */
        u8 T6_reportid;
 
        /* for reset handling */
        struct completion reset_completion;
+
+       /* for config update handling */
+       struct completion crc_completion;
 };
 
 static size_t mxt_obj_size(const struct mxt_object *obj)
        }
 }
 
-static unsigned mxt_extract_T6_csum(const u8 *csum)
+static u16 mxt_extract_T6_csum(const u8 *csum)
 {
        return csum[0] | (csum[1] << 8) | (csum[2] << 16);
 }
        struct device *dev = &data->client->dev;
        u8 reportid;
        bool update_input = false;
+       u32 crc;
 
        do {
                if (mxt_read_message(data, &message)) {
 
                if (reportid == data->T6_reportid) {
                        u8 status = payload[0];
-                       unsigned csum = mxt_extract_T6_csum(&payload[1]);
+
+                       crc = mxt_extract_T6_csum(&payload[1]);
+                       if (crc != data->config_crc) {
+                               data->config_crc = crc;
+                               complete(&data->crc_completion);
+                       }
+
                        dev_dbg(dev, "Status: %02x Config Checksum: %06x\n",
-                               status, csum);
+                               status, data->config_crc);
 
                        if (status & MXT_T6_STATUS_RESET)
                                complete(&data->reset_completion);
        return 0;
 }
 
+static void mxt_update_crc(struct mxt_data *data, u8 cmd, u8 value)
+{
+       /*
+        * On failure, CRC is set to 0 and config will always be
+        * downloaded.
+        */
+       data->config_crc = 0;
+       reinit_completion(&data->crc_completion);
+
+       mxt_t6_command(data, cmd, value, true);
+
+       /*
+        * Wait for crc message. On failure, CRC is set to 0 and config will
+        * always be downloaded.
+        */
+       mxt_wait_for_completion(data, &data->crc_completion, MXT_CRC_TIMEOUT);
+}
+
 static int mxt_check_reg_init(struct mxt_data *data)
 {
        const struct mxt_platform_data *pdata = data->pdata;
                return 0;
        }
 
+       mxt_update_crc(data, MXT_COMMAND_REPORTALL, 1);
+
+       if (data->config_crc == pdata->config_crc) {
+               dev_info(dev, "Config CRC 0x%06X: OK\n", data->config_crc);
+               return 0;
+       }
+
+       dev_info(dev, "Config CRC 0x%06X: does not match 0x%06X\n",
+                data->config_crc, pdata->config_crc);
+
        for (i = 0; i < data->info.object_num; i++) {
                object = data->object_table + i;
 
                index += size;
        }
 
+       mxt_update_crc(data, MXT_COMMAND_BACKUPNV, MXT_BACKUP_VALUE);
+
+       ret = mxt_soft_reset(data);
+       if (ret)
+               return ret;
+
+       dev_info(dev, "Config successfully updated\n");
+
        return 0;
 }
 
                goto err_free_object_table;
        }
 
-       error = mxt_t6_command(data, MXT_COMMAND_BACKUPNV,
-                              MXT_BACKUP_VALUE, false);
-       if (!error)
-               mxt_soft_reset(data);
-
        /* Update matrix size at info struct */
        error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
        if (error)
 
        init_completion(&data->bl_completion);
        init_completion(&data->reset_completion);
+       init_completion(&data->crc_completion);
 
        mxt_calc_resolution(data);