* Re: [PATCH V3 1/9] dt-bindings: iio: imu: icm42607: Add devicetree binding
From: Rob Herring @ 2026-04-08 19:44 UTC (permalink / raw)
To: Chris Morgan
Cc: Chris Morgan, linux-iio, andy, nuno.sa, dlechner, jic23,
jean-baptiste.maneyrol, linux-rockchip, devicetree, heiko,
conor+dt, krzk+dt, andriy.shevchenko
In-Reply-To: <PH0PR19MB9973386B000D79AD04904C96B2A55BA@PH0PR19MB997338.namprd19.prod.outlook.com>
On Wed, Apr 8, 2026 at 9:31 AM Chris Morgan <macromorgan@hotmail.com> wrote:
>
> On Wed, Apr 08, 2026 at 08:19:44AM -0500, Rob Herring wrote:
> > On Mon, Mar 30, 2026 at 02:58:45PM -0500, Chris Morgan wrote:
> > > From: Chris Morgan <macromorgan@hotmail.com>
> > >
> > Subject space is limited, so don't say devicetree binding twice:
> >
> > dt-bindings: iio: imu: Add Invensense ICM42607
> >
> > > Add devicetree binding for the Invensense ICM42607 and Invensense
> > > ICM42607P inertial measurement unit. This unit is a combined
> > > accelerometer, gyroscope, and thermometer available via I2C or SPI.
> > >
> > > This device is functionally very similar to the icm42600 series with a
> > > very different register layout.
> >
> > Similar enough to use the same binding schema?
>
> Yes. I was under the (possibly mistaken) impression that different drivers
> required different binding schemas, but these should be similar enough to
> use the same schema if it's allowed.
Total fine. Bindings and drivers can be 1:1, N:1 or 1:N.
Rob
^ permalink raw reply
* Re: [PATCH 2/3] nvmem: Add the Raspberry Pi OTP driver
From: Gregor Herburger @ 2026-04-08 19:47 UTC (permalink / raw)
To: Stefan Wahren
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Florian Fainelli,
Ray Jui, Scott Branden, Broadcom internal kernel review list,
Srinivas Kandagatla, devicetree, linux-rpi-kernel,
linux-arm-kernel, linux-kernel
In-Reply-To: <251100fe-db96-4d83-899a-cd764582d698@gmx.net>
Hi Stefan,
thanks for the review.
> > +config NVMEM_RASPBERRYPI_OTP
> > + tristate "Raspberry Pi OTP support"
> > + # Make sure not 'y' when RASPBERRYPI_FIRMWARE is 'm'. This can only
> > + # happen when COMPILE_TEST=y, hence the added !RASPBERRYPI_FIRMWARE.
> I don't think these comments are necessary, because this applies to other
> firmware drivers, too.
I have seen this in all the other drivers that depend on RASPBERRYPI_FIRMWARE
so I added it here as well. I can remove it.
> > + depends on RASPBERRYPI_FIRMWARE || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE)
> > + help
> > + This driver provides access to the Raspberry Pi OTP memory via the
> > + nvmem subsystem. The driver supports the customer otp as well as the
> > + device specific private key OTP.
> > +
> > + This driver can also be built as a module. If so, the module
> > + will be called raspberrypi-otp.
> > endif
> > diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
> > index 7252b8ec88d4..8ca2095e068f 100644
> Is there any reason, why we cannot register this driver in
> rpi_firmware_probe() like hwmon and clk driver?
>
> I like to avoid the complete dt-binding from patch 1.
The private OTP registers are not available on all Raspberries. Afaik
only on 4 and 5. So I think these registers must be described through
the device tree. Therefore the bindings are needed.
> > +module_platform_driver(raspberry_otp_driver);
> > +
> > +MODULE_AUTHOR("Gregor Herburger <gregor.herburger@linutronix.de>");
> > +MODULE_DESCRIPTION("Raspberry OTP driver");
> Raspberry Pi OTP driver ?
Yes. I will update in the next version.
^ permalink raw reply
* Re: [PATCH 2/3] nvmem: Add the Raspberry Pi OTP driver
From: Stefan Wahren @ 2026-04-08 20:03 UTC (permalink / raw)
To: Gregor Herburger
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Florian Fainelli,
Ray Jui, Scott Branden, Broadcom internal kernel review list,
Srinivas Kandagatla, devicetree, linux-rpi-kernel,
linux-arm-kernel, linux-kernel
In-Reply-To: <adaw1rr3WlDjvyQp@gregor-framework>
Am 08.04.26 um 21:47 schrieb Gregor Herburger:
> Hi Stefan,
>
> thanks for the review.
>> Is there any reason, why we cannot register this driver in
>> rpi_firmware_probe() like hwmon and clk driver?
>>
>> I like to avoid the complete dt-binding from patch 1.
> The private OTP registers are not available on all Raspberries. Afaik
> only on 4 and 5. So I think these registers must be described through
> the device tree. Therefore the bindings are needed.
This binding doesn't represent some kind of hardware, it's just some
firmware interface. A proper DT binding would describe the MMIO address
range for OTP access.
If you need some distinction between the Raspberry Pi generations there
are firmware tags to do this.
Regards
^ permalink raw reply
* Re: [PATCH 2/2] arm64: dts: imx8dxl: Add SolidRun SoM and HummingBoard
From: Andrew Lunn @ 2026-04-08 20:12 UTC (permalink / raw)
To: Josua Mayer
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Yazan Shhady, Mikhail Anikin, Alexander Dahl, devicetree,
linux-kernel, imx, linux-arm-kernel
In-Reply-To: <20260408-imx8dxl-sr-som-v1-2-ce5a39acd713@solid-run.com>
> +&eqos {
> + phy-mode = "rgmii-id";
> + pinctrl-0 = <&eqos_pins>;
> + pinctrl-names = "default";
> + status = "okay";
> +
> + fixed-link {
> + full-duplex;
> + speed = <1000>;
> + };
> +};
> + ethernet-switch@0 {
> + compatible = "nxp,sja1110a";
....
> +
> + /* to CPU */
> + port@2 {
> + reg = <0x2>;
> + ethernet = <&eqos>;
> + label = "cpu";
> + phy-mode = "rgmii-id";
> + rx-internal-delay-ps = <2000>;
> + tx-internal-delay-ps = <2000>;
The eqos is using rgmii-id, this port is using rmgii-id, and you set
the delays to 2000ns. How is this not resulting in 4000ns delays?
Andrew
^ permalink raw reply
* Re: [PATCH 2/2] iio: dac: mcp47feb02: add MCP48FEB02 SPI driver to MCP47FEB02 I2C driver
From: Andy Shevchenko @ 2026-04-08 20:22 UTC (permalink / raw)
To: David Lechner
Cc: Ariana Lazar, Jonathan Cameron, Nuno Sá, Andy Shevchenko,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Cameron,
Conor Dooley, linux-iio, devicetree, linux-kernel
In-Reply-To: <1e05b8f9-e95e-458d-9179-ac8268023ae5@baylibre.com>
On Sat, Apr 04, 2026 at 08:49:55AM -0500, David Lechner wrote:
> On 4/3/26 5:50 AM, Ariana Lazar wrote:
> > This is the iio driver for Microchip MCP48FxBy1/2/4/8 series of
> > buffered voltage output Digital-to-Analog Converters with nonvolatile or
> > volatile memory on top of MCP47FEB02. The families support up to 8
> > output channels and have 8-bit, 10-bit or 12-bit resolution.
> >
> > The MCP47FEB02 driver was split into three modules: mcp47feb02-core.c,
> > mcp47feb02-i2c.c and mcp47feb02-spi.c in order to support both DAC families
> > - I2C (MCP47F(E/V)BXX) and SPI (MCP48F(E/V)BXX).
...
> > Fixes: bf394cc80369 ("iio: dac: adding support for Microchip MCP47FEB02")
Really?! (See also below)
...
> > obj-$(CONFIG_MCP47FEB02) += mcp47feb02.o
>
> Shouldn't we be removing this old file?
> The patch series would be eaiser to understand if it was split into
> one commit to split the existing driver into two files and then
> another commit to add support for the new parts.
Exactly! We do not expect to have this huge contribution as a fix, it just
a normal development and hence the existing code needs to be refactored.
> > +mcp47feb02-objs := mcp47feb02-core.o
> > +obj-$(CONFIG_MCP47FEB02_I2C) += mcp47feb02-i2c.o
> > +obj-$(CONFIG_MCP47FEB02_SPI) += mcp47feb02-spi.o
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* [PATCH v2 0/3] Add Tegra264 HTE provider
From: Suneel Garapati @ 2026-04-08 21:24 UTC (permalink / raw)
To: dipenp, jonathanh, thierry.reding, krzk+dt, conor+dt, amhetre,
sheetal, kkartik, robh, pshete, timestamp, devicetree,
linux-tegra, linux-kernel
Cc: Suneel Garapati
This patch series mainly adds support for the Tegra264 HTE provider.
- Update devicetree bindings to add Tegra264 support
- Add support in driver for Tegra264 chip including new tsc clock
parameters setup per SoC as values differ for Tegra264
- Populate device-tree nodes for Tegra264 GTE instances
- One of devicetree nodes has reference to gpio_aon node that is
dependent on this series [1]
1 - https://patchwork.ozlabs.org/project/linux-gpio/patch/20260128085114.1137725-3-pshete@nvidia.com/
---
Changes in v2:
- Devicetree bindings has nvidia,slices property deprecated for Tegra264
Suneel Garapati (3):
dt-bindings: timestamp: Add Tegra264 support
hte: tegra194: Add Tegra264 GTE support
arm64: tegra: Add GTE nodes for Tegra264
.../timestamp/nvidia,tegra194-hte.yaml | 14 ++
arch/arm64/boot/dts/nvidia/tegra264.dtsi | 19 +++
drivers/hte/hte-tegra194.c | 133 +++++++++++++++++-
3 files changed, 161 insertions(+), 5 deletions(-)
--
2.34.1
^ permalink raw reply
* [PATCH v2 1/3] dt-bindings: timestamp: Add Tegra264 support
From: Suneel Garapati @ 2026-04-08 21:24 UTC (permalink / raw)
To: dipenp, jonathanh, thierry.reding, krzk+dt, conor+dt, amhetre,
sheetal, kkartik, robh, pshete, timestamp, devicetree,
linux-tegra, linux-kernel
Cc: Suneel Garapati
In-Reply-To: <20260408212413.217692-1-suneelg@nvidia.com>
Add timestamp provider support for the Tegra264 in devicetree
bindings. Tegra264 has two generic timestamping engines (GTE)
which are the always-on GTE (AON) and legacy interrupt
controller (LIC) GTE.
'nvidia,slices' property is deprecated and hence not allowed for
Tegra264.
Signed-off-by: Suneel Garapati <suneelg@nvidia.com>
---
v1:
- nvidia,slices property is deprecated and hence false for Tegra264
---
.../bindings/timestamp/nvidia,tegra194-hte.yaml | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/Documentation/devicetree/bindings/timestamp/nvidia,tegra194-hte.yaml b/Documentation/devicetree/bindings/timestamp/nvidia,tegra194-hte.yaml
index 456797967adc..a96d6cd23895 100644
--- a/Documentation/devicetree/bindings/timestamp/nvidia,tegra194-hte.yaml
+++ b/Documentation/devicetree/bindings/timestamp/nvidia,tegra194-hte.yaml
@@ -25,6 +25,8 @@ properties:
- nvidia,tegra194-gte-lic
- nvidia,tegra234-gte-aon
- nvidia,tegra234-gte-lic
+ - nvidia,tegra264-gte-aon
+ - nvidia,tegra264-gte-lic
reg:
maxItems: 1
@@ -112,10 +114,22 @@ allOf:
contains:
enum:
- nvidia,tegra234-gte-aon
+ - nvidia,tegra264-gte-aon
then:
required:
- nvidia,gpio-controller
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - nvidia,tegra264-gte-aon
+ - nvidia,tegra264-gte-lic
+ then:
+ properties:
+ nvidia,slices: false
+
additionalProperties: false
examples:
--
2.34.1
^ permalink raw reply related
* [PATCH v2 2/3] hte: tegra194: Add Tegra264 GTE support
From: Suneel Garapati @ 2026-04-08 21:24 UTC (permalink / raw)
To: dipenp, jonathanh, thierry.reding, krzk+dt, conor+dt, amhetre,
sheetal, kkartik, robh, pshete, timestamp, devicetree,
linux-tegra, linux-kernel
Cc: Suneel Garapati
In-Reply-To: <20260408212413.217692-1-suneelg@nvidia.com>
Add AON-GTE mapping and LIC GTE instance support for the Tegra264.
Move TSC clock parameters from macros to members of SoC data
as values differ for Tegra264 chip.
Signed-off-by: Suneel Garapati <suneelg@nvidia.com>
---
drivers/hte/hte-tegra194.c | 133 +++++++++++++++++++++++++++++++++++--
1 file changed, 128 insertions(+), 5 deletions(-)
diff --git a/drivers/hte/hte-tegra194.c b/drivers/hte/hte-tegra194.c
index 690eb9be30fb..4a7702b32b24 100644
--- a/drivers/hte/hte-tegra194.c
+++ b/drivers/hte/hte-tegra194.c
@@ -20,10 +20,11 @@
#define HTE_SUSPEND 0
-/* HTE source clock TSC is 31.25MHz */
+/* HTE source clock TSC is 1GHz for T264 and 31.25MHz for others */
#define HTE_TS_CLK_RATE_HZ 31250000ULL
+#define HTE_TS_CLK_RATE_1G 1000000000ULL
#define HTE_CLK_RATE_NS 32
-#define HTE_TS_NS_SHIFT __builtin_ctz(HTE_CLK_RATE_NS)
+#define HTE_CLK_RATE_NS_1G 1
#define NV_AON_SLICE_INVALID -1
#define NV_LINES_IN_SLICE 32
@@ -120,6 +121,8 @@ struct tegra_hte_data {
u32 slices;
u32 map_sz;
u32 sec_map_sz;
+ u64 tsc_clkrate_hz;
+ u32 tsc_clkrate_ns;
const struct tegra_hte_line_mapped *map;
const struct tegra_hte_line_mapped *sec_map;
};
@@ -317,6 +320,94 @@ static const struct tegra_hte_line_mapped tegra234_aon_gpio_sec_map[] = {
[40] = {2, NV_AON_HTE_SLICE2_IRQ_GPIO_23},
};
+static const struct tegra_hte_line_mapped tegra264_aon_gpio_map[] = {
+ /* gpio, slice, bit_index */
+ /* AA port */
+ [0] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_29},
+ [1] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_28},
+ [2] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_27},
+ [3] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_26},
+ [4] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_25},
+ [5] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_24},
+ [6] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_23},
+ [7] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_22},
+ /* BB port */
+ [8] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_21},
+ [9] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_20},
+ /* CC port */
+ [10] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_19},
+ [11] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_18},
+ [12] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_17},
+ [13] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_16},
+ [14] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_15},
+ [15] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_14},
+ [16] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_13},
+ [17] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_12},
+ /* DD port */
+ [18] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_11},
+ [19] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_10},
+ [20] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_9},
+ [21] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_8},
+ [22] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_7},
+ [23] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_6},
+ [24] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_5},
+ [25] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_4},
+ /* EE port */
+ [26] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_3},
+ [27] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_2},
+ [28] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_1},
+ [29] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_0},
+};
+
+static const struct tegra_hte_line_mapped tegra264_aon_gpio_sec_map[] = {
+ /* gpio, slice, bit_index */
+ /* AA port */
+ [0] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_29},
+ [1] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_28},
+ [2] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_27},
+ [3] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_26},
+ [4] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_25},
+ [5] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_24},
+ [6] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_23},
+ [7] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_22},
+ /* BB port */
+ [8] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_21},
+ [9] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_20},
+ [10] = {NV_AON_SLICE_INVALID, 0},
+ [11] = {NV_AON_SLICE_INVALID, 0},
+ [12] = {NV_AON_SLICE_INVALID, 0},
+ [13] = {NV_AON_SLICE_INVALID, 0},
+ [14] = {NV_AON_SLICE_INVALID, 0},
+ [15] = {NV_AON_SLICE_INVALID, 0},
+ /* CC port */
+ [16] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_19},
+ [17] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_18},
+ [18] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_17},
+ [19] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_16},
+ [20] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_15},
+ [21] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_14},
+ [22] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_13},
+ [23] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_12},
+ /* DD port */
+ [24] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_11},
+ [25] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_10},
+ [26] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_9},
+ [27] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_8},
+ [28] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_7},
+ [29] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_6},
+ [30] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_5},
+ [31] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_4},
+ /* EE port */
+ [32] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_3},
+ [33] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_2},
+ [34] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_1},
+ [35] = {3, NV_AON_HTE_SLICE2_IRQ_GPIO_0},
+ [36] = {NV_AON_SLICE_INVALID, 0},
+ [37] = {NV_AON_SLICE_INVALID, 0},
+ [38] = {NV_AON_SLICE_INVALID, 0},
+ [39] = {NV_AON_SLICE_INVALID, 0},
+};
+
static const struct tegra_hte_data t194_aon_hte = {
.map_sz = ARRAY_SIZE(tegra194_aon_gpio_map),
.map = tegra194_aon_gpio_map,
@@ -324,6 +415,8 @@ static const struct tegra_hte_data t194_aon_hte = {
.sec_map = tegra194_aon_gpio_sec_map,
.type = HTE_TEGRA_TYPE_GPIO,
.slices = 3,
+ .tsc_clkrate_hz = HTE_TS_CLK_RATE_HZ,
+ .tsc_clkrate_ns = HTE_CLK_RATE_NS,
};
static const struct tegra_hte_data t234_aon_hte = {
@@ -333,6 +426,19 @@ static const struct tegra_hte_data t234_aon_hte = {
.sec_map = tegra234_aon_gpio_sec_map,
.type = HTE_TEGRA_TYPE_GPIO,
.slices = 3,
+ .tsc_clkrate_hz = HTE_TS_CLK_RATE_HZ,
+ .tsc_clkrate_ns = HTE_CLK_RATE_NS,
+};
+
+static const struct tegra_hte_data t264_aon_hte = {
+ .map_sz = ARRAY_SIZE(tegra264_aon_gpio_map),
+ .map = tegra264_aon_gpio_map,
+ .sec_map_sz = ARRAY_SIZE(tegra264_aon_gpio_sec_map),
+ .sec_map = tegra264_aon_gpio_sec_map,
+ .type = HTE_TEGRA_TYPE_GPIO,
+ .slices = 4,
+ .tsc_clkrate_hz = HTE_TS_CLK_RATE_1G,
+ .tsc_clkrate_ns = HTE_CLK_RATE_NS_1G,
};
static const struct tegra_hte_data t194_lic_hte = {
@@ -340,6 +446,8 @@ static const struct tegra_hte_data t194_lic_hte = {
.map = NULL,
.type = HTE_TEGRA_TYPE_LIC,
.slices = 11,
+ .tsc_clkrate_hz = HTE_TS_CLK_RATE_HZ,
+ .tsc_clkrate_ns = HTE_CLK_RATE_NS,
};
static const struct tegra_hte_data t234_lic_hte = {
@@ -347,6 +455,17 @@ static const struct tegra_hte_data t234_lic_hte = {
.map = NULL,
.type = HTE_TEGRA_TYPE_LIC,
.slices = 17,
+ .tsc_clkrate_hz = HTE_TS_CLK_RATE_HZ,
+ .tsc_clkrate_ns = HTE_CLK_RATE_NS,
+};
+
+static const struct tegra_hte_data t264_lic_hte = {
+ .map_sz = 0,
+ .map = NULL,
+ .type = HTE_TEGRA_TYPE_LIC,
+ .slices = 10,
+ .tsc_clkrate_hz = HTE_TS_CLK_RATE_1G,
+ .tsc_clkrate_ns = HTE_CLK_RATE_NS_1G,
};
static inline u32 tegra_hte_readl(struct tegra_hte_soc *hte, u32 reg)
@@ -574,12 +693,12 @@ static int tegra_hte_release(struct hte_chip *chip, struct hte_ts_desc *desc,
static int tegra_hte_clk_src_info(struct hte_chip *chip,
struct hte_clk_info *ci)
{
- (void)chip;
+ struct tegra_hte_soc *hte_dev = chip->data;
if (!ci)
return -EINVAL;
- ci->hz = HTE_TS_CLK_RATE_HZ;
+ ci->hz = hte_dev->prov_data->tsc_clkrate_hz;
ci->type = CLOCK_MONOTONIC;
return 0;
@@ -602,8 +721,10 @@ static void tegra_hte_read_fifo(struct tegra_hte_soc *gs)
{
u32 tsh, tsl, src, pv, cv, acv, slice, bit_index, line_id;
u64 tsc;
+ u8 tsc_ns_shift;
struct hte_ts_data el;
+ tsc_ns_shift = __builtin_ctz(gs->prov_data->tsc_clkrate_ns);
while ((tegra_hte_readl(gs, HTE_TESTATUS) >>
HTE_TESTATUS_OCCUPANCY_SHIFT) &
HTE_TESTATUS_OCCUPANCY_MASK) {
@@ -621,7 +742,7 @@ static void tegra_hte_read_fifo(struct tegra_hte_soc *gs)
while (acv) {
bit_index = __builtin_ctz(acv);
line_id = bit_index + (slice << 5);
- el.tsc = tsc << HTE_TS_NS_SHIFT;
+ el.tsc = tsc << tsc_ns_shift;
el.raw_level = tegra_hte_get_level(gs, line_id);
hte_push_ts_ns(gs->chip, line_id, &el);
acv &= ~BIT(bit_index);
@@ -656,6 +777,8 @@ static const struct of_device_id tegra_hte_of_match[] = {
{ .compatible = "nvidia,tegra194-gte-aon", .data = &t194_aon_hte},
{ .compatible = "nvidia,tegra234-gte-lic", .data = &t234_lic_hte},
{ .compatible = "nvidia,tegra234-gte-aon", .data = &t234_aon_hte},
+ { .compatible = "nvidia,tegra264-gte-lic", .data = &t264_lic_hte},
+ { .compatible = "nvidia,tegra264-gte-aon", .data = &t264_aon_hte},
{ }
};
MODULE_DEVICE_TABLE(of, tegra_hte_of_match);
--
2.34.1
^ permalink raw reply related
* [PATCH v2 3/3] arm64: tegra: Add GTE nodes for Tegra264
From: Suneel Garapati @ 2026-04-08 21:24 UTC (permalink / raw)
To: dipenp, jonathanh, thierry.reding, krzk+dt, conor+dt, amhetre,
sheetal, kkartik, robh, pshete, timestamp, devicetree,
linux-tegra, linux-kernel
Cc: Suneel Garapati
In-Reply-To: <20260408212413.217692-1-suneelg@nvidia.com>
Add AON GPIO and system LIC GTE instances for Tegra264.
Signed-off-by: Suneel Garapati <suneelg@nvidia.com>
---
arch/arm64/boot/dts/nvidia/tegra264.dtsi | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/arch/arm64/boot/dts/nvidia/tegra264.dtsi b/arch/arm64/boot/dts/nvidia/tegra264.dtsi
index 06d8357bdf52..c6630733d5e3 100644
--- a/arch/arm64/boot/dts/nvidia/tegra264.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra264.dtsi
@@ -3207,6 +3207,15 @@ agic_page5: interrupt-controller@99b0000 {
};
};
+ hte_lic: hardware-timestamp@8380000 {
+ compatible = "nvidia,tegra264-gte-lic";
+ reg = <0x0 0x08380000 0x0 0x10000>;
+ interrupts = <GIC_SPI 0x00000268 IRQ_TYPE_LEVEL_HIGH>;
+ nvidia,int-threshold = <1>;
+ #timestamp-cells = <1>;
+ status = "disabled";
+ };
+
gpcdma: dma-controller@8400000 {
compatible = "nvidia,tegra264-gpcdma", "nvidia,tegra186-gpcdma";
reg = <0x0 0x08400000 0x0 0x210000>;
@@ -3267,6 +3276,16 @@ hsp_top: hsp@8800000 {
#mbox-cells = <2>;
};
+ hte_aon: hardware-timestamp@c2b0000 {
+ compatible = "nvidia,tegra264-gte-aon";
+ reg = <0x0 0x0c2b0000 0x0 0x10000>;
+ interrupts = <GIC_SPI 0x00000226 IRQ_TYPE_LEVEL_HIGH>;
+ nvidia,int-threshold = <1>;
+ #timestamp-cells = <1>;
+ nvidia,gpio-controller = <&gpio_aon>;
+ status = "disabled";
+ };
+
rtc: rtc@c2c0000 {
compatible = "nvidia,tegra264-rtc", "nvidia,tegra20-rtc";
reg = <0x0 0x0c2c0000 0x0 0x10000>;
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v3 3/3] dt-bindings: i3c: Add AST2600 I3C global registers
From: Rob Herring (Arm) @ 2026-04-08 21:35 UTC (permalink / raw)
To: Dawid Glazik
Cc: Andrew Jeffery, Krzysztof Kozlowski, Joel Stanley,
linux-arm-kernel, Frank Li, Conor Dooley, linux-i3c,
Maciej Lawniczak, Alexandre Belloni, linux-aspeed, devicetree
In-Reply-To: <7f55458097ef651b4fc46650254afd3fa7b87348.1775679285.git.dawid.glazik@linux.intel.com>
On Wed, 08 Apr 2026 22:34:35 +0200, Dawid Glazik wrote:
> Introduce the device-tree bindings for I3C global registers found on
> AST2600 SoCs.
>
> Signed-off-by: Dawid Glazik <dawid.glazik@linux.intel.com>
> ---
> I wasn't sure if I should add newline at the end of the
> file or not so I took
> https://github.com/torvalds/linux/tree/master/Documentation/devicetree/bindings/i3c
> as an example.
> ---
> .../i3c/aspeed,ast2600-i3c-global.yaml | 55 +++++++++++++++++++
> 1 file changed, 55 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/i3c/aspeed,ast2600-i3c-global.yaml
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
./Documentation/devicetree/bindings/i3c/aspeed,ast2600-i3c-global.yaml:55:4: [error] no new line character at the end of file (new-line-at-end-of-file)
dtschema/dtc warnings/errors:
Lexical error: Documentation/devicetree/bindings/i3c/aspeed,ast2600-i3c-global.example.dts:27.35-55 Unexpected 'ASPEED_RESET_I3C_DMA'
FATAL ERROR: Syntax error parsing input tree
make[2]: *** [scripts/Makefile.dtbs:140: Documentation/devicetree/bindings/i3c/aspeed,ast2600-i3c-global.example.dtb] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1597: dt_binding_check] Error 2
make: *** [Makefile:248: __sub-make] Error 2
doc reference errors (make refcheckdocs):
See https://patchwork.kernel.org/project/devicetree/patch/7f55458097ef651b4fc46650254afd3fa7b87348.1775679285.git.dawid.glazik@linux.intel.com
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply
* Re: [PATCH 2/2] drm/panel: simple: Add EDT ETML1010G0DKA panel
From: Dominik Haller @ 2026-04-08 21:45 UTC (permalink / raw)
To: neil.armstrong@linaro.org, Frank.li@nxp.com
Cc: dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
krzysztof.kozlowski+dt@linaro.org, sam@ravnborg.org,
upstream@phytec.de, robh+dt@kernel.org, thierry.reding@gmail.com
In-Reply-To: <adRw6sNItxMNEfK6@lizhi-Precision-Tower-5810>
On Mo, 2026-04-06 at 22:50 -0400, Frank Li wrote:
> On Mon, Feb 06, 2023 at 02:20:31PM +0000, Dominik Haller wrote:
> > Hello,
>
> Neil Armstrong:
>
> It is quite old. Any reason why not pick this patch?
Hi,
this panel is eol and we've switched to etml1010g3dra and
ph128800t006-zhc01 in our kits.
So this patch can be dropped.
Dominik
>
> Frank
> >
> > ping here, this one got forgotten.
> > It still applies on drm-misc-next and v6.2-rc7
> >
> >
> > On 18.08.22 14:45, Dominik Haller wrote:
> > > Add support for the EDT ETML1010G0DKA 10.1" 1280x800 LVDS panel.
> > >
> > > Signed-off-by: Dominik Haller <d.haller@phytec.de>
> > > ---
> > > drivers/gpu/drm/panel/panel-simple.c | 29
> > > ++++++++++++++++++++++++++++
> > > 1 file changed, 29 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/panel/panel-simple.c
> > > b/drivers/gpu/drm/panel/panel-simple.c
> > > index f9e1f85daef7..9314db24ab51 100644
> > > --- a/drivers/gpu/drm/panel/panel-simple.c
> > > +++ b/drivers/gpu/drm/panel/panel-simple.c
> > > @@ -1779,6 +1779,32 @@ static const struct panel_desc
> > > edt_etml0700y5dha = {
> > > .connector_type = DRM_MODE_CONNECTOR_LVDS,
> > > };
> > >
> > > +static const struct drm_display_mode edt_etml1010g0dka_mode = {
> > > + .clock = 70000,
> > > + .hdisplay = 1280,
> > > + .hsync_start = 1280 + 100,
> > > + .hsync_end = 1280 + 100 + 19,
> > > + .htotal = 1280 + 100 + 19 + 41,
> > > + .vdisplay = 800,
> > > + .vsync_start = 800 + 4,
> > > + .vsync_end = 800 + 4 + 4,
> > > + .vtotal = 800 + 4 + 4 + 15,
> > > + .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC,
> > > +};
> > > +
> > > +static const struct panel_desc edt_etml1010g0dka = {
> > > + .modes = &edt_etml1010g0dka_mode,
> > > + .num_modes = 1,
> > > + .bpc = 8,
> > > + .size = {
> > > + .width = 216,
> > > + .height = 135,
> > > + },
> > > + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
> > > + .bus_flags = DRM_BUS_FLAG_DE_HIGH,
> > > + .connector_type = DRM_MODE_CONNECTOR_LVDS,
> > > +};
> > > +
> > > static const struct drm_display_mode edt_etmv570g2dhu_mode = {
> > > .clock = 25175,
> > > .hdisplay = 640,
> > > @@ -4057,6 +4083,9 @@ static const struct of_device_id
> > > platform_of_match[] = {
> > > }, {
> > > .compatible = "edt,etml0700y5dha",
> > > .data = &edt_etml0700y5dha,
> > > + }, {
> > > + .compatible = "edt,etml1010g0dka",
> > > + .data = &edt_etml1010g0dka,
> > > }, {
> > > .compatible = "edt,etmv570g2dhu",
> > > .data = &edt_etmv570g2dhu,
> >
> >
> > --
> > PHYTEC Messtechnik GmbH | Barcelona-Allee 1 | 55129 Mainz, Germany
> >
> > Geschäftsführer: Dipl.-Ing. Michael Mitezki, Dipl.-Ing. Bodo Huber
> > |
> > Handelsregister Mainz HRB 4656 | Finanzamt Mainz-Mitte | St.Nr.
> > 266500608, DE 149059855
> >
^ permalink raw reply
* Re: [PATCH v5 5/6] clk: fsl-sai: Extract clock setup into fsl_sai_clk_register()
From: Brian Masney @ 2026-04-08 21:58 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-clk, Conor Dooley, Krzysztof Kozlowski, Michael Turquette,
Michael Walle, Rob Herring, Stephen Boyd, devicetree,
linux-kernel
In-Reply-To: <20260407211123.77602-5-marex@nabladev.com>
Hi Marek,
On Tue, Apr 07, 2026 at 11:10:02PM +0200, Marek Vasut wrote:
> Create helper function fsl_sai_clk_register() to set up and register
> SAI clock. Rename BCLK specific struct fsl_sai_clk members with bclk_
> prefix. Use of_node_full_name(dev->of_node) and clock name to register
> uniquely named clock. This is done in preparation for the follow up
> patch, which adds MCLK support.
>
> Signed-off-by: Marek Vasut <marex@nabladev.com>
> ---
> Cc: Brian Masney <bmasney@redhat.com>
> Cc: Conor Dooley <conor+dt@kernel.org>
> Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Michael Walle <michael@walle.cc>
> Cc: Rob Herring <robh@kernel.org>
> Cc: Stephen Boyd <sboyd@kernel.org>
> Cc: devicetree@vger.kernel.org
> Cc: linux-clk@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> ---
> V4: New patch
> V5: - Include fsl_sai_of_clk_get() which returns only BCLK in here already
> - s/hw/chw/ in fsl_sai_clk_register
> ---
> drivers/clk/clk-fsl-sai.c | 90 +++++++++++++++++++++++++++------------
> 1 file changed, 63 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/clk/clk-fsl-sai.c b/drivers/clk/clk-fsl-sai.c
> index 27925893c4c27..01c5e26f55517 100644
> --- a/drivers/clk/clk-fsl-sai.c
> +++ b/drivers/clk/clk-fsl-sai.c
> @@ -26,20 +26,71 @@ struct fsl_sai_data {
> };
>
> struct fsl_sai_clk {
> - struct clk_divider div;
> - struct clk_gate gate;
> + struct clk_divider bclk_div;
> + struct clk_gate bclk_gate;
> + struct clk_hw *bclk_hw;
> spinlock_t lock;
> };
>
> +static struct clk_hw *
> +fsl_sai_of_clk_get(struct of_phandle_args *clkspec, void *data)
> +{
> + struct fsl_sai_clk *sai_clk = data;
> +
> + return sai_clk->bclk_hw;
> +}
> +
> +static int fsl_sai_clk_register(struct device *dev, void __iomem *base,
> + spinlock_t *lock, struct clk_divider *div,
> + struct clk_gate *gate, struct clk_hw **hw,
> + const int gate_bit, const int dir_bit,
> + const int div_reg, char *name)
> +{
> + const struct fsl_sai_data *data = device_get_match_data(dev);
> + struct clk_parent_data pdata = { .index = 0 };
> + struct clk_hw *chw;
> + char *cname;
> +
> + gate->reg = base + data->offset + I2S_CSR;
> + gate->bit_idx = gate_bit;
> + gate->lock = lock;
> +
> + div->reg = base + div_reg;
> + div->shift = CR2_DIV_SHIFT;
> + div->width = CR2_DIV_WIDTH;
> + div->lock = lock;
> +
> + cname = devm_kasprintf(dev, GFP_KERNEL, "%s.%s",
> + of_node_full_name(dev->of_node), name);
Sashiko has the following feedback:
https://sashiko.dev/#/patchset/20260407211123.77602-1-marex%40nabladev.com
Does using of_node_full_name() break debugfs directory creation?
The full node name usually contains slashes (e.g., soc/bus@1000/sai@2000),
which causes lookup_one_len() to reject the name with -EACCES when the CCF
tries to create the directories.
Also, if the device is instantiated without Device Tree, this evaluates to
"<no-node>", potentially causing collisions if multiple instances exist.
Would dev_name(dev) be more appropriate here?
> + if (!cname)
> + return -ENOMEM;
> +
> + chw = devm_clk_hw_register_composite_pdata(dev, cname,
> + &pdata, 1, NULL, NULL,
> + &div->hw,
> + &clk_divider_ops,
> + &gate->hw,
> + &clk_gate_ops,
> + CLK_SET_RATE_GATE);
> + if (IS_ERR(chw))
> + return PTR_ERR(chw);
> +
> + *hw = chw;
> +
> + /* Set clock direction */
> + writel(dir_bit, base + div_reg);
Sashiko also has the following feedback:
Is it safe to initialize the hardware register after registering the clock
with the CCF?
During devm_clk_hw_register_composite_pdata(), the Common Clock Framework
inspects the hardware to calculate and cache the initial clock rate based on
the existing divider value.
The subsequent writel() completely overwrites the 32-bit register, setting
the direction bit and zeroing out the divider bits. Because this occurs
after registration, the CCF is completely unaware of the change, leaving its
cached rate stale and mismatched with the hardware.
Additionally, since the clock is already exposed to the system, could this
lockless writel() race with concurrent clock operations like clk_set_rate()
and clobber new divider configurations?
The original code safely performed this initialization before registration.
Brian
^ permalink raw reply
* Re: [PATCH v5 5/6] clk: fsl-sai: Extract clock setup into fsl_sai_clk_register()
From: Brian Masney @ 2026-04-08 22:12 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-clk, Conor Dooley, Krzysztof Kozlowski, Michael Turquette,
Michael Walle, Rob Herring, Stephen Boyd, devicetree,
linux-kernel
In-Reply-To: <20260407211123.77602-5-marex@nabladev.com>
Hi Marek,
On Tue, Apr 07, 2026 at 11:10:02PM +0200, Marek Vasut wrote:
> Create helper function fsl_sai_clk_register() to set up and register
> SAI clock. Rename BCLK specific struct fsl_sai_clk members with bclk_
> prefix. Use of_node_full_name(dev->of_node) and clock name to register
> uniquely named clock. This is done in preparation for the follow up
> patch, which adds MCLK support.
>
> Signed-off-by: Marek Vasut <marex@nabladev.com>
> ---
> Cc: Brian Masney <bmasney@redhat.com>
> Cc: Conor Dooley <conor+dt@kernel.org>
> Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Michael Walle <michael@walle.cc>
> Cc: Rob Herring <robh@kernel.org>
> Cc: Stephen Boyd <sboyd@kernel.org>
> Cc: devicetree@vger.kernel.org
> Cc: linux-clk@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> ---
> V4: New patch
> V5: - Include fsl_sai_of_clk_get() which returns only BCLK in here already
> - s/hw/chw/ in fsl_sai_clk_register
> ---
> drivers/clk/clk-fsl-sai.c | 90 +++++++++++++++++++++++++++------------
> 1 file changed, 63 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/clk/clk-fsl-sai.c b/drivers/clk/clk-fsl-sai.c
> index 27925893c4c27..01c5e26f55517 100644
> --- a/drivers/clk/clk-fsl-sai.c
> +++ b/drivers/clk/clk-fsl-sai.c
> @@ -26,20 +26,71 @@ struct fsl_sai_data {
> };
>
> struct fsl_sai_clk {
> - struct clk_divider div;
> - struct clk_gate gate;
> + struct clk_divider bclk_div;
> + struct clk_gate bclk_gate;
> + struct clk_hw *bclk_hw;
> spinlock_t lock;
> };
>
> +static struct clk_hw *
> +fsl_sai_of_clk_get(struct of_phandle_args *clkspec, void *data)
> +{
> + struct fsl_sai_clk *sai_clk = data;
> +
> + return sai_clk->bclk_hw;
> +}
> +
> +static int fsl_sai_clk_register(struct device *dev, void __iomem *base,
> + spinlock_t *lock, struct clk_divider *div,
> + struct clk_gate *gate, struct clk_hw **hw,
> + const int gate_bit, const int dir_bit,
> + const int div_reg, char *name)
> +{
> + const struct fsl_sai_data *data = device_get_match_data(dev);
> + struct clk_parent_data pdata = { .index = 0 };
> + struct clk_hw *chw;
> + char *cname;
> +
> + gate->reg = base + data->offset + I2S_CSR;
> + gate->bit_idx = gate_bit;
> + gate->lock = lock;
> +
> + div->reg = base + div_reg;
> + div->shift = CR2_DIV_SHIFT;
> + div->width = CR2_DIV_WIDTH;
> + div->lock = lock;
> +
> + cname = devm_kasprintf(dev, GFP_KERNEL, "%s.%s",
> + of_node_full_name(dev->of_node), name);
> + if (!cname)
> + return -ENOMEM;
> +
> + chw = devm_clk_hw_register_composite_pdata(dev, cname,
> + &pdata, 1, NULL, NULL,
> + &div->hw,
> + &clk_divider_ops,
> + &gate->hw,
> + &clk_gate_ops,
> + CLK_SET_RATE_GATE);
> + if (IS_ERR(chw))
> + return PTR_ERR(chw);
> +
> + *hw = chw;
> +
> + /* Set clock direction */
> + writel(dir_bit, base + div_reg);
> +
> + return 0;
> +}
> +
> static int fsl_sai_clk_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> const struct fsl_sai_data *data = device_get_match_data(dev);
> struct fsl_sai_clk *sai_clk;
> - struct clk_parent_data pdata = { .index = 0 };
> struct clk *clk_bus;
> void __iomem *base;
> - struct clk_hw *hw;
> + int ret;
>
> sai_clk = devm_kzalloc(dev, sizeof(*sai_clk), GFP_KERNEL);
> if (!sai_clk)
> @@ -55,29 +106,14 @@ static int fsl_sai_clk_probe(struct platform_device *pdev)
>
> spin_lock_init(&sai_clk->lock);
>
> - sai_clk->gate.reg = base + data->offset + I2S_CSR;
> - sai_clk->gate.bit_idx = CSR_BCE_BIT;
> - sai_clk->gate.lock = &sai_clk->lock;
> -
> - sai_clk->div.reg = base + data->offset + I2S_CR2;
> - sai_clk->div.shift = CR2_DIV_SHIFT;
> - sai_clk->div.width = CR2_DIV_WIDTH;
> - sai_clk->div.lock = &sai_clk->lock;
> -
> - /* set clock direction, we are the BCLK master */
> - writel(CR2_BCD, base + data->offset + I2S_CR2);
> -
> - hw = devm_clk_hw_register_composite_pdata(dev, dev->of_node->name,
> - &pdata, 1, NULL, NULL,
> - &sai_clk->div.hw,
> - &clk_divider_ops,
> - &sai_clk->gate.hw,
> - &clk_gate_ops,
> - CLK_SET_RATE_GATE);
> - if (IS_ERR(hw))
> - return PTR_ERR(hw);
> -
> - return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw);
> + ret = fsl_sai_clk_register(dev, base, &sai_clk->lock,
> + &sai_clk->bclk_div, &sai_clk->bclk_gate,
> + &sai_clk->bclk_hw, CSR_BCE_BIT, CR2_BCD,
> + data->offset + I2S_CR2, "BCLK");
^^^^^^^^^^^^^^^^^^^^^^
Sashiko reports the following:
https://sashiko.dev/#/patchset/20260407211123.77602-1-marex%40nabladev.com
For MCLK, this evaluates to writel(MCR_MOE, base + I2S_MCR). Does this
overwrite the entire register and clear all other bits to 0? This could zero
out fields like the MCLK Divider Enable and Clock Source Select, breaking
the MCLK hardware divider.
It's the same behavior as what was there previously. There's a lot more
to the comment. Can you look and see if there's anything else valid in
Sashiko's comment that should be addressed while changes are being made
here?
Otherwise, based on what was there previously, this looks good to me.
Brian
^ permalink raw reply
* [PATCH v4 00/11] Input: support for STM FTS5
From: David Heidelberg via B4 Relay @ 2026-04-08 22:15 UTC (permalink / raw)
To: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
Bjorn Andersson, Konrad Dybcio
Cc: Petr Hodina, linux-input, linux-stm32, linux-arm-kernel,
linux-kernel, Krzysztof Kozlowski, devicetree, linux-arm-msm,
phone-devel, David Heidelberg, Konrad Dybcio
Used on various phones. Minimal viable driver.
Includes device-tree enabling touchscreen on Pixel 3.
What is missing:
- switching between AP and SLPI mode (to be able to wake up phone by touch)
- firmware loading
- anything above basic touch
Signed-off-by: David Heidelberg <david@ixit.cz>
---
Changes in v4:
- Wrap everything below enabling the supplies into stmfts_configure()
to avoid bunch of gotos to power off on error (Dmitry T.)
- Finished chip specific ops and removed is_fts5. (Dmitry T.)
- Link to v3: https://lore.kernel.org/r/20260403-stmfts5-v3-0-5da768cfd201@ixit.cz
Changes in v3:
- s/touchscreen_pins/touchscreen_irq_n. (Konrad)
- Use interrupts-extended. (Konrad)
- Fixed rebase conflict against 8665ceb926ec ("Input: stmfts - use guard notation when acquiring mutex")
- Rename switch-gpios to mode-switch-gpios.
- Do not define properties in if:then: branches. (Krzysztof)
- Link to v2: https://lore.kernel.org/r/20260315-stmfts5-v2-0-70bc83ee9591@ixit.cz
Changes in v2:
- Fix typo in the binding s/switch-gpio/switch-gpios/.
- Deduplacate allOf. (Rob yamllint)
- Add missing S-off-by. (Dmitry B.)
- Dropped irq-gpios as it's not needed. (Konrad)
- Correct x and y touchscreen area size. (Konrad)
- Correct reset introduction commit description. (Krzysztof)
- Partially implemented chip specific ops. (Dmitry T.)
- Separeted license naming cleanup into separate commit (Dmitry T.)
- Link to v1: https://lore.kernel.org/r/20260301-stmfts5-v1-0-22c458b9ac68@ixit.cz
---
David Heidelberg (7):
Input: stmfts - Fix the MODULE_LICENSE() string
Input: stmfts - Use dev struct directly
Input: stmfts - Switch to devm_regulator_bulk_get_const
Input: stmfts - abstract reading information from the firmware
Input: stmfts - disable regulators when power on fails
dt-bindings: input: touchscreen: st,stmfts: Introduce reset GPIO
dt-bindings: input: touchscreen: st,stmfts: Introduce STM FTS5
Petr Hodina (4):
Input: stmfts - use client to make future code cleaner
Input: stmfts - add optional reset GPIO support
Input: stmfts - support FTS5
arm64: dts: qcom: sdm845-google: Add STM FTS touchscreen support
.../bindings/input/touchscreen/st,stmfts.yaml | 19 +-
.../arm64/boot/dts/qcom/sdm845-google-blueline.dts | 19 +-
arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi | 2 +-
drivers/input/touchscreen/stmfts.c | 601 +++++++++++++++++++--
4 files changed, 580 insertions(+), 61 deletions(-)
---
base-commit: db7efce4ae23ad5e42f5f55428f529ff62b86fab
change-id: 20260214-stmfts5-b47311fbd732
Best regards,
--
David Heidelberg <david@ixit.cz>
^ permalink raw reply
* [PATCH v4 01/11] Input: stmfts - Fix the MODULE_LICENSE() string
From: David Heidelberg via B4 Relay @ 2026-04-08 22:15 UTC (permalink / raw)
To: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
Bjorn Andersson, Konrad Dybcio
Cc: Petr Hodina, linux-input, linux-stm32, linux-arm-kernel,
linux-kernel, Krzysztof Kozlowski, devicetree, linux-arm-msm,
phone-devel, David Heidelberg
In-Reply-To: <20260409-stmfts5-v4-0-64fe62027db5@ixit.cz>
From: David Heidelberg <david@ixit.cz>
Replace the bogus "GPL v2" with "GPL" as MODULE_LICNSE() string. The
value does not declare the module's exact license, but only lets the
module loader test whether the module is Free Software or not.
See commit bf7fbeeae6db ("module: Cure the MODULE_LICENSE "GPL" vs.
"GPL v2" bogosity") in the details of the issue. The fix is to use
"GPL" for all modules under any variant of the GPL.
Signed-off-by: David Heidelberg <david@ixit.cz>
---
drivers/input/touchscreen/stmfts.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index 8af87d0b6eb64..def6bd0c8e059 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -807,4 +807,4 @@ module_i2c_driver(stmfts_driver);
MODULE_AUTHOR("Andi Shyti <andi.shyti@samsung.com>");
MODULE_DESCRIPTION("STMicroelectronics FTS Touch Screen");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
--
2.53.0
^ permalink raw reply related
* [PATCH v4 02/11] Input: stmfts - Use dev struct directly
From: David Heidelberg via B4 Relay @ 2026-04-08 22:15 UTC (permalink / raw)
To: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
Bjorn Andersson, Konrad Dybcio
Cc: Petr Hodina, linux-input, linux-stm32, linux-arm-kernel,
linux-kernel, Krzysztof Kozlowski, devicetree, linux-arm-msm,
phone-devel, David Heidelberg
In-Reply-To: <20260409-stmfts5-v4-0-64fe62027db5@ixit.cz>
From: David Heidelberg <david@ixit.cz>
Makes the code better readable and noticably shorter.
Signed-off-by: David Heidelberg <david@ixit.cz>
---
drivers/input/touchscreen/stmfts.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index def6bd0c8e059..7b1e975a85668 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -619,6 +619,7 @@ static int stmfts_enable_led(struct stmfts_data *sdata)
static int stmfts_probe(struct i2c_client *client)
{
+ struct device *dev = &client->dev;
int err;
struct stmfts_data *sdata;
@@ -627,7 +628,7 @@ static int stmfts_probe(struct i2c_client *client)
I2C_FUNC_SMBUS_I2C_BLOCK))
return -ENODEV;
- sdata = devm_kzalloc(&client->dev, sizeof(*sdata), GFP_KERNEL);
+ sdata = devm_kzalloc(dev, sizeof(*sdata), GFP_KERNEL);
if (!sdata)
return -ENOMEM;
@@ -639,13 +640,13 @@ static int stmfts_probe(struct i2c_client *client)
sdata->regulators[STMFTS_REGULATOR_VDD].supply = "vdd";
sdata->regulators[STMFTS_REGULATOR_AVDD].supply = "avdd";
- err = devm_regulator_bulk_get(&client->dev,
+ err = devm_regulator_bulk_get(dev,
ARRAY_SIZE(sdata->regulators),
sdata->regulators);
if (err)
return err;
- sdata->input = devm_input_allocate_device(&client->dev);
+ sdata->input = devm_input_allocate_device(dev);
if (!sdata->input)
return -ENOMEM;
@@ -664,7 +665,7 @@ static int stmfts_probe(struct i2c_client *client)
input_set_abs_params(sdata->input, ABS_MT_PRESSURE, 0, 255, 0, 0);
input_set_abs_params(sdata->input, ABS_DISTANCE, 0, 255, 0, 0);
- sdata->use_key = device_property_read_bool(&client->dev,
+ sdata->use_key = device_property_read_bool(dev,
"touch-key-connected");
if (sdata->use_key) {
input_set_capability(sdata->input, EV_KEY, KEY_MENU);
@@ -685,20 +686,20 @@ static int stmfts_probe(struct i2c_client *client)
* interrupts. To be on the safe side it's better to not enable
* the interrupts during their request.
*/
- err = devm_request_threaded_irq(&client->dev, client->irq,
+ err = devm_request_threaded_irq(dev, client->irq,
NULL, stmfts_irq_handler,
IRQF_ONESHOT | IRQF_NO_AUTOEN,
"stmfts_irq", sdata);
if (err)
return err;
- dev_dbg(&client->dev, "initializing ST-Microelectronics FTS...\n");
+ dev_dbg(dev, "initializing ST-Microelectronics FTS...\n");
err = stmfts_power_on(sdata);
if (err)
return err;
- err = devm_add_action_or_reset(&client->dev, stmfts_power_off, sdata);
+ err = devm_add_action_or_reset(dev, stmfts_power_off, sdata);
if (err)
return err;
@@ -715,13 +716,13 @@ static int stmfts_probe(struct i2c_client *client)
* without LEDs. The ledvdd regulator pointer will be
* used as a flag.
*/
- dev_warn(&client->dev, "unable to use touchkey leds\n");
+ dev_warn(dev, "unable to use touchkey leds\n");
sdata->ledvdd = NULL;
}
}
- pm_runtime_enable(&client->dev);
- device_enable_async_suspend(&client->dev);
+ pm_runtime_enable(dev);
+ device_enable_async_suspend(dev);
return 0;
}
--
2.53.0
^ permalink raw reply related
* [PATCH v4 03/11] Input: stmfts - Switch to devm_regulator_bulk_get_const
From: David Heidelberg via B4 Relay @ 2026-04-08 22:15 UTC (permalink / raw)
To: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
Bjorn Andersson, Konrad Dybcio
Cc: Petr Hodina, linux-input, linux-stm32, linux-arm-kernel,
linux-kernel, Krzysztof Kozlowski, devicetree, linux-arm-msm,
phone-devel, David Heidelberg
In-Reply-To: <20260409-stmfts5-v4-0-64fe62027db5@ixit.cz>
From: David Heidelberg <david@ixit.cz>
Switch to devm_regulator_bulk_get_const() to stop setting the supplies
list in probe(), and move the regulator_bulk_data struct in static const.
Signed-off-by: David Heidelberg <david@ixit.cz>
---
drivers/input/touchscreen/stmfts.c | 25 ++++++++++++-------------
1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index 7b1e975a85668..ff884e04ad4c8 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -69,9 +69,9 @@
#define STMFTS_MAX_FINGERS 10
#define STMFTS_DEV_NAME "stmfts"
-enum stmfts_regulators {
- STMFTS_REGULATOR_VDD,
- STMFTS_REGULATOR_AVDD,
+static const struct regulator_bulk_data stmfts_supplies[] = {
+ { .supply = "vdd" },
+ { .supply = "avdd" },
};
struct stmfts_data {
@@ -82,7 +82,7 @@ struct stmfts_data {
struct touchscreen_properties prop;
- struct regulator_bulk_data regulators[2];
+ struct regulator_bulk_data *supplies;
/*
* Presence of ledvdd will be used also to check
@@ -523,8 +523,8 @@ static int stmfts_power_on(struct stmfts_data *sdata)
int err;
u8 reg[8];
- err = regulator_bulk_enable(ARRAY_SIZE(sdata->regulators),
- sdata->regulators);
+ err = regulator_bulk_enable(ARRAY_SIZE(stmfts_supplies),
+ sdata->supplies);
if (err)
return err;
@@ -589,8 +589,8 @@ static void stmfts_power_off(void *data)
struct stmfts_data *sdata = data;
disable_irq(sdata->client->irq);
- regulator_bulk_disable(ARRAY_SIZE(sdata->regulators),
- sdata->regulators);
+ regulator_bulk_disable(ARRAY_SIZE(stmfts_supplies),
+ sdata->supplies);
}
static int stmfts_enable_led(struct stmfts_data *sdata)
@@ -638,11 +638,10 @@ static int stmfts_probe(struct i2c_client *client)
mutex_init(&sdata->mutex);
init_completion(&sdata->cmd_done);
- sdata->regulators[STMFTS_REGULATOR_VDD].supply = "vdd";
- sdata->regulators[STMFTS_REGULATOR_AVDD].supply = "avdd";
- err = devm_regulator_bulk_get(dev,
- ARRAY_SIZE(sdata->regulators),
- sdata->regulators);
+ err = devm_regulator_bulk_get_const(dev,
+ ARRAY_SIZE(stmfts_supplies),
+ stmfts_supplies,
+ &sdata->supplies);
if (err)
return err;
--
2.53.0
^ permalink raw reply related
* [PATCH v4 05/11] Input: stmfts - disable regulators when power on fails
From: David Heidelberg via B4 Relay @ 2026-04-08 22:15 UTC (permalink / raw)
To: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
Bjorn Andersson, Konrad Dybcio
Cc: Petr Hodina, linux-input, linux-stm32, linux-arm-kernel,
linux-kernel, Krzysztof Kozlowski, devicetree, linux-arm-msm,
phone-devel, David Heidelberg
In-Reply-To: <20260409-stmfts5-v4-0-64fe62027db5@ixit.cz>
From: David Heidelberg <david@ixit.cz>
We must power off regulators after failing at power on phase.
Create stmfts_configure function, so we don't have to use goto.
Signed-off-by: David Heidelberg <david@ixit.cz>
---
drivers/input/touchscreen/stmfts.c | 37 ++++++++++++++++++++++++-------------
1 file changed, 24 insertions(+), 13 deletions(-)
diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index 71d9b747ccfc5..290511dd69437 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -539,22 +539,10 @@ static int stmfts_read_system_info(struct stmfts_data *sdata)
return 0;
}
-static int stmfts_power_on(struct stmfts_data *sdata)
+static int stmfts_configure(struct stmfts_data *sdata)
{
int err;
- err = regulator_bulk_enable(ARRAY_SIZE(stmfts_supplies),
- sdata->supplies);
- if (err)
- return err;
-
- /*
- * The datasheet does not specify the power on time, but considering
- * that the reset time is < 10ms, I sleep 20ms to be sure
- */
- msleep(20);
-
-
err = stmfts_read_system_info(sdata);
if (err)
return err;
@@ -596,6 +584,29 @@ static int stmfts_power_on(struct stmfts_data *sdata)
return 0;
}
+static int stmfts_power_on(struct stmfts_data *sdata)
+{
+ int err;
+
+ err = regulator_bulk_enable(ARRAY_SIZE(stmfts_supplies),
+ sdata->supplies);
+ if (err)
+ return err;
+
+ /*
+ * The datasheet does not specify the power on time, but considering
+ * that the reset time is < 10ms, I sleep 20ms to be sure
+ */
+ msleep(20);
+
+ err = stmfts_configure(sdata);
+ if (err)
+ regulator_bulk_disable(ARRAY_SIZE(stmfts_supplies),
+ sdata->supplies);
+
+ return err;
+}
+
static void stmfts_power_off(void *data)
{
struct stmfts_data *sdata = data;
--
2.53.0
^ permalink raw reply related
* [PATCH v4 08/11] Input: stmfts - add optional reset GPIO support
From: David Heidelberg via B4 Relay @ 2026-04-08 22:15 UTC (permalink / raw)
To: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
Bjorn Andersson, Konrad Dybcio
Cc: Petr Hodina, linux-input, linux-stm32, linux-arm-kernel,
linux-kernel, Krzysztof Kozlowski, devicetree, linux-arm-msm,
phone-devel, David Heidelberg
In-Reply-To: <20260409-stmfts5-v4-0-64fe62027db5@ixit.cz>
From: Petr Hodina <petr.hodina@protonmail.com>
Add support for an optional "reset-gpios" property. If present, the
driver drives the reset line high at probe time and releases it during
power-on, after the regulators have been enabled.
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Co-developed-by: David Heidelberg <david@ixit.cz>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
drivers/input/touchscreen/stmfts.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index b61a19e954296..1e6d9a287cd0c 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -77,6 +77,7 @@ static const struct regulator_bulk_data stmfts_supplies[] = {
struct stmfts_data {
struct i2c_client *client;
struct input_dev *input;
+ struct gpio_desc *reset_gpio;
struct led_classdev led_cdev;
struct mutex mutex;
@@ -539,6 +540,15 @@ static int stmfts_read_system_info(struct stmfts_data *sdata)
return 0;
}
+static void stmfts_reset(struct stmfts_data *sdata)
+{
+ gpiod_set_value_cansleep(sdata->reset_gpio, 1);
+ msleep(20);
+
+ gpiod_set_value_cansleep(sdata->reset_gpio, 0);
+ msleep(50);
+}
+
static int stmfts_configure(struct stmfts_data *sdata)
{
int err;
@@ -599,6 +609,9 @@ static int stmfts_power_on(struct stmfts_data *sdata)
*/
msleep(20);
+ if (sdata->reset_gpio)
+ stmfts_reset(sdata);
+
err = stmfts_configure(sdata);
if (err)
regulator_bulk_disable(ARRAY_SIZE(stmfts_supplies),
@@ -612,6 +625,10 @@ static void stmfts_power_off(void *data)
struct stmfts_data *sdata = data;
disable_irq(sdata->client->irq);
+
+ if (sdata->reset_gpio)
+ gpiod_set_value_cansleep(sdata->reset_gpio, 1);
+
regulator_bulk_disable(ARRAY_SIZE(stmfts_supplies),
sdata->supplies);
}
@@ -668,6 +685,12 @@ static int stmfts_probe(struct i2c_client *client)
if (err)
return err;
+ sdata->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(sdata->reset_gpio))
+ return dev_err_probe(dev, PTR_ERR(sdata->reset_gpio),
+ "Failed to get GPIO 'reset'\n");
+
sdata->input = devm_input_allocate_device(dev);
if (!sdata->input)
return -ENOMEM;
--
2.53.0
^ permalink raw reply related
* [PATCH v4 07/11] dt-bindings: input: touchscreen: st,stmfts: Introduce reset GPIO
From: David Heidelberg via B4 Relay @ 2026-04-08 22:15 UTC (permalink / raw)
To: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
Bjorn Andersson, Konrad Dybcio
Cc: Petr Hodina, linux-input, linux-stm32, linux-arm-kernel,
linux-kernel, Krzysztof Kozlowski, devicetree, linux-arm-msm,
phone-devel, David Heidelberg
In-Reply-To: <20260409-stmfts5-v4-0-64fe62027db5@ixit.cz>
From: David Heidelberg <david@ixit.cz>
FTS has associated reset GPIO, document it.
Signed-off-by: David Heidelberg <david@ixit.cz>
---
Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml b/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml
index 12256ae7df90d..64c4f24ea3dd0 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml
@@ -40,6 +40,10 @@ properties:
vdd-supply:
description: Power supply
+ reset-gpios:
+ description: Reset GPIO (active-low)
+ maxItems: 1
+
required:
- compatible
- reg
--
2.53.0
^ permalink raw reply related
* [PATCH v4 09/11] dt-bindings: input: touchscreen: st,stmfts: Introduce STM FTS5
From: David Heidelberg via B4 Relay @ 2026-04-08 22:15 UTC (permalink / raw)
To: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
Bjorn Andersson, Konrad Dybcio
Cc: Petr Hodina, linux-input, linux-stm32, linux-arm-kernel,
linux-kernel, Krzysztof Kozlowski, devicetree, linux-arm-msm,
phone-devel, David Heidelberg
In-Reply-To: <20260409-stmfts5-v4-0-64fe62027db5@ixit.cz>
From: David Heidelberg <david@ixit.cz>
Introduce more recent STM FTS5 touchscreen support.
Signed-off-by: David Heidelberg <david@ixit.cz>
---
.../devicetree/bindings/input/touchscreen/st,stmfts.yaml | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml b/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml
index 64c4f24ea3dd0..441fc92b9a4ed 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/st,stmfts.yaml
@@ -16,10 +16,19 @@ description:
allOf:
- $ref: touchscreen.yaml#
+ - if:
+ properties:
+ compatible:
+ const: st,stmfts5
+ then:
+ required:
+ - mode-switch-gpios
properties:
compatible:
- const: st,stmfts
+ enum:
+ - st,stmfts
+ - st,stmfts5
reg:
maxItems: 1
@@ -40,6 +49,10 @@ properties:
vdd-supply:
description: Power supply
+ mode-switch-gpios:
+ description: Switch between touchscreen SLPI and AP mode.
+ maxItems: 1
+
reset-gpios:
description: Reset GPIO (active-low)
maxItems: 1
--
2.53.0
^ permalink raw reply related
* [PATCH v4 04/11] Input: stmfts - abstract reading information from the firmware
From: David Heidelberg via B4 Relay @ 2026-04-08 22:15 UTC (permalink / raw)
To: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
Bjorn Andersson, Konrad Dybcio
Cc: Petr Hodina, linux-input, linux-stm32, linux-arm-kernel,
linux-kernel, Krzysztof Kozlowski, devicetree, linux-arm-msm,
phone-devel, David Heidelberg
In-Reply-To: <20260409-stmfts5-v4-0-64fe62027db5@ixit.cz>
From: David Heidelberg <david@ixit.cz>
Improves readability and makes splitting power on function in following
commit easier.
Signed-off-by: David Heidelberg <david@ixit.cz>
---
drivers/input/touchscreen/stmfts.c | 36 ++++++++++++++++++++++++------------
1 file changed, 24 insertions(+), 12 deletions(-)
diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index ff884e04ad4c8..71d9b747ccfc5 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -518,22 +518,11 @@ static struct attribute *stmfts_sysfs_attrs[] = {
};
ATTRIBUTE_GROUPS(stmfts_sysfs);
-static int stmfts_power_on(struct stmfts_data *sdata)
+static int stmfts_read_system_info(struct stmfts_data *sdata)
{
int err;
u8 reg[8];
- err = regulator_bulk_enable(ARRAY_SIZE(stmfts_supplies),
- sdata->supplies);
- if (err)
- return err;
-
- /*
- * The datasheet does not specify the power on time, but considering
- * that the reset time is < 10ms, I sleep 20ms to be sure
- */
- msleep(20);
-
err = i2c_smbus_read_i2c_block_data(sdata->client, STMFTS_READ_INFO,
sizeof(reg), reg);
if (err < 0)
@@ -547,6 +536,29 @@ static int stmfts_power_on(struct stmfts_data *sdata)
sdata->config_id = reg[4];
sdata->config_ver = reg[5];
+ return 0;
+}
+
+static int stmfts_power_on(struct stmfts_data *sdata)
+{
+ int err;
+
+ err = regulator_bulk_enable(ARRAY_SIZE(stmfts_supplies),
+ sdata->supplies);
+ if (err)
+ return err;
+
+ /*
+ * The datasheet does not specify the power on time, but considering
+ * that the reset time is < 10ms, I sleep 20ms to be sure
+ */
+ msleep(20);
+
+
+ err = stmfts_read_system_info(sdata);
+ if (err)
+ return err;
+
enable_irq(sdata->client->irq);
msleep(50);
--
2.53.0
^ permalink raw reply related
* [PATCH v4 06/11] Input: stmfts - use client to make future code cleaner
From: David Heidelberg via B4 Relay @ 2026-04-08 22:15 UTC (permalink / raw)
To: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
Bjorn Andersson, Konrad Dybcio
Cc: Petr Hodina, linux-input, linux-stm32, linux-arm-kernel,
linux-kernel, Krzysztof Kozlowski, devicetree, linux-arm-msm,
phone-devel, David Heidelberg
In-Reply-To: <20260409-stmfts5-v4-0-64fe62027db5@ixit.cz>
From: Petr Hodina <petr.hodina@protonmail.com>
Make code cleaner, compiler will optimize it away anyway.
Preparation for FTM5 support, where more steps are needed.
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
drivers/input/touchscreen/stmfts.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index 290511dd69437..b61a19e954296 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -769,9 +769,10 @@ static int stmfts_runtime_suspend(struct device *dev)
static int stmfts_runtime_resume(struct device *dev)
{
struct stmfts_data *sdata = dev_get_drvdata(dev);
+ struct i2c_client *client = sdata->client;
int ret;
- ret = i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_OUT);
+ ret = i2c_smbus_write_byte(client, STMFTS_SLEEP_OUT);
if (ret)
dev_err(dev, "failed to resume device: %d\n", ret);
--
2.53.0
^ permalink raw reply related
* [PATCH v4 11/11] arm64: dts: qcom: sdm845-google: Add STM FTS touchscreen support
From: David Heidelberg via B4 Relay @ 2026-04-08 22:15 UTC (permalink / raw)
To: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
Bjorn Andersson, Konrad Dybcio
Cc: Petr Hodina, linux-input, linux-stm32, linux-arm-kernel,
linux-kernel, Krzysztof Kozlowski, devicetree, linux-arm-msm,
phone-devel, David Heidelberg, Konrad Dybcio
In-Reply-To: <20260409-stmfts5-v4-0-64fe62027db5@ixit.cz>
From: Petr Hodina <petr.hodina@protonmail.com>
Basic touchscreen connected to second i2c bus.
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Co-developed-by: David Heidelberg <david@ixit.cz>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
arch/arm64/boot/dts/qcom/sdm845-google-blueline.dts | 19 ++++++++++++++++++-
arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi | 2 +-
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/sdm845-google-blueline.dts b/arch/arm64/boot/dts/qcom/sdm845-google-blueline.dts
index fa89be500fb85..8fb988130b551 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-google-blueline.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-google-blueline.dts
@@ -26,7 +26,24 @@ &i2c2 {
status = "okay";
- /* ST,FTS @ 49 */
+ touchscreen@49 {
+ compatible = "st,stmfts5";
+ reg = <0x49>;
+
+ pinctrl-0 = <&touchscreen_irq_n>, <&touchscreen_reset>;
+ pinctrl-names = "default";
+
+ interrupts-extended = <&tlmm 125 IRQ_TYPE_LEVEL_LOW>;
+
+ mode-switch-gpios = <&tlmm 136 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&tlmm 99 GPIO_ACTIVE_LOW>;
+
+ avdd-supply = <&vreg_l14a_1p8>;
+ vdd-supply = <&vreg_l19a_3p3>;
+
+ touchscreen-size-x = <1080>;
+ touchscreen-size-y = <2160>;
+ };
};
&mdss_dsi0 {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi
index 6930066857768..4653c63ec26d2 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-google-common.dtsi
@@ -466,7 +466,7 @@ touchscreen_reset: ts-reset-state {
bias-pull-up;
};
- touchscreen_pins: ts-pins-gpio-state {
+ touchscreen_irq_n: ts-irq-n-gpio-state {
pins = "gpio125";
function = "gpio";
drive-strength = <2>;
--
2.53.0
^ permalink raw reply related
* [PATCH v4 10/11] Input: stmfts - support FTS5
From: David Heidelberg via B4 Relay @ 2026-04-08 22:15 UTC (permalink / raw)
To: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
Bjorn Andersson, Konrad Dybcio
Cc: Petr Hodina, linux-input, linux-stm32, linux-arm-kernel,
linux-kernel, Krzysztof Kozlowski, devicetree, linux-arm-msm,
phone-devel, David Heidelberg
In-Reply-To: <20260409-stmfts5-v4-0-64fe62027db5@ixit.cz>
From: Petr Hodina <petr.hodina@protonmail.com>
FTS support SLPI and AP mode, introduce mode-switch GPIO to switch between
those two. Currently we can handle only full power AP mode, so we just
keep the AP on.
Useful for devices like Pixel 3 (blueline) and many others.
Signed-off-by: Petr Hodina <petr.hodina@protonmail.com>
Co-developed-by: David Heidelberg <david@ixit.cz>
Signed-off-by: David Heidelberg <david@ixit.cz>
---
drivers/input/touchscreen/stmfts.c | 494 ++++++++++++++++++++++++++++++++++---
1 file changed, 466 insertions(+), 28 deletions(-)
diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c
index 1e6d9a287cd0c..e613299e37557 100644
--- a/drivers/input/touchscreen/stmfts.c
+++ b/drivers/input/touchscreen/stmfts.c
@@ -1,8 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
-// STMicroelectronics FTS Touchscreen device driver
-//
-// Copyright (c) 2017 Samsung Electronics Co., Ltd.
-// Copyright (c) 2017 Andi Shyti <andi@etezian.org>
+/* STMicroelectronics FTS Touchscreen device driver
+ *
+ * Copyright 2017 Samsung Electronics Co., Ltd.
+ * Copyright 2017 Andi Shyti <andi@etezian.org>
+ * Copyright David Heidelberg <david@ixit.cz>
+ * Copyright Petr Hodina <petr.hodina@protonmail.com>
+ */
#include <linux/delay.h>
#include <linux/i2c.h>
@@ -12,6 +15,7 @@
#include <linux/irq.h>
#include <linux/leds.h>
#include <linux/module.h>
+#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
@@ -34,6 +38,7 @@
#define STMFTS_FULL_FORCE_CALIBRATION 0xa2
#define STMFTS_MS_CX_TUNING 0xa3
#define STMFTS_SS_CX_TUNING 0xa4
+#define STMFTS5_SET_SCAN_MODE 0xa0
/* events */
#define STMFTS_EV_NO_EVENT 0x00
@@ -51,12 +56,32 @@
#define STMFTS_EV_STATUS 0x16
#define STMFTS_EV_DEBUG 0xdb
+/* events FTS5 */
+#define STMFTS5_EV_CONTROLLER_READY 0x03
+/* FTM5 event IDs (full byte, not masked) */
+#define STMFTS5_EV_MULTI_TOUCH_ENTER 0x13
+#define STMFTS5_EV_MULTI_TOUCH_MOTION 0x23
+#define STMFTS5_EV_MULTI_TOUCH_LEAVE 0x33
+#define STMFTS5_EV_STATUS_UPDATE 0x43
+#define STMFTS5_EV_USER_REPORT 0x53
+#define STMFTS5_EV_DEBUG 0xe3
+#define STMFTS5_EV_ERROR 0xf3
+
/* multi touch related event masks */
#define STMFTS_MASK_EVENT_ID 0x0f
#define STMFTS_MASK_TOUCH_ID 0xf0
#define STMFTS_MASK_LEFT_EVENT 0x0f
#define STMFTS_MASK_X_MSB 0x0f
#define STMFTS_MASK_Y_LSB 0xf0
+#define STMFTS5_MASK_TOUCH_TYPE 0x0f
+
+/* touch type classifications */
+#define STMFTS_TOUCH_TYPE_INVALID 0x00
+#define STMFTS_TOUCH_TYPE_FINGER 0x01
+#define STMFTS_TOUCH_TYPE_GLOVE 0x02
+#define STMFTS_TOUCH_TYPE_STYLUS 0x03
+#define STMFTS_TOUCH_TYPE_PALM 0x04
+#define STMFTS_TOUCH_TYPE_HOVER 0x05
/* key related event masks */
#define STMFTS_MASK_KEY_NO_TOUCH 0x00
@@ -75,9 +100,12 @@ static const struct regulator_bulk_data stmfts_supplies[] = {
};
struct stmfts_data {
+ const struct stmfts_chip_ops *ops;
+
struct i2c_client *client;
struct input_dev *input;
struct gpio_desc *reset_gpio;
+ struct gpio_desc *mode_switch_gpio;
struct led_classdev led_cdev;
struct mutex mutex;
@@ -101,12 +129,27 @@ struct stmfts_data {
struct completion cmd_done;
+ unsigned long touch_id;
+ unsigned long stylus_id;
+
bool use_key;
bool led_status;
bool hover_enabled;
+ bool stylus_enabled;
bool running;
};
+struct stmfts_chip_ops {
+ int (*configure)(struct stmfts_data *sdata);
+ void (*power_off)(struct stmfts_data *sdata);
+ int (*setup_input)(struct stmfts_data *sdata);
+ int (*input_open)(struct input_dev *dev);
+ void (*input_close)(struct input_dev *dev);
+ void (*parse_events)(struct stmfts_data *sdata);
+ int (*set_hover)(struct stmfts_data *sdata, bool enable);
+ int (*runtime_resume)(struct stmfts_data *sdata);
+};
+
static int stmfts_brightness_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
@@ -169,6 +212,7 @@ static int stmfts_read_events(struct stmfts_data *sdata)
return ret == ARRAY_SIZE(msgs) ? 0 : -EIO;
}
+/* FTS4 event handling functions */
static void stmfts_report_contact_event(struct stmfts_data *sdata,
const u8 event[])
{
@@ -204,6 +248,157 @@ static void stmfts_report_contact_release(struct stmfts_data *sdata,
input_sync(sdata->input);
}
+/* FTS5 event handling functions */
+static void stmfts5_report_contact_event(struct stmfts_data *sdata,
+ const u8 event[])
+{
+ u8 area;
+ u8 maj;
+ u8 min;
+ /* FTM5 event format:
+ * event[0] = event ID (0x13/0x23)
+ * event[1] = touch type (low 4 bits) | touch ID (high 4 bits)
+ * event[2] = X LSB
+ * event[3] = X MSB (low 4 bits) | Y MSB (high 4 bits)
+ * event[4] = Y LSB
+ * event[5] = pressure
+ * event[6] = major (low 4 bits) | minor (high 4 bits)
+ * event[7] = minor (high 2 bits)
+ */
+ u8 touch_id = (event[1] & STMFTS_MASK_TOUCH_ID) >> 4;
+ u8 touch_type = event[1] & STMFTS5_MASK_TOUCH_TYPE;
+ int x, y, distance;
+ unsigned int tool = MT_TOOL_FINGER;
+ bool touch_condition = true;
+
+ /* Parse coordinates with better precision */
+ x = (((int)event[3] & STMFTS_MASK_X_MSB) << 8) | event[2];
+ y = ((int)event[4] << 4) | ((event[3] & STMFTS_MASK_Y_LSB) >> 4);
+
+ /* Parse pressure - ensure non-zero for active touch */
+ area = event[5];
+ if (area <= 0 && touch_type != STMFTS_TOUCH_TYPE_HOVER) {
+ /* Should not happen for contact events. Set minimum pressure
+ * to prevent touch from being dropped
+ */
+ dev_warn_once(&sdata->client->dev,
+ "zero pressure on contact event, slot %d\n", touch_id);
+ area = 1;
+ }
+
+ /* Parse touch area with improved bit extraction */
+ maj = (((event[0] & 0x0C) << 2) | ((event[6] & 0xF0) >> 4));
+ min = (((event[7] & 0xC0) >> 2) | (event[6] & 0x0F));
+
+ /* Distance is 0 for touching, max for hovering */
+ distance = 0;
+
+ /* Classify touch type and set appropriate tool and parameters */
+ switch (touch_type) {
+ case STMFTS_TOUCH_TYPE_STYLUS:
+ if (sdata->stylus_enabled) {
+ tool = MT_TOOL_PEN;
+ __set_bit(touch_id, &sdata->stylus_id);
+ __clear_bit(touch_id, &sdata->touch_id);
+ break;
+ }
+ fallthrough; /* Report as finger if stylus not enabled */
+
+ case STMFTS_TOUCH_TYPE_FINGER:
+ case STMFTS_TOUCH_TYPE_GLOVE:
+ tool = MT_TOOL_FINGER;
+ __set_bit(touch_id, &sdata->touch_id);
+ __clear_bit(touch_id, &sdata->stylus_id);
+ break;
+
+ case STMFTS_TOUCH_TYPE_PALM:
+ /* Palm touch - report but can be filtered by userspace */
+ tool = MT_TOOL_PALM;
+ __set_bit(touch_id, &sdata->touch_id);
+ __clear_bit(touch_id, &sdata->stylus_id);
+ break;
+
+ case STMFTS_TOUCH_TYPE_HOVER:
+ tool = MT_TOOL_FINGER;
+ touch_condition = false;
+ area = 0;
+ distance = 255;
+ __set_bit(touch_id, &sdata->touch_id);
+ __clear_bit(touch_id, &sdata->stylus_id);
+ break;
+
+ case STMFTS_TOUCH_TYPE_INVALID:
+ default:
+ dev_warn(&sdata->client->dev,
+ "invalid touch type %d for slot %d\n",
+ touch_type, touch_id);
+ return;
+ }
+
+ /* Boundary check - some devices report max value, adjust */
+ if (x >= sdata->prop.max_x)
+ x = sdata->prop.max_x - 1;
+ if (y >= sdata->prop.max_y)
+ y = sdata->prop.max_y - 1;
+
+ input_mt_slot(sdata->input, touch_id);
+ input_report_key(sdata->input, BTN_TOUCH, touch_condition);
+ input_mt_report_slot_state(sdata->input, tool, true);
+
+ input_report_abs(sdata->input, ABS_MT_POSITION_X, x);
+ input_report_abs(sdata->input, ABS_MT_POSITION_Y, y);
+ input_report_abs(sdata->input, ABS_MT_TOUCH_MAJOR, maj);
+ input_report_abs(sdata->input, ABS_MT_TOUCH_MINOR, min);
+ input_report_abs(sdata->input, ABS_MT_PRESSURE, area);
+ input_report_abs(sdata->input, ABS_MT_DISTANCE, distance);
+
+ input_sync(sdata->input);
+}
+
+static void stmfts5_report_contact_release(struct stmfts_data *sdata,
+ const u8 event[])
+{
+ /* FTM5 format: touch ID is in high 4 bits of event[1] */
+ u8 touch_id = (event[1] & STMFTS_MASK_TOUCH_ID) >> 4;
+ u8 touch_type = event[1] & STMFTS5_MASK_TOUCH_TYPE;
+ unsigned int tool = MT_TOOL_FINGER;
+
+ /* Determine tool type based on touch classification */
+ switch (touch_type) {
+ case STMFTS_TOUCH_TYPE_STYLUS:
+ if (sdata->stylus_enabled) {
+ tool = MT_TOOL_PEN;
+ __clear_bit(touch_id, &sdata->stylus_id);
+ } else {
+ __clear_bit(touch_id, &sdata->touch_id);
+ }
+ break;
+
+ case STMFTS_TOUCH_TYPE_PALM:
+ tool = MT_TOOL_PALM;
+ __clear_bit(touch_id, &sdata->touch_id);
+ break;
+
+ case STMFTS_TOUCH_TYPE_FINGER:
+ case STMFTS_TOUCH_TYPE_GLOVE:
+ case STMFTS_TOUCH_TYPE_HOVER:
+ default:
+ tool = MT_TOOL_FINGER;
+ __clear_bit(touch_id, &sdata->touch_id);
+ break;
+ }
+
+ input_mt_slot(sdata->input, touch_id);
+ input_report_abs(sdata->input, ABS_MT_PRESSURE, 0);
+ input_mt_report_slot_state(sdata->input, tool, false);
+
+ /* Report BTN_TOUCH only if no touches remain */
+ if (!sdata->touch_id && !sdata->stylus_id)
+ input_report_key(sdata->input, BTN_TOUCH, 0);
+
+ input_sync(sdata->input);
+}
+
static void stmfts_report_hover_event(struct stmfts_data *sdata,
const u8 event[])
{
@@ -251,7 +446,6 @@ static void stmfts_parse_events(struct stmfts_data *sdata)
u8 *event = &sdata->data[i * STMFTS_EVENT_SIZE];
switch (event[0]) {
-
case STMFTS_EV_CONTROLLER_READY:
case STMFTS_EV_SLEEP_OUT_CONTROLLER_READY:
case STMFTS_EV_STATUS:
@@ -264,7 +458,6 @@ static void stmfts_parse_events(struct stmfts_data *sdata)
}
switch (event[0] & STMFTS_MASK_EVENT_ID) {
-
case STMFTS_EV_MULTI_TOUCH_ENTER:
case STMFTS_EV_MULTI_TOUCH_MOTION:
stmfts_report_contact_event(sdata, event);
@@ -298,6 +491,45 @@ static void stmfts_parse_events(struct stmfts_data *sdata)
}
}
+static void stmfts5_parse_events(struct stmfts_data *sdata)
+{
+ for (int i = 0; i < STMFTS_STACK_DEPTH; i++) {
+ u8 *event = &sdata->data[i * STMFTS_EVENT_SIZE];
+
+ switch (event[0]) {
+ case STMFTS5_EV_CONTROLLER_READY:
+ complete(&sdata->cmd_done);
+ fallthrough;
+
+ case STMFTS_EV_NO_EVENT:
+ case STMFTS5_EV_STATUS_UPDATE:
+ case STMFTS5_EV_USER_REPORT:
+ case STMFTS5_EV_DEBUG:
+ return;
+
+ case STMFTS5_EV_MULTI_TOUCH_ENTER:
+ case STMFTS5_EV_MULTI_TOUCH_MOTION:
+ stmfts5_report_contact_event(sdata, event);
+ break;
+
+ case STMFTS5_EV_MULTI_TOUCH_LEAVE:
+ stmfts5_report_contact_release(sdata, event);
+ break;
+
+ case STMFTS5_EV_ERROR:
+ dev_warn(&sdata->client->dev,
+ "error code: 0x%x%x%x%x%x%x",
+ event[6], event[5], event[4],
+ event[3], event[2], event[1]);
+ break;
+
+ default:
+ dev_err(&sdata->client->dev,
+ "unknown FTS5 event %#02x\n", event[0]);
+ }
+ }
+}
+
static irqreturn_t stmfts_irq_handler(int irq, void *dev)
{
struct stmfts_data *sdata = dev;
@@ -310,7 +542,7 @@ static irqreturn_t stmfts_irq_handler(int irq, void *dev)
dev_err(&sdata->client->dev,
"failed to read events: %d\n", err);
else
- stmfts_parse_events(sdata);
+ sdata->ops->parse_events(sdata);
return IRQ_HANDLED;
}
@@ -332,6 +564,25 @@ static int stmfts_command(struct stmfts_data *sdata, const u8 cmd)
return 0;
}
+static int stmfts5_set_scan_mode(struct stmfts_data *sdata, const u8 val)
+{
+ int err;
+
+ u8 scan_mode_cmd[3] = { STMFTS5_SET_SCAN_MODE, 0x00, val };
+ struct i2c_msg msg = {
+ .addr = sdata->client->addr,
+ .len = sizeof(scan_mode_cmd),
+ .buf = scan_mode_cmd,
+ };
+
+ err = i2c_transfer(sdata->client->adapter, &msg, 1);
+ if (err != 1)
+ return err < 0 ? err : -EIO;
+
+ return 0;
+
+}
+
static int stmfts_input_open(struct input_dev *dev)
{
struct stmfts_data *sdata = input_get_drvdata(dev);
@@ -371,6 +622,28 @@ static int stmfts_input_open(struct input_dev *dev)
return 0;
}
+static int stmfts5_input_open(struct input_dev *dev)
+{
+ struct stmfts_data *sdata = input_get_drvdata(dev);
+ int err;
+
+ err = pm_runtime_resume_and_get(&sdata->client->dev);
+ if (err)
+ return err;
+
+ mutex_lock(&sdata->mutex);
+ sdata->running = true;
+ mutex_unlock(&sdata->mutex);
+
+ err = stmfts5_set_scan_mode(sdata, 0xff);
+ if (err) {
+ pm_runtime_put_sync(&sdata->client->dev);
+ return err;
+ }
+
+ return 0;
+}
+
static void stmfts_input_close(struct input_dev *dev)
{
struct stmfts_data *sdata = input_get_drvdata(dev);
@@ -404,6 +677,23 @@ static void stmfts_input_close(struct input_dev *dev)
pm_runtime_put_sync(&sdata->client->dev);
}
+static void stmfts5_input_close(struct input_dev *dev)
+{
+ struct stmfts_data *sdata = input_get_drvdata(dev);
+ int err;
+
+ err = stmfts5_set_scan_mode(sdata, 0x00);
+ if (err)
+ dev_warn(&sdata->client->dev,
+ "failed to disable touchscreen: %d\n", err);
+
+ mutex_lock(&sdata->mutex);
+ sdata->running = false;
+ mutex_unlock(&sdata->mutex);
+
+ pm_runtime_put_sync(&sdata->client->dev);
+}
+
static ssize_t stmfts_sysfs_chip_id(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -484,10 +774,8 @@ static ssize_t stmfts_sysfs_hover_enable_write(struct device *dev,
guard(mutex)(&sdata->mutex);
if (hover != sdata->hover_enabled) {
- if (sdata->running) {
- err = i2c_smbus_write_byte(sdata->client,
- value ? STMFTS_SS_HOVER_SENSE_ON :
- STMFTS_SS_HOVER_SENSE_OFF);
+ if (sdata->running && sdata->ops->set_hover) {
+ err = sdata->ops->set_hover(sdata, hover);
if (err)
return err;
}
@@ -612,7 +900,7 @@ static int stmfts_power_on(struct stmfts_data *sdata)
if (sdata->reset_gpio)
stmfts_reset(sdata);
- err = stmfts_configure(sdata);
+ err = sdata->ops->configure(sdata);
if (err)
regulator_bulk_disable(ARRAY_SIZE(stmfts_supplies),
sdata->supplies);
@@ -620,6 +908,29 @@ static int stmfts_power_on(struct stmfts_data *sdata)
return err;
}
+static int stmfts5_configure(struct stmfts_data *sdata)
+{
+ u8 event[STMFTS_EVENT_SIZE];
+ int ret;
+
+ /* Verify I2C communication */
+ ret = i2c_smbus_read_i2c_block_data(sdata->client,
+ STMFTS_READ_ALL_EVENT,
+ sizeof(event), event);
+ if (ret < 0)
+ return ret;
+
+ enable_irq(sdata->client->irq);
+
+ return 0;
+}
+
+static void stmfts5_chip_power_off(struct stmfts_data *sdata)
+{
+ i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_IN);
+ msleep(20);
+}
+
static void stmfts_power_off(void *data)
{
struct stmfts_data *sdata = data;
@@ -629,10 +940,73 @@ static void stmfts_power_off(void *data)
if (sdata->reset_gpio)
gpiod_set_value_cansleep(sdata->reset_gpio, 1);
+ if (sdata->ops->power_off)
+ sdata->ops->power_off(sdata);
+
regulator_bulk_disable(ARRAY_SIZE(stmfts_supplies),
sdata->supplies);
}
+static int stmfts_setup_input(struct stmfts_data *sdata)
+{
+ struct device *dev = &sdata->client->dev;
+
+ input_set_abs_params(sdata->input, ABS_MT_ORIENTATION, 0, 255, 0, 0);
+ input_set_abs_params(sdata->input, ABS_DISTANCE, 0, 255, 0, 0);
+
+ sdata->use_key = device_property_read_bool(dev, "touch-key-connected");
+ if (sdata->use_key) {
+ input_set_capability(sdata->input, EV_KEY, KEY_MENU);
+ input_set_capability(sdata->input, EV_KEY, KEY_BACK);
+ }
+
+ return input_mt_init_slots(sdata->input, STMFTS_MAX_FINGERS,
+ INPUT_MT_DIRECT);
+}
+
+static int stmfts5_setup_input(struct stmfts_data *sdata)
+{
+ struct device *dev = &sdata->client->dev;
+
+ sdata->mode_switch_gpio = devm_gpiod_get_optional(dev, "mode-switch",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(sdata->mode_switch_gpio))
+ return dev_err_probe(dev, PTR_ERR(sdata->mode_switch_gpio),
+ "Failed to get GPIO 'switch'\n");
+
+ /* Mark as direct input device for calibration support */
+ __set_bit(INPUT_PROP_DIRECT, sdata->input->propbit);
+
+ /* Set up basic touch capabilities */
+ input_set_capability(sdata->input, EV_KEY, BTN_TOUCH);
+
+ /* Set resolution for accurate calibration */
+ if (!input_abs_get_res(sdata->input, ABS_MT_POSITION_X)) {
+ input_abs_set_res(sdata->input, ABS_MT_POSITION_X, 10);
+ input_abs_set_res(sdata->input, ABS_MT_POSITION_Y, 10);
+ }
+
+ input_set_abs_params(sdata->input, ABS_MT_DISTANCE, 0, 255, 0, 0);
+
+ /* Enable stylus support if requested */
+ sdata->stylus_enabled = device_property_read_bool(dev, "stylus-enabled");
+
+ /* Initialize touch tracking bitmaps */
+ sdata->touch_id = 0;
+ sdata->stylus_id = 0;
+
+ /* Initialize MT slots with support for pen tool type */
+ return input_mt_init_slots(sdata->input, STMFTS_MAX_FINGERS,
+ INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+}
+
+static int stmfts_set_hover(struct stmfts_data *sdata, bool enable)
+{
+ return i2c_smbus_write_byte(sdata->client,
+ enable ? STMFTS_SS_HOVER_SENSE_ON :
+ STMFTS_SS_HOVER_SENSE_OFF);
+}
+
static int stmfts_enable_led(struct stmfts_data *sdata)
{
int err;
@@ -678,6 +1052,8 @@ static int stmfts_probe(struct i2c_client *client)
mutex_init(&sdata->mutex);
init_completion(&sdata->cmd_done);
+ sdata->ops = of_device_get_match_data(dev);
+
err = devm_regulator_bulk_get_const(dev,
ARRAY_SIZE(stmfts_supplies),
stmfts_supplies,
@@ -697,8 +1073,8 @@ static int stmfts_probe(struct i2c_client *client)
sdata->input->name = STMFTS_DEV_NAME;
sdata->input->id.bustype = BUS_I2C;
- sdata->input->open = stmfts_input_open;
- sdata->input->close = stmfts_input_close;
+ sdata->input->open = sdata->ops->input_open;
+ sdata->input->close = sdata->ops->input_close;
input_set_capability(sdata->input, EV_ABS, ABS_MT_POSITION_X);
input_set_capability(sdata->input, EV_ABS, ABS_MT_POSITION_Y);
@@ -706,19 +1082,9 @@ static int stmfts_probe(struct i2c_client *client)
input_set_abs_params(sdata->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
input_set_abs_params(sdata->input, ABS_MT_TOUCH_MINOR, 0, 255, 0, 0);
- input_set_abs_params(sdata->input, ABS_MT_ORIENTATION, 0, 255, 0, 0);
input_set_abs_params(sdata->input, ABS_MT_PRESSURE, 0, 255, 0, 0);
- input_set_abs_params(sdata->input, ABS_DISTANCE, 0, 255, 0, 0);
-
- sdata->use_key = device_property_read_bool(dev,
- "touch-key-connected");
- if (sdata->use_key) {
- input_set_capability(sdata->input, EV_KEY, KEY_MENU);
- input_set_capability(sdata->input, EV_KEY, KEY_BACK);
- }
- err = input_mt_init_slots(sdata->input,
- STMFTS_MAX_FINGERS, INPUT_MT_DIRECT);
+ err = sdata->ops->setup_input(sdata);
if (err)
return err;
@@ -789,13 +1155,62 @@ static int stmfts_runtime_suspend(struct device *dev)
return ret;
}
-static int stmfts_runtime_resume(struct device *dev)
+static int stmfts_chip_runtime_resume(struct stmfts_data *sdata)
+{
+ return i2c_smbus_write_byte(sdata->client, STMFTS_SLEEP_OUT);
+}
+
+static int stmfts5_chip_runtime_resume(struct stmfts_data *sdata)
{
- struct stmfts_data *sdata = dev_get_drvdata(dev);
struct i2c_client *client = sdata->client;
+ struct device *dev = &client->dev;
+ u8 int_enable_cmd[4] = {0xB6, 0x00, 0x2C, 0x01};
+ struct i2c_msg msg = {
+ .addr = client->addr,
+ .len = sizeof(int_enable_cmd),
+ .buf = int_enable_cmd,
+ };
int ret;
ret = i2c_smbus_write_byte(client, STMFTS_SLEEP_OUT);
+ if (ret)
+ return ret;
+
+ msleep(20);
+
+ /* Perform capacitance tuning after wakeup */
+ ret = i2c_smbus_write_byte(client, STMFTS_MS_CX_TUNING);
+ if (ret)
+ dev_warn(dev, "MS_CX_TUNING failed: %d\n", ret);
+ msleep(20);
+
+ ret = i2c_smbus_write_byte(client, STMFTS_SS_CX_TUNING);
+ if (ret)
+ dev_warn(dev, "SS_CX_TUNING failed: %d\n", ret);
+ msleep(20);
+
+ /* Force calibration */
+ ret = i2c_smbus_write_byte(client, STMFTS_FULL_FORCE_CALIBRATION);
+ if (ret)
+ dev_warn(dev, "FORCE_CALIBRATION failed: %d\n", ret);
+ msleep(50);
+
+ /* Enable controller interrupts */
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret != 1)
+ return ret < 0 ? ret : -EIO;
+
+ msleep(20);
+
+ return 0;
+}
+
+static int stmfts_runtime_resume(struct device *dev)
+{
+ struct stmfts_data *sdata = dev_get_drvdata(dev);
+ int ret;
+
+ ret = sdata->ops->runtime_resume(sdata);
if (ret)
dev_err(dev, "failed to resume device: %d\n", ret);
@@ -824,8 +1239,29 @@ static const struct dev_pm_ops stmfts_pm_ops = {
};
#ifdef CONFIG_OF
+static const struct stmfts_chip_ops stmfts4_ops = {
+ .configure = stmfts_configure,
+ .setup_input = stmfts_setup_input,
+ .input_open = stmfts_input_open,
+ .input_close = stmfts_input_close,
+ .parse_events = stmfts_parse_events,
+ .set_hover = stmfts_set_hover,
+ .runtime_resume = stmfts_chip_runtime_resume,
+};
+
+static const struct stmfts_chip_ops stmfts5_ops = {
+ .configure = stmfts5_configure,
+ .power_off = stmfts5_chip_power_off,
+ .setup_input = stmfts5_setup_input,
+ .input_open = stmfts5_input_open,
+ .input_close = stmfts5_input_close,
+ .parse_events = stmfts5_parse_events,
+ .runtime_resume = stmfts5_chip_runtime_resume,
+};
+
static const struct of_device_id stmfts_of_match[] = {
- { .compatible = "st,stmfts", },
+ { .compatible = "st,stmfts", .data = &stmfts4_ops },
+ { .compatible = "st,stmfts5", .data = &stmfts5_ops },
{ },
};
MODULE_DEVICE_TABLE(of, stmfts_of_match);
@@ -853,5 +1289,7 @@ static struct i2c_driver stmfts_driver = {
module_i2c_driver(stmfts_driver);
MODULE_AUTHOR("Andi Shyti <andi.shyti@samsung.com>");
+MODULE_AUTHOR("David Heidelberg <david@ixit.cz>");
+MODULE_AUTHOR("Petr Hodina <petr.hodina@protonmail.com>");
MODULE_DESCRIPTION("STMicroelectronics FTS Touch Screen");
MODULE_LICENSE("GPL");
--
2.53.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox