This is the first part in upstreaming a set of around 100 patches that were developed in NXP's vendor Linux Factory kernel over the course of several years.
This part is mainly concerned with correcting some historical mistakes which make extending the driver more difficult: - The 3 instances of this SerDes block, as seen on NXP LX2160A, need to be differentiated somehow, because otherwise, the driver cannot reject a configuration which is unsupported by the hardware. The proposal is to do that based on compatible string. - Lanes cannot have electrical parameters described in the device tree, because they are not described in the device tree. - The register naming scheme forces us to modify a single register field per lynx_28g_lane_rmw() call - leads to inefficient code - lynx_28g_lane_set_sgmii(), lynx_28g_lane_set_10gbaser() are unfit for their required roles when the current SerDes protocol is 25GBase-R. They are replaced with a better structured approach. - USXGMII and 10GBase-R have different protocol converters, and should be treated separately by the SerDes driver.
The device tree binding + driver changes are all non-breaking. I also have device tree conversions for LX2160A and LX2162A which are also non-breaking due to their partial nature.
If I were to replace patterns such as: phys = <&serdes_2 0>; with: phys = <&serdes_2_lane_a>;
then the corresponding device tree conversions would also be breaking. I don't _need_ to do that to make progress, but eventually I would like to be able to.
In order to be able to make that kind of change in a non-breaking manner in a reasonable number of years, I would like patches 1-3 to be backported to stable kernels.
Compared to v3 here: https://lore.kernel.org/linux-phy/20250926180505.760089-1-vladimir.oltean@nx... there are some new patches, but it overall shrank in size because I deferred new features to "part 2". Essentially, v4 is like v3, except with a better plan to handle device tree transitions without breakage, and with the following patches temporarily dropped: [PATCH v3 phy 14/17] phy: lynx-28g: add support for 25GBASER [PATCH v3 phy 15/17] phy: lynx-28g: use timeouts when waiting for lane halt and reset [PATCH v3 phy 16/17] phy: lynx-28g: truly power the lanes up or down [PATCH v3 phy 17/17] phy: lynx-28g: implement phy_exit() operation
Compared to v2 here: https://lore.kernel.org/lkml/d0c8bbf8-a0c5-469f-a148-de2235948c0f@solid-run.... v3 grew in size due to Josua's request to avoid unbounded loops waiting for lane resets/halts/stops to complete.
Compared to v1 here: https://lore.kernel.org/lkml/20250904154402.300032-1-vladimir.oltean@nxp.com... v2 grew in size due to Josua's request for a device tree binding where individual lanes have their own OF nodes. This seems to be the right moment to make that change.
Detailed change log in individual patches. Thanks to Josua, Rob, Conor, Krzysztof, Ioana who provided feedback on the previous version, and I hope it has all been addressed.
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
Ioana Ciornei (1): phy: lynx-28g: configure more equalization params for 1GbE and 10GbE
Vladimir Oltean (15): dt-bindings: phy: lynx-28g: permit lane OF PHY providers phy: lynx-28g: refactor lane probing to lynx_28g_probe_lane() phy: lynx-28g: support individual lanes as OF PHY providers phy: lynx-28g: remove LYNX_28G_ prefix from register names phy: lynx-28g: don't concatenate lynx_28g_lane_rmw() argument "reg" with "val" and "mask" phy: lynx-28g: use FIELD_GET() and FIELD_PREP() phy: lynx-28g: convert iowrite32() calls with magic values to macros phy: lynx-28g: restructure protocol configuration register accesses phy: lynx-28g: make lynx_28g_set_lane_mode() more systematic phy: lynx-28g: refactor lane->interface to lane->mode phy: lynx-28g: distinguish between 10GBASE-R and USXGMII phy: lynx-28g: use "dev" argument more in lynx_28g_probe() phy: lynx-28g: improve lynx_28g_probe() sequence dt-bindings: phy: lynx-28g: add compatible strings per SerDes and instantiation phy: lynx-28g: probe on per-SoC and per-instance compatible strings
.../devicetree/bindings/phy/fsl,lynx-28g.yaml | 153 +- drivers/phy/freescale/phy-fsl-lynx-28g.c | 1271 +++++++++++++---- 2 files changed, 1134 insertions(+), 290 deletions(-)
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.... 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>; + }; }; };
On Mon, 10 Nov 2025 11:22:26 +0200, Vladimir Oltean wrote:
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.... 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(-)
Reviewed-by: Rob Herring (Arm) robh@kernel.org
On 10-11-25, 11:22, Vladimir Oltean wrote:
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.... 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
You can keep cc lines after s-o-b line after the '---' separator, that way it will be skipped when applying while email client will cc folks.
My main question was cc stable, for a binding additions, that might not be helpful as dts may not have these updates, so why port bindings?
Hi Vinod,
Thanks for taking a look at this patch set!
On Thu, Nov 13, 2025 at 10:16:49PM +0530, Vinod Koul wrote:
Link: https://lore.kernel.org/lkml/02270f62-9334-400c-b7b9-7e6a44dbbfc9@solid-run.... 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
You can keep cc lines after s-o-b line after the '---' separator, that way it will be skipped when applying while email client will cc folks.
Yes, but keeping the CC list even when the patch is applied was the intention, especially for stable.
My main question was cc stable, for a binding additions, that might not be helpful as dts may not have these updates, so why port bindings?
There is a faction of people, whose point as a matter of fact I do understand, is that if you make an update to the device tree, you shouldn't be required to also update the kernel for things to continue to work as before.
The purpose of backporting the binding addition to stable is exactly in order for kernels such as linux-6.12.y to start supporting modified device trees, such that one day we could roll out such modifications. The series doesn't depend on that, but the "DT is ABI" statement has implications in terms of kernel <-> device tree compatibility, if you consider the fact that they can be delivered to a board through different channels. For example, you try to ship a bootloader that provides its own device tree to the kernel to support generic distros which don't come with device trees prepackaged, and you have to support 2 LTS kernels with that same device tree.
This simplifies the main control flow a little bit and makes the logic reusable for probing the lanes with OF nodes if those exist.
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 13/17] phy: lynx-28g: probe on per-SoC and per-instance compatible strings" to deal only with lane OF nodes, in a backportable way
drivers/phy/freescale/phy-fsl-lynx-28g.c | 42 +++++++++++++++--------- 1 file changed, 26 insertions(+), 16 deletions(-)
diff --git a/drivers/phy/freescale/phy-fsl-lynx-28g.c b/drivers/phy/freescale/phy-fsl-lynx-28g.c index c20d2636c5e9..901240bbcade 100644 --- a/drivers/phy/freescale/phy-fsl-lynx-28g.c +++ b/drivers/phy/freescale/phy-fsl-lynx-28g.c @@ -579,12 +579,33 @@ static struct phy *lynx_28g_xlate(struct device *dev, return priv->lane[idx].phy; }
+static int lynx_28g_probe_lane(struct lynx_28g_priv *priv, int id, + struct device_node *dn) +{ + struct lynx_28g_lane *lane = &priv->lane[id]; + struct phy *phy; + + memset(lane, 0, sizeof(*lane)); + + phy = devm_phy_create(priv->dev, dn, &lynx_28g_ops); + if (IS_ERR(phy)) + return PTR_ERR(phy); + + lane->priv = priv; + lane->phy = phy; + lane->id = id; + phy_set_drvdata(phy, lane); + lynx_28g_lane_read_configuration(lane); + + return 0; +} + static int lynx_28g_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct phy_provider *provider; struct lynx_28g_priv *priv; - int i; + int err;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -597,21 +618,10 @@ static int lynx_28g_probe(struct platform_device *pdev)
lynx_28g_pll_read_configuration(priv);
- for (i = 0; i < LYNX_28G_NUM_LANE; i++) { - struct lynx_28g_lane *lane = &priv->lane[i]; - struct phy *phy; - - memset(lane, 0, sizeof(*lane)); - - phy = devm_phy_create(&pdev->dev, NULL, &lynx_28g_ops); - if (IS_ERR(phy)) - return PTR_ERR(phy); - - lane->priv = priv; - lane->phy = phy; - lane->id = i; - phy_set_drvdata(phy, lane); - lynx_28g_lane_read_configuration(lane); + for (int i = 0; i < LYNX_28G_NUM_LANE; i++) { + err = lynx_28g_probe_lane(priv, i, NULL); + if (err) + return err; }
dev_set_drvdata(dev, priv);
On 10-11-25, 11:22, Vladimir Oltean wrote:
This simplifies the main control flow a little bit and makes the logic reusable for probing the lanes with OF nodes if those exist.
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 13/17] phy: lynx-28g: probe on per-SoC and per-instance compatible strings" to deal only with lane OF nodes, in a backportable way
drivers/phy/freescale/phy-fsl-lynx-28g.c | 42 +++++++++++++++--------- 1 file changed, 26 insertions(+), 16 deletions(-)
diff --git a/drivers/phy/freescale/phy-fsl-lynx-28g.c b/drivers/phy/freescale/phy-fsl-lynx-28g.c index c20d2636c5e9..901240bbcade 100644 --- a/drivers/phy/freescale/phy-fsl-lynx-28g.c +++ b/drivers/phy/freescale/phy-fsl-lynx-28g.c @@ -579,12 +579,33 @@ static struct phy *lynx_28g_xlate(struct device *dev, return priv->lane[idx].phy; } +static int lynx_28g_probe_lane(struct lynx_28g_priv *priv, int id,
struct device_node *dn)+{
- struct lynx_28g_lane *lane = &priv->lane[id];
- struct phy *phy;
- memset(lane, 0, sizeof(*lane));
priv is kzalloc, so why memset here?
On Thu, Nov 13, 2025 at 10:19:55PM +0530, Vinod Koul wrote:
On 10-11-25, 11:22, Vladimir Oltean wrote:
diff --git a/drivers/phy/freescale/phy-fsl-lynx-28g.c b/drivers/phy/freescale/phy-fsl-lynx-28g.c index c20d2636c5e9..901240bbcade 100644 --- a/drivers/phy/freescale/phy-fsl-lynx-28g.c +++ b/drivers/phy/freescale/phy-fsl-lynx-28g.c @@ -579,12 +579,33 @@ static struct phy *lynx_28g_xlate(struct device *dev, return priv->lane[idx].phy; } +static int lynx_28g_probe_lane(struct lynx_28g_priv *priv, int id,
struct device_node *dn)+{
- struct lynx_28g_lane *lane = &priv->lane[id];
- struct phy *phy;
- memset(lane, 0, sizeof(*lane));
priv is kzalloc, so why memset here?
Great question, but this is a pattern that was pre-existing in the code, and I don't like modifying code as I move it. I had to put a stop somewhere (series is already 16 patch long). I can absolutely remove the memset in part 2 once this one is merged.
Currently, the bindings of this multi-lane SerDes are such that consumers specify the lane index in the PHY cell, and the lane itself is not described in the device tree.
It is desirable to describe individual Lynx 28G SerDes lanes in the device tree, in order to be able to customize electrical properties such as those in Documentation/devicetree/bindings/phy/transmit-amplitude.yaml (or others).
If each lane may have an OF node, it appears natural for consumers to have their "phys" phandle point to that OF node.
The problem is that transitioning between one format and another is a breaking change. The bindings of the 28G Lynx SerDes can themselves be extended in a backward-compatible way, but the consumers cannot be modified without breaking them.
Namely, if we have:
&mac { phys = <&serdes1 0>; };
we cannot update the device tree to:
&mac { phys = <&serdes1_lane_0>; };
because old kernels cannot resolve this phandle to a valid PHY.
The proposal here is to keep tolerating existing device trees, which are not supposed to be changed, but modify lynx_28g_xlate() to also resolve the new format with #phy-cells = <0> in the lanes.
This way we support 3 modes: - Legacy device trees, no OF nodes for lanes - New device trees, OF nodes for lanes and "phys" phandle points towards them - Hybrid device trees, OF nodes for lanes (to describe electrical parameters), but "phys" phandle points towards the SerDes top-level provider
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 13/17] phy: lynx-28g: probe on per-SoC and per-instance compatible strings" to deal only with lane OF nodes, in a backportable way - contains a new idea to support phandles either to the SerDes or to lane nodes, via a single xlate function that redirects to of_phy_simple_xlate() if the phandle is to the lane, or is implemented as before if the phandle is to the SerDes. - Compared to v3 where we decided based on the compatible string whether to use lynx_28g_xlate() which expects the SerDes as PHY provider, or of_phy_simple_xlate() which expects the lanes as PHY provider, here we completely decouple those two concepts and patch lynx_28g_xlate() to support both cases.
drivers/phy/freescale/phy-fsl-lynx-28g.c | 49 +++++++++++++++++++++--- 1 file changed, 44 insertions(+), 5 deletions(-)
diff --git a/drivers/phy/freescale/phy-fsl-lynx-28g.c b/drivers/phy/freescale/phy-fsl-lynx-28g.c index 901240bbcade..61a992ff274f 100644 --- a/drivers/phy/freescale/phy-fsl-lynx-28g.c +++ b/drivers/phy/freescale/phy-fsl-lynx-28g.c @@ -571,7 +571,14 @@ static struct phy *lynx_28g_xlate(struct device *dev, const struct of_phandle_args *args) { struct lynx_28g_priv *priv = dev_get_drvdata(dev); - int idx = args->args[0]; + int idx; + + if (args->args_count == 0) + return of_phy_simple_xlate(dev, args); + else if (args->args_count != 1) + return ERR_PTR(-ENODEV); + + idx = args->args[0];
if (WARN_ON(idx >= LYNX_28G_NUM_LANE)) return ERR_PTR(-EINVAL); @@ -605,6 +612,7 @@ static int lynx_28g_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct phy_provider *provider; struct lynx_28g_priv *priv; + struct device_node *dn; int err;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); @@ -618,10 +626,41 @@ static int lynx_28g_probe(struct platform_device *pdev)
lynx_28g_pll_read_configuration(priv);
- for (int i = 0; i < LYNX_28G_NUM_LANE; i++) { - err = lynx_28g_probe_lane(priv, i, NULL); - if (err) - return err; + dn = dev_of_node(dev); + if (of_get_child_count(dn)) { + struct device_node *child; + + for_each_available_child_of_node(dn, child) { + u32 reg; + + /* PHY subnode name must be 'phy'. */ + if (!(of_node_name_eq(child, "phy"))) + continue; + + if (of_property_read_u32(child, "reg", ®)) { + dev_err(dev, "No "reg" property for %pOF\n", child); + of_node_put(child); + return -EINVAL; + } + + if (reg >= LYNX_28G_NUM_LANE) { + dev_err(dev, ""reg" property out of range for %pOF\n", child); + of_node_put(child); + return -EINVAL; + } + + err = lynx_28g_probe_lane(priv, reg, child); + if (err) { + of_node_put(child); + return err; + } + } + } else { + for (int i = 0; i < LYNX_28G_NUM_LANE; i++) { + err = lynx_28g_probe_lane(priv, i, NULL); + if (err) + return err; + } }
dev_set_drvdata(dev, priv);
linux-stable-mirror@lists.linaro.org