diff options
author | Nick Dyer <nick.dyer@itdev.co.uk> | 2011-10-07 16:14:29 +0100 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 12:37:36 -0700 |
commit | cb81e3f2e13dad30cd432f33154392f3dd80c068 (patch) | |
tree | 36cb08d80a5a68c68f4cdb2eec55c3aacf4df04a /drivers/input/touchscreen/atmel_mxt_ts.c | |
parent | 0b7779dca31037d946feec6a0fa9a0f7cd361063 (diff) |
Input: atmel_mxt_ts - Implement CRC check for configuration data.
The configuration is stored in NVRAM on the maXTouch chip. When the device is
reset it reports a CRC of the stored configuration values. Therefore it isn't
necessary to send the configuration on each probe - we can check the CRC
matches and avoid a timeconsuming backup/reset cycle.
Signed-off-by: Nick Dyer <nick.dyer@itdev.co.uk>
Rebase-Id: R01e1f28b5a48dd8ff6055faa51914d3605e55234
Diffstat (limited to 'drivers/input/touchscreen/atmel_mxt_ts.c')
-rw-r--r-- | drivers/input/touchscreen/atmel_mxt_ts.c | 144 |
1 files changed, 93 insertions, 51 deletions
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 73ad49452005..bddba256b7f4 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -635,19 +635,79 @@ end: return IRQ_HANDLED; } +static int mxt_make_highchg(struct mxt_data *data) +{ + struct device *dev = &data->client->dev; + struct mxt_message message; + int count = 10; + int error; + + /* Read dummy message to make high CHG pin */ + do { + error = mxt_read_message(data, &message); + if (error) + return error; + } while (message.reportid != MXT_RPTID_NOMSG && --count); + + if (!count) { + dev_err(dev, "CHG pin isn't cleared\n"); + return -EBUSY; + } + + return 0; +} + static int mxt_check_reg_init(struct mxt_data *data) { + struct i2c_client *client = data->client; const struct mxt_platform_data *pdata = data->pdata; struct mxt_object *object; + struct mxt_message message; struct device *dev = &data->client->dev; int index = 0; + int timeout_counter = 0; int i, j, config_offset; + int error; + u32 current_crc; + u8 command_register; if (!pdata->config) { dev_dbg(dev, "No cfg data defined, skipping reg init\n"); return 0; } + /* Try to read the config checksum of the existing cfg */ + mxt_write_object(data, MXT_GEN_COMMAND_T6, + MXT_COMMAND_REPORTALL, 1); + msleep(30); + + error = mxt_read_message(data, &message); + if (error) + return error; + + object = mxt_get_object(data, MXT_GEN_COMMAND_T6); + if (!object) + return -EIO; + + /* Check if this message is from command processor (which has + only one reporting ID), if so, bytes 1-3 are the checksum. */ + if (message.reportid == object->max_reportid) { + current_crc = message.message[1] | (message.message[2] << 8) | + (message.message[3] << 16); + } else { + dev_err(dev, "Failure retrieving cfg checksum, " + "forcing load\n"); + current_crc = 0xFFFFFFFF; + } + + if (current_crc == pdata->config_crc) { + dev_info(dev, "Config CRC 0x%06X: OK\n", current_crc); + return 0; + } else { + dev_info(dev, "Config CRC 0x%06X: does not match file 0x%06X\n", + current_crc, pdata->config_crc); + } + for (i = 0; i < data->info.object_num; i++) { object = data->object_table + i; @@ -668,26 +728,45 @@ static int mxt_check_reg_init(struct mxt_data *data) index += object->size * object->instances; } - return 0; -} + dev_info(dev, "Config written\n"); -static int mxt_make_highchg(struct mxt_data *data) -{ - struct device *dev = &data->client->dev; - struct mxt_message message; - int count = 10; - int error; + error = mxt_make_highchg(data); + if (error) + return error; - /* Read dummy message to make high CHG pin */ + /* Backup to memory */ + mxt_write_object(data, MXT_GEN_COMMAND_T6, + MXT_COMMAND_BACKUPNV, + MXT_BACKUP_VALUE); + msleep(MXT_BACKUP_TIME); do { - error = mxt_read_message(data, &message); + error = mxt_read_object(data, MXT_GEN_COMMAND_T6, + MXT_COMMAND_BACKUPNV, + &command_register); if (error) return error; - } while (message.reportid != MXT_RPTID_NOMSG && --count); + msleep(20); + } while ((command_register != 0) && (timeout_counter++ <= 100)); + if (timeout_counter > 100) { + dev_err(&client->dev, "No response after backup!\n"); + return -EIO; + } - if (!count) { - dev_err(dev, "CHG pin isn't cleared\n"); - return -EBUSY; + /* Soft reset */ + mxt_write_object(data, MXT_GEN_COMMAND_T6, + MXT_COMMAND_RESET, 1); + if (data->pdata->read_chg == NULL) { + msleep(MXT_RESET_NOCHGREAD); + } else { + msleep(MXT_RESET_TIME); + + timeout_counter = 0; + while ((timeout_counter++ <= 100) && data->pdata->read_chg()) + msleep(20); + if (timeout_counter > 100) { + dev_err(&client->dev, "No response after reset!\n"); + return -EIO; + } } return 0; @@ -829,9 +908,7 @@ static int mxt_initialize(struct mxt_data *data) struct i2c_client *client = data->client; struct mxt_info *info = &data->info; int error; - int timeout_counter = 0; u8 val; - u8 command_register; error = mxt_get_info(data); if (error) @@ -862,41 +939,6 @@ static int mxt_initialize(struct mxt_data *data) mxt_handle_pdata(data); - /* Backup to memory */ - mxt_write_object(data, MXT_GEN_COMMAND_T6, - MXT_COMMAND_BACKUPNV, - MXT_BACKUP_VALUE); - msleep(MXT_BACKUP_TIME); - do { - error = mxt_read_object(data, MXT_GEN_COMMAND_T6, - MXT_COMMAND_BACKUPNV, - &command_register); - if (error) - return error; - msleep(20); - } while ((command_register != 0) && (timeout_counter++ <= 100)); - if (timeout_counter > 100) { - dev_err(&client->dev, "No response after backup!\n"); - return -EIO; - } - - /* Soft reset */ - mxt_write_object(data, MXT_GEN_COMMAND_T6, - MXT_COMMAND_RESET, 1); - if (data->pdata->read_chg == NULL) { - msleep(MXT_RESET_NOCHGREAD); - } else { - msleep(MXT_RESET_TIME); - - timeout_counter = 0; - while ((timeout_counter++ <= 100) && data->pdata->read_chg()) - msleep(20); - if (timeout_counter > 100) { - dev_err(&client->dev, "No response after reset!\n"); - return -EIO; - } - } - /* Update matrix size at info struct */ error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val); if (error) |