cyttsp5_loader.c 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581
  1. /*
  2. * cyttsp5_loader.c
  3. * Parade TrueTouch(TM) Standard Product V5 FW Loader Module.
  4. * For use with Parade touchscreen controllers.
  5. * Supported parts include:
  6. * CYTMA5XX
  7. * CYTMA448
  8. * CYTMA445A
  9. * CYTT21XXX
  10. * CYTT31XXX
  11. *
  12. * Copyright (C) 2015 Parade Technologies
  13. * Copyright (C) 2012-2015 Cypress Semiconductor, Inc.
  14. *
  15. * This program is free software; you can redistribute it and/or
  16. * modify it under the terms of the GNU General Public License
  17. * version 2, and only version 2, as published by the
  18. * Free Software Foundation.
  19. *
  20. * This program is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * Contact Parade Technologies at www.paradetech.com <ttdrivers@paradetech.com>
  26. *
  27. */
  28. #include "cyttsp5_regs.h"
  29. #include <linux/firmware.h>
  30. #define CYTTSP5_LOADER_NAME "cyttsp5_loader"
  31. #define CY_FW_MANUAL_UPGRADE_FILE_NAME "cyttsp5_fw_manual_upgrade"
  32. /* Enable UPGRADE_FW_AND_CONFIG_IN_PROBE definition
  33. * to perform FW and config upgrade during probe
  34. * instead of scheduling a work for it
  35. */
  36. /* #define UPGRADE_FW_AND_CONFIG_IN_PROBE */
  37. #define CYTTSP5_AUTO_LOAD_FOR_CORRUPTED_FW 1
  38. #define CYTTSP5_LOADER_FW_UPGRADE_RETRY_COUNT 3
  39. #define CYTTSP5_FW_UPGRADE \
  40. (defined(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_FW_UPGRADE) \
  41. || defined(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_BINARY_FW_UPGRADE))
  42. #define CYTTSP5_TTCONFIG_UPGRADE \
  43. (defined(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_TTCONFIG_UPGRADE) \
  44. || defined(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_MANUAL_TTCONFIG_UPGRADE))
  45. static const u8 cyttsp5_security_key[] = {
  46. 0xA5, 0x01, 0x02, 0x03, 0xFF, 0xFE, 0xFD, 0x5A
  47. };
  48. /* Timeout values in ms. */
  49. #define CY_LDR_REQUEST_EXCLUSIVE_TIMEOUT 500
  50. #define CY_LDR_SWITCH_TO_APP_MODE_TIMEOUT 300
  51. #define CY_MAX_STATUS_SIZE 32
  52. #define CY_DATA_MAX_ROW_SIZE 256
  53. #define CY_DATA_ROW_SIZE 128
  54. #define CY_ARRAY_ID_OFFSET 0
  55. #define CY_ROW_NUM_OFFSET 1
  56. #define CY_ROW_SIZE_OFFSET 3
  57. #define CY_ROW_DATA_OFFSET 5
  58. #define CY_POST_TT_CFG_CRC_MASK 0x2
  59. struct cyttsp5_loader_data {
  60. struct device *dev;
  61. struct cyttsp5_sysinfo *si;
  62. u8 status_buf[CY_MAX_STATUS_SIZE];
  63. struct completion int_running;
  64. struct completion calibration_complete;
  65. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_BINARY_FW_UPGRADE
  66. struct completion builtin_bin_fw_complete;
  67. int builtin_bin_fw_status;
  68. bool is_manual_upgrade_enabled;
  69. #endif
  70. struct work_struct fw_and_config_upgrade;
  71. struct work_struct calibration_work;
  72. struct cyttsp5_loader_platform_data *loader_pdata;
  73. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_MANUAL_TTCONFIG_UPGRADE
  74. struct mutex config_lock;
  75. u8 *config_data;
  76. int config_size;
  77. bool config_loading;
  78. #endif
  79. };
  80. struct cyttsp5_dev_id {
  81. u32 silicon_id;
  82. u8 rev_id;
  83. u32 bl_ver;
  84. };
  85. struct cyttsp5_hex_image {
  86. u8 array_id;
  87. u16 row_num;
  88. u16 row_size;
  89. u8 row_data[CY_DATA_ROW_SIZE];
  90. } __packed;
  91. static struct cyttsp5_core_commands *cmd;
  92. static struct cyttsp5_module loader_module;
  93. static inline struct cyttsp5_loader_data *cyttsp5_get_loader_data(
  94. struct device *dev)
  95. {
  96. return cyttsp5_get_module_data(dev, &loader_module);
  97. }
  98. #if CYTTSP5_FW_UPGRADE \
  99. || defined(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_TTCONFIG_UPGRADE)
  100. static u8 cyttsp5_get_panel_id(struct device *dev)
  101. {
  102. struct cyttsp5_core_data *cd = dev_get_drvdata(dev);
  103. return cd->panel_id;
  104. }
  105. #endif
  106. #if CYTTSP5_FW_UPGRADE || CYTTSP5_TTCONFIG_UPGRADE
  107. /*
  108. * return code:
  109. * -1: Do not upgrade firmware
  110. * 0: Version info same, let caller decide
  111. * 1: Do a firmware upgrade
  112. */
  113. static int cyttsp5_check_firmware_version(struct device *dev,
  114. u32 fw_ver_new, u32 fw_revctrl_new)
  115. {
  116. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  117. u32 fw_ver_img;
  118. u32 fw_revctrl_img;
  119. fw_ver_img = ld->si->cydata.fw_ver_major << 8;
  120. fw_ver_img += ld->si->cydata.fw_ver_minor;
  121. parade_debug(dev, DEBUG_LEVEL_1,
  122. "%s: img vers:0x%04X new vers:0x%04X\n", __func__,
  123. fw_ver_img, fw_ver_new);
  124. if (fw_ver_new > fw_ver_img) {
  125. parade_debug(dev, DEBUG_LEVEL_1,
  126. "%s: Image is newer, will upgrade\n", __func__);
  127. return 1;
  128. }
  129. if (fw_ver_new < fw_ver_img) {
  130. parade_debug(dev, DEBUG_LEVEL_1,
  131. "%s: Image is older, will NOT upgrade\n", __func__);
  132. return -1;
  133. }
  134. fw_revctrl_img = ld->si->cydata.revctrl;
  135. parade_debug(dev, DEBUG_LEVEL_1,
  136. "%s: img revctrl:0x%04X new revctrl:0x%04X\n",
  137. __func__, fw_revctrl_img, fw_revctrl_new);
  138. if (fw_revctrl_new > fw_revctrl_img) {
  139. parade_debug(dev, DEBUG_LEVEL_1,
  140. "%s: Image is newer, will upgrade\n", __func__);
  141. return 1;
  142. }
  143. if (fw_revctrl_new < fw_revctrl_img) {
  144. parade_debug(dev, DEBUG_LEVEL_1,
  145. "%s: Image is older, will NOT upgrade\n", __func__);
  146. return -1;
  147. }
  148. return 0;
  149. }
  150. static void cyttsp5_calibrate_idacs(struct work_struct *calibration_work)
  151. {
  152. struct cyttsp5_loader_data *ld = container_of(calibration_work,
  153. struct cyttsp5_loader_data, calibration_work);
  154. struct device *dev = ld->dev;
  155. u8 mode;
  156. u8 status;
  157. int rc;
  158. rc = cmd->request_exclusive(dev, CY_LDR_REQUEST_EXCLUSIVE_TIMEOUT);
  159. if (rc < 0)
  160. goto exit;
  161. rc = cmd->nonhid_cmd->suspend_scanning(dev, 0);
  162. if (rc < 0)
  163. goto release;
  164. for (mode = 0; mode < 3; mode++) {
  165. rc = cmd->nonhid_cmd->calibrate_idacs(dev, 0, mode, &status);
  166. if (rc < 0)
  167. goto release;
  168. }
  169. rc = cmd->nonhid_cmd->resume_scanning(dev, 0);
  170. if (rc < 0)
  171. goto release;
  172. parade_debug(dev, DEBUG_LEVEL_1, "%s: Calibration Done\n", __func__);
  173. release:
  174. cmd->release_exclusive(dev);
  175. exit:
  176. complete(&ld->calibration_complete);
  177. }
  178. static int cyttsp5_calibration_attention(struct device *dev)
  179. {
  180. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  181. int rc = 0;
  182. schedule_work(&ld->calibration_work);
  183. cmd->unsubscribe_attention(dev, CY_ATTEN_STARTUP, CYTTSP5_LOADER_NAME,
  184. cyttsp5_calibration_attention, 0);
  185. return rc;
  186. }
  187. #endif /* CYTTSP5_FW_UPGRADE || CYTTSP5_TTCONFIG_UPGRADE */
  188. #if CYTTSP5_FW_UPGRADE
  189. static u8 *cyttsp5_get_row_(struct device *dev, u8 *row_buf,
  190. u8 *image_buf, int size)
  191. {
  192. memcpy(row_buf, image_buf, size);
  193. return image_buf + size;
  194. }
  195. static int cyttsp5_ldr_enter_(struct device *dev, struct cyttsp5_dev_id *dev_id)
  196. {
  197. int rc;
  198. u8 return_data[8];
  199. u8 mode;
  200. dev_id->silicon_id = 0;
  201. dev_id->rev_id = 0;
  202. dev_id->bl_ver = 0;
  203. cmd->request_reset(dev);
  204. rc = cmd->request_get_mode(dev, 0, &mode);
  205. if (rc < 0)
  206. return rc;
  207. if (mode == CY_MODE_UNKNOWN)
  208. return -EINVAL;
  209. if (mode == CY_MODE_OPERATIONAL) {
  210. rc = cmd->nonhid_cmd->start_bl(dev, 0);
  211. if (rc < 0)
  212. return rc;
  213. }
  214. rc = cmd->nonhid_cmd->get_bl_info(dev, 0, return_data);
  215. if (rc < 0)
  216. return rc;
  217. dev_id->silicon_id = get_unaligned_le32(&return_data[0]);
  218. dev_id->rev_id = return_data[4];
  219. dev_id->bl_ver = return_data[5] + (return_data[6] << 8)
  220. + (return_data[7] << 16);
  221. return 0;
  222. }
  223. static int cyttsp5_ldr_init_(struct device *dev,
  224. struct cyttsp5_hex_image *row_image)
  225. {
  226. return cmd->nonhid_cmd->initiate_bl(dev, 0, 8,
  227. (u8 *)cyttsp5_security_key, row_image->row_size,
  228. row_image->row_data);
  229. }
  230. static int cyttsp5_ldr_parse_row_(struct device *dev, u8 *row_buf,
  231. struct cyttsp5_hex_image *row_image)
  232. {
  233. int rc = 0;
  234. row_image->array_id = row_buf[CY_ARRAY_ID_OFFSET];
  235. row_image->row_num = get_unaligned_be16(&row_buf[CY_ROW_NUM_OFFSET]);
  236. row_image->row_size = get_unaligned_be16(&row_buf[CY_ROW_SIZE_OFFSET]);
  237. if (row_image->row_size > ARRAY_SIZE(row_image->row_data)) {
  238. dev_err(dev, "%s: row data buffer overflow\n", __func__);
  239. rc = -EOVERFLOW;
  240. goto cyttsp5_ldr_parse_row_exit;
  241. }
  242. memcpy(row_image->row_data, &row_buf[CY_ROW_DATA_OFFSET],
  243. row_image->row_size);
  244. cyttsp5_ldr_parse_row_exit:
  245. return rc;
  246. }
  247. static int cyttsp5_ldr_prog_row_(struct device *dev,
  248. struct cyttsp5_hex_image *row_image)
  249. {
  250. u16 length = row_image->row_size + 3;
  251. u8 data[3 + row_image->row_size];
  252. u8 offset = 0;
  253. data[offset++] = row_image->array_id;
  254. data[offset++] = LOW_BYTE(row_image->row_num);
  255. data[offset++] = HI_BYTE(row_image->row_num);
  256. memcpy(data + 3, row_image->row_data, row_image->row_size);
  257. return cmd->nonhid_cmd->prog_and_verify(dev, 0, length, data);
  258. }
  259. static int cyttsp5_ldr_verify_chksum_(struct device *dev)
  260. {
  261. u8 result;
  262. int rc;
  263. rc = cmd->nonhid_cmd->verify_app_integrity(dev, 0, &result);
  264. if (rc)
  265. return rc;
  266. /* fail */
  267. if (result == 0)
  268. return -EINVAL;
  269. return 0;
  270. }
  271. static int cyttsp5_ldr_exit_(struct device *dev)
  272. {
  273. return cmd->nonhid_cmd->launch_app(dev, 0);
  274. }
  275. static int cyttsp5_load_app_(struct device *dev, const u8 *fw, int fw_size)
  276. {
  277. struct cyttsp5_dev_id *dev_id;
  278. struct cyttsp5_hex_image *row_image;
  279. u8 *row_buf;
  280. size_t image_rec_size;
  281. size_t row_buf_size = CY_DATA_MAX_ROW_SIZE;
  282. int row_count = 0;
  283. u8 *p;
  284. u8 *last_row;
  285. int rc;
  286. int rc_tmp;
  287. image_rec_size = sizeof(struct cyttsp5_hex_image);
  288. if (fw_size % image_rec_size != 0) {
  289. dev_err(dev, "%s: Firmware image is misaligned\n", __func__);
  290. rc = -EINVAL;
  291. goto _cyttsp5_load_app_error;
  292. }
  293. dev_info(dev, "%s: start load app\n", __func__);
  294. #ifdef TTHE_TUNER_SUPPORT
  295. cmd->request_tthe_print(dev, NULL, 0, "start load app");
  296. #endif
  297. row_buf = kzalloc(row_buf_size, GFP_KERNEL);
  298. row_image = kzalloc(sizeof(struct cyttsp5_hex_image), GFP_KERNEL);
  299. dev_id = kzalloc(sizeof(struct cyttsp5_dev_id), GFP_KERNEL);
  300. if (!row_buf || !row_image || !dev_id) {
  301. rc = -ENOMEM;
  302. goto _cyttsp5_load_app_exit;
  303. }
  304. cmd->request_stop_wd(dev);
  305. dev_info(dev, "%s: Send BL Loader Enter\n", __func__);
  306. #ifdef TTHE_TUNER_SUPPORT
  307. cmd->request_tthe_print(dev, NULL, 0, "Send BL Loader Enter");
  308. #endif
  309. rc = cyttsp5_ldr_enter_(dev, dev_id);
  310. if (rc) {
  311. dev_err(dev, "%s: Error cannot start Loader (ret=%d)\n",
  312. __func__, rc);
  313. goto _cyttsp5_load_app_exit;
  314. }
  315. parade_debug(dev, DEBUG_LEVEL_2, "%s: dev: silicon id=%08X rev=%02X bl=%08X\n",
  316. __func__, dev_id->silicon_id,
  317. dev_id->rev_id, dev_id->bl_ver);
  318. /* get last row */
  319. last_row = (u8 *)fw + fw_size - image_rec_size;
  320. cyttsp5_get_row_(dev, row_buf, last_row, image_rec_size);
  321. cyttsp5_ldr_parse_row_(dev, row_buf, row_image);
  322. /* initialise bootloader */
  323. rc = cyttsp5_ldr_init_(dev, row_image);
  324. if (rc) {
  325. dev_err(dev, "%s: Error cannot init Loader (ret=%d)\n",
  326. __func__, rc);
  327. goto _cyttsp5_load_app_exit;
  328. }
  329. dev_info(dev, "%s: Send BL Loader Blocks\n", __func__);
  330. #ifdef TTHE_TUNER_SUPPORT
  331. cmd->request_tthe_print(dev, NULL, 0, "Send BL Loader Blocks");
  332. #endif
  333. p = (u8 *)fw;
  334. while (p < last_row) {
  335. /* Get row */
  336. parade_debug(dev, DEBUG_LEVEL_1, "%s: read row=%d\n",
  337. __func__, ++row_count);
  338. memset(row_buf, 0, row_buf_size);
  339. p = cyttsp5_get_row_(dev, row_buf, p, image_rec_size);
  340. /* Parse row */
  341. parade_debug(dev, DEBUG_LEVEL_2, "%s: p=%p buf=%p buf[0]=%02X\n",
  342. __func__, p, row_buf, row_buf[0]);
  343. rc = cyttsp5_ldr_parse_row_(dev, row_buf, row_image);
  344. parade_debug(dev, DEBUG_LEVEL_2, "%s: array_id=%02X row_num=%04X(%d) row_size=%04X(%d)\n",
  345. __func__, row_image->array_id,
  346. row_image->row_num, row_image->row_num,
  347. row_image->row_size, row_image->row_size);
  348. if (rc) {
  349. dev_err(dev, "%s: Parse Row Error (a=%d r=%d ret=%d\n",
  350. __func__, row_image->array_id,
  351. row_image->row_num, rc);
  352. goto _cyttsp5_load_app_exit;
  353. } else {
  354. parade_debug(dev, DEBUG_LEVEL_2, "%s: Parse Row (a=%d r=%d ret=%d\n",
  355. __func__, row_image->array_id,
  356. row_image->row_num, rc);
  357. }
  358. /* program row */
  359. rc = cyttsp5_ldr_prog_row_(dev, row_image);
  360. if (rc) {
  361. dev_err(dev, "%s: Program Row Error (array=%d row=%d ret=%d)\n",
  362. __func__, row_image->array_id,
  363. row_image->row_num, rc);
  364. goto _cyttsp5_load_app_exit;
  365. }
  366. parade_debug(dev, DEBUG_LEVEL_2, "%s: array=%d row_cnt=%d row_num=%04X\n",
  367. __func__, row_image->array_id, row_count,
  368. row_image->row_num);
  369. }
  370. /* exit loader */
  371. dev_info(dev, "%s: Send BL Loader Terminate\n", __func__);
  372. #ifdef TTHE_TUNER_SUPPORT
  373. cmd->request_tthe_print(dev, NULL, 0, "Send BL Loader Terminate");
  374. #endif
  375. rc = cyttsp5_ldr_exit_(dev);
  376. if (rc) {
  377. dev_err(dev, "%s: Error on exit Loader (ret=%d)\n",
  378. __func__, rc);
  379. /* verify app checksum */
  380. rc_tmp = cyttsp5_ldr_verify_chksum_(dev);
  381. if (rc_tmp)
  382. dev_err(dev, "%s: ldr_verify_chksum fail r=%d\n",
  383. __func__, rc_tmp);
  384. else
  385. dev_info(dev, "%s: APP Checksum Verified\n", __func__);
  386. }
  387. _cyttsp5_load_app_exit:
  388. kfree(row_buf);
  389. kfree(row_image);
  390. kfree(dev_id);
  391. _cyttsp5_load_app_error:
  392. return rc;
  393. }
  394. static int cyttsp5_upgrade_firmware(struct device *dev, const u8 *fw_img,
  395. int fw_size)
  396. {
  397. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  398. int retry = CYTTSP5_LOADER_FW_UPGRADE_RETRY_COUNT;
  399. bool wait_for_calibration_complete = false;
  400. int rc;
  401. pm_runtime_get_sync(dev);
  402. rc = cmd->request_exclusive(dev, CY_LDR_REQUEST_EXCLUSIVE_TIMEOUT);
  403. if (rc < 0)
  404. goto exit;
  405. while (retry--) {
  406. rc = cyttsp5_load_app_(dev, fw_img, fw_size);
  407. if (rc < 0)
  408. dev_err(dev, "%s: Firmware update failed rc=%d, retry:%d\n",
  409. __func__, rc, retry);
  410. else
  411. break;
  412. msleep(20);
  413. }
  414. if (rc < 0) {
  415. dev_err(dev, "%s: Firmware update failed with error code %d\n",
  416. __func__, rc);
  417. } else if (ld->loader_pdata &&
  418. (ld->loader_pdata->flags
  419. & CY_LOADER_FLAG_CALIBRATE_AFTER_FW_UPGRADE)) {
  420. #if (KERNEL_VERSION(3, 13, 0) <= LINUX_VERSION_CODE)
  421. reinit_completion(&ld->calibration_complete);
  422. #else
  423. INIT_COMPLETION(ld->calibration_complete);
  424. #endif
  425. /* set up call back for startup */
  426. parade_debug(dev, DEBUG_LEVEL_2, "%s: Adding callback for calibration\n",
  427. __func__);
  428. rc = cmd->subscribe_attention(dev, CY_ATTEN_STARTUP,
  429. CYTTSP5_LOADER_NAME, cyttsp5_calibration_attention, 0);
  430. if (rc) {
  431. dev_err(dev, "%s: Failed adding callback for calibration\n",
  432. __func__);
  433. dev_err(dev, "%s: No calibration will be performed\n",
  434. __func__);
  435. rc = 0;
  436. } else
  437. wait_for_calibration_complete = true;
  438. }
  439. cmd->release_exclusive(dev);
  440. exit:
  441. if (!rc)
  442. cmd->request_restart(dev, true);
  443. pm_runtime_put_sync(dev);
  444. if (wait_for_calibration_complete)
  445. wait_for_completion(&ld->calibration_complete);
  446. return rc;
  447. }
  448. static int cyttsp5_loader_attention(struct device *dev)
  449. {
  450. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  451. complete(&ld->int_running);
  452. return 0;
  453. }
  454. #endif /* CYTTSP5_FW_UPGRADE */
  455. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_FW_UPGRADE
  456. static int cyttsp5_check_firmware_version_platform(struct device *dev,
  457. struct cyttsp5_touch_firmware *fw)
  458. {
  459. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  460. u32 fw_ver_new;
  461. u32 fw_revctrl_new;
  462. int upgrade;
  463. if (!ld->si) {
  464. dev_info(dev, "%s: No firmware infomation found, device FW may be corrupted\n",
  465. __func__);
  466. return CYTTSP5_AUTO_LOAD_FOR_CORRUPTED_FW;
  467. }
  468. fw_ver_new = get_unaligned_be16(fw->ver + 2);
  469. /* 4 middle bytes are not used */
  470. fw_revctrl_new = get_unaligned_be32(fw->ver + 8);
  471. upgrade = cyttsp5_check_firmware_version(dev, fw_ver_new,
  472. fw_revctrl_new);
  473. if (upgrade > 0)
  474. return 1;
  475. return 0;
  476. }
  477. static struct cyttsp5_touch_firmware *cyttsp5_get_platform_firmware(
  478. struct device *dev)
  479. {
  480. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  481. struct cyttsp5_touch_firmware **fws;
  482. struct cyttsp5_touch_firmware *fw;
  483. u8 panel_id;
  484. panel_id = cyttsp5_get_panel_id(dev);
  485. if (panel_id == PANEL_ID_NOT_ENABLED) {
  486. parade_debug(dev, DEBUG_LEVEL_1, "%s: Panel ID not enabled, using legacy firmware\n",
  487. __func__);
  488. return ld->loader_pdata->fw;
  489. }
  490. fws = ld->loader_pdata->fws;
  491. if (!fws) {
  492. dev_err(dev, "%s: No firmwares provided\n", __func__);
  493. return NULL;
  494. }
  495. /* Find FW according to the Panel ID */
  496. while ((fw = *fws++)) {
  497. if (fw->panel_id == panel_id) {
  498. parade_debug(dev, DEBUG_LEVEL_1, "%s: Found matching fw:%p with Panel ID: 0x%02X\n",
  499. __func__, fw, fw->panel_id);
  500. return fw;
  501. }
  502. parade_debug(dev, DEBUG_LEVEL_2, "%s: Found mismatching fw:%p with Panel ID: 0x%02X\n",
  503. __func__, fw, fw->panel_id);
  504. }
  505. return NULL;
  506. }
  507. static int upgrade_firmware_from_platform(struct device *dev,
  508. bool forced)
  509. {
  510. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  511. struct cyttsp5_touch_firmware *fw;
  512. int rc = -ENODEV;
  513. int upgrade;
  514. if (!ld->loader_pdata) {
  515. dev_err(dev, "%s: No loader platform data\n", __func__);
  516. return rc;
  517. }
  518. fw = cyttsp5_get_platform_firmware(dev);
  519. if (!fw || !fw->img || !fw->size) {
  520. dev_err(dev, "%s: No platform firmware\n", __func__);
  521. return rc;
  522. }
  523. if (!fw->ver || !fw->vsize) {
  524. dev_err(dev, "%s: No platform firmware version\n",
  525. __func__);
  526. return rc;
  527. }
  528. if (forced)
  529. upgrade = forced;
  530. else
  531. upgrade = cyttsp5_check_firmware_version_platform(dev, fw);
  532. if (upgrade)
  533. return cyttsp5_upgrade_firmware(dev, fw->img, fw->size);
  534. return rc;
  535. }
  536. #endif /* CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_FW_UPGRADE */
  537. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_BINARY_FW_UPGRADE
  538. static void _cyttsp5_firmware_cont(const struct firmware *fw, void *context)
  539. {
  540. struct device *dev = context;
  541. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  542. u8 header_size = 0;
  543. if (!fw)
  544. goto cyttsp5_firmware_cont_exit;
  545. if (!fw->data || !fw->size) {
  546. dev_err(dev, "%s: No firmware received\n", __func__);
  547. goto cyttsp5_firmware_cont_release_exit;
  548. }
  549. header_size = fw->data[0];
  550. if (header_size >= (fw->size + 1)) {
  551. dev_err(dev, "%s: Firmware format is invalid\n", __func__);
  552. goto cyttsp5_firmware_cont_release_exit;
  553. }
  554. cyttsp5_upgrade_firmware(dev, &(fw->data[header_size + 1]),
  555. fw->size - (header_size + 1));
  556. cyttsp5_firmware_cont_release_exit:
  557. release_firmware(fw);
  558. cyttsp5_firmware_cont_exit:
  559. ld->is_manual_upgrade_enabled = 0;
  560. }
  561. static int cyttsp5_check_firmware_version_builtin(struct device *dev,
  562. const struct firmware *fw)
  563. {
  564. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  565. u32 fw_ver_new;
  566. u32 fw_revctrl_new;
  567. int upgrade;
  568. if (!ld->si) {
  569. dev_info(dev, "%s: No firmware infomation found, device FW may be corrupted\n",
  570. __func__);
  571. return CYTTSP5_AUTO_LOAD_FOR_CORRUPTED_FW;
  572. }
  573. fw_ver_new = get_unaligned_be16(fw->data + 3);
  574. /* 4 middle bytes are not used */
  575. fw_revctrl_new = get_unaligned_be32(fw->data + 9);
  576. upgrade = cyttsp5_check_firmware_version(dev, fw_ver_new,
  577. fw_revctrl_new);
  578. if (upgrade > 0)
  579. return 1;
  580. return 0;
  581. }
  582. static void _cyttsp5_firmware_cont_builtin(const struct firmware *fw,
  583. void *context)
  584. {
  585. struct device *dev = context;
  586. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  587. int upgrade;
  588. if (!fw) {
  589. dev_info(dev, "%s: No builtin firmware\n", __func__);
  590. goto _cyttsp5_firmware_cont_builtin_exit;
  591. }
  592. if (!fw->data || !fw->size) {
  593. dev_err(dev, "%s: Invalid builtin firmware\n", __func__);
  594. goto _cyttsp5_firmware_cont_builtin_exit;
  595. }
  596. parade_debug(dev, DEBUG_LEVEL_1, "%s: Found firmware\n", __func__);
  597. upgrade = cyttsp5_check_firmware_version_builtin(dev, fw);
  598. if (upgrade) {
  599. _cyttsp5_firmware_cont(fw, dev);
  600. ld->builtin_bin_fw_status = 0;
  601. complete(&ld->builtin_bin_fw_complete);
  602. return;
  603. }
  604. _cyttsp5_firmware_cont_builtin_exit:
  605. release_firmware(fw);
  606. ld->builtin_bin_fw_status = -EINVAL;
  607. complete(&ld->builtin_bin_fw_complete);
  608. }
  609. static int upgrade_firmware_from_class(struct device *dev)
  610. {
  611. int retval;
  612. parade_debug(dev, DEBUG_LEVEL_2,
  613. "%s: Enabling firmware class loader\n", __func__);
  614. retval = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
  615. CY_FW_MANUAL_UPGRADE_FILE_NAME, dev, GFP_KERNEL, dev,
  616. _cyttsp5_firmware_cont);
  617. if (retval < 0) {
  618. dev_err(dev, "%s: Fail request firmware class file load\n",
  619. __func__);
  620. return retval;
  621. }
  622. return 0;
  623. }
  624. /*
  625. * Generates binary FW filename as following:
  626. * - Panel ID not enabled: cyttsp5_fw.bin
  627. * - Panel ID enabled: cyttsp5_fw_pidXX.bin
  628. */
  629. static char *generate_firmware_filename(struct device *dev)
  630. {
  631. char *filename;
  632. u8 panel_id;
  633. #define FILENAME_LEN_MAX 64
  634. filename = kzalloc(FILENAME_LEN_MAX, GFP_KERNEL);
  635. if (!filename)
  636. return NULL;
  637. panel_id = cyttsp5_get_panel_id(dev);
  638. if (panel_id == PANEL_ID_NOT_ENABLED)
  639. snprintf(filename, FILENAME_LEN_MAX, "%s", CY_FW_FILE_NAME);
  640. else
  641. snprintf(filename, FILENAME_LEN_MAX, "%s_pid%02X%s",
  642. CY_FW_FILE_PREFIX, panel_id, CY_FW_FILE_SUFFIX);
  643. parade_debug(dev, DEBUG_LEVEL_1, "%s: Filename: %s\n",
  644. __func__, filename);
  645. return filename;
  646. }
  647. static int upgrade_firmware_from_builtin(struct device *dev)
  648. {
  649. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  650. char *filename;
  651. int retval;
  652. parade_debug(dev, DEBUG_LEVEL_2,
  653. "%s: Enabling firmware class loader built-in\n",
  654. __func__);
  655. filename = generate_firmware_filename(dev);
  656. if (!filename)
  657. return -ENOMEM;
  658. retval = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
  659. filename, dev, GFP_KERNEL, dev,
  660. _cyttsp5_firmware_cont_builtin);
  661. if (retval < 0) {
  662. dev_err(dev, "%s: Fail request firmware class file load\n",
  663. __func__);
  664. goto exit;
  665. }
  666. /* wait until FW binary upgrade finishes */
  667. wait_for_completion(&ld->builtin_bin_fw_complete);
  668. retval = ld->builtin_bin_fw_status;
  669. exit:
  670. kfree(filename);
  671. return retval;
  672. }
  673. #endif /* CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_BINARY_FW_UPGRADE */
  674. #if CYTTSP5_TTCONFIG_UPGRADE
  675. static int cyttsp5_write_config_row_(struct device *dev, u8 ebid,
  676. u16 row_number, u16 row_size, u8 *data)
  677. {
  678. int rc;
  679. u16 actual_write_len;
  680. rc = cmd->nonhid_cmd->write_conf_block(dev, 0, row_number,
  681. row_size, ebid, data, (u8 *)cyttsp5_security_key,
  682. &actual_write_len);
  683. if (rc) {
  684. dev_err(dev, "%s: Fail Put EBID=%d row=%d cmd fail r=%d\n",
  685. __func__, ebid, row_number, rc);
  686. return rc;
  687. }
  688. if (actual_write_len != row_size) {
  689. dev_err(dev, "%s: Fail Put EBID=%d row=%d wrong write size=%d\n",
  690. __func__, ebid, row_number, actual_write_len);
  691. rc = -EINVAL;
  692. }
  693. return rc;
  694. }
  695. static int cyttsp5_upgrade_ttconfig(struct device *dev,
  696. const u8 *ttconfig_data, int ttconfig_size)
  697. {
  698. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  699. bool wait_for_calibration_complete = false;
  700. u8 ebid = CY_TCH_PARM_EBID;
  701. u16 row_size = CY_DATA_ROW_SIZE;
  702. u16 table_size;
  703. u16 row_count;
  704. u16 residue;
  705. u8 *row_buf;
  706. u8 verify_crc_status;
  707. u16 calculated_crc;
  708. u16 stored_crc;
  709. int rc = 0;
  710. int i;
  711. table_size = ttconfig_size;
  712. row_count = table_size / row_size;
  713. row_buf = (u8 *)ttconfig_data;
  714. parade_debug(dev, DEBUG_LEVEL_1, "%s: size:%d row_size=%d row_count=%d\n",
  715. __func__, table_size, row_size, row_count);
  716. pm_runtime_get_sync(dev);
  717. rc = cmd->request_exclusive(dev, CY_LDR_REQUEST_EXCLUSIVE_TIMEOUT);
  718. if (rc < 0)
  719. goto exit;
  720. rc = cmd->nonhid_cmd->suspend_scanning(dev, 0);
  721. if (rc < 0)
  722. goto release;
  723. for (i = 0; i < row_count; i++) {
  724. parade_debug(dev, DEBUG_LEVEL_1, "%s: row=%d size=%d\n",
  725. __func__, i, row_size);
  726. rc = cyttsp5_write_config_row_(dev, ebid, i, row_size,
  727. row_buf);
  728. if (rc) {
  729. dev_err(dev, "%s: Fail put row=%d r=%d\n",
  730. __func__, i, rc);
  731. break;
  732. }
  733. row_buf += row_size;
  734. }
  735. if (!rc) {
  736. residue = table_size % row_size;
  737. parade_debug(dev, DEBUG_LEVEL_1, "%s: row=%d size=%d\n",
  738. __func__, i, residue);
  739. rc = cyttsp5_write_config_row_(dev, ebid, i, residue,
  740. row_buf);
  741. row_count++;
  742. if (rc)
  743. dev_err(dev, "%s: Fail put row=%d r=%d\n",
  744. __func__, i, rc);
  745. }
  746. if (!rc)
  747. parade_debug(dev, DEBUG_LEVEL_1,
  748. "%s: TT_CFG updated: rows:%d bytes:%d\n",
  749. __func__, row_count, table_size);
  750. rc = cmd->nonhid_cmd->verify_config_block_crc(dev, 0, ebid,
  751. &verify_crc_status, &calculated_crc, &stored_crc);
  752. if (rc || verify_crc_status)
  753. dev_err(dev, "%s: CRC Failed, ebid=%d, status=%d, scrc=%X ccrc=%X\n",
  754. __func__, ebid, verify_crc_status,
  755. calculated_crc, stored_crc);
  756. else
  757. parade_debug(dev, DEBUG_LEVEL_1,
  758. "%s: CRC PASS, ebid=%d, status=%d, scrc=%X ccrc=%X\n",
  759. __func__, ebid, verify_crc_status,
  760. calculated_crc, stored_crc);
  761. rc = cmd->nonhid_cmd->resume_scanning(dev, 0);
  762. if (rc < 0)
  763. goto release;
  764. if (ld->loader_pdata &&
  765. (ld->loader_pdata->flags
  766. & CY_LOADER_FLAG_CALIBRATE_AFTER_TTCONFIG_UPGRADE)) {
  767. #if (KERNEL_VERSION(3, 13, 0) <= LINUX_VERSION_CODE)
  768. reinit_completion(&ld->calibration_complete);
  769. #else
  770. INIT_COMPLETION(ld->calibration_complete);
  771. #endif
  772. /* set up call back for startup */
  773. parade_debug(dev, DEBUG_LEVEL_2, "%s: Adding callback for calibration\n",
  774. __func__);
  775. rc = cmd->subscribe_attention(dev, CY_ATTEN_STARTUP,
  776. CYTTSP5_LOADER_NAME, cyttsp5_calibration_attention, 0);
  777. if (rc) {
  778. dev_err(dev, "%s: Failed adding callback for calibration\n",
  779. __func__);
  780. dev_err(dev, "%s: No calibration will be performed\n",
  781. __func__);
  782. rc = 0;
  783. } else
  784. wait_for_calibration_complete = true;
  785. }
  786. release:
  787. cmd->release_exclusive(dev);
  788. exit:
  789. if (!rc)
  790. cmd->request_restart(dev, true);
  791. pm_runtime_put_sync(dev);
  792. if (wait_for_calibration_complete)
  793. wait_for_completion(&ld->calibration_complete);
  794. return rc;
  795. }
  796. #endif /* CYTTSP5_TTCONFIG_UPGRADE */
  797. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_TTCONFIG_UPGRADE
  798. static int cyttsp5_get_ttconfig_crc(struct device *dev,
  799. const u8 *ttconfig_data, int ttconfig_size, u16 *crc)
  800. {
  801. u16 crc_loc;
  802. crc_loc = get_unaligned_le16(&ttconfig_data[2]);
  803. if (ttconfig_size < crc_loc + 2)
  804. return -EINVAL;
  805. *crc = get_unaligned_le16(&ttconfig_data[crc_loc]);
  806. return 0;
  807. }
  808. static int cyttsp5_get_ttconfig_version(struct device *dev,
  809. const u8 *ttconfig_data, int ttconfig_size, u16 *version)
  810. {
  811. if (ttconfig_size < CY_TTCONFIG_VERSION_OFFSET
  812. + CY_TTCONFIG_VERSION_SIZE)
  813. return -EINVAL;
  814. *version = get_unaligned_le16(
  815. &ttconfig_data[CY_TTCONFIG_VERSION_OFFSET]);
  816. return 0;
  817. }
  818. static int cyttsp5_check_ttconfig_version(struct device *dev,
  819. const u8 *ttconfig_data, int ttconfig_size)
  820. {
  821. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  822. u16 cfg_crc_new;
  823. int rc;
  824. if (!ld->si)
  825. return 0;
  826. /* Check for config version */
  827. if (ld->loader_pdata->flags &
  828. CY_LOADER_FLAG_CHECK_TTCONFIG_VERSION) {
  829. u16 cfg_ver_new;
  830. rc = cyttsp5_get_ttconfig_version(dev, ttconfig_data,
  831. ttconfig_size, &cfg_ver_new);
  832. if (rc)
  833. return 0;
  834. parade_debug(dev, DEBUG_LEVEL_1, "%s: img_ver:0x%04X new_ver:0x%04X\n",
  835. __func__, ld->si->cydata.fw_ver_conf, cfg_ver_new);
  836. /* Check if config version is newer */
  837. if (cfg_ver_new > ld->si->cydata.fw_ver_conf) {
  838. parade_debug(dev, DEBUG_LEVEL_1, "%s: Config version newer, will upgrade\n",
  839. __func__);
  840. return 1;
  841. }
  842. parade_debug(dev, DEBUG_LEVEL_1, "%s: Config version is identical or older, will NOT upgrade\n",
  843. __func__);
  844. /* Check for config CRC */
  845. } else {
  846. rc = cyttsp5_get_ttconfig_crc(dev, ttconfig_data,
  847. ttconfig_size, &cfg_crc_new);
  848. if (rc)
  849. return 0;
  850. parade_debug(dev, DEBUG_LEVEL_1, "%s: img_crc:0x%04X new_crc:0x%04X\n",
  851. __func__, ld->si->ttconfig.crc, cfg_crc_new);
  852. if (cfg_crc_new != ld->si->ttconfig.crc) {
  853. parade_debug(dev, DEBUG_LEVEL_1, "%s: Config CRC different, will upgrade\n",
  854. __func__);
  855. return 1;
  856. }
  857. parade_debug(dev, DEBUG_LEVEL_1, "%s: Config CRC equal, will NOT upgrade\n",
  858. __func__);
  859. }
  860. return 0;
  861. }
  862. static int cyttsp5_check_ttconfig_version_platform(struct device *dev,
  863. struct cyttsp5_touch_config *ttconfig)
  864. {
  865. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  866. u32 fw_ver_config;
  867. u32 fw_revctrl_config;
  868. if (!ld->si) {
  869. dev_info(dev, "%s: No firmware infomation found, device FW may be corrupted\n",
  870. __func__);
  871. return 0;
  872. }
  873. fw_ver_config = get_unaligned_be16(ttconfig->fw_ver + 2);
  874. /* 4 middle bytes are not used */
  875. fw_revctrl_config = get_unaligned_be32(ttconfig->fw_ver + 8);
  876. /* FW versions should match */
  877. if (cyttsp5_check_firmware_version(dev, fw_ver_config,
  878. fw_revctrl_config)) {
  879. dev_err(dev, "%s: FW versions mismatch\n", __func__);
  880. return 0;
  881. }
  882. /* Check PowerOn Self Test, TT_CFG CRC bit */
  883. if ((ld->si->cydata.post_code & CY_POST_TT_CFG_CRC_MASK) == 0) {
  884. parade_debug(dev, DEBUG_LEVEL_1, "%s: POST, TT_CFG failed (%X), will upgrade\n",
  885. __func__, ld->si->cydata.post_code);
  886. return 1;
  887. }
  888. return cyttsp5_check_ttconfig_version(dev, ttconfig->param_regs->data,
  889. ttconfig->param_regs->size);
  890. }
  891. static struct cyttsp5_touch_config *cyttsp5_get_platform_ttconfig(
  892. struct device *dev)
  893. {
  894. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  895. struct cyttsp5_touch_config **ttconfigs;
  896. struct cyttsp5_touch_config *ttconfig;
  897. u8 panel_id;
  898. panel_id = cyttsp5_get_panel_id(dev);
  899. if (panel_id == PANEL_ID_NOT_ENABLED) {
  900. /* TODO: Make debug message */
  901. dev_info(dev, "%s: Panel ID not enabled, using legacy ttconfig\n",
  902. __func__);
  903. return ld->loader_pdata->ttconfig;
  904. }
  905. ttconfigs = ld->loader_pdata->ttconfigs;
  906. if (!ttconfigs)
  907. return NULL;
  908. /* Find TT config according to the Panel ID */
  909. while ((ttconfig = *ttconfigs++)) {
  910. if (ttconfig->panel_id == panel_id) {
  911. /* TODO: Make debug message */
  912. dev_info(dev, "%s: Found matching ttconfig:%p with Panel ID: 0x%02X\n",
  913. __func__, ttconfig, ttconfig->panel_id);
  914. return ttconfig;
  915. }
  916. parade_debug(dev, DEBUG_LEVEL_2, "%s: Found mismatching ttconfig:%p with Panel ID: 0x%02X\n",
  917. __func__, ttconfig, ttconfig->panel_id);
  918. }
  919. return NULL;
  920. }
  921. static int upgrade_ttconfig_from_platform(struct device *dev)
  922. {
  923. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  924. struct cyttsp5_touch_config *ttconfig;
  925. struct touch_settings *param_regs;
  926. struct cyttsp5_touch_fw;
  927. int rc = -ENODEV;
  928. int upgrade;
  929. if (!ld->loader_pdata) {
  930. dev_info(dev, "%s: No loader platform data\n", __func__);
  931. return rc;
  932. }
  933. ttconfig = cyttsp5_get_platform_ttconfig(dev);
  934. if (!ttconfig) {
  935. dev_info(dev, "%s: No ttconfig data\n", __func__);
  936. return rc;
  937. }
  938. param_regs = ttconfig->param_regs;
  939. if (!param_regs) {
  940. dev_info(dev, "%s: No touch parameters\n", __func__);
  941. return rc;
  942. }
  943. if (!param_regs->data || !param_regs->size) {
  944. dev_info(dev, "%s: Invalid touch parameters\n", __func__);
  945. return rc;
  946. }
  947. if (!ttconfig->fw_ver || !ttconfig->fw_vsize) {
  948. dev_info(dev, "%s: Invalid FW version for touch parameters\n",
  949. __func__);
  950. return rc;
  951. }
  952. upgrade = cyttsp5_check_ttconfig_version_platform(dev, ttconfig);
  953. if (upgrade)
  954. return cyttsp5_upgrade_ttconfig(dev, param_regs->data,
  955. param_regs->size);
  956. return rc;
  957. }
  958. #endif /* CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_TTCONFIG_UPGRADE */
  959. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_MANUAL_TTCONFIG_UPGRADE
  960. static ssize_t cyttsp5_config_data_write(struct file *filp,
  961. struct kobject *kobj, struct bin_attribute *bin_attr,
  962. char *buf, loff_t offset, size_t count)
  963. {
  964. struct device *dev = container_of(kobj, struct device, kobj);
  965. struct cyttsp5_loader_data *data = cyttsp5_get_loader_data(dev);
  966. u8 *p;
  967. parade_debug(dev, DEBUG_LEVEL_2, "%s: offset:%lld count:%zu\n",
  968. __func__, offset, count);
  969. mutex_lock(&data->config_lock);
  970. if (!data->config_loading) {
  971. mutex_unlock(&data->config_lock);
  972. return -ENODEV;
  973. }
  974. p = krealloc(data->config_data, offset + count, GFP_KERNEL);
  975. if (!p) {
  976. kfree(data->config_data);
  977. data->config_data = NULL;
  978. mutex_unlock(&data->config_lock);
  979. return -ENOMEM;
  980. }
  981. data->config_data = p;
  982. memcpy(&data->config_data[offset], buf, count);
  983. data->config_size += count;
  984. mutex_unlock(&data->config_lock);
  985. return count;
  986. }
  987. static struct bin_attribute bin_attr_config_data = {
  988. .attr = {
  989. .name = "config_data",
  990. .mode = S_IWUSR,
  991. },
  992. .size = 0,
  993. .write = cyttsp5_config_data_write,
  994. };
  995. static ssize_t cyttsp5_config_loading_show(struct device *dev,
  996. struct device_attribute *attr, char *buf)
  997. {
  998. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  999. bool config_loading;
  1000. mutex_lock(&ld->config_lock);
  1001. config_loading = ld->config_loading;
  1002. mutex_unlock(&ld->config_lock);
  1003. return sprintf(buf, "%d\n", config_loading);
  1004. }
  1005. static int cyttsp5_verify_ttconfig_binary(struct device *dev,
  1006. u8 *bin_config_data, int bin_config_size, u8 **start, int *len)
  1007. {
  1008. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  1009. int header_size;
  1010. u16 config_size;
  1011. u32 fw_ver_config;
  1012. u32 fw_revctrl_config;
  1013. if (!ld->si) {
  1014. dev_err(dev, "%s: No firmware infomation found, device FW may be corrupted\n",
  1015. __func__);
  1016. return -ENODEV;
  1017. }
  1018. /*
  1019. * We need 11 bytes for FW version control info and at
  1020. * least 6 bytes in config (Length + Max Length + CRC)
  1021. */
  1022. header_size = bin_config_data[0] + 1;
  1023. if (header_size < 11 || header_size >= bin_config_size - 6) {
  1024. dev_err(dev, "%s: Invalid header size %d\n", __func__,
  1025. header_size);
  1026. return -EINVAL;
  1027. }
  1028. fw_ver_config = get_unaligned_be16(&bin_config_data[1]);
  1029. /* 4 middle bytes are not used */
  1030. fw_revctrl_config = get_unaligned_be32(&bin_config_data[7]);
  1031. /* FW versions should match */
  1032. if (cyttsp5_check_firmware_version(dev, fw_ver_config,
  1033. fw_revctrl_config)) {
  1034. dev_err(dev, "%s: FW versions mismatch\n", __func__);
  1035. return -EINVAL;
  1036. }
  1037. config_size = get_unaligned_le16(&bin_config_data[header_size]);
  1038. /* Perform a simple size check (2 bytes for CRC) */
  1039. if (config_size != bin_config_size - header_size - 2) {
  1040. dev_err(dev, "%s: Config size invalid\n", __func__);
  1041. return -EINVAL;
  1042. }
  1043. *start = &bin_config_data[header_size];
  1044. *len = bin_config_size - header_size;
  1045. return 0;
  1046. }
  1047. /*
  1048. * 1: Start loading TT Config
  1049. * 0: End loading TT Config and perform upgrade
  1050. *-1: Exit loading
  1051. */
  1052. static ssize_t cyttsp5_config_loading_store(struct device *dev,
  1053. struct device_attribute *attr, const char *buf, size_t size)
  1054. {
  1055. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  1056. long value;
  1057. u8 *start;
  1058. int length;
  1059. int rc;
  1060. rc = kstrtol(buf, 10, &value);
  1061. if (rc < 0 || value < -1 || value > 1) {
  1062. dev_err(dev, "%s: Invalid value\n", __func__);
  1063. return size;
  1064. }
  1065. mutex_lock(&ld->config_lock);
  1066. if (value == 1)
  1067. ld->config_loading = true;
  1068. else if (value == -1)
  1069. ld->config_loading = false;
  1070. else if (value == 0 && ld->config_loading) {
  1071. ld->config_loading = false;
  1072. if (ld->config_size == 0) {
  1073. dev_err(dev, "%s: No config data\n", __func__);
  1074. goto exit_free;
  1075. }
  1076. rc = cyttsp5_verify_ttconfig_binary(dev,
  1077. ld->config_data, ld->config_size,
  1078. &start, &length);
  1079. if (rc)
  1080. goto exit_free;
  1081. rc = cyttsp5_upgrade_ttconfig(dev, start, length);
  1082. }
  1083. exit_free:
  1084. kfree(ld->config_data);
  1085. ld->config_data = NULL;
  1086. ld->config_size = 0;
  1087. mutex_unlock(&ld->config_lock);
  1088. if (rc)
  1089. return rc;
  1090. return size;
  1091. }
  1092. static DEVICE_ATTR(config_loading, S_IRUSR | S_IWUSR,
  1093. cyttsp5_config_loading_show, cyttsp5_config_loading_store);
  1094. #endif /* CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_MANUAL_TTCONFIG_UPGRADE */
  1095. static void cyttsp5_fw_and_config_upgrade(
  1096. struct work_struct *fw_and_config_upgrade)
  1097. {
  1098. struct cyttsp5_loader_data *ld = container_of(fw_and_config_upgrade,
  1099. struct cyttsp5_loader_data, fw_and_config_upgrade);
  1100. struct device *dev = ld->dev;
  1101. ld->si = cmd->request_sysinfo(dev);
  1102. if (!ld->si)
  1103. dev_err(dev, "%s: Fail get sysinfo pointer from core\n",
  1104. __func__);
  1105. #if !CYTTSP5_FW_UPGRADE
  1106. dev_info(dev, "%s: No FW upgrade method selected!\n", __func__);
  1107. #endif
  1108. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_FW_UPGRADE
  1109. if (!upgrade_firmware_from_platform(dev, false))
  1110. return;
  1111. #endif
  1112. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_BINARY_FW_UPGRADE
  1113. if (!upgrade_firmware_from_builtin(dev))
  1114. return;
  1115. #endif
  1116. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_TTCONFIG_UPGRADE
  1117. if (!upgrade_ttconfig_from_platform(dev))
  1118. return;
  1119. #endif
  1120. }
  1121. #if CYTTSP5_FW_UPGRADE
  1122. static int cyttsp5_fw_upgrade_cb(struct device *dev)
  1123. {
  1124. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_FW_UPGRADE
  1125. if (!upgrade_firmware_from_platform(dev, false))
  1126. return 1;
  1127. #endif
  1128. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_BINARY_FW_UPGRADE
  1129. if (!upgrade_firmware_from_builtin(dev))
  1130. return 1;
  1131. #endif
  1132. return 0;
  1133. }
  1134. #endif
  1135. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_FW_UPGRADE
  1136. static ssize_t cyttsp5_forced_upgrade_store(struct device *dev,
  1137. struct device_attribute *attr, const char *buf, size_t size)
  1138. {
  1139. int rc = upgrade_firmware_from_platform(dev, true);
  1140. if (rc)
  1141. return rc;
  1142. return size;
  1143. }
  1144. static DEVICE_ATTR(forced_upgrade, S_IWUSR,
  1145. NULL, cyttsp5_forced_upgrade_store);
  1146. #endif
  1147. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_BINARY_FW_UPGRADE
  1148. static ssize_t cyttsp5_manual_upgrade_store(struct device *dev,
  1149. struct device_attribute *attr, const char *buf, size_t size)
  1150. {
  1151. struct cyttsp5_loader_data *ld = cyttsp5_get_loader_data(dev);
  1152. int rc;
  1153. if (ld->is_manual_upgrade_enabled)
  1154. return -EBUSY;
  1155. ld->is_manual_upgrade_enabled = 1;
  1156. rc = upgrade_firmware_from_class(ld->dev);
  1157. if (rc < 0)
  1158. ld->is_manual_upgrade_enabled = 0;
  1159. return size;
  1160. }
  1161. static DEVICE_ATTR(manual_upgrade, S_IWUSR,
  1162. NULL, cyttsp5_manual_upgrade_store);
  1163. #endif
  1164. static int cyttsp5_loader_probe(struct device *dev, void **data)
  1165. {
  1166. struct cyttsp5_loader_data *ld;
  1167. struct cyttsp5_platform_data *pdata = dev_get_platdata(dev);
  1168. int rc;
  1169. if (!pdata || !pdata->loader_pdata) {
  1170. dev_err(dev, "%s: Missing platform data\n", __func__);
  1171. rc = -ENODEV;
  1172. goto error_no_pdata;
  1173. }
  1174. ld = kzalloc(sizeof(*ld), GFP_KERNEL);
  1175. if (!ld) {
  1176. rc = -ENOMEM;
  1177. goto error_alloc_data_failed;
  1178. }
  1179. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_FW_UPGRADE
  1180. rc = device_create_file(dev, &dev_attr_forced_upgrade);
  1181. if (rc) {
  1182. dev_err(dev, "%s: Error, could not create forced_upgrade\n",
  1183. __func__);
  1184. goto error_create_forced_upgrade;
  1185. }
  1186. #endif
  1187. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_BINARY_FW_UPGRADE
  1188. rc = device_create_file(dev, &dev_attr_manual_upgrade);
  1189. if (rc) {
  1190. dev_err(dev, "%s: Error, could not create manual_upgrade\n",
  1191. __func__);
  1192. goto error_create_manual_upgrade;
  1193. }
  1194. #endif
  1195. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_MANUAL_TTCONFIG_UPGRADE
  1196. rc = device_create_file(dev, &dev_attr_config_loading);
  1197. if (rc) {
  1198. dev_err(dev, "%s: Error, could not create config_loading\n",
  1199. __func__);
  1200. goto error_create_config_loading;
  1201. }
  1202. rc = device_create_bin_file(dev, &bin_attr_config_data);
  1203. if (rc) {
  1204. dev_err(dev, "%s: Error, could not create config_data\n",
  1205. __func__);
  1206. goto error_create_config_data;
  1207. }
  1208. #endif
  1209. ld->loader_pdata = pdata->loader_pdata;
  1210. ld->dev = dev;
  1211. *data = ld;
  1212. #if CYTTSP5_FW_UPGRADE
  1213. init_completion(&ld->int_running);
  1214. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_BINARY_FW_UPGRADE
  1215. init_completion(&ld->builtin_bin_fw_complete);
  1216. #endif
  1217. cmd->subscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_LOADER_NAME,
  1218. cyttsp5_loader_attention, CY_MODE_BOOTLOADER);
  1219. cmd->subscribe_attention(dev, CY_ATTEN_LOADER, CYTTSP5_LOADER_NAME,
  1220. cyttsp5_fw_upgrade_cb, CY_MODE_UNKNOWN);
  1221. #endif
  1222. #if CYTTSP5_FW_UPGRADE || CYTTSP5_TTCONFIG_UPGRADE
  1223. init_completion(&ld->calibration_complete);
  1224. INIT_WORK(&ld->calibration_work, cyttsp5_calibrate_idacs);
  1225. #endif
  1226. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_MANUAL_TTCONFIG_UPGRADE
  1227. mutex_init(&ld->config_lock);
  1228. #endif
  1229. #ifdef UPGRADE_FW_AND_CONFIG_IN_PROBE
  1230. /* Call FW and config upgrade directly in probe */
  1231. cyttsp5_fw_and_config_upgrade(&ld->fw_and_config_upgrade);
  1232. #else
  1233. INIT_WORK(&ld->fw_and_config_upgrade, cyttsp5_fw_and_config_upgrade);
  1234. schedule_work(&ld->fw_and_config_upgrade);
  1235. #endif
  1236. dev_info(dev, "%s: Successful probe %s\n", __func__, dev_name(dev));
  1237. return 0;
  1238. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_MANUAL_TTCONFIG_UPGRADE
  1239. error_create_config_data:
  1240. device_remove_file(dev, &dev_attr_config_loading);
  1241. error_create_config_loading:
  1242. #endif
  1243. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_BINARY_FW_UPGRADE
  1244. device_remove_file(dev, &dev_attr_manual_upgrade);
  1245. error_create_manual_upgrade:
  1246. #endif
  1247. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_FW_UPGRADE
  1248. device_remove_file(dev, &dev_attr_forced_upgrade);
  1249. error_create_forced_upgrade:
  1250. #endif
  1251. kfree(ld);
  1252. error_alloc_data_failed:
  1253. error_no_pdata:
  1254. dev_err(dev, "%s failed.\n", __func__);
  1255. return rc;
  1256. }
  1257. static void cyttsp5_loader_release(struct device *dev, void *data)
  1258. {
  1259. struct cyttsp5_loader_data *ld = (struct cyttsp5_loader_data *)data;
  1260. #if CYTTSP5_FW_UPGRADE
  1261. cmd->unsubscribe_attention(dev, CY_ATTEN_IRQ, CYTTSP5_LOADER_NAME,
  1262. cyttsp5_loader_attention, CY_MODE_BOOTLOADER);
  1263. cmd->unsubscribe_attention(dev, CY_ATTEN_LOADER, CYTTSP5_LOADER_NAME,
  1264. cyttsp5_fw_upgrade_cb, CY_MODE_UNKNOWN);
  1265. #endif
  1266. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_MANUAL_TTCONFIG_UPGRADE
  1267. device_remove_bin_file(dev, &bin_attr_config_data);
  1268. device_remove_file(dev, &dev_attr_config_loading);
  1269. kfree(ld->config_data);
  1270. #endif
  1271. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_BINARY_FW_UPGRADE
  1272. device_remove_file(dev, &dev_attr_manual_upgrade);
  1273. #endif
  1274. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP5_PLATFORM_FW_UPGRADE
  1275. device_remove_file(dev, &dev_attr_forced_upgrade);
  1276. #endif
  1277. kfree(ld);
  1278. }
  1279. static struct cyttsp5_module loader_module = {
  1280. .name = CYTTSP5_LOADER_NAME,
  1281. .probe = cyttsp5_loader_probe,
  1282. .release = cyttsp5_loader_release,
  1283. };
  1284. static int __init cyttsp5_loader_init(void)
  1285. {
  1286. int rc;
  1287. cmd = cyttsp5_get_commands();
  1288. if (!cmd)
  1289. return -EINVAL;
  1290. rc = cyttsp5_register_module(&loader_module);
  1291. if (rc < 0) {
  1292. pr_err("%s: Error, failed registering module\n",
  1293. __func__);
  1294. return rc;
  1295. }
  1296. pr_info("%s: Parade TTSP FW Loader Driver (Built %s) rc=%d\n",
  1297. __func__, CY_DRIVER_VERSION, rc);
  1298. return 0;
  1299. }
  1300. module_init(cyttsp5_loader_init);
  1301. static void __exit cyttsp5_loader_exit(void)
  1302. {
  1303. cyttsp5_unregister_module(&loader_module);
  1304. }
  1305. module_exit(cyttsp5_loader_exit);
  1306. MODULE_LICENSE("GPL");
  1307. MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product FW Loader Driver");
  1308. MODULE_AUTHOR("Parade Technologies <ttdrivers@paradetech.com>");