diff --git a/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt b/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt index 0b57ba0b62a0..c95ccad4a841 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt @@ -24,6 +24,8 @@ Optional properties: - ite,wakeup : boolean, use this to support touch-to-wake feature. - ite,palm-detect-en : boolean, use this to send palm-detect-keycode when palm is detected. + - ite,fw-name : Specify firmware file name in /etc/firmware + - ite,cfg-name : Specify config file name in /etc/firmware Required properties palm-detect-en feature: - ite,palm-detect-keycode : The keycode that is required to be sent when @@ -43,5 +45,7 @@ Example: ite,wakeup; ite,palm-detect-en; ite,palm-detect-keycode = <142>; + ite,fw-name = "ite7260_fw.bin"; + ite,cfg-name = "ite7260_cfg.bin"; }; }; diff --git a/drivers/input/touchscreen/it7258_ts_i2c.c b/drivers/input/touchscreen/it7258_ts_i2c.c index 99fc54a0bf4b..c3dd88c08d7e 100644 --- a/drivers/input/touchscreen/it7258_ts_i2c.c +++ b/drivers/input/touchscreen/it7258_ts_i2c.c @@ -27,12 +27,24 @@ #include #include #include +#include #define MAX_BUFFER_SIZE 144 #define DEVICE_NAME "IT7260" #define SCREEN_X_RESOLUTION 320 #define SCREEN_Y_RESOLUTION 320 #define DEBUGFS_DIR_NAME "ts_debug" +#define FW_NAME "it7260_fw.bin" +#define CFG_NAME "it7260_cfg.bin" +#define VER_BUFFER_SIZE 4 +#define IT_FW_CHECK(x, y) \ + (((x)[0] < (y)->data[8]) || ((x)[1] < (y)->data[9]) || \ + ((x)[2] < (y)->data[10]) || ((x)[3] < (y)->data[11])) +#define IT_CFG_CHECK(x, y) \ + (((x)[0] < (y)->data[(y)->size - 8]) || \ + ((x)[1] < (y)->data[(y)->size - 7]) || \ + ((x)[2] < (y)->data[(y)->size - 6]) || \ + ((x)[3] < (y)->data[(y)->size - 5])) /* all commands writes go to this idx */ #define BUF_COMMAND 0x20 @@ -55,8 +67,8 @@ #define CMD_IDENT_CHIP 0x00 /* VERSION_LENGTH bytes of data in response */ #define CMD_READ_VERSIONS 0x01 -#define VER_FIRMWARE 0x00 -#define VER_CONFIG 0x06 +#define SUB_CMD_READ_FIRMWARE_VERSION 0x00 +#define SUB_CMD_READ_CONFIG_VERSION 0x06 #define VERSION_LENGTH 10 /* subcommand is zero, next byte is power mode */ #define CMD_PWR_CTL 0x04 @@ -70,8 +82,8 @@ /* needs to be followed by 4 bytes of zeroes */ #define CMD_CALIBRATE 0x13 #define CMD_FIRMWARE_UPGRADE 0x60 -#define FIRMWARE_MODE_ENTER 0x00 -#define FIRMWARE_MODE_EXIT 0x80 +#define SUB_CMD_ENTER_FW_UPGRADE_MODE 0x00 +#define SUB_CMD_EXIT_FW_UPGRADE_MODE 0x80 /* address for FW read/write */ #define CMD_SET_START_OFFSET 0x61 /* subcommand is number of bytes to write */ @@ -135,6 +147,8 @@ struct IT7260_ts_platform_data { bool wakeup; bool palm_detect_en; u16 palm_detect_keycode; + const char *fw_name; + const char *cfg_name; }; struct IT7260_ts_data { @@ -145,10 +159,17 @@ struct IT7260_ts_data { struct regulator *avdd; bool device_needs_wakeup; bool suspended; - struct work_struct work_pm_relax; bool fw_upgrade_result; + bool cfg_upgrade_result; + bool fw_cfg_uploading; + struct work_struct work_pm_relax; bool calibration_success; bool had_finger_down; + char fw_name[MAX_BUFFER_SIZE]; + char cfg_name[MAX_BUFFER_SIZE]; + struct mutex fw_cfg_mutex; + u8 fw_ver[VER_BUFFER_SIZE]; + u8 cfg_ver[VER_BUFFER_SIZE]; #ifdef CONFIG_FB struct notifier_block fb_notif; #endif @@ -269,7 +290,7 @@ static bool IT7260_i2cWrite(uint8_t buf_index, const uint8_t *buffer, return IT7260_i2cWriteNoReadyCheck(buf_index, buffer, buf_len); } -static bool IT7260_chipFirmwareReinitialize(uint8_t command) +static bool IT7260_firmware_reinitialize(u8 command) { uint8_t cmd[] = {command}; uint8_t rsp[2]; @@ -284,13 +305,14 @@ static bool IT7260_chipFirmwareReinitialize(uint8_t command) return !rsp[0] && !rsp[1]; } -static bool IT7260_chipFirmwareUpgradeModeEnterExit(bool enter) +static bool IT7260_enter_exit_fw_ugrade_mode(bool enter) { uint8_t cmd[] = {CMD_FIRMWARE_UPGRADE, 0, 'I', 'T', '7', '2', '6', '0', 0x55, 0xAA}; uint8_t resp[2]; - cmd[1] = enter ? FIRMWARE_MODE_ENTER : FIRMWARE_MODE_EXIT; + cmd[1] = enter ? SUB_CMD_ENTER_FW_UPGRADE_MODE : + SUB_CMD_EXIT_FW_UPGRADE_MODE; if (!IT7260_i2cWrite(BUF_COMMAND, cmd, sizeof(cmd))) return false; @@ -321,7 +343,7 @@ static bool IT7260_chipSetStartOffset(uint16_t offset) /* write fw_length bytes from fw_data at chip offset wr_start_offset */ -static bool IT7260_chipFlashWriteAndVerify(unsigned int fw_length, +static bool IT7260_fw_flash_write_verify(unsigned int fw_length, const uint8_t *fw_data, uint16_t wr_start_offset) { uint32_t cur_data_off; @@ -384,71 +406,171 @@ static bool IT7260_chipFlashWriteAndVerify(unsigned int fw_length, return true; } -static bool IT7260_chipFirmwareUpload(uint32_t fw_len, const uint8_t *fw_data, - uint32_t cfg_len, const uint8_t *cfg_data) -{ - bool success = false; - - /* enter fw upload mode */ - if (!IT7260_chipFirmwareUpgradeModeEnterExit(true)) - return false; - - /* flash the firmware if requested */ - if (fw_len && fw_data && !IT7260_chipFlashWriteAndVerify(fw_len, - fw_data, 0)) { - dev_err(&gl_ts->client->dev, "failed to upload touch firmware\n"); - goto out; - } - - /* flash config data if requested */ - if (cfg_len && cfg_data && !IT7260_chipFlashWriteAndVerify(cfg_len, - cfg_data, CHIP_FLASH_SIZE - cfg_len)) { - dev_err(&gl_ts->client->dev, "failed to upload touch cfg data\n"); - goto out; - } - - success = true; - -out: - return IT7260_chipFirmwareUpgradeModeEnterExit(false) && - IT7260_chipFirmwareReinitialize(CMD_FIRMWARE_REINIT_6F) && - success; -} - - /* - * both buffers should be VERSION_LENGTH in size, - * but only a part of them is significant + * this code to get versions from the chip via i2c transactions, and save + * them in driver data structure. */ -static bool IT7260_chipGetVersions(uint8_t *ver_fw, uint8_t *ver_cfg, - bool log_it) +static void IT7260_get_chip_versions(struct device *dev) { - /* - * this code to get versions is reproduced as was written, but it does - * not make sense. Something here *PROBABLY IS* wrong - */ - static const uint8_t cmd_read_fw_ver[] = {CMD_READ_VERSIONS, - VER_FIRMWARE}; - static const uint8_t cmd_read_cfg_ver[] = {CMD_READ_VERSIONS, - VER_CONFIG}; + static const u8 cmd_read_fw_ver[] = {CMD_READ_VERSIONS, + SUB_CMD_READ_FIRMWARE_VERSION}; + static const u8 cmd_read_cfg_ver[] = {CMD_READ_VERSIONS, + SUB_CMD_READ_CONFIG_VERSION}; + u8 ver_fw[VERSION_LENGTH], ver_cfg[VERSION_LENGTH]; bool ret = true; - /* - * this structure is so that we definitely do all the calls, but still - * return a status in case anyone cares - */ ret = IT7260_i2cWrite(BUF_COMMAND, cmd_read_fw_ver, - sizeof(cmd_read_fw_ver)) && ret; - ret = IT7260_i2cRead(BUF_RESPONSE, ver_fw, VERSION_LENGTH) && ret; - ret = IT7260_i2cWrite(BUF_COMMAND, cmd_read_cfg_ver, - sizeof(cmd_read_cfg_ver)) && ret; - ret = IT7260_i2cRead(BUF_RESPONSE, ver_cfg, VERSION_LENGTH) && ret; + sizeof(cmd_read_fw_ver)); + if (ret) { + ret = IT7260_i2cRead(BUF_RESPONSE, ver_fw, VERSION_LENGTH); + if (ret) + memcpy(gl_ts->fw_ver, ver_fw + (5 * sizeof(u8)), + VER_BUFFER_SIZE * sizeof(u8)); + } + if (!ret) + dev_err(dev, "failed to read fw version from chip\n"); - if (log_it) - dev_info(&gl_ts->client->dev, - "current versions: fw@{%X,%X,%X,%X}, cfg@{%X,%X,%X,%X}\n", - ver_fw[5], ver_fw[6], ver_fw[7], ver_fw[8], - ver_cfg[1], ver_cfg[2], ver_cfg[3], ver_cfg[4]); + ret = IT7260_i2cWrite(BUF_COMMAND, cmd_read_cfg_ver, + sizeof(cmd_read_cfg_ver)); + if (ret) { + ret = IT7260_i2cRead(BUF_RESPONSE, ver_cfg, VERSION_LENGTH) + && ret; + if (ret) + memcpy(gl_ts->cfg_ver, ver_cfg + (1 * sizeof(u8)), + VER_BUFFER_SIZE * sizeof(u8)); + } + if (!ret) + dev_err(dev, "failed to read cfg version from chip\n"); + + dev_info(dev, "Current fw{%X.%X.%X.%X} cfg{%X.%X.%X.%X}\n", + gl_ts->fw_ver[0], gl_ts->fw_ver[1], gl_ts->fw_ver[2], + gl_ts->fw_ver[3], gl_ts->cfg_ver[0], gl_ts->cfg_ver[1], + gl_ts->cfg_ver[2], gl_ts->cfg_ver[3]); +} + +static int IT7260_cfg_upload(struct device *dev, bool force) +{ + const struct firmware *cfg = NULL; + int ret; + bool success, cfg_upgrade = false; + + ret = request_firmware(&cfg, gl_ts->cfg_name, dev); + if (ret) { + dev_err(dev, "failed to get config data %s for it7260 %d\n", + gl_ts->cfg_name, ret); + return ret; + } + + /* + * This compares the cfg version number from chip and the cfg + * data file. IT flashes only when version of cfg data file is + * greater than that of chip or if it is set for force cfg upgrade. + */ + if (force) + cfg_upgrade = true; + else if (IT_CFG_CHECK(gl_ts->cfg_ver, cfg)) + cfg_upgrade = true; + + if (!cfg_upgrade) { + dev_err(dev, "CFG upgrade no required ...\n"); + ret = -EFAULT; + goto out; + } else { + dev_info(dev, "Config upgrading...\n"); + + disable_irq(gl_ts->client->irq); + /* enter cfg upload mode */ + success = IT7260_enter_exit_fw_ugrade_mode(true); + if (!success) { + dev_err(dev, "Can't enter cfg upgrade mode\n"); + ret = -EIO; + goto out; + } + /* flash config data if requested */ + success = IT7260_fw_flash_write_verify(cfg->size, cfg->data, + CHIP_FLASH_SIZE - cfg->size); + if (!success) { + dev_err(dev, "failed to upgrade touch cfg data\n"); + IT7260_enter_exit_fw_ugrade_mode(false); + IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_6F); + ret = -EIO; + goto out; + } else { + memcpy(gl_ts->cfg_ver, cfg->data + + (cfg->size - 8 * sizeof(u8)), + VER_BUFFER_SIZE * sizeof(u8)); + dev_info(dev, "CFG upgrade is success. New cfg ver: %X.%X.%X.%X\n", + gl_ts->cfg_ver[0], gl_ts->cfg_ver[1], + gl_ts->cfg_ver[2], gl_ts->cfg_ver[3]); + + } + enable_irq(gl_ts->client->irq); + } + +out: + release_firmware(cfg); + + return ret; +} + +static int IT7260_fw_upload(struct device *dev, bool force) +{ + const struct firmware *fw = NULL; + int ret; + bool success, fw_upgrade = false; + + ret = request_firmware(&fw, gl_ts->fw_name, dev); + if (ret) { + dev_err(dev, "failed to get firmware %s for it7260 %d\n", + gl_ts->fw_name, ret); + return ret; + } + + /* + * This compares the fw version number from chip and the fw data + * file. It flashes only when version of fw data file is greater + * than that of chip or it it is set for force fw upgrade. + */ + if (force) + fw_upgrade = true; + else if (IT_FW_CHECK(gl_ts->fw_ver, fw)) + fw_upgrade = true; + + if (!fw_upgrade) { + dev_err(dev, "FW upgrade not required ...\n"); + ret = -EFAULT; + goto out; + } else { + dev_info(dev, "Firmware upgrading...\n"); + + disable_irq(gl_ts->client->irq); + /* enter fw upload mode */ + success = IT7260_enter_exit_fw_ugrade_mode(true); + if (!success) { + dev_err(dev, "Can't enter fw upgrade mode\n"); + ret = -EIO; + goto out; + } + /* flash the firmware if requested */ + success = IT7260_fw_flash_write_verify(fw->size, fw->data, 0); + if (!success) { + dev_err(dev, "failed to upgrade touch firmware\n"); + IT7260_enter_exit_fw_ugrade_mode(false); + IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_6F); + ret = -EIO; + goto out; + } else { + memcpy(gl_ts->fw_ver, fw->data + (8 * sizeof(u8)), + VER_BUFFER_SIZE * sizeof(u8)); + dev_info(dev, "FW upgrade is success. New fw ver: %X.%X.%X.%X\n", + gl_ts->fw_ver[0], gl_ts->fw_ver[1], + gl_ts->fw_ver[2], gl_ts->fw_ver[3]); + } + enable_irq(gl_ts->client->irq); + } + +out: + release_firmware(fw); return ret; } @@ -468,75 +590,91 @@ static int IT7260_ts_chipLowPowerMode(bool low) return 0; } -static ssize_t sysfsUpgradeStore(struct device *dev, +static ssize_t sysfs_fw_upgrade_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - const struct firmware *fw, *cfg; - uint8_t ver_fw[10], ver_cfg[10]; - unsigned fw_len = 0, cfg_len = 0; - bool success; int mode = 0, ret; - ret = request_firmware(&fw, "it7260.fw", dev); - if (ret) - dev_dbg(dev, "failed to get firmware for it7260 %d\n", ret); - else - fw_len = fw->size; - - ret = request_firmware(&cfg, "it7260.cfg", dev); - if (ret) - dev_dbg(dev, "failed to get config data for it7260 %d\n", ret); - else - cfg_len = cfg->size; - - ret = kstrtoint(buf, 10, &mode); - - IT7260_chipGetVersions(ver_fw, ver_cfg, true); - - gl_ts->fw_upgrade_result = false; - if (fw_len && cfg_len) { - if ((mode > 0) && ((ver_fw[5] < fw->data[8] || - ver_fw[6] < fw->data[9] || - ver_fw[7] < fw->data[10] || - ver_fw[8] < fw->data[11]) || - (ver_cfg[1] < cfg->data[cfg_len - 8] || - ver_cfg[2] < cfg->data[cfg_len - 7] || - ver_cfg[3] < cfg->data[cfg_len - 6] || - ver_cfg[4] < cfg->data[cfg_len - 5]))) { - dev_info(dev, "firmware/config will be upgraded\n"); - disable_irq(gl_ts->client->irq); - /* upgrade the fw and cfg */ - success = IT7260_chipFirmwareUpload(fw_len, fw->data, - cfg_len, cfg->data); - enable_irq(gl_ts->client->irq); - - gl_ts->fw_upgrade_result = success; - dev_info(dev, "fw/cfg upload %s\n", - success ? "success" : "failed"); - } else { - dev_info(dev, "firmware/config upgrade not needed\n"); - } + if (gl_ts->suspended) { + dev_err(dev, "Device is suspended, can't flash fw!!!\n"); + return -EBUSY; } - if (fw_len) - release_firmware(fw); + ret = kstrtoint(buf, 10, &mode); + if (!ret) { + dev_err(dev, "failed to read input for sysfs\n"); + return -EINVAL; + } - if (cfg_len) - release_firmware(cfg); + mutex_lock(&gl_ts->fw_cfg_mutex); + if (mode == 1) { + gl_ts->fw_cfg_uploading = true; + ret = IT7260_fw_upload(dev, false); + if (ret) { + dev_err(dev, "Failed to flash fw: %d", ret); + gl_ts->fw_upgrade_result = false; + } else { + gl_ts->fw_upgrade_result = true; + } + gl_ts->fw_cfg_uploading = false; + } + mutex_unlock(&gl_ts->fw_cfg_mutex); return count; } -static ssize_t sysfsUpgradeShow(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t sysfs_cfg_upgrade_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { - return snprintf(buf, MAX_BUFFER_SIZE, "%d", gl_ts->fw_upgrade_result); + int mode = 0, ret; + + if (gl_ts->suspended) { + dev_err(dev, "Device is suspended, can't flash cfg!!!\n"); + return -EBUSY; + } + + ret = kstrtoint(buf, 10, &mode); + if (!ret) { + dev_err(dev, "failed to read input for sysfs\n"); + return -EINVAL; + } + + mutex_lock(&gl_ts->fw_cfg_mutex); + if (mode == 1) { + gl_ts->fw_cfg_uploading = true; + ret = IT7260_cfg_upload(dev, false); + if (ret) { + dev_err(dev, "Failed to flash cfg: %d", ret); + gl_ts->cfg_upgrade_result = false; + } else { + gl_ts->cfg_upgrade_result = true; + } + gl_ts->fw_cfg_uploading = false; + } + mutex_unlock(&gl_ts->fw_cfg_mutex); + + return count; } -static ssize_t sysfsCalibrationShow(struct device *dev, +static ssize_t sysfs_fw_upgrade_show(struct device *dev, struct device_attribute *attr, char *buf) { - return snprintf(buf, MAX_BUFFER_SIZE, "%d", gl_ts->calibration_success); + return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n", + gl_ts->fw_upgrade_result); +} + +static ssize_t sysfs_cfg_upgrade_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n", + gl_ts->cfg_upgrade_result); +} + +static ssize_t sysfs_calibration_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n", + gl_ts->calibration_success); } static bool IT7260_chipSendCalibrationCmd(bool auto_tune_on) @@ -547,7 +685,7 @@ static bool IT7260_chipSendCalibrationCmd(bool auto_tune_on) sizeof(cmd_calibrate)); } -static ssize_t sysfsCalibrationStore(struct device *dev, +static ssize_t sysfs_calibration_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { uint8_t resp; @@ -560,20 +698,20 @@ static ssize_t sysfsCalibrationStore(struct device *dev, /* * previous logic that was here never called - * IT7260_chipFirmwareReinitialize() due to checking a + * IT7260_firmware_reinitialize() due to checking a * guaranteed-not-null value against null. We now * call it. Hopefully this is OK */ if (!resp) - dev_dbg(dev, "IT7260_chipFirmwareReinitialize -> %s\n", - IT7260_chipFirmwareReinitialize(CMD_FIRMWARE_REINIT_6F) + dev_dbg(dev, "IT7260_firmware_reinitialize-> %s\n", + IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_6F) ? "success" : "fail"); } return count; } -` -static ssize_t sysfsPointShow(struct device *dev, + +static ssize_t sysfs_point_show(struct device *dev, struct device_attribute *attr, char *buf) { uint8_t point_data[sizeof(struct PointData)]; @@ -582,37 +720,35 @@ static ssize_t sysfsPointShow(struct device *dev, readSuccess = IT7260_i2cReadNoReadyCheck(BUF_POINT_INFO, point_data, sizeof(point_data)); - ret = snprintf(buf, MAX_BUFFER_SIZE, - "point_show read ret[%d]--point[%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x]=\n", - readSuccess, point_data[0], point_data[1], point_data[2], - point_data[3], point_data[4], point_data[5], point_data[6], - point_data[7], point_data[8], point_data[9], point_data[10], - point_data[11], point_data[12], point_data[13]); + if (readSuccess) { + ret = scnprintf(buf, MAX_BUFFER_SIZE, + "point_show read ret[%d]--point[%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x][%x]\n", + readSuccess, point_data[0], point_data[1], + point_data[2], point_data[3], point_data[4], + point_data[5], point_data[6], point_data[7], + point_data[8], point_data[9], point_data[10], + point_data[11], point_data[12], point_data[13]); + } else { + ret = scnprintf(buf, MAX_BUFFER_SIZE, + "failed to read point data\n"); + } dev_dbg(dev, "%s", buf); return ret; } -static ssize_t sysfsPointStore(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - return count; -} - -static ssize_t sysfsVersionShow(struct device *dev, +static ssize_t sysfs_version_show(struct device *dev, struct device_attribute *attr, char *buf) { - uint8_t ver_fw[10], ver_cfg[10]; - - IT7260_chipGetVersions(ver_fw, ver_cfg, false); - return snprintf(buf, MAX_BUFFER_SIZE, - "fw{%x,%x,%x,%x} # cfg{%x,%x,%x,%x}\n", - ver_fw[5], ver_fw[6], ver_fw[7], ver_fw[8], - ver_cfg[1], ver_cfg[2], ver_cfg[3], ver_cfg[4]); + return scnprintf(buf, MAX_BUFFER_SIZE, + "fw{%X.%X.%X.%X} cfg{%X.%X.%X.%X}\n", + gl_ts->fw_ver[0], gl_ts->fw_ver[1], gl_ts->fw_ver[2], + gl_ts->fw_ver[3], gl_ts->cfg_ver[0], gl_ts->cfg_ver[1], + gl_ts->cfg_ver[2], gl_ts->cfg_ver[3]); } -static ssize_t sysfsSleepShow(struct device *dev, +static ssize_t sysfs_sleep_show(struct device *dev, struct device_attribute *attr, char *buf) { /* @@ -624,7 +760,7 @@ static ssize_t sysfsSleepShow(struct device *dev, return 1; } -static ssize_t sysfsSleepStore(struct device *dev, +static ssize_t sysfs_sleep_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int go_to_sleep, ret; @@ -654,23 +790,95 @@ static ssize_t sysfsSleepStore(struct device *dev, return count; } +static ssize_t sysfs_cfg_name_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + char *strptr; + + if (count >= MAX_BUFFER_SIZE) { + dev_err(dev, "Input over %d chars long\n", MAX_BUFFER_SIZE); + return -EINVAL; + } + + strptr = strnstr(buf, ".bin", count); + if (!strptr) { + dev_err(dev, "Input is invalid cfg file\n"); + return -EINVAL; + } + + strlcpy(gl_ts->cfg_name, buf, count); + + return count; +} + +static ssize_t sysfs_cfg_name_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + if (strnlen(gl_ts->cfg_name, MAX_BUFFER_SIZE) > 0) + return scnprintf(buf, MAX_BUFFER_SIZE, "%s\n", + gl_ts->cfg_name); + else + return scnprintf(buf, MAX_BUFFER_SIZE, + "No config file name given\n"); +} + +static ssize_t sysfs_fw_name_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + char *strptr; + + if (count >= MAX_BUFFER_SIZE) { + dev_err(dev, "Input over %d chars long\n", MAX_BUFFER_SIZE); + return -EINVAL; + } + + strptr = strnstr(buf, ".bin", count); + if (!strptr) { + dev_err(dev, "Input is invalid fw file\n"); + return -EINVAL; + } + + strlcpy(gl_ts->fw_name, buf, count); + return count; +} + +static ssize_t sysfs_fw_name_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + if (strnlen(gl_ts->fw_name, MAX_BUFFER_SIZE) > 0) + return scnprintf(buf, MAX_BUFFER_SIZE, "%s\n", + gl_ts->fw_name); + else + return scnprintf(buf, MAX_BUFFER_SIZE, + "No firmware file name given\n"); +} + static DEVICE_ATTR(version, S_IRUGO | S_IWUSR, - sysfsVersionShow, NULL); + sysfs_version_show, NULL); static DEVICE_ATTR(sleep, S_IRUGO | S_IWUSR, - sysfsSleepShow, sysfsSleepStore); -static DEVICE_ATTR(calibration, S_IRUGO|S_IWUSR|S_IWGRP, - sysfsCalibrationShow, sysfsCalibrationStore); -static DEVICE_ATTR(upgrade, S_IRUGO|S_IWUSR|S_IWGRP, - sysfsUpgradeShow, sysfsUpgradeStore); -static DEVICE_ATTR(point, S_IRUGO|S_IWUSR|S_IWGRP, - sysfsPointShow, sysfsPointStore); + sysfs_sleep_show, sysfs_sleep_store); +static DEVICE_ATTR(calibration, S_IRUGO | S_IWUSR, + sysfs_calibration_show, sysfs_calibration_store); +static DEVICE_ATTR(fw_update, S_IRUGO | S_IWUSR, + sysfs_fw_upgrade_show, sysfs_fw_upgrade_store); +static DEVICE_ATTR(cfg_update, S_IRUGO | S_IWUSR, + sysfs_cfg_upgrade_show, sysfs_cfg_upgrade_store); +static DEVICE_ATTR(point, S_IRUGO | S_IWUSR, + sysfs_point_show, NULL); +static DEVICE_ATTR(fw_name, S_IRUGO | S_IWUSR, + sysfs_fw_name_show, sysfs_fw_name_store); +static DEVICE_ATTR(cfg_name, S_IRUGO | S_IWUSR, + sysfs_cfg_name_show, sysfs_cfg_name_store); static struct attribute *it7260_attributes[] = { &dev_attr_version.attr, &dev_attr_sleep.attr, &dev_attr_calibration.attr, - &dev_attr_upgrade.attr, + &dev_attr_fw_update.attr, + &dev_attr_cfg_update.attr, &dev_attr_point.attr, + &dev_attr_fw_name.attr, + &dev_attr_cfg_name.attr, NULL }; @@ -686,7 +894,7 @@ static void IT7260_chipExternalCalibration(bool autoTuneEnabled) IT7260_chipSendCalibrationCmd(autoTuneEnabled)); IT7260_waitDeviceReady(true, true); IT7260_i2cReadNoReadyCheck(BUF_RESPONSE, resp, sizeof(resp)); - IT7260_chipFirmwareReinitialize(CMD_FIRMWARE_REINIT_C); + IT7260_firmware_reinitialize(CMD_FIRMWARE_REINIT_C); } void IT7260_sendCalibrationCmd(void) @@ -975,11 +1183,32 @@ static int IT7260_ts_probe(struct i2c_client *client, } } + ret = of_property_read_string(client->dev.of_node, + "ite,fw-name", &pdata->fw_name); + if (ret && (ret != -EINVAL)) { + dev_err(&client->dev, "Unable to read fw file name %d\n", ret); + return ret; + } + + ret = of_property_read_string(client->dev.of_node, + "ite,cfg-name", &pdata->cfg_name); + if (ret && (ret != -EINVAL)) { + dev_err(&client->dev, "Unable to read cfg file name %d\n", ret); + return ret; + } + + snprintf(gl_ts->fw_name, MAX_BUFFER_SIZE, "%s", + (pdata->fw_name != NULL) ? pdata->fw_name : FW_NAME); + snprintf(gl_ts->cfg_name, MAX_BUFFER_SIZE, "%s", + (pdata->cfg_name != NULL) ? pdata->cfg_name : CFG_NAME); + if (!IT7260_chipIdentify()) { dev_err(&client->dev, "Failed to identify chip!!!"); goto err_identification_fail; } + IT7260_get_chip_versions(&client->dev); + gl_ts->input_dev = input_allocate_device(); if (!gl_ts->input_dev) { dev_err(&client->dev, "failed to allocate input device\n"); @@ -987,6 +1216,9 @@ static int IT7260_ts_probe(struct i2c_client *client, goto err_input_alloc; } + /* Initialize mutex for fw and cfg upgrade */ + mutex_init(&gl_ts->fw_cfg_mutex); + gl_ts->input_dev->name = DEVICE_NAME; gl_ts->input_dev->phys = "I2C"; gl_ts->input_dev->id.bustype = BUS_I2C; @@ -1035,7 +1267,7 @@ static int IT7260_ts_probe(struct i2c_client *client, ret = fb_register_client(&gl_ts->fb_notif); if (ret) - dev_err(&client->dev, "Unable to register fb_notifier: %d\n", + dev_err(&client->dev, "Unable to register fb_notifier %d\n", ret); #endif @@ -1162,9 +1394,11 @@ static int IT7260_ts_resume(struct device *dev) return 0; } - if (device_may_wakeup(dev) && (gl_ts->device_needs_wakeup)) { - gl_ts->device_needs_wakeup = false; - disable_irq_wake(gl_ts->client->irq); + if (device_may_wakeup(dev)) { + if (gl_ts->device_needs_wakeup) { + gl_ts->device_needs_wakeup = false; + disable_irq_wake(gl_ts->client->irq); + } return 0; } @@ -1178,14 +1412,21 @@ static int IT7260_ts_resume(struct device *dev) static int IT7260_ts_suspend(struct device *dev) { + if (gl_ts->fw_cfg_uploading) { + dev_dbg(dev, "Fw/cfg uploading. Can't go to suspend.\n"); + return -EBUSY; + } + if (gl_ts->suspended) { dev_info(dev, "Already in suspend state\n"); return 0; } - if (device_may_wakeup(dev) && (!gl_ts->device_needs_wakeup)) { - gl_ts->device_needs_wakeup = true; - enable_irq_wake(gl_ts->client->irq); + if (device_may_wakeup(dev)) { + if (!gl_ts->device_needs_wakeup) { + gl_ts->device_needs_wakeup = true; + enable_irq_wake(gl_ts->client->irq); + } return 0; }