summaryrefslogtreecommitdiff
path: root/goodix_brl_fwupdate.c
diff options
context:
space:
mode:
authorWendly Li <wendlyli@google.com>2022-01-06 07:52:19 +0000
committerWendly Li <wendlyli@google.com>2022-01-21 03:53:14 +0000
commit0f9e7e8f390c3d06c81cac7c2a94d341a25cd896 (patch)
tree582bc6c608ebec8cfbf4631c00ee7c17970665b5 /goodix_brl_fwupdate.c
parentf4cbd1e784f777c544763bb0e2bdb65ad5c685cf (diff)
downloadgoodix_touch-0f9e7e8f390c3d06c81cac7c2a94d341a25cd896.tar.gz
Import v1.0.0 driver
Bug: 214018056 Bug: 214118475 Change-Id: I34f2afbc46ad1e4ac025cf199f323cf09e27ddec Signed-off-by: Wendly Li <wendlyli@google.com>
Diffstat (limited to 'goodix_brl_fwupdate.c')
-rw-r--r--goodix_brl_fwupdate.c138
1 files changed, 53 insertions, 85 deletions
diff --git a/goodix_brl_fwupdate.c b/goodix_brl_fwupdate.c
index 6bce047..b01d572 100644
--- a/goodix_brl_fwupdate.c
+++ b/goodix_brl_fwupdate.c
@@ -192,6 +192,7 @@ struct firmware_summary {
struct firmware_data {
struct firmware_summary fw_summary;
const struct firmware *firmware;
+ struct firmware *fw_sysfs;
};
struct config_data {
@@ -325,7 +326,11 @@ static int goodix_parse_firmware(struct firmware_data *fw_data)
fw_summary = &fw_data->fw_summary;
/* copy firmware head info */
- firmware = fw_data->firmware;
+ if (goodix_fw_update_ctrl.mode & UPDATE_MODE_SRC_SYSFS)
+ firmware = fw_data->fw_sysfs;
+ else
+ firmware = fw_data->firmware;
+
if (firmware->size < subsys_info_offset) {
ts_err("Invalid firmware size:%zu", firmware->size);
r = -EINVAL;
@@ -337,7 +342,8 @@ static int goodix_parse_firmware(struct firmware_data *fw_data)
fw_summary->size = le32_to_cpu(fw_summary->size);
if (firmware->size != fw_summary->size + FW_FILE_CHECKSUM_OFFSET) {
ts_err("Bad firmware, size not match, %zu != %d",
- firmware->size, fw_summary->size + 6);
+ firmware->size,
+ fw_summary->size + FW_FILE_CHECKSUM_OFFSET);
r = -EINVAL;
goto err_size;
}
@@ -627,7 +633,8 @@ static int goodix_update_prepare(struct fw_update_ctrl *fwu_ctrl)
ts_info("Success hold CPU");
/* enable misctl clock */
- if (fwu_ctrl->core_data->bus->ic_type == IC_TYPE_BERLIN_D)
+ if (fwu_ctrl->core_data->bus->ic_type == IC_TYPE_BERLIN_D ||
+ fwu_ctrl->core_data->bus->ic_type == IC_TYPE_NOTTINGHAM)
goodix_reg_write(misctl_reg, (u8 *)&enable_misctl_val, 4);
else
goodix_reg_write(misctl_reg, (u8 *)&enable_misctl_val, 1);
@@ -703,7 +710,7 @@ static int goodix_send_flash_cmd(struct goodix_flash_cmd *flash_cmd)
}
ts_info("flash cmd ack check pass");
- msleep(80);
+ msleep(50);
retry = 20;
for (i = 0; i < retry; i++) {
ret = goodix_reg_read(
@@ -716,7 +723,7 @@ static int goodix_send_flash_cmd(struct goodix_flash_cmd *flash_cmd)
ts_info("flash cmd status not ready, retry %d, ack 0x%x, status 0x%x, ret %d",
i, tmp_cmd.ack, tmp_cmd.status, ret);
- msleep(20);
+ usleep_range(10000, 11000);
}
ts_err("flash cmd status error %d, ack 0x%x, status 0x%x, ret %d", i,
@@ -773,7 +780,7 @@ static int goodix_flash_package(
ret = goodix_send_flash_cmd(&flash_cmd);
if (!ret) {
- ts_info("success write package to 0x%x, len %d",
+ ts_info("success write package to 0x%05X, len %d",
flash_addr, pkg_len - 4);
return 0;
}
@@ -817,7 +824,7 @@ static int goodix_flash_subsystem(struct fw_subsys_info *subsys)
while (total_size > 0) {
data_size = total_size > ISP_MAX_BUFFERSIZE ? ISP_MAX_BUFFERSIZE
: total_size;
- ts_info("Flash firmware to %08x,size:%u bytes",
+ ts_info("Flash firmware to 0x%05X,size:%u bytes",
subsys_base_addr + offset, data_size);
memcpy(fw_packet, &subsys->data[offset], data_size);
@@ -828,7 +835,7 @@ static int goodix_flash_subsystem(struct fw_subsys_info *subsys)
r = goodix_flash_package(subsys->type, fw_packet,
subsys_base_addr + offset, data_size + 4);
if (r) {
- ts_err("failed flash to %08x,size:%u bytes",
+ ts_err("failed flash to 0x%05X,size:%u bytes",
subsys_base_addr + offset, data_size);
break;
}
@@ -866,7 +873,7 @@ static int goodix_flash_firmware(struct fw_update_ctrl *fw_ctrl)
/* flash config data first if we have */
if (fw_ctrl->ic_config && fw_ctrl->ic_config->len) {
subsys_cfg.data = fw_ctrl->ic_config->data;
- subsys_cfg.size = fw_ctrl->ic_config->len;
+ subsys_cfg.size = GOODIX_CFG_MAX_SIZE;
subsys_cfg.flash_addr = config_data_reg;
subsys_cfg.type = CONFIG_DATA_TYPE;
r = goodix_flash_subsystem(&subsys_cfg);
@@ -938,10 +945,10 @@ int goodix_fw_update_proc(struct fw_update_ctrl *fwu_ctrl)
if (!(fwu_ctrl->mode & UPDATE_MODE_FORCE)) {
ret = goodix_fw_version_compare(fwu_ctrl);
if (!ret) {
- ts_info("firmware upgraded");
+ ts_info("no need to upgrade");
return 0;
- } else
- ts_info("need to upgrade");
+ }
+ ts_info("need to upgrade");
}
start_update:
@@ -1029,73 +1036,29 @@ static ssize_t goodix_sysfs_update_en_store(struct device *dev,
return -EINVAL;
}
-static ssize_t goodix_sysfs_fwsize_show(
- struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct fw_update_ctrl *fw_ctrl = &goodix_fw_update_ctrl;
- int r = -EINVAL;
-
- if (fw_ctrl && fw_ctrl->fw_data.firmware)
- r = snprintf(buf, PAGE_SIZE, "%zu\n",
- fw_ctrl->fw_data.firmware->size);
- return r;
-}
-
-static ssize_t goodix_sysfs_fwsize_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct fw_update_ctrl *fw_ctrl = &goodix_fw_update_ctrl;
- struct firmware *fw;
- u8 **data;
- size_t size = 0;
-
- if (!fw_ctrl)
- return -EINVAL;
-
- if (sscanf(buf, "%zu", &size) < 0 || !size) {
- ts_err("Failed to get fwsize");
- return -EFAULT;
- }
-
- /* use vmalloc to alloc huge memory */
- fw = vmalloc(sizeof(*fw) + size);
- if (!fw)
- return -ENOMEM;
- mutex_lock(&fw_ctrl->mutex);
- memset(fw, 0x00, sizeof(*fw) + size);
- data = (u8 **)&fw->data;
- *data = (u8 *)fw + sizeof(struct firmware);
- fw->size = size;
- fw_ctrl->fw_data.firmware = fw;
- fw_ctrl->mode = UPDATE_MODE_SRC_SYSFS;
- mutex_unlock(&fw_ctrl->mutex);
- return count;
-}
-
static ssize_t goodix_sysfs_fwimage_store(struct file *file,
struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t pos,
size_t count)
{
- struct fw_update_ctrl *fw_ctrl = &goodix_fw_update_ctrl;
- struct firmware_data *fw_data;
-
- fw_data = &fw_ctrl->fw_data;
-
- if (!fw_data->firmware) {
- ts_err("Need set fw image size first");
- return -ENOMEM;
- }
+ struct firmware **fw = &goodix_fw_update_ctrl.fw_data.fw_sysfs;
- if (fw_data->firmware->size == 0) {
- ts_err("Invalid firmware size");
- return -EINVAL;
+ if (*fw == NULL) {
+ *fw = kzalloc(sizeof(**fw), GFP_KERNEL);
+ if (*fw == NULL)
+ return -ENOMEM;
+ (*fw)->data = vmalloc(GOODIX_FW_MAX_SIEZE);
+ if ((*fw)->data == NULL) {
+ kfree(*fw);
+ *fw = NULL;
+ return -ENOMEM;
+ }
}
- if (pos + count > fw_data->firmware->size)
+ if (pos + count > GOODIX_FW_MAX_SIEZE)
return -EFAULT;
- mutex_lock(&fw_ctrl->mutex);
- memcpy((u8 *)&fw_data->firmware->data[pos], buf, count);
- mutex_unlock(&fw_ctrl->mutex);
+ memcpy((u8 *)&(*fw)->data[pos], buf, count);
+ (*fw)->size = pos + count;
+
return count;
}
@@ -1136,12 +1099,10 @@ static ssize_t goodix_sysfs_result_show(
}
static DEVICE_ATTR(update_en, 0220, NULL, goodix_sysfs_update_en_store);
-static DEVICE_ATTR(
- fwsize, 0664, goodix_sysfs_fwsize_show, goodix_sysfs_fwsize_store);
static DEVICE_ATTR(result, 0664, goodix_sysfs_result_show, NULL);
static struct attribute *goodix_fwu_attrs[] = { &dev_attr_update_en.attr,
- &dev_attr_fwsize.attr, &dev_attr_result.attr };
+ &dev_attr_result.attr };
static int goodix_fw_sysfs_init(
struct goodix_ts_core *core_data, struct fw_update_ctrl *fw_ctrl)
@@ -1168,7 +1129,7 @@ static int goodix_fw_sysfs_init(
}
fw_ctrl->attr_fwimage.attr.name = "fwimage";
- fw_ctrl->attr_fwimage.attr.mode = 0666;
+ fw_ctrl->attr_fwimage.attr.mode = 0664;
fw_ctrl->attr_fwimage.size = 0;
fw_ctrl->attr_fwimage.write = goodix_sysfs_fwimage_store;
ret = sysfs_create_bin_file(fw_ctrl->kobj, &fw_ctrl->attr_fwimage);
@@ -1244,7 +1205,6 @@ static inline void goodix_release_firmware(struct firmware_data *fw_data)
static int goodix_fw_update_thread(void *data)
{
struct fw_update_ctrl *fwu_ctrl = data;
- struct firmware *temp_firmware = NULL;
ktime_t start, end;
int r = -EINVAL;
@@ -1253,37 +1213,45 @@ static int goodix_fw_update_thread(void *data)
fwu_ctrl->status = UPSTA_NOTWORK;
mutex_lock(&fwu_ctrl->mutex);
+ ts_debug("notify update start");
+ goodix_ts_blocking_notify(NOTIFY_FWUPDATE_START, NULL);
+
if (fwu_ctrl->mode & UPDATE_MODE_SRC_REQUEST) {
ts_info("Firmware request update starts");
r = goodix_request_firmware(
&fwu_ctrl->fw_data, fwu_ctrl->fw_name);
if (r < 0)
goto out;
-
} else if (fwu_ctrl->mode & UPDATE_MODE_SRC_SYSFS) {
- if (!fwu_ctrl->fw_data.firmware) {
+ if (!fwu_ctrl->fw_data.fw_sysfs) {
ts_err("Invalid firmware from sysfs");
r = -EINVAL;
goto out;
}
+ if (fwu_ctrl->fw_data.fw_sysfs->size < 4096) {
+ ts_err("Invalid firmware size[%ld] from sysfs",
+ fwu_ctrl->fw_data.fw_sysfs->size);
+ vfree(fwu_ctrl->fw_data.fw_sysfs->data);
+ kfree(fwu_ctrl->fw_data.fw_sysfs);
+ fwu_ctrl->fw_data.fw_sysfs = NULL;
+ r = -EINVAL;
+ goto out;
+ }
} else {
ts_err("unknown update mode 0x%x", fwu_ctrl->mode);
r = -EINVAL;
goto out;
}
- ts_debug("notify update start");
- goodix_ts_blocking_notify(NOTIFY_FWUPDATE_START, NULL);
-
/* ready to update */
ts_debug("start update proc");
r = goodix_fw_update_proc(fwu_ctrl);
/* clean */
- if (fwu_ctrl->mode & UPDATE_MODE_SRC_HEAD) {
- kfree(fwu_ctrl->fw_data.firmware);
- fwu_ctrl->fw_data.firmware = NULL;
- temp_firmware = NULL;
+ if (fwu_ctrl->mode & UPDATE_MODE_SRC_SYSFS) {
+ vfree(fwu_ctrl->fw_data.fw_sysfs->data);
+ kfree(fwu_ctrl->fw_data.fw_sysfs);
+ fwu_ctrl->fw_data.fw_sysfs = NULL;
} else if (fwu_ctrl->mode & UPDATE_MODE_SRC_REQUEST) {
goodix_release_firmware(&fwu_ctrl->fw_data);
}