blob: c01ab0ea0a8d77099efaca0894f9c1141d88a1f2 [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 Chin669d27c2012-12-24 15:42:30 +080038
39#define BOOTLOADER_ID_OFFSET 0
40#define FLASH_PROPERTIES_OFFSET 2
41#define BLOCK_SIZE_OFFSET 3
42#define FW_BLOCK_COUNT_OFFSET 5
43
44#define REG_MAP (1 << 0)
45#define UNLOCKED (1 << 1)
46#define HAS_CONFIG_ID (1 << 2)
47#define HAS_PERM_CONFIG (1 << 3)
48#define HAS_BL_CONFIG (1 << 4)
49#define HAS_DISP_CONFIG (1 << 5)
50#define HAS_CTRL1 (1 << 6)
51
52#define BLOCK_NUMBER_OFFSET 0
53#define BLOCK_DATA_OFFSET 2
54
Amy Maloched9bf0d92013-06-19 17:19:23 -070055#define RMI4_INFO_MAX_LEN 200
56
57#define RMI4_STORE_TS_INFO(buf, id, rev, fw_ver) \
58 snprintf(buf, RMI4_INFO_MAX_LEN, \
59 "controller\t= synaptics\n" \
60 "model\t\t= %d rev %d\n" \
61 "fw_ver\t\t= %d\n", id, rev, fw_ver)
62
Amy Malocheafcecb22013-04-16 18:43:22 -070063enum falsh_config_area {
64 UI_CONFIG_AREA = 0x00,
65 PERM_CONFIG_AREA = 0x01,
66 BL_CONFIG_AREA = 0x02,
67 DISP_CONFIG_AREA = 0x03
68};
Alexandra Chin669d27c2012-12-24 15:42:30 +080069
70enum flash_command {
71 CMD_WRITE_FW_BLOCK = 0x2,
72 CMD_ERASE_ALL = 0x3,
73 CMD_READ_CONFIG_BLOCK = 0x5,
74 CMD_WRITE_CONFIG_BLOCK = 0x6,
75 CMD_ERASE_CONFIG = 0x7,
Amy Malocheafcecb22013-04-16 18:43:22 -070076 CMD_READ_SENSOR_ID = 0x8,
Alexandra Chin669d27c2012-12-24 15:42:30 +080077 CMD_ERASE_BL_CONFIG = 0x9,
78 CMD_ERASE_DISP_CONFIG = 0xA,
Amy Malocheafcecb22013-04-16 18:43:22 -070079 CMD_ENABLE_FLASH_PROG = 0xF
Alexandra Chin669d27c2012-12-24 15:42:30 +080080};
81
Alexandra Chind5591a62013-02-07 12:59:15 -080082enum flash_area {
83 NONE,
84 UI_FIRMWARE,
Amy Maloche2c4c48c2013-05-01 20:06:23 -070085 CONFIG_AREA,
86 MISMATCH
Alexandra Chind5591a62013-02-07 12:59:15 -080087};
88
Amy Malocheafcecb22013-04-16 18:43:22 -070089enum image_file_option {
90 OPTION_BUILD_INFO = 0,
91 OPTION_CONTAIN_BOOTLOADER = 1,
92};
93
Alexandra Chin669d27c2012-12-24 15:42:30 +080094#define SLEEP_MODE_NORMAL (0x00)
95#define SLEEP_MODE_SENSOR_SLEEP (0x01)
96#define SLEEP_MODE_RESERVED0 (0x02)
97#define SLEEP_MODE_RESERVED1 (0x03)
98
99#define ENABLE_WAIT_MS (1 * 1000)
100#define WRITE_WAIT_MS (3 * 1000)
101#define ERASE_WAIT_MS (5 * 1000)
Alexandra Chind5591a62013-02-07 12:59:15 -0800102#define RESET_WAIT_MS (500)
Alexandra Chin669d27c2012-12-24 15:42:30 +0800103
Amy Malocheafcecb22013-04-16 18:43:22 -0700104#define POLLING_MODE 0
105
Alexandra Chind5591a62013-02-07 12:59:15 -0800106#define SLEEP_TIME_US 50
Alexandra Chin669d27c2012-12-24 15:42:30 +0800107
Alexandra Chin669d27c2012-12-24 15:42:30 +0800108static int fwu_wait_for_idle(int timeout_ms);
109
Amy Malocheafcecb22013-04-16 18:43:22 -0700110struct image_header_data {
111 union {
112 struct {
113 /* 0x00-0x0F */
114 unsigned char file_checksum[4];
115 unsigned char reserved_04;
116 unsigned char reserved_05;
117 unsigned char options_firmware_id:1;
118 unsigned char options_contain_bootloader:1;
119 unsigned char options_reserved:6;
120 unsigned char bootloader_version;
121 unsigned char firmware_size[4];
122 unsigned char config_size[4];
123 /* 0x10-0x1F */
124 unsigned char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE];
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700125 unsigned char pkg_id_lsb;
126 unsigned char pkg_id_msb;
127 unsigned char pkg_id_rev_lsb;
128 unsigned char pkg_id_rev_msb;
Amy Malocheafcecb22013-04-16 18:43:22 -0700129 unsigned char product_info[SYNAPTICS_RMI4_PRODUCT_INFO_SIZE];
130 /* 0x20-0x2F */
131 unsigned char reserved_20_2f[0x10];
132 /* 0x30-0x3F */
133 unsigned char ds_firmware_id[0x10];
134 /* 0x40-0x4F */
135 unsigned char ds_customize_info[10];
136 unsigned char reserved_4a_4f[6];
137 /* 0x50-0x53*/
138 unsigned char firmware_id[4];
139 } __packed;
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700140 unsigned char data[0x54];
Amy Malocheafcecb22013-04-16 18:43:22 -0700141 };
142};
143
Alexandra Chin669d27c2012-12-24 15:42:30 +0800144struct image_header {
145 unsigned int checksum;
146 unsigned int image_size;
147 unsigned int config_size;
148 unsigned char options;
149 unsigned char bootloader_version;
150 unsigned char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
151 unsigned char product_info[SYNAPTICS_RMI4_PRODUCT_INFO_SIZE];
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700152 u16 package_id;
153 u16 package_revision_id;
Amy Malocheafcecb22013-04-16 18:43:22 -0700154 unsigned int firmware_id;
155 bool is_contain_build_info;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800156};
157
158struct pdt_properties {
159 union {
160 struct {
161 unsigned char reserved_1:6;
162 unsigned char has_bsr:1;
163 unsigned char reserved_2:1;
164 } __packed;
165 unsigned char data[1];
166 };
167};
168
169struct f01_device_status {
170 union {
171 struct {
172 unsigned char status_code:4;
173 unsigned char reserved:2;
174 unsigned char flash_prog:1;
175 unsigned char unconfigured:1;
176 } __packed;
177 unsigned char data[1];
178 };
179};
180
181struct f01_device_control {
182 union {
183 struct {
184 unsigned char sleep_mode:2;
185 unsigned char nosleep:1;
186 unsigned char reserved:2;
187 unsigned char charger_connected:1;
188 unsigned char report_rate:1;
189 unsigned char configured:1;
190 } __packed;
191 unsigned char data[1];
192 };
193};
194
195struct f34_flash_control {
196 union {
197 struct {
198 unsigned char command:4;
199 unsigned char status:3;
200 unsigned char program_enabled:1;
201 } __packed;
202 unsigned char data[1];
203 };
204};
205
206struct f34_flash_properties {
207 union {
208 struct {
209 unsigned char regmap:1;
210 unsigned char unlocked:1;
211 unsigned char has_configid:1;
212 unsigned char has_perm_config:1;
213 unsigned char has_bl_config:1;
214 unsigned char has_display_config:1;
215 unsigned char has_blob_config:1;
216 unsigned char reserved:1;
217 } __packed;
218 unsigned char data[1];
219 };
220};
221
222struct synaptics_rmi4_fwu_handle {
223 bool initialized;
Alexandra Chind5591a62013-02-07 12:59:15 -0800224 bool force_update;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800225 char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
226 unsigned int image_size;
227 unsigned int data_pos;
228 unsigned char intr_mask;
229 unsigned char bootloader_id[2];
230 unsigned char productinfo1;
231 unsigned char productinfo2;
232 unsigned char *ext_data_source;
233 unsigned char *read_config_buf;
234 const unsigned char *firmware_data;
235 const unsigned char *config_data;
236 unsigned short block_size;
237 unsigned short fw_block_count;
238 unsigned short config_block_count;
239 unsigned short perm_config_block_count;
240 unsigned short bl_config_block_count;
241 unsigned short disp_config_block_count;
242 unsigned short config_size;
243 unsigned short config_area;
244 unsigned short addr_f34_flash_control;
245 unsigned short addr_f01_interrupt_register;
246 struct synaptics_rmi4_fn_desc f01_fd;
247 struct synaptics_rmi4_fn_desc f34_fd;
248 struct synaptics_rmi4_exp_fn_ptr *fn_ptr;
249 struct synaptics_rmi4_data *rmi4_data;
250 struct f34_flash_control flash_control;
251 struct f34_flash_properties flash_properties;
Alexandra Chind5591a62013-02-07 12:59:15 -0800252 struct workqueue_struct *fwu_workqueue;
253 struct delayed_work fwu_work;
Amy Malocheb494b9a2013-05-13 18:01:53 -0700254 char firmware_name[NAME_BUFFER_SIZE];
Amy Maloched9bf0d92013-06-19 17:19:23 -0700255 char *ts_info;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800256};
257
258static struct synaptics_rmi4_fwu_handle *fwu;
259
260static struct completion remove_complete;
261
262static unsigned int extract_uint(const unsigned char *ptr)
263{
264 return (unsigned int)ptr[0] +
265 (unsigned int)ptr[1] * 0x100 +
266 (unsigned int)ptr[2] * 0x10000 +
267 (unsigned int)ptr[3] * 0x1000000;
268}
269
Amy Malocheafcecb22013-04-16 18:43:22 -0700270static unsigned int extract_uint_be(const unsigned char *ptr)
271{
272 return (unsigned int)ptr[3] +
273 (unsigned int)ptr[2] * 0x100 +
274 (unsigned int)ptr[1] * 0x10000 +
275 (unsigned int)ptr[0] * 0x1000000;
276}
277
Amy Maloched9bf0d92013-06-19 17:19:23 -0700278static void synaptics_rmi4_update_debug_info(void)
279{
280 unsigned char pkg_id[4];
281 unsigned int build_id;
282 struct synaptics_rmi4_device_info *rmi;
283 /* read device package id */
284 fwu->fn_ptr->read(fwu->rmi4_data,
285 fwu->f01_fd.query_base_addr + 17,
286 pkg_id,
287 sizeof(pkg_id));
288 rmi = &(fwu->rmi4_data->rmi4_mod_info);
289
290 build_id = (unsigned int)rmi->build_id[0] +
291 (unsigned int)rmi->build_id[1] * 0x100 +
292 (unsigned int)rmi->build_id[2] * 0x10000;
293
294 RMI4_STORE_TS_INFO(fwu->ts_info, pkg_id[1] << 8 | pkg_id[0],
295 pkg_id[3] << 8 | pkg_id[2], build_id);
296}
297
Alexandra Chin669d27c2012-12-24 15:42:30 +0800298static void parse_header(struct image_header *header,
299 const unsigned char *fw_image)
300{
Amy Malocheafcecb22013-04-16 18:43:22 -0700301 struct image_header_data *data = (struct image_header_data *)fw_image;
302 header->checksum = extract_uint(data->file_checksum);
303 header->bootloader_version = data->bootloader_version;
304 header->image_size = extract_uint(data->firmware_size);
305 header->config_size = extract_uint(data->config_size);
306 memcpy(header->product_id, data->product_id,
307 sizeof(data->product_id));
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700308 header->product_id[sizeof(data->product_id)] = 0;
309
Amy Malocheafcecb22013-04-16 18:43:22 -0700310 memcpy(header->product_info, data->product_info,
311 sizeof(data->product_info));
312
313 header->is_contain_build_info =
314 (data->options_firmware_id == (1 << OPTION_BUILD_INFO));
315 if (header->is_contain_build_info) {
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700316 header->package_id = (data->pkg_id_rev_msb << 8) |
317 data->pkg_id_lsb;
318 header->package_revision_id = (data->pkg_id_rev_msb << 8) |
319 data->pkg_id_rev_lsb;
320 dev_info(&fwu->rmi4_data->i2c_client->dev,
321 "%s Package ID %d Rev %d\n", __func__,
322 header->package_id, header->package_revision_id);
323
Amy Malocheafcecb22013-04-16 18:43:22 -0700324 header->firmware_id = extract_uint(data->firmware_id);
325 dev_info(&fwu->rmi4_data->i2c_client->dev,
326 "%s Firwmare build id %d\n", __func__,
327 header->firmware_id);
328 }
Alexandra Chin669d27c2012-12-24 15:42:30 +0800329
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700330 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
Alexandra Chin669d27c2012-12-24 15:42:30 +0800331 "Firwmare size %d, config size %d\n",
332 header->image_size,
333 header->config_size);
Alexandra Chin669d27c2012-12-24 15:42:30 +0800334 return;
335}
336
Alexandra Chin669d27c2012-12-24 15:42:30 +0800337static int fwu_read_f01_device_status(struct f01_device_status *status)
338{
339 int retval;
340
341 retval = fwu->fn_ptr->read(fwu->rmi4_data,
342 fwu->f01_fd.data_base_addr,
343 status->data,
344 sizeof(status->data));
345 if (retval < 0) {
346 dev_err(&fwu->rmi4_data->i2c_client->dev,
347 "%s: Failed to read F01 device status\n",
348 __func__);
349 return retval;
350 }
351
352 return 0;
353}
354
355static int fwu_read_f34_queries(void)
356{
357 int retval;
358 unsigned char count = 4;
359 unsigned char buf[10];
360 struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
361
362 retval = fwu->fn_ptr->read(fwu->rmi4_data,
363 fwu->f34_fd.query_base_addr + BOOTLOADER_ID_OFFSET,
364 fwu->bootloader_id,
365 sizeof(fwu->bootloader_id));
366 if (retval < 0) {
367 dev_err(&i2c_client->dev,
368 "%s: Failed to read bootloader ID\n",
369 __func__);
370 return retval;
371 }
372
373 retval = fwu->fn_ptr->read(fwu->rmi4_data,
374 fwu->f34_fd.query_base_addr + FLASH_PROPERTIES_OFFSET,
375 fwu->flash_properties.data,
376 sizeof(fwu->flash_properties.data));
377 if (retval < 0) {
378 dev_err(&i2c_client->dev,
379 "%s: Failed to read flash properties\n",
380 __func__);
381 return retval;
382 }
383
Alexandra Chind5591a62013-02-07 12:59:15 -0800384 dev_info(&i2c_client->dev, "%s perm:%d, bl:%d, display:%d\n",
Alexandra Chin669d27c2012-12-24 15:42:30 +0800385 __func__,
386 fwu->flash_properties.has_perm_config,
387 fwu->flash_properties.has_bl_config,
388 fwu->flash_properties.has_display_config);
389
390 if (fwu->flash_properties.has_perm_config)
391 count += 2;
392
393 if (fwu->flash_properties.has_bl_config)
394 count += 2;
395
396 if (fwu->flash_properties.has_display_config)
397 count += 2;
398
399 retval = fwu->fn_ptr->read(fwu->rmi4_data,
400 fwu->f34_fd.query_base_addr + BLOCK_SIZE_OFFSET,
401 buf,
402 2);
403 if (retval < 0) {
404 dev_err(&i2c_client->dev,
405 "%s: Failed to read block size info\n",
406 __func__);
407 return retval;
408 }
409
410 batohs(&fwu->block_size, &(buf[0]));
411
412 retval = fwu->fn_ptr->read(fwu->rmi4_data,
413 fwu->f34_fd.query_base_addr + FW_BLOCK_COUNT_OFFSET,
414 buf,
415 count);
416 if (retval < 0) {
417 dev_err(&i2c_client->dev,
418 "%s: Failed to read block count info\n",
419 __func__);
420 return retval;
421 }
422
423 batohs(&fwu->fw_block_count, &(buf[0]));
424 batohs(&fwu->config_block_count, &(buf[2]));
425
426 count = 4;
427
428 if (fwu->flash_properties.has_perm_config) {
429 batohs(&fwu->perm_config_block_count, &(buf[count]));
430 count += 2;
431 }
432
433 if (fwu->flash_properties.has_bl_config) {
434 batohs(&fwu->bl_config_block_count, &(buf[count]));
435 count += 2;
436 }
437
438 if (fwu->flash_properties.has_display_config)
439 batohs(&fwu->disp_config_block_count, &(buf[count]));
440
441 fwu->addr_f34_flash_control = fwu->f34_fd.data_base_addr +
442 BLOCK_DATA_OFFSET +
443 fwu->block_size;
444 return 0;
445}
446
447static int fwu_read_interrupt_status(void)
448{
449 int retval;
450 unsigned char interrupt_status;
451 retval = fwu->fn_ptr->read(fwu->rmi4_data,
452 fwu->addr_f01_interrupt_register,
453 &interrupt_status,
454 sizeof(interrupt_status));
455 if (retval < 0) {
456 dev_err(&fwu->rmi4_data->i2c_client->dev,
457 "%s: Failed to read flash status\n",
458 __func__);
459 return retval;
460 }
461 return interrupt_status;
462}
463
464static int fwu_read_f34_flash_status(void)
465{
466 int retval;
467 retval = fwu->fn_ptr->read(fwu->rmi4_data,
468 fwu->addr_f34_flash_control,
469 fwu->flash_control.data,
470 sizeof(fwu->flash_control.data));
471 if (retval < 0) {
472 dev_err(&fwu->rmi4_data->i2c_client->dev,
473 "%s: Failed to read flash status\n",
474 __func__);
475 return retval;
476 }
477 return 0;
478}
479
480static int fwu_reset_device(void)
481{
482 int retval;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800483
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700484 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
Alexandra Chind5591a62013-02-07 12:59:15 -0800485 "%s: Reset device\n",
486 __func__);
Alexandra Chin669d27c2012-12-24 15:42:30 +0800487
Alexandra Chin669d27c2012-12-24 15:42:30 +0800488 retval = fwu->rmi4_data->reset_device(fwu->rmi4_data);
489 if (retval < 0) {
490 dev_err(&fwu->rmi4_data->i2c_client->dev,
491 "%s: Failed to reset core driver after reflash\n",
492 __func__);
493 return retval;
494 }
495 return 0;
496}
497
498static int fwu_write_f34_command(unsigned char cmd)
499{
500 int retval;
501
Alexandra Chind5591a62013-02-07 12:59:15 -0800502 fwu->flash_control.data[0] = cmd;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800503 retval = fwu->fn_ptr->write(fwu->rmi4_data,
504 fwu->addr_f34_flash_control,
Alexandra Chind5591a62013-02-07 12:59:15 -0800505 fwu->flash_control.data,
506 sizeof(fwu->flash_control.data));
Alexandra Chin669d27c2012-12-24 15:42:30 +0800507 if (retval < 0) {
508 dev_err(&fwu->rmi4_data->i2c_client->dev,
509 "%s: Failed to write command 0x%02x\n",
Alexandra Chind5591a62013-02-07 12:59:15 -0800510 __func__, fwu->flash_control.data[0]);
Alexandra Chin669d27c2012-12-24 15:42:30 +0800511 return retval;
512 }
513 return 0;
514}
515
Alexandra Chin669d27c2012-12-24 15:42:30 +0800516static int fwu_wait_for_idle(int timeout_ms)
517{
518 int count = 0;
Alexandra Chind5591a62013-02-07 12:59:15 -0800519 int timeout_count = ((timeout_ms * 1000) / SLEEP_TIME_US) + 1;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800520 do {
Amy Malocheafcecb22013-04-16 18:43:22 -0700521 #if POLLING_MODE
522 fwu_read_f34_flash_status();
523 #endif
Alexandra Chind5591a62013-02-07 12:59:15 -0800524 if (fwu->flash_control.command == 0x00)
Alexandra Chin669d27c2012-12-24 15:42:30 +0800525 return 0;
526
Alexandra Chind5591a62013-02-07 12:59:15 -0800527 usleep_range(SLEEP_TIME_US, SLEEP_TIME_US + 100);
528 } while (count++ < timeout_count);
529
530 fwu_read_f34_flash_status();
531 if (fwu->flash_control.command == 0x00)
532 return 0;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800533
534 dev_err(&fwu->rmi4_data->i2c_client->dev,
535 "%s: Timed out waiting for idle status\n",
536 __func__);
537
538 return -ETIMEDOUT;
539}
540
Amy Malocheafcecb22013-04-16 18:43:22 -0700541static enum flash_area fwu_go_nogo(struct image_header *header)
Alexandra Chind5591a62013-02-07 12:59:15 -0800542{
543 int retval = 0;
544 int index = 0;
545 int deviceFirmwareID;
546 int imageConfigID;
547 int deviceConfigID;
548 unsigned long imageFirmwareID;
549 unsigned char firmware_id[4];
550 unsigned char config_id[4];
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700551 unsigned char pkg_id[4];
Alexandra Chind5591a62013-02-07 12:59:15 -0800552 char *strptr;
553 char *imagePR = kzalloc(sizeof(MAX_FIRMWARE_ID_LEN), GFP_KERNEL);
554 enum flash_area flash_area = NONE;
555 struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
556 struct f01_device_status f01_device_status;
557
558 if (fwu->force_update) {
559 flash_area = UI_FIRMWARE;
560 goto exit;
561 }
562
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700563 if (header->is_contain_build_info) {
564 /* if package id does not match, do not update firmware */
565 fwu->fn_ptr->read(fwu->rmi4_data,
566 fwu->f01_fd.query_base_addr + 17,
567 pkg_id,
568 sizeof(pkg_id));
569
570 if (header->package_id != ((pkg_id[1] << 8) | pkg_id[0])) {
571 flash_area = MISMATCH;
572 goto exit;
573 }
574 if (header->package_revision_id !=
575 ((pkg_id[3] << 8) | pkg_id[2])) {
576 flash_area = MISMATCH;
577 goto exit;
578 }
579 }
580
Alexandra Chind5591a62013-02-07 12:59:15 -0800581 retval = fwu_read_f01_device_status(&f01_device_status);
582 if (retval < 0) {
583 flash_area = NONE;
584 goto exit;
585 }
586
Alexandra Chind5591a62013-02-07 12:59:15 -0800587 /* Force update firmware when device is in bootloader mode */
588 if (f01_device_status.flash_prog) {
589 dev_info(&i2c_client->dev,
590 "%s: In flash prog mode\n",
591 __func__);
592 flash_area = UI_FIRMWARE;
593 goto exit;
594 }
595
Alexandra Chind5591a62013-02-07 12:59:15 -0800596 /* device firmware id */
597 retval = fwu->fn_ptr->read(fwu->rmi4_data,
598 fwu->f01_fd.query_base_addr + 18,
599 firmware_id,
600 sizeof(firmware_id));
601 if (retval < 0) {
602 dev_err(&i2c_client->dev,
Amy Malocheafcecb22013-04-16 18:43:22 -0700603 "%s: Failed to read firmware ID (code %d).\n",
604 __func__, retval);
Alexandra Chind5591a62013-02-07 12:59:15 -0800605 goto exit;
606 }
607 firmware_id[3] = 0;
608 deviceFirmwareID = extract_uint(firmware_id);
609
610 /* .img firmware id */
Amy Malocheafcecb22013-04-16 18:43:22 -0700611 if (header->is_contain_build_info) {
Alexandra Chind5591a62013-02-07 12:59:15 -0800612 dev_err(&i2c_client->dev,
Amy Malocheafcecb22013-04-16 18:43:22 -0700613 "%s: Image option contains build info.\n",
614 __func__);
615 imageFirmwareID = header->firmware_id;
616 } else {
617 strptr = strnstr(fwu->firmware_name, "PR",
618 sizeof(fwu->firmware_name));
619 if (!strptr) {
620 dev_err(&i2c_client->dev,
621 "No valid PR number (PRxxxxxxx)" \
622 "found in image file name...\n");
623 goto exit;
624 }
625
626 strptr += 2;
627 while (strptr[index] >= '0' && strptr[index] <= '9') {
628 imagePR[index] = strptr[index];
629 index++;
630 }
631 imagePR[index] = 0;
632
633 retval = kstrtoul(imagePR, 10, &imageFirmwareID);
634 if (retval == -EINVAL) {
635 dev_err(&i2c_client->dev,
636 "invalid image firmware id...\n");
637 goto exit;
638 }
Alexandra Chind5591a62013-02-07 12:59:15 -0800639 }
640
Amy Malocheafcecb22013-04-16 18:43:22 -0700641 dev_dbg(&i2c_client->dev,
Alexandra Chind5591a62013-02-07 12:59:15 -0800642 "Device firmware id %d, .img firmware id %d\n",
643 deviceFirmwareID,
644 (unsigned int)imageFirmwareID);
645 if (imageFirmwareID > deviceFirmwareID) {
646 flash_area = UI_FIRMWARE;
647 goto exit;
Alexandra Chinc556cf02013-03-19 17:46:05 -0700648 } else if (imageFirmwareID < deviceFirmwareID) {
649 flash_area = NONE;
650 dev_info(&i2c_client->dev,
Amy Malocheafcecb22013-04-16 18:43:22 -0700651 "%s: Img fw is older than device fw. Skip fw update.\n",
652 __func__);
Alexandra Chinc556cf02013-03-19 17:46:05 -0700653 goto exit;
Alexandra Chind5591a62013-02-07 12:59:15 -0800654 }
655
656 /* device config id */
657 retval = fwu->fn_ptr->read(fwu->rmi4_data,
658 fwu->f34_fd.ctrl_base_addr,
659 config_id,
660 sizeof(config_id));
661 if (retval < 0) {
662 dev_err(&i2c_client->dev,
Amy Malocheafcecb22013-04-16 18:43:22 -0700663 "%s: Failed to read config ID (code %d).\n",
664 __func__, retval);
Alexandra Chind5591a62013-02-07 12:59:15 -0800665 flash_area = NONE;
666 goto exit;
667 }
Amy Malocheafcecb22013-04-16 18:43:22 -0700668 deviceConfigID = extract_uint_be(config_id);
Alexandra Chind5591a62013-02-07 12:59:15 -0800669
Amy Malocheafcecb22013-04-16 18:43:22 -0700670 dev_dbg(&i2c_client->dev,
Alexandra Chind5591a62013-02-07 12:59:15 -0800671 "Device config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
672 config_id[0], config_id[1], config_id[2], config_id[3]);
673
674 /* .img config id */
Amy Malocheafcecb22013-04-16 18:43:22 -0700675 dev_dbg(&i2c_client->dev,
Alexandra Chind5591a62013-02-07 12:59:15 -0800676 ".img config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
677 fwu->config_data[0],
678 fwu->config_data[1],
679 fwu->config_data[2],
680 fwu->config_data[3]);
Amy Malocheafcecb22013-04-16 18:43:22 -0700681 imageConfigID = extract_uint_be(fwu->config_data);
682
683 dev_dbg(&i2c_client->dev,
684 "%s: Device config ID %d, .img config ID %d\n",
685 __func__, deviceConfigID, imageConfigID);
Alexandra Chind5591a62013-02-07 12:59:15 -0800686
687 if (imageConfigID > deviceConfigID) {
688 flash_area = CONFIG_AREA;
689 goto exit;
690 }
Alexandra Chind5591a62013-02-07 12:59:15 -0800691exit:
692 kfree(imagePR);
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700693 if (flash_area == MISMATCH)
694 dev_info(&i2c_client->dev,
695 "%s: Package ID indicates mismatch of firmware and" \
696 " controller compatibility\n", __func__);
697 else if (flash_area == NONE)
Alexandra Chind5591a62013-02-07 12:59:15 -0800698 dev_info(&i2c_client->dev,
Amy Malocheafcecb22013-04-16 18:43:22 -0700699 "%s: Nothing needs to be updated\n", __func__);
Alexandra Chind5591a62013-02-07 12:59:15 -0800700 else
701 dev_info(&i2c_client->dev,
Amy Malocheafcecb22013-04-16 18:43:22 -0700702 "%s: Update %s block\n", __func__,
Alexandra Chind5591a62013-02-07 12:59:15 -0800703 flash_area == UI_FIRMWARE ? "UI FW" : "CONFIG");
704 return flash_area;
705}
706
Alexandra Chin669d27c2012-12-24 15:42:30 +0800707static int fwu_scan_pdt(void)
708{
709 int retval;
710 unsigned char ii;
711 unsigned char intr_count = 0;
712 unsigned char intr_off;
713 unsigned char intr_src;
714 unsigned short addr;
715 bool f01found = false;
716 bool f34found = false;
717 struct synaptics_rmi4_fn_desc rmi_fd;
718
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700719 dev_dbg(&fwu->rmi4_data->i2c_client->dev, "Scan PDT\n");
Alexandra Chin669d27c2012-12-24 15:42:30 +0800720
721 for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) {
722 retval = fwu->fn_ptr->read(fwu->rmi4_data,
723 addr,
724 (unsigned char *)&rmi_fd,
725 sizeof(rmi_fd));
726 if (retval < 0)
727 return retval;
728
729 if (rmi_fd.fn_number) {
730 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
731 "%s: Found F%02x\n",
732 __func__, rmi_fd.fn_number);
733 switch (rmi_fd.fn_number) {
734 case SYNAPTICS_RMI4_F01:
735 f01found = true;
736 fwu->f01_fd = rmi_fd;
737 fwu->addr_f01_interrupt_register =
738 fwu->f01_fd.data_base_addr + 1;
739 break;
740 case SYNAPTICS_RMI4_F34:
741 f34found = true;
742 fwu->f34_fd = rmi_fd;
743 fwu->intr_mask = 0;
744 intr_src = rmi_fd.intr_src_count;
745 intr_off = intr_count % 8;
746 for (ii = intr_off;
747 ii < ((intr_src & MASK_3BIT) +
748 intr_off);
749 ii++)
750 fwu->intr_mask |= 1 << ii;
751 break;
752 }
753 } else
754 break;
755
756 intr_count += (rmi_fd.intr_src_count & MASK_3BIT);
757 }
758
759 if (!f01found || !f34found) {
760 dev_err(&fwu->rmi4_data->i2c_client->dev,
761 "%s: Failed to find both F01 and F34\n",
762 __func__);
763 return -EINVAL;
764 }
765
766 fwu_read_interrupt_status();
767 return 0;
768}
769
770static int fwu_write_blocks(unsigned char *block_ptr, unsigned short block_cnt,
771 unsigned char command)
772{
773 int retval;
774 unsigned char block_offset[] = {0, 0};
775 unsigned short block_num;
Alexandra Chind5591a62013-02-07 12:59:15 -0800776 struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800777#ifdef SHOW_PROGRESS
778 unsigned int progress = (command == CMD_WRITE_CONFIG_BLOCK) ?
779 10 : 100;
780#endif
Alexandra Chind5591a62013-02-07 12:59:15 -0800781
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700782 dev_dbg(&i2c_client->dev,
Alexandra Chind5591a62013-02-07 12:59:15 -0800783 "%s: Start to update %s blocks\n",
784 __func__,
785 command == CMD_WRITE_CONFIG_BLOCK ?
786 "config" : "firmware");
Alexandra Chin669d27c2012-12-24 15:42:30 +0800787 retval = fwu->fn_ptr->write(fwu->rmi4_data,
788 fwu->f34_fd.data_base_addr + BLOCK_NUMBER_OFFSET,
789 block_offset,
790 sizeof(block_offset));
791 if (retval < 0) {
Alexandra Chind5591a62013-02-07 12:59:15 -0800792 dev_err(&i2c_client->dev,
Alexandra Chin669d27c2012-12-24 15:42:30 +0800793 "%s: Failed to write to block number registers\n",
794 __func__);
795 return retval;
796 }
797
798 for (block_num = 0; block_num < block_cnt; block_num++) {
799#ifdef SHOW_PROGRESS
800 if (block_num % progress == 0)
Alexandra Chind5591a62013-02-07 12:59:15 -0800801 dev_info(&i2c_client->dev,
802 "%s: update %s %3d / %3d\n",
803 __func__,
804 command == CMD_WRITE_CONFIG_BLOCK ?
805 "config" : "firmware",
806 block_num, block_cnt);
Alexandra Chin669d27c2012-12-24 15:42:30 +0800807#endif
808 retval = fwu->fn_ptr->write(fwu->rmi4_data,
809 fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET,
810 block_ptr,
811 fwu->block_size);
812 if (retval < 0) {
Alexandra Chind5591a62013-02-07 12:59:15 -0800813 dev_err(&i2c_client->dev,
Alexandra Chin669d27c2012-12-24 15:42:30 +0800814 "%s: Failed to write block data (block %d)\n",
815 __func__, block_num);
816 return retval;
817 }
818
819 retval = fwu_write_f34_command(command);
820 if (retval < 0) {
Alexandra Chind5591a62013-02-07 12:59:15 -0800821 dev_err(&i2c_client->dev,
Alexandra Chin669d27c2012-12-24 15:42:30 +0800822 "%s: Failed to write command for block %d\n",
823 __func__, block_num);
824 return retval;
825 }
826
827 retval = fwu_wait_for_idle(WRITE_WAIT_MS);
828 if (retval < 0) {
Alexandra Chind5591a62013-02-07 12:59:15 -0800829 dev_err(&i2c_client->dev,
830 "%s: Failed to wait for idle status (block %d)\n",
831 __func__, block_num);
Alexandra Chin669d27c2012-12-24 15:42:30 +0800832 return retval;
833 }
834
Alexandra Chind5591a62013-02-07 12:59:15 -0800835 if (fwu->flash_control.status != 0x00) {
836 dev_err(&i2c_client->dev,
837 "%s: Flash block %d failed, status 0x%02X\n",
Alexandra Chin669d27c2012-12-24 15:42:30 +0800838 __func__, block_num, retval);
Shantanu Jain41f0d472013-01-04 12:14:37 +0530839 return retval;
Alexandra Chin669d27c2012-12-24 15:42:30 +0800840 }
Alexandra Chind5591a62013-02-07 12:59:15 -0800841
Alexandra Chin669d27c2012-12-24 15:42:30 +0800842 block_ptr += fwu->block_size;
843 }
844#ifdef SHOW_PROGRESS
Alexandra Chind5591a62013-02-07 12:59:15 -0800845 dev_info(&i2c_client->dev,
846 "%s: update %s %3d / %3d\n",
847 __func__,
848 command == CMD_WRITE_CONFIG_BLOCK ?
849 "config" : "firmware",
850 block_cnt, block_cnt);
Alexandra Chin669d27c2012-12-24 15:42:30 +0800851#endif
852 return 0;
853}
854
855static int fwu_write_firmware(void)
856{
857 return fwu_write_blocks((unsigned char *)fwu->firmware_data,
858 fwu->fw_block_count, CMD_WRITE_FW_BLOCK);
859}
860
861static int fwu_write_configuration(void)
862{
863 return fwu_write_blocks((unsigned char *)fwu->config_data,
864 fwu->config_block_count, CMD_WRITE_CONFIG_BLOCK);
865}
866
867static int fwu_write_bootloader_id(void)
868{
869 int retval;
870
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700871 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
Alexandra Chind5591a62013-02-07 12:59:15 -0800872 "Write bootloader ID 0x%02X 0x%02X\n",
873 fwu->bootloader_id[0],
874 fwu->bootloader_id[1]);
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700875
Alexandra Chin669d27c2012-12-24 15:42:30 +0800876 retval = fwu->fn_ptr->write(fwu->rmi4_data,
877 fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET,
878 fwu->bootloader_id,
879 sizeof(fwu->bootloader_id));
880 if (retval < 0) {
881 dev_err(&fwu->rmi4_data->i2c_client->dev,
882 "%s: Failed to write bootloader ID\n",
883 __func__);
884 return retval;
885 }
886
887 return 0;
888}
889
890static int fwu_enter_flash_prog(void)
891{
892 int retval;
893 struct f01_device_status f01_device_status;
894 struct f01_device_control f01_device_control;
895
Amy Maloche2c4c48c2013-05-01 20:06:23 -0700896 dev_dbg(&fwu->rmi4_data->i2c_client->dev, "Enter bootloader mode\n");
897
Alexandra Chin669d27c2012-12-24 15:42:30 +0800898 retval = fwu_read_f01_device_status(&f01_device_status);
899 if (retval < 0)
900 return retval;
901
902 if (f01_device_status.flash_prog) {
903 dev_info(&fwu->rmi4_data->i2c_client->dev,
904 "%s: Already in flash prog mode\n",
905 __func__);
906 return 0;
907 }
908
909 retval = fwu_write_bootloader_id();
910 if (retval < 0)
911 return retval;
912
913 retval = fwu_write_f34_command(CMD_ENABLE_FLASH_PROG);
914 if (retval < 0)
915 return retval;
916
917 retval = fwu_wait_for_idle(ENABLE_WAIT_MS);
918 if (retval < 0)
919 return retval;
920
Alexandra Chin669d27c2012-12-24 15:42:30 +0800921 retval = fwu_scan_pdt();
922 if (retval < 0)
923 return retval;
924
925 retval = fwu_read_f01_device_status(&f01_device_status);
926 if (retval < 0)
927 return retval;
928
929 if (!f01_device_status.flash_prog) {
930 dev_err(&fwu->rmi4_data->i2c_client->dev,
931 "%s: Not in flash prog mode\n",
932 __func__);
933 return -EINVAL;
934 }
935
936 retval = fwu_read_f34_queries();
937 if (retval < 0)
938 return retval;
939
940 retval = fwu->fn_ptr->read(fwu->rmi4_data,
941 fwu->f01_fd.ctrl_base_addr,
942 f01_device_control.data,
943 sizeof(f01_device_control.data));
944 if (retval < 0) {
945 dev_err(&fwu->rmi4_data->i2c_client->dev,
946 "%s: Failed to read F01 device control\n",
947 __func__);
948 return retval;
949 }
950
951 f01_device_control.nosleep = true;
952 f01_device_control.sleep_mode = SLEEP_MODE_NORMAL;
953
954 retval = fwu->fn_ptr->write(fwu->rmi4_data,
955 fwu->f01_fd.ctrl_base_addr,
956 f01_device_control.data,
957 sizeof(f01_device_control.data));
958 if (retval < 0) {
959 dev_err(&fwu->rmi4_data->i2c_client->dev,
960 "%s: Failed to write F01 device control\n",
961 __func__);
962 return retval;
963 }
964
965 return retval;
966}
967
968static int fwu_do_reflash(void)
969{
970 int retval;
971
972 retval = fwu_enter_flash_prog();
973 if (retval < 0)
974 return retval;
975
976 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
977 "%s: Entered flash prog mode\n",
978 __func__);
979
980 retval = fwu_write_bootloader_id();
981 if (retval < 0)
982 return retval;
983
984 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
985 "%s: Bootloader ID written\n",
986 __func__);
987
988 retval = fwu_write_f34_command(CMD_ERASE_ALL);
989 if (retval < 0)
990 return retval;
991
992 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
993 "%s: Erase all command written\n",
994 __func__);
995
996 retval = fwu_wait_for_idle(ERASE_WAIT_MS);
997 if (retval < 0)
998 return retval;
999
Alexandra Chind5591a62013-02-07 12:59:15 -08001000 if (fwu->flash_control.status != 0x00) {
1001 dev_err(&fwu->rmi4_data->i2c_client->dev,
1002 "%s: Erase all command failed, status 0x%02X\n",
1003 __func__, retval);
1004 return -1;
1005 }
Alexandra Chin669d27c2012-12-24 15:42:30 +08001006
1007 if (fwu->firmware_data) {
1008 retval = fwu_write_firmware();
1009 if (retval < 0)
1010 return retval;
1011 pr_notice("%s: Firmware programmed\n", __func__);
1012 }
1013
1014 if (fwu->config_data) {
1015 retval = fwu_write_configuration();
1016 if (retval < 0)
1017 return retval;
1018 pr_notice("%s: Configuration programmed\n", __func__);
1019 }
1020
1021 return retval;
1022}
1023
Alexandra Chin669d27c2012-12-24 15:42:30 +08001024static int fwu_do_write_config(void)
1025{
1026 int retval;
1027
1028 retval = fwu_enter_flash_prog();
1029 if (retval < 0)
1030 return retval;
1031
1032 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1033 "%s: Entered flash prog mode\n",
1034 __func__);
1035
1036 if (fwu->config_area == PERM_CONFIG_AREA) {
1037 fwu->config_block_count = fwu->perm_config_block_count;
1038 goto write_config;
1039 }
1040
1041 retval = fwu_write_bootloader_id();
1042 if (retval < 0)
1043 return retval;
1044
1045 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1046 "%s: Bootloader ID written\n",
1047 __func__);
1048
1049 switch (fwu->config_area) {
1050 case UI_CONFIG_AREA:
1051 retval = fwu_write_f34_command(CMD_ERASE_CONFIG);
1052 break;
1053 case BL_CONFIG_AREA:
1054 retval = fwu_write_f34_command(CMD_ERASE_BL_CONFIG);
1055 fwu->config_block_count = fwu->bl_config_block_count;
1056 break;
1057 case DISP_CONFIG_AREA:
1058 retval = fwu_write_f34_command(CMD_ERASE_DISP_CONFIG);
1059 fwu->config_block_count = fwu->disp_config_block_count;
1060 break;
1061 }
1062 if (retval < 0)
1063 return retval;
1064
1065 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1066 "%s: Erase command written\n",
1067 __func__);
1068
1069 retval = fwu_wait_for_idle(ERASE_WAIT_MS);
1070 if (retval < 0)
1071 return retval;
1072
1073 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1074 "%s: Idle status detected\n",
1075 __func__);
1076
1077write_config:
1078 retval = fwu_write_configuration();
1079 if (retval < 0)
1080 return retval;
1081
1082 pr_notice("%s: Config written\n", __func__);
1083
1084 return retval;
1085}
1086
1087static int fwu_start_write_config(void)
1088{
1089 int retval;
1090 struct image_header header;
1091
1092 switch (fwu->config_area) {
1093 case UI_CONFIG_AREA:
1094 break;
1095 case PERM_CONFIG_AREA:
1096 if (!fwu->flash_properties.has_perm_config)
1097 return -EINVAL;
1098 break;
1099 case BL_CONFIG_AREA:
1100 if (!fwu->flash_properties.has_bl_config)
1101 return -EINVAL;
1102 break;
1103 case DISP_CONFIG_AREA:
1104 if (!fwu->flash_properties.has_display_config)
1105 return -EINVAL;
1106 break;
1107 default:
1108 return -EINVAL;
1109 }
1110
1111 if (fwu->ext_data_source)
1112 fwu->config_data = fwu->ext_data_source;
1113 else
1114 return -EINVAL;
1115
1116 if (fwu->config_area == UI_CONFIG_AREA) {
1117 parse_header(&header, fwu->ext_data_source);
1118
1119 if (header.config_size) {
1120 fwu->config_data = fwu->ext_data_source +
1121 FW_IMAGE_OFFSET +
1122 header.image_size;
1123 } else {
1124 return -EINVAL;
1125 }
1126 }
1127
1128 pr_notice("%s: Start of write config process\n", __func__);
1129
1130 retval = fwu_do_write_config();
1131 if (retval < 0) {
1132 dev_err(&fwu->rmi4_data->i2c_client->dev,
1133 "%s: Failed to write config\n",
1134 __func__);
1135 }
1136
1137 fwu->rmi4_data->reset_device(fwu->rmi4_data);
1138
1139 pr_notice("%s: End of write config process\n", __func__);
1140
1141 return retval;
1142}
1143
1144static int fwu_do_read_config(void)
1145{
1146 int retval;
1147 unsigned char block_offset[] = {0, 0};
1148 unsigned short block_num;
1149 unsigned short block_count;
1150 unsigned short index = 0;
1151
1152 retval = fwu_enter_flash_prog();
1153 if (retval < 0)
1154 goto exit;
1155
1156 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1157 "%s: Entered flash prog mode\n",
1158 __func__);
1159
1160 switch (fwu->config_area) {
1161 case UI_CONFIG_AREA:
1162 block_count = fwu->config_block_count;
1163 break;
1164 case PERM_CONFIG_AREA:
1165 if (!fwu->flash_properties.has_perm_config) {
1166 retval = -EINVAL;
1167 goto exit;
1168 }
1169 block_count = fwu->perm_config_block_count;
1170 break;
1171 case BL_CONFIG_AREA:
1172 if (!fwu->flash_properties.has_bl_config) {
1173 retval = -EINVAL;
1174 goto exit;
1175 }
1176 block_count = fwu->bl_config_block_count;
1177 break;
1178 case DISP_CONFIG_AREA:
1179 if (!fwu->flash_properties.has_display_config) {
1180 retval = -EINVAL;
1181 goto exit;
1182 }
1183 block_count = fwu->disp_config_block_count;
1184 break;
1185 default:
1186 retval = -EINVAL;
1187 goto exit;
1188 }
1189
1190 fwu->config_size = fwu->block_size * block_count;
1191
1192 kfree(fwu->read_config_buf);
1193 fwu->read_config_buf = kzalloc(fwu->config_size, GFP_KERNEL);
1194
1195 block_offset[1] |= (fwu->config_area << 5);
1196
1197 retval = fwu->fn_ptr->write(fwu->rmi4_data,
1198 fwu->f34_fd.data_base_addr + BLOCK_NUMBER_OFFSET,
1199 block_offset,
1200 sizeof(block_offset));
1201 if (retval < 0) {
1202 dev_err(&fwu->rmi4_data->i2c_client->dev,
1203 "%s: Failed to write to block number registers\n",
1204 __func__);
1205 goto exit;
1206 }
1207
1208 for (block_num = 0; block_num < block_count; block_num++) {
1209 retval = fwu_write_f34_command(CMD_READ_CONFIG_BLOCK);
1210 if (retval < 0) {
1211 dev_err(&fwu->rmi4_data->i2c_client->dev,
1212 "%s: Failed to write read config command\n",
1213 __func__);
1214 goto exit;
1215 }
1216
1217 retval = fwu_wait_for_idle(WRITE_WAIT_MS);
1218 if (retval < 0) {
1219 dev_err(&fwu->rmi4_data->i2c_client->dev,
1220 "%s: Failed to wait for idle status\n",
1221 __func__);
1222 goto exit;
1223 }
1224
1225 retval = fwu->fn_ptr->read(fwu->rmi4_data,
1226 fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET,
1227 &fwu->read_config_buf[index],
1228 fwu->block_size);
1229 if (retval < 0) {
1230 dev_err(&fwu->rmi4_data->i2c_client->dev,
1231 "%s: Failed to read block data (block %d)\n",
1232 __func__, block_num);
1233 goto exit;
1234 }
1235
1236 index += fwu->block_size;
1237 }
1238
1239exit:
1240 fwu->rmi4_data->reset_device(fwu->rmi4_data);
1241
1242 return retval;
1243}
1244
Alexandra Chind5591a62013-02-07 12:59:15 -08001245static int fwu_start_reflash(void)
1246{
Amy Malocheafcecb22013-04-16 18:43:22 -07001247 int retval = 0;
Alexandra Chind5591a62013-02-07 12:59:15 -08001248 struct image_header header;
1249 const unsigned char *fw_image;
1250 const struct firmware *fw_entry = NULL;
1251 struct f01_device_status f01_device_status;
1252 enum flash_area flash_area;
1253
1254 pr_notice("%s: Start of reflash process\n", __func__);
1255
Amy Malocheb494b9a2013-05-13 18:01:53 -07001256 if (strnlen(fwu->rmi4_data->fw_image_name, NAME_BUFFER_SIZE) == 0) {
Amy Malochecb835832013-03-26 18:06:05 -07001257 dev_err(&fwu->rmi4_data->i2c_client->dev,
1258 "Firmware image name not given, skipping update\n");
Amy Malocheb494b9a2013-05-13 18:01:53 -07001259 return 0;
1260 }
1261
1262 if (strnlen(fwu->rmi4_data->fw_image_name, NAME_BUFFER_SIZE) ==
1263 NAME_BUFFER_SIZE) {
1264 dev_err(&fwu->rmi4_data->i2c_client->dev,
1265 "Firmware image name exceeds max length (%d), " \
1266 "skipping update\n", NAME_BUFFER_SIZE);
1267 return 0;
Amy Malochecb835832013-03-26 18:06:05 -07001268 }
1269
Alexandra Chind5591a62013-02-07 12:59:15 -08001270 if (fwu->ext_data_source)
1271 fw_image = fwu->ext_data_source;
1272 else {
Amy Malocheafcecb22013-04-16 18:43:22 -07001273 snprintf(fwu->firmware_name, NAME_BUFFER_SIZE, "%s",
1274 fwu->rmi4_data->fw_image_name);
1275 dev_info(&fwu->rmi4_data->i2c_client->dev,
1276 "%s: Requesting firmware image %s\n",
1277 __func__, fwu->firmware_name);
Alexandra Chind5591a62013-02-07 12:59:15 -08001278
Amy Malochecb835832013-03-26 18:06:05 -07001279 retval = request_firmware(&fw_entry,
Amy Malocheafcecb22013-04-16 18:43:22 -07001280 fwu->firmware_name,
Alexandra Chind5591a62013-02-07 12:59:15 -08001281 &fwu->rmi4_data->i2c_client->dev);
1282 if (retval != 0) {
1283 dev_err(&fwu->rmi4_data->i2c_client->dev,
1284 "%s: Firmware image %s not available\n",
Amy Malochecb835832013-03-26 18:06:05 -07001285 __func__,
Amy Malocheafcecb22013-04-16 18:43:22 -07001286 fwu->firmware_name);
Amy Malocheb494b9a2013-05-13 18:01:53 -07001287 return -EINVAL;
Alexandra Chind5591a62013-02-07 12:59:15 -08001288 }
1289
1290 dev_dbg(&fwu->rmi4_data->i2c_client->dev,
1291 "%s: Firmware image size = %d\n",
1292 __func__, fw_entry->size);
1293
1294 fw_image = fw_entry->data;
1295 }
1296
1297 parse_header(&header, fw_image);
1298
1299 if (header.image_size)
1300 fwu->firmware_data = fw_image + FW_IMAGE_OFFSET;
1301 if (header.config_size) {
1302 fwu->config_data = fw_image + FW_IMAGE_OFFSET +
1303 header.image_size;
1304 }
1305
1306 if (fwu->ext_data_source)
1307 flash_area = UI_FIRMWARE;
1308 else
Amy Malocheafcecb22013-04-16 18:43:22 -07001309 flash_area = fwu_go_nogo(&header);
Alexandra Chind5591a62013-02-07 12:59:15 -08001310
1311 switch (flash_area) {
1312 case NONE:
Amy Maloche2c4c48c2013-05-01 20:06:23 -07001313 case MISMATCH:
1314 retval = 0;
Alexandra Chind5591a62013-02-07 12:59:15 -08001315 dev_info(&fwu->rmi4_data->i2c_client->dev,
1316 "%s: No need to do reflash.\n",
1317 __func__);
1318 goto exit;
1319 case UI_FIRMWARE:
1320 retval = fwu_do_reflash();
1321 break;
1322 case CONFIG_AREA:
1323 retval = fwu_do_write_config();
1324 break;
1325 default:
1326 dev_err(&fwu->rmi4_data->i2c_client->dev,
1327 "%s: Unknown flash area\n",
1328 __func__);
1329 goto exit;
1330 }
1331
1332 if (retval < 0) {
1333 dev_err(&fwu->rmi4_data->i2c_client->dev,
1334 "%s: Failed to do reflash\n",
1335 __func__);
1336 }
1337
1338 /* reset device */
1339 fwu_reset_device();
1340
1341 /* check device status */
1342 retval = fwu_read_f01_device_status(&f01_device_status);
1343 if (retval < 0)
1344 goto exit;
1345
1346 dev_info(&fwu->rmi4_data->i2c_client->dev, "Device is in %s mode\n",
1347 f01_device_status.flash_prog == 1 ? "bootloader" : "UI");
1348 if (f01_device_status.flash_prog)
1349 dev_info(&fwu->rmi4_data->i2c_client->dev, "Flash status %d\n",
1350 f01_device_status.status_code);
1351
1352 if (f01_device_status.flash_prog) {
1353 dev_info(&fwu->rmi4_data->i2c_client->dev,
1354 "%s: Device is in flash prog mode 0x%02X\n",
1355 __func__, f01_device_status.status_code);
1356 retval = 0;
1357 goto exit;
1358 }
1359
Amy Malocheb494b9a2013-05-13 18:01:53 -07001360exit:
Alexandra Chind5591a62013-02-07 12:59:15 -08001361 if (fw_entry)
1362 release_firmware(fw_entry);
1363
1364 pr_notice("%s: End of reflash process\n", __func__);
Alexandra Chind5591a62013-02-07 12:59:15 -08001365 return retval;
1366}
1367
Alexandra Chin669d27c2012-12-24 15:42:30 +08001368int synaptics_fw_updater(unsigned char *fw_data)
1369{
1370 int retval;
1371
1372 if (!fwu)
1373 return -ENODEV;
1374
1375 if (!fwu->initialized)
1376 return -ENODEV;
1377
Amy Malocheb494b9a2013-05-13 18:01:53 -07001378 fwu->rmi4_data->fw_updating = true;
Amy Maloche986863d2013-06-10 15:13:57 -07001379 if (fwu->rmi4_data->suspended == true) {
Amy Malocheb494b9a2013-05-13 18:01:53 -07001380 fwu->rmi4_data->fw_updating = false;
1381 dev_err(&fwu->rmi4_data->i2c_client->dev,
1382 "Cannot start fw upgrade while device is in suspend\n");
1383 return -EBUSY;
1384 }
1385
Alexandra Chin669d27c2012-12-24 15:42:30 +08001386 fwu->ext_data_source = fw_data;
1387 fwu->config_area = UI_CONFIG_AREA;
1388
1389 retval = fwu_start_reflash();
Amy Malocheb494b9a2013-05-13 18:01:53 -07001390 fwu->rmi4_data->fw_updating = false;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001391
Amy Maloched9bf0d92013-06-19 17:19:23 -07001392 synaptics_rmi4_update_debug_info();
1393
Alexandra Chin669d27c2012-12-24 15:42:30 +08001394 return retval;
1395}
1396EXPORT_SYMBOL(synaptics_fw_updater);
1397
1398static ssize_t fwu_sysfs_show_image(struct file *data_file,
1399 struct kobject *kobj, struct bin_attribute *attributes,
1400 char *buf, loff_t pos, size_t count)
1401{
1402 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1403
1404 if (count < fwu->config_size) {
1405 dev_err(&rmi4_data->i2c_client->dev,
1406 "%s: Not enough space (%d bytes) in buffer\n",
1407 __func__, count);
1408 return -EINVAL;
1409 }
1410
1411 memcpy(buf, fwu->read_config_buf, fwu->config_size);
1412
1413 return fwu->config_size;
1414}
1415
1416static ssize_t fwu_sysfs_store_image(struct file *data_file,
1417 struct kobject *kobj, struct bin_attribute *attributes,
1418 char *buf, loff_t pos, size_t count)
1419{
1420 memcpy((void *)(&fwu->ext_data_source[fwu->data_pos]),
1421 (const void *)buf,
1422 count);
1423
1424 fwu->data_pos += count;
1425
1426 return count;
1427}
1428
Amy Malocheb494b9a2013-05-13 18:01:53 -07001429static ssize_t fwu_sysfs_fw_name_store(struct device *dev,
1430 struct device_attribute *attr, const char *buf, size_t count)
1431{
1432 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1433 char *strptr;
1434
1435 if (count >= NAME_BUFFER_SIZE) {
1436 dev_err(&rmi4_data->i2c_client->dev,
1437 "Input over %d characters long\n", NAME_BUFFER_SIZE);
1438 return -EINVAL;
1439 }
1440
1441 strptr = strnstr(buf, ".img",
1442 count);
1443 if (!strptr) {
1444 dev_err(&rmi4_data->i2c_client->dev,
1445 "Input is not valid .img file\n");
1446 return -EINVAL;
1447 }
1448
1449 strlcpy(rmi4_data->fw_image_name, buf, count);
1450 return count;
1451}
1452
1453static ssize_t fwu_sysfs_fw_name_show(struct device *dev,
1454 struct device_attribute *attr, char *buf)
1455{
1456 if (strnlen(fwu->rmi4_data->fw_image_name, NAME_BUFFER_SIZE) > 0)
1457 return snprintf(buf, PAGE_SIZE, "%s\n",
1458 fwu->rmi4_data->fw_image_name);
1459 else
1460 return snprintf(buf, PAGE_SIZE, "No firmware name given\n");
1461}
1462
Amy Maloche5e0360e2013-05-01 13:31:57 -07001463static ssize_t fwu_sysfs_force_reflash_store(struct device *dev,
1464 struct device_attribute *attr, const char *buf, size_t count)
1465{
1466 int retval;
1467 unsigned int input;
1468 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1469
1470 if (sscanf(buf, "%u", &input) != 1) {
1471 retval = -EINVAL;
1472 goto exit;
1473 }
1474
1475 if (input != 1) {
1476 retval = -EINVAL;
1477 goto exit;
1478 }
1479
1480 fwu->force_update = true;
1481 retval = synaptics_fw_updater(fwu->ext_data_source);
1482 if (retval < 0) {
1483 dev_err(&rmi4_data->i2c_client->dev,
1484 "%s: Failed to do reflash\n",
1485 __func__);
1486 goto exit;
1487 }
1488
1489 retval = count;
1490
1491exit:
1492 kfree(fwu->ext_data_source);
1493 fwu->ext_data_source = NULL;
1494 return retval;
1495}
1496
Alexandra Chin669d27c2012-12-24 15:42:30 +08001497static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
1498 struct device_attribute *attr, const char *buf, size_t count)
1499{
1500 int retval;
1501 unsigned int input;
1502 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1503
1504 if (sscanf(buf, "%u", &input) != 1) {
1505 retval = -EINVAL;
1506 goto exit;
1507 }
1508
1509 if (input != 1) {
1510 retval = -EINVAL;
1511 goto exit;
1512 }
1513
1514 retval = synaptics_fw_updater(fwu->ext_data_source);
1515 if (retval < 0) {
1516 dev_err(&rmi4_data->i2c_client->dev,
1517 "%s: Failed to do reflash\n",
1518 __func__);
1519 goto exit;
1520 }
1521
1522 retval = count;
1523
1524exit:
1525 kfree(fwu->ext_data_source);
1526 fwu->ext_data_source = NULL;
1527 return retval;
1528}
1529
1530static ssize_t fwu_sysfs_write_config_store(struct device *dev,
1531 struct device_attribute *attr, const char *buf, size_t count)
1532{
1533 int retval;
1534 unsigned int input;
1535 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1536
1537 if (sscanf(buf, "%u", &input) != 1) {
1538 retval = -EINVAL;
1539 goto exit;
1540 }
1541
1542 if (input != 1) {
1543 retval = -EINVAL;
1544 goto exit;
1545 }
1546
1547 retval = fwu_start_write_config();
1548 if (retval < 0) {
1549 dev_err(&rmi4_data->i2c_client->dev,
1550 "%s: Failed to write config\n",
1551 __func__);
1552 goto exit;
1553 }
1554
1555 retval = count;
1556
1557exit:
1558 kfree(fwu->ext_data_source);
1559 fwu->ext_data_source = NULL;
1560 return retval;
1561}
1562
1563static ssize_t fwu_sysfs_read_config_store(struct device *dev,
1564 struct device_attribute *attr, const char *buf, size_t count)
1565{
1566 int retval;
1567 unsigned int input;
1568 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1569
1570 if (sscanf(buf, "%u", &input) != 1)
1571 return -EINVAL;
1572
1573 if (input != 1)
1574 return -EINVAL;
1575
1576 retval = fwu_do_read_config();
1577 if (retval < 0) {
1578 dev_err(&rmi4_data->i2c_client->dev,
1579 "%s: Failed to read config\n",
1580 __func__);
1581 return retval;
1582 }
1583
1584 return count;
1585}
1586
1587static ssize_t fwu_sysfs_config_area_store(struct device *dev,
1588 struct device_attribute *attr, const char *buf, size_t count)
1589{
1590 int retval;
1591 unsigned long config_area;
1592
Shantanu Jain41f0d472013-01-04 12:14:37 +05301593 retval = kstrtoul(buf, 10, &config_area);
Alexandra Chin669d27c2012-12-24 15:42:30 +08001594 if (retval)
1595 return retval;
1596
1597 fwu->config_area = config_area;
1598
1599 return count;
1600}
1601
1602static ssize_t fwu_sysfs_image_size_store(struct device *dev,
1603 struct device_attribute *attr, const char *buf, size_t count)
1604{
1605 int retval;
1606 unsigned long size;
1607 struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
1608
Shantanu Jain41f0d472013-01-04 12:14:37 +05301609 retval = kstrtoul(buf, 10, &size);
Alexandra Chin669d27c2012-12-24 15:42:30 +08001610 if (retval)
1611 return retval;
1612
1613 fwu->image_size = size;
1614 fwu->data_pos = 0;
1615
1616 kfree(fwu->ext_data_source);
1617 fwu->ext_data_source = kzalloc(fwu->image_size, GFP_KERNEL);
1618 if (!fwu->ext_data_source) {
1619 dev_err(&rmi4_data->i2c_client->dev,
1620 "%s: Failed to alloc mem for image data\n",
1621 __func__);
1622 return -ENOMEM;
1623 }
1624
1625 return count;
1626}
1627
1628static ssize_t fwu_sysfs_block_size_show(struct device *dev,
1629 struct device_attribute *attr, char *buf)
1630{
1631 return snprintf(buf, PAGE_SIZE, "%u\n", fwu->block_size);
1632}
1633
1634static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev,
1635 struct device_attribute *attr, char *buf)
1636{
1637 return snprintf(buf, PAGE_SIZE, "%u\n", fwu->fw_block_count);
1638}
1639
1640static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev,
1641 struct device_attribute *attr, char *buf)
1642{
1643 return snprintf(buf, PAGE_SIZE, "%u\n", fwu->config_block_count);
1644}
1645
1646static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev,
1647 struct device_attribute *attr, char *buf)
1648{
1649 return snprintf(buf, PAGE_SIZE, "%u\n", fwu->perm_config_block_count);
1650}
1651
1652static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev,
1653 struct device_attribute *attr, char *buf)
1654{
1655 return snprintf(buf, PAGE_SIZE, "%u\n", fwu->bl_config_block_count);
1656}
1657
1658static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev,
1659 struct device_attribute *attr, char *buf)
1660{
1661 return snprintf(buf, PAGE_SIZE, "%u\n", fwu->disp_config_block_count);
1662}
1663
Amy Maloched25bd8c2013-01-25 12:34:31 -08001664static ssize_t fwu_sysfs_config_id_show(struct device *dev,
1665 struct device_attribute *attr, char *buf)
1666{
Amy Maloche581f7402013-02-19 16:29:37 -08001667 unsigned char config_id[4];
Amy Maloched25bd8c2013-01-25 12:34:31 -08001668 /* device config id */
1669 fwu->fn_ptr->read(fwu->rmi4_data,
1670 fwu->f34_fd.ctrl_base_addr,
1671 config_id,
1672 sizeof(config_id));
1673
1674 return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n",
1675 config_id[0], config_id[1], config_id[2], config_id[3]);
1676}
1677
Amy Maloche2c4c48c2013-05-01 20:06:23 -07001678static ssize_t fwu_sysfs_package_id_show(struct device *dev,
1679 struct device_attribute *attr, char *buf)
1680{
1681 unsigned char pkg_id[4];
1682 /* read device package id */
1683 fwu->fn_ptr->read(fwu->rmi4_data,
1684 fwu->f01_fd.query_base_addr + 17,
1685 pkg_id,
1686 sizeof(pkg_id));
1687
1688 return snprintf(buf, PAGE_SIZE, "%d rev %d\n",
1689 (pkg_id[1] << 8) | pkg_id[0],
1690 (pkg_id[3] << 8) | pkg_id[2]);
1691}
1692
Amy Maloched9bf0d92013-06-19 17:19:23 -07001693static int synaptics_rmi4_debug_dump_info(struct seq_file *m, void *v)
1694{
1695 seq_printf(m, "%s\n", fwu->ts_info);
1696
1697 return 0;
1698}
1699
1700static int debugfs_dump_info_open(struct inode *inode, struct file *file)
1701{
1702 return single_open(file, synaptics_rmi4_debug_dump_info,
1703 inode->i_private);
1704}
1705
1706static const struct file_operations debug_dump_info_fops = {
1707 .owner = THIS_MODULE,
1708 .open = debugfs_dump_info_open,
1709 .read = seq_read,
1710 .release = single_release,
1711};
1712
Alexandra Chin669d27c2012-12-24 15:42:30 +08001713static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data,
1714 unsigned char intr_mask)
1715{
1716 if (fwu->intr_mask & intr_mask)
1717 fwu_read_f34_flash_status();
1718
1719 return;
1720}
1721
Amy Malocheb494b9a2013-05-13 18:01:53 -07001722static struct bin_attribute dev_attr_data = {
1723 .attr = {
1724 .name = "data",
1725 .mode = (S_IRUGO | S_IWUGO),
1726 },
1727 .size = 0,
1728 .read = fwu_sysfs_show_image,
1729 .write = fwu_sysfs_store_image,
1730};
1731
1732static struct device_attribute attrs[] = {
1733 __ATTR(fw_name, S_IWUGO | S_IRUGO,
1734 fwu_sysfs_fw_name_show,
1735 fwu_sysfs_fw_name_store),
1736 __ATTR(force_update_fw, S_IWUGO,
1737 synaptics_rmi4_show_error,
1738 fwu_sysfs_force_reflash_store),
1739 __ATTR(update_fw, S_IWUGO,
1740 synaptics_rmi4_show_error,
1741 fwu_sysfs_do_reflash_store),
1742 __ATTR(writeconfig, S_IWUGO,
1743 synaptics_rmi4_show_error,
1744 fwu_sysfs_write_config_store),
1745 __ATTR(readconfig, S_IWUGO,
1746 synaptics_rmi4_show_error,
1747 fwu_sysfs_read_config_store),
1748 __ATTR(configarea, S_IWUGO,
1749 synaptics_rmi4_show_error,
1750 fwu_sysfs_config_area_store),
1751 __ATTR(imagesize, S_IWUGO,
1752 synaptics_rmi4_show_error,
1753 fwu_sysfs_image_size_store),
1754 __ATTR(blocksize, S_IRUGO,
1755 fwu_sysfs_block_size_show,
1756 synaptics_rmi4_store_error),
1757 __ATTR(fwblockcount, S_IRUGO,
1758 fwu_sysfs_firmware_block_count_show,
1759 synaptics_rmi4_store_error),
1760 __ATTR(configblockcount, S_IRUGO,
1761 fwu_sysfs_configuration_block_count_show,
1762 synaptics_rmi4_store_error),
1763 __ATTR(permconfigblockcount, S_IRUGO,
1764 fwu_sysfs_perm_config_block_count_show,
1765 synaptics_rmi4_store_error),
1766 __ATTR(blconfigblockcount, S_IRUGO,
1767 fwu_sysfs_bl_config_block_count_show,
1768 synaptics_rmi4_store_error),
1769 __ATTR(dispconfigblockcount, S_IRUGO,
1770 fwu_sysfs_disp_config_block_count_show,
1771 synaptics_rmi4_store_error),
1772 __ATTR(config_id, S_IRUGO,
1773 fwu_sysfs_config_id_show,
1774 synaptics_rmi4_store_error),
Amy Maloche2c4c48c2013-05-01 20:06:23 -07001775 __ATTR(package_id, S_IRUGO,
1776 fwu_sysfs_package_id_show,
1777 synaptics_rmi4_store_error),
Amy Malocheb494b9a2013-05-13 18:01:53 -07001778};
1779
1780
Alexandra Chind5591a62013-02-07 12:59:15 -08001781static void synaptics_rmi4_fwu_work(struct work_struct *work)
1782{
1783 fwu_start_reflash();
1784}
1785
Alexandra Chin669d27c2012-12-24 15:42:30 +08001786static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
1787{
1788 int retval;
1789 unsigned char attr_count;
1790 struct pdt_properties pdt_props;
Amy Maloched9bf0d92013-06-19 17:19:23 -07001791 struct dentry *temp;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001792
1793 fwu = kzalloc(sizeof(*fwu), GFP_KERNEL);
1794 if (!fwu) {
1795 dev_err(&rmi4_data->i2c_client->dev,
1796 "%s: Failed to alloc mem for fwu\n",
1797 __func__);
1798 goto exit;
1799 }
1800
1801 fwu->fn_ptr = kzalloc(sizeof(*(fwu->fn_ptr)), GFP_KERNEL);
1802 if (!fwu->fn_ptr) {
1803 dev_err(&rmi4_data->i2c_client->dev,
1804 "%s: Failed to alloc mem for fn_ptr\n",
1805 __func__);
1806 retval = -ENOMEM;
1807 goto exit_free_fwu;
1808 }
1809
1810 fwu->rmi4_data = rmi4_data;
1811 fwu->fn_ptr->read = rmi4_data->i2c_read;
1812 fwu->fn_ptr->write = rmi4_data->i2c_write;
1813 fwu->fn_ptr->enable = rmi4_data->irq_enable;
1814
1815 retval = fwu->fn_ptr->read(rmi4_data,
1816 PDT_PROPS,
1817 pdt_props.data,
1818 sizeof(pdt_props.data));
1819 if (retval < 0) {
1820 dev_dbg(&rmi4_data->i2c_client->dev,
1821 "%s: Failed to read PDT properties, assuming 0x00\n",
1822 __func__);
1823 } else if (pdt_props.has_bsr) {
1824 dev_err(&rmi4_data->i2c_client->dev,
1825 "%s: Reflash for LTS not currently supported\n",
1826 __func__);
1827 goto exit_free_mem;
1828 }
1829
1830 retval = fwu_scan_pdt();
1831 if (retval < 0)
1832 goto exit_free_mem;
1833
1834 fwu->productinfo1 = rmi4_data->rmi4_mod_info.product_info[0];
1835 fwu->productinfo2 = rmi4_data->rmi4_mod_info.product_info[1];
1836
1837 memcpy(fwu->product_id, rmi4_data->rmi4_mod_info.product_id_string,
1838 SYNAPTICS_RMI4_PRODUCT_ID_SIZE);
1839 fwu->product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE] = 0;
1840
1841 dev_dbg(&rmi4_data->i2c_client->dev,
1842 "%s: F01 product info: 0x%04x 0x%04x\n",
1843 __func__, fwu->productinfo1, fwu->productinfo2);
1844 dev_dbg(&rmi4_data->i2c_client->dev,
1845 "%s: F01 product ID: %s\n",
1846 __func__, fwu->product_id);
1847
1848 retval = fwu_read_f34_queries();
1849 if (retval < 0)
1850 goto exit_free_mem;
1851
1852 fwu->initialized = true;
Alexandra Chind5591a62013-02-07 12:59:15 -08001853 fwu->force_update = FORCE_UPDATE;
Alexandra Chin669d27c2012-12-24 15:42:30 +08001854
Amy Maloche4d54ac42013-06-11 12:09:44 -07001855 retval = sysfs_create_bin_file(&rmi4_data->i2c_client->dev.kobj,
Alexandra Chin669d27c2012-12-24 15:42:30 +08001856 &dev_attr_data);
1857 if (retval < 0) {
1858 dev_err(&rmi4_data->i2c_client->dev,
1859 "%s: Failed to create sysfs bin file\n",
1860 __func__);
1861 goto exit_free_mem;
1862 }
1863
1864 for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
Amy Maloche4d54ac42013-06-11 12:09:44 -07001865 retval = sysfs_create_file(&rmi4_data->i2c_client->dev.kobj,
Alexandra Chin669d27c2012-12-24 15:42:30 +08001866 &attrs[attr_count].attr);
1867 if (retval < 0) {
1868 dev_err(&rmi4_data->i2c_client->dev,
1869 "%s: Failed to create sysfs attributes\n",
1870 __func__);
1871 retval = -ENODEV;
1872 goto exit_remove_attrs;
1873 }
1874 }
1875
Amy Maloched9bf0d92013-06-19 17:19:23 -07001876 temp = debugfs_create_file("dump_info", S_IRUSR | S_IWUSR,
1877 fwu->rmi4_data->dir, fwu->rmi4_data,
1878 &debug_dump_info_fops);
1879 if (temp == NULL || IS_ERR(temp)) {
1880 dev_err(&rmi4_data->i2c_client->dev,
1881 "%s: Failed to create debugfs dump info file\n",
1882 __func__);
1883 retval = PTR_ERR(temp);
1884 goto exit_remove_attrs;
1885 }
1886
1887 fwu->ts_info = kzalloc(RMI4_INFO_MAX_LEN, GFP_KERNEL);
1888 if (!fwu->ts_info) {
1889 dev_err(&rmi4_data->i2c_client->dev, "Not enough memory\n");
1890 goto exit_free_ts_info;
1891 }
1892
1893 synaptics_rmi4_update_debug_info();
1894
Alexandra Chind5591a62013-02-07 12:59:15 -08001895#ifdef INSIDE_FIRMWARE_UPDATE
1896 fwu->fwu_workqueue = create_singlethread_workqueue("fwu_workqueue");
1897 INIT_DELAYED_WORK(&fwu->fwu_work, synaptics_rmi4_fwu_work);
1898 queue_delayed_work(fwu->fwu_workqueue,
1899 &fwu->fwu_work,
1900 msecs_to_jiffies(1000));
1901#endif
Alexandra Chinc556cf02013-03-19 17:46:05 -07001902
1903 init_completion(&remove_complete);
1904
Alexandra Chin669d27c2012-12-24 15:42:30 +08001905 return 0;
Amy Maloched9bf0d92013-06-19 17:19:23 -07001906exit_free_ts_info:
1907 debugfs_remove(temp);
Alexandra Chin669d27c2012-12-24 15:42:30 +08001908exit_remove_attrs:
1909for (attr_count--; attr_count >= 0; attr_count--) {
1910 sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
1911 &attrs[attr_count].attr);
1912}
1913
1914sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
1915
1916exit_free_mem:
1917 kfree(fwu->fn_ptr);
1918
1919exit_free_fwu:
1920 kfree(fwu);
1921
1922exit:
1923 return 0;
1924}
1925
1926static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data)
1927{
1928 unsigned char attr_count;
1929
1930 sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
1931
1932 for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
1933 sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
1934 &attrs[attr_count].attr);
1935 }
1936
1937 kfree(fwu->fn_ptr);
1938 kfree(fwu);
1939
1940 complete(&remove_complete);
1941
1942 return;
1943}
1944
1945static int __init rmi4_fw_update_module_init(void)
1946{
1947 synaptics_rmi4_new_function(RMI_FW_UPDATER, true,
1948 synaptics_rmi4_fwu_init,
1949 synaptics_rmi4_fwu_remove,
1950 synaptics_rmi4_fwu_attn);
1951 return 0;
1952}
1953
1954static void __exit rmi4_fw_update_module_exit(void)
1955{
Alexandra Chin669d27c2012-12-24 15:42:30 +08001956 synaptics_rmi4_new_function(RMI_FW_UPDATER, false,
1957 synaptics_rmi4_fwu_init,
1958 synaptics_rmi4_fwu_remove,
1959 synaptics_rmi4_fwu_attn);
1960 wait_for_completion(&remove_complete);
1961 return;
1962}
1963
1964module_init(rmi4_fw_update_module_init);
1965module_exit(rmi4_fw_update_module_exit);
1966
1967MODULE_AUTHOR("Synaptics, Inc.");
1968MODULE_DESCRIPTION("RMI4 FW Update Module");
Alexandra Chinbd1dac22013-02-22 12:33:19 -08001969MODULE_LICENSE("GPL v2");