From 84df22401f18c68ddbbe1d2e7b65967bffdd0dc6 Mon Sep 17 00:00:00 2001 From: haojl2 Date: Tue, 2 Jul 2019 12:05:51 +0800 Subject: [PATCH] fpc1020: Add reset function if defined in dts. If dts defined reset pin, kernel driver reset FPC IC. If dts not defined this pin, reset function will do nothing. Change-Id: I59c413c519bd030efa5d3f1ba4a223681db06cdc Signed-off-by: haojl2 Reviewed-on: https://gerrit.mot.com/1379449 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Weilong Wu Reviewed-by: Lei Chen Reviewed-by: Jianqi Yang Submit-Approved: Jira Key --- drivers/input/misc/fpc_fps_mmi/fpc1020_tee.c | 72 ++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/drivers/input/misc/fpc_fps_mmi/fpc1020_tee.c b/drivers/input/misc/fpc_fps_mmi/fpc1020_tee.c index 77070c9ba616..140a0c210a41 100644 --- a/drivers/input/misc/fpc_fps_mmi/fpc1020_tee.c +++ b/drivers/input/misc/fpc_fps_mmi/fpc1020_tee.c @@ -21,6 +21,13 @@ #include #include +#define RESET_LOW_SLEEP_MIN_US 5000 +#define RESET_LOW_SLEEP_MAX_US (RESET_LOW_SLEEP_MIN_US + 100) +#define RESET_HIGH_SLEEP1_MIN_US 100 +#define RESET_HIGH_SLEEP1_MAX_US (RESET_HIGH_SLEEP1_MIN_US + 100) +#define RESET_HIGH_SLEEP2_MIN_US 5000 +#define RESET_HIGH_SLEEP2_MAX_US (RESET_HIGH_SLEEP2_MIN_US + 100) + struct FPS_data { unsigned int enabled; unsigned int state; @@ -119,8 +126,54 @@ struct fpc1020_data { int irq_gpio; int irq_num; unsigned int irq_cnt; + int rst_gpio; }; +static int hw_reset(struct fpc1020_data *fpc1020) +{ + int irq_gpio; + struct device *dev = fpc1020->dev; + int rc = 0; + + if (!gpio_is_valid(fpc1020->rst_gpio)) { + dev_warn(dev, "reset pin is invalid\n"); + goto exit; + } + + rc = gpio_direction_output(fpc1020->rst_gpio, 1); + if (rc) + goto exit; + usleep_range(RESET_HIGH_SLEEP1_MIN_US, RESET_HIGH_SLEEP1_MAX_US); + + rc = gpio_direction_output(fpc1020->rst_gpio, 0); + if (rc) + goto exit; + usleep_range(RESET_LOW_SLEEP_MIN_US, RESET_LOW_SLEEP_MAX_US); + + rc = gpio_direction_output(fpc1020->rst_gpio, 1); + if (rc) + goto exit; + usleep_range(RESET_HIGH_SLEEP2_MIN_US, RESET_HIGH_SLEEP2_MAX_US); + + irq_gpio = gpio_get_value(fpc1020->irq_gpio); + dev_info(dev, "IRQ after reset %d\n", irq_gpio); + +exit: + return rc; +} + +static ssize_t hw_reset_set(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int rc; + struct fpc1020_data *fpc1020 = dev_get_drvdata(dev); + + rc = hw_reset(fpc1020); + + return rc ? rc : count; +} +static DEVICE_ATTR(hw_reset, S_IWUSR, NULL, hw_reset_set); + static ssize_t dev_enable_set(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -176,6 +229,7 @@ static struct attribute *attributes[] = { &dev_attr_dev_enable.attr, &dev_attr_irq.attr, &dev_attr_irq_cnt.attr, + &dev_attr_hw_reset.attr, #ifdef CONFIG_INPUT_MISC_FPC1020_SAVE_TO_CLASS_DEVICE &dev_attr_vendor.attr, &dev_attr_modalias.attr, @@ -219,6 +273,10 @@ static int fpc1020_request_named_gpio(struct fpc1020_data *fpc1020, int rc; *gpio = of_get_named_gpio(np, label, 0); + if (!gpio_is_valid(*gpio)) { + dev_err(dev, "gpio %s is invalid\n", label); + return -EINVAL; + } rc = devm_gpio_request(dev, *gpio, label); if (rc) { dev_err(dev, "failed to request gpio %d\n", *gpio); @@ -306,6 +364,20 @@ static int fpc1020_probe(struct platform_device *pdev) if (rc) goto exit; + rc = fpc1020_request_named_gpio(fpc1020, "rst", + &fpc1020->rst_gpio); + if (rc) + fpc1020->rst_gpio = -EINVAL; + + if (gpio_is_valid(fpc1020->rst_gpio)) { + usleep_range(RESET_LOW_SLEEP_MIN_US, RESET_LOW_SLEEP_MAX_US); + rc = gpio_direction_output(fpc1020->rst_gpio, 1); + if (rc) { + dev_err(dev, "cannot set reset pin direction\n"); + goto exit; + } + } + rc = device_init_wakeup(fpc1020->dev, true); if (rc) goto exit;