blob: 9f326f1482e3cdf39d06301877053fe8743be559 [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
Alexandra Chin823a2f52013-07-29 16:09:52 -070035#define DO_LOCKDOWN false
Alexandra Chind5591a62013-02-07 12:59:15 -080036#define INSIDE_FIRMWARE_UPDATE
Alexandra Chin669d27c2012-12-24 15:42:30 +080037
Alexandra Chin669d27c2012-12-24 15:42:30 +080038#define FW_IMAGE_OFFSET 0x100
Alexandra Chin400f26e2013-07-25 11:58:17 -070039/* 0 to ignore flash block check to speed up flash time */
40#define CHECK_FLASH_BLOCK_STATUS 1
Alexandra Chin669d27c2012-12-24 15:42:30 +080041
42#define REG_MAP (1 << 0)
43#define UNLOCKED (1 << 1)
44#define HAS_CONFIG_ID (1 << 2)
45#define HAS_PERM_CONFIG (1 << 3)
46#define HAS_BL_CONFIG (1 << 4)
47#define HAS_DISP_CONFIG (1 << 5)
48#define HAS_CTRL1 (1 << 6)
49
Amy Maloched9bf0d92013-06-19 17:19:23 -070050#define RMI4_INFO_MAX_LEN 200
51
52#define RMI4_STORE_TS_INFO(buf, id, rev, fw_ver) \
53 snprintf(buf, RMI4_INFO_MAX_LEN, \
54 "controller\t= synaptics\n" \
55 "model\t\t= %d rev %d\n" \
56 "fw_ver\t\t= %d\n", id, rev, fw_ver)
57
Amy Malocheafcecb22013-04-16 18:43:22 -070058enum falsh_config_area {
59 UI_CONFIG_AREA = 0x00,
60 PERM_CONFIG_AREA = 0x01,
61 BL_CONFIG_AREA = 0x02,
62 DISP_CONFIG_AREA = 0x03
63};
Alexandra Chin669d27c2012-12-24 15:42:30 +080064
65enum flash_command {
66 CMD_WRITE_FW_BLOCK = 0x2,
67 CMD_ERASE_ALL = 0x3,
Alexandra Chin823a2f52013-07-29 16:09:52 -070068 CMD_WRITE_LOCKDOWN_BLOCK = 0x4,
Alexandra Chin669d27c2012-12-24 15:42:30 +080069 CMD_READ_CONFIG_BLOCK = 0x5,
70 CMD_WRITE_CONFIG_BLOCK = 0x6,
71 CMD_ERASE_CONFIG = 0x7,
Amy Malocheafcecb22013-04-16 18:43:22 -070072 CMD_READ_SENSOR_ID = 0x8,
Alexandra Chin669d27c2012-12-24 15:42:30 +080073 CMD_ERASE_BL_CONFIG = 0x9,
74 CMD_ERASE_DISP_CONFIG = 0xA,
Amy Malocheafcecb22013-04-16 18:43:22 -070075 CMD_ENABLE_FLASH_PROG = 0xF
Alexandra Chin669d27c2012-12-24 15:42:30 +080076};
77
Alexandra Chind5591a62013-02-07 12:59:15 -080078enum flash_area {
79 NONE,
80 UI_FIRMWARE,
Amy Maloche2c4c48c2013-05-01 20:06:23 -070081 CONFIG_AREA,
82 MISMATCH
Alexandra Chind5591a62013-02-07 12:59:15 -080083};
84
Amy Malocheafcecb22013-04-16 18:43:22 -070085enum image_file_option {
86 OPTION_BUILD_INFO = 0,
87 OPTION_CONTAIN_BOOTLOADER = 1,
88};
89
Alexandra Chin400f26e2013-07-25 11:58:17 -070090enum flash_offset {
91 OFFSET_BOOTLOADER_ID,
92 OFFSET_FLASH_PROPERTIES,
93 OFFSET_BLOCK_SIZE,
94 OFFSET_FW_BLOCK_COUNT,
95 OFFSET_BLOCK_NUMBER,
96 OFFSET_BLOCK_DATA,
97 OFFSET_FLASH_CONTROL,
98 OFFSET_FLASH_STATUS
99};
100
Alexandra Chin823a2f52013-07-29 16:09:52 -0700101enum flash_update_mode {
102 NORMAL = 1,
103 FORCE = 2,
104 LOCKDOWN = 8
105};
106
Alexandra Chin669d27c2012-12-24 15:42:30 +0800107#define SLEEP_MODE_NORMAL (0x00)
108#define SLEEP_MODE_SENSOR_SLEEP (0x01)
109#define SLEEP_MODE_RESERVED0 (0x02)
110#define SLEEP_MODE_RESERVED1 (0x03)
111
112#define ENABLE_WAIT_MS (1 * 1000)
113#define WRITE_WAIT_MS (3 * 1000)
114#define ERASE_WAIT_MS (5 * 1000)
Alexandra Chind5591a62013-02-07 12:59:15 -0800115#define RESET_WAIT_MS (500)
Alexandra Chin669d27c2012-12-24 15:42:30 +0800116
Alexandra Chin400f26e2013-07-25 11:58:17 -0700117#define SLEEP_TIME_US 100
Alexandra Chin669d27c2012-12-24 15:42:30 +0800118
Alexandra Chin669d27c2012-12-24 15:42:30 +0800119static int fwu_wait_for_idle(int timeout_ms);
120
Amy Malocheafcecb22013-04-16 18:43:22 -0700121struct image_header_data {
122 union {
123 struct {
124 /* 0x00-0x0F */
125 unsigned char file_checksum[4];
126 unsigned char reserved_04;
127 unsigned char reserved_05;
128 unsigned char options_firmware_id:1;
129 unsigned char options_contain_bootloader:1;
130 unsigned char options_reserved:6;
131 unsigned char bootloader_version;
132 unsigned char firmware_size[4];
133 unsigned char config_size[4];
134 /* 0x10-0x1F */
135 unsigned char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE];
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700136 unsigned char pkg_id_lsb;
137 unsigned char pkg_id_msb;
138 unsigned char pkg_id_rev_lsb;
139 unsigned char pkg_id_rev_msb;
Amy Malocheafcecb22013-04-16 18:43:22 -0700140 unsigned char product_info[SYNAPTICS_RMI4_PRODUCT_INFO_SIZE];
141 /* 0x20-0x2F */
142 unsigned char reserved_20_2f[0x10];
143 /* 0x30-0x3F */
144 unsigned char ds_firmware_id[0x10];
145 /* 0x40-0x4F */
146 unsigned char ds_customize_info[10];
147 unsigned char reserved_4a_4f[6];
148 /* 0x50-0x53*/
149 unsigned char firmware_id[4];
150 } __packed;
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700151 unsigned char data[0x54];
Amy Malocheafcecb22013-04-16 18:43:22 -0700152 };
153};
154
Alexandra Chin823a2f52013-07-29 16:09:52 -0700155struct image_content {
156 bool is_contain_build_info;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800157 unsigned int checksum;
158 unsigned int image_size;
159 unsigned int config_size;
160 unsigned char options;
161 unsigned char bootloader_version;
162 unsigned char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
163 unsigned char product_info[SYNAPTICS_RMI4_PRODUCT_INFO_SIZE];
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700164 u16 package_id;
165 u16 package_revision_id;
Amy Malocheafcecb22013-04-16 18:43:22 -0700166 unsigned int firmware_id;
Alexandra Chin823a2f52013-07-29 16:09:52 -0700167 const unsigned char *firmware_data;
168 const unsigned char *config_data;
169 const unsigned char *lockdown_data;
170 unsigned short lockdown_block_count;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800171};
172
173struct pdt_properties {
174 union {
175 struct {
176 unsigned char reserved_1:6;
177 unsigned char has_bsr:1;
178 unsigned char reserved_2:1;
179 } __packed;
180 unsigned char data[1];
181 };
182};
183
184struct f01_device_status {
185 union {
186 struct {
187 unsigned char status_code:4;
188 unsigned char reserved:2;
189 unsigned char flash_prog:1;
190 unsigned char unconfigured:1;
191 } __packed;
192 unsigned char data[1];
193 };
194};
195
196struct f01_device_control {
197 union {
198 struct {
199 unsigned char sleep_mode:2;
200 unsigned char nosleep:1;
201 unsigned char reserved:2;
202 unsigned char charger_connected:1;
203 unsigned char report_rate:1;
204 unsigned char configured:1;
205 } __packed;
206 unsigned char data[1];
207 };
208};
209
210struct f34_flash_control {
211 union {
Alexandra Chin400f26e2013-07-25 11:58:17 -0700212 /* version 0 */
Alexandra Chin669d27c2012-12-24 15:42:30 +0800213 struct {
Alexandra Chin400f26e2013-07-25 11:58:17 -0700214 unsigned char command_v0:4;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800215 unsigned char status:3;
216 unsigned char program_enabled:1;
217 } __packed;
Alexandra Chin400f26e2013-07-25 11:58:17 -0700218 /* version 1 */
219 struct {
220 unsigned char command_v1:6;
221 unsigned char reserved:2;
222 } __packed;
223 unsigned char data[1];
224 };
225};
226
227struct f34_flash_status {
228 union {
229 struct {
230 unsigned char status:6;
231 unsigned char reserved:1;
232 unsigned char program_enabled:1;
233 } __packed;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800234 unsigned char data[1];
235 };
236};
237
238struct f34_flash_properties {
239 union {
240 struct {
241 unsigned char regmap:1;
242 unsigned char unlocked:1;
243 unsigned char has_configid:1;
244 unsigned char has_perm_config:1;
245 unsigned char has_bl_config:1;
246 unsigned char has_display_config:1;
247 unsigned char has_blob_config:1;
248 unsigned char reserved:1;
249 } __packed;
250 unsigned char data[1];
251 };
252};
253
254struct synaptics_rmi4_fwu_handle {
255 bool initialized;
Alexandra Chind5591a62013-02-07 12:59:15 -0800256 bool force_update;
Alexandra Chin823a2f52013-07-29 16:09:52 -0700257 bool do_lockdown;
Alexandra Chin400f26e2013-07-25 11:58:17 -0700258 bool interrupt_flag;
259 bool polling_mode;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800260 char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
261 unsigned int image_size;
262 unsigned int data_pos;
263 unsigned char intr_mask;
264 unsigned char bootloader_id[2];
265 unsigned char productinfo1;
266 unsigned char productinfo2;
267 unsigned char *ext_data_source;
268 unsigned char *read_config_buf;
269 const unsigned char *firmware_data;
270 const unsigned char *config_data;
Alexandra Chin823a2f52013-07-29 16:09:52 -0700271 const unsigned char *lockdown_data;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800272 unsigned short block_size;
273 unsigned short fw_block_count;
274 unsigned short config_block_count;
Alexandra Chin823a2f52013-07-29 16:09:52 -0700275 unsigned short lockdown_block_count;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800276 unsigned short perm_config_block_count;
277 unsigned short bl_config_block_count;
278 unsigned short disp_config_block_count;
279 unsigned short config_size;
280 unsigned short config_area;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800281 unsigned short addr_f01_interrupt_register;
Alexandra Chin823a2f52013-07-29 16:09:52 -0700282 const unsigned char *data_buffer;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800283 struct synaptics_rmi4_fn_desc f01_fd;
284 struct synaptics_rmi4_fn_desc f34_fd;
285 struct synaptics_rmi4_exp_fn_ptr *fn_ptr;
286 struct synaptics_rmi4_data *rmi4_data;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800287 struct f34_flash_properties flash_properties;
Alexandra Chind5591a62013-02-07 12:59:15 -0800288 struct workqueue_struct *fwu_workqueue;
289 struct delayed_work fwu_work;
Alexandra Chin823a2f52013-07-29 16:09:52 -0700290 char image_name[NAME_BUFFER_SIZE];
291 struct image_content image_content;
Amy Maloched9bf0d92013-06-19 17:19:23 -0700292 char *ts_info;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800293};
294
295static struct synaptics_rmi4_fwu_handle *fwu;
296
Alexandra Chind9e204d2013-07-25 15:23:01 -0700297DECLARE_COMPLETION(fwu_remove_complete);
Alexandra Chin669d27c2012-12-24 15:42:30 +0800298
299static unsigned int extract_uint(const unsigned char *ptr)
300{
301 return (unsigned int)ptr[0] +
302 (unsigned int)ptr[1] * 0x100 +
303 (unsigned int)ptr[2] * 0x10000 +
304 (unsigned int)ptr[3] * 0x1000000;
305}
306
Amy Malocheafcecb22013-04-16 18:43:22 -0700307static unsigned int extract_uint_be(const unsigned char *ptr)
308{
309 return (unsigned int)ptr[3] +
310 (unsigned int)ptr[2] * 0x100 +
311 (unsigned int)ptr[1] * 0x10000 +
312 (unsigned int)ptr[0] * 0x1000000;
313}
314
Amy Maloched9bf0d92013-06-19 17:19:23 -0700315static void synaptics_rmi4_update_debug_info(void)
316{
317 unsigned char pkg_id[4];
318 unsigned int build_id;
319 struct synaptics_rmi4_device_info *rmi;
320 /* read device package id */
321 fwu->fn_ptr->read(fwu->rmi4_data,
322 fwu->f01_fd.query_base_addr + 17,
323 pkg_id,
324 sizeof(pkg_id));
325 rmi = &(fwu->rmi4_data->rmi4_mod_info);
326
327 build_id = (unsigned int)rmi->build_id[0] +
328 (unsigned int)rmi->build_id[1] * 0x100 +
329 (unsigned int)rmi->build_id[2] * 0x10000;
330
331 RMI4_STORE_TS_INFO(fwu->ts_info, pkg_id[1] << 8 | pkg_id[0],
332 pkg_id[3] << 8 | pkg_id[2], build_id);
333}
334
Alexandra Chin823a2f52013-07-29 16:09:52 -0700335static void parse_header(void)
Alexandra Chin669d27c2012-12-24 15:42:30 +0800336{
Alexandra Chin823a2f52013-07-29 16:09:52 -0700337 struct image_content *img = &fwu->image_content;
338 struct image_header_data *data =
339 (struct image_header_data *)fwu->data_buffer;
340 img->checksum = extract_uint(data->file_checksum);
341 img->bootloader_version = data->bootloader_version;
342 img->image_size = extract_uint(data->firmware_size);
343 img->config_size = extract_uint(data->config_size);
344 memcpy(img->product_id, data->product_id,
Amy Malocheafcecb22013-04-16 18:43:22 -0700345 sizeof(data->product_id));
Alexandra Chin823a2f52013-07-29 16:09:52 -0700346 img->product_id[sizeof(data->product_id)] = 0;
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700347
Alexandra Chin823a2f52013-07-29 16:09:52 -0700348 img->product_id[sizeof(data->product_info)] = 0;
349 memcpy(img->product_info, data->product_info,
Amy Malocheafcecb22013-04-16 18:43:22 -0700350 sizeof(data->product_info));
351
Alexandra Chin823a2f52013-07-29 16:09:52 -0700352 img->is_contain_build_info =
Amy Malocheafcecb22013-04-16 18:43:22 -0700353 (data->options_firmware_id == (1 << OPTION_BUILD_INFO));
Alexandra Chin823a2f52013-07-29 16:09:52 -0700354
355 if (img->is_contain_build_info) {
356 img->firmware_id = extract_uint(data->firmware_id);
357 img->package_id = (data->pkg_id_rev_msb << 8) |
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700358 data->pkg_id_lsb;
Alexandra Chin823a2f52013-07-29 16:09:52 -0700359 img->package_revision_id = (data->pkg_id_rev_msb << 8) |
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700360 data->pkg_id_rev_lsb;
361 dev_info(&fwu->rmi4_data->i2c_client->dev,
362 "%s Package ID %d Rev %d\n", __func__,
Alexandra Chin823a2f52013-07-29 16:09:52 -0700363 img->package_id, img->package_revision_id);
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700364
Alexandra Chin823a2f52013-07-29 16:09:52 -0700365 img->firmware_id = extract_uint(data->firmware_id);
Amy Malocheafcecb22013-04-16 18:43:22 -0700366 dev_info(&fwu->rmi4_data->i2c_client->dev,
367 "%s Firwmare build id %d\n", __func__,
Alexandra Chin823a2f52013-07-29 16:09:52 -0700368 img->firmware_id);
Amy Malocheafcecb22013-04-16 18:43:22 -0700369 }
Alexandra Chin669d27c2012-12-24 15:42:30 +0800370
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700371 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
Alexandra Chin669d27c2012-12-24 15:42:30 +0800372 "Firwmare size %d, config size %d\n",
Alexandra Chin823a2f52013-07-29 16:09:52 -0700373 img->image_size,
374 img->config_size);
375
376 /* get UI firmware offset */
377 if (img->image_size)
378 img->firmware_data = fwu->data_buffer + FW_IMAGE_OFFSET;
379 /* get config offset*/
380 if (img->config_size)
381 img->config_data = fwu->data_buffer + FW_IMAGE_OFFSET +
382 img->image_size;
383 /* get lockdown offset*/
384 switch (img->bootloader_version) {
385 case 3:
386 case 4:
387 img->lockdown_block_count = 4;
388 break;
389 case 5:
390 case 6:
391 img->lockdown_block_count = 5;
392 break;
393 default:
394 dev_warn(&fwu->rmi4_data->i2c_client->dev,
395 "%s: Not support lockdown in " \
396 "bootloader version V%d\n",
397 __func__, img->bootloader_version);
398 img->lockdown_data = NULL;
399 }
400
401 img->lockdown_data = fwu->data_buffer +
402 FW_IMAGE_OFFSET -
403 img->lockdown_block_count * fwu->block_size;
404
405 fwu->lockdown_block_count = img->lockdown_block_count;
406 fwu->lockdown_data = img->lockdown_data;
407 fwu->config_data = img->config_data;
408 fwu->firmware_data = img->firmware_data;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800409 return;
410}
411
Alexandra Chin669d27c2012-12-24 15:42:30 +0800412static int fwu_read_f01_device_status(struct f01_device_status *status)
413{
414 int retval;
415
416 retval = fwu->fn_ptr->read(fwu->rmi4_data,
417 fwu->f01_fd.data_base_addr,
418 status->data,
419 sizeof(status->data));
420 if (retval < 0) {
421 dev_err(&fwu->rmi4_data->i2c_client->dev,
422 "%s: Failed to read F01 device status\n",
423 __func__);
424 return retval;
425 }
426
427 return 0;
428}
429
Alexandra Chin400f26e2013-07-25 11:58:17 -0700430static unsigned short fwu_get_address(enum flash_offset type)
431{
432 int offset;
433 unsigned short addr = 0;
434 struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
435
436 switch (type) {
437 case OFFSET_BOOTLOADER_ID:
438 offset = 0;
439 addr = fwu->f34_fd.query_base_addr + offset;
440 break;
441 case OFFSET_FLASH_PROPERTIES:
442 offset = ((fwu->f34_fd.version == 0) ? 2 : 1);
443 addr = fwu->f34_fd.query_base_addr + offset;
444 break;
445 case OFFSET_BLOCK_SIZE:
446 offset = ((fwu->f34_fd.version == 0) ? 3 : 2);
447 addr = fwu->f34_fd.query_base_addr + offset;
448 break;
449 case OFFSET_FW_BLOCK_COUNT:
450 offset = ((fwu->f34_fd.version == 0) ? 5 : 3);
451 addr = fwu->f34_fd.query_base_addr + offset;
452 break;
453 case OFFSET_BLOCK_NUMBER:
454 offset = 0;
455 addr = fwu->f34_fd.data_base_addr + offset;
456 break;
457 case OFFSET_BLOCK_DATA:
458 offset = ((fwu->f34_fd.version == 0) ? 2 : 1);
459 addr = fwu->f34_fd.data_base_addr + offset;
460 break;
461 case OFFSET_FLASH_CONTROL:
462 offset = ((fwu->f34_fd.version == 0) ?
463 2 + (fwu->block_size) : 2);
464 addr = fwu->f34_fd.data_base_addr + offset;
465 break;
466 case OFFSET_FLASH_STATUS:
467 if (fwu->f34_fd.version == 1) {
468 offset = 3;
469 addr = fwu->f34_fd.data_base_addr + offset;
470 } else if (fwu->f34_fd.version == 0) {
471 dev_warn(&i2c_client->dev,
472 "%s: F$34 version 0 does not contain " \
473 "flash status register\n",
474 __func__);
475 }
476 break;
477 default:
478 dev_err(&i2c_client->dev,
479 "%s: Unknown flash offset (%d)\n",
480 __func__, type);
481 break;
482 }
483 return addr;
484}
485
Alexandra Chin669d27c2012-12-24 15:42:30 +0800486static int fwu_read_f34_queries(void)
487{
488 int retval;
489 unsigned char count = 4;
490 unsigned char buf[10];
491 struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
492
493 retval = fwu->fn_ptr->read(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -0700494 fwu_get_address(OFFSET_BOOTLOADER_ID),
Alexandra Chin669d27c2012-12-24 15:42:30 +0800495 fwu->bootloader_id,
496 sizeof(fwu->bootloader_id));
497 if (retval < 0) {
498 dev_err(&i2c_client->dev,
499 "%s: Failed to read bootloader ID\n",
500 __func__);
501 return retval;
502 }
503
504 retval = fwu->fn_ptr->read(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -0700505 fwu_get_address(OFFSET_FLASH_PROPERTIES),
Alexandra Chin669d27c2012-12-24 15:42:30 +0800506 fwu->flash_properties.data,
507 sizeof(fwu->flash_properties.data));
508 if (retval < 0) {
509 dev_err(&i2c_client->dev,
510 "%s: Failed to read flash properties\n",
511 __func__);
512 return retval;
513 }
514
Alexandra Chind5591a62013-02-07 12:59:15 -0800515 dev_info(&i2c_client->dev, "%s perm:%d, bl:%d, display:%d\n",
Alexandra Chin669d27c2012-12-24 15:42:30 +0800516 __func__,
517 fwu->flash_properties.has_perm_config,
518 fwu->flash_properties.has_bl_config,
519 fwu->flash_properties.has_display_config);
520
521 if (fwu->flash_properties.has_perm_config)
522 count += 2;
523
524 if (fwu->flash_properties.has_bl_config)
525 count += 2;
526
527 if (fwu->flash_properties.has_display_config)
528 count += 2;
529
530 retval = fwu->fn_ptr->read(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -0700531 fwu_get_address(OFFSET_BLOCK_SIZE),
Alexandra Chin669d27c2012-12-24 15:42:30 +0800532 buf,
533 2);
534 if (retval < 0) {
535 dev_err(&i2c_client->dev,
536 "%s: Failed to read block size info\n",
537 __func__);
538 return retval;
539 }
540
541 batohs(&fwu->block_size, &(buf[0]));
542
543 retval = fwu->fn_ptr->read(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -0700544 fwu_get_address(OFFSET_FW_BLOCK_COUNT),
Alexandra Chin669d27c2012-12-24 15:42:30 +0800545 buf,
546 count);
547 if (retval < 0) {
548 dev_err(&i2c_client->dev,
Alexandra Chin400f26e2013-07-25 11:58:17 -0700549 "%s: Failed to read block count info\n",
550 __func__);
Alexandra Chin669d27c2012-12-24 15:42:30 +0800551 return retval;
552 }
553
554 batohs(&fwu->fw_block_count, &(buf[0]));
555 batohs(&fwu->config_block_count, &(buf[2]));
556
557 count = 4;
558
559 if (fwu->flash_properties.has_perm_config) {
560 batohs(&fwu->perm_config_block_count, &(buf[count]));
561 count += 2;
562 }
563
564 if (fwu->flash_properties.has_bl_config) {
565 batohs(&fwu->bl_config_block_count, &(buf[count]));
566 count += 2;
567 }
568
569 if (fwu->flash_properties.has_display_config)
570 batohs(&fwu->disp_config_block_count, &(buf[count]));
571
Alexandra Chin669d27c2012-12-24 15:42:30 +0800572 return 0;
573}
574
575static int fwu_read_interrupt_status(void)
576{
577 int retval;
578 unsigned char interrupt_status;
579 retval = fwu->fn_ptr->read(fwu->rmi4_data,
580 fwu->addr_f01_interrupt_register,
581 &interrupt_status,
582 sizeof(interrupt_status));
583 if (retval < 0) {
584 dev_err(&fwu->rmi4_data->i2c_client->dev,
585 "%s: Failed to read flash status\n",
586 __func__);
587 return retval;
588 }
589 return interrupt_status;
590}
591
Alexandra Chin400f26e2013-07-25 11:58:17 -0700592static int fwu_read_f34_flash_status(unsigned char *status)
Alexandra Chin669d27c2012-12-24 15:42:30 +0800593{
594 int retval;
Alexandra Chin400f26e2013-07-25 11:58:17 -0700595 struct f34_flash_control flash_control;
596 struct f34_flash_status flash_status;
597
598 if (fwu->f34_fd.version == 1) {
599 retval = fwu->fn_ptr->read(fwu->rmi4_data,
600 fwu_get_address(OFFSET_FLASH_STATUS),
601 flash_status.data,
602 sizeof(flash_status.data));
603 if (retval < 0) {
604 dev_err(&fwu->rmi4_data->i2c_client->dev,
Alexandra Chin669d27c2012-12-24 15:42:30 +0800605 "%s: Failed to read flash status\n",
606 __func__);
Alexandra Chin400f26e2013-07-25 11:58:17 -0700607 return -EIO;
608 }
609 *status = flash_status.status;
610 } else {
611 retval = fwu->fn_ptr->read(fwu->rmi4_data,
612 fwu_get_address(OFFSET_FLASH_CONTROL),
613 flash_control.data,
614 sizeof(flash_control.data));
615 if (retval < 0) {
616 dev_err(&fwu->rmi4_data->i2c_client->dev,
617 "%s: Failed to read flash status\n",
618 __func__);
619 return -EIO;
620 }
621 *status = flash_control.status;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800622 }
623 return 0;
624}
625
626static int fwu_reset_device(void)
627{
628 int retval;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800629
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700630 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
Alexandra Chind5591a62013-02-07 12:59:15 -0800631 "%s: Reset device\n",
632 __func__);
Alexandra Chin669d27c2012-12-24 15:42:30 +0800633
Alexandra Chin669d27c2012-12-24 15:42:30 +0800634 retval = fwu->rmi4_data->reset_device(fwu->rmi4_data);
635 if (retval < 0) {
636 dev_err(&fwu->rmi4_data->i2c_client->dev,
637 "%s: Failed to reset core driver after reflash\n",
638 __func__);
639 return retval;
640 }
Alexandra Chin400f26e2013-07-25 11:58:17 -0700641
642 fwu->polling_mode = false;
643
Alexandra Chin669d27c2012-12-24 15:42:30 +0800644 return 0;
645}
646
647static int fwu_write_f34_command(unsigned char cmd)
648{
649 int retval;
Alexandra Chin400f26e2013-07-25 11:58:17 -0700650 struct f34_flash_control flash_control;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800651
Alexandra Chin400f26e2013-07-25 11:58:17 -0700652 flash_control.data[0] = cmd;
653 fwu->interrupt_flag = false;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800654 retval = fwu->fn_ptr->write(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -0700655 fwu_get_address(OFFSET_FLASH_CONTROL),
656 flash_control.data,
657 sizeof(flash_control.data));
Alexandra Chin669d27c2012-12-24 15:42:30 +0800658 if (retval < 0) {
659 dev_err(&fwu->rmi4_data->i2c_client->dev,
660 "%s: Failed to write command 0x%02x\n",
Alexandra Chin400f26e2013-07-25 11:58:17 -0700661 __func__, flash_control.data[0]);
Alexandra Chin669d27c2012-12-24 15:42:30 +0800662 return retval;
663 }
664 return 0;
665}
666
Alexandra Chin669d27c2012-12-24 15:42:30 +0800667static int fwu_wait_for_idle(int timeout_ms)
668{
669 int count = 0;
Alexandra Chind5591a62013-02-07 12:59:15 -0800670 int timeout_count = ((timeout_ms * 1000) / SLEEP_TIME_US) + 1;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800671 do {
Alexandra Chin400f26e2013-07-25 11:58:17 -0700672 if (fwu->interrupt_flag)
Alexandra Chin669d27c2012-12-24 15:42:30 +0800673 return 0;
Alexandra Chin400f26e2013-07-25 11:58:17 -0700674 if (fwu->polling_mode)
675 if (fwu->intr_mask & fwu_read_interrupt_status())
676 return 0;
677 usleep_range(SLEEP_TIME_US, SLEEP_TIME_US + 1);
Alexandra Chind5591a62013-02-07 12:59:15 -0800678 } while (count++ < timeout_count);
679
Alexandra Chin400f26e2013-07-25 11:58:17 -0700680 if (fwu->intr_mask & fwu_read_interrupt_status()) {
681 fwu->polling_mode = true;
682 dev_info(&fwu->rmi4_data->i2c_client->dev,
683 "%s: Switch to polling mode\n",
684 __func__);
Alexandra Chind5591a62013-02-07 12:59:15 -0800685 return 0;
Alexandra Chin400f26e2013-07-25 11:58:17 -0700686 }
Alexandra Chin669d27c2012-12-24 15:42:30 +0800687
688 dev_err(&fwu->rmi4_data->i2c_client->dev,
689 "%s: Timed out waiting for idle status\n",
690 __func__);
691
692 return -ETIMEDOUT;
693}
694
Alexandra Chin823a2f52013-07-29 16:09:52 -0700695static enum flash_area fwu_go_nogo(void)
Alexandra Chind5591a62013-02-07 12:59:15 -0800696{
697 int retval = 0;
698 int index = 0;
699 int deviceFirmwareID;
700 int imageConfigID;
701 int deviceConfigID;
702 unsigned long imageFirmwareID;
703 unsigned char firmware_id[4];
704 unsigned char config_id[4];
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700705 unsigned char pkg_id[4];
Alexandra Chind5591a62013-02-07 12:59:15 -0800706 char *strptr;
707 char *imagePR = kzalloc(sizeof(MAX_FIRMWARE_ID_LEN), GFP_KERNEL);
708 enum flash_area flash_area = NONE;
709 struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
710 struct f01_device_status f01_device_status;
Alexandra Chin823a2f52013-07-29 16:09:52 -0700711 struct image_content *img = &fwu->image_content;
Alexandra Chind5591a62013-02-07 12:59:15 -0800712
713 if (fwu->force_update) {
714 flash_area = UI_FIRMWARE;
715 goto exit;
716 }
717
Alexandra Chin823a2f52013-07-29 16:09:52 -0700718 if (img->is_contain_build_info) {
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700719 /* if package id does not match, do not update firmware */
720 fwu->fn_ptr->read(fwu->rmi4_data,
721 fwu->f01_fd.query_base_addr + 17,
722 pkg_id,
723 sizeof(pkg_id));
724
Alexandra Chin823a2f52013-07-29 16:09:52 -0700725 if (img->package_id != ((pkg_id[1] << 8) | pkg_id[0])) {
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700726 flash_area = MISMATCH;
727 goto exit;
728 }
Alexandra Chin823a2f52013-07-29 16:09:52 -0700729 if (img->package_revision_id !=
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700730 ((pkg_id[3] << 8) | pkg_id[2])) {
731 flash_area = MISMATCH;
732 goto exit;
733 }
734 }
735
Alexandra Chin400f26e2013-07-25 11:58:17 -0700736 /* check firmware size */
Alexandra Chin823a2f52013-07-29 16:09:52 -0700737 if (fwu->fw_block_count*fwu->block_size != img->image_size) {
Alexandra Chin400f26e2013-07-25 11:58:17 -0700738 dev_err(&i2c_client->dev,
739 "%s: firmware size of device (%d) != .img (%d)\n",
740 __func__,
741 fwu->config_block_count * fwu->block_size,
Alexandra Chin823a2f52013-07-29 16:09:52 -0700742 img->image_size);
Alexandra Chin400f26e2013-07-25 11:58:17 -0700743 flash_area = NONE;
744 goto exit;
745 }
746
747 /* check config size */
Alexandra Chin823a2f52013-07-29 16:09:52 -0700748 if (fwu->config_block_count*fwu->block_size != img->config_size) {
Alexandra Chin400f26e2013-07-25 11:58:17 -0700749 dev_err(&i2c_client->dev,
750 "%s: config size of device (%d) != .img (%d)\n",
751 __func__,
752 fwu->config_block_count * fwu->block_size,
Alexandra Chin823a2f52013-07-29 16:09:52 -0700753 img->config_size);
Alexandra Chin400f26e2013-07-25 11:58:17 -0700754 flash_area = NONE;
755 goto exit;
756 }
757
Alexandra Chind5591a62013-02-07 12:59:15 -0800758 retval = fwu_read_f01_device_status(&f01_device_status);
759 if (retval < 0) {
760 flash_area = NONE;
761 goto exit;
762 }
763
Alexandra Chind5591a62013-02-07 12:59:15 -0800764 /* Force update firmware when device is in bootloader mode */
765 if (f01_device_status.flash_prog) {
766 dev_info(&i2c_client->dev,
767 "%s: In flash prog mode\n",
768 __func__);
769 flash_area = UI_FIRMWARE;
770 goto exit;
771 }
772
Alexandra Chind5591a62013-02-07 12:59:15 -0800773 /* device firmware id */
774 retval = fwu->fn_ptr->read(fwu->rmi4_data,
775 fwu->f01_fd.query_base_addr + 18,
776 firmware_id,
777 sizeof(firmware_id));
778 if (retval < 0) {
779 dev_err(&i2c_client->dev,
Amy Malocheafcecb22013-04-16 18:43:22 -0700780 "%s: Failed to read firmware ID (code %d).\n",
781 __func__, retval);
Alexandra Chind5591a62013-02-07 12:59:15 -0800782 goto exit;
783 }
784 firmware_id[3] = 0;
785 deviceFirmwareID = extract_uint(firmware_id);
786
787 /* .img firmware id */
Alexandra Chin823a2f52013-07-29 16:09:52 -0700788 if (img->is_contain_build_info) {
Alexandra Chind5591a62013-02-07 12:59:15 -0800789 dev_err(&i2c_client->dev,
Amy Malocheafcecb22013-04-16 18:43:22 -0700790 "%s: Image option contains build info.\n",
791 __func__);
Alexandra Chin823a2f52013-07-29 16:09:52 -0700792 imageFirmwareID = img->firmware_id;
Amy Malocheafcecb22013-04-16 18:43:22 -0700793 } else {
Alexandra Chin823a2f52013-07-29 16:09:52 -0700794 if (!fwu->image_name) {
795 dev_info(&i2c_client->dev,
796 "%s: Unknown image file name\n",
797 __func__);
798 flash_area = UI_FIRMWARE;
799 goto exit;
800 }
801 strptr = strnstr(fwu->image_name, "PR",
802 sizeof(fwu->image_name));
Amy Malocheafcecb22013-04-16 18:43:22 -0700803 if (!strptr) {
804 dev_err(&i2c_client->dev,
805 "No valid PR number (PRxxxxxxx)" \
806 "found in image file name...\n");
807 goto exit;
808 }
809
810 strptr += 2;
811 while (strptr[index] >= '0' && strptr[index] <= '9') {
812 imagePR[index] = strptr[index];
813 index++;
814 }
815 imagePR[index] = 0;
816
817 retval = kstrtoul(imagePR, 10, &imageFirmwareID);
818 if (retval == -EINVAL) {
819 dev_err(&i2c_client->dev,
820 "invalid image firmware id...\n");
821 goto exit;
822 }
Alexandra Chind5591a62013-02-07 12:59:15 -0800823 }
824
Amy Malocheafcecb22013-04-16 18:43:22 -0700825 dev_dbg(&i2c_client->dev,
Alexandra Chind5591a62013-02-07 12:59:15 -0800826 "Device firmware id %d, .img firmware id %d\n",
827 deviceFirmwareID,
828 (unsigned int)imageFirmwareID);
829 if (imageFirmwareID > deviceFirmwareID) {
830 flash_area = UI_FIRMWARE;
831 goto exit;
Alexandra Chinc556cf02013-03-19 17:46:05 -0700832 } else if (imageFirmwareID < deviceFirmwareID) {
833 flash_area = NONE;
834 dev_info(&i2c_client->dev,
Amy Malocheafcecb22013-04-16 18:43:22 -0700835 "%s: Img fw is older than device fw. Skip fw update.\n",
836 __func__);
Alexandra Chinc556cf02013-03-19 17:46:05 -0700837 goto exit;
Alexandra Chind5591a62013-02-07 12:59:15 -0800838 }
839
840 /* device config id */
841 retval = fwu->fn_ptr->read(fwu->rmi4_data,
842 fwu->f34_fd.ctrl_base_addr,
843 config_id,
844 sizeof(config_id));
845 if (retval < 0) {
846 dev_err(&i2c_client->dev,
Amy Malocheafcecb22013-04-16 18:43:22 -0700847 "%s: Failed to read config ID (code %d).\n",
848 __func__, retval);
Alexandra Chind5591a62013-02-07 12:59:15 -0800849 flash_area = NONE;
850 goto exit;
851 }
Amy Malocheafcecb22013-04-16 18:43:22 -0700852 deviceConfigID = extract_uint_be(config_id);
Alexandra Chind5591a62013-02-07 12:59:15 -0800853
Amy Malocheafcecb22013-04-16 18:43:22 -0700854 dev_dbg(&i2c_client->dev,
Alexandra Chind5591a62013-02-07 12:59:15 -0800855 "Device config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
856 config_id[0], config_id[1], config_id[2], config_id[3]);
857
858 /* .img config id */
Amy Malocheafcecb22013-04-16 18:43:22 -0700859 dev_dbg(&i2c_client->dev,
Alexandra Chind5591a62013-02-07 12:59:15 -0800860 ".img config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
861 fwu->config_data[0],
862 fwu->config_data[1],
863 fwu->config_data[2],
864 fwu->config_data[3]);
Amy Malocheafcecb22013-04-16 18:43:22 -0700865 imageConfigID = extract_uint_be(fwu->config_data);
866
867 dev_dbg(&i2c_client->dev,
868 "%s: Device config ID %d, .img config ID %d\n",
869 __func__, deviceConfigID, imageConfigID);
Alexandra Chind5591a62013-02-07 12:59:15 -0800870
871 if (imageConfigID > deviceConfigID) {
872 flash_area = CONFIG_AREA;
873 goto exit;
874 }
Alexandra Chind5591a62013-02-07 12:59:15 -0800875exit:
876 kfree(imagePR);
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700877 if (flash_area == MISMATCH)
878 dev_info(&i2c_client->dev,
879 "%s: Package ID indicates mismatch of firmware and" \
880 " controller compatibility\n", __func__);
881 else if (flash_area == NONE)
Alexandra Chind5591a62013-02-07 12:59:15 -0800882 dev_info(&i2c_client->dev,
Amy Malocheafcecb22013-04-16 18:43:22 -0700883 "%s: Nothing needs to be updated\n", __func__);
Alexandra Chind5591a62013-02-07 12:59:15 -0800884 else
885 dev_info(&i2c_client->dev,
Amy Malocheafcecb22013-04-16 18:43:22 -0700886 "%s: Update %s block\n", __func__,
Alexandra Chind5591a62013-02-07 12:59:15 -0800887 flash_area == UI_FIRMWARE ? "UI FW" : "CONFIG");
888 return flash_area;
889}
890
Alexandra Chin669d27c2012-12-24 15:42:30 +0800891static int fwu_scan_pdt(void)
892{
893 int retval;
894 unsigned char ii;
895 unsigned char intr_count = 0;
896 unsigned char intr_off;
897 unsigned char intr_src;
898 unsigned short addr;
899 bool f01found = false;
900 bool f34found = false;
901 struct synaptics_rmi4_fn_desc rmi_fd;
902
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700903 dev_dbg(&fwu->rmi4_data->i2c_client->dev, "Scan PDT\n");
Alexandra Chin669d27c2012-12-24 15:42:30 +0800904
905 for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) {
906 retval = fwu->fn_ptr->read(fwu->rmi4_data,
907 addr,
908 (unsigned char *)&rmi_fd,
909 sizeof(rmi_fd));
910 if (retval < 0)
911 return retval;
912
913 if (rmi_fd.fn_number) {
914 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
915 "%s: Found F%02x\n",
916 __func__, rmi_fd.fn_number);
917 switch (rmi_fd.fn_number) {
918 case SYNAPTICS_RMI4_F01:
919 f01found = true;
920 fwu->f01_fd = rmi_fd;
921 fwu->addr_f01_interrupt_register =
922 fwu->f01_fd.data_base_addr + 1;
923 break;
924 case SYNAPTICS_RMI4_F34:
925 f34found = true;
926 fwu->f34_fd = rmi_fd;
927 fwu->intr_mask = 0;
928 intr_src = rmi_fd.intr_src_count;
929 intr_off = intr_count % 8;
930 for (ii = intr_off;
931 ii < ((intr_src & MASK_3BIT) +
932 intr_off);
933 ii++)
934 fwu->intr_mask |= 1 << ii;
935 break;
936 }
937 } else
938 break;
939
940 intr_count += (rmi_fd.intr_src_count & MASK_3BIT);
941 }
942
943 if (!f01found || !f34found) {
944 dev_err(&fwu->rmi4_data->i2c_client->dev,
945 "%s: Failed to find both F01 and F34\n",
946 __func__);
947 return -EINVAL;
948 }
949
950 fwu_read_interrupt_status();
951 return 0;
952}
953
954static int fwu_write_blocks(unsigned char *block_ptr, unsigned short block_cnt,
955 unsigned char command)
956{
957 int retval;
Alexandra Chin400f26e2013-07-25 11:58:17 -0700958 unsigned char flash_status;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800959 unsigned char block_offset[] = {0, 0};
960 unsigned short block_num;
Alexandra Chin400f26e2013-07-25 11:58:17 -0700961 unsigned short addr_block_data = fwu_get_address(OFFSET_BLOCK_DATA);
962 unsigned short addr_block_num = fwu_get_address(OFFSET_BLOCK_NUMBER);
Alexandra Chind5591a62013-02-07 12:59:15 -0800963 struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800964#ifdef SHOW_PROGRESS
Alexandra Chin823a2f52013-07-29 16:09:52 -0700965 unsigned int progress;
966 unsigned char command_str[10];
967 switch (command) {
968 case CMD_WRITE_CONFIG_BLOCK:
969 progress = 10;
970 strlcpy(command_str, "config", 10);
971 break;
972 case CMD_WRITE_FW_BLOCK:
973 progress = 100;
974 strlcpy(command_str, "firmware", 10);
975 break;
976 case CMD_WRITE_LOCKDOWN_BLOCK:
977 progress = 1;
978 strlcpy(command_str, "lockdown", 10);
979 break;
980 default:
981 progress = 1;
982 strlcpy(command_str, "unknown", 10);
983 break;
984 }
Alexandra Chin669d27c2012-12-24 15:42:30 +0800985#endif
Alexandra Chind5591a62013-02-07 12:59:15 -0800986
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700987 dev_dbg(&i2c_client->dev,
Alexandra Chind5591a62013-02-07 12:59:15 -0800988 "%s: Start to update %s blocks\n",
989 __func__,
Alexandra Chin823a2f52013-07-29 16:09:52 -0700990 command_str);
Alexandra Chin669d27c2012-12-24 15:42:30 +0800991 retval = fwu->fn_ptr->write(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -0700992 addr_block_num,
Alexandra Chin669d27c2012-12-24 15:42:30 +0800993 block_offset,
994 sizeof(block_offset));
995 if (retval < 0) {
Alexandra Chind5591a62013-02-07 12:59:15 -0800996 dev_err(&i2c_client->dev,
Alexandra Chin669d27c2012-12-24 15:42:30 +0800997 "%s: Failed to write to block number registers\n",
998 __func__);
999 return retval;
1000 }
1001
1002 for (block_num = 0; block_num < block_cnt; block_num++) {
1003#ifdef SHOW_PROGRESS
1004 if (block_num % progress == 0)
Alexandra Chind5591a62013-02-07 12:59:15 -08001005 dev_info(&i2c_client->dev,
1006 "%s: update %s %3d / %3d\n",
1007 __func__,
Alexandra Chin823a2f52013-07-29 16:09:52 -07001008 command_str,
Alexandra Chind5591a62013-02-07 12:59:15 -08001009 block_num, block_cnt);
Alexandra Chin669d27c2012-12-24 15:42:30 +08001010#endif
1011 retval = fwu->fn_ptr->write(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -07001012 addr_block_data,
Alexandra Chin669d27c2012-12-24 15:42:30 +08001013 block_ptr,
1014 fwu->block_size);
1015 if (retval < 0) {
Alexandra Chind5591a62013-02-07 12:59:15 -08001016 dev_err(&i2c_client->dev,
Alexandra Chin669d27c2012-12-24 15:42:30 +08001017 "%s: Failed to write block data (block %d)\n",
1018 __func__, block_num);
1019 return retval;
1020 }
1021
1022 retval = fwu_write_f34_command(command);
1023 if (retval < 0) {
Alexandra Chind5591a62013-02-07 12:59:15 -08001024 dev_err(&i2c_client->dev,
Alexandra Chin669d27c2012-12-24 15:42:30 +08001025 "%s: Failed to write command for block %d\n",
1026 __func__, block_num);
1027 return retval;
1028 }
1029
1030 retval = fwu_wait_for_idle(WRITE_WAIT_MS);
1031 if (retval < 0) {
Alexandra Chind5591a62013-02-07 12:59:15 -08001032 dev_err(&i2c_client->dev,
1033 "%s: Failed to wait for idle status (block %d)\n",
1034 __func__, block_num);
Alexandra Chin669d27c2012-12-24 15:42:30 +08001035 return retval;
1036 }
1037
Alexandra Chin400f26e2013-07-25 11:58:17 -07001038 #if CHECK_FLASH_BLOCK_STATUS
1039 retval = fwu_read_f34_flash_status(&flash_status);
1040 if (retval < 0) {
Alexandra Chind5591a62013-02-07 12:59:15 -08001041 dev_err(&i2c_client->dev,
Alexandra Chin400f26e2013-07-25 11:58:17 -07001042 "%s: Failed to read flash status (block %d)\n",
1043 __func__, block_num);
Shantanu Jain41f0d472013-01-04 12:14:37 +05301044 return retval;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001045 }
Alexandra Chin400f26e2013-07-25 11:58:17 -07001046 if (flash_status != 0x00) {
1047 dev_err(&i2c_client->dev,
1048 "%s: Flash block %d failed, status 0x%02X\n",
1049 __func__, block_num, flash_status);
1050 return -EINVAL;
1051 }
1052 #endif
Alexandra Chin669d27c2012-12-24 15:42:30 +08001053 block_ptr += fwu->block_size;
1054 }
1055#ifdef SHOW_PROGRESS
Alexandra Chind5591a62013-02-07 12:59:15 -08001056 dev_info(&i2c_client->dev,
1057 "%s: update %s %3d / %3d\n",
1058 __func__,
Alexandra Chin823a2f52013-07-29 16:09:52 -07001059 command_str,
Alexandra Chind5591a62013-02-07 12:59:15 -08001060 block_cnt, block_cnt);
Alexandra Chin669d27c2012-12-24 15:42:30 +08001061#endif
1062 return 0;
1063}
1064
1065static int fwu_write_firmware(void)
1066{
1067 return fwu_write_blocks((unsigned char *)fwu->firmware_data,
1068 fwu->fw_block_count, CMD_WRITE_FW_BLOCK);
1069}
1070
1071static int fwu_write_configuration(void)
1072{
1073 return fwu_write_blocks((unsigned char *)fwu->config_data,
1074 fwu->config_block_count, CMD_WRITE_CONFIG_BLOCK);
1075}
1076
Alexandra Chin823a2f52013-07-29 16:09:52 -07001077static int fwu_write_lockdown_block(void)
1078{
1079 return fwu_write_blocks((unsigned char *)fwu->lockdown_data,
1080 fwu->lockdown_block_count, CMD_WRITE_LOCKDOWN_BLOCK);
1081}
1082
Alexandra Chin669d27c2012-12-24 15:42:30 +08001083static int fwu_write_bootloader_id(void)
1084{
1085 int retval;
1086
Amy Maloche2c4c48c2013-05-01 20:06:23 -07001087 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
Alexandra Chind5591a62013-02-07 12:59:15 -08001088 "Write bootloader ID 0x%02X 0x%02X\n",
1089 fwu->bootloader_id[0],
1090 fwu->bootloader_id[1]);
Amy Maloche2c4c48c2013-05-01 20:06:23 -07001091
Alexandra Chin669d27c2012-12-24 15:42:30 +08001092 retval = fwu->fn_ptr->write(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -07001093 fwu_get_address(OFFSET_BLOCK_DATA),
Alexandra Chin669d27c2012-12-24 15:42:30 +08001094 fwu->bootloader_id,
1095 sizeof(fwu->bootloader_id));
1096 if (retval < 0) {
1097 dev_err(&fwu->rmi4_data->i2c_client->dev,
1098 "%s: Failed to write bootloader ID\n",
1099 __func__);
1100 return retval;
1101 }
1102
1103 return 0;
1104}
1105
Alexandra Chin823a2f52013-07-29 16:09:52 -07001106static int fwu_enter_flash_prog(bool force)
Alexandra Chin669d27c2012-12-24 15:42:30 +08001107{
1108 int retval;
1109 struct f01_device_status f01_device_status;
1110 struct f01_device_control f01_device_control;
1111
Amy Maloche2c4c48c2013-05-01 20:06:23 -07001112 dev_dbg(&fwu->rmi4_data->i2c_client->dev, "Enter bootloader mode\n");
1113
Alexandra Chin669d27c2012-12-24 15:42:30 +08001114 retval = fwu_read_f01_device_status(&f01_device_status);
1115 if (retval < 0)
1116 return retval;
1117
1118 if (f01_device_status.flash_prog) {
1119 dev_info(&fwu->rmi4_data->i2c_client->dev,
1120 "%s: Already in flash prog mode\n",
1121 __func__);
1122 return 0;
1123 }
1124
1125 retval = fwu_write_bootloader_id();
1126 if (retval < 0)
1127 return retval;
1128
1129 retval = fwu_write_f34_command(CMD_ENABLE_FLASH_PROG);
1130 if (retval < 0)
1131 return retval;
1132
1133 retval = fwu_wait_for_idle(ENABLE_WAIT_MS);
1134 if (retval < 0)
1135 return retval;
1136
Alexandra Chin669d27c2012-12-24 15:42:30 +08001137 retval = fwu_scan_pdt();
1138 if (retval < 0)
1139 return retval;
1140
1141 retval = fwu_read_f01_device_status(&f01_device_status);
1142 if (retval < 0)
1143 return retval;
1144
1145 if (!f01_device_status.flash_prog) {
1146 dev_err(&fwu->rmi4_data->i2c_client->dev,
1147 "%s: Not in flash prog mode\n",
1148 __func__);
1149 return -EINVAL;
1150 }
1151
1152 retval = fwu_read_f34_queries();
1153 if (retval < 0)
1154 return retval;
1155
1156 retval = fwu->fn_ptr->read(fwu->rmi4_data,
1157 fwu->f01_fd.ctrl_base_addr,
1158 f01_device_control.data,
1159 sizeof(f01_device_control.data));
1160 if (retval < 0) {
1161 dev_err(&fwu->rmi4_data->i2c_client->dev,
1162 "%s: Failed to read F01 device control\n",
1163 __func__);
1164 return retval;
1165 }
1166
1167 f01_device_control.nosleep = true;
1168 f01_device_control.sleep_mode = SLEEP_MODE_NORMAL;
1169
1170 retval = fwu->fn_ptr->write(fwu->rmi4_data,
1171 fwu->f01_fd.ctrl_base_addr,
1172 f01_device_control.data,
1173 sizeof(f01_device_control.data));
1174 if (retval < 0) {
1175 dev_err(&fwu->rmi4_data->i2c_client->dev,
1176 "%s: Failed to write F01 device control\n",
1177 __func__);
1178 return retval;
1179 }
Alexandra Chin400f26e2013-07-25 11:58:17 -07001180 fwu->polling_mode = false;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001181 return retval;
1182}
1183
Alexandra Chin669d27c2012-12-24 15:42:30 +08001184static int fwu_do_write_config(void)
1185{
1186 int retval;
1187
Alexandra Chin823a2f52013-07-29 16:09:52 -07001188 retval = fwu_enter_flash_prog(false);
Alexandra Chin669d27c2012-12-24 15:42:30 +08001189 if (retval < 0)
1190 return retval;
1191
1192 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1193 "%s: Entered flash prog mode\n",
1194 __func__);
1195
1196 if (fwu->config_area == PERM_CONFIG_AREA) {
1197 fwu->config_block_count = fwu->perm_config_block_count;
1198 goto write_config;
1199 }
1200
1201 retval = fwu_write_bootloader_id();
1202 if (retval < 0)
1203 return retval;
1204
1205 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1206 "%s: Bootloader ID written\n",
1207 __func__);
1208
1209 switch (fwu->config_area) {
1210 case UI_CONFIG_AREA:
1211 retval = fwu_write_f34_command(CMD_ERASE_CONFIG);
1212 break;
1213 case BL_CONFIG_AREA:
1214 retval = fwu_write_f34_command(CMD_ERASE_BL_CONFIG);
1215 fwu->config_block_count = fwu->bl_config_block_count;
1216 break;
1217 case DISP_CONFIG_AREA:
1218 retval = fwu_write_f34_command(CMD_ERASE_DISP_CONFIG);
1219 fwu->config_block_count = fwu->disp_config_block_count;
1220 break;
1221 }
1222 if (retval < 0)
1223 return retval;
1224
1225 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1226 "%s: Erase command written\n",
1227 __func__);
1228
1229 retval = fwu_wait_for_idle(ERASE_WAIT_MS);
1230 if (retval < 0)
1231 return retval;
1232
1233 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1234 "%s: Idle status detected\n",
1235 __func__);
1236
1237write_config:
1238 retval = fwu_write_configuration();
1239 if (retval < 0)
1240 return retval;
1241
1242 pr_notice("%s: Config written\n", __func__);
1243
1244 return retval;
1245}
1246
1247static int fwu_start_write_config(void)
1248{
1249 int retval;
Alexandra Chin823a2f52013-07-29 16:09:52 -07001250 int block_count;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001251
1252 switch (fwu->config_area) {
1253 case UI_CONFIG_AREA:
Alexandra Chin823a2f52013-07-29 16:09:52 -07001254 block_count = fwu->config_block_count;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001255 break;
1256 case PERM_CONFIG_AREA:
1257 if (!fwu->flash_properties.has_perm_config)
1258 return -EINVAL;
Alexandra Chin823a2f52013-07-29 16:09:52 -07001259 block_count = fwu->perm_config_block_count;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001260 break;
1261 case BL_CONFIG_AREA:
1262 if (!fwu->flash_properties.has_bl_config)
1263 return -EINVAL;
Alexandra Chin823a2f52013-07-29 16:09:52 -07001264 block_count = fwu->bl_config_block_count;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001265 break;
1266 case DISP_CONFIG_AREA:
1267 if (!fwu->flash_properties.has_display_config)
1268 return -EINVAL;
Alexandra Chin823a2f52013-07-29 16:09:52 -07001269 block_count = fwu->disp_config_block_count;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001270 break;
1271 default:
1272 return -EINVAL;
1273 }
1274
Alexandra Chin823a2f52013-07-29 16:09:52 -07001275 if (fwu->image_size == block_count*fwu->block_size) {
1276 dev_info(&fwu->rmi4_data->i2c_client->dev,
1277 "%s: write config from config file\n",
1278 __func__);
1279 fwu->config_data = fwu->data_buffer;
1280 } else {
1281 parse_header();
Alexandra Chin669d27c2012-12-24 15:42:30 +08001282 }
1283
1284 pr_notice("%s: Start of write config process\n", __func__);
1285
1286 retval = fwu_do_write_config();
1287 if (retval < 0) {
1288 dev_err(&fwu->rmi4_data->i2c_client->dev,
1289 "%s: Failed to write config\n",
1290 __func__);
1291 }
1292
1293 fwu->rmi4_data->reset_device(fwu->rmi4_data);
1294
1295 pr_notice("%s: End of write config process\n", __func__);
1296
1297 return retval;
1298}
1299
Alexandra Chin823a2f52013-07-29 16:09:52 -07001300static int fwu_do_write_lockdown(bool reset)
1301{
1302 int retval;
1303
1304 pr_notice("%s: Start of lockdown process\n", __func__);
1305
1306 retval = fwu_enter_flash_prog(false);
1307 if (retval < 0)
1308 return retval;
1309
1310 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1311 "%s: Entered flash prog mode\n",
1312 __func__);
1313
1314 if (fwu->flash_properties.unlocked == 0) {
1315 dev_err(&fwu->rmi4_data->i2c_client->dev,
1316 "%s: Device has been locked!\n",
1317 __func__);
1318 if (reset)
1319 goto exit;
1320 else
1321 return -EINVAL;
1322 }
1323
1324 retval = fwu_write_lockdown_block();
1325 if (retval < 0)
1326 return retval;
1327
1328 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1329 "%s:Lockdown device\n",
1330 __func__);
1331
1332exit:
1333 if (reset)
1334 retval = fwu->rmi4_data->reset_device(fwu->rmi4_data);
1335 else
1336 retval = fwu_enter_flash_prog(true);
1337
1338 if (retval < 0)
1339 return retval;
1340
1341 pr_notice("%s: End of lockdown process\n", __func__);
1342
1343 return retval;
1344}
1345
1346static int fwu_start_write_lockdown(void)
1347{
1348 parse_header();
1349 return fwu_do_write_lockdown(true);
1350}
1351
Alexandra Chin669d27c2012-12-24 15:42:30 +08001352static int fwu_do_read_config(void)
1353{
1354 int retval;
1355 unsigned char block_offset[] = {0, 0};
1356 unsigned short block_num;
1357 unsigned short block_count;
1358 unsigned short index = 0;
1359
Alexandra Chin669d27c2012-12-24 15:42:30 +08001360 switch (fwu->config_area) {
1361 case UI_CONFIG_AREA:
1362 block_count = fwu->config_block_count;
1363 break;
1364 case PERM_CONFIG_AREA:
1365 if (!fwu->flash_properties.has_perm_config) {
1366 retval = -EINVAL;
1367 goto exit;
1368 }
1369 block_count = fwu->perm_config_block_count;
1370 break;
1371 case BL_CONFIG_AREA:
1372 if (!fwu->flash_properties.has_bl_config) {
1373 retval = -EINVAL;
1374 goto exit;
1375 }
1376 block_count = fwu->bl_config_block_count;
1377 break;
1378 case DISP_CONFIG_AREA:
1379 if (!fwu->flash_properties.has_display_config) {
1380 retval = -EINVAL;
1381 goto exit;
1382 }
1383 block_count = fwu->disp_config_block_count;
1384 break;
1385 default:
1386 retval = -EINVAL;
1387 goto exit;
1388 }
1389
1390 fwu->config_size = fwu->block_size * block_count;
1391
1392 kfree(fwu->read_config_buf);
1393 fwu->read_config_buf = kzalloc(fwu->config_size, GFP_KERNEL);
1394
1395 block_offset[1] |= (fwu->config_area << 5);
1396
1397 retval = fwu->fn_ptr->write(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -07001398 fwu_get_address(OFFSET_BLOCK_NUMBER),
Alexandra Chin669d27c2012-12-24 15:42:30 +08001399 block_offset,
1400 sizeof(block_offset));
1401 if (retval < 0) {
1402 dev_err(&fwu->rmi4_data->i2c_client->dev,
1403 "%s: Failed to write to block number registers\n",
1404 __func__);
1405 goto exit;
1406 }
1407
1408 for (block_num = 0; block_num < block_count; block_num++) {
1409 retval = fwu_write_f34_command(CMD_READ_CONFIG_BLOCK);
1410 if (retval < 0) {
1411 dev_err(&fwu->rmi4_data->i2c_client->dev,
1412 "%s: Failed to write read config command\n",
1413 __func__);
1414 goto exit;
1415 }
1416
1417 retval = fwu_wait_for_idle(WRITE_WAIT_MS);
1418 if (retval < 0) {
1419 dev_err(&fwu->rmi4_data->i2c_client->dev,
1420 "%s: Failed to wait for idle status\n",
1421 __func__);
1422 goto exit;
1423 }
1424
1425 retval = fwu->fn_ptr->read(fwu->rmi4_data,
Alexandra Chin400f26e2013-07-25 11:58:17 -07001426 fwu_get_address(OFFSET_BLOCK_DATA),
Alexandra Chin669d27c2012-12-24 15:42:30 +08001427 &fwu->read_config_buf[index],
1428 fwu->block_size);
1429 if (retval < 0) {
1430 dev_err(&fwu->rmi4_data->i2c_client->dev,
1431 "%s: Failed to read block data (block %d)\n",
1432 __func__, block_num);
1433 goto exit;
1434 }
1435
1436 index += fwu->block_size;
1437 }
1438
1439exit:
Alexandra Chin823a2f52013-07-29 16:09:52 -07001440 return retval;
1441}
1442
1443static int fwu_do_reflash(void)
1444{
1445 int retval;
1446 unsigned char flash_status;
1447
1448 if (fwu->do_lockdown) {
1449 retval = fwu_do_write_lockdown(false);
1450 if (retval < 0)
1451 dev_warn(&fwu->rmi4_data->i2c_client->dev,
1452 "%s: Skip lockdown process.\n",
1453 __func__);
1454 }
1455 retval = fwu_enter_flash_prog(false);
1456 if (retval < 0)
1457 return retval;
1458 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1459 "%s: Entered flash prog mode\n",
1460 __func__);
1461
1462 retval = fwu_write_bootloader_id();
1463 if (retval < 0)
1464 return retval;
1465
1466 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1467 "%s: Bootloader ID written\n",
1468 __func__);
1469
1470 retval = fwu_write_f34_command(CMD_ERASE_ALL);
1471 if (retval < 0)
1472 return retval;
1473
1474 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1475 "%s: Erase all command written\n",
1476 __func__);
1477
1478 retval = fwu_wait_for_idle(ERASE_WAIT_MS);
1479 if (retval < 0)
1480 return retval;
1481
1482 retval = fwu_read_f34_flash_status(&flash_status);
1483 if (retval < 0)
1484 return retval;
1485 if (flash_status != 0x00) {
1486 dev_err(&fwu->rmi4_data->i2c_client->dev,
1487 "%s: Erase all command failed, status 0x%02X\n",
1488 __func__, flash_status);
1489 return -EINVAL;
1490 }
1491
1492 if (fwu->firmware_data) {
1493 retval = fwu_write_firmware();
1494 if (retval < 0)
1495 return retval;
1496 pr_notice("%s: Firmware programmed\n", __func__);
1497 }
1498
1499 if (fwu->config_data) {
1500 retval = fwu_write_configuration();
1501 if (retval < 0)
1502 return retval;
1503 pr_notice("%s: Configuration programmed\n", __func__);
1504 }
Alexandra Chin669d27c2012-12-24 15:42:30 +08001505
1506 return retval;
1507}
1508
Alexandra Chind5591a62013-02-07 12:59:15 -08001509static int fwu_start_reflash(void)
1510{
Amy Malocheafcecb22013-04-16 18:43:22 -07001511 int retval = 0;
Alexandra Chind5591a62013-02-07 12:59:15 -08001512 const struct firmware *fw_entry = NULL;
1513 struct f01_device_status f01_device_status;
1514 enum flash_area flash_area;
1515
1516 pr_notice("%s: Start of reflash process\n", __func__);
1517
1518 if (fwu->ext_data_source)
Alexandra Chin823a2f52013-07-29 16:09:52 -07001519 dev_info(&fwu->rmi4_data->i2c_client->dev,
1520 "%s Load .img file from commandline.\n",
1521 __func__);
Alexandra Chind5591a62013-02-07 12:59:15 -08001522 else {
Alexandra Chin400f26e2013-07-25 11:58:17 -07001523 if (strnlen(fwu->rmi4_data->fw_image_name,
1524 NAME_BUFFER_SIZE) == 0) {
1525 dev_err(&fwu->rmi4_data->i2c_client->dev,
1526 "Firmware image name not given, "\
1527 "skipping update\n");
1528 return 0;
1529 }
1530
1531 if (strnlen(fwu->rmi4_data->fw_image_name, NAME_BUFFER_SIZE) ==
1532 NAME_BUFFER_SIZE) {
1533 dev_err(&fwu->rmi4_data->i2c_client->dev,
1534 "Firmware image name exceeds max length " \
1535 "(%d), skipping update\n", NAME_BUFFER_SIZE);
1536 return 0;
1537 }
1538
Alexandra Chin823a2f52013-07-29 16:09:52 -07001539 snprintf(fwu->image_name, NAME_BUFFER_SIZE, "%s",
Amy Malocheafcecb22013-04-16 18:43:22 -07001540 fwu->rmi4_data->fw_image_name);
1541 dev_info(&fwu->rmi4_data->i2c_client->dev,
1542 "%s: Requesting firmware image %s\n",
Alexandra Chin823a2f52013-07-29 16:09:52 -07001543 __func__, fwu->image_name);
Alexandra Chind5591a62013-02-07 12:59:15 -08001544
Amy Malochecb835832013-03-26 18:06:05 -07001545 retval = request_firmware(&fw_entry,
Alexandra Chin823a2f52013-07-29 16:09:52 -07001546 fwu->image_name,
Alexandra Chind5591a62013-02-07 12:59:15 -08001547 &fwu->rmi4_data->i2c_client->dev);
1548 if (retval != 0) {
1549 dev_err(&fwu->rmi4_data->i2c_client->dev,
1550 "%s: Firmware image %s not available\n",
Amy Malochecb835832013-03-26 18:06:05 -07001551 __func__,
Alexandra Chin823a2f52013-07-29 16:09:52 -07001552 fwu->image_name);
Amy Malocheb494b9a2013-05-13 18:01:53 -07001553 return -EINVAL;
Alexandra Chind5591a62013-02-07 12:59:15 -08001554 }
1555
1556 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1557 "%s: Firmware image size = %d\n",
1558 __func__, fw_entry->size);
1559
Alexandra Chin823a2f52013-07-29 16:09:52 -07001560 fwu->data_buffer = fw_entry->data;
Alexandra Chind5591a62013-02-07 12:59:15 -08001561 }
1562
Alexandra Chin823a2f52013-07-29 16:09:52 -07001563 parse_header();
1564 flash_area = fwu_go_nogo();
Alexandra Chin400f26e2013-07-25 11:58:17 -07001565
1566 if (fwu->rmi4_data->sensor_sleep) {
1567 dev_err(&fwu->rmi4_data->i2c_client->dev,
1568 "%s: Sensor sleeping\n",
1569 __func__);
Alexandra Chin823a2f52013-07-29 16:09:52 -07001570 retval = -ENODEV;
1571 goto exit;
Alexandra Chin400f26e2013-07-25 11:58:17 -07001572 }
1573 fwu->rmi4_data->stay_awake = true;
Alexandra Chind5591a62013-02-07 12:59:15 -08001574
1575 switch (flash_area) {
1576 case NONE:
Amy Maloche2c4c48c2013-05-01 20:06:23 -07001577 case MISMATCH:
1578 retval = 0;
Alexandra Chind5591a62013-02-07 12:59:15 -08001579 dev_info(&fwu->rmi4_data->i2c_client->dev,
1580 "%s: No need to do reflash.\n",
1581 __func__);
1582 goto exit;
1583 case UI_FIRMWARE:
1584 retval = fwu_do_reflash();
1585 break;
1586 case CONFIG_AREA:
1587 retval = fwu_do_write_config();
1588 break;
1589 default:
1590 dev_err(&fwu->rmi4_data->i2c_client->dev,
1591 "%s: Unknown flash area\n",
1592 __func__);
Alexandra Chin823a2f52013-07-29 16:09:52 -07001593 retval = -EINVAL;
Alexandra Chind5591a62013-02-07 12:59:15 -08001594 goto exit;
1595 }
1596
Alexandra Chin823a2f52013-07-29 16:09:52 -07001597 if (retval < 0)
Alexandra Chind5591a62013-02-07 12:59:15 -08001598 dev_err(&fwu->rmi4_data->i2c_client->dev,
1599 "%s: Failed to do reflash\n",
1600 __func__);
Alexandra Chind5591a62013-02-07 12:59:15 -08001601
1602 /* reset device */
1603 fwu_reset_device();
1604
1605 /* check device status */
1606 retval = fwu_read_f01_device_status(&f01_device_status);
1607 if (retval < 0)
1608 goto exit;
1609
1610 dev_info(&fwu->rmi4_data->i2c_client->dev, "Device is in %s mode\n",
1611 f01_device_status.flash_prog == 1 ? "bootloader" : "UI");
1612 if (f01_device_status.flash_prog)
1613 dev_info(&fwu->rmi4_data->i2c_client->dev, "Flash status %d\n",
1614 f01_device_status.status_code);
1615
1616 if (f01_device_status.flash_prog) {
1617 dev_info(&fwu->rmi4_data->i2c_client->dev,
1618 "%s: Device is in flash prog mode 0x%02X\n",
1619 __func__, f01_device_status.status_code);
Alexandra Chind5591a62013-02-07 12:59:15 -08001620 }
1621
Amy Malocheb494b9a2013-05-13 18:01:53 -07001622exit:
Alexandra Chind5591a62013-02-07 12:59:15 -08001623 if (fw_entry)
1624 release_firmware(fw_entry);
1625
1626 pr_notice("%s: End of reflash process\n", __func__);
Alexandra Chin400f26e2013-07-25 11:58:17 -07001627 fwu->rmi4_data->stay_awake = false;
Alexandra Chind5591a62013-02-07 12:59:15 -08001628 return retval;
1629}
1630
Alexandra Chin823a2f52013-07-29 16:09:52 -07001631int synaptics_fw_updater(void)
Alexandra Chin669d27c2012-12-24 15:42:30 +08001632{
1633 int retval;
1634
1635 if (!fwu)
1636 return -ENODEV;
1637
1638 if (!fwu->initialized)
1639 return -ENODEV;
1640
Amy Malocheb494b9a2013-05-13 18:01:53 -07001641 fwu->rmi4_data->fw_updating = true;
Amy Maloche986863d2013-06-10 15:13:57 -07001642 if (fwu->rmi4_data->suspended == true) {
Amy Malocheb494b9a2013-05-13 18:01:53 -07001643 fwu->rmi4_data->fw_updating = false;
1644 dev_err(&fwu->rmi4_data->i2c_client->dev,
1645 "Cannot start fw upgrade while device is in suspend\n");
1646 return -EBUSY;
1647 }
1648
Alexandra Chin669d27c2012-12-24 15:42:30 +08001649 fwu->config_area = UI_CONFIG_AREA;
1650
1651 retval = fwu_start_reflash();
Amy Malocheb494b9a2013-05-13 18:01:53 -07001652 fwu->rmi4_data->fw_updating = false;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001653
Amy Maloched9bf0d92013-06-19 17:19:23 -07001654 synaptics_rmi4_update_debug_info();
1655
Alexandra Chin669d27c2012-12-24 15:42:30 +08001656 return retval;
1657}
1658EXPORT_SYMBOL(synaptics_fw_updater);
1659
1660static ssize_t fwu_sysfs_show_image(struct file *data_file,
1661 struct kobject *kobj, struct bin_attribute *attributes,
1662 char *buf, loff_t pos, size_t count)
1663{
1664 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1665
1666 if (count < fwu->config_size) {
1667 dev_err(&rmi4_data->i2c_client->dev,
1668 "%s: Not enough space (%d bytes) in buffer\n",
1669 __func__, count);
1670 return -EINVAL;
1671 }
1672
1673 memcpy(buf, fwu->read_config_buf, fwu->config_size);
1674
1675 return fwu->config_size;
1676}
1677
1678static ssize_t fwu_sysfs_store_image(struct file *data_file,
1679 struct kobject *kobj, struct bin_attribute *attributes,
1680 char *buf, loff_t pos, size_t count)
1681{
1682 memcpy((void *)(&fwu->ext_data_source[fwu->data_pos]),
1683 (const void *)buf,
1684 count);
1685
Alexandra Chin823a2f52013-07-29 16:09:52 -07001686 fwu->data_buffer = fwu->ext_data_source;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001687 fwu->data_pos += count;
1688
1689 return count;
1690}
1691
Alexandra Chin823a2f52013-07-29 16:09:52 -07001692static ssize_t fwu_sysfs_image_name_store(struct device *dev,
Amy Malocheb494b9a2013-05-13 18:01:53 -07001693 struct device_attribute *attr, const char *buf, size_t count)
1694{
1695 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1696 char *strptr;
1697
1698 if (count >= NAME_BUFFER_SIZE) {
1699 dev_err(&rmi4_data->i2c_client->dev,
1700 "Input over %d characters long\n", NAME_BUFFER_SIZE);
1701 return -EINVAL;
1702 }
1703
1704 strptr = strnstr(buf, ".img",
1705 count);
1706 if (!strptr) {
1707 dev_err(&rmi4_data->i2c_client->dev,
1708 "Input is not valid .img file\n");
1709 return -EINVAL;
1710 }
1711
1712 strlcpy(rmi4_data->fw_image_name, buf, count);
1713 return count;
1714}
1715
Alexandra Chin823a2f52013-07-29 16:09:52 -07001716static ssize_t fwu_sysfs_image_name_show(struct device *dev,
Amy Malocheb494b9a2013-05-13 18:01:53 -07001717 struct device_attribute *attr, char *buf)
1718{
1719 if (strnlen(fwu->rmi4_data->fw_image_name, NAME_BUFFER_SIZE) > 0)
1720 return snprintf(buf, PAGE_SIZE, "%s\n",
1721 fwu->rmi4_data->fw_image_name);
1722 else
1723 return snprintf(buf, PAGE_SIZE, "No firmware name given\n");
1724}
1725
Amy Maloche5e0360e2013-05-01 13:31:57 -07001726static ssize_t fwu_sysfs_force_reflash_store(struct device *dev,
1727 struct device_attribute *attr, const char *buf, size_t count)
1728{
1729 int retval;
1730 unsigned int input;
1731 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1732
1733 if (sscanf(buf, "%u", &input) != 1) {
1734 retval = -EINVAL;
1735 goto exit;
1736 }
1737
1738 if (input != 1) {
1739 retval = -EINVAL;
1740 goto exit;
1741 }
Alexandra Chin823a2f52013-07-29 16:09:52 -07001742 if (LOCKDOWN)
1743 fwu->do_lockdown = true;
Amy Maloche5e0360e2013-05-01 13:31:57 -07001744
1745 fwu->force_update = true;
Alexandra Chin823a2f52013-07-29 16:09:52 -07001746 retval = synaptics_fw_updater();
Amy Maloche5e0360e2013-05-01 13:31:57 -07001747 if (retval < 0) {
1748 dev_err(&rmi4_data->i2c_client->dev,
1749 "%s: Failed to do reflash\n",
1750 __func__);
1751 goto exit;
1752 }
1753
1754 retval = count;
1755
1756exit:
1757 kfree(fwu->ext_data_source);
1758 fwu->ext_data_source = NULL;
Alexandra Chin823a2f52013-07-29 16:09:52 -07001759 fwu->force_update = FORCE_UPDATE;
1760 fwu->do_lockdown = DO_LOCKDOWN;
Amy Maloche5e0360e2013-05-01 13:31:57 -07001761 return retval;
1762}
1763
Alexandra Chin669d27c2012-12-24 15:42:30 +08001764static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
1765 struct device_attribute *attr, const char *buf, size_t count)
1766{
1767 int retval;
1768 unsigned int input;
1769 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1770
1771 if (sscanf(buf, "%u", &input) != 1) {
1772 retval = -EINVAL;
1773 goto exit;
1774 }
1775
Alexandra Chin823a2f52013-07-29 16:09:52 -07001776 if (input & LOCKDOWN) {
1777 fwu->do_lockdown = true;
1778 input &= ~LOCKDOWN;
1779 }
1780
1781 if ((input != NORMAL) && (input != FORCE)) {
1782 retval = -EINVAL;
1783 goto exit;
1784 }
1785
1786 if (input == FORCE)
1787 fwu->force_update = true;
1788
1789 retval = synaptics_fw_updater();
1790 if (retval < 0) {
1791 dev_err(&rmi4_data->i2c_client->dev,
1792 "%s: Failed to do reflash\n",
1793 __func__);
1794 goto exit;
1795 }
1796
1797 retval = count;
1798
1799exit:
1800 kfree(fwu->ext_data_source);
1801 fwu->ext_data_source = NULL;
1802 fwu->force_update = FORCE_UPDATE;
1803 fwu->do_lockdown = DO_LOCKDOWN;
1804 return retval;
1805}
1806
1807static ssize_t fwu_sysfs_write_lockdown_store(struct device *dev,
1808 struct device_attribute *attr, const char *buf, size_t count)
1809{
1810 int retval;
1811 unsigned int input;
1812 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1813
1814 if (sscanf(buf, "%u", &input) != 1) {
1815 retval = -EINVAL;
1816 goto exit;
1817 }
1818
Alexandra Chin669d27c2012-12-24 15:42:30 +08001819 if (input != 1) {
1820 retval = -EINVAL;
1821 goto exit;
1822 }
1823
Alexandra Chin823a2f52013-07-29 16:09:52 -07001824 retval = fwu_start_write_lockdown();
Alexandra Chin669d27c2012-12-24 15:42:30 +08001825 if (retval < 0) {
1826 dev_err(&rmi4_data->i2c_client->dev,
Alexandra Chin823a2f52013-07-29 16:09:52 -07001827 "%s: Failed to write lockdown block\n",
Alexandra Chin669d27c2012-12-24 15:42:30 +08001828 __func__);
1829 goto exit;
1830 }
1831
1832 retval = count;
1833
1834exit:
1835 kfree(fwu->ext_data_source);
1836 fwu->ext_data_source = NULL;
Alexandra Chin823a2f52013-07-29 16:09:52 -07001837 fwu->force_update = FORCE_UPDATE;
1838 fwu->do_lockdown = DO_LOCKDOWN;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001839 return retval;
1840}
1841
1842static ssize_t fwu_sysfs_write_config_store(struct device *dev,
1843 struct device_attribute *attr, const char *buf, size_t count)
1844{
1845 int retval;
1846 unsigned int input;
1847 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1848
1849 if (sscanf(buf, "%u", &input) != 1) {
1850 retval = -EINVAL;
1851 goto exit;
1852 }
1853
1854 if (input != 1) {
1855 retval = -EINVAL;
1856 goto exit;
1857 }
1858
1859 retval = fwu_start_write_config();
1860 if (retval < 0) {
1861 dev_err(&rmi4_data->i2c_client->dev,
1862 "%s: Failed to write config\n",
1863 __func__);
1864 goto exit;
1865 }
1866
1867 retval = count;
1868
1869exit:
1870 kfree(fwu->ext_data_source);
1871 fwu->ext_data_source = NULL;
1872 return retval;
1873}
1874
1875static ssize_t fwu_sysfs_read_config_store(struct device *dev,
1876 struct device_attribute *attr, const char *buf, size_t count)
1877{
1878 int retval;
1879 unsigned int input;
1880 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1881
1882 if (sscanf(buf, "%u", &input) != 1)
1883 return -EINVAL;
1884
1885 if (input != 1)
1886 return -EINVAL;
1887
1888 retval = fwu_do_read_config();
1889 if (retval < 0) {
1890 dev_err(&rmi4_data->i2c_client->dev,
1891 "%s: Failed to read config\n",
1892 __func__);
1893 return retval;
1894 }
1895
1896 return count;
1897}
1898
1899static ssize_t fwu_sysfs_config_area_store(struct device *dev,
1900 struct device_attribute *attr, const char *buf, size_t count)
1901{
1902 int retval;
1903 unsigned long config_area;
1904
Shantanu Jain41f0d472013-01-04 12:14:37 +05301905 retval = kstrtoul(buf, 10, &config_area);
Alexandra Chin669d27c2012-12-24 15:42:30 +08001906 if (retval)
1907 return retval;
1908
1909 fwu->config_area = config_area;
1910
1911 return count;
1912}
1913
1914static ssize_t fwu_sysfs_image_size_store(struct device *dev,
1915 struct device_attribute *attr, const char *buf, size_t count)
1916{
1917 int retval;
1918 unsigned long size;
1919 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1920
Shantanu Jain41f0d472013-01-04 12:14:37 +05301921 retval = kstrtoul(buf, 10, &size);
Alexandra Chin669d27c2012-12-24 15:42:30 +08001922 if (retval)
1923 return retval;
1924
1925 fwu->image_size = size;
1926 fwu->data_pos = 0;
1927
1928 kfree(fwu->ext_data_source);
1929 fwu->ext_data_source = kzalloc(fwu->image_size, GFP_KERNEL);
1930 if (!fwu->ext_data_source) {
1931 dev_err(&rmi4_data->i2c_client->dev,
1932 "%s: Failed to alloc mem for image data\n",
1933 __func__);
1934 return -ENOMEM;
1935 }
1936
1937 return count;
1938}
1939
1940static ssize_t fwu_sysfs_block_size_show(struct device *dev,
1941 struct device_attribute *attr, char *buf)
1942{
1943 return snprintf(buf, PAGE_SIZE, "%u\n", fwu->block_size);
1944}
1945
1946static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev,
1947 struct device_attribute *attr, char *buf)
1948{
1949 return snprintf(buf, PAGE_SIZE, "%u\n", fwu->fw_block_count);
1950}
1951
1952static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev,
1953 struct device_attribute *attr, char *buf)
1954{
1955 return snprintf(buf, PAGE_SIZE, "%u\n", fwu->config_block_count);
1956}
1957
1958static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev,
1959 struct device_attribute *attr, char *buf)
1960{
1961 return snprintf(buf, PAGE_SIZE, "%u\n", fwu->perm_config_block_count);
1962}
1963
1964static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev,
1965 struct device_attribute *attr, char *buf)
1966{
1967 return snprintf(buf, PAGE_SIZE, "%u\n", fwu->bl_config_block_count);
1968}
1969
1970static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev,
1971 struct device_attribute *attr, char *buf)
1972{
1973 return snprintf(buf, PAGE_SIZE, "%u\n", fwu->disp_config_block_count);
1974}
1975
Amy Maloched25bd8c2013-01-25 12:34:31 -08001976static ssize_t fwu_sysfs_config_id_show(struct device *dev,
1977 struct device_attribute *attr, char *buf)
1978{
Amy Maloche581f7402013-02-19 16:29:37 -08001979 unsigned char config_id[4];
Amy Maloched25bd8c2013-01-25 12:34:31 -08001980 /* device config id */
1981 fwu->fn_ptr->read(fwu->rmi4_data,
1982 fwu->f34_fd.ctrl_base_addr,
1983 config_id,
1984 sizeof(config_id));
1985
1986 return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n",
1987 config_id[0], config_id[1], config_id[2], config_id[3]);
1988}
1989
Amy Maloche2c4c48c2013-05-01 20:06:23 -07001990static ssize_t fwu_sysfs_package_id_show(struct device *dev,
1991 struct device_attribute *attr, char *buf)
1992{
1993 unsigned char pkg_id[4];
1994 /* read device package id */
1995 fwu->fn_ptr->read(fwu->rmi4_data,
1996 fwu->f01_fd.query_base_addr + 17,
1997 pkg_id,
1998 sizeof(pkg_id));
1999
2000 return snprintf(buf, PAGE_SIZE, "%d rev %d\n",
2001 (pkg_id[1] << 8) | pkg_id[0],
2002 (pkg_id[3] << 8) | pkg_id[2]);
2003}
2004
Amy Maloched9bf0d92013-06-19 17:19:23 -07002005static int synaptics_rmi4_debug_dump_info(struct seq_file *m, void *v)
2006{
2007 seq_printf(m, "%s\n", fwu->ts_info);
2008
2009 return 0;
2010}
2011
2012static int debugfs_dump_info_open(struct inode *inode, struct file *file)
2013{
2014 return single_open(file, synaptics_rmi4_debug_dump_info,
2015 inode->i_private);
2016}
2017
2018static const struct file_operations debug_dump_info_fops = {
2019 .owner = THIS_MODULE,
2020 .open = debugfs_dump_info_open,
2021 .read = seq_read,
2022 .release = single_release,
2023};
2024
Alexandra Chin669d27c2012-12-24 15:42:30 +08002025static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data,
2026 unsigned char intr_mask)
2027{
2028 if (fwu->intr_mask & intr_mask)
Alexandra Chin400f26e2013-07-25 11:58:17 -07002029 fwu->interrupt_flag = true;
Alexandra Chin669d27c2012-12-24 15:42:30 +08002030
2031 return;
2032}
2033
Amy Malocheb494b9a2013-05-13 18:01:53 -07002034static struct bin_attribute dev_attr_data = {
2035 .attr = {
2036 .name = "data",
Amy Maloche8b99ec92013-06-24 17:13:42 -07002037 .mode = (S_IRUGO | S_IWUSR | S_IWGRP),
Amy Malocheb494b9a2013-05-13 18:01:53 -07002038 },
2039 .size = 0,
2040 .read = fwu_sysfs_show_image,
2041 .write = fwu_sysfs_store_image,
2042};
2043
2044static struct device_attribute attrs[] = {
Amy Maloche8b99ec92013-06-24 17:13:42 -07002045 __ATTR(fw_name, S_IRUGO | S_IWUSR | S_IWGRP,
Alexandra Chin823a2f52013-07-29 16:09:52 -07002046 fwu_sysfs_image_name_show,
2047 fwu_sysfs_image_name_store),
Amy Maloche8b99ec92013-06-24 17:13:42 -07002048 __ATTR(force_update_fw, S_IRUGO | S_IWUSR | S_IWGRP,
Amy Malocheb494b9a2013-05-13 18:01:53 -07002049 synaptics_rmi4_show_error,
2050 fwu_sysfs_force_reflash_store),
Amy Maloche8b99ec92013-06-24 17:13:42 -07002051 __ATTR(update_fw, S_IRUGO | S_IWUSR | S_IWGRP,
Amy Malocheb494b9a2013-05-13 18:01:53 -07002052 synaptics_rmi4_show_error,
2053 fwu_sysfs_do_reflash_store),
Amy Maloche8b99ec92013-06-24 17:13:42 -07002054 __ATTR(writeconfig, S_IRUGO | S_IWUSR | S_IWGRP,
Amy Malocheb494b9a2013-05-13 18:01:53 -07002055 synaptics_rmi4_show_error,
2056 fwu_sysfs_write_config_store),
Amy Maloche52e06182013-09-06 18:24:33 -07002057 __ATTR(writelockdown, S_IRUGO | S_IWUSR | S_IWGRP,
Alexandra Chin823a2f52013-07-29 16:09:52 -07002058 synaptics_rmi4_show_error,
2059 fwu_sysfs_write_lockdown_store),
Amy Maloche8b99ec92013-06-24 17:13:42 -07002060 __ATTR(readconfig, S_IRUGO | S_IWUSR | S_IWGRP,
Amy Malocheb494b9a2013-05-13 18:01:53 -07002061 synaptics_rmi4_show_error,
2062 fwu_sysfs_read_config_store),
Amy Maloche8b99ec92013-06-24 17:13:42 -07002063 __ATTR(configarea, S_IRUGO | S_IWUSR | S_IWGRP,
Amy Malocheb494b9a2013-05-13 18:01:53 -07002064 synaptics_rmi4_show_error,
2065 fwu_sysfs_config_area_store),
Amy Maloche8b99ec92013-06-24 17:13:42 -07002066 __ATTR(imagesize, S_IRUGO | S_IWUSR | S_IWGRP,
Amy Malocheb494b9a2013-05-13 18:01:53 -07002067 synaptics_rmi4_show_error,
2068 fwu_sysfs_image_size_store),
2069 __ATTR(blocksize, S_IRUGO,
2070 fwu_sysfs_block_size_show,
2071 synaptics_rmi4_store_error),
2072 __ATTR(fwblockcount, S_IRUGO,
2073 fwu_sysfs_firmware_block_count_show,
2074 synaptics_rmi4_store_error),
2075 __ATTR(configblockcount, S_IRUGO,
2076 fwu_sysfs_configuration_block_count_show,
2077 synaptics_rmi4_store_error),
2078 __ATTR(permconfigblockcount, S_IRUGO,
2079 fwu_sysfs_perm_config_block_count_show,
2080 synaptics_rmi4_store_error),
2081 __ATTR(blconfigblockcount, S_IRUGO,
2082 fwu_sysfs_bl_config_block_count_show,
2083 synaptics_rmi4_store_error),
2084 __ATTR(dispconfigblockcount, S_IRUGO,
2085 fwu_sysfs_disp_config_block_count_show,
2086 synaptics_rmi4_store_error),
2087 __ATTR(config_id, S_IRUGO,
2088 fwu_sysfs_config_id_show,
2089 synaptics_rmi4_store_error),
Amy Maloche2c4c48c2013-05-01 20:06:23 -07002090 __ATTR(package_id, S_IRUGO,
2091 fwu_sysfs_package_id_show,
2092 synaptics_rmi4_store_error),
Amy Malocheb494b9a2013-05-13 18:01:53 -07002093};
2094
2095
Alexandra Chind5591a62013-02-07 12:59:15 -08002096static void synaptics_rmi4_fwu_work(struct work_struct *work)
2097{
2098 fwu_start_reflash();
2099}
2100
Alexandra Chin669d27c2012-12-24 15:42:30 +08002101static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
2102{
2103 int retval;
2104 unsigned char attr_count;
2105 struct pdt_properties pdt_props;
Amy Maloched9bf0d92013-06-19 17:19:23 -07002106 struct dentry *temp;
Alexandra Chin669d27c2012-12-24 15:42:30 +08002107
2108 fwu = kzalloc(sizeof(*fwu), GFP_KERNEL);
2109 if (!fwu) {
2110 dev_err(&rmi4_data->i2c_client->dev,
2111 "%s: Failed to alloc mem for fwu\n",
2112 __func__);
2113 goto exit;
2114 }
2115
2116 fwu->fn_ptr = kzalloc(sizeof(*(fwu->fn_ptr)), GFP_KERNEL);
2117 if (!fwu->fn_ptr) {
2118 dev_err(&rmi4_data->i2c_client->dev,
2119 "%s: Failed to alloc mem for fn_ptr\n",
2120 __func__);
2121 retval = -ENOMEM;
2122 goto exit_free_fwu;
2123 }
2124
2125 fwu->rmi4_data = rmi4_data;
2126 fwu->fn_ptr->read = rmi4_data->i2c_read;
2127 fwu->fn_ptr->write = rmi4_data->i2c_write;
2128 fwu->fn_ptr->enable = rmi4_data->irq_enable;
2129
2130 retval = fwu->fn_ptr->read(rmi4_data,
2131 PDT_PROPS,
2132 pdt_props.data,
2133 sizeof(pdt_props.data));
2134 if (retval < 0) {
2135 dev_dbg(&rmi4_data->i2c_client->dev,
2136 "%s: Failed to read PDT properties, assuming 0x00\n",
2137 __func__);
2138 } else if (pdt_props.has_bsr) {
2139 dev_err(&rmi4_data->i2c_client->dev,
2140 "%s: Reflash for LTS not currently supported\n",
2141 __func__);
2142 goto exit_free_mem;
2143 }
2144
2145 retval = fwu_scan_pdt();
2146 if (retval < 0)
2147 goto exit_free_mem;
2148
2149 fwu->productinfo1 = rmi4_data->rmi4_mod_info.product_info[0];
2150 fwu->productinfo2 = rmi4_data->rmi4_mod_info.product_info[1];
2151
2152 memcpy(fwu->product_id, rmi4_data->rmi4_mod_info.product_id_string,
2153 SYNAPTICS_RMI4_PRODUCT_ID_SIZE);
2154 fwu->product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE] = 0;
2155
2156 dev_dbg(&rmi4_data->i2c_client->dev,
2157 "%s: F01 product info: 0x%04x 0x%04x\n",
2158 __func__, fwu->productinfo1, fwu->productinfo2);
2159 dev_dbg(&rmi4_data->i2c_client->dev,
2160 "%s: F01 product ID: %s\n",
2161 __func__, fwu->product_id);
2162
2163 retval = fwu_read_f34_queries();
2164 if (retval < 0)
2165 goto exit_free_mem;
2166
2167 fwu->initialized = true;
Alexandra Chind5591a62013-02-07 12:59:15 -08002168 fwu->force_update = FORCE_UPDATE;
Alexandra Chin823a2f52013-07-29 16:09:52 -07002169 fwu->do_lockdown = DO_LOCKDOWN;
2170 fwu->initialized = true;
Alexandra Chin400f26e2013-07-25 11:58:17 -07002171 fwu->polling_mode = false;
Alexandra Chin669d27c2012-12-24 15:42:30 +08002172
Amy Maloche4d54ac42013-06-11 12:09:44 -07002173 retval = sysfs_create_bin_file(&rmi4_data->i2c_client->dev.kobj,
Alexandra Chin669d27c2012-12-24 15:42:30 +08002174 &dev_attr_data);
2175 if (retval < 0) {
2176 dev_err(&rmi4_data->i2c_client->dev,
2177 "%s: Failed to create sysfs bin file\n",
2178 __func__);
2179 goto exit_free_mem;
2180 }
2181
2182 for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
Amy Maloche4d54ac42013-06-11 12:09:44 -07002183 retval = sysfs_create_file(&rmi4_data->i2c_client->dev.kobj,
Alexandra Chin669d27c2012-12-24 15:42:30 +08002184 &attrs[attr_count].attr);
2185 if (retval < 0) {
2186 dev_err(&rmi4_data->i2c_client->dev,
2187 "%s: Failed to create sysfs attributes\n",
2188 __func__);
2189 retval = -ENODEV;
2190 goto exit_remove_attrs;
2191 }
2192 }
2193
Amy Maloched9bf0d92013-06-19 17:19:23 -07002194 temp = debugfs_create_file("dump_info", S_IRUSR | S_IWUSR,
2195 fwu->rmi4_data->dir, fwu->rmi4_data,
2196 &debug_dump_info_fops);
2197 if (temp == NULL || IS_ERR(temp)) {
2198 dev_err(&rmi4_data->i2c_client->dev,
2199 "%s: Failed to create debugfs dump info file\n",
2200 __func__);
2201 retval = PTR_ERR(temp);
2202 goto exit_remove_attrs;
2203 }
2204
2205 fwu->ts_info = kzalloc(RMI4_INFO_MAX_LEN, GFP_KERNEL);
2206 if (!fwu->ts_info) {
2207 dev_err(&rmi4_data->i2c_client->dev, "Not enough memory\n");
2208 goto exit_free_ts_info;
2209 }
2210
2211 synaptics_rmi4_update_debug_info();
2212
Alexandra Chind5591a62013-02-07 12:59:15 -08002213#ifdef INSIDE_FIRMWARE_UPDATE
2214 fwu->fwu_workqueue = create_singlethread_workqueue("fwu_workqueue");
2215 INIT_DELAYED_WORK(&fwu->fwu_work, synaptics_rmi4_fwu_work);
2216 queue_delayed_work(fwu->fwu_workqueue,
2217 &fwu->fwu_work,
2218 msecs_to_jiffies(1000));
2219#endif
Alexandra Chinc556cf02013-03-19 17:46:05 -07002220
Alexandra Chin669d27c2012-12-24 15:42:30 +08002221 return 0;
Amy Maloched9bf0d92013-06-19 17:19:23 -07002222exit_free_ts_info:
2223 debugfs_remove(temp);
Alexandra Chin669d27c2012-12-24 15:42:30 +08002224exit_remove_attrs:
Alexandra Chin823a2f52013-07-29 16:09:52 -07002225 for (attr_count--; attr_count >= 0; attr_count--) {
2226 sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
2227 &attrs[attr_count].attr);
2228 }
Alexandra Chin669d27c2012-12-24 15:42:30 +08002229
Alexandra Chin823a2f52013-07-29 16:09:52 -07002230 sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
Alexandra Chin669d27c2012-12-24 15:42:30 +08002231
2232exit_free_mem:
2233 kfree(fwu->fn_ptr);
2234
2235exit_free_fwu:
2236 kfree(fwu);
Alexandra Chin823a2f52013-07-29 16:09:52 -07002237 fwu = NULL;
Alexandra Chin669d27c2012-12-24 15:42:30 +08002238
2239exit:
2240 return 0;
2241}
2242
2243static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data)
2244{
2245 unsigned char attr_count;
2246
2247 sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
2248
2249 for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
2250 sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
2251 &attrs[attr_count].attr);
2252 }
2253
Alexandra Chin823a2f52013-07-29 16:09:52 -07002254 kfree(fwu->read_config_buf);
Alexandra Chin669d27c2012-12-24 15:42:30 +08002255 kfree(fwu->fn_ptr);
2256 kfree(fwu);
2257
Alexandra Chind9e204d2013-07-25 15:23:01 -07002258 complete(&fwu_remove_complete);
Alexandra Chin669d27c2012-12-24 15:42:30 +08002259
2260 return;
2261}
2262
2263static int __init rmi4_fw_update_module_init(void)
2264{
2265 synaptics_rmi4_new_function(RMI_FW_UPDATER, true,
2266 synaptics_rmi4_fwu_init,
2267 synaptics_rmi4_fwu_remove,
2268 synaptics_rmi4_fwu_attn);
2269 return 0;
2270}
2271
2272static void __exit rmi4_fw_update_module_exit(void)
2273{
Alexandra Chin669d27c2012-12-24 15:42:30 +08002274 synaptics_rmi4_new_function(RMI_FW_UPDATER, false,
2275 synaptics_rmi4_fwu_init,
2276 synaptics_rmi4_fwu_remove,
2277 synaptics_rmi4_fwu_attn);
Alexandra Chind9e204d2013-07-25 15:23:01 -07002278 wait_for_completion(&fwu_remove_complete);
Alexandra Chin669d27c2012-12-24 15:42:30 +08002279 return;
2280}
2281
2282module_init(rmi4_fw_update_module_init);
2283module_exit(rmi4_fw_update_module_exit);
2284
2285MODULE_AUTHOR("Synaptics, Inc.");
2286MODULE_DESCRIPTION("RMI4 FW Update Module");
Alexandra Chinbd1dac22013-02-22 12:33:19 -08002287MODULE_LICENSE("GPL v2");