summaryrefslogtreecommitdiff
path: root/drivers/input/touchscreen/atmel_mxt_ts.c
diff options
context:
space:
mode:
authorNick Dyer <nick.dyer@itdev.co.uk>2011-10-07 16:14:29 +0100
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 12:37:36 -0700
commitcb81e3f2e13dad30cd432f33154392f3dd80c068 (patch)
tree36cb08d80a5a68c68f4cdb2eec55c3aacf4df04a /drivers/input/touchscreen/atmel_mxt_ts.c
parent0b7779dca31037d946feec6a0fa9a0f7cd361063 (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.c144
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)