All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexandre Hamamdjian <azkali.limited@gmail.com>
To: Dmitry Torokhov <dmitry.torokhov@gmail.com>,
	 Henrik Rydberg <rydberg@bitmath.org>,
	Rob Herring <robh@kernel.org>,
	 Krzysztof Kozlowski <krzk+dt@kernel.org>,
	 Conor Dooley <conor+dt@kernel.org>
Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
	 devicetree@vger.kernel.org,
	Alexandre Hamamdjian <azkali.limited@gmail.com>,
	 Teguh Sobirin <teguh@sobir.in>
Subject: [PATCH 3/4] Input: edt-ft5x06 - allow reading the touch frame one register at a time
Date: Thu, 23 Jul 2026 18:27:10 +0700	[thread overview]
Message-ID: <20260723-b4-ft5426-v1-3-d4b4e32be042@gmail.com> (raw)
In-Reply-To: <20260723-b4-ft5426-v1-0-d4b4e32be042@gmail.com>

From: Teguh Sobirin <teguh@sobir.in>

Every touch interrupt reads the whole touch frame in a single i2c block
read via regmap_bulk_read(). On some boards the i2c controller the panel
is wired to cannot sustain that multi-byte transfer: on the AYANEO Pocket
DS the FocalTech FT5426 sits on a marginal Qualcomm GENI bus that
intermittently aborts a long read with -EAGAIN or -ETIMEDOUT, and the
GENI controller has no bus recovery, so the block read fails on nearly
every interrupt and the panel is unusable.

Honour the "no-regmap-bulk-read" property. When set, the driver reads the
frame one register at a time with a short retry on the transient bus
errors, keeping each transfer small enough to complete. Boards on a
healthy bus keep using the single bulk transfer and are unaffected.

Signed-off-by: Teguh Sobirin <teguh@sobir.in>
Co-developed-by: Alexandre Hamamdjian <azkali.limited@gmail.com>
Signed-off-by: Alexandre Hamamdjian <azkali.limited@gmail.com>
---
 drivers/input/touchscreen/edt-ft5x06.c | 37 ++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index d6c3d033b83d..ac61ac44fd64 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -146,6 +146,7 @@ struct edt_ft5x06_ts_data {
 	enum edt_ver version;
 	unsigned int crc_errors;
 	unsigned int header_errors;
+	bool no_regmap_bulk_read;
 };
 
 struct edt_i2c_chip_data {
@@ -295,6 +296,31 @@ static const struct regmap_config edt_M06_i2c_regmap_config = {
 	.write = edt_M06_i2c_write,
 };
 
+static int edt_ft5x06_bulk_read(struct regmap *map, unsigned int start,
+				void *val, size_t len)
+{
+	u8 *dst = val;
+	size_t off;
+
+	for (off = 0; off < len; off++) {
+		unsigned int v;
+		int ret, tries;
+
+		for (tries = 0; tries < 3; tries++) {
+			ret = regmap_read(map, start + off, &v);
+			if (!ret)
+				break;
+			if (ret == -ETIMEDOUT || ret == -EAGAIN)
+				usleep_range(2000, 4000);
+		}
+		if (ret)
+			return ret;
+		dst[off] = v;
+	}
+
+	return 0;
+}
+
 static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
 {
 	struct edt_ft5x06_ts_data *tsdata = dev_id;
@@ -304,8 +330,12 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
 	int error;
 
 	memset(rdbuf, 0, sizeof(rdbuf));
-	error = regmap_bulk_read(tsdata->regmap, tsdata->tdata_cmd, rdbuf,
-				 tsdata->tdata_len);
+	if (tsdata->no_regmap_bulk_read)
+		error = edt_ft5x06_bulk_read(tsdata->regmap, tsdata->tdata_cmd,
+					     rdbuf, tsdata->tdata_len);
+	else
+		error = regmap_bulk_read(tsdata->regmap, tsdata->tdata_cmd,
+					 rdbuf, tsdata->tdata_len);
 	if (error) {
 		dev_err_ratelimited(dev, "Unable to fetch data, error: %d\n",
 				    error);
@@ -1212,6 +1242,9 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
 		return error;
 	}
 
+	tsdata->no_regmap_bulk_read =
+		device_property_read_bool(&client->dev, "no-regmap-bulk-read");
+
 	/*
 	 * Check which sleep modes we can support. Power-off requires the
 	 * reset-pin to ensure correct power-down/power-up behaviour. Start with

-- 
2.55.0


WARNING: multiple messages have this Message-ID (diff)
From: Alexandre Hamamdjian via B4 Relay <devnull+azkali.limited.gmail.com@kernel.org>
To: Dmitry Torokhov <dmitry.torokhov@gmail.com>,
	 Henrik Rydberg <rydberg@bitmath.org>,
	Rob Herring <robh@kernel.org>,
	 Krzysztof Kozlowski <krzk+dt@kernel.org>,
	 Conor Dooley <conor+dt@kernel.org>
Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
	 devicetree@vger.kernel.org,
	Alexandre Hamamdjian <azkali.limited@gmail.com>,
	 Teguh Sobirin <teguh@sobir.in>
Subject: [PATCH 3/4] Input: edt-ft5x06 - allow reading the touch frame one register at a time
Date: Thu, 23 Jul 2026 18:27:10 +0700	[thread overview]
Message-ID: <20260723-b4-ft5426-v1-3-d4b4e32be042@gmail.com> (raw)
In-Reply-To: <20260723-b4-ft5426-v1-0-d4b4e32be042@gmail.com>

From: Teguh Sobirin <teguh@sobir.in>

Every touch interrupt reads the whole touch frame in a single i2c block
read via regmap_bulk_read(). On some boards the i2c controller the panel
is wired to cannot sustain that multi-byte transfer: on the AYANEO Pocket
DS the FocalTech FT5426 sits on a marginal Qualcomm GENI bus that
intermittently aborts a long read with -EAGAIN or -ETIMEDOUT, and the
GENI controller has no bus recovery, so the block read fails on nearly
every interrupt and the panel is unusable.

Honour the "no-regmap-bulk-read" property. When set, the driver reads the
frame one register at a time with a short retry on the transient bus
errors, keeping each transfer small enough to complete. Boards on a
healthy bus keep using the single bulk transfer and are unaffected.

Signed-off-by: Teguh Sobirin <teguh@sobir.in>
Co-developed-by: Alexandre Hamamdjian <azkali.limited@gmail.com>
Signed-off-by: Alexandre Hamamdjian <azkali.limited@gmail.com>
---
 drivers/input/touchscreen/edt-ft5x06.c | 37 ++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index d6c3d033b83d..ac61ac44fd64 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -146,6 +146,7 @@ struct edt_ft5x06_ts_data {
 	enum edt_ver version;
 	unsigned int crc_errors;
 	unsigned int header_errors;
+	bool no_regmap_bulk_read;
 };
 
 struct edt_i2c_chip_data {
@@ -295,6 +296,31 @@ static const struct regmap_config edt_M06_i2c_regmap_config = {
 	.write = edt_M06_i2c_write,
 };
 
+static int edt_ft5x06_bulk_read(struct regmap *map, unsigned int start,
+				void *val, size_t len)
+{
+	u8 *dst = val;
+	size_t off;
+
+	for (off = 0; off < len; off++) {
+		unsigned int v;
+		int ret, tries;
+
+		for (tries = 0; tries < 3; tries++) {
+			ret = regmap_read(map, start + off, &v);
+			if (!ret)
+				break;
+			if (ret == -ETIMEDOUT || ret == -EAGAIN)
+				usleep_range(2000, 4000);
+		}
+		if (ret)
+			return ret;
+		dst[off] = v;
+	}
+
+	return 0;
+}
+
 static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
 {
 	struct edt_ft5x06_ts_data *tsdata = dev_id;
@@ -304,8 +330,12 @@ static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
 	int error;
 
 	memset(rdbuf, 0, sizeof(rdbuf));
-	error = regmap_bulk_read(tsdata->regmap, tsdata->tdata_cmd, rdbuf,
-				 tsdata->tdata_len);
+	if (tsdata->no_regmap_bulk_read)
+		error = edt_ft5x06_bulk_read(tsdata->regmap, tsdata->tdata_cmd,
+					     rdbuf, tsdata->tdata_len);
+	else
+		error = regmap_bulk_read(tsdata->regmap, tsdata->tdata_cmd,
+					 rdbuf, tsdata->tdata_len);
 	if (error) {
 		dev_err_ratelimited(dev, "Unable to fetch data, error: %d\n",
 				    error);
@@ -1212,6 +1242,9 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client)
 		return error;
 	}
 
+	tsdata->no_regmap_bulk_read =
+		device_property_read_bool(&client->dev, "no-regmap-bulk-read");
+
 	/*
 	 * Check which sleep modes we can support. Power-off requires the
 	 * reset-pin to ensure correct power-down/power-up behaviour. Start with

-- 
2.55.0



  parent reply	other threads:[~2026-07-23 11:27 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-23 11:27 [PATCH 0/4] Input: edt-ft5x06: robustness fixes for a FocalTech FT5426 on a marginal bus Alexandre Hamamdjian
2026-07-23 11:27 ` Alexandre Hamamdjian via B4 Relay
2026-07-23 11:27 ` [PATCH 1/4] Input: edt-ft5x06 - ignore contacts with an out-of-range slot id Alexandre Hamamdjian
2026-07-23 11:27   ` Alexandre Hamamdjian via B4 Relay
2026-07-23 11:40   ` sashiko-bot
2026-07-23 17:45     ` Dmitry Torokhov
2026-07-23 11:27 ` [PATCH 2/4] dt-bindings: input: edt-ft5x06 - add no-regmap-bulk-read property Alexandre Hamamdjian
2026-07-23 11:27   ` Alexandre Hamamdjian via B4 Relay
2026-07-23 11:35   ` sashiko-bot
2026-07-23 15:56   ` Conor Dooley
2026-07-23 11:27 ` Alexandre Hamamdjian [this message]
2026-07-23 11:27   ` [PATCH 3/4] Input: edt-ft5x06 - allow reading the touch frame one register at a time Alexandre Hamamdjian via B4 Relay
2026-07-23 11:39   ` sashiko-bot
2026-07-23 11:27 ` [PATCH 4/4] Input: edt-ft5x06 - poll while a contact is down to recover dropped releases Alexandre Hamamdjian
2026-07-23 11:27   ` Alexandre Hamamdjian via B4 Relay
2026-07-23 11:39   ` sashiko-bot

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=20260723-b4-ft5426-v1-3-d4b4e32be042@gmail.com \
    --to=azkali.limited@gmail.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=dmitry.torokhov@gmail.com \
    --cc=krzk+dt@kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=robh@kernel.org \
    --cc=rydberg@bitmath.org \
    --cc=teguh@sobir.in \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.