12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436 |
- /* 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 "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;
- }
- #define STATUS_POLLING_PERIOD_US 1000
- static int fwu_wait_for_idle(int timeout_ms)
- {
- int count = 0;
- int timeout_count = ((timeout_ms * 1000) / MAX_SLEEP_TIME_US) + 1;
- int polling_period = STATUS_POLLING_PERIOD_US / MAX_SLEEP_TIME_US;
- do {
- usleep_range(MIN_SLEEP_TIME_US, MAX_SLEEP_TIME_US);
- count++;
- if ((timeout_ms == WRITE_WAIT_MS) && (count >= polling_period) && ((count % polling_period) == 0)) {
- fwu_read_f34_flash_status();
- } else 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;
- }
- pr_info("synaptics %s:%d\n",__func__,__LINE__);
- 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;
- 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__);
- }
- pr_info("synaptics %s:%d\n",__func__,__LINE__);
- return retval;
- }
- static int fwu_start_reflash(void)
- {
- int retval = 0, retry = 3;
- 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));
- pr_info("synaptics %s:%d\n",__func__,__LINE__);
- 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);
- pr_info("synaptics %s:%d\n",__func__,__LINE__);
- }
- dev_info(&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();
- pr_info("synaptics %s:%d\n",__func__,__LINE__);
- 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;
- }
|