2 * mms100_ISC_download.c - Touchscreen driver for Melfas MMS-series touch controllers
4 * Copyright (C) 2011 Google Inc.
5 * Author: Dima Zavin <dima@android.com>
6 * Simon Wilson <simonwilson@google.com>
8 * ISP reflashing code based on original code from Melfas.
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.
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>
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
,
32 bool isc_entered
= false;
33 static int mms_isc_transfer_cmd(struct i2c_client
*client
, int cmd
)
36 struct isc_packet pkt
= { ISC_ADDR
, cmd
};
37 struct i2c_msg msg
= {
40 .len
= sizeof(struct isc_packet
),
44 retval
= i2c_transfer(client
->adapter
, &msg
, 1);
45 TPD_DMESG("mms_isc_transfer_cmd, retval = %d\n",retval
);
49 static int mms_isc_enter(struct i2c_client
*client
)
53 retval
= i2c_smbus_write_byte_data(client
, MMS_CMD_ENTER_ISC
, true);
58 static int mms_isc_exit(struct i2c_client
*client
)
61 return mms_isc_transfer_cmd(client
, ISC_CMD_EXIT
);
64 static int mms_isc_read_status(struct i2c_client
*client
, u32 val
)
66 u8 cmd
= ISC_CMD_READ_STATUS
;
72 ret
= i2c_smbus_read_i2c_block_data(client
, cmd
, 4, (u8
*)&result
);
79 TPD_DMESG("status read fail. cnt : %d, val : 0x%x != 0x%x\n",
85 static int mms_isc_erase_page(struct i2c_client
*client
, int page
)
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
);
91 static int mms_flash_section(struct i2c_client
*client
, struct mms_fw_img
*img
, const u8
*data
,
92 struct mms_ext_hdr
*ext
)
94 struct isc_packet
*isc_packet
;
97 struct i2c_msg msg
[2] = {
99 .addr
= client
->addr
| I2C_DMA_FLAG
,
102 .addr
= client
->addr
| I2C_DMA_FLAG
,
107 int ptr
= img
->offset
;
108 TPD_DMESG("mms_flash_section\n");
110 isc_packet
= kzalloc(sizeof(*isc_packet
) + ISC_XFER_LEN
, GFP_KERNEL
);
111 isc_packet
->cmd
= ISC_ADDR
;
113 msg
[0].buf
= (u8
*)isc_packet
;
114 msg
[1].buf
= kzalloc(ISC_XFER_LEN
, GFP_KERNEL
);
116 for (page
= img
->start_page
; page
<= img
->end_page
; page
++)
118 if (ext
->data
[page
] & EXT_INFO_ERASE
)
119 ret
= mms_isc_erase_page(client
, page
);
122 TPD_DMESG("MMS-ISC, mms_isc_erase_page,ret = %d, Line: %d, Failed\n",ret
, __LINE__
);
126 TPD_DMESG("MMS-ISC, mms_isc_erase_page, %d, Sucess\n",__LINE__
);
128 if (!(ext
->data
[page
] & EXT_INFO_WRITE
))
130 ptr
+= MMS_FLASH_PAGE_SZ
;
134 for (i
= 0; i
< ISC_BLOCK_NUM
; i
++, ptr
+= ISC_XFER_LEN
)
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
;
141 memcpy(isc_packet
->data
, data
+ ptr
, ISC_XFER_LEN
);
142 ret
= melfas_i2c_DMA_RW_isc(melfas_i2c_client
,ISC_DMA_W
,
144 msg
[0].buf
,msg
[0].len
);
147 TPD_DMESG("MMS-ISC, flash firmware,ret = %d, Line: %d, Failed\n",ret
, __LINE__
);
151 TPD_DMESG("MMS-ISC, flash firmware, Success, page = %d, i= %d\n",page
,i
);
152 //if (i2c_transfer(client->adapter, msg, 1) != 1)
155 /* verify firmware */
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
);
164 TPD_DMESG("MMS-ISC, verify firmware,ret = %d, Failed, page = %d, i= %d\n",ret
,page
,i
);
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))
172 if (memcmp(isc_packet
->data
, msg
[1].buf
, ISC_XFER_LEN
))
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);
179 print_hex_dump(KERN_ERR
, "mms fw rd : ",
180 DUMP_PREFIX_OFFSET
, 16, 1,
181 msg
[1].buf
, ISC_XFER_LEN
, false);
183 TPD_DMESG("MMS-ISC, flash verify failed\n");
191 TPD_DMESG("MMS-ISC, section [%d] update succeeded\n", img
->type
);
197 TPD_DMESG("MMS-ISC, i2c failed @ %s\n", __func__
);
209 static int mms_flash_fw(const struct firmware
*fw
, struct i2c_client
*client
)
213 struct mms_bin_hdr
*fw_hdr
;
214 struct mms_fw_img
**img
;
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
;
221 bool update_flag
= false;
223 TPD_DMESG("mms_flash_fw \n");
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
);
230 TPD_DMESG("failed to obtain ver. info\n");
231 memset(ver
, 0xff, sizeof(ver
));
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
);
238 TPD_DMESG("MMS-ISC, mms_isc_enter, %d, Failed\n",__LINE__
);
243 TPD_DMESG("MMS-ISC, mms_isc_enter, %d, Sucess\n",__LINE__
);
246 for (i
= 0; i
< fw_hdr
->section_num
; i
++, offset
+= sizeof(struct mms_fw_img
))
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
;
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
]);
258 if ((ret
= mms_flash_section(client
, img
[i
], fw
->data
+ fw_hdr
->binary_offset
, ext
))) {
264 TPD_DMESG("MMS-ISC, section [%d] is up to date\n", i
);
269 ret
= mms_isc_exit(client
);
273 TPD_DMESG("MMS-ISC, mms_isc_exit, Failed\n");
278 TPD_DMESG("MMS-ISC, mms_isc_exit, Sucess\n");
286 //update finished, check the firmware to confirm
287 if (melfas_check_firmware(client
)) {
288 TPD_DMESG("failed to obtain version after flash\n");
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
]);
307 if (isc_entered
)//(update_flag)
309 ret
= mms_isc_exit(client
);
312 TPD_DMESG("MMS-ISC, mms_isc_exit, Failed\n");
316 TPD_DMESG("MMS-ISC, mms_isc_exit, Sucess\n");
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);
332 //extern struct completion mms200_init_done;
334 PR 453322,temp solution. if failed in update,we try another i2c address
336 void mms_fw_update_controller(const struct firmware
*fw
, struct i2c_client
*client
)
341 TPD_DMESG("mms_fw_update_controller \n");
343 TPD_DMESG("failed to read firmware\n");
344 //complete_all(&mms200_init_done);
349 ret
= mms_flash_fw(fw
, client
);
353 TPD_DMESG("modify i2c addr to 0x48\n");
358 TPD_DMESG("modify i2c addr to 0x20\n");
360 } while ((ret
!= 0) && (--retires
));
363 TPD_DMESG("failed to flash firmware after retires\n");
367 int isc_fw_download(struct i2c_client
*client
, const u8
*data
, size_t len
)
377 buff
= kzalloc(1024, GFP_KERNEL
);
380 TPD_DMESG("%s: failed to allocate memory\n", __func__
);
387 /*1, enterring ISC mode */
388 ret
= mms_isc_enter(client
);
391 TPD_DMESG("fail to enter ISC mode(err=%d)\n", ret
);
394 usleep_range(10000, 20000);
395 TPD_DMESG("isc_fw, Step 1: Enter ISC mode\n");
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
;
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
]);
411 if ((ret
= mms_flash_section(info
, img
[i
], fw
->data
+ fw_hdr
->binary_offset
, ext
))) {
417 dev_info(&client
->dev
, "section [%d] is up to date\n", i
);
423 /*3, exit ISC mode */
424 ret
= mms_isc_exit(client
);
425 TPD_DMESG("isc_fw, Step 1: Exit ISC mode\n");