summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/it7258_ts_i2c.txt4
-rw-r--r--drivers/input/touchscreen/it7258_ts_i2c.c543
2 files changed, 396 insertions, 151 deletions
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 <linux/fb.h>
#include <linux/debugfs.h>
#include <linux/input/mt.h>
+#include <linux/string.h>
#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)
+/*
+ * this code to get versions from the chip via i2c transactions, and save
+ * them in driver data structure.
+ */
+static void IT7260_get_chip_versions(struct device *dev)
{
- bool success = false;
+ 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;
- /* enter fw upload mode */
- if (!IT7260_chipFirmwareUpgradeModeEnterExit(true))
- return false;
+ ret = IT7260_i2cWrite(BUF_COMMAND, cmd_read_fw_ver,
+ 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");
- /* 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;
+ 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");
- /* 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;
+ 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;
}
- success = true;
+ /*
+ * 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:
- return IT7260_chipFirmwareUpgradeModeEnterExit(false) &&
- IT7260_chipFirmwareReinitialize(CMD_FIRMWARE_REINIT_6F) &&
- success;
-}
+ release_firmware(cfg);
+ return ret;
+}
-/*
- * both buffers should be VERSION_LENGTH in size,
- * but only a part of them is significant
- */
-static bool IT7260_chipGetVersions(uint8_t *ver_fw, uint8_t *ver_cfg,
- bool log_it)
+static int IT7260_fw_upload(struct device *dev, bool force)
{
- /*
- * 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};
- bool ret = true;
+ 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 structure is so that we definitely do all the calls, but still
- * return a status in case anyone cares
+ * 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.
*/
- 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;
+ 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);
+ }
- 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]);
+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;
+ if (gl_ts->suspended) {
+ dev_err(dev, "Device is suspended, can't flash fw!!!\n");
+ return -EBUSY;
+ }
ret = kstrtoint(buf, 10, &mode);
+ if (!ret) {
+ dev_err(dev, "failed to read input for sysfs\n");
+ return -EINVAL;
+ }
- 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");
+ 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 sysfs_cfg_upgrade_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int mode = 0, ret;
+
+ if (gl_ts->suspended) {
+ dev_err(dev, "Device is suspended, can't flash cfg!!!\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_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 sysfsUpgradeShow(struct device *dev,
+static ssize_t sysfs_fw_upgrade_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ 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 snprintf(buf, MAX_BUFFER_SIZE, "%d", gl_ts->fw_upgrade_result);
+ return scnprintf(buf, MAX_BUFFER_SIZE, "%d\n",
+ gl_ts->cfg_upgrade_result);
}
-static ssize_t sysfsCalibrationShow(struct device *dev,
+static ssize_t sysfs_calibration_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->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;
}