blob: 70c1307d0e08fd61383d0e63efec187b5128651b [file] [log] [blame]
Alexandra Chin669d27c2012-12-24 15:42:30 +08001/*
2 * Synaptics RMI4 touchscreen driver
3 *
4 * Copyright (C) 2012 Synaptics Incorporated
5 *
6 * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
7 * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/slab.h>
23#include <linux/i2c.h>
24#include <linux/interrupt.h>
25#include <linux/delay.h>
26#include <linux/input.h>
27#include <linux/firmware.h>
Amy Malocheafcecb22013-04-16 18:43:22 -070028#include <linux/string.h>
Alexandra Chin669d27c2012-12-24 15:42:30 +080029#include <linux/input/synaptics_dsx.h>
30#include "synaptics_i2c_rmi4.h"
31
Alexandra Chin669d27c2012-12-24 15:42:30 +080032#define SHOW_PROGRESS
Alexandra Chind5591a62013-02-07 12:59:15 -080033#define MAX_FIRMWARE_ID_LEN 10
34#define FORCE_UPDATE false
35#define INSIDE_FIRMWARE_UPDATE
Alexandra Chin669d27c2012-12-24 15:42:30 +080036
Alexandra Chin669d27c2012-12-24 15:42:30 +080037#define FW_IMAGE_OFFSET 0x100
Alexandra Chin400f26e2013-07-25 11:58:17 -070038/* 0 to ignore flash block check to speed up flash time */
39#define CHECK_FLASH_BLOCK_STATUS 1
Alexandra Chin669d27c2012-12-24 15:42:30 +080040
41#define REG_MAP (1 << 0)
42#define UNLOCKED (1 << 1)
43#define HAS_CONFIG_ID (1 << 2)
44#define HAS_PERM_CONFIG (1 << 3)
45#define HAS_BL_CONFIG (1 << 4)
46#define HAS_DISP_CONFIG (1 << 5)
47#define HAS_CTRL1 (1 << 6)
48
Amy Maloched9bf0d92013-06-19 17:19:23 -070049#define RMI4_INFO_MAX_LEN 200
50
51#define RMI4_STORE_TS_INFO(buf, id, rev, fw_ver) \
52 snprintf(buf, RMI4_INFO_MAX_LEN, \
53 "controller\t= synaptics\n" \
54 "model\t\t= %d rev %d\n" \
55 "fw_ver\t\t= %d\n", id, rev, fw_ver)
56
Amy Malocheafcecb22013-04-16 18:43:22 -070057enum falsh_config_area {
58 UI_CONFIG_AREA = 0x00,
59 PERM_CONFIG_AREA = 0x01,
60 BL_CONFIG_AREA = 0x02,
61 DISP_CONFIG_AREA = 0x03
62};
Alexandra Chin669d27c2012-12-24 15:42:30 +080063
64enum flash_command {
65 CMD_WRITE_FW_BLOCK = 0x2,
66 CMD_ERASE_ALL = 0x3,
Alexandra Chin823a2f52013-07-29 16:09:52 -070067 CMD_WRITE_LOCKDOWN_BLOCK = 0x4,
Alexandra Chin669d27c2012-12-24 15:42:30 +080068 CMD_READ_CONFIG_BLOCK = 0x5,
69 CMD_WRITE_CONFIG_BLOCK = 0x6,
70 CMD_ERASE_CONFIG = 0x7,
Amy Malocheafcecb22013-04-16 18:43:22 -070071 CMD_READ_SENSOR_ID = 0x8,
Alexandra Chin669d27c2012-12-24 15:42:30 +080072 CMD_ERASE_BL_CONFIG = 0x9,
73 CMD_ERASE_DISP_CONFIG = 0xA,
Amy Malocheafcecb22013-04-16 18:43:22 -070074 CMD_ENABLE_FLASH_PROG = 0xF
Alexandra Chin669d27c2012-12-24 15:42:30 +080075};
76
Alexandra Chind5591a62013-02-07 12:59:15 -080077enum flash_area {
78 NONE,
79 UI_FIRMWARE,
Amy Maloche2c4c48c2013-05-01 20:06:23 -070080 CONFIG_AREA,
81 MISMATCH
Alexandra Chind5591a62013-02-07 12:59:15 -080082};
83
Amy Malocheafcecb22013-04-16 18:43:22 -070084enum image_file_option {
85 OPTION_BUILD_INFO = 0,
86 OPTION_CONTAIN_BOOTLOADER = 1,
87};
88
Alexandra Chin400f26e2013-07-25 11:58:17 -070089enum flash_offset {
90 OFFSET_BOOTLOADER_ID,
91 OFFSET_FLASH_PROPERTIES,
92 OFFSET_BLOCK_SIZE,
93 OFFSET_FW_BLOCK_COUNT,
94 OFFSET_BLOCK_NUMBER,
95 OFFSET_BLOCK_DATA,
96 OFFSET_FLASH_CONTROL,
97 OFFSET_FLASH_STATUS
98};
99
Alexandra Chin823a2f52013-07-29 16:09:52 -0700100enum flash_update_mode {
101 NORMAL = 1,
102 FORCE = 2,
103 LOCKDOWN = 8
104};
105
Alexandra Chin669d27c2012-12-24 15:42:30 +0800106#define SLEEP_MODE_NORMAL (0x00)
107#define SLEEP_MODE_SENSOR_SLEEP (0x01)
108#define SLEEP_MODE_RESERVED0 (0x02)
109#define SLEEP_MODE_RESERVED1 (0x03)
110
111#define ENABLE_WAIT_MS (1 * 1000)
112#define WRITE_WAIT_MS (3 * 1000)
113#define ERASE_WAIT_MS (5 * 1000)
Alexandra Chind5591a62013-02-07 12:59:15 -0800114#define RESET_WAIT_MS (500)
Alexandra Chin669d27c2012-12-24 15:42:30 +0800115
Alexandra Chin400f26e2013-07-25 11:58:17 -0700116#define SLEEP_TIME_US 100
Alexandra Chin669d27c2012-12-24 15:42:30 +0800117
Alexandra Chin669d27c2012-12-24 15:42:30 +0800118static int fwu_wait_for_idle(int timeout_ms);
119
Amy Malocheafcecb22013-04-16 18:43:22 -0700120struct image_header_data {
121 union {
122 struct {
123 /* 0x00-0x0F */
124 unsigned char file_checksum[4];
125 unsigned char reserved_04;
126 unsigned char reserved_05;
127 unsigned char options_firmware_id:1;
128 unsigned char options_contain_bootloader:1;
129 unsigned char options_reserved:6;
130 unsigned char bootloader_version;
131 unsigned char firmware_size[4];
132 unsigned char config_size[4];
133 /* 0x10-0x1F */
134 unsigned char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE];
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700135 unsigned char pkg_id_lsb;
136 unsigned char pkg_id_msb;
137 unsigned char pkg_id_rev_lsb;
138 unsigned char pkg_id_rev_msb;
Amy Malocheafcecb22013-04-16 18:43:22 -0700139 unsigned char product_info[SYNAPTICS_RMI4_PRODUCT_INFO_SIZE];
140 /* 0x20-0x2F */
141 unsigned char reserved_20_2f[0x10];
142 /* 0x30-0x3F */
143 unsigned char ds_firmware_id[0x10];
144 /* 0x40-0x4F */
145 unsigned char ds_customize_info[10];
146 unsigned char reserved_4a_4f[6];
147 /* 0x50-0x53*/
148 unsigned char firmware_id[4];
149 } __packed;
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700150 unsigned char data[0x54];
Amy Malocheafcecb22013-04-16 18:43:22 -0700151 };
152};
153
Alexandra Chin823a2f52013-07-29 16:09:52 -0700154struct image_content {
155 bool is_contain_build_info;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800156 unsigned int checksum;
157 unsigned int image_size;
158 unsigned int config_size;
159 unsigned char options;
160 unsigned char bootloader_version;
161 unsigned char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
162 unsigned char product_info[SYNAPTICS_RMI4_PRODUCT_INFO_SIZE];
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700163 u16 package_id;
164 u16 package_revision_id;
Amy Malocheafcecb22013-04-16 18:43:22 -0700165 unsigned int firmware_id;
Alexandra Chin823a2f52013-07-29 16:09:52 -0700166 const unsigned char *firmware_data;
167 const unsigned char *config_data;
168 const unsigned char *lockdown_data;
169 unsigned short lockdown_block_count;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800170};
171
172struct pdt_properties {
173 union {
174 struct {
175 unsigned char reserved_1:6;
176 unsigned char has_bsr:1;
177 unsigned char reserved_2:1;
178 } __packed;
179 unsigned char data[1];
180 };
181};
182
183struct f01_device_status {
184 union {
185 struct {
186 unsigned char status_code:4;
187 unsigned char reserved:2;
188 unsigned char flash_prog:1;
189 unsigned char unconfigured:1;
190 } __packed;
191 unsigned char data[1];
192 };
193};
194
195struct f01_device_control {
196 union {
197 struct {
198 unsigned char sleep_mode:2;
199 unsigned char nosleep:1;
200 unsigned char reserved:2;
201 unsigned char charger_connected:1;
202 unsigned char report_rate:1;
203 unsigned char configured:1;
204 } __packed;
205 unsigned char data[1];
206 };
207};
208
209struct f34_flash_control {
210 union {
Alexandra Chin400f26e2013-07-25 11:58:17 -0700211 /* version 0 */
Alexandra Chin669d27c2012-12-24 15:42:30 +0800212 struct {
Alexandra Chin400f26e2013-07-25 11:58:17 -0700213 unsigned char command_v0:4;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800214 unsigned char status:3;
215 unsigned char program_enabled:1;
216 } __packed;
Alexandra Chin400f26e2013-07-25 11:58:17 -0700217 /* version 1 */
218 struct {
219 unsigned char command_v1:6;
220 unsigned char reserved:2;
221 } __packed;
222 unsigned char data[1];
223 };
224};
225
226struct f34_flash_status {
227 union {
228 struct {
229 unsigned char status:6;
230 unsigned char reserved:1;
231 unsigned char program_enabled:1;
232 } __packed;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800233 unsigned char data[1];
234 };
235};
236
237struct f34_flash_properties {
238 union {
239 struct {
240 unsigned char regmap:1;
241 unsigned char unlocked:1;
242 unsigned char has_configid:1;
243 unsigned char has_perm_config:1;
244 unsigned char has_bl_config:1;
245 unsigned char has_display_config:1;
246 unsigned char has_blob_config:1;
247 unsigned char reserved:1;
248 } __packed;
249 unsigned char data[1];
250 };
251};
252
253struct synaptics_rmi4_fwu_handle {
254 bool initialized;
Alexandra Chind5591a62013-02-07 12:59:15 -0800255 bool force_update;
Alexandra Chin823a2f52013-07-29 16:09:52 -0700256 bool do_lockdown;
Alexandra Chin400f26e2013-07-25 11:58:17 -0700257 bool interrupt_flag;
258 bool polling_mode;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800259 char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
260 unsigned int image_size;
261 unsigned int data_pos;
262 unsigned char intr_mask;
263 unsigned char bootloader_id[2];
264 unsigned char productinfo1;
265 unsigned char productinfo2;
266 unsigned char *ext_data_source;
267 unsigned char *read_config_buf;
268 const unsigned char *firmware_data;
269 const unsigned char *config_data;
Alexandra Chin823a2f52013-07-29 16:09:52 -0700270 const unsigned char *lockdown_data;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800271 unsigned short block_size;
272 unsigned short fw_block_count;
273 unsigned short config_block_count;
Alexandra Chin823a2f52013-07-29 16:09:52 -0700274 unsigned short lockdown_block_count;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800275 unsigned short perm_config_block_count;
276 unsigned short bl_config_block_count;
277 unsigned short disp_config_block_count;
278 unsigned short config_size;
279 unsigned short config_area;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800280 unsigned short addr_f01_interrupt_register;
Alexandra Chin823a2f52013-07-29 16:09:52 -0700281 const unsigned char *data_buffer;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800282 struct synaptics_rmi4_fn_desc f01_fd;
283 struct synaptics_rmi4_fn_desc f34_fd;
284 struct synaptics_rmi4_exp_fn_ptr *fn_ptr;
285 struct synaptics_rmi4_data *rmi4_data;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800286 struct f34_flash_properties flash_properties;
Alexandra Chind5591a62013-02-07 12:59:15 -0800287 struct workqueue_struct *fwu_workqueue;
288 struct delayed_work fwu_work;
Alexandra Chin823a2f52013-07-29 16:09:52 -0700289 char image_name[NAME_BUFFER_SIZE];
290 struct image_content image_content;
Amy Maloched9bf0d92013-06-19 17:19:23 -0700291 char *ts_info;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800292};
293
294static struct synaptics_rmi4_fwu_handle *fwu;
295
Alexandra Chind9e204d2013-07-25 15:23:01 -0700296DECLARE_COMPLETION(fwu_remove_complete);
Alexandra Chin669d27c2012-12-24 15:42:30 +0800297
298static unsigned int extract_uint(const unsigned char *ptr)
299{
300 return (unsigned int)ptr[0] +
301 (unsigned int)ptr[1] * 0x100 +
302 (unsigned int)ptr[2] * 0x10000 +
303 (unsigned int)ptr[3] * 0x1000000;
304}
305
Amy Malocheafcecb22013-04-16 18:43:22 -0700306static unsigned int extract_uint_be(const unsigned char *ptr)
307{
308 return (unsigned int)ptr[3] +
309 (unsigned int)ptr[2] * 0x100 +
310 (unsigned int)ptr[1] * 0x10000 +
311 (unsigned int)ptr[0] * 0x1000000;
312}
313
Amy Maloched9bf0d92013-06-19 17:19:23 -0700314static void synaptics_rmi4_update_debug_info(void)
315{
316 unsigned char pkg_id[4];
317 unsigned int build_id;
318 struct synaptics_rmi4_device_info *rmi;
319 /* read device package id */
320 fwu->fn_ptr->read(fwu->rmi4_data,
321 fwu->f01_fd.query_base_addr + 17,
322 pkg_id,
323 sizeof(pkg_id));
324 rmi = &(fwu->rmi4_data->rmi4_mod_info);
325
326 build_id = (unsigned int)rmi->build_id[0] +
327 (unsigned int)rmi->build_id[1] * 0x100 +
328 (unsigned int)rmi->build_id[2] * 0x10000;
329
330 RMI4_STORE_TS_INFO(fwu->ts_info, pkg_id[1] << 8 | pkg_id[0],
331 pkg_id[3] << 8 | pkg_id[2], build_id);
332}
333
Alexandra Chin823a2f52013-07-29 16:09:52 -0700334static void parse_header(void)
Alexandra Chin669d27c2012-12-24 15:42:30 +0800335{
Alexandra Chin823a2f52013-07-29 16:09:52 -0700336 struct image_content *img = &fwu->image_content;
337 struct image_header_data *data =
338 (struct image_header_data *)fwu->data_buffer;
339 img->checksum = extract_uint(data->file_checksum);
340 img->bootloader_version = data->bootloader_version;
341 img->image_size = extract_uint(data->firmware_size);
342 img->config_size = extract_uint(data->config_size);
343 memcpy(img->product_id, data->product_id,
Amy Malocheafcecb22013-04-16 18:43:22 -0700344 sizeof(data->product_id));
Alexandra Chin823a2f52013-07-29 16:09:52 -0700345 img->product_id[sizeof(data->product_id)] = 0;
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700346
Alexandra Chin823a2f52013-07-29 16:09:52 -0700347 img->product_id[sizeof(data->product_info)] = 0;
348 memcpy(img->product_info, data->product_info,
Amy Malocheafcecb22013-04-16 18:43:22 -0700349 sizeof(data->product_info));
350
Alexandra Chin823a2f52013-07-29 16:09:52 -0700351 img->is_contain_build_info =
Amy Malocheafcecb22013-04-16 18:43:22 -0700352 (data->options_firmware_id == (1 << OPTION_BUILD_INFO));
Alexandra Chin823a2f52013-07-29 16:09:52 -0700353
354 if (img->is_contain_build_info) {
355 img->firmware_id = extract_uint(data->firmware_id);
356 img->package_id = (data->pkg_id_rev_msb << 8) |
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700357 data->pkg_id_lsb;
Alexandra Chin823a2f52013-07-29 16:09:52 -0700358 img->package_revision_id = (data->pkg_id_rev_msb << 8) |
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700359 data->pkg_id_rev_lsb;
360 dev_info(&fwu->rmi4_data->i2c_client->dev,
361 "%s Package ID %d Rev %d\n", __func__,
Alexandra Chin823a2f52013-07-29 16:09:52 -0700362 img->package_id, img->package_revision_id);
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700363
Alexandra Chin823a2f52013-07-29 16:09:52 -0700364 img->firmware_id = extract_uint(data->firmware_id);
Amy Malocheafcecb22013-04-16 18:43:22 -0700365 dev_info(&fwu->rmi4_data->i2c_client->dev,
366 "%s Firwmare build id %d\n", __func__,
Alexandra Chin823a2f52013-07-29 16:09:52 -0700367 img->firmware_id);
Amy Malocheafcecb22013-04-16 18:43:22 -0700368 }
Alexandra Chin669d27c2012-12-24 15:42:30 +0800369
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700370 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
Alexandra Chin669d27c2012-12-24 15:42:30 +0800371 "Firwmare size %d, config size %d\n",
Alexandra Chin823a2f52013-07-29 16:09:52 -0700372 img->image_size,
373 img->config_size);
374
375 /* get UI firmware offset */
376 if (img->image_size)
377 img->firmware_data = fwu->data_buffer + FW_IMAGE_OFFSET;
378 /* get config offset*/
379 if (img->config_size)
380 img->config_data = fwu->data_buffer + FW_IMAGE_OFFSET +
381 img->image_size;
382 /* get lockdown offset*/
383 switch (img->bootloader_version) {
384 case 3:
385 case 4:
386 img->lockdown_block_count = 4;
387 break;
388 case 5:
389 case 6:
390 img->lockdown_block_count = 5;
391 break;
392 default:
393 dev_warn(&fwu->rmi4_data->i2c_client->dev,
394 "%s: Not support lockdown in " \
395 "bootloader version V%d\n",
396 __func__, img->bootloader_version);
397 img->lockdown_data = NULL;
398 }
399
400 img->lockdown_data = fwu->data_buffer +
401 FW_IMAGE_OFFSET -
402 img->lockdown_block_count * fwu->block_size;
403
404 fwu->lockdown_block_count = img->lockdown_block_count;
405 fwu->lockdown_data = img->lockdown_data;
406 fwu->config_data = img->config_data;
407 fwu->firmware_data = img->firmware_data;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800408 return;
409}
410
Alexandra Chin669d27c2012-12-24 15:42:30 +0800411static int fwu_read_f01_device_status(struct f01_device_status *status)
412{
413 int retval;
414
415 retval = fwu->fn_ptr->read(fwu->rmi4_data,
416 fwu->f01_fd.data_base_addr,
417 status->data,
418 sizeof(status->data));
419 if (retval < 0) {
420 dev_err(&fwu->rmi4_data->i2c_client->dev,
421 "%s: Failed to read F01 device status\n",
422 __func__);
423 return retval;
424 }
425
426 return 0;
427}
428
Alexandra Chin400f26e2013-07-25 11:58:17 -0700429static unsigned short fwu_get_address(enum flash_offset type)
430{
431 int offset;
432 unsigned short addr = 0;
433 struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
434
435 switch (type) {
436 case OFFSET_BOOTLOADER_ID:
437 offset = 0;
438 addr = fwu->f34_fd.query_base_addr + offset;
439 break;
440 case OFFSET_FLASH_PROPERTIES:
441 offset = ((fwu->f34_fd.version == 0) ? 2 : 1);
442 addr = fwu->f34_fd.query_base_addr + offset;
443 break;
444 case OFFSET_BLOCK_SIZE:
445 offset = ((fwu->f34_fd.version == 0) ? 3 : 2);
446 addr = fwu->f34_fd.query_base_addr + offset;
447 break;
448 case OFFSET_FW_BLOCK_COUNT:
449 offset = ((fwu->f34_fd.version == 0) ? 5 : 3);
450 addr = fwu->f34_fd.query_base_addr + offset;
451 break;
452 case OFFSET_BLOCK_NUMBER:
453 offset = 0;
454 addr = fwu->f34_fd.data_base_addr + offset;
455 break;
456 case OFFSET_BLOCK_DATA:
457 offset = ((fwu->f34_fd.version == 0) ? 2 : 1);
458 addr = fwu->f34_fd.data_base_addr + offset;
459 break;
460 case OFFSET_FLASH_CONTROL:
461 offset = ((fwu->f34_fd.version == 0) ?
462 2 + (fwu->block_size) : 2);
463 addr = fwu->f34_fd.data_base_addr + offset;
464 break;
465 case OFFSET_FLASH_STATUS:
466 if (fwu->f34_fd.version == 1) {
467 offset = 3;
468 addr = fwu->f34_fd.data_base_addr + offset;
469 } else if (fwu->f34_fd.version == 0) {
470 dev_warn(&i2c_client->dev,
471 "%s: F$34 version 0 does not contain " \
472 "flash status register\n",
473 __func__);
474 }
475 break;
476 default:
477 dev_err(&i2c_client->dev,
478 "%s: Unknown flash offset (%d)\n",
479 __func__, type);
480 break;
481 }
482 return addr;
483}
484
Alexandra Chin669d27c2012-12-24 15:42:30 +0800485static int fwu_read_f34_queries(void)
486{
487 int retval;
488 unsigned char count = 4;
489 unsigned char buf[10];
490 struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
491
492 retval = fwu->fn_ptr->read(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -0700493 fwu_get_address(OFFSET_BOOTLOADER_ID),
Alexandra Chin669d27c2012-12-24 15:42:30 +0800494 fwu->bootloader_id,
495 sizeof(fwu->bootloader_id));
496 if (retval < 0) {
497 dev_err(&i2c_client->dev,
498 "%s: Failed to read bootloader ID\n",
499 __func__);
500 return retval;
501 }
502
503 retval = fwu->fn_ptr->read(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -0700504 fwu_get_address(OFFSET_FLASH_PROPERTIES),
Alexandra Chin669d27c2012-12-24 15:42:30 +0800505 fwu->flash_properties.data,
506 sizeof(fwu->flash_properties.data));
507 if (retval < 0) {
508 dev_err(&i2c_client->dev,
509 "%s: Failed to read flash properties\n",
510 __func__);
511 return retval;
512 }
513
Alexandra Chind5591a62013-02-07 12:59:15 -0800514 dev_info(&i2c_client->dev, "%s perm:%d, bl:%d, display:%d\n",
Alexandra Chin669d27c2012-12-24 15:42:30 +0800515 __func__,
516 fwu->flash_properties.has_perm_config,
517 fwu->flash_properties.has_bl_config,
518 fwu->flash_properties.has_display_config);
519
520 if (fwu->flash_properties.has_perm_config)
521 count += 2;
522
523 if (fwu->flash_properties.has_bl_config)
524 count += 2;
525
526 if (fwu->flash_properties.has_display_config)
527 count += 2;
528
529 retval = fwu->fn_ptr->read(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -0700530 fwu_get_address(OFFSET_BLOCK_SIZE),
Alexandra Chin669d27c2012-12-24 15:42:30 +0800531 buf,
532 2);
533 if (retval < 0) {
534 dev_err(&i2c_client->dev,
535 "%s: Failed to read block size info\n",
536 __func__);
537 return retval;
538 }
539
540 batohs(&fwu->block_size, &(buf[0]));
541
542 retval = fwu->fn_ptr->read(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -0700543 fwu_get_address(OFFSET_FW_BLOCK_COUNT),
Alexandra Chin669d27c2012-12-24 15:42:30 +0800544 buf,
545 count);
546 if (retval < 0) {
547 dev_err(&i2c_client->dev,
Alexandra Chin400f26e2013-07-25 11:58:17 -0700548 "%s: Failed to read block count info\n",
549 __func__);
Alexandra Chin669d27c2012-12-24 15:42:30 +0800550 return retval;
551 }
552
553 batohs(&fwu->fw_block_count, &(buf[0]));
554 batohs(&fwu->config_block_count, &(buf[2]));
555
556 count = 4;
557
558 if (fwu->flash_properties.has_perm_config) {
559 batohs(&fwu->perm_config_block_count, &(buf[count]));
560 count += 2;
561 }
562
563 if (fwu->flash_properties.has_bl_config) {
564 batohs(&fwu->bl_config_block_count, &(buf[count]));
565 count += 2;
566 }
567
568 if (fwu->flash_properties.has_display_config)
569 batohs(&fwu->disp_config_block_count, &(buf[count]));
570
Alexandra Chin669d27c2012-12-24 15:42:30 +0800571 return 0;
572}
573
574static int fwu_read_interrupt_status(void)
575{
576 int retval;
577 unsigned char interrupt_status;
578 retval = fwu->fn_ptr->read(fwu->rmi4_data,
579 fwu->addr_f01_interrupt_register,
580 &interrupt_status,
581 sizeof(interrupt_status));
582 if (retval < 0) {
583 dev_err(&fwu->rmi4_data->i2c_client->dev,
584 "%s: Failed to read flash status\n",
585 __func__);
586 return retval;
587 }
588 return interrupt_status;
589}
590
Alexandra Chin400f26e2013-07-25 11:58:17 -0700591static int fwu_read_f34_flash_status(unsigned char *status)
Alexandra Chin669d27c2012-12-24 15:42:30 +0800592{
593 int retval;
Alexandra Chin400f26e2013-07-25 11:58:17 -0700594 struct f34_flash_control flash_control;
595 struct f34_flash_status flash_status;
596
597 if (fwu->f34_fd.version == 1) {
598 retval = fwu->fn_ptr->read(fwu->rmi4_data,
599 fwu_get_address(OFFSET_FLASH_STATUS),
600 flash_status.data,
601 sizeof(flash_status.data));
602 if (retval < 0) {
603 dev_err(&fwu->rmi4_data->i2c_client->dev,
Alexandra Chin669d27c2012-12-24 15:42:30 +0800604 "%s: Failed to read flash status\n",
605 __func__);
Alexandra Chin400f26e2013-07-25 11:58:17 -0700606 return -EIO;
607 }
608 *status = flash_status.status;
609 } else {
610 retval = fwu->fn_ptr->read(fwu->rmi4_data,
611 fwu_get_address(OFFSET_FLASH_CONTROL),
612 flash_control.data,
613 sizeof(flash_control.data));
614 if (retval < 0) {
615 dev_err(&fwu->rmi4_data->i2c_client->dev,
616 "%s: Failed to read flash status\n",
617 __func__);
618 return -EIO;
619 }
620 *status = flash_control.status;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800621 }
622 return 0;
623}
624
625static int fwu_reset_device(void)
626{
627 int retval;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800628
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700629 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
Alexandra Chind5591a62013-02-07 12:59:15 -0800630 "%s: Reset device\n",
631 __func__);
Alexandra Chin669d27c2012-12-24 15:42:30 +0800632
Alexandra Chin669d27c2012-12-24 15:42:30 +0800633 retval = fwu->rmi4_data->reset_device(fwu->rmi4_data);
634 if (retval < 0) {
635 dev_err(&fwu->rmi4_data->i2c_client->dev,
636 "%s: Failed to reset core driver after reflash\n",
637 __func__);
638 return retval;
639 }
Alexandra Chin400f26e2013-07-25 11:58:17 -0700640
641 fwu->polling_mode = false;
642
Alexandra Chin669d27c2012-12-24 15:42:30 +0800643 return 0;
644}
645
646static int fwu_write_f34_command(unsigned char cmd)
647{
648 int retval;
Alexandra Chin400f26e2013-07-25 11:58:17 -0700649 struct f34_flash_control flash_control;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800650
Alexandra Chin400f26e2013-07-25 11:58:17 -0700651 flash_control.data[0] = cmd;
652 fwu->interrupt_flag = false;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800653 retval = fwu->fn_ptr->write(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -0700654 fwu_get_address(OFFSET_FLASH_CONTROL),
655 flash_control.data,
656 sizeof(flash_control.data));
Alexandra Chin669d27c2012-12-24 15:42:30 +0800657 if (retval < 0) {
658 dev_err(&fwu->rmi4_data->i2c_client->dev,
659 "%s: Failed to write command 0x%02x\n",
Alexandra Chin400f26e2013-07-25 11:58:17 -0700660 __func__, flash_control.data[0]);
Alexandra Chin669d27c2012-12-24 15:42:30 +0800661 return retval;
662 }
663 return 0;
664}
665
Alexandra Chin669d27c2012-12-24 15:42:30 +0800666static int fwu_wait_for_idle(int timeout_ms)
667{
668 int count = 0;
Alexandra Chind5591a62013-02-07 12:59:15 -0800669 int timeout_count = ((timeout_ms * 1000) / SLEEP_TIME_US) + 1;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800670 do {
Alexandra Chin400f26e2013-07-25 11:58:17 -0700671 if (fwu->interrupt_flag)
Alexandra Chin669d27c2012-12-24 15:42:30 +0800672 return 0;
Alexandra Chin400f26e2013-07-25 11:58:17 -0700673 if (fwu->polling_mode)
674 if (fwu->intr_mask & fwu_read_interrupt_status())
675 return 0;
676 usleep_range(SLEEP_TIME_US, SLEEP_TIME_US + 1);
Alexandra Chind5591a62013-02-07 12:59:15 -0800677 } while (count++ < timeout_count);
678
Alexandra Chin400f26e2013-07-25 11:58:17 -0700679 if (fwu->intr_mask & fwu_read_interrupt_status()) {
680 fwu->polling_mode = true;
681 dev_info(&fwu->rmi4_data->i2c_client->dev,
682 "%s: Switch to polling mode\n",
683 __func__);
Alexandra Chind5591a62013-02-07 12:59:15 -0800684 return 0;
Alexandra Chin400f26e2013-07-25 11:58:17 -0700685 }
Alexandra Chin669d27c2012-12-24 15:42:30 +0800686
687 dev_err(&fwu->rmi4_data->i2c_client->dev,
688 "%s: Timed out waiting for idle status\n",
689 __func__);
690
691 return -ETIMEDOUT;
692}
693
Alexandra Chin823a2f52013-07-29 16:09:52 -0700694static enum flash_area fwu_go_nogo(void)
Alexandra Chind5591a62013-02-07 12:59:15 -0800695{
696 int retval = 0;
697 int index = 0;
698 int deviceFirmwareID;
699 int imageConfigID;
700 int deviceConfigID;
701 unsigned long imageFirmwareID;
702 unsigned char firmware_id[4];
703 unsigned char config_id[4];
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700704 unsigned char pkg_id[4];
Alexandra Chind5591a62013-02-07 12:59:15 -0800705 char *strptr;
706 char *imagePR = kzalloc(sizeof(MAX_FIRMWARE_ID_LEN), GFP_KERNEL);
707 enum flash_area flash_area = NONE;
708 struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
709 struct f01_device_status f01_device_status;
Alexandra Chin823a2f52013-07-29 16:09:52 -0700710 struct image_content *img = &fwu->image_content;
Alexandra Chind5591a62013-02-07 12:59:15 -0800711
712 if (fwu->force_update) {
713 flash_area = UI_FIRMWARE;
714 goto exit;
715 }
716
Alexandra Chin823a2f52013-07-29 16:09:52 -0700717 if (img->is_contain_build_info) {
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700718 /* if package id does not match, do not update firmware */
719 fwu->fn_ptr->read(fwu->rmi4_data,
720 fwu->f01_fd.query_base_addr + 17,
721 pkg_id,
722 sizeof(pkg_id));
723
Alexandra Chin823a2f52013-07-29 16:09:52 -0700724 if (img->package_id != ((pkg_id[1] << 8) | pkg_id[0])) {
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700725 flash_area = MISMATCH;
726 goto exit;
727 }
Alexandra Chin823a2f52013-07-29 16:09:52 -0700728 if (img->package_revision_id !=
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700729 ((pkg_id[3] << 8) | pkg_id[2])) {
730 flash_area = MISMATCH;
731 goto exit;
732 }
733 }
734
Alexandra Chin400f26e2013-07-25 11:58:17 -0700735 /* check firmware size */
Alexandra Chin823a2f52013-07-29 16:09:52 -0700736 if (fwu->fw_block_count*fwu->block_size != img->image_size) {
Alexandra Chin400f26e2013-07-25 11:58:17 -0700737 dev_err(&i2c_client->dev,
738 "%s: firmware size of device (%d) != .img (%d)\n",
739 __func__,
740 fwu->config_block_count * fwu->block_size,
Alexandra Chin823a2f52013-07-29 16:09:52 -0700741 img->image_size);
Alexandra Chin400f26e2013-07-25 11:58:17 -0700742 flash_area = NONE;
743 goto exit;
744 }
745
746 /* check config size */
Alexandra Chin823a2f52013-07-29 16:09:52 -0700747 if (fwu->config_block_count*fwu->block_size != img->config_size) {
Alexandra Chin400f26e2013-07-25 11:58:17 -0700748 dev_err(&i2c_client->dev,
749 "%s: config size of device (%d) != .img (%d)\n",
750 __func__,
751 fwu->config_block_count * fwu->block_size,
Alexandra Chin823a2f52013-07-29 16:09:52 -0700752 img->config_size);
Alexandra Chin400f26e2013-07-25 11:58:17 -0700753 flash_area = NONE;
754 goto exit;
755 }
756
Alexandra Chind5591a62013-02-07 12:59:15 -0800757 retval = fwu_read_f01_device_status(&f01_device_status);
758 if (retval < 0) {
759 flash_area = NONE;
760 goto exit;
761 }
762
Alexandra Chind5591a62013-02-07 12:59:15 -0800763 /* Force update firmware when device is in bootloader mode */
764 if (f01_device_status.flash_prog) {
765 dev_info(&i2c_client->dev,
766 "%s: In flash prog mode\n",
767 __func__);
768 flash_area = UI_FIRMWARE;
769 goto exit;
770 }
771
Alexandra Chind5591a62013-02-07 12:59:15 -0800772 /* device firmware id */
773 retval = fwu->fn_ptr->read(fwu->rmi4_data,
774 fwu->f01_fd.query_base_addr + 18,
775 firmware_id,
776 sizeof(firmware_id));
777 if (retval < 0) {
778 dev_err(&i2c_client->dev,
Amy Malocheafcecb22013-04-16 18:43:22 -0700779 "%s: Failed to read firmware ID (code %d).\n",
780 __func__, retval);
Alexandra Chind5591a62013-02-07 12:59:15 -0800781 goto exit;
782 }
783 firmware_id[3] = 0;
784 deviceFirmwareID = extract_uint(firmware_id);
785
786 /* .img firmware id */
Alexandra Chin823a2f52013-07-29 16:09:52 -0700787 if (img->is_contain_build_info) {
Alexandra Chind5591a62013-02-07 12:59:15 -0800788 dev_err(&i2c_client->dev,
Amy Malocheafcecb22013-04-16 18:43:22 -0700789 "%s: Image option contains build info.\n",
790 __func__);
Alexandra Chin823a2f52013-07-29 16:09:52 -0700791 imageFirmwareID = img->firmware_id;
Amy Malocheafcecb22013-04-16 18:43:22 -0700792 } else {
Alexandra Chin823a2f52013-07-29 16:09:52 -0700793 if (!fwu->image_name) {
794 dev_info(&i2c_client->dev,
795 "%s: Unknown image file name\n",
796 __func__);
797 flash_area = UI_FIRMWARE;
798 goto exit;
799 }
800 strptr = strnstr(fwu->image_name, "PR",
801 sizeof(fwu->image_name));
Amy Malocheafcecb22013-04-16 18:43:22 -0700802 if (!strptr) {
803 dev_err(&i2c_client->dev,
804 "No valid PR number (PRxxxxxxx)" \
805 "found in image file name...\n");
806 goto exit;
807 }
808
809 strptr += 2;
810 while (strptr[index] >= '0' && strptr[index] <= '9') {
811 imagePR[index] = strptr[index];
812 index++;
813 }
814 imagePR[index] = 0;
815
816 retval = kstrtoul(imagePR, 10, &imageFirmwareID);
817 if (retval == -EINVAL) {
818 dev_err(&i2c_client->dev,
819 "invalid image firmware id...\n");
820 goto exit;
821 }
Alexandra Chind5591a62013-02-07 12:59:15 -0800822 }
823
Amy Malocheafcecb22013-04-16 18:43:22 -0700824 dev_dbg(&i2c_client->dev,
Alexandra Chind5591a62013-02-07 12:59:15 -0800825 "Device firmware id %d, .img firmware id %d\n",
826 deviceFirmwareID,
827 (unsigned int)imageFirmwareID);
828 if (imageFirmwareID > deviceFirmwareID) {
829 flash_area = UI_FIRMWARE;
830 goto exit;
Alexandra Chinc556cf02013-03-19 17:46:05 -0700831 } else if (imageFirmwareID < deviceFirmwareID) {
832 flash_area = NONE;
833 dev_info(&i2c_client->dev,
Amy Malocheafcecb22013-04-16 18:43:22 -0700834 "%s: Img fw is older than device fw. Skip fw update.\n",
835 __func__);
Alexandra Chinc556cf02013-03-19 17:46:05 -0700836 goto exit;
Alexandra Chind5591a62013-02-07 12:59:15 -0800837 }
838
839 /* device config id */
840 retval = fwu->fn_ptr->read(fwu->rmi4_data,
841 fwu->f34_fd.ctrl_base_addr,
842 config_id,
843 sizeof(config_id));
844 if (retval < 0) {
845 dev_err(&i2c_client->dev,
Amy Malocheafcecb22013-04-16 18:43:22 -0700846 "%s: Failed to read config ID (code %d).\n",
847 __func__, retval);
Alexandra Chind5591a62013-02-07 12:59:15 -0800848 flash_area = NONE;
849 goto exit;
850 }
Amy Malocheafcecb22013-04-16 18:43:22 -0700851 deviceConfigID = extract_uint_be(config_id);
Alexandra Chind5591a62013-02-07 12:59:15 -0800852
Amy Malocheafcecb22013-04-16 18:43:22 -0700853 dev_dbg(&i2c_client->dev,
Alexandra Chind5591a62013-02-07 12:59:15 -0800854 "Device config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
855 config_id[0], config_id[1], config_id[2], config_id[3]);
856
857 /* .img config id */
Amy Malocheafcecb22013-04-16 18:43:22 -0700858 dev_dbg(&i2c_client->dev,
Alexandra Chind5591a62013-02-07 12:59:15 -0800859 ".img config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
860 fwu->config_data[0],
861 fwu->config_data[1],
862 fwu->config_data[2],
863 fwu->config_data[3]);
Amy Malocheafcecb22013-04-16 18:43:22 -0700864 imageConfigID = extract_uint_be(fwu->config_data);
865
866 dev_dbg(&i2c_client->dev,
867 "%s: Device config ID %d, .img config ID %d\n",
868 __func__, deviceConfigID, imageConfigID);
Alexandra Chind5591a62013-02-07 12:59:15 -0800869
870 if (imageConfigID > deviceConfigID) {
871 flash_area = CONFIG_AREA;
872 goto exit;
873 }
Alexandra Chind5591a62013-02-07 12:59:15 -0800874exit:
875 kfree(imagePR);
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700876 if (flash_area == MISMATCH)
877 dev_info(&i2c_client->dev,
878 "%s: Package ID indicates mismatch of firmware and" \
879 " controller compatibility\n", __func__);
880 else if (flash_area == NONE)
Alexandra Chind5591a62013-02-07 12:59:15 -0800881 dev_info(&i2c_client->dev,
Amy Malocheafcecb22013-04-16 18:43:22 -0700882 "%s: Nothing needs to be updated\n", __func__);
Alexandra Chind5591a62013-02-07 12:59:15 -0800883 else
884 dev_info(&i2c_client->dev,
Amy Malocheafcecb22013-04-16 18:43:22 -0700885 "%s: Update %s block\n", __func__,
Alexandra Chind5591a62013-02-07 12:59:15 -0800886 flash_area == UI_FIRMWARE ? "UI FW" : "CONFIG");
887 return flash_area;
888}
889
Alexandra Chin669d27c2012-12-24 15:42:30 +0800890static int fwu_scan_pdt(void)
891{
892 int retval;
893 unsigned char ii;
894 unsigned char intr_count = 0;
895 unsigned char intr_off;
896 unsigned char intr_src;
897 unsigned short addr;
898 bool f01found = false;
899 bool f34found = false;
900 struct synaptics_rmi4_fn_desc rmi_fd;
901
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700902 dev_dbg(&fwu->rmi4_data->i2c_client->dev, "Scan PDT\n");
Alexandra Chin669d27c2012-12-24 15:42:30 +0800903
904 for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) {
905 retval = fwu->fn_ptr->read(fwu->rmi4_data,
906 addr,
907 (unsigned char *)&rmi_fd,
908 sizeof(rmi_fd));
909 if (retval < 0)
910 return retval;
911
912 if (rmi_fd.fn_number) {
913 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
914 "%s: Found F%02x\n",
915 __func__, rmi_fd.fn_number);
916 switch (rmi_fd.fn_number) {
917 case SYNAPTICS_RMI4_F01:
918 f01found = true;
919 fwu->f01_fd = rmi_fd;
920 fwu->addr_f01_interrupt_register =
921 fwu->f01_fd.data_base_addr + 1;
922 break;
923 case SYNAPTICS_RMI4_F34:
924 f34found = true;
925 fwu->f34_fd = rmi_fd;
926 fwu->intr_mask = 0;
927 intr_src = rmi_fd.intr_src_count;
928 intr_off = intr_count % 8;
929 for (ii = intr_off;
930 ii < ((intr_src & MASK_3BIT) +
931 intr_off);
932 ii++)
933 fwu->intr_mask |= 1 << ii;
934 break;
935 }
936 } else
937 break;
938
939 intr_count += (rmi_fd.intr_src_count & MASK_3BIT);
940 }
941
942 if (!f01found || !f34found) {
943 dev_err(&fwu->rmi4_data->i2c_client->dev,
944 "%s: Failed to find both F01 and F34\n",
945 __func__);
946 return -EINVAL;
947 }
948
949 fwu_read_interrupt_status();
950 return 0;
951}
952
953static int fwu_write_blocks(unsigned char *block_ptr, unsigned short block_cnt,
954 unsigned char command)
955{
956 int retval;
Alexandra Chin400f26e2013-07-25 11:58:17 -0700957 unsigned char flash_status;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800958 unsigned char block_offset[] = {0, 0};
959 unsigned short block_num;
Alexandra Chin400f26e2013-07-25 11:58:17 -0700960 unsigned short addr_block_data = fwu_get_address(OFFSET_BLOCK_DATA);
961 unsigned short addr_block_num = fwu_get_address(OFFSET_BLOCK_NUMBER);
Alexandra Chind5591a62013-02-07 12:59:15 -0800962 struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800963#ifdef SHOW_PROGRESS
Alexandra Chin823a2f52013-07-29 16:09:52 -0700964 unsigned int progress;
965 unsigned char command_str[10];
966 switch (command) {
967 case CMD_WRITE_CONFIG_BLOCK:
968 progress = 10;
969 strlcpy(command_str, "config", 10);
970 break;
971 case CMD_WRITE_FW_BLOCK:
972 progress = 100;
973 strlcpy(command_str, "firmware", 10);
974 break;
975 case CMD_WRITE_LOCKDOWN_BLOCK:
976 progress = 1;
977 strlcpy(command_str, "lockdown", 10);
978 break;
979 default:
980 progress = 1;
981 strlcpy(command_str, "unknown", 10);
982 break;
983 }
Alexandra Chin669d27c2012-12-24 15:42:30 +0800984#endif
Alexandra Chind5591a62013-02-07 12:59:15 -0800985
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700986 dev_dbg(&i2c_client->dev,
Alexandra Chind5591a62013-02-07 12:59:15 -0800987 "%s: Start to update %s blocks\n",
988 __func__,
Alexandra Chin823a2f52013-07-29 16:09:52 -0700989 command_str);
Alexandra Chin669d27c2012-12-24 15:42:30 +0800990 retval = fwu->fn_ptr->write(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -0700991 addr_block_num,
Alexandra Chin669d27c2012-12-24 15:42:30 +0800992 block_offset,
993 sizeof(block_offset));
994 if (retval < 0) {
Alexandra Chind5591a62013-02-07 12:59:15 -0800995 dev_err(&i2c_client->dev,
Alexandra Chin669d27c2012-12-24 15:42:30 +0800996 "%s: Failed to write to block number registers\n",
997 __func__);
998 return retval;
999 }
1000
1001 for (block_num = 0; block_num < block_cnt; block_num++) {
1002#ifdef SHOW_PROGRESS
1003 if (block_num % progress == 0)
Alexandra Chind5591a62013-02-07 12:59:15 -08001004 dev_info(&i2c_client->dev,
1005 "%s: update %s %3d / %3d\n",
1006 __func__,
Alexandra Chin823a2f52013-07-29 16:09:52 -07001007 command_str,
Alexandra Chind5591a62013-02-07 12:59:15 -08001008 block_num, block_cnt);
Alexandra Chin669d27c2012-12-24 15:42:30 +08001009#endif
1010 retval = fwu->fn_ptr->write(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -07001011 addr_block_data,
Alexandra Chin669d27c2012-12-24 15:42:30 +08001012 block_ptr,
1013 fwu->block_size);
1014 if (retval < 0) {
Alexandra Chind5591a62013-02-07 12:59:15 -08001015 dev_err(&i2c_client->dev,
Alexandra Chin669d27c2012-12-24 15:42:30 +08001016 "%s: Failed to write block data (block %d)\n",
1017 __func__, block_num);
1018 return retval;
1019 }
1020
1021 retval = fwu_write_f34_command(command);
1022 if (retval < 0) {
Alexandra Chind5591a62013-02-07 12:59:15 -08001023 dev_err(&i2c_client->dev,
Alexandra Chin669d27c2012-12-24 15:42:30 +08001024 "%s: Failed to write command for block %d\n",
1025 __func__, block_num);
1026 return retval;
1027 }
1028
1029 retval = fwu_wait_for_idle(WRITE_WAIT_MS);
1030 if (retval < 0) {
Alexandra Chind5591a62013-02-07 12:59:15 -08001031 dev_err(&i2c_client->dev,
1032 "%s: Failed to wait for idle status (block %d)\n",
1033 __func__, block_num);
Alexandra Chin669d27c2012-12-24 15:42:30 +08001034 return retval;
1035 }
1036
Alexandra Chin400f26e2013-07-25 11:58:17 -07001037 #if CHECK_FLASH_BLOCK_STATUS
1038 retval = fwu_read_f34_flash_status(&flash_status);
1039 if (retval < 0) {
Alexandra Chind5591a62013-02-07 12:59:15 -08001040 dev_err(&i2c_client->dev,
Alexandra Chin400f26e2013-07-25 11:58:17 -07001041 "%s: Failed to read flash status (block %d)\n",
1042 __func__, block_num);
Shantanu Jain41f0d472013-01-04 12:14:37 +05301043 return retval;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001044 }
Alexandra Chin400f26e2013-07-25 11:58:17 -07001045 if (flash_status != 0x00) {
1046 dev_err(&i2c_client->dev,
1047 "%s: Flash block %d failed, status 0x%02X\n",
1048 __func__, block_num, flash_status);
1049 return -EINVAL;
1050 }
1051 #endif
Alexandra Chin669d27c2012-12-24 15:42:30 +08001052 block_ptr += fwu->block_size;
1053 }
1054#ifdef SHOW_PROGRESS
Alexandra Chind5591a62013-02-07 12:59:15 -08001055 dev_info(&i2c_client->dev,
1056 "%s: update %s %3d / %3d\n",
1057 __func__,
Alexandra Chin823a2f52013-07-29 16:09:52 -07001058 command_str,
Alexandra Chind5591a62013-02-07 12:59:15 -08001059 block_cnt, block_cnt);
Alexandra Chin669d27c2012-12-24 15:42:30 +08001060#endif
1061 return 0;
1062}
1063
1064static int fwu_write_firmware(void)
1065{
1066 return fwu_write_blocks((unsigned char *)fwu->firmware_data,
1067 fwu->fw_block_count, CMD_WRITE_FW_BLOCK);
1068}
1069
1070static int fwu_write_configuration(void)
1071{
1072 return fwu_write_blocks((unsigned char *)fwu->config_data,
1073 fwu->config_block_count, CMD_WRITE_CONFIG_BLOCK);
1074}
1075
Alexandra Chin823a2f52013-07-29 16:09:52 -07001076static int fwu_write_lockdown_block(void)
1077{
1078 return fwu_write_blocks((unsigned char *)fwu->lockdown_data,
1079 fwu->lockdown_block_count, CMD_WRITE_LOCKDOWN_BLOCK);
1080}
1081
Alexandra Chin669d27c2012-12-24 15:42:30 +08001082static int fwu_write_bootloader_id(void)
1083{
1084 int retval;
1085
Amy Maloche2c4c48c2013-05-01 20:06:23 -07001086 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
Alexandra Chind5591a62013-02-07 12:59:15 -08001087 "Write bootloader ID 0x%02X 0x%02X\n",
1088 fwu->bootloader_id[0],
1089 fwu->bootloader_id[1]);
Amy Maloche2c4c48c2013-05-01 20:06:23 -07001090
Alexandra Chin669d27c2012-12-24 15:42:30 +08001091 retval = fwu->fn_ptr->write(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -07001092 fwu_get_address(OFFSET_BLOCK_DATA),
Alexandra Chin669d27c2012-12-24 15:42:30 +08001093 fwu->bootloader_id,
1094 sizeof(fwu->bootloader_id));
1095 if (retval < 0) {
1096 dev_err(&fwu->rmi4_data->i2c_client->dev,
1097 "%s: Failed to write bootloader ID\n",
1098 __func__);
1099 return retval;
1100 }
1101
1102 return 0;
1103}
1104
Alexandra Chin823a2f52013-07-29 16:09:52 -07001105static int fwu_enter_flash_prog(bool force)
Alexandra Chin669d27c2012-12-24 15:42:30 +08001106{
1107 int retval;
1108 struct f01_device_status f01_device_status;
1109 struct f01_device_control f01_device_control;
1110
Amy Maloche2c4c48c2013-05-01 20:06:23 -07001111 dev_dbg(&fwu->rmi4_data->i2c_client->dev, "Enter bootloader mode\n");
1112
Alexandra Chin669d27c2012-12-24 15:42:30 +08001113 retval = fwu_read_f01_device_status(&f01_device_status);
1114 if (retval < 0)
1115 return retval;
1116
Amy Malochecb78b1d2013-08-27 16:34:11 -07001117 if (force) {
1118 dev_info(&fwu->rmi4_data->i2c_client->dev,
1119 "%s: Force to enter flash prog mode\n",
1120 __func__);
1121 } else if (f01_device_status.flash_prog) {
Alexandra Chin669d27c2012-12-24 15:42:30 +08001122 dev_info(&fwu->rmi4_data->i2c_client->dev,
1123 "%s: Already in flash prog mode\n",
1124 __func__);
1125 return 0;
1126 }
1127
1128 retval = fwu_write_bootloader_id();
1129 if (retval < 0)
1130 return retval;
1131
1132 retval = fwu_write_f34_command(CMD_ENABLE_FLASH_PROG);
1133 if (retval < 0)
1134 return retval;
1135
1136 retval = fwu_wait_for_idle(ENABLE_WAIT_MS);
1137 if (retval < 0)
1138 return retval;
1139
Alexandra Chin669d27c2012-12-24 15:42:30 +08001140 retval = fwu_scan_pdt();
1141 if (retval < 0)
1142 return retval;
1143
1144 retval = fwu_read_f01_device_status(&f01_device_status);
1145 if (retval < 0)
1146 return retval;
1147
1148 if (!f01_device_status.flash_prog) {
1149 dev_err(&fwu->rmi4_data->i2c_client->dev,
1150 "%s: Not in flash prog mode\n",
1151 __func__);
1152 return -EINVAL;
1153 }
1154
1155 retval = fwu_read_f34_queries();
1156 if (retval < 0)
1157 return retval;
1158
1159 retval = fwu->fn_ptr->read(fwu->rmi4_data,
1160 fwu->f01_fd.ctrl_base_addr,
1161 f01_device_control.data,
1162 sizeof(f01_device_control.data));
1163 if (retval < 0) {
1164 dev_err(&fwu->rmi4_data->i2c_client->dev,
1165 "%s: Failed to read F01 device control\n",
1166 __func__);
1167 return retval;
1168 }
1169
1170 f01_device_control.nosleep = true;
1171 f01_device_control.sleep_mode = SLEEP_MODE_NORMAL;
1172
1173 retval = fwu->fn_ptr->write(fwu->rmi4_data,
1174 fwu->f01_fd.ctrl_base_addr,
1175 f01_device_control.data,
1176 sizeof(f01_device_control.data));
1177 if (retval < 0) {
1178 dev_err(&fwu->rmi4_data->i2c_client->dev,
1179 "%s: Failed to write F01 device control\n",
1180 __func__);
1181 return retval;
1182 }
Alexandra Chin400f26e2013-07-25 11:58:17 -07001183 fwu->polling_mode = false;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001184 return retval;
1185}
1186
Alexandra Chin669d27c2012-12-24 15:42:30 +08001187static int fwu_do_write_config(void)
1188{
1189 int retval;
1190
Alexandra Chin823a2f52013-07-29 16:09:52 -07001191 retval = fwu_enter_flash_prog(false);
Alexandra Chin669d27c2012-12-24 15:42:30 +08001192 if (retval < 0)
1193 return retval;
1194
1195 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1196 "%s: Entered flash prog mode\n",
1197 __func__);
1198
1199 if (fwu->config_area == PERM_CONFIG_AREA) {
1200 fwu->config_block_count = fwu->perm_config_block_count;
1201 goto write_config;
1202 }
1203
1204 retval = fwu_write_bootloader_id();
1205 if (retval < 0)
1206 return retval;
1207
1208 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1209 "%s: Bootloader ID written\n",
1210 __func__);
1211
1212 switch (fwu->config_area) {
1213 case UI_CONFIG_AREA:
1214 retval = fwu_write_f34_command(CMD_ERASE_CONFIG);
1215 break;
1216 case BL_CONFIG_AREA:
1217 retval = fwu_write_f34_command(CMD_ERASE_BL_CONFIG);
1218 fwu->config_block_count = fwu->bl_config_block_count;
1219 break;
1220 case DISP_CONFIG_AREA:
1221 retval = fwu_write_f34_command(CMD_ERASE_DISP_CONFIG);
1222 fwu->config_block_count = fwu->disp_config_block_count;
1223 break;
1224 }
1225 if (retval < 0)
1226 return retval;
1227
1228 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1229 "%s: Erase command written\n",
1230 __func__);
1231
1232 retval = fwu_wait_for_idle(ERASE_WAIT_MS);
1233 if (retval < 0)
1234 return retval;
1235
1236 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1237 "%s: Idle status detected\n",
1238 __func__);
1239
1240write_config:
1241 retval = fwu_write_configuration();
1242 if (retval < 0)
1243 return retval;
1244
1245 pr_notice("%s: Config written\n", __func__);
1246
1247 return retval;
1248}
1249
1250static int fwu_start_write_config(void)
1251{
1252 int retval;
Alexandra Chin823a2f52013-07-29 16:09:52 -07001253 int block_count;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001254
1255 switch (fwu->config_area) {
1256 case UI_CONFIG_AREA:
Alexandra Chin823a2f52013-07-29 16:09:52 -07001257 block_count = fwu->config_block_count;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001258 break;
1259 case PERM_CONFIG_AREA:
1260 if (!fwu->flash_properties.has_perm_config)
1261 return -EINVAL;
Alexandra Chin823a2f52013-07-29 16:09:52 -07001262 block_count = fwu->perm_config_block_count;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001263 break;
1264 case BL_CONFIG_AREA:
1265 if (!fwu->flash_properties.has_bl_config)
1266 return -EINVAL;
Alexandra Chin823a2f52013-07-29 16:09:52 -07001267 block_count = fwu->bl_config_block_count;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001268 break;
1269 case DISP_CONFIG_AREA:
1270 if (!fwu->flash_properties.has_display_config)
1271 return -EINVAL;
Alexandra Chin823a2f52013-07-29 16:09:52 -07001272 block_count = fwu->disp_config_block_count;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001273 break;
1274 default:
1275 return -EINVAL;
1276 }
1277
Alexandra Chin823a2f52013-07-29 16:09:52 -07001278 if (fwu->image_size == block_count*fwu->block_size) {
1279 dev_info(&fwu->rmi4_data->i2c_client->dev,
1280 "%s: write config from config file\n",
1281 __func__);
1282 fwu->config_data = fwu->data_buffer;
1283 } else {
1284 parse_header();
Alexandra Chin669d27c2012-12-24 15:42:30 +08001285 }
1286
1287 pr_notice("%s: Start of write config process\n", __func__);
1288
1289 retval = fwu_do_write_config();
1290 if (retval < 0) {
1291 dev_err(&fwu->rmi4_data->i2c_client->dev,
1292 "%s: Failed to write config\n",
1293 __func__);
1294 }
1295
1296 fwu->rmi4_data->reset_device(fwu->rmi4_data);
1297
1298 pr_notice("%s: End of write config process\n", __func__);
1299
1300 return retval;
1301}
1302
Alexandra Chin823a2f52013-07-29 16:09:52 -07001303static int fwu_do_write_lockdown(bool reset)
1304{
1305 int retval;
1306
1307 pr_notice("%s: Start of lockdown process\n", __func__);
1308
1309 retval = fwu_enter_flash_prog(false);
1310 if (retval < 0)
1311 return retval;
1312
1313 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1314 "%s: Entered flash prog mode\n",
1315 __func__);
1316
1317 if (fwu->flash_properties.unlocked == 0) {
1318 dev_err(&fwu->rmi4_data->i2c_client->dev,
1319 "%s: Device has been locked!\n",
1320 __func__);
1321 if (reset)
1322 goto exit;
1323 else
1324 return -EINVAL;
1325 }
1326
1327 retval = fwu_write_lockdown_block();
1328 if (retval < 0)
1329 return retval;
1330
1331 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1332 "%s:Lockdown device\n",
1333 __func__);
1334
1335exit:
1336 if (reset)
1337 retval = fwu->rmi4_data->reset_device(fwu->rmi4_data);
1338 else
1339 retval = fwu_enter_flash_prog(true);
1340
1341 if (retval < 0)
1342 return retval;
1343
1344 pr_notice("%s: End of lockdown process\n", __func__);
1345
1346 return retval;
1347}
1348
1349static int fwu_start_write_lockdown(void)
1350{
1351 parse_header();
1352 return fwu_do_write_lockdown(true);
1353}
1354
Alexandra Chin669d27c2012-12-24 15:42:30 +08001355static int fwu_do_read_config(void)
1356{
1357 int retval;
1358 unsigned char block_offset[] = {0, 0};
1359 unsigned short block_num;
1360 unsigned short block_count;
1361 unsigned short index = 0;
1362
Alexandra Chin669d27c2012-12-24 15:42:30 +08001363 switch (fwu->config_area) {
1364 case UI_CONFIG_AREA:
1365 block_count = fwu->config_block_count;
1366 break;
1367 case PERM_CONFIG_AREA:
1368 if (!fwu->flash_properties.has_perm_config) {
1369 retval = -EINVAL;
1370 goto exit;
1371 }
1372 block_count = fwu->perm_config_block_count;
1373 break;
1374 case BL_CONFIG_AREA:
1375 if (!fwu->flash_properties.has_bl_config) {
1376 retval = -EINVAL;
1377 goto exit;
1378 }
1379 block_count = fwu->bl_config_block_count;
1380 break;
1381 case DISP_CONFIG_AREA:
1382 if (!fwu->flash_properties.has_display_config) {
1383 retval = -EINVAL;
1384 goto exit;
1385 }
1386 block_count = fwu->disp_config_block_count;
1387 break;
1388 default:
1389 retval = -EINVAL;
1390 goto exit;
1391 }
1392
1393 fwu->config_size = fwu->block_size * block_count;
1394
1395 kfree(fwu->read_config_buf);
1396 fwu->read_config_buf = kzalloc(fwu->config_size, GFP_KERNEL);
1397
1398 block_offset[1] |= (fwu->config_area << 5);
1399
1400 retval = fwu->fn_ptr->write(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -07001401 fwu_get_address(OFFSET_BLOCK_NUMBER),
Alexandra Chin669d27c2012-12-24 15:42:30 +08001402 block_offset,
1403 sizeof(block_offset));
1404 if (retval < 0) {
1405 dev_err(&fwu->rmi4_data->i2c_client->dev,
1406 "%s: Failed to write to block number registers\n",
1407 __func__);
1408 goto exit;
1409 }
1410
1411 for (block_num = 0; block_num < block_count; block_num++) {
1412 retval = fwu_write_f34_command(CMD_READ_CONFIG_BLOCK);
1413 if (retval < 0) {
1414 dev_err(&fwu->rmi4_data->i2c_client->dev,
1415 "%s: Failed to write read config command\n",
1416 __func__);
1417 goto exit;
1418 }
1419
1420 retval = fwu_wait_for_idle(WRITE_WAIT_MS);
1421 if (retval < 0) {
1422 dev_err(&fwu->rmi4_data->i2c_client->dev,
1423 "%s: Failed to wait for idle status\n",
1424 __func__);
1425 goto exit;
1426 }
1427
1428 retval = fwu->fn_ptr->read(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -07001429 fwu_get_address(OFFSET_BLOCK_DATA),
Alexandra Chin669d27c2012-12-24 15:42:30 +08001430 &fwu->read_config_buf[index],
1431 fwu->block_size);
1432 if (retval < 0) {
1433 dev_err(&fwu->rmi4_data->i2c_client->dev,
1434 "%s: Failed to read block data (block %d)\n",
1435 __func__, block_num);
1436 goto exit;
1437 }
1438
1439 index += fwu->block_size;
1440 }
1441
1442exit:
Alexandra Chin823a2f52013-07-29 16:09:52 -07001443 return retval;
1444}
1445
1446static int fwu_do_reflash(void)
1447{
1448 int retval;
1449 unsigned char flash_status;
1450
1451 if (fwu->do_lockdown) {
1452 retval = fwu_do_write_lockdown(false);
1453 if (retval < 0)
1454 dev_warn(&fwu->rmi4_data->i2c_client->dev,
1455 "%s: Skip lockdown process.\n",
1456 __func__);
1457 }
1458 retval = fwu_enter_flash_prog(false);
1459 if (retval < 0)
1460 return retval;
1461 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1462 "%s: Entered flash prog mode\n",
1463 __func__);
1464
1465 retval = fwu_write_bootloader_id();
1466 if (retval < 0)
1467 return retval;
1468
1469 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1470 "%s: Bootloader ID written\n",
1471 __func__);
1472
1473 retval = fwu_write_f34_command(CMD_ERASE_ALL);
1474 if (retval < 0)
1475 return retval;
1476
1477 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1478 "%s: Erase all command written\n",
1479 __func__);
1480
Amy Malochecb78b1d2013-08-27 16:34:11 -07001481 if (fwu->polling_mode)
1482 msleep(100);
1483
Alexandra Chin823a2f52013-07-29 16:09:52 -07001484 retval = fwu_wait_for_idle(ERASE_WAIT_MS);
1485 if (retval < 0)
1486 return retval;
1487
1488 retval = fwu_read_f34_flash_status(&flash_status);
1489 if (retval < 0)
1490 return retval;
1491 if (flash_status != 0x00) {
1492 dev_err(&fwu->rmi4_data->i2c_client->dev,
1493 "%s: Erase all command failed, status 0x%02X\n",
1494 __func__, flash_status);
1495 return -EINVAL;
1496 }
1497
1498 if (fwu->firmware_data) {
1499 retval = fwu_write_firmware();
1500 if (retval < 0)
1501 return retval;
1502 pr_notice("%s: Firmware programmed\n", __func__);
1503 }
1504
1505 if (fwu->config_data) {
1506 retval = fwu_write_configuration();
1507 if (retval < 0)
1508 return retval;
1509 pr_notice("%s: Configuration programmed\n", __func__);
1510 }
Alexandra Chin669d27c2012-12-24 15:42:30 +08001511
1512 return retval;
1513}
1514
Alexandra Chind5591a62013-02-07 12:59:15 -08001515static int fwu_start_reflash(void)
1516{
Amy Malocheafcecb22013-04-16 18:43:22 -07001517 int retval = 0;
Alexandra Chind5591a62013-02-07 12:59:15 -08001518 const struct firmware *fw_entry = NULL;
1519 struct f01_device_status f01_device_status;
1520 enum flash_area flash_area;
1521
1522 pr_notice("%s: Start of reflash process\n", __func__);
1523
1524 if (fwu->ext_data_source)
Alexandra Chin823a2f52013-07-29 16:09:52 -07001525 dev_info(&fwu->rmi4_data->i2c_client->dev,
1526 "%s Load .img file from commandline.\n",
1527 __func__);
Alexandra Chind5591a62013-02-07 12:59:15 -08001528 else {
Alexandra Chin400f26e2013-07-25 11:58:17 -07001529 if (strnlen(fwu->rmi4_data->fw_image_name,
1530 NAME_BUFFER_SIZE) == 0) {
1531 dev_err(&fwu->rmi4_data->i2c_client->dev,
1532 "Firmware image name not given, "\
1533 "skipping update\n");
1534 return 0;
1535 }
1536
1537 if (strnlen(fwu->rmi4_data->fw_image_name, NAME_BUFFER_SIZE) ==
1538 NAME_BUFFER_SIZE) {
1539 dev_err(&fwu->rmi4_data->i2c_client->dev,
1540 "Firmware image name exceeds max length " \
1541 "(%d), skipping update\n", NAME_BUFFER_SIZE);
1542 return 0;
1543 }
1544
Alexandra Chin823a2f52013-07-29 16:09:52 -07001545 snprintf(fwu->image_name, NAME_BUFFER_SIZE, "%s",
Amy Malocheafcecb22013-04-16 18:43:22 -07001546 fwu->rmi4_data->fw_image_name);
1547 dev_info(&fwu->rmi4_data->i2c_client->dev,
1548 "%s: Requesting firmware image %s\n",
Alexandra Chin823a2f52013-07-29 16:09:52 -07001549 __func__, fwu->image_name);
Alexandra Chind5591a62013-02-07 12:59:15 -08001550
Amy Malochecb835832013-03-26 18:06:05 -07001551 retval = request_firmware(&fw_entry,
Alexandra Chin823a2f52013-07-29 16:09:52 -07001552 fwu->image_name,
Alexandra Chind5591a62013-02-07 12:59:15 -08001553 &fwu->rmi4_data->i2c_client->dev);
1554 if (retval != 0) {
1555 dev_err(&fwu->rmi4_data->i2c_client->dev,
1556 "%s: Firmware image %s not available\n",
Amy Malochecb835832013-03-26 18:06:05 -07001557 __func__,
Alexandra Chin823a2f52013-07-29 16:09:52 -07001558 fwu->image_name);
Amy Malocheb494b9a2013-05-13 18:01:53 -07001559 return -EINVAL;
Alexandra Chind5591a62013-02-07 12:59:15 -08001560 }
1561
1562 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1563 "%s: Firmware image size = %d\n",
1564 __func__, fw_entry->size);
1565
Alexandra Chin823a2f52013-07-29 16:09:52 -07001566 fwu->data_buffer = fw_entry->data;
Alexandra Chind5591a62013-02-07 12:59:15 -08001567 }
1568
Alexandra Chin823a2f52013-07-29 16:09:52 -07001569 parse_header();
1570 flash_area = fwu_go_nogo();
Alexandra Chin400f26e2013-07-25 11:58:17 -07001571
1572 if (fwu->rmi4_data->sensor_sleep) {
1573 dev_err(&fwu->rmi4_data->i2c_client->dev,
1574 "%s: Sensor sleeping\n",
1575 __func__);
Alexandra Chin823a2f52013-07-29 16:09:52 -07001576 retval = -ENODEV;
1577 goto exit;
Alexandra Chin400f26e2013-07-25 11:58:17 -07001578 }
1579 fwu->rmi4_data->stay_awake = true;
Alexandra Chind5591a62013-02-07 12:59:15 -08001580
1581 switch (flash_area) {
1582 case NONE:
Amy Maloche2c4c48c2013-05-01 20:06:23 -07001583 case MISMATCH:
1584 retval = 0;
Alexandra Chind5591a62013-02-07 12:59:15 -08001585 dev_info(&fwu->rmi4_data->i2c_client->dev,
1586 "%s: No need to do reflash.\n",
1587 __func__);
1588 goto exit;
1589 case UI_FIRMWARE:
1590 retval = fwu_do_reflash();
1591 break;
1592 case CONFIG_AREA:
1593 retval = fwu_do_write_config();
1594 break;
1595 default:
1596 dev_err(&fwu->rmi4_data->i2c_client->dev,
1597 "%s: Unknown flash area\n",
1598 __func__);
Alexandra Chin823a2f52013-07-29 16:09:52 -07001599 retval = -EINVAL;
Alexandra Chind5591a62013-02-07 12:59:15 -08001600 goto exit;
1601 }
1602
Alexandra Chin823a2f52013-07-29 16:09:52 -07001603 if (retval < 0)
Alexandra Chind5591a62013-02-07 12:59:15 -08001604 dev_err(&fwu->rmi4_data->i2c_client->dev,
1605 "%s: Failed to do reflash\n",
1606 __func__);
Alexandra Chind5591a62013-02-07 12:59:15 -08001607
1608 /* reset device */
1609 fwu_reset_device();
1610
1611 /* check device status */
1612 retval = fwu_read_f01_device_status(&f01_device_status);
1613 if (retval < 0)
1614 goto exit;
1615
1616 dev_info(&fwu->rmi4_data->i2c_client->dev, "Device is in %s mode\n",
1617 f01_device_status.flash_prog == 1 ? "bootloader" : "UI");
1618 if (f01_device_status.flash_prog)
1619 dev_info(&fwu->rmi4_data->i2c_client->dev, "Flash status %d\n",
1620 f01_device_status.status_code);
1621
1622 if (f01_device_status.flash_prog) {
1623 dev_info(&fwu->rmi4_data->i2c_client->dev,
1624 "%s: Device is in flash prog mode 0x%02X\n",
1625 __func__, f01_device_status.status_code);
Alexandra Chind5591a62013-02-07 12:59:15 -08001626 }
1627
Amy Malocheb494b9a2013-05-13 18:01:53 -07001628exit:
Alexandra Chind5591a62013-02-07 12:59:15 -08001629 if (fw_entry)
1630 release_firmware(fw_entry);
1631
1632 pr_notice("%s: End of reflash process\n", __func__);
Alexandra Chin400f26e2013-07-25 11:58:17 -07001633 fwu->rmi4_data->stay_awake = false;
Alexandra Chind5591a62013-02-07 12:59:15 -08001634 return retval;
1635}
1636
Alexandra Chin823a2f52013-07-29 16:09:52 -07001637int synaptics_fw_updater(void)
Alexandra Chin669d27c2012-12-24 15:42:30 +08001638{
1639 int retval;
1640
1641 if (!fwu)
1642 return -ENODEV;
1643
1644 if (!fwu->initialized)
1645 return -ENODEV;
1646
Amy Malocheb494b9a2013-05-13 18:01:53 -07001647 fwu->rmi4_data->fw_updating = true;
Amy Maloche986863d2013-06-10 15:13:57 -07001648 if (fwu->rmi4_data->suspended == true) {
Amy Malocheb494b9a2013-05-13 18:01:53 -07001649 fwu->rmi4_data->fw_updating = false;
1650 dev_err(&fwu->rmi4_data->i2c_client->dev,
1651 "Cannot start fw upgrade while device is in suspend\n");
1652 return -EBUSY;
1653 }
1654
Alexandra Chin669d27c2012-12-24 15:42:30 +08001655 fwu->config_area = UI_CONFIG_AREA;
1656
1657 retval = fwu_start_reflash();
Amy Malocheb494b9a2013-05-13 18:01:53 -07001658 fwu->rmi4_data->fw_updating = false;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001659
Amy Maloched9bf0d92013-06-19 17:19:23 -07001660 synaptics_rmi4_update_debug_info();
1661
Alexandra Chin669d27c2012-12-24 15:42:30 +08001662 return retval;
1663}
1664EXPORT_SYMBOL(synaptics_fw_updater);
1665
1666static ssize_t fwu_sysfs_show_image(struct file *data_file,
1667 struct kobject *kobj, struct bin_attribute *attributes,
1668 char *buf, loff_t pos, size_t count)
1669{
1670 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1671
1672 if (count < fwu->config_size) {
1673 dev_err(&rmi4_data->i2c_client->dev,
1674 "%s: Not enough space (%d bytes) in buffer\n",
1675 __func__, count);
1676 return -EINVAL;
1677 }
1678
1679 memcpy(buf, fwu->read_config_buf, fwu->config_size);
1680
1681 return fwu->config_size;
1682}
1683
1684static ssize_t fwu_sysfs_store_image(struct file *data_file,
1685 struct kobject *kobj, struct bin_attribute *attributes,
1686 char *buf, loff_t pos, size_t count)
1687{
1688 memcpy((void *)(&fwu->ext_data_source[fwu->data_pos]),
1689 (const void *)buf,
1690 count);
1691
Alexandra Chin823a2f52013-07-29 16:09:52 -07001692 fwu->data_buffer = fwu->ext_data_source;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001693 fwu->data_pos += count;
1694
1695 return count;
1696}
1697
Alexandra Chin823a2f52013-07-29 16:09:52 -07001698static ssize_t fwu_sysfs_image_name_store(struct device *dev,
Amy Malocheb494b9a2013-05-13 18:01:53 -07001699 struct device_attribute *attr, const char *buf, size_t count)
1700{
1701 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1702 char *strptr;
1703
1704 if (count >= NAME_BUFFER_SIZE) {
1705 dev_err(&rmi4_data->i2c_client->dev,
1706 "Input over %d characters long\n", NAME_BUFFER_SIZE);
1707 return -EINVAL;
1708 }
1709
1710 strptr = strnstr(buf, ".img",
1711 count);
1712 if (!strptr) {
1713 dev_err(&rmi4_data->i2c_client->dev,
1714 "Input is not valid .img file\n");
1715 return -EINVAL;
1716 }
1717
1718 strlcpy(rmi4_data->fw_image_name, buf, count);
1719 return count;
1720}
1721
Alexandra Chin823a2f52013-07-29 16:09:52 -07001722static ssize_t fwu_sysfs_image_name_show(struct device *dev,
Amy Malocheb494b9a2013-05-13 18:01:53 -07001723 struct device_attribute *attr, char *buf)
1724{
1725 if (strnlen(fwu->rmi4_data->fw_image_name, NAME_BUFFER_SIZE) > 0)
1726 return snprintf(buf, PAGE_SIZE, "%s\n",
1727 fwu->rmi4_data->fw_image_name);
1728 else
1729 return snprintf(buf, PAGE_SIZE, "No firmware name given\n");
1730}
1731
Amy Maloche5e0360e2013-05-01 13:31:57 -07001732static ssize_t fwu_sysfs_force_reflash_store(struct device *dev,
1733 struct device_attribute *attr, const char *buf, size_t count)
1734{
1735 int retval;
1736 unsigned int input;
1737 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1738
1739 if (sscanf(buf, "%u", &input) != 1) {
1740 retval = -EINVAL;
1741 goto exit;
1742 }
1743
1744 if (input != 1) {
1745 retval = -EINVAL;
1746 goto exit;
1747 }
Alexandra Chin823a2f52013-07-29 16:09:52 -07001748 if (LOCKDOWN)
1749 fwu->do_lockdown = true;
Amy Maloche5e0360e2013-05-01 13:31:57 -07001750
1751 fwu->force_update = true;
Alexandra Chin823a2f52013-07-29 16:09:52 -07001752 retval = synaptics_fw_updater();
Amy Maloche5e0360e2013-05-01 13:31:57 -07001753 if (retval < 0) {
1754 dev_err(&rmi4_data->i2c_client->dev,
1755 "%s: Failed to do reflash\n",
1756 __func__);
1757 goto exit;
1758 }
1759
1760 retval = count;
1761
1762exit:
1763 kfree(fwu->ext_data_source);
1764 fwu->ext_data_source = NULL;
Alexandra Chin823a2f52013-07-29 16:09:52 -07001765 fwu->force_update = FORCE_UPDATE;
Amy Maloche37a75b72013-08-06 13:27:50 -07001766 fwu->do_lockdown = rmi4_data->board->do_lockdown;
Amy Maloche5e0360e2013-05-01 13:31:57 -07001767 return retval;
1768}
1769
Alexandra Chin669d27c2012-12-24 15:42:30 +08001770static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
1771 struct device_attribute *attr, const char *buf, size_t count)
1772{
1773 int retval;
1774 unsigned int input;
1775 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1776
1777 if (sscanf(buf, "%u", &input) != 1) {
1778 retval = -EINVAL;
1779 goto exit;
1780 }
1781
Alexandra Chin823a2f52013-07-29 16:09:52 -07001782 if (input & LOCKDOWN) {
1783 fwu->do_lockdown = true;
1784 input &= ~LOCKDOWN;
1785 }
1786
1787 if ((input != NORMAL) && (input != FORCE)) {
1788 retval = -EINVAL;
1789 goto exit;
1790 }
1791
1792 if (input == FORCE)
1793 fwu->force_update = true;
1794
1795 retval = synaptics_fw_updater();
1796 if (retval < 0) {
1797 dev_err(&rmi4_data->i2c_client->dev,
1798 "%s: Failed to do reflash\n",
1799 __func__);
1800 goto exit;
1801 }
1802
1803 retval = count;
1804
1805exit:
1806 kfree(fwu->ext_data_source);
1807 fwu->ext_data_source = NULL;
1808 fwu->force_update = FORCE_UPDATE;
Amy Maloche37a75b72013-08-06 13:27:50 -07001809 fwu->do_lockdown = rmi4_data->board->do_lockdown;
Alexandra Chin823a2f52013-07-29 16:09:52 -07001810 return retval;
1811}
1812
1813static ssize_t fwu_sysfs_write_lockdown_store(struct device *dev,
1814 struct device_attribute *attr, const char *buf, size_t count)
1815{
1816 int retval;
1817 unsigned int input;
1818 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1819
1820 if (sscanf(buf, "%u", &input) != 1) {
1821 retval = -EINVAL;
1822 goto exit;
1823 }
1824
Alexandra Chin669d27c2012-12-24 15:42:30 +08001825 if (input != 1) {
1826 retval = -EINVAL;
1827 goto exit;
1828 }
1829
Alexandra Chin823a2f52013-07-29 16:09:52 -07001830 retval = fwu_start_write_lockdown();
Alexandra Chin669d27c2012-12-24 15:42:30 +08001831 if (retval < 0) {
1832 dev_err(&rmi4_data->i2c_client->dev,
Alexandra Chin823a2f52013-07-29 16:09:52 -07001833 "%s: Failed to write lockdown block\n",
Alexandra Chin669d27c2012-12-24 15:42:30 +08001834 __func__);
1835 goto exit;
1836 }
1837
1838 retval = count;
1839
1840exit:
1841 kfree(fwu->ext_data_source);
1842 fwu->ext_data_source = NULL;
Alexandra Chin823a2f52013-07-29 16:09:52 -07001843 fwu->force_update = FORCE_UPDATE;
Amy Maloche37a75b72013-08-06 13:27:50 -07001844 fwu->do_lockdown = rmi4_data->board->do_lockdown;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001845 return retval;
1846}
1847
1848static ssize_t fwu_sysfs_write_config_store(struct device *dev,
1849 struct device_attribute *attr, const char *buf, size_t count)
1850{
1851 int retval;
1852 unsigned int input;
1853 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1854
1855 if (sscanf(buf, "%u", &input) != 1) {
1856 retval = -EINVAL;
1857 goto exit;
1858 }
1859
1860 if (input != 1) {
1861 retval = -EINVAL;
1862 goto exit;
1863 }
1864
1865 retval = fwu_start_write_config();
1866 if (retval < 0) {
1867 dev_err(&rmi4_data->i2c_client->dev,
1868 "%s: Failed to write config\n",
1869 __func__);
1870 goto exit;
1871 }
1872
1873 retval = count;
1874
1875exit:
1876 kfree(fwu->ext_data_source);
1877 fwu->ext_data_source = NULL;
1878 return retval;
1879}
1880
1881static ssize_t fwu_sysfs_read_config_store(struct device *dev,
1882 struct device_attribute *attr, const char *buf, size_t count)
1883{
1884 int retval;
1885 unsigned int input;
1886 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1887
1888 if (sscanf(buf, "%u", &input) != 1)
1889 return -EINVAL;
1890
1891 if (input != 1)
1892 return -EINVAL;
1893
1894 retval = fwu_do_read_config();
1895 if (retval < 0) {
1896 dev_err(&rmi4_data->i2c_client->dev,
1897 "%s: Failed to read config\n",
1898 __func__);
1899 return retval;
1900 }
1901
1902 return count;
1903}
1904
1905static ssize_t fwu_sysfs_config_area_store(struct device *dev,
1906 struct device_attribute *attr, const char *buf, size_t count)
1907{
1908 int retval;
1909 unsigned long config_area;
1910
Shantanu Jain41f0d472013-01-04 12:14:37 +05301911 retval = kstrtoul(buf, 10, &config_area);
Alexandra Chin669d27c2012-12-24 15:42:30 +08001912 if (retval)
1913 return retval;
1914
1915 fwu->config_area = config_area;
1916
1917 return count;
1918}
1919
1920static ssize_t fwu_sysfs_image_size_store(struct device *dev,
1921 struct device_attribute *attr, const char *buf, size_t count)
1922{
1923 int retval;
1924 unsigned long size;
1925 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1926
Shantanu Jain41f0d472013-01-04 12:14:37 +05301927 retval = kstrtoul(buf, 10, &size);
Alexandra Chin669d27c2012-12-24 15:42:30 +08001928 if (retval)
1929 return retval;
1930
1931 fwu->image_size = size;
1932 fwu->data_pos = 0;
1933
1934 kfree(fwu->ext_data_source);
1935 fwu->ext_data_source = kzalloc(fwu->image_size, GFP_KERNEL);
1936 if (!fwu->ext_data_source) {
1937 dev_err(&rmi4_data->i2c_client->dev,
1938 "%s: Failed to alloc mem for image data\n",
1939 __func__);
1940 return -ENOMEM;
1941 }
1942
1943 return count;
1944}
1945
1946static ssize_t fwu_sysfs_block_size_show(struct device *dev,
1947 struct device_attribute *attr, char *buf)
1948{
1949 return snprintf(buf, PAGE_SIZE, "%u\n", fwu->block_size);
1950}
1951
1952static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev,
1953 struct device_attribute *attr, char *buf)
1954{
1955 return snprintf(buf, PAGE_SIZE, "%u\n", fwu->fw_block_count);
1956}
1957
1958static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev,
1959 struct device_attribute *attr, char *buf)
1960{
1961 return snprintf(buf, PAGE_SIZE, "%u\n", fwu->config_block_count);
1962}
1963
1964static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev,
1965 struct device_attribute *attr, char *buf)
1966{
1967 return snprintf(buf, PAGE_SIZE, "%u\n", fwu->perm_config_block_count);
1968}
1969
1970static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev,
1971 struct device_attribute *attr, char *buf)
1972{
1973 return snprintf(buf, PAGE_SIZE, "%u\n", fwu->bl_config_block_count);
1974}
1975
1976static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev,
1977 struct device_attribute *attr, char *buf)
1978{
1979 return snprintf(buf, PAGE_SIZE, "%u\n", fwu->disp_config_block_count);
1980}
1981
Amy Maloched25bd8c2013-01-25 12:34:31 -08001982static ssize_t fwu_sysfs_config_id_show(struct device *dev,
1983 struct device_attribute *attr, char *buf)
1984{
Amy Maloche581f7402013-02-19 16:29:37 -08001985 unsigned char config_id[4];
Amy Maloched25bd8c2013-01-25 12:34:31 -08001986 /* device config id */
1987 fwu->fn_ptr->read(fwu->rmi4_data,
1988 fwu->f34_fd.ctrl_base_addr,
1989 config_id,
1990 sizeof(config_id));
1991
1992 return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n",
1993 config_id[0], config_id[1], config_id[2], config_id[3]);
1994}
1995
Amy Maloche2c4c48c2013-05-01 20:06:23 -07001996static ssize_t fwu_sysfs_package_id_show(struct device *dev,
1997 struct device_attribute *attr, char *buf)
1998{
1999 unsigned char pkg_id[4];
2000 /* read device package id */
2001 fwu->fn_ptr->read(fwu->rmi4_data,
2002 fwu->f01_fd.query_base_addr + 17,
2003 pkg_id,
2004 sizeof(pkg_id));
2005
2006 return snprintf(buf, PAGE_SIZE, "%d rev %d\n",
2007 (pkg_id[1] << 8) | pkg_id[0],
2008 (pkg_id[3] << 8) | pkg_id[2]);
2009}
2010
Amy Maloched9bf0d92013-06-19 17:19:23 -07002011static int synaptics_rmi4_debug_dump_info(struct seq_file *m, void *v)
2012{
2013 seq_printf(m, "%s\n", fwu->ts_info);
2014
2015 return 0;
2016}
2017
2018static int debugfs_dump_info_open(struct inode *inode, struct file *file)
2019{
2020 return single_open(file, synaptics_rmi4_debug_dump_info,
2021 inode->i_private);
2022}
2023
2024static const struct file_operations debug_dump_info_fops = {
2025 .owner = THIS_MODULE,
2026 .open = debugfs_dump_info_open,
2027 .read = seq_read,
2028 .release = single_release,
2029};
2030
Alexandra Chin669d27c2012-12-24 15:42:30 +08002031static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data,
2032 unsigned char intr_mask)
2033{
Alexandra Chinb2d3aea2013-09-24 11:58:02 -07002034 if (!fwu)
2035 return;
2036
Alexandra Chin669d27c2012-12-24 15:42:30 +08002037 if (fwu->intr_mask & intr_mask)
Alexandra Chin400f26e2013-07-25 11:58:17 -07002038 fwu->interrupt_flag = true;
Alexandra Chin669d27c2012-12-24 15:42:30 +08002039
2040 return;
2041}
2042
Amy Malocheb494b9a2013-05-13 18:01:53 -07002043static struct bin_attribute dev_attr_data = {
2044 .attr = {
2045 .name = "data",
Amy Maloche8b99ec92013-06-24 17:13:42 -07002046 .mode = (S_IRUGO | S_IWUSR | S_IWGRP),
Amy Malocheb494b9a2013-05-13 18:01:53 -07002047 },
2048 .size = 0,
2049 .read = fwu_sysfs_show_image,
2050 .write = fwu_sysfs_store_image,
2051};
2052
2053static struct device_attribute attrs[] = {
Amy Maloche8b99ec92013-06-24 17:13:42 -07002054 __ATTR(fw_name, S_IRUGO | S_IWUSR | S_IWGRP,
Alexandra Chin823a2f52013-07-29 16:09:52 -07002055 fwu_sysfs_image_name_show,
2056 fwu_sysfs_image_name_store),
Amy Maloche8b99ec92013-06-24 17:13:42 -07002057 __ATTR(force_update_fw, S_IRUGO | S_IWUSR | S_IWGRP,
Amy Malocheb494b9a2013-05-13 18:01:53 -07002058 synaptics_rmi4_show_error,
2059 fwu_sysfs_force_reflash_store),
Amy Maloche8b99ec92013-06-24 17:13:42 -07002060 __ATTR(update_fw, S_IRUGO | S_IWUSR | S_IWGRP,
Amy Malocheb494b9a2013-05-13 18:01:53 -07002061 synaptics_rmi4_show_error,
2062 fwu_sysfs_do_reflash_store),
Amy Maloche8b99ec92013-06-24 17:13:42 -07002063 __ATTR(writeconfig, S_IRUGO | S_IWUSR | S_IWGRP,
Amy Malocheb494b9a2013-05-13 18:01:53 -07002064 synaptics_rmi4_show_error,
2065 fwu_sysfs_write_config_store),
Amy Maloche52e06182013-09-06 18:24:33 -07002066 __ATTR(writelockdown, S_IRUGO | S_IWUSR | S_IWGRP,
Alexandra Chin823a2f52013-07-29 16:09:52 -07002067 synaptics_rmi4_show_error,
2068 fwu_sysfs_write_lockdown_store),
Amy Maloche8b99ec92013-06-24 17:13:42 -07002069 __ATTR(readconfig, S_IRUGO | S_IWUSR | S_IWGRP,
Amy Malocheb494b9a2013-05-13 18:01:53 -07002070 synaptics_rmi4_show_error,
2071 fwu_sysfs_read_config_store),
Amy Maloche8b99ec92013-06-24 17:13:42 -07002072 __ATTR(configarea, S_IRUGO | S_IWUSR | S_IWGRP,
Amy Malocheb494b9a2013-05-13 18:01:53 -07002073 synaptics_rmi4_show_error,
2074 fwu_sysfs_config_area_store),
Amy Maloche8b99ec92013-06-24 17:13:42 -07002075 __ATTR(imagesize, S_IRUGO | S_IWUSR | S_IWGRP,
Amy Malocheb494b9a2013-05-13 18:01:53 -07002076 synaptics_rmi4_show_error,
2077 fwu_sysfs_image_size_store),
2078 __ATTR(blocksize, S_IRUGO,
2079 fwu_sysfs_block_size_show,
2080 synaptics_rmi4_store_error),
2081 __ATTR(fwblockcount, S_IRUGO,
2082 fwu_sysfs_firmware_block_count_show,
2083 synaptics_rmi4_store_error),
2084 __ATTR(configblockcount, S_IRUGO,
2085 fwu_sysfs_configuration_block_count_show,
2086 synaptics_rmi4_store_error),
2087 __ATTR(permconfigblockcount, S_IRUGO,
2088 fwu_sysfs_perm_config_block_count_show,
2089 synaptics_rmi4_store_error),
2090 __ATTR(blconfigblockcount, S_IRUGO,
2091 fwu_sysfs_bl_config_block_count_show,
2092 synaptics_rmi4_store_error),
2093 __ATTR(dispconfigblockcount, S_IRUGO,
2094 fwu_sysfs_disp_config_block_count_show,
2095 synaptics_rmi4_store_error),
2096 __ATTR(config_id, S_IRUGO,
2097 fwu_sysfs_config_id_show,
2098 synaptics_rmi4_store_error),
Amy Maloche2c4c48c2013-05-01 20:06:23 -07002099 __ATTR(package_id, S_IRUGO,
2100 fwu_sysfs_package_id_show,
2101 synaptics_rmi4_store_error),
Amy Malocheb494b9a2013-05-13 18:01:53 -07002102};
2103
2104
Alexandra Chind5591a62013-02-07 12:59:15 -08002105static void synaptics_rmi4_fwu_work(struct work_struct *work)
2106{
2107 fwu_start_reflash();
2108}
2109
Alexandra Chin669d27c2012-12-24 15:42:30 +08002110static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
2111{
2112 int retval;
2113 unsigned char attr_count;
2114 struct pdt_properties pdt_props;
Amy Maloched9bf0d92013-06-19 17:19:23 -07002115 struct dentry *temp;
Alexandra Chin669d27c2012-12-24 15:42:30 +08002116
2117 fwu = kzalloc(sizeof(*fwu), GFP_KERNEL);
2118 if (!fwu) {
2119 dev_err(&rmi4_data->i2c_client->dev,
2120 "%s: Failed to alloc mem for fwu\n",
2121 __func__);
Alexandra Chinb2d3aea2013-09-24 11:58:02 -07002122 retval = -ENOMEM;
Alexandra Chin669d27c2012-12-24 15:42:30 +08002123 goto exit;
2124 }
2125
2126 fwu->fn_ptr = kzalloc(sizeof(*(fwu->fn_ptr)), GFP_KERNEL);
2127 if (!fwu->fn_ptr) {
2128 dev_err(&rmi4_data->i2c_client->dev,
2129 "%s: Failed to alloc mem for fn_ptr\n",
2130 __func__);
2131 retval = -ENOMEM;
2132 goto exit_free_fwu;
2133 }
2134
2135 fwu->rmi4_data = rmi4_data;
2136 fwu->fn_ptr->read = rmi4_data->i2c_read;
2137 fwu->fn_ptr->write = rmi4_data->i2c_write;
2138 fwu->fn_ptr->enable = rmi4_data->irq_enable;
2139
2140 retval = fwu->fn_ptr->read(rmi4_data,
2141 PDT_PROPS,
2142 pdt_props.data,
2143 sizeof(pdt_props.data));
2144 if (retval < 0) {
2145 dev_dbg(&rmi4_data->i2c_client->dev,
2146 "%s: Failed to read PDT properties, assuming 0x00\n",
2147 __func__);
Alexandra Chinb2d3aea2013-09-24 11:58:02 -07002148 goto exit_free_mem;
Alexandra Chin669d27c2012-12-24 15:42:30 +08002149 } else if (pdt_props.has_bsr) {
2150 dev_err(&rmi4_data->i2c_client->dev,
2151 "%s: Reflash for LTS not currently supported\n",
2152 __func__);
Alexandra Chinb2d3aea2013-09-24 11:58:02 -07002153 retval = -EINVAL;
Alexandra Chin669d27c2012-12-24 15:42:30 +08002154 goto exit_free_mem;
2155 }
2156
2157 retval = fwu_scan_pdt();
2158 if (retval < 0)
2159 goto exit_free_mem;
2160
2161 fwu->productinfo1 = rmi4_data->rmi4_mod_info.product_info[0];
2162 fwu->productinfo2 = rmi4_data->rmi4_mod_info.product_info[1];
2163
2164 memcpy(fwu->product_id, rmi4_data->rmi4_mod_info.product_id_string,
2165 SYNAPTICS_RMI4_PRODUCT_ID_SIZE);
2166 fwu->product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE] = 0;
2167
2168 dev_dbg(&rmi4_data->i2c_client->dev,
2169 "%s: F01 product info: 0x%04x 0x%04x\n",
2170 __func__, fwu->productinfo1, fwu->productinfo2);
2171 dev_dbg(&rmi4_data->i2c_client->dev,
2172 "%s: F01 product ID: %s\n",
2173 __func__, fwu->product_id);
2174
2175 retval = fwu_read_f34_queries();
2176 if (retval < 0)
2177 goto exit_free_mem;
2178
2179 fwu->initialized = true;
Alexandra Chind5591a62013-02-07 12:59:15 -08002180 fwu->force_update = FORCE_UPDATE;
Amy Maloche37a75b72013-08-06 13:27:50 -07002181 fwu->do_lockdown = rmi4_data->board->do_lockdown;
Alexandra Chin823a2f52013-07-29 16:09:52 -07002182 fwu->initialized = true;
Alexandra Chin400f26e2013-07-25 11:58:17 -07002183 fwu->polling_mode = false;
Alexandra Chin669d27c2012-12-24 15:42:30 +08002184
Amy Maloche4d54ac42013-06-11 12:09:44 -07002185 retval = sysfs_create_bin_file(&rmi4_data->i2c_client->dev.kobj,
Alexandra Chin669d27c2012-12-24 15:42:30 +08002186 &dev_attr_data);
2187 if (retval < 0) {
2188 dev_err(&rmi4_data->i2c_client->dev,
2189 "%s: Failed to create sysfs bin file\n",
2190 __func__);
2191 goto exit_free_mem;
2192 }
2193
2194 for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
Amy Maloche4d54ac42013-06-11 12:09:44 -07002195 retval = sysfs_create_file(&rmi4_data->i2c_client->dev.kobj,
Alexandra Chin669d27c2012-12-24 15:42:30 +08002196 &attrs[attr_count].attr);
2197 if (retval < 0) {
2198 dev_err(&rmi4_data->i2c_client->dev,
2199 "%s: Failed to create sysfs attributes\n",
2200 __func__);
2201 retval = -ENODEV;
2202 goto exit_remove_attrs;
2203 }
2204 }
2205
Amy Maloched9bf0d92013-06-19 17:19:23 -07002206 temp = debugfs_create_file("dump_info", S_IRUSR | S_IWUSR,
2207 fwu->rmi4_data->dir, fwu->rmi4_data,
2208 &debug_dump_info_fops);
2209 if (temp == NULL || IS_ERR(temp)) {
2210 dev_err(&rmi4_data->i2c_client->dev,
2211 "%s: Failed to create debugfs dump info file\n",
2212 __func__);
2213 retval = PTR_ERR(temp);
2214 goto exit_remove_attrs;
2215 }
2216
2217 fwu->ts_info = kzalloc(RMI4_INFO_MAX_LEN, GFP_KERNEL);
2218 if (!fwu->ts_info) {
2219 dev_err(&rmi4_data->i2c_client->dev, "Not enough memory\n");
2220 goto exit_free_ts_info;
2221 }
2222
2223 synaptics_rmi4_update_debug_info();
2224
Alexandra Chind5591a62013-02-07 12:59:15 -08002225#ifdef INSIDE_FIRMWARE_UPDATE
2226 fwu->fwu_workqueue = create_singlethread_workqueue("fwu_workqueue");
2227 INIT_DELAYED_WORK(&fwu->fwu_work, synaptics_rmi4_fwu_work);
2228 queue_delayed_work(fwu->fwu_workqueue,
2229 &fwu->fwu_work,
2230 msecs_to_jiffies(1000));
2231#endif
Alexandra Chinc556cf02013-03-19 17:46:05 -07002232
Alexandra Chin669d27c2012-12-24 15:42:30 +08002233 return 0;
Amy Maloched9bf0d92013-06-19 17:19:23 -07002234exit_free_ts_info:
2235 debugfs_remove(temp);
Alexandra Chin669d27c2012-12-24 15:42:30 +08002236exit_remove_attrs:
Alexandra Chin823a2f52013-07-29 16:09:52 -07002237 for (attr_count--; attr_count >= 0; attr_count--) {
2238 sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
2239 &attrs[attr_count].attr);
2240 }
Alexandra Chin669d27c2012-12-24 15:42:30 +08002241
Alexandra Chin823a2f52013-07-29 16:09:52 -07002242 sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
Alexandra Chin669d27c2012-12-24 15:42:30 +08002243
2244exit_free_mem:
2245 kfree(fwu->fn_ptr);
2246
2247exit_free_fwu:
2248 kfree(fwu);
Alexandra Chin823a2f52013-07-29 16:09:52 -07002249 fwu = NULL;
Alexandra Chin669d27c2012-12-24 15:42:30 +08002250
2251exit:
Alexandra Chinb2d3aea2013-09-24 11:58:02 -07002252 return retval;
Alexandra Chin669d27c2012-12-24 15:42:30 +08002253}
2254
2255static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data)
2256{
2257 unsigned char attr_count;
2258
2259 sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
2260
2261 for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
2262 sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
2263 &attrs[attr_count].attr);
2264 }
2265
Alexandra Chin823a2f52013-07-29 16:09:52 -07002266 kfree(fwu->read_config_buf);
Alexandra Chin669d27c2012-12-24 15:42:30 +08002267 kfree(fwu->fn_ptr);
2268 kfree(fwu);
2269
Alexandra Chind9e204d2013-07-25 15:23:01 -07002270 complete(&fwu_remove_complete);
Alexandra Chin669d27c2012-12-24 15:42:30 +08002271
2272 return;
2273}
2274
2275static int __init rmi4_fw_update_module_init(void)
2276{
2277 synaptics_rmi4_new_function(RMI_FW_UPDATER, true,
2278 synaptics_rmi4_fwu_init,
2279 synaptics_rmi4_fwu_remove,
2280 synaptics_rmi4_fwu_attn);
2281 return 0;
2282}
2283
2284static void __exit rmi4_fw_update_module_exit(void)
2285{
Alexandra Chin669d27c2012-12-24 15:42:30 +08002286 synaptics_rmi4_new_function(RMI_FW_UPDATER, false,
2287 synaptics_rmi4_fwu_init,
2288 synaptics_rmi4_fwu_remove,
2289 synaptics_rmi4_fwu_attn);
Alexandra Chind9e204d2013-07-25 15:23:01 -07002290 wait_for_completion(&fwu_remove_complete);
Alexandra Chin669d27c2012-12-24 15:42:30 +08002291 return;
2292}
2293
2294module_init(rmi4_fw_update_module_init);
2295module_exit(rmi4_fw_update_module_exit);
2296
2297MODULE_AUTHOR("Synaptics, Inc.");
2298MODULE_DESCRIPTION("RMI4 FW Update Module");
Alexandra Chinbd1dac22013-02-22 12:33:19 -08002299MODULE_LICENSE("GPL v2");