cyttsp4_loader.c 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924
  1. /*
  2. * cyttsp4_loader.c
  3. * Cypress TrueTouch(TM) Standard Product V4 FW loader module.
  4. * For use with Cypress Txx4xx parts.
  5. * Supported parts include:
  6. * TMA4XX
  7. * TMA1036
  8. *
  9. * Copyright (C) 2009-2012 Cypress Semiconductor, Inc.
  10. * Copyright (C) 2011 Motorola Mobility, Inc.
  11. *
  12. * This program is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU General Public License
  14. * version 2, and only version 2, as published by the
  15. * Free Software Foundation.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com>
  23. *
  24. */
  25. #include "cyttsp4_regs.h"
  26. #include <linux/firmware.h>
  27. #include <linux/version.h>
  28. #define CYTTSP4_LOADER_NAME "cyttsp4_loader"
  29. #define CYTTSP4_AUTO_LOAD_FOR_CORRUPTED_FW 1
  30. #define UPGRADE_FW_IN_PROBE
  31. //#define CALIBRATE_IN_LOADER
  32. #define CYTTSP4_FW_UPGRADE \
  33. (defined(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_PLATFORM_FW_UPGRADE) \
  34. || defined(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_BINARY_FW_UPGRADE))
  35. #define CYTTSP4_TTCONFIG_UPGRADE \
  36. (defined(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_PLATFORM_TTCONFIG_UPGRADE) \
  37. || defined(CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_MANUAL_TTCONFIG_UPGRADE))
  38. #define CY_CMD_BYTE 1
  39. #define CY_STATUS_BYTE 1
  40. #define CY_MAX_STATUS_SIZE 32
  41. #define CY_START_OF_PACKET 0x01
  42. #define CY_END_OF_PACKET 0x17
  43. #define CY_DATA_ROW_SIZE 288
  44. #define CY_DATA_ROW_SIZE_TMA400 128
  45. #define CY_PACKET_DATA_LEN 96
  46. #define CY_MAX_PACKET_LEN 512
  47. #define CY_COMM_BUSY 0xFF
  48. #define CY_CMD_BUSY 0xFE
  49. #define CY_ARRAY_ID_OFFSET 0
  50. #define CY_ROW_NUM_OFFSET 1
  51. #define CY_ROW_SIZE_OFFSET 3
  52. #define CY_ROW_DATA_OFFSET 5
  53. #define CY_CMD_LDR_HOST_SYNC 0xFF /* tma400 */
  54. #define CY_CMD_LDR_EXIT 0x3B
  55. #define CY_CMD_LDR_EXIT_CMD_SIZE 7
  56. #define CY_CMD_LDR_EXIT_STAT_SIZE 7
  57. #define CY_CMD_LDR_ENTER 0x38
  58. #define CY_CMD_LDR_ENTER_CMD_SIZE 7
  59. #define CY_CMD_LDR_ENTER_STAT_SIZE 15
  60. #define CY_CMD_LDR_INIT 0x48
  61. #define CY_CMD_LDR_INIT_CMD_SIZE 15
  62. #define CY_CMD_LDR_INIT_STAT_SIZE 7
  63. #define CY_CMD_LDR_PROG_ROW 0x39
  64. #define CY_CMD_LDR_PROG_ROW_STAT_SIZE 7
  65. #define CY_CMD_LDR_VERIFY_ROW 0x3A
  66. #define CY_CMD_LDR_VERIFY_ROW_STAT_SIZE 8
  67. #define CY_CMD_LDR_VERIFY_ROW_CMD_SIZE 10
  68. #define CY_CMD_LDR_VERIFY_CHKSUM 0x31
  69. #define CY_CMD_LDR_VERIFY_CHKSUM_CMD_SIZE 7
  70. #define CY_CMD_LDR_VERIFY_CHKSUM_STAT_SIZE 8
  71. struct cyttsp4_loader_data {
  72. struct device *dev;
  73. struct cyttsp4_sysinfo *si;
  74. struct completion int_running;
  75. #if !defined(UPGRADE_FW_IN_PROBE)
  76. struct work_struct fw_and_config_upgrade;
  77. #endif
  78. #if defined(CALIBRATE_IN_LOADER)
  79. struct work_struct calibration_work;
  80. #endif
  81. struct cyttsp4_loader_platform_data *loader_pdata;
  82. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_BINARY_FW_UPGRADE
  83. struct completion builtin_bin_fw_complete;
  84. int builtin_bin_fw_status;
  85. #endif
  86. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_MANUAL_TTCONFIG_UPGRADE
  87. struct mutex config_lock;
  88. u8 *config_data;
  89. int config_size;
  90. bool config_loading;
  91. #endif
  92. u8 status_buf[CY_MAX_STATUS_SIZE];
  93. };
  94. struct cyttsp4_dev_id {
  95. u32 silicon_id;
  96. u8 rev_id;
  97. u32 bl_ver;
  98. };
  99. enum ldr_status {
  100. ERROR_SUCCESS = 0,
  101. ERROR_COMMAND = 1,
  102. ERROR_FLASH_ARRAY = 2,
  103. ERROR_PACKET_DATA = 3,
  104. ERROR_PACKET_LEN = 4,
  105. ERROR_PACKET_CHECKSUM = 5,
  106. ERROR_FLASH_PROTECTION = 6,
  107. ERROR_FLASH_CHECKSUM = 7,
  108. ERROR_VERIFY_IMAGE = 8,
  109. ERROR_UKNOWN1 = 9,
  110. ERROR_UKNOWN2 = 10,
  111. ERROR_UKNOWN3 = 11,
  112. ERROR_UKNOWN4 = 12,
  113. ERROR_UKNOWN5 = 13,
  114. ERROR_UKNOWN6 = 14,
  115. ERROR_INVALID_COMMAND = 15,
  116. ERROR_INVALID
  117. };
  118. static struct cyttsp4_core_commands *cmd;
  119. static inline struct cyttsp4_loader_data *cyttsp4_get_loader_data(
  120. struct device *dev)
  121. {
  122. return cyttsp4_get_dynamic_data(dev, CY_MODULE_LOADER);
  123. }
  124. #if !defined(SAMSUNG_TSP_INFO)
  125. #if CYTTSP4_FW_UPGRADE || CYTTSP4_TTCONFIG_UPGRADE
  126. /*
  127. * return code:
  128. * -1: Firmware version compared is older
  129. * 0: Firmware version compared is identical
  130. * 1: Firmware version compared is newer
  131. */
  132. static int cyttsp4_check_firmware_version(struct device *dev, u32 fw_ver_new,
  133. u32 fw_revctrl_new_h, u32 fw_revctrl_new_l)
  134. {
  135. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  136. u32 fw_ver_img;
  137. u32 fw_revctrl_img_h;
  138. u32 fw_revctrl_img_l;
  139. fw_ver_img = ld->si->si_ptrs.cydata->fw_ver_major << 8;
  140. fw_ver_img += ld->si->si_ptrs.cydata->fw_ver_minor;
  141. dev_dbg(dev, "%s: img vers:0x%04X new vers:0x%04X\n", __func__,
  142. fw_ver_img, fw_ver_new);
  143. if (fw_ver_new > fw_ver_img)
  144. return 1;
  145. if (fw_ver_new < fw_ver_img)
  146. return -1;
  147. fw_revctrl_img_h = be32_to_cpu(
  148. *(u32 *)(ld->si->si_ptrs.cydata->revctrl + 0));
  149. dev_dbg(dev, "%s: img revctrl_h:0x%04X new revctrl_h:0x%04X\n",
  150. __func__, fw_revctrl_img_h, fw_revctrl_new_h);
  151. if (fw_revctrl_new_h > fw_revctrl_img_h)
  152. return 1;
  153. if (fw_revctrl_new_h < fw_revctrl_img_h)
  154. return -1;
  155. fw_revctrl_img_l = be32_to_cpu(
  156. *(u32 *)(ld->si->si_ptrs.cydata->revctrl + 4));
  157. dev_dbg(dev, "%s: img revctrl_l:0x%04X new revctrl_l:0x%04X\n",
  158. __func__, fw_revctrl_img_l, fw_revctrl_new_l);
  159. if (fw_revctrl_new_l > fw_revctrl_img_l)
  160. return 1;
  161. if (fw_revctrl_new_l < fw_revctrl_img_l)
  162. return -1;
  163. return 0;
  164. }
  165. #endif /* CYTTSP4_FW_UPGRADE || CYTTSP4_TTCONFIG_UPGRADE */
  166. #endif//SAMSUNG_TSP_INFO
  167. #if CYTTSP4_FW_UPGRADE
  168. static u16 _cyttsp4_compute_crc(u8 *buf, int size)
  169. {
  170. u16 crc = 0xffff;
  171. u16 tmp;
  172. int i;
  173. if (size == 0)
  174. crc = ~crc;
  175. else {
  176. do {
  177. for (i = 0, tmp = 0x00ff & *buf++; i < 8;
  178. i++, tmp >>= 1) {
  179. if ((crc & 0x0001) ^ (tmp & 0x0001))
  180. crc = (crc >> 1) ^ 0x8408;
  181. else
  182. crc >>= 1;
  183. }
  184. } while (--size);
  185. crc = ~crc;
  186. tmp = crc;
  187. crc = (crc << 8) | (tmp >> 8 & 0xFF);
  188. }
  189. return crc;
  190. }
  191. static u16 _cyttsp4_get_short(u8 *buf)
  192. {
  193. return ((u16)(*buf) << 8) + *(buf+1);
  194. }
  195. static u8 *_cyttsp4_get_row(struct device *dev, u8 *row_buf, u8 *image_buf,
  196. int size)
  197. {
  198. memcpy(row_buf, image_buf, size);
  199. image_buf = image_buf + size;
  200. return image_buf;
  201. }
  202. static int _cyttsp4_get_status(struct device *dev, u8 *buf, int size,
  203. unsigned long timeout_ms)
  204. {
  205. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  206. unsigned long uretval;
  207. int tries;
  208. int retval = 0;
  209. if (timeout_ms != 0) {
  210. /* wait until status ready interrupt or timeout occurs */
  211. uretval = wait_for_completion_timeout(
  212. &ld->int_running, msecs_to_jiffies(timeout_ms));
  213. /* TODO: Reconsider purpose of having retries here */
  214. for (tries = 0; tries < 2; tries++) {
  215. retval = cmd->read(dev, CY_MODE_BOOTLOADER, CY_REG_BASE,
  216. buf, size);
  217. /*
  218. * retry if bus read error or
  219. * status byte shows not ready
  220. */
  221. if (buf[1] == CY_COMM_BUSY || buf[1] == CY_CMD_BUSY)
  222. msleep(20); /* TODO: Constant if code kept */
  223. else
  224. break;
  225. }
  226. dev_vdbg(dev, "%s: tries=%d ret=%d status=%02X\n",
  227. __func__, tries, retval, buf[1]);
  228. }
  229. return retval;
  230. }
  231. static int _cyttsp4_send_cmd(struct device *dev, const u8 *cmd_buf,
  232. int cmd_size, u8 *stat_ret, size_t num_stat_byte,
  233. size_t status_size, unsigned long timeout_ms)
  234. {
  235. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  236. u8 *status_buf = ld->status_buf;
  237. int retval = 0;
  238. if (!cmd_buf)
  239. goto _cyttsp4_send_cmd_exit;
  240. if (!cmd_size)
  241. goto _cyttsp4_send_cmd_exit;
  242. if (timeout_ms > 0)
  243. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
  244. reinit_completion(&ld->int_running);
  245. #else
  246. INIT_COMPLETION(ld->int_running);
  247. #endif
  248. retval = cmd->write(dev, CY_MODE_BOOTLOADER, CY_REG_BASE, cmd_buf,
  249. cmd_size);
  250. if (retval < 0) {
  251. dev_err(dev, "%s: Fail writing command=%02X\n",
  252. __func__, cmd_buf[CY_CMD_BYTE]);
  253. goto _cyttsp4_send_cmd_exit;
  254. }
  255. if (timeout_ms > 0) {
  256. memset(status_buf, 0, sizeof(ld->status_buf));
  257. retval = _cyttsp4_get_status(dev, status_buf,
  258. status_size, timeout_ms);
  259. if (retval < 0 || status_buf[0] != CY_START_OF_PACKET) {
  260. dev_err(dev, "%s: Error getting status r=%d status_buf[0]=%02X\n",
  261. __func__, retval, status_buf[0]);
  262. if (!(retval < 0))
  263. retval = -EIO;
  264. goto _cyttsp4_send_cmd_exit;
  265. } else {
  266. if (status_buf[CY_STATUS_BYTE] != ERROR_SUCCESS) {
  267. dev_err(dev, "%s: Status=0x%02X error\n",
  268. __func__, status_buf[CY_STATUS_BYTE]);
  269. retval = -EIO;
  270. } else if (stat_ret != NULL) {
  271. if (num_stat_byte < status_size)
  272. *stat_ret = status_buf[num_stat_byte];
  273. else
  274. *stat_ret = 0;
  275. }
  276. }
  277. } else {
  278. if (stat_ret != NULL)
  279. *stat_ret = ERROR_SUCCESS;
  280. }
  281. _cyttsp4_send_cmd_exit:
  282. return retval;
  283. }
  284. static int _cyttsp4_ldr_enter(struct device *dev, struct cyttsp4_dev_id *dev_id)
  285. {
  286. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  287. u16 crc = 0;
  288. int i = 0;
  289. size_t cmd_size = 0;
  290. u8 *status_buf = &ld->status_buf[0];
  291. u8 status = 0;
  292. int retval;
  293. /* +1 for TMA400 host sync byte */
  294. u8 ldr_enter_cmd[CY_CMD_LDR_ENTER_CMD_SIZE+1];
  295. memset(status_buf, 0, sizeof(ld->status_buf));
  296. dev_id->bl_ver = 0;
  297. dev_id->rev_id = 0;
  298. dev_id->silicon_id = 0;
  299. ldr_enter_cmd[i++] = CY_CMD_LDR_HOST_SYNC;
  300. ldr_enter_cmd[i++] = CY_START_OF_PACKET;
  301. ldr_enter_cmd[i++] = CY_CMD_LDR_ENTER;
  302. ldr_enter_cmd[i++] = 0x00; /* data len lsb */
  303. ldr_enter_cmd[i++] = 0x00; /* data len msb */
  304. crc = _cyttsp4_compute_crc(&ldr_enter_cmd[1], i - 1);
  305. cmd_size = sizeof(ldr_enter_cmd);
  306. ldr_enter_cmd[i++] = (u8)crc;
  307. ldr_enter_cmd[i++] = (u8)(crc >> 8);
  308. ldr_enter_cmd[i++] = CY_END_OF_PACKET;
  309. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
  310. reinit_completion(&ld->int_running);
  311. #else
  312. INIT_COMPLETION(ld->int_running);
  313. #endif
  314. retval = cmd->write(dev, CY_MODE_BOOTLOADER, CY_REG_BASE, ldr_enter_cmd,
  315. cmd_size);
  316. if (retval < 0) {
  317. dev_err(dev, "%s: write block failed %d\n", __func__, retval);
  318. return retval;
  319. }
  320. retval = _cyttsp4_get_status(dev, status_buf,
  321. CY_CMD_LDR_ENTER_STAT_SIZE, CY_LDR_CMD_TIMEOUT);
  322. if (retval < 0) {
  323. dev_err(dev, "%s: Fail get status to Enter Loader command r=%d\n",
  324. __func__, retval);
  325. return retval;
  326. }
  327. status = status_buf[CY_STATUS_BYTE];
  328. if (status == ERROR_SUCCESS) {
  329. dev_id->bl_ver =
  330. status_buf[11] << 16 |
  331. status_buf[10] << 8 |
  332. status_buf[9] << 0;
  333. dev_id->rev_id =
  334. status_buf[8] << 0;
  335. dev_id->silicon_id =
  336. status_buf[7] << 24 |
  337. status_buf[6] << 16 |
  338. status_buf[5] << 8 |
  339. status_buf[4] << 0;
  340. retval = 0;
  341. } else
  342. retval = -EIO;
  343. dev_vdbg(dev, "%s: status=%d bl_ver=%08X rev_id=%02X silicon_id=%08X\n",
  344. __func__, status, dev_id->bl_ver, dev_id->rev_id,
  345. dev_id->silicon_id);
  346. return retval;
  347. }
  348. static int _cyttsp4_ldr_init(struct device *dev)
  349. {
  350. u16 crc;
  351. int i = 0;
  352. int retval = 0;
  353. const u8 *cyttsp4_security_key;
  354. int key_size;
  355. /* +1 for TMA400 host sync byte */
  356. u8 ldr_init_cmd[CY_CMD_LDR_INIT_CMD_SIZE+1];
  357. cyttsp4_security_key = cmd->get_security_key(dev, &key_size);
  358. ldr_init_cmd[i++] = CY_CMD_LDR_HOST_SYNC;
  359. ldr_init_cmd[i++] = CY_START_OF_PACKET;
  360. ldr_init_cmd[i++] = CY_CMD_LDR_INIT;
  361. ldr_init_cmd[i++] = 0x08; /* data len lsb */
  362. ldr_init_cmd[i++] = 0x00; /* data len msb */
  363. memcpy(&ldr_init_cmd[i], cyttsp4_security_key,
  364. key_size);
  365. i += key_size;
  366. crc = _cyttsp4_compute_crc(&ldr_init_cmd[1], i - 1);
  367. ldr_init_cmd[i++] = (u8)crc;
  368. ldr_init_cmd[i++] = (u8)(crc >> 8);
  369. ldr_init_cmd[i++] = CY_END_OF_PACKET;
  370. retval = _cyttsp4_send_cmd(dev, ldr_init_cmd, i, NULL, 0,
  371. CY_CMD_LDR_INIT_STAT_SIZE,
  372. CY_LDR_CMD_INIT_TIMEOUT);
  373. if (retval < 0)
  374. dev_err(dev, "%s: Fail ldr init r=%d\n", __func__, retval);
  375. return retval;
  376. }
  377. struct cyttsp4_hex_image {
  378. u8 array_id;
  379. u16 row_num;
  380. u16 row_size;
  381. u8 row_data[CY_DATA_ROW_SIZE];
  382. } __packed;
  383. static int _cyttsp4_ldr_parse_row(struct device *dev, u8 *row_buf,
  384. struct cyttsp4_hex_image *row_image)
  385. {
  386. int retval = 0;
  387. row_image->array_id = row_buf[CY_ARRAY_ID_OFFSET];
  388. row_image->row_num = _cyttsp4_get_short(&row_buf[CY_ROW_NUM_OFFSET]);
  389. row_image->row_size = _cyttsp4_get_short(&row_buf[CY_ROW_SIZE_OFFSET]);
  390. if (row_image->row_size > ARRAY_SIZE(row_image->row_data)) {
  391. dev_err(dev, "%s: row data buffer overflow\n", __func__);
  392. retval = -EOVERFLOW;
  393. goto cyttsp4_ldr_parse_row_exit;
  394. }
  395. memcpy(row_image->row_data, &row_buf[CY_ROW_DATA_OFFSET],
  396. row_image->row_size);
  397. cyttsp4_ldr_parse_row_exit:
  398. return retval;
  399. }
  400. static int _cyttsp4_ldr_prog_row(struct device *dev,
  401. struct cyttsp4_hex_image *row_image)
  402. {
  403. u16 crc;
  404. int next;
  405. int data;
  406. int row_data;
  407. u16 row_sum;
  408. size_t data_len;
  409. int retval = 0;
  410. u8 *cmd = kzalloc(CY_MAX_PACKET_LEN, GFP_KERNEL);
  411. if (cmd != NULL) {
  412. row_data = 0;
  413. row_sum = 0;
  414. next = 0;
  415. cmd[next++] = CY_CMD_LDR_HOST_SYNC;
  416. cmd[next++] = CY_START_OF_PACKET;
  417. cmd[next++] = CY_CMD_LDR_PROG_ROW;
  418. /*
  419. * include array id size and row id size in CY_PACKET_DATA_LEN
  420. */
  421. data_len = CY_DATA_ROW_SIZE_TMA400;
  422. cmd[next++] = (u8)(data_len+3);
  423. cmd[next++] = (u8)((data_len+3) >> 8);
  424. cmd[next++] = row_image->array_id;
  425. cmd[next++] = (u8)row_image->row_num;
  426. cmd[next++] = (u8)(row_image->row_num >> 8);
  427. for (data = 0;
  428. data < data_len; data++) {
  429. cmd[next] = row_image->row_data[row_data++];
  430. row_sum += cmd[next];
  431. next++;
  432. }
  433. crc = _cyttsp4_compute_crc(&cmd[1], next - 1);
  434. cmd[next++] = (u8)crc;
  435. cmd[next++] = (u8)(crc >> 8);
  436. cmd[next++] = CY_END_OF_PACKET;
  437. retval = _cyttsp4_send_cmd(dev, cmd, next, NULL, 0,
  438. CY_CMD_LDR_PROG_ROW_STAT_SIZE,
  439. CY_LDR_CMD_TIMEOUT);
  440. if (retval < 0) {
  441. dev_err(dev, "%s: prog row=%d fail r=%d\n",
  442. __func__, row_image->row_num, retval);
  443. goto cyttsp4_ldr_prog_row_exit;
  444. }
  445. } else {
  446. dev_err(dev, "%s prog row error - cmd buf is NULL\n", __func__);
  447. retval = -EIO;
  448. }
  449. cyttsp4_ldr_prog_row_exit:
  450. kfree(cmd);
  451. return retval;
  452. }
  453. static int _cyttsp4_ldr_verify_row(struct device *dev,
  454. struct cyttsp4_hex_image *row_image)
  455. {
  456. u16 crc = 0;
  457. int i = 0;
  458. u8 verify_checksum;
  459. int retval = 0;
  460. /* +1 for TMA400 host sync byte */
  461. u8 ldr_verify_row_cmd[CY_CMD_LDR_VERIFY_ROW_CMD_SIZE+1];
  462. ldr_verify_row_cmd[i++] = CY_CMD_LDR_HOST_SYNC;
  463. ldr_verify_row_cmd[i++] = CY_START_OF_PACKET;
  464. ldr_verify_row_cmd[i++] = CY_CMD_LDR_VERIFY_ROW;
  465. ldr_verify_row_cmd[i++] = 0x03; /* data len lsb */
  466. ldr_verify_row_cmd[i++] = 0x00; /* data len msb */
  467. ldr_verify_row_cmd[i++] = row_image->array_id;
  468. ldr_verify_row_cmd[i++] = (u8)row_image->row_num;
  469. ldr_verify_row_cmd[i++] = (u8)(row_image->row_num >> 8);
  470. crc = _cyttsp4_compute_crc(&ldr_verify_row_cmd[1], i - 1);
  471. ldr_verify_row_cmd[i++] = (u8)crc;
  472. ldr_verify_row_cmd[i++] = (u8)(crc >> 8);
  473. ldr_verify_row_cmd[i++] = CY_END_OF_PACKET;
  474. retval = _cyttsp4_send_cmd(dev, ldr_verify_row_cmd, i,
  475. &verify_checksum, 4,
  476. CY_CMD_LDR_VERIFY_ROW_STAT_SIZE,
  477. CY_LDR_CMD_TIMEOUT);
  478. if (retval < 0)
  479. dev_err(dev, "%s: verify row=%d fail r=%d\n",
  480. __func__, row_image->row_num, retval);
  481. return retval;
  482. }
  483. static int _cyttsp4_ldr_verify_chksum(struct device *dev,
  484. u8 *app_chksum)
  485. {
  486. u16 crc = 0;
  487. int i = 0;
  488. int retval = 0;
  489. /* +1 for TMA400 host sync byte */
  490. u8 ldr_verify_chksum_cmd[CY_CMD_LDR_VERIFY_CHKSUM_CMD_SIZE+1];
  491. ldr_verify_chksum_cmd[i++] = CY_CMD_LDR_HOST_SYNC;
  492. ldr_verify_chksum_cmd[i++] = CY_START_OF_PACKET;
  493. ldr_verify_chksum_cmd[i++] = CY_CMD_LDR_VERIFY_CHKSUM;
  494. ldr_verify_chksum_cmd[i++] = 0x00; /* data len lsb */
  495. ldr_verify_chksum_cmd[i++] = 0x00; /* data len msb */
  496. crc = _cyttsp4_compute_crc(&ldr_verify_chksum_cmd[1], i - 1);
  497. ldr_verify_chksum_cmd[i++] = (u8)crc;
  498. ldr_verify_chksum_cmd[i++] = (u8)(crc >> 8);
  499. ldr_verify_chksum_cmd[i++] = CY_END_OF_PACKET;
  500. retval = _cyttsp4_send_cmd(dev, ldr_verify_chksum_cmd, i,
  501. app_chksum, 4,
  502. CY_CMD_LDR_VERIFY_CHKSUM_STAT_SIZE,
  503. CY_LDR_CMD_TIMEOUT);
  504. if (retval < 0)
  505. dev_err(dev, "%s: verify checksum fail r=%d\n",
  506. __func__, retval);
  507. return retval;
  508. }
  509. /* Constructs loader exit command and sends via _cyttsp4_send_cmd() */
  510. static int _cyttsp4_ldr_exit(struct device *dev)
  511. {
  512. u16 crc = 0;
  513. int i = 0;
  514. int retval;
  515. /* +1 for TMA400 host sync byte */
  516. u8 ldr_exit_cmd[CY_CMD_LDR_EXIT_CMD_SIZE+1];
  517. ldr_exit_cmd[i++] = CY_CMD_LDR_HOST_SYNC;
  518. ldr_exit_cmd[i++] = CY_START_OF_PACKET;
  519. ldr_exit_cmd[i++] = CY_CMD_LDR_EXIT;
  520. ldr_exit_cmd[i++] = 0x00; /* data len lsb */
  521. ldr_exit_cmd[i++] = 0x00; /* data len msb */
  522. crc = _cyttsp4_compute_crc(&ldr_exit_cmd[1], i - 1);
  523. ldr_exit_cmd[i++] = (u8)crc;
  524. ldr_exit_cmd[i++] = (u8)(crc >> 8);
  525. ldr_exit_cmd[i++] = CY_END_OF_PACKET;
  526. retval = _cyttsp4_send_cmd(dev, ldr_exit_cmd, i, NULL, 0,
  527. CY_CMD_LDR_EXIT_STAT_SIZE, 0);
  528. if (retval < 0)
  529. dev_err(dev, "%s: BL Loader exit fail r=%d\n",
  530. __func__, retval);
  531. dev_vdbg(dev, "%s: Exit BL Loader r=%d\n", __func__, retval);
  532. return retval;
  533. }
  534. static int _cyttsp4_load_app(struct device *dev, const u8 *fw, int fw_size)
  535. {
  536. u8 *p;
  537. int ret;
  538. int retval; /* need separate return value at exit stage */
  539. struct cyttsp4_dev_id *file_id = NULL;
  540. struct cyttsp4_dev_id *dev_id = NULL;
  541. struct cyttsp4_hex_image *row_image = NULL;
  542. u8 app_chksum;
  543. u8 *row_buf = NULL;
  544. /* Prevent loading if TMA ver not defined. */
  545. size_t image_rec_size = fw_size + 1;
  546. size_t row_buf_size = 1024 > CY_MAX_PRBUF_SIZE ?
  547. 1024 : CY_MAX_PRBUF_SIZE;
  548. int row_count = 0;
  549. image_rec_size = CY_DATA_ROW_SIZE_TMA400 +
  550. (sizeof(struct cyttsp4_hex_image) - CY_DATA_ROW_SIZE);
  551. if (fw_size % image_rec_size != 0) {
  552. dev_err(dev,
  553. "%s: Firmware image is misaligned\n", __func__);
  554. retval = -EINVAL;
  555. goto _cyttsp4_load_app_exit;
  556. }
  557. dev_info(dev, "%s: start load app\n", __func__);
  558. row_buf = kzalloc(row_buf_size, GFP_KERNEL);
  559. row_image = kzalloc(sizeof(struct cyttsp4_hex_image), GFP_KERNEL);
  560. file_id = kzalloc(sizeof(struct cyttsp4_dev_id), GFP_KERNEL);
  561. dev_id = kzalloc(sizeof(struct cyttsp4_dev_id), GFP_KERNEL);
  562. if (row_buf == NULL || row_image == NULL ||
  563. file_id == NULL || dev_id == NULL) {
  564. dev_err(dev,
  565. "%s: Unable to alloc row buffers(%p %p %p %p)\n",
  566. __func__, row_buf, row_image, file_id, dev_id);
  567. retval = -ENOMEM;
  568. goto _cyttsp4_load_app_exit;
  569. }
  570. cmd->request_stop_wd(dev);
  571. p = (u8 *)fw;
  572. /* Enter Loader and return Silicon ID and Rev */
  573. retval = cmd->request_reset(dev);
  574. if (retval < 0) {
  575. dev_err(dev,
  576. "%s: Fail reset device r=%d\n", __func__, retval);
  577. goto _cyttsp4_load_app_exit;
  578. }
  579. dev_info(dev, "%s: Send BL Loader Enter\n", __func__);
  580. retval = _cyttsp4_ldr_enter(dev, dev_id);
  581. if (retval < 0) {
  582. dev_err(dev, "%s: Error cannot start Loader (ret=%d)\n",
  583. __func__, retval);
  584. goto _cyttsp4_load_app_exit;
  585. }
  586. dev_vdbg(dev, "%s: dev: silicon id=%08X rev=%02X bl=%08X\n",
  587. __func__, dev_id->silicon_id,
  588. dev_id->rev_id, dev_id->bl_ver);
  589. udelay(1000);
  590. retval = _cyttsp4_ldr_init(dev);
  591. if (retval < 0) {
  592. dev_err(dev,
  593. "%s: Error cannot init Loader (ret=%d)\n",
  594. __func__, retval);
  595. goto _cyttsp4_load_app_exit;
  596. }
  597. dev_info(dev, "%s: Send BL Loader Blocks\n", __func__);
  598. while (p < (fw + fw_size)) {
  599. /* Get row */
  600. dev_vdbg(dev, "%s: read row=%d\n", __func__, ++row_count);
  601. memset(row_buf, 0, row_buf_size);
  602. p = _cyttsp4_get_row(dev, row_buf, p, image_rec_size);
  603. /* Parse row */
  604. dev_vdbg(dev, "%s: p=%p buf=%p buf[0]=%02X\n", __func__,
  605. p, row_buf, row_buf[0]);
  606. retval = _cyttsp4_ldr_parse_row(dev, row_buf, row_image);
  607. dev_vdbg(dev, "%s: array_id=%02X row_num=%04X(%d) row_size=%04X(%d)\n",
  608. __func__, row_image->array_id,
  609. row_image->row_num, row_image->row_num,
  610. row_image->row_size, row_image->row_size);
  611. if (retval < 0) {
  612. dev_err(dev, "%s: Parse Row Error (a=%d r=%d ret=%d\n",
  613. __func__, row_image->array_id,
  614. row_image->row_num, retval);
  615. goto bl_exit;
  616. } else {
  617. dev_vdbg(dev, "%s: Parse Row (a=%d r=%d ret=%d\n",
  618. __func__, row_image->array_id,
  619. row_image->row_num, retval);
  620. }
  621. /* program row */
  622. retval = _cyttsp4_ldr_prog_row(dev, row_image);
  623. if (retval < 0) {
  624. dev_err(dev, "%s: Program Row Error (array=%d row=%d ret=%d)\n",
  625. __func__, row_image->array_id,
  626. row_image->row_num, retval);
  627. goto _cyttsp4_load_app_exit;
  628. }
  629. /* verify row */
  630. retval = _cyttsp4_ldr_verify_row(dev, row_image);
  631. if (retval < 0) {
  632. dev_err(dev, "%s: Verify Row Error (array=%d row=%d ret=%d)\n",
  633. __func__, row_image->array_id,
  634. row_image->row_num, retval);
  635. goto _cyttsp4_load_app_exit;
  636. }
  637. dev_vdbg(dev, "%s: array=%d row_cnt=%d row_num=%04X\n",
  638. __func__, row_image->array_id, row_count,
  639. row_image->row_num);
  640. }
  641. /* verify app checksum */
  642. retval = _cyttsp4_ldr_verify_chksum(dev, &app_chksum);
  643. dev_dbg(dev, "%s: Application Checksum = %02X r=%d\n",
  644. __func__, app_chksum, retval);
  645. if (retval < 0) {
  646. dev_err(dev, "%s: ldr_verify_chksum fail r=%d\n",
  647. __func__, retval);
  648. retval = 0;
  649. }
  650. /* exit loader */
  651. bl_exit:
  652. dev_info(dev, "%s: Send BL Loader Terminate\n", __func__);
  653. ret = _cyttsp4_ldr_exit(dev);
  654. if (ret) {
  655. dev_err(dev, "%s: Error on exit Loader (ret=%d)\n",
  656. __func__, ret);
  657. retval = ret;
  658. }
  659. _cyttsp4_load_app_exit:
  660. kfree(row_buf);
  661. kfree(row_image);
  662. kfree(file_id);
  663. kfree(dev_id);
  664. return retval;
  665. }
  666. #ifdef CALIBRATE_IN_LOADER
  667. static void cyttsp4_fw_calibrate(struct work_struct *calibration_work)
  668. {
  669. struct cyttsp4_loader_data *ld = container_of(calibration_work,
  670. struct cyttsp4_loader_data, calibration_work);
  671. struct device *dev = ld->dev;
  672. u8 cmd_buf[CY_CMD_CAT_CALIBRATE_IDAC_CMD_SZ];
  673. u8 return_buf[CY_CMD_CAT_CALIBRATE_IDAC_RET_SZ];
  674. int rc;
  675. dev_dbg(dev, "%s: \n", __func__);
  676. pm_runtime_get_sync(dev);
  677. dev_vdbg(dev, "%s: Requesting exclusive\n", __func__);
  678. rc = cmd->request_exclusive(dev, CY_LDR_REQUEST_EXCLUSIVE_TIMEOUT);
  679. if (rc < 0) {
  680. dev_err(dev, "%s: Error on request exclusive r=%d\n",
  681. __func__, rc);
  682. goto exit;
  683. }
  684. dev_vdbg(dev, "%s: Requesting mode change to CAT\n", __func__);
  685. rc = cmd->request_set_mode(dev, CY_MODE_CAT);
  686. if (rc < 0) {
  687. dev_err(dev, "%s: Error on request set mode r=%d\n",
  688. __func__, rc);
  689. goto exit_release;
  690. }
  691. cmd_buf[0] = CY_CMD_CAT_CALIBRATE_IDACS;
  692. cmd_buf[1] = 0x00; /* Mutual Capacitance Screen */
  693. rc = cmd->request_exec_cmd(dev, CY_MODE_CAT,
  694. cmd_buf, CY_CMD_CAT_CALIBRATE_IDAC_CMD_SZ,
  695. return_buf, CY_CMD_CAT_CALIBRATE_IDAC_RET_SZ,
  696. CY_CALIBRATE_COMPLETE_TIMEOUT);
  697. if (rc < 0) {
  698. dev_err(dev, "%s: Unable to execute calibrate command.\n",
  699. __func__);
  700. goto exit_setmode;
  701. }
  702. if (return_buf[0] != CY_CMD_STATUS_SUCCESS) {
  703. dev_err(dev, "%s: calibrate command unsuccessful\n", __func__);
  704. goto exit_setmode;
  705. }
  706. cmd_buf[1] = 0x01; /* Mutual Capacitance Button */
  707. rc = cmd->request_exec_cmd(dev, CY_MODE_CAT,
  708. cmd_buf, CY_CMD_CAT_CALIBRATE_IDAC_CMD_SZ,
  709. return_buf, CY_CMD_CAT_CALIBRATE_IDAC_RET_SZ,
  710. CY_CALIBRATE_COMPLETE_TIMEOUT);
  711. if (rc < 0) {
  712. dev_err(dev, "%s: Unable to execute calibrate command.\n",
  713. __func__);
  714. goto exit_setmode;
  715. }
  716. if (return_buf[0] != CY_CMD_STATUS_SUCCESS) {
  717. dev_err(dev, "%s: calibrate command unsuccessful\n", __func__);
  718. goto exit_setmode;
  719. }
  720. cmd_buf[1] = 0x02; /* Self Capacitance */
  721. rc = cmd->request_exec_cmd(dev, CY_MODE_CAT,
  722. cmd_buf, CY_CMD_CAT_CALIBRATE_IDAC_CMD_SZ,
  723. return_buf, CY_CMD_CAT_CALIBRATE_IDAC_RET_SZ,
  724. CY_CALIBRATE_COMPLETE_TIMEOUT);
  725. if (rc < 0) {
  726. dev_err(dev, "%s: Unable to execute calibrate command.\n",
  727. __func__);
  728. goto exit_setmode;
  729. }
  730. if (return_buf[0] != CY_CMD_STATUS_SUCCESS) {
  731. dev_err(dev, "%s: calibrate command unsuccessful\n", __func__);
  732. goto exit_setmode;
  733. }
  734. exit_setmode:
  735. rc = cmd->request_set_mode(dev, CY_MODE_OPERATIONAL);
  736. if (rc < 0)
  737. dev_err(dev, "%s: Error on request set mode 2 r=%d\n",
  738. __func__, rc);
  739. exit_release:
  740. rc = cmd->release_exclusive(dev);
  741. if (rc < 0)
  742. dev_err(dev, "%s: Error on release exclusive r=%d\n",
  743. __func__, rc);
  744. exit:
  745. pm_runtime_put(dev);
  746. }
  747. static int cyttsp4_fw_calibration_attention(struct device *dev)
  748. {
  749. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  750. int rc = 0;
  751. dev_dbg(dev, "%s: \n", __func__);
  752. schedule_work(&ld->calibration_work);
  753. cmd->unsubscribe_attention(dev, CY_ATTEN_STARTUP, CY_MODULE_LOADER,
  754. cyttsp4_fw_calibration_attention, 0);
  755. return rc;
  756. }
  757. #endif//CALIBRATE_IN_LOADER
  758. static int cyttsp4_upgrade_firmware(struct device *dev,
  759. const u8 *fw_img, int fw_size)
  760. {
  761. #ifdef CALIBRATE_IN_LOADER
  762. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  763. #endif
  764. int rc;
  765. pm_runtime_get_sync(dev);
  766. rc = cmd->request_exclusive(dev, CY_LDR_REQUEST_EXCLUSIVE_TIMEOUT);
  767. if (rc < 0)
  768. goto exit;
  769. rc = _cyttsp4_load_app(dev, fw_img, fw_size);
  770. if (rc < 0) {
  771. dev_err(dev, "%s: Firmware update failed with error code %d\n",
  772. __func__, rc);
  773. }
  774. #ifdef CALIBRATE_IN_LOADER
  775. else if (ld->loader_pdata &&
  776. (ld->loader_pdata->flags &
  777. CY_LOADER_FLAG_CALIBRATE_AFTER_FW_UPGRADE)) {
  778. /* set up call back for startup */
  779. dev_vdbg(dev, "%s: Adding callback for calibration\n",
  780. __func__);
  781. rc = cmd->subscribe_attention(dev, CY_ATTEN_STARTUP,
  782. CY_MODULE_LOADER,
  783. cyttsp4_fw_calibration_attention, 0);
  784. if (rc) {
  785. dev_err(dev, "%s: Failed adding callback for calibration\n",
  786. __func__);
  787. dev_err(dev, "%s: No calibration will be performed\n",
  788. __func__);
  789. rc = 0;
  790. }
  791. }
  792. #endif//CALIBRATE_IN_LOADER
  793. cmd->release_exclusive(dev);
  794. cmd->request_restart(dev, false);
  795. exit:
  796. pm_runtime_put(dev);
  797. return rc;
  798. }
  799. static int cyttsp4_loader_attention(struct device *dev)
  800. {
  801. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  802. complete(&ld->int_running);
  803. return 0;
  804. }
  805. #endif /* CYTTSP4_FW_UPGRADE */
  806. #ifdef SAMSUNG_TSP_INFO
  807. static int check_firmware_samsung(struct device *dev,
  808. struct cyttsp4_touch_firmware *fw)
  809. {
  810. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  811. struct cyttsp4_samsung_tsp_info *sti;
  812. if (!ld->si) {
  813. dev_info(dev, "%s: No firmware infomation found, device FW may be corrupted\n",
  814. __func__);
  815. return CYTTSP4_AUTO_LOAD_FOR_CORRUPTED_FW;
  816. }
  817. if (!(ld->si->si_ptrs.test->post_codel &
  818. CY_POST_CODEL_CFG_DATA_CRC_FAIL)) {
  819. dev_info(dev, "%s: POST, TT_CFG failed (0x%04X), will upgrade\n",
  820. __func__, ld->si->si_ptrs.test->post_codel);
  821. return CYTTSP4_AUTO_LOAD_FOR_CORRUPTED_FW;
  822. }
  823. sti = ld->si->sti;
  824. dev_info(dev, "%s: phone hw ver=0x%02x, tsp hw ver=0x%02x\n",
  825. __func__, fw->hw_version, sti->hw_version);
  826. dev_info(dev, "%s: phone fw ver=0x%04x, tsp fw ver=0x%04x\n",
  827. __func__, fw->fw_version, get_unaligned_be16(&sti->fw_versionh));
  828. dev_info(dev, "%s: phone cfg ver=0x%02x, tsp cfg ver=0x%02x\n",
  829. __func__, fw->cfg_version, sti->config_version);
  830. if (fw->hw_version != sti->hw_version) {
  831. dev_info(dev, "%s: hw version is different, will upgrade.\n", __func__);
  832. return 1;
  833. }
  834. if (fw->fw_version > get_unaligned_be16(&sti->fw_versionh)) {
  835. dev_info(dev, "%s: fw version is newer, will upgrade.\n", __func__);
  836. return 1;
  837. }
  838. if (fw->cfg_version > sti->config_version) {
  839. dev_info(dev, "%s: config version is newer, will upgrade.\n", __func__);
  840. return 1;
  841. }
  842. dev_info(dev, "%s: upgrade not required\n", __func__);
  843. return 0;
  844. }
  845. #endif//SAMSUNG_TSP_INFO
  846. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_PLATFORM_FW_UPGRADE
  847. static int cyttsp4_check_firmware_version_platform(struct device *dev,
  848. struct cyttsp4_touch_firmware *fw)
  849. {
  850. #ifdef SAMSUNG_TSP_INFO
  851. return check_firmware_samsung(dev, fw);
  852. #else//SAMSUNG_TSP_INFO
  853. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  854. u32 fw_ver_new;
  855. u32 fw_revctrl_new_h;
  856. u32 fw_revctrl_new_l;
  857. int upgrade;
  858. if (!ld->si) {
  859. dev_info(dev, "%s: No firmware infomation found, device FW may be corrupted\n",
  860. __func__);
  861. return CYTTSP4_AUTO_LOAD_FOR_CORRUPTED_FW;
  862. }
  863. fw_ver_new = get_unaligned_be16(fw->ver + 2);
  864. fw_revctrl_new_h = get_unaligned_be32(fw->ver + 4);
  865. fw_revctrl_new_l = get_unaligned_be32(fw->ver + 8);
  866. upgrade = cyttsp4_check_firmware_version(dev, fw_ver_new,
  867. fw_revctrl_new_h, fw_revctrl_new_l);
  868. if (upgrade > 0)
  869. return 1;
  870. #endif//SAMSUNG_TSP_INFO
  871. return 0;
  872. }
  873. int upgrade_firmware_from_platform(struct device *dev, bool forced)
  874. {
  875. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  876. struct cyttsp4_touch_firmware *fw;
  877. int rc = -ENOSYS;
  878. int upgrade;
  879. if (!ld->loader_pdata) {
  880. dev_err(dev, "%s: No loader platform data\n", __func__);
  881. return rc;
  882. }
  883. fw = ld->loader_pdata->fw;
  884. if (!fw || !fw->img || !fw->size) {
  885. dev_err(dev, "%s: No platform firmware\n", __func__);
  886. return rc;
  887. }
  888. if (!fw->ver || !fw->vsize) {
  889. dev_err(dev, "%s: No platform firmware version\n",
  890. __func__);
  891. return rc;
  892. }
  893. rc = 0;
  894. if (forced)
  895. upgrade = forced;
  896. else
  897. upgrade = cyttsp4_check_firmware_version_platform(dev, fw);
  898. if (upgrade)
  899. rc = cyttsp4_upgrade_firmware(dev, fw->img, fw->size);
  900. return rc;
  901. }
  902. #endif /* CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_PLATFORM_FW_UPGRADE */
  903. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_BINARY_FW_UPGRADE
  904. static void _cyttsp4_firmware_cont(const struct firmware *fw, void *context)
  905. {
  906. struct device *dev = context;
  907. u8 header_size = 0;
  908. if (!fw)
  909. goto cyttsp4_firmware_cont_exit;
  910. if (!fw->data || !fw->size) {
  911. dev_err(dev, "%s: No firmware received\n", __func__);
  912. goto cyttsp4_firmware_cont_release_exit;
  913. }
  914. header_size = fw->data[0];
  915. dev_dbg(dev, "%s: header_size=0x%02x\n", __func__, header_size);
  916. dev_dbg(dev, "%s: fw->size=0x%08x\n", __func__, fw->size);
  917. if (header_size >= (fw->size + 1)) {
  918. dev_err(dev, "%s: Firmware format is invalid\n", __func__);
  919. goto cyttsp4_firmware_cont_release_exit;
  920. }
  921. cyttsp4_upgrade_firmware(dev, &(fw->data[header_size + 1]),
  922. fw->size - (header_size + 1));
  923. cyttsp4_firmware_cont_release_exit:
  924. release_firmware(fw);
  925. cyttsp4_firmware_cont_exit:
  926. return;
  927. }
  928. static int cyttsp4_check_firmware_version_builtin(struct device *dev,
  929. const struct firmware *fw)
  930. {
  931. #ifdef SAMSUNG_TSP_INFO
  932. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  933. if (!ld->si) {
  934. dev_info(dev, "%s: No firmware infomation found, device FW may be corrupted\n",
  935. __func__);
  936. return CYTTSP4_AUTO_LOAD_FOR_CORRUPTED_FW;
  937. }
  938. if (!(ld->si->si_ptrs.test->post_codel &
  939. CY_POST_CODEL_CFG_DATA_CRC_FAIL)) {
  940. dev_info(dev, "%s: POST, TT_CFG failed (0x%04X), will upgrade\n",
  941. __func__, ld->si->si_ptrs.test->post_codel);
  942. return CYTTSP4_AUTO_LOAD_FOR_CORRUPTED_FW;
  943. }
  944. dev_dbg(dev, "%s: POST = 0x%04x\n", __func__, ld->si->si_ptrs.test->post_codel);
  945. #else//SAMSUNG_TSP_INFO
  946. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  947. u32 fw_ver_new;
  948. u32 fw_revctrl_new_h;
  949. u32 fw_revctrl_new_l;
  950. int upgrade;
  951. if (!ld->si) {
  952. dev_info(dev, "%s: No firmware infomation found, device FW may be corrupted\n",
  953. __func__);
  954. return CYTTSP4_AUTO_LOAD_FOR_CORRUPTED_FW;
  955. }
  956. fw_ver_new = get_unaligned_be16(fw->data + 3);
  957. fw_revctrl_new_h = get_unaligned_be32(fw->data + 5);
  958. fw_revctrl_new_l = get_unaligned_be32(fw->data + 9);
  959. upgrade = cyttsp4_check_firmware_version(dev, fw_ver_new,
  960. fw_revctrl_new_h, fw_revctrl_new_l);
  961. if (upgrade > 0)
  962. return 1;
  963. #endif//SAMSUNG_TSP_INFO
  964. return 0;
  965. }
  966. static void _cyttsp4_firmware_cont_builtin(const struct firmware *fw,
  967. void *context)
  968. {
  969. struct device *dev = context;
  970. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  971. int upgrade;
  972. if (!fw) {
  973. dev_info(dev, "%s: No builtin firmware\n", __func__);
  974. goto _cyttsp4_firmware_cont_builtin_exit;
  975. }
  976. if (!fw->data || !fw->size) {
  977. dev_err(dev, "%s: Invalid builtin firmware\n", __func__);
  978. goto _cyttsp4_firmware_cont_builtin_exit;
  979. }
  980. dev_dbg(dev, "%s: Found firmware\n", __func__);
  981. upgrade = cyttsp4_check_firmware_version_builtin(dev, fw);
  982. if (upgrade) {
  983. _cyttsp4_firmware_cont(fw, dev);
  984. ld->builtin_bin_fw_status = 0;
  985. complete(&ld->builtin_bin_fw_complete);
  986. return;
  987. }
  988. _cyttsp4_firmware_cont_builtin_exit:
  989. release_firmware(fw);
  990. ld->builtin_bin_fw_status = -EINVAL;
  991. complete(&ld->builtin_bin_fw_complete);
  992. }
  993. static int upgrade_firmware_from_class(struct device *dev)
  994. {
  995. int retval;
  996. dev_vdbg(dev, "%s: Enabling firmware class loader\n", __func__);
  997. retval = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, "",
  998. dev, GFP_KERNEL, dev, _cyttsp4_firmware_cont);
  999. if (retval < 0) {
  1000. dev_err(dev, "%s: Fail request firmware class file load\n",
  1001. __func__);
  1002. return retval;
  1003. }
  1004. return 0;
  1005. }
  1006. static int upgrade_firmware_from_builtin(struct device *dev)
  1007. {
  1008. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  1009. int retval;
  1010. dev_vdbg(dev, "%s: Enabling firmware class loader built-in\n",
  1011. __func__);
  1012. retval = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
  1013. CY_FW_FILE_NAME, dev, GFP_KERNEL, dev,
  1014. _cyttsp4_firmware_cont_builtin);
  1015. if (retval < 0) {
  1016. dev_err(dev, "%s: Fail request firmware class file load\n",
  1017. __func__);
  1018. return retval;
  1019. }
  1020. /* wait until FW binary upgrade finishes */
  1021. wait_for_completion(&ld->builtin_bin_fw_complete);
  1022. return ld->builtin_bin_fw_status;
  1023. }
  1024. #include <linux/fs.h>
  1025. #include <asm/uaccess.h>
  1026. #include <linux/uaccess.h>
  1027. int upgrade_firmware_from_sdcard(struct device *dev)
  1028. {
  1029. struct cyttsp4_loader_data *ld;
  1030. struct firmware fw;
  1031. /*struct firmware {
  1032. size_t size;
  1033. const u8 *data;*/
  1034. struct file *fp;
  1035. mm_segment_t old_fs;
  1036. long fsize, nread;
  1037. u8 **ums_data = (u8**)&fw.data;
  1038. u8 header_size = 0;
  1039. int rc = 0;
  1040. ld = cyttsp4_get_loader_data(dev);
  1041. if (!ld->loader_pdata) {
  1042. rc = -ENODEV;
  1043. dev_err(dev, "%s: No loader platform data\n", __func__);
  1044. return rc;
  1045. }
  1046. old_fs = get_fs();
  1047. set_fs(KERNEL_DS);
  1048. fp = filp_open(ld->loader_pdata->sdcard_path, O_RDONLY, S_IRUSR);
  1049. if (IS_ERR(fp)) {
  1050. dev_err(dev, "%s: failed to open %s\n", __func__,
  1051. ld->loader_pdata->sdcard_path);
  1052. rc = -ENOENT;
  1053. set_fs(old_fs);
  1054. return rc;
  1055. }
  1056. fsize = fp->f_path.dentry->d_inode->i_size;
  1057. dev_info(dev, "%s: start, file path %s, size %ld Bytes\n",
  1058. __func__, ld->loader_pdata->sdcard_path, fsize);
  1059. *ums_data = kmalloc(fsize, GFP_KERNEL);
  1060. if (IS_ERR(*ums_data)) {
  1061. dev_err(dev, "%s: kmalloc failed\n", __func__);
  1062. rc = -EFAULT;
  1063. goto malloc_error;
  1064. }
  1065. nread = vfs_read(fp, (char __user *)*ums_data,
  1066. fsize, &fp->f_pos);
  1067. dev_info(dev, "%s: nread %ld Bytes\n", __func__, nread);
  1068. if (nread != fsize) {
  1069. dev_err(dev, "%s: failed to read firmware file, nread %ld Bytes\n",
  1070. __func__, nread);
  1071. rc = -EIO;
  1072. kfree(*ums_data);
  1073. goto read_err;
  1074. }
  1075. fw.size = nread;
  1076. dev_dbg(dev, "%s: bin data[0~3]=0x%02x 0x%02x 0x%02x 0x%02x\n", __func__,
  1077. fw.data[0], fw.data[1], fw.data[2], fw.data[3]);
  1078. filp_close(fp, current->files);
  1079. set_fs(old_fs);
  1080. header_size = fw.data[0];
  1081. dev_dbg(dev, "%s: header_size=0x%02x\n", __func__, header_size);
  1082. dev_dbg(dev, "%s: fw.size=0x%08x\n", __func__, fw.size);
  1083. if (header_size >= (fw.size + 1)) {
  1084. dev_err(dev, "%s: Firmware format is invalid\n", __func__);
  1085. rc = -EINVAL;
  1086. goto release_and_exit;
  1087. }
  1088. rc = cyttsp4_upgrade_firmware(dev, &(fw.data[header_size + 1]),
  1089. fw.size - (header_size + 1));
  1090. release_and_exit:
  1091. kfree(*ums_data);
  1092. return rc;
  1093. read_err:
  1094. malloc_error:
  1095. filp_close(fp, current->files);
  1096. set_fs(old_fs);
  1097. return rc;
  1098. }
  1099. #endif /* CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_BINARY_FW_UPGRADE */
  1100. #if CYTTSP4_TTCONFIG_UPGRADE
  1101. static int cyttsp4_upgrade_ttconfig(struct device *dev,
  1102. const u8 *ttconfig_data, int ttconfig_size)
  1103. {
  1104. int rc, rc2;
  1105. pm_runtime_get_sync(dev);
  1106. dev_vdbg(dev, "%s: Requesting exclusive\n", __func__);
  1107. rc = cmd->request_exclusive(dev, CY_LDR_REQUEST_EXCLUSIVE_TIMEOUT);
  1108. if (rc < 0) {
  1109. dev_err(dev, "%s: Error on request exclusive r=%d\n",
  1110. __func__, rc);
  1111. goto exit;
  1112. }
  1113. dev_vdbg(dev, "%s: Requesting mode change to CAT\n", __func__);
  1114. rc = cmd->request_set_mode(dev, CY_MODE_CAT);
  1115. if (rc < 0) {
  1116. dev_err(dev, "%s: Error on request set mode r=%d\n",
  1117. __func__, rc);
  1118. goto exit_release;
  1119. }
  1120. rc = cmd->request_write_config(dev, CY_TCH_PARM_EBID,
  1121. 0, (u8 *)ttconfig_data, ttconfig_size);
  1122. if (rc < 0) {
  1123. dev_err(dev, "%s: Error on request write config r=%d\n",
  1124. __func__, rc);
  1125. goto exit_setmode;
  1126. }
  1127. exit_setmode:
  1128. rc2 = cmd->request_set_mode(dev, CY_MODE_OPERATIONAL);
  1129. if (rc2 < 0)
  1130. dev_err(dev, "%s: Error on request set mode r=%d\n",
  1131. __func__, rc2);
  1132. exit_release:
  1133. rc2 = cmd->release_exclusive(dev);
  1134. if (rc < 0)
  1135. dev_err(dev, "%s: Error on release exclusive r=%d\n",
  1136. __func__, rc2);
  1137. exit:
  1138. if (!rc)
  1139. cmd->request_restart(dev, true);
  1140. pm_runtime_put(dev);
  1141. return rc;
  1142. }
  1143. #endif /* CYTTSP4_TTCONFIG_UPGRADE */
  1144. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_PLATFORM_TTCONFIG_UPGRADE
  1145. static int cyttsp4_get_ttconfig_crc(struct device *dev,
  1146. const u8 *ttconfig_data, int ttconfig_size, u16 *crc)
  1147. {
  1148. u16 crc_loc;
  1149. crc_loc = get_unaligned_le16(&ttconfig_data[2]);
  1150. if (ttconfig_size < crc_loc + 2)
  1151. return -EINVAL;
  1152. *crc = get_unaligned_le16(&ttconfig_data[crc_loc]);
  1153. return 0;
  1154. }
  1155. static int cyttsp4_get_ttconfig_version(struct device *dev,
  1156. const u8 *ttconfig_data, int ttconfig_size, u16 *version)
  1157. {
  1158. if (ttconfig_size < CY_TTCONFIG_VERSION_OFFSET
  1159. + CY_TTCONFIG_VERSION_SIZE)
  1160. return -EINVAL;
  1161. *version = get_unaligned_le16(
  1162. &ttconfig_data[CY_TTCONFIG_VERSION_OFFSET]);
  1163. return 0;
  1164. }
  1165. static int cyttsp4_check_ttconfig_version(struct device *dev,
  1166. const u8 *ttconfig_data, int ttconfig_size)
  1167. {
  1168. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  1169. int rc;
  1170. if (!ld->si)
  1171. return 0;
  1172. /* Check if device POST config CRC test failed */
  1173. if (!(ld->si->si_ptrs.test->post_codel &
  1174. CY_POST_CODEL_CFG_DATA_CRC_FAIL)) {
  1175. dev_info(dev, "%s: Config CRC invalid, will upgrade\n",
  1176. __func__);
  1177. return 1;
  1178. }
  1179. /* Check for config version */
  1180. if (ld->loader_pdata->flags &
  1181. CY_LOADER_FLAG_CHECK_TTCONFIG_VERSION) {
  1182. u16 cfg_ver_new;
  1183. rc = cyttsp4_get_ttconfig_version(dev, ttconfig_data,
  1184. ttconfig_size, &cfg_ver_new);
  1185. if (rc)
  1186. return 0;
  1187. dev_dbg(dev, "%s: img_ver:0x%04X new_ver:0x%04X\n",
  1188. __func__, ld->si->ttconfig.version, cfg_ver_new);
  1189. /* Check if config version is newer */
  1190. if (cfg_ver_new > ld->si->ttconfig.version) {
  1191. dev_dbg(dev, "%s: Config version newer, will upgrade\n",
  1192. __func__);
  1193. return 1;
  1194. }
  1195. dev_dbg(dev, "%s: Config version is identical or older, will NOT upgrade\n",
  1196. __func__);
  1197. /* Check for config CRC */
  1198. } else {
  1199. u16 cfg_crc_new;
  1200. rc = cyttsp4_get_ttconfig_crc(dev, ttconfig_data,
  1201. ttconfig_size, &cfg_crc_new);
  1202. if (rc)
  1203. return 0;
  1204. dev_dbg(dev, "%s: img_crc:0x%04X new_crc:0x%04X\n",
  1205. __func__, ld->si->ttconfig.crc, cfg_crc_new);
  1206. /* Check if config CRC different. */
  1207. if (cfg_crc_new != ld->si->ttconfig.crc) {
  1208. dev_dbg(dev, "%s: Config CRC different, will upgrade\n",
  1209. __func__);
  1210. return 1;
  1211. }
  1212. dev_dbg(dev, "%s: Config CRC equal, will NOT upgrade\n",
  1213. __func__);
  1214. }
  1215. return 0;
  1216. }
  1217. static int cyttsp4_check_ttconfig_version_platform(struct device *dev,
  1218. struct cyttsp4_touch_config *ttconfig)
  1219. {
  1220. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  1221. u32 fw_ver_config;
  1222. u32 fw_revctrl_config_h;
  1223. u32 fw_revctrl_config_l;
  1224. if (!ld->si) {
  1225. dev_info(dev, "%s: No firmware infomation found, device FW may be corrupted\n",
  1226. __func__);
  1227. return 0;
  1228. }
  1229. fw_ver_config = get_unaligned_be16(ttconfig->fw_ver + 2);
  1230. fw_revctrl_config_h = get_unaligned_be32(ttconfig->fw_ver + 4);
  1231. fw_revctrl_config_l = get_unaligned_be32(ttconfig->fw_ver + 8);
  1232. /* FW versions should match */
  1233. if (cyttsp4_check_firmware_version(dev, fw_ver_config,
  1234. fw_revctrl_config_h, fw_revctrl_config_l)) {
  1235. dev_err(dev, "%s: FW versions mismatch\n", __func__);
  1236. return 0;
  1237. }
  1238. return cyttsp4_check_ttconfig_version(dev, ttconfig->param_regs->data,
  1239. ttconfig->param_regs->size);
  1240. }
  1241. static int upgrade_ttconfig_from_platform(struct device *dev)
  1242. {
  1243. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  1244. struct cyttsp4_touch_config *ttconfig;
  1245. struct touch_settings *param_regs;
  1246. struct cyttsp4_touch_fw;
  1247. int rc = -ENOSYS;
  1248. int upgrade;
  1249. if (!ld->loader_pdata) {
  1250. dev_info(dev, "%s: No loader platform data\n", __func__);
  1251. return rc;
  1252. }
  1253. ttconfig = ld->loader_pdata->ttconfig;
  1254. if (!ttconfig) {
  1255. dev_info(dev, "%s: No ttconfig data\n", __func__);
  1256. return rc;
  1257. }
  1258. param_regs = ttconfig->param_regs;
  1259. if (!param_regs) {
  1260. dev_info(dev, "%s: No touch parameters\n", __func__);
  1261. return rc;
  1262. }
  1263. if (!param_regs->data || !param_regs->size) {
  1264. dev_info(dev, "%s: Invalid touch parameters\n", __func__);
  1265. return rc;
  1266. }
  1267. if (!ttconfig->fw_ver || !ttconfig->fw_vsize) {
  1268. dev_info(dev, "%s: Invalid FW version for touch parameters\n",
  1269. __func__);
  1270. return rc;
  1271. }
  1272. upgrade = cyttsp4_check_ttconfig_version_platform(dev, ttconfig);
  1273. if (upgrade)
  1274. return cyttsp4_upgrade_ttconfig(dev, param_regs->data,
  1275. param_regs->size);
  1276. return rc;
  1277. }
  1278. #endif /* CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_PLATFORM_TTCONFIG_UPGRADE */
  1279. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_MANUAL_TTCONFIG_UPGRADE
  1280. static ssize_t cyttsp4_config_data_write(struct file *filp,
  1281. struct kobject *kobj, struct bin_attribute *bin_attr,
  1282. char *buf, loff_t offset, size_t count)
  1283. {
  1284. struct device *dev = container_of(kobj, struct device, kobj);
  1285. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  1286. u8 *p;
  1287. dev_vdbg(dev, "%s: offset:%lld count:%d\n", __func__, offset, count);
  1288. mutex_lock(&ld->config_lock);
  1289. if (!ld->config_loading) {
  1290. mutex_unlock(&ld->config_lock);
  1291. return -ENODEV;
  1292. }
  1293. p = krealloc(ld->config_data, offset + count, GFP_KERNEL);
  1294. if (!p) {
  1295. kfree(ld->config_data);
  1296. ld->config_data = NULL;
  1297. ld->config_size = 0;
  1298. ld->config_loading = false;
  1299. mutex_unlock(&ld->config_lock);
  1300. return -ENOMEM;
  1301. }
  1302. ld->config_data = p;
  1303. memcpy(&ld->config_data[offset], buf, count);
  1304. ld->config_size += count;
  1305. mutex_unlock(&ld->config_lock);
  1306. return count;
  1307. }
  1308. static struct bin_attribute bin_attr_config_data = {
  1309. .attr = {
  1310. .name = "config_data",
  1311. .mode = S_IWUSR,
  1312. },
  1313. .size = 0,
  1314. .write = cyttsp4_config_data_write,
  1315. };
  1316. static ssize_t cyttsp4_config_loading_show(struct device *dev,
  1317. struct device_attribute *attr, char *buf)
  1318. {
  1319. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  1320. bool config_loading;
  1321. mutex_lock(&ld->config_lock);
  1322. config_loading = ld->config_loading;
  1323. mutex_unlock(&ld->config_lock);
  1324. return sprintf(buf, "%d\n", config_loading);
  1325. }
  1326. static int cyttsp4_verify_ttconfig_binary(struct device *dev,
  1327. u8 *bin_config_data, int bin_config_size, u8 **start, int *len)
  1328. {
  1329. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  1330. int header_size;
  1331. u16 config_size;
  1332. u16 max_config_size;
  1333. u32 fw_ver_config;
  1334. u32 fw_revctrl_config_h;
  1335. u32 fw_revctrl_config_l;
  1336. if (!ld->si) {
  1337. dev_err(dev, "%s: No firmware infomation found, device FW may be corrupted\n",
  1338. __func__);
  1339. return -ENODEV;
  1340. }
  1341. /*
  1342. * We need 11 bytes for FW version control info and at
  1343. * least 6 bytes in config (Length + Max Length + CRC)
  1344. */
  1345. header_size = bin_config_data[0] + 1;
  1346. if (header_size < 11 || header_size >= bin_config_size - 6) {
  1347. dev_err(dev, "%s: Invalid header size %d\n", __func__,
  1348. header_size);
  1349. return -EINVAL;
  1350. }
  1351. fw_ver_config = get_unaligned_be16(&bin_config_data[1]);
  1352. fw_revctrl_config_h = get_unaligned_be32(&bin_config_data[3]);
  1353. fw_revctrl_config_l = get_unaligned_be32(&bin_config_data[7]);
  1354. /* FW versions should match */
  1355. if (cyttsp4_check_firmware_version(dev, fw_ver_config,
  1356. fw_revctrl_config_h, fw_revctrl_config_l)) {
  1357. dev_err(dev, "%s: FW versions mismatch\n", __func__);
  1358. return -EINVAL;
  1359. }
  1360. config_size = get_unaligned_le16(&bin_config_data[header_size]);
  1361. max_config_size =
  1362. get_unaligned_le16(&bin_config_data[header_size + 2]);
  1363. /* Perform a simple size check (2 bytes for CRC) */
  1364. if (config_size != bin_config_size - header_size - 2) {
  1365. dev_err(dev, "%s: Config size invalid\n", __func__);
  1366. return -EINVAL;
  1367. }
  1368. /* Perform a size check against device config length */
  1369. if (config_size != ld->si->ttconfig.length
  1370. || max_config_size != ld->si->ttconfig.max_length) {
  1371. dev_err(dev, "%s: Config size mismatch\n", __func__);
  1372. return -EINVAL;
  1373. }
  1374. *start = &bin_config_data[header_size];
  1375. *len = bin_config_size - header_size;
  1376. return 0;
  1377. }
  1378. /*
  1379. * 1: Start loading TT Config
  1380. * 0: End loading TT Config and perform upgrade
  1381. *-1: Exit loading
  1382. */
  1383. static ssize_t cyttsp4_config_loading_store(struct device *dev,
  1384. struct device_attribute *attr, const char *buf, size_t size)
  1385. {
  1386. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  1387. long value;
  1388. u8 *start;
  1389. int length;
  1390. int rc;
  1391. rc = kstrtol(buf, 10, &value);
  1392. if (rc < 0 || value < -1 || value > 1) {
  1393. dev_err(dev, "%s: Invalid value\n", __func__);
  1394. return size;
  1395. }
  1396. mutex_lock(&ld->config_lock);
  1397. if (value == 1)
  1398. ld->config_loading = true;
  1399. else if (value == -1)
  1400. ld->config_loading = false;
  1401. else if (value == 0 && ld->config_loading) {
  1402. ld->config_loading = false;
  1403. if (ld->config_size == 0) {
  1404. dev_err(dev, "%s: No config data\n", __func__);
  1405. goto exit_free;
  1406. }
  1407. rc = cyttsp4_verify_ttconfig_binary(dev,
  1408. ld->config_data, ld->config_size,
  1409. &start, &length);
  1410. if (rc)
  1411. goto exit_free;
  1412. rc = cyttsp4_upgrade_ttconfig(dev, start, length);
  1413. }
  1414. exit_free:
  1415. kfree(ld->config_data);
  1416. ld->config_data = NULL;
  1417. ld->config_size = 0;
  1418. mutex_unlock(&ld->config_lock);
  1419. if (rc)
  1420. return rc;
  1421. return size;
  1422. }
  1423. static DEVICE_ATTR(config_loading, S_IRUSR | S_IWUSR,
  1424. cyttsp4_config_loading_show, cyttsp4_config_loading_store);
  1425. #endif /* CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_MANUAL_TTCONFIG_UPGRADE */
  1426. #if !defined(UPGRADE_FW_IN_PROBE)
  1427. static void cyttsp4_fw_and_config_upgrade(
  1428. struct work_struct *fw_and_config_upgrade)
  1429. #else
  1430. static void cyttsp4_fw_and_config_upgrade(
  1431. struct cyttsp4_loader_data *ld)
  1432. #endif
  1433. {
  1434. #if !defined(UPGRADE_FW_IN_PROBE)
  1435. struct cyttsp4_loader_data *ld = container_of(fw_and_config_upgrade,
  1436. struct cyttsp4_loader_data, fw_and_config_upgrade);
  1437. #endif
  1438. struct device *dev = ld->dev;
  1439. ld->si = cmd->request_sysinfo(dev);
  1440. if (!ld->si)
  1441. dev_err(dev, "%s: Fail get sysinfo pointer from core\n",
  1442. __func__);
  1443. #if !CYTTSP4_FW_UPGRADE
  1444. dev_info(dev, "%s: No FW upgrade method selected!\n", __func__);
  1445. #endif
  1446. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_PLATFORM_FW_UPGRADE
  1447. if (!upgrade_firmware_from_platform(dev, false))
  1448. return;
  1449. #endif
  1450. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_BINARY_FW_UPGRADE
  1451. if (!upgrade_firmware_from_builtin(dev))
  1452. return;
  1453. #endif
  1454. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_PLATFORM_TTCONFIG_UPGRADE
  1455. if (!upgrade_ttconfig_from_platform(dev))
  1456. return;
  1457. #endif
  1458. }
  1459. #if CYTTSP4_FW_UPGRADE
  1460. static int cyttsp4_fw_upgrade_cb(struct device *dev)
  1461. {
  1462. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_PLATFORM_FW_UPGRADE
  1463. if (!upgrade_firmware_from_platform(dev, false))
  1464. return 1;
  1465. #endif
  1466. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_BINARY_FW_UPGRADE
  1467. if (!upgrade_firmware_from_builtin(dev))
  1468. return 1;
  1469. #endif
  1470. return 0;
  1471. }
  1472. #endif
  1473. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_PLATFORM_FW_UPGRADE
  1474. static ssize_t cyttsp4_forced_upgrade_store(struct device *dev,
  1475. struct device_attribute *attr, const char *buf, size_t size)
  1476. {
  1477. int rc = upgrade_firmware_from_platform(dev, true);
  1478. if (rc)
  1479. return rc;
  1480. return size;
  1481. }
  1482. static DEVICE_ATTR(forced_upgrade, S_IRUSR | S_IWUSR,
  1483. NULL, cyttsp4_forced_upgrade_store);
  1484. #endif
  1485. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_BINARY_FW_UPGRADE
  1486. static ssize_t cyttsp4_manual_upgrade_store(struct device *dev,
  1487. struct device_attribute *attr, const char *buf, size_t size)
  1488. {
  1489. upgrade_firmware_from_class(dev);
  1490. return size;
  1491. }
  1492. static DEVICE_ATTR(manual_upgrade, S_IRUSR | S_IWUSR,
  1493. NULL, cyttsp4_manual_upgrade_store);
  1494. #endif
  1495. int cyttsp4_loader_probe(struct device *dev)
  1496. {
  1497. struct cyttsp4_core_data *cd = dev_get_drvdata(dev);
  1498. struct cyttsp4_loader_data *ld;
  1499. struct cyttsp4_platform_data *pdata = dev_get_platdata(dev);
  1500. int rc;
  1501. dev_info(dev, "%s: \n", __func__);
  1502. cmd = cyttsp4_get_commands();
  1503. if (!cmd)
  1504. {
  1505. dev_err(dev, "%s: cmd invalid\n", __func__);
  1506. return -EINVAL;
  1507. }
  1508. if (!pdata || !pdata->loader_pdata) {
  1509. dev_err(dev, "%s: Missing platform data\n", __func__);
  1510. rc = -ENODEV;
  1511. goto error_no_pdata;
  1512. }
  1513. ld = kzalloc(sizeof(*ld), GFP_KERNEL);
  1514. if (!ld) {
  1515. dev_err(dev, "%s: Error, kzalloc\n", __func__);
  1516. rc = -ENOMEM;
  1517. goto error_alloc_data_failed;
  1518. }
  1519. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_PLATFORM_FW_UPGRADE
  1520. rc = device_create_file(dev, &dev_attr_forced_upgrade);
  1521. if (rc) {
  1522. dev_err(dev, "%s: Error, could not create forced_upgrade\n",
  1523. __func__);
  1524. goto error_create_forced_upgrade;
  1525. }
  1526. #endif
  1527. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_BINARY_FW_UPGRADE
  1528. rc = device_create_file(dev, &dev_attr_manual_upgrade);
  1529. if (rc) {
  1530. dev_err(dev, "%s: Error, could not create manual_upgrade\n",
  1531. __func__);
  1532. goto error_create_manual_upgrade;
  1533. }
  1534. #endif
  1535. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_MANUAL_TTCONFIG_UPGRADE
  1536. rc = device_create_file(dev, &dev_attr_config_loading);
  1537. if (rc) {
  1538. dev_err(dev, "%s: Error, could not create config_loading\n",
  1539. __func__);
  1540. goto error_create_config_loading;
  1541. }
  1542. rc = device_create_bin_file(dev, &bin_attr_config_data);
  1543. if (rc) {
  1544. dev_err(dev, "%s: Error, could not create config_data\n",
  1545. __func__);
  1546. goto error_create_config_data;
  1547. }
  1548. #endif
  1549. ld->loader_pdata = pdata->loader_pdata;
  1550. ld->dev = dev;
  1551. cd->cyttsp4_dynamic_data[CY_MODULE_LOADER] = ld;
  1552. #if CYTTSP4_FW_UPGRADE
  1553. init_completion(&ld->int_running);
  1554. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_BINARY_FW_UPGRADE
  1555. init_completion(&ld->builtin_bin_fw_complete);
  1556. #endif
  1557. cmd->subscribe_attention(dev, CY_ATTEN_IRQ, CY_MODULE_LOADER,
  1558. cyttsp4_loader_attention, CY_MODE_BOOTLOADER);
  1559. cmd->subscribe_attention(dev, CY_ATTEN_LOADER, CY_MODULE_LOADER,
  1560. cyttsp4_fw_upgrade_cb, CY_MODE_UNKNOWN);
  1561. #ifdef CALIBRATE_IN_LOADER
  1562. INIT_WORK(&ld->calibration_work, cyttsp4_fw_calibrate);
  1563. #endif
  1564. #endif//CYTTSP4_FW_UPGRADE
  1565. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_MANUAL_TTCONFIG_UPGRADE
  1566. mutex_init(&ld->config_lock);
  1567. #endif
  1568. #if !defined(UPGRADE_FW_IN_PROBE)
  1569. INIT_WORK(&ld->fw_and_config_upgrade, cyttsp4_fw_and_config_upgrade);
  1570. schedule_work(&ld->fw_and_config_upgrade);
  1571. #else
  1572. cyttsp4_fw_and_config_upgrade(ld);
  1573. #endif
  1574. dev_info(dev, "%s: Successful probe %s\n", __func__, dev_name(dev));
  1575. return 0;
  1576. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_MANUAL_TTCONFIG_UPGRADE
  1577. error_create_config_data:
  1578. device_remove_file(dev, &dev_attr_config_loading);
  1579. error_create_config_loading:
  1580. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_BINARY_FW_UPGRADE
  1581. device_remove_file(dev, &dev_attr_manual_upgrade);
  1582. #endif
  1583. #endif
  1584. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_BINARY_FW_UPGRADE
  1585. error_create_manual_upgrade:
  1586. #endif
  1587. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_PLATFORM_FW_UPGRADE
  1588. device_remove_file(dev, &dev_attr_forced_upgrade);
  1589. error_create_forced_upgrade:
  1590. #endif
  1591. cd->cyttsp4_dynamic_data[CY_MODULE_LOADER] = NULL;
  1592. kfree(ld);
  1593. error_alloc_data_failed:
  1594. error_no_pdata:
  1595. dev_err(dev, "%s failed.\n", __func__);
  1596. return rc;
  1597. }
  1598. int cyttsp4_loader_release(struct device *dev)
  1599. {
  1600. struct cyttsp4_core_data *cd = dev_get_drvdata(dev);
  1601. struct cyttsp4_loader_data *ld = cyttsp4_get_loader_data(dev);
  1602. int rc = 0;
  1603. dev_dbg(dev, "%s\n", __func__);
  1604. #if CYTTSP4_FW_UPGRADE
  1605. rc = cmd->unsubscribe_attention(dev, CY_ATTEN_IRQ, CY_MODULE_LOADER,
  1606. cyttsp4_loader_attention, CY_MODE_BOOTLOADER);
  1607. if (rc < 0)
  1608. dev_err(dev, "%s: Failed to restart IC with error code %d\n",
  1609. __func__, rc);
  1610. #endif
  1611. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_MANUAL_TTCONFIG_UPGRADE
  1612. device_remove_bin_file(dev, &bin_attr_config_data);
  1613. device_remove_file(dev, &dev_attr_config_loading);
  1614. kfree(ld->config_data);
  1615. #endif
  1616. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_BINARY_FW_UPGRADE
  1617. device_remove_file(dev, &dev_attr_manual_upgrade);
  1618. #endif
  1619. #ifdef CONFIG_TOUCHSCREEN_CYPRESS_CYTTSP4_PLATFORM_FW_UPGRADE
  1620. device_remove_file(dev, &dev_attr_forced_upgrade);
  1621. #endif
  1622. cd->cyttsp4_dynamic_data[CY_MODULE_LOADER] = NULL;
  1623. kfree(ld);
  1624. return rc;
  1625. }