diff options
author | Iiro Valkonen <iiro.valkonen@atmel.com> | 2014-05-19 02:03:44 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-05-19 02:27:25 -0400 |
commit | a4a2ef462a5fb3a2d66cbf98dab124f34926f6bb (patch) | |
tree | 7bfc79e513e11a0090fd9eb83845ecdd83937dcf | |
parent | a0434b751d0a2cc29d264f26a48962c1648aac10 (diff) |
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: Nick Dyer <nick.dyer@itdev.co.uk>
Acked-by: Benson Leung <bleung@chromium.org>
Acked-by: Yufeng Shen <miletus@chromium.org>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r-- | drivers/input/touchscreen/atmel_mxt_ts.c | 109 |
1 files changed, 87 insertions, 22 deletions
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index d5b30434c4ac..d3aef870d255 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
@@ -87,6 +87,9 @@ | |||
87 | #define MXT_COMMAND_REPORTALL 3 | 87 | #define MXT_COMMAND_REPORTALL 3 |
88 | #define MXT_COMMAND_DIAGNOSTIC 5 | 88 | #define MXT_COMMAND_DIAGNOSTIC 5 |
89 | 89 | ||
90 | /* Define for T6 status byte */ | ||
91 | #define MXT_T6_STATUS_RESET (1 << 7) | ||
92 | |||
90 | /* MXT_GEN_POWER_T7 field */ | 93 | /* MXT_GEN_POWER_T7 field */ |
91 | #define MXT_POWER_IDLEACQINT 0 | 94 | #define MXT_POWER_IDLEACQINT 0 |
92 | #define MXT_POWER_ACTVACQINT 1 | 95 | #define MXT_POWER_ACTVACQINT 1 |
@@ -178,9 +181,13 @@ | |||
178 | 181 | ||
179 | /* Define for MXT_GEN_COMMAND_T6 */ | 182 | /* Define for MXT_GEN_COMMAND_T6 */ |
180 | #define MXT_BOOT_VALUE 0xa5 | 183 | #define MXT_BOOT_VALUE 0xa5 |
184 | #define MXT_RESET_VALUE 0x01 | ||
181 | #define MXT_BACKUP_VALUE 0x55 | 185 | #define MXT_BACKUP_VALUE 0x55 |
186 | |||
187 | /* Delay times */ | ||
182 | #define MXT_BACKUP_TIME 50 /* msec */ | 188 | #define MXT_BACKUP_TIME 50 /* msec */ |
183 | #define MXT_RESET_TIME 200 /* msec */ | 189 | #define MXT_RESET_TIME 200 /* msec */ |
190 | #define MXT_RESET_TIMEOUT 3000 /* msec */ | ||
184 | #define MXT_FW_RESET_TIME 3000 /* msec */ | 191 | #define MXT_FW_RESET_TIME 3000 /* msec */ |
185 | #define MXT_FW_CHG_TIMEOUT 300 /* msec */ | 192 | #define MXT_FW_CHG_TIMEOUT 300 /* msec */ |
186 | 193 | ||
@@ -255,12 +262,16 @@ struct mxt_data { | |||
255 | 262 | ||
256 | /* Cached parameters from object table */ | 263 | /* Cached parameters from object table */ |
257 | u8 T6_reportid; | 264 | u8 T6_reportid; |
265 | u16 T6_address; | ||
258 | u8 T9_reportid_min; | 266 | u8 T9_reportid_min; |
259 | u8 T9_reportid_max; | 267 | u8 T9_reportid_max; |
260 | u8 T19_reportid; | 268 | u8 T19_reportid; |
261 | 269 | ||
262 | /* for fw update in bootloader */ | 270 | /* for fw update in bootloader */ |
263 | struct completion bl_completion; | 271 | struct completion bl_completion; |
272 | |||
273 | /* for reset handling */ | ||
274 | struct completion reset_completion; | ||
264 | }; | 275 | }; |
265 | 276 | ||
266 | static size_t mxt_obj_size(const struct mxt_object *obj) | 277 | static size_t mxt_obj_size(const struct mxt_object *obj) |
@@ -344,10 +355,11 @@ static void mxt_dump_message(struct device *dev, | |||
344 | message->reportid, 7, message->message); | 355 | message->reportid, 7, message->message); |
345 | } | 356 | } |
346 | 357 | ||
347 | static int mxt_wait_for_chg(struct mxt_data *data, unsigned int timeout_ms) | 358 | static int mxt_wait_for_completion(struct mxt_data *data, |
359 | struct completion *comp, | ||
360 | unsigned int timeout_ms) | ||
348 | { | 361 | { |
349 | struct device *dev = &data->client->dev; | 362 | struct device *dev = &data->client->dev; |
350 | struct completion *comp = &data->bl_completion; | ||
351 | unsigned long timeout = msecs_to_jiffies(timeout_ms); | 363 | unsigned long timeout = msecs_to_jiffies(timeout_ms); |
352 | long ret; | 364 | long ret; |
353 | 365 | ||
@@ -375,7 +387,8 @@ recheck: | |||
375 | * CHG assertion before reading the status byte. | 387 | * CHG assertion before reading the status byte. |
376 | * Once the status byte has been read, the line is deasserted. | 388 | * Once the status byte has been read, the line is deasserted. |
377 | */ | 389 | */ |
378 | ret = mxt_wait_for_chg(data, MXT_FW_CHG_TIMEOUT); | 390 | ret = mxt_wait_for_completion(data, &data->bl_completion, |
391 | MXT_FW_CHG_TIMEOUT); | ||
379 | if (ret) { | 392 | if (ret) { |
380 | /* | 393 | /* |
381 | * TODO: handle -ERESTARTSYS better by terminating | 394 | * TODO: handle -ERESTARTSYS better by terminating |
@@ -654,6 +667,9 @@ static irqreturn_t mxt_process_messages_until_invalid(struct mxt_data *data) | |||
654 | unsigned csum = mxt_extract_T6_csum(&payload[1]); | 667 | unsigned csum = mxt_extract_T6_csum(&payload[1]); |
655 | dev_dbg(dev, "Status: %02x Config Checksum: %06x\n", | 668 | dev_dbg(dev, "Status: %02x Config Checksum: %06x\n", |
656 | status, csum); | 669 | status, csum); |
670 | |||
671 | if (status & MXT_T6_STATUS_RESET) | ||
672 | complete(&data->reset_completion); | ||
657 | } else if (mxt_is_T9_message(data, &message)) { | 673 | } else if (mxt_is_T9_message(data, &message)) { |
658 | int id = reportid - data->T9_reportid_min; | 674 | int id = reportid - data->T9_reportid_min; |
659 | mxt_input_touchevent(data, &message, id); | 675 | mxt_input_touchevent(data, &message, id); |
@@ -687,6 +703,59 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id) | |||
687 | return mxt_process_messages_until_invalid(data); | 703 | return mxt_process_messages_until_invalid(data); |
688 | } | 704 | } |
689 | 705 | ||
706 | static int mxt_t6_command(struct mxt_data *data, u16 cmd_offset, | ||
707 | u8 value, bool wait) | ||
708 | { | ||
709 | u16 reg; | ||
710 | u8 command_register; | ||
711 | int timeout_counter = 0; | ||
712 | int ret; | ||
713 | |||
714 | reg = data->T6_address + cmd_offset; | ||
715 | |||
716 | ret = mxt_write_reg(data->client, reg, value); | ||
717 | if (ret) | ||
718 | return ret; | ||
719 | |||
720 | if (!wait) | ||
721 | return 0; | ||
722 | |||
723 | do { | ||
724 | msleep(20); | ||
725 | ret = __mxt_read_reg(data->client, reg, 1, &command_register); | ||
726 | if (ret) | ||
727 | return ret; | ||
728 | } while (command_register != 0 && timeout_counter++ <= 100); | ||
729 | |||
730 | if (timeout_counter > 100) { | ||
731 | dev_err(&data->client->dev, "Command failed!\n"); | ||
732 | return -EIO; | ||
733 | } | ||
734 | |||
735 | return 0; | ||
736 | } | ||
737 | |||
738 | static int mxt_soft_reset(struct mxt_data *data) | ||
739 | { | ||
740 | struct device *dev = &data->client->dev; | ||
741 | int ret = 0; | ||
742 | |||
743 | dev_info(dev, "Resetting chip\n"); | ||
744 | |||
745 | reinit_completion(&data->reset_completion); | ||
746 | |||
747 | ret = mxt_t6_command(data, MXT_COMMAND_RESET, MXT_RESET_VALUE, false); | ||
748 | if (ret) | ||
749 | return ret; | ||
750 | |||
751 | ret = mxt_wait_for_completion(data, &data->reset_completion, | ||
752 | MXT_RESET_TIMEOUT); | ||
753 | if (ret) | ||
754 | return ret; | ||
755 | |||
756 | return 0; | ||
757 | } | ||
758 | |||
690 | static int mxt_check_reg_init(struct mxt_data *data) | 759 | static int mxt_check_reg_init(struct mxt_data *data) |
691 | { | 760 | { |
692 | const struct mxt_platform_data *pdata = data->pdata; | 761 | const struct mxt_platform_data *pdata = data->pdata; |
@@ -800,6 +869,7 @@ static int mxt_get_object_table(struct mxt_data *data) | |||
800 | switch (object->type) { | 869 | switch (object->type) { |
801 | case MXT_GEN_COMMAND_T6: | 870 | case MXT_GEN_COMMAND_T6: |
802 | data->T6_reportid = min_id; | 871 | data->T6_reportid = min_id; |
872 | data->T6_address = object->start_address; | ||
803 | break; | 873 | break; |
804 | case MXT_TOUCH_MULTI_T9: | 874 | case MXT_TOUCH_MULTI_T9: |
805 | data->T9_reportid_min = min_id; | 875 | data->T9_reportid_min = min_id; |
@@ -853,16 +923,10 @@ static int mxt_initialize(struct mxt_data *data) | |||
853 | if (error) | 923 | if (error) |
854 | goto err_free_object_table; | 924 | goto err_free_object_table; |
855 | 925 | ||
856 | /* Backup to memory */ | 926 | error = mxt_t6_command(data, MXT_COMMAND_BACKUPNV, |
857 | mxt_write_object(data, MXT_GEN_COMMAND_T6, | 927 | MXT_BACKUP_VALUE, false); |
858 | MXT_COMMAND_BACKUPNV, | 928 | if (!error) |
859 | MXT_BACKUP_VALUE); | 929 | mxt_soft_reset(data); |
860 | msleep(MXT_BACKUP_TIME); | ||
861 | |||
862 | /* Soft reset */ | ||
863 | mxt_write_object(data, MXT_GEN_COMMAND_T6, | ||
864 | MXT_COMMAND_RESET, 1); | ||
865 | msleep(MXT_RESET_TIME); | ||
866 | 930 | ||
867 | /* Update matrix size at info struct */ | 931 | /* Update matrix size at info struct */ |
868 | error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val); | 932 | 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 | /* Change to the bootloader mode */ | 1068 | /* Change to the bootloader mode */ |
1005 | data->in_bootloader = true; | 1069 | data->in_bootloader = true; |
1006 | 1070 | ||
1007 | mxt_write_object(data, MXT_GEN_COMMAND_T6, | 1071 | ret = mxt_t6_command(data, MXT_COMMAND_RESET, MXT_BOOT_VALUE, false); |
1008 | MXT_COMMAND_RESET, MXT_BOOT_VALUE); | 1072 | if (ret) |
1073 | goto release_firmware; | ||
1074 | |||
1009 | msleep(MXT_RESET_TIME); | 1075 | msleep(MXT_RESET_TIME); |
1010 | 1076 | ||
1011 | /* Change to slave address of bootloader */ | 1077 | /* Change to slave address of bootloader */ |
@@ -1048,7 +1114,8 @@ static int mxt_load_fw(struct device *dev, const char *fn) | |||
1048 | } | 1114 | } |
1049 | 1115 | ||
1050 | /* Wait for flash. */ | 1116 | /* Wait for flash. */ |
1051 | ret = mxt_wait_for_chg(data, MXT_FW_RESET_TIME); | 1117 | ret = mxt_wait_for_completion(data, &data->bl_completion, |
1118 | MXT_FW_RESET_TIME); | ||
1052 | if (ret) | 1119 | if (ret) |
1053 | goto disable_irq; | 1120 | goto disable_irq; |
1054 | 1121 | ||
@@ -1057,12 +1124,13 @@ static int mxt_load_fw(struct device *dev, const char *fn) | |||
1057 | * the CHG line after bootloading has finished, so ignore potential | 1124 | * the CHG line after bootloading has finished, so ignore potential |
1058 | * errors. | 1125 | * errors. |
1059 | */ | 1126 | */ |
1060 | mxt_wait_for_chg(data, MXT_FW_RESET_TIME); | 1127 | mxt_wait_for_completion(data, &data->bl_completion, MXT_FW_RESET_TIME); |
1061 | 1128 | ||
1062 | data->in_bootloader = false; | 1129 | data->in_bootloader = false; |
1063 | 1130 | ||
1064 | disable_irq: | 1131 | disable_irq: |
1065 | disable_irq(data->irq); | 1132 | disable_irq(data->irq); |
1133 | release_firmware: | ||
1066 | release_firmware(fw); | 1134 | release_firmware(fw); |
1067 | 1135 | ||
1068 | /* Change to slave address of application */ | 1136 | /* Change to slave address of application */ |
@@ -1187,6 +1255,7 @@ static int mxt_probe(struct i2c_client *client, | |||
1187 | data->irq = client->irq; | 1255 | data->irq = client->irq; |
1188 | 1256 | ||
1189 | init_completion(&data->bl_completion); | 1257 | init_completion(&data->bl_completion); |
1258 | init_completion(&data->reset_completion); | ||
1190 | 1259 | ||
1191 | mxt_calc_resolution(data); | 1260 | mxt_calc_resolution(data); |
1192 | 1261 | ||
@@ -1314,11 +1383,7 @@ static int mxt_resume(struct device *dev) | |||
1314 | struct mxt_data *data = i2c_get_clientdata(client); | 1383 | struct mxt_data *data = i2c_get_clientdata(client); |
1315 | struct input_dev *input_dev = data->input_dev; | 1384 | struct input_dev *input_dev = data->input_dev; |
1316 | 1385 | ||
1317 | /* Soft reset */ | 1386 | mxt_soft_reset(data); |
1318 | mxt_write_object(data, MXT_GEN_COMMAND_T6, | ||
1319 | MXT_COMMAND_RESET, 1); | ||
1320 | |||
1321 | msleep(MXT_RESET_TIME); | ||
1322 | 1387 | ||
1323 | mutex_lock(&input_dev->mutex); | 1388 | mutex_lock(&input_dev->mutex); |
1324 | 1389 | ||