import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / input / touchscreen / mediatek / mms244 / mms200_isc.c
1 /*
2 * mms100_ISC_download.c - Touchscreen driver for Melfas MMS-series touch controllers
3 *
4 * Copyright (C) 2011 Google Inc.
5 * Author: Dima Zavin <dima@android.com>
6 * Simon Wilson <simonwilson@google.com>
7 *
8 * ISP reflashing code based on original code from Melfas.
9 *
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 *
16 */
17 #include <linux/delay.h>
18 #include <linux/i2c.h>
19 #include <linux/slab.h>
20 #include <linux/firmware.h>
21 #include <linux/completion.h>
22 #include <asm/unaligned.h>
23
24 #include "tpd.h"
25 #include "mms200_ts.h"
26 extern struct i2c_client *melfas_i2c_client;
27 extern void mms_reboot(void);
28 extern int melfas_check_firmware(struct i2c_client *client);
29 extern int melfas_i2c_DMA_RW_isc(struct i2c_client *client,int rw,
30 U8 *rxbuf, U16 rlen,
31 U8 *txbuf, U16 tlen);
32 bool isc_entered = false;
33 static int mms_isc_transfer_cmd(struct i2c_client *client, int cmd)
34 {
35 int retval;
36 struct isc_packet pkt = { ISC_ADDR, cmd };
37 struct i2c_msg msg = {
38 .addr = client->addr,
39 .flags = 0,
40 .len = sizeof(struct isc_packet),
41 .buf = (u8 *)&pkt,
42 };
43
44 retval = i2c_transfer(client->adapter, &msg, 1);
45 TPD_DMESG("mms_isc_transfer_cmd, retval = %d\n",retval);
46 return retval;
47 }
48
49 static int mms_isc_enter(struct i2c_client *client)
50 {
51 int retval;
52 isc_entered = true;
53 retval = i2c_smbus_write_byte_data(client, MMS_CMD_ENTER_ISC, true);
54
55 return retval;
56 }
57
58 static int mms_isc_exit(struct i2c_client *client)
59 {
60 isc_entered = false;
61 return mms_isc_transfer_cmd(client, ISC_CMD_EXIT);
62 }
63
64 static int mms_isc_read_status(struct i2c_client *client, u32 val)
65 {
66 u8 cmd = ISC_CMD_READ_STATUS;
67 u32 result = 0;
68 int cnt = 100;
69 int ret = 0;
70
71 do {
72 ret = i2c_smbus_read_i2c_block_data(client, cmd, 4, (u8 *)&result);
73 if (result == val)
74 break;
75 msleep(1);
76 } while (--cnt);
77
78 if (!cnt) {
79 TPD_DMESG("status read fail. cnt : %d, val : 0x%x != 0x%x\n",
80 cnt, result, val);
81 }
82
83 return ret;
84 }
85 static int mms_isc_erase_page(struct i2c_client *client, int page)
86 {
87 return mms_isc_transfer_cmd(client, ISC_CMD_PAGE_ERASE | page) ||
88 mms_isc_read_status(client, ISC_PAGE_ERASE_DONE | ISC_PAGE_ERASE_ENTER | page);
89 }
90
91 static int mms_flash_section(struct i2c_client *client, struct mms_fw_img *img, const u8 *data,
92 struct mms_ext_hdr *ext)
93 {
94 struct isc_packet *isc_packet;
95 int ret;
96 int page, i;
97 struct i2c_msg msg[2] = {
98 {
99 .addr = client->addr | I2C_DMA_FLAG,
100 .flags = 0,
101 }, {
102 .addr = client->addr | I2C_DMA_FLAG,
103 .flags = I2C_M_RD,
104 .len = ISC_XFER_LEN,
105 },
106 };
107 int ptr = img->offset;
108 TPD_DMESG("mms_flash_section\n");
109
110 isc_packet = kzalloc(sizeof(*isc_packet) + ISC_XFER_LEN, GFP_KERNEL);
111 isc_packet->cmd = ISC_ADDR;
112
113 msg[0].buf = (u8 *)isc_packet;
114 msg[1].buf = kzalloc(ISC_XFER_LEN, GFP_KERNEL);
115
116 for (page = img->start_page; page <= img->end_page; page++)
117 {
118 if (ext->data[page] & EXT_INFO_ERASE)
119 ret = mms_isc_erase_page(client, page);
120 if (ret < 0)
121 {
122 TPD_DMESG("MMS-ISC, mms_isc_erase_page,ret = %d, Line: %d, Failed\n",ret, __LINE__);
123 goto i2c_err;
124 }
125 else
126 TPD_DMESG("MMS-ISC, mms_isc_erase_page, %d, Sucess\n",__LINE__);
127
128 if (!(ext->data[page] & EXT_INFO_WRITE))
129 {
130 ptr += MMS_FLASH_PAGE_SZ;
131 continue;
132 }
133
134 for (i = 0; i < ISC_BLOCK_NUM; i++, ptr += ISC_XFER_LEN)
135 {
136 /* flash firmware */
137 u32 tmp = page * 256 + i * (ISC_XFER_LEN / 4);
138 put_unaligned_le32(tmp, &isc_packet->addr);
139 msg[0].len = sizeof(struct isc_packet) + ISC_XFER_LEN;
140
141 memcpy(isc_packet->data, data + ptr, ISC_XFER_LEN);
142 ret = melfas_i2c_DMA_RW_isc(melfas_i2c_client,ISC_DMA_W,
143 NULL,NULL,
144 msg[0].buf,msg[0].len);
145 if (ret < 0)
146 {
147 TPD_DMESG("MMS-ISC, flash firmware,ret = %d, Line: %d, Failed\n",ret, __LINE__);
148 goto i2c_err;
149 }
150 else
151 TPD_DMESG("MMS-ISC, flash firmware, Success, page = %d, i= %d\n",page,i);
152 //if (i2c_transfer(client->adapter, msg, 1) != 1)
153 // goto i2c_err;
154
155 /* verify firmware */
156 tmp |= ISC_CMD_READ;
157 put_unaligned_le32(tmp, &isc_packet->addr);
158 msg[0].len = sizeof(struct isc_packet);
159 ret = melfas_i2c_DMA_RW_isc(melfas_i2c_client,ISC_DMA_R,
160 msg[1].buf,msg[1].len,
161 msg[0].buf,msg[0].len);
162 if (ret < 0)
163 {
164 TPD_DMESG("MMS-ISC, verify firmware,ret = %d, Failed, page = %d, i= %d\n",ret,page,i);
165 goto i2c_err;
166 }
167 else
168 TPD_DMESG("MMS-ISC, verify firmware, Success, page = %d, i= %d\n",page,i);
169 //if (i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)) != ARRAY_SIZE(msg))
170 // goto i2c_err;
171
172 if (memcmp(isc_packet->data, msg[1].buf, ISC_XFER_LEN))
173 {
174 #if FLASH_VERBOSE_DEBUG
175 print_hex_dump(KERN_ERR, "mms fw wr : ",
176 DUMP_PREFIX_OFFSET, 16, 1,
177 isc_packet->data, ISC_XFER_LEN, false);
178
179 print_hex_dump(KERN_ERR, "mms fw rd : ",
180 DUMP_PREFIX_OFFSET, 16, 1,
181 msg[1].buf, ISC_XFER_LEN, false);
182 #endif
183 TPD_DMESG("MMS-ISC, flash verify failed\n");
184 ret = -1;
185 goto out;
186 }
187
188 }
189 }
190
191 TPD_DMESG("MMS-ISC, section [%d] update succeeded\n", img->type);
192
193 ret = 0;
194 goto out;
195
196 i2c_err:
197 TPD_DMESG("MMS-ISC, i2c failed @ %s\n", __func__);
198 ret = -1;
199
200 out:
201 kfree(isc_packet);
202 kfree(msg[1].buf);
203
204 return ret;
205
206 }
207
208
209 static int mms_flash_fw(const struct firmware *fw, struct i2c_client *client)
210 {
211 int ret;
212 int i;
213 struct mms_bin_hdr *fw_hdr;
214 struct mms_fw_img **img;
215
216 u8 ver[MAX_SECTION_NUM];
217 u8 target[MAX_SECTION_NUM];
218 int offset = sizeof(struct mms_bin_hdr);
219 struct mms_ext_hdr *ext;
220 int retires = 3;
221 bool update_flag = false;
222
223 TPD_DMESG("mms_flash_fw \n");
224
225 fw_hdr = (struct mms_bin_hdr *)fw->data;
226 ext = (struct mms_ext_hdr *)(fw->data + fw_hdr->extention_offset);
227 img = kzalloc(sizeof(*img) * fw_hdr->section_num, GFP_KERNEL);
228
229 if (retires < 0) {
230 TPD_DMESG("failed to obtain ver. info\n");
231 memset(ver, 0xff, sizeof(ver));
232 } else {
233 print_hex_dump(KERN_INFO, "mms_ts fw ver : ", DUMP_PREFIX_NONE, 16, 1,
234 ver, MAX_SECTION_NUM, false);
235 ret = mms_isc_enter(client);
236 if (ret <0)
237 {
238 TPD_DMESG("MMS-ISC, mms_isc_enter, %d, Failed\n",__LINE__);
239 mms_reboot();
240 goto out;
241 }
242 else
243 TPD_DMESG("MMS-ISC, mms_isc_enter, %d, Sucess\n",__LINE__);
244 }
245
246 for (i = 0; i < fw_hdr->section_num; i++, offset += sizeof(struct mms_fw_img))
247 {
248 TPD_DMESG("MMS-ISC, section_num = %d, offset = %d \n",fw_hdr->section_num,sizeof(struct mms_fw_img));
249 img[i] = (struct mms_fw_img *)(fw->data + offset);
250 target[i] = img[i]->version;
251
252 if (ver[img[i]->type] != target[i]) {
253 TPD_DMESG("MMS-ISC, section [%d] is need to be updated. ver : 0x%x, bin : 0x%x\n",
254 i, ver[i], target[i]);
255
256 update_flag = true;
257
258 if ((ret = mms_flash_section(client, img[i], fw->data + fw_hdr->binary_offset, ext))) {
259 mms_reboot();
260 goto out;
261 }
262
263 } else {
264 TPD_DMESG("MMS-ISC, section [%d] is up to date\n", i);
265 }
266 }
267
268 if (update_flag)
269 ret = mms_isc_exit(client);
270
271 if (ret < 0)
272 {
273 TPD_DMESG("MMS-ISC, mms_isc_exit, Failed\n");
274 goto out;
275 }
276 else
277 {
278 TPD_DMESG("MMS-ISC, mms_isc_exit, Sucess\n");
279 }
280
281
282 msleep(5);
283
284 mms_reboot();
285 #if 0
286 //update finished, check the firmware to confirm
287 if (melfas_check_firmware(client)) {
288 TPD_DMESG("failed to obtain version after flash\n");
289 ret = -1;
290 goto out;
291 } else {
292 for (i = 0; i < fw_hdr->section_num; i++) {
293 if (ver[img[i]->type] != target[i]) {
294 TPD_DMESG("version mismatch after flash. [%d] 0x%x != 0x%x\n",
295 i, ver[img[i]->type], target[i]);
296
297 ret = -1;
298 goto out;
299 }
300 }
301 }
302 #endif
303 ret = 0;
304
305 out:
306 kfree(img);
307 if (isc_entered)//(update_flag)
308 {
309 ret = mms_isc_exit(client);
310 if (ret < 0)
311 {
312 TPD_DMESG("MMS-ISC, mms_isc_exit, Failed\n");
313 }
314 else
315 {
316 TPD_DMESG("MMS-ISC, mms_isc_exit, Sucess\n");
317 }
318 }
319
320 msleep(5);
321
322 mms_reboot();
323
324 //mms_ts_config(info);
325 i2c_smbus_read_byte_data(client, MMS_TX_NUM);
326 i2c_smbus_read_byte_data(client, MMS_RX_NUM);
327 //release_firmware(fw);
328
329 return ret;
330
331 }
332 //extern struct completion mms200_init_done;
333 /*
334 PR 453322,temp solution. if failed in update,we try another i2c address
335 */
336 void mms_fw_update_controller(const struct firmware *fw, struct i2c_client *client)
337 {
338 int retires = 3;
339 int ret;
340
341 TPD_DMESG("mms_fw_update_controller \n");
342 if (!fw) {
343 TPD_DMESG("failed to read firmware\n");
344 //complete_all(&mms200_init_done);
345 return;
346 }
347
348 do {
349 ret = mms_flash_fw(fw, client);
350 if(ret < 0)
351 {
352 client->addr = 0x48;
353 TPD_DMESG("modify i2c addr to 0x48\n");
354 }
355 else
356 {
357 client->addr = 0x20;
358 TPD_DMESG("modify i2c addr to 0x20\n");
359 }
360 } while ((ret != 0) && (--retires));
361 client->addr = 0x20;
362 if (!retires) {
363 TPD_DMESG("failed to flash firmware after retires\n");
364 }
365 }
366
367 int isc_fw_download(struct i2c_client *client, const u8 *data, size_t len)
368 {
369 #if 0
370 u8 *buff;
371 u16 crc_buf;
372 int src_idx;
373 int dest_idx;
374 int ret;
375 int i, j;
376
377 buff = kzalloc(1024, GFP_KERNEL);
378 if (!buff)
379 {
380 TPD_DMESG("%s: failed to allocate memory\n", __func__);
381 kfree(buff);
382
383 ret = -1;
384 return ret;
385 }
386
387 /*1, enterring ISC mode */
388 ret = mms_isc_enter(client);
389 if (ret < 0)
390 {
391 TPD_DMESG("fail to enter ISC mode(err=%d)\n", ret);
392 return ret;
393 }
394 usleep_range(10000, 20000);
395 TPD_DMESG("isc_fw, Step 1: Enter ISC mode\n");
396
397
398 #if 0
399 /*2, enter ISC update mode */
400 for (i = 0; i < fw_hdr->section_num; i++, offset += sizeof(struct mms_fw_img)) {
401 img[i] = (struct mms_fw_img *)(fw->data + offset);
402 target[i] = img[i]->version;
403
404 if (ver[img[i]->type] != target[i]) {
405 dev_info(&client->dev,
406 "section [%d] is need to be updated. ver : 0x%x, bin : 0x%x\n",
407 i, ver[i], target[i]);
408
409 update_flag = true;
410
411 if ((ret = mms_flash_section(info, img[i], fw->data + fw_hdr->binary_offset, ext))) {
412 mms_reboot( );
413 goto out;
414 }
415
416 } else {
417 dev_info(&client->dev, "section [%d] is up to date\n", i);
418 }
419 }
420
421 #endif
422
423 /*3, exit ISC mode */
424 ret = mms_isc_exit(client);
425 TPD_DMESG("isc_fw, Step 1: Exit ISC mode\n");
426
427 kfree(buff);
428
429 return ret;
430
431 #endif
432 }
433