linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3] Input: tsc2007 - enable GPIO chips that can sleep
@ 2023-03-28 15:31 Benjamin Bara
  0 siblings, 0 replies; only message in thread
From: Benjamin Bara @ 2023-03-28 15:31 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: richard.leitner, christophe.jaillet, linux-input, linux-kernel,
	Benjamin Bara, Richard Leitner

From: Benjamin Bara <benjamin.bara@skidata.com>

This enables the usage of "can_sleep" GPIO chips as "pin up" GPIO.
This might be the case if the GPIO chip is an expander behind i2c.

As the pendown value is read during a hard IRQ, the read process is not
allowed to sleep. Therefore, find out if the read process can sleep and
if so, just return true. During the following soft IRQ, the read process
is allowed to sleep and therefore the actual value can be read.

Signed-off-by: Benjamin Bara <benjamin.bara@skidata.com>
Signed-off-by: Richard Leitner <richard.leitner@skidata.com>
---
This is basically a resend of v2 with extended commit message.

v2: https://lore.kernel.org/lkml/20220715074534.3116678-1-bbara93@gmail.com/

----
v3:
- extend commit message

v2:
- fix style mentioned by Christophe
---
 drivers/input/touchscreen/tsc2007.h      |  1 +
 drivers/input/touchscreen/tsc2007_core.c | 34 +++++++++++++++++++++++++++-----
 2 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/drivers/input/touchscreen/tsc2007.h b/drivers/input/touchscreen/tsc2007.h
index 69b08dd6c8df..cdd90d727160 100644
--- a/drivers/input/touchscreen/tsc2007.h
+++ b/drivers/input/touchscreen/tsc2007.h
@@ -78,6 +78,7 @@ struct tsc2007 {
 	bool			stopped;
 
 	int			(*get_pendown_state)(struct device *);
+	int			(*get_pendown_state_cansleep)(struct device *dev);
 	void			(*clear_penirq)(void);
 
 	struct mutex		mlock;
diff --git a/drivers/input/touchscreen/tsc2007_core.c b/drivers/input/touchscreen/tsc2007_core.c
index 3c793fb70a0e..764cec1036e1 100644
--- a/drivers/input/touchscreen/tsc2007_core.c
+++ b/drivers/input/touchscreen/tsc2007_core.c
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
@@ -108,6 +109,14 @@ bool tsc2007_is_pen_down(struct tsc2007 *ts)
 	return ts->get_pendown_state(&ts->client->dev);
 }
 
+static bool tsc2007_is_pen_down_cansleep(struct tsc2007 *ts)
+{
+	if (!ts->get_pendown_state_cansleep)
+		return true;
+
+	return ts->get_pendown_state_cansleep(&ts->client->dev);
+}
+
 static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
 {
 	struct tsc2007 *ts = handle;
@@ -115,7 +124,7 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
 	struct ts_event tc;
 	u32 rt;
 
-	while (!ts->stopped && tsc2007_is_pen_down(ts)) {
+	while (!ts->stopped && tsc2007_is_pen_down_cansleep(ts)) {
 
 		/* pen is down, continue with the measurement */
 
@@ -125,7 +134,7 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
 
 		rt = tsc2007_calculate_resistance(ts, &tc);
 
-		if (!rt && !ts->get_pendown_state) {
+		if (!rt && !ts->get_pendown_state_cansleep) {
 			/*
 			 * If pressure reported is 0 and we don't have
 			 * callback to check pendown state, we have to
@@ -229,6 +238,14 @@ static int tsc2007_get_pendown_state_gpio(struct device *dev)
 	return gpiod_get_value(ts->gpiod);
 }
 
+static int tsc2007_get_pendown_state_gpio_cansleep(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct tsc2007 *ts = i2c_get_clientdata(client);
+
+	return gpiod_get_value_cansleep(ts->gpiod);
+}
+
 static int tsc2007_probe_properties(struct device *dev, struct tsc2007 *ts)
 {
 	u32 val32;
@@ -264,10 +281,17 @@ static int tsc2007_probe_properties(struct device *dev, struct tsc2007 *ts)
 	if (IS_ERR(ts->gpiod))
 		return PTR_ERR(ts->gpiod);
 
-	if (ts->gpiod)
-		ts->get_pendown_state = tsc2007_get_pendown_state_gpio;
-	else
+	if (ts->gpiod) {
+		ts->get_pendown_state_cansleep = tsc2007_get_pendown_state_gpio_cansleep;
+
+		/* pendown pin is read during hard irq -> gpio chip is not allowed to sleep */
+		if (gpiod_to_chip(ts->gpiod) && !gpiod_to_chip(ts->gpiod)->can_sleep)
+			ts->get_pendown_state = tsc2007_get_pendown_state_gpio;
+		else
+			dev_dbg(dev, "Pen down GPIO chip can sleep\n");
+	} else {
 		dev_warn(dev, "Pen down GPIO is not specified in properties\n");
+	}
 
 	return 0;
 }

---
base-commit: 197b6b60ae7bc51dd0814953c562833143b292aa
change-id: 20230328-tsc2007-sleep-f65953ae32d0

Best regards,
-- 
Benjamin Bara <benjamin.bara@skidata.com>


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2023-03-28 15:32 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-28 15:31 [PATCH v3] Input: tsc2007 - enable GPIO chips that can sleep Benjamin Bara

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).