diff options
author | Nick Dyer <nick.dyer@itdev.co.uk> | 2014-05-19 02:10:49 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-05-19 02:27:27 -0400 |
commit | f28a842db6fc25d5ac53d70a9608d38d7a9dcd3a (patch) | |
tree | b7f05212f4cfd2849541af55584f82dd0f86a580 | |
parent | c3f78043d5aea39205a14c580babd87fbdcfa148 (diff) |
Input: atmel_mxt_ts - add additional bootloader addresses
Move bootloaders reads/writes into separate functions. Instead of switching
client->addr, define new field bootloader_addr in mxt_data. Implement
lookup calculation for bootloader addresses.
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 | 138 |
1 files changed, 93 insertions, 45 deletions
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 61f9ef221d12..44c1be65dbb4 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
@@ -29,12 +29,6 @@ | |||
29 | #define MXT_VER_21 21 | 29 | #define MXT_VER_21 21 |
30 | #define MXT_VER_22 22 | 30 | #define MXT_VER_22 22 |
31 | 31 | ||
32 | /* Slave addresses */ | ||
33 | #define MXT_APP_LOW 0x4a | ||
34 | #define MXT_APP_HIGH 0x4b | ||
35 | #define MXT_BOOT_LOW 0x24 | ||
36 | #define MXT_BOOT_HIGH 0x25 | ||
37 | |||
38 | /* Firmware */ | 32 | /* Firmware */ |
39 | #define MXT_FW_NAME "maxtouch.fw" | 33 | #define MXT_FW_NAME "maxtouch.fw" |
40 | 34 | ||
@@ -261,6 +255,7 @@ struct mxt_data { | |||
261 | unsigned int max_y; | 255 | unsigned int max_y; |
262 | bool in_bootloader; | 256 | bool in_bootloader; |
263 | u32 config_crc; | 257 | u32 config_crc; |
258 | u8 bootloader_addr; | ||
264 | 259 | ||
265 | /* Cached parameters from object table */ | 260 | /* Cached parameters from object table */ |
266 | u8 T6_reportid; | 261 | u8 T6_reportid; |
@@ -378,9 +373,82 @@ static int mxt_wait_for_completion(struct mxt_data *data, | |||
378 | return 0; | 373 | return 0; |
379 | } | 374 | } |
380 | 375 | ||
376 | static int mxt_bootloader_read(struct mxt_data *data, | ||
377 | u8 *val, unsigned int count) | ||
378 | { | ||
379 | int ret; | ||
380 | struct i2c_msg msg; | ||
381 | |||
382 | msg.addr = data->bootloader_addr; | ||
383 | msg.flags = data->client->flags & I2C_M_TEN; | ||
384 | msg.flags |= I2C_M_RD; | ||
385 | msg.len = count; | ||
386 | msg.buf = val; | ||
387 | |||
388 | ret = i2c_transfer(data->client->adapter, &msg, 1); | ||
389 | |||
390 | if (ret == 1) { | ||
391 | ret = 0; | ||
392 | } else { | ||
393 | ret = ret < 0 ? ret : -EIO; | ||
394 | dev_err(&data->client->dev, "%s: i2c recv failed (%d)\n", | ||
395 | __func__, ret); | ||
396 | } | ||
397 | |||
398 | return ret; | ||
399 | } | ||
400 | |||
401 | static int mxt_bootloader_write(struct mxt_data *data, | ||
402 | const u8 * const val, unsigned int count) | ||
403 | { | ||
404 | int ret; | ||
405 | struct i2c_msg msg; | ||
406 | |||
407 | msg.addr = data->bootloader_addr; | ||
408 | msg.flags = data->client->flags & I2C_M_TEN; | ||
409 | msg.len = count; | ||
410 | msg.buf = (u8 *)val; | ||
411 | |||
412 | ret = i2c_transfer(data->client->adapter, &msg, 1); | ||
413 | if (ret == 1) { | ||
414 | ret = 0; | ||
415 | } else { | ||
416 | ret = ret < 0 ? ret : -EIO; | ||
417 | dev_err(&data->client->dev, "%s: i2c send failed (%d)\n", | ||
418 | __func__, ret); | ||
419 | } | ||
420 | |||
421 | return ret; | ||
422 | } | ||
423 | |||
424 | static int mxt_lookup_bootloader_address(struct mxt_data *data) | ||
425 | { | ||
426 | u8 appmode = data->client->addr; | ||
427 | u8 bootloader; | ||
428 | |||
429 | switch (appmode) { | ||
430 | case 0x4a: | ||
431 | case 0x4b: | ||
432 | case 0x4c: | ||
433 | case 0x4d: | ||
434 | case 0x5a: | ||
435 | case 0x5b: | ||
436 | bootloader = appmode - 0x26; | ||
437 | break; | ||
438 | default: | ||
439 | dev_err(&data->client->dev, | ||
440 | "Appmode i2c address 0x%02x not found\n", | ||
441 | appmode); | ||
442 | return -EINVAL; | ||
443 | } | ||
444 | |||
445 | data->bootloader_addr = bootloader; | ||
446 | return 0; | ||
447 | } | ||
448 | |||
381 | static int mxt_check_bootloader(struct mxt_data *data, unsigned int state) | 449 | static int mxt_check_bootloader(struct mxt_data *data, unsigned int state) |
382 | { | 450 | { |
383 | struct i2c_client *client = data->client; | 451 | struct device *dev = &data->client->dev; |
384 | u8 val; | 452 | u8 val; |
385 | int ret; | 453 | int ret; |
386 | 454 | ||
@@ -401,15 +469,14 @@ recheck: | |||
401 | * by writing length 0x000 to device (iff we are in | 469 | * by writing length 0x000 to device (iff we are in |
402 | * WAITING_FRAME_DATA state). | 470 | * WAITING_FRAME_DATA state). |
403 | */ | 471 | */ |
404 | dev_err(&client->dev, "Update wait error %d\n", ret); | 472 | dev_err(dev, "Update wait error %d\n", ret); |
405 | return ret; | 473 | return ret; |
406 | } | 474 | } |
407 | } | 475 | } |
408 | 476 | ||
409 | if (i2c_master_recv(client, &val, 1) != 1) { | 477 | ret = mxt_bootloader_read(data, &val, 1); |
410 | dev_err(&client->dev, "%s: i2c recv failed\n", __func__); | 478 | if (ret) |
411 | return -EIO; | 479 | return ret; |
412 | } | ||
413 | 480 | ||
414 | switch (state) { | 481 | switch (state) { |
415 | case MXT_WAITING_BOOTLOAD_CMD: | 482 | case MXT_WAITING_BOOTLOAD_CMD: |
@@ -425,7 +492,7 @@ recheck: | |||
425 | } | 492 | } |
426 | 493 | ||
427 | if (val != state) { | 494 | if (val != state) { |
428 | dev_err(&client->dev, "Invalid bootloader state %02X != %02X\n", | 495 | dev_err(dev, "Invalid bootloader state %02X != %02X\n", |
429 | val, state); | 496 | val, state); |
430 | return -EINVAL; | 497 | return -EINVAL; |
431 | } | 498 | } |
@@ -433,28 +500,17 @@ recheck: | |||
433 | return 0; | 500 | return 0; |
434 | } | 501 | } |
435 | 502 | ||
436 | static int mxt_unlock_bootloader(struct i2c_client *client) | 503 | static int mxt_unlock_bootloader(struct mxt_data *data) |
437 | { | 504 | { |
505 | int ret; | ||
438 | u8 buf[2]; | 506 | u8 buf[2]; |
439 | 507 | ||
440 | buf[0] = MXT_UNLOCK_CMD_LSB; | 508 | buf[0] = MXT_UNLOCK_CMD_LSB; |
441 | buf[1] = MXT_UNLOCK_CMD_MSB; | 509 | buf[1] = MXT_UNLOCK_CMD_MSB; |
442 | 510 | ||
443 | if (i2c_master_send(client, buf, 2) != 2) { | 511 | ret = mxt_bootloader_write(data, buf, 2); |
444 | dev_err(&client->dev, "%s: i2c send failed\n", __func__); | 512 | if (ret) |
445 | return -EIO; | 513 | return ret; |
446 | } | ||
447 | |||
448 | return 0; | ||
449 | } | ||
450 | |||
451 | static int mxt_fw_write(struct i2c_client *client, | ||
452 | const u8 *data, unsigned int frame_size) | ||
453 | { | ||
454 | if (i2c_master_send(client, data, frame_size) != frame_size) { | ||
455 | dev_err(&client->dev, "%s: i2c send failed\n", __func__); | ||
456 | return -EIO; | ||
457 | } | ||
458 | 514 | ||
459 | return 0; | 515 | return 0; |
460 | } | 516 | } |
@@ -1102,7 +1158,6 @@ done: | |||
1102 | static int mxt_load_fw(struct device *dev, const char *fn) | 1158 | static int mxt_load_fw(struct device *dev, const char *fn) |
1103 | { | 1159 | { |
1104 | struct mxt_data *data = dev_get_drvdata(dev); | 1160 | struct mxt_data *data = dev_get_drvdata(dev); |
1105 | struct i2c_client *client = data->client; | ||
1106 | const struct firmware *fw = NULL; | 1161 | const struct firmware *fw = NULL; |
1107 | unsigned int frame_size; | 1162 | unsigned int frame_size; |
1108 | unsigned int pos = 0; | 1163 | unsigned int pos = 0; |
@@ -1114,6 +1169,10 @@ static int mxt_load_fw(struct device *dev, const char *fn) | |||
1114 | return ret; | 1169 | return ret; |
1115 | } | 1170 | } |
1116 | 1171 | ||
1172 | ret = mxt_lookup_bootloader_address(data); | ||
1173 | if (ret) | ||
1174 | goto release_firmware; | ||
1175 | |||
1117 | /* Change to the bootloader mode */ | 1176 | /* Change to the bootloader mode */ |
1118 | data->in_bootloader = true; | 1177 | data->in_bootloader = true; |
1119 | 1178 | ||
@@ -1123,12 +1182,6 @@ static int mxt_load_fw(struct device *dev, const char *fn) | |||
1123 | 1182 | ||
1124 | msleep(MXT_RESET_TIME); | 1183 | msleep(MXT_RESET_TIME); |
1125 | 1184 | ||
1126 | /* Change to slave address of bootloader */ | ||
1127 | if (client->addr == MXT_APP_LOW) | ||
1128 | client->addr = MXT_BOOT_LOW; | ||
1129 | else | ||
1130 | client->addr = MXT_BOOT_HIGH; | ||
1131 | |||
1132 | reinit_completion(&data->bl_completion); | 1185 | reinit_completion(&data->bl_completion); |
1133 | 1186 | ||
1134 | ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD); | 1187 | ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD); |
@@ -1136,7 +1189,7 @@ static int mxt_load_fw(struct device *dev, const char *fn) | |||
1136 | goto disable_irq; | 1189 | goto disable_irq; |
1137 | 1190 | ||
1138 | /* Unlock bootloader */ | 1191 | /* Unlock bootloader */ |
1139 | mxt_unlock_bootloader(client); | 1192 | mxt_unlock_bootloader(data); |
1140 | 1193 | ||
1141 | while (pos < fw->size) { | 1194 | while (pos < fw->size) { |
1142 | ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA); | 1195 | ret = mxt_check_bootloader(data, MXT_WAITING_FRAME_DATA); |
@@ -1151,7 +1204,9 @@ static int mxt_load_fw(struct device *dev, const char *fn) | |||
1151 | frame_size += 2; | 1204 | frame_size += 2; |
1152 | 1205 | ||
1153 | /* Write one frame to device */ | 1206 | /* Write one frame to device */ |
1154 | mxt_fw_write(client, fw->data + pos, frame_size); | 1207 | ret = mxt_bootloader_write(data, fw->data + pos, frame_size); |
1208 | if (ret) | ||
1209 | goto disable_irq; | ||
1155 | 1210 | ||
1156 | ret = mxt_check_bootloader(data, MXT_FRAME_CRC_PASS); | 1211 | ret = mxt_check_bootloader(data, MXT_FRAME_CRC_PASS); |
1157 | if (ret) | 1212 | if (ret) |
@@ -1181,13 +1236,6 @@ disable_irq: | |||
1181 | disable_irq(data->irq); | 1236 | disable_irq(data->irq); |
1182 | release_firmware: | 1237 | release_firmware: |
1183 | release_firmware(fw); | 1238 | release_firmware(fw); |
1184 | |||
1185 | /* Change to slave address of application */ | ||
1186 | if (client->addr == MXT_BOOT_LOW) | ||
1187 | client->addr = MXT_APP_LOW; | ||
1188 | else | ||
1189 | client->addr = MXT_APP_HIGH; | ||
1190 | |||
1191 | return ret; | 1239 | return ret; |
1192 | } | 1240 | } |
1193 | 1241 | ||