Commit a4a2ef46 authored by Iiro Valkonen's avatar Iiro Valkonen Committed by Dmitry Torokhov

Input: atmel_mxt_ts - make wait-after-reset period compatible with all chips

The delay before the chip can be accessed after reset varies between
different chips in maXTouch family. Waiting for an interrupt and a T6
status message with the RESET bit set is a better behaviour.
Signed-off-by: default avatarNick Dyer <nick.dyer@itdev.co.uk>
Acked-by: default avatarBenson Leung <bleung@chromium.org>
Acked-by: default avatarYufeng Shen <miletus@chromium.org>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent a0434b75
...@@ -87,6 +87,9 @@ ...@@ -87,6 +87,9 @@
#define MXT_COMMAND_REPORTALL 3 #define MXT_COMMAND_REPORTALL 3
#define MXT_COMMAND_DIAGNOSTIC 5 #define MXT_COMMAND_DIAGNOSTIC 5
/* Define for T6 status byte */
#define MXT_T6_STATUS_RESET (1 << 7)
/* MXT_GEN_POWER_T7 field */ /* MXT_GEN_POWER_T7 field */
#define MXT_POWER_IDLEACQINT 0 #define MXT_POWER_IDLEACQINT 0
#define MXT_POWER_ACTVACQINT 1 #define MXT_POWER_ACTVACQINT 1
...@@ -178,9 +181,13 @@ ...@@ -178,9 +181,13 @@
/* Define for MXT_GEN_COMMAND_T6 */ /* Define for MXT_GEN_COMMAND_T6 */
#define MXT_BOOT_VALUE 0xa5 #define MXT_BOOT_VALUE 0xa5
#define MXT_RESET_VALUE 0x01
#define MXT_BACKUP_VALUE 0x55 #define MXT_BACKUP_VALUE 0x55
/* Delay times */
#define MXT_BACKUP_TIME 50 /* msec */ #define MXT_BACKUP_TIME 50 /* msec */
#define MXT_RESET_TIME 200 /* msec */ #define MXT_RESET_TIME 200 /* msec */
#define MXT_RESET_TIMEOUT 3000 /* msec */
#define MXT_FW_RESET_TIME 3000 /* msec */ #define MXT_FW_RESET_TIME 3000 /* msec */
#define MXT_FW_CHG_TIMEOUT 300 /* msec */ #define MXT_FW_CHG_TIMEOUT 300 /* msec */
...@@ -255,12 +262,16 @@ struct mxt_data { ...@@ -255,12 +262,16 @@ struct mxt_data {
/* Cached parameters from object table */ /* Cached parameters from object table */
u8 T6_reportid; u8 T6_reportid;
u16 T6_address;
u8 T9_reportid_min; u8 T9_reportid_min;
u8 T9_reportid_max; u8 T9_reportid_max;
u8 T19_reportid; u8 T19_reportid;
/* for fw update in bootloader */ /* for fw update in bootloader */
struct completion bl_completion; struct completion bl_completion;
/* for reset handling */
struct completion reset_completion;
}; };
static size_t mxt_obj_size(const struct mxt_object *obj) static size_t mxt_obj_size(const struct mxt_object *obj)
...@@ -344,10 +355,11 @@ static void mxt_dump_message(struct device *dev, ...@@ -344,10 +355,11 @@ static void mxt_dump_message(struct device *dev,
message->reportid, 7, message->message); message->reportid, 7, message->message);
} }
static int mxt_wait_for_chg(struct mxt_data *data, unsigned int timeout_ms) static int mxt_wait_for_completion(struct mxt_data *data,
struct completion *comp,
unsigned int timeout_ms)
{ {
struct device *dev = &data->client->dev; struct device *dev = &data->client->dev;
struct completion *comp = &data->bl_completion;
unsigned long timeout = msecs_to_jiffies(timeout_ms); unsigned long timeout = msecs_to_jiffies(timeout_ms);
long ret; long ret;
...@@ -375,7 +387,8 @@ static int mxt_check_bootloader(struct mxt_data *data, unsigned int state) ...@@ -375,7 +387,8 @@ static int mxt_check_bootloader(struct mxt_data *data, unsigned int state)
* CHG assertion before reading the status byte. * CHG assertion before reading the status byte.
* Once the status byte has been read, the line is deasserted. * Once the status byte has been read, the line is deasserted.
*/ */
ret = mxt_wait_for_chg(data, MXT_FW_CHG_TIMEOUT); ret = mxt_wait_for_completion(data, &data->bl_completion,
MXT_FW_CHG_TIMEOUT);
if (ret) { if (ret) {
/* /*
* TODO: handle -ERESTARTSYS better by terminating * TODO: handle -ERESTARTSYS better by terminating
...@@ -654,6 +667,9 @@ static irqreturn_t mxt_process_messages_until_invalid(struct mxt_data *data) ...@@ -654,6 +667,9 @@ static irqreturn_t mxt_process_messages_until_invalid(struct mxt_data *data)
unsigned csum = mxt_extract_T6_csum(&payload[1]); unsigned csum = mxt_extract_T6_csum(&payload[1]);
dev_dbg(dev, "Status: %02x Config Checksum: %06x\n", dev_dbg(dev, "Status: %02x Config Checksum: %06x\n",
status, csum); status, csum);
if (status & MXT_T6_STATUS_RESET)
complete(&data->reset_completion);
} else if (mxt_is_T9_message(data, &message)) { } else if (mxt_is_T9_message(data, &message)) {
int id = reportid - data->T9_reportid_min; int id = reportid - data->T9_reportid_min;
mxt_input_touchevent(data, &message, id); mxt_input_touchevent(data, &message, id);
...@@ -687,6 +703,59 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id) ...@@ -687,6 +703,59 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id)
return mxt_process_messages_until_invalid(data); return mxt_process_messages_until_invalid(data);
} }
static int mxt_t6_command(struct mxt_data *data, u16 cmd_offset,
u8 value, bool wait)
{
u16 reg;
u8 command_register;
int timeout_counter = 0;
int ret;
reg = data->T6_address + cmd_offset;
ret = mxt_write_reg(data->client, reg, value);
if (ret)
return ret;
if (!wait)
return 0;
do {
msleep(20);
ret = __mxt_read_reg(data->client, reg, 1, &command_register);
if (ret)
return ret;
} while (command_register != 0 && timeout_counter++ <= 100);
if (timeout_counter > 100) {
dev_err(&data->client->dev, "Command failed!\n");
return -EIO;
}
return 0;
}
static int mxt_soft_reset(struct mxt_data *data)
{
struct device *dev = &data->client->dev;
int ret = 0;
dev_info(dev, "Resetting chip\n");
reinit_completion(&data->reset_completion);
ret = mxt_t6_command(data, MXT_COMMAND_RESET, MXT_RESET_VALUE, false);
if (ret)
return ret;
ret = mxt_wait_for_completion(data, &data->reset_completion,
MXT_RESET_TIMEOUT);
if (ret)
return ret;
return 0;
}
static int mxt_check_reg_init(struct mxt_data *data) static int mxt_check_reg_init(struct mxt_data *data)
{ {
const struct mxt_platform_data *pdata = data->pdata; const struct mxt_platform_data *pdata = data->pdata;
...@@ -800,6 +869,7 @@ static int mxt_get_object_table(struct mxt_data *data) ...@@ -800,6 +869,7 @@ static int mxt_get_object_table(struct mxt_data *data)
switch (object->type) { switch (object->type) {
case MXT_GEN_COMMAND_T6: case MXT_GEN_COMMAND_T6:
data->T6_reportid = min_id; data->T6_reportid = min_id;
data->T6_address = object->start_address;
break; break;
case MXT_TOUCH_MULTI_T9: case MXT_TOUCH_MULTI_T9:
data->T9_reportid_min = min_id; data->T9_reportid_min = min_id;
...@@ -853,16 +923,10 @@ static int mxt_initialize(struct mxt_data *data) ...@@ -853,16 +923,10 @@ static int mxt_initialize(struct mxt_data *data)
if (error) if (error)
goto err_free_object_table; goto err_free_object_table;
/* Backup to memory */ error = mxt_t6_command(data, MXT_COMMAND_BACKUPNV,
mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_BACKUP_VALUE, false);
MXT_COMMAND_BACKUPNV, if (!error)
MXT_BACKUP_VALUE); mxt_soft_reset(data);
msleep(MXT_BACKUP_TIME);
/* Soft reset */
mxt_write_object(data, MXT_GEN_COMMAND_T6,
MXT_COMMAND_RESET, 1);
msleep(MXT_RESET_TIME);
/* Update matrix size at info struct */ /* Update matrix size at info struct */
error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val); error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
...@@ -1004,8 +1068,10 @@ static int mxt_load_fw(struct device *dev, const char *fn) ...@@ -1004,8 +1068,10 @@ static int mxt_load_fw(struct device *dev, const char *fn)
/* Change to the bootloader mode */ /* Change to the bootloader mode */
data->in_bootloader = true; data->in_bootloader = true;
mxt_write_object(data, MXT_GEN_COMMAND_T6, ret = mxt_t6_command(data, MXT_COMMAND_RESET, MXT_BOOT_VALUE, false);
MXT_COMMAND_RESET, MXT_BOOT_VALUE); if (ret)
goto release_firmware;
msleep(MXT_RESET_TIME); msleep(MXT_RESET_TIME);
/* Change to slave address of bootloader */ /* Change to slave address of bootloader */
...@@ -1048,7 +1114,8 @@ static int mxt_load_fw(struct device *dev, const char *fn) ...@@ -1048,7 +1114,8 @@ static int mxt_load_fw(struct device *dev, const char *fn)
} }
/* Wait for flash. */ /* Wait for flash. */
ret = mxt_wait_for_chg(data, MXT_FW_RESET_TIME); ret = mxt_wait_for_completion(data, &data->bl_completion,
MXT_FW_RESET_TIME);
if (ret) if (ret)
goto disable_irq; goto disable_irq;
...@@ -1057,12 +1124,13 @@ static int mxt_load_fw(struct device *dev, const char *fn) ...@@ -1057,12 +1124,13 @@ static int mxt_load_fw(struct device *dev, const char *fn)
* the CHG line after bootloading has finished, so ignore potential * the CHG line after bootloading has finished, so ignore potential
* errors. * errors.
*/ */
mxt_wait_for_chg(data, MXT_FW_RESET_TIME); mxt_wait_for_completion(data, &data->bl_completion, MXT_FW_RESET_TIME);
data->in_bootloader = false; data->in_bootloader = false;
disable_irq: disable_irq:
disable_irq(data->irq); disable_irq(data->irq);
release_firmware:
release_firmware(fw); release_firmware(fw);
/* Change to slave address of application */ /* Change to slave address of application */
...@@ -1187,6 +1255,7 @@ static int mxt_probe(struct i2c_client *client, ...@@ -1187,6 +1255,7 @@ static int mxt_probe(struct i2c_client *client,
data->irq = client->irq; data->irq = client->irq;
init_completion(&data->bl_completion); init_completion(&data->bl_completion);
init_completion(&data->reset_completion);
mxt_calc_resolution(data); mxt_calc_resolution(data);
...@@ -1314,11 +1383,7 @@ static int mxt_resume(struct device *dev) ...@@ -1314,11 +1383,7 @@ static int mxt_resume(struct device *dev)
struct mxt_data *data = i2c_get_clientdata(client); struct mxt_data *data = i2c_get_clientdata(client);
struct input_dev *input_dev = data->input_dev; struct input_dev *input_dev = data->input_dev;
/* Soft reset */ mxt_soft_reset(data);
mxt_write_object(data, MXT_GEN_COMMAND_T6,
MXT_COMMAND_RESET, 1);
msleep(MXT_RESET_TIME);
mutex_lock(&input_dev->mutex); mutex_lock(&input_dev->mutex);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment