* RE: [PATCH V11 02/12] PCI: host-generic: Add common helpers for parsing Root Port properties
From: Sherry Sun @ 2026-04-09 2:58 UTC (permalink / raw)
To: Manivannan Sadhasivam
Cc: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
Frank Li, s.hauer@pengutronix.de, kernel@pengutronix.de,
festevam@gmail.com, lpieralisi@kernel.org, kwilczynski@kernel.org,
bhelgaas@google.com, Hongxing Zhu, l.stach@pengutronix.de,
imx@lists.linux.dev, linux-pci@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <yijf6mwclpx6n7giucgykxvrm73baicy2urhzns34sxgloli3z@ygose2qrgvuz>
> On Wed, Apr 08, 2026 at 06:34:02AM +0000, Sherry Sun wrote:
>
> [...]
>
> > > > +/**
> > > > + * pci_host_common_parse_port - Parse a single Root Port node
> > > > + * @dev: Device pointer
> > > > + * @bridge: PCI host bridge
> > > > + * @node: Device tree node of the Root Port
> > > > + *
> > > > + * Returns: 0 on success, negative error code on failure */
> > > > +static int pci_host_common_parse_port(struct device *dev,
> > > > + struct pci_host_bridge *bridge,
> > > > + struct device_node *node) {
> > > > + struct pci_host_port *port;
> > > > + struct gpio_desc *reset;
> > > > +
> > > > + reset = devm_fwnode_gpiod_get(dev, of_fwnode_handle(node),
> > > > + "reset", GPIOD_ASIS, "PERST#");
> > >
> > > Sorry, I missed this earlier.
> > >
> > > Since PERST# is optional, you cannot reliably detect whether the
> > > Root Port binding intentionally skipped the PERST# GPIO or legacy
> > > binding is used, just by checking for PERST# in Root Port node.
> > >
> > > So this helper should do 3 things:
> > >
> > > 1. If PERST# is found in Root Port node, use it.
> > > 2. If not, check the RC node and if present, return -ENOENT to
> > > fallback to the legacy binding.
> > > 3. If not found in both nodes, assume that the PERST# is not present
> > > in the design, and proceed with parsing Root Port binding further.
> >
> > Hi Mani, understand, does the following code looks ok for above three
> cases?
> >
> > /* Check if PERST# is present in Root Port node */
> > reset = devm_fwnode_gpiod_get(dev, of_fwnode_handle(node),
> > "reset", GPIOD_ASIS, "PERST#");
> > if (IS_ERR(reset)) {
> > /* If error is not -ENOENT, it's a real error */
> > if (PTR_ERR(reset) != -ENOENT)
> > return PTR_ERR(reset);
> >
> > /* PERST# not found in Root Port node, check RC node */
> > rc_has_reset = of_property_read_bool(dev->of_node, "reset-gpios") ||
> > of_property_read_bool(dev->of_node, "reset-gpio");
>
> Just:
> if (of_property_read_bool(dev->of_node, "reset-gpios") ||
> of_property_read_bool(dev->of_node, "reset-gpio")) {
> return -ENOENT;
> }
Ok, will do.
>
> > if (rc_has_reset)
> > return -ENOENT;
> >
> > /* No PERST# in either node, assume not present in design */
> > reset = NULL;
> > }
> >
> > port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
> > if (!port)
> > return -ENOMEM;
> > ...
> >
> > >
> > > But there is one more important limitation here. Right now, this API
> > > only handles PERST#. But if another vendor tries to use it and if
> > > they need other properties such as PHY, clocks etc... those
> > > resources should be fetched optionally only by this helper. But if
> > > the controller has a hard dependency on those resources, the driver will
> fail to operate.
> > >
> > > I don't think we can fix this limitation though and those platforms
> > > should ensure that the resource dependency is correctly modeled in
> > > DT binding and the DTS is validated properly. It'd be good to
> > > mention this in the kernel doc of this API.
> >
> > Ok, I will add a NOTE for this in this API description.
> >
> > >
> > > > + if (IS_ERR(reset))
> > > > + return PTR_ERR(reset);
> > > > +
> > > > + port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
> > > > + if (!port)
> > > > + return -ENOMEM;
> > > > +
> > > > + port->reset = reset;
> > > > + INIT_LIST_HEAD(&port->list);
> > > > + list_add_tail(&port->list, &bridge->ports);
> > > > +
> > > > + return 0;
> > > > +}
> > > > +
> > > > +/**
> > > > + * pci_host_common_parse_ports - Parse Root Port nodes from
> > > > +device tree
> > > > + * @dev: Device pointer
> > > > + * @bridge: PCI host bridge
> > > > + *
> > > > + * This function iterates through child nodes of the host bridge
> > > > +and parses
> > > > + * Root Port properties (currently only reset GPIO).
> > > > + *
> > > > + * Returns: 0 on success, -ENOENT if no ports found, other
> > > > +negative error codes
> > > > + * on failure
> > > > + */
> > > > +int pci_host_common_parse_ports(struct device *dev, struct
> > > > +pci_host_bridge *bridge) {
> > > > + int ret = -ENOENT;
> > > > +
> > > > + for_each_available_child_of_node_scoped(dev->of_node, of_port) {
> > > > + if (!of_node_is_type(of_port, "pci"))
> > > > + continue;
> > > > + ret = pci_host_common_parse_port(dev, bridge, of_port);
> > > > + if (ret)
> > > > + return ret;
> > >
> > > As Sashiko flagged, you need to make sure that
> > > devm_add_action_or_reset() is added even during the error path:
> >
> > Yes, it needs to be fixed. We can handle it with the following two methods, I
> am not sure which method is better or more preferable?
> >
> > #1: register cleanup action after first successful port parse and use
> cleanup_registered flag to avoid duplicate register.
> > int ret = -ENOENT;
> > bool cleanup_registered = false;
> >
> > for_each_available_child_of_node_scoped(dev->of_node, of_port) {
> > if (!of_node_is_type(of_port, "pci"))
> > continue;
> > ret = pci_host_common_parse_port(dev, bridge, of_port);
> > if (ret)
> > return ret;
> >
> > /* Register cleanup action after first successful port parse */
> > if (!cleanup_registered) {
> > ret = devm_add_action_or_reset(dev,
> > pci_host_common_delete_ports,
> > &bridge->ports);
>
> Even if you register devm_add_action_or_reset(), it won't be called when
> pci_host_common_parse_port() fails since the legacy fallback will be used.
>
> So you need to manually call pci_host_common_delete_ports() in the error
> path.
Get your point, so seems I should just add the err_cleanup handle path like this, right?
for_each_available_child_of_node_scoped(dev->of_node, of_port) {
if (!of_node_is_type(of_port, "pci"))
continue;
ret = pci_host_common_parse_port(dev, bridge, of_port);
if (ret)
goto err_cleanup;
}
if (ret)
return ret;
return devm_add_action_or_reset(dev, pci_host_common_delete_ports,
&bridge->ports);
err_cleanup:
pci_host_common_delete_ports(&bridge->ports);
return ret;
Best Regards
Sherry
^ permalink raw reply
* [PATCH] drm/bridge: stm_lvds: Do not fail atomic_check on disabled connector
From: Marek Vasut @ 2026-04-09 2:48 UTC (permalink / raw)
To: dri-devel
Cc: Marek Vasut, Alexandre Torgue, David Airlie, Maarten Lankhorst,
Maxime Coquelin, Maxime Ripard, Philippe Cornu,
Raphael Gallais-Pou, Simona Vetter, Thomas Zimmermann,
Yannick Fertre, linux-arm-kernel, linux-kernel, linux-stm32
If the connector is disabled, the new connector state has .crtc field
set to NULL and there is nothing more to validate after that point.
The .crtc field being NULL is not an error. Test for .crtc being NULL,
and if it is NULL, exit early with return 0.
This fixes a failure in suspend/resume path, where the connector is
already disabled, but .atomic_check is called, fails, returns -EINVAL
and blocks the suspend entry.
Fixes: aca1cbc1c986 ("drm/stm: lvds: add new STM32 LVDS Display Interface Transmitter driver")
Signed-off-by: Marek Vasut <marex@nabladev.com>
---
Cc: Alexandre Torgue <alexandre.torgue@foss.st.com>
Cc: David Airlie <airlied@gmail.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Philippe Cornu <philippe.cornu@foss.st.com>
Cc: Raphael Gallais-Pou <raphael.gallais-pou@foss.st.com>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Yannick Fertre <yannick.fertre@foss.st.com>
Cc: dri-devel@lists.freedesktop.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-stm32@st-md-mailman.stormreply.com
---
drivers/gpu/drm/stm/lvds.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/stm/lvds.c b/drivers/gpu/drm/stm/lvds.c
index fe38c0984b2b5..25e2ba98f36ae 100644
--- a/drivers/gpu/drm/stm/lvds.c
+++ b/drivers/gpu/drm/stm/lvds.c
@@ -897,14 +897,14 @@ static int lvds_connector_atomic_check(struct drm_connector *connector,
if (!conn_state)
return -EINVAL;
+ if (!conn_state->crtc)
+ return 0;
+
if (list_empty(&connector->modes)) {
drm_dbg(connector->dev, "connector: empty modes list\n");
return -EINVAL;
}
- if (!conn_state->crtc)
- return -EINVAL;
-
panel_mode = list_first_entry(&connector->modes,
struct drm_display_mode, head);
--
2.53.0
^ permalink raw reply related
* RE: [PATCH V11 04/12] PCI: imx6: Add support for parsing the reset property in new Root Port binding
From: Sherry Sun @ 2026-04-09 2:40 UTC (permalink / raw)
To: Manivannan Sadhasivam
Cc: robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org,
Frank Li, s.hauer@pengutronix.de, kernel@pengutronix.de,
festevam@gmail.com, lpieralisi@kernel.org, kwilczynski@kernel.org,
bhelgaas@google.com, Hongxing Zhu, l.stach@pengutronix.de,
imx@lists.linux.dev, linux-pci@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <t5x45nyn6lw7cofzj2rec5j6z2ml6kve2hvzeeastdrv4hilsu@ujhkmltpp5ky>
> Subject: Re: [PATCH V11 04/12] PCI: imx6: Add support for parsing the reset
> property in new Root Port binding
>
> On Wed, Apr 08, 2026 at 08:34:03AM +0000, Sherry Sun wrote:
> > > On Tue, Apr 07, 2026 at 06:41:46PM +0800, Sherry Sun wrote:
> > > > The current DT binding for pci-imx6 specifies the 'reset-gpios'
> > > > property in the host bridge node. However, the PERST# signal
> > > > logically belongs to individual Root Ports rather than the host bridge
> itself.
> > > > This becomes important when supporting PCIe KeyE connector and PCI
> > > > power control framework for pci-imx6 driver, which requires
> > > > properties to be specified in Root Port nodes.
> > > >
> > > > Add support for parsing 'reset-gpios' from Root Port child nodes
> > > > using the common helper pci_host_common_parse_ports(), and update
> > > > the reset GPIO handling to use the parsed port list from
> > > > bridge->ports. To maintain DT backwards compatibility, fallback to
> > > > the legacy method of parsing the host bridge node if the reset
> > > > property is not present in the Root Port node.
> > > >
> > > > Since now the reset GPIO is obtained with GPIOD_ASIS flag, it may
> > > > be in input mode, using gpiod_direction_output() instead of
> > > > gpiod_set_value_cansleep() to ensure the reset GPIO is properly
> > > > configured as output before setting its value.
> > > >
> > > > Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
> > > > ---
> > > > drivers/pci/controller/dwc/pci-imx6.c | 75
> > > > +++++++++++++++++++++------
> > > > 1 file changed, 60 insertions(+), 15 deletions(-)
> > > >
> > > > diff --git a/drivers/pci/controller/dwc/pci-imx6.c
> > > > b/drivers/pci/controller/dwc/pci-imx6.c
> > > > index d99da7e42590..dd8f9c0fcec4 100644
> > > > --- a/drivers/pci/controller/dwc/pci-imx6.c
> > > > +++ b/drivers/pci/controller/dwc/pci-imx6.c
> > > > @@ -34,6 +34,7 @@
> > > > #include <linux/pm_runtime.h>
> > > >
> > > > #include "../../pci.h"
> > > > +#include "../pci-host-common.h"
> > > > #include "pcie-designware.h"
> > > >
> > > > #define IMX8MQ_GPR_PCIE_REF_USE_PAD BIT(9)
> > > > @@ -152,7 +153,6 @@ struct imx_lut_data {
> > > >
> > > > struct imx_pcie {
> > > > struct dw_pcie *pci;
> > > > - struct gpio_desc *reset_gpiod;
> > > > struct clk_bulk_data *clks;
> > > > int num_clks;
> > > > bool supports_clkreq;
> > > > @@ -1224,6 +1224,32 @@ static void imx_pcie_disable_device(struct
> > > pci_host_bridge *bridge,
> > > > imx_pcie_remove_lut(imx_pcie, pci_dev_id(pdev)); }
> > > >
> > > > +static int imx_pcie_parse_legacy_binding(struct imx_pcie *pcie) {
> > > > + struct device *dev = pcie->pci->dev;
> > > > + struct pci_host_bridge *bridge = pcie->pci->pp.bridge;
> > > > + struct pci_host_port *port;
> > > > + struct gpio_desc *reset;
> > > > +
> > > > + reset = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS);
> > > > + if (IS_ERR(reset))
> > > > + return PTR_ERR(reset);
> > > > +
> > > > + if (!reset)
> > > > + return 0;
> > > > +
> > > > + port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
> > > > + if (!port)
> > > > + return -ENOMEM;
> > > > +
> > > > + port->reset = reset;
> > > > + INIT_LIST_HEAD(&port->list);
> > > > + list_add_tail(&port->list, &bridge->ports);
> > > > +
> > > > + return devm_add_action_or_reset(dev,
> > > pci_host_common_delete_ports,
> > > > + &bridge->ports);
> > > > +}
> > > > +
> > > > static void imx_pcie_vpcie_aux_disable(void *data) {
> > > > struct regulator *vpcie_aux = data; @@ -1233,13 +1259,22 @@
> > > > static void imx_pcie_vpcie_aux_disable(void
> > > > *data)
> > > >
> > > > static void imx_pcie_assert_perst(struct imx_pcie *imx_pcie, bool
> > > > assert) {
> > > > - if (assert) {
> > > > - gpiod_set_value_cansleep(imx_pcie->reset_gpiod, 1);
> > > > - } else {
> > > > - if (imx_pcie->reset_gpiod) {
> > > > - msleep(PCIE_T_PVPERL_MS);
> > > > - gpiod_set_value_cansleep(imx_pcie->reset_gpiod, 0);
> > > > - msleep(PCIE_RESET_CONFIG_WAIT_MS);
> > > > + struct dw_pcie *pci = imx_pcie->pci;
> > > > + struct pci_host_bridge *bridge = pci->pp.bridge;
> > > > + struct pci_host_port *port;
> > > > +
> > > > + if (!bridge)
> > > > + return;
> > > > +
> > > > + list_for_each_entry(port, &bridge->ports, list) {
> > > > + if (assert) {
> > > > + gpiod_direction_output(port->reset, 1);
> > > > + } else {
> > > > + if (port->reset) {
> > > > + msleep(PCIE_T_PVPERL_MS);
> > > > + gpiod_direction_output(port->reset, 0);
> > > > + msleep(PCIE_RESET_CONFIG_WAIT_MS);
> > > > + }
> > >
> > > Sashiko flagged this loop:
> > >
> > > ```
> > > Does this loop multiply the initialization delays?
> > > If a controller has multiple Root Ports, the msleep calls will run
> > > sequentially for each port, linearly increasing the delay. Could we
> > > optimize this by asserting all reset GPIOs, waiting the pre-delay
> > > once, de-asserting all GPIOs, and waiting the post-delay once for the entire
> bus?
> > > ```
> > >
> > > Maybe you should do:
> > >
> > > if (!list_empty(&bridge->ports) && !assert)
> > > msleep(PCIE_T_PVPERL_MS);
> > >
> > > list_for_each_entry(port, &bridge->ports, list) {
> > > ...
> > > gpiod_direction_output(port->reset, 0);
> > > ...
> > > }
> > >
> > > if (!list_empty(&bridge->ports) && !assert)
> > > msleep(PCIE_RESET_CONFIG_WAIT_MS);
> > >
> >
> > Hi Mani, I think the code below looks clearer, is that ok for you?
> >
> > if (assert) {
> > list_for_each_entry(port, &bridge->ports, list)
> > gpiod_direction_output(port->reset, 1);
> > } else {
> > if (list_empty(&bridge->ports))
> > return;
> >
>
> This check should be moved out of the if() condition. Other than this, the
> change looks good.
Ok, will do.
>
> > msleep(PCIE_T_PVPERL_MS);
> > list_for_each_entry(port, &bridge->ports, list)
> > gpiod_direction_output(port->reset, 0);
> > msleep(PCIE_RESET_CONFIG_WAIT_MS);
> > }
> >
> > > And then this:
> > >
> > > ```
> > > Also, since this function is called from imx_pcie_resume_noirq,
> > > which executes with hardware interrupts disabled, does the use of
> > > msleep here trigger a 'sleeping while atomic' bug?
> > > ```
> > >
> > > This is a valid concern. You should use mdelay(). But I'd recommend
> > > switching to IRQ enabled callback, resume() instead. There is no
> > > complelling reason to use resume_noirq() in this driver and adding
> > > delays in noirq() callbacks is not recommended as it may increase the
> overall system resume time.
> > >
> > > I will submit a separate series to convert dw_pcie_resume_noirq()
> > > and its callers to IRQ enabled callbacks since this
> > > dw_pcie_resume_noirq() could potentially cause delay up to 1sec.
> >
> > Yes, this is not a new bug introduced by this patch. I agree we should
> > covert the convert dw_pcie_resume_noirq() and the caller to IRQ
> > enabled callbacks to fix this in a separate patch series.
> > For now, should I leave it as is, or switch to mdelay in this patch?
> >
>
> Just use mdelay() in your patch for now.
Ok, thanks!
Best Regards
Sherry
^ permalink raw reply
* Re: [PATCH] arm64: dts: imx93-9x9-qsb: Add tianma,tm050rdh03 panel
From: Liu Ying @ 2026-04-09 2:19 UTC (permalink / raw)
To: Frank Li
Cc: Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, imx, linux-arm-kernel,
devicetree, linux-kernel
In-Reply-To: <adYy9xesCKsYWNBg@lizhi-Precision-Tower-5810>
On Wed, Apr 08, 2026 at 06:50:31AM -0400, Frank Li wrote:
> On Wed, Apr 08, 2026 at 04:40:37PM +0800, Liu Ying wrote:
>> On Wed, Apr 08, 2026 at 04:28:40AM -0400, Frank Li wrote:
> ...
>>>>>>>
>>>>>>> Is it possible to appply this overlay file and kd50g21-40nt-a1 overlay file
>>>>>>>
>>>>>>> to imx93-9x9-qsb.dtb, so needn't create dtsi.
>>>>>>
>>>>>> I'm sorry, I don't get your question here.
>>>>>> Anyway, the DT overlays are needed, because the 40-pin EXP/PRI interface on
>>>>>> the i.MX93 9x9 QSB board can not only connect to a DPI panel adapter board
>>>>>> but also to an audio hat[2], and maybe more. The newly introduced .dtsi
>>>>>> file just aims to avoid duplicated code.
>>>>>
>>>>> My means apply two overlay files to dtb
>>>>>
>>>>> imx93-9x9-qsb-tianma-tm050rdh03-dtbs += imx93-9x9-qsb.dtb imx93-9x9-qsb-ontat-kd50g21-40nt-a1.dtbo imx93-9x9-qsb-tianma-tm050rdh03.dtbo
>>
>> This ...
>>
>>>>>
>>>>> In imx93-9x9-qsb-tianma-tm050rdh03.dtbo, only include
>>>>> &{/} {
>>>>> panel {
>>>>> compatible = "tianma,tm050rdh03";
>>>>> enable-gpios = <&pcal6524 8 GPIO_ACTIVE_HIGH>;
>>>>> };
>>>>> };
>>>>
>>>> If an user wants to use imx93-9x9-qsb.dtb and the DT overlay blob
>>>> imx93-9x9-qsb-tianma-tm050rdh03.dtbo to enable the tianma,tm050rdh03
>>>> DPI panel, then it won't work unless the user also apply
>>>> imx93-9x9-qsb-ontat-kd50g21-40nt-a1.dtbo, right?
>>>>
>>>>>
>>>
>>> Yes, imx93-9x9-qsb-tianma-tm050rdh03.dtb already created, which already
>>> applied both overlay file.
>>
>> .... indicates that imx93-9x9-qsb-tianma-tm050rdh03.dtb is generated by
>> applying both imx93-9x9-qsb-ontat-kd50g21-40nt-a1.dtbo and
>> imx93-9x9-qsb-tianma-tm050rdh03.dtbo to imx93-9x9-qsb.dtb.
>> While, imx93-9x9-qsb-tianma-tm050rdh03.dtbo(a DT overlay blob) just contains
>> the panel node, which means that an user __cannot_ enable the tianma,tm050rdh03
>> DPI panel by only applying it to imx93-9x9-qsb.dtb, unless the user also
>> applies imx93-9x9-qsb-ontat-kd50g21-40nt-a1.dtbo. That's why the .dtsi
>> file is needed.
>
> what's problem if we require user do that? Makefile already create finial
> imx93-9x9-qsb-tianma-tm050rdh03.dtb.
The problem is that the user would apply imx93-9x9-qsb-tianma-tm050rdh03.dtbo
to imx93-9x9-qsb.dtb to enable the tianma,tm050rdh03 DPI panel, say in the
U-boot stage with the 'fdt' command, which is fairly a typical usecase, just
like the user would apply imx93-9x9-qsb-ontat-kd50g21-40nt-a1.dtbo to
imx93-9x9-qsb.dtb to enable the ontat,kd50g21-40nt-a1 DPI panel. We cannot
ask the user to additionally apply imx93-9x9-qsb-ontat-kd50g21-40nt-a1.dtbo
to enable the tianma,tm050rdh03 DPI panel, because that's very confusing.
Note that imx93-9x9-qsb-tianma-tm050rdh03.dtb certainly can be used to
enable the tianma,tm050rdh03 DPI panel, but in addition to that,
imx93-9x9-qsb.dtb + imx93-9x9-qsb-tianma-tm050rdh03.dtbo can also be
used to enable the panel.
>
> Any user really apply dtso manaully without use kernel's Makefile?
That's not relevant.
The point is that imx93-9x9-qsb-tianma-tm050rdh03.dtbo would be generated
and applied by the user to imx93-9x9-qsb.dtb to enable the tianma,tm050rdh03
DPI panel.
>
>>
>>>
>>> can the same board be use for imx91 or other evk boards?
>>
>> Yes, both tianma,tm050rdh03 and ontat,kd50g21-40nt-a1 DPI panels can be
>> connected to i.MX91/93 11x11 EVK and 9x9 QSB boards.
>
> Is it possible to use one overlay files for all imx91/imx93 boards?
No, that's impossible, because they use GPIO backlight or PWM backlight,
different GPIOs to enable DPI panels and different GPIO hogs.
>
> Frank
>>
>>>
>>> Frank
>>>
>>>>> Frank
>>>>>>
>>>>>> [2] https://www.nxp.com/design/design-center/development-boards-and-designs/mx93aud-hat-audio-board:MX93AUD-HAT
>>>>>>
>>>>>>>
>>>>>>> Frank
>>>>>>>>
>>>>>>>> ---
>>>>>>>> base-commit: 816f193dd0d95246f208590924dd962b192def78
>>>>>>>> change-id: 20260407-tianma-tm050rdh03-imx93-9x9-qsb-6e4bbbde3d08
>>>>>>>>
>>>>>>>> Best regards,
>>>>>>>> --
>>>>>>>> Liu Ying <victor.liu@nxp.com>
>>>>>>>>
>>>>>>
>>>>>> --
>>>>>> Regards,
>>>>>> Liu Ying
>>>>
>>>> --
>>>> Regards,
>>>> Liu Ying
>>
>> --
>> Regards,
>> Liu Ying
--
Regards,
Liu Ying
^ permalink raw reply
* Re: [RFC V1 00/16] arm64/mm: Enable 128 bit page table entries
From: Anshuman Khandual @ 2026-04-09 2:08 UTC (permalink / raw)
To: David Hildenbrand (Arm), linux-arm-kernel
Cc: Catalin Marinas, Will Deacon, Ryan Roberts, Mark Rutland,
Lorenzo Stoakes, Andrew Morton, Mike Rapoport, Linu Cherian,
linux-kernel, linux-mm
In-Reply-To: <c664368c-fe2c-42d8-b488-e9e30b342491@kernel.org>
On 08/04/26 5:43 PM, David Hildenbrand (Arm) wrote:
> On 4/8/26 12:53, Anshuman Khandual wrote:
>> On 07/04/26 8:14 PM, David Hildenbrand (Arm) wrote:
>>> On 2/24/26 06:11, Anshuman Khandual wrote:
>>>> FEAT_D128 is a new arm architecture feature adding support for VMSAv9-128
>>>> translation system. FEAT_D128 is an optional feature from ARMV9.3 onwards.
>>>> So with this feature arm64 platforms could have two different translation
>>>> systems, VMSAv8-64 and VMSAv9-128 could selectively be enabled.
>>>>
>>>> FEAT_D128 adds 128 bit page table entries, thus supporting larger physical
>>>> and virtual address range while also expanding available room for more MMU
>>>> management feature bits both for HW and SW.
>>>>
>>>> This series has been split into two parts. Generic MM changes followed by
>>>> arm64 platform changes, finally enabling D128 with a new config ARM64_D128.
>>>>
>>>> READ_ONCE() on page table entries get routed via level specific pxdp_get()
>>>> helpers which platforms could then override when required. These accessors
>>>> on arm64 platform help in ensuring page table accesses are performed in an
>>>> atomic manner while reading 128 bit page table entries.
>>>>
>>>> All ARM64_VA_BITS and ARM64_PA_BITS combinations for all page sizes are now
>>>> supported both on D64 and D128 translation regimes. Although new 56 bits VA
>>>> space is not yet supported. Similarly FEAT_D128 skip level is not supported
>>>> currently.
>>>>
>>>> Basic page table geometry has been changed with D128 as there are now fewer
>>>> entries per level. Please refer to the following table for leaf entry sizes
>>>>
>>>> D64 D128
>>>> ------------------------------------------------
>>>> | PAGE_SIZE | PMD | PUD | PMD | PUD |
>>>> -----------------------------|-----------------|
>>>> | 4K | 2M | 1G | 1M | 256M |
>>>> | 16K | 32M | 64G | 16M | 16G |
>>>> | 64K | 512M | 4T | 256M | 1T |
>>>> ------------------------------------------------
>>>>
>>>
>>> Interesting. That means user space will have it even harder to optimize
>>> for THP sizes.
>>>
>>> What's the effect on cont-pte? Do they still span the same number of
>>> entries and there is effectively no change?
>>
>> The numbers are the same for 4K base page size but will need
>> some changes for 16K and 64K base page sizes. Something that
>> git missed in this series, will fix it.
>
> Oh, and it would be great to also clearly spell out the effect on
> hugetlb as well. I assume the available hugetlb sizes will change as well.
Sure will update the required information in the commit message as well as in
file arch/arm64/mm/hugetlb.c, where HugeTLB sizes support matrix is enlisted.
^ permalink raw reply
* RE: Status of thermal support for i.MX93
From: Jacky Bai @ 2026-04-09 1:59 UTC (permalink / raw)
To: Stefan Wahren, Alice Guo, Frank Li
Cc: Fabio Estevam, imx@lists.linux.dev, Linux ARM,
open list:GENERIC PM DOMAINS, Daniel Lezcano, Sascha Hauer
In-Reply-To: <1ad05dc4-9eaa-4fc2-a665-e17521fd333c@gmx.net>
Hi Stefan,
> Subject: Status of thermal support for i.MX93
>
> Hi,
>
> AFAIK the thermal support for i.MX93 hasn't been mainlined yet. The last
> version I can find is here [1].
>
> Are there any plans to finish this work?
>
I thought Frank answered the comments and no further action to do from my side, So it slipped
From my memory.
I just rechecked the comments history, it seems still have some comments need to be resolved.
I will handle them and send out a new version.
Thx for point this out.
BR
> Thanks
>
^ permalink raw reply
* Re: [PATCH v7 0/4] PCI: Add support for resetting the Root Ports in a platform specific way
From: Brian Norris @ 2026-04-09 1:58 UTC (permalink / raw)
To: Hongxing Zhu
Cc: manivannan.sadhasivam@oss.qualcomm.com, Bjorn Helgaas,
Mahesh J Salgaonkar, Oliver O'Halloran, Will Deacon,
Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Heiko Stuebner, Philipp Zabel,
linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org,
linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org,
linux-arm-msm@vger.kernel.org, linux-rockchip@lists.infradead.org,
Niklas Cassel, Wilfred Mallawa, Krishna Chaitanya Chundru,
Lukas Wunner, Wilson Ding, Miles Chen
In-Reply-To: <AS8PR04MB883389FD2A016F9E02756B048C49A@AS8PR04MB8833.eurprd04.prod.outlook.com>
Hi Richard and Mani,
For the record, I've been using a form of an earlier version of this
patchset in my environment for some time now, and I've run across
problems that *might* relate to what Richard is reporting, but I'm not
quite sure at the moment. Details below.
On Wed, Mar 25, 2026 at 07:06:49AM +0000, Hongxing Zhu wrote:
> Hi Mani:
> I've accidentally encountered a new issue based on the reset root port patch-set.
> After performing a few hot-reset operations, the PCIe link enters a continuous up/down cycling pattern.
>
> I found that calling pci_reset_secondary_bus() first in pcibios_reset_secondary_bus() appears to resolve this issue.
> Have you experienced a similar problem?
>
> "
> ...
> [ 141.897701] imx6q-pcie 4c300000.pcie: PCIe(LNK_STS:0x00000700) link up detected
> [ 142.086341] imx6q-pcie 4c300000.pcie: PCIe Gen.3 x1 link up
> [ 142.092038] imx6q-pcie 4c300000.pcie: PCIe(LNK_STS:0x00000c00) link down detected
> ...
> "
>
> Platform: i.MX95 EVK board plus local Root Ports reset supports based on the #1 and #2 patches of v7 patch-set.
> Notes of the logs:
> - One Gen3 NVME device is connected.
> - "./memtool 4c341058=0;./memtool 4c341058=1;" is used to toggle the LTSSM_EN bit to trigger the link down.
> - Toggle BIT6 of Bridge Control Register to trigger hot reset by "./memtool 4c30003c=004001ff; ./memtool 4c30003c=000001ff;"
> - The Root Port reset patches works correctly at first.
> However, after several hot-reset triggers, the link enters a repeated down/up cycling state.
>
> Logs:
> [ 3.553188] imx6q-pcie 4c300000.pcie: host bridge /soc/pcie@4c300000 ranges:
> [ 3.560308] imx6q-pcie 4c300000.pcie: IO 0x006ff00000..0x006fffffff -> 0x0000000000
> [ 3.568525] imx6q-pcie 4c300000.pcie: MEM 0x0910000000..0x091fffffff -> 0x0010000000
> [ 3.577314] imx6q-pcie 4c300000.pcie: config reg[1] 0x60100000 == cpu 0x60100000
> [ 3.796029] imx6q-pcie 4c300000.pcie: iATU: unroll T, 128 ob, 128 ib, align 4K, limit 1024G
> [ 4.003746] imx6q-pcie 4c300000.pcie: PCIe Gen.3 x1 link up
> [ 4.009553] imx6q-pcie 4c300000.pcie: PCI host bridge to bus 0000:00
> root@imx95evk:~#
> root@imx95evk:~#
> root@imx95evk:~# ./memtool 4c341058=0;./memtool 4c341058=1; Writing 32-bit value 0x0 to address 0x4C341058
> Writing 32-bit v
> [ 87.265348] imx6q-pcie 4c300000.pcie: PCIe(LNK_STS:0x00000d01) link down detected
> alue 0x1 to adder
> [ 87.273106] imx6q-pcie 4c300000.pcie: Stop root bus and handle link down
> ss 0x4C341058
> [ 87.281264] pcieport 0000:00:00.0: Recovering Root Port due to Link Down
> [ 87.289245] pci 0000:01:00.0: AER: can't recover (no error_detected callback)
> root@imx95evk:~# [ 87.514216] imx6q-pcie 4c300000.pcie: PCIe(LNK_STS:0x00000700) link up detected
> [ 87.702968] imx6q-pcie 4c300000.pcie: PCIe Gen.3 x1 link up
> [ 87.834983] pcieport 0000:00:00.0: Root Port has been reset
> [ 87.840714] pcieport 0000:00:00.0: AER: device recovery failed
> [ 87.846592] imx6q-pcie 4c300000.pcie: Rescan bus after link up is detected
> [ 87.855947] pcieport 0000:00:00.0: bridge configuration invalid ([bus 00-00]), reconfiguring
I've seen this same line ("bridge configuration invalid") before, and I
believe that's because the saved state (pci_save_state(); more about
this below) is invalid -- it contains 0 values in places where they
should be non-zero. So when those values are restored
(pci_restore_state()), we get confused.
I believe we've pinned down one reason this invalid state occurs -- it's
because of an automatic (mis)feature in the DesignWare PCIe hardware.
Specifically, it's because of what the controller does during a surprise
link-down error.
From the Designware docs:
"[...] during normal operation, the link might fail and go down. After
this link-down event, the controller requests the DWC_pcie_clkrst.v
module to hot-reset the controller. There is no difference in the
handling of a link-down reset or a hot reset; the controller asserts
the link_req_rst_not output requesting the DWC_pcie_clkrst.v module to
reset the controller."
In some of the adjacent documentation (and confirmed in local testing),
it suggests that this automatic reset will also reset various DBI (i.e.,
PCIe config space) registers. It also seems as if there's not really a
good way to completely stop this automatic reset -- the docs mention
some SW methods prevent the reset, but they all seem racy or incomplete.
Anyway, I think this implies that patch 1 is somewhat wrong [1]. It
includes some code like this:
pci_save_state(dev);
ret = host->reset_root_port(host, dev);
if (ret)
pci_err(dev, "Failed to reset Root Port: %d\n", ret);
else
/* Now restore it on success */
pci_restore_state(dev);
That first line (pci_save_state()) is prone to saving invalid state,
depending on whether the link-down event has finished flushing and
resetting the controller yet or not. The resulting impact is a bit hard
to judge, depending on what (mis)configuration you end up with.
I also noticed commit a2f1e22390ac ("PCI/ERR: Ensure error
recoverability at all times") was merged recently. With that change, I
believe it is now safe to perform pci_restore_state() even without
pci_save_state() here.
So ... can we remove pci_save_state() from
pcibios_reset_secondary_bus()? Might that help? It sounds like my above
observations *may* match Richard's reports, but I'm not sure. And
anyway, the documented hardware behavior is racy, so it's hard to
propose a foolproof solution.
Brian
[1] At least, for DesignWare controllers.
> [ 87.864423] pci_bus 0000:01: busn_res: [bus 01-ff] end is updated to 01
>
> root@imx95evk:~#
> root@imx95evk:~# cat /proc/interrupts | grep lnk;
> 273: 2 0 0 0 0 0 GICv3 342 Level PCIe PME, lnk_notify
> root@imx95evk:~#
> root@imx95evk:~#
> root@imx95evk:~# ./memtool 4c30003c=004001ff; ./memtool 4c30003c=000001ff; Writing 32-bit va
> [ 107.028086] imx6q-pcie 4c300000.pcie: PCIe(LNK_STS:0x00000d00) link down detected lue 0x4001FF to a
> [ 107.037018] imx6q-pcie 4c300000.pcie: Stop root bus and handle link down ddress 0x4C30003C
> [ 107.045137] pcieport 0000:00:00.0: Recovering Root Port due to Link Down
>
> Writing 32-bit
> [ 107.053332] pci 0000:01:00.0: AER: can't recover (no error_detected callback) value 0x1FF to address 0x4C30003C root@imx95evk:~#
> [ 107.282146] imx6q-pcie 4c300000.pcie: PCIe(LNK_STS:0x00000700) link up detected
> [ 107.470801] imx6q-pcie 4c300000.pcie: PCIe Gen.3 x1 link up
> [ 107.602823] pcieport 0000:00:00.0: Root Port has been reset
> [ 107.608601] pcieport 0000:00:00.0: AER: device recovery failed
> [ 107.614497] imx6q-pcie 4c300000.pcie: Rescan bus after link up is detected
> [ 107.623805] pcieport 0000:00:00.0: bridge configuration invalid ([bus 00-00]), reconfiguring
> [ 107.632281] pci_bus 0000:01: busn_res: [bus 01] end is updated to 01
>
> root@imx95evk:~#
> root@imx95evk:~# cat /proc/interrupts | grep lnk;
> 273: 4 0 0 0 0 0 GICv3 342 Level PCIe PME, lnk_notify
> root@imx95evk:~#
> root@imx95evk:~# ./memtool 4c30003c=004001ff; ./memtool 4c30003c=000001ff; Writing 32-bit va
> [ 133.424041] imx6q-pcie 4c300000.pcie: PCIe(LNK_STS:0x00000d00) link down detected lue 0x4001FF to a
> [ 133.432954] imx6q-pcie 4c300000.pcie: Stop root bus and handle link down ddress 0x4C30003C
> [ 133.441106] pcieport 0000:00:00.0: Recovering Root Port due to Link Down
>
> Writing 32-bit
> [ 133.449309] pci 0000:01:00.0: AER: can't recover (no error_detected callback) value 0x1FF to address 0x4C30003C root@imx95evk:~#
> [ 133.677824] imx6q-pcie 4c300000.pcie: PCIe(LNK_STS:0x00000700) link up detected
> [ 133.870414] imx6q-pcie 4c300000.pcie: PCIe Gen.3 x1 link up
> [ 134.002534] pcieport 0000:00:00.0: Root Port has been reset
> [ 134.008307] pcieport 0000:00:00.0: AER: device recovery failed
> [ 134.014193] imx6q-pcie 4c300000.pcie: Rescan bus after link up is detected
> [ 134.023418] pcieport 0000:00:00.0: bridge configuration invalid ([bus 00-00]), reconfiguring
> [ 134.031881] pci_bus 0000:01: busn_res: [bus 01] end is updated to 01
>
> root@imx95evk:~# ./memtool 4c30003c=004001ff; ./memtool 4c30003c=000001ff; Writing 32-bit va
> [ 140.149713] imx6q-pcie 4c300000.pcie: PCIe(LNK_STS:0x00000d00) link down detected lue 0x4001FF to a
> [ 140.158614] imx6q-pcie 4c300000.pcie: Stop root bus and handle link down ddress 0x4C30003C
> [ 140.166779] pcieport 0000:00:00.0: Recovering Root Port due to Link Down
> [ 140.174981] pci 0000:01:00.0: AER: can't recover (no error_detected callback) Writing 32-bit value 0x1FF to address 0x4C30003C root@imx95evk:~#
> [ 140.401605] imx6q-pcie 4c300000.pcie: PCIe(LNK_STS:0x00000700) link up detected
> [ 140.590491] imx6q-pcie 4c300000.pcie: PCIe Gen.3 x1 link up
> [ 140.596206] imx6q-pcie 4c300000.pcie: PCIe(LNK_STS:0x00000c00) link down detected
>
> root@imx95evk:~#
> [ 141.630311] pcieport 0000:00:00.0: Data Link Layer Link Active not set in 100 msec
> [ 141.637950] pcieport 0000:00:00.0: Failed to reset Root Port: -25
> [ 141.644095] pcieport 0000:00:00.0: AER: subordinate device reset failed
> [ 141.650883] pcieport 0000:00:00.0: AER: device recovery failed
> [ 141.656784] imx6q-pcie 4c300000.pcie: Stop root bus and handle link down
> [ 141.663520] pcieport 0000:00:00.0: Recovering Root Port due to Link Down
> [ 141.670271] pci 0000:01:00.0: AER: can't recover (no error_detected callback)
> [ 141.897701] imx6q-pcie 4c300000.pcie: PCIe(LNK_STS:0x00000700) link up detected
> [ 142.086341] imx6q-pcie 4c300000.pcie: PCIe Gen.3 x1 link up
> [ 142.092038] imx6q-pcie 4c300000.pcie: PCIe(LNK_STS:0x00000c00) link down detected
> [ 143.126273] pcieport 0000:00:00.0: Data Link Layer Link Active not set in 100 msec
> [ 143.133919] pcieport 0000:00:00.0: Failed to reset Root Port: -25
> [ 143.140052] pcieport 0000:00:00.0: AER: subordinate device reset failed
> [ 143.146747] pcieport 0000:00:00.0: AER: device recovery failed
> [ 143.152604] imx6q-pcie 4c300000.pcie: Stop root bus and handle link down
> [ 143.159314] pcieport 0000:00:00.0: Recovering Root Port due to Link Down
> [ 143.166022] pci 0000:01:00.0: AER: can't recover (no error_detected callback)
> [ 143.389723] imx6q-pcie 4c300000.pcie: PCIe(LNK_STS:0x00000700) link up detected
> [ 143.582294] imx6q-pcie 4c300000.pcie: PCIe Gen.3 x1 link up
> [ 143.587996] imx6q-pcie 4c300000.pcie: PCIe(LNK_STS:0x00000c00) link down detected
>
>
> Thanks.
> Best Regards
> Richard Zhu
^ permalink raw reply
* Re: [PATCH] iommu/arm-smmu-qcom: Fix fastrpc compatible string in ACTLR client match table
From: Dmitry Baryshkov @ 2026-04-09 1:48 UTC (permalink / raw)
To: bibek.patro
Cc: Rob Clark, Will Deacon, Robin Murphy, Joerg Roedel,
Dmitry Baryshkov, iommu, linux-arm-msm, linux-arm-kernel,
linux-kernel, srinivas.kandagatla
In-Reply-To: <20260408130825.3268733-1-bibek.patro@oss.qualcomm.com>
On Wed, Apr 08, 2026 at 06:38:25PM +0530, bibek.patro@oss.qualcomm.com wrote:
> From: Bibek Kumar Patro <bibek.patro@oss.qualcomm.com>
>
> The qcom_smmu_actlr_client_of_match table contained "qcom,fastrpc" as
> the compatible string for applying ACTLR prefetch settings to FastRPC
> devices. However, "qcom,fastrpc" is the compatible string for the parent
> rpmsg channel node, which is not an IOMMU client — it carries no
> "iommus" property in the device tree and is never attached to an SMMU
> context bank.
>
> The actual IOMMU clients are the compute context bank (CB) child nodes,
> which use the compatible string "qcom,fastrpc-compute-cb". These nodes
> carry the "iommus" property and are probed by fastrpc_cb_driver via
> fastrpc_cb_probe(), which sets up the DMA mask and IOMMU mappings for
> each FastRPC session. The device tree structure is:
>
> fastrpc {
> compatible = "qcom,fastrpc"; /* rpmsg channel, no iommus */
> ...
> compute-cb@3 {
> compatible = "qcom,fastrpc-compute-cb";
> iommus = <&apps_smmu 0x1823 0x0>; /* actual IOMMU client */
> };
> };
>
> Since qcom_smmu_set_actlr_dev() calls of_match_device() against the
> device being attached to the SMMU context bank, the "qcom,fastrpc"
> entry was never matching any device. As a result, the ACTLR prefetch
> settings (PREFETCH_DEEP | CPRE | CMTLB) were silently never applied
> for FastRPC compute context banks.
>
> Fix this by replacing "qcom,fastrpc" with "qcom,fastrpc-compute-cb"
> in the match table so that the ACTLR settings are correctly applied
> to the compute CB devices that are the true IOMMU clients.
>
> Assisted-by: Anthropic:claude-4-6-sonnet
> Fixes: 3e35c3e725de ("iommu/arm-smmu: Add ACTLR data and support for qcom_smmu_500")
> Signed-off-by: Bibek Kumar Patro <bibek.patro@oss.qualcomm.com>
> ---
>
> While there is an ongoing discussion [1] on how to differentiate ACTLR
> prefetch settings between compute DSP and audio DSP fastrpc devices, it
> is necessary to first fix the compatible string to "qcom,fastrpc-compute-cb".
> Both compute DSP and audio DSP fastrpc nodes use this compatible string,
> so both will receive the ACTLR settings after this fix. However, for
> audio DSP devices the effect remains the same as the current
> state since they do not actively use prefetch — the write is effectively
> a NOP for them. The fix is meaningful for compute DSP devices, which
> actively use prefetch and were previously being silently skipped.
>
> [1]: https://lore.kernel.org/all/9b4c895a-c822-40e6-bb92-8fdcd09c82d3@oss.qualcomm.com/
>
> drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH v2 2/3] remoteproc: imx_rproc: Pass bootaddr to SM CPU/LMM reset vector
From: Peng Fan @ 2026-04-09 0:30 UTC (permalink / raw)
To: Mathieu Poirier
Cc: Peng Fan, Bjorn Andersson, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Daniel Baluta, linux-remoteproc@vger.kernel.org,
devicetree@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
In-Reply-To: <adZ4WIaC6WN97JhR@p14s>
On Wed, Apr 08, 2026 at 09:46:32AM -0600, Mathieu Poirier wrote:
>On Wed, Apr 08, 2026 at 01:30:16AM +0000, Peng Fan wrote:
>> > Subject: Re: [PATCH v2 2/3] remoteproc: imx_rproc: Pass bootaddr to
>> > SM CPU/LMM reset vector
>> >
>> [...]
>> >
>> > >
>> > > Aligning the ELF entry point with the hardware reset base on
>> > Cortex‑M
>> > > systems is possible, but it comes with several risks.
>> >
>> > I'm not asking to align the ELF entry point with the hardware reset base.
>> > All I want is to have the correct start address embedded in the ELF file
>> > to avoid having to use a mask.
>>
>> I see, per my understanding:
>> FreeRTOS typically exposes __isr_vector, which corresponds to the hardware
>> reset / vector table base.
>> Zephyr (Cortex‑M) exposes _vector_table, which serves the same purpose.
>> I am not certain about other RTOSes, but the pattern seems consistent:
>> the vector table base is already available as a named ELF symbol.
>>
>> Given that, if the preferred approach is to parse the ELF and explicitly
>> retrieve the hardware reset base, I can update the implementation accordingly.
>> If you prefer to parse the elf file to get the hardware reset base,
>> I could update to use them.
>>
>> Options1: Something as below:
>> 1. Include rproc_elf_find_symbol in remoteproc_elf_loader.c
>> 2. Use below in imx_rproc.c
>> ret = rproc_elf_find_symbol(rproc, fw, "__isr_vector", &vector_base);
>> if (ret)
>> ret = rproc_elf_find_symbol(rproc, fw, "__vector_table", &vector_base);
>>
>> if (!ret)
>> rproc->bootaddr = vector_base
>> else
>> dev_info(dev, "no __isr_vector or __vector_table\n")
>
>No
If your concern is about rproc->bootaddr, I could introduce
imx_rproc->vector_base for i.MX. Please help detail a bit.
>
>>
>> This makes the hardware reset base explicit, avoids masking e_entry.
>>
>> Option 2: User‑provided reset symbol via sysfs
>> As an alternative, we could expose a sysfs attribute,
>> e.g. reset_symbol, allowing users to specify the symbol name
>> to be used as the reset base:
>>
>> echo __isr_vector > /sys/class/remoteproc/remoteprocX/reset_symbol
>>
>
>Definitely not.
>
>The definition of e_entry in the specification is clear, i.e "the address of the
>entry point from where the process starts executing". If masking is required
>because the tool that puts the image together gets the wrong address, then it
>should be fixed.
The hardware reset base is the address from which the hardware fetches the
initial stack pointer and program counter values and loads them into the SP
and PC registers. In contrast, bootaddr (i.e. e_entry) represents the address
at which the CPU starts executing code (the PC value after reset). As you
pointed out earlier, this distinction is clear.
In our case, we need to obtain the hardware reset base and pass that value to
the system firmware. However, e_entry should not be set to the hardware reset
base. Doing so would introduce the issues I described in [1]. This means we
should not modify the Zephyr or FreeRTOS build outputs to make e_entry equal
to the hardware reset base.
Given these constraints, the feasible solutions I can see are either:
- option 1 (explicitly retrieving the hardware reset base), or
- continuing to use masking.
Please suggest.
[1] https://lore.kernel.org/all/acs2PAZq2k3zjmDW@shlinux89/
Thanks,
Peng
>
>> The remoteproc core would then resolve that symbol from
>> the ELF and set rproc->bootaddr accordingly.
>> This provides maximum flexibility but does introduce a new user‑visible ABI,
>> so I see it more as an opt‑in or fallback mechanism.
>>
>> Please let me know which approach you prefer, and I will update
>> this series accordingly in v3..
>>
>> Thanks,
>> Peng.
>>
>>
>> >
>> > > 1, Semantic mismatch (ELF vs. hardware behavior) 2, Debuggers may
>> > > attempt to set breakpoints or start execution at the entry symbol
>> > >
^ permalink raw reply
* ✅ PASS: Test report for for-kernelci (7.0.0-rc7, upstream-arm-next, af497322)
From: cki-project @ 2026-04-09 0:03 UTC (permalink / raw)
To: linux-arm-kernel, catalin.marinas, will
Hi, we tested your kernel and here are the results:
Overall result: PASSED
Merge: OK
Compile: OK
Test: OK
Tested-by: CKI Project <cki-project@redhat.com>
Kernel information:
Commit message: Merge remote-tracking branch 'origin/nocache-cleanup' into for-kernelci
You can find all the details about the test run at
https://datawarehouse.cki-project.org/kcidb/checkouts/redhat:2438429461
If you find a failure unrelated to your changes, please ask the test maintainer to review it.
This will prevent the failures from being incorrectly reported in the future.
Please reply to this email if you have any questions about the tests that we
ran or if you have any suggestions on how to make future tests more effective.
,-. ,-.
( C ) ( K ) Continuous
`-',-.`-' Kernel
( I ) Integration
`-'
______________________________________________________________________________
^ permalink raw reply
* Re: [PATCH v4 11/11] arm64: dts: qcom: sdm845-google: Add STM FTS touchscreen support
From: Dmitry Baryshkov @ 2026-04-08 23:56 UTC (permalink / raw)
To: david
Cc: Dmitry Torokhov, Maxime Coquelin, Alexandre Torgue, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Henrik Rydberg,
Bjorn Andersson, Konrad Dybcio, Petr Hodina, linux-input,
linux-stm32, linux-arm-kernel, linux-kernel, Krzysztof Kozlowski,
devicetree, linux-arm-msm, phone-devel, Konrad Dybcio
In-Reply-To: <20260409-stmfts5-v4-11-64fe62027db5@ixit.cz>
On Thu, Apr 09, 2026 at 12:15:54AM +0200, David Heidelberg via B4 Relay wrote:
> 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(-)
>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
--
With best wishes
Dmitry
^ permalink raw reply
* [PATCH net] net: ethernet: mtk_eth_soc: initialize PPE per-tag-layer MTU registers
From: Daniel Golle @ 2026-04-08 23:33 UTC (permalink / raw)
To: Felix Fietkau, Lorenzo Bianconi, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger,
AngeloGioacchino Del Regno, Pablo Neira Ayuso, netdev,
linux-kernel, linux-arm-kernel, linux-mediatek
Cc: Chad Monroe, Elad Yifee, João Duarte, John Crispin
The PPE enforces output frame size limits via per-tag-layer VLAN_MTU
registers that the driver never initializes. The hardware defaults do
not account for PPPoE overhead, causing the PPE to punt encapsulated
frames back to the CPU instead of forwarding them.
Initialize the registers at PPE start and on MTU changes using the
maximum GMAC MTU. This is a conservative approximation -- the actual
per-PPE requirement depends on egress path, but using the global
maximum ensures the limits are never too small.
Fixes: ba37b7caf1ed2 ("net: ethernet: mtk_eth_soc: add support for initializing the PPE")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/ethernet/mediatek/mtk_eth_soc.c | 22 ++++++++++++++-
drivers/net/ethernet/mediatek/mtk_ppe.c | 30 +++++++++++++++++++++
drivers/net/ethernet/mediatek/mtk_ppe.h | 1 +
3 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 1767463475de4..06880fa86f0ea 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -3922,12 +3922,23 @@ static int mtk_device_event(struct notifier_block *n, unsigned long event, void
return NOTIFY_DONE;
}
+static int mtk_max_gmac_mtu(struct mtk_eth *eth)
+{
+ int i, max_mtu = ETH_DATA_LEN;
+
+ for (i = 0; i < ARRAY_SIZE(eth->netdev); i++)
+ if (eth->netdev[i] && eth->netdev[i]->mtu > max_mtu)
+ max_mtu = eth->netdev[i]->mtu;
+
+ return max_mtu;
+}
+
static int mtk_open(struct net_device *dev)
{
struct mtk_mac *mac = netdev_priv(dev);
struct mtk_eth *eth = mac->hw;
struct mtk_mac *target_mac;
- int i, err, ppe_num;
+ int i, err, ppe_num, mtu;
ppe_num = eth->soc->ppe_num;
@@ -3974,6 +3985,10 @@ static int mtk_open(struct net_device *dev)
mtk_gdm_config(eth, target_mac->id, gdm_config);
}
+ mtu = mtk_max_gmac_mtu(eth);
+ for (i = 0; i < ARRAY_SIZE(eth->ppe); i++)
+ mtk_ppe_update_mtu(eth->ppe[i], mtu);
+
napi_enable(ð->tx_napi);
napi_enable(ð->rx_napi[0].napi);
mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
@@ -4788,6 +4803,7 @@ static int mtk_change_mtu(struct net_device *dev, int new_mtu)
int length = new_mtu + MTK_RX_ETH_HLEN;
struct mtk_mac *mac = netdev_priv(dev);
struct mtk_eth *eth = mac->hw;
+ int max_mtu, i;
if (rcu_access_pointer(eth->prog) &&
length > MTK_PP_MAX_BUF_SIZE) {
@@ -4798,6 +4814,10 @@ static int mtk_change_mtu(struct net_device *dev, int new_mtu)
mtk_set_mcr_max_rx(mac, length);
WRITE_ONCE(dev->mtu, new_mtu);
+ max_mtu = mtk_max_gmac_mtu(eth);
+ for (i = 0; i < ARRAY_SIZE(eth->ppe); i++)
+ mtk_ppe_update_mtu(eth->ppe[i], max_mtu);
+
return 0;
}
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
index 79c11e179d894..9e829a2e4354e 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
@@ -973,6 +973,36 @@ static void mtk_ppe_init_foe_table(struct mtk_ppe *ppe)
}
}
+void mtk_ppe_update_mtu(struct mtk_ppe *ppe, int mtu)
+{
+ int base;
+ u32 val;
+
+ if (!ppe)
+ return;
+
+ /* The PPE checks output frame size against per-tag-layer MTU limits,
+ * treating PPPoE and DSA tags just like 802.1Q VLAN tags. The Linux
+ * device MTU already accounts for PPPoE (PPPOE_SES_HLEN) and DSA tag
+ * overhead, but 802.1Q VLAN tags are handled transparently without
+ * being reflected by the lower device MTU being increased by 4.
+ * Use the maximum MTU across all GMAC interfaces so that PPE output
+ * frame limits are sufficiently high regardless of which port a flow
+ * egresses through.
+ */
+ base = ETH_HLEN + mtu;
+
+ val = FIELD_PREP(MTK_PPE_VLAN_MTU0_NONE, base) |
+ FIELD_PREP(MTK_PPE_VLAN_MTU0_1TAG, base + VLAN_HLEN);
+ ppe_w32(ppe, MTK_PPE_VLAN_MTU0, val);
+
+ val = FIELD_PREP(MTK_PPE_VLAN_MTU1_2TAG,
+ base + 2 * VLAN_HLEN) |
+ FIELD_PREP(MTK_PPE_VLAN_MTU1_3TAG,
+ base + 3 * VLAN_HLEN);
+ ppe_w32(ppe, MTK_PPE_VLAN_MTU1, val);
+}
+
void mtk_ppe_start(struct mtk_ppe *ppe)
{
u32 val;
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.h b/drivers/net/ethernet/mediatek/mtk_ppe.h
index 223f709e2704f..ba85e39a155bf 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe.h
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
@@ -346,6 +346,7 @@ struct mtk_ppe {
struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index);
void mtk_ppe_deinit(struct mtk_eth *eth);
+void mtk_ppe_update_mtu(struct mtk_ppe *ppe, int mtu);
void mtk_ppe_start(struct mtk_ppe *ppe);
int mtk_ppe_stop(struct mtk_ppe *ppe);
int mtk_ppe_prepare_reset(struct mtk_ppe *ppe);
--
2.53.0
^ permalink raw reply related
* [PATCH] nvmem: rockchip-otp: alloc clks with main struct
From: Rosen Penev @ 2026-04-08 23:01 UTC (permalink / raw)
To: linux-rockchip
Cc: Srinivas Kandagatla, Heiko Stuebner,
moderated list:ARM/Rockchip SoC support, open list
Use a flexible array member to simplify allocation slightly. No need for
a separate calloc.
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
drivers/nvmem/rockchip-otp.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c
index 0ec78b5e19e7..2c0feb036f3f 100644
--- a/drivers/nvmem/rockchip-otp.c
+++ b/drivers/nvmem/rockchip-otp.c
@@ -78,9 +78,9 @@ struct rockchip_data {
struct rockchip_otp {
struct device *dev;
void __iomem *base;
- struct clk_bulk_data *clks;
struct reset_control *rst;
const struct rockchip_data *data;
+ struct clk_bulk_data clks[];
};
static int rockchip_otp_reset(struct rockchip_otp *otp)
@@ -424,7 +424,7 @@ static int rockchip_otp_probe(struct platform_device *pdev)
if (!data)
return dev_err_probe(dev, -EINVAL, "failed to get match data\n");
- otp = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_otp),
+ otp = devm_kzalloc(&pdev->dev, struct_size(otp, clks, data->num_clks),
GFP_KERNEL);
if (!otp)
return -ENOMEM;
@@ -436,11 +436,6 @@ static int rockchip_otp_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(otp->base),
"failed to ioremap resource\n");
- otp->clks = devm_kcalloc(dev, data->num_clks, sizeof(*otp->clks),
- GFP_KERNEL);
- if (!otp->clks)
- return -ENOMEM;
-
for (i = 0; i < data->num_clks; ++i)
otp->clks[i].id = data->clks[i];
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v5 3/4] clk: keystone: sci-clk: add restore_context() operation
From: Brian Masney @ 2026-04-08 22:30 UTC (permalink / raw)
To: Thomas Richard (TI)
Cc: Nishanth Menon, Tero Kristo, Santosh Shilimkar, Michael Turquette,
Stephen Boyd, Gregory CLEMENT, richard.genoud, Udit Kumar,
Prasanth Mantena, Abhash Kumar, Thomas Petazzoni,
linux-arm-kernel, linux-kernel, linux-clk, Dhruva Gole
In-Reply-To: <20260407-ti-sci-jacinto-s2r-restore-irq-v5-3-97b28f2d93f9@bootlin.com>
Hi Thomas,
On Tue, Apr 07, 2026 at 04:25:08PM +0200, Thomas Richard (TI) wrote:
> Implement the restore_context() operation to restore the clock rate and the
> clock parent state. The clock rate is saved in sci_clk struct during
> set_rate() operation. The parent index is saved in sci_clk struct during
> set_parent() operation. During clock registration, the core retrieves each
> clock’s parent using get_parent() operation to ensure the internal clock
> tree reflects the actual hardware state, including any configurations made
> by the bootloader. So we also save the parent index in get_parent().
>
> Reviewed-by: Dhruva Gole <d-gole@ti.com>
> Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com>
> ---
> drivers/clk/keystone/sci-clk.c | 42 ++++++++++++++++++++++++++++++++++--------
> 1 file changed, 34 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/clk/keystone/sci-clk.c b/drivers/clk/keystone/sci-clk.c
> index 9d5071223f4c..428050a05de3 100644
> --- a/drivers/clk/keystone/sci-clk.c
> +++ b/drivers/clk/keystone/sci-clk.c
> @@ -47,6 +47,8 @@ struct sci_clk_provider {
> * @node: Link for handling clocks probed via DT
> * @cached_req: Cached requested freq for determine rate calls
> * @cached_res: Cached result freq for determine rate calls
> + * @parent_id: Parent index for this clock
> + * @rate: Clock rate
> */
> struct sci_clk {
> struct clk_hw hw;
> @@ -58,6 +60,8 @@ struct sci_clk {
> struct list_head node;
> unsigned long cached_req;
> unsigned long cached_res;
> + u8 parent_id;
> + unsigned long rate;
> };
>
> #define to_sci_clk(_hw) container_of(_hw, struct sci_clk, hw)
> @@ -210,10 +214,16 @@ static int sci_clk_set_rate(struct clk_hw *hw, unsigned long rate,
> unsigned long parent_rate)
> {
> struct sci_clk *clk = to_sci_clk(hw);
> + int ret;
> +
> + ret = clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id,
> + clk->clk_id, rate / 10 * 9, rate,
> + rate / 10 * 11);
>
> - return clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id,
> - clk->clk_id, rate / 10 * 9, rate,
> - rate / 10 * 11);
> + if (!ret)
> + clk->rate = rate;
> +
> + return ret;
> }
Should the computed rate from sci_clk_recalc_rate() be saved as well?
>
> /**
> @@ -237,9 +247,9 @@ static u8 sci_clk_get_parent(struct clk_hw *hw)
> return 0;
> }
>
> - parent_id = parent_id - clk->clk_id - 1;
> + clk->parent_id = (u8)(parent_id - clk->clk_id - 1);
>
> - return (u8)parent_id;
> + return clk->parent_id;
> }
>
> /**
> @@ -252,12 +262,27 @@ static u8 sci_clk_get_parent(struct clk_hw *hw)
> static int sci_clk_set_parent(struct clk_hw *hw, u8 index)
> {
> struct sci_clk *clk = to_sci_clk(hw);
> + int ret;
>
> clk->cached_req = 0;
>
> - return clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id,
> - clk->clk_id,
> - index + 1 + clk->clk_id);
> + ret = clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id,
> + clk->clk_id,
> + index + 1 + clk->clk_id);
> + if (!ret)
> + clk->parent_id = index;
> +
> + return ret;
> +}
> +
> +static void sci_clk_restore_context(struct clk_hw *hw)
> +{
> + struct sci_clk *clk = to_sci_clk(hw);
> +
> + sci_clk_set_parent(hw, clk->parent_id);
Are all of these clocks muxes?
Brian
> +
> + if (clk->rate)
> + sci_clk_set_rate(hw, clk->rate, 0);
> }
>
> static const struct clk_ops sci_clk_ops = {
> @@ -269,6 +294,7 @@ static const struct clk_ops sci_clk_ops = {
> .set_rate = sci_clk_set_rate,
> .get_parent = sci_clk_get_parent,
> .set_parent = sci_clk_set_parent,
> + .restore_context = sci_clk_restore_context,
> };
>
> /**
>
> --
> 2.53.0
>
^ permalink raw reply
* [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
* [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 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 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 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 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 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 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 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 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 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
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