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 | ||
