Devicetree
 help / color / mirror / Atom feed
* Re: [RFC PATCH v3 3/5] iio: buffer: Extend DMAengine buffer interfaces to take extra sysfs attributes
From: David Lechner @ 2026-06-19 14:17 UTC (permalink / raw)
  To: Marcelo Schmitt, Nuno Sá
  Cc: Marcelo Schmitt, linux-iio, devicetree, linux-kernel, jic23,
	nuno.sa, Michael.Hennerich, andy, robh, krzk+dt, conor+dt,
	pop.ioan-daniel
In-Reply-To: <ajVKzNgGzoueI1lW@debian-BULLSEYE-live-builder-AMD64>

On 6/19/26 8:57 AM, Marcelo Schmitt wrote:
> On 06/18, Nuno Sá wrote:
>> On Wed, Jun 17, 2026 at 04:43:18PM -0500, David Lechner wrote:
>>> On 6/16/26 9:03 PM, Marcelo Schmitt wrote:
>>>> Some devices using DMAengine buffers are connected to extra hardware that
>>>> allows setting how fast data is transferred to/from the buffer. However,
>>>> those extra pieces of harwdware are external to the sensor chip such that
>>>> supporting the transfer speed as a sensor property is a bit of an
>>>> inaccuracy. Expand IIO DMAengine buffer interfaces to take arguments for
>>>> extra sysfs attributes, enabling the transfer speed to be configured
>>>> through the buffer interface.
>>>
>>> This message is a bit confusing. It sounds like it is attempting to
>>> control something about the DMA controller itself. But based on the
>>> later patches, it looks like this is just so we can add arbitrary
>>> sysfs attributes to the bufferX directory. And in this specific case,
>>> a sampling_frequency attribute.
>>
>> Agreed. Seems like rate control comes from the buffer.
> 
> For this series, that was the actual result. Since we already have extra
> sysfs attributes for kfifo and for triggered buffers, I thought of trying it
> wish DMAengine buffers as well. The intent is to decouple the sampling frequency
> sysfs attributes (which depend on SPI offload and PWM availability) from the ADC
> IIO device. And the reason for that is to avoid making the device driver
> directly select SPI_OFFLOAD and/or depend on PWM because these devices can be
> used without offloading.
> 
Selecting SPI_OFFLOAD when it isn't needed isn't a big deal IMHO, it just isn't
very much code at all. And PWM is quite common for fans and backlights, so it
seems like it would be rare to have a system that didn't have PWM enabled for
something else already. So it just seems like extra work to me to try to make
things optional when it may never be needed in practice.

^ permalink raw reply

* Re: [PATCH RFC 1/3] dt-bindings: iio: adc: Add reference-source property
From: Conor Dooley @ 2026-06-19 14:14 UTC (permalink / raw)
  To: Kurt Borja
  Cc: Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	David Lechner, Nuno Sá, Andy Shevchenko, linux-iio,
	devicetree, linux-kernel
In-Reply-To: <20260618-new-channel-props-v1-1-963c1b5cf40a@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 1267 bytes --]

On Thu, Jun 18, 2026 at 07:33:01PM -0500, Kurt Borja wrote:
> Some ADCs have configurable voltage reference sources for each channel.
> 
> Signed-off-by: Kurt Borja <kuurtb@gmail.com>
> ---
>  Documentation/devicetree/bindings/iio/adc/adc.yaml | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/iio/adc/adc.yaml b/Documentation/devicetree/bindings/iio/adc/adc.yaml
> index b9bc02b5b07a4c..c74c2084fdb68c 100644
> --- a/Documentation/devicetree/bindings/iio/adc/adc.yaml
> +++ b/Documentation/devicetree/bindings/iio/adc/adc.yaml
> @@ -73,6 +73,16 @@ properties:
>        device design and can interact with other characteristics such as
>        settling time.
>  
> +  reference-source:
> +    $ref: /schemas/types.yaml#/definitions/uint32-array
> +    maxItems: 2
> +    minItems: 1
> +    description:
> +      Indicates the voltage reference source or sources for this channel.
> +
> +      This array describes either a single reference source or a positive and
> +      negative reference sources.

I have no idea from this description what this actually refers to. Is it
a pin? A supply? A channel?

> +
>  anyOf:
>    - oneOf:
>        - required:
> 
> -- 
> 2.54.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* Re: [PATCH v3 1/2] dt-bindings: iio: dac: Add AD5529R
From: Conor Dooley @ 2026-06-19 14:12 UTC (permalink / raw)
  To: Nuno Sá
  Cc: Janani Sunil, Jonathan Cameron, Rodrigo Alencar, Janani Sunil,
	Lars-Peter Clausen, Michael Hennerich, David Lechner,
	Nuno Sá, Andy Shevchenko, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Philipp Zabel, Jonathan Corbet, Shuah Khan,
	linux-iio, devicetree, linux-kernel, linux-doc, Mark Brown
In-Reply-To: <ajU73_TkKrSbqD4f@nsa>

[-- Attachment #1: Type: text/plain, Size: 12325 bytes --]

On Fri, Jun 19, 2026 at 02:01:08PM +0100, Nuno Sá wrote:
> On Fri, Jun 19, 2026 at 12:40:54PM +0100, Conor Dooley wrote:
> > On Fri, Jun 19, 2026 at 12:36:55PM +0100, Conor Dooley wrote:
> > > On Fri, Jun 19, 2026 at 12:33:11PM +0200, Janani Sunil wrote:
> > > > 
> > > > On 6/14/26 21:44, Jonathan Cameron wrote:
> > > > > On Tue, 9 Jun 2026 16:47:23 +0200
> > > > > Janani Sunil <jan.sun97@gmail.com> wrote:
> > > > > 
> > > > > > On 5/26/26 15:11, Rodrigo Alencar wrote:
> > > > > > > On 26/05/19 05:42PM, Janani Sunil wrote:
> > > > > > > > Devicetree bindings for AD5529R 16 channel 12/16 bit high voltage,
> > > > > > > > buffered voltage output digital-to-analog converter (DAC) with an
> > > > > > > > integrated precision reference.
> > > > > > > ...
> > > > > > > Probably others may comment on that, but...
> > > > > > > 
> > > > > > > This parent node may support device addressing for multi-device support through
> > > > > > > those ID pins. I suppose that each device may have its own power supplies or
> > > > > > > other resources like the toggle pins or reset and enable.
> > > > > > > 
> > > > > > > That way I suppose that an example would look like...
> > > > > > > > +
> > > > > > > > +patternProperties:
> > > > > > > > +  "^channel@([0-9]|1[0-5])$":
> > > > > > > > +    type: object
> > > > > > > > +    description: Child nodes for individual channel configuration
> > > > > > > > +
> > > > > > > > +    properties:
> > > > > > > > +      reg:
> > > > > > > > +        description: Channel number.
> > > > > > > > +        minimum: 0
> > > > > > > > +        maximum: 15
> > > > > > > > +
> > > > > > > > +      adi,output-range-microvolt:
> > > > > > > > +        description: |
> > > > > > > > +          Output voltage range for this channel as [min, max] in microvolts.
> > > > > > > > +          If not specified, defaults to 0V to 5V range.
> > > > > > > > +        oneOf:
> > > > > > > > +          - items:
> > > > > > > > +              - const: 0
> > > > > > > > +              - enum: [5000000, 10000000, 20000000, 40000000]
> > > > > > > > +          - items:
> > > > > > > > +              - const: -5000000
> > > > > > > > +              - const: 5000000
> > > > > > > > +          - items:
> > > > > > > > +              - const: -10000000
> > > > > > > > +              - const: 10000000
> > > > > > > > +          - items:
> > > > > > > > +              - const: -15000000
> > > > > > > > +              - const: 15000000
> > > > > > > > +          - items:
> > > > > > > > +              - const: -20000000
> > > > > > > > +              - const: 20000000
> > > > > > > > +
> > > > > > > > +    required:
> > > > > > > > +      - reg
> > > > > > > > +
> > > > > > > > +    additionalProperties: false
> > > > > > > > +
> > > > > > > > +required:
> > > > > > > > +  - compatible
> > > > > > > > +  - reg
> > > > > > > > +  - vdd-supply
> > > > > > > > +  - avdd-supply
> > > > > > > > +  - hvdd-supply
> > > > > > > > +
> > > > > > > > +dependencies:
> > > > > > > > +  spi-cpha: [ spi-cpol ]
> > > > > > > > +  spi-cpol: [ spi-cpha ]
> > > > > > > > +
> > > > > > > > +allOf:
> > > > > > > > +  - $ref: /schemas/spi/spi-peripheral-props.yaml#
> > > > > > > > +
> > > > > > > > +unevaluatedProperties: false
> > > > > > > > +
> > > > > > > > +examples:
> > > > > > > > +  - |
> > > > > > > > +    #include <dt-bindings/gpio/gpio.h>
> > > > > > > > +
> > > > > > > > +    spi {
> > > > > > > > +        #address-cells = <1>;
> > > > > > > > +        #size-cells = <0>;
> > > > > > > > +
> > > > > > > > +        dac@0 {
> > > > > > > > +            compatible = "adi,ad5529r-16";
> > > > > > > > +            reg = <0>;
> > > > > > > > +            spi-max-frequency = <25000000>;
> > > > > > > > +
> > > > > > > > +            vdd-supply = <&vdd_regulator>;
> > > > > > > > +            avdd-supply = <&avdd_regulator>;
> > > > > > > > +            hvdd-supply = <&hvdd_regulator>;
> > > > > > > > +            hvss-supply = <&hvss_regulator>;
> > > > > > > > +
> > > > > > > > +            reset-gpios = <&gpio0 87 GPIO_ACTIVE_LOW>;
> > > > > > > > +
> > > > > > > > +            #address-cells = <1>;
> > > > > > > > +            #size-cells = <0>;
> > > > > > > > +
> > > > > > > > +            channel@0 {
> > > > > > > > +                reg = <0>;
> > > > > > > > +                adi,output-range-microvolt = <0 5000000>;
> > > > > > > > +            };
> > > > > > > > +
> > > > > > > > +            channel@1 {
> > > > > > > > +                reg = <1>;
> > > > > > > > +                adi,output-range-microvolt = <(-10000000) 10000000>;
> > > > > > > > +            };
> > > > > > > > +
> > > > > > > > +            channel@2 {
> > > > > > > > +                reg = <2>;
> > > > > > > > +                adi,output-range-microvolt = <0 40000000>;
> > > > > > > > +            };
> > > > > > > > +        };
> > > > > > > > +    };
> > > > > > > ...
> > > > > > > 
> > > > > > > 	spi {
> > > > > > > 		#address-cells = <1>;
> > > > > > > 		#size-cells = <0>;
> > > > > > > 
> > > > > > > 		multi-dac@0 {
> > > > > > > 			compatible = "adi,ad5529r-16";
> > > > > > > 			reg = <0>;
> > > > > > > 			spi-max-frequency = <25000000>;
> > > > > > > 
> > > > > > > 			#address-cells = <1>;
> > > > > > > 			#size-cells = <0>;
> > > > > > > 
> > > > > > > 			dac@0 {
> > > > > > > 				reg = <0>;
> > > > > > > 				vdd-supply = <&vdd_regulator>;
> > > > > > > 				avdd-supply = <&avdd_regulator>;
> > > > > > > 				hvdd-supply = <&hvdd_regulator>;
> > > > > > > 				hvss-supply = <&hvss_regulator>;
> > > > > > > 
> > > > > > > 				reset-gpios = <&gpio0 87 GPIO_ACTIVE_LOW>;
> > > > > > > 
> > > > > > > 				#address-cells = <1>;
> > > > > > > 				#size-cells = <0>;
> > > > > > > 
> > > > > > > 				channel@0 {
> > > > > > > 					reg = <0>;
> > > > > > > 					adi,output-range-microvolt = <0 5000000>;
> > > > > > > 				};
> > > > > > > 
> > > > > > > 				channel@1 {
> > > > > > > 					reg = <1>;
> > > > > > > 					adi,output-range-microvolt = <(-10000000) 10000000>;
> > > > > > > 				};
> > > > > > > 
> > > > > > > 				channel@2 {
> > > > > > > 					reg = <2>;
> > > > > > > 					adi,output-range-microvolt = <0 40000000>;
> > > > > > > 				};
> > > > > > > 			}
> > > > > > > 
> > > > > > > 			dac@1 {
> > > > > > > 				reg = <1>;
> > > > > > > 				vdd-supply = <&vdd_regulator>;
> > > > > > > 				avdd-supply = <&avdd_regulator>;
> > > > > > > 				hvdd-supply = <&hvdd_regulator>;
> > > > > > > 				hvss-supply = <&hvss_regulator>;
> > > > > > > 
> > > > > > > 				reset-gpios = <&gpio0 88 GPIO_ACTIVE_LOW>;
> > > > > > > 
> > > > > > > 				#address-cells = <1>;
> > > > > > > 				#size-cells = <0>;
> > > > > > > 
> > > > > > > 				channel@0 {
> > > > > > > 					reg = <0>;
> > > > > > > 					adi,output-range-microvolt = <0 5000000>;
> > > > > > > 				};
> > > > > > > 
> > > > > > > 				channel@1 {
> > > > > > > 					reg = <1>;
> > > > > > > 					adi,output-range-microvolt = <(-10000000) 10000000>;
> > > > > > > 				};
> > > > > > > 			}
> > > > > > > 		};
> > > > > > > 	};
> > > > > > > 
> > > > > > > then you might need something like:
> > > > > > > 
> > > > > > > 	patternProperties:
> > > > > > > 		"^dac@[0-3]$":
> > > > > > > 
> > > > > > > and put most of the things under this node pattern.
> > > > > > > 
> > > > > > > So the main driver that you're putting together might need to handle up to four instances.
> > > > > > > Even if your current driver cannot handle this, the dt-bindings might need cover that.
> > > > > > > 
> > > > > > > Need to double check if each dac node needs a separate compatible, so you would maybe populate
> > > > > > > a platform data to be shared with the child nodes, which would be a separate driver.
> > > > > > > (not sure if it would make sense to mix and match ad5529r-16 and ad5529r-12).
> > > > > > Hi Rodrigo,
> > > > > > 
> > > > > > Thank you for looking at this.
> > > > > > 
> > > > > > For now, I would prefer to keep the binding scoped to a single AD5529R device instance. The current
> > > > > > hardware/use case we have only needs one device node and the driver is written around that model as well.
> > > > > > While the device addressing pins could allow multi-device topology, we do not have an actual platform using
> > > > > > that configuration at the moment, so I would prefer not to introduce an extra parent/child binding structure
> > > > > > speculatively without a validating use case.
> > > > > Interesting feature - kind of similar to address control on a typical i2c bus device, or
> > > > > looking at it another way a kind of distributed SPI mux.
> > > > > 
> > > > > Challenge of a binding is we need to anticipate the future.  So I think we do need something
> > > > > like Rodrigo is suggesting even if we only (for now) support a single instance in the driver.
> > > > > That would leave the path open to supporting the addressing at a later date.
> > > > > An alternative might be to look at it like a chained device setup. In those we pretend there
> > > > > is just one device with a lot of channels etc.  The snag is that here things are more loosely
> > > > > coupled whereas for those devices it tends to be you have to read / write the same register
> > > > > in all devices in the chain as one big SPI message.
> > > > > 
> > > > > +CC Mark Brown as he may know of some precedence for this feature. For his reference..
> > > > > - Each of these device has 2 ID pins.  The SPI transfers have to contain the 2 bit
> > > > > value that matches that or they are ignored.  Thus a single bus + 1 chip select can
> > > > > be used to talk to 4 devices.  Question is what that looks like in device tree + I guess
> > > > > longer term how to support it cleanly in SPI.
> > > 
> > > I'd swear I have seen this before, from some Microchip devices. Let me
> > > see if I can find what I am thinking of...
> > 
> > 
> > microchip,mcp3911 and microchip,mcp3564 both seem to do this with
> > slightly different properties.
> > 
> >   microchip,device-addr:
> >     description: Device address when multiple MCP3911 chips are present on the same SPI bus.
> >     $ref: /schemas/types.yaml#/definitions/uint32
> >     enum: [0, 1, 2, 3]
> >     default: 0
> > 
> > and
> > 
> > 
> >   microchip,hw-device-address:
> >     $ref: /schemas/types.yaml#/definitions/uint32
> >     minimum: 0
> >     maximum: 3
> >     description:
> >       The address is set on a per-device basis by fuses in the factory,
> >       configured on request. If not requested, the fuses are set for 0x1.
> >       The device address is part of the device markings to avoid
> >       potential confusion. This address is coded on two bits, so four possible
> >       addresses are available when multiple devices are present on the same
> >       SPI bus with only one Chip Select line for all devices.
> >       Each device communication starts by a CS falling edge, followed by the
> >       clocking of the device address (BITS[7:6] - top two bits of COMMAND BYTE
> >       which is first one on the wire).
> > 
> > This sounds exactly like the sort of feature that you're dealing with
> > here?
> > 
> 
> The core idea yes but for this chip, things are a bit more annoying (but
> Janani can correct me if I'm wrong). Here, each device can, in theory,
> have it's own supplies, pins and at the very least, channels with maybe
> different scales. That is why Janani is proposing dac nodes. Given I
> honestly don't like much of that "adi,ad5529r-bus" compatible I wondered
> about solving this at the spi level.
> 
> Ah and to make it more annoying, we can also mix 12 and 16 bits variants
> together in the same bus.

I'm definitely missing something, because that property for the
microchip devices is not impacted what else is on the bus. AFAICT, you
could have an mcp3911 and an mcp3564 on the same bus even though both
are completely different devices with different drivers. They have
individual device nodes and their own supplies etc etc. These aren't
per-channel properties on an adc or dac, they're per child device on a
spi bus.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* Re: [RFC PATCH net-next v8 12/12] net: airoha: add phylink support
From: sashiko-bot @ 2026-06-19 14:11 UTC (permalink / raw)
  To: Christian Marangi; +Cc: devicetree, robh, conor+dt
In-Reply-To: <20260618125752.1223-13-ansuelsmth@gmail.com>

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

New issues:
- [High] PCS configuration fails because netdev->dev.fwnode is not initialized before calling fwnode_phylink_pcs_count() and fwnode_phylink_pcs_parse().

Pre-existing issues:
- [High] Spinlock deadlock due to acquiring `port->lock` without disabling softirqs.
--

commit c3dd483dacef136d470df9049b76a9b65a5390bc
Author: Christian Marangi <ansuelsmth@gmail.com>

net: airoha: add phylink support

Add phylink support for each GDM port. For GDM1 add the internal interface
mode as the only supported mode. For GDM2/3/4 add the required
configuration of the PCS to make the external PHY or attached SFP cage
work.

> diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
> index 64dde6464f3fb..3ea8deee3e950 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.c
> +++ b/drivers/net/ethernet/airoha/airoha_eth.c
> @@ -1788,7 +1789,7 @@ static void airoha_update_hw_stats(struct airoha_gdm_dev *dev)
>  	struct airoha_gdm_port *port = dev->port;
>  	int i;
>  
> -	spin_lock(&port->stats_lock);
> +	spin_lock(&port->lock);

[Severity: High]
This is a pre-existing issue, but can this cause a spinlock deadlock if a
softirq interrupts a process-context thread holding this lock?

This function is reachable from ndo_get_stats64, which the networking core
can invoke from softirq/BH context (e.g., via bonding or team drivers). If
this lock is also acquired in process context without disabling softirqs, a
deadlock can occur.

[ ... ]
> @@ -3168,6 +3199,155 @@ bool airoha_is_valid_gdm_dev(struct airoha_eth *eth,
[ ... ]
> +static void airoha_mac_link_up(struct phylink_config *config, struct phy_device *phy,
> +			       unsigned int mode, phy_interface_t interface,
> +			       int speed, int duplex, bool tx_pause, bool rx_pause)
> +{
[ ... ]
> +	spin_lock(&port->lock);

[Severity: High]
Does acquiring port->lock here expose the deadlock mentioned above?

airoha_mac_link_up() executes in process context. If a softirq interrupts it
while holding port->lock, the softirq might call airoha_update_hw_stats()
and attempt to acquire the exact same lock.

Should this and other process-context acquisitions of port->lock use
spin_lock_bh() instead?

> +	/* Configure TX/RX frag based on speed */
[ ... ]
> +static int airoha_setup_phylink(struct net_device *netdev)
> +{
[ ... ]
> +	} else {
> +		config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
> +					   MAC_10 | MAC_100 | MAC_1000 |
> +					   MAC_2500FD | MAC_5000FD | MAC_10000FD;
> +
> +		config->num_possible_pcs = fwnode_phylink_pcs_count(dev_fwnode(config->dev));

[Severity: High]
Will dev_fwnode() return NULL here because netdev->dev.fwnode is not yet
initialized?

In airoha_alloc_gdm_device(), the device tree node is assigned using
netdev->dev.of_node = of_node_get(np), but the generic fwnode pointer is
left uninitialized.

Since airoha_setup_phylink() runs before register_netdevice(), dev_fwnode()
evaluates to NULL. This causes fwnode_phylink_pcs_count() to unconditionally
return 0, and fwnode_phylink_pcs_parse() to fail later in
airoha_fill_available_pcs().

Does this silently disable PCS discovery and break support for external PHYs
and SFP cages?

Could this be resolved by using device_set_node(&netdev->dev,
of_fwnode_handle(np)) in airoha_alloc_gdm_device(), or by passing
of_fwnode_handle(np) directly?

> +		config->fill_available_pcs = airoha_fill_available_pcs;
[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260618125752.1223-1-ansuelsmth@gmail.com?part=12

^ permalink raw reply

* Re: [RFC PATCH net-next v8 11/12] net: pcs: airoha: add PCS driver for Airoha AN7581 SoC
From: sashiko-bot @ 2026-06-19 14:11 UTC (permalink / raw)
  To: Christian Marangi; +Cc: devicetree, robh, conor+dt
In-Reply-To: <20260618125752.1223-12-ansuelsmth@gmail.com>

Thank you for your contribution! Sashiko AI review found 8 potential issue(s) to consider:
- [High] Bringing up a second port on multi-port devices (e.g., PCIe) inadvertently resets the shared global reset lines and analog PLLs, breaking the active link on the first port.
- [High] Sticky AN configuration bits break subsequent inband auto-negotiation configurations.
- [High] The driver acquires a generic PHY for USB ports but never initializes or powers it on.
- [High] Multiple regmap_read() calls fail to check for error codes, leading to uninitialized stack memory being consumed.
- [Medium] The RX signal detection loop polls the hardware status register 6 times back-to-back without any delay.
- [Medium] The return value of `airoha_pcs_setup_scu()` is ignored, which can lead to writing to hardware registers while the device is still held in reset.
- [Medium] Missing delay between reset assertion and deassertion.
- [Medium] Using read-modify-write on Write-1-to-Clear (W1C) interrupt status registers will unintentionally clear unhandled interrupts.
--

commit 1a7ffd4436659e2a919b7ea23223e2dc899f6f4c
Author: Christian Marangi <ansuelsmth@gmail.com>
Subject: net: pcs: airoha: add PCS driver for Airoha AN7581 SoC

This commit adds a new PCS driver for the Airoha AN7581 SoC, supporting
Ethernet, PON, PCIe, and USB SERDES. It registers as a PCS provider for
fwnode usage and supports various modes including USXGMII, 10G-BASER, and
SGMII.

> diff --git a/drivers/net/pcs/airoha/pcs-airoha-common.c b/drivers/net/pcs/airoha/pcs-airoha-common.c
> --- /dev/null
> +++ b/drivers/net/pcs/airoha/pcs-airoha-common.c
> @@ ... @@
> +static int airoha_pcs_setup_scu(struct airoha_pcs_priv *priv,
> +				int index, phy_interface_t interface)
> +{
[ ... ]
> +	/* TODO better handle reset from MAC */
> +	ret = reset_control_bulk_assert(ARRAY_SIZE(priv->rsts),
> +					priv->rsts);
> +	if (ret)
> +		return ret;
> +
> +	ret = reset_control_bulk_deassert(ARRAY_SIZE(priv->rsts),
> +					  priv->rsts);
> +	if (ret)
> +		return ret;

[Severity: Medium]
Will the hardware reliably detect this reset?  The reset is asserted and
immediately deasserted without any delay (such as usleep_range) between them,
which might result in a pulse too short for the hardware to sample correctly.

[Severity: High]
Does this unconditionally reset the global device-wide mac and phy reset lines
on every port's pre_config?  In multi-port scenarios like PCIe, bringing up a
second port seems like it would inadvertently reset these shared lines and
destroy the active configuration of the already-running first port.

> diff --git a/drivers/net/pcs/airoha/pcs-an7581.c b/drivers/net/pcs/airoha/pcs-an7581.c
> --- /dev/null
> +++ b/drivers/net/pcs/airoha/pcs-an7581.c
> @@ ... @@
> +static void an7581_pcs_jcpll_bringup(struct airoha_pcs_priv *priv,
> +				     int index, phy_interface_t interface)
> +{
[ ... ]
> +	/* This comment only apply to Serdes PCIe that expose
> +	 * 2 PCS.
> +	 *
> +	 * The Serdes PCIe expose 2 PCS but always require
> +	 * the PMA for the first PCS to be configured
> +	 * for correct functionality for JCPLL.
> +	 */
> +	pcs_pma = priv->pcs_pma[0];

[Severity: High]
Could this hardcoded access to port 0's PMA registers break an active link?
By toggling the shared analog PLLs and resets via priv->pcs_pma[0] when
configuring port 1, it appears this might drop the link of port 0.

> @@ ... @@
> +static bool an7581_pcs_have_rx_signal(struct airoha_pcs_priv *priv, int index)
> +{
> +	struct regmap *pcs_pma = priv->pcs_pma[index];
> +	unsigned int count = 0;
> +	u32 val;
> +	int i;
> +
> +	regmap_write(pcs_pma, AIROHA_PCS_PMA_DIG_RESERVE_0,
> +		     AIROHA_PCS_TRIGGER_RX_SIDGET_SCAN);
> +
> +	/* Scan 6 times for RX sigdet module to detect RX signal */
> +	for (i = 0; i < AIROHA_PCS_MAX_RX_SIGDET_TRY; i++) {
> +		regmap_read(pcs_pma, AIROHA_PCS_PMA_DIG_RO_RESERVE_2,
> +			    &val);
> +		if (val & AIROHA_PCS_RX_SIGDET)
> +			count++;
> +	}

[Severity: Medium]
Can the analog circuitry complete the scan in time?  The loop polls the status
register 6 times back-to-back without any temporal spacing, meaning the CPU
might instantaneously sample the exact same state in a few nanoseconds before
the hardware has time to vary its output.

> diff --git a/drivers/net/pcs/airoha/pcs-airoha-common.c b/drivers/net/pcs/airoha/pcs-airoha-common.c
> --- /dev/null
> +++ b/drivers/net/pcs/airoha/pcs-airoha-common.c
> @@ ... @@
> +static int airoha_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
> +			     phy_interface_t interface,
> +			     const unsigned long *advertising,
> +			     bool permit_pause_to_mac)
> +{
[ ... ]
> +	if (interface == PHY_INTERFACE_MODE_1000BASEX &&
> +	    neg_mode != PHYLINK_PCS_NEG_INBAND_ENABLED) {
> +		regmap_set_bits(maps->hsgmii_pcs, AIROHA_PCS_HSGMII_PCS_CTROL_1,
> +				AIROHA_PCS_SGMII_SEND_AN_ERR_EN);
> +
> +		regmap_set_bits(maps->hsgmii_pcs, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_FORCE_CL37,
> +				AIROHA_PCS_HSGMII_AN_FORCE_AN_DONE);
> +	}

[Severity: High]
Are these sticky AN configuration bits ever cleared if the port is later
reconfigured for a mode that requires inband auto-negotiation?  Since the
USB port does not issue a global reset during bringup, these force AN done
bits might permanently leak and break inband AN until a hard reboot.

> @@ ... @@
> +static int airoha_pcs_probe(struct platform_device *pdev)
> +{
[ ... ]
> +	if (data->port_type == AIROHA_PCS_USB) {
> +		struct phy *phy;
> +
> +		phy = devm_phy_get(dev, NULL);
> +		if (IS_ERR(phy))
> +			return dev_err_probe(dev, PTR_ERR(phy), "failed to get phy\n");
> +
> +		priv->phy = phy;
> +	}

> diff --git a/drivers/net/pcs/airoha/pcs-an7581.c b/drivers/net/pcs/airoha/pcs-an7581.c
> --- /dev/null
> +++ b/drivers/net/pcs/airoha/pcs-an7581.c
> @@ ... @@
> +int an7581_pcs_usb_bringup(struct airoha_pcs_priv *priv,
> +			   int index, phy_interface_t interface)
> +{
> +	int ret;
> +
> +	ret = phy_set_mode_ext(priv->phy, PHY_MODE_ETHERNET, interface);
> +	if (ret)
> +		return ret;

[Severity: High]
Does this code ever initialize or power on the generic PHY?  The PHY is
acquired during probe and its mode is set during bringup, but there are no
calls to phy_init() or phy_power_on().  Failing to do so leaves the PHY
unclocked or powered down, rendering the USB PCS non-functional.

> diff --git a/drivers/net/pcs/airoha/pcs-airoha-common.c b/drivers/net/pcs/airoha/pcs-airoha-common.c
> --- /dev/null
> +++ b/drivers/net/pcs/airoha/pcs-airoha-common.c
> @@ ... @@
> +static void airoha_pcs_pre_config(struct phylink_pcs *pcs,
> +				  phy_interface_t interface)
> +{
> +	struct airoha_pcs_port *port = to_airoha_pcs_port(pcs);
> +	struct airoha_pcs_priv *priv = port->priv;
> +	struct airoha_pcs_maps *maps;
> +
> +	maps = &priv->maps[port->index];
> +
> +	/* Select HSGMII or USXGMII in SCU regs */
> +	airoha_pcs_setup_scu(priv, port->index, interface);
> +
> +	/* MPI MBI disable */
> +	regmap_set_bits(maps->pcs_mac, AIROHA_PCS_XFI_MAC_XFI_GIB_CFG,

[Severity: Medium]
Is it safe to ignore the return value of airoha_pcs_setup_scu() here?
If the reset toggling fails, the hardware might remain held in reset,
which could cause subsequent MMIO writes to stall the bus or fail silently.

> @@ ... @@
> +static void airoha_pcs_get_state_sgmii(struct airoha_pcs_priv *priv,
> +				       unsigned int neg_mode, int index,
> +				       struct phylink_link_state *state)
> +{
> +	struct airoha_pcs_maps *maps = &priv->maps[index];
> +	u32 bmsr, lpa;
> +
> +	regmap_read(maps->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_1,
> +		    &bmsr);
> +	regmap_read(maps->hsgmii_an, AIROHA_PCS_HSGMII_AN_SGMII_REG_AN_5,
> +		    &lpa);

[Severity: High]
Does this code risk using uninitialized stack variables?  The return values of
regmap_read() are not checked. If the MMIO read fails due to power management
or hardware faults, random stack data in bmsr and lpa will be used to set
network state parameters, leaking garbage into the networking stack.

> @@ ... @@
> +static void airoha_pcs_interrupt_init_usxgmii(struct airoha_pcs_priv *priv,
> +					      int index)
> +{
[ ... ]
> +	/* Clear any pending interrupt */
> +	regmap_set_bits(maps->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_INT_STA_2,
> +			AIROHA_PCS_USXGMII_RPCS_FSM_DEC_ERR_INT |
> +			AIROHA_PCS_USXGMII_R_TYPE_E_INT |
> +			AIROHA_PCS_USXGMII_R_TYPE_T_INT |
> +			AIROHA_PCS_USXGMII_R_TYPE_D_INT);

[Severity: Medium]
Will this unintentionally clear unhandled interrupts?  Using regmap_set_bits()
performs a read-modify-write operation.  If these status registers are
Write-1-to-Clear (W1C), it will read all active interrupts and write them back
as 1, silently clearing all pending interrupts instead of just the ones
specified in the mask.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260618125752.1223-1-ansuelsmth@gmail.com?part=11

^ permalink raw reply

* Re: [RFC PATCH net-next v8 09/12] net: phylink: add .pcs_link_down PCS OP
From: sashiko-bot @ 2026-06-19 14:11 UTC (permalink / raw)
  To: Christian Marangi; +Cc: robh, devicetree, conor+dt
In-Reply-To: <20260618125752.1223-10-ansuelsmth@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Copy-paste error in the kernel-doc comment for the newly added `pcs_link_down` function incorrectly names it `pcs_link_up`.
--

commit 2d1df5800af742cd81f1378ff1f3f3bc3801c928
Author: Christian Marangi <ansuelsmth@gmail.com>

net: phylink: add .pcs_link_down PCS OP

Permits a PCS driver to define a specific operation to tear down the link
between the MAC and the PCS. Adds a new .pcs_link_down callback which is
called after .mac_link_down during phylink_link_down().

> diff --git a/include/linux/phylink.h b/include/linux/phylink.h
> index 15e6b1a39dfe2..ecf4c384fd31c 100644
> --- a/include/linux/phylink.h
> +++ b/include/linux/phylink.h

[ ... ]

> @@ -690,6 +692,16 @@ void pcs_an_restart(struct phylink_pcs *pcs);
>  void pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
>  		 phy_interface_t interface, int speed, int duplex);
>  
> +/**
> + * pcs_link_up() - tear down link between MAC and PCS

[Severity: Low]
This isn't a bug, but should this kernel-doc block name the function
pcs_link_down() instead of pcs_link_up()? It appears the function name was
carried over from above, which might trigger kernel-doc warnings during
documentation builds.

> + * @pcs: a pointer to a &struct phylink_pcs.
> + *
> + * This call will be made just after mac_link_down() to inform the PCS the
> + * link has gone down. PCS should be configured to stop processing packets
> + * for transmission and reception.
> + */
> +void pcs_link_down(struct phylink_pcs *pcs);
> +
>  /**
>   * pcs_disable_eee() - Disable EEE at the PCS
>   * @pcs: a pointer to a &struct phylink_pcs

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260618125752.1223-1-ansuelsmth@gmail.com?part=9

^ permalink raw reply

* Re: [RFC PATCH net-next v8 03/12] net: phylink: add phylink_release_pcs() to externally release a PCS
From: sashiko-bot @ 2026-06-19 14:11 UTC (permalink / raw)
  To: Christian Marangi; +Cc: conor+dt, robh, devicetree
In-Reply-To: <20260618125752.1223-4-ansuelsmth@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Unconditional and unbalanced `phylink_link_down()` in `phylink_release_pcs()` causes duplicate `mac_link_down()` callbacks and corrupts the internal phylink state machine.
--

commit 2b29c68aa2ea3d8d4cc5979668a733bbdab7236c
Author: Christian Marangi <ansuelsmth@gmail.com>

net: phylink: add phylink_release_pcs() to externally release a PCS

This commit introduces phylink_release_pcs() to allow removing a PCS from a
phylink instance. When the released PCS is the active one, the link is
brought down and a major config is forced to trigger a reconfiguration.

> diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
> index c38bcd43b8c8b..064d6f5a06da4 100644
> --- a/drivers/net/phy/phylink.c
> +++ b/drivers/net/phy/phylink.c

[ ... ]

> @@ -918,6 +920,60 @@ static void phylink_resolve_an_pause(struct phylink_link_state *state)

[ ... ]

> +	/*
> +	 * Check if we are removing the PCS currently
> +	 * in use by phylink. If this is the case, tear down
> +	 * the link, force phylink resolve to reconfigure the
> +	 * interface mode, disable the current PCS and set the
> +	 * phylink PCS to NULL.
> +	 */
> +	if (pl->pcs == pcs) {
> +		phylink_link_down(pl);
> +		phylink_pcs_disable(pl->pcs);
> +
> +		pl->force_major_config = true;

[Severity: High]
Does this unconditional call to phylink_link_down() cause unbalanced
mac_link_down() callbacks if the link is already down?

Also, if the link was up, does pl->old_link_state need to be cleared here?

For PHYLINK_DEV instances that lack a netdev, phylink_link_is_up(pl) relies
entirely on pl->old_link_state. Because pl->old_link_state remains true, the
scheduled phylink_resolve() evaluates cur_link_state as true.

Inside phylink_resolve():

1. The force_major_config block sees cur_link_state == true and calls
phylink_link_down() a second time, then sets cur_link_state = false.

2. Later, the state update block compares link_state.link != cur_link_state
(false != false), evaluating to false. As a result, pl->old_link_state is
NOT updated and remains true permanently.

3. On the next phylink_resolve() run, cur_link_state again evaluates to
true. The state update block compares link_state.link != cur_link_state
(false != true), evaluating to true, and calls phylink_link_down(pl) a third
time.

Can this state machine corruption result in multiple unbalanced
mac_link_down() calls and cause clock underflows, regulator warnings, or
hardware lockups in MAC drivers?

> +		pl->pcs = NULL;
> +	}
> +
> +	mutex_unlock(&pl->state_mutex);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260618125752.1223-1-ansuelsmth@gmail.com?part=3

^ permalink raw reply

* Re: [RFC PATCH net-next v8 05/12] net: phylink: support late PCS provider attach
From: sashiko-bot @ 2026-06-19 14:11 UTC (permalink / raw)
  To: Christian Marangi; +Cc: robh, conor+dt, devicetree
In-Reply-To: <20260618125752.1223-6-ansuelsmth@gmail.com>

Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider:
- [Critical] Unconditional `list_add()` in `pcs_provider_notify()` leads to list corruption for shared PCS providers.
- [Critical] Missing PCS removal handling leads to Use-After-Free in `pl->pcs_list`.
- [High] TOCTOU race in `phylink_create()` allows a late PCS provider to be permanently missed.
- [High] Incorrect fwnode used for `pcs-handle` lookup silently breaks late attach on multi-port devices (e.g. DSA).
- [High] Late attach updates supported interfaces but leaves ethtool linkmodes stale.
- [High] `pcs_provider_notify()` ignores subsequent PCS instances if a MAC requires multiple PCSs from the same provider fwnode.
- [High] Self-deadlock due to unconditional `rtnl_lock()` acquisition in the PCS notifier callback.
--

commit 101d55ca1c5df8e03923c9d69f42065ce0d1aab9
Author: Christian Marangi <ansuelsmth@gmail.com>

net: phylink: support late PCS provider attach

This commit adds support for late PCS provider attachment in phylink.
It creates a global notifier chain for PCS providers and allows phylink
instances to subscribe and dynamically add PCS providers when they become
available.

> diff --git a/drivers/net/pcs/pcs.c b/drivers/net/pcs/pcs.c
> index 0cc4daf7beeae..7a9d91b2a34da 100644
> --- a/drivers/net/pcs/pcs.c
> +++ b/drivers/net/pcs/pcs.c
[ ... ]
> @@ -150,6 +167,38 @@ struct phylink_pcs *fwnode_pcs_get(struct fwnode_handle *fwnode, unsigned int in
>  }
>  EXPORT_SYMBOL_GPL(fwnode_pcs_get);
>  
> +struct phylink_pcs *
> +fwnode_phylink_pcs_get_from_fwnode(struct fwnode_handle *fwnode,
> +				   struct fwnode_handle *pcs_fwnode)
> +{
> +	struct fwnode_reference_args pcsspec;
> +	int index = 0;
> +	int ret;
> +
> +	/* Loop until we find a matching PCS node or
> +	 * fwnode_parse_pcsspec() returns error
> +	 * if we don't have any other PCS reference to check.
> +	 */
> +	while (true) {
> +		ret = fwnode_parse_pcsspec(fwnode, index, NULL, &pcsspec);
> +		if (ret)
> +			return ERR_PTR(ret);
> +
> +		/* Exit loop if we found the matching PCS node */
> +		if (pcsspec.fwnode == pcs_fwnode) {
> +			fwnode_handle_put(pcsspec.fwnode);
> +			break;
> +		}

[Severity: High]
Does breaking out of the loop on the first match ignore subsequent PCS 
instances if a MAC requires multiple PCSs from the same provider?

If a phylink instance is configured to use multiple PCSs from the same 
provider, it seems the subsequent indices will never be discovered since the 
notifier only fires once per provider fwnode.

> +
> +		/* Check the next PCS reference */
> +		fwnode_handle_put(pcsspec.fwnode);
> +		index++;
> +	}
> +
> +	return fwnode_pcs_get(fwnode, index);
> +}
> +EXPORT_SYMBOL_GPL(fwnode_phylink_pcs_get_from_fwnode);
> +
>  unsigned int fwnode_phylink_pcs_count(struct fwnode_handle *fwnode)
>  {
>  	struct fwnode_reference_args out_args;
> diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
> index 064d6f5a06da4..b9a212bd12064 100644
> --- a/drivers/net/phy/phylink.c
> +++ b/drivers/net/phy/phylink.c
[ ... ]
> @@ -2000,6 +2002,53 @@ static int phylink_fill_available_pcs(struct phylink *pl,
>  	return ret;
>  }
>  
> +static int pcs_provider_notify(struct notifier_block *self,
> +			       unsigned long val, void *data)
> +{
> +	struct phylink *pl = container_of(self, struct phylink, fwnode_pcs_nb);
> +	struct fwnode_handle *pcs_fwnode = data;
> +	struct phylink_pcs *pcs;
> +
> +	rtnl_lock();

[Severity: High]
Can this unconditional lock acquisition cause a self-deadlock?

Because the provider addition is emitted via a synchronous blocking notifier, 
if a network driver or subsystem calls fwnode_pcs_add_provider() from a 
context that already holds rtnl_lock(), wouldn't this attempt to acquire 
the lock a second time?

> +
> +	/* Check if the just added PCS provider is
> +	 * in the phylink instance pcs-handle property.
> +	 */
> +	pcs = fwnode_phylink_pcs_get_from_fwnode(dev_fwnode(pl->config->dev),
> +						 pcs_fwnode);

[Severity: High]
Does this use the correct fwnode for multi-port devices like DSA switches?

It looks like pl->config->dev points to the parent switch's device, not the 
individual port. If the port-specific fwnode passed to phylink_create() isn't 
used here, will this search the switch's root device node instead and silently 
fail to find the pcs-handle?

> +	if (IS_ERR(pcs)) {
> +		rtnl_unlock();
> +		return NOTIFY_DONE;
> +	}
> +
> +	/* Add the PCS */
> +	mutex_lock(&pl->state_mutex);
> +
> +	/* Link PCS with phylink */
> +	list_add(&pcs->list, &pl->pcs_list);

[Severity: Critical]
Could this unconditional list addition corrupt the list if a single PCS 
provider is shared by multiple phylink instances?

If a single PCS provider is referenced by multiple ports on a switch, 
pcs_provider_notify() will trigger for each phylink instance. Since the 
list head inside struct phylink_pcs can only be part of one list at a time, 
won't the second list_add() corrupt the first phylink instance's pcs_list?

> +	pcs->phylink = pl;
> +
> +	/* Refresh supported interfaces */
> +	phy_interface_copy(pl->supported_interfaces,
> +			   pl->config->supported_interfaces);
> +	list_for_each_entry(pcs, &pl->pcs_list, list)
> +		phy_interface_or(pl->supported_interfaces,
> +				 pl->supported_interfaces,
> +				 pcs->supported_interfaces);

[Severity: High]
Is a call to phylink_validate() needed here to update the ethtool linkmodes?

This updates the supported interfaces mask with the PCS capabilities, but 
without recalculating pl->supported and pl->link_config.advertising, will 
the device fail to advertise or negotiate the new speeds and duplexes enabled 
by the late-attached PCS?

> +
> +	/* Force an interface reconfig if major config fail */
> +	if (pl->major_config_failed)
> +		pl->force_major_config = true;
> +
> +	mutex_unlock(&pl->state_mutex);
> +
> +	rtnl_unlock();
> +
> +	phylink_run_resolve(pl);
> +
> +	return NOTIFY_OK;
> +}
[ ... ]
> @@ -2124,6 +2173,12 @@ struct phylink *phylink_create(struct phylink_config *config,
>  	if (ret < 0)
>  		goto unlink_pcs_list;
>  
> +	/* Register notifier for late PCS attach */
> +	if (!phy_interface_empty(config->pcs_interfaces)) {
> +		pl->fwnode_pcs_nb.notifier_call = pcs_provider_notify;
> +		register_fwnode_pcs_notifier(&pl->fwnode_pcs_nb);
> +	}

[Severity: High]
Is there a race condition between the initial scan for available PCS 
providers and the registration of this late-attach notifier?

In phylink_create(), the initial scan happens here:

	ret = phylink_fill_available_pcs(pl, config);
	if (ret < 0)
		goto free_pl;

If a PCS provider driver probes and triggers the provider add notification 
after phylink_fill_available_pcs() but before register_fwnode_pcs_notifier() 
is called, won't the notification be permanently missed?

> +
>  	return pl;
>  
>  unlink_pcs_list:
> diff --git a/include/linux/pcs/pcs.h b/include/linux/pcs/pcs.h
> index b7cfdd680b2ab..45e8f96662db2 100644
> --- a/include/linux/pcs/pcs.h
> +++ b/include/linux/pcs/pcs.h
> @@ -4,7 +4,36 @@
>  
>  #include <linux/phylink.h>
>  
> +enum fwnode_pcs_notify_event {
> +	FWNODE_PCS_PROVIDER_ADD,
> +};

[Severity: Critical]
Is there a missing mechanism to handle PCS provider removal?

Without a corresponding remove event, when a PCS provider driver is unbound 
and frees the struct phylink_pcs, phylink is not notified. Since phylink 
retains the freed PCS pointer in pl->pcs_list, won't subsequent operations 
like phylink_resolve() iterate over the list and trigger a use-after-free?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260618125752.1223-1-ansuelsmth@gmail.com?part=5

^ permalink raw reply

* Re: [RFC PATCH net-next v8 02/12] net: phylink: introduce internal phylink PCS handling
From: sashiko-bot @ 2026-06-19 14:11 UTC (permalink / raw)
  To: Christian Marangi; +Cc: robh, conor+dt, devicetree
In-Reply-To: <20260618125752.1223-3-ansuelsmth@gmail.com>

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] Missing `list_del(&pcs->list)` in the error path of `phylink_create()` leaves dangling pointers to freed memory.
- [High] `phylink_validate_mac_and_pcs()` fails to return an error when a required PCS is not found.
- [High] `phy_interface_or()` mishandles the 'empty means all' semantic for `pcs->supported_interfaces`.
- [High] Race condition causing a Use-After-Free in `phylink_pcs_change()` during `phylink_destroy()`.
- [Medium] `phylink_fill_available_pcs()` reverses the priority order of the provided PCS array.
--

commit b5576005f95ddfaef269adf2938d4dda4a006f6b
Author: Christian Marangi <ansuelsmth@gmail.com>

net: phylink: introduce internal phylink PCS handling

This commit introduces an internal linked list implementation for handling
PCS devices within phylink, providing an alternative to the .mac_select_pcs
callback. It allows MAC drivers to provide an array of available PCS devices
which are automatically mapped and selected based on the interface mode.

> diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
> index 4d59c0dd78dbf..c38bcd43b8c8b 100644
> --- a/drivers/net/phy/phylink.c
> +++ b/drivers/net/phy/phylink.c

[ ... ]

> @@ -518,12 +523,29 @@ static void phylink_validate_mask_caps(unsigned long *supported,
>  	linkmode_and(state->advertising, state->advertising, mask);
>  }
>  
> +static int phylink_validate_pcs_interface(struct phylink_pcs *pcs,
> +					  phy_interface_t interface)
> +{
> +	/* If PCS define an empty supported_interfaces value, assume
> +	 * all interface are supported.
> +	 */
> +	if (phy_interface_empty(pcs->supported_interfaces))
> +		return 0;
> +
> +	/* Ensure that this PCS supports the interface mode */
> +	if (!test_bit(interface, pcs->supported_interfaces))
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
>  static int phylink_validate_mac_and_pcs(struct phylink *pl,
>  					unsigned long *supported,
>  					struct phylink_link_state *state)
>  {
> -	struct phylink_pcs *pcs = NULL;
>  	unsigned long capabilities;
> +	struct phylink_pcs *pcs;
> +	bool pcs_found = false;
>  	int ret;
>  
>  	/* Get the PCS for this interface mode */
> @@ -531,9 +553,24 @@ static int phylink_validate_mac_and_pcs(struct phylink *pl,
>  		pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface);
>  		if (IS_ERR(pcs))
>  			return PTR_ERR(pcs);
> +
> +		pcs_found = !!pcs;
> +	/*
> +	 * Find a PCS in available PCS list for the requested interface.
> +	 *
> +	 * Skip searching if the MAC doesn't require a dedicated PCS for
> +	 * the requested interface.
> +	 */
> +	} else if (test_bit(state->interface, pl->config->pcs_interfaces)) {
> +		list_for_each_entry(pcs, &pl->pcs_list, list) {
> +			if (!phylink_validate_pcs_interface(pcs, state->interface)) {
> +				pcs_found = true;
> +				break;
> +			}
> +		}
>  	}
>  
> -	if (pcs) {
> +	if (pcs_found) {

[Severity: High]
Does this code incorrectly fall through and return success when a required PCS
is not found?

If test_bit(state->interface, pl->config->pcs_interfaces) requires a dedicated
PCS, but none in pl->pcs_list matches, pcs_found remains false. The function
then skips the pcs_found validation block, proceeds to validate MAC
capabilities, and successfully returns 0.

Could this falsely advertise the interface as supported, leading to failures
later in phylink_major_config() where the missing PCS causes an abort? Should
there be an explicit error return when a required PCS is not found?

[ ... ]

> @@ -1834,6 +1906,44 @@ int phylink_set_fixed_link(struct phylink *pl,
>  }
>  EXPORT_SYMBOL_GPL(phylink_set_fixed_link);
>  
> +static int phylink_fill_available_pcs(struct phylink *pl,
> +				      struct phylink_config *config)
> +{
> +	struct phylink_pcs **pcss;
> +	int i, ret;
> +
> +	if (!config->num_possible_pcs)
> +		return 0;
> +
> +	if (!config->fill_available_pcs) {
> +		dev_err(config->dev,
> +			"phylink: error: num_possible_pcs defined but no fill_available_pcs\n");
> +		return -EINVAL;
> +	}
> +
> +	pcss = kzalloc_objs(*pcss, config->num_possible_pcs);
> +	if (!pcss)
> +		return -ENOMEM;
> +
> +	ret = config->fill_available_pcs(config, pcss, config->num_possible_pcs);
> +	if (ret < 0)
> +		goto out;
> +
> +	for (i = 0; i < config->num_possible_pcs; i++) {
> +		struct phylink_pcs *pcs = pcss[i];
> +
> +		if (!pcs)
> +			continue;
> +
> +		list_add(&pcs->list, &pl->pcs_list);
> +	}

[Severity: Medium]
Does this loop reverse the intended priority order of the provided PCS array?

The function iterates sequentially through the pcss array and uses list_add()
to insert each PCS at the head of the list. When evaluating the list from head
to tail later (e.g., in phylink_validate_mac_and_pcs()), the MAC driver's
lowest-priority PCS (last in the array) will be checked before higher-priority
ones.

Should this use list_add_tail() instead to preserve the array order?

[ ... ]

> @@ -1872,10 +1993,26 @@ struct phylink *phylink_create(struct phylink_config *config,
>  	mutex_init(&pl->phydev_mutex);
>  	mutex_init(&pl->state_mutex);
>  	INIT_WORK(&pl->resolve, phylink_resolve);
> +	INIT_LIST_HEAD(&pl->pcs_list);
> +
> +	/* Fill the PCS list with available PCS from phylink config */
> +	ret = phylink_fill_available_pcs(pl, config);
> +	if (ret < 0)
> +		goto free_pl;
> +
> +	/* Link available PCS to phylink */
> +	list_for_each_entry(pcs, &pl->pcs_list, list)
> +		pcs->phylink = pl;
>  
>  	phy_interface_copy(pl->supported_interfaces,
>  			   config->supported_interfaces);
>  
> +	/* Update supported interfaces */
> +	list_for_each_entry(pcs, &pl->pcs_list, list)
> +		phy_interface_or(pl->supported_interfaces,
> +				 pl->supported_interfaces,
> +				 pcs->supported_interfaces);

[Severity: High]
Does this loop mishandle the empty means all semantic for supported
interfaces?

The subsystem defines that an empty pcs->supported_interfaces mask means the
PCS supports all interfaces (as handled in phylink_validate_pcs_interface()).
However, OR-ing an empty bitmask into pl->supported_interfaces contributes
no interfaces at all.

Could this silently drop capabilities for generic PCSs that leave their
supported_interfaces empty?

[ ... ]

> @@ -1917,28 +2053,29 @@ struct phylink *phylink_create(struct phylink_config *config,
>  	phylink_validate(pl, pl->supported, &pl->link_config);
>  
>  	ret = phylink_parse_mode(pl, fwnode);
> -	if (ret < 0) {
> -		kfree(pl);
> -		return ERR_PTR(ret);
> -	}
> +	if (ret < 0)
> +		goto unlink_pcs_list;
>  
>  	if (pl->cfg_link_an_mode == MLO_AN_FIXED) {
>  		ret = phylink_parse_fixedlink(pl, fwnode);
> -		if (ret < 0) {
> -			kfree(pl);
> -			return ERR_PTR(ret);
> -		}
> +		if (ret < 0)
> +			goto unlink_pcs_list;
>  	}
>  
>  	pl->req_link_an_mode = pl->cfg_link_an_mode;
>  
>  	ret = phylink_register_sfp(pl, fwnode);
> -	if (ret < 0) {
> -		kfree(pl);
> -		return ERR_PTR(ret);
> -	}
> +	if (ret < 0)
> +		goto unlink_pcs_list;
>  
>  	return pl;
> +
> +unlink_pcs_list:
> +	list_for_each_entry(pcs, &pl->pcs_list, list)
> +		pcs->phylink = NULL;
> +free_pl:
> +	kfree(pl);
> +	return ERR_PTR(ret);
>  }

[Severity: High]
Does this error path leave dangling pointers to freed memory?

The loop clears pcs->phylink but fails to call list_del(&pcs->list) before
freeing pl. Because the phylink_pcs structures are long-lived and owned by the
MAC driver or provider, their list nodes are left pointing to the freed
pl->pcs_list memory.

If a driver retries initialization and provides the same PCS objects, could
this list corruption lead to a use-after-free crash during the list_add()
step?

[ ... ]

> @@ -2413,8 +2560,15 @@ void phylink_pcs_change(struct phylink_pcs *pcs, bool up)
>  {
>  	struct phylink *pl = pcs->phylink;
>  
> -	if (pl)
> -		phylink_link_changed(pl, up, "pcs");
> +	/*
> +	 * Ignore PCS link state change if the PCS is not
> +	 * attached to a phylink instance or the phylink
> +	 * instance is not currently using this PCS.
> +	 */
> +	if (!pl || READ_ONCE(pl->pcs) != pcs)
> +		return;
> +
> +	phylink_link_changed(pl, up, "pcs");
>  }

[Severity: High]
Is there a race condition here during phylink_destroy() that can cause a
use-after-free?

If an external PCS driver triggers an interrupt and calls phylink_pcs_change()
concurrently with phylink_destroy(), pl might be read as non-NULL before
phylink_destroy() unlinks the PCS and frees pl.

Without proper synchronization (like RCU or a lock), could the interrupt
handler be preempted, and subsequently dereference pl via READ_ONCE(pl->pcs)
after it has been freed?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260618125752.1223-1-ansuelsmth@gmail.com?part=2

^ permalink raw reply

* Re: [RFC PATCH net-next v8 04/12] net: pcs: implement Firmware node support for PCS driver
From: sashiko-bot @ 2026-06-19 14:11 UTC (permalink / raw)
  To: Christian Marangi; +Cc: robh, conor+dt, devicetree
In-Reply-To: <20260618125752.1223-5-ansuelsmth@gmail.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] The PCS provider framework lacks module reference counting, exposing consumers to Use-After-Free crashes during concurrent driver removal.
- [Medium] `fwnode_phylink_pcs_count()` silently truncates the PCS count on Device Tree errors instead of propagating them.
- [Low] Dead code and illogical condition in `fwnode_parse_pcsspec`.
--

commit 31d56c9668ba31e1d161e00a93f5481143830f95
Author: Christian Marangi <ansuelsmth@gmail.com>

net: pcs: implement Firmware node support for PCS driver

Implement the foundation of Firmware node support for PCS driver.
This implements a simple Provider API where a PCS driver can
expose multiple PCS with an xlate .get function.

> diff --git a/drivers/net/pcs/pcs.c b/drivers/net/pcs/pcs.c
> new file mode 100644
> index 0000000000000..0cc4daf7beeae
> --- /dev/null
> +++ b/drivers/net/pcs/pcs.c
[ ... ]
> +static int fwnode_parse_pcsspec(const struct fwnode_handle *fwnode,
> +				int index, const char *name,
> +				struct fwnode_reference_args *out_args)
> +{
> +	int ret;
> +
> +	if (!fwnode)
> +		return -EINVAL;
> +
> +	if (name) {
> +		index = fwnode_property_match_string(fwnode, "pcs-names",
> +						     name);
> +		if (index < 0)
> +			return index;
> +	}
> +
> +	ret = fwnode_property_get_reference_args(fwnode, "pcs-handle",
> +						 "#pcs-cells",
> +						 -1, index, out_args);
> +	if (ret || (name && index < 0))
> +		return ret;
> +
> +	return 0;
> +}

[Severity: Low]
Is the condition (name && index < 0) needed here? 

The earlier check:

	if (name) {
		index = fwnode_property_match_string(fwnode, "pcs-names",
						     name);
		if (index < 0)
			return index;
	}

already returns early if name is present and index is less than zero, so
index will always be >= 0 when we reach this final check.

[ ... ]
> +static struct phylink_pcs *
> +fwnode_pcs_get_from_pcsspec(struct fwnode_reference_args *pcsspec)
> +{
> +	struct fwnode_pcs_provider *provider;
> +	struct phylink_pcs *pcs = ERR_PTR(-ENODEV);
> +
> +	if (!pcsspec)
> +		return ERR_PTR(-EINVAL);
> +
> +	mutex_lock(&fwnode_pcs_mutex);
> +	list_for_each_entry(provider, &fwnode_pcs_providers, link) {
> +		if (provider->fwnode == pcsspec->fwnode) {
> +			pcs = provider->get(pcsspec, provider->data);
> +			if (!IS_ERR(pcs))
> +				break;
> +		}
> +	}
> +	mutex_unlock(&fwnode_pcs_mutex);
> +
> +	return pcs;
> +}

[Severity: High]
Is there a way to prevent the provider module from being unloaded while the
consumer is actively using the PCS?

It looks like this framework doesn't capture the module owner (e.g. by passing
THIS_MODULE to fwnode_pcs_add_provider) or use try_module_get() when handing
the pointer to the consumer in fwnode_pcs_get_from_pcsspec().

If a consumer calls fwnode_pcs_get() but hasn't yet linked the PCS to its
pl->pcs_list (meaning pcs->phylink is still NULL), and the provider unbinds
during this window, phylink_release_pcs() might act as a no-op. The provider
could free the PCS memory while the consumer still holds the pointer, leading
to a use-after-free crash.

[ ... ]
> +unsigned int fwnode_phylink_pcs_count(struct fwnode_handle *fwnode)
> +{
> +	struct fwnode_reference_args out_args;
> +	int index = 0;
> +	int ret;
> +
> +	while (true) {
> +		ret = fwnode_property_get_reference_args(fwnode, "pcs-handle",
> +							 "#pcs-cells",
> +							 -1, index, &out_args);
> +		/* We expect to reach an -ENOENT error while counting */
> +		if (ret)
> +			break;
> +
> +		fwnode_handle_put(out_args.fwnode);
> +		index++;
> +	}
> +
> +	return index;
> +}

[Severity: Medium]
Does this function silently truncate the count on malformed device tree nodes?

If fwnode_property_get_reference_args() returns a critical error like -EINVAL,
the loop breaks and returns the current index. Because the function returns an
unsigned int, negative error codes aren't propagated to the caller. 

Could this mask actual configuration errors and cause the MAC driver to proceed
with an incomplete PCS configuration instead of failing the probe?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260618125752.1223-1-ansuelsmth@gmail.com?part=4

^ permalink raw reply

* Re: [RFC PATCH net-next v8 08/12] of: property: fw_devlink: Add support for "pcs-handle"
From: sashiko-bot @ 2026-06-19 14:11 UTC (permalink / raw)
  To: Christian Marangi; +Cc: devicetree, conor+dt, robh
In-Reply-To: <20260618125752.1223-9-ansuelsmth@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] fwnode_property_get_reference_args() usage in newly added pcs.c causes -EINVAL on existing DTs due to lacking a cell count fallback.
--

commit 91acc7e182a01f5abd0ae44dd757caf24a80257a
Author: Christian Marangi <ansuelsmth@gmail.com>

of: property: fw_devlink: Add support for "pcs-handle"

Add support for parsing PCS binding so that fw_devlink can
enforce the dependency with Ethernet port.

> diff --git a/drivers/of/property.c b/drivers/of/property.c
> index 136946f8b746f..e6584a2f705d2 100644
> --- a/drivers/of/property.c
> +++ b/drivers/of/property.c
> @@ -1392,6 +1392,7 @@ DEFINE_SIMPLE_PROP(access_controllers, "access-controllers", "#access-controller
>  DEFINE_SIMPLE_PROP(pses, "pses", "#pse-cells")
>  DEFINE_SIMPLE_PROP(power_supplies, "power-supplies", NULL)
>  DEFINE_SIMPLE_PROP(mmc_pwrseq, "mmc-pwrseq", NULL)
> +DEFINE_SIMPLE_PROP(pcs_handle, "pcs-handle", "#pcs-cells")

[Severity: Medium]
While this fw_devlink integration correctly falls back to 0 cells (via
parse_prop_cells()) when #pcs-cells is missing, the newly added API in
drivers/net/pcs/pcs.c does not.

In drivers/net/pcs/pcs.c:fwnode_parse_pcsspec(), the fallback cell count is
hardcoded to -1:

	ret = fwnode_property_get_reference_args(fwnode, "pcs-handle",
						 "#pcs-cells",
						 -1, index, out_args);

Similarly, in drivers/net/pcs/pcs.c:fwnode_phylink_pcs_count():

		ret = fwnode_property_get_reference_args(fwnode, "pcs-handle",
							 "#pcs-cells",
							 -1, index, &out_args);

Passing -1 as the fallback cell count causes parsing to fail with -EINVAL on
existing devicetrees where the pcs-handle property points to a node without
#pcs-cells.

Could this create a regression for the pcs-handle binding, causing existing
MAC drivers that migrate to this new API to fail discovery of their PCS?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260618125752.1223-1-ansuelsmth@gmail.com?part=8

^ permalink raw reply

* Re: [PATCH v5 1/1] arm64: dts: add tqma9596la-mba95xxca
From: Frank Li @ 2026-06-19 14:10 UTC (permalink / raw)
  To: Alexander Stein
  Cc: Frank Li, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Geert Uytterhoeven, Magnus Damm, Markus Niebel, imx,
	linux-arm-kernel, devicetree, linux-kernel, linux,
	linux-renesas-soc
In-Reply-To: <20260619112434.1121610-1-alexander.stein@ew.tq-group.com>

On Fri, Jun 19, 2026 at 01:24:30PM +0200, Alexander Stein wrote:
> From: Markus Niebel <Markus.Niebel@ew.tq-group.com>
>
> This adds support for TQMa95xxLA modules, designed to be soldered
> on a carrier board. MBa95xxCA is a carrier reference board / starter kit
> design.
>
> There is a common device tree for all variants with e.g. reduced
> CPU core / feature count.
>
> Enable the external accessible PCIe controllers as host,
> add clocking and reset GPIO. While at it, add hogs for GPIO
> lines from the M.2 slots until M.2 connector driver is available.
>
> Signed-off-by: Markus Niebel <Markus.Niebel@ew.tq-group.com>
> Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
> ---
> Changes in v5:
> * Limit LPSPI4 max frequency
> * Replace PCIe M2 Key-E GPIO hogs with dedicated connector node
> * Fix PCIe clock configuration
>
> Changes in v4:
> * Fix LPSPI4 pad muxing and control
>
> Changes in v3:
> * Moved reserved-memory to board-lebel
> * Remove VPU reserved memory (unused for now)
> * Fix typo in connector comment
>
> Changes in v2:
> * removed useless regulator
> * added USB PD source configuration
> * Removed unused uart-has-rtscts properties (unused by LPUART)
> * Fixed RTS/CTS pullups in pinctrl
> * Added thermalzone on module
>
>  arch/arm64/boot/dts/freescale/Makefile        |   1 +
>  .../freescale/imx95-tqma9596la-mba95xxca.dts  | 963 ++++++++++++++++++
>  .../boot/dts/freescale/imx95-tqma9596la.dtsi  | 278 +++++
>  3 files changed, 1242 insertions(+)
>  create mode 100644 arch/arm64/boot/dts/freescale/imx95-tqma9596la-mba95xxca.dts
>  create mode 100644 arch/arm64/boot/dts/freescale/imx95-tqma9596la.dtsi
>
> diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
> index 8ddaab127ab9c..43e1dc51b11d7 100644
> --- a/arch/arm64/boot/dts/freescale/Makefile
> +++ b/arch/arm64/boot/dts/freescale/Makefile
> @@ -649,6 +649,7 @@ dtb-$(CONFIG_ARCH_MXC) += imx95-19x19-frdm-pro.dtb
>  dtb-$(CONFIG_ARCH_MXC) += imx95-aquila-clover.dtb
>  dtb-$(CONFIG_ARCH_MXC) += imx95-aquila-dev.dtb
>  dtb-$(CONFIG_ARCH_MXC) += imx95-toradex-smarc-dev.dtb
> +dtb-$(CONFIG_ARCH_MXC) += imx95-tqma9596la-mba95xxca.dtb
>  dtb-$(CONFIG_ARCH_MXC) += imx95-tqma9596sa-mb-smarc-2.dtb
>  dtb-$(CONFIG_ARCH_MXC) += imx95-var-dart-sonata.dtb
>  dtb-$(CONFIG_ARCH_MXC) += imx95-verdin-nonwifi-dahlia.dtb
...
> +
> +	ptn5110: usb-typec@50 {
> +		compatible = "nxp,ptn5110", "tcpci";
> +		reg = <0x50>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&pinctrl_typec>;
> +		interrupt-parent = <&gpio2>;
> +		interrupts = <28 IRQ_TYPE_LEVEL_LOW>;
> +
> +		typec_con: connector {
> +			compatible = "usb-c-connector";
> +			label = "X9";
> +			power-role = "source";
> +			data-role = "dual";
> +			source-pdos = <PDO_FIXED(5000, 500, PDO_FIXED_USB_COMM)>;
> +			self-powered;
> +
> +			port {
> +				typec_con_hs: endpoint {
> +					remote-endpoint = <&typec_hs>;
> +				};
> +			};
> +		};
> +	};
> +
> +	sensor_mb: temperature-sensor@1e {

please order by hex address value

> +		compatible = "nxp,se97b", "jedec,jc-42.4-temp";
> +		reg = <0x1e>;
> +	};
> +
...
> +		m2-keye-dev_bt-wake-hog {
> +			gpio-hog;
> +			gpios = <4 GPIO_ACTIVE_LOW>;
> +			input;
> +			line-name = "M2_KEYE_DEV_BT_WAKE#";
> +		};

Now Key E connector already be upstreamed.

Documentation/devicetree/bindings/connector/pcie-m2-e-connector.yaml,
which already define these gpios.

Frank


^ permalink raw reply

* Re: [PATCH v3 1/5] dt-bindings: iio: adc: Add ltc2378
From: Conor Dooley @ 2026-06-19 14:07 UTC (permalink / raw)
  To: Marcelo Schmitt
  Cc: Marcelo Schmitt, linux-iio, devicetree, linux-kernel, jic23,
	nuno.sa, Michael.Hennerich, dlechner, andy, robh, krzk+dt,
	conor+dt, pop.ioan-daniel
In-Reply-To: <ajU-_j1SWYbfjWla@debian-BULLSEYE-live-builder-AMD64>

[-- Attachment #1: Type: text/plain, Size: 6690 bytes --]

On Fri, Jun 19, 2026 at 10:07:10AM -0300, Marcelo Schmitt wrote:
> On 06/17, Conor Dooley wrote:
> > On Wed, Jun 17, 2026 at 02:14:32PM -0300, Marcelo Schmitt wrote:
> > > On 06/17, Conor Dooley wrote:
> > > > On Tue, Jun 16, 2026 at 11:03:11PM -0300, Marcelo Schmitt wrote:
> > > > > Document how to describe LTC2378-20 and similar ADCs in device tree.
> > > > > 
> > > > > Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
> > > > > ---
> > > > > Change log v2 -> v3:
> > > > > - Re-added device tree fallback compatibles for LTC2378 chips, now with options
> > > > >   to provide a single compatible string or a pair of single compatible string
> > > > >   plus a fallback string to a slower sample rate spec in case a driver for the
> > > > >   specific part is not found.
> > > > > 
> > > > >  .../bindings/iio/adc/adi,ltc2378.yaml         | 160 ++++++++++++++++++
> > > > >  MAINTAINERS                                   |   7 +
> > > > >  2 files changed, 167 insertions(+)
> > > > >  create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ltc2378.yaml
> > > > > 
> > > > > diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ltc2378.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ltc2378.yaml
> > > > > new file mode 100644
> > > > > index 000000000000..7d30a2cade8f
> > > > > --- /dev/null
> > > > > +++ b/Documentation/devicetree/bindings/iio/adc/adi,ltc2378.yaml
> > > > > @@ -0,0 +1,160 @@
> > > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > > > +%YAML 1.2
> > > > > +---
> > > > > +$id: http://devicetree.org/schemas/iio/adc/adi,ltc2378.yaml#
> > > > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > > > +
> > > > > +title: Analog Devices LTC2378 and similar Analog to Digital Converters
> > > > > +
> > > > > +maintainers:
> > > > > +  - Marcelo Schmitt <marcelo.schmitt@analog.com>
> > > > > +
> > > > > +description: |
> > > > > +  Analog Devices LTC2378 series of ADCs.
> > > > > +  Specifications can be found at:
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/233818fa.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/236416fa.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/236418f.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/236716fa.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/236718f.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/236816f.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/236818f.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/236918fa.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/237016fa.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/237616fa.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/237618fa.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/237620fb.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/237716fa.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/237718fa.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/237720fb.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/237816fa.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/237818fa.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/237820fb.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/237918fb.pdf
> > > > > +    https://www.analog.com/media/en/technical-documentation/data-sheets/238016fb.pdf
> > > > > +
> > > > > +$ref: /schemas/spi/spi-peripheral-props.yaml#
> > > > > +
> > > > > +properties:
> > > > > +  compatible:
> > > > > +    oneOf:
> > > > > +      # Single compatible string match.
> > > > > +      - enum:
> > > > > +          - adi,ltc2338-18
> > > > > +          - adi,ltc2364-16
> > > > > +          - adi,ltc2364-18
> > > > > +          - adi,ltc2367-16
> > > > > +          - adi,ltc2367-18
> > > > > +          - adi,ltc2368-16
> > > > > +          - adi,ltc2368-18
> > > > > +          - adi,ltc2369-18
> > > > > +          - adi,ltc2370-16
> > > > > +          - adi,ltc2376-16
> > > > > +          - adi,ltc2376-18
> > > > > +          - adi,ltc2376-20
> > > > > +          - adi,ltc2377-16
> > > > > +          - adi,ltc2377-18
> > > > > +          - adi,ltc2377-20
> > > > > +          - adi,ltc2378-16
> > > > > +          - adi,ltc2378-18
> > > > > +          - adi,ltc2378-20
> > > > > +          - adi,ltc2379-18
> > > > > +          - adi,ltc2380-16
> > > > > +
> > > > > +      # Low sample rate fallback for 16-bit unipolar sensors.
> > > > > +      - items:
> > > > > +          - enum:
> > > > > +              - adi,ltc2370-16 # 2 MSPS
> > > > > +              - adi,ltc2368-16 # 1 MSPS
> > > > > +              - adi,ltc2367-16 # 500 kSPS
> > > > > +          - const: adi,ltc2364-16 # fallback (250 kSPS)
> > > > 
> ...
> > > > What actually is the impact of the sample rate on the programming model?
> > > If the user tries to set a sample rate beyond the maximum supported, software
> > > can throw an error to indicate that.
> > 
> > I think you have misunderstood this. I was asking how the driver
> > interacts with the hardware. Do all devices come out of reset with the
> > minimum sampling rate? Or a per-device default rate? Do the faster
> > devices support all slower rates? If they do, do the registers have the
> > same meaning and the same value sets 2370-16 device to 1 MSPS as
> > 2368-16.
> 
> Ah, the sampling rate is indirectly dictated both by how fast the CNV pin is
> toggled and how fast SPI transfers run. Each rising edge of CNV starts a new
> ADC conversion. Software may take spi-max-frequency as default but it will also
> need to set a pace for CNV, and there is no default for that. The CNV pin may
> also toggled on demand (e.g. single-shot read) and so I'd say all devices
> support all slower sample rates. What software ought to do is orchestrate CNV
> and SPI transfers to meet the timing requirements. No configuration registers
> to be set.

I forget if I asked for other changes, but the compatible setup then is 
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* Re: [PATCH net-next v5 12/15] onsemi: s2500: Add driver support for TS2500 MAC-PHY
From: Uwe Kleine-König @ 2026-06-19 13:59 UTC (permalink / raw)
  To: Selvamani.Rajagopal
  Cc: Andrew Lunn, Piergiorgio Beruto, Heiner Kallweit, Russell King,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Andrew Lunn, Parthiban Veerasooran, Richard Cochran, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Simon Horman, Jonathan Corbet,
	Shuah Khan, netdev, linux-kernel, devicetree, linux-doc,
	Jerry Ray
In-Reply-To: <20260614-s2500-mac-phy-support-v5-12-89874b72f725@onsemi.com>

[-- Attachment #1: Type: text/plain, Size: 1190 bytes --]

On Sun, Jun 14, 2026 at 10:00:28AM -0700, Selvamani Rajagopal via B4 Relay wrote:
> +static const struct of_device_id s2500_of_match[] = {
> +	{ .compatible = "onnn,s2500" },
> +	{}

s/{}/{ }/

> +};
> +
> +static const struct spi_device_id s2500_ids[] = {
> +	{ "s2500" },
> +	{}
> +};

Please make this:

static const struct spi_device_id s2500_ids[] = {
	{ .name = "s2500" },
	{ }
};

> +MODULE_DEVICE_TABLE(spi, s2500_ids);
> +
> +static struct spi_driver s2500_driver = {
> +	.driver = {
> +		.name	= DRV_NAME,
> +		.of_match_table = s2500_of_match,
> +	},
> +	.probe		= s2500_probe,
> +	.remove		= s2500_remove,
> +	.id_table	= s2500_ids,

Tastes are different, but the idea to align = is usually screwed by
follow up patches. Here it's broken from the start. If you ask me: Use a
single space before each =.

> +};
> +
> +module_spi_driver(s2500_driver);

Usually there is no empty line between the driver struct and the macro
registering it.

> +
> +MODULE_AUTHOR("Piergiorgio Beruto <pier.beruto@onsemi.com>");
> +MODULE_AUTHOR("Selva Rajagopal <selvamani.rajagopal@onsemi.com>");
> +MODULE_DESCRIPTION("onsemi MACPHY ethernet driver");
> +MODULE_LICENSE("GPL");

Best regards
Uwe

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [RFC PATCH v3 3/5] iio: buffer: Extend DMAengine buffer interfaces to take extra sysfs attributes
From: Marcelo Schmitt @ 2026-06-19 13:57 UTC (permalink / raw)
  To: Nuno Sá
  Cc: David Lechner, Marcelo Schmitt, linux-iio, devicetree,
	linux-kernel, jic23, nuno.sa, Michael.Hennerich, andy, robh,
	krzk+dt, conor+dt, pop.ioan-daniel
In-Reply-To: <ajPJdoTgpw7Ndczh@nsa>

On 06/18, Nuno Sá wrote:
> On Wed, Jun 17, 2026 at 04:43:18PM -0500, David Lechner wrote:
> > On 6/16/26 9:03 PM, Marcelo Schmitt wrote:
> > > Some devices using DMAengine buffers are connected to extra hardware that
> > > allows setting how fast data is transferred to/from the buffer. However,
> > > those extra pieces of harwdware are external to the sensor chip such that
> > > supporting the transfer speed as a sensor property is a bit of an
> > > inaccuracy. Expand IIO DMAengine buffer interfaces to take arguments for
> > > extra sysfs attributes, enabling the transfer speed to be configured
> > > through the buffer interface.
> > 
> > This message is a bit confusing. It sounds like it is attempting to
> > control something about the DMA controller itself. But based on the
> > later patches, it looks like this is just so we can add arbitrary
> > sysfs attributes to the bufferX directory. And in this specific case,
> > a sampling_frequency attribute.
> 
> Agreed. Seems like rate control comes from the buffer.

For this series, that was the actual result. Since we already have extra
sysfs attributes for kfifo and for triggered buffers, I thought of trying it
wish DMAengine buffers as well. The intent is to decouple the sampling frequency
sysfs attributes (which depend on SPI offload and PWM availability) from the ADC
IIO device. And the reason for that is to avoid making the device driver
directly select SPI_OFFLOAD and/or depend on PWM because these devices can be
used without offloading.

> 
> > 
> > > 
> > > Signed-off-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
> > > ---
> > > New patch.
> > > 
> > > Now that I've come to this buffer "solution", I have pretty much convinced
> > > myself it would be better to instead have some sort of IIO trigger to control
> > > the signal source connected to SPI offloading trigger module.
> > > 
> > In the other chips with SPI offload we've done already, we just used
> > IIO_CHAN_INFO_SAMP_FREQ to control the SPI offload trigger rate.
> > Any reason why we can't do that here? In the original SPI offload
> > discussions, IIRC the general consensus was that adding a trigger
> > just to control that was overkill when I suggested the same.
> > 
> 
> I tend to agree with David. Even if we come to a conclusion that we
> can't use IIO_CHAN_INFO_SAMP_FREQ to control the trigger rate, I'm not
> really convinced sysfs interfaces on the buffer itself are the place for
> this.

I understand it might be odd and confusing to have the sampling freq attributes
in the buffer. Using IIO_CHAN_INFO_SAMP_FREQ shall also work for this device
so I'll probably switch to that. Though, an interesting point Jonathan made on
v2 was that some devices have sampling frequency controls natively (e.g. ad7173).
I wonder if having a trigger device would help with the SPI offload dependency
separation. We might avoid attribute name clashing for some devices as bonus.

Thanks,
Marcelo

^ permalink raw reply

* Re: [PATCH V11 4/9] iio: imu: inv_icm42607: Add I2C and SPI For icm42607
From: Uwe Kleine-König @ 2026-06-19 13:54 UTC (permalink / raw)
  To: Chris Morgan
  Cc: linux-iio, andy, nuno.sa, dlechner, jic23, jean-baptiste.maneyrol,
	linux-rockchip, devicetree, heiko, conor+dt, krzk+dt, robh,
	andriy.shevchenko, Chris Morgan
In-Reply-To: <20260610175455.19006-5-macroalpha82@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 462 bytes --]

Hello,

On Wed, Jun 10, 2026 at 12:54:48PM -0500, Chris Morgan wrote:
> +static const struct spi_device_id inv_icm42607_spi_id_table[] = {
> +	{
> +		.name = "icm42607",
> +		.driver_data = (kernel_ulong_t)&inv_icm42607_hw_data
> +	}, {
> +		.name = "icm42607p",
> +		.driver_data = (kernel_ulong_t)&inv_icm42607p_hw_data
> +	},
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(spi, inv_icm42607_spi_id_table);

Missing comma after the .driver_data lines.

Best regards
Uwe

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH 2/2] drm/solomon: Add SSD1351 OLED display driver
From: Uwe Kleine-König @ 2026-06-19 13:52 UTC (permalink / raw)
  To: Amit Barzilai
  Cc: maarten.lankhorst, mripard, tzimmermann, airlied, simona, javierm,
	robh, krzk+dt, conor+dt, dri-devel, devicetree, linux-kernel
In-Reply-To: <20260610164428.180091-3-amit.barzilai22@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 22175 bytes --]

On Wed, Jun 10, 2026 at 07:44:28PM +0300, Amit Barzilai wrote:
> Add a DRM/KMS driver for the Solomon SSD1351, a 128x128 65k-color RGB
> OLED controller driven over a 4-wire SPI bus (clock, data, chip-select
> and a Data/Command GPIO).
> 
> Unlike the monochrome and grayscale SSD13xx parts handled by the ssd130x
> driver, the SSD1351 has a native 16-bit RGB565 frame format, so the
> driver uploads pixels as RGB565 rather than down-converting to RGB332.
> Its command set (column/row range 0x15/0x75, write-RAM 0x5c) differs from
> MIPI DCS, so the generic mipi_dbi helpers cannot be reused for the pixel
> path and a small SPI command/data layer is implemented instead.
> 
> The driver advertises XRGB8888 to userspace and converts to big-endian
> RGB565 on flush via drm_fb_xrgb8888_to_rgb565be(), building on the GEM
> SHMEM and atomic modeset/shadow-plane helpers with damage-clipped partial
> updates. Panels wired with a BGR sub-pixel order are handled through the
> colour remap register.
> 
> Also add the DRM_SSD1351 Kconfig/Makefile entries and a MAINTAINERS
> record.
> 
> Assisted-by: Claude:claude-opus-4-8
> Signed-off-by: Amit Barzilai <amit.barzilai22@gmail.com>
> ---
>  MAINTAINERS                       |   7 +
>  drivers/gpu/drm/solomon/Kconfig   |  14 +
>  drivers/gpu/drm/solomon/Makefile  |   1 +
>  drivers/gpu/drm/solomon/ssd1351.c | 556 ++++++++++++++++++++++++++++++
>  4 files changed, 578 insertions(+)
>  create mode 100644 drivers/gpu/drm/solomon/ssd1351.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 8e80296449ba..1e2b662c5aed 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8377,6 +8377,13 @@ F:	Documentation/devicetree/bindings/display/solomon,ssd-common.yaml
>  F:	Documentation/devicetree/bindings/display/solomon,ssd13*.yaml
>  F:	drivers/gpu/drm/solomon/ssd130x*
>  
> +DRM DRIVER FOR SOLOMON SSD1351 OLED DISPLAYS
> +M:	Amit Barzilai <amit.barzilai22@gmail.com>
> +S:	Maintained
> +T:	git https://gitlab.freedesktop.org/drm/misc/kernel.git
> +F:	Documentation/devicetree/bindings/display/solomon,ssd1351.yaml
> +F:	drivers/gpu/drm/solomon/ssd1351.c
> +
>  DRM DRIVER FOR ST-ERICSSON MCDE
>  M:	Linus Walleij <linusw@kernel.org>
>  S:	Maintained
> diff --git a/drivers/gpu/drm/solomon/Kconfig b/drivers/gpu/drm/solomon/Kconfig
> index 400a6cab3a67..957dc36dc495 100644
> --- a/drivers/gpu/drm/solomon/Kconfig
> +++ b/drivers/gpu/drm/solomon/Kconfig
> @@ -30,3 +30,17 @@ config DRM_SSD130X_SPI
>  	  Say Y here if the SSD13xx OLED display is connected via SPI bus.
>  
>  	  If M is selected the module will be called ssd130x-spi.
> +
> +config DRM_SSD1351
> +	tristate "DRM support for Solomon SSD1351 OLED displays"
> +	depends on DRM && SPI && MMU
> +	select DRM_CLIENT_SELECTION
> +	select DRM_GEM_SHMEM_HELPER
> +	select DRM_KMS_HELPER
> +	help
> +	  DRM driver for the Solomon SSD1351 RGB565 color OLED controller
> +	  connected via 4-wire SPI. It drives up to a 128x128 65k-color
> +	  panel and uploads pixels in the controller's native RGB565
> +	  format, exposing a standard DRM/KMS device to userspace.
> +
> +	  If M is selected the module will be called ssd1351.
> diff --git a/drivers/gpu/drm/solomon/Makefile b/drivers/gpu/drm/solomon/Makefile
> index b5fc792257d7..35ca60e4cf36 100644
> --- a/drivers/gpu/drm/solomon/Makefile
> +++ b/drivers/gpu/drm/solomon/Makefile
> @@ -1,3 +1,4 @@
>  obj-$(CONFIG_DRM_SSD130X)	+= ssd130x.o
>  obj-$(CONFIG_DRM_SSD130X_I2C)	+= ssd130x-i2c.o
>  obj-$(CONFIG_DRM_SSD130X_SPI)	+= ssd130x-spi.o
> +obj-$(CONFIG_DRM_SSD1351)	+= ssd1351.o
> diff --git a/drivers/gpu/drm/solomon/ssd1351.c b/drivers/gpu/drm/solomon/ssd1351.c
> new file mode 100644
> index 000000000000..7c4a5c461afb
> --- /dev/null
> +++ b/drivers/gpu/drm/solomon/ssd1351.c
> @@ -0,0 +1,556 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * DRM driver for the Solomon SSD1351 RGB565 color OLED controller
> + *
> + * The SSD1351 drives up to a 128x128 65k-color OLED panel over a 4-wire
> + * SPI bus (clock, data, chip-select and a Data/Command GPIO). Unlike the
> + * monochrome and grayscale SSD13xx parts handled by the ssd130x driver,
> + * the SSD1351 has a native 16-bit RGB565 frame format, so this driver
> + * uploads pixels as RGB565 rather than down-converting to RGB332.
> + *
> + * The command set (column/row range 0x15/0x75, write-RAM 0x5c) differs
> + * from MIPI DCS, so the generic mipi_dbi helpers cannot be reused for the
> + * pixel path; a small SPI command/data layer is implemented here instead.
> + *
> + * Author: Amit Barzilai <amit.barzilai22@gmail.com>
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/gpio/consumer.h>
> +#include <linux/module.h>
> +#include <linux/property.h>
> +#include <linux/spi/spi.h>
> +
> +#include <drm/clients/drm_client_setup.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_damage_helper.h>
> +#include <drm/drm_atomic.h>
> +#include <drm/drm_drv.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_fbdev_shmem.h>
> +#include <drm/drm_format_helper.h>
> +#include <drm/drm_gem_atomic_helper.h>
> +#include <drm/drm_gem_shmem_helper.h>
> +#include <drm/drm_gem_framebuffer_helper.h>
> +#include <drm/drm_managed.h>
> +#include <drm/drm_modeset_helper.h>
> +#include <drm/drm_probe_helper.h>
> +#include <drm/drm_print.h>
> +#include <drm/drm_rect.h>
> +
> +#define SSD1351_WIDTH 128
> +#define SSD1351_HEIGHT 128
> +
> +/* Commands */
> +#define SSD1351_SET_COL_ADDRESS 0x15
> +#define SSD1351_WRITE_RAM 0x5c
> +#define SSD1351_SET_ROW_ADDRESS 0x75
> +#define SSD1351_SET_REMAP 0xa0
> +#define SSD1351_SET_START_LINE 0xa1
> +#define SSD1351_SET_DISPLAY_OFFSET 0xa2
> +#define SSD1351_SET_DISPLAY_NORMAL 0xa6
> +#define SSD1351_SET_FUNCTION 0xab
> +#define SSD1351_SET_DISPLAY_OFF 0xae
> +#define SSD1351_SET_DISPLAY_ON 0xaf
> +#define SSD1351_SET_PHASE_LENGTH 0xb1
> +#define SSD1351_SET_CLOCK_DIV 0xb3
> +#define SSD1351_SET_VSL 0xb4
> +#define SSD1351_SET_GPIO 0xb5
> +#define SSD1351_SET_PRECHARGE2 0xb6
> +#define SSD1351_SET_PRECHARGE 0xbb
> +#define SSD1351_SET_VCOMH 0xbe
> +#define SSD1351_SET_CONTRAST 0xc1
> +#define SSD1351_SET_CONTRAST_MASTER 0xc7
> +#define SSD1351_SET_MUX_RATIO 0xca
> +#define SSD1351_SET_COMMAND_LOCK 0xfd
> +
> +/* Re-map / Color Depth (command 0xa0) bits */
> +#define SSD1351_REMAP_COLUMN BIT(1) /* reverse column (SEG) order */
> +#define SSD1351_REMAP_COLOR_BGR BIT(2) /* swap sub-pixel color order */
> +#define SSD1351_REMAP_COM_SCAN BIT(4) /* reverse COM scan direction */
> +#define SSD1351_REMAP_COM_SPLIT BIT(5) /* odd/even COM split */
> +#define SSD1351_REMAP_65K BIT(6) /* 65k (RGB565) color depth */
> +
> +struct ssd1351_device {
> +	struct drm_device drm;
> +	struct spi_device *spi;
> +	struct gpio_desc *reset;
> +	struct gpio_desc *dc;
> +	u32 rotation;
> +
> +	/* Scratch buffer holding one frame of RGB565 pixels for SPI upload */
> +	u8 *tx_buf;
> +
> +	struct drm_plane plane;
> +	struct drm_crtc crtc;
> +	struct drm_encoder encoder;
> +	struct drm_connector connector;
> +};
> +
> +static struct ssd1351_device *drm_to_ssd1351(struct drm_device *drm)
> +{
> +	return container_of(drm, struct ssd1351_device, drm);
> +}
> +
> +/*
> + * SPI access. The D/C GPIO selects whether the bytes shifted out are
> + * interpreted as a command (low) or as data (high).
> + */
> +static int ssd1351_write_cmd(struct ssd1351_device *ssd1351, u8 cmd,
> +			     const u8 *params, size_t num)
> +{
> +	int ret;
> +
> +	gpiod_set_value_cansleep(ssd1351->dc, 0);
> +	ret = spi_write(ssd1351->spi, &cmd, 1);
> +	if (ret)
> +		return ret;
> +
> +	if (num) {
> +		gpiod_set_value_cansleep(ssd1351->dc, 1);
> +		ret = spi_write(ssd1351->spi, params, num);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/* Send a command followed by a fixed list of single-byte parameters. */
> +#define ssd1351_command(ssd1351, cmd, ...)                   \
> +	({                                                   \
> +		static const u8 _params[] = { __VA_ARGS__ }; \
> +		ssd1351_write_cmd((ssd1351), (cmd), _params, \
> +				  ARRAY_SIZE(_params));      \
> +	})
> +
> +static void ssd1351_reset(struct ssd1351_device *ssd1351)
> +{
> +	if (!ssd1351->reset)
> +		return;
> +
> +	/*
> +	 * Work in logical levels: 1 asserts reset, 0 releases it. The DT's
> +	 * GPIO_ACTIVE_LOW flag handles the physical inversion, so this pulse is
> +	 * correct regardless of how the board wires the RES# line.
> +	 */
> +	gpiod_set_value_cansleep(ssd1351->reset, 1);
> +	usleep_range(20, 1000);
> +	gpiod_set_value_cansleep(ssd1351->reset, 0);
> +	msleep(120);
> +}
> +
> +static int ssd1351_init_display(struct ssd1351_device *ssd1351)
> +{
> +	u8 remap = SSD1351_REMAP_65K | SSD1351_REMAP_COM_SPLIT |
> +		   SSD1351_REMAP_COLOR_BGR;
> +	int ret;
> +
> +	ssd1351_reset(ssd1351);
> +
> +	/* Unlock the controller and allow access to all command registers */
> +	ret = ssd1351_command(ssd1351, SSD1351_SET_COMMAND_LOCK, 0x12);
> +	if (ret)
> +		return ret;
> +	ret = ssd1351_command(ssd1351, SSD1351_SET_COMMAND_LOCK, 0xb1);
> +	if (ret)
> +		return ret;
> +
> +	ret = ssd1351_command(ssd1351, SSD1351_SET_DISPLAY_OFF);
> +	if (ret)
> +		return ret;
> +
> +	ret = ret ?: ssd1351_command(ssd1351, SSD1351_SET_CLOCK_DIV, 0xf1);
> +	ret = ret ?: ssd1351_command(ssd1351, SSD1351_SET_MUX_RATIO, 0x7f);
> +	ret = ret ?: ssd1351_command(ssd1351, SSD1351_SET_COL_ADDRESS, 0x00, 0x7f);
> +	ret = ret ?: ssd1351_command(ssd1351, SSD1351_SET_ROW_ADDRESS, 0x00, 0x7f);
> +	ret = ret ?: ssd1351_command(ssd1351, SSD1351_SET_START_LINE, 0x00);
> +	ret = ret ?: ssd1351_command(ssd1351, SSD1351_SET_DISPLAY_OFFSET, 0x00);
> +	ret = ret ?: ssd1351_command(ssd1351, SSD1351_SET_GPIO, 0x00);
> +	ret = ret ?: ssd1351_command(ssd1351, SSD1351_SET_FUNCTION, 0x01);
> +	ret = ret ?: ssd1351_command(ssd1351, SSD1351_SET_PHASE_LENGTH, 0x32);
> +	ret = ret ?: ssd1351_command(ssd1351, SSD1351_SET_VSL, 0xa0, 0xb5, 0x55);
> +	ret = ret ?: ssd1351_command(ssd1351, SSD1351_SET_PRECHARGE, 0x17);
> +	ret = ret ?: ssd1351_command(ssd1351, SSD1351_SET_VCOMH, 0x05);
> +	ret = ret ?: ssd1351_command(ssd1351, SSD1351_SET_CONTRAST, 0xc8, 0x80, 0xc8);
> +	ret = ret ?: ssd1351_command(ssd1351, SSD1351_SET_CONTRAST_MASTER, 0x0f);
> +	ret = ret ?: ssd1351_command(ssd1351, SSD1351_SET_PRECHARGE2, 0x01);
> +	ret = ret ?: ssd1351_command(ssd1351, SSD1351_SET_DISPLAY_NORMAL);
> +	if (ret)
> +		return ret;
> +
> +	/*
> +	 * Select 65k (RGB565) color depth and the orientation. 0 and 180 degrees
> +	 * are reached with the column/COM-scan mirror bits while keeping the
> +	 * controller in horizontal address-increment mode, which matches the
> +	 * row-major pixel data produced below. The hardware can also rotate by
> +	 * 90/270 via the vertical address-increment bit, but that transposes the
> +	 * upload and would require a transposing blit + window remap that this
> +	 * driver does not implement; such rotations are rejected at probe.
> +	 */
> +	if (ssd1351->rotation == 180)
> +		remap |= SSD1351_REMAP_COLUMN;
> +	else
> +		remap |= SSD1351_REMAP_COM_SCAN;
> +
> +	ret = ssd1351_write_cmd(ssd1351, SSD1351_SET_REMAP, &remap, 1);
> +	if (ret)
> +		return ret;
> +
> +	return ssd1351_command(ssd1351, SSD1351_SET_DISPLAY_ON);
> +}
> +
> +static void ssd1351_fb_blit_rect(struct ssd1351_device *ssd1351,
> +				 struct drm_framebuffer *fb,
> +				 const struct iosys_map *vmap,
> +				 struct drm_rect *rect,
> +				 struct drm_format_conv_state *fmtcnv_state)
> +{
> +	unsigned int width = drm_rect_width(rect);
> +	unsigned int height = drm_rect_height(rect);
> +	unsigned int dst_pitch = width * sizeof(u16);
> +	struct iosys_map dst;
> +	u8 range[2];
> +
> +	iosys_map_set_vaddr(&dst, ssd1351->tx_buf);
> +
> +	/*
> +	 * The panel expects RGB565 most-significant byte first; the big-endian
> +	 * conversion produces exactly that byte stream for the 8-bit SPI words.
> +	 */
> +	drm_fb_xrgb8888_to_rgb565be(&dst, &dst_pitch, vmap, fb, rect,
> +				    fmtcnv_state);
> +
> +	range[0] = rect->x1;
> +	range[1] = rect->x2 - 1;
> +	if (ssd1351_write_cmd(ssd1351, SSD1351_SET_COL_ADDRESS, range,
> +			      sizeof(range)))
> +		return;
> +
> +	range[0] = rect->y1;
> +	range[1] = rect->y2 - 1;
> +	if (ssd1351_write_cmd(ssd1351, SSD1351_SET_ROW_ADDRESS, range,
> +			      sizeof(range)))
> +		return;
> +
> +	ssd1351_write_cmd(ssd1351, SSD1351_WRITE_RAM, ssd1351->tx_buf,
> +			  width * height * sizeof(u16));
> +}
> +
> +/*
> + * Plane
> + */
> +
> +static int ssd1351_plane_atomic_check(struct drm_plane *plane,
> +				      struct drm_atomic_state *state)
> +{
> +	struct drm_plane_state *plane_state =
> +		drm_atomic_get_new_plane_state(state, plane);
> +	struct drm_crtc *crtc = plane_state->crtc;
> +	struct drm_crtc_state *crtc_state = NULL;
> +
> +	if (crtc)
> +		crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
> +
> +	return drm_atomic_helper_check_plane_state(plane_state, crtc_state,
> +						   DRM_PLANE_NO_SCALING,
> +						   DRM_PLANE_NO_SCALING, false,
> +						   false);
> +}
> +
> +static void ssd1351_plane_atomic_update(struct drm_plane *plane,
> +					struct drm_atomic_state *state)
> +{
> +	struct drm_plane_state *plane_state =
> +		drm_atomic_get_new_plane_state(state, plane);
> +	struct drm_plane_state *old_plane_state =
> +		drm_atomic_get_old_plane_state(state, plane);
> +	struct drm_shadow_plane_state *shadow_plane_state =
> +		to_drm_shadow_plane_state(plane_state);
> +	struct ssd1351_device *ssd1351 = drm_to_ssd1351(plane->dev);
> +	struct drm_framebuffer *fb = plane_state->fb;
> +	struct drm_atomic_helper_damage_iter iter;
> +	struct drm_rect damage;
> +	struct drm_rect dst_clip;
> +	int idx;
> +
> +	if (!fb)
> +		return;
> +
> +	if (!drm_dev_enter(&ssd1351->drm, &idx))
> +		return;
> +
> +	if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE))
> +		goto out_drm_dev_exit;
> +
> +	drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
> +	drm_atomic_for_each_plane_damage(&iter, &damage) {
> +		dst_clip = plane_state->dst;
> +
> +		if (!drm_rect_intersect(&dst_clip, &damage))
> +			continue;
> +
> +		ssd1351_fb_blit_rect(ssd1351, fb, &shadow_plane_state->data[0],
> +				     &dst_clip,
> +				     &shadow_plane_state->fmtcnv_state);
> +	}
> +
> +	drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
> +
> +out_drm_dev_exit:
> +	drm_dev_exit(idx);
> +}
> +
> +static const struct drm_plane_helper_funcs ssd1351_plane_helper_funcs = {
> +	DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
> +	.atomic_check = ssd1351_plane_atomic_check,
> +	.atomic_update = ssd1351_plane_atomic_update,
> +};
> +
> +static const struct drm_plane_funcs ssd1351_plane_funcs = {
> +	DRM_GEM_SHADOW_PLANE_FUNCS,
> +	.update_plane = drm_atomic_helper_update_plane,
> +	.disable_plane = drm_atomic_helper_disable_plane,
> +	.destroy = drm_plane_cleanup,
> +};
> +
> +static const u32 ssd1351_formats[] = {
> +	DRM_FORMAT_XRGB8888,
> +};
> +
> +/*
> + * CRTC
> + */
> +
> +static void ssd1351_crtc_atomic_enable(struct drm_crtc *crtc,
> +				       struct drm_atomic_state *state)
> +{
> +	struct ssd1351_device *ssd1351 = drm_to_ssd1351(crtc->dev);
> +	int idx, ret;
> +
> +	if (!drm_dev_enter(crtc->dev, &idx))
> +		return;
> +
> +	ret = ssd1351_init_display(ssd1351);
> +	if (ret)
> +		drm_err(crtc->dev, "Failed to initialize display: %d\n", ret);
> +
> +	drm_dev_exit(idx);
> +}
> +
> +static void ssd1351_crtc_atomic_disable(struct drm_crtc *crtc,
> +					struct drm_atomic_state *state)
> +{
> +	struct ssd1351_device *ssd1351 = drm_to_ssd1351(crtc->dev);
> +	int idx;
> +
> +	if (!drm_dev_enter(crtc->dev, &idx))
> +		return;
> +
> +	ssd1351_command(ssd1351, SSD1351_SET_DISPLAY_OFF);
> +
> +	drm_dev_exit(idx);
> +}
> +
> +static const struct drm_crtc_helper_funcs ssd1351_crtc_helper_funcs = {
> +	.atomic_check = drm_crtc_helper_atomic_check,
> +	.atomic_enable = ssd1351_crtc_atomic_enable,
> +	.atomic_disable = ssd1351_crtc_atomic_disable,
> +};
> +
> +static const struct drm_crtc_funcs ssd1351_crtc_funcs = {
> +	.reset = drm_atomic_helper_crtc_reset,
> +	.destroy = drm_crtc_cleanup,
> +	.set_config = drm_atomic_helper_set_config,
> +	.page_flip = drm_atomic_helper_page_flip,
> +	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
> +};
> +
> +/*
> + * Encoder
> + */
> +
> +static const struct drm_encoder_funcs ssd1351_encoder_funcs = {
> +	.destroy = drm_encoder_cleanup,
> +};
> +
> +/*
> + * Connector
> + */
> +
> +static const struct drm_display_mode ssd1351_mode = {
> +	DRM_SIMPLE_MODE(SSD1351_WIDTH, SSD1351_HEIGHT, 24, 24),
> +};
> +
> +static int ssd1351_connector_get_modes(struct drm_connector *connector)
> +{
> +	return drm_connector_helper_get_modes_fixed(connector, &ssd1351_mode);
> +}
> +
> +static const struct drm_connector_helper_funcs ssd1351_connector_helper_funcs = {
> +	.get_modes = ssd1351_connector_get_modes,
> +};
> +
> +static const struct drm_connector_funcs ssd1351_connector_funcs = {
> +	.reset = drm_atomic_helper_connector_reset,
> +	.fill_modes = drm_helper_probe_single_connector_modes,
> +	.destroy = drm_connector_cleanup,
> +	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
> +	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
> +};
> +
> +static const struct drm_mode_config_funcs ssd1351_mode_config_funcs = {
> +	.fb_create = drm_gem_fb_create_with_dirty,
> +	.atomic_check = drm_atomic_helper_check,
> +	.atomic_commit = drm_atomic_helper_commit,
> +};
> +
> +/*
> + * Driver
> + */
> +
> +DEFINE_DRM_GEM_FOPS(ssd1351_fops);
> +
> +static const struct drm_driver ssd1351_driver = {
> +	.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
> +	.fops = &ssd1351_fops,
> +	DRM_GEM_SHMEM_DRIVER_OPS,
> +	DRM_FBDEV_SHMEM_DRIVER_OPS,
> +	.name = "ssd1351",
> +	.desc = "Solomon SSD1351",
> +	.major = 1,
> +	.minor = 0,
> +};
> +
> +static int ssd1351_probe(struct spi_device *spi)
> +{
> +	struct device *dev = &spi->dev;
> +	struct ssd1351_device *ssd1351;
> +	struct drm_device *drm;
> +	int ret;
> +
> +	ssd1351 = devm_drm_dev_alloc(dev, &ssd1351_driver,
> +				     struct ssd1351_device, drm);
> +	if (IS_ERR(ssd1351))
> +		return PTR_ERR(ssd1351);
> +
> +	drm = &ssd1351->drm;
> +	ssd1351->spi = spi;
> +	spi_set_drvdata(spi, drm);
> +
> +	ssd1351->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
> +	if (IS_ERR(ssd1351->reset))
> +		return dev_err_probe(dev, PTR_ERR(ssd1351->reset),
> +				     "Failed to get reset GPIO\n");
> +
> +	ssd1351->dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW);
> +	if (IS_ERR(ssd1351->dc))
> +		return dev_err_probe(dev, PTR_ERR(ssd1351->dc),
> +				     "Failed to get D/C GPIO\n");
> +
> +	device_property_read_u32(dev, "rotation", &ssd1351->rotation);
> +	if (ssd1351->rotation != 0 && ssd1351->rotation != 180)
> +		return dev_err_probe(dev, -EINVAL,
> +				     "Unsupported rotation %u; only 0 and 180 are supported\n",
> +				     ssd1351->rotation);
> +
> +	ssd1351->tx_buf = devm_kmalloc(dev,
> +				       SSD1351_WIDTH * SSD1351_HEIGHT * sizeof(u16),
> +				       GFP_KERNEL);
> +	if (!ssd1351->tx_buf)
> +		return -ENOMEM;
> +
> +	ret = drmm_mode_config_init(drm);
> +	if (ret)
> +		return ret;
> +
> +	drm->mode_config.min_width = SSD1351_WIDTH;
> +	drm->mode_config.max_width = SSD1351_WIDTH;
> +	drm->mode_config.min_height = SSD1351_HEIGHT;
> +	drm->mode_config.max_height = SSD1351_HEIGHT;
> +	drm->mode_config.preferred_depth = 24;
> +	drm->mode_config.funcs = &ssd1351_mode_config_funcs;
> +
> +	ret = drm_universal_plane_init(drm, &ssd1351->plane, 0,
> +				       &ssd1351_plane_funcs, ssd1351_formats,
> +				       ARRAY_SIZE(ssd1351_formats), NULL,
> +				       DRM_PLANE_TYPE_PRIMARY, NULL);
> +	if (ret)
> +		return ret;
> +	drm_plane_helper_add(&ssd1351->plane, &ssd1351_plane_helper_funcs);
> +	drm_plane_enable_fb_damage_clips(&ssd1351->plane);
> +
> +	ret = drm_crtc_init_with_planes(drm, &ssd1351->crtc, &ssd1351->plane,
> +					NULL, &ssd1351_crtc_funcs, NULL);
> +	if (ret)
> +		return ret;
> +	drm_crtc_helper_add(&ssd1351->crtc, &ssd1351_crtc_helper_funcs);
> +
> +	ret = drm_encoder_init(drm, &ssd1351->encoder, &ssd1351_encoder_funcs,
> +			       DRM_MODE_ENCODER_NONE, NULL);
> +	if (ret)
> +		return ret;
> +	ssd1351->encoder.possible_crtcs = drm_crtc_mask(&ssd1351->crtc);
> +
> +	ret = drm_connector_init(drm, &ssd1351->connector,
> +				 &ssd1351_connector_funcs,
> +				 DRM_MODE_CONNECTOR_SPI);
> +	if (ret)
> +		return ret;
> +	drm_connector_helper_add(&ssd1351->connector,
> +				 &ssd1351_connector_helper_funcs);
> +
> +	ret = drm_connector_attach_encoder(&ssd1351->connector,
> +					   &ssd1351->encoder);
> +	if (ret)
> +		return ret;
> +
> +	drm_mode_config_reset(drm);
> +
> +	ret = drm_dev_register(drm, 0);
> +	if (ret)
> +		return ret;
> +
> +	drm_client_setup(drm, NULL);
> +
> +	return 0;
> +}
> +
> +static void ssd1351_remove(struct spi_device *spi)
> +{
> +	struct drm_device *drm = spi_get_drvdata(spi);
> +
> +	drm_dev_unplug(drm);
> +	drm_atomic_helper_shutdown(drm);
> +}
> +
> +static void ssd1351_shutdown(struct spi_device *spi)
> +{
> +	drm_atomic_helper_shutdown(spi_get_drvdata(spi));
> +}
> +
> +static const struct of_device_id ssd1351_of_match[] = {
> +	{ .compatible = "solomon,ssd1351" },
> +	{}

s/{}/{ }/ to match the most used style.

> +};
> +MODULE_DEVICE_TABLE(of, ssd1351_of_match);
> +
> +static const struct spi_device_id ssd1351_id[] = { { "ssd1351", 0 }, {} };

Please make this:

static const struct spi_device_id ssd1351_id[] = {
	{ .name = "ssd1351" },
	{ }
};

Best regards
Uwe

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH v5 2/2] leds: ltc3208: Add driver for LTC3208 Multidisplay LED Driver
From: Uwe Kleine-König @ 2026-06-19 13:49 UTC (permalink / raw)
  To: Jan Carlo Roleda
  Cc: Lee Jones, Pavel Machek, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-kernel, linux-leds, devicetree
In-Reply-To: <20260619-upstream-ltc3208-v5-2-075d18060606@analog.com>

[-- Attachment #1: Type: text/plain, Size: 4568 bytes --]

On Fri, Jun 19, 2026 at 06:45:09AM +0800, Jan Carlo Roleda wrote:
> [...]
> +static int ltc3208_probe(struct i2c_client *client)
> +{
> +	enum ltc3208_aux_channel aux_channels[LTC3208_NUM_AUX_LEDS];
> +	struct ltc3208 *ddata;
> +	struct regmap *regmap;
> +	bool disable_rgb_aux4_dropout_signal;
> +	bool disable_camhl_pin;
> +	bool set_sub_control_pin;
> +	int ret;
> +	u8 reg_val;
> +
> +	regmap = devm_regmap_init_i2c(client, &ltc3208_regmap_cfg);
> +	if (IS_ERR(regmap))
> +		return dev_err_probe(&client->dev, PTR_ERR(regmap),
> +				     "Failed to initialize regmap\n");
> +
> +	ddata = devm_kzalloc(&client->dev, sizeof(*ddata), GFP_KERNEL);
> +	if (!ddata)
> +		return -ENOMEM;
> +
> +	ddata->regmap = regmap;
> +
> +	disable_camhl_pin = device_property_read_bool(&client->dev,
> +						      "adi,disable-camhl-pin");
> +	set_sub_control_pin =
> +		device_property_read_bool(&client->dev, "adi,cfg-enrgbs-pin");
> +	disable_rgb_aux4_dropout_signal = device_property_read_bool(
> +		&client->dev, "adi,disable-rgb-aux4-dropout");

Unusual line break. I'd write that as:

	disable_rgb_aux4_dropout_signal =
		device_property_read_bool(&client->dev,
					  "adi,disable-rgb-aux4-dropout");


> +
> +	reg_val = FIELD_PREP(LTC3208_OPT_EN_RGBS, set_sub_control_pin) |
> +		  FIELD_PREP(LTC3208_OPT_DIS_CAMHILO, disable_camhl_pin) |
> +		  FIELD_PREP(LTC3208_OPT_DIS_RGBDROP,
> +			     disable_rgb_aux4_dropout_signal);
> +
> +	ret = regmap_write(regmap, LTC3208_REG_G_OPT, reg_val);
> +	if (ret)
> +		return dev_err_probe(&client->dev, ret,
> +				     "error writing to options register\n");
> +
> +	/* Initialize aux channel configurations */
> +	for (int i = 0; i < LTC3208_NUM_AUX_LEDS; i++) {
> +		ret = device_property_match_property_string(
> +			&client->dev, ltc3208_dt_aux_channels[i],
> +			ltc3208_aux_opt, LTC3208_NUM_AUX_OPT);
> +		/* Fallback to default value (AUX) if not found */
> +		if (ret == -EINVAL)
> +			aux_channels[i] = LTC3208_AUX_CHAN_AUX;
> +		else if (ret >= 0)
> +			aux_channels[i] = ret;
> +	}
> +
> +	reg_val = FIELD_PREP(LTC3208_AUX1_MASK, aux_channels[0]) |
> +		  FIELD_PREP(LTC3208_AUX2_MASK, aux_channels[1]) |
> +		  FIELD_PREP(LTC3208_AUX3_MASK, aux_channels[2]) |
> +		  FIELD_PREP(LTC3208_AUX4_MASK, aux_channels[3]);
> +
> +	ret = regmap_write(regmap, LTC3208_REG_E_AUX_SELECT, reg_val);
> +	if (ret)
> +		return dev_err_probe(&client->dev, ret,
> +			"error writing to aux channel register.\n");
> +
> +	i2c_set_clientdata(client, ddata);

From a quick glance, this is unused.

> +	device_for_each_child_node_scoped(&client->dev, child) {
> +		struct ltc3208_led *led;
> +		struct led_init_data init_data = {};
> +		u32 chan;
> +
> +		ret = fwnode_property_read_u32(child, "reg", &chan);
> +		if (ret)
> +			return dev_err_probe(&client->dev, ret,
> +					    "Failed to get reg value of LED\n");
> +		else if (chan >= LTC3208_NUM_LED_GRPS)
> +			return dev_err_probe(&client->dev, ret,
> +					     "%d is an invalid LED ID\n", chan);
> +
> +		led = &ddata->leds[chan];
> +
> +		led->rfield =
> +			devm_regmap_field_alloc(&client->dev, ddata->regmap,
> +						ltc3208_led_reg_field[chan]);
> +		if (IS_ERR(led->rfield))
> +			return dev_err_probe(&client->dev, PTR_ERR(led->rfield),
> +					     "cannot allocate regmap field\n");
> +		led->client = client;
> +		led->channel = chan;
> +		led->cdev.brightness_set_blocking = ltc3208_led_set_brightness;
> +		led->cdev.max_brightness = LTC3208_MAX_BRIGHTNESS_4BIT;
> +
> +		if (chan == LTC3208_CHAN_MAIN || chan == LTC3208_CHAN_SUB)
> +			led->cdev.max_brightness = LTC3208_MAX_BRIGHTNESS_8BIT;
> +
> +		init_data.fwnode = child;
> +
> +		ret = devm_led_classdev_register_ext(&client->dev, &led->cdev,
> +						     &init_data);
> +		if (ret)
> +			return dev_err_probe(&client->dev, ret,
> +					     "LED %u Register failed.\n", chan);
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id ltc3208_match_table[] = {
> +	{.compatible = "adi,ltc3208"},
> +	{}
> +};

Please make this:

static const struct of_device_id ltc3208_match_table[] = {
	{ .compatible = "adi,ltc3208" },
	{ }
};


> +MODULE_DEVICE_TABLE(of, ltc3208_match_table);
> +
> +static const struct i2c_device_id ltc3208_idtable[] = {
> +	{ "ltc3208" },
> +	{}
> +};

Please make this:

static const struct i2c_device_id ltc3208_idtable[] = {
	{ .name = "ltc3208" },
	{ }
};

> +MODULE_DEVICE_TABLE(i2c, ltc3208_idtable);

Best regards
Uwe

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH v5 3/3] regulator: Add regulator driver for Unisoc SC2730 PMIC
From: Uwe Kleine-König @ 2026-06-19 13:42 UTC (permalink / raw)
  To: Otto Pflüger
  Cc: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Orson Zhai, Baolin Wang, Chunyan Zhang, Lee Jones,
	linux-kernel, devicetree, Zhongfa Wang
In-Reply-To: <20260619-sc2730-regulators-v5-3-0a24c7ed7a97@abscue.de>

[-- Attachment #1: Type: text/plain, Size: 1436 bytes --]

Hello Otto,

On Fri, Jun 19, 2026 at 01:41:49PM +0200, Otto Pflüger wrote:
> +static int sc2730_regulator_probe(struct platform_device *pdev)
> +{
> +	int i, ret;
> +	struct regmap *regmap;
> +	struct regulator_config config = { };
> +	struct regulator_dev *rdev;
> +
> +	regmap = dev_get_regmap(pdev->dev.parent, NULL);
> +	if (!regmap) {
> +		dev_err(&pdev->dev, "failed to get regmap.\n");
> +		return -ENODEV;
> +	}
> +
> +	ret = sc2730_regulator_unlock(regmap);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to release regulator lock\n");
> +		return ret;
> +	}

This can be shortend (and improved) to:

	if (ret)
		return dev_err_probe(&pdev->dev, ret, "failed to release regulator lock\n");

ditto for the other error messages in .probe().

> +
> +	config.dev = pdev->dev.parent;
> +	config.regmap = regmap;
> +
> +	for (i = 0; i < ARRAY_SIZE(regulators); i++) {
> +		rdev = devm_regulator_register(&pdev->dev, &regulators[i], &config);
> +		if (IS_ERR(rdev)) {
> +			dev_err(&pdev->dev, "failed to register regulator %s\n",
> +				regulators[i].name);
> +			return PTR_ERR(rdev);
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct platform_device_id sc2730_regulator_id_table[] = {
> +	{ "sc2730-regulator" },

Please make this

	{ .name = "sc2730-regulator" },

> +	{ }
> +};
> +MODULE_DEVICE_TABLE(platform, sc2730_regulator_id_table);

Best regards
Uwe

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* [PATCH v2 2/2] arm: dts: xilinx: Add support for MYIR MYS-7Z020-V2 board
From: Liu Yu @ 2026-06-19 13:23 UTC (permalink / raw)
  To: Michal Simek
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, devicetree,
	linux-arm-kernel, Liu Yu
In-Reply-To: <20260619132355.1776-1-f78fk@live.com>

Add device tree support for the MYIR MYS-7Z020-V2 board based on
the Xilinx Zynq-7000 XC7Z020 SoC.

The board supports:
- UART serial console
- MicroSD card interface
- Gigabit Ethernet
- QSPI NOR flash
- GPIO-based user LEDs and push-button

Link: https://www.myirtech.com/list.asp?id=708

Signed-off-by: Liu Yu <f78fk@live.com>
---
 arch/arm/boot/dts/xilinx/Makefile             |   1 +
 .../arm/boot/dts/xilinx/zynq-mys-7z020-v2.dts | 232 ++++++++++++++++++
 2 files changed, 233 insertions(+)
 create mode 100644 arch/arm/boot/dts/xilinx/zynq-mys-7z020-v2.dts

diff --git a/arch/arm/boot/dts/xilinx/Makefile b/arch/arm/boot/dts/xilinx/Makefile
index 9233e539b192..6c59116013f1 100644
--- a/arch/arm/boot/dts/xilinx/Makefile
+++ b/arch/arm/boot/dts/xilinx/Makefile
@@ -3,6 +3,7 @@ dtb-$(CONFIG_ARCH_ZYNQ) += \
 	zynq-cc108.dtb \
 	zynq-ebaz4205.dtb \
 	zynq-microzed.dtb \
+	zynq-mys-7z020-v2.dtb \
 	zynq-parallella.dtb \
 	zynq-zc702.dtb \
 	zynq-zc706.dtb \
diff --git a/arch/arm/boot/dts/xilinx/zynq-mys-7z020-v2.dts b/arch/arm/boot/dts/xilinx/zynq-mys-7z020-v2.dts
new file mode 100644
index 000000000000..b55133133e2f
--- /dev/null
+++ b/arch/arm/boot/dts/xilinx/zynq-mys-7z020-v2.dts
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2026 Liu Yu <f78fk@live.com>
+ */
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "zynq-7000.dtsi"
+
+/ {
+	model = "MYIR MYS-7Z020-V2 Board";
+	compatible = "myir,mys-7z020-v2", "xlnx,zynq-7000";
+
+	aliases {
+		ethernet0 = &gem0;
+		mmc0 = &sdhci0;
+		serial0 = &uart1;
+		spi0 = &qspi;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		autorepeat;
+
+		key-user {
+			label = "USR";
+			gpios = <&gpio0 50 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_PROG1>;
+			wakeup-source;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		led-blue {
+			label = "led_blue";
+			gpios = <&gpio0 115 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		led-green {
+			label = "led_green";
+			gpios = <&gpio0 114 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		led-red {
+			label = "led_red";
+			gpios = <&gpio0 116 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		usr-led1 {
+			label = "usr_led1";
+			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+
+		usr-led2 {
+			label = "usr_led2";
+			gpios = <&gpio0 9 GPIO_ACTIVE_LOW>;
+			default-state = "off";
+		};
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x40000000>;
+	};
+};
+
+&clkc {
+	ps-clk-frequency = <33333333>;
+};
+
+&gem0 {
+	phy-mode = "rgmii-id";
+	phy-handle = <&ethernet_phy>;
+
+	status = "okay";
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethernet_phy: ethernet-phy@7 {
+			reg = <0x7>;
+		};
+	};
+};
+
+&gpio0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpio0_default>;
+};
+
+&pinctrl0 {
+	pinctrl_gpio0_default: gpio0-default {
+		mux {
+			function = "gpio0";
+			groups = "gpio0_0_grp", "gpio0_9_grp", "gpio0_50_grp";
+		};
+		conf {
+			groups = "gpio0_0_grp", "gpio0_9_grp", "gpio0_50_grp";
+			slew-rate = <0>;
+			io-standard = <1>;
+		};
+		conf-pull-up {
+			pins = "MIO0", "MIO9", "MIO50";
+			bias-pull-up;
+		};
+	};
+
+	pinctrl_sdhci0_default: sdhci0-default {
+		mux {
+			groups = "sdio0_2_grp";
+			function = "sdio0";
+		};
+		mux-cd {
+			groups = "gpio0_46_grp";
+			function = "sdio0_cd";
+		};
+		conf {
+			groups = "sdio0_2_grp";
+			slew-rate = <0>;
+			io-standard = <1>;
+			bias-disable;
+		};
+		conf-cd {
+			pins = "MIO46";
+			bias-pull-up;
+			slew-rate = <0>;
+			io-standard = <1>;
+		};
+	};
+
+	pinctrl_uart1_default: uart1-default {
+		mux {
+			groups = "uart1_10_grp";
+			function = "uart1";
+		};
+		conf {
+			groups = "uart1_10_grp";
+			slew-rate = <0>;
+			io-standard = <1>;
+		};
+		conf-rx {
+			pins = "MIO49";
+			bias-high-impedance;
+		};
+		conf-tx {
+			pins = "MIO48";
+			bias-disable;
+		};
+	};
+};
+
+&qspi {
+	num-cs = <1>;
+
+	status = "okay";
+
+	flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <50000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "qspi-boot";
+				reg = <0x0 0x80000>;
+			};
+
+			partition@80000 {
+				label = "qspi-bootenv";
+				reg = <0x80000 0x20000>;
+			};
+
+			partition@a0000 {
+				label = "qspi-bitstream";
+				reg = <0xa0000 0x460000>;
+			};
+
+			partition@500000 {
+				label = "qspi-kernel";
+				reg = <0x500000 0x480000>;
+			};
+
+			partition@980000 {
+				label = "qspi-devicetree";
+				reg = <0x980000 0x10000>;
+			};
+
+			partition@990000 {
+				label = "qspi-rootfs";
+				reg = <0x990000 0x600000>;
+			};
+
+			partition@f90000 {
+				label = "data";
+				reg = <0xf90000 0x70000>;
+			};
+		};
+	};
+};
+
+&sdhci0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhci0_default>;
+	disable-wp;
+
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_default>;
+
+	status = "okay";
+};
+
-- 
2.43.0


^ permalink raw reply related

* [PATCH v2 1/2] dt-bindings: soc: xilinx: Add MYIR MYS-7Z020-V2 board
From: Liu Yu @ 2026-06-19 13:23 UTC (permalink / raw)
  To: Michal Simek
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, devicetree,
	linux-arm-kernel, Liu Yu
In-Reply-To: <20260619132355.1776-1-f78fk@live.com>

Add compatible string for the MYIR MYS-7Z020-V2 board, based on
the Xilinx Zynq-7000 XC7Z020 SoC.

Signed-off-by: Liu Yu <f78fk@live.com>
---
 Documentation/devicetree/bindings/soc/xilinx/xilinx.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/soc/xilinx/xilinx.yaml b/Documentation/devicetree/bindings/soc/xilinx/xilinx.yaml
index c9f99e0df2b3..72a84b628da3 100644
--- a/Documentation/devicetree/bindings/soc/xilinx/xilinx.yaml
+++ b/Documentation/devicetree/bindings/soc/xilinx/xilinx.yaml
@@ -23,6 +23,7 @@ properties:
               - digilent,zynq-zybo
               - digilent,zynq-zybo-z7
               - ebang,ebaz4205
+              - myir,mys-7z020-v2
               - myir,zynq-zturn-v5
               - myir,zynq-zturn
               - xlnx,zynq-cc108
-- 
2.43.0


^ permalink raw reply related

* [PATCH v2 0/2] arm: dts: xilinx: Add MYIR MYS-7Z020-V2 board support
From: Liu Yu @ 2026-06-19 13:23 UTC (permalink / raw)
  To: Michal Simek
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, devicetree,
	linux-arm-kernel, Liu Yu
In-Reply-To: <20260619102214.223121-1-f78fk@live.com>

This series adds basic device tree and binding documentation support
for the MYIR MYS-7Z020-V2 development board, which is based on the
Xilinx Zynq-7000 (XC7Z020) SoC.

The first patch introduces the device tree file enabling essential
hardware support such as the serial console, MicroSD, Gigabit Ethernet,
QSPI flash, and user LEDs/buttons. The second patch adds the corresponding
compatible string to the Xilinx SoC bindings documentation.

Changes in v2:
  - Add missing pinmux configuration (sdio0_cd) for MIO46 to correctly
    route the hardware SD card detect signal, resolving the automated
    review warning.

Liu Yu (2):
  dt-bindings: soc: xilinx: Add MYIR MYS-7Z020-V2 board
  arm: dts: xilinx: Add support for MYIR MYS-7Z020-V2 board

 .../bindings/soc/xilinx/xilinx.yaml           |   1 +
 arch/arm/boot/dts/xilinx/Makefile             |   1 +
 .../arm/boot/dts/xilinx/zynq-mys-7z020-v2.dts | 232 ++++++++++++++++++
 3 files changed, 234 insertions(+)
 create mode 100644 arch/arm/boot/dts/xilinx/zynq-mys-7z020-v2.dts

-- 
2.43.0


^ permalink raw reply

* Re: [PATCH v3 1/5] dt-bindings: iio: adc: Add ltc2378
From: Marcelo Schmitt @ 2026-06-19 13:17 UTC (permalink / raw)
  To: David Lechner
  Cc: Marcelo Schmitt, linux-iio, devicetree, linux-kernel, jic23,
	nuno.sa, Michael.Hennerich, andy, robh, krzk+dt, conor+dt,
	pop.ioan-daniel
In-Reply-To: <76d39d2a-051d-4706-8433-3d3eb97e7f2a@baylibre.com>

On 06/17, David Lechner wrote:
> On 6/16/26 9:03 PM, Marcelo Schmitt wrote:
> > Document how to describe LTC2378-20 and similar ADCs in device tree.
> > 
> 
> ...
> 
> > +  vdd-supply:
> > +    description: A 2.5V supply that powers the chip (VDD).
> > +
> > +  ovdd-supply:
> > +    description:
> > +      A 1.71V to 5.25V supply that sets the logic level for digital interface.
> > +
> > +  ref-supply:
> > +    description:
> > +      A 2.5V to 5.1V supply for the reference input (REF).
> > +
> > +  cnv-gpios:
> > +    description:
> > +      When provided, this property indicates the GPIO that is connected to the
> > +      CNV pin.
> > +    maxItems: 1
> 
> Missing pwms property for when CNV pin is connected to PWM.

Ah, thanks for pointing that out. Will add that in v4.

> 
> > +
> > +  interrupts:
> > +    description:
> > +      Interrupt for signaling the completion of conversion results. The active
> > +      low signal provided on the BUSY pin asserts when ADC conversions finish.
> > +    maxItems: 1
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - vdd-supply
> > +  - ovdd-supply
> > +  - ref-supply
> 
> I only looked at LTC2338-18, but it has a REFIN, which is optional.
> Nothing named REF that is required.
> 
Hmm, I think that's the only device that has it differently. Will add allOf/if
properties to differentiate these.

Thanks,
Marcelo

^ permalink raw reply

* Re: [PATCH 1/2] arm64: dts: qcom: sc8280xp: Add camera MCLK pinctrl
From: Vladimir Zapolskiy @ 2026-06-19 13:16 UTC (permalink / raw)
  To: Konrad Dybcio, Pengyu Luo
  Cc: Bjorn Andersson, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <162da512-1142-48fa-bf7d-0b2393467a75@oss.qualcomm.com>

On 6/19/26 16:03, Konrad Dybcio wrote:
> On 6/19/26 2:59 PM, Vladimir Zapolskiy wrote:
>> On 6/19/26 15:35, Konrad Dybcio wrote:
>>> On 6/11/26 7:29 AM, Pengyu Luo wrote:
>>>> On Tue, Jun 9, 2026 at 8:17 PM Konrad Dybcio
>>>> <konrad.dybcio@oss.qualcomm.com> wrote:
>>>>>
>>>>> On 6/7/26 6:04 PM, Pengyu Luo wrote:
>>>>>> Define pinctrl definitions to enable camera master clocks on sc8280xp.
>>>>>>
>>>>>> Suggested-by: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
>>>>>> Signed-off-by: Pengyu Luo <mitltlatltl@gmail.com>
>>>>>> ---
>>>>>>    arch/arm64/boot/dts/qcom/sc8280xp.dtsi | 56 ++++++++++++++++++++++++++
>>>>>>    1 file changed, 56 insertions(+)
>>>>>>
>>>>>> diff --git a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
>>>>>> index a2bd6b10e475..0dbcd3069a3b 100644
>>>>>> --- a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
>>>>>> +++ b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
>>>>>> @@ -5484,6 +5484,62 @@ tlmm: pinctrl@f100000 {
>>>>>>                         gpio-ranges = <&tlmm 0 0 230>;
>>>>>>                         wakeup-parent = <&pdc>;
>>>>>>
>>>>>> +                     cam_mclk0_default: cam-mclk0-default-state {
>>>>>> +                             pins = "gpio119";
>>>>>> +                             function = "cam_mclk";
>>>>>> +                             drive-strength = <6>;
>>>>>
>>>>> Other platforms set this to 2 by default.
>>>>>
>>>>> What's the value set on Windows when the camera is in use?
>>>>>
>>>>
>>>> It is 6mA.
>>>>
>>>> Let us get ctl_reg first on Windows
>>>>
>>>> lkd> !dd f111000 L8
>>>> # f111000 00000284 00000002 000000e2 00000000
>>>> # f111010 00000001 00000801 00000000 00000000
>>>>
>>>> ctl_reg => 0x284
>>>>
>>>> in msm_gpio_dbg_show_one()
>>>> ...
>>>> drive = (ctl_reg >> g->drv_bit) & 7; // (0x284 >> 6) & 7 == 2
>>>> ...
>>>> seq_printf(s, " %dmA", msm_regval_to_drive(drive)); // (drive + 1) * 2 == 6;
>>>> ...
>>>>
>>>> x13s should be the same as gaokun3 in this part.
>>>
>>> I confirmed as much and I'm willing to believe this is a default for
>>> all 8280 devices
>>>
>>> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
>>>
>>> for the second patch, please mention in the commit message that the value
>>> will now match windows and please add a fixes tag
>>>
>>
>> I believe the second change cannot be tagged as Fixes in sense that it
>> strictly depends on a not going to be backported non-fix commit, and thus
>> backporting of just 2/2 change as is will break the matter. Reordering of
>> the commits placing the fix commit as the first one should be fine though.
> 
> The Fixes tag makes the patch eligible for backporting through AUTOSEL
> but is itself not the same as "please backport"
> 

That's correct, and due Documentation/process/stable-kernel-rules.rst it
would make sense to add Cc: <stable+noautosel@kernel.org> to the next
version of the change to help stable tree maintainers, since it is known
in advance that the unmodified and Fixes tagged 2/2 change shall not be
considered as a candidate change to the stable tree. Or is it excessive?

IMHO here it might be better to properly arrange the changes and backport
the fix.

-- 
Best wishes,
Vladimir

^ permalink raw reply

* [PATCH v6] dt-bindings: misc: convert lis302.txt to YAML
From: Jad Keskes @ 2026-06-19 13:14 UTC (permalink / raw)
  To: Eric Piel, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: Jonathan Cameron, devicetree, linux-kernel, Jad Keskes

Replace the old lis302.txt with a YAML binding covering all four
compatibles (st,lis3lv02d, st,lis302dl-spi, st,lis331dlh,
st,lis33de) and their ~35 DT properties.

The old txt documented st,click-thresh-* and st,click-click-time-limit
but the code reads st,click-threshold-* and st,click-time-limit.
Keep the old names as deprecated so existing DTBs don't break.

Tested: dt_binding_check. dtbs_check against 7 omap/am335x DTBs
(am335x-evm, am335x-evmsk, am335x-pepper, am437x-sk-evm, omap3-n900,
omap3-n950, omap3-gta04a3) — no misc schema errors. Pre-existing
IIO schema errors on paired compatible nodes unchanged.

Signed-off-by: Jad Keskes <inasj268@gmail.com>
---

v6:
  - ACTUALLY commit the changes this time (git add before git commit --amend)
  - Remove redundant select block
  - Remove Vdd-supply/Vdd_IO-supply: false from SPI branch
  - Split allOf into two independent if/then branches
 .../devicetree/bindings/iio/accel/lis302.txt  | 119 ------
 .../bindings/misc/st,lis3lv02d.yaml           | 381 ++++++++++++++++++
 MAINTAINERS                                   |   1 +
 3 files changed, 382 insertions(+), 119 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/iio/accel/lis302.txt
 create mode 100644 Documentation/devicetree/bindings/misc/st,lis3lv02d.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/misc/st,lis3lv02d.yaml b/Documentation/devicetree/bindings/misc/st,lis3lv02d.yaml
new file mode 100644
index 000000000000..9c9280ec074e
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/st,lis3lv02d.yaml
@@ -0,0 +1,381 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/misc/st,lis3lv02d.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: STMicroelectronics LIS3LV02D and similar accelerometers (misc driver)
+
+maintainers:
+  - Eric Piel <eric.piel@tremplin-utc.net>
+
+description:
+  This binding describes the STMicroelectronics accelerometers supported by
+  the misc/lis3lv02d driver. This driver provides input (joystick) and
+  hardware monitoring support, in contrast to the IIO st-accel driver which
+  also supports some of these devices.
+  Refer to Documentation/devicetree/bindings/iio/st,st-sensors.yaml for the
+  IIO binding.
+
+properties:
+  compatible:
+    oneOf:
+      - items:
+          - enum:
+              - st,lis331dlh
+              - st,lis33de
+          - const: st,lis3lv02d
+      - const: st,lis331dlh
+      - const: st,lis3lv02d
+      - const: st,lis302dl-spi
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    minItems: 1
+    maxItems: 2
+
+  spi-max-frequency:
+    description: SPI bus frequency; should be set to 1000000 unless
+      constrained by external circuitry.
+    maximum: 1000000
+
+  Vdd-supply:
+    description: The input supply for Vdd.
+
+  Vdd_IO-supply:
+    description: The input supply for Vdd_IO.
+
+  st,click-single-x:
+    description: Issue an interrupt on single click events on the X axis.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,click-double-x:
+    description: Issue an interrupt on double click events on the X axis.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,click-single-y:
+    description: Issue an interrupt on single click events on the Y axis.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,click-double-y:
+    description: Issue an interrupt on double click events on the Y axis.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,click-single-z:
+    description: Issue an interrupt on single click events on the Z axis.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,click-double-z:
+    description: Issue an interrupt on double click events on the Z axis.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,click-thresh-x:
+    description: X axis click threshold (deprecated spelling, use st,click-threshold-x).
+    $ref: /schemas/types.yaml#/definitions/uint32
+    deprecated: true
+
+  st,click-thresh-y:
+    description: Y axis click threshold (deprecated spelling, use st,click-threshold-y).
+    $ref: /schemas/types.yaml#/definitions/uint32
+    deprecated: true
+
+  st,click-thresh-z:
+    description: Z axis click threshold (deprecated spelling, use st,click-threshold-z).
+    $ref: /schemas/types.yaml#/definitions/uint32
+    deprecated: true
+
+  st,click-threshold-x:
+    description: X axis click threshold.
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  st,click-threshold-y:
+    description: Y axis click threshold.
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  st,click-threshold-z:
+    description: Z axis click threshold.
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  st,click-click-time-limit:
+    description: Click time limit (deprecated spelling, use st,click-time-limit).
+    $ref: /schemas/types.yaml#/definitions/uint32
+    maximum: 255
+    deprecated: true
+
+  st,click-time-limit:
+    description: Click time limit, from 0 to 127.5 msec with step of 0.5 msec.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    maximum: 255
+
+  st,click-latency:
+    description: Click latency, from 0 to 255 msec with step of 1 msec.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    maximum: 255
+
+  st,click-window:
+    description: Click window, from 0 to 255 msec with step of 1 msec.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    maximum: 255
+
+  st,irq1-disable:
+    description: Disable IRQ 1.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,irq1-ff-wu-1:
+    description: Raise IRQ 1 on FF_WU_1 condition.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,irq1-ff-wu-2:
+    description: Raise IRQ 1 on FF_WU_2 condition.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,irq1-data-ready:
+    description: Raise IRQ 1 on data ready condition.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,irq1-click:
+    description: Raise IRQ 1 on click condition.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,irq2-disable:
+    description: Disable IRQ 2.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,irq2-ff-wu-1:
+    description: Raise IRQ 2 on FF_WU_1 condition.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,irq2-ff-wu-2:
+    description: Raise IRQ 2 on FF_WU_2 condition.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,irq2-data-ready:
+    description: Raise IRQ 2 on data ready condition.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,irq2-click:
+    description: Raise IRQ 2 on click condition.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,irq-open-drain:
+    description: Consider IRQ lines open-drain.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,irq-active-low:
+    description: Make IRQ lines active low.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,wu-duration-1:
+    description: Duration register for Free-Fall/Wake-Up interrupt 1.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    maximum: 255
+
+  st,wu-duration-2:
+    description: Duration register for Free-Fall/Wake-Up interrupt 2.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    maximum: 255
+
+  st,wakeup-x-lo:
+    description: Set wakeup condition on X axis for lower limit.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,wakeup-x-hi:
+    description: Set wakeup condition on X axis for upper limit.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,wakeup-y-lo:
+    description: Set wakeup condition on Y axis for lower limit.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,wakeup-y-hi:
+    description: Set wakeup condition on Y axis for upper limit.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,wakeup-z-lo:
+    description: Set wakeup condition on Z axis for lower limit.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,wakeup-z-hi:
+    description: Set wakeup condition on Z axis for upper limit.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,wakeup-threshold:
+    description: Set wakeup threshold.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    maximum: 255
+
+  st,wakeup2-x-lo:
+    description: Set wakeup condition on X axis for lower limit for second wakeup engine.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,wakeup2-x-hi:
+    description: Set wakeup condition on X axis for upper limit for second wakeup engine.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,wakeup2-y-lo:
+    description: Set wakeup condition on Y axis for lower limit for second wakeup engine.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,wakeup2-y-hi:
+    description: Set wakeup condition on Y axis for upper limit for second wakeup engine.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,wakeup2-z-lo:
+    description: Set wakeup condition on Z axis for lower limit for second wakeup engine.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,wakeup2-z-hi:
+    description: Set wakeup condition on Z axis for upper limit for second wakeup engine.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,wakeup2-threshold:
+    description: Set wakeup threshold for second wakeup engine.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    maximum: 255
+
+  st,highpass-cutoff-hz:
+    description: Highpass cut-off frequency. Valid values are 1, 2, 4 or 8.
+    enum: [1, 2, 4, 8]
+
+  st,hipass1-disable:
+    description: Disable highpass filter 1.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,hipass2-disable:
+    description: Disable highpass filter 2.
+    $ref: /schemas/types.yaml#/definitions/flag
+
+  st,default-rate:
+    description: Set the default output data rate.
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  st,axis-x:
+    description: Set the X axis mapping. Negative values can be used for inverted axis.
+    $ref: /schemas/types.yaml#/definitions/int32
+
+  st,axis-y:
+    description: Set the Y axis mapping. Negative values can be used for inverted axis.
+    $ref: /schemas/types.yaml#/definitions/int32
+
+  st,axis-z:
+    description: Set the Z axis mapping. Negative values can be used for inverted axis.
+    $ref: /schemas/types.yaml#/definitions/int32
+
+  st,min-limit-x:
+    description: Minimum limit for X axis (used by self-test).
+    $ref: /schemas/types.yaml#/definitions/int32
+
+  st,min-limit-y:
+    description: Minimum limit for Y axis (used by self-test).
+    $ref: /schemas/types.yaml#/definitions/int32
+
+  st,min-limit-z:
+    description: Minimum limit for Z axis (used by self-test).
+    $ref: /schemas/types.yaml#/definitions/int32
+
+  st,max-limit-x:
+    description: Maximum limit for X axis (used by self-test).
+    $ref: /schemas/types.yaml#/definitions/int32
+
+  st,max-limit-y:
+    description: Maximum limit for Y axis (used by self-test).
+    $ref: /schemas/types.yaml#/definitions/int32
+
+  st,max-limit-z:
+    description: Maximum limit for Z axis (used by self-test).
+    $ref: /schemas/types.yaml#/definitions/int32
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: st,lis302dl-spi
+    then:
+      required:
+        - spi-max-frequency
+        - interrupts
+  - if:
+      properties:
+        compatible:
+          not:
+            contains:
+              const: st,lis302dl-spi
+    then:
+      required:
+        - Vdd-supply
+        - Vdd_IO-supply
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        accelerometer@18 {
+            compatible = "st,lis331dlh", "st,lis3lv02d";
+            reg = <0x18>;
+            Vdd-supply = <&lis3_reg>;
+            Vdd_IO-supply = <&lis3_reg>;
+            interrupt-parent = <&gpio2>;
+            interrupts = <18 0>;
+
+            st,click-single-x;
+            st,click-single-y;
+            st,click-single-z;
+            st,click-threshold-x = <10>;
+            st,click-threshold-y = <10>;
+            st,click-threshold-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>;
+        };
+    };
+  - |
+    spi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        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-threshold-x = <10>;
+            st,click-threshold-y = <10>;
+            st,click-threshold-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;
+        };
+    };
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 9ec290e38b44..4cffabbabf0e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14858,6 +14858,7 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/
 LIS3LV02D ACCELEROMETER DRIVER
 M:	Eric Piel <eric.piel@tremplin-utc.net>
 S:	Maintained
+F:	Documentation/devicetree/bindings/misc/st,lis3lv02d.yaml
 F:	Documentation/misc-devices/lis3lv02d.rst
 F:	drivers/misc/lis3lv02d/
 F:	drivers/platform/x86/hp/hp_accel.c
-- 
2.54.0


^ permalink raw reply related


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