xref: /OK3568_Linux_fs/kernel/drivers/input/touchscreen/focaltech_touch/focaltech_upgrade_ft8201.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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