linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Douglas Anderson <dianders@chromium.org>
To: jkosina@suse.cz, benjamin.tissoires@redhat.com,
	gregkh@linuxfoundation.org
Cc: andrea@borgia.bo.it, kai.heng.feng@canonical.com,
	linux-input@vger.kernel.org, swboyd@chromium.org,
	hdegoede@redhat.com, Douglas Anderson <dianders@chromium.org>,
	Aaron Ma <aaron.ma@canonical.com>,
	Daniel Playfair Cal <daniel.playfair.cal@gmail.com>,
	Jiri Kosina <jikos@kernel.org>, Pavel Balan <admin@kryma.net>,
	Xiaofei Tan <tanxiaofei@huawei.com>,
	You-Sheng Yang <vicamo.yang@canonical.com>,
	linux-kernel@vger.kernel.org
Subject: [PATCH v2 3/3] HID: i2c-hid: Support the Goodix GT7375P touchscreen
Date: Fri, 23 Oct 2020 16:22:54 -0700	[thread overview]
Message-ID: <20201023162220.v2.3.Ied4ce10d229cd7c69abf13a0361ba0b8d82eb9c4@changeid> (raw)
In-Reply-To: <20201023162220.v2.1.I45b53fe84e2215946f900f5b28bab1aa9d029ac7@changeid>

The Goodix GT7375P touchscreen uses i2c-hid so we can support it with
just a few changes to the i2c-hid driver.  Specifically this
touchscreen needs to control a reset GPIO during its power sequencing.

The Goodix timing diagram shows this:

         +----------------------------------
         |
AVDD ----+
               +------------------------------
         | (a) |
RESET ---------+
                     +-------------
               | (b) |
I2C comm OK ---------+

Where (a) is 10 ms and (b) is 120 ms.

While we could just add some properties and specify this generically
in the device tree, the guidance from the device tree maintainer is
that it's better to list the specific model and infer everything from
there.  Thus that's what this patch implements.

Signed-off-by: Douglas Anderson <dianders@chromium.org>
---

Changes in v2:
- Use a separate compatible string for this new touchscreen.
- Get timings based on the compatible string.

 drivers/hid/i2c-hid/i2c-hid-core.c    | 50 ++++++++++++++++++++++++++-
 include/linux/platform_data/i2c-hid.h |  5 +++
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
index 786e3e9af1c9..0b2cd78b05e1 100644
--- a/drivers/hid/i2c-hid/i2c-hid-core.c
+++ b/drivers/hid/i2c-hid/i2c-hid-core.c
@@ -71,6 +71,12 @@ do {									  \
 		dev_printk(KERN_DEBUG, &(ihid)->client->dev, fmt, ##arg); \
 } while (0)
 
+struct i2c_hid_match_data {
+	u16 hid_descriptor_address;
+	int post_power_delay_ms;
+	int post_gpio_reset_delay_ms;
+};
+
 struct i2c_hid_desc {
 	__le16 wHIDDescLength;
 	__le16 bcdVersion;
@@ -962,6 +968,21 @@ static inline void i2c_hid_acpi_enable_wakeup(struct device *dev) {}
 #endif
 
 #ifdef CONFIG_OF
+static bool i2c_hid_init_from_of_match(struct device *dev,
+				       struct i2c_hid_platform_data *pdata)
+{
+	const struct i2c_hid_match_data *match_data = device_get_match_data(dev);
+
+	if (!match_data)
+		return false;
+
+	pdata->hid_descriptor_address = match_data->hid_descriptor_address;
+	pdata->post_power_delay_ms = match_data->post_power_delay_ms;
+	pdata->post_gpio_reset_delay_ms = match_data->post_gpio_reset_delay_ms;
+
+	return true;
+}
+
 static int i2c_hid_of_probe(struct i2c_client *client,
 		struct i2c_hid_platform_data *pdata)
 {
@@ -969,6 +990,11 @@ static int i2c_hid_of_probe(struct i2c_client *client,
 	u32 val;
 	int ret;
 
+	/* Try getting everything based on the compatible string first */
+	if (i2c_hid_init_from_of_match(&client->dev, pdata))
+		return 0;
+
+	/* Fallback to getting hid-descr-addr from a property */
 	ret = of_property_read_u32(dev->of_node, "hid-descr-addr", &val);
 	if (ret) {
 		dev_err(&client->dev, "HID register address not provided\n");
@@ -984,8 +1010,15 @@ static int i2c_hid_of_probe(struct i2c_client *client,
 	return 0;
 }
 
+static const struct i2c_hid_match_data goodix_gt7375p_match_data = {
+	.hid_descriptor_address = 0x0001,
+	.post_power_delay_ms = 10,
+	.post_gpio_reset_delay_ms = 120,
+};
+
 static const struct of_device_id i2c_hid_of_match[] = {
-	{ .compatible = "hid-over-i2c" },
+	{ .compatible = "goodix,gt7375p", .data = &goodix_gt7375p_match_data },
+	{ .compatible = "hid-over-i2c" }, /* Deprecated */
 	{},
 };
 MODULE_DEVICE_TABLE(of, i2c_hid_of_match);
@@ -1053,6 +1086,12 @@ static int i2c_hid_probe(struct i2c_client *client,
 	ihid->pdata.supplies[0].supply = "vdd";
 	ihid->pdata.supplies[1].supply = "vddl";
 
+	/* Start out with reset asserted */
+	ihid->pdata.reset_gpio =
+		devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ihid->pdata.reset_gpio))
+		return PTR_ERR(ihid->pdata.reset_gpio);
+
 	ret = devm_regulator_bulk_get(&client->dev,
 				      ARRAY_SIZE(ihid->pdata.supplies),
 				      ihid->pdata.supplies);
@@ -1067,6 +1106,10 @@ static int i2c_hid_probe(struct i2c_client *client,
 	if (ihid->pdata.post_power_delay_ms)
 		msleep(ihid->pdata.post_power_delay_ms);
 
+	gpiod_set_value_cansleep(ihid->pdata.reset_gpio, 0);
+	if (ihid->pdata.post_gpio_reset_delay_ms)
+		msleep(ihid->pdata.post_gpio_reset_delay_ms);
+
 	i2c_set_clientdata(client, ihid);
 
 	ihid->client = client;
@@ -1163,6 +1206,7 @@ static int i2c_hid_remove(struct i2c_client *client)
 	if (ihid->bufsize)
 		i2c_hid_free_buffers(ihid);
 
+	gpiod_set_value_cansleep(ihid->pdata.reset_gpio, 1);
 	regulator_bulk_disable(ARRAY_SIZE(ihid->pdata.supplies),
 			       ihid->pdata.supplies);
 
@@ -1228,6 +1272,10 @@ static int i2c_hid_resume(struct device *dev)
 
 		if (ihid->pdata.post_power_delay_ms)
 			msleep(ihid->pdata.post_power_delay_ms);
+
+		gpiod_set_value_cansleep(ihid->pdata.reset_gpio, 0);
+		if (ihid->pdata.post_gpio_reset_delay_ms)
+			msleep(ihid->pdata.post_gpio_reset_delay_ms);
 	} else if (ihid->irq_wake_enabled) {
 		wake_status = disable_irq_wake(client->irq);
 		if (!wake_status)
diff --git a/include/linux/platform_data/i2c-hid.h b/include/linux/platform_data/i2c-hid.h
index c628bb5e1061..b2150223ffa6 100644
--- a/include/linux/platform_data/i2c-hid.h
+++ b/include/linux/platform_data/i2c-hid.h
@@ -12,6 +12,7 @@
 #ifndef __LINUX_I2C_HID_H
 #define __LINUX_I2C_HID_H
 
+#include <linux/gpio/consumer.h>
 #include <linux/regulator/consumer.h>
 #include <linux/types.h>
 
@@ -20,6 +21,8 @@
  * @hid_descriptor_address: i2c register where the HID descriptor is stored.
  * @supplies: regulators for powering on the device.
  * @post_power_delay_ms: delay after powering on before device is usable.
+ * @post_gpio_reset_delay_ms: delay after reset via GPIO.
+ * @reset_gpio: optional gpio to de-assert after post_power_delay_ms.
  *
  * Note that it is the responsibility of the platform driver (or the acpi 5.0
  * driver, or the flattened device tree) to setup the irq related to the gpio in
@@ -36,6 +39,8 @@ struct i2c_hid_platform_data {
 	u16 hid_descriptor_address;
 	struct regulator_bulk_data supplies[2];
 	int post_power_delay_ms;
+	int post_gpio_reset_delay_ms;
+	struct gpio_desc *reset_gpio;
 };
 
 #endif /* __LINUX_I2C_HID_H */
-- 
2.29.0.rc1.297.gfa9743e501-goog


  parent reply	other threads:[~2020-10-23 23:23 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-23 23:22 [PATCH v2 1/3] dt-bindings: HID: i2c-hid: Label this binding as deprecated Douglas Anderson
2020-10-23 23:22 ` [PATCH v2 2/3] dt-bindings: HID: i2c-hid: Introduce bindings for the Goodix GT7375P Douglas Anderson
2020-10-23 23:30   ` Doug Anderson
2020-10-30 10:52   ` Benjamin Tissoires
2020-10-23 23:22 ` Douglas Anderson [this message]
2020-10-30 11:01   ` [PATCH v2 3/3] HID: i2c-hid: Support the Goodix GT7375P touchscreen Benjamin Tissoires
2020-10-30 10:51 ` [PATCH v2 1/3] dt-bindings: HID: i2c-hid: Label this binding as deprecated Benjamin Tissoires
2020-10-30 18:00   ` Rob Herring
2020-10-30 19:12     ` Benjamin Tissoires
2020-10-30 20:11       ` Dmitry Torokhov
2020-11-03  0:18       ` Doug Anderson
2020-10-30 16:47 ` Rob Herring
2020-11-03  0:16   ` Doug Anderson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201023162220.v2.3.Ied4ce10d229cd7c69abf13a0361ba0b8d82eb9c4@changeid \
    --to=dianders@chromium.org \
    --cc=aaron.ma@canonical.com \
    --cc=admin@kryma.net \
    --cc=andrea@borgia.bo.it \
    --cc=benjamin.tissoires@redhat.com \
    --cc=daniel.playfair.cal@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=hdegoede@redhat.com \
    --cc=jikos@kernel.org \
    --cc=jkosina@suse.cz \
    --cc=kai.heng.feng@canonical.com \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=swboyd@chromium.org \
    --cc=tanxiaofei@huawei.com \
    --cc=vicamo.yang@canonical.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).