1 /*
2 *
3 * FocalTech fts TouchScreen driver.
4 *
5 * Copyright (c) 2012-2018, Focaltech Ltd. All rights reserved.
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18 /*****************************************************************************
19 *
20 * File Name: focaltech_upgrade_ft8006m.c
21 *
22 * Author: Focaltech Driver Team
23 *
24 * Created: 2016-12-29
25 *
26 * Abstract:
27 *
28 * Reference:
29 *
30 *****************************************************************************/
31
32 /*****************************************************************************
33 * 1.Included header files
34 *****************************************************************************/
35 #include "focaltech_core.h"
36 #include "focaltech_flash.h"
37
38 /*****************************************************************************
39 * Global variable or extern global variabls/functions
40 *****************************************************************************/
41 u8 pb_file_ft8006m[] = {
42 #include "include/pramboot/FT8006M_Pramboot_V1.6_20180426_le.h"
43 };
44
45 /*****************************************************************************
46 * Private constant and macro definitions using #define
47 *****************************************************************************/
48 #define FTS_MAX_LEN_APP_FT8006M (94 * 1024)
49
50 #define MAX_BANK_DATA 0x80
51 #define MAX_GAMMA_LEN 0x180
52 #define LIC_CHECKSUM_H_OFF 0x00
53 #define LIC_CHECKSUM_L_OFF 0x01
54 #define LIC_LCD_ECC_H_OFF 0x04
55 #define LIC_LCD_ECC_L_OFF 0x05
56 #define LIC_ECC_REG_H_OFF 0x43D
57 #define LIC_ECC_REG_L_OFF 0x43C
58 #define LIC_REG_2 0xB2
59
60 static int gamma_enable[] = { 0x040d, 0x91, 0x80, 0x00, 0x19, 0x01 };
61 union short_bits {
62 u16 dshort;
63 struct bits {
64 u16 bit0: 1;
65 u16 bit1: 1;
66 u16 bit2: 1;
67 u16 bit3: 1;
68 u16 bit4: 1;
69 u16 bit5: 1;
70 u16 bit6: 1;
71 u16 bit7: 1;
72 u16 bit8: 1;
73 u16 bit9: 1;
74 u16 bit10: 1;
75 u16 bit11: 1;
76 u16 bit12: 1;
77 u16 bit13: 1;
78 u16 bit14: 1;
79 u16 bit15: 1;
80 } bits;
81 };
82
83 /*****************************************************************************
84 * Static function prototypes
85 *****************************************************************************/
86
87 /* calculate lcd init code ecc */
cal_lcdinitcode_ecc(u8 * buf,u16 * ecc_val)88 static int cal_lcdinitcode_ecc(u8 *buf, u16 *ecc_val)
89 {
90 u32 bank_crc_en = 0;
91 u8 bank_data[MAX_BANK_DATA] = { 0 };
92 u16 bank_len = 0;
93 u16 bank_addr = 0;
94 u32 bank_num = 0;
95 u16 file_len = 0;
96 u16 pos = 0;
97 int i = 0;
98 union short_bits ecc;
99 union short_bits ecc_last;
100 union short_bits temp_byte;
101 u8 bank_mapping[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9,
102 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x18,
103 0x19, 0x1A, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x22, 0x23, 0x24
104 }; /* Actaul mipi bank */
105 u8 banknum = 0;
106
107 ecc.dshort = 0;
108 ecc_last.dshort = 0;
109 temp_byte.dshort = 0;
110
111 file_len = (u16)(((u16)buf[2] << 8) + buf[3]);
112 if ((file_len >= FTS_MAX_LEN_SECTOR) || (file_len <= FTS_MIN_LEN)) {
113 FTS_ERROR("host lcd init code len(%x) is too large", file_len);
114 return -EINVAL;
115 }
116
117 bank_crc_en = (u32)(((u32)buf[9] << 24) + ((u32)buf[8] << 16) + \
118 ((u32)buf[7] << 8) + (u32)buf[6]);
119 FTS_INFO("lcd init code len=%x bank en=%x", file_len, bank_crc_en);
120
121 pos = 0x0A; /* addr of first bank */
122 while (pos < file_len) {
123 bank_addr = (u16)(((u16)buf[pos + 0] << 8 ) + buf[pos + 1]);
124 bank_len = (u16)(((u16)buf[pos + 2] << 8 ) + buf[pos + 3]);
125 /* FTS_INFO("bank pos=%x bank_addr=%x bank_len=%x", pos, bank_addr, bank_len); */
126 if (bank_len > MAX_BANK_DATA)
127 return -EINVAL;
128 memset(bank_data, 0, MAX_BANK_DATA);
129 memcpy(bank_data, buf + pos + 4, bank_len);
130
131 bank_num = (bank_addr - 0x8000) / MAX_BANK_DATA;
132 /* FTS_INFO("actual mipi bank number = %x", bank_num); */
133 for (i = 0; i < sizeof(bank_mapping) / sizeof(u8); i++) {
134 if (bank_num == bank_mapping[i]) {
135 banknum = i;
136 break;
137 }
138 }
139 if (i >= sizeof(bank_mapping) / sizeof(u8)) {
140 FTS_INFO("actual mipi bank(%d) not find in bank mapping, need jump", bank_num);
141 } else {
142 /* FTS_INFO("bank number = %d", banknum); */
143 if ((bank_crc_en >> banknum) & 0x01) {
144 for (i = 0; i < MAX_BANK_DATA; i++) {
145 temp_byte.dshort = (u16)bank_data[i];
146 /* if(i == 0) */
147 /* FTS_INFO("data0=%x, %d %d %d %d %d %d %d %d", temp_byte.dshort, temp_byte.bits.bit0, */
148 /* temp_byte.bits.bit1, temp_byte.bits.bit2, temp_byte.bits.bit3, temp_byte.bits.bit4, */
149 /* temp_byte.bits.bit5, temp_byte.bits.bit6, temp_byte.bits.bit7); */
150
151 ecc.bits.bit0 = ecc_last.bits.bit8 ^ ecc_last.bits.bit9 ^ ecc_last.bits.bit10 ^ ecc_last.bits.bit11
152 ^ ecc_last.bits.bit12 ^ ecc_last.bits.bit13 ^ ecc_last.bits.bit14 ^ ecc_last.bits.bit15
153 ^ temp_byte.bits.bit0 ^ temp_byte.bits.bit1 ^ temp_byte.bits.bit2 ^ temp_byte.bits.bit3
154 ^ temp_byte.bits.bit4 ^ temp_byte.bits.bit5 ^ temp_byte.bits.bit6 ^ temp_byte.bits.bit7;
155
156 ecc.bits.bit1 = ecc_last.bits.bit9 ^ ecc_last.bits.bit10 ^ ecc_last.bits.bit11 ^ ecc_last.bits.bit12
157 ^ ecc_last.bits.bit13 ^ ecc_last.bits.bit14 ^ ecc_last.bits.bit15
158 ^ temp_byte.bits.bit1 ^ temp_byte.bits.bit2 ^ temp_byte.bits.bit3 ^ temp_byte.bits.bit4
159 ^ temp_byte.bits.bit5 ^ temp_byte.bits.bit6 ^ temp_byte.bits.bit7;
160
161 ecc.bits.bit2 = ecc_last.bits.bit8 ^ ecc_last.bits.bit9 ^ temp_byte.bits.bit0 ^ temp_byte.bits.bit1;
162
163 ecc.bits.bit3 = ecc_last.bits.bit9 ^ ecc_last.bits.bit10 ^ temp_byte.bits.bit1 ^ temp_byte.bits.bit2;
164
165 ecc.bits.bit4 = ecc_last.bits.bit10 ^ ecc_last.bits.bit11 ^ temp_byte.bits.bit2 ^ temp_byte.bits.bit3;
166
167 ecc.bits.bit5 = ecc_last.bits.bit11 ^ ecc_last.bits.bit12 ^ temp_byte.bits.bit3 ^ temp_byte.bits.bit4;
168
169 ecc.bits.bit6 = ecc_last.bits.bit12 ^ ecc_last.bits.bit13 ^ temp_byte.bits.bit4 ^ temp_byte.bits.bit5;
170
171 ecc.bits.bit7 = ecc_last.bits.bit13 ^ ecc_last.bits.bit14 ^ temp_byte.bits.bit5 ^ temp_byte.bits.bit6;
172
173 ecc.bits.bit8 = ecc_last.bits.bit0 ^ ecc_last.bits.bit14 ^ ecc_last.bits.bit15 ^ temp_byte.bits.bit6 ^ temp_byte.bits.bit7;
174
175 ecc.bits.bit9 = ecc_last.bits.bit1 ^ ecc_last.bits.bit15 ^ temp_byte.bits.bit7;
176
177 ecc.bits.bit10 = ecc_last.bits.bit2;
178
179 ecc.bits.bit11 = ecc_last.bits.bit3;
180
181 ecc.bits.bit12 = ecc_last.bits.bit4;
182
183 ecc.bits.bit13 = ecc_last.bits.bit5;
184
185 ecc.bits.bit14 = ecc_last.bits.bit6;
186
187 ecc.bits.bit15 = ecc_last.bits.bit7 ^ ecc_last.bits.bit8 ^ ecc_last.bits.bit9 ^ ecc_last.bits.bit10
188 ^ ecc_last.bits.bit11 ^ ecc_last.bits.bit12 ^ ecc_last.bits.bit13 ^ ecc_last.bits.bit14 ^ ecc_last.bits.bit15
189 ^ temp_byte.bits.bit0 ^ temp_byte.bits.bit1 ^ temp_byte.bits.bit2 ^ temp_byte.bits.bit3
190 ^ temp_byte.bits.bit4 ^ temp_byte.bits.bit5 ^ temp_byte.bits.bit6 ^ temp_byte.bits.bit7;
191
192 ecc_last.dshort = ecc.dshort;
193
194 }
195 }
196 }
197 pos += bank_len + 4;
198 }
199
200 *ecc_val = ecc.dshort;
201 return 0;
202 }
203
204 /* calculate lcd init code checksum */
cal_lcdinitcode_checksum(u8 * ptr,int length)205 static u16 cal_lcdinitcode_checksum(u8 *ptr , int length)
206 {
207 /* CRC16 */
208 u16 cfcs = 0;
209 int i, j;
210
211 if (length % 2) {
212 return 0xFFFF;
213 }
214
215 for ( i = 0; i < length; i += 2 ) {
216 cfcs ^= ((ptr[i] << 8) + ptr[i + 1]);
217 for (j = 0; j < 16; j ++) {
218 if (cfcs & 1) {
219 cfcs = (u16)((cfcs >> 1) ^ ((1 << 15) + (1 << 10) + (1 << 3)));
220 } else {
221 cfcs >>= 1;
222 }
223 }
224 }
225 return cfcs;
226 }
227
print_data(u8 * buf,u32 len)228 static int print_data(u8 *buf, u32 len)
229 {
230 int i = 0;
231 int n = 0;
232 u8 *p = NULL;
233
234 p = kzalloc(len * 4, GFP_KERNEL);
235 for (i = 0; i < len; i++) {
236 n += snprintf(p + n, PAGE_SIZE, "%02x ", buf[i]);
237 }
238
239 FTS_DEBUG("%s", p);
240
241 kfree(p);
242 return 0;
243 }
244
read_3gamma(struct i2c_client * client,u8 ** gamma,u16 * len)245 static int read_3gamma(struct i2c_client *client, u8 **gamma, u16 *len)
246 {
247 int ret = 0;
248 int i = 0;
249 int packet_num = 0;
250 int packet_len = 0;
251 int remainder = 0;
252 u8 cmd[4] = { 0 };
253 u32 addr = 0x01D000;
254 u8 gamma_header[0x20] = { 0 };
255 u16 gamma_len = 0;
256 u16 gamma_len_n = 0;
257 u16 pos = 0;
258 bool gamma_has_enable = false;
259 u8 *pgamma = NULL;
260 int j = 0;
261 u8 gamma_ecc = 0;
262
263 cmd[0] = 0x03;
264 cmd[1] = (u8)(addr >> 16);
265 cmd[2] = (u8)(addr >> 8);
266 cmd[3] = (u8)addr;
267 fts_i2c_write(client, cmd, 4);
268 msleep(10);
269 ret = fts_i2c_read(client, NULL, 0, gamma_header, 0x20);
270 if (ret < 0) {
271 FTS_ERROR("read 3-gamma header fail");
272 return ret;
273 }
274
275 gamma_len = (u16)((u16)gamma_header[0] << 8) + gamma_header[1];
276 gamma_len_n = (u16)((u16)gamma_header[2] << 8) + gamma_header[3];
277
278 if ((gamma_len + gamma_len_n) != 0xFFFF) {
279 FTS_INFO("gamma length check fail:%x %x", gamma_len, gamma_len);
280 return -EIO;
281 }
282
283 if ((gamma_header[4] + gamma_header[5]) != 0xFF) {
284 FTS_INFO("gamma ecc check fail:%x %x", gamma_header[4], gamma_header[5]);
285 return -EIO;
286 }
287
288 if (gamma_len > MAX_GAMMA_LEN) {
289 FTS_ERROR("gamma data len(%d) is too long", gamma_len);
290 return -EINVAL;
291 }
292
293 *gamma = kzalloc(MAX_GAMMA_LEN, GFP_KERNEL);
294 if (NULL == *gamma) {
295 FTS_ERROR("malloc gamma memory fail");
296 return -ENOMEM;
297 }
298 pgamma = *gamma;
299
300 packet_num = gamma_len / 256;
301 packet_len = 256;
302 remainder = gamma_len % 256;
303 if (remainder) packet_num++;
304 FTS_INFO("3-gamma len:%d", gamma_len);
305 cmd[0] = 0x03;
306 addr += 0x20;
307 for (i = 0; i < packet_num; i++) {
308 addr += i * 256;
309 cmd[1] = (u8)(addr >> 16);
310 cmd[2] = (u8)(addr >> 8);
311 cmd[3] = (u8)addr;
312 if ((i == packet_num - 1) && remainder)
313 packet_len = remainder;
314 fts_i2c_write(client, cmd, 4);
315 msleep(10);
316 ret = fts_i2c_read(client, NULL, 0, pgamma + i * 256, packet_len);
317 if (ret < 0) {
318 FTS_ERROR("read 3-gamma data fail");
319 return ret;
320 }
321 }
322
323 /* ecc */
324 for (j = 0; j < gamma_len; j++) {
325 gamma_ecc ^= pgamma[j];
326 }
327 FTS_INFO("back_3gamma_ecc: 0x%x, 0x%x", gamma_ecc, gamma_header[0x04]);
328 if (gamma_ecc != gamma_header[0x04]) {
329 FTS_ERROR("back gamma ecc check fail:%x %x", gamma_ecc, gamma_header[0x04]);
330 return -EIO;
331 }
332
333 /* check last byte is 91 80 00 19 01 */
334 pos = gamma_len - 5;
335
336 if (pos > MAX_GAMMA_LEN) {
337 FTS_ERROR("pos len(%d) is too long", pos);
338 return -EINVAL;
339 }
340
341 if ((gamma_enable[1] == pgamma[pos]) && (gamma_enable[2] == pgamma[pos + 1])
342 && (gamma_enable[3] == pgamma[pos + 2]) && (gamma_enable[4] == pgamma[pos + 3])) {
343 gamma_has_enable = true;
344 }
345
346 if (false == gamma_has_enable) {
347 FTS_INFO("3-gamma has no gamma enable info");
348 pgamma[gamma_len++] = gamma_enable[1];
349 pgamma[gamma_len++] = gamma_enable[2];
350 pgamma[gamma_len++] = gamma_enable[3];
351 pgamma[gamma_len++] = gamma_enable[4];
352 pgamma[gamma_len++] = gamma_enable[5];
353 }
354
355 *len = gamma_len;
356
357 FTS_DEBUG("read 3-gamma data:");
358 print_data(*gamma, gamma_len);
359
360 return 0;
361 }
362
replace_3gamma(u8 * initcode,u8 * gamma,u16 gamma_len)363 static int replace_3gamma(u8 *initcode, u8 *gamma, u16 gamma_len)
364 {
365 u16 gamma_pos = 0;
366 int gamma_analog[] = { 0x003A, 0x85, 0x00, 0x00, 0x2C, 0x2B };
367 int gamma_digital1[] = { 0x0355, 0x8D, 0x00, 0x00, 0x80, 0x80 };
368 int gamma_digital2[] = { 0x03d9, 0x8D, 0x80, 0x00, 0x14, 0x13 };
369
370 /* Analog Gamma */
371 if ((initcode[gamma_analog[0]] == gamma[gamma_pos])
372 && (initcode[gamma_analog[0] + 1] == gamma[gamma_pos + 1])) {
373 memcpy(initcode + gamma_analog[0] + 4 , gamma + gamma_pos + 4, gamma_analog[5]);
374 gamma_pos += gamma_analog[5] + 4;
375 } else
376 goto find_gamma_bank_err;
377
378 /* Digital1 Gamma */
379 if ((initcode[gamma_digital1[0]] == gamma[gamma_pos])
380 && (initcode[gamma_digital1[0] + 1] == gamma[gamma_pos + 1])) {
381 memcpy(initcode + gamma_digital1[0] + 4 , gamma + gamma_pos + 4, gamma_digital1[5]);
382 gamma_pos += gamma_digital1[5] + 4;
383 } else
384 goto find_gamma_bank_err;
385
386 /* Digital2 Gamma */
387 if ((initcode[gamma_digital2[0]] == gamma[gamma_pos])
388 && (initcode[gamma_digital2[0] + 1] == gamma[gamma_pos + 1])) {
389 memcpy(initcode + gamma_digital2[0] + 4 , gamma + gamma_pos + 4, gamma_digital2[5]);
390 gamma_pos += gamma_digital2[5] + 4;
391 } else
392 goto find_gamma_bank_err;
393
394 /* enable Gamma */
395 if ((initcode[gamma_enable[0]] == gamma[gamma_pos])
396 && (initcode[gamma_enable[0] + 1] == gamma[gamma_pos + 1])) {
397 if (gamma[gamma_pos + 4])
398 initcode[gamma_enable[0] + 4 + 15] |= 0x01;
399 else
400 initcode[gamma_enable[0] + 4 + 15] &= 0xFE;
401 //gamma_pos += 1 + 4;
402 } else
403 goto find_gamma_bank_err;
404
405 FTS_DEBUG("replace 3-gamma data:");
406 print_data(initcode, 1100);
407
408 return 0;
409
410 find_gamma_bank_err:
411 FTS_INFO("3-gamma bank(%02x %02x) not find",
412 gamma[gamma_pos], gamma[gamma_pos + 1]);
413 return -ENODATA;
414 }
415
416 /*
417 * read_replace_3gamma - read and replace 3-gamma data
418 */
read_replace_3gamma(struct i2c_client * client,u8 * buf,bool flag)419 static int read_replace_3gamma(struct i2c_client *client, u8 *buf, bool flag)
420 {
421 int ret = 0;
422 u16 initcode_ecc = 0;
423 u16 initcode_checksum = 0;
424 u8 *tmpbuf = NULL;
425 u8 *gamma = NULL;
426 u16 gamma_len = 0;
427 u16 hlic_len = 0;
428 int base_addr = 0;
429 int i = 0;
430
431 FTS_FUNC_ENTER();
432
433 ret = read_3gamma(client, &gamma, &gamma_len);
434 if (ret < 0) {
435 FTS_INFO("no vaid 3-gamma data, not replace");
436 if (gamma) {
437 kfree(gamma);
438 gamma = NULL;
439 }
440 return 0;
441 }
442
443 base_addr = 0;
444 for (i = 0; i < 2; i++) {
445 if (1 == i) {
446 if (true == flag)
447 base_addr = 0x7C0;
448 else
449 break;
450 }
451
452 tmpbuf = buf + base_addr;
453 ret = replace_3gamma(tmpbuf, gamma, gamma_len);
454 if (ret < 0) {
455 FTS_ERROR("replace 3-gamma fail");
456 goto REPLACE_GAMMA_ERR;
457 }
458
459 ret = cal_lcdinitcode_ecc(tmpbuf, &initcode_ecc);
460 if (ret < 0) {
461 FTS_ERROR("lcd init code ecc calculate fail");
462 goto REPLACE_GAMMA_ERR;
463 }
464 FTS_INFO("lcd init code cal ecc:%04x", initcode_ecc);
465 tmpbuf[LIC_LCD_ECC_H_OFF] = (u8)(initcode_ecc >> 8);
466 tmpbuf[LIC_LCD_ECC_L_OFF] = (u8)(initcode_ecc);
467 tmpbuf[LIC_ECC_REG_H_OFF] = (u8)(initcode_ecc >> 8);
468 tmpbuf[LIC_ECC_REG_L_OFF] = (u8)(initcode_ecc);
469
470 hlic_len = (u16)(((u16)tmpbuf[2]) << 8) + tmpbuf[3];
471 initcode_checksum = cal_lcdinitcode_checksum(tmpbuf + 2, hlic_len - 2);
472 FTS_INFO("lcd init code calc checksum:0x%04x", initcode_checksum);
473 tmpbuf[LIC_CHECKSUM_H_OFF] = (u8)(initcode_checksum >> 8);
474 tmpbuf[LIC_CHECKSUM_L_OFF] = (u8)(initcode_checksum);
475 }
476
477 if (gamma) {
478 kfree(gamma);
479 gamma = NULL;
480 }
481
482 FTS_FUNC_EXIT();
483 return 0;
484
485 REPLACE_GAMMA_ERR:
486 if (gamma) {
487 kfree(gamma);
488 gamma = NULL;
489 }
490 return ret;
491 }
492
493 /*
494 * check_initial_code_valid - check initial code valid or not
495 */
check_initial_code_valid(struct i2c_client * client,u8 * buf)496 static int check_initial_code_valid(struct i2c_client *client, u8 *buf)
497 {
498 int ret = 0;
499 u16 initcode_ecc = 0;
500 u16 buf_ecc = 0;
501 u16 initcode_checksum = 0;
502 u16 buf_checksum = 0;
503 u16 hlic_len = 0;
504
505 hlic_len = (u16)(((u16)buf[2]) << 8) + buf[3];
506 if ((hlic_len >= FTS_MAX_LEN_SECTOR) || (hlic_len <= FTS_MIN_LEN)) {
507 FTS_ERROR("host lcd init code len(%x) is too large", hlic_len);
508 return -EINVAL;
509 }
510
511 initcode_checksum = cal_lcdinitcode_checksum(buf + 2, hlic_len - 2);
512 buf_checksum = ((u16)((u16)buf[0] << 8) + buf[1]);
513 FTS_INFO("lcd init code calc checksum:0x%04x,0x%04x", initcode_checksum, buf_checksum);
514 if (initcode_checksum != buf_checksum) {
515 FTS_ERROR("Initial Code checksum fail");
516 return -EINVAL;
517 }
518
519 ret = cal_lcdinitcode_ecc(buf, &initcode_ecc);
520 if (ret < 0) {
521 FTS_ERROR("lcd init code ecc calculate fail");
522 return ret;
523 }
524 buf_ecc = ((u16)((u16)buf[4] << 8) + buf[5]);
525 FTS_INFO("lcd init code cal ecc:%04x, %04x", initcode_ecc, buf_ecc);
526 if (initcode_ecc != buf_ecc) {
527 FTS_ERROR("Initial Code ecc check fail");
528 return -EINVAL;
529 }
530
531 return 0;
532 }
533
fts_ft8006m_check_ide(u8 * buf,u32 len)534 static bool fts_ft8006m_check_ide(u8 *buf, u32 len)
535 {
536 u32 off = 0;
537
538 FTS_INFO("Host FW file IDE version check");
539 if (NULL == buf) {
540 FTS_ERROR("buf is null fail");
541 return false;
542 }
543
544 if (len < FTS_MAX_LEN_FILE) {
545 FTS_INFO("buf len(%x) abnormal, no IDE", len);
546 return false;
547 }
548
549 off = upgrade_func_ft8006m.paramcfgoff;
550 if ((buf[off] == 'I') && (buf[off + 1] == 'D') && (buf[off + 2] == 'E'))
551 return true;
552
553 return false;
554 }
555
556 /* fts_ft8006m_write_ecc - write and check ecc
557 * return 0 if success
558 */
fts_ft8006m_write_ecc(struct i2c_client * client,u32 saddr,u8 * buf,u32 len)559 static int fts_ft8006m_write_ecc(
560 struct i2c_client *client,
561 u32 saddr,
562 u8 *buf,
563 u32 len)
564 {
565 int ecc_in_host = 0;
566 int ecc_in_tp = 0;
567
568 ecc_in_host = fts_flash_write_buf(client, saddr, buf, len, 1);
569 if (ecc_in_host < 0 ) {
570 FTS_ERROR("write buffer to flash fail");
571 return ecc_in_host;
572 }
573
574 /* ecc */
575 ecc_in_tp = fts_fwupg_ecc_cal(client, saddr, len);
576 if (ecc_in_tp < 0 ) {
577 FTS_ERROR("ecc read fail");
578 return ecc_in_tp;
579 }
580
581 FTS_INFO("ecc in tp:%x, host:%x", ecc_in_tp, ecc_in_host);
582 if (ecc_in_tp != ecc_in_host) {
583 FTS_ERROR("ecc check fail");
584 return -EIO;
585 }
586
587 return 0;
588 }
589
590 /************************************************************************
591 * Name: fts_ft8006m_param_flash
592 * Brief: param upgrade(erase/write/ecc check)
593 * Input: buf - all.bin
594 * len - len of all.bin
595 * Output:
596 * Return: return 0 if success, otherwise return error code
597 ***********************************************************************/
fts_ft8006m_param_flash(struct i2c_client * client,u8 * buf,u32 len)598 static int fts_ft8006m_param_flash(struct i2c_client *client, u8 *buf, u32 len)
599 {
600 int ret = 0;
601 u8 cmd[2] = { 0 };
602 u32 delay = 0;
603 u32 start_addr = 0;
604 u32 paramcfg_len = 0;
605 u8 *tmpbuf = NULL;
606
607 /* erase gesture & parameter sector */
608 cmd[0] = FTS_CMD_FLASH_MODE;
609 cmd[1] = FLASH_MODE_PARAM_VALUE;
610 ret = fts_i2c_write(client, cmd, 2);
611 if (ret < 0) {
612 FTS_ERROR("upgrade mode(09) cmd write fail");
613 goto PARAM_FLASH_ERR;
614 }
615
616 delay = FTS_ERASE_SECTOR_DELAY * 2;
617 ret = fts_fwupg_erase(client, delay);
618 if (ret < 0) {
619 FTS_ERROR("erase cmd write fail");
620 goto PARAM_FLASH_ERR;
621 }
622
623 /* write flash */
624 start_addr = upgrade_func_ft8006m.paramcfgoff;
625 paramcfg_len = FTS_MAX_LEN_SECTOR;
626 tmpbuf = buf + start_addr;
627 ret = fts_ft8006m_write_ecc(client, start_addr, tmpbuf, paramcfg_len);
628 if (ret < 0 ) {
629 FTS_ERROR("parameter configure area write fail");
630 goto PARAM_FLASH_ERR;
631 }
632
633 start_addr = upgrade_func_ft8006m.paramcfg2off;
634 paramcfg_len = FTS_MAX_LEN_SECTOR;
635 tmpbuf = buf + start_addr;
636 ret = fts_ft8006m_write_ecc(client, start_addr, tmpbuf, paramcfg_len);
637 if (ret < 0 ) {
638 FTS_ERROR("parameter2 configure area write fail");
639 goto PARAM_FLASH_ERR;
640 }
641
642 return 0;
643
644 PARAM_FLASH_ERR:
645 return ret;
646 }
647
648 /*
649 * fts_get_hlic_ver - read host lcd init code version
650 *
651 * return 0 if host lcd init code is valid, otherwise return error code
652 */
fts_ft8006m_get_hlic_ver(u8 * initcode)653 static int fts_ft8006m_get_hlic_ver(u8 *initcode)
654 {
655 u8 *hlic_buf = initcode;
656 u16 hlic_len = 0;
657 u8 hlic_ver[2] = { 0 };
658
659 hlic_len = (u16)(((u16)hlic_buf[2]) << 8) + hlic_buf[3];
660 FTS_INFO("host lcd init code len:%x", hlic_len);
661 if ((hlic_len >= FTS_MAX_LEN_SECTOR) || (hlic_len <= FTS_MIN_LEN)) {
662 FTS_ERROR("host lcd init code len(%x) is too large", hlic_len);
663 return -EINVAL;
664 }
665
666 hlic_ver[0] = hlic_buf[hlic_len];
667 hlic_ver[1] = hlic_buf[hlic_len + 1];
668
669 FTS_INFO("host lcd init code ver:%x %x", hlic_ver[0], hlic_ver[1]);
670 if (0xFF != (hlic_ver[0] + hlic_ver[1])) {
671 FTS_ERROR("host lcd init code version check fail");
672 return -EINVAL;
673 }
674
675 return hlic_ver[0];
676 }
677
678 /************************************************************************
679 * Name: fts_ft8006m_upgrade
680 * Brief:
681 * Input: buf - all.bin
682 * len - len of all.bin
683 * Output:
684 * Return: return 0 if success, otherwise return error code
685 ***********************************************************************/
fts_ft8006m_upgrade(struct i2c_client * client,u8 * buf,u32 len)686 static int fts_ft8006m_upgrade(struct i2c_client *client, u8 *buf, u32 len)
687 {
688 int ret = 0;
689 u8 *tmpbuf = NULL;
690 u8 cmd[2] = { 0 };
691 u32 delay = 0;
692 u32 start_addr = 0;
693 u32 app_1_len = 0;
694 u32 app_2_len = 0;
695 u32 app_len = 0;
696 u32 off = 0;
697
698 FTS_INFO("app upgrade...");
699 if (NULL == buf) {
700 FTS_ERROR("fw file buffer is null");
701 return -EINVAL;
702 }
703
704 if ((len < FTS_MIN_LEN) || (len > FTS_MAX_LEN_FILE)) {
705 FTS_ERROR("fw file buffer len(%x) fail", len);
706 return -EINVAL;
707 }
708
709 off = upgrade_func_ft8006m.appoff + FTS_APPINFO_OFF + FTS_APPINFO_APPLEN_OFF;
710 app_1_len = (((u32)buf[off] << 8) + buf[off + 1]);
711 off = upgrade_func_ft8006m.appoff + FTS_APPINFO_OFF + FTS_APPINFO_APPLEN2_OFF;
712 app_2_len = (((u32)buf[off] << 8) + buf[off + 1]);
713 app_len = (app_2_len << 16) + app_1_len;
714 if ((app_len < FTS_MIN_LEN) || (app_len > FTS_MAX_LEN_APP_FT8006M)) {
715 FTS_ERROR("app len(%x) fail", app_len);
716 return -EINVAL;
717 }
718
719 /* enter into upgrade environment */
720 ret = fts_fwupg_enter_into_boot(client);
721 if (ret < 0) {
722 FTS_ERROR("enter into pramboot/bootloader fail,ret=%d", ret);
723 goto APP_UPG_ERR;
724 }
725
726 /* erase gesture & parameter sector */
727 cmd[0] = FTS_CMD_FLASH_MODE;
728 cmd[1] = FLASH_MODE_UPGRADE_VALUE;
729 ret = fts_i2c_write(client, cmd, 2);
730 if (ret < 0) {
731 FTS_ERROR("upgrade mode(09) cmd write fail");
732 goto APP_UPG_ERR;
733 }
734
735 delay = FTS_ERASE_SECTOR_DELAY * (app_len / FTS_MAX_LEN_SECTOR);
736 ret = fts_fwupg_erase(client, delay);
737 if (ret < 0) {
738 FTS_ERROR("erase cmd write fail");
739 goto APP_UPG_ERR;
740 }
741
742 /* write flash */
743 start_addr = upgrade_func_ft8006m.appoff;
744 tmpbuf = buf + start_addr;
745 ret = fts_ft8006m_write_ecc(client, start_addr, tmpbuf, app_len);
746 if (ret < 0 ) {
747 FTS_ERROR("app buffer write fail");
748 goto APP_UPG_ERR;
749 }
750
751 if (fts_ft8006m_check_ide(buf, len)) {
752 FTS_INFO("erase and write param configure area");
753 ret = fts_ft8006m_param_flash(client, buf, len);
754 if (ret < 0 ) {
755 FTS_ERROR("param upgrade(erase/write/ecc) fail");
756 goto APP_UPG_ERR;
757 }
758 }
759
760 FTS_INFO("upgrade success, reset to normal boot");
761 ret = fts_fwupg_reset_in_boot(client);
762 if (ret < 0) {
763 FTS_ERROR("reset to normal boot fail");
764 }
765 msleep(400);
766 return 0;
767
768 APP_UPG_ERR:
769 return ret;
770 }
771
772 /************************************************************************
773 * Name: fts_ft8006m_lic_upgrade
774 * Brief:
775 * Input: buf - all.bin
776 * len - len of all.bin
777 * Output:
778 * Return: return 0 if success, otherwise return error code
779 ***********************************************************************/
fts_ft8006m_lic_upgrade(struct i2c_client * client,u8 * buf,u32 len)780 static int fts_ft8006m_lic_upgrade(struct i2c_client *client, u8 *buf, u32 len)
781 {
782 int ret = 0;
783 u8 *tmpbuf = NULL;
784 u8 cmd[2] = { 0 };
785 u32 delay = 0;
786 u32 start_addr = 0;
787 u32 lic_len = 0;
788 u8 val = 0;
789 bool flag = false;
790
791 FTS_INFO("LCD initial code upgrade...");
792 if (NULL == buf) {
793 FTS_ERROR("fw file buffer is null");
794 return -EINVAL;
795 }
796
797 if ((len < FTS_MIN_LEN) || (len > FTS_MAX_LEN_FILE)) {
798 FTS_ERROR("fw file buffer len(%x) fail", len);
799 return -EINVAL;
800 }
801
802 ret = check_initial_code_valid(client, buf);
803 if (ret < 0) {
804 FTS_ERROR("initial code invalid, not upgrade lcd init code");
805 return -EINVAL;
806 }
807
808 ret = fts_i2c_read_reg(client, LIC_REG_2, &val);
809 FTS_DEBUG("lic flag:%x", val);
810 if ((ret > 0) && (1 == val))
811 flag = true;
812
813 lic_len = FTS_MAX_LEN_SECTOR;
814 /* remalloc memory for initcode, need change content of initcode afterwise */
815 tmpbuf = kzalloc(lic_len, GFP_KERNEL);
816 if (NULL == tmpbuf) {
817 FTS_INFO("initial code buf malloc fail");
818 return -EINVAL;
819 }
820 start_addr = upgrade_func_ft8006m.licoff;
821 memcpy(tmpbuf, buf + start_addr, lic_len);
822
823 /* enter into upgrade environment */
824 ret = fts_fwupg_enter_into_boot(client);
825 if (ret < 0) {
826 FTS_ERROR("enter into pramboot/bootloader fail,ret=%d", ret);
827 goto LIC_UPG_ERR;
828 }
829
830 /* 3-gamma remap */
831 ret = read_replace_3gamma(client, tmpbuf, flag);
832 if (ret < 0) {
833 FTS_ERROR("replace 3-gamma fail, not upgrade lcd init code");
834 goto LIC_UPG_ERR;
835 }
836
837 /* erase gesture & parameter sector */
838 cmd[0] = FTS_CMD_FLASH_MODE;
839 cmd[1] = FLASH_MODE_LIC_VALUE;
840 ret = fts_i2c_write(client, cmd, 2);
841 if (ret < 0) {
842 FTS_ERROR("upgrade mode(09) cmd write fail");
843 goto LIC_UPG_ERR;
844 }
845
846 delay = FTS_ERASE_SECTOR_DELAY * 1;
847 ret = fts_fwupg_erase(client, delay);
848 if (ret < 0) {
849 FTS_ERROR("erase cmd write fail");
850 goto LIC_UPG_ERR;
851 }
852
853 ret = fts_ft8006m_write_ecc(client, start_addr, tmpbuf, lic_len);
854 if (ret < 0 ) {
855 FTS_ERROR("LCD initial code write fail");
856 goto LIC_UPG_ERR;
857 }
858
859 FTS_INFO("upgrade success, reset to normal boot");
860 ret = fts_fwupg_reset_in_boot(client);
861 if (ret < 0) {
862 FTS_ERROR("reset to normal boot fail");
863 }
864
865 if (tmpbuf) {
866 kfree(tmpbuf);
867 tmpbuf = NULL;
868 }
869
870 msleep(400);
871 return 0;
872
873 LIC_UPG_ERR:
874 if (tmpbuf) {
875 kfree(tmpbuf);
876 tmpbuf = NULL;
877 }
878 return ret;
879 }
880
881 /************************************************************************
882 * Name: fts_ft8006m_param_upgrade
883 * Brief:
884 * Input: buf - all.bin
885 * len - len of all.bin
886 * Output:
887 * Return: return 0 if success, otherwise return error code
888 ***********************************************************************/
fts_ft8006m_param_upgrade(struct i2c_client * client,u8 * buf,u32 len)889 static int fts_ft8006m_param_upgrade(struct i2c_client *client, u8 *buf, u32 len)
890 {
891 int ret = 0;
892
893 FTS_INFO("parameter configure upgrade...");
894 if (NULL == buf) {
895 FTS_ERROR("fw file buffer is null");
896 return -EINVAL;
897 }
898
899 if ((len < FTS_MIN_LEN) || (len > FTS_MAX_LEN_FILE)) {
900 FTS_ERROR("fw file buffer len(%x) fail", len);
901 return -EINVAL;
902 }
903
904 /* enter into upgrade environment */
905 ret = fts_fwupg_enter_into_boot(client);
906 if (ret < 0) {
907 FTS_ERROR("enter into pramboot/bootloader fail,ret=%d", ret);
908 goto PARAM_UPG_ERR;
909 }
910
911 ret = fts_ft8006m_param_flash(client, buf, len);
912 if (ret < 0 ) {
913 FTS_ERROR("param upgrade(erase/write/ecc) fail");
914 goto PARAM_UPG_ERR;
915 }
916
917 FTS_INFO("upgrade success, reset to normal boot");
918 ret = fts_fwupg_reset_in_boot(client);
919 if (ret < 0) {
920 FTS_ERROR("reset to normal boot fail");
921 }
922
923 msleep(400);
924 return 0;
925
926 PARAM_UPG_ERR:
927 return ret;
928 }
929
930 /************************************************************************
931 * Name: fts_ft8006m_force_upgrade
932 * Brief:
933 * Input: buf - all.bin
934 * len - constant:128 * 1024
935 * Output:
936 * Return: return 0 if success, otherwise return error code
937 ***********************************************************************/
fts_ft8006m_force_upgrade(struct i2c_client * client,u8 * buf,u32 len)938 static int fts_ft8006m_force_upgrade(struct i2c_client *client, u8 *buf, u32 len)
939 {
940 int ret = 0;
941 u8 *tmpbuf = NULL;
942 u8 cmd[2] = { 0 };
943 u32 delay = 0;
944 u32 start_addr = 0;
945 u32 tmplen = 0;
946
947 FTS_INFO("fw force upgrade...");
948 if (NULL == buf) {
949 FTS_ERROR("fw file buffer is null");
950 return -EINVAL;
951 }
952
953 if ((len < FTS_MIN_LEN) || (len > FTS_MAX_LEN_FILE)) {
954 FTS_ERROR("fw file buffer len(%x) fail", len);
955 return -EINVAL;
956 }
957
958 /* enter into upgrade environment */
959 ret = fts_fwupg_enter_into_boot(client);
960 if (ret < 0) {
961 FTS_ERROR("enter into pramboot/bootloader fail,ret=%d", ret);
962 goto FORCE_UPG_ERR;
963 }
964
965 /* erase 0k~116k flash */
966 cmd[0] = FTS_CMD_FLASH_MODE;
967 cmd[1] = FLASH_MODE_WRITE_FLASH_VALUE;
968 ret = fts_i2c_write(client, cmd, 2);
969 if (ret < 0) {
970 FTS_ERROR("upgrade mode(09) cmd write fail");
971 goto FORCE_UPG_ERR;
972 }
973
974 if (len > (116 * 1024)) {
975 tmplen = 116 * 1024;
976 } else {
977 tmplen = len;
978 }
979 delay = FTS_ERASE_SECTOR_DELAY * (tmplen / FTS_MAX_LEN_SECTOR);
980 ret = fts_fwupg_erase(client, delay);
981 if (ret < 0) {
982 FTS_ERROR("erase cmd write fail");
983 goto FORCE_UPG_ERR;
984 }
985
986 /* write flash */
987 start_addr = 0;
988 tmpbuf = buf + start_addr;
989 ret = fts_ft8006m_write_ecc(client, start_addr, tmpbuf, tmplen);
990 if (ret < 0 ) {
991 FTS_ERROR("app buffer write fail");
992 goto FORCE_UPG_ERR;
993 }
994
995 if (fts_ft8006m_check_ide(buf, len)) {
996 FTS_INFO("erase and write param configure area");
997 ret = fts_ft8006m_param_flash(client, buf, len);
998 if (ret < 0 ) {
999 FTS_ERROR("param upgrade(erase/write/ecc) fail");
1000 goto FORCE_UPG_ERR;
1001 }
1002 }
1003
1004 FTS_INFO("upgrade success, reset to normal boot");
1005 FORCE_UPG_ERR:
1006 ret = fts_fwupg_reset_in_boot(client);
1007 if (ret < 0) {
1008 FTS_ERROR("reset to normal boot fail");
1009 }
1010
1011 msleep(400);
1012 return ret;
1013 }
1014
1015 struct upgrade_func upgrade_func_ft8006m = {
1016 .ctype = {0x07, 0x10},
1017 .fwveroff = 0x510E,
1018 .fwcfgoff = 0x0F80,
1019 .appoff = 0x5000,
1020 .licoff = 0x0000,
1021 .paramcfgoff = 0x1F000,
1022 .paramcfgveroff = 0x1F004,
1023 .paramcfg2off = 0x4000,
1024 .pramboot_supported = true,
1025 .pramboot = pb_file_ft8006m,
1026 .pb_length = sizeof(pb_file_ft8006m),
1027 .hid_supported = false,
1028 .upgrade = fts_ft8006m_upgrade,
1029 .get_hlic_ver = fts_ft8006m_get_hlic_ver,
1030 .lic_upgrade = fts_ft8006m_lic_upgrade,
1031 .param_upgrade = fts_ft8006m_param_upgrade,
1032 .force_upgrade = fts_ft8006m_force_upgrade,
1033 };
1034