[PATCH v2 phy 12/16] dt-bindings: phy: lynx-28g: add compatible strings per SerDes and instantiation

Vladimir Oltean
2025-09-23T19:45:30Z

Going by the generic "fsl,lynx-28g" compatible string and expecting all
SerDes instantiations on all SoCs to use it was a mistake.

They all share the same register map, sure, but the number of protocol
converters and lanes which are instantiated differs in a way that isn't
detectable by the programming interface.

Using a separate compatible string per SerDes instantiation is
sufficient for any device driver to distinguish these features and/or
any instance-specific quirk. It also reflects how the SoC reference
manual provides different tables with protocol combinations for each
SerDes. NXP clearly documents these as not identical, and refers to them
as such (SerDes 1, 2, etc).

The other sufficient approach would be to list in the device tree all
protocols supported by each lane. That was attempted in this unmerged
patch set for the older Lynx 10G family:
https://lore.kernel.org/linux-phy/20230413160607.4128315-3-sean.anderson@seco.com/

but IMO that approach is more drawn-out and more prone to errors,
whereas this one is more succinct and obviously correct.

Since this compatible string change breaks forward compatibility of old
kernels with new device trees (which is OK with the known users), this
is a good time to fulfill another user request, which is that individual
SerDes lanes should have had their own OF nodes, so that we can
customize electrical parameters:
https://lore.kernel.org/lkml/02270f62-9334-400c-b7b9-7e6a44dbbfc9@solid-run.com/

This request requires #phy-cells = <0>, and because "fsl,lynx-28g"
requires #phy-cells = <1>, we obviously cannot have both at the same
time.

Change the expected name of the top-level node to "serdes", and update
the example too.

Cc: Rob Herring <robh@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: devicetree@vger.kernel.org
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
v1->v2:
- drop the usage of "fsl,lynx-28g" as a fallback compatible
- mark "fsl,lynx-28g" as deprecated
- implement Josua's request for per-lane OF nodes for the new compatible
strings

.../devicetree/bindings/phy/fsl,lynx-28g.yaml | 146 +++++++++++++++++-
1 file changed, 140 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/fsl,lynx-28g.yaml b/Documentation/devicetree/bindings/phy/fsl,lynx-28g.yaml
index ff9f9ca0f19c..390c9ecd94cc 100644
--- a/Documentation/devicetree/bindings/phy/fsl,lynx-28g.yaml
+++ b/Documentation/devicetree/bindings/phy/fsl,lynx-28g.yaml
@@ -9,21 +9,113 @@ title: Freescale Lynx 28G SerDes PHY
maintainers:
- Ioana Ciornei <ioana.ciornei@nxp.com>

+description: |
+ The Lynx 28G is a multi-lane, multi-protocol SerDes (PCIe, SATA, Ethernet)
+ present in multiple instances on NXP LX2160A and LX2162A SoCs. All instances
+ share a common register map and programming model, however they differ in
+ supported protocols per lane in a way that is not detectable by said
+ programming model without prior knowledge. The distinction is made through
+ the compatible string.
+
properties:
compatible:
- enum:
- - fsl,lynx-28g
+ oneOf:
+ - const: fsl,lynx-28g
+ deprecated: true
+ description: |
+ Legacy compatibility string for Lynx 28G SerDes. The capabilities
+ of managed lanes are limited to 1GbE and 10GbE (depending on the
+ availability of an adequate PLL clock net frequency). Deprecated, use
+ device-specific strings instead.
+ - enum:
+ - fsl,lx2160a-serdes1
+ - fsl,lx2160a-serdes2
+ - fsl,lx2160a-serdes3
+ - fsl,lx2162a-serdes1
+ - fsl,lx2162a-serdes2

reg:
maxItems: 1

+ "#address-cells":
+ const: 1
+ description: "Address cells for child lane nodes"
+
+ "#size-cells":
+ const: 0
+ description: "Size cells for child lane nodes"
+
"#phy-cells":
+ description: "Number of cells in PHY specifier (legacy binding only)"
const: 1

+patternProperties:
+ "^phy@[0-9a-f]+$":
+ type: object
+ description: Individual SerDes lane acting as PHY provider
+
+ properties:
+ reg:
+ description: Lane number
+ maxItems: 1
+
+ "#phy-cells":
+ description: Number of cells in PHY specifier for this lane
+ const: 0
+
+ required:
+ - reg
+ - "#phy-cells"
+
+ additionalProperties: false
+
required:
- compatible
- reg
- - "#phy-cells"
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ const: fsl,lynx-28g
+ then:
+ # Legacy case: parent is PHY provider
+ properties:
+ "#phy-cells":
+ const: 1
+ "#address-cells": false
+ "#size-cells": false
+ required:
+ - "#phy-cells"
+ patternProperties:
+ "^phy@[0-9a-f]+$": false
+ else:
+ # Modern case: children are PHY providers
+ properties:
+ "#phy-cells": false
+ required:
+ - "#address-cells"
+ - "#size-cells"
+
+ # LX2162A SerDes 1 has fewer lanes than the others
+ - if:
+ properties:
+ compatible:
+ const: fsl,lx2162a-serdes1
+ then:
+ patternProperties:
+ "^phy@[0-9a-f]+$":
+ properties:
+ reg:
+ description: Lane number (lanes 4-7 only for LX2162A SerDes 1)
+ enum: [4, 5, 6, 7]
+ else:
+ patternProperties:
+ "^phy@[0-9a-f]+$":
+ properties:
+ reg:
+ description: Lane number (lanes 0-7)
+ enum: [0, 1, 2, 3, 4, 5, 6, 7]

additionalProperties: false

@@ -32,9 +124,51 @@ examples:
soc {
#address-cells = <2>;
#size-cells = <2>;
- serdes_1: phy@1ea0000 {
- compatible = "fsl,lynx-28g";
+
+ serdes_1: serdes@1ea0000 {
+ compatible = "fsl,lx2160a-serdes1";
reg = <0x0 0x1ea0000 0x0 0x1e30>;
- #phy-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy@0 {
+ reg = <0>;
+ #phy-cells = <0>;
+ };
+
+ phy@1 {
+ reg = <1>;
+ #phy-cells = <0>;
+ };
+
+ phy@2 {
+ reg = <2>;
+ #phy-cells = <0>;
+ };
+
+ phy@3 {
+ reg = <3>;
+ #phy-cells = <0>;
+ };
+
+ phy@4 {
+ reg = <4>;
+ #phy-cells = <0>;
+ };
+
+ phy@5 {
+ reg = <5>;
+ #phy-cells = <0>;
+ };
+
+ phy@6 {
+ reg = <6>;
+ #phy-cells = <0>;
+ };
+
+ phy@7 {
+ reg = <7>;
+ #phy-cells = <0>;
+ };
};
};
--
2.34.1