Devicetree
 help / color / mirror / Atom feed
* [PATCH 0/3] ESWIN EPH8621 touchscreen support for Fairphone (Gen. 6)
@ 2026-09-11 15:16 Luca Weiss
  2026-09-11 15:16 ` [PATCH 1/3] dt-bindings: input: touchscreen: document ESWIN EPH8621 Luca Weiss
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Luca Weiss @ 2026-09-11 15:16 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Henrik Rydberg, Bjorn Andersson, Konrad Dybcio
  Cc: ~postmarketos/upstreaming, phone-devel, linux-input, devicetree,
	linux-kernel, linux-arm-msm, Luca Weiss

Add dt-bindings, driver and dts additions to support the touchscreen on
Fairphone (Gen. 6).

Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
---
Luca Weiss (3):
      dt-bindings: input: touchscreen: document ESWIN EPH8621
      Input: Add driver for ESWIN EPH8621 touchscreen IC
      arm64: dts: qcom: milos-fairphone-fp6: Add touchscreen

 .../bindings/input/touchscreen/eswin,eph8621.yaml  |  79 ++++++
 arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts   |  29 +-
 drivers/input/touchscreen/Kconfig                  |  12 +
 drivers/input/touchscreen/Makefile                 |   1 +
 drivers/input/touchscreen/eswin_eph8621.c          | 310 +++++++++++++++++++++
 5 files changed, 430 insertions(+), 1 deletion(-)
---
base-commit: 5e036ce12de91c6fd674dad33b169c6150be2a7a
change-id: 20260911-eswin-eph8621-5d3d766e2b0c

Best regards,
--  
Luca Weiss <luca.weiss@fairphone.com>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] dt-bindings: input: touchscreen: document ESWIN EPH8621
  2026-09-11 15:16 [PATCH 0/3] ESWIN EPH8621 touchscreen support for Fairphone (Gen. 6) Luca Weiss
@ 2026-09-11 15:16 ` Luca Weiss
  2026-09-13  9:28   ` Krzysztof Kozlowski
  2026-09-11 15:16 ` [PATCH 2/3] Input: Add driver for ESWIN EPH8621 touchscreen IC Luca Weiss
  2026-09-11 15:16 ` [PATCH 3/3] arm64: dts: qcom: milos-fairphone-fp6: Add touchscreen Luca Weiss
  2 siblings, 1 reply; 7+ messages in thread
From: Luca Weiss @ 2026-09-11 15:16 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Henrik Rydberg, Bjorn Andersson, Konrad Dybcio
  Cc: ~postmarketos/upstreaming, phone-devel, linux-input, devicetree,
	linux-kernel, linux-arm-msm, Luca Weiss

Document the ESWIN EPH8621 touchscreen controller, which can operate in
SPI mode. Other touchscreen controllers from the EPH861X family (and
potentially also EPH8621) can also operate in I2C mode, this was not
added yet.

Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
---
 .../bindings/input/touchscreen/eswin,eph8621.yaml  | 79 ++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/Documentation/devicetree/bindings/input/touchscreen/eswin,eph8621.yaml b/Documentation/devicetree/bindings/input/touchscreen/eswin,eph8621.yaml
new file mode 100644
index 000000000000..03f981ba19e4
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/eswin,eph8621.yaml
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/eswin,eph8621.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ESWIN EPH8621 touchscreen controller
+
+maintainers:
+  - Luca Weiss <luca.weiss@fairphone.com>
+
+allOf:
+  - $ref: touchscreen.yaml#
+  - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+properties:
+  compatible:
+    enum:
+      - eswin,eph8621
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  reset-gpios:
+    maxItems: 1
+
+  avdd-supply:
+    description: Power supply regulator on AVDD pin
+
+  vddio-supply:
+    description: Power supply regulator on VDDIO pin
+
+  spi-max-frequency: true
+  touchscreen-inverted-x: true
+  touchscreen-inverted-y: true
+  touchscreen-size-x: true
+  touchscreen-size-y: true
+  touchscreen-swapped-x-y: true
+
+additionalProperties: false
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - avdd-supply
+  - vddio-supply
+  - touchscreen-size-x
+  - touchscreen-size-y
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/gpio/gpio.h>
+    spi {
+      #address-cells = <1>;
+      #size-cells = <0>;
+      touchscreen@0 {
+        compatible = "eswin,eph8621";
+        reg = <0>;
+
+        avdd-supply = <&vreg_l22b>;
+        vddio-supply = <&vreg_l9b>;
+
+        interrupts-extended = <&tlmm 19 IRQ_TYPE_LEVEL_LOW>;
+        reset-gpios = <&tlmm 20 GPIO_ACTIVE_LOW>;
+
+        spi-max-frequency = <2000000>;
+
+        touchscreen-size-x = <1116>;
+        touchscreen-size-y = <2484>;
+        touchscreen-inverted-x;
+      };
+    };
+
+...

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/3] Input: Add driver for ESWIN EPH8621 touchscreen IC
  2026-09-11 15:16 [PATCH 0/3] ESWIN EPH8621 touchscreen support for Fairphone (Gen. 6) Luca Weiss
  2026-09-11 15:16 ` [PATCH 1/3] dt-bindings: input: touchscreen: document ESWIN EPH8621 Luca Weiss
@ 2026-09-11 15:16 ` Luca Weiss
  2026-09-11 15:26   ` sashiko-bot
  2026-09-11 15:16 ` [PATCH 3/3] arm64: dts: qcom: milos-fairphone-fp6: Add touchscreen Luca Weiss
  2 siblings, 1 reply; 7+ messages in thread
From: Luca Weiss @ 2026-09-11 15:16 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Henrik Rydberg, Bjorn Andersson, Konrad Dybcio
  Cc: ~postmarketos/upstreaming, phone-devel, linux-input, devicetree,
	linux-kernel, linux-arm-msm, Luca Weiss

Add a driver for the ESWIN EPH8621 touchscreens, connected via SPI.

The driver this is based on - EPH861X - also supports I2C but this is
not added the Fairphone (Gen. 6) has the touchscreen connected via SPI.

Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
---
 drivers/input/touchscreen/Kconfig         |  12 ++
 drivers/input/touchscreen/Makefile        |   1 +
 drivers/input/touchscreen/eswin_eph8621.c | 310 ++++++++++++++++++++++++++++++
 3 files changed, 323 insertions(+)

diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 9b9ae8ac3f7f..007b589cef8e 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -360,6 +360,18 @@ config TOUCHSCREEN_EGALAX_SERIAL
 	  To compile this driver as a module, choose M here: the
 	  module will be called egalax_ts_serial.
 
+config TOUCHSCREEN_ESWIN_EPH8621
+	tristate "ESWIN EPH8621 touchscreen"
+	depends on SPI_MASTER
+	help
+	  Say Y here if you have a ESWIN EPH8621 connected to
+	  your system via SPI.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called eswin_eph8621.
+
 config TOUCHSCREEN_EXC3000
 	tristate "EETI EXC3000 multi-touch panel support"
 	depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index bfd9de83389d..4540169d9b54 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_TOUCHSCREEN_ELAN)		+= elants_i2c.o
 obj-$(CONFIG_TOUCHSCREEN_ELO)		+= elo.o
 obj-$(CONFIG_TOUCHSCREEN_EGALAX)	+= egalax_ts.o
 obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL)	+= egalax_ts_serial.o
+obj-$(CONFIG_TOUCHSCREEN_ESWIN_EPH8621)	+= eswin_eph8621.o
 obj-$(CONFIG_TOUCHSCREEN_EXC3000)	+= exc3000.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)	+= fujitsu_ts.o
 obj-$(CONFIG_TOUCHSCREEN_GOODIX)	+= goodix_ts.o
diff --git a/drivers/input/touchscreen/eswin_eph8621.c b/drivers/input/touchscreen/eswin_eph8621.c
new file mode 100644
index 000000000000..12b90cc89052
--- /dev/null
+++ b/drivers/input/touchscreen/eswin_eph8621.c
@@ -0,0 +1,310 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * ESWIN EPH8621 series touchscreen driver
+ *
+ * Copyright (C) 2026 Luca Weiss <luca.weiss@fairphone.com>
+ *
+ * Based on original EPH861X driver by chris.ollerenshaw@eswin.com
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/sizes.h>
+#include <linux/spi/spi.h>
+
+#define ESWIN_MAX_TOUCHES		10
+#define ESWIN_COMMS_BUF_SIZE		3072
+
+/* TLV Protocol Definitions */
+#define TLV_HEADER_SIZE			3 /* 1 byte Type + 2 bytes Length */
+#define TLV_TYPE_FIELD			0
+#define TLV_LENGTH_FIELD		1
+
+#define TLV_REPORT_DATA			0x23
+#define EVENT_REPORT_TYPE_OFFSET	4
+#define EVENT_REPORT_TYPE_MASK		0xF0
+#define EVENT_REPORT_LENGTH_MASK	0x0F
+
+/* Event Types */
+#define CONTACT_TYPE			1
+#define RELEASE_TYPE			2
+
+struct eswin_touch {
+	struct device *dev;
+	struct input_dev *input;
+
+	struct gpio_desc *reset_gpio;
+	struct regulator_bulk_data supplies[2];
+
+	struct touchscreen_properties prop;
+
+	u8 *rx_buf;
+	u8 *tx_buf;
+};
+
+static int eswin_spi_read(struct eswin_touch *ts, u16 len, u8 *buf)
+{
+	struct spi_device *spi = to_spi_device(ts->dev);
+	struct spi_transfer xfer = {
+		.tx_buf = ts->tx_buf,
+		.rx_buf = ts->rx_buf,
+		.len = len,
+	};
+	int error;
+
+	if (len > ESWIN_COMMS_BUF_SIZE)
+		return -EINVAL;
+
+	/* ESWIN requires 0xFF dummy bytes clocked out to read data */
+	memset(ts->tx_buf, 0xFF, len);
+	error = spi_sync_transfer(spi, &xfer, 1);
+	if (error)
+		return error;
+
+	memcpy(buf, ts->rx_buf, len);
+	return 0;
+}
+
+/*
+ * Core Touch Handling
+ */
+static int eswin_comms_two_stage_read(struct eswin_touch *ts, u8 *buf)
+{
+	u16 payload_len;
+	int error;
+
+	/* Stage 1: Read 3-byte header */
+	error = eswin_spi_read(ts, TLV_HEADER_SIZE, buf);
+	if (error)
+		return error;
+
+	payload_len = buf[TLV_LENGTH_FIELD] | (buf[TLV_LENGTH_FIELD + 1] << 8);
+	if (payload_len == 0 || payload_len > ESWIN_COMMS_BUF_SIZE - TLV_HEADER_SIZE)
+		return -EINVAL;
+
+	udelay(50);
+
+	/* Stage 2: Read full packet (Header + Payload) */
+	return eswin_spi_read(ts, payload_len + TLV_HEADER_SIZE, buf);
+}
+
+static void eswin_report_contact(struct eswin_touch *ts, u8 *payload)
+{
+	u8 touch_type = (payload[0] & EVENT_REPORT_TYPE_MASK) >> EVENT_REPORT_TYPE_OFFSET;
+	u8 slot = payload[1];
+	u16 x = payload[2] | (payload[3] << 8);
+	u16 y = payload[4] | (payload[5] << 8);
+	u8 width = payload[6];
+	u8 height = payload[7];
+	bool active = false;
+
+	switch (touch_type) {
+	case CONTACT_TYPE:
+		active = true;
+		break;
+	case RELEASE_TYPE:
+		active = false;
+		break;
+	default:
+		dev_warn_ratelimited(ts->dev, "Unhandled touch type: %d\n", touch_type);
+		return;
+	}
+
+	input_mt_slot(ts->input, slot);
+	input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, active);
+
+	if (active) {
+		touchscreen_report_pos(ts->input, &ts->prop, x, y, true);
+		input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, height);
+		input_report_abs(ts->input, ABS_MT_TOUCH_MINOR, width);
+	}
+}
+
+static void eswin_process_report(struct eswin_touch *ts, u8 *buf)
+{
+	u16 total_len = buf[TLV_LENGTH_FIELD] | (buf[TLV_LENGTH_FIELD + 1] << 8);
+	u16 offset = TLV_HEADER_SIZE;
+
+	if (buf[TLV_TYPE_FIELD] != TLV_REPORT_DATA)
+		return;
+
+	while (offset < total_len + TLV_HEADER_SIZE) {
+		u8 ev_len = buf[offset] & EVENT_REPORT_LENGTH_MASK;
+
+		eswin_report_contact(ts, &buf[offset]);
+		offset += (ev_len + 1);
+	}
+
+	input_mt_sync_frame(ts->input);
+	input_sync(ts->input);
+}
+
+static irqreturn_t eswin_interrupt(int irq, void *dev_id)
+{
+	struct eswin_touch *ts = dev_id;
+	int error;
+
+	error = eswin_comms_two_stage_read(ts, ts->rx_buf);
+	if (!error)
+		eswin_process_report(ts, ts->rx_buf);
+
+	return IRQ_HANDLED;
+}
+
+static int eswin_power_on(struct eswin_touch *ts)
+{
+	int error;
+
+	error = regulator_bulk_enable(ARRAY_SIZE(ts->supplies), ts->supplies);
+	if (error)
+		return error;
+
+	msleep(150);
+	gpiod_set_value_cansleep(ts->reset_gpio, 0);
+	msleep(100);
+
+	return 0;
+}
+
+static void eswin_power_off(struct eswin_touch *ts)
+{
+	gpiod_set_value_cansleep(ts->reset_gpio, 1);
+	regulator_bulk_disable(ARRAY_SIZE(ts->supplies), ts->supplies);
+}
+
+static void eswin_power_off_act(void *data)
+{
+	struct eswin_touch *ts = data;
+
+	eswin_power_off(ts);
+}
+
+static int eswin_probe(struct spi_device *spi)
+{
+	struct device *dev = &spi->dev;
+	struct eswin_touch *ts;
+	int error;
+
+	ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
+	if (!ts)
+		return -ENOMEM;
+
+	ts->dev = dev;
+	spi_set_drvdata(spi, ts);
+
+	spi->mode = SPI_MODE_3;
+	spi->bits_per_word = 8;
+	error = spi_setup(spi);
+	if (error)
+		return dev_err_probe(dev, error, "Failed to setup SPI\n");
+
+	ts->rx_buf = devm_kzalloc(dev, ESWIN_COMMS_BUF_SIZE, GFP_KERNEL);
+	ts->tx_buf = devm_kzalloc(dev, ESWIN_COMMS_BUF_SIZE, GFP_KERNEL);
+	if (!ts->rx_buf || !ts->tx_buf)
+		return -ENOMEM;
+
+	ts->supplies[0].supply = "vddio";
+	ts->supplies[1].supply = "avdd";
+	error = devm_regulator_bulk_get(dev, ARRAY_SIZE(ts->supplies), ts->supplies);
+	if (error)
+		return dev_err_probe(dev, error, "Failed to get regulators\n");
+
+	ts->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(ts->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(ts->reset_gpio),
+				     "Failed to request reset GPIO\n");
+
+	error = eswin_power_on(ts);
+	if (error)
+		return dev_err_probe(dev, error, "Failed to power on\n");
+
+	error = devm_add_action_or_reset(dev, eswin_power_off_act, ts);
+	if (error)
+		return error;
+
+	ts->input = devm_input_allocate_device(dev);
+	if (!ts->input)
+		return -ENOMEM;
+
+	ts->input->name = "ESWIN Touchscreen";
+	ts->input->id.bustype = BUS_SPI;
+
+	input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, SZ_64K - 1, 0, 0);
+	input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, SZ_64K - 1, 0, 0);
+	input_set_abs_params(ts->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+	input_set_abs_params(ts->input, ABS_MT_TOUCH_MINOR, 0, 255, 0, 0);
+
+	touchscreen_parse_properties(ts->input, true, &ts->prop);
+
+	error = input_mt_init_slots(ts->input, ESWIN_MAX_TOUCHES, INPUT_MT_DIRECT);
+	if (error)
+		return dev_err_probe(dev, error, "Failed to initialize MT slots\n");
+
+	error = devm_request_threaded_irq(dev, spi->irq, NULL, eswin_interrupt,
+					  IRQF_ONESHOT, dev_name(dev), ts);
+	if (error)
+		return dev_err_probe(dev, error, "Failed to request IRQ\n");
+
+	return input_register_device(ts->input);
+}
+
+static int eswin_suspend(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct eswin_touch *ts = spi_get_drvdata(spi);
+
+	disable_irq(spi->irq);
+	eswin_power_off(ts);
+
+	return 0;
+}
+
+static int eswin_resume(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct eswin_touch *ts = spi_get_drvdata(spi);
+	int error;
+
+	error = eswin_power_on(ts);
+	if (error)
+		return error;
+
+	enable_irq(spi->irq);
+
+	return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(eswin_pm_ops, eswin_suspend, eswin_resume);
+
+static const struct of_device_id eswin_of_match[] = {
+	{ .compatible = "eswin,eph8621" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, eswin_of_match);
+
+static const struct spi_device_id eswin_spi_id[] = {
+	{ .name = "eph8621" },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, eswin_spi_id);
+
+static struct spi_driver eswin_spi_driver = {
+	.driver = {
+		.name = "eswin_eph8621",
+		.of_match_table = eswin_of_match,
+		.pm = pm_sleep_ptr(&eswin_pm_ops),
+	},
+	.probe = eswin_probe,
+	.id_table = eswin_spi_id,
+};
+module_spi_driver(eswin_spi_driver);
+
+MODULE_AUTHOR("Luca Weiss <luca.weiss@fairphone.com>");
+MODULE_DESCRIPTION("ESWIN EPH8621 SPI touchscreen driver");
+MODULE_LICENSE("GPL");

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/3] arm64: dts: qcom: milos-fairphone-fp6: Add touchscreen
  2026-09-11 15:16 [PATCH 0/3] ESWIN EPH8621 touchscreen support for Fairphone (Gen. 6) Luca Weiss
  2026-09-11 15:16 ` [PATCH 1/3] dt-bindings: input: touchscreen: document ESWIN EPH8621 Luca Weiss
  2026-09-11 15:16 ` [PATCH 2/3] Input: Add driver for ESWIN EPH8621 touchscreen IC Luca Weiss
@ 2026-09-11 15:16 ` Luca Weiss
  2026-09-11 15:43   ` Konrad Dybcio
  2 siblings, 1 reply; 7+ messages in thread
From: Luca Weiss @ 2026-09-11 15:16 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Henrik Rydberg, Bjorn Andersson, Konrad Dybcio
  Cc: ~postmarketos/upstreaming, phone-devel, linux-input, devicetree,
	linux-kernel, linux-arm-msm, Luca Weiss

Add a node for the ESWIN EPH8621 touchscreen connected via SPI and the
pinctrl state for the two GPIOs connected to the touchscreen.

Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
---
 arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts | 29 +++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts b/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
index 4b7ae87270ac..498fde3d3d18 100644
--- a/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
+++ b/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
@@ -983,7 +983,27 @@ &sdhc_2 {
 };
 
 &spi0 {
-	/* Eswin EPH8621 touchscreen @ 0 */
+	status = "okay";
+
+	touchscreen@0 {
+		compatible = "eswin,eph8621";
+		reg = <0>;
+
+		avdd-supply = <&vreg_l22b>;
+		vddio-supply = <&vreg_l9b>;
+
+		interrupts-extended = <&tlmm 19 IRQ_TYPE_LEVEL_LOW>;
+		reset-gpios = <&tlmm 20 GPIO_ACTIVE_LOW>;
+
+		pinctrl-0 = <&touchscreen_default>;
+		pinctrl-names = "default";
+
+		spi-max-frequency = <2000000>;
+
+		touchscreen-size-x = <1116>;
+		touchscreen-size-y = <2484>;
+		touchscreen-inverted-x;
+	};
 };
 
 &tlmm {
@@ -991,6 +1011,13 @@ &tlmm {
 			       <13 1>, /* NC */
 			       <63 2>; /* WLAN UART */
 
+	touchscreen_default: touchscreen-default-state {
+		pins = "gpio19", "gpio20";
+		function = "gpio";
+		drive-strength = <2>;
+		bias-disable;
+	};
+
 	sdc2_card_det_n: sdc2-card-det-state {
 		pins = "gpio65";
 		function = "gpio";

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/3] Input: Add driver for ESWIN EPH8621 touchscreen IC
  2026-09-11 15:16 ` [PATCH 2/3] Input: Add driver for ESWIN EPH8621 touchscreen IC Luca Weiss
@ 2026-09-11 15:26   ` sashiko-bot
  0 siblings, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-09-11 15:26 UTC (permalink / raw)
  To: Luca Weiss; +Cc: dmitry.torokhov, devicetree, robh, linux-input, conor+dt

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] Double-fetch / TOCTOU vulnerability in packet length parsing allows massive out-of-bounds read and an infinite loop.
- [High] Missing length validation before parsing contact events leads to heap out-of-bounds reads.
- [Medium] Overlapping memory regions in memcpy() due to identical source and destination pointers.
- [Medium] Unvalidated slot ID silently corrupts input multi-touch state for valid contacts.
--

commit 6fa34851ae5b4f1c363bd77f86f1478eb5ce13e6
Author: Luca Weiss <luca.weiss@fairphone.com>

Input: Add driver for ESWIN EPH8621 touchscreen IC

Adds a driver for the ESWIN EPH8621 touchscreens connected via SPI.

> diff --git a/drivers/input/touchscreen/eswin_eph8621.c b/drivers/input/touchscreen/eswin_eph8621.c
> new file mode 100644
> index 0000000000000..12b90cc89052e
> --- /dev/null
> +++ b/drivers/input/touchscreen/eswin_eph8621.c
[ ... ]
> static int eswin_spi_read(struct eswin_touch *ts, u16 len, u8 *buf)
> {
> 	struct spi_device *spi = to_spi_device(ts->dev);
> 	struct spi_transfer xfer = {
> 		.tx_buf = ts->tx_buf,
> 		.rx_buf = ts->rx_buf,
> 		.len = len,
> 	};
> 	int error;
> 
> 	if (len > ESWIN_COMMS_BUF_SIZE)
> 		return -EINVAL;
> 
> 	/* ESWIN requires 0xFF dummy bytes clocked out to read data */
> 	memset(ts->tx_buf, 0xFF, len);
> 	error = spi_sync_transfer(spi, &xfer, 1);
> 	if (error)
> 		return error;
> 
> 	memcpy(buf, ts->rx_buf, len);

[Severity: Medium]
Is this memcpy() safe from overlapping memory regions?

Looking at eswin_interrupt(), it passes ts->rx_buf as the buf argument to
eswin_comms_two_stage_read(), which subsequently passes it to this function:

eswin_interrupt() {
        error = eswin_comms_two_stage_read(ts, ts->rx_buf);
...

This means buf and ts->rx_buf point to the exact same memory address. Since
the SPI transfer writes data directly into ts->rx_buf, does this memcpy()
trigger undefined behavior due to the identical source and destination
pointers?

[ ... ]
> static void eswin_report_contact(struct eswin_touch *ts, u8 *payload)
> {
> 	u8 touch_type = (payload[0] & EVENT_REPORT_TYPE_MASK) >> EVENT_REPORT_TYPE_OFFSET;
> 	u8 slot = payload[1];

[Severity: Medium]
Is the slot ID extracted from the device payload validated anywhere before
use?

If the hardware reports an invalid slot index (e.g., slot >=
ESWIN_MAX_TOUCHES), input_mt_slot() safely ignores it, leaving the active
mt->slot unchanged. However, the subsequent code unconditionally proceeds
to report X/Y coordinates and touch properties.

Could this cause the driver to apply malformed event data to the
previously active, valid slot, corrupting the multi-touch state?

[ ... ]
> static void eswin_process_report(struct eswin_touch *ts, u8 *buf)
> {
> 	u16 total_len = buf[TLV_LENGTH_FIELD] | (buf[TLV_LENGTH_FIELD + 1] << 8);

[Severity: High]
Does this recalculation introduce a double-fetch vulnerability?

The SPI controller initially reads the 3-byte header into ts->rx_buf and
safely validates payload_len. However, the second SPI transfer in
eswin_comms_two_stage_read() overwrites ts->rx_buf with the full packet.

Here, total_len is blindly recalculated from this newly fetched, unvalidated
header data. If a glitchy or malicious device provides a valid length for
the first read and a huge length (e.g., 0xFFFF) for the second, total_len
is set to an unchecked value.

> 	u16 offset = TLV_HEADER_SIZE;
> 
> 	if (buf[TLV_TYPE_FIELD] != TLV_REPORT_DATA)
> 		return;
> 
> 	while (offset < total_len + TLV_HEADER_SIZE) {

[Severity: High]
Can this loop condition result in an infinite loop and out-of-bounds reads?

If total_len was manipulated by the double-fetch issue above to be 0xFFFF,
total_len + TLV_HEADER_SIZE becomes 65538. Since offset is a u16, it can
never reach 65538, causing the condition to evaluate to true forever.

> 		u8 ev_len = buf[offset] & EVENT_REPORT_LENGTH_MASK;
> 
> 		eswin_report_contact(ts, &buf[offset]);

[Severity: High]
Can this function call trigger an out-of-bounds heap read?

The loop verifies that offset is less than the packet end, but does not
check if at least 8 bytes remain to safely parse a full contact event.

If offset is near the end of the 3072-byte buffer (e.g., offset = 3070),
eswin_report_contact() unconditionally reads up to payload[7] for the
height, which reads past the end of the heap allocation.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260911-eswin-eph8621-v1-0-db447ff9e445@fairphone.com?part=2

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 3/3] arm64: dts: qcom: milos-fairphone-fp6: Add touchscreen
  2026-09-11 15:16 ` [PATCH 3/3] arm64: dts: qcom: milos-fairphone-fp6: Add touchscreen Luca Weiss
@ 2026-09-11 15:43   ` Konrad Dybcio
  0 siblings, 0 replies; 7+ messages in thread
From: Konrad Dybcio @ 2026-09-11 15:43 UTC (permalink / raw)
  To: Luca Weiss, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Henrik Rydberg, Bjorn Andersson, Konrad Dybcio
  Cc: ~postmarketos/upstreaming, phone-devel, linux-input, devicetree,
	linux-kernel, linux-arm-msm

On 9/11/26 5:16 PM, Luca Weiss wrote:
> Add a node for the ESWIN EPH8621 touchscreen connected via SPI and the
> pinctrl state for the two GPIOs connected to the touchscreen.
> 
> Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
> ---

Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>

Konrad

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/3] dt-bindings: input: touchscreen: document ESWIN EPH8621
  2026-09-11 15:16 ` [PATCH 1/3] dt-bindings: input: touchscreen: document ESWIN EPH8621 Luca Weiss
@ 2026-09-13  9:28   ` Krzysztof Kozlowski
  0 siblings, 0 replies; 7+ messages in thread
From: Krzysztof Kozlowski @ 2026-09-13  9:28 UTC (permalink / raw)
  To: Luca Weiss
  Cc: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Henrik Rydberg, Bjorn Andersson, Konrad Dybcio,
	~postmarketos/upstreaming, phone-devel, linux-input, devicetree,
	linux-kernel, linux-arm-msm

On Fri, Sep 11, 2026 at 05:16:09PM +0200, Luca Weiss wrote:
> Document the ESWIN EPH8621 touchscreen controller, which can operate in
> SPI mode. Other touchscreen controllers from the EPH861X family (and
> potentially also EPH8621) can also operate in I2C mode, this was not
> added yet.
> 
> Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
> ---
>  .../bindings/input/touchscreen/eswin,eph8621.yaml  | 79 ++++++++++++++++++++++

...

> +  touchscreen-swapped-x-y: true
> +
> +additionalProperties: false

If there is going to be a new version, this should be just before
example.


Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>

Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-09-13  9:28 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-11 15:16 [PATCH 0/3] ESWIN EPH8621 touchscreen support for Fairphone (Gen. 6) Luca Weiss
2026-09-11 15:16 ` [PATCH 1/3] dt-bindings: input: touchscreen: document ESWIN EPH8621 Luca Weiss
2026-09-13  9:28   ` Krzysztof Kozlowski
2026-09-11 15:16 ` [PATCH 2/3] Input: Add driver for ESWIN EPH8621 touchscreen IC Luca Weiss
2026-09-11 15:26   ` sashiko-bot
2026-09-11 15:16 ` [PATCH 3/3] arm64: dts: qcom: milos-fairphone-fp6: Add touchscreen Luca Weiss
2026-09-11 15:43   ` Konrad Dybcio

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox