From 5a89916df2c8d2635b82a457cd4945dd73c1de3c Mon Sep 17 00:00:00 2001 From: Nick Dyer Date: Tue, 31 Jan 2017 15:25:56 -0800 Subject: [PATCH] Input: synaptics-rmi4 - add sysfs attribute update_fw_status The attribute returns the percentage complete. If the firmware update fails, it reports a negative error code. Signed-off-by: Nick Dyer Tested-by: Chris Healy Acked-by: Benjamin Tissoires Signed-off-by: Dmitry Torokhov --- drivers/input/rmi4/rmi_f34.c | 92 ++++++++++++++++++++++++---------- drivers/input/rmi4/rmi_f34.h | 4 ++ drivers/input/rmi4/rmi_f34v7.c | 11 ++++ 3 files changed, 80 insertions(+), 27 deletions(-) diff --git a/drivers/input/rmi4/rmi_f34.c b/drivers/input/rmi4/rmi_f34.c index c3285cefe9b6..902b99007885 100644 --- a/drivers/input/rmi4/rmi_f34.c +++ b/drivers/input/rmi4/rmi_f34.c @@ -157,6 +157,9 @@ static int rmi_f34_write_blocks(struct f34_data *f34, const void *data, i + 1, block_count); data += f34->v5.block_size; + f34->update_progress += f34->v5.block_size; + f34->update_status = (f34->update_progress * 100) / + f34->update_size; } return 0; @@ -174,7 +177,7 @@ static int rmi_f34_write_config(struct f34_data *f34, const void *data) F34_WRITE_CONFIG_BLOCK); } -int rmi_f34_enable_flash(struct f34_data *f34) +static int rmi_f34_enable_flash(struct f34_data *f34) { return rmi_f34_command(f34, F34_ENABLE_FLASH_PROG, F34_ENABLE_WAIT_MS, true); @@ -184,9 +187,14 @@ static int rmi_f34_flash_firmware(struct f34_data *f34, const struct rmi_f34_firmware *syn_fw) { struct rmi_function *fn = f34->fn; + u32 image_size = le32_to_cpu(syn_fw->image_size); + u32 config_size = le32_to_cpu(syn_fw->config_size); int ret; - if (syn_fw->image_size) { + f34->update_progress = 0; + f34->update_size = image_size + config_size; + + if (image_size) { dev_info(&fn->dev, "Erasing firmware...\n"); ret = rmi_f34_command(f34, F34_ERASE_ALL, F34_ERASE_WAIT_MS, true); @@ -194,18 +202,18 @@ static int rmi_f34_flash_firmware(struct f34_data *f34, return ret; dev_info(&fn->dev, "Writing firmware (%d bytes)...\n", - syn_fw->image_size); + image_size); ret = rmi_f34_write_firmware(f34, syn_fw->data); if (ret) return ret; } - if (syn_fw->config_size) { + if (config_size) { /* * We only need to erase config if we haven't updated * firmware. */ - if (!syn_fw->image_size) { + if (!image_size) { dev_info(&fn->dev, "Erasing config...\n"); ret = rmi_f34_command(f34, F34_ERASE_CONFIG, F34_ERASE_WAIT_MS, true); @@ -214,9 +222,8 @@ static int rmi_f34_flash_firmware(struct f34_data *f34, } dev_info(&fn->dev, "Writing config (%d bytes)...\n", - syn_fw->config_size); - ret = rmi_f34_write_config(f34, - &syn_fw->data[syn_fw->image_size]); + config_size); + ret = rmi_f34_write_config(f34, &syn_fw->data[image_size]); if (ret) return ret; } @@ -224,21 +231,23 @@ static int rmi_f34_flash_firmware(struct f34_data *f34, return 0; } -int rmi_f34_update_firmware(struct f34_data *f34, const struct firmware *fw) +static int rmi_f34_update_firmware(struct f34_data *f34, + const struct firmware *fw) { - const struct rmi_f34_firmware *syn_fw; + const struct rmi_f34_firmware *syn_fw = + (const struct rmi_f34_firmware *)fw->data; + u32 image_size = le32_to_cpu(syn_fw->image_size); + u32 config_size = le32_to_cpu(syn_fw->config_size); int ret; - syn_fw = (const struct rmi_f34_firmware *)fw->data; BUILD_BUG_ON(offsetof(struct rmi_f34_firmware, data) != F34_FW_IMAGE_OFFSET); rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, - "FW size:%d, checksum:%08x, image_size:%d, config_size:%d\n", - (int)fw->size, + "FW size:%zd, checksum:%08x, image_size:%d, config_size:%d\n", + fw->size, le32_to_cpu(syn_fw->checksum), - le32_to_cpu(syn_fw->image_size), - le32_to_cpu(syn_fw->config_size)); + image_size, config_size); rmi_dbg(RMI_DEBUG_FN, &f34->fn->dev, "FW bootloader_id:%02x, product_id:%.*s, info: %02x%02x\n", @@ -246,27 +255,25 @@ int rmi_f34_update_firmware(struct f34_data *f34, const struct firmware *fw) (int)sizeof(syn_fw->product_id), syn_fw->product_id, syn_fw->product_info[0], syn_fw->product_info[1]); - if (syn_fw->image_size && - syn_fw->image_size != f34->v5.fw_blocks * f34->v5.block_size) { + if (image_size && image_size != f34->v5.fw_blocks * f34->v5.block_size) { dev_err(&f34->fn->dev, "Bad firmware image: fw size %d, expected %d\n", - syn_fw->image_size, - f34->v5.fw_blocks * f34->v5.block_size); + image_size, f34->v5.fw_blocks * f34->v5.block_size); ret = -EILSEQ; goto out; } - if (syn_fw->config_size && - syn_fw->config_size != f34->v5.config_blocks * f34->v5.block_size) { + if (config_size && + config_size != f34->v5.config_blocks * f34->v5.block_size) { dev_err(&f34->fn->dev, "Bad firmware image: config size %d, expected %d\n", - syn_fw->config_size, + config_size, f34->v5.config_blocks * f34->v5.block_size); ret = -EILSEQ; goto out; } - if (syn_fw->image_size && !syn_fw->config_size) { + if (image_size && !config_size) { dev_err(&f34->fn->dev, "Bad firmware image: no config data\n"); ret = -EILSEQ; goto out; @@ -283,6 +290,17 @@ out: return ret; } +static int rmi_f34_status(struct rmi_function *fn) +{ + struct f34_data *f34 = dev_get_drvdata(&fn->dev); + + /* + * The status is the percentage complete, or once complete, + * zero for success or a negative return code. + */ + return f34->update_status; +} + static int rmi_firmware_update(struct rmi_driver_data *data, const struct firmware *fw) { @@ -346,7 +364,13 @@ static int rmi_firmware_update(struct rmi_driver_data *data, else ret = rmi_f34_update_firmware(f34, fw); - dev_info(&f34->fn->dev, "Firmware update complete, status:%d\n", ret); + if (ret) { + f34->update_status = ret; + dev_err(&f34->fn->dev, + "Firmware update failed, status: %d\n", ret); + } else { + dev_info(&f34->fn->dev, "Firmware update complete\n"); + } rmi_disable_irq(rmi_dev, false); @@ -377,9 +401,6 @@ static int rmi_firmware_update(struct rmi_driver_data *data, return ret; } -static int rmi_firmware_update(struct rmi_driver_data *data, - const struct firmware *fw); - static ssize_t rmi_driver_update_fw_store(struct device *dev, struct device_attribute *dattr, const char *buf, size_t count) @@ -414,8 +435,25 @@ static ssize_t rmi_driver_update_fw_store(struct device *dev, static DEVICE_ATTR(update_fw, 0200, NULL, rmi_driver_update_fw_store); +static ssize_t rmi_driver_update_fw_status_show(struct device *dev, + struct device_attribute *dattr, + char *buf) +{ + struct rmi_driver_data *data = dev_get_drvdata(dev); + int update_status = 0; + + if (data->f34_container) + update_status = rmi_f34_status(data->f34_container); + + return scnprintf(buf, PAGE_SIZE, "%d\n", update_status); +} + +static DEVICE_ATTR(update_fw_status, 0444, + rmi_driver_update_fw_status_show, NULL); + static struct attribute *rmi_firmware_attrs[] = { &dev_attr_update_fw.attr, + &dev_attr_update_fw_status.attr, NULL }; diff --git a/drivers/input/rmi4/rmi_f34.h b/drivers/input/rmi4/rmi_f34.h index 2c21056dc375..43a91349b28d 100644 --- a/drivers/input/rmi4/rmi_f34.h +++ b/drivers/input/rmi4/rmi_f34.h @@ -301,6 +301,10 @@ struct f34_data { unsigned char bootloader_id[5]; unsigned char configuration_id[CONFIG_ID_SIZE*2 + 1]; + int update_status; + int update_progress; + int update_size; + union { struct f34v5_data v5; struct f34v7_data v7; diff --git a/drivers/input/rmi4/rmi_f34v7.c b/drivers/input/rmi4/rmi_f34v7.c index ca31f9539d9b..56c6c39ad31e 100644 --- a/drivers/input/rmi4/rmi_f34v7.c +++ b/drivers/input/rmi4/rmi_f34v7.c @@ -588,6 +588,7 @@ static int rmi_f34v7_check_ui_firmware_size(struct f34_data *f34) u16 block_count; block_count = f34->v7.img.ui_firmware.size / f34->v7.block_size; + f34->update_size += block_count; if (block_count != f34->v7.blkcount.ui_firmware) { dev_err(&f34->fn->dev, @@ -604,6 +605,7 @@ static int rmi_f34v7_check_ui_config_size(struct f34_data *f34) u16 block_count; block_count = f34->v7.img.ui_config.size / f34->v7.block_size; + f34->update_size += block_count; if (block_count != f34->v7.blkcount.ui_config) { dev_err(&f34->fn->dev, "UI config size mismatch\n"); @@ -618,6 +620,7 @@ static int rmi_f34v7_check_dp_config_size(struct f34_data *f34) u16 block_count; block_count = f34->v7.img.dp_config.size / f34->v7.block_size; + f34->update_size += block_count; if (block_count != f34->v7.blkcount.dp_config) { dev_err(&f34->fn->dev, "Display config size mismatch\n"); @@ -632,6 +635,8 @@ static int rmi_f34v7_check_guest_code_size(struct f34_data *f34) u16 block_count; block_count = f34->v7.img.guest_code.size / f34->v7.block_size; + f34->update_size += block_count; + if (block_count != f34->v7.blkcount.guest_code) { dev_err(&f34->fn->dev, "Guest code size mismatch\n"); return -EINVAL; @@ -645,6 +650,7 @@ static int rmi_f34v7_check_bl_config_size(struct f34_data *f34) u16 block_count; block_count = f34->v7.img.bl_config.size / f34->v7.block_size; + f34->update_size += block_count; if (block_count != f34->v7.blkcount.bl_config) { dev_err(&f34->fn->dev, "Bootloader config size mismatch\n"); @@ -881,6 +887,9 @@ static int rmi_f34v7_write_f34v7_blocks(struct f34_data *f34, block_ptr += (transfer * f34->v7.block_size); remaining -= transfer; + f34->update_progress += transfer; + f34->update_status = (f34->update_progress * 100) / + f34->update_size; } while (remaining); return 0; @@ -1191,6 +1200,8 @@ int rmi_f34v7_do_reflash(struct f34_data *f34, const struct firmware *fw) rmi_f34v7_read_queries_bl_version(f34); f34->v7.image = fw->data; + f34->update_progress = 0; + f34->update_size = 0; ret = rmi_f34v7_parse_image_info(f34); if (ret < 0) -- 2.20.1