tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / input / touchscreen / ist30xxa / ist30xx_update.c
1 /*
2  *  Copyright (C) 2010,Imagis Technology Co. Ltd. All Rights Reserved.
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  */
15
16 #include <linux/i2c.h>
17 #include <linux/delay.h>
18 #include <linux/slab.h>
19 #include <linux/firmware.h>
20 #include <linux/stat.h>
21 #include <asm/unaligned.h>
22 #include <linux/uaccess.h>
23 #include <linux/fcntl.h>
24 #include <linux/file.h>
25 #include <linux/fs.h>
26 #include <linux/err.h>
27
28 #include "ist30xx.h"
29 #include "ist30xx_update.h"
30 #include "ist30xx_tracking.h"
31
32 #if IST30XX_DEBUG
33 #include "ist30xx_misc.h"
34 #endif
35
36 #if IST30XX_INTERNAL_BIN
37 #include "./firmware/core_prime.h"
38 #if IST30XX_MULTIPLE_TSP
39 //#include "./firmware/core_prime.h"
40 #endif
41 #endif  // IST30XX_INTERNAL_BIN
42
43 struct ist30xx_tags *ts_tags;
44
45 u32 ist30xx_fw_ver = 0;
46 u32 ist30xx_param_ver = 0;
47 u32 ist30xx_sub_ver = 0;
48
49 extern struct ist30xx_data *ts_data;
50
51 extern void ist30xx_disable_irq(struct ist30xx_data *data);
52 extern void ist30xx_enable_irq(struct ist30xx_data *data);
53
54 int ist30xx_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
55                          int msg_num, u8 *cmd_buf)
56 {
57         int ret = 0;
58         int idx = msg_num - 1;
59         int size = msgs[idx].len;
60         u8 *msg_buf = NULL;
61         u8 *pbuf = NULL;
62         int trans_size, max_size = 0;
63
64         if (msg_num == WRITE_CMD_MSG_LEN)
65                 max_size = I2C_MAX_WRITE_SIZE;
66         else if (msg_num == READ_CMD_MSG_LEN)
67                 max_size = I2C_MAX_READ_SIZE;
68
69         if (unlikely(max_size == 0)) {
70                 tsp_err("%s() : transaction size(%d)\n", __func__, max_size);
71                 return -EINVAL;
72         }
73
74         if (msg_num == WRITE_CMD_MSG_LEN) {
75                 msg_buf = kmalloc(max_size + IST30XX_ADDR_LEN, GFP_KERNEL);
76                 if (!msg_buf)
77                         return -ENOMEM;
78                 memcpy(msg_buf, cmd_buf, IST30XX_ADDR_LEN);
79                 pbuf = msgs[idx].buf;
80         }
81
82         while (size > 0) {
83                 trans_size = (size >= max_size ? max_size : size);
84
85                 msgs[idx].len = trans_size;
86                 if (msg_num == WRITE_CMD_MSG_LEN) {
87                         memcpy(&msg_buf[IST30XX_ADDR_LEN], pbuf, trans_size);
88                         msgs[idx].buf = msg_buf;
89                         msgs[idx].len += IST30XX_ADDR_LEN;
90                 }
91                 ret = i2c_transfer(adap, msgs, msg_num);
92                 if (unlikely(ret != msg_num)) {
93                         tsp_err("%s() : i2c_transfer failed(%d), num=%d\n",
94                                 __func__, ret, msg_num);
95                         break;
96                 }
97
98                 if (msg_num == WRITE_CMD_MSG_LEN)
99                         pbuf += trans_size;
100                 else
101                         msgs[idx].buf += trans_size;
102
103                 size -= trans_size;
104         }
105
106         if (msg_num == WRITE_CMD_MSG_LEN)
107                 kfree(msg_buf);
108
109         return ret;
110 }
111
112 int ist30xx_read_buf(struct i2c_client *client, u32 cmd, u32 *buf, u16 len)
113 {
114         int ret, i;
115         u32 le_reg = cpu_to_be32(cmd);
116
117         struct i2c_msg msg[READ_CMD_MSG_LEN] = {
118                 {
119                         .addr = client->addr,
120                         .flags = 0,
121                         .len = IST30XX_ADDR_LEN,
122                         .buf = (u8 *)&le_reg,
123                 },
124                 {
125                         .addr = client->addr,
126                         .flags = I2C_M_RD,
127                         .len = len * IST30XX_DATA_LEN,
128                         .buf = (u8 *)buf,
129                 },
130         };
131
132         ret = ist30xx_i2c_transfer(client->adapter, msg, READ_CMD_MSG_LEN, NULL);
133         if (unlikely(ret != READ_CMD_MSG_LEN))
134                 return -EIO;
135
136         for (i = 0; i < len; i++)
137                 buf[i] = cpu_to_be32(buf[i]);
138
139         return 0;
140 }
141
142 int ist30xx_write_buf(struct i2c_client *client, u32 cmd, u32 *buf, u16 len)
143 {
144         int i;
145         int ret;
146         struct i2c_msg msg;
147         u8 cmd_buf[IST30XX_ADDR_LEN];
148         u8 msg_buf[IST30XX_DATA_LEN * (len + 1)];
149
150         put_unaligned_be32(cmd, cmd_buf);
151
152         if (likely(len > 0)) {
153                 for (i = 0; i < len; i++)
154                         put_unaligned_be32(buf[i], msg_buf + (i * IST30XX_DATA_LEN));
155         } else {
156                 /* then add dummy data(4byte) */
157                 put_unaligned_be32(0, msg_buf);
158                 len = 1;
159         }
160
161         msg.addr = client->addr;
162         msg.flags = 0;
163         msg.len = IST30XX_DATA_LEN * len;
164         msg.buf = msg_buf;
165
166         ret = ist30xx_i2c_transfer(client->adapter, &msg, WRITE_CMD_MSG_LEN,
167                                    cmd_buf);
168         if (unlikely(ret != WRITE_CMD_MSG_LEN))
169                 return -EIO;
170
171         return 0;
172 }
173
174 int ist30xxb_burst_read(struct i2c_client *client, u32 addr,
175                         u32 *buf32, int len)
176 {
177         int ret = 0;
178         int i;
179         int max_len = I2C_MAX_READ_SIZE / IST30XX_DATA_LEN;
180
181         addr |= IST30XXB_BURST_ACCESS;
182
183         for (i = 0; i < len; i += max_len) {
184                 if (len < max_len) max_len = len;
185
186                 ret = ist30xx_read_buf(client, addr, buf32, max_len);
187                 if (unlikely(ret)) {
188                         tsp_err("Burst fail, addr: %x\n", __func__, addr);
189                         return ret;
190                 }
191
192                 addr += max_len * IST30XX_DATA_LEN;
193                 buf32 += max_len;
194         }
195
196         return 0;
197 }
198
199 #define IST30XXB_ISP_READ       (1)
200 #define IST30XXB_ISP_WRITE      (2)
201 #define IST30XXB_ISP_ERASE_ALL  (3)
202 #define IST30XXB_ISP_ERASE_PAGE (4)
203
204 int ist30xxb_isp_reset(void)
205 {
206         int ret = 0;
207
208 #if (IMAGIS_TSP_IC == IMAGIS_IST3038)
209         ret = ist30xx_write_cmd(ts_data->client, IST30XXB_REG_EEPMODE, 0x180);
210         if (unlikely(ret))
211                 return ret;
212 #else
213         ret = ist30xx_write_cmd(ts_data->client, IST30XXB_REG_EEPPWRCTRL, 0xB200);
214         if (unlikely(ret))
215                 return ret;
216
217         ret = ist30xx_write_cmd(ts_data->client, IST30XXB_REG_EEPPWRCTRL, 0x9200);
218         if (unlikely(ret))
219                 return ret;
220 #endif
221         msleep(1);
222
223         return ret;
224 }
225
226 int ist30xxb_isp_enable(bool enable)
227 {
228         int ret = 0;
229
230         if (enable) {
231                 ret = ist30xx_write_cmd(ts_data->client, IST30XXB_REG_EEPISPEN, 0x1);
232                 if (unlikely(ret))
233                         return ret;
234
235                 ret = ist30xx_write_cmd(ts_data->client, IST30XXB_REG_LDOOSC, 0x74C8);
236                 if (unlikely(ret))
237                         return ret;
238
239                 ret = ist30xx_write_cmd(ts_data->client, IST30XXB_REG_CLKDIV, 0x3);
240                 if (unlikely(ret))
241                         return ret;
242
243 #if (IMAGIS_TSP_IC != IMAGIS_IST3038)
244                 ret = ist30xx_write_cmd(ts_data->client,
245                                         IST30XXB_REG_PADCTRL, 0x03300000);
246                 if (unlikely(ret))
247                         return ret;
248 #endif
249
250                 msleep(10);
251
252                 ret = ist30xx_write_cmd(ts_data->client, IST30XXB_REG_WDTCON, 0x0);
253                 if (unlikely(ret))
254                         return ret;
255         } else {
256                 ret = ist30xx_write_cmd(ts_data->client, IST30XXB_REG_EEPISPEN, 0x0);
257                 if (unlikely(ret))
258                         return ret;
259
260                 msleep(1);
261         }
262
263         return 0;
264 }
265
266 int ist30xxb_isp_mode(int mode)
267 {
268         int ret = 0;
269         u32 val = 0;
270
271         switch (mode) {
272         case IST30XXB_ISP_READ:
273                 val = 0x1C0;
274                 break;
275         case IST30XXB_ISP_WRITE:
276                 val = 0x1A8;
277                 break;
278         case IST30XXB_ISP_ERASE_ALL:
279                 val = 0x1A7;
280                 break;
281         case IST30XXB_ISP_ERASE_PAGE:
282                 val = 0x1A3;
283                 break;
284         default:
285                 tsp_err("ISP fail, unknown mode\n");
286                 return -EINVAL;
287         }
288
289         ret = ist30xx_write_cmd(ts_data->client, IST30XXB_REG_EEPMODE, val);
290         if (unlikely(ret)) {
291                 tsp_err("ISP fail, IST30XXB_REG_EEPMODE\n");
292                 return ret;
293         }
294
295         return 0;
296 }
297
298 int ist30xxb_isp_erase(struct i2c_client *client, int mode, u32 addr)
299 {
300         int ret = 0;
301         u32 val = 0x1A0;
302         u8 buf[EEPROM_PAGE_SIZE] = { 0, };
303
304         ret = ist30xxb_isp_mode(mode);
305         if (unlikely(ret))
306                 return ret;
307
308         ret = ist30xx_write_cmd(client, IST30XXB_REG_EEPADDR, addr);
309         if (unlikely(ret)) {
310                 tsp_err("ISP fail, IST30XXB_REG_EEPADDR\n");
311                 return ret;
312         }
313
314         val = (EEPROM_PAGE_SIZE / IST30XX_DATA_LEN);
315         ret = ist30xx_write_buf(client, IST30XXB_REG_EEPWDAT, (u32 *)buf, val);
316         if (unlikely(ret)) {
317                 tsp_err("ISP fail, IST30XXB_REG_EEPWDAT\n");
318                 return ret;
319         }
320
321         msleep(30);
322
323         ist30xxb_isp_reset();
324
325         return 0;
326 }
327
328 int ist30xxb_isp_write(struct i2c_client *client, u32 addr,
329                        const u32 *buf32, int len)
330 {
331         int ret = 0;
332
333         ret = ist30xx_write_cmd(client, IST30XXB_REG_EEPADDR, addr);
334         if (unlikely(ret)) {
335                 tsp_err("ISP fail, IST30XXB_REG_EEPADDR\n");
336                 return ret;
337         }
338
339         ret = ist30xx_write_buf(client, IST30XXB_REG_EEPWDAT, (u32 *)buf32, len);
340         if (unlikely(ret)) {
341                 tsp_err("ISP fail, IST30XXB_REG_EEPWDAT\n");
342                 return ret;
343         }
344
345         return 0;
346 }
347
348 int ist30xxb_isp_read(struct i2c_client *client, u32 addr,
349                       u32 *buf32, int len)
350 {
351         int ret = 0;
352         int i;
353         int max_len = I2C_MAX_READ_SIZE / IST30XX_DATA_LEN;
354
355         for (i = 0; i < len; i += max_len) {
356                 if (len < max_len) max_len = len;
357
358                 /* IST30xxB ISP read mode */
359                 ret = ist30xxb_isp_mode(IST30XXB_ISP_READ);
360                 if (unlikely(ret))
361                         return ret;
362
363                 ret = ist30xx_write_cmd(client, IST30XXB_REG_EEPADDR, addr);
364                 if (unlikely(ret)) {
365                         tsp_err("ISP fail, IST30XXB_REG_EEPADDR\n");
366                         return ret;
367                 }
368
369                 ret = ist30xx_read_buf(client, IST30XXB_REG_EEPRDAT, buf32, max_len);
370                 if (unlikely(ret)) {
371                         tsp_err("ISP fail, IST30XXB_REG_EEPWDAT\n");
372                         return ret;
373                 }
374
375                 addr += max_len * IST30XX_DATA_LEN;
376                 buf32 += max_len;
377         }
378
379         return 0;
380 }
381
382 int ist30xxb_cmd_read_chksum(struct i2c_client *client,
383                              u32 start_addr, u32 end_addr, u32 *chksum)
384 {
385         int ret = 0;
386         u32 val = (1 << 31); // Chkecksum enable
387
388         val |= start_addr;
389         val |= (end_addr / IST30XX_DATA_LEN - 1) << 16;
390
391         ret = ist30xx_write_cmd(client, IST30XXB_REG_CHKSMOD, val);
392         if (unlikely(ret)) {
393                 tsp_err("ISP fail, IST30XXB_REG_CHKSMOD (%x)\n", val);
394                 return ret;
395         }
396         msleep(10);
397
398         ret = ist30xx_read_cmd(client, IST30XXB_REG_CHKSDAT, chksum);
399         if (unlikely(ret)) {
400                 tsp_err("ISP fail, IST30XXB_REG_CHKSDAT (%x)\n", chksum);
401                 return ret;
402         }
403
404         return 0;
405 }
406
407 int ist30xxb_read_chksum(struct i2c_client *client, u32 *chksum)
408 {
409         int ret = 0;
410         u32 start_addr, end_addr;
411         u32 chksum1 = 0, chksum2 = 0;
412
413         start_addr = 0;
414         end_addr = ts_data->tags.fw_addr + ts_data->tags.fw_size;
415         ret = ist30xxb_cmd_read_chksum(client, start_addr, end_addr, &chksum1);
416         if (unlikely(ret))
417                 return ret;
418
419         start_addr = ts_data->tags.cfg_addr;
420         end_addr = ts_data->tags.sensor3_addr + ts_data->tags.sensor3_size;
421         ret = ist30xxb_cmd_read_chksum(client, start_addr, end_addr, &chksum2);
422         if (unlikely(ret))
423                 return ret;
424
425         *chksum = chksum1 | (chksum2 << 16);
426
427         tsp_info("chksum: %x(%x~%x, %x~%x)\n", *chksum,
428                  0, ts_data->tags.fw_addr + ts_data->tags.fw_size,
429                  start_addr, end_addr);
430
431         return 0;
432 }
433
434 int ist30xxb_read_chksum_all(struct i2c_client *client, u32 *chksum)
435 {
436         int ret = 0;
437         u32 start_addr, end_addr;
438
439         start_addr = 0;
440         end_addr = IST30XX_EEPROM_SIZE;
441         ret = ist30xxb_cmd_read_chksum(client, start_addr, end_addr, chksum);
442         if (unlikely(ret))
443                 return ret;
444
445         tsp_info("chksum: %x(%x~%x)\n", *chksum, start_addr, end_addr);
446
447         return 0;
448 }
449
450 int ist30xxb_isp_fw_read(struct i2c_client *client, u32 *buf32)
451 {
452         int ret = 0;
453         int i;
454
455         u16 addr = EEPROM_BASE_ADDR;
456         int len = EEPROM_PAGE_SIZE / IST30XX_DATA_LEN;
457
458         ist30xx_reset(true);
459
460         /* IST30xxB ISP enable */
461         ret = ist30xxb_isp_enable(true);
462         if (unlikely(ret))
463                 return ret;
464
465         for (i = 0; i < IST30XX_EEPROM_SIZE; i += EEPROM_PAGE_SIZE) {
466                 ret = ist30xxb_isp_read(client, addr, buf32, len);
467                 if (unlikely(ret))
468                         goto isp_fw_read_end;
469
470                 addr += EEPROM_PAGE_SIZE;
471                 buf32 += len;
472         }
473
474 isp_fw_read_end:
475         /* IST30xxB ISP disable */
476         ist30xxb_isp_enable(false);
477         return ret;
478 }
479
480 int ist30xxb_isp_fw_update(struct i2c_client *client, const u8 *buf,
481                            u32 *chksum)
482 {
483         int ret = 0;
484         int i;
485         u32 page_cnt = IST30XX_EEPROM_SIZE / EEPROM_PAGE_SIZE;
486         u16 addr = EEPROM_BASE_ADDR;
487         int len = EEPROM_PAGE_SIZE / IST30XX_DATA_LEN;
488
489         ist30xx_tracking(TRACK_CMD_FWUPDATE);
490
491         /* IST30xxB ISP enable */
492         ret = ist30xxb_isp_enable(true);
493         if (unlikely(ret))
494                 goto isp_fw_update_end;
495
496         /* IST30xxB ISP erase */
497         ret = ist30xxb_isp_erase(client, IST30XXB_ISP_ERASE_ALL, 0);
498         if (unlikely(ret))
499                 goto isp_fw_update_end;
500
501 #if (IMAGIS_TSP_IC == IMAGIS_IST3038)
502         /* IST30xxB ISP read all checksum */
503         ret = ist30xxb_read_chksum_all(client, chksum);
504         if (unlikely(ret))
505                 goto isp_fw_update_end;
506
507         /* IST30xxB compare checksum */
508         if (unlikely(*chksum != 0))
509                 goto isp_fw_update_end;
510 #endif
511
512         /* IST30xxB power reset */
513         ist30xx_reset(true);
514
515         /* IST30xxB ISP enable */
516         ret = ist30xxb_isp_enable(true);
517         if (unlikely(ret))
518                 goto isp_fw_update_end;
519
520         for (i = 0; i < page_cnt; i++) {
521                 /* IST30xxB ISP write mode */
522                 ret = ist30xxb_isp_mode(IST30XXB_ISP_WRITE);
523                 if (unlikely(ret))
524                         goto isp_fw_update_end;
525
526                 ret = ist30xxb_isp_write(client, addr, (u32 *)buf, len);
527                 if (unlikely(ret))
528                         goto isp_fw_update_end;
529
530                 addr += EEPROM_PAGE_SIZE;
531                 buf += EEPROM_PAGE_SIZE;
532
533                 msleep(5);
534
535                 ist30xxb_isp_reset();
536         }
537
538 #if (IMAGIS_TSP_IC == IMAGIS_IST3038)
539         ist30xxb_read_chksum_all(client, chksum);
540 #endif
541
542 isp_fw_update_end:
543         /* IST30xxB ISP disable */
544         ist30xxb_isp_enable(false);
545         return ret;
546 }
547
548 int ist30xx_fw_write(struct i2c_client *client, const u8 *buf)
549 {
550         int ret;
551         int len;
552         u32 *buf32 = (u32 *)(buf + ts_data->fw.index);
553         u32 size = ts_data->fw.size;
554
555         if (unlikely((size <= 0) || (size > IST30XX_EEPROM_SIZE)))
556                 return -ENOEXEC;
557
558         while (size > 0) {
559                 len = (size >= EEPROM_PAGE_SIZE ? EEPROM_PAGE_SIZE : size);
560
561                 ret = ist30xx_write_buf(client, CMD_ENTER_FW_UPDATE, buf32, (len >> 2));
562                 if (unlikely(ret))
563                         return ret;
564
565                 buf32 += (len >> 2);
566                 size -= len;
567
568                 msleep(5);
569         }
570         return 0;
571 }
572
573
574 u32 ist30xx_parse_ver(int flag, const u8 *buf)
575 {
576         u32 ver = 0;
577         u32 *buf32 = (u32 *)buf;
578
579         if (flag == FLAG_FW)
580                 ver = (u32)buf32[(ts_data->tags.flag_addr + 60) >> 2];
581         else if (flag == FLAG_SUB)
582                 ver = (u32)buf32[(ts_data->tags.flag_addr + 52) >> 2];
583         else if (flag == FLAG_PARAM)
584                 ver = (u32)(buf32[(ts_data->tags.cfg_addr + 4) >> 2] & 0xFFFF);
585         else
586                 tsp_warn("Parsing ver's flag is not corrent!\n");
587
588         return ver;
589 }
590
591
592 int calib_ms_delay = WAIT_CALIB_CNT;
593 int ist30xx_calib_wait(void)
594 {
595         int cnt = calib_ms_delay;
596
597         ts_data->status.calib_msg = 0;
598         while (cnt-- > 0) {
599                 msleep(100);
600
601                 if (ts_data->status.calib_msg) {
602                         tsp_info("Calibration status : %d, Max raw gap : %d - (%08x)\n",
603                                  CALIB_TO_STATUS(ts_data->status.calib_msg),
604                                  CALIB_TO_GAP(ts_data->status.calib_msg),
605                                  ts_data->status.calib_msg);
606
607                         if (CALIB_TO_OS_VALUE(ts_data->status.calib_msg) == 0xFFFF)
608                                 return 1;
609                         else if (CALIB_TO_STATUS(ts_data->status.calib_msg) == 0)
610                                 return 0;  // Calibrate success
611                         else
612                                 return -EAGAIN;
613                 }
614         }
615         tsp_warn("Calibration time out\n");
616
617         return -EPERM;
618 }
619
620 int ist30xx_calibrate(int wait_cnt)
621 {
622         int ret = -ENOEXEC;
623
624         tsp_info("*** Calibrate %ds ***\n", calib_ms_delay / 10);
625
626         ts_data->status.update = 1;
627         while (wait_cnt--) {
628                 ist30xx_disable_irq(ts_data);
629                 ist30xx_reset(false);
630
631                 ret = ist30xx_cmd_calibrate(ts_data->client);
632                 if (unlikely(ret))
633                         continue;
634
635                 ist30xx_enable_irq(ts_data);
636                 ret = ist30xx_calib_wait();
637                 if (likely(!ret))
638                         break;
639         }
640
641         ist30xx_disable_irq(ts_data);
642
643         ist30xx_reset(false);
644
645         ts_data->status.update = 2;
646
647         ist30xx_enable_irq(ts_data);
648
649         return ret;
650 }
651
652
653 int ist30xx_parse_tags(struct ist30xx_data *data, const u8 *buf, const u32 size)
654 {
655         int ret = -EPERM;
656
657         ts_tags = (struct ist30xx_tags *)(&buf[size - sizeof(struct ist30xx_tags)]);
658
659         if (!strncmp(ts_tags->magic1, IST30XX_TAG_MAGIC, sizeof(ts_tags->magic1))
660             && !strncmp(ts_tags->magic2, IST30XX_TAG_MAGIC, sizeof(ts_tags->magic2))
661             ) {
662                 data->fw.index = ts_tags->fw_addr;
663                 data->fw.size = ts_tags->flag_addr - ts_tags->fw_addr +
664                                 ts_tags->flag_size;
665                 data->fw.chksum = ts_tags->chksum;
666                 data->tags = *ts_tags;
667
668                 ret = 0;
669         }
670
671         tsp_verb("Tagts magic1: %s, magic2: %s\n",
672                  ts_tags->magic1, ts_tags->magic2);
673         tsp_verb(" fw: %x(%x)\n", ts_tags->fw_addr, ts_tags->fw_size);
674         tsp_verb(" flag: %x(%x)\n", ts_tags->flag_addr, ts_tags->flag_size);
675         tsp_verb(" cfg: %x(%x)\n", ts_tags->cfg_addr, ts_tags->cfg_size);
676         tsp_verb(" sensor1: %x(%x)\n", ts_tags->sensor1_addr,
677                  ts_tags->sensor1_size);
678         tsp_verb(" sensor2: %x(%x)\n", ts_tags->sensor2_addr,
679                  ts_tags->sensor2_size);
680         tsp_verb(" sensor3: %x(%x)\n", ts_tags->sensor3_addr,
681                  ts_tags->sensor3_size);
682         tsp_verb(" chksum: %x\n", ts_tags->chksum);
683         tsp_verb(" build time : %04d/%02d/%02d (%02d:%02d:%02d)\n",
684                  ts_tags->year, ts_tags->month, ts_tags->day,
685                  ts_tags->hour, ts_tags->min, ts_tags->sec);
686
687         return ret;
688 }
689
690 void ist30xx_get_update_info(struct ist30xx_data *data, const u8 *buf,
691                              const u32 size)
692 {
693         int ret;
694
695         ret = ist30xx_parse_tags(data, buf, size);
696         if (unlikely(ret != TAGS_PARSE_OK))
697                 tsp_warn("Cannot find tags of F/W, make a tags by 'tagts.exe'\n");
698 }
699
700 #if (IST30XX_DEBUG) && (IST30XX_INTERNAL_BIN)
701 extern TSP_INFO ist30xx_tsp_info;
702 extern TKEY_INFO ist30xx_tkey_info;
703 int ist30xx_get_tkey_info(struct ist30xx_data *data)
704 {
705         int ret = 0;
706         TSP_INFO *tsp = &ist30xx_tsp_info;
707         TKEY_INFO *tkey = &ist30xx_tkey_info;
708         u8 *cfg_buf;
709
710         cfg_buf = (u8 *)&data->fw.buf[data->tags.cfg_addr];
711
712         tkey->enable = (bool)(cfg_buf[0x321] & 1);
713         tkey->axis_rx = (bool)((cfg_buf[0x321] >> 1) & 1);
714         tkey->key_num = (u8)cfg_buf[0x322];
715     tkey->baseline = (u16)((cfg_buf[0x324] << 8) | cfg_buf[0x323]);
716         tkey->ch_num[0] = (u8)cfg_buf[0x326];
717         tkey->ch_num[1] = (u8)cfg_buf[0x327];
718         tkey->ch_num[2] = (u8)cfg_buf[0x328];
719         tkey->ch_num[3] = (u8)cfg_buf[0x329];
720         tkey->ch_num[4] = (u8)cfg_buf[0x32A];
721
722         if (tkey->axis_rx) {
723                 if (tsp->dir.swap_xy)
724                         tsp->height -= 1;
725                 else
726                         tsp->width -= 1;
727         } else {
728                 if (tsp->dir.swap_xy)
729                         tsp->width -= 1;
730                 else
731                         tsp->height -= 1;
732         }
733
734         return ret;
735 }
736
737 #define TSP_INFO_SWAP_XY    (1 << 0)
738 #define TSP_INFO_FLIP_X     (1 << 1)
739 #define TSP_INFO_FLIP_Y     (1 << 2)
740 int ist30xx_get_tsp_info(struct ist30xx_data *data)
741 {
742         int ret = 0;
743         TSP_INFO *tsp = &ist30xx_tsp_info;
744         u8 *cfg_buf, *sensor_buf;
745
746         cfg_buf = (u8 *)&data->fw.buf[data->tags.cfg_addr];
747         sensor_buf = (u8 *)&data->fw.buf[data->tags.sensor1_addr];
748
749         tsp->finger_num = (u8)cfg_buf[0x304];
750         tsp->dir.swap_xy = (bool)(cfg_buf[0x305] & TSP_INFO_SWAP_XY ? true : false);
751         tsp->dir.flip_x = (bool)(cfg_buf[0x305] & TSP_INFO_FLIP_X ? true : false);
752         tsp->dir.flip_y = (bool)(cfg_buf[0x305] & TSP_INFO_FLIP_Y ? true : false);
753     tsp->baseline = (u16)((cfg_buf[0x319] << 8) | cfg_buf[0x318]);
754
755         tsp->ch_num.tx = (u8)sensor_buf[0x40];
756         tsp->ch_num.rx = (u8)sensor_buf[0x41];
757
758         tsp->node.len = tsp->ch_num.tx * tsp->ch_num.rx;
759         tsp->height = (tsp->dir.swap_xy ? tsp->ch_num.rx : tsp->ch_num.tx);
760         tsp->width = (tsp->dir.swap_xy ? tsp->ch_num.tx : tsp->ch_num.rx);
761
762         return ret;
763 }
764 #endif // (IST30XX_DEBUG) && (IST30XX_INTERNAL_BIN)
765
766
767 #define update_next_step(ret)   { if (unlikely(ret)) goto end; }
768 int ist30xx_fw_update(struct i2c_client *client, const u8 *buf, int size,
769                       bool mode)
770 {
771         int ret = 0;
772         u32 chksum = 0;
773         struct ist30xx_fw *fw = &ts_data->fw;
774
775         tsp_info("*** Firmware update ***\n");
776         tsp_info(" core: %x, param: %x, sub: %x (addr: 0x%x ~ 0x%x)\n",
777                  ist30xx_fw_ver, ist30xx_param_ver, ist30xx_sub_ver,
778                  fw->index, (fw->index + fw->size));
779
780         ts_data->status.update = 1;
781
782         ist30xx_disable_irq(ts_data);
783
784         ist30xx_reset(true);
785
786         if (mode) { /* ISP Mode */
787                 ret = ist30xxb_isp_fw_update(client, buf, &chksum);
788                 update_next_step(ret);
789         } else { /* I2C SW Mode */
790                 ret = ist30xx_cmd_update(client, CMD_ENTER_FW_UPDATE);
791                 update_next_step(ret);
792
793                 ret = ist30xx_fw_write(client, buf);
794                 update_next_step(ret);
795         }
796         msleep(50);
797
798         buf += IST30XX_EEPROM_SIZE;
799         size -= IST30XX_EEPROM_SIZE;
800
801         ist30xx_reset(false);
802
803         ret = ist30xx_read_cmd(client, CMD_GET_CHECKSUM, &chksum);
804         if (unlikely((ret) || (chksum != fw->chksum)))
805                 goto end;
806
807         ret = ist30xx_get_ver_info(ts_data);
808         update_next_step(ret);
809
810 end:
811         if (unlikely(ret)) {
812                 tsp_warn("Firmware update Fail!, ret=%d\n", ret);
813         } else if (unlikely(chksum != fw->chksum)) {
814                 tsp_warn("Error CheckSum: %x(%x)\n", chksum, fw->chksum);
815                 ret = -ENOEXEC;
816         }
817
818         ist30xx_enable_irq(ts_data);
819
820         ts_data->status.update = 2;
821
822         return ret;
823 }
824
825 int ist30xx_fw_recovery(struct ist30xx_data *data)
826 {
827         int ret = -EPERM;
828         u8 *fw = data->fw.buf;
829         int fw_size = data->fw.buf_size;
830
831         ist30xx_get_update_info(data, fw, fw_size);
832         ist30xx_fw_ver = ist30xx_parse_ver(FLAG_FW, fw);
833         ist30xx_param_ver = ist30xx_parse_ver(FLAG_PARAM, fw);
834         ist30xx_sub_ver = ist30xx_parse_ver(FLAG_SUB, fw);
835
836         mutex_lock(&ist30xx_mutex);
837         ret = ist30xx_fw_update(data->client, fw, fw_size, true);
838         ist30xx_calibrate(1);
839         mutex_unlock(&ist30xx_mutex);
840
841         ist30xx_start(data);
842
843         return ret;
844 }
845
846 #if IST30XX_INTERNAL_BIN
847 int ist30xx_check_fw(struct ist30xx_data *data, const u8 *buf)
848 {
849         int ret;
850         u32 chksum;
851
852         ret = ist30xx_read_cmd(data->client, CMD_GET_CHECKSUM, &chksum);
853         if (unlikely(ret))
854                 return ret;
855
856         if (unlikely(chksum != data->fw.chksum)) {
857                 tsp_warn("Checksum compare error, (IC: %08x, Bin: %08x)\n",
858                          chksum, data->fw.chksum);
859                 return -EPERM;
860         }
861
862         return 0;
863 }
864
865 bool ist30xx_check_valid_vendor(u32 tsp_vendor)
866 {
867         switch (tsp_vendor) {
868         case TSP_TYPE_ALPS:
869         case TSP_TYPE_EELY:
870         case TSP_TYPE_TOP:
871         case TSP_TYPE_MELFAS:
872         case TSP_TYPE_ILJIN:
873         case TSP_TYPE_SYNOPEX:
874         case TSP_TYPE_SMAC:
875         case TSP_TYPE_TAEYANG:
876         case TSP_TYPE_TOVIS:
877         case TSP_TYPE_ELK:
878         case TSP_TYPE_OTHERS:
879                 return true;
880         default:
881                 return false;
882         }
883
884         return false;
885 }
886
887 #if IST30XX_MULTIPLE_TSP
888 void ist30xx_set_tsp_fw(struct ist30xx_data *data)
889 {
890         char *str;
891         struct ist30xx_fw *fw = &data->fw;
892
893         switch (data->tsp_type) {
894         case TSP_TYPE_ALPS:
895         case TSP_TYPE_ILJIN:
896                 str = "ALPS/ILJIN";
897                 fw->buf = (u8 *)ist30xxb_fw;
898                 fw->buf_size = sizeof(ist30xxb_fw);
899                 break;
900         case TSP_TYPE_EELY:
901                 str = "EELY";
902                 fw->buf = (u8 *)ist30xxb_fw2;
903                 fw->buf_size = sizeof(ist30xxb_fw2);
904                 break;
905
906         case TSP_TYPE_UNKNOWN:
907         default:
908                 str = "Unknown";
909                 tsp_warn("Unknown TSP vendor(0x%x)\n", data->tsp_type);
910                 break;
911         }
912         tsp_info("TSP vendor : %s(%x)\n", str, data->tsp_type);
913
914         ist30xx_get_update_info(ts_data, fw->buf, fw->buf_size);
915         ist30xx_fw_ver = ist30xx_parse_ver(FLAG_FW, fw->buf);
916         ist30xx_param_ver = ist30xx_parse_ver(FLAG_PARAM, fw->buf);
917         ist30xx_sub_ver = ist30xx_parse_ver(FLAG_SUB, fw->buf);
918 }
919 #endif  // IST30XX_MULTIPLE_TSP
920
921 int ist30xx_check_auto_update(struct ist30xx_data *data)
922 {
923         int ret = 0;
924         int retry = IST30XX_FW_UPDATE_RETRY;
925         u32 tsp_type = TSP_TYPE_UNKNOWN;
926         u32 chksum;
927         bool tsp_check = false;
928         struct ist30xx_fw *fw = &data->fw;
929
930         while (retry--) {
931                 ret = ist30xx_read_cmd(data->client,
932                                        CMD_GET_TSP_PANNEL_TYPE, &tsp_type);
933                 if (likely(ret == 0)) {
934                         if (likely(ist30xx_check_valid_vendor(tsp_type) == true))
935                                 tsp_check = true;
936                         break;
937                 }
938         }
939
940         retry = IST30XX_FW_UPDATE_RETRY;
941
942         if (unlikely(!tsp_check))
943                 goto fw_check_end;
944
945         ist30xx_get_ver_info(data);
946
947         if (likely((fw->param_ver > 0) && (fw->param_ver < 0xFFFFFFFF))) {
948                 if (unlikely(((fw->core_ver & MASK_FW_VER) != IST30XX_FW_VER3) &&
949                              ((fw->core_ver & MASK_FW_VER) != IST30XX_FW_VER4) &&
950                              ((fw->core_ver & MASK_FW_VER) != IST30XX_FW_VER5)))
951                         goto fw_check_end;
952
953                 tsp_info("Version compare IC: %x(%x), BIN: %x(%x)\n",
954                          fw->param_ver, fw->core_ver, ist30xx_param_ver, ist30xx_fw_ver);
955
956                 /* If FW version is same, check FW checksum */
957                 if (likely((fw->core_ver == ist30xx_fw_ver) &&
958                            (fw->param_ver == ist30xx_param_ver) &&
959                            (fw->sub_ver == 0))) {
960                         ret = ist30xx_read_cmd(data->client, CMD_GET_CHECKSUM, &chksum);
961                         if (unlikely((ret) || (chksum != fw->chksum))) {
962                                 tsp_warn("Checksum error, IC: %x, Bin: %x (ret: %d)\n",
963                                          chksum, fw->chksum, ret);
964                                 goto fw_check_end;
965                         }
966                 }
967
968                 /*
969                  *  fw->core_ver : FW core version in TSP IC
970                  *  fw->param_ver : FW version if TSP IC
971                  *  ist30xx_fw_ver : FW core version in FW Binary
972                  *  ist30xx_fw_ver : FW version in FW Binary
973                  */
974                 /* If the ver of binary is higher than ver of IC, FW update operate. */
975
976                 if (likely((fw->core_ver >= ist30xx_fw_ver) &&
977                            (fw->param_ver >= ist30xx_param_ver)))
978                         return 0;
979         }
980
981 fw_check_end:
982         return -EAGAIN;
983 }
984
985 int ist30xx_auto_bin_update(struct ist30xx_data *data)
986 {
987         int ret = 0;
988         int retry = IST30XX_FW_UPDATE_RETRY;
989         struct ist30xx_fw *fw = &data->fw;
990
991         fw->buf = (u8 *)ist30xxb_fw;
992         fw->buf_size = sizeof(ist30xxb_fw);
993
994 #if IST30XX_MULTIPLE_TSP
995         ist30xx_set_tsp_fw(data);
996 #else
997         ist30xx_get_update_info(data, fw->buf, fw->buf_size);
998         ist30xx_fw_ver = ist30xx_parse_ver(FLAG_FW, fw->buf);
999         ist30xx_param_ver = ist30xx_parse_ver(FLAG_PARAM, fw->buf);
1000         ist30xx_sub_ver = ist30xx_parse_ver(FLAG_SUB, fw->buf);
1001 #endif
1002
1003         tsp_info("IC: %x, Binary ver core: %x, param: %x, sub: %x\n",
1004                  data->chip_id, ist30xx_fw_ver, ist30xx_param_ver, ist30xx_sub_ver);
1005     
1006         mutex_lock(&ist30xx_mutex);
1007         ret = ist30xx_check_auto_update(data);
1008         mutex_unlock(&ist30xx_mutex);
1009
1010         if (likely(ret >= 0))
1011                 return ret;
1012
1013 update_bin:   // TSP is not ready / FW update
1014         tsp_info("Update version. param(core): %x(%x, %x) -> %x(%x, %x)\n",
1015                  fw->param_ver, fw->core_ver, fw->sub_ver,
1016                  ist30xx_param_ver, ist30xx_fw_ver, ist30xx_sub_ver);
1017
1018         mutex_lock(&ist30xx_mutex);
1019         while (retry--) {
1020                 ret = ist30xx_fw_update(data->client, fw->buf, fw->buf_size, true);
1021                 if (unlikely(!ret))
1022                         break;
1023         }
1024         mutex_unlock(&ist30xx_mutex);
1025
1026         if (unlikely(ret))
1027                 return ret;
1028
1029         if (unlikely(retry > 0 && ist30xx_check_fw(data, fw->buf)))
1030                 goto update_bin;
1031
1032         ist30xx_calibrate(IST30XX_FW_UPDATE_RETRY);
1033
1034         return ret;
1035 }
1036 #endif // IST30XX_INTERNAL_BIN
1037
1038 #define MAX_FILE_PATH   255
1039 /* sysfs: /sys/class/touch/firmware/firmware */
1040 ssize_t ist30xx_fw_store(struct device *dev, struct device_attribute *attr,
1041                          const char *buf, size_t size)
1042 {
1043         int ret;
1044         int fw_size = 0;
1045         u8 *fw = NULL;
1046         const u8 *buff = 0;
1047         mm_segment_t old_fs = { 0 };
1048         struct file *fp = NULL;
1049         long fsize = 0, nread = 0;
1050         char fw_path[MAX_FILE_PATH];
1051         const struct firmware *request_fw = NULL;
1052         int mode = 0;
1053         int calib = 1;
1054
1055         sscanf(buf, "%d %d", &mode, &calib);
1056
1057         switch (mode) {
1058         case MASK_UPDATE_INTERNAL:
1059 #if IST30XX_INTERNAL_BIN
1060                 fw = ts_data->fw.buf;
1061                 fw_size = ts_data->fw.buf_size;
1062 #else
1063                 tsp_warn("Not support internal bin!!\n", );
1064                 return size;
1065 #endif
1066                 break;
1067
1068         case MASK_UPDATE_FW:
1069                 ret = request_firmware(&request_fw, IST30XXB_FW_NAME,
1070                                        &ts_data->client->dev);
1071                 if (ret) {
1072                         tsp_warn("File not found, %s\n", IST30XXB_FW_NAME);
1073                         return size;
1074                 }
1075
1076                 fw = (u8 *)request_fw->data;
1077                 fw_size = (u32)request_fw->size;
1078                 break;
1079
1080         case MASK_UPDATE_SDCARD:
1081                 old_fs = get_fs();
1082                 set_fs(get_ds());
1083
1084                 snprintf(fw_path, MAX_FILE_PATH, "/sdcard/touch/firmware/%s",
1085                          IST30XXB_FW_NAME);
1086                 fp = filp_open(fw_path, O_RDONLY, 0);
1087                 if (IS_ERR(fp)) {
1088                         tsp_info("file %s open error:%d\n", fw_path, (s32)fp);
1089                         goto err_file_open;
1090                 }
1091
1092                 fsize = fp->f_path.dentry->d_inode->i_size;
1093
1094                 buff = kzalloc((size_t)fsize, GFP_KERNEL);
1095                 if (!buff) {
1096                         tsp_info("fail to alloc buffer\n");
1097                         goto err_alloc;
1098                 }
1099
1100                 nread = vfs_read(fp, (char __user *)buff, fsize, &fp->f_pos);
1101                 if (nread != fsize) {
1102                         tsp_info("mismatch fw size\n");
1103                         goto err_fw_size;
1104                 }
1105
1106                 fw = (u8 *)buff;
1107                 fw_size = (u32)fsize;
1108
1109                 filp_close(fp, current->files);
1110                 tsp_info("firmware is loaded!!\n");
1111                 break;
1112
1113         case MASK_UPDATE_ERASE:
1114                 tsp_info("EEPROM all erase!!\n");
1115
1116                 mutex_lock(&ist30xx_mutex);
1117                 ist30xx_disable_irq(ts_data);
1118                 ist30xxb_isp_enable(true);
1119                 ist30xxb_isp_erase(ts_data->client, IST30XXB_ISP_ERASE_ALL, 0);
1120                 ist30xxb_isp_enable(false);
1121                 ist30xx_reset(false);
1122                 ist30xx_enable_irq(ts_data);
1123                 mutex_unlock(&ist30xx_mutex);
1124
1125                 ist30xx_start(ts_data);
1126
1127         default:
1128                 return size;
1129         }
1130
1131         ist30xx_get_update_info(ts_data, fw, fw_size);
1132         ist30xx_fw_ver = ist30xx_parse_ver(FLAG_FW, fw);
1133         ist30xx_param_ver = ist30xx_parse_ver(FLAG_PARAM, fw);
1134         ist30xx_sub_ver = ist30xx_parse_ver(FLAG_SUB, fw);
1135
1136         mutex_lock(&ist30xx_mutex);
1137         ist30xx_fw_update(ts_data->client, fw, fw_size, true);
1138
1139         if (calib)
1140                 ist30xx_calibrate(1);
1141         mutex_unlock(&ist30xx_mutex);
1142
1143         ist30xx_start(ts_data);
1144
1145         if (request_fw != NULL)
1146                 release_firmware(request_fw);
1147
1148         if (fp != NULL) {
1149 err_fw_size:
1150                 kfree(buff);
1151 err_alloc:
1152                 filp_close(fp, NULL);
1153 err_file_open:
1154                 set_fs(old_fs);
1155         }
1156
1157         return size;
1158 }
1159
1160 /* sysfs: /sys/class/touch/firmware/fw_sdcard */
1161 ssize_t ist30xx_fw_sdcard_show(struct device *dev,
1162                                struct device_attribute *attr, char *buf)
1163 {
1164         int fw_size = 0;
1165         u8 *fw = NULL;
1166         const u8 *buff = 0;
1167         mm_segment_t old_fs = { 0 };
1168         struct file *fp = NULL;
1169         long fsize = 0, nread = 0;
1170         char fw_path[MAX_FILE_PATH];
1171
1172         old_fs = get_fs();
1173         set_fs(get_ds());
1174
1175         snprintf(fw_path, MAX_FILE_PATH, "/sdcard/touch/firmware/%s",
1176                  IST30XXB_FW_NAME);
1177         fp = filp_open(fw_path, O_RDONLY, 0);
1178         if (IS_ERR(fp)) {
1179                 tsp_info("file %s open error:%d\n", fw_path, (s32)fp);
1180                 goto err_file_open;
1181         }
1182
1183         fsize = fp->f_path.dentry->d_inode->i_size;
1184
1185         buff = kzalloc((size_t)fsize, GFP_KERNEL);
1186         if (!buff) {
1187                 tsp_info("fail to alloc buffer\n");
1188                 goto err_alloc;
1189         }
1190
1191         nread = vfs_read(fp, (char __user *)buff, fsize, &fp->f_pos);
1192         if (nread != fsize) {
1193                 tsp_info("mismatch fw size\n");
1194                 goto err_fw_size;
1195         }
1196
1197         fw = (u8 *)buff;
1198         fw_size = (u32)fsize;
1199
1200         filp_close(fp, current->files);
1201         tsp_info("firmware is loaded!!\n");
1202
1203         ist30xx_get_update_info(ts_data, fw, fw_size);
1204         ist30xx_fw_ver = ist30xx_parse_ver(FLAG_FW, fw);
1205         ist30xx_param_ver = ist30xx_parse_ver(FLAG_PARAM, fw);
1206         ist30xx_sub_ver = ist30xx_parse_ver(FLAG_SUB, fw);
1207
1208         mutex_lock(&ist30xx_mutex);
1209         ist30xx_fw_update(ts_data->client, fw, fw_size, true);
1210         mutex_unlock(&ist30xx_mutex);
1211
1212         ist30xx_start(ts_data);
1213
1214 err_fw_size:
1215         if (buff)
1216                 kfree(buff);
1217 err_alloc:
1218         if (fp)
1219                 filp_close(fp, NULL);
1220 err_file_open:
1221         set_fs(old_fs);
1222
1223         return 0;
1224 }
1225
1226 /* sysfs: /sys/class/touch/firmware/firmware */
1227 ssize_t ist30xx_fw_status_show(struct device *dev,
1228                                struct device_attribute *attr, char *buf)
1229 {
1230         int count;
1231
1232         switch (ts_data->status.update) {
1233         case 1:
1234                 count = sprintf(buf, "Downloading\n");
1235                 break;
1236         case 2:
1237                 count = sprintf(buf, "Update success, ver %x(%x) -> %x(%x, %x), "
1238                                 "status : %d, gap : %d\n",
1239                                 ts_data->fw.prev_param_ver, ts_data->fw.prev_core_ver,
1240                                 ts_data->fw.param_ver, ts_data->fw.core_ver,
1241                                 ts_data->fw.sub_ver,
1242                                 CALIB_TO_STATUS(ts_data->status.calib_msg),
1243                                 CALIB_TO_GAP(ts_data->status.calib_msg));
1244                 break;
1245         default:
1246                 count = sprintf(buf, "Pass\n");
1247         }
1248
1249         return count;
1250 }
1251
1252 /* sysfs: /sys/class/touch/firmware/fw_read */
1253 u32 buf32_eeprom[IST30XX_EEPROM_SIZE / IST30XX_DATA_LEN];
1254 ssize_t ist30xx_fw_read_show(struct device *dev, struct device_attribute *attr,
1255                              char *buf)
1256 {
1257         int i;
1258         u8 *buf8 = (u8 *)buf32_eeprom;;
1259
1260         mutex_lock(&ist30xx_mutex);
1261         ist30xx_disable_irq(ts_data);
1262
1263         ist30xxb_isp_fw_read(ts_data->client, buf32_eeprom);
1264         for (i = 0; i < IST30XX_EEPROM_SIZE; i += 16) {
1265                 tsp_debug("%07x: %02x%02x %02x%02x %02x%02x %02x%02x "
1266                           "%02x%02x %02x%02x %02x%02x %02x%02x\n", i,
1267                           buf8[i], buf8[i + 1], buf8[i + 2], buf8[i + 3],
1268                           buf8[i + 4], buf8[i + 5], buf8[i + 6], buf8[i + 7],
1269                           buf8[i + 8], buf8[i + 9], buf8[i + 10], buf8[i + 11],
1270                           buf8[i + 12], buf8[i + 13], buf8[i + 14], buf8[i + 15]);
1271         }
1272
1273         ist30xx_reset(false);
1274         ist30xx_enable_irq(ts_data);
1275         mutex_unlock(&ist30xx_mutex);
1276
1277         ist30xx_start(ts_data);
1278
1279         return 0;
1280 }
1281
1282 /* sysfs: /sys/class/touch/firmware/version */
1283 ssize_t ist30xx_fw_version_show(struct device *dev,
1284                                 struct device_attribute *attr, char *buf)
1285 {
1286         int count;
1287
1288         count = sprintf(buf, "ID: %x, f/w core: %x, param: %x, sub: %x\n",
1289                         ts_data->chip_id, ts_data->fw.core_ver,
1290                         ts_data->fw.param_ver, ts_data->fw.sub_ver);
1291
1292 #if IST30XX_INTERNAL_BIN
1293         {
1294                 char msg[128];
1295
1296                 ist30xx_get_update_info(ts_data, ts_data->fw.buf, ts_data->fw.buf_size);
1297
1298                 count += snprintf(msg, sizeof(msg),
1299                                   " Header - f/w ver: %x, param: %x, sub: %x\r\n",
1300                                   ist30xx_parse_ver(FLAG_FW, ts_data->fw.buf),
1301                                   ist30xx_parse_ver(FLAG_PARAM, ts_data->fw.buf),
1302                                   ist30xx_parse_ver(FLAG_SUB, ts_data->fw.buf));
1303                 strncat(buf, msg, sizeof(msg));
1304         }
1305 #endif
1306
1307         return count;
1308 }
1309
1310
1311 /* sysfs  */
1312 static DEVICE_ATTR(fw_read, S_IRWXUGO, ist30xx_fw_read_show, NULL);
1313 static DEVICE_ATTR(firmware, S_IRWXUGO, ist30xx_fw_status_show,
1314                    ist30xx_fw_store);
1315 static DEVICE_ATTR(fw_sdcard, S_IRWXUGO, ist30xx_fw_sdcard_show, NULL);
1316 static DEVICE_ATTR(version, S_IRWXUGO, ist30xx_fw_version_show, NULL);
1317
1318 struct class *ist30xx_class;
1319 struct device *ist30xx_fw_dev;
1320
1321 static struct attribute *fw_attributes[] = {
1322         &dev_attr_fw_read.attr,
1323         &dev_attr_firmware.attr,
1324         &dev_attr_fw_sdcard.attr,
1325         &dev_attr_version.attr,
1326         NULL,
1327 };
1328
1329 static struct attribute_group fw_attr_group = {
1330         .attrs  = fw_attributes,
1331 };
1332
1333 int ist30xx_init_update_sysfs(void)
1334 {
1335         /* /sys/class/touch */
1336         ist30xx_class = class_create(THIS_MODULE, "touch");
1337
1338         /* /sys/class/touch/firmware */
1339         ist30xx_fw_dev = device_create(ist30xx_class, NULL, 0, NULL, "firmware");
1340
1341         /* /sys/class/touch/firmware/... */
1342         if (unlikely(sysfs_create_group(&ist30xx_fw_dev->kobj, &fw_attr_group)))
1343                 tsp_err("Failed to create sysfs group(%s)!\n", "firmware");
1344
1345         ts_data->status.update = 0;
1346         ts_data->status.calib = 0;
1347
1348         return 0;
1349 }