diff options
author | Wendly Li <wendlyli@google.com> | 2022-01-06 07:52:19 +0000 |
---|---|---|
committer | Wendly Li <wendlyli@google.com> | 2022-01-21 03:53:14 +0000 |
commit | 0f9e7e8f390c3d06c81cac7c2a94d341a25cd896 (patch) | |
tree | 582bc6c608ebec8cfbf4631c00ee7c17970665b5 /goodix_brl_fwupdate.c | |
parent | f4cbd1e784f777c544763bb0e2bdb65ad5c685cf (diff) | |
download | goodix_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.c | 138 |
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); } |