[PATCH v4 phy 01/16] dt-bindings: phy: lynx-28g: permit lane OF PHY providers

Vladimir Oltean
2025-11-10T09:23:03Z

Josua Mayer requested to have OF nodes for each lane, so that he
(and other board developers) can further describe electrical parameters
individually.

For this use case, we need a container node to apply the already
existing Documentation/devicetree/bindings/phy/transmit-amplitude.yaml,
plus whatever other schemas might get standardized for TX equalization
parameters, polarity inversion etc.

When lane OF nodes exist, these are also PHY providers ("phys" phandles
can point directly to them). Compare that to the existing binding, where
the PHY provider is the top-level SerDes node, and the second cell in
the "phys" phandle specifies the lane index.

The new binding format overlaps over the old one without interfering,
but there is a caveat:

Existing device trees, which already have "phys = <&serdes1 0>" cannot
be converted to "phys = <&serdes_1_lane_a>", because in doing so, we
would break compatibility with old kernels which don't understand how to
translate the latter phandle to a PHY.

The transition to the new phandle format can be performed only after a
reasonable amount of time has elapsed after this schema change and the
corresponding driver change have been backported to stable kernels.

However, the aforementioned transition is not strictly necessary, and
the "hybrid" description (where individual lanes have their own OF node,
but are not pointed to by the "phys" phandle) can remain for an
indefinite amount of time, even if a little inelegant.

For newly introduced device trees, where there are no compatibility
concerns with old kernels to speak of, it is strongly recommended to use
the "phys = <&serdes_1_lane_a>" format. The same holds for phandles
towards lanes of LX2160A SerDes #3, which at the time of writing is not
yet described in fsl-lx2160a.dtsi, so there is no legacy to maintain.

To avoid the strange situation where we have a "phy" (SerDes node) ->
"phy" (lane node) hierarchy, let's rename the expected name of the
top-level node to "serdes", and update the example too. This has a
theoretical chance of causing regressions if bootloaders search for
hardcoded paths rather than using aliases, but to the best of my
knowledge, for LX2160A/LX2162A this is not the case.

Link: https://lore.kernel.org/lkml/02270f62-9334-400c-b7b9-7e6a44dbbfc9@solid-run.com/
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
Cc: stable@vger.kernel.org
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
v3-v4: patch is new (broken out from previous "[PATCH v3 phy 12/17]
dt-bindings: phy: lynx-28g: add compatible strings per SerDes
and instantiation") to deal just with the lane OF nodes, in a
backportable way

.../devicetree/bindings/phy/fsl,lynx-28g.yaml | 71 ++++++++++++++++++-
1 file changed, 70 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/fsl,lynx-28g.yaml b/Documentation/devicetree/bindings/phy/fsl,lynx-28g.yaml
index ff9f9ca0f19c..e96229c2f8fb 100644
--- a/Documentation/devicetree/bindings/phy/fsl,lynx-28g.yaml
+++ b/Documentation/devicetree/bindings/phy/fsl,lynx-28g.yaml
@@ -20,6 +20,32 @@ properties:
"#phy-cells":
const: 1

+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+patternProperties:
+ "^phy@[0-7]$":
+ type: object
+ description: SerDes lane (single RX/TX differential pair)
+
+ properties:
+ reg:
+ minimum: 0
+ maximum: 7
+ description: Lane index as seen in register map
+
+ "#phy-cells":
+ const: 0
+
+ required:
+ - reg
+ - "#phy-cells"
+
+ additionalProperties: false
+
required:
- compatible
- reg
@@ -32,9 +58,52 @@ examples:
soc {
#address-cells = <2>;
#size-cells = <2>;
- serdes_1: phy@1ea0000 {
+
+ serdes@1ea0000 {
compatible = "fsl,lynx-28g";
reg = <0x0 0x1ea0000 0x0 0x1e30>;
+ #address-cells = <1>;
+ #size-cells = <0>;
#phy-cells = <1>;
+
+ 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>;
+ };
};
};