synaptics_tcm_zeroflash.c 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012
  1. /*
  2. * Synaptics TCM touchscreen driver
  3. *
  4. * Copyright (C) 2017-2019 Synaptics Incorporated. All rights reserved.
  5. *
  6. * Copyright (C) 2017-2019 Scott Lin <[email protected]>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * INFORMATION CONTAINED IN THIS DOCUMENT IS PROVIDED "AS-IS," AND SYNAPTICS
  19. * EXPRESSLY DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES, INCLUDING ANY
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
  21. * AND ANY WARRANTIES OF NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS.
  22. * IN NO EVENT SHALL SYNAPTICS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, PUNITIVE, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN CONNECTION
  24. * WITH THE USE OF THE INFORMATION CONTAINED IN THIS DOCUMENT, HOWEVER CAUSED
  25. * AND BASED ON ANY THEORY OF LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  26. * NEGLIGENCE OR OTHER TORTIOUS ACTION, AND EVEN IF SYNAPTICS WAS ADVISED OF
  27. * THE POSSIBILITY OF SUCH DAMAGE. IF A TRIBUNAL OF COMPETENT JURISDICTION DOES
  28. * NOT PERMIT THE DISCLAIMER OF DIRECT DAMAGES OR ANY OTHER DAMAGES, SYNAPTICS'
  29. * TOTAL CUMULATIVE LIABILITY TO ANY PARTY SHALL NOT EXCEED ONE HUNDRED U.S.
  30. * DOLLARS.
  31. */
  32. #include <linux/gpio.h>
  33. #include <linux/crc32.h>
  34. #include <linux/firmware.h>
  35. #include "synaptics_tcm_core.h"
  36. #define FW_IMAGE_NAME "synaptics/hdl_firmware.img"
  37. #define BOOT_CONFIG_ID "BOOT_CONFIG"
  38. #define F35_APP_CODE_ID "F35_APP_CODE"
  39. #define APP_CONFIG_ID "APP_CONFIG"
  40. #define DISP_CONFIG_ID "DISPLAY"
  41. #define IMAGE_FILE_MAGIC_VALUE 0x4818472b
  42. #define FLASH_AREA_MAGIC_VALUE 0x7c05e516
  43. #define PDT_START_ADDR 0x00e9
  44. #define PDT_END_ADDR 0x00ee
  45. #define UBL_FN_NUMBER 0x35
  46. #define F35_CTRL3_OFFSET 18
  47. #define F35_CTRL7_OFFSET 22
  48. #define F35_WRITE_FW_TO_PMEM_COMMAND 4
  49. #define RESET_TO_HDL_DELAY_MS 12
  50. #define DOWNLOAD_RETRY_COUNT 10
  51. enum f35_error_code {
  52. SUCCESS = 0,
  53. UNKNOWN_FLASH_PRESENT,
  54. MAGIC_NUMBER_NOT_PRESENT,
  55. INVALID_BLOCK_NUMBER,
  56. BLOCK_NOT_ERASED,
  57. NO_FLASH_PRESENT,
  58. CHECKSUM_FAILURE,
  59. WRITE_FAILURE,
  60. INVALID_COMMAND,
  61. IN_DEBUG_MODE,
  62. INVALID_HEADER,
  63. REQUESTING_FIRMWARE,
  64. INVALID_CONFIGURATION,
  65. DISABLE_BLOCK_PROTECT_FAILURE,
  66. };
  67. enum config_download {
  68. HDL_INVALID = 0,
  69. HDL_TOUCH_CONFIG,
  70. HDL_DISPLAY_CONFIG,
  71. HDL_DISPLAY_CONFIG_TO_RAM,
  72. };
  73. struct area_descriptor {
  74. unsigned char magic_value[4];
  75. unsigned char id_string[16];
  76. unsigned char flags[4];
  77. unsigned char flash_addr_words[4];
  78. unsigned char length[4];
  79. unsigned char checksum[4];
  80. };
  81. struct block_data {
  82. const unsigned char *data;
  83. unsigned int size;
  84. unsigned int flash_addr;
  85. };
  86. struct image_info {
  87. unsigned int packrat_number;
  88. struct block_data boot_config;
  89. struct block_data app_firmware;
  90. struct block_data app_config;
  91. struct block_data disp_config;
  92. };
  93. struct image_header {
  94. unsigned char magic_value[4];
  95. unsigned char num_of_areas[4];
  96. };
  97. struct rmi_f35_query {
  98. unsigned char version:4;
  99. unsigned char has_debug_mode:1;
  100. unsigned char has_data5:1;
  101. unsigned char has_query1:1;
  102. unsigned char has_query2:1;
  103. unsigned char chunk_size;
  104. unsigned char has_ctrl7:1;
  105. unsigned char has_host_download:1;
  106. unsigned char has_spi_master:1;
  107. unsigned char advanced_recovery_mode:1;
  108. unsigned char reserved:4;
  109. } __packed;
  110. struct rmi_f35_data {
  111. unsigned char error_code:5;
  112. unsigned char recovery_mode_forced:1;
  113. unsigned char nvm_programmed:1;
  114. unsigned char in_recovery:1;
  115. } __packed;
  116. struct rmi_pdt_entry {
  117. unsigned char query_base_addr;
  118. unsigned char command_base_addr;
  119. unsigned char control_base_addr;
  120. unsigned char data_base_addr;
  121. unsigned char intr_src_count:3;
  122. unsigned char reserved_1:2;
  123. unsigned char fn_version:2;
  124. unsigned char reserved_2:1;
  125. unsigned char fn_number;
  126. } __packed;
  127. struct rmi_addr {
  128. unsigned short query_base;
  129. unsigned short command_base;
  130. unsigned short control_base;
  131. unsigned short data_base;
  132. };
  133. struct firmware_status {
  134. unsigned short invalid_static_config:1;
  135. unsigned short need_disp_config:1;
  136. unsigned short need_app_config:1;
  137. unsigned short hdl_version:4;
  138. unsigned short reserved:9;
  139. } __packed;
  140. struct zeroflash_hcd {
  141. bool has_hdl;
  142. bool f35_ready;
  143. const unsigned char *image;
  144. unsigned char *buf;
  145. const struct firmware *fw_entry;
  146. struct work_struct config_work;
  147. struct work_struct firmware_work;
  148. struct workqueue_struct *workqueue;
  149. struct rmi_addr f35_addr;
  150. struct image_info image_info;
  151. struct firmware_status fw_status;
  152. struct syna_tcm_buffer out;
  153. struct syna_tcm_buffer resp;
  154. struct syna_tcm_hcd *tcm_hcd;
  155. };
  156. DECLARE_COMPLETION(zeroflash_remove_complete);
  157. static struct zeroflash_hcd *zeroflash_hcd;
  158. static int zeroflash_check_uboot(void)
  159. {
  160. int retval;
  161. unsigned char fn_number;
  162. struct rmi_f35_query query;
  163. struct rmi_pdt_entry p_entry;
  164. struct syna_tcm_hcd *tcm_hcd = zeroflash_hcd->tcm_hcd;
  165. retval = syna_tcm_rmi_read(tcm_hcd,
  166. PDT_END_ADDR,
  167. &fn_number,
  168. sizeof(fn_number));
  169. if (retval < 0) {
  170. LOGE(tcm_hcd->pdev->dev.parent,
  171. "Failed to read RMI function number\n");
  172. return retval;
  173. }
  174. LOGD(tcm_hcd->pdev->dev.parent,
  175. "Found F$%02x\n",
  176. fn_number);
  177. if (fn_number != UBL_FN_NUMBER) {
  178. LOGE(tcm_hcd->pdev->dev.parent,
  179. "Failed to find F$35\n");
  180. return -ENODEV;
  181. }
  182. if (zeroflash_hcd->f35_ready)
  183. return 0;
  184. retval = syna_tcm_rmi_read(tcm_hcd,
  185. PDT_START_ADDR,
  186. (unsigned char *)&p_entry,
  187. sizeof(p_entry));
  188. if (retval < 0) {
  189. LOGE(tcm_hcd->pdev->dev.parent,
  190. "Failed to read PDT entry\n");
  191. return retval;
  192. }
  193. zeroflash_hcd->f35_addr.query_base = p_entry.query_base_addr;
  194. zeroflash_hcd->f35_addr.command_base = p_entry.command_base_addr;
  195. zeroflash_hcd->f35_addr.control_base = p_entry.control_base_addr;
  196. zeroflash_hcd->f35_addr.data_base = p_entry.data_base_addr;
  197. retval = syna_tcm_rmi_read(tcm_hcd,
  198. zeroflash_hcd->f35_addr.query_base,
  199. (unsigned char *)&query,
  200. sizeof(query));
  201. if (retval < 0) {
  202. LOGE(tcm_hcd->pdev->dev.parent,
  203. "Failed to read F$35 query\n");
  204. return retval;
  205. }
  206. zeroflash_hcd->f35_ready = true;
  207. if (query.has_query2 && query.has_ctrl7 && query.has_host_download) {
  208. zeroflash_hcd->has_hdl = true;
  209. } else {
  210. LOGE(tcm_hcd->pdev->dev.parent,
  211. "Host download not supported\n");
  212. zeroflash_hcd->has_hdl = false;
  213. return -ENODEV;
  214. }
  215. return 0;
  216. }
  217. static int zeroflash_parse_fw_image(void)
  218. {
  219. unsigned int idx;
  220. unsigned int addr;
  221. unsigned int offset;
  222. unsigned int length;
  223. unsigned int checksum;
  224. unsigned int flash_addr;
  225. unsigned int magic_value;
  226. unsigned int num_of_areas;
  227. struct image_header *header;
  228. struct image_info *image_info;
  229. struct area_descriptor *descriptor;
  230. struct syna_tcm_hcd *tcm_hcd = zeroflash_hcd->tcm_hcd;
  231. const unsigned char *image;
  232. const unsigned char *content;
  233. image = zeroflash_hcd->image;
  234. image_info = &zeroflash_hcd->image_info;
  235. header = (struct image_header *)image;
  236. magic_value = le4_to_uint(header->magic_value);
  237. if (magic_value != IMAGE_FILE_MAGIC_VALUE) {
  238. LOGE(tcm_hcd->pdev->dev.parent,
  239. "Invalid image file magic value\n");
  240. return -EINVAL;
  241. }
  242. memset(image_info, 0x00, sizeof(*image_info));
  243. offset = sizeof(*header);
  244. num_of_areas = le4_to_uint(header->num_of_areas);
  245. for (idx = 0; idx < num_of_areas; idx++) {
  246. addr = le4_to_uint(image + offset);
  247. descriptor = (struct area_descriptor *)(image + addr);
  248. offset += 4;
  249. magic_value = le4_to_uint(descriptor->magic_value);
  250. if (magic_value != FLASH_AREA_MAGIC_VALUE)
  251. continue;
  252. length = le4_to_uint(descriptor->length);
  253. content = (unsigned char *)descriptor + sizeof(*descriptor);
  254. flash_addr = le4_to_uint(descriptor->flash_addr_words) * 2;
  255. checksum = le4_to_uint(descriptor->checksum);
  256. if (!memcmp((char *)descriptor->id_string,
  257. BOOT_CONFIG_ID,
  258. strlen(BOOT_CONFIG_ID))) {
  259. if (checksum != (crc32(~0, content, length) ^ ~0)) {
  260. LOGE(tcm_hcd->pdev->dev.parent,
  261. "Boot config checksum error\n");
  262. return -EINVAL;
  263. }
  264. image_info->boot_config.size = length;
  265. image_info->boot_config.data = content;
  266. image_info->boot_config.flash_addr = flash_addr;
  267. LOGD(tcm_hcd->pdev->dev.parent,
  268. "Boot config size = %d\n",
  269. length);
  270. LOGD(tcm_hcd->pdev->dev.parent,
  271. "Boot config flash address = 0x%08x\n",
  272. flash_addr);
  273. } else if (!memcmp((char *)descriptor->id_string,
  274. F35_APP_CODE_ID,
  275. strlen(F35_APP_CODE_ID))) {
  276. if (checksum != (crc32(~0, content, length) ^ ~0)) {
  277. LOGE(tcm_hcd->pdev->dev.parent,
  278. "APP firmware checksum error\n");
  279. return -EINVAL;
  280. }
  281. image_info->app_firmware.size = length;
  282. image_info->app_firmware.data = content;
  283. image_info->app_firmware.flash_addr = flash_addr;
  284. LOGD(tcm_hcd->pdev->dev.parent,
  285. "Application firmware size = %d\n",
  286. length);
  287. LOGD(tcm_hcd->pdev->dev.parent,
  288. "Application firmware flash address = 0x%08x\n",
  289. flash_addr);
  290. } else if (!memcmp((char *)descriptor->id_string,
  291. APP_CONFIG_ID,
  292. strlen(APP_CONFIG_ID))) {
  293. if (checksum != (crc32(~0, content, length) ^ ~0)) {
  294. LOGE(tcm_hcd->pdev->dev.parent,
  295. "Application config checksum error\n");
  296. return -EINVAL;
  297. }
  298. image_info->app_config.size = length;
  299. image_info->app_config.data = content;
  300. image_info->app_config.flash_addr = flash_addr;
  301. image_info->packrat_number = le4_to_uint(&content[14]);
  302. LOGD(tcm_hcd->pdev->dev.parent,
  303. "Application config size = %d\n",
  304. length);
  305. LOGD(tcm_hcd->pdev->dev.parent,
  306. "Application config flash address = 0x%08x\n",
  307. flash_addr);
  308. } else if (!memcmp((char *)descriptor->id_string,
  309. DISP_CONFIG_ID,
  310. strlen(DISP_CONFIG_ID))) {
  311. if (checksum != (crc32(~0, content, length) ^ ~0)) {
  312. LOGE(tcm_hcd->pdev->dev.parent,
  313. "Display config checksum error\n");
  314. return -EINVAL;
  315. }
  316. image_info->disp_config.size = length;
  317. image_info->disp_config.data = content;
  318. image_info->disp_config.flash_addr = flash_addr;
  319. LOGD(tcm_hcd->pdev->dev.parent,
  320. "Display config size = %d\n",
  321. length);
  322. LOGD(tcm_hcd->pdev->dev.parent,
  323. "Display config flash address = 0x%08x\n",
  324. flash_addr);
  325. }
  326. }
  327. return 0;
  328. }
  329. static int zeroflash_get_fw_image(void)
  330. {
  331. int retval;
  332. struct syna_tcm_hcd *tcm_hcd = zeroflash_hcd->tcm_hcd;
  333. if (zeroflash_hcd->fw_entry != NULL)
  334. return 0;
  335. do {
  336. retval = request_firmware(&zeroflash_hcd->fw_entry,
  337. FW_IMAGE_NAME,
  338. tcm_hcd->pdev->dev.parent);
  339. if (retval < 0) {
  340. LOGD(tcm_hcd->pdev->dev.parent,
  341. "Failed to request %s\n",
  342. FW_IMAGE_NAME);
  343. msleep(100);
  344. } else {
  345. break;
  346. }
  347. } while (1);
  348. LOGD(tcm_hcd->pdev->dev.parent,
  349. "Firmware image size = %d\n",
  350. (unsigned int)zeroflash_hcd->fw_entry->size);
  351. zeroflash_hcd->image = zeroflash_hcd->fw_entry->data;
  352. retval = zeroflash_parse_fw_image();
  353. if (retval < 0) {
  354. LOGE(tcm_hcd->pdev->dev.parent,
  355. "Failed to parse firmware image\n");
  356. release_firmware(zeroflash_hcd->fw_entry);
  357. zeroflash_hcd->fw_entry = NULL;
  358. zeroflash_hcd->image = NULL;
  359. return retval;
  360. }
  361. return 0;
  362. }
  363. static void zeroflash_download_config(void)
  364. {
  365. struct firmware_status *fw_status;
  366. struct syna_tcm_hcd *tcm_hcd = zeroflash_hcd->tcm_hcd;
  367. fw_status = &zeroflash_hcd->fw_status;
  368. if (!fw_status->need_app_config && !fw_status->need_disp_config) {
  369. if (atomic_read(&tcm_hcd->helper.task) == HELP_NONE) {
  370. atomic_set(&tcm_hcd->helper.task,
  371. HELP_SEND_RESET_NOTIFICATION);
  372. queue_work(tcm_hcd->helper.workqueue,
  373. &tcm_hcd->helper.work);
  374. }
  375. atomic_set(&tcm_hcd->host_downloading, 0);
  376. return;
  377. }
  378. queue_work(zeroflash_hcd->workqueue, &zeroflash_hcd->config_work);
  379. }
  380. static void zeroflash_download_firmware(void)
  381. {
  382. queue_work(zeroflash_hcd->workqueue, &zeroflash_hcd->firmware_work);
  383. }
  384. static int zeroflash_download_disp_config(void)
  385. {
  386. int retval;
  387. unsigned char response_code;
  388. struct image_info *image_info;
  389. struct syna_tcm_hcd *tcm_hcd = zeroflash_hcd->tcm_hcd;
  390. static unsigned int retry_count;
  391. LOGN(tcm_hcd->pdev->dev.parent,
  392. "Downloading display config\n");
  393. image_info = &zeroflash_hcd->image_info;
  394. if (image_info->disp_config.size == 0) {
  395. LOGE(tcm_hcd->pdev->dev.parent,
  396. "No display config in image file\n");
  397. return -EINVAL;
  398. }
  399. LOCK_BUFFER(zeroflash_hcd->out);
  400. retval = syna_tcm_alloc_mem(tcm_hcd,
  401. &zeroflash_hcd->out,
  402. image_info->disp_config.size + 2);
  403. if (retval < 0) {
  404. LOGE(tcm_hcd->pdev->dev.parent,
  405. "Failed to allocate memory for out.buf\n");
  406. goto unlock_out;
  407. }
  408. switch (zeroflash_hcd->fw_status.hdl_version) {
  409. case 0:
  410. zeroflash_hcd->out.buf[0] = 1;
  411. break;
  412. case 1:
  413. zeroflash_hcd->out.buf[0] = 2;
  414. break;
  415. default:
  416. retval = -EINVAL;
  417. LOGE(tcm_hcd->pdev->dev.parent,
  418. "Invalid HDL version (%d)\n",
  419. zeroflash_hcd->fw_status.hdl_version);
  420. goto unlock_out;
  421. }
  422. zeroflash_hcd->out.buf[1] = HDL_DISPLAY_CONFIG;
  423. retval = secure_memcpy(&zeroflash_hcd->out.buf[2],
  424. zeroflash_hcd->out.buf_size - 2,
  425. image_info->disp_config.data,
  426. image_info->disp_config.size,
  427. image_info->disp_config.size);
  428. if (retval < 0) {
  429. LOGE(tcm_hcd->pdev->dev.parent,
  430. "Failed to copy display config data\n");
  431. goto unlock_out;
  432. }
  433. zeroflash_hcd->out.data_length = image_info->disp_config.size + 2;
  434. LOCK_BUFFER(zeroflash_hcd->resp);
  435. retval = tcm_hcd->write_message(tcm_hcd,
  436. CMD_DOWNLOAD_CONFIG,
  437. zeroflash_hcd->out.buf,
  438. zeroflash_hcd->out.data_length,
  439. &zeroflash_hcd->resp.buf,
  440. &zeroflash_hcd->resp.buf_size,
  441. &zeroflash_hcd->resp.data_length,
  442. &response_code,
  443. 0);
  444. if (retval < 0) {
  445. LOGE(tcm_hcd->pdev->dev.parent,
  446. "Failed to write command %s\n",
  447. STR(CMD_DOWNLOAD_CONFIG));
  448. if (response_code != STATUS_ERROR)
  449. goto unlock_resp;
  450. retry_count++;
  451. if (DOWNLOAD_RETRY_COUNT && retry_count > DOWNLOAD_RETRY_COUNT)
  452. goto unlock_resp;
  453. } else {
  454. retry_count = 0;
  455. }
  456. retval = secure_memcpy((unsigned char *)&zeroflash_hcd->fw_status,
  457. sizeof(zeroflash_hcd->fw_status),
  458. zeroflash_hcd->resp.buf,
  459. zeroflash_hcd->resp.buf_size,
  460. sizeof(zeroflash_hcd->fw_status));
  461. if (retval < 0) {
  462. LOGE(tcm_hcd->pdev->dev.parent,
  463. "Failed to copy firmware status\n");
  464. goto unlock_resp;
  465. }
  466. LOGN(tcm_hcd->pdev->dev.parent,
  467. "Display config downloaded\n");
  468. retval = 0;
  469. unlock_resp:
  470. UNLOCK_BUFFER(zeroflash_hcd->resp);
  471. unlock_out:
  472. UNLOCK_BUFFER(zeroflash_hcd->out);
  473. return retval;
  474. }
  475. static int zeroflash_download_app_config(void)
  476. {
  477. int retval;
  478. unsigned char padding;
  479. unsigned char response_code;
  480. struct image_info *image_info;
  481. struct syna_tcm_hcd *tcm_hcd = zeroflash_hcd->tcm_hcd;
  482. static unsigned int retry_count;
  483. LOGN(tcm_hcd->pdev->dev.parent,
  484. "Downloading application config\n");
  485. image_info = &zeroflash_hcd->image_info;
  486. if (image_info->app_config.size == 0) {
  487. LOGE(tcm_hcd->pdev->dev.parent,
  488. "No application config in image file\n");
  489. return -EINVAL;
  490. }
  491. padding = image_info->app_config.size % 8;
  492. if (padding)
  493. padding = 8 - padding;
  494. LOCK_BUFFER(zeroflash_hcd->out);
  495. retval = syna_tcm_alloc_mem(tcm_hcd,
  496. &zeroflash_hcd->out,
  497. image_info->app_config.size + 2 + padding);
  498. if (retval < 0) {
  499. LOGE(tcm_hcd->pdev->dev.parent,
  500. "Failed to allocate memory for out.buf\n");
  501. goto unlock_out;
  502. }
  503. switch (zeroflash_hcd->fw_status.hdl_version) {
  504. case 0:
  505. zeroflash_hcd->out.buf[0] = 1;
  506. break;
  507. case 1:
  508. zeroflash_hcd->out.buf[0] = 2;
  509. break;
  510. default:
  511. retval = -EINVAL;
  512. LOGE(tcm_hcd->pdev->dev.parent,
  513. "Invalid HDL version (%d)\n",
  514. zeroflash_hcd->fw_status.hdl_version);
  515. goto unlock_out;
  516. }
  517. zeroflash_hcd->out.buf[1] = HDL_TOUCH_CONFIG;
  518. retval = secure_memcpy(&zeroflash_hcd->out.buf[2],
  519. zeroflash_hcd->out.buf_size - 2,
  520. image_info->app_config.data,
  521. image_info->app_config.size,
  522. image_info->app_config.size);
  523. if (retval < 0) {
  524. LOGE(tcm_hcd->pdev->dev.parent,
  525. "Failed to copy application config data\n");
  526. goto unlock_out;
  527. }
  528. zeroflash_hcd->out.data_length = image_info->app_config.size + 2;
  529. zeroflash_hcd->out.data_length += padding;
  530. LOCK_BUFFER(zeroflash_hcd->resp);
  531. retval = tcm_hcd->write_message(tcm_hcd,
  532. CMD_DOWNLOAD_CONFIG,
  533. zeroflash_hcd->out.buf,
  534. zeroflash_hcd->out.data_length,
  535. &zeroflash_hcd->resp.buf,
  536. &zeroflash_hcd->resp.buf_size,
  537. &zeroflash_hcd->resp.data_length,
  538. &response_code,
  539. 0);
  540. if (retval < 0) {
  541. LOGE(tcm_hcd->pdev->dev.parent,
  542. "Failed to write command %s\n",
  543. STR(CMD_DOWNLOAD_CONFIG));
  544. if (response_code != STATUS_ERROR)
  545. goto unlock_resp;
  546. retry_count++;
  547. if (DOWNLOAD_RETRY_COUNT && retry_count > DOWNLOAD_RETRY_COUNT)
  548. goto unlock_resp;
  549. } else {
  550. retry_count = 0;
  551. }
  552. retval = secure_memcpy((unsigned char *)&zeroflash_hcd->fw_status,
  553. sizeof(zeroflash_hcd->fw_status),
  554. zeroflash_hcd->resp.buf,
  555. zeroflash_hcd->resp.buf_size,
  556. sizeof(zeroflash_hcd->fw_status));
  557. if (retval < 0) {
  558. LOGE(tcm_hcd->pdev->dev.parent,
  559. "Failed to copy firmware status\n");
  560. goto unlock_resp;
  561. }
  562. LOGN(tcm_hcd->pdev->dev.parent,
  563. "Application config downloaded\n");
  564. retval = 0;
  565. unlock_resp:
  566. UNLOCK_BUFFER(zeroflash_hcd->resp);
  567. unlock_out:
  568. UNLOCK_BUFFER(zeroflash_hcd->out);
  569. return retval;
  570. }
  571. static void zeroflash_download_config_work(struct work_struct *work)
  572. {
  573. int retval;
  574. struct syna_tcm_hcd *tcm_hcd = zeroflash_hcd->tcm_hcd;
  575. retval = zeroflash_get_fw_image();
  576. if (retval < 0) {
  577. LOGE(tcm_hcd->pdev->dev.parent,
  578. "Failed to get firmware image\n");
  579. return;
  580. }
  581. LOGN(tcm_hcd->pdev->dev.parent,
  582. "Start of config download\n");
  583. if (zeroflash_hcd->fw_status.need_app_config) {
  584. retval = zeroflash_download_app_config();
  585. if (retval < 0) {
  586. LOGE(tcm_hcd->pdev->dev.parent,
  587. "Failed to download application config\n");
  588. return;
  589. }
  590. goto exit;
  591. }
  592. if (zeroflash_hcd->fw_status.need_disp_config) {
  593. retval = zeroflash_download_disp_config();
  594. if (retval < 0) {
  595. LOGE(tcm_hcd->pdev->dev.parent,
  596. "Failed to download display config\n");
  597. return;
  598. }
  599. goto exit;
  600. }
  601. exit:
  602. LOGN(tcm_hcd->pdev->dev.parent,
  603. "End of config download\n");
  604. zeroflash_download_config();
  605. }
  606. static int zeroflash_download_app_fw(void)
  607. {
  608. int retval;
  609. unsigned char command;
  610. struct image_info *image_info;
  611. struct syna_tcm_hcd *tcm_hcd = zeroflash_hcd->tcm_hcd;
  612. #if RESET_TO_HDL_DELAY_MS
  613. const struct syna_tcm_board_data *bdata = tcm_hcd->hw_if->bdata;
  614. #endif
  615. LOGN(tcm_hcd->pdev->dev.parent,
  616. "Downloading application firmware\n");
  617. image_info = &zeroflash_hcd->image_info;
  618. if (image_info->app_firmware.size == 0) {
  619. LOGE(tcm_hcd->pdev->dev.parent,
  620. "No application firmware in image file\n");
  621. return -EINVAL;
  622. }
  623. LOCK_BUFFER(zeroflash_hcd->out);
  624. retval = syna_tcm_alloc_mem(tcm_hcd,
  625. &zeroflash_hcd->out,
  626. image_info->app_firmware.size);
  627. if (retval < 0) {
  628. LOGE(tcm_hcd->pdev->dev.parent,
  629. "Failed to allocate memory for out.buf\n");
  630. UNLOCK_BUFFER(zeroflash_hcd->out);
  631. return retval;
  632. }
  633. retval = secure_memcpy(zeroflash_hcd->out.buf,
  634. zeroflash_hcd->out.buf_size,
  635. image_info->app_firmware.data,
  636. image_info->app_firmware.size,
  637. image_info->app_firmware.size);
  638. if (retval < 0) {
  639. LOGE(tcm_hcd->pdev->dev.parent,
  640. "Failed to copy application firmware data\n");
  641. UNLOCK_BUFFER(zeroflash_hcd->out);
  642. return retval;
  643. }
  644. zeroflash_hcd->out.data_length = image_info->app_firmware.size;
  645. command = F35_WRITE_FW_TO_PMEM_COMMAND;
  646. #if RESET_TO_HDL_DELAY_MS
  647. gpio_set_value(bdata->reset_gpio, bdata->reset_on_state);
  648. msleep(bdata->reset_active_ms);
  649. gpio_set_value(bdata->reset_gpio, !bdata->reset_on_state);
  650. msleep(RESET_TO_HDL_DELAY_MS);
  651. #endif
  652. retval = syna_tcm_rmi_write(tcm_hcd,
  653. zeroflash_hcd->f35_addr.control_base + F35_CTRL3_OFFSET,
  654. &command,
  655. sizeof(command));
  656. if (retval < 0) {
  657. LOGE(tcm_hcd->pdev->dev.parent,
  658. "Failed to write F$35 command\n");
  659. UNLOCK_BUFFER(zeroflash_hcd->out);
  660. return retval;
  661. }
  662. retval = syna_tcm_rmi_write(tcm_hcd,
  663. zeroflash_hcd->f35_addr.control_base + F35_CTRL7_OFFSET,
  664. zeroflash_hcd->out.buf,
  665. zeroflash_hcd->out.data_length);
  666. if (retval < 0) {
  667. LOGE(tcm_hcd->pdev->dev.parent,
  668. "Failed to write application firmware data\n");
  669. UNLOCK_BUFFER(zeroflash_hcd->out);
  670. return retval;
  671. }
  672. UNLOCK_BUFFER(zeroflash_hcd->out);
  673. LOGN(tcm_hcd->pdev->dev.parent,
  674. "Application firmware downloaded\n");
  675. return 0;
  676. }
  677. static void zeroflash_download_firmware_work(struct work_struct *work)
  678. {
  679. int retval;
  680. struct rmi_f35_data data;
  681. struct syna_tcm_hcd *tcm_hcd = zeroflash_hcd->tcm_hcd;
  682. static unsigned int retry_count;
  683. retval = zeroflash_check_uboot();
  684. if (retval < 0) {
  685. LOGE(tcm_hcd->pdev->dev.parent,
  686. "Microbootloader support unavailable\n");
  687. goto exit;
  688. }
  689. atomic_set(&tcm_hcd->host_downloading, 1);
  690. retval = syna_tcm_rmi_read(tcm_hcd,
  691. zeroflash_hcd->f35_addr.data_base,
  692. (unsigned char *)&data,
  693. sizeof(data));
  694. if (retval < 0) {
  695. LOGE(tcm_hcd->pdev->dev.parent,
  696. "Failed to read F$35 data\n");
  697. goto exit;
  698. }
  699. if (data.error_code != REQUESTING_FIRMWARE) {
  700. LOGE(tcm_hcd->pdev->dev.parent,
  701. "Microbootloader error code = 0x%02x\n",
  702. data.error_code);
  703. if (data.error_code != CHECKSUM_FAILURE) {
  704. retval = -EIO;
  705. goto exit;
  706. } else {
  707. retry_count++;
  708. }
  709. } else {
  710. retry_count = 0;
  711. }
  712. retval = zeroflash_get_fw_image();
  713. if (retval < 0) {
  714. LOGE(tcm_hcd->pdev->dev.parent,
  715. "Failed to get firmware image\n");
  716. goto exit;
  717. }
  718. LOGN(tcm_hcd->pdev->dev.parent,
  719. "Start of firmware download\n");
  720. retval = zeroflash_download_app_fw();
  721. if (retval < 0) {
  722. LOGE(tcm_hcd->pdev->dev.parent,
  723. "Failed to download application firmware\n");
  724. goto exit;
  725. }
  726. LOGN(tcm_hcd->pdev->dev.parent,
  727. "End of firmware download\n");
  728. exit:
  729. if (retval < 0)
  730. retry_count++;
  731. if (DOWNLOAD_RETRY_COUNT && retry_count > DOWNLOAD_RETRY_COUNT) {
  732. retval = tcm_hcd->enable_irq(tcm_hcd, false, true);
  733. if (retval < 0) {
  734. LOGE(tcm_hcd->pdev->dev.parent,
  735. "Failed to disable interrupt\n");
  736. }
  737. } else {
  738. retval = tcm_hcd->enable_irq(tcm_hcd, true, NULL);
  739. if (retval < 0) {
  740. LOGE(tcm_hcd->pdev->dev.parent,
  741. "Failed to enable interrupt\n");
  742. }
  743. }
  744. }
  745. static int zeroflash_init(struct syna_tcm_hcd *tcm_hcd)
  746. {
  747. zeroflash_hcd = kzalloc(sizeof(*zeroflash_hcd), GFP_KERNEL);
  748. if (!zeroflash_hcd) {
  749. LOGE(tcm_hcd->pdev->dev.parent,
  750. "Failed to allocate memory for zeroflash_hcd\n");
  751. return -ENOMEM;
  752. }
  753. zeroflash_hcd->tcm_hcd = tcm_hcd;
  754. INIT_BUFFER(zeroflash_hcd->out, false);
  755. INIT_BUFFER(zeroflash_hcd->resp, false);
  756. zeroflash_hcd->workqueue =
  757. create_singlethread_workqueue("syna_tcm_zeroflash");
  758. INIT_WORK(&zeroflash_hcd->config_work,
  759. zeroflash_download_config_work);
  760. INIT_WORK(&zeroflash_hcd->firmware_work,
  761. zeroflash_download_firmware_work);
  762. if (tcm_hcd->init_okay == false &&
  763. tcm_hcd->hw_if->bus_io->type == BUS_SPI)
  764. zeroflash_download_firmware();
  765. return 0;
  766. }
  767. static int zeroflash_remove(struct syna_tcm_hcd *tcm_hcd)
  768. {
  769. if (!zeroflash_hcd)
  770. goto exit;
  771. if (zeroflash_hcd->fw_entry)
  772. release_firmware(zeroflash_hcd->fw_entry);
  773. cancel_work_sync(&zeroflash_hcd->config_work);
  774. cancel_work_sync(&zeroflash_hcd->firmware_work);
  775. flush_workqueue(zeroflash_hcd->workqueue);
  776. destroy_workqueue(zeroflash_hcd->workqueue);
  777. RELEASE_BUFFER(zeroflash_hcd->resp);
  778. RELEASE_BUFFER(zeroflash_hcd->out);
  779. kfree(zeroflash_hcd);
  780. zeroflash_hcd = NULL;
  781. exit:
  782. complete(&zeroflash_remove_complete);
  783. return 0;
  784. }
  785. static int zeroflash_syncbox(struct syna_tcm_hcd *tcm_hcd)
  786. {
  787. int retval;
  788. unsigned char *fw_status;
  789. if (!zeroflash_hcd)
  790. return 0;
  791. switch (tcm_hcd->report.id) {
  792. case REPORT_STATUS:
  793. fw_status = (unsigned char *)&zeroflash_hcd->fw_status;
  794. retval = secure_memcpy(fw_status,
  795. sizeof(zeroflash_hcd->fw_status),
  796. tcm_hcd->report.buffer.buf,
  797. tcm_hcd->report.buffer.buf_size,
  798. sizeof(zeroflash_hcd->fw_status));
  799. if (retval < 0) {
  800. LOGE(tcm_hcd->pdev->dev.parent,
  801. "Failed to copy firmware status\n");
  802. return retval;
  803. }
  804. zeroflash_download_config();
  805. break;
  806. case REPORT_HDL:
  807. retval = tcm_hcd->enable_irq(tcm_hcd, false, true);
  808. if (retval < 0) {
  809. LOGE(tcm_hcd->pdev->dev.parent,
  810. "Failed to disable interrupt\n");
  811. return retval;
  812. }
  813. zeroflash_download_firmware();
  814. break;
  815. default:
  816. break;
  817. }
  818. return 0;
  819. }
  820. static int zeroflash_reset(struct syna_tcm_hcd *tcm_hcd)
  821. {
  822. int retval;
  823. if (!zeroflash_hcd) {
  824. retval = zeroflash_init(tcm_hcd);
  825. return retval;
  826. }
  827. return 0;
  828. }
  829. static struct syna_tcm_module_cb zeroflash_module = {
  830. .type = TCM_ZEROFLASH,
  831. .init = zeroflash_init,
  832. .remove = zeroflash_remove,
  833. .syncbox = zeroflash_syncbox,
  834. .asyncbox = NULL,
  835. .reset = zeroflash_reset,
  836. .suspend = NULL,
  837. .resume = NULL,
  838. .early_suspend = NULL,
  839. };
  840. static int __init zeroflash_module_init(void)
  841. {
  842. return syna_tcm_add_module(&zeroflash_module, true);
  843. }
  844. static void __exit zeroflash_module_exit(void)
  845. {
  846. syna_tcm_add_module(&zeroflash_module, false);
  847. wait_for_completion(&zeroflash_remove_complete);
  848. }
  849. module_init(zeroflash_module_init);
  850. module_exit(zeroflash_module_exit);
  851. MODULE_AUTHOR("Synaptics, Inc.");
  852. MODULE_DESCRIPTION("Synaptics TCM Zeroflash Module");
  853. MODULE_LICENSE("GPL v2");