From 2309496836b032729c6e1b3bf2ba338a7f840e4b Mon Sep 17 00:00:00 2001 From: Shantanu Jain Date: Tue, 19 Nov 2013 09:52:24 +0530 Subject: [PATCH] input: touchscreen: Add firmware upgrade via sysfs entry Add sysfs entry for firmware upgrade support in Goodix driver. CRs-fixed: 575618 Change-Id: If71d4020223547e0db425c9fd37819c6166efcab Signed-off-by: Shantanu Jain --- drivers/input/touchscreen/gt9xx/gt9xx.c | 75 +++++++++++++++++++++---- drivers/input/touchscreen/gt9xx/gt9xx.h | 5 +- 2 files changed, 67 insertions(+), 13 deletions(-) diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c index a71526a3186..d03a205b8a0 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx.c +++ b/drivers/input/touchscreen/gt9xx/gt9xx.c @@ -1528,12 +1528,62 @@ static ssize_t gtp_fw_name_store(struct device *dev, return size; } +static ssize_t gtp_fw_upgrade_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct goodix_ts_data *ts = dev_get_drvdata(dev); + return snprintf(buf, 2, "%d\n", ts->fw_loading); +} + +static ssize_t gtp_fw_upgrade_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct goodix_ts_data *ts = dev_get_drvdata(dev); + unsigned long val; + int ret; + + if (size > 2) + return -EINVAL; + + ret = kstrtoul(buf, 10, &val); + if (ret != 0) + return ret; + + if (ts->gtp_is_suspend) { + dev_err(&ts->client->dev, + "Can't start fw upgrade. Device is in suspend state."); + return -EBUSY; + } + + mutex_lock(&ts->input_dev->mutex); + if (!ts->fw_loading && val) { + disable_irq(ts->client->irq); + ts->fw_loading = true; + if (config_enabled(CONFIG_GT9XX_TOUCHPANEL_UPDATE)) { + ret = gup_update_proc(NULL); + if (ret == FAIL) + dev_err(&ts->client->dev, + "Fail to update GTP firmware.\n"); + } + ts->fw_loading = false; + enable_irq(ts->client->irq); + } + mutex_unlock(&ts->input_dev->mutex); + + return size; +} + static DEVICE_ATTR(fw_name, (S_IRUGO | S_IWUSR | S_IWGRP), gtp_fw_name_show, gtp_fw_name_store); +static DEVICE_ATTR(fw_upgrade, (S_IRUGO | S_IWUSR | S_IWGRP), + gtp_fw_upgrade_show, + gtp_fw_upgrade_store); static struct attribute *gtp_attrs[] = { &dev_attr_fw_name.attr, + &dev_attr_fw_upgrade.attr, NULL }; @@ -1771,9 +1821,7 @@ static int goodix_ts_probe(struct i2c_client *client, return -EINVAL; } -#if GTP_ESD_PROTECT i2c_connect_client = client; -#endif if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { dev_err(&client->dev, "GTP I2C not supported\n"); @@ -1827,15 +1875,14 @@ static int goodix_ts_probe(struct i2c_client *client, strlcpy(ts->fw_name, pdata->fw_name, strlen(pdata->fw_name) + 1); -#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE - ret = gup_init_update_proc(ts); - if (ret < 0) { - dev_err(&client->dev, - "GTP Create firmware update thread error.\n"); - goto exit_power_off; + if (config_enabled(CONFIG_GT9XX_TOUCHPANEL_UPDATE)) { + ret = gup_init_update_proc(ts); + if (ret < 0) { + dev_err(&client->dev, + "GTP Create firmware update thread error.\n"); + goto exit_power_off; + } } -#endif - ret = gtp_init_panel(ts); if (ret < 0) { dev_err(&client->dev, "GTP init panel failed.\n"); @@ -2032,6 +2079,14 @@ static int goodix_ts_suspend(struct device *dev) } mutex_lock(&ts->lock); + + if (ts->fw_loading) { + dev_info(&ts->client->dev, + "Fw upgrade in progress, can't go to suspend."); + mutex_unlock(&ts->lock); + return 0; + } + #if GTP_ESD_PROTECT gtp_esd_switch(ts->client, SWITCH_OFF); #endif diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.h b/drivers/input/touchscreen/gt9xx/gt9xx.h index 4d656ddc605..c509d2b3e84 100644 --- a/drivers/input/touchscreen/gt9xx/gt9xx.h +++ b/drivers/input/touchscreen/gt9xx/gt9xx.h @@ -92,6 +92,7 @@ struct goodix_ts_data { u8 fw_error; bool power_on; struct mutex lock; + bool fw_loading; struct regulator *avdd; struct regulator *vdd; struct regulator *vcc_i2c; @@ -215,11 +216,9 @@ s32 init_wr_node(struct i2c_client *client); void uninit_wr_node(void); #endif -#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE -extern u8 gup_init_update_proc(struct goodix_ts_data *ts); +u8 gup_init_update_proc(struct goodix_ts_data *ts); s32 gup_enter_update_mode(struct i2c_client *client); void gup_leave_update_mode(struct i2c_client *client); s32 gup_update_proc(void *dir); extern struct i2c_client *i2c_connect_client; -#endif #endif /* _GOODIX_GT9XX_H_ */