Devicetree
 help / color / mirror / Atom feed
* [PATCH 2/4] drm/bridge: lontium-lt9611c: Increase MCU poll timeout to 200ms
From: Mohit Dsor @ 2026-06-10 21:14 UTC (permalink / raw)
  To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
	Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Vinod Koul
  Cc: dri-devel, devicetree, linux-kernel, Mohit Dsor, boss,
	qc-display-maintainer
In-Reply-To: <20260611-lt9611-b4-send-v1-0-42abbcd3bb1e@oss.qualcomm.com>

The on-chip MCU may take longer than 100ms to respond on some hardware
variants or slower I2C buses, causing spurious -ETIMEDOUT errors during
normal operation. Double the poll timeout from 100ms to 200ms to improve
reliability without changing the poll interval.

Signed-off-by: Mohit Dsor <mohit.dsor@oss.qualcomm.com>
---
 drivers/gpu/drm/bridge/lontium-lt9611c.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/bridge/lontium-lt9611c.c b/drivers/gpu/drm/bridge/lontium-lt9611c.c
index cb584855fd8f..b0402726367e 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611c.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611c.c
@@ -97,7 +97,7 @@ static int lt9611c_read_write_flow(struct lt9611c *lt9611c, u8 *params,
 	regmap_write(lt9611c->regmap, 0xe0de, 0x01);
 
 	ret = regmap_read_poll_timeout(lt9611c->regmap, 0xe0ae, temp,
-				       temp == 0x01, 1000, 100 * 1000);
+				       temp == 0x01, 1000, 200 * 1000);
 	if (ret)
 		return -ETIMEDOUT;
 
@@ -107,7 +107,7 @@ static int lt9611c_read_write_flow(struct lt9611c *lt9611c, u8 *params,
 	regmap_write(lt9611c->regmap, 0xe0de, 0x02);
 
 	ret = regmap_read_poll_timeout(lt9611c->regmap, 0xe0ae, temp,
-				       temp == 0x02, 1000, 100 * 1000);
+				       temp == 0x02, 1000, 200 * 1000);
 	if (ret)
 		return -ETIMEDOUT;
 

-- 
2.34.1


^ permalink raw reply related

* [PATCH 1/4] dt-bindings: brige: lt9611c: add port-select property for LT9611C
From: Mohit Dsor @ 2026-06-10 21:14 UTC (permalink / raw)
  To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
	Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Vinod Koul
  Cc: dri-devel, devicetree, linux-kernel, Mohit Dsor, boss,
	qc-display-maintainer
In-Reply-To: <20260611-lt9611-b4-send-v1-0-42abbcd3bb1e@oss.qualcomm.com>

Add a new optional `lontium,port-select` property to describe the DSI
input port configuration for the LT9611C variant, which supports
single-port (A or B) and dual-port (A+B) operation.

This property allows explicitly selecting the active DSI input port(s):
  0 = port A (default)
  1 = port B
  2 = ports A and B (dual-port)

Signed-off-by: Mohit Dsor <mohit.dsor@oss.qualcomm.com>
---
 .../devicetree/bindings/display/bridge/lontium,lt9611.yaml  | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml b/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml
index e0821a63d9d7..77220f893bf8 100644
--- a/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/lontium,lt9611.yaml
@@ -41,6 +41,17 @@ properties:
   vcc-supply:
     description: Regulator for 3.3V IO power.
 
+  lontium,port-select:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1, 2]
+    default: 0
+    description: |
+      Selects which DSI input port(s) the bridge uses. Only relevant for
+      the lontium,lt9611c compatible.
+        0 = PORT_SELECT_A  - single DSI port A (default)
+        1 = PORT_SELECT_B  - single DSI port B
+        2 = PORT_SELECT_AB - dual DSI ports A and B
+
   ports:
     $ref: /schemas/graph.yaml#/properties/ports
 
@@ -104,6 +115,8 @@ examples:
         vdd-supply = <&lt9611_1v8>;
         vcc-supply = <&lt9611_3v3>;
 
+        lontium,port-select = <1>;
+
         ports {
           #address-cells = <1>;
           #size-cells = <0>;

-- 
2.34.1


^ permalink raw reply related

* [PATCH 0/4] (no cover subject)
From: Mohit Dsor @ 2026-06-10 21:14 UTC (permalink / raw)
  To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
	Jonas Karlman, Jernej Skrabec, Luca Ceresoli, David Airlie,
	Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Vinod Koul
  Cc: dri-devel, devicetree, linux-kernel, Mohit Dsor, boss,
	qc-display-maintainer

From: Mohit Dsor <mohit.dsor@oss.qualcomm.com>
Subject: [PATCH 0/4] LT9611C improvements and fixes updates

Hi,

This series contains improvements and fixes for the Lontium LT9611C
MIPI DSI to HDMI bridge driver, along with DT binding updates.

The key addition is support for selecting the DSI input port using
a new device tree property, which is required for configurations
using port B or dual-port (A+B) operation.

Summary of changes:
- Add DSI port selection support via DT property
- Fixes and improvements
- Increase MCU polling timeout for stability

- Add dt-binding for port configuration

Patches:

1. dt-bindings: bridge: lt9611c: add port-select property for LT9611C
2. drm/bridge: lontium-lt9611c: Increase MCU poll timeout to 200ms
3. drm-bridge: lontium lt9611c: fixes and improvements
4. drm/bridge: lontium-lt9611c: Add DSI port selection via DT property

This has been tested on LT9611C-based platforms.
Please review.

Thanks,
Mohit

Signed-off-by: Mohit Dsor <mohit.dsor@oss.qualcomm.com>
---
Mohit Dsor (4):
      dt-bindings: brige: lt9611c: add port-select property for LT9611C
      drm/bridge: lontium-lt9611c: Increase MCU poll timeout to 200ms
      drm-bridge: lontium lt9611c: fixes and improvements
      drm/bridge: lontium-lt9611c: Add DSI port selection via DT property

 .../bindings/display/bridge/lontium,lt9611.yaml    | 13 ++++
 drivers/gpu/drm/bridge/lontium-lt9611c.c           | 79 ++++++++++++++++++++--
 2 files changed, 85 insertions(+), 7 deletions(-)
---
base-commit: 7b61c580d964f499f3eaf96d6579a7127dda606b
change-id: 20260611-lt9611-b4-send-6f1d39c2d6d7
prerequisite-message-id: <20260420061644.1251070-1-syyang@lontium.com>
prerequisite-patch-id: 5e0ea8907c87174a28fac5456fc51183d8e8b36f
prerequisite-patch-id: 6fd8685174c2c83b8871d9e6419c6f3bd29ccc1a

Best regards,
--  
Mohit Dsor <mohit.dsor@oss.qualcomm.com>


^ permalink raw reply

* Re: [PATCH 1/3] dt-bindings: interrupt-controller: ti,irq-crossbar: Convert to DT schema
From: Bhargav Joshi @ 2026-06-10 21:12 UTC (permalink / raw)
  To: Rob Herring
  Cc: Krzysztof Kozlowski, Conor Dooley, Thomas Gleixner, Sricharan R,
	Aaro Koskinen, Andreas Kemnade, Kevin Hilman, Roger Quadros,
	Tony Lindgren, devicetree, linux-kernel, linux-omap, goledhruva,
	m-chawdhry, daniel.baluta, simona.toaca
In-Reply-To: <20260610195658.GA702518-robh@kernel.org>

Hi,

On Thu, Jun 11, 2026 at 1:27 AM Rob Herring <robh@kernel.org> wrote:
>
> On Sat, Jun 06, 2026 at 02:26:10AM +0530, Bhargav Joshi wrote:
> > Convert TI irq-crossbar binding from text format to DT schema.
> >
> > As part of conversion following changes are made:
> >  - Add '#interrupt-cells' as a required property which was missing in
> >    text binding
> >  - As irq-crossbar is interrupt-controller. Move binding from
> >    bindings/arm/omap to bindings/interrupt-controller
> >  - property ti,irqs-reserved is defined and used as a array but other
> >    binding ti,pruss-intc.yaml uses same property name as a unit8 bitmask
> >    which causes erros in dt_binding_check. Update ti,irqs-reserved
> >    property name to ti,crossbar-irqs-reserved to resolve duplicate naming.
>
> Defining a new property breaks the ABI. We will need to fix dtschema to
> handle it. What's the error?
property irqs-reserved is defined in two bindings with different types which
causes dt_binding_check to raise following errors:
  - File "/lib/python3.14/site-packages/dtschema/validator.py", line
522, in check_duplicate_property_types
  - print(f"{self.schemas[sch_id]['$filename']}: {p}: multiple
incompatible types: {v['type']}", file=sys.stderr)
  - KeyError: 'http://devicetree.org/schemas/interrupt-controller/ti,pruss-intc.yaml#'
dtschema version: 2026.4
>
> Rob

Best Regards,
Bhargav

^ permalink raw reply

* Re: [PATCH v2] dt-bindings: interrupt-controller: renesas,r9a09g077-icu: Fix reg size in example
From: Rob Herring (Arm) @ 2026-06-10 20:16 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Krzysztof Kozlowski, Cosmin Tanislav, Conor Dooley, Magnus Damm,
	Krzysztof Kozlowski, Thomas Gleixner, linux-kernel,
	linux-renesas-soc, devicetree
In-Reply-To: <364ff570c8a1845fab24bd89557f06c9e406f8de.1781105007.git.geert+renesas@glider.be>


On Wed, 10 Jun 2026 17:24:45 +0200, Geert Uytterhoeven wrote:
> According to Figure 5.1 ("Unified memory map"), the safety register
> block is 64 KiB large, just like the non-safety register block.
> 
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
> ---
> v2:
>   - Drop Fixes tag,
>   - Add Acked-by.
> ---
>  .../bindings/interrupt-controller/renesas,r9a09g077-icu.yaml    | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 

Applied, thanks!


^ permalink raw reply

* Re: [PATCH v2] dt-bindings: phy: sc8280xp-qmp-pcie: Disallow bifurcation register on Purwa
From: Rob Herring (Arm) @ 2026-06-10 20:00 UTC (permalink / raw)
  To: Konrad Dybcio
  Cc: linux-phy, Neil Armstrong, linux-arm-msm, Krzysztof Kozlowski,
	Konrad Dybcio, Vinod Koul, YijieYang, Krzysztof Kozlowski,
	Conor Dooley, devicetree, linux-kernel
In-Reply-To: <20260610-topic-purwa_phy_shutup_warning-v2-1-951c1fbfe9b2@oss.qualcomm.com>


On Wed, 10 Jun 2026 11:45:12 +0200, Konrad Dybcio wrote:
> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> 
> Neither of the two Gen4x4 PHYs found on Purwa supports bifurcation.
> The PHY is however physically laid out as if it were to, since there
> are two separate ports (A/B).
> 
> Split out a new if-then block to un-require the bifurcation register
> handle to squash this warning:
> 
> purwa-iot-evk.dtb: phy@1bd4000 (qcom,x1p42100-qmp-gen4x4-pcie-phy): 'qcom,4ln-config-sel' is a required property
> 
> Fixes: 2e1ffd4c1805 ("dt-bindings: phy: qcom,qmp-pcie: Add X1P42100 PCIe Gen4x4 PHY")
> Reported-by: Rob Herring <robh@kernel.org>
> Closes: https://lore.kernel.org/linux-arm-msm/176857775469.1631885.16133311938753588148.robh@kernel.org/
> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> ---
> Changes in v2:
> - Rebase
> - Don't drop the mention of the warning, as it now actually exists in
>   the tree..
> - Link to v1: https://lore.kernel.org/r/20260119-topic-purwa_phy_shutup_warning-v1-1-997a692b31c6@oss.qualcomm.com
> 
> To: Vinod Koul <vkoul@kernel.org>
> To: Neil Armstrong <neil.armstrong@linaro.org>
> To: Rob Herring <robh@kernel.org>
> To: Krzysztof Kozlowski <krzk+dt@kernel.org>
> To: Conor Dooley <conor+dt@kernel.org>
> To: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> Cc: Krzysztof Kozlowski <krzk@kernel.org>
> Cc: linux-arm-msm@vger.kernel.org
> Cc: linux-phy@lists.infradead.org
> Cc: devicetree@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> ---
>  .../devicetree/bindings/phy/qcom,sc8280xp-qmp-pcie-phy.yaml | 13 +++++++++++--
>  1 file changed, 11 insertions(+), 2 deletions(-)
> 

Acked-by: Rob Herring (Arm) <robh@kernel.org>


^ permalink raw reply

* Re: [PATCH 1/7] dt-bindings: interrupt-controller: realtek,rtl-intc: Allow 2 interrupt cells
From: Rob Herring (Arm) @ 2026-06-10 19:59 UTC (permalink / raw)
  To: Markus Stockhausen
  Cc: devicetree, mail, krzk+dt, conor+dt, john, tglx, bert,
	linux-kernel
In-Reply-To: <20260605211646.2101652-2-markus.stockhausen@gmx.de>


On Fri, 05 Jun 2026 23:16:40 +0200, Markus Stockhausen wrote:
> The Realtek Otto SoC interrupt controller supports hardware interrupt
> routing to multiple parent CPU interrupt lines. To utilize this
> multi-domain support, peripheral devices need a way to explicitly
> specify their desired parent interrupt line in the device tree.
> 
> Update the "#interrupt-cells" property to accept either 1 or 2 cells.
> - 1 cell: Specifies the hardware interrupt index, implicitly routing it
>   to the first available parent (maintaining backward compatibility).
> - 2 cells: The first cell specifies the hardware interrupt index and
>   the second cell specifies the targeted parent interrupt index.
> 
> Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
> ---
>  .../bindings/interrupt-controller/realtek,rtl-intc.yaml      | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>


^ permalink raw reply

* Re: AW: [PATCH 1/7] dt-bindings: interrupt-controller: realtek,rtl-intc: Allow 2 interrupt cells
From: Rob Herring @ 2026-06-10 19:58 UTC (permalink / raw)
  To: Markus Stockhausen
  Cc: conor+dt, devicetree, sashiko-reviews, 'Thomas Gleixner'
In-Reply-To: <064801dcf776$2cbb8280$86328780$@gmx.de>

On Mon, Jun 08, 2026 at 08:39:43PM +0200, Markus Stockhausen wrote:
> Hi,
> 
> > Von: sashiko-bot@kernel.org <sashiko-bot@kernel.org> 
> > Gesendet: Freitag, 5. Juni 2026 23:26
> > An: Markus Stockhausen <markus.stockhausen@gmx.de>
> > Cc: devicetree@vger.kernel.org; robh@kernel.org; conor+dt@kernel.org
> > Betreff: Re: [PATCH 1/7] dt-bindings: interrupt-controller: realtek,rtl-intc: Allow 2 interrupt cells
> > 
> > Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> > - [Medium] The cell-count property `#interrupt-cells` uses an `enum` constraint instead of a `const` constraint, violating dt-bindings subsystem rules.
> > --
> >
> > commit 11a7c1b034a74e6212dca3ea81cd1ec7e513c49c
> > Author: Markus Stockhausen <markus.stockhausen@gmx.de>
> >
> > dt-bindings: interrupt-controller: realtek,rtl-intc: Allow 2 interrupt cells
> >
> > This commit updates the #interrupt-cells property to accept either 1 or 2
> > cells to support explicit hardware interrupt routing to multiple parent CPU
> > interrupt lines.
> >
> > > diff --git a/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml b/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml
> > > --- a/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml
> > > +++ b/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml
> > > @@ -32,8 +32,9 @@ properties:
> > >  
> > >    "#interrupt-cells":
> > >      description:
> > > -      SoC interrupt line index.
> > > -    const: 1
> > > +      First cell is the SoC interrupt line index. Optional second cell
> > > +      specifies the parent interrupt index to route to.
> > > +    enum: [1, 2]
> >
> > [Severity: Medium]
> > Does this change violate the subsystem requirements for cell-count properties?
> 
> Is switching form const:1 to const: 2 the right way here?
> Even if the driver changes handle the old 1 cell syntax 
> gracefully?

I don't know what rule sashiko is talking about. It is fine.

Rob

^ permalink raw reply

* Re: [PATCH 1/3] dt-bindings: interrupt-controller: ti,irq-crossbar: Convert to DT schema
From: Rob Herring @ 2026-06-10 19:56 UTC (permalink / raw)
  To: Bhargav Joshi
  Cc: Krzysztof Kozlowski, Conor Dooley, Thomas Gleixner, Sricharan R,
	Aaro Koskinen, Andreas Kemnade, Kevin Hilman, Roger Quadros,
	Tony Lindgren, devicetree, linux-kernel, linux-omap, goledhruva,
	m-chawdhry, daniel.baluta, simona.toaca
In-Reply-To: <20260606-crossbar-v1-1-f67f7cb9ee50@gmail.com>

On Sat, Jun 06, 2026 at 02:26:10AM +0530, Bhargav Joshi wrote:
> Convert TI irq-crossbar binding from text format to DT schema.
> 
> As part of conversion following changes are made:
>  - Add '#interrupt-cells' as a required property which was missing in
>    text binding
>  - As irq-crossbar is interrupt-controller. Move binding from
>    bindings/arm/omap to bindings/interrupt-controller
>  - property ti,irqs-reserved is defined and used as a array but other
>    binding ti,pruss-intc.yaml uses same property name as a unit8 bitmask
>    which causes erros in dt_binding_check. Update ti,irqs-reserved
>    property name to ti,crossbar-irqs-reserved to resolve duplicate naming.

Defining a new property breaks the ABI. We will need to fix dtschema to 
handle it. What's the error?

Rob

^ permalink raw reply

* Re: [PATCH net v4 3/4] net: ethernet: oa_tc6: mdiobus->parent initialized with NULL
From: sashiko-bot @ 2026-06-10 19:50 UTC (permalink / raw)
  To: Selvamani Rajagopal via B4 Relay; +Cc: robh, conor+dt, devicetree
In-Reply-To: <20260609-level-trigger-v4-3-6f389abdd192@onsemi.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

Pre-existing issues:
- [High] Use-After-Free during driver removal due to missing devm teardown synchronization.
- [High] Hardware-induced kernel panic (DoS) due to unchecked `skb_put()` extending beyond allocated buffer bounds.
- [High] Race condition freezing the TX queue due to lockless `waiting_tx_skb` check.
--

commit 2c34943e07dcd7c39f87708d303b4633c83360bd
Author: Selvamani Rajagopal <Selvamani.Rajagopal@onsemi.com>

net: ethernet: oa_tc6: mdiobus->parent initialized with NULL
    
As "dev" pointer in oa_tc6 structure is never initialized,
mbiosub->parent was initialized with NULL.  This change
fixes the issue.

> diff --git a/drivers/net/ethernet/oa_tc6.c b/drivers/net/ethernet/oa_tc6.c
> index 20c9e98d1d607..0710a5a8dcdec 100644
> --- a/drivers/net/ethernet/oa_tc6.c
> +++ b/drivers/net/ethernet/oa_tc6.c
> @@ -108,7 +108,6 @@
>  
>  /* Internal structure for MAC-PHY drivers */
>  struct oa_tc6 {
> -	struct device *dev;
>  	struct net_device *netdev;
>  	struct phy_device *phydev;
>  	struct mii_bus *mdiobus;

[ ... ]

[Severity: High]
This is a pre-existing issue, but could this teardown sequence result in a
use-after-free crash?

In drivers/net/ethernet/microchip/lan865x/lan865x.c:lan865x_remove():

    unregister_netdev(priv->netdev);
    oa_tc6_exit(priv->tc6);
    free_netdev(priv->netdev);

The driver registers a threaded IRQ using devres. This means the IRQ is freed
after the remove() function completes.

Could the IRQ thread run concurrently with or after oa_tc6_exit() and
free_netdev(), accessing the freed SKBs and netdev structure since the active
background thread is not canceled before freeing its resources?

[Severity: High]
This isn't a bug introduced by this patch, but does this code properly
validate the buffer boundaries before appending data?

In drivers/net/ethernet/oa_tc6.c:oa_tc6_prcs_ongoing_rx_frame():

    oa_tc6_update_rx_skb(tc6, payload, OA_TC6_CHUNK_PAYLOAD_SIZE);

Which appends data unconditionally in oa_tc6_update_rx_skb():

    memcpy(skb_put(tc6->rx_skb, length), payload, length);

If a faulty or malicious MAC-PHY continuously sends data chunks without
asserting the end_valid flag, wouldn't skb_put() hit the end of the buffer
and trigger skb_over_panic() since there is no check against skb_tailroom()?

[Severity: High]
This is a pre-existing issue, but could this lockless check cause the TX
queue to freeze permanently?

In drivers/net/ethernet/oa_tc6.c:oa_tc6_start_xmit():

    if (tc6->waiting_tx_skb) {
        netif_stop_queue(tc6->netdev);
        return NETDEV_TX_BUSY;
    }

And in oa_tc6_try_spi_transfer() on the worker thread:

    if (!tc6->waiting_tx_skb && netif_queue_stopped(tc6->netdev))
        netif_wake_queue(tc6->netdev);

If the worker thread takes the lock, clears waiting_tx_skb, and evaluates
netif_queue_stopped() before start_xmit() actually stops the queue, the
worker thread skips waking the queue.

When start_xmit() resumes, it stops the queue and returns NETDEV_TX_BUSY.
Since waiting_tx_skb is now NULL and the worker missed the wake-up, is there
anything left to wake the queue?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260609-level-trigger-v4-0-6f389abdd192@onsemi.com?part=3

^ permalink raw reply

* Re: [PATCH net v4 1/4] net: ethernet: oa_tc6: Interrupt is active low, level triggered.
From: sashiko-bot @ 2026-06-10 19:50 UTC (permalink / raw)
  To: Selvamani Rajagopal via B4 Relay; +Cc: conor+dt, devicetree, robh
In-Reply-To: <20260609-level-trigger-v4-1-6f389abdd192@onsemi.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Missing IRQ teardown in `oa_tc6_exit()` allows the threaded IRQ to run concurrently with or after driver teardown, causing Use-After-Free of SKBs.
- [High] Unmasking a level-triggered interrupt without clearing the hardware condition causes an interrupt storm on SPI/protocol errors.
--

commit 5c9cbbecd5c1eb1d5efb41b338ac224d42d08b34
Author: Selvamani Rajagopal <Selvamani.Rajagopal@onsemi.com>
net: ethernet: oa_tc6: Interrupt is active low, level triggered.

This patch modifies the interrupt handling mechanism for the oa_tc6 driver.
It replaces the kthread-based SPI transfer approach with a threaded IRQ, and
configures the interrupt trigger type from edge-falling to level-low.

> diff --git a/drivers/net/ethernet/oa_tc6.c b/drivers/net/ethernet/oa_tc6.c
> index 91a906a7918a2..e2c0843207f24 100644
> --- a/drivers/net/ethernet/oa_tc6.c
> +++ b/drivers/net/ethernet/oa_tc6.c

[ ... ]

> @@ -1105,29 +1104,18 @@ static int oa_tc6_try_spi_transfer(struct oa_tc6 *tc6)
>  	return 0;
>  }
>  
> -static int oa_tc6_spi_thread_handler(void *data)
> +static irqreturn_t oa_tc6_macphy_threaded_irq(int irq, void *data)
>  {
>  	struct oa_tc6 *tc6 = data;
> -	int ret;
> -
> -	while (likely(!kthread_should_stop())) {
> -		/* This kthread will be waken up if there is a tx skb or mac-phy
> -		 * interrupt to perform spi transfer with tx chunks.
> -		 */
> -		wait_event_interruptible(tc6->spi_wq, tc6->int_flag ||
> -					 (tc6->waiting_tx_skb &&
> -					 tc6->tx_credits) ||
> -					 kthread_should_stop());
> -
> -		if (kthread_should_stop())
> -			break;
>  
> +	while (tc6->int_flag || (tc6->waiting_tx_skb && tc6->tx_credits)) {
>  		ret = oa_tc6_try_spi_transfer(tc6);
>  		if (ret)
> -			return ret;
> +			break;
>  	}
>  
> -	return 0;
> +	return IRQ_HANDLED;
>  }

[Severity: High]
If oa_tc6_try_spi_transfer() fails (e.g., due to an SPI transfer failure)
and returns an error, the loop breaks and returns IRQ_HANDLED.

Since the IRQ is now configured as level-triggered, returning IRQ_HANDLED
will cause the genirq core to unmask the interrupt. If the hardware condition
was not successfully cleared due to the transfer failure, won't this result
in an immediate interrupt storm that locks up the CPU?

Should the IRQ be explicitly disabled (e.g., via disable_irq_nosync()) when
aborting on an unrecoverable error?

[ ... ]

> @@ -1357,7 +1331,6 @@ EXPORT_SYMBOL_GPL(oa_tc6_init);
>  void oa_tc6_exit(struct oa_tc6 *tc6)
>  {
>  	oa_tc6_phy_exit(tc6);
> -	kthread_stop(tc6->spi_thread);
>  	dev_kfree_skb_any(tc6->ongoing_tx_skb);
>  	dev_kfree_skb_any(tc6->waiting_tx_skb);
>  	dev_kfree_skb_any(tc6->rx_skb);
>  }

[Severity: High]
Does this code introduce a use-after-free window?

The patch removes kthread_stop(), but it doesn't explicitly disable or free
the newly added threaded IRQ here. Since the IRQ was requested with
devm_request_threaded_irq(), it will remain fully active until the devres
cleanup phase, which occurs after the driver's remove path finishes.

If the threaded IRQ runs concurrently with or after oa_tc6_exit(), can it
access tc6->ongoing_tx_skb, tc6->waiting_tx_skb, or tc6->rx_skb while they
are being unconditionally freed by dev_kfree_skb_any()?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260609-level-trigger-v4-0-6f389abdd192@onsemi.com?part=1

^ permalink raw reply

* Re: [PATCH net v4 2/4] net: ethernet: oa_tc6: No return on rx buffer overflow error
From: sashiko-bot @ 2026-06-10 19:50 UTC (permalink / raw)
  To: Selvamani Rajagopal via B4 Relay; +Cc: robh, conor+dt, devicetree
In-Reply-To: <20260609-level-trigger-v4-2-6f389abdd192@onsemi.com>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

New issues:
- [High] The newly added check for `-EAGAIN` in the threaded IRQ loop is dead code for its intended purpose (RX overflow recovery) and introduces a dangerous tight busy-loop if the underlying SPI driver fails.

Pre-existing issues:
- [Critical] Missing tailroom check before calling `skb_put()` on the receive path allows a malformed or malicious MAC-PHY stream to cause an `skb_over_panic()`.
- [Critical] Out-of-bounds memory access due to unvalidated hardware inputs for TX credits and RX chunks.
- [High] The device IRQ is not disabled before freeing SKB pointers in `oa_tc6_exit()`, leading to a race condition and use-after-free.
--

commit bd14c34a7b1c3dad290ba34e28faf15014377d8e
Author: Selvamani Rajagopal <Selvamani.Rajagopal@onsemi.com>

net: ethernet: oa_tc6: No return on rx buffer overflow error

This patch modifies the threaded IRQ handler to retry the SPI transfer if
oa_tc6_try_spi_transfer() returns -EAGAIN. This is intended to gracefully
recover from RX buffer overflow errors by discarding bad data chunks.

> diff --git a/drivers/net/ethernet/oa_tc6.c b/drivers/net/ethernet/oa_tc6.c
> --- a/drivers/net/ethernet/oa_tc6.c
> +++ b/drivers/net/ethernet/oa_tc6.c
> @@ -1111,6 +1111,8 @@ static irqreturn_t oa_tc6_macphy_threaded_irq(int irq, void *data)
>  
>  	while (tc6->int_flag || (tc6->waiting_tx_skb && tc6->tx_credits)) {
>  		ret = oa_tc6_try_spi_transfer(tc6);
> +		if (ret == -EAGAIN)
> +			continue;

[Severity: High]
Can oa_tc6_try_spi_transfer() actually return -EAGAIN for an RX overflow
condition here?

Looking at oa_tc6_try_spi_transfer(), it catches the -EAGAIN internally:

static int oa_tc6_try_spi_transfer(struct oa_tc6 *tc6)
{
        ...
        ret = oa_tc6_process_spi_data_rx_buf(tc6, spi_len);
        if (ret) {
                if (ret == -EAGAIN)
                        continue;
        ...
}

Since it loops internally, it seems it won't return -EAGAIN to the IRQ
handler for an RX overflow.

The only way oa_tc6_try_spi_transfer() returns -EAGAIN to the caller
is if the underlying SPI transfer fails with -EAGAIN.

If that happens, wouldn't this new continue statement create a tight infinite
busy-loop in the threaded IRQ handler context without sleeping?

>  		if (ret)
>  			break;
>  	}

[Severity: Critical]
This is a pre-existing issue, but does oa_tc6_update_rx_skb() verify that
the skb has sufficient tailroom before calling skb_put()?

In the receive path, data is copied into the skb:

static void oa_tc6_update_rx_skb(struct oa_tc6 *tc6, u8 *payload, u16 length)
{
        ...
        memcpy(skb_put(tc6->rx_skb, length), payload, length);
}

This is called repeatedly for ongoing frames by oa_tc6_prcs_ongoing_rx_frame()
which appends 64-byte payload chunks to the skb.

If a faulty MAC-PHY or bit-flip streams chunks without setting the end_valid
bit, could the unconditional calls to skb_put() overrun the SKB's tailroom
and trigger a kernel panic via skb_over_panic()?

[Severity: High]
This is a pre-existing issue, but is the device IRQ properly disabled
before oa_tc6_exit() frees the SKB pointers?

oa_tc6_exit() does the following:

static void oa_tc6_exit(struct oa_tc6 *tc6)
{
        ...
        dev_kfree_skb_any(tc6->ongoing_tx_skb);
        dev_kfree_skb_any(tc6->waiting_tx_skb);
        dev_kfree_skb_any(tc6->rx_skb);
        ...
}

Since the driver uses devm_request_threaded_irq(), the IRQ remains active
until the driver unbinds, which happens after oa_tc6_exit() returns.

If an interrupt fires concurrently while oa_tc6_exit() calls
dev_kfree_skb_any(), could the still-active oa_tc6_macphy_threaded_irq()
handler attempt to access these freed pointers?

[Severity: Critical]
This is a pre-existing issue, but do we validate the chunk counts read
from the hardware?

The driver updates the chunk counts from hardware registers:

static void oa_tc6_update_buffer_status_from_register(struct oa_tc6 *tc6,
                                                      u32 value)
{
        tc6->rx_chunks_available = FIELD_GET(BUFFER_STATUS_RX_CHUNKS_AVAILABLE,
                                             value);
        ...
}

These bitfields are 8 bits wide, allowing values up to 255. However, the
SPI data buffers are statically sized to handle a maximum of
OA_TC6_MAX_TX_CHUNKS (48).

If the hardware reports a value larger than 48, could loops like
oa_tc6_add_empty_chunks_to_spi_buf() write past the bounds of
spi_data_tx_buf and cause memory corruption during the SPI transfer?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260609-level-trigger-v4-0-6f389abdd192@onsemi.com?part=2

^ permalink raw reply

* Re: [PATCH v11 2/2] hwmon: temperature: add support for EMC1812
From: Guenter Roeck @ 2026-06-10 19:50 UTC (permalink / raw)
  To: Marius Cristea
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
	linux-hwmon, devicetree, linux-kernel, linux-doc
In-Reply-To: <20260610-hw_mon-emc1812-v11-2-cef809af5c19@microchip.com>

On Wed, Jun 10, 2026 at 06:19:47PM +0300, Marius Cristea wrote:
> This is the hwmon driver for Microchip EMC1812/13/14/15/33
> Multichannel Low-Voltage Remote Diode Sensor Family.
> 
> EMC1812 has one external remote temperature monitoring channel.
> EMC1813 has two external remote temperature monitoring channels.
> EMC1814 has three external remote temperature monitoring channels,
> channels 2 and 3 support anti parallel diode.
> EMC1815 has four external remote temperature monitoring channels and
> channels 1/2  and 3/4 support anti parallel diode.
> EMC1833 has two external remote temperature monitoring channels and
> channels 1 and 2 support anti parallel diode.
> Resistance Error Correction is supported on channels 1/2 and 3/4.
> 
> Signed-off-by: Marius Cristea <marius.cristea@microchip.com>

Applied.

Thanks,
Guenter

^ permalink raw reply

* Re: [PATCH v11 1/2] dt-bindings: hwmon: temperature: add support for EMC1812
From: Guenter Roeck @ 2026-06-10 19:46 UTC (permalink / raw)
  To: Marius Cristea
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet,
	linux-hwmon, devicetree, linux-kernel, linux-doc
In-Reply-To: <20260610-hw_mon-emc1812-v11-1-cef809af5c19@microchip.com>

On Wed, Jun 10, 2026 at 06:19:46PM +0300, Marius Cristea wrote:
> This is the devicetree schema for Microchip EMC1812/13/14/15/33
> Multichannel Low-Voltage Remote Diode Sensor Family. It also
> updates the MAINTAINERS file to include the new driver.
> 
> EMC1812 has one external remote temperature monitoring channel.
> EMC1813 has two external remote temperature monitoring channels.
> EMC1814 has three external remote temperature monitoring channels and
> channels 2 and 3 support anti parallel diode.
> EMC1815 has four external remote temperature monitoring channels and
> channels 1/2  and 3/4 support anti parallel diode.
> EMC1833 has two external remote temperature monitoring channels and
> channels 1 and 2 support anti parallel diode.
> Resistance Error Correction is supported on channels 1/2 and 3/4.
> 
> Signed-off-by: Marius Cristea <marius.cristea@microchip.com>
> Reviewed-by: Rob Herring (Arm) <robh@kernel.org>

Applied.

Thanks,
Guenter

^ permalink raw reply

* [PATCH net-next v3 3/5] net: mdio: realtek-rtl9300: Make otto_emdio_read_cmd() generic
From: Markus Stockhausen @ 2026-06-10 19:41 UTC (permalink / raw)
  To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
	chris.packham, daniel, robh, krzk+dt, conor+dt, devicetree
  Cc: Markus Stockhausen, Maxime Chevallier
In-Reply-To: <20260610194145.4153668-1-markus.stockhausen@gmx.de>

The otto_emdio_read_cmd() helper still uses RTL9300 specific properties.
This cannot be made generic as the I/O register has different layouts for
the different SoCs. E.g.

- RTL930x: data in bits 31-16, data out bits 15-0
- RTL931x: data in bits 15-0, data out bits 31-16

Add a mask parameter to the function signature and fill it properly
in the callers. As the masks will always have bits set from constant
defines, there is no need for a consistency check.

Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
 drivers/net/mdio/mdio-realtek-rtl9300.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/net/mdio/mdio-realtek-rtl9300.c b/drivers/net/mdio/mdio-realtek-rtl9300.c
index 007a07136fa1..5aa447ed6424 100644
--- a/drivers/net/mdio/mdio-realtek-rtl9300.c
+++ b/drivers/net/mdio/mdio-realtek-rtl9300.c
@@ -191,7 +191,7 @@ static int otto_emdio_run_cmd(struct mii_bus *bus, u32 cmd,
 }
 
 static int otto_emdio_read_cmd(struct mii_bus *bus, u32 cmd,
-			       struct otto_emdio_cmd_regs *cmd_data, u32 *value)
+			       struct otto_emdio_cmd_regs *cmd_data, u32 mask, u32 *value)
 {
 	struct otto_emdio_priv *priv = otto_emdio_bus_to_priv(bus);
 	int ret;
@@ -205,7 +205,7 @@ static int otto_emdio_read_cmd(struct mii_bus *bus, u32 cmd,
 	if (ret)
 		return ret;
 
-	*value = FIELD_GET(RTL9300_PHY_CTRL_DATA, *value);
+	*value = field_get(mask, *value);
 
 	return 0;
 }
@@ -230,7 +230,8 @@ static int otto_emdio_9300_read_c22(struct mii_bus *bus, int port, int regnum, u
 		.io_data	= FIELD_PREP(RTL9300_PHY_CTRL_INDATA, port),
 	};
 
-	return otto_emdio_read_cmd(bus, RTL9300_PHY_CTRL_TYPE_C22, &cmd_data, value);
+	return otto_emdio_read_cmd(bus, RTL9300_PHY_CTRL_TYPE_C22, &cmd_data,
+				   RTL9300_PHY_CTRL_DATA, value);
 }
 
 static int otto_emdio_9300_write_c22(struct mii_bus *bus, int port, int regnum, u16 value)
@@ -256,7 +257,8 @@ static int otto_emdio_9300_read_c45(struct mii_bus *bus, int port,
 		.io_data	= FIELD_PREP(RTL9300_PHY_CTRL_INDATA, port),
 	};
 
-	return otto_emdio_read_cmd(bus, RTL9300_PHY_CTRL_TYPE_C45, &cmd_data, value);
+	return otto_emdio_read_cmd(bus, RTL9300_PHY_CTRL_TYPE_C45, &cmd_data,
+				   RTL9300_PHY_CTRL_DATA, value);
 }
 
 static int otto_emdio_9300_write_c45(struct mii_bus *bus, int port,
-- 
2.54.0


^ permalink raw reply related

* [PATCH net-next v3 5/5] net: mdio: realtek-rtl9300: Add support for RTL931x
From: Markus Stockhausen @ 2026-06-10 19:41 UTC (permalink / raw)
  To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
	chris.packham, daniel, robh, krzk+dt, conor+dt, devicetree
  Cc: Markus Stockhausen
In-Reply-To: <20260610194145.4153668-1-markus.stockhausen@gmx.de>

The MDIO driver has been prepared for multiple device support. Add all
required bits for the RTL931x (aka mango) series. This is straightforward
but some things are worth to be mentioned.

- In contrast to RTL930x the I/O register has the input/output fields
  swapped. Upper 16 bits are for read/outputs, and the lower 16 bits
  are for write/inputs.
- The supported "pages" are 8192 and thus the raw page is 8191
- The devices support up to 56 ports. Thus the MAX_PORTS definition
  is increased by this commit.
- There are multiple global SMI controller registers with a different
  layout from RTL930x devices. Therefore a separate setup_controller()
  callback is added.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
 drivers/net/mdio/mdio-realtek-rtl9300.c | 123 +++++++++++++++++++++++-
 1 file changed, 122 insertions(+), 1 deletion(-)

diff --git a/drivers/net/mdio/mdio-realtek-rtl9300.c b/drivers/net/mdio/mdio-realtek-rtl9300.c
index 1cdf2049cfa5..892ed3780a65 100644
--- a/drivers/net/mdio/mdio-realtek-rtl9300.c
+++ b/drivers/net/mdio/mdio-realtek-rtl9300.c
@@ -73,6 +73,31 @@
 #define RTL9300_SMI_ACCESS_PHY_CTRL_3		0xcb7c
 #define RTL9300_SMI_PORT0_5_ADDR_CTRL		0xcb80
 
+#define RTL9310_NUM_BUSES			4
+#define RTL9310_NUM_PAGES			8192
+#define RTL9310_NUM_PORTS			56
+#define RTL9310_SMI_GLB_CTRL1			0x0cbc
+#define   RTL9310_SMI_GLB_FMT_SEL_C45(intf)	BIT((intf) * 2 + 1)
+#define RTL9310_SMI_INDRT_ACCESS_CTRL_0		0x0c00
+#define   RTL9310_PHY_CTRL_REG_ADDR		GENMASK(10, 6)
+#define   RTL9310_PHY_CTRL_MAIN_PAGE		GENMASK(23, 11)
+#define   RTL9310_PHY_CTRL_READ			0
+#define   RTL9310_PHY_CTRL_WRITE		BIT(4)
+#define   RTL9310_PHY_CTRL_TYPE_C45		BIT(3)
+#define   RTL9310_PHY_CTRL_TYPE_C22		0
+#define   RTL9310_PHY_CTRL_FAIL			BIT(1)
+#define RTL9310_SMI_INDRT_ACCESS_BC_PHYID_CTRL	0x0c14
+#define   RTL9310_BC_PORT_ID			GENMASK(10, 5)
+#define RTL9310_SMI_INDRT_ACCESS_CTRL_1		0x0c04
+#define RTL9310_SMI_INDRT_ACCESS_CTRL_2_LOW	0x0c08
+#define RTL9310_SMI_INDRT_ACCESS_CTRL_2_HIGH	0x0c0c
+#define RTL9310_SMI_INDRT_ACCESS_CTRL_3		0x0c10 /* I/O fields flipped */
+#define   RTL9310_PHY_CTRL_DATA			GENMASK(31, 16)
+#define   RTL9310_PHY_CTRL_INDATA		GENMASK(15, 0)
+#define RTL9310_SMI_INDRT_ACCESS_MMD_CTRL	0x0c18
+#define RTL9310_SMI_PORT_ADDR_CTRL		0x0c74
+#define RTL9310_SMI_PORT_POLLING_SEL		0x0c9c
+
 #define PHY_CTRL_CMD				BIT(0)
 #define PHY_CTRL_MMD_DEVAD			GENMASK(20, 16)
 #define PHY_CTRL_MMD_REG			GENMASK(15, 0)
@@ -81,7 +106,7 @@
 #define MAP_BITS_PER_ADDR			5
 #define MAP_BITS_PER_BUS			2
 #define MAP_BUSES_PER_REG			16
-#define MAX_PORTS				28
+#define MAX_PORTS				56
 #define MAX_SMI_BUSSES				4
 #define RAW_PAGE(priv)				((priv)->info->num_pages - 1)
 
@@ -294,6 +319,60 @@ static int otto_emdio_9300_write_c45(struct mii_bus *bus, int port,
 	return otto_emdio_write_cmd(bus, RTL9300_PHY_CTRL_TYPE_C45, &cmd_data);
 }
 
+static int otto_emdio_9310_read_c22(struct mii_bus *bus, int port, int regnum, u32 *value)
+{
+	struct otto_emdio_priv *priv = otto_emdio_bus_to_priv(bus);
+	struct otto_emdio_cmd_regs cmd_data = {
+		.broadcast	= FIELD_PREP(RTL9310_BC_PORT_ID, port),
+		.c22_data	= FIELD_PREP(RTL9310_PHY_CTRL_REG_ADDR, regnum) |
+				  FIELD_PREP(RTL9310_PHY_CTRL_MAIN_PAGE, RAW_PAGE(priv)),
+	};
+
+	return otto_emdio_read_cmd(bus, RTL9310_PHY_CTRL_TYPE_C22, &cmd_data,
+				   RTL9310_PHY_CTRL_DATA, value);
+}
+
+static int otto_emdio_9310_write_c22(struct mii_bus *bus, int port, int regnum, u16 value)
+{
+	struct otto_emdio_priv *priv = otto_emdio_bus_to_priv(bus);
+	struct otto_emdio_cmd_regs cmd_data = {
+		.c22_data	= FIELD_PREP(RTL9310_PHY_CTRL_REG_ADDR, regnum) |
+				  FIELD_PREP(RTL9310_PHY_CTRL_MAIN_PAGE, RAW_PAGE(priv)),
+		.io_data	= FIELD_PREP(RTL9310_PHY_CTRL_INDATA, value),
+		.port_mask_high	= (u32)(BIT_ULL(port) >> 32),
+		.port_mask_low	= (u32)(BIT_ULL(port)),
+	};
+
+	return otto_emdio_write_cmd(bus, RTL9310_PHY_CTRL_TYPE_C22, &cmd_data);
+}
+
+static int otto_emdio_9310_read_c45(struct mii_bus *bus, int port,
+				    int dev_addr, int regnum, u32 *value)
+{
+	struct otto_emdio_cmd_regs cmd_data = {
+		.broadcast	= FIELD_PREP(RTL9310_BC_PORT_ID, port),
+		.c45_data	= FIELD_PREP(PHY_CTRL_MMD_DEVAD, dev_addr) |
+				  FIELD_PREP(PHY_CTRL_MMD_REG, regnum),
+	};
+
+	return otto_emdio_read_cmd(bus, RTL9310_PHY_CTRL_TYPE_C45, &cmd_data,
+				   RTL9310_PHY_CTRL_DATA, value);
+}
+
+static int otto_emdio_9310_write_c45(struct mii_bus *bus, int port,
+				     int dev_addr, int regnum, u16 value)
+{
+	struct otto_emdio_cmd_regs cmd_data = {
+		.c45_data	= FIELD_PREP(PHY_CTRL_MMD_DEVAD, dev_addr) |
+				  FIELD_PREP(PHY_CTRL_MMD_REG, regnum),
+		.io_data	= FIELD_PREP(RTL9310_PHY_CTRL_INDATA, value),
+		.port_mask_high	= (u32)(BIT_ULL(port) >> 32),
+		.port_mask_low	= (u32)(BIT_ULL(port)),
+	};
+
+	return otto_emdio_write_cmd(bus, RTL9310_PHY_CTRL_TYPE_C45, &cmd_data);
+}
+
 static int otto_emdio_read_c22(struct mii_bus *bus, int phy_id, int regnum)
 {
 	struct otto_emdio_priv *priv = otto_emdio_bus_to_priv(bus);
@@ -413,6 +492,22 @@ static int otto_emdio_9300_setup_controller(struct otto_emdio_priv *priv)
 	return 0;
 }
 
+static int otto_emdio_9310_setup_controller(struct otto_emdio_priv *priv)
+{
+	int i, err;
+
+	/* Put the interfaces into C45 mode if required */
+	for (i = 0; i < priv->info->num_buses; i++) {
+		err = regmap_assign_bits(priv->regmap, RTL9310_SMI_GLB_CTRL1,
+					 RTL9310_SMI_GLB_FMT_SEL_C45(i),
+					 priv->smi_bus_is_c45[i]);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
 static int otto_emdio_probe_one(struct device *dev, struct otto_emdio_priv *priv,
 				 struct fwnode_handle *node)
 {
@@ -624,8 +719,34 @@ static const struct otto_emdio_info otto_emdio_9300_info = {
 	.write_c45 = otto_emdio_9300_write_c45,
 };
 
+static const struct otto_emdio_info otto_emdio_9310_info = {
+	.addr_map_base = RTL9310_SMI_PORT_ADDR_CTRL,
+	.bus_map_base = RTL9310_SMI_PORT_POLLING_SEL,
+	.cmd_fail = RTL9310_PHY_CTRL_FAIL,
+	.cmd_read = RTL9310_PHY_CTRL_READ,
+	.cmd_write = RTL9310_PHY_CTRL_WRITE,
+	.cmd_regs = {
+		.broadcast = RTL9310_SMI_INDRT_ACCESS_BC_PHYID_CTRL,
+		.c22_data = RTL9310_SMI_INDRT_ACCESS_CTRL_0,
+		.c45_data = RTL9310_SMI_INDRT_ACCESS_MMD_CTRL,
+		.ext_page = RTL9310_SMI_INDRT_ACCESS_CTRL_1,
+		.io_data = RTL9310_SMI_INDRT_ACCESS_CTRL_3,
+		.port_mask_low = RTL9310_SMI_INDRT_ACCESS_CTRL_2_LOW,
+		.port_mask_high = RTL9310_SMI_INDRT_ACCESS_CTRL_2_HIGH,
+	},
+	.num_buses = RTL9310_NUM_BUSES,
+	.num_pages = RTL9310_NUM_PAGES,
+	.num_ports = RTL9310_NUM_PORTS,
+	.setup_controller = otto_emdio_9310_setup_controller,
+	.read_c22 = otto_emdio_9310_read_c22,
+	.read_c45 = otto_emdio_9310_read_c45,
+	.write_c22 = otto_emdio_9310_write_c22,
+	.write_c45 = otto_emdio_9310_write_c45,
+};
+
 static const struct of_device_id otto_emdio_ids[] = {
 	{ .compatible = "realtek,rtl9301-mdio", .data = &otto_emdio_9300_info },
+	{ .compatible = "realtek,rtl9311-mdio", .data = &otto_emdio_9310_info },
 	{}
 };
 MODULE_DEVICE_TABLE(of, otto_emdio_ids);
-- 
2.54.0


^ permalink raw reply related

* [PATCH net-next v3 2/5] net: mdio: realtek-rtl9300: Add prefix to register field defines
From: Markus Stockhausen @ 2026-06-10 19:41 UTC (permalink / raw)
  To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
	chris.packham, daniel, robh, krzk+dt, conor+dt, devicetree
  Cc: Markus Stockhausen
In-Reply-To: <20260610194145.4153668-1-markus.stockhausen@gmx.de>

The current Realtek Otto MDIO driver has some define leftovers without
a SoC prefix. When adding new devices there will be an overlap for some
of them. Sort this out as follows:

- PHY_CTRL_CMD/PHY_CTRL_MMD_DEVAD/PHY_CTRL_MMD_REG are common for all
  series. Leave them as is but move them into a separate block.
- Add RTL9300 prefix to all other defines and adapt the callers.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
 drivers/net/mdio/mdio-realtek-rtl9300.c | 63 +++++++++++++------------
 1 file changed, 32 insertions(+), 31 deletions(-)

diff --git a/drivers/net/mdio/mdio-realtek-rtl9300.c b/drivers/net/mdio/mdio-realtek-rtl9300.c
index 92c8f2512476..007a07136fa1 100644
--- a/drivers/net/mdio/mdio-realtek-rtl9300.c
+++ b/drivers/net/mdio/mdio-realtek-rtl9300.c
@@ -59,23 +59,24 @@
 #define RTL9300_SMI_PORT0_15_POLLING_SEL	0xca08
 #define RTL9300_SMI_ACCESS_PHY_CTRL_0		0xcb70
 #define RTL9300_SMI_ACCESS_PHY_CTRL_1		0xcb74
-#define   PHY_CTRL_REG_ADDR			GENMASK(24, 20)
-#define   PHY_CTRL_PARK_PAGE			GENMASK(19, 15)
-#define   PHY_CTRL_MAIN_PAGE			GENMASK(14, 3)
-#define   PHY_CTRL_WRITE			BIT(2)
-#define   PHY_CTRL_READ				0
-#define   PHY_CTRL_TYPE_C45			BIT(1)
-#define   PHY_CTRL_TYPE_C22			0
-#define   PHY_CTRL_CMD				BIT(0)
-#define   PHY_CTRL_FAIL				BIT(25)
+#define   RTL9300_PHY_CTRL_REG_ADDR		GENMASK(24, 20)
+#define   RTL9300_PHY_CTRL_PARK_PAGE		GENMASK(19, 15)
+#define   RTL9300_PHY_CTRL_MAIN_PAGE		GENMASK(14, 3)
+#define   RTL9300_PHY_CTRL_WRITE		BIT(2)
+#define   RTL9300_PHY_CTRL_READ			0
+#define   RTL9300_PHY_CTRL_TYPE_C45		BIT(1)
+#define   RTL9300_PHY_CTRL_TYPE_C22		0
+#define   RTL9300_PHY_CTRL_FAIL			BIT(25)
 #define RTL9300_SMI_ACCESS_PHY_CTRL_2		0xcb78
-#define   PHY_CTRL_INDATA			GENMASK(31, 16)
-#define   PHY_CTRL_DATA				GENMASK(15, 0)
+#define   RTL9300_PHY_CTRL_INDATA		GENMASK(31, 16)
+#define   RTL9300_PHY_CTRL_DATA			GENMASK(15, 0)
 #define RTL9300_SMI_ACCESS_PHY_CTRL_3		0xcb7c
-#define   PHY_CTRL_MMD_DEVAD			GENMASK(20, 16)
-#define   PHY_CTRL_MMD_REG			GENMASK(15, 0)
 #define RTL9300_SMI_PORT0_5_ADDR_CTRL		0xcb80
 
+#define PHY_CTRL_CMD				BIT(0)
+#define PHY_CTRL_MMD_DEVAD			GENMASK(20, 16)
+#define PHY_CTRL_MMD_REG			GENMASK(15, 0)
+
 #define MAP_ADDRS_PER_REG			6
 #define MAP_BITS_PER_ADDR			5
 #define MAP_BITS_PER_BUS			2
@@ -204,7 +205,7 @@ static int otto_emdio_read_cmd(struct mii_bus *bus, u32 cmd,
 	if (ret)
 		return ret;
 
-	*value = FIELD_GET(PHY_CTRL_DATA, *value);
+	*value = FIELD_GET(RTL9300_PHY_CTRL_DATA, *value);
 
 	return 0;
 }
@@ -223,27 +224,27 @@ static int otto_emdio_9300_read_c22(struct mii_bus *bus, int port, int regnum, u
 {
 	struct otto_emdio_priv *priv = otto_emdio_bus_to_priv(bus);
 	struct otto_emdio_cmd_regs cmd_data = {
-		.c22_data	= FIELD_PREP(PHY_CTRL_REG_ADDR, regnum) |
-				  FIELD_PREP(PHY_CTRL_PARK_PAGE, 0x1f) |
-				  FIELD_PREP(PHY_CTRL_MAIN_PAGE, RAW_PAGE(priv)),
-		.io_data	= FIELD_PREP(PHY_CTRL_INDATA, port),
+		.c22_data	= FIELD_PREP(RTL9300_PHY_CTRL_REG_ADDR, regnum) |
+				  FIELD_PREP(RTL9300_PHY_CTRL_PARK_PAGE, 0x1f) |
+				  FIELD_PREP(RTL9300_PHY_CTRL_MAIN_PAGE, RAW_PAGE(priv)),
+		.io_data	= FIELD_PREP(RTL9300_PHY_CTRL_INDATA, port),
 	};
 
-	return otto_emdio_read_cmd(bus, PHY_CTRL_TYPE_C22, &cmd_data, value);
+	return otto_emdio_read_cmd(bus, RTL9300_PHY_CTRL_TYPE_C22, &cmd_data, value);
 }
 
 static int otto_emdio_9300_write_c22(struct mii_bus *bus, int port, int regnum, u16 value)
 {
 	struct otto_emdio_priv *priv = otto_emdio_bus_to_priv(bus);
 	struct otto_emdio_cmd_regs cmd_data = {
-		.c22_data	= FIELD_PREP(PHY_CTRL_REG_ADDR, regnum) |
-				  FIELD_PREP(PHY_CTRL_PARK_PAGE, 0x1f) |
-				  FIELD_PREP(PHY_CTRL_MAIN_PAGE, RAW_PAGE(priv)),
-		.io_data	= FIELD_PREP(PHY_CTRL_INDATA, value),
+		.c22_data	= FIELD_PREP(RTL9300_PHY_CTRL_REG_ADDR, regnum) |
+				  FIELD_PREP(RTL9300_PHY_CTRL_PARK_PAGE, 0x1f) |
+				  FIELD_PREP(RTL9300_PHY_CTRL_MAIN_PAGE, RAW_PAGE(priv)),
+		.io_data	= FIELD_PREP(RTL9300_PHY_CTRL_INDATA, value),
 		.port_mask_low	= BIT(port),
 	};
 
-	return otto_emdio_write_cmd(bus, PHY_CTRL_TYPE_C22, &cmd_data);
+	return otto_emdio_write_cmd(bus, RTL9300_PHY_CTRL_TYPE_C22, &cmd_data);
 }
 
 static int otto_emdio_9300_read_c45(struct mii_bus *bus, int port,
@@ -252,10 +253,10 @@ static int otto_emdio_9300_read_c45(struct mii_bus *bus, int port,
 	struct otto_emdio_cmd_regs cmd_data = {
 		.c45_data	= FIELD_PREP(PHY_CTRL_MMD_DEVAD, dev_addr) |
 				  FIELD_PREP(PHY_CTRL_MMD_REG, regnum),
-		.io_data	= FIELD_PREP(PHY_CTRL_INDATA, port),
+		.io_data	= FIELD_PREP(RTL9300_PHY_CTRL_INDATA, port),
 	};
 
-	return otto_emdio_read_cmd(bus, PHY_CTRL_TYPE_C45, &cmd_data, value);
+	return otto_emdio_read_cmd(bus, RTL9300_PHY_CTRL_TYPE_C45, &cmd_data, value);
 }
 
 static int otto_emdio_9300_write_c45(struct mii_bus *bus, int port,
@@ -264,11 +265,11 @@ static int otto_emdio_9300_write_c45(struct mii_bus *bus, int port,
 	struct otto_emdio_cmd_regs cmd_data = {
 		.c45_data	= FIELD_PREP(PHY_CTRL_MMD_DEVAD, dev_addr) |
 				  FIELD_PREP(PHY_CTRL_MMD_REG, regnum),
-		.io_data	= FIELD_PREP(PHY_CTRL_INDATA, value),
+		.io_data	= FIELD_PREP(RTL9300_PHY_CTRL_INDATA, value),
 		.port_mask_low	= BIT(port),
 	};
 
-	return otto_emdio_write_cmd(bus, PHY_CTRL_TYPE_C45, &cmd_data);
+	return otto_emdio_write_cmd(bus, RTL9300_PHY_CTRL_TYPE_C45, &cmd_data);
 }
 
 static int otto_emdio_read_c22(struct mii_bus *bus, int phy_id, int regnum)
@@ -582,9 +583,9 @@ static int otto_emdio_probe(struct platform_device *pdev)
 static const struct otto_emdio_info otto_emdio_9300_info = {
 	.addr_map_base = RTL9300_SMI_PORT0_5_ADDR_CTRL,
 	.bus_map_base = RTL9300_SMI_PORT0_15_POLLING_SEL,
-	.cmd_fail = PHY_CTRL_FAIL,
-	.cmd_read = PHY_CTRL_READ,
-	.cmd_write = PHY_CTRL_WRITE,
+	.cmd_fail = RTL9300_PHY_CTRL_FAIL,
+	.cmd_read = RTL9300_PHY_CTRL_READ,
+	.cmd_write = RTL9300_PHY_CTRL_WRITE,
 	.cmd_regs = {
 		.c22_data = RTL9300_SMI_ACCESS_PHY_CTRL_1,
 		.c45_data = RTL9300_SMI_ACCESS_PHY_CTRL_3,
-- 
2.54.0


^ permalink raw reply related

* [PATCH net-next v3 4/5] net: mdio: realtek-rtl9300: Add registers for high port count models
From: Markus Stockhausen @ 2026-06-10 19:41 UTC (permalink / raw)
  To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
	chris.packham, daniel, robh, krzk+dt, conor+dt, devicetree
  Cc: Markus Stockhausen
In-Reply-To: <20260610194145.4153668-1-markus.stockhausen@gmx.de>

The high port count models of the Realtek Otto switches have additional
registers to instrument the MDIO controller. These are:

- High port mask: A bitfield that extends the already existing low port
  mask to select ports starting from 32.
- Broadcast: This takes the port number during reads on the RTL931x.
- Extended page: Some additional page info. The SDK does not give much
  information about this. Basically some fixed value must be written
  into it during access.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
 drivers/net/mdio/mdio-realtek-rtl9300.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/net/mdio/mdio-realtek-rtl9300.c b/drivers/net/mdio/mdio-realtek-rtl9300.c
index 5aa447ed6424..1cdf2049cfa5 100644
--- a/drivers/net/mdio/mdio-realtek-rtl9300.c
+++ b/drivers/net/mdio/mdio-realtek-rtl9300.c
@@ -91,6 +91,10 @@ struct otto_emdio_cmd_regs {
 	u32 c45_data;
 	u32 io_data;
 	u32 port_mask_low;
+	/* additional registers for high port count models RTL839x/RTL931x */
+	u32 port_mask_high;
+	u32 broadcast;
+	u32 ext_page;
 };
 
 struct otto_emdio_priv {
@@ -164,6 +168,22 @@ static int otto_emdio_run_cmd(struct mii_bus *bus, u32 cmd,
 		return ret;
 
 	/* Fill all registers. Hardware will read only the needed bits depending on command */
+	if (info->cmd_regs.port_mask_high) {
+		/* Fill extra registers for high port count models */
+		ret = regmap_write(priv->regmap, info->cmd_regs.broadcast, cmd_data->broadcast);
+		if (ret)
+			return ret;
+
+		ret = regmap_write(priv->regmap, info->cmd_regs.ext_page, cmd_data->ext_page);
+		if (ret)
+			return ret;
+
+		ret = regmap_write(priv->regmap,
+				   info->cmd_regs.port_mask_high, cmd_data->port_mask_high);
+		if (ret)
+			return ret;
+	}
+
 	ret = regmap_write(priv->regmap, info->cmd_regs.port_mask_low, cmd_data->port_mask_low);
 	if (ret)
 		return ret;
-- 
2.54.0


^ permalink raw reply related

* [PATCH net-next v3 1/5] dt-bindings: net: realtek,rtl9301-mdio: Add RTL931x series
From: Markus Stockhausen @ 2026-06-10 19:41 UTC (permalink / raw)
  To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
	chris.packham, daniel, robh, krzk+dt, conor+dt, devicetree
  Cc: Markus Stockhausen, Krzysztof Kozlowski
In-Reply-To: <20260610194145.4153668-1-markus.stockhausen@gmx.de>

The 10G Realtek Otto switches are divided into two series

- Longan: RTL930x up to 28 ports
- Mango : RTL931x up to 56 ports

The Mango based devices have 3 different SoCs RTL9311, RTL9312 and RTL9313.
The MDIO controller of these switches works like the existing RTL930x
logic but has different characteristics and different registers. Add new
compatibles in the device tree.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
 .../devicetree/bindings/net/realtek,rtl9301-mdio.yaml    | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/realtek,rtl9301-mdio.yaml b/Documentation/devicetree/bindings/net/realtek,rtl9301-mdio.yaml
index 02e4e33e9969..271e05bae9c5 100644
--- a/Documentation/devicetree/bindings/net/realtek,rtl9301-mdio.yaml
+++ b/Documentation/devicetree/bindings/net/realtek,rtl9301-mdio.yaml
@@ -18,7 +18,14 @@ properties:
               - realtek,rtl9302c-mdio
               - realtek,rtl9303-mdio
           - const: realtek,rtl9301-mdio
-      - const: realtek,rtl9301-mdio
+      - items:
+          - enum:
+              - realtek,rtl9312-mdio
+              - realtek,rtl9313-mdio
+          - const: realtek,rtl9311-mdio
+      - enum:
+          - realtek,rtl9301-mdio
+          - realtek,rtl9311-mdio
 
   '#address-cells':
     const: 1
-- 
2.54.0


^ permalink raw reply related

* [PATCH net-next v3 0/5] net: mdio: realtek-rtl9300: Add RTL931x support
From: Markus Stockhausen @ 2026-06-10 19:41 UTC (permalink / raw)
  To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
	chris.packham, daniel, robh, krzk+dt, conor+dt, devicetree
  Cc: Markus Stockhausen

The Realtek Otto switch platform consists of four different series

- RTL838x aka maple   : 28 port 1G Switches
- RTL839x aka cypress : 52 port 1G Switches
- RTL930x aka longan  : 28 port 1G/2.5G/10G Switches
- RTL931x aka mango   : 56 port 1G/2.5G/10G Switches

This patch series adds support for the RTL931x devices. For this

- Enhance device tree binding.
- Implement final cleanups and enhancments for the driver.
- Add RTL931x coding.

Remark: Instead of this series it was planned to bring support for  
hardware polling configuration first. It turns out that more testing
is needed - especially for the RTL83xx SoCs. Instead add the lineup 
of the RTL931x devices, that are known to have no obvious bus and
polling issues (at least from testing and vendor SDK perspective).  

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---

v2 -> v3
  - Replace open mask coding with field_get()
  - Fix typo in patch 4 subject
  - Add Reviewed-by to all patches
v2: https://lore.kernel.org/netdev/20260609052856.3142922-1-markus.stockhausen@gmx.de/

v1 -> v2
  - Fix subject of cover letter
  - Convert const/const to enum in device tree
v1: https://lore.kernel.org/netdev/20260607125406.2853607-1-markus.stockhausen@gmx.de/


Markus Stockhausen (5):
  dt-bindings: net: realtek,rtl9301-mdio: Add RTL931x series
  net: mdio: realtek-rtl9300: Add prefix to register field defines
  net: mdio: realtek-rtl9300: Make otto_emdio_read_cmd() generic
  net: mdio: realtek-rtl9300: Add registers for high port count models
  net: mdio: realtek-rtl9300: Add support for RTL931x

 .../bindings/net/realtek,rtl9301-mdio.yaml    |   9 +-
 drivers/net/mdio/mdio-realtek-rtl9300.c       | 210 +++++++++++++++---
 2 files changed, 185 insertions(+), 34 deletions(-)

-- 
2.54.0


^ permalink raw reply

* Re: [PATCH 2/3] powercap: qcom: Add SPEL powercap driver
From: Manaf Meethalavalappu Pallikunhi @ 2026-06-10 19:33 UTC (permalink / raw)
  To: Daniel Lezcano, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Rafael J. Wysocki, Bjorn Andersson, Konrad Dybcio
  Cc: linux-arm-msm, devicetree, linux-kernel, linux-pm, Gaurav Kohli
In-Reply-To: <a1b599f9-44a8-4cd6-b4ea-5c28eef9f221@oss.qualcomm.com>

Hi Daniel,


On 5/27/2026 12:06 AM, Daniel Lezcano wrote:
> On 5/19/26 12:49, Manaf Meethalavalappu Pallikunhi wrote:
>> The Qualcomm SoC Power and Electrical Limits (SPEL) provides hardware
>> based power monitoring and limiting capabilities for various power
>> domains including System, SoC, CPU clusters, GPU, and various other
>> subsystems.
>>
>> The driver integrates with the Linux powercap framework, exposing SPEL
>> capabilities through powercap sysfs interfaces.
>>
>> Signed-off-by: Manaf Meethalavalappu Pallikunhi 
>> <manaf.pallikunhi@oss.qualcomm.com>
>> ---
>>   MAINTAINERS                  |   1 +
>>   drivers/powercap/Kconfig     |  13 +
>>   drivers/powercap/Makefile    |   1 +
>>   drivers/powercap/qcom_spel.c | 787 +++++++++++++++++++++++++++++++++ 
>> ++++++++++
>>   4 files changed, 802 insertions(+)
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index c63f147e8c54..5c7542754ab6 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -22238,6 +22238,7 @@ M:    Manaf Meethalavalappu Pallikunhi 
>> <manaf.pallikunhi@oss.qualcomm.com>
>>   L:    linux-arm-msm@vger.kernel.org
>>   S:    Maintained
>>   F:    Documentation/devicetree/bindings/power/limits/qcom,spel.yaml
>> +F:    drivers/powercap/qcom_spel.c
>>   QUALCOMM PPE DRIVER
>>   M:    Luo Jie <quic_luoj@quicinc.com>
>> diff --git a/drivers/powercap/Kconfig b/drivers/powercap/Kconfig
>> index 03c4c796d993..e3a47c653499 100644
>> --- a/drivers/powercap/Kconfig
>> +++ b/drivers/powercap/Kconfig
>> @@ -93,4 +93,17 @@ config DTPM_DEVFREQ
>>       help
>>         This enables support for device power limitation based on
>>         energy model.
>> +
>> +config QCOM_SPEL
>> +    tristate "Qualcomm SPEL Powercap driver"
>> +    depends on ARM64 || COMPILE_TEST
>> +    help
>> +      This enables support for the Qualcomm SoC Power and Electrical
>> +      Limits (SPEL) hardware, which allows power limits to be
>> +      enforced and monitored on Qualcomm SoCs.
>> +
>> +      SPEL provides energy monitoring and power capping for multiple
>> +      domains including system, SoC, CPU clusters, GPU, and various
>> +      other subsystems.
>> +
>>   endif
>> diff --git a/drivers/powercap/Makefile b/drivers/powercap/Makefile
>> index 5ab0dce565b9..8235fb9d3df6 100644
>> --- a/drivers/powercap/Makefile
>> +++ b/drivers/powercap/Makefile
>> @@ -8,3 +8,4 @@ obj-$(CONFIG_INTEL_RAPL) += intel_rapl_msr.o
>>   obj-$(CONFIG_INTEL_RAPL_TPMI) += intel_rapl_tpmi.o
>>   obj-$(CONFIG_IDLE_INJECT) += idle_inject.o
>>   obj-$(CONFIG_ARM_SCMI_POWERCAP) += arm_scmi_powercap.o
>> +obj-$(CONFIG_QCOM_SPEL) += qcom_spel.o
>> diff --git a/drivers/powercap/qcom_spel.c b/drivers/powercap/qcom_spel.c
>> new file mode 100644
>> index 000000000000..fed5647959a5
>> --- /dev/null
>> +++ b/drivers/powercap/qcom_spel.c
>> @@ -0,0 +1,787 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Qualcomm SPEL (SoC Power and Electrical Limits) Driver
>> + *
>> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
>> + */
>> +
>> +#include <linux/bitmap.h>
>> +#include <linux/device.h>
>> +#include <linux/io.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/mod_devicetable.h>
>> +#include <linux/mutex.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/powercap.h>
>> +#include <linux/slab.h>
>> +#include <linux/types.h>
>> +
>> +/* SPEL register bitmasks */
>> +#define ENERGY_STATUS_MASK        0xFFFFFFFF
>> +
>> +#define POWER_LIMIT_MASK        0x00007FFF
>> +#define POWER_LIMIT_ENABLE        BIT(31)
>> +
>> +#define TIME_WINDOW_MASK_L        0x00007FFF    /* bits [14:0] */
>> +#define TIME_WINDOW_MASK_H        0x007F0000    /* bits [22:16] */
>> +
>> +#define ENERGY_UNIT_OFFSET        16
>> +#define ENERGY_UNIT_MASK        0xF0000
>> +
>> +#define TIME_UNIT_OFFSET        8
>> +#define TIME_UNIT_MASK            0xF00
>> +
>> +#define POWER_UNIT_OFFSET        0
>> +#define POWER_UNIT_MASK            0x7
>> +
>> +#define LIMITS_CAPABILITY_OFFSET    0x20
>> +#define ENERGY_RPT_UNIT_OFFSET        0x04
>> +
>> +#define ENERGY_UNIT_SCALE        1000
>> +
>> +#define SPEL_DOMAIN_NAME_LENGTH        16
>> +
>> +/* Domain types */
>> +enum spel_domain_type {
>> +    SPEL_DOMAIN_SYS,
>> +    SPEL_DOMAIN_SOC,
>> +    SPEL_DOMAIN_CL0,
>> +    SPEL_DOMAIN_CL1,
>> +    SPEL_DOMAIN_CL2,
>> +    SPEL_DOMAIN_IGPU,
>> +    SPEL_DOMAIN_DGPU,
>> +    SPEL_DOMAIN_NSP,
>> +    SPEL_DOMAIN_MMCX,
>> +    SPEL_DOMAIN_INFRA,
>> +    SPEL_DOMAIN_DRAM,
>> +    SPEL_DOMAIN_MDM,
>> +    SPEL_DOMAIN_WLAN,
>> +    SPEL_DOMAIN_USB1,
>> +    SPEL_DOMAIN_USB2,
>> +    SPEL_DOMAIN_USB3,
>> +    SPEL_DOMAIN_MAX,
>> +};
>> +
>> +/* Power limit IDs */
>> +enum spel_power_limit_id {
>> +    POWER_LIMIT1,
>> +    POWER_LIMIT2,
>> +    POWER_LIMIT3,
>> +    POWER_LIMIT4,
>> +    NR_POWER_LIMITS,
>> +};
>> +
>> +/* Unit types for conversion */
>> +enum unit_type {
>> +    POWER_UNIT,
>> +    ENERGY_UNIT,
>> +    TIME_UNIT,
>> +};
>> +
>> +/* Power limit operation types */
>> +enum pl_ops_type {
>> +    PL_LIMIT,
>> +    PL_TIME_WINDOW,
>> +};
>> +
>> +static const char *pl_names[NR_POWER_LIMITS] = {
>> +    [POWER_LIMIT1] = "pl1",
>> +    [POWER_LIMIT2] = "pl2",
>> +    [POWER_LIMIT3] = "pl3",
>> +    [POWER_LIMIT4] = "pl4",
>> +};
> 
> Do you want to use NR_POWER_LIMITS instead of ARRAY_SIZE() ?

ACK, I will move to ARRAY_SIZE>
> Please unify the naming NR_POWER_LIMITS -> POWER_LIMITS_MAX

ACK

> 
>> +static const char *const spel_domain_names[] = {
>> +    "sys", "soc", "cl0", "cl1", "cl2", "igpu", "dgpu", "nsp",
>> +    "mmcx", "infra", "dram", "mdm", "wlan", "usb1", "usb2", "usb3",
>> +};
>> +
>> +/* Domain register offsets in node base */
>> +static const u32 domain_offsets[SPEL_DOMAIN_MAX] = {
>> +    [SPEL_DOMAIN_SYS]    = 0x40,
>> +    [SPEL_DOMAIN_SOC]    = 0x00,
>> +    [SPEL_DOMAIN_CL0]    = 0x5C,
>> +    [SPEL_DOMAIN_CL1]    = 0x60,
>> +    [SPEL_DOMAIN_CL2]    = 0x64,
>> +    [SPEL_DOMAIN_IGPU]    = 0x08,
>> +    [SPEL_DOMAIN_DGPU]    = 0x44,
>> +    [SPEL_DOMAIN_NSP]    = 0x0C,
>> +    [SPEL_DOMAIN_MMCX]    = 0x10,
>> +    [SPEL_DOMAIN_INFRA]    = 0x18,
>> +    [SPEL_DOMAIN_DRAM]    = 0x1C,
>> +    [SPEL_DOMAIN_MDM]    = 0x48,
>> +    [SPEL_DOMAIN_WLAN]    = 0x4C,
>> +    [SPEL_DOMAIN_USB1]    = 0x50,
>> +    [SPEL_DOMAIN_USB2]    = 0x54,
>> +    [SPEL_DOMAIN_USB3]    = 0x58,
>> +};
> 
> Same comment

ACK

> 
>> +/**
>> + * struct spel_constraint_info - Power limit constraint information
>> + * @limit_offset:    Register offset for power limit value
>> + * @time_window_offset:    Register offset for time window
>> + * @supported_mask:    Bit mask in capability register
> 
> Where is 'supported_mask' initialized?

It is part of constraint_info table and used as bit mask to compare 
againt capability config register value during init for each PL for 
different domains.

> 
>> + * @domain_id:        Domain this constraint applies to
>> + * @pl_id:        Power limit ID (PL1, PL2, etc.)
> 
> [ ... ]
> 
>> +
>> +/**
>> + * struct spel_domain - SPEL power domain
>> + * @power_zone:        Powercap zone
>> + * @lock:        Mutex protecting register access
>> + * @sp:            Parent system
>> + * @status_reg:        Energy counter register
>> + * @pl_name:        Power limit names
>> + * @name:        Domain name
>> + * @id:            Domain type ID
>> + */
>> +struct spel_domain {
> 
> [ ... ]
> 
>> +    struct spel_system *sp;
> 
> [ ... ]
> 
>> +struct spel_system {
>> +    struct spel_domain *domains;
> 
> [ ... ]
> 
>> +};
> 
> There is a cyclic dependency between struct spel_system <-> struct 
> spel_domain. Could it be solved ?

ACK

> 
>> +#define power_zone_to_spel_domain(_zone) \
>> +    container_of(_zone, struct spel_domain, power_zone)
>> +
>> +/* Helper functions */
>> +static bool is_pl_valid(struct spel_domain *sd, int pl)
>> +{
>> +    if (pl < POWER_LIMIT1 || pl >= NR_POWER_LIMITS)
>> +        return false;
> 
> The call to this function is strange. It is like you don't trust your 
> own code.

ACK, I will remove it in v2

> 
>> +    return sd->pl_name[pl] ? true : false;
>> +}
>> +
> 
> [ ... ]
> 
>> +
>> +    switch (pl_op) {
>> +    case PL_LIMIT:
>> +        value &= POWER_LIMIT_MASK;
>> +        if (xlate)
>> +            *data = spel_unit_xlate(sd, POWER_UNIT, value, 0);
>> +        else
>> +            *data = value;
>> +        break;
>> +    case PL_TIME_WINDOW:
>> +        /* Decode time window: bits [22:16] are upper 7 bits, [14:0] 
>> are lower 15 bits */
>> +        value = ((value & TIME_WINDOW_MASK_H) >> 16 << 15) |
>> +            (value & TIME_WINDOW_MASK_L);
> 
> [ ... ]
> 
>> +        reg_val = (reg_val & ~POWER_LIMIT_MASK) | new_val;
>> +
> 
> [ ... ]
> 
>> +        if (new_val == 0)
>> +            reg_val &= ~POWER_LIMIT_ENABLE;
>> +        else
>> +            reg_val |= POWER_LIMIT_ENABLE;
>> +        break;
> 
> [ ... ]
> 
>> +    case PL_TIME_WINDOW:
>> +        /*
>> +         * Encode time window: upper 7 bits to [22:16], lower 15 bits 
>> to [14:0]
>> +         * Time window register is separate from limit register 
>> (different offset),
>> +         * so we write only the time window bits without preserving 
>> any enable bit.
>> +         */
>> +        new_val = spel_unit_xlate(sd, TIME_UNIT, value, 1);
>> +        reg_val = (((new_val >> 15) & 0x7F) << 16) |
>> +              (new_val & 0x7FFF);
> 
> 
> The trend today is to use the FIELD_* macros for bits ops

ACK

> 
>> +        break;
>> +    default:
>> +        return -EINVAL;
>> +    }
>> +
>> +    writel(reg_val, reg_addr);
>> +    return 0;
>> +}
>> +
>> +/* Powercap zone operations */
>> +static int spel_get_energy_counter(struct powercap_zone *power_zone, 
>> u64 *energy_raw)
>> +{
>> +    struct spel_domain *sd = power_zone_to_spel_domain(power_zone);
>> +    u64 value;
>> +
>> +    value = readl(sd->status_reg);
> 
> nit: seems an line in between would help for the readability

ACK

> 
>> +    *energy_raw = spel_unit_xlate(sd, ENERGY_UNIT, value, 0);
>> +
>> +    return 0;
>> +}
>> +
>> +static int spel_get_max_energy_counter(struct powercap_zone *pcd_dev, 
>> u64 *energy)
>> +{
>> +    struct spel_domain *sd = power_zone_to_spel_domain(pcd_dev);
>> +
>> +    *energy = spel_unit_xlate(sd, ENERGY_UNIT, ENERGY_STATUS_MASK, 0);
> 
> nit: missing line

ACK>
>> +    return 0;
>> +}
>> +
>> +static int spel_release_zone(struct powercap_zone *power_zone)
>> +{
>> +    return 0;
>> +}
>> +
>> +static int spel_find_nr_power_limit(struct spel_domain *sd)
>> +{
>> +    int i, nr_pl = 0;
>> +
>> +    for (i = 0; i < NR_POWER_LIMITS; i++) {
>> +        if (is_pl_valid(sd, i))
>> +            nr_pl++;
>> +    }
>> +
>> +    return nr_pl;
>> +}
>> +
>> +static const struct powercap_zone_ops zone_ops = {
>> +    .get_energy_uj = spel_get_energy_counter,
>> +    .get_max_energy_range_uj = spel_get_max_energy_counter,
>> +    .release = spel_release_zone,
>> +};
>> +
>> +/* Constraint operations */
>> +static int spel_constraint_to_pl(struct spel_domain *sd, int cid)
>> +{
>> +    int i, j;
> 
> 'j' name is misleading because it is usually used for nested 'for' blocks

ACK

> 
>> +    for (i = POWER_LIMIT1, j = 0; i < NR_POWER_LIMITS; i++) {
> 
> Do not rely on POWER_LIMIT1 because if someday it is moved in the enum, 
> all the code assuming it is zero will be broken

ACK

> 
>> +        if (is_pl_valid(sd, i) && j++ == cid)
>  > +            return i;> +    }
>> +
>> +    return -EINVAL;
>> +}
>> +
>> +static int spel_set_power_limit(struct powercap_zone *power_zone, int 
>> cid,
>> +                u64 power_limit)
>> +{
>> +    struct spel_domain *sd = power_zone_to_spel_domain(power_zone);
>> +    int id;
>> +
>> +    id = spel_constraint_to_pl(sd, cid);
>> +    if (id < 0)
>> +        return id;
>> +
>> +    return spel_write_pl_data(sd, id, PL_LIMIT, power_limit);
>> +}
>> +
>> +static int spel_get_power_limit(struct powercap_zone *power_zone, int 
>> cid,
>> +                u64 *data)
>> +{
>> +    struct spel_domain *sd = power_zone_to_spel_domain(power_zone);
>> +    u64 val;
>> +    int ret, id;
>> +
>> +    id = spel_constraint_to_pl(sd, cid);
>> +    if (id < 0)
>> +        return id;
>> +
>> +    ret = spel_read_pl_data(sd, id, PL_LIMIT, true, &val);
>> +    if (!ret)
>> +        *data = val;
>> +
>> +    return ret;
>> +}
>> +
>> +static int spel_set_time_window(struct powercap_zone *power_zone, int 
>> cid,
>> +                u64 window)
>> +{
>> +    struct spel_domain *sd = power_zone_to_spel_domain(power_zone);
>> +    int id;
>> +
>> +    id = spel_constraint_to_pl(sd, cid);
>> +    if (id < 0)
>> +        return id;
>> +
>> +    return spel_write_pl_data(sd, id, PL_TIME_WINDOW, window);
>> +}
>> +
>> +static int spel_get_time_window(struct powercap_zone *power_zone, int 
>> cid,
>> +                u64 *data)
>> +{
>> +    struct spel_domain *sd = power_zone_to_spel_domain(power_zone);
>> +    u64 val;
>> +    int ret, id;
>> +
>> +    id = spel_constraint_to_pl(sd, cid);
>> +    if (id < 0)
>> +        return id;
>> +
>> +    ret = spel_read_pl_data(sd, id, PL_TIME_WINDOW, true, &val);
>> +    if (!ret)
>> +        *data = val;
>> +
>> +    return ret;
>> +}
>> +
>> +static const char *spel_get_constraint_name(struct powercap_zone 
>> *power_zone,
>> +                        int cid)
>> +{
>> +    struct spel_domain *sd = power_zone_to_spel_domain(power_zone);
>> +    int id;
>> +
>> +    id = spel_constraint_to_pl(sd, cid);
>> +    if (id >= 0)
>> +        return sd->pl_name[id];
>> +
>> +    return NULL;
>> +}
>> +
>> +static const struct powercap_zone_constraint_ops constraint_ops = {
>> +    .set_power_limit_uw = spel_set_power_limit,
>> +    .get_power_limit_uw = spel_get_power_limit,
>> +    .set_time_window_us = spel_set_time_window,
>> +    .get_time_window_us = spel_get_time_window,
>> +    .get_name = spel_get_constraint_name,
>> +};
>> +
>> +static void spel_init_domains(struct spel_system *sp)
>> +{
>> +    unsigned int i;
>> +
>> +    for (i = 0; i < SPEL_DOMAIN_MAX; i++) {
>> +        struct spel_domain *sd = &sp->domains[i];
>> +
>> +        sd->sp = sp;
>> +        snprintf(sd->name, SPEL_DOMAIN_NAME_LENGTH, "%s",
>> +             spel_domain_names[i]);
>> +        sd->id = i;
>> +        sd->status_reg = sp->node_base + domain_offsets[i];
>> +
>> +        /* PL1 is always supported (required for powercap 
>> registration) */
>> +        sp->limits[i] = BIT(POWER_LIMIT1);
>> +        sd->pl_name[POWER_LIMIT1] = pl_names[POWER_LIMIT1];
>> +    }
>> +}
>> +
>> +static int spel_check_unit(struct spel_system *sp)
>> +{
>> +    u32 value, shift;
>> +
>> +    /* Read power_unit and time_unit from offset 0x0 */
>> +    value = readl(sp->config_base);
>> +
>> +    /*
>> +     * Unit calculation: 1 / (2^shift)
>> +     * Masks limit: TIME_UNIT (4 bits, max 15), POWER_UNIT (3 bits, 
>> max 7).
>> +     */
>> +    shift = (value & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET;
>> +    sp->power_unit = 1000000 / (1 << shift);
>> +
>> +    shift = (value & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET;
>> +    sp->time_unit = 1000000 / (1 << shift);
>> +
>> +    /* Read energy_unit from ENERGY_RPT_UNIT_OFFSET */
>> +    value = readl(sp->config_base + ENERGY_RPT_UNIT_OFFSET);
>> +
>> +    /*
>> +     * Unit calculation: 1 / (2^shift)
>> +     * Masks limit: ENERGY_UNIT (4 bits, max 15).
>> +     */
>> +    shift = (value & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET;
>> +    sp->energy_unit = ENERGY_UNIT_SCALE * 1000000 / (1 << shift);
>> +
>> +    dev_dbg(sp->dev, "Units: energy=%dnJ, time=%dus, power=%duW\n",
>> +        sp->energy_unit, sp->time_unit, sp->power_unit);
>> +
>> +    return 0;
>> +}
>> +
>> +static void spel_detect_powerlimit(struct spel_domain *sd)
>> +{
>> +    struct spel_system *sp = sd->sp;
>> +    u32 capabilities;
>> +    int i, j;
>> +
>> +    capabilities = readl(sp->config_base + LIMITS_CAPABILITY_OFFSET);
>> +
>> +    /* Detect power limits from hardware capabilities */
>> +    for (i = POWER_LIMIT2; i < NR_POWER_LIMITS; i++) {
> 
> For my understanding, why is it starting at POWER_LIMIT2 ?

Since It is failing to register a powercap zone with 0 constraint, I 
need to add alteast one constraint for each domain. PL1 is added by 
default for all domains.

> 
>> +        for (j = 0; j < ARRAY_SIZE(constraints); j++) {
>> +            struct spel_constraint_info *ci = &constraints[j];
>> +
>> +            if (ci->domain_id == sd->id && ci->pl_id == i) {
>> +                if (capabilities & ci->supported_mask) {
>> +                    sp->limits[sd->id] |= BIT(i);
>> +                    sd->pl_name[i] = pl_names[i];
> 
> So, that explains the is_pl_valid()
> 
> Please do not use duplicated array with non-NULL pointer checks
> 
> Or sd->pl_name[] contains all the *valids* power limits, so its size is 
> different than (or equal to) pl_names. Or it is a fixed array with a 
> structure containing a flag telling if it is enabled or not.
> 
> No need to duplicate the array

ACK

> 
>> +                }
>> +                break;
>> +            }
>> +        }
>> +    }
>> +}
>> +
> 
> [ ... ]
> 
>> +static void spel_remove(struct platform_device *pdev)
>> +{
>> +    struct spel_system *sp = platform_get_drvdata(pdev);
>> +    int i;
>> +
>> +    if (!sp)
>> +        return;
> 
> Why test if the value is correct? There is no reason it changed after 
> 'probe' was successful

ACK

Thanks,
Manaf

> 
>> +
>> +    /* Unregister in reverse order: children first, then SOC, then 
>> SYS */
>> +    for (i = SPEL_DOMAIN_MAX - 1; i >= 0; i--)
>> +        powercap_unregister_zone(sp->control_type, &sp- 
>> >domains[i].power_zone);
>> +
>> +    powercap_unregister_control_type(sp->control_type);
>> +}
>> +
>> +static const struct of_device_id spel_of_match[] = {
>> +    { .compatible = "qcom,spel" },
>> +    { }
>> +};
>> +MODULE_DEVICE_TABLE(of, spel_of_match);
>> +
>> +static struct platform_driver spel_driver = {
>> +    .probe = spel_probe,
>> +    .remove = spel_remove,
>> +    .driver = {
>> +        .name = "qcom_spel",
>> +        .of_match_table = spel_of_match,
>> +    },
>> +};
>> +
>> +module_platform_driver(spel_driver);
>> +
>> +MODULE_DESCRIPTION("Qualcomm SPEL Powercap Driver");
>> +MODULE_LICENSE("GPL");
>>
> 


^ permalink raw reply

* Re: [PATCH] dt-bindings: nvmem: consumer: Make 'nvmem' an array of one-item entries
From: Rob Herring (Arm) @ 2026-06-10 19:28 UTC (permalink / raw)
  To: Konrad Dybcio
  Cc: Conor Dooley, linux-kernel, Srinivas Kandagatla,
	Krzysztof Kozlowski, devicetree, Konrad Dybcio
In-Reply-To: <20260610-topic-nvmem_schema_warning_fix-v1-1-4029becf13f9@oss.qualcomm.com>


On Wed, 10 Jun 2026 14:52:42 +0200, Konrad Dybcio wrote:
> From: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> 
> 'nvmem' unlike 'nvmem-cells', consumes references to just a single
> phandle with no arguments (i.e. with 0 cells).
> 
> Constrain the schema to enforce that, so that the number of such
> single-item entries can then be regulated by IP block-specific YAMLs.
> 
> Suggested-by: Rob Herring <robh@kernel.org>
> Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> ---
> qcom/qcs6490-rb3gen2.dtb: pmic@2 (qcom,pm8350c): pwm:nvmem: [[397, 398]] is too short
>         from schema $id: http://devicetree.org/schemas/mfd/qcom,spmi-pmic.yaml
> qcom/qcs6490-rb3gen2.dtb: pwm (qcom,pm8350c-pwm): nvmem: [[397, 398]] is too short
>         from schema $id: http://devicetree.org/schemas/leds/leds-qcom-lpg.yaml
> ---
>  Documentation/devicetree/bindings/nvmem/nvmem-consumer.yaml | 2 ++
>  1 file changed, 2 insertions(+)
> 

Given we're close to the merge window I applied so it goes into 7.2.

Rob

^ permalink raw reply

* Re: [PATCH] dt-bindings: iio: accel: Convert lis302 binding to YAML schema
From: Rob Herring @ 2026-06-10 19:23 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Md Shofiqul Islam, linux-iio, devicetree, dlechner, nuno.sa, andy,
	krzk+dt, conor+dt, krzk, linux-kernel
In-Reply-To: <20260610165640.411c1477@jic23-huawei>

On Wed, Jun 10, 2026 at 04:56:40PM +0100, Jonathan Cameron wrote:
> On Wed, 10 Jun 2026 14:00:51 +0300
> Md Shofiqul Islam <shofiqtest@gmail.com> wrote:
> 
> > Convert the STMicroelectronics LIS302DL/LIS3LV02D accelerometer device
> > tree binding from plain text format to YAML schema format.
> > 
> > The binding covers two variants matched via their respective bus drivers:
> > - SPI: st,lis302dl-spi (drivers/misc/lis3lv02d/lis3lv02d_spi.c)
> > - I2C: st,lis3lv02d   (drivers/misc/lis3lv02d/lis3lv02d_i2c.c)
> > 
> > Document all vendor-specific properties read by the driver via
> > of_property_read_*(), including click detection, IRQ routing, free-fall/
> > wake-up engines, high-pass filtering, axis remapping, output data rate,
> > and self-test limits.
> > 
> > Also correct the click threshold property names: the driver reads
> > "st,click-threshold-{x,y,z}" but the old .txt documented them as
> > "st,click-thresh-{x,y,z}".
> > 
> > Validated with: make dt_binding_check   DT_SCHEMA_FILES=Documentation/devicetree/bindings/iio/accel/st,lis302dl.yaml
> > 
> > Signed-off-by: Md Shofiqul Islam <shofiqtest@gmail.com>
> 
> Hi.
> 
> So the conundrum here is whether we want to keep carrying this binding
> as it dates to a previous era.
> 
> The driver never made it to IIO and is still in drivers/misc.
> The majority of what is the text document should never have been
> in DT in the first place. I'll guess this dates all the way back
> to the wild west days before we had regular binding review.

Where the driver is doesn't matter for the binding. Unless the 1 
apparent user is will to change things, we should just document what is 
in use (and nothing more). Some of this looks like it can be droppped.

Rob

^ permalink raw reply

* Re: [PATCH] dt-bindings: iio: accel: Convert lis302 binding to YAML schema
From: Rob Herring @ 2026-06-10 19:20 UTC (permalink / raw)
  To: Md Shofiqul Islam
  Cc: linux-iio, devicetree, jic23, dlechner, nuno.sa, andy, krzk+dt,
	conor+dt, krzk, linux-kernel
In-Reply-To: <20260610110051.1228-1-shofiqtest@gmail.com>

On Wed, Jun 10, 2026 at 02:00:51PM +0300, Md Shofiqul Islam wrote:
> Convert the STMicroelectronics LIS302DL/LIS3LV02D accelerometer device
> tree binding from plain text format to YAML schema format.
> 
> The binding covers two variants matched via their respective bus drivers:
> - SPI: st,lis302dl-spi (drivers/misc/lis3lv02d/lis3lv02d_spi.c)
> - I2C: st,lis3lv02d   (drivers/misc/lis3lv02d/lis3lv02d_i2c.c)
> 
> Document all vendor-specific properties read by the driver via
> of_property_read_*(), including click detection, IRQ routing, free-fall/
> wake-up engines, high-pass filtering, axis remapping, output data rate,
> and self-test limits.
> 
> Also correct the click threshold property names: the driver reads
> "st,click-threshold-{x,y,z}" but the old .txt documented them as
> "st,click-thresh-{x,y,z}".
> 
> Validated with: make dt_binding_check   DT_SCHEMA_FILES=Documentation/devicetree/bindings/iio/accel/st,lis302dl.yaml
> 
> Signed-off-by: Md Shofiqul Islam <shofiqtest@gmail.com>
> ---
>  .../devicetree/bindings/iio/accel/lis302.txt  | 119 ------
>  .../bindings/iio/accel/st,lis302dl.yaml       | 343 ++++++++++++++++++
>  2 files changed, 343 insertions(+), 119 deletions(-)
>  delete mode 100644 Documentation/devicetree/bindings/iio/accel/lis302.txt
>  create mode 100644 Documentation/devicetree/bindings/iio/accel/st,lis302dl.yaml
> 
> diff --git a/Documentation/devicetree/bindings/iio/accel/lis302.txt b/Documentation/devicetree/bindings/iio/accel/lis302.txt
> deleted file mode 100644
> index 457539647f36..000000000000
> --- a/Documentation/devicetree/bindings/iio/accel/lis302.txt
> +++ /dev/null
> @@ -1,119 +0,0 @@
> -LIS302 accelerometer devicetree bindings
> -
> -This device is matched via its bus drivers, and has a number of properties
> -that apply in on the generic device (independent from the bus).
> -
> -
> -Required properties for the SPI bindings:
> - - compatible: 		should be set to "st,lis3lv02d-spi"
> - - reg:			the chipselect index
> - - spi-max-frequency:	maximal bus speed, should be set to 1000000 unless
> -			constrained by external circuitry
> - - interrupts:		the interrupt generated by the device
> -
> -Required properties for the I2C bindings:
> - - compatible:		should be set to "st,lis3lv02d"
> - - reg:			i2c slave address
> - - Vdd-supply:		The input supply for Vdd
> - - Vdd_IO-supply:	The input supply for Vdd_IO
> -
> -
> -Optional properties for all bus drivers:
> -
> - - st,click-single-{x,y,z}:	if present, tells the device to issue an
> -				interrupt on single click events on the
> -				x/y/z axis.
> - - st,click-double-{x,y,z}:	if present, tells the device to issue an
> -				interrupt on double click events on the
> -				x/y/z axis.
> - - st,click-thresh-{x,y,z}:	set the x/y/z axis threshold
> - - st,click-click-time-limit:	click time limit, from 0 to 127.5msec
> -				with step of 0.5 msec
> - - st,click-latency:		click latency, from 0 to 255 msec with
> -				step of 1 msec.
> - - st,click-window:		click window, from 0 to 255 msec with
> -				step of 1 msec.
> - - st,irq{1,2}-disable:		disable IRQ 1/2
> - - st,irq{1,2}-ff-wu-1:		raise IRQ 1/2 on FF_WU_1 condition
> - - st,irq{1,2}-ff-wu-2:		raise IRQ 1/2 on FF_WU_2 condition
> - - st,irq{1,2}-data-ready:	raise IRQ 1/2 on data ready condition
> - - st,irq{1,2}-click:		raise IRQ 1/2 on click condition
> - - st,irq-open-drain:		consider IRQ lines open-drain
> - - st,irq-active-low:		make IRQ lines active low
> - - st,wu-duration-1:		duration register for Free-Fall/Wake-Up
> -				interrupt 1
> - - st,wu-duration-2:		duration register for Free-Fall/Wake-Up
> -				interrupt 2
> - - st,wakeup-{x,y,z}-{lo,hi}:	set wakeup condition on x/y/z axis for
> -				upper/lower limit
> - - st,wakeup-threshold:		set wakeup threshold
> - - st,wakeup2-{x,y,z}-{lo,hi}:	set wakeup condition on x/y/z axis for
> -				upper/lower limit for second wakeup
> -				engine.
> - - st,wakeup2-threshold:	set wakeup threshold for second wakeup
> -				engine.
> - - st,highpass-cutoff-hz=:	1, 2, 4 or 8 for 1Hz, 2Hz, 4Hz or 8Hz of
> -				highpass cut-off frequency
> - - st,hipass{1,2}-disable:	disable highpass 1/2.
> - - st,default-rate=:		set the default rate
> - - st,axis-{x,y,z}=:		set the axis to map to the three coordinates.
> -				Negative values can be used for inverted axis.
> - - st,{min,max}-limit-{x,y,z}	set the min/max limits for x/y/z axis
> -				(used by self-test)
> -
> -
> -Example for a SPI device node:
> -
> -	accelerometer@0 {
> -		compatible = "st,lis302dl-spi";
> -		reg = <0>;
> -		spi-max-frequency = <1000000>;
> -		interrupt-parent = <&gpio>;
> -		interrupts = <104 0>;
> -
> -		st,click-single-x;
> -		st,click-single-y;
> -		st,click-single-z;
> -		st,click-thresh-x = <10>;
> -		st,click-thresh-y = <10>;
> -		st,click-thresh-z = <10>;
> -		st,irq1-click;
> -		st,irq2-click;
> -		st,wakeup-x-lo;
> -		st,wakeup-x-hi;
> -		st,wakeup-y-lo;
> -		st,wakeup-y-hi;
> -		st,wakeup-z-lo;
> -		st,wakeup-z-hi;
> -	};
> -
> -Example for a I2C device node:
> -
> -	lis331dlh: accelerometer@18 {
> -		compatible = "st,lis331dlh", "st,lis3lv02d";
> -		reg = <0x18>;
> -		Vdd-supply = <&lis3_reg>;
> -		Vdd_IO-supply = <&lis3_reg>;
> -
> -		st,click-single-x;
> -		st,click-single-y;
> -		st,click-single-z;
> -		st,click-thresh-x = <10>;
> -		st,click-thresh-y = <10>;
> -		st,click-thresh-z = <10>;
> -		st,irq1-click;
> -		st,irq2-click;
> -		st,wakeup-x-lo;
> -		st,wakeup-x-hi;
> -		st,wakeup-y-lo;
> -		st,wakeup-y-hi;
> -		st,wakeup-z-lo;
> -		st,wakeup-z-hi;
> -		st,min-limit-x = <120>;
> -		st,min-limit-y = <120>;
> -		st,min-limit-z = <140>;
> -		st,max-limit-x = <550>;
> -		st,max-limit-y = <550>;
> -		st,max-limit-z = <750>;
> -	};
> -
> diff --git a/Documentation/devicetree/bindings/iio/accel/st,lis302dl.yaml b/Documentation/devicetree/bindings/iio/accel/st,lis302dl.yaml
> new file mode 100644
> index 000000000000..befc419f7f39
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/accel/st,lis302dl.yaml
> @@ -0,0 +1,343 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/iio/accel/st,lis302dl.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: STMicroelectronics LIS302DL/LIS3LV02D 3-Axis Accelerometer
> +
> +maintainers:
> +  - Jonathan Cameron <jic23@kernel.org>
> +
> +description: |
> +  STMicroelectronics LIS302DL (SPI) and LIS3LV02D (I2C) 3-axis MEMS
> +  accelerometers. Supports click detection, free-fall/wake-up interrupts,
> +  high-pass filtering, axis remapping, and self-test functions.
> +
> +  Driver located at drivers/misc/lis3lv02d/.

Bindings are independent from a driver, so drop this.

> +
> +properties:
> +  compatible:
> +    enum:
> +      - st,lis302dl-spi
> +      - st,lis3lv02d

These compatibles are already present in st,st-sensors.yaml. The long 
list of properties are not. Probably need to drop them from 
st,st-sensors.yaml.

I would suggest you remove anything here (compatibles and 
properties) that is not used on the 1 platform using this binding. If 
there's no platform using I2C interface, then that could be removed from 
the driver too.

> +
> +  reg:
> +    maxItems: 1
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  Vdd-supply:
> +    description: Main power supply regulator (I2C variant).
> +
> +  Vdd_IO-supply:
> +    description: I/O power supply regulator (I2C variant).
> +
> +  st,click-single-x:
> +    type: boolean
> +    description: Enable single-click detection on X axis.
> +
> +  st,click-double-x:
> +    type: boolean
> +    description: Enable double-click detection on X axis.
> +
> +  st,click-single-y:
> +    type: boolean
> +    description: Enable single-click detection on Y axis.
> +
> +  st,click-double-y:
> +    type: boolean
> +    description: Enable double-click detection on Y axis.
> +
> +  st,click-single-z:
> +    type: boolean
> +    description: Enable single-click detection on Z axis.
> +
> +  st,click-double-z:
> +    type: boolean
> +    description: Enable double-click detection on Z axis.
> +
> +  st,click-threshold-x:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: Click detection threshold for X axis.
> +
> +  st,click-threshold-y:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: Click detection threshold for Y axis.
> +
> +  st,click-threshold-z:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: Click detection threshold for Z axis.
> +
> +  st,click-time-limit:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: Click time limit, 0 to 127.5 ms in 0.5 ms steps.
> +
> +  st,click-latency:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: Click latency, 0 to 255 ms in 1 ms steps.
> +
> +  st,click-window:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: Click window, 0 to 255 ms in 1 ms steps.
> +
> +  st,irq1-disable:
> +    type: boolean
> +    description: Disable IRQ1 pin.
> +
> +  st,irq1-ff-wu-1:
> +    type: boolean
> +    description: Route free-fall/wake-up 1 event to IRQ1 pin.
> +
> +  st,irq1-ff-wu-2:
> +    type: boolean
> +    description: Route free-fall/wake-up 2 event to IRQ1 pin.
> +
> +  st,irq1-data-ready:
> +    type: boolean
> +    description: Route data-ready event to IRQ1 pin.
> +
> +  st,irq1-click:
> +    type: boolean
> +    description: Route click event to IRQ1 pin.
> +
> +  st,irq2-disable:
> +    type: boolean
> +    description: Disable IRQ2 pin.
> +
> +  st,irq2-ff-wu-1:
> +    type: boolean
> +    description: Route free-fall/wake-up 1 event to IRQ2 pin.
> +
> +  st,irq2-ff-wu-2:
> +    type: boolean
> +    description: Route free-fall/wake-up 2 event to IRQ2 pin.
> +
> +  st,irq2-data-ready:
> +    type: boolean
> +    description: Route data-ready event to IRQ2 pin.
> +
> +  st,irq2-click:
> +    type: boolean
> +    description: Route click event to IRQ2 pin.
> +
> +  st,irq-open-drain:
> +    type: boolean
> +    description: Configure IRQ lines as open-drain.
> +
> +  st,irq-active-low:
> +    type: boolean
> +    description: Configure IRQ lines as active-low.
> +
> +  st,wu-duration-1:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: Duration register for free-fall/wake-up interrupt 1.
> +
> +  st,wu-duration-2:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: Duration register for free-fall/wake-up interrupt 2.
> +
> +  st,wakeup-x-lo:
> +    type: boolean
> +    description: Enable wake-up on X axis lower threshold crossing.
> +
> +  st,wakeup-x-hi:
> +    type: boolean
> +    description: Enable wake-up on X axis upper threshold crossing.
> +
> +  st,wakeup-y-lo:
> +    type: boolean
> +    description: Enable wake-up on Y axis lower threshold crossing.
> +
> +  st,wakeup-y-hi:
> +    type: boolean
> +    description: Enable wake-up on Y axis upper threshold crossing.
> +
> +  st,wakeup-z-lo:
> +    type: boolean
> +    description: Enable wake-up on Z axis lower threshold crossing.
> +
> +  st,wakeup-z-hi:
> +    type: boolean
> +    description: Enable wake-up on Z axis upper threshold crossing.
> +
> +  st,wakeup-threshold:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: Threshold for wake-up engine 1.
> +
> +  st,wakeup2-x-lo:
> +    type: boolean
> +    description: Enable wake-up engine 2 on X axis lower threshold.
> +
> +  st,wakeup2-x-hi:
> +    type: boolean
> +    description: Enable wake-up engine 2 on X axis upper threshold.
> +
> +  st,wakeup2-y-lo:
> +    type: boolean
> +    description: Enable wake-up engine 2 on Y axis lower threshold.
> +
> +  st,wakeup2-y-hi:
> +    type: boolean
> +    description: Enable wake-up engine 2 on Y axis upper threshold.
> +
> +  st,wakeup2-z-lo:
> +    type: boolean
> +    description: Enable wake-up engine 2 on Z axis lower threshold.
> +
> +  st,wakeup2-z-hi:
> +    type: boolean
> +    description: Enable wake-up engine 2 on Z axis upper threshold.
> +
> +  st,wakeup2-threshold:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: Threshold for wake-up engine 2.
> +
> +  st,highpass-cutoff-hz:
> +    enum: [1, 2, 4, 8]
> +    description: High-pass filter cut-off frequency in Hz.
> +
> +  st,hipass1-disable:
> +    type: boolean
> +    description: Disable high-pass filter 1.
> +
> +  st,hipass2-disable:
> +    type: boolean
> +    description: Disable high-pass filter 2.
> +
> +  st,axis-x:
> +    $ref: /schemas/types.yaml#/definitions/int32
> +    description: |

Don't need '|'.

> +      Map physical X axis. Negative values invert the direction.
> +      Valid range -3 to 3, excluding 0.

Define the range with schema, not free form text.

Rob

^ permalink raw reply

* Re: (subset) [PATCH v2 00/15] var-som-6ul: improve support for variants
From: Frank.Li @ 2026-06-10 19:18 UTC (permalink / raw)
  To: robh, krzk+dt, conor+dt, andrzej.hajda, neil.armstrong, rfoss,
	Laurent.pinchart, jonas, jernej.skrabec, maarten.lankhorst,
	mripard, tzimmermann, airlied, simona, s.hauer, kernel, festevam,
	shawnguo, laurent.pinchart+renesas, antonin.godard,
	Hugo Villeneuve
  Cc: Frank Li, devicetree, linux-kernel, dri-devel, imx,
	linux-arm-kernel, Hugo Villeneuve
In-Reply-To: <20260305180651.1827087-1-hugo@hugovil.com>

From: Frank Li <Frank.Li@nxp.com>


On Thu, 05 Mar 2026 13:06:15 -0500, Hugo Villeneuve wrote:
> From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
>
> Hello,
> this patch series improves support for Variscite VAR-SOM-6UL based boards.
>
> The first two patches fix DT/dmesg warnings.
>
> [...]

Applied, thanks!

[14/15] dt-bindings: display/lvds-codec: add ti,sn65lvds93
        commit: bd584193a91ef2e190a2cf19f9320387fda1a21d

Other dts part already picked by me. This binding have not picked by
subsystem mainatiner by twice ping. I picked it to avoid CHECK_DTB warnings.


Best regards,
--
Frank Li <Frank.Li@nxp.com>

^ permalink raw reply


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