123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452 |
- /* Synaptics Register Mapped Interface (RMI4) I2C Physical Layer Driver.
- * Copyright (c) 2007-2012, Synaptics Incorporated
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <asm/unaligned.h>
- #include <mach/cpufreq.h>
- #include <linux/slab.h>
- #include <linux/i2c.h>
- #include <linux/interrupt.h>
- #include <linux/delay.h>
- #include <linux/input.h>
- #include <linux/firmware.h>
- #include "synaptics_i2c_rmi.h"
- #define F01_DEVICE_STATUS 0X0004
- #define CHECKSUM_OFFSET 0x00
- #define BOOTLOADER_VERSION_OFFSET 0x07
- #define IMAGE_SIZE_OFFSET 0x08
- #define CONFIG_SIZE_OFFSET 0x0C
- #define PRODUCT_ID_OFFSET 0x10
- #define PRODUCT_INFO_OFFSET 0x1E
- #define FW_IMAGE_OFFSET 0x100
- #define PRODUCT_ID_SIZE 10
- #define BOOTLOADER_ID_OFFSET 0
- #define FLASH_PROPERTIES_OFFSET 1
- #define BLOCK_SIZE_OFFSET 2
- #define BLOCK_COUNT_OFFSET 3
- #define REG_MAP (1 << 0)
- #define UNLOCKED (1 << 1)
- #define HAS_CONFIG_ID (1 << 2)
- #define HAS_PERM_CONFIG (1 << 3)
- #define HAS_BL_CONFIG (1 << 4)
- #define HAS_DISP_CONFIG (1 << 5)
- #define HAS_CTRL1 (1 << 6)
- #define BLOCK_NUMBER_OFFSET 0
- #define BLOCK_DATA_OFFSET 1
- #define FLASH_COMMAND_OFFSET 2
- #define FLASH_STATUS_OFFSET 3
- #define UI_CONFIG_AREA 0x00
- #define PERM_CONFIG_AREA 0x01
- #define BL_CONFIG_AREA 0x02
- #define DISP_CONFIG_AREA 0x03
- #define CMD_WRITE_FW_BLOCK 0x2
- #define CMD_ERASE_ALL 0x3
- #define CMD_READ_CONFIG_BLOCK 0x5
- #define CMD_WRITE_CONFIG_BLOCK 0x6
- #define CMD_ERASE_CONFIG 0x7
- #define CMD_ERASE_BL_CONFIG 0x9
- #define CMD_ERASE_DISP_CONFIG 0xa
- #define CMD_ENABLE_FLASH_PROG 0xf
- #define SLEEP_MODE_NORMAL (0x00)
- #define SLEEP_MODE_SENSOR_SLEEP (0x01)
- #define SLEEP_MODE_RESERVED0 (0x02)
- #define SLEEP_MODE_RESERVED1 (0x03)
- #define ENABLE_WAIT_MS (1 * 1000)
- #define WRITE_WAIT_MS (3 * 1000)
- #define ERASE_WAIT_MS (5 * 1000)
- #define MIN_SLEEP_TIME_US 50
- #define MAX_SLEEP_TIME_US 100
- static ssize_t fwu_sysfs_show_image(struct file *data_file,
- struct kobject *kobj, struct bin_attribute *attributes,
- char *buf, loff_t pos, size_t count);
- static ssize_t fwu_sysfs_store_image(struct file *data_file,
- struct kobject *kobj, struct bin_attribute *attributes,
- char *buf, loff_t pos, size_t count);
- static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
- static ssize_t fwu_sysfs_write_config_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
- static ssize_t fwu_sysfs_read_config_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
- static ssize_t fwu_sysfs_config_area_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
- static ssize_t fwu_sysfs_image_size_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
- static ssize_t fwu_sysfs_block_size_show(struct device *dev,
- struct device_attribute *attr, char *buf);
- static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf);
- static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf);
- static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf);
- static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf);
- static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf);
- struct image_header {
- unsigned int checksum;
- unsigned int image_size;
- unsigned int config_size;
- unsigned char options;
- unsigned char bootloader_version;
- unsigned char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
- unsigned char product_info[SYNAPTICS_RMI4_PRODUCT_INFO_SIZE];
- };
- struct pdt_properties {
- union {
- struct {
- unsigned char reserved_1:6;
- unsigned char has_bsr:1;
- unsigned char reserved_2:1;
- } __packed;
- unsigned char data[1];
- };
- };
- struct f01_device_status {
- union {
- struct {
- unsigned char status_code:4;
- unsigned char reserved:2;
- unsigned char flash_prog:1;
- unsigned char unconfigured:1;
- } __packed;
- unsigned char data[1];
- };
- };
- struct f01_device_control {
- union {
- struct {
- unsigned char sleep_mode:2;
- unsigned char nosleep:1;
- unsigned char reserved:2;
- unsigned char charger_connected:1;
- unsigned char report_rate:1;
- unsigned char configured:1;
- } __packed;
- unsigned char data[1];
- };
- };
- struct f34_flash_status {
- union {
- struct {
- unsigned char status:6;
- unsigned char reserved:1;
- unsigned char program_enabled:1;
- } __packed;
- unsigned char data[1];
- };
- };
- struct synaptics_rmi4_fwu_handle {
- bool initialized;
- bool has_perm_config;
- bool has_bl_config;
- bool has_disp_config;
- unsigned int image_size;
- unsigned int data_pos;
- unsigned char *ext_data_source;
- unsigned char *read_config_buf;
- unsigned char intr_mask;
- unsigned char command;
- unsigned char bootloader_id[2];
- unsigned char flash_properties;
- unsigned char productinfo1;
- unsigned char productinfo2;
- unsigned short block_size;
- unsigned short fw_block_count;
- unsigned short config_block_count;
- unsigned short perm_config_block_count;
- unsigned short bl_config_block_count;
- unsigned short disp_config_block_count;
- unsigned short config_size;
- unsigned short config_area;
- char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
- const unsigned char *firmware_data;
- const unsigned char *config_data;
- struct f34_flash_status flash_status;
- struct synaptics_rmi4_fn_desc f01_fd;
- struct synaptics_rmi4_fn_desc f34_fd;
- struct synaptics_rmi4_exp_fn_ptr *fn_ptr;
- struct synaptics_rmi4_data *rmi4_data;
- };
- static struct bin_attribute dev_attr_data = {
- .attr = {
- .name = "data",
- .mode = (S_IRUGO | S_IWUSR | S_IWGRP),
- },
- .size = 0,
- .read = fwu_sysfs_show_image,
- .write = fwu_sysfs_store_image,
- };
- static struct device_attribute attrs[] = {
- __ATTR(doreflash, S_IWUSR | S_IWGRP,
- synaptics_rmi4_show_error,
- fwu_sysfs_do_reflash_store),
- __ATTR(writeconfig, S_IWUSR | S_IWGRP,
- synaptics_rmi4_show_error,
- fwu_sysfs_write_config_store),
- __ATTR(readconfig, S_IWUSR | S_IWGRP,
- synaptics_rmi4_show_error,
- fwu_sysfs_read_config_store),
- __ATTR(configarea, S_IWUSR | S_IWGRP,
- synaptics_rmi4_show_error,
- fwu_sysfs_config_area_store),
- __ATTR(imagesize, S_IWUSR | S_IWGRP,
- synaptics_rmi4_show_error,
- fwu_sysfs_image_size_store),
- __ATTR(blocksize, S_IRUGO,
- fwu_sysfs_block_size_show,
- synaptics_rmi4_store_error),
- __ATTR(fwblockcount, S_IRUGO,
- fwu_sysfs_firmware_block_count_show,
- synaptics_rmi4_store_error),
- __ATTR(configblockcount, S_IRUGO,
- fwu_sysfs_configuration_block_count_show,
- synaptics_rmi4_store_error),
- __ATTR(permconfigblockcount, S_IRUGO,
- fwu_sysfs_perm_config_block_count_show,
- synaptics_rmi4_store_error),
- __ATTR(blconfigblockcount, S_IRUGO,
- fwu_sysfs_bl_config_block_count_show,
- synaptics_rmi4_store_error),
- __ATTR(dispconfigblockcount, S_IRUGO,
- fwu_sysfs_disp_config_block_count_show,
- synaptics_rmi4_store_error),
- };
- static struct synaptics_rmi4_fwu_handle *fwu;
- static unsigned int extract_uint(const unsigned char *ptr)
- {
- return (unsigned int)ptr[0] +
- (unsigned int)ptr[1] * 0x100 +
- (unsigned int)ptr[2] * 0x10000 +
- (unsigned int)ptr[3] * 0x1000000;
- }
- static void parse_header(struct image_header *header,
- const unsigned char *fw_image)
- {
- header->checksum = extract_uint(&fw_image[CHECKSUM_OFFSET]);
- header->bootloader_version = fw_image[BOOTLOADER_VERSION_OFFSET];
- header->image_size = extract_uint(&fw_image[IMAGE_SIZE_OFFSET]);
- header->config_size = extract_uint(&fw_image[CONFIG_SIZE_OFFSET]);
- memcpy(header->product_id, &fw_image[PRODUCT_ID_OFFSET],
- SYNAPTICS_RMI4_PRODUCT_ID_SIZE);
- header->product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE] = 0;
- memcpy(header->product_info, &fw_image[PRODUCT_INFO_OFFSET],
- SYNAPTICS_RMI4_PRODUCT_INFO_SIZE);
- return;
- }
- static int fwu_read_f01_device_status(struct f01_device_status *status)
- {
- int retval;
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f01_fd.data_base_addr,
- status->data,
- sizeof(status->data));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to read F01 device status\n",
- __func__);
- return retval;
- }
- return 0;
- }
- static int fwu_read_f34_queries(void)
- {
- int retval;
- unsigned char count;
- unsigned char buf[10];
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.query_base_addr + BOOTLOADER_ID_OFFSET,
- fwu->bootloader_id,
- sizeof(fwu->bootloader_id));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to read bootloader ID\n",
- __func__);
- return retval;
- }
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.query_base_addr + FLASH_PROPERTIES_OFFSET,
- &fwu->flash_properties,
- sizeof(fwu->flash_properties));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to read flash properties\n",
- __func__);
- return retval;
- }
- count = 4;
- if (fwu->flash_properties & HAS_PERM_CONFIG) {
- fwu->has_perm_config = 1;
- count += 2;
- }
- if (fwu->flash_properties & HAS_BL_CONFIG) {
- fwu->has_bl_config = 1;
- count += 2;
- }
- if (fwu->flash_properties & HAS_DISP_CONFIG) {
- fwu->has_disp_config = 1;
- count += 2;
- }
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.query_base_addr + BLOCK_SIZE_OFFSET,
- buf,
- 2);
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to read block size info\n",
- __func__);
- return retval;
- }
- batohs(&fwu->block_size, &(buf[0]));
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.query_base_addr + BLOCK_COUNT_OFFSET,
- buf,
- count);
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to read block count info\n",
- __func__);
- return retval;
- }
- batohs(&fwu->fw_block_count, &(buf[0]));
- batohs(&fwu->config_block_count, &(buf[2]));
- count = 4;
- if (fwu->has_perm_config) {
- batohs(&fwu->perm_config_block_count, &(buf[count]));
- count += 2;
- }
- if (fwu->has_bl_config) {
- batohs(&fwu->bl_config_block_count, &(buf[count]));
- count += 2;
- }
- if (fwu->has_disp_config)
- batohs(&fwu->disp_config_block_count, &(buf[count]));
- return 0;
- }
- static int fwu_read_f34_flash_status(void)
- {
- int retval;
- unsigned char status;
- unsigned char command;
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.data_base_addr + FLASH_STATUS_OFFSET,
- &status,
- sizeof(status));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to read flash status\n",
- __func__);
- return retval;
- }
- /* Program enabled bit not available - force bit to be set */
- fwu->flash_status.program_enabled = 1;
- fwu->flash_status.status = status & MASK_3BIT;
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.data_base_addr + FLASH_COMMAND_OFFSET,
- &command,
- sizeof(command));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to read flash command\n",
- __func__);
- return retval;
- }
- fwu->command = command & MASK_4BIT;
- return 0;
- }
- static int fwu_write_f34_command(unsigned char cmd)
- {
- int retval;
- unsigned char command = cmd;
- retval = fwu->fn_ptr->write(fwu->rmi4_data,
- fwu->f34_fd.data_base_addr + FLASH_COMMAND_OFFSET,
- &command,
- sizeof(command));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to write command 0x%02x\n",
- __func__, command);
- return retval;
- }
- fwu->command = cmd;
- return 0;
- }
- static int fwu_wait_for_idle(int timeout_ms)
- {
- int count = 0;
- int timeout_count = ((timeout_ms * 1000) / MAX_SLEEP_TIME_US) + 1;
- do {
- usleep_range(MIN_SLEEP_TIME_US, MAX_SLEEP_TIME_US);
- count++;
- if (count == timeout_count)
- fwu_read_f34_flash_status();
- if ((fwu->command == 0x00) &&
- (fwu->flash_status.status == 0x00))
- return 0;
- } while (count < timeout_count);
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Timed out waiting for idle status\n",
- __func__);
- return -ETIMEDOUT;
- }
- static int fwu_scan_pdt(void)
- {
- int retval;
- unsigned char ii;
- unsigned char intr_count = 0;
- unsigned char intr_off;
- unsigned char intr_src;
- unsigned short addr;
- bool f01found = false;
- bool f34found = false;
- struct synaptics_rmi4_fn_desc rmi_fd;
- for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) {
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- addr,
- (unsigned char *)&rmi_fd,
- sizeof(rmi_fd));
- if (retval < 0)
- return retval;
- if (rmi_fd.fn_number) {
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Found F%02x\n",
- __func__, rmi_fd.fn_number);
- switch (rmi_fd.fn_number) {
- case SYNAPTICS_RMI4_F01:
- f01found = true;
- fwu->f01_fd.query_base_addr =
- rmi_fd.query_base_addr;
- fwu->f01_fd.ctrl_base_addr =
- rmi_fd.ctrl_base_addr;
- fwu->f01_fd.data_base_addr =
- rmi_fd.data_base_addr;
- fwu->f01_fd.cmd_base_addr =
- rmi_fd.cmd_base_addr;
- break;
- case SYNAPTICS_RMI4_F34:
- f34found = true;
- fwu->f34_fd.query_base_addr =
- rmi_fd.query_base_addr;
- fwu->f34_fd.ctrl_base_addr =
- rmi_fd.ctrl_base_addr;
- fwu->f34_fd.data_base_addr =
- rmi_fd.data_base_addr;
- fwu->intr_mask = 0;
- intr_src = rmi_fd.intr_src_count;
- intr_off = intr_count % 8;
- for (ii = intr_off;
- ii < ((intr_src & MASK_3BIT) +
- intr_off);
- ii++) {
- fwu->intr_mask |= 1 << ii;
- }
- break;
- }
- } else {
- break;
- }
- intr_count += (rmi_fd.intr_src_count & MASK_3BIT);
- }
- if (!f01found || !f34found) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to find both F01 and F34\n",
- __func__);
- return -EINVAL;
- }
- return 0;
- }
- static int fwu_write_blocks(unsigned char *block_ptr, unsigned short block_cnt,
- unsigned char command)
- {
- int retval;
- unsigned char block_offset[] = {0, 0};
- unsigned short block_num;
- block_offset[1] |= (fwu->config_area << 5);
- retval = fwu->fn_ptr->write(fwu->rmi4_data,
- fwu->f34_fd.data_base_addr + BLOCK_NUMBER_OFFSET,
- block_offset,
- sizeof(block_offset));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to write to block number registers\n",
- __func__);
- return retval;
- }
- for (block_num = 0; block_num < block_cnt; block_num++) {
- retval = fwu->fn_ptr->write(fwu->rmi4_data,
- fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET,
- block_ptr,
- fwu->block_size);
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to write block data (block %d)\n",
- __func__, block_num);
- return retval;
- }
- retval = fwu_write_f34_command(command);
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to write command for block %d\n",
- __func__, block_num);
- return retval;
- }
- retval = fwu_wait_for_idle(WRITE_WAIT_MS);
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to wait for idle status (block %d)\n",
- __func__, block_num);
- return retval;
- }
- block_ptr += fwu->block_size;
- }
- return 0;
- }
- static int fwu_write_firmware(void)
- {
- return fwu_write_blocks((unsigned char *)fwu->firmware_data,
- fwu->fw_block_count, CMD_WRITE_FW_BLOCK);
- }
- static int fwu_write_configuration(void)
- {
- return fwu_write_blocks((unsigned char *)fwu->config_data,
- fwu->config_block_count, CMD_WRITE_CONFIG_BLOCK);
- }
- static int fwu_write_bootloader_id(void)
- {
- int retval;
- retval = fwu->fn_ptr->write(fwu->rmi4_data,
- fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET,
- fwu->bootloader_id,
- sizeof(fwu->bootloader_id));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to write bootloader ID\n",
- __func__);
- return retval;
- }
- return 0;
- }
- static int fwu_enter_flash_prog(void)
- {
- int retval;
- struct f01_device_status f01_device_status;
- struct f01_device_control f01_device_control;
- retval = fwu_write_bootloader_id();
- if (retval < 0)
- return retval;
- retval = fwu_write_f34_command(CMD_ENABLE_FLASH_PROG);
- if (retval < 0)
- return retval;
- retval = fwu_wait_for_idle(ENABLE_WAIT_MS);
- if (retval < 0)
- return retval;
- if (!fwu->flash_status.program_enabled) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Program enabled bit not set\n",
- __func__);
- return -EINVAL;
- }
- retval = fwu_scan_pdt();
- if (retval < 0)
- return retval;
- retval = fwu_read_f01_device_status(&f01_device_status);
- if (retval < 0)
- return retval;
- if (!f01_device_status.flash_prog) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Not in flash prog mode\n",
- __func__);
- return -EINVAL;
- }
- retval = fwu_read_f34_queries();
- if (retval < 0)
- return retval;
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f01_fd.ctrl_base_addr,
- f01_device_control.data,
- sizeof(f01_device_control.data));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to read F01 device control\n",
- __func__);
- return retval;
- }
- f01_device_control.nosleep = true;
- f01_device_control.sleep_mode = SLEEP_MODE_NORMAL;
- retval = fwu->fn_ptr->write(fwu->rmi4_data,
- fwu->f01_fd.ctrl_base_addr,
- f01_device_control.data,
- sizeof(f01_device_control.data));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to write F01 device control\n",
- __func__);
- return retval;
- }
- return retval;
- }
- static int fwu_do_reflash(void)
- {
- int retval;
- #ifdef CONFIG_MACH_JS01LTEDCM
- retval = set_freq_limit(DVFS_TOUCH_ID,MIN_TOUCH_LIMIT);
- if (retval < 0)
- return retval;
- #endif
- retval = fwu_enter_flash_prog();
- if (retval < 0)
- return retval;
- dev_info(&fwu->rmi4_data->i2c_client->dev,
- "%s: Entered flash prog mode\n",
- __func__);
- retval = fwu_write_bootloader_id();
- if (retval < 0)
- return retval;
- dev_info(&fwu->rmi4_data->i2c_client->dev,
- "%s: Bootloader ID written\n",
- __func__);
- retval = fwu_write_f34_command(CMD_ERASE_ALL);
- if (retval < 0)
- return retval;
- dev_info(&fwu->rmi4_data->i2c_client->dev,
- "%s: Erase all command written\n",
- __func__);
- retval = fwu_wait_for_idle(ERASE_WAIT_MS);
- if (retval < 0)
- return retval;
- dev_info(&fwu->rmi4_data->i2c_client->dev,
- "%s: Idle status detected\n",
- __func__);
- if (fwu->firmware_data) {
- retval = fwu_write_firmware();
- if (retval < 0)
- return retval;
- dev_info(&fwu->rmi4_data->i2c_client->dev, "%s: Firmware programmed\n",
- __func__);
- }
- if (fwu->config_data) {
- retval = fwu_write_configuration();
- if (retval < 0)
- return retval;
- dev_info(&fwu->rmi4_data->i2c_client->dev, "%s: Configuration programmed\n",
- __func__);
- }
- return retval;
- }
- static int fwu_start_reflash(void)
- {
- int retval = 0, retry = 3;
- #ifdef CONFIG_MACH_JS01LTEDCM
- int ret = 0;
- #endif
- unsigned char device_status;
- struct image_header header;
- const unsigned char *fw_image;
- if (fwu->rmi4_data->sensor_sleep || fwu->rmi4_data->touch_stopped) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Sensor sleeping or stopped\n",
- __func__);
- return -ENODEV;
- }
- fwu->rmi4_data->stay_awake = true;
- if (!fwu->ext_data_source) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Firmware data is NULL\n", __func__);
- return -ENODEV;
- }
- fw_image = fwu->ext_data_source;
- parse_header(&header, fw_image);
- if (header.image_size)
- fwu->firmware_data = fw_image + FW_IMAGE_OFFSET;
- if (header.config_size) {
- fwu->config_data = fw_image + FW_IMAGE_OFFSET +
- header.image_size;
- }
- while (retry--) {
- mutex_lock(&(fwu->rmi4_data->rmi4_reflash_mutex));
- fwu->rmi4_data->doing_reflash = true;
- retval = fwu_do_reflash();
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to do reflash\n",
- __func__);
- }
- fwu->rmi4_data->reset_device(fwu->rmi4_data);
- fwu->rmi4_data->doing_reflash = false;
- mutex_unlock(&(fwu->rmi4_data->rmi4_reflash_mutex));
- fwu->fn_ptr->read(fwu->rmi4_data,
- F01_DEVICE_STATUS,
- &device_status,
- sizeof(device_status));
- if (!(device_status & (1 << 6)))
- break;
- else
- dev_info(&fwu->rmi4_data->i2c_client->dev,
- "%s: flash prog bit = %x, retry = %d\n",
- __func__, device_status & (1 << 6), retry);
- }
- #ifdef CONFIG_MACH_JS01LTEDCM
- ret = set_freq_limit(DVFS_TOUCH_ID, -1);
- if (ret < 0)
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: in fw update, failed booster stop.\n",
- __func__);
- #endif
- dev_dbg(&fwu->rmi4_data->i2c_client->dev, "%s: End of reflash process\n",
- __func__);
- fwu->rmi4_data->stay_awake = false;
- return retval;
- }
- static int fwu_do_write_config(void)
- {
- int retval;
- retval = fwu_enter_flash_prog();
- if (retval < 0)
- return retval;
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Entered flash prog mode\n",
- __func__);
- if (fwu->config_area == PERM_CONFIG_AREA) {
- fwu->config_block_count = fwu->perm_config_block_count;
- goto write_config;
- }
- retval = fwu_write_bootloader_id();
- if (retval < 0)
- return retval;
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Bootloader ID written\n",
- __func__);
- switch (fwu->config_area) {
- case UI_CONFIG_AREA:
- retval = fwu_write_f34_command(CMD_ERASE_CONFIG);
- break;
- case BL_CONFIG_AREA:
- retval = fwu_write_f34_command(CMD_ERASE_BL_CONFIG);
- fwu->config_block_count = fwu->bl_config_block_count;
- break;
- case DISP_CONFIG_AREA:
- retval = fwu_write_f34_command(CMD_ERASE_DISP_CONFIG);
- fwu->config_block_count = fwu->disp_config_block_count;
- break;
- }
- if (retval < 0)
- return retval;
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Erase command written\n",
- __func__);
- retval = fwu_wait_for_idle(ERASE_WAIT_MS);
- if (retval < 0)
- return retval;
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Idle status detected\n",
- __func__);
- write_config:
- retval = fwu_write_configuration();
- if (retval < 0)
- return retval;
- dev_info(&fwu->rmi4_data->i2c_client->dev, "%s: Config written\n",
- __func__);
- return retval;
- }
- static int fwu_start_write_config(void)
- {
- int retval;
- struct image_header header;
- switch (fwu->config_area) {
- case UI_CONFIG_AREA:
- break;
- case PERM_CONFIG_AREA:
- if (!fwu->has_perm_config)
- return -EINVAL;
- break;
- case BL_CONFIG_AREA:
- if (!fwu->has_bl_config)
- return -EINVAL;
- break;
- case DISP_CONFIG_AREA:
- if (!fwu->has_disp_config)
- return -EINVAL;
- break;
- default:
- return -EINVAL;
- }
- if (fwu->ext_data_source)
- fwu->config_data = fwu->ext_data_source;
- else
- return -EINVAL;
- if (fwu->config_area == UI_CONFIG_AREA) {
- parse_header(&header, fwu->ext_data_source);
- if (header.config_size) {
- fwu->config_data = fwu->ext_data_source +
- FW_IMAGE_OFFSET +
- header.image_size;
- } else {
- return -EINVAL;
- }
- }
- dev_info(&fwu->rmi4_data->i2c_client->dev, "%s: Start of write config process\n",
- __func__);
- fwu->rmi4_data->doing_reflash = true;
- retval = fwu_do_write_config();
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to write config\n",
- __func__);
- }
- fwu->rmi4_data->reset_device(fwu->rmi4_data);
- fwu->rmi4_data->doing_reflash = false;
- dev_info(&fwu->rmi4_data->i2c_client->dev, "%s: End of write config process\n",
- __func__);
- return retval;
- }
- static int fwu_do_read_config(void)
- {
- int retval;
- unsigned char block_offset[] = {0, 0};
- unsigned short block_num;
- unsigned short block_count;
- unsigned short index = 0;
- retval = fwu_enter_flash_prog();
- if (retval < 0)
- goto exit;
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Entered flash prog mode\n",
- __func__);
- switch (fwu->config_area) {
- case UI_CONFIG_AREA:
- block_count = fwu->config_block_count;
- break;
- case PERM_CONFIG_AREA:
- if (!fwu->has_perm_config) {
- retval = -EINVAL;
- goto exit;
- }
- block_count = fwu->perm_config_block_count;
- break;
- case BL_CONFIG_AREA:
- if (!fwu->has_bl_config) {
- retval = -EINVAL;
- goto exit;
- }
- block_count = fwu->bl_config_block_count;
- break;
- case DISP_CONFIG_AREA:
- if (!fwu->has_disp_config) {
- retval = -EINVAL;
- goto exit;
- }
- block_count = fwu->disp_config_block_count;
- break;
- default:
- retval = -EINVAL;
- goto exit;
- }
- fwu->config_size = fwu->block_size * block_count;
- kfree(fwu->read_config_buf);
- fwu->read_config_buf = kzalloc(fwu->config_size, GFP_KERNEL);
- block_offset[1] |= (fwu->config_area << 5);
- retval = fwu->fn_ptr->write(fwu->rmi4_data,
- fwu->f34_fd.data_base_addr + BLOCK_NUMBER_OFFSET,
- block_offset,
- sizeof(block_offset));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to write to block number registers\n",
- __func__);
- goto exit;
- }
- for (block_num = 0; block_num < block_count; block_num++) {
- retval = fwu_write_f34_command(CMD_READ_CONFIG_BLOCK);
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to write read config command\n",
- __func__);
- goto exit;
- }
- retval = fwu_wait_for_idle(WRITE_WAIT_MS);
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to wait for idle status\n",
- __func__);
- goto exit;
- }
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET,
- &fwu->read_config_buf[index],
- fwu->block_size);
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to read block data (block %d)\n",
- __func__, block_num);
- goto exit;
- }
- index += fwu->block_size;
- }
- exit:
- fwu->rmi4_data->reset_device(fwu->rmi4_data);
- return retval;
- }
- int synaptics_fw_updater(unsigned char *fw_data)
- {
- int retval;
- if (!fwu)
- return -ENODEV;
- if (!fwu->initialized)
- return -ENODEV;
- if (!fw_data) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Firmware data is NULL\n", __func__);
- return -ENODEV;
- }
- fwu->ext_data_source = fw_data;
- fwu->config_area = UI_CONFIG_AREA;
- retval = fwu_start_reflash();
- return retval;
- }
- EXPORT_SYMBOL(synaptics_fw_updater);
- static ssize_t fwu_sysfs_show_image(struct file *data_file,
- struct kobject *kobj, struct bin_attribute *attributes,
- char *buf, loff_t pos, size_t count)
- {
- struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- if (count < fwu->config_size) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Not enough space (%d bytes) in buffer\n",
- __func__, count);
- return -EINVAL;
- }
- memcpy(buf, fwu->read_config_buf, fwu->config_size);
- return fwu->config_size;
- }
- static ssize_t fwu_sysfs_store_image(struct file *data_file,
- struct kobject *kobj, struct bin_attribute *attributes,
- char *buf, loff_t pos, size_t count)
- {
- memcpy((void *)(&fwu->ext_data_source[fwu->data_pos]),
- (const void *)buf,
- count);
- fwu->data_pos += count;
- return count;
- }
- static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- int retval;
- unsigned int input;
- struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- if (sscanf(buf, "%u", &input) != 1) {
- retval = -EINVAL;
- goto exit;
- }
- if (input != 1) {
- retval = -EINVAL;
- goto exit;
- }
- retval = synaptics_fw_updater(fwu->ext_data_source);
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to do reflash\n",
- __func__);
- goto exit;
- }
- retval = count;
- exit:
- kfree(fwu->ext_data_source);
- fwu->ext_data_source = NULL;
- return retval;
- }
- static ssize_t fwu_sysfs_write_config_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- int retval;
- unsigned int input;
- struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- if (sscanf(buf, "%u", &input) != 1) {
- retval = -EINVAL;
- goto exit;
- }
- if (input != 1) {
- retval = -EINVAL;
- goto exit;
- }
- retval = fwu_start_write_config();
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to write config\n",
- __func__);
- goto exit;
- }
- retval = count;
- exit:
- kfree(fwu->ext_data_source);
- fwu->ext_data_source = NULL;
- return retval;
- }
- static ssize_t fwu_sysfs_read_config_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- int retval;
- unsigned int input;
- struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- if (sscanf(buf, "%u", &input) != 1)
- return -EINVAL;
- if (input != 1)
- return -EINVAL;
- retval = fwu_do_read_config();
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to read config\n",
- __func__);
- return retval;
- }
- return count;
- }
- static ssize_t fwu_sysfs_config_area_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- int retval;
- unsigned long config_area;
- retval = kstrtoul(buf, 10, &config_area);
- if (retval)
- return retval;
- fwu->config_area = config_area;
- return count;
- }
- static ssize_t fwu_sysfs_image_size_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- int retval;
- unsigned long size;
- struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
- retval = kstrtoul(buf, 10, &size);
- if (retval)
- return retval;
- fwu->image_size = size;
- fwu->data_pos = 0;
- kfree(fwu->ext_data_source);
- fwu->ext_data_source = kzalloc(fwu->image_size, GFP_KERNEL);
- if (!fwu->ext_data_source) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to alloc mem for image data\n",
- __func__);
- return -ENOMEM;
- }
- return count;
- }
- static ssize_t fwu_sysfs_block_size_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- return snprintf(buf, PAGE_SIZE, "%u\n", fwu->block_size);
- }
- static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- return snprintf(buf, PAGE_SIZE, "%u\n", fwu->fw_block_count);
- }
- static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- return snprintf(buf, PAGE_SIZE, "%u\n", fwu->config_block_count);
- }
- static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- return snprintf(buf, PAGE_SIZE, "%u\n", fwu->perm_config_block_count);
- }
- static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- return snprintf(buf, PAGE_SIZE, "%u\n", fwu->bl_config_block_count);
- }
- static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- return snprintf(buf, PAGE_SIZE, "%u\n", fwu->disp_config_block_count);
- }
- static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data,
- unsigned char intr_mask)
- {
- if (fwu->intr_mask & intr_mask)
- fwu_read_f34_flash_status();
- return;
- }
- static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
- {
- int retval;
- unsigned char attr_count;
- int attr_count_num;
- struct pdt_properties pdt_props;
- fwu = kzalloc(sizeof(*fwu), GFP_KERNEL);
- if (!fwu) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to alloc mem for fwu\n",
- __func__);
- goto exit;
- }
- fwu->fn_ptr = kzalloc(sizeof(*(fwu->fn_ptr)), GFP_KERNEL);
- if (!fwu->fn_ptr) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to alloc mem for fn_ptr\n",
- __func__);
- retval = -ENOMEM;
- goto exit_free_fwu;
- }
- fwu->rmi4_data = rmi4_data;
- fwu->fn_ptr->read = rmi4_data->i2c_read;
- fwu->fn_ptr->write = rmi4_data->i2c_write;
- fwu->fn_ptr->enable = rmi4_data->irq_enable;
- retval = fwu->fn_ptr->read(rmi4_data,
- PDT_PROPS,
- pdt_props.data,
- sizeof(pdt_props.data));
- if (retval < 0) {
- dev_info(&rmi4_data->i2c_client->dev,
- "%s: Failed to read PDT properties, assuming 0x00\n",
- __func__);
- } else if (pdt_props.has_bsr) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Reflash for LTS not currently supported\n",
- __func__);
- goto exit_free_mem;
- }
- retval = fwu_scan_pdt();
- if (retval < 0)
- goto exit_free_mem;
- fwu->productinfo1 = rmi4_data->rmi4_mod_info.product_info[0];
- fwu->productinfo2 = rmi4_data->rmi4_mod_info.product_info[1];
- memcpy(fwu->product_id, rmi4_data->rmi4_mod_info.product_id_string,
- SYNAPTICS_RMI4_PRODUCT_ID_SIZE);
- fwu->product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE] = 0;
- #if defined(CONFIG_MACH_JACTIVESKT)
- /* Fortius Use only B Type. So read and use ic_revision_of_ic from IC */
- #else
- /* Check the IC revision from product ID value
- * we can check the ic revision with f34_ctrl_3 but to read production
- * ID is more safity. because it is non-user writerble area.
- */
- if (rmi4_data->ic_revision_of_ic < 0xB0) {
- if ((strncmp(fwu->product_id,
- SYNAPTICS_PRODUCT_ID_B0, 5) == 0)
- || (strncmp(fwu->product_id,
- SYNAPTICS_PRODUCT_ID_B0_SPAIR, 6) == 0)) {
- rmi4_data->ic_revision_of_ic = 0xB0;
- } else
- rmi4_data->ic_revision_of_ic = 0xA1;
- }
- #endif
- dev_info(&rmi4_data->i2c_client->dev, "%s: [IC] [F01 product info, ID(revision)] [0x%04X 0x%04X, %s(0X%X)]\n",
- __func__, fwu->productinfo1,
- fwu->productinfo2, fwu->product_id,
- rmi4_data->ic_revision_of_ic);
- retval = fwu_read_f34_queries();
- if (retval < 0)
- goto exit_free_mem;
- fwu->initialized = true;
- retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj,
- &dev_attr_data);
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to create sysfs bin file\n",
- __func__);
- goto exit_free_mem;
- }
- for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
- retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj,
- &attrs[attr_count].attr);
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to create sysfs attributes\n",
- __func__);
- retval = -ENODEV;
- goto exit_remove_attrs;
- }
- }
- return 0;
- exit_remove_attrs:
- attr_count_num = (int)attr_count;
- for (attr_count_num--; attr_count_num >= 0; attr_count_num--) {
- sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
- &attrs[attr_count].attr);
- }
- sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
- exit_free_mem:
- kfree(fwu->fn_ptr);
- exit_free_fwu:
- kfree(fwu);
- exit:
- return 0;
- }
- static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data)
- {
- unsigned char attr_count;
- sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
- for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
- sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
- &attrs[attr_count].attr);
- }
- kfree(fwu->fn_ptr);
- kfree(fwu);
- return;
- }
- int rmi4_fw_update_module_register(void)
- {
- int retval;
- retval = synaptics_rmi4_new_function(RMI_FW_UPDATER,
- synaptics_rmi4_fwu_init,
- synaptics_rmi4_fwu_remove,
- synaptics_rmi4_fwu_attn);
- return retval;
- }
|