* Re: [PATCH net-next 0/9] net: stmmac: qcom-ethqos: further serdes reorganisation
From: Vinod Koul @ 2026-02-27 13:47 UTC (permalink / raw)
To: Russell King (Oracle)
Cc: Andrew Lunn, Alexandre Torgue, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, linux-arm-kernel, linux-arm-msm,
linux-phy, linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
Paolo Abeni
In-Reply-To: <aZ66uXCwGgH7B_A-@shell.armlinux.org.uk>
On 25-02-26, 09:02, Russell King (Oracle) wrote:
> Note: only 8 patches in this series, not 9 as the subject line says,
> as the set_clk_tx_rate() patch became part of the first series.
>
> On Wed, Feb 25, 2026 at 09:00:41AM +0000, Russell King (Oracle) wrote:
> > This is part 2 of the qcom-ethqos series, part 1 has now been merged.
> >
> > This part of the series focuses on the generic PHY driver, but these
> > changes have dependencies on the ethernet driver, hence why
> > it will need to go via net-next. Furthermore, subsequent changes
> > depend on these patches.
This lgtm, can we get signed tag so that we can pull this into phy tree
as well
Thanks
--
~Vinod
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH net-next 7/8] phy: qcom-sgmii-eth: relax order of .power_on() vs .set_mode*()
From: Vinod Koul @ 2026-02-27 13:45 UTC (permalink / raw)
To: Russell King (Oracle)
Cc: Andrew Lunn, Alexandre Torgue, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, linux-arm-kernel, linux-arm-msm,
linux-phy, linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
Paolo Abeni
In-Reply-To: <E1vvCcE-0000000ArLT-1COQ@rmk-PC.armlinux.org.uk>
On 25-02-26, 10:59, Russell King (Oracle) wrote:
> Allow any order of the .power_on() and .set_mode*() methods as per the
> recent discussion. This means phy_power_on() with this SerDes will now
> restore the previous setup without requiring a subsequent
> phy_set_mode*() call.
>
> Tested-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
> Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Acked-by: Vinod Koul <vkoul@kernel.org>
--
~Vinod
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH net-next 6/8] phy: qcom-sgmii-eth: remove qcom_dwmac_sgmii_phy_interface()
From: Vinod Koul @ 2026-02-27 13:45 UTC (permalink / raw)
To: Russell King (Oracle)
Cc: Andrew Lunn, Alexandre Torgue, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, linux-arm-kernel, linux-arm-msm,
linux-phy, linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
Paolo Abeni
In-Reply-To: <E1vvCc9-0000000ArLG-0if1@rmk-PC.armlinux.org.uk>
On 25-02-26, 10:59, Russell King (Oracle) wrote:
> Now that qcom_dwmac_sgmii_phy_interface() only serves to validate the
> passed interface mode, combine it with qcom_dwmac_sgmii_phy_validate(),
> and use qcom_dwmac_sgmii_phy_validate() to validate the mode in
> qcom_dwmac_sgmii_phy_set_mode().
>
> Tested-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
> Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Acked-by: Vinod Koul <vkoul@kernel.org>
--
~Vinod
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH net-next 5/8] phy: qcom-sgmii-eth: use PHY interface mode for SerDes settings
From: Vinod Koul @ 2026-02-27 13:43 UTC (permalink / raw)
To: Russell King (Oracle)
Cc: Andrew Lunn, Alexandre Torgue, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, linux-arm-kernel, linux-arm-msm,
linux-phy, linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
Paolo Abeni
In-Reply-To: <E1vvCc4-0000000ArLA-0Eix@rmk-PC.armlinux.org.uk>
On 25-02-26, 10:59, Russell King (Oracle) wrote:
> As established in the previous commit, using SPEED_1000 and SPEED_2500
> does not make sense for a SerDes due to the PCS encoding that is used
> over the SerDes link, which inflates the data rate at the SerDes. Thus,
> the use of these constants in a SerDes driver is incorrect.
>
> Since qcom-sgmii-eth no longer implements phy_set_speed(), but instead
> uses the PHY interface mode passed via the .set_mode() method, convert
> the driver to use the PHY interface mode internally to decide whether
> to configure the SerDes for 1.25Gbps or 3.125Gbps mode.
Acked-by: Vinod Koul <vkoul@kernel.org>
--
~Vinod
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH net-next 4/8] phy: qcom-sgmii-eth: remove .set_speed() implementation
From: Vinod Koul @ 2026-02-27 13:42 UTC (permalink / raw)
To: Russell King (Oracle)
Cc: Andrew Lunn, Alexandre Torgue, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, linux-arm-kernel, linux-arm-msm,
linux-phy, linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
Paolo Abeni
In-Reply-To: <E1vvCby-0000000ArL4-3x4U@rmk-PC.armlinux.org.uk>
On 25-02-26, 10:59, Russell King (Oracle) wrote:
> Now that the qcom-ethqos driver has migrated to use phy_set_mode_ext()
> rather than phy_set_speed() to configure the SerDes, the support for
> phy_set_speed() is now obsolete. Remove support for this method.
>
> Using the MAC speed for the SerDes is never correct due to the PCS
> encoding. For SGMII and 2500BASE-X, the PCS uses 8B10B encoding, and
> so:
>
> MAC rate * PCS output bits / PCS input bits = SerDes rate
> 1000M * 10 / 8 = 1250M
> 2500M * 10 / 8 = 3125M
>
> Tested-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
> Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Acked-by: Vinod Koul <vkoul@kernel.org>
--
~Vinod
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH] phy: qcom: qmp-usbc: Fix out-of-bounds array access in dp swing config
From: Xiangxu Yin via B4 Relay @ 2026-02-27 12:15 UTC (permalink / raw)
To: Vinod Koul, Neil Armstrong, Dmitry Baryshkov
Cc: linux-arm-msm, linux-phy, linux-kernel, fange.zhang, yongxing.mou,
li.liu, tingwei.zhang, Konrad Dybcio, Dan Carpenter, Xiangxu Yin
From: Xiangxu Yin <xiangxu.yin@oss.qualcomm.com>
swing_tbl and pre_emphasis_tbl are 4x4 arrays (valid indices 0-3), but
the boundary check uses "> 4" instead of ">= 4", allowing index 4 to
cause an out-of-bounds access.
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Fixes: 81791c45c8e0 ("phy: qcom: qmp-usbc: Add QCS615 USB/DP PHY config and DP mode support")
Signed-off-by: Xiangxu Yin <xiangxu.yin@oss.qualcomm.com>
---
drivers/phy/qualcomm/phy-qcom-qmp-usbc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c b/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c
index 14feb77789b3..0dd7000614f4 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c
@@ -794,7 +794,7 @@ static int qmp_v2_configure_dp_swing(struct qmp_usbc *qmp)
p_level = max(p_level, dp_opts->pre[i]);
}
- if (v_level > 4 || p_level > 4) {
+ if (v_level >= 4 || p_level >= 4) {
dev_err(qmp->dev, "Invalid v(%d) | p(%d) level)\n",
v_level, p_level);
return -EINVAL;
---
base-commit: 7d6661873f6b54c75195780a40d66bad3d482d8f
change-id: 20260227-master-8b948c5633ea
Best regards,
--
Xiangxu Yin <xiangxu.yin@oss.qualcomm.com>
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema
From: Bryan O'Donoghue @ 2026-02-27 9:47 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Neil Armstrong,
Bryan O'Donoghue, Vladimir Zapolskiy, linux-arm-msm,
linux-phy, linux-media, devicetree, linux-kernel
In-Reply-To: <20260227-overjoyed-spiritual-saluki-7561c2@quoll>
On 27/02/2026 09:41, Krzysztof Kozlowski wrote:
> On Thu, Feb 26, 2026 at 12:34:25PM +0000, Bryan O'Donoghue wrote:
>> Add a base schema initially compatible with x1e80100 to describe MIPI CSI2
>> PHY devices.
>>
>> The hardware can support both C-PHY and D-PHY modes. The CSIPHY devices
>> have their own pinouts on the SoC as well as their own individual voltage
>> rails.
>>
>> The need to model voltage rails on a per-PHY basis leads us to define
>> CSIPHY devices as individual nodes.
>>
>> Two nice outcomes in terms of schema and DT arise from this change.
>>
>> 1. The ability to define on a per-PHY basis voltage rails.
>> 2. The ability to require those voltage.
>>
>> We have had a complete bodge upstream for this where a single set of
>> voltage rail for all CSIPHYs has been buried inside of CAMSS.
>>
>> Much like the I2C bus which is dedicated to Camera sensors - the CCI bus in
>> CAMSS parlance, the CSIPHY devices should be individually modelled.
>>
>> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
>> ---
>> .../bindings/phy/qcom,x1e80100-csi2-phy.yaml | 114 +++++++++++++++++++++
>> 1 file changed, 114 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml
>> new file mode 100644
>> index 0000000000000..c937d26ccbda9
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml
>> @@ -0,0 +1,114 @@
>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/phy/qcom,x1e80100-csi2-phy.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Qualcomm CSI2 PHY
>
> Qualcomm SoC CSI2 PHY
>
>
>> +
>> +maintainers:
>> + - Bryan O'Donoghue <bod@kernel.org>
>> +
>> +description:
>> + Qualcomm MIPI CSI2 C-PHY/D-PHY combination PHY. Connects MIPI CSI2 sensors
>> + to Qualcomm's Camera CSI Decoder. The PHY supports both C-PHY and D-PHY
>> + modes.
>
> So just to be clear: this is not MIPI CSI, but only the CSI PHY? There
> are no ports here, which seems fine for the phy and will be in the MIPI
> CSI block?
CAMSS ports map to the CSID - CSI Decoder yes.
>
>> +
>> +properties:
>> + compatible:
>> + const: qcom,x1e80100-csi2-phy
>> +
>> + reg:
>> + maxItems: 1
>> +
>> + "#phy-cells":
>> + const: 1
>> +
>> + clocks:
>> + maxItems: 4
>> +
>> + clock-names:
>> + items:
>> + - const: csiphy
>
> probably: core or iface
>
>> + - const: csiphy_timer
>
> timer
>
>> + - const: camnoc_axi
>
> axi or noc
>
>> + - const: cpas_ahb
>
> bus, ahb or cpas, depending whether this is only one ahb or this is bus of
> some cpas subblock
>
> See also: https://lore.kernel.org/all/20260115-sm6150_evk-v3-2-81526dd15543@oss.qualcomm.com/
>
>
>> +
>> + interrupts:
>> + maxItems: 1
>> +
>> + operating-points-v2:
>
> Just true. It is not an array.
LOL I asked a chatbot to review my submission and it told me to change
this from true to a list.
€90 subscription well spent...
Thanks for review.
---
bod
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v3 1/2] dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema
From: Krzysztof Kozlowski @ 2026-02-27 9:41 UTC (permalink / raw)
To: Bryan O'Donoghue
Cc: Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Neil Armstrong,
Bryan O'Donoghue, Vladimir Zapolskiy, linux-arm-msm,
linux-phy, linux-media, devicetree, linux-kernel
In-Reply-To: <20260226-x1e-csi2-phy-v3-1-11e608759410@linaro.org>
On Thu, Feb 26, 2026 at 12:34:25PM +0000, Bryan O'Donoghue wrote:
> Add a base schema initially compatible with x1e80100 to describe MIPI CSI2
> PHY devices.
>
> The hardware can support both C-PHY and D-PHY modes. The CSIPHY devices
> have their own pinouts on the SoC as well as their own individual voltage
> rails.
>
> The need to model voltage rails on a per-PHY basis leads us to define
> CSIPHY devices as individual nodes.
>
> Two nice outcomes in terms of schema and DT arise from this change.
>
> 1. The ability to define on a per-PHY basis voltage rails.
> 2. The ability to require those voltage.
>
> We have had a complete bodge upstream for this where a single set of
> voltage rail for all CSIPHYs has been buried inside of CAMSS.
>
> Much like the I2C bus which is dedicated to Camera sensors - the CCI bus in
> CAMSS parlance, the CSIPHY devices should be individually modelled.
>
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> ---
> .../bindings/phy/qcom,x1e80100-csi2-phy.yaml | 114 +++++++++++++++++++++
> 1 file changed, 114 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml
> new file mode 100644
> index 0000000000000..c937d26ccbda9
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml
> @@ -0,0 +1,114 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/phy/qcom,x1e80100-csi2-phy.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Qualcomm CSI2 PHY
Qualcomm SoC CSI2 PHY
> +
> +maintainers:
> + - Bryan O'Donoghue <bod@kernel.org>
> +
> +description:
> + Qualcomm MIPI CSI2 C-PHY/D-PHY combination PHY. Connects MIPI CSI2 sensors
> + to Qualcomm's Camera CSI Decoder. The PHY supports both C-PHY and D-PHY
> + modes.
So just to be clear: this is not MIPI CSI, but only the CSI PHY? There
are no ports here, which seems fine for the phy and will be in the MIPI
CSI block?
> +
> +properties:
> + compatible:
> + const: qcom,x1e80100-csi2-phy
> +
> + reg:
> + maxItems: 1
> +
> + "#phy-cells":
> + const: 1
> +
> + clocks:
> + maxItems: 4
> +
> + clock-names:
> + items:
> + - const: csiphy
probably: core or iface
> + - const: csiphy_timer
timer
> + - const: camnoc_axi
axi or noc
> + - const: cpas_ahb
bus, ahb or cpas, depending whether this is only one ahb or this is bus of
some cpas subblock
See also: https://lore.kernel.org/all/20260115-sm6150_evk-v3-2-81526dd15543@oss.qualcomm.com/
> +
> + interrupts:
> + maxItems: 1
> +
> + operating-points-v2:
Just true. It is not an array.
> + maxItems: 1
Also opp-table like in other schemas.
> +
> + power-domains:
> + maxItems: 1
> +
> + vdda-0p8-supply:
> + description: Phandle to a 0.8V regulator supply to a PHY.
> +
> + vdda-1p2-supply:
> + description: Phandle to 1.2V regulator supply to a PHY.
> +
> +required:
> + - compatible
> + - reg
> + - "#phy-cells"
> + - clocks
> + - clock-names
> + - interrupts
> + - operating-points-v2
> + - power-domains
> + - vdda-0p8-supply
> + - vdda-1p2-supply
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/interrupt-controller/arm-gic.h>
> + #include <dt-bindings/clock/qcom,x1e80100-camcc.h>
> + #include <dt-bindings/clock/qcom,x1e80100-gcc.h>
> + #include <dt-bindings/phy/phy.h>
> +
> + csiphy@ace4000 {
phy@ or csi-phy@
> + compatible = "qcom,x1e80100-csi2-phy";
> + reg = <0x0ace4000 0x2000>;
> + #phy-cells = <1>;
> +
> + clocks = <&camcc CAM_CC_CSIPHY0_CLK>,
> + <&camcc CAM_CC_CSI0PHYTIMER_CLK>,
> + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>,
> + <&camcc CAM_CC_CPAS_AHB_CLK>;
> + clock-names = "csiphy",
> + "csiphy_timer",
> + "camnoc_axi",
> + "cpas_ahb";
> +
> + operating-points-v2 = <&csiphy_opp_table>;
> +
> + interrupts = <GIC_SPI 477 IRQ_TYPE_EDGE_RISING>;
> +
> + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>;
> +
> + vdda-0p8-supply = <&vreg_l2c_0p8>;
> + vdda-1p2-supply = <&vreg_l1c_1p2>;
> + };
> +
> + csiphy_opp_table: opp-table-csiphy {
Drop entire node, not relevant here.
Best regards,
Krzysztof
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [bug report] phy: qcom: qmp-usbc: Add QCS615 USB/DP PHY config and DP mode support
From: Xiangxu Yin @ 2026-02-27 5:11 UTC (permalink / raw)
To: Konrad Dybcio, Dan Carpenter
Cc: Neil Armstrong, linux-arm-msm, linux-phy, linux-kernel,
Dmitry Baryshkov, li.liu
In-Reply-To: <e110546e-dd18-4ebe-9281-adfbdde98d7a@oss.qualcomm.com>
On 2/17/2026 11:27 PM, Konrad Dybcio wrote:
> On 2/6/26 2:39 PM, Dan Carpenter wrote:
>> [ Smatch checking is paused while we raise funding. #SadFace
>> https://lore.kernel.org/all/aTaiGSbWZ9DJaGo7@stanley.mountain/ -dan ]
>>
>> Hello Xiangxu Yin,
>>
>> Commit 81791c45c8e0 ("phy: qcom: qmp-usbc: Add QCS615 USB/DP PHY
>> config and DP mode support") from Dec 15, 2025 (linux-next), leads to
>> the following Smatch static checker warning:
>>
>> drivers/phy/qualcomm/phy-qcom-qmp-usbc.c:803 qmp_v2_configure_dp_swing()
>> index hardmax out of bounds '(*cfg->swing_tbl)[v_level]' size=4 max='4' rl='0-4'
>>
>> drivers/phy/qualcomm/phy-qcom-qmp-usbc.c
>> 777 static int qmp_v2_configure_dp_swing(struct qmp_usbc *qmp)
>> 778 {
>> 779 const struct qmp_phy_cfg *cfg = qmp->cfg;
>> 780 const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
>> 781 void __iomem *tx = qmp->dp_tx;
>> 782 void __iomem *tx2 = qmp->dp_tx2;
>> 783 unsigned int v_level = 0, p_level = 0;
>> 784 u8 voltage_swing_cfg, pre_emphasis_cfg;
>> 785 int i;
>> 786
>> 787 if (dp_opts->lanes > 4) {
>> 788 dev_err(qmp->dev, "Invalid lane_num(%d)\n", dp_opts->lanes);
>> 789 return -EINVAL;
>> 790 }
>> 791
>> 792 for (i = 0; i < dp_opts->lanes; i++) {
>> 793 v_level = max(v_level, dp_opts->voltage[i]);
>> 794 p_level = max(p_level, dp_opts->pre[i]);
>> 795 }
>> 796
>> 797 if (v_level > 4 || p_level > 4) {
>>
>> These should be >= 4 instead of >.
>>
>> 798 dev_err(qmp->dev, "Invalid v(%d) | p(%d) level)\n",
>> 799 v_level, p_level);
>> 800 return -EINVAL;
>> 801 }
>> 802
>> --> 803 voltage_swing_cfg = (*cfg->swing_tbl)[v_level][p_level];
>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> This is a 4x4 array.
> Thanks Dan for the report
>
> Xiangxu, are you planning to send a patch to address that?
>
> Konrad
Thanks for the notice, Dan & Konrad.
I just got back from a long leave and will submit the relevant patches as soon as possible.
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v3 2/2] phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver
From: Dmitry Baryshkov @ 2026-02-27 1:40 UTC (permalink / raw)
To: Bryan O'Donoghue
Cc: Vinod Koul, Kishon Vijay Abraham I, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Neil Armstrong,
Bryan O'Donoghue, Vladimir Zapolskiy, linux-arm-msm,
linux-phy, linux-media, devicetree, linux-kernel
In-Reply-To: <20260226-x1e-csi2-phy-v3-2-11e608759410@linaro.org>
On Thu, Feb 26, 2026 at 12:34:26PM +0000, Bryan O'Donoghue wrote:
> Add a new MIPI CSI2 driver in DPHY mode initially. The entire set of
> existing CAMSS CSI PHY init sequences are imported in order to save time
> and effort in later patches.
>
> The following devices are supported in this drop:
> "qcom,x1e80100-csi2-phy"
>
> In-line with other PHY drivers the process node is included in the name. At
> the moment we follow the assignment of lane positions - the bitmap of
> physical input lanes to logical lane numbers as a linear list per the
> existing DPHY @lanes data-member.
>
> This is fine for us in upstream at the moment since we also map the lanes
> contiguously but, our hardware can support different lane mappings so we
> should in the future extend out the DPHY structure to capture the mapping.
>
> The Qualcomm 3PH class of PHYs can do both DPHY and CPHY mode. For now only
> DPHY is supported.
>
> In porting some of the logic over from camss-csiphy*.c to here its also
> possible to rationalise some of the code.
>
> In particular use of regulator_bulk and clk_bulk as well as dropping the
> seemingly useless and unused interrupt handler.
>
> The PHY sequences and a lot of the logic that goes with them are well
> proven in CAMSS and mature so the main thing to watch out for here is how
> to get the right sequencing of regulators, clocks and register-writes.
>
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> ---
> MAINTAINERS | 11 +
> drivers/phy/qualcomm/Kconfig | 13 +
> drivers/phy/qualcomm/Makefile | 5 +
> drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c | 384 +++++++++++++++++++++
> drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c | 307 ++++++++++++++++
> drivers/phy/qualcomm/phy-qcom-mipi-csi2.h | 102 ++++++
> 6 files changed, 822 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 62ccdc72384d4..fe19722355d94 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -21542,6 +21542,17 @@ S: Maintained
> F: Documentation/devicetree/bindings/media/qcom,*-iris.yaml
> F: drivers/media/platform/qcom/iris/
>
> +QUALCOMM MIPI CSI2 PHY DRIVER
> +M: Bryan O'Donoghue <bod@kernel.org>
> +L: linux-phy@lists.infradead.org
> +L: linux-media@vger.kernel.org
> +L: linux-arm-msm@vger.kernel.org
> +S: Supported
> +F: Documentation/devicetree/bindings/phy/qcom,*-csi2-phy.yaml
> +F: drivers/phy/qualcomm/phy-qcom-mipi-csi2*.c
> +F: drivers/phy/qualcomm/phy-qcom-mipi-csi2*.h
> +F: include/dt-bindings/phy/phy-qcom-mipi-csi2*
> +
> QUALCOMM NAND CONTROLLER DRIVER
> M: Manivannan Sadhasivam <mani@kernel.org>
> L: linux-mtd@lists.infradead.org
> diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig
> index 60a0ead127fa9..ea33025a40fd0 100644
> --- a/drivers/phy/qualcomm/Kconfig
> +++ b/drivers/phy/qualcomm/Kconfig
> @@ -28,6 +28,19 @@ config PHY_QCOM_EDP
> Enable this driver to support the Qualcomm eDP PHY found in various
> Qualcomm chipsets.
>
> +config PHY_QCOM_MIPI_CSI2
> + tristate "Qualcomm MIPI CSI2 PHY driver"
> + depends on ARCH_QCOM || COMPILE_TEST
> + depends on OF
> + depends on COMMON_CLK
> + select GENERIC_PHY
> + select GENERIC_PHY_MIPI_DPHY
> + help
> + Enable this to support the MIPI CSI2 PHY driver found in various
> + Qualcomm chipsets. This PHY is used to connect MIPI CSI2
> + camera sensors to the CSI Decoder in the Qualcomm Camera Subsystem
> + CAMSS.
> +
> config PHY_QCOM_IPQ4019_USB
> tristate "Qualcomm IPQ4019 USB PHY driver"
> depends on OF && (ARCH_QCOM || COMPILE_TEST)
> diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile
> index b71a6a0bed3f1..382cb594b06b6 100644
> --- a/drivers/phy/qualcomm/Makefile
> +++ b/drivers/phy/qualcomm/Makefile
> @@ -6,6 +6,11 @@ obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) += phy-qcom-ipq4019-usb.o
> obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o
> obj-$(CONFIG_PHY_QCOM_M31_USB) += phy-qcom-m31.o
> obj-$(CONFIG_PHY_QCOM_M31_EUSB) += phy-qcom-m31-eusb2.o
> +
> +phy-qcom-mipi-csi2-objs += phy-qcom-mipi-csi2-core.o \
> + phy-qcom-mipi-csi2-3ph-dphy.o
> +obj-$(CONFIG_PHY_QCOM_MIPI_CSI2) += phy-qcom-mipi-csi2.o
> +
> obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o
>
> obj-$(CONFIG_PHY_QCOM_QMP_COMBO) += phy-qcom-qmp-combo.o phy-qcom-qmp-usbc.o
> diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c
> new file mode 100644
> index 0000000000000..f9f3451e9a5e1
> --- /dev/null
> +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c
> @@ -0,0 +1,384 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * camss-phy_qcom_mipi_csi2-3ph-1-0.c
And it doesn't match the driver anymore. Please drop it.
> + *
> + * Qualcomm MSM Camera Subsystem - CSIPHY Module 3phase v1.0
> + *
> + * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
> + * Copyright (C) 2016-2025 Linaro Ltd.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/time64.h>
> +
> +#include "phy-qcom-mipi-csi2.h"
> +
> +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(offset, n) ((offset) + 0x4 * (n))
> +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL0_PHY_SW_RESET BIT(0)
> +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE BIT(7)
> +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_COMMON_PWRDN_B BIT(0)
> +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_SHOW_REV_ID BIT(1)
> +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL10_IRQ_CLEAR_CMD BIT(0)
> +#define CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(offset, n) ((offset) + 0xb0 + 0x4 * (n))
> +
> +/*
> + * 3 phase CSI has 19 common status regs with only 0-10 being used
> + * and 11-18 being reserved.
> + */
> +#define CSI_COMMON_STATUS_NUM 11
> +/*
> + * There are a number of common control registers
> + * The offset to clear the CSIPHY IRQ status starts @ 22
> + * So to clear CSI_COMMON_STATUS0 this is CSI_COMMON_CONTROL22, STATUS1 is
> + * CONTROL23 and so on
> + */
> +#define CSI_CTRL_STATUS_INDEX 22
> +
> +/*
> + * There are 43 COMMON_CTRL registers with regs after # 33 being reserved
> + */
> +#define CSI_CTRL_MAX 33
> +
> +#define CSIPHY_DEFAULT_PARAMS 0
> +#define CSIPHY_LANE_ENABLE 1
Unused
> +#define CSIPHY_SETTLE_CNT_LOWER_BYTE 2
> +#define CSIPHY_SETTLE_CNT_HIGHER_BYTE 3
Unused
> +#define CSIPHY_DNP_PARAMS 4
> +#define CSIPHY_2PH_REGS 5
> +#define CSIPHY_3PH_REGS 6
Both are unused
> +#define CSIPHY_SKEW_CAL 7
> +
> +/* 4nm 2PH v 2.1.2 2p5Gbps 4 lane DPHY mode */
> +static const struct
> +mipi_csi2phy_lane_regs lane_regs_x1e80100[] = {
> + /* Power up lanes 2ph mode */
> + {.reg_addr = 0x1014, .reg_data = 0xD5, .param_type = CSIPHY_DEFAULT_PARAMS},
As you are moving the driver, it might also make sense to split / rework
the huge table with the code sequence. The code is easier to adapt.
As you can see in the tables, there are repetitive code patterns, which
correspond to the lane programming. Once that is extracted, it would be
much, much easier to manipulate the data.
It's fine if you are just moving the data with the intention of
improving it later, but then please state so in the commit message.
Also, please use low-case hex, I think it was a recommended practice
nowadays.
> + {.reg_addr = 0x101C, .reg_data = 0x7A, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x1018, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
> +
> + {.reg_addr = 0x0094, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x00A0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0090, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0098, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0094, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0030, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0000, .reg_data = 0x8E, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0038, .reg_data = 0xFE, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x002C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0034, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x001C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0014, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x003C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0004, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0020, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0008, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE},
> + {.reg_addr = 0x0010, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0094, .reg_data = 0xD7, .param_type = CSIPHY_SKEW_CAL},
> + {.reg_addr = 0x005C, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL},
> + {.reg_addr = 0x0060, .reg_data = 0xBD, .param_type = CSIPHY_SKEW_CAL},
> + {.reg_addr = 0x0064, .reg_data = 0x7F, .param_type = CSIPHY_SKEW_CAL},
> +
> + {.reg_addr = 0x0E94, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0EA0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0E90, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0E98, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0E94, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0E30, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0E28, .reg_data = 0x04, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0E00, .reg_data = 0x80, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0E0C, .reg_data = 0xFF, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0E38, .reg_data = 0x1F, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0E2C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0E34, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0E1C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0E14, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0E3C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0E04, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0E20, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0E08, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE},
> + {.reg_addr = 0x0E10, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS},
> +
> + {.reg_addr = 0x0494, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x04A0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0490, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0498, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0494, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0430, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0400, .reg_data = 0x8E, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0438, .reg_data = 0xFE, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x042C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0434, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x041C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0414, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x043C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0404, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0420, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0408, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE},
> + {.reg_addr = 0x0410, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0494, .reg_data = 0xD7, .param_type = CSIPHY_SKEW_CAL},
> + {.reg_addr = 0x045C, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL},
> + {.reg_addr = 0x0460, .reg_data = 0xBD, .param_type = CSIPHY_SKEW_CAL},
> + {.reg_addr = 0x0464, .reg_data = 0x7F, .param_type = CSIPHY_SKEW_CAL},
> +
> + {.reg_addr = 0x0894, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x08A0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0890, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0898, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0894, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0830, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0800, .reg_data = 0x8E, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0838, .reg_data = 0xFE, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x082C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0834, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x081C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0814, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x083C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0804, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0820, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0808, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE},
> + {.reg_addr = 0x0810, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0894, .reg_data = 0xD7, .param_type = CSIPHY_SKEW_CAL},
> + {.reg_addr = 0x085C, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL},
> + {.reg_addr = 0x0860, .reg_data = 0xBD, .param_type = CSIPHY_SKEW_CAL},
> + {.reg_addr = 0x0864, .reg_data = 0x7F, .param_type = CSIPHY_SKEW_CAL},
> +
> + {.reg_addr = 0x0C94, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0CA0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0C90, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0C98, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0C94, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0C30, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0C00, .reg_data = 0x8E, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0C38, .reg_data = 0xFE, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0C2C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0C34, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0C1C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0C14, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0C3C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0C04, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0C20, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0C08, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE},
> + {.reg_addr = 0x0C10, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS},
> + {.reg_addr = 0x0C94, .reg_data = 0xD7, .param_type = CSIPHY_SKEW_CAL},
> + {.reg_addr = 0x0C5C, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL},
> + {.reg_addr = 0x0C60, .reg_data = 0xBD, .param_type = CSIPHY_SKEW_CAL},
> + {.reg_addr = 0x0C64, .reg_data = 0x7F, .param_type = CSIPHY_SKEW_CAL},
> +};
> +
> +static inline const struct mipi_csi2phy_device_regs *
> +csi2phy_dev_to_regs(struct mipi_csi2phy_device *csi2phy)
> +{
> + return &csi2phy->soc_cfg->reg_info;
> +}
> +
> +static void phy_qcom_mipi_csi2_hw_version_read(struct mipi_csi2phy_device *csi2phy)
> +{
> + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy);
> + u32 tmp;
> +
> + writel(CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_SHOW_REV_ID, csi2phy->base +
> + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6));
> +
> + tmp = readl_relaxed(csi2phy->base +
> + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 12));
> + csi2phy->hw_version = tmp;
> +
> + tmp = readl_relaxed(csi2phy->base +
> + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 13));
> + csi2phy->hw_version |= (tmp << 8) & 0xFF00;
> +
> + tmp = readl_relaxed(csi2phy->base +
> + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 14));
> + csi2phy->hw_version |= (tmp << 16) & 0xFF0000;
> +
> + tmp = readl_relaxed(csi2phy->base +
> + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 15));
> + csi2phy->hw_version |= (tmp << 24) & 0xFF000000;
> +
> + dev_dbg_once(csi2phy->dev, "CSIPHY 3PH HW Version = 0x%08x\n", csi2phy->hw_version);
> +}
> +
> +/*
> + * phy_qcom_mipi_csi2_reset - Perform software reset on CSIPHY module
> + * @phy_qcom_mipi_csi2: CSIPHY device
> + */
> +static void phy_qcom_mipi_csi2_reset(struct mipi_csi2phy_device *csi2phy)
> +{
> + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy);
> +
> + writel(CSIPHY_3PH_CMN_CSI_COMMON_CTRL0_PHY_SW_RESET,
> + csi2phy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0));
> + usleep_range(5000, 8000);
> + writel(0x0, csi2phy->base +
> + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0));
> +}
> +
> +/*
> + * phy_qcom_mipi_csi2_settle_cnt_calc - Calculate settle count value
> + *
> + * Helper function to calculate settle count value. This is
> + * based on the CSI2 T_hs_settle parameter which in turn
> + * is calculated based on the CSI2 transmitter link frequency.
> + *
> + * Return settle count value or 0 if the CSI2 link frequency
> + * is not available
> + */
> +static u8 phy_qcom_mipi_csi2_settle_cnt_calc(s64 link_freq, u32 timer_clk_rate)
> +{
> + u32 t_hs_prepare_max_ps;
> + u32 timer_period_ps;
> + u32 t_hs_settle_ps;
> + u8 settle_cnt;
> + u32 ui_ps;
> +
> + if (link_freq <= 0)
> + return 0;
> +
> + ui_ps = div_u64(PSEC_PER_SEC, link_freq);
> + ui_ps /= 2;
> + t_hs_prepare_max_ps = 85000 + 6 * ui_ps;
> + t_hs_settle_ps = t_hs_prepare_max_ps;
> +
> + timer_period_ps = div_u64(PSEC_PER_SEC, timer_clk_rate);
> + settle_cnt = t_hs_settle_ps / timer_period_ps - 6;
> +
> + return settle_cnt;
> +}
> +
> +static void
> +phy_qcom_mipi_csi2_gen2_config_lanes(struct mipi_csi2phy_device *csi2phy,
> + u8 settle_cnt)
> +{
> + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy);
> + const struct mipi_csi2phy_lane_regs *r = regs->init_seq;
> + int i, array_size = regs->lane_array_size;
> + u32 val;
> +
> + for (i = 0; i < array_size; i++, r++) {
> + switch (r->param_type) {
> + case CSIPHY_SETTLE_CNT_LOWER_BYTE:
> + val = settle_cnt & 0xff;
> + break;
> + case CSIPHY_SKEW_CAL:
> + /* TODO: support application of skew from dt flag */
> + continue;
> + default:
> + val = r->reg_data;
> + break;
> + }
> + writel(val, csi2phy->base + r->reg_addr);
> + if (r->delay_us)
> + udelay(r->delay_us);
> + }
> +}
> +
> +static int phy_qcom_mipi_csi2_lanes_enable(struct mipi_csi2phy_device *csi2phy,
> + struct mipi_csi2phy_stream_cfg *cfg)
> +{
> + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy);
> + struct mipi_csi2phy_lanes_cfg *lane_cfg = &cfg->lane_cfg;
> + u8 settle_cnt;
> + u8 val;
> + int i;
> +
> + settle_cnt = phy_qcom_mipi_csi2_settle_cnt_calc(cfg->link_freq, csi2phy->timer_clk_rate);
> +
> + val = CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE;
> + for (i = 0; i < cfg->num_data_lanes; i++)
> + val |= BIT(lane_cfg->data[i].pos * 2);
> +
> + writel(val, csi2phy->base +
> + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 5));
> +
> + val = CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_COMMON_PWRDN_B;
> + writel(val, csi2phy->base +
> + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6));
> +
> + val = 0x02;
> + writel(val, csi2phy->base +
> + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 7));
> +
> + val = 0x00;
> + writel(val, csi2phy->base +
> + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0));
> +
> + phy_qcom_mipi_csi2_gen2_config_lanes(csi2phy, settle_cnt);
> +
> + /* IRQ_MASK registers - disable all interrupts */
> + for (i = CSI_COMMON_STATUS_NUM; i < CSI_CTRL_STATUS_INDEX; i++) {
> + writel(0, csi2phy->base +
> + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, i));
> + }
> +
> + return 0;
> +}
> +
> +static void
> +phy_qcom_mipi_csi2_lanes_disable(struct mipi_csi2phy_device *csi2phy,
> + struct mipi_csi2phy_stream_cfg *cfg)
> +{
> + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy);
> +
> + writel(0, csi2phy->base +
> + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 5));
> +
> + writel(0, csi2phy->base +
> + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6));
> +}
> +
> +static const struct mipi_csi2phy_hw_ops phy_qcom_mipi_csi2_ops_3ph_1_0 = {
> + .hw_version_read = phy_qcom_mipi_csi2_hw_version_read,
> + .reset = phy_qcom_mipi_csi2_reset,
> + .lanes_enable = phy_qcom_mipi_csi2_lanes_enable,
> + .lanes_disable = phy_qcom_mipi_csi2_lanes_disable,
> +};
> +
> +static const struct mipi_csi2phy_clk_freq zero = { 0 };
> +
> +static const struct mipi_csi2phy_clk_freq dphy_4nm_x1e_csiphy = {
> + .freq = {
> + 300000000, 400000000, 480000000
> + },
> + .num_freq = 3,
> +};
> +
> +static const struct mipi_csi2phy_clk_freq dphy_4nm_x1e_csiphy_timer = {
> + .freq = {
> + 266666667, 400000000
> + },
> + .num_freq = 2,
As you are migrating to a modern codebase, these values should be set
via the OPP tables instead.
> +};
> +
> +static const char * const x1e_clks[] = {
> + "camnoc_axi",
> + "cpas_ahb",
> + "csiphy",
> + "csiphy_timer"
> +};
> +
> +const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e = {
> + .ops = &phy_qcom_mipi_csi2_ops_3ph_1_0,
> + .reg_info = {
> + .init_seq = lane_regs_x1e80100,
> + .lane_array_size = ARRAY_SIZE(lane_regs_x1e80100),
> + .common_regs_offset = 0x1000,
> + .generation = GEN2,
Does this generation match anything in the actual hardware?
> + },
> + .supply_names = (const char *[]){
> + "vdda-0p8",
> + "vdda-1p2"
> + },
> + .num_supplies = 2,
> + .clk_names = (const char **)x1e_clks,
> + .num_clk = ARRAY_SIZE(x1e_clks),
> + .opp_clk = x1e_clks[2],
> + .timer_clk = x1e_clks[3],
> + .clk_freq = {
> + zero,
> + zero,
> + dphy_4nm_x1e_csiphy,
> + dphy_4nm_x1e_csiphy_timer,
> + },
> +};
> diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c
> new file mode 100644
> index 0000000000000..454144f81b719
> --- /dev/null
> +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c
> @@ -0,0 +1,307 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2025, Linaro Ltd.
> + */
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/pm_opp.h>
> +#include <linux/phy/phy.h>
> +#include <linux/phy/phy-mipi-dphy.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/reset.h>
> +#include <linux/slab.h>
> +
> +#include "phy-qcom-mipi-csi2.h"
> +
> +#define CAMSS_CLOCK_MARGIN_NUMERATOR 105
> +#define CAMSS_CLOCK_MARGIN_DENOMINATOR 100
> +
> +static inline void phy_qcom_mipi_csi2_add_clock_margin(u64 *rate)
> +{
> + *rate *= CAMSS_CLOCK_MARGIN_NUMERATOR;
> + *rate = div_u64(*rate, CAMSS_CLOCK_MARGIN_DENOMINATOR);
> +}
> +
> +static int
> +phy_qcom_mipi_csi2_set_clock_rates(struct mipi_csi2phy_device *csi2phy,
> + s64 link_freq)
> +{
> + const struct mipi_csi2phy_soc_cfg *soc_cfg = csi2phy->soc_cfg;
> + unsigned long rates[MAX_CSI2PHY_CLKS] = {0};
> + struct device *dev = csi2phy->dev;
> + unsigned long vote_freq = 0;
> + int i, j;
> + int ret;
> +
> + for (i = 0; i < soc_cfg->num_clk; i++) {
> + const struct mipi_csi2phy_clk_freq *clk_freq = &soc_cfg->clk_freq[i];
> + const char *clk_name = soc_cfg->clk_names[i];
> + struct clk *clk = csi2phy->clks[i].clk;
> + u64 min_rate = link_freq / 4;
> + long round_rate;
> +
> + phy_qcom_mipi_csi2_add_clock_margin(&min_rate);
> +
> + /* This clock should be enabled only not set */
> + if (!clk_freq->num_freq)
> + continue;
> +
> + for (j = 0; j < clk_freq->num_freq; j++)
> + if (min_rate < clk_freq->freq[j])
> + break;
> +
> + if (j == clk_freq->num_freq) {
> + dev_err(dev,
> + "Pixel clock %llu is too high for %s\n",
> + min_rate, clk_name);
> + return -EINVAL;
> + }
> +
> + /* if sensor pixel clock is not available
> + * set highest possible CSIPHY clock rate
> + */
> + if (min_rate == 0)
> + j = clk_freq->num_freq - 1;
> +
> + round_rate = clk_round_rate(clk, clk_freq->freq[j]);
> + if (round_rate < 0) {
> + dev_err(dev, "clk round rate failed: %ld\n",
> + round_rate);
> + return -EINVAL;
> + }
All of this code looks like a poor man's implementation of the OPP
handling, finding the highest possible clock rate, etc.
> +
> + rates[i] = round_rate;
> +
> + if (!strcmp(clk_name, soc_cfg->timer_clk))
> + csi2phy->timer_clk_rate = round_rate;
> +
> + if (!strcmp(clk_name, soc_cfg->opp_clk))
> + vote_freq = round_rate;
> + }
> +
> + if (!vote_freq) {
> + dev_err(dev, "Unable to find operating point frequency\n");
> + return -ENODEV;
> + };
> +
> + dev_dbg(dev, "OPP freq: %lu Hz\n", vote_freq);
> +
> + ret = dev_pm_opp_set_rate(dev, vote_freq);
> + if (ret < 0) {
> + dev_err(dev, "Failed to set OPP rate: %d\n", ret);
> + return ret;
> + }
> +
> + for (i = 0; i < soc_cfg->num_clk; i++) {
> + if (rates[i] == 0)
> + continue;
> +
> + dev_dbg(dev, "Setting clk %s to %lu Hz\n",
> + soc_cfg->clk_names[i], rates[i]);
> +
> + ret = clk_set_rate(csi2phy->clks[i].clk, rates[i]);
> + if (ret < 0) {
> + dev_err(dev, "clk_set_rate failed for %s: %d\n",
> + soc_cfg->clk_names[i], ret);
> + return ret;
> + }
> + }
> +
> + return 0;
> +}
> +
--
With best wishes
Dmitry
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH RESEND2 net-next 0/8] net: stmmac: qcom-ethqos: further serdes reorganisation
From: Jakub Kicinski @ 2026-02-27 1:26 UTC (permalink / raw)
To: Russell King (Oracle)
Cc: Andrew Lunn, Alexandre Torgue, Andrew Lunn, David S. Miller,
Eric Dumazet, linux-arm-kernel, linux-arm-msm, linux-phy,
linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
Paolo Abeni, Vinod Koul
In-Reply-To: <aaDSJAc-x2-klvHJ@shell.armlinux.org.uk>
On Thu, 26 Feb 2026 23:07:16 +0000 Russell King (Oracle) wrote:
> Subject: [PATCH RESEND2 net-next 0/8] net: stmmac: qcom-ethqos: further serdes reorganisation
The only exception to the 24h rule is if a reviewer _asks_ you
to repost ASAP. Maintainers also wait, there are no exceptions.
Please don't do this again. Having to deal with multi-tier system
of privileges and rules will make our (maintainers) job even more
miserable than it already is.
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH RESEND2 net-next 8/8] net: stmmac: qcom-ethqos: remove phy_set_mode_ext() after phy_power_on()
From: Russell King (Oracle) @ 2026-02-26 23:09 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, linux-arm-kernel, linux-arm-msm, linux-phy,
linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
Paolo Abeni, Vinod Koul
In-Reply-To: <aaDSJAc-x2-klvHJ@shell.armlinux.org.uk>
The call to phy_set_mode_ext() after phy_power_on() was a work-around
for the qcom-sgmii-eth SerDes driver that only re-enabled its clocks on
phy_power_on() but did not configure the PHY. Now that the SerDes driver
fully configures the SerDes at phy_power_on(), there is no need to call
phy_set_mode_ext() immediately afterwards.
This also means we no longer need to record the previous operating mode
of the driver - this is up to the SerDes driver. In any case, the only
thing that we care about is the SerDes provides the necessary clocks to
the stmmac core to allow it to reset at this point. The actual mode is
irrelevant at this point as the correct mode will be configured in
ethqos_mac_finish_serdes() just before the network device is brought
online.
Reviewed-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Tested-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
.../stmicro/stmmac/dwmac-qcom-ethqos.c | 18 ++----------------
1 file changed, 2 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index 8913f6f02b9e..cb1c074c2053 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -105,7 +105,6 @@ struct qcom_ethqos {
struct clk *link_clk;
struct phy *serdes_phy;
- phy_interface_t serdes_mode;
phy_interface_t phy_mode;
const struct ethqos_emac_por *rgmii_por;
@@ -648,17 +647,8 @@ static int qcom_ethqos_serdes_powerup(struct net_device *ndev, void *priv)
return ret;
ret = phy_power_on(ethqos->serdes_phy);
- if (ret) {
- phy_exit(ethqos->serdes_phy);
- return ret;
- }
-
- ret = phy_set_mode_ext(ethqos->serdes_phy, PHY_MODE_ETHERNET,
- ethqos->serdes_mode);
- if (ret) {
- phy_power_off(ethqos->serdes_phy);
+ if (ret)
phy_exit(ethqos->serdes_phy);
- }
return ret;
}
@@ -681,12 +671,9 @@ static int ethqos_mac_finish_serdes(struct net_device *ndev, void *priv,
qcom_ethqos_set_sgmii_loopback(ethqos, false);
if (interface == PHY_INTERFACE_MODE_SGMII ||
- interface == PHY_INTERFACE_MODE_2500BASEX) {
+ interface == PHY_INTERFACE_MODE_2500BASEX)
ret = phy_set_mode_ext(ethqos->serdes_phy, PHY_MODE_ETHERNET,
interface);
- if (ret == 0)
- ethqos->serdes_mode = interface;
- }
return ret;
}
@@ -839,7 +826,6 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
plat_dat->host_dma_width = data->dma_addr_width;
if (ethqos->serdes_phy) {
- ethqos->serdes_mode = PHY_INTERFACE_MODE_SGMII;
plat_dat->serdes_powerup = qcom_ethqos_serdes_powerup;
plat_dat->serdes_powerdown = qcom_ethqos_serdes_powerdown;
}
--
2.47.3
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH RESEND2 net-next 7/8] phy: qcom-sgmii-eth: relax order of .power_on() vs .set_mode*()
From: Russell King (Oracle) @ 2026-02-26 23:09 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, linux-arm-kernel, linux-arm-msm, linux-phy,
linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
Paolo Abeni, Vinod Koul
In-Reply-To: <aaDSJAc-x2-klvHJ@shell.armlinux.org.uk>
Allow any order of the .power_on() and .set_mode*() methods as per the
recent discussion. This means phy_power_on() with this SerDes will now
restore the previous setup without requiring a subsequent
phy_set_mode*() call.
Tested-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
index 6332ff291fdf..f48faa2929a6 100644
--- a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
+++ b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
@@ -271,8 +271,17 @@ static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy)
static int qcom_dwmac_sgmii_phy_power_on(struct phy *phy)
{
struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
+ int ret;
+
+ ret = clk_prepare_enable(data->refclk);
+ if (ret < 0)
+ return ret;
- return clk_prepare_enable(data->refclk);
+ ret = qcom_dwmac_sgmii_phy_calibrate(phy);
+ if (ret < 0)
+ clk_disable_unprepare(data->refclk);
+
+ return ret;
}
static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy)
@@ -318,6 +327,9 @@ static int qcom_dwmac_sgmii_phy_set_mode(struct phy *phy, enum phy_mode mode,
if (submode != data->interface)
data->interface = submode;
+ if (phy->power_count == 0)
+ return 0;
+
return qcom_dwmac_sgmii_phy_calibrate(phy);
}
--
2.47.3
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH RESEND2 net-next 6/8] phy: qcom-sgmii-eth: remove qcom_dwmac_sgmii_phy_interface()
From: Russell King (Oracle) @ 2026-02-26 23:09 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, linux-arm-kernel, linux-arm-msm, linux-phy,
linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
Paolo Abeni, Vinod Koul
In-Reply-To: <aaDSJAc-x2-klvHJ@shell.armlinux.org.uk>
Now that qcom_dwmac_sgmii_phy_interface() only serves to validate the
passed interface mode, combine it with qcom_dwmac_sgmii_phy_validate(),
and use qcom_dwmac_sgmii_phy_validate() to validate the mode in
qcom_dwmac_sgmii_phy_set_mode().
Tested-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 27 +++++++++--------------
1 file changed, 10 insertions(+), 17 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
index 58ff15601206..6332ff291fdf 100644
--- a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
+++ b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
@@ -290,7 +290,9 @@ static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy)
return 0;
}
-static int qcom_dwmac_sgmii_phy_interface(enum phy_mode mode, int submode)
+static int qcom_dwmac_sgmii_phy_validate(struct phy *phy, enum phy_mode mode,
+ int submode,
+ union phy_configure_opts *opts)
{
if (mode != PHY_MODE_ETHERNET)
return -EINVAL;
@@ -298,7 +300,7 @@ static int qcom_dwmac_sgmii_phy_interface(enum phy_mode mode, int submode)
if (submode == PHY_INTERFACE_MODE_SGMII ||
submode == PHY_INTERFACE_MODE_1000BASEX ||
submode == PHY_INTERFACE_MODE_2500BASEX)
- return submode;
+ return 0;
return -EINVAL;
}
@@ -307,27 +309,18 @@ static int qcom_dwmac_sgmii_phy_set_mode(struct phy *phy, enum phy_mode mode,
int submode)
{
struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
- int interface;
+ int ret;
- interface = qcom_dwmac_sgmii_phy_interface(mode, submode);
- if (interface < 0)
- return interface;
+ ret = qcom_dwmac_sgmii_phy_validate(phy, mode, submode, NULL);
+ if (ret)
+ return ret;
- if (interface != data->interface)
- data->interface = interface;
+ if (submode != data->interface)
+ data->interface = submode;
return qcom_dwmac_sgmii_phy_calibrate(phy);
}
-static int qcom_dwmac_sgmii_phy_validate(struct phy *phy, enum phy_mode mode,
- int submode,
- union phy_configure_opts *opts)
-{
- int ret = qcom_dwmac_sgmii_phy_interface(mode, submode);
-
- return ret < 0 ? ret : 0;
-}
-
static const struct phy_ops qcom_dwmac_sgmii_phy_ops = {
.power_on = qcom_dwmac_sgmii_phy_power_on,
.power_off = qcom_dwmac_sgmii_phy_power_off,
--
2.47.3
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH RESEND2 net-next 5/8] phy: qcom-sgmii-eth: use PHY interface mode for SerDes settings
From: Russell King (Oracle) @ 2026-02-26 23:09 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, linux-arm-kernel, linux-arm-msm, linux-phy,
linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
Paolo Abeni, Vinod Koul
In-Reply-To: <aaDSJAc-x2-klvHJ@shell.armlinux.org.uk>
As established in the previous commit, using SPEED_1000 and SPEED_2500
does not make sense for a SerDes due to the PCS encoding that is used
over the SerDes link, which inflates the data rate at the SerDes. Thus,
the use of these constants in a SerDes driver is incorrect.
Since qcom-sgmii-eth no longer implements phy_set_speed(), but instead
uses the PHY interface mode passed via the .set_mode() method, convert
the driver to use the PHY interface mode internally to decide whether
to configure the SerDes for 1.25Gbps or 3.125Gbps mode.
Tested-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 41 ++++++++++++-----------
1 file changed, 21 insertions(+), 20 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
index dcfdb7d0e8ea..58ff15601206 100644
--- a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
+++ b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
@@ -29,7 +29,7 @@
struct qcom_dwmac_sgmii_phy_data {
struct regmap *regmap;
struct clk *refclk;
- int speed;
+ phy_interface_t interface;
};
static void qcom_dwmac_sgmii_phy_init_1g(struct regmap *regmap)
@@ -223,15 +223,18 @@ static int qcom_dwmac_sgmii_phy_calibrate(struct phy *phy)
struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
struct device *dev = phy->dev.parent;
- switch (data->speed) {
- case SPEED_10:
- case SPEED_100:
- case SPEED_1000:
+ switch (data->interface) {
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_1000BASEX:
+ /* 1.25Gbps mode */
qcom_dwmac_sgmii_phy_init_1g(data->regmap);
break;
- case SPEED_2500:
+ case PHY_INTERFACE_MODE_2500BASEX:
+ /* 3.125Gbps mode */
qcom_dwmac_sgmii_phy_init_2p5g(data->regmap);
break;
+ default:
+ return -EINVAL;
}
if (qcom_dwmac_sgmii_phy_poll_status(data->regmap,
@@ -287,17 +290,15 @@ static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy)
return 0;
}
-static int qcom_dwmac_sgmii_phy_speed(enum phy_mode mode, int submode)
+static int qcom_dwmac_sgmii_phy_interface(enum phy_mode mode, int submode)
{
if (mode != PHY_MODE_ETHERNET)
return -EINVAL;
if (submode == PHY_INTERFACE_MODE_SGMII ||
- submode == PHY_INTERFACE_MODE_1000BASEX)
- return SPEED_1000;
-
- if (submode == PHY_INTERFACE_MODE_2500BASEX)
- return SPEED_2500;
+ submode == PHY_INTERFACE_MODE_1000BASEX ||
+ submode == PHY_INTERFACE_MODE_2500BASEX)
+ return submode;
return -EINVAL;
}
@@ -306,14 +307,14 @@ static int qcom_dwmac_sgmii_phy_set_mode(struct phy *phy, enum phy_mode mode,
int submode)
{
struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
- int speed;
+ int interface;
- speed = qcom_dwmac_sgmii_phy_speed(mode, submode);
- if (speed < 0)
- return speed;
+ interface = qcom_dwmac_sgmii_phy_interface(mode, submode);
+ if (interface < 0)
+ return interface;
- if (speed != data->speed)
- data->speed = speed;
+ if (interface != data->interface)
+ data->interface = interface;
return qcom_dwmac_sgmii_phy_calibrate(phy);
}
@@ -322,7 +323,7 @@ static int qcom_dwmac_sgmii_phy_validate(struct phy *phy, enum phy_mode mode,
int submode,
union phy_configure_opts *opts)
{
- int ret = qcom_dwmac_sgmii_phy_speed(mode, submode);
+ int ret = qcom_dwmac_sgmii_phy_interface(mode, submode);
return ret < 0 ? ret : 0;
}
@@ -356,7 +357,7 @@ static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev)
if (!data)
return -ENOMEM;
- data->speed = SPEED_10;
+ data->interface = PHY_INTERFACE_MODE_SGMII;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
--
2.47.3
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH RESEND2 net-next 4/8] phy: qcom-sgmii-eth: remove .set_speed() implementation
From: Russell King (Oracle) @ 2026-02-26 23:09 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, linux-arm-kernel, linux-arm-msm, linux-phy,
linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
Paolo Abeni, Vinod Koul
In-Reply-To: <aaDSJAc-x2-klvHJ@shell.armlinux.org.uk>
Now that the qcom-ethqos driver has migrated to use phy_set_mode_ext()
rather than phy_set_speed() to configure the SerDes, the support for
phy_set_speed() is now obsolete. Remove support for this method.
Using the MAC speed for the SerDes is never correct due to the PCS
encoding. For SGMII and 2500BASE-X, the PCS uses 8B10B encoding, and
so:
MAC rate * PCS output bits / PCS input bits = SerDes rate
1000M * 10 / 8 = 1250M
2500M * 10 / 8 = 3125M
Tested-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
index 4ea3dce7719f..dcfdb7d0e8ea 100644
--- a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
+++ b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
@@ -318,16 +318,6 @@ static int qcom_dwmac_sgmii_phy_set_mode(struct phy *phy, enum phy_mode mode,
return qcom_dwmac_sgmii_phy_calibrate(phy);
}
-static int qcom_dwmac_sgmii_phy_set_speed(struct phy *phy, int speed)
-{
- struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
-
- if (speed != data->speed)
- data->speed = speed;
-
- return qcom_dwmac_sgmii_phy_calibrate(phy);
-}
-
static int qcom_dwmac_sgmii_phy_validate(struct phy *phy, enum phy_mode mode,
int submode,
union phy_configure_opts *opts)
@@ -341,7 +331,6 @@ static const struct phy_ops qcom_dwmac_sgmii_phy_ops = {
.power_on = qcom_dwmac_sgmii_phy_power_on,
.power_off = qcom_dwmac_sgmii_phy_power_off,
.set_mode = qcom_dwmac_sgmii_phy_set_mode,
- .set_speed = qcom_dwmac_sgmii_phy_set_speed,
.validate = qcom_dwmac_sgmii_phy_validate,
.calibrate = qcom_dwmac_sgmii_phy_calibrate,
.owner = THIS_MODULE,
--
2.47.3
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH RESEND2 net-next 3/8] net: stmmac: qcom-ethqos: convert to use phy_set_mode_ext()
From: Russell King (Oracle) @ 2026-02-26 23:09 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, linux-arm-kernel, linux-arm-msm, linux-phy,
linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
Paolo Abeni, Vinod Koul
In-Reply-To: <aaDSJAc-x2-klvHJ@shell.armlinux.org.uk>
qcom-sgmii-eth now accepts the phy_set_mode*() calls to configure the
SerDes, taking a PHY interface mode rather than a speed. This allows
the elimination of the interface mode to speed conversion in
ethqos_mac_finish_serdes().
Tested-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
.../stmicro/stmmac/dwmac-qcom-ethqos.c | 23 ++++++++-----------
1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index 57cbe800f652..8913f6f02b9e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -105,7 +105,7 @@ struct qcom_ethqos {
struct clk *link_clk;
struct phy *serdes_phy;
- int serdes_speed;
+ phy_interface_t serdes_mode;
phy_interface_t phy_mode;
const struct ethqos_emac_por *rgmii_por;
@@ -653,7 +653,8 @@ static int qcom_ethqos_serdes_powerup(struct net_device *ndev, void *priv)
return ret;
}
- ret = phy_set_speed(ethqos->serdes_phy, ethqos->serdes_speed);
+ ret = phy_set_mode_ext(ethqos->serdes_phy, PHY_MODE_ETHERNET,
+ ethqos->serdes_mode);
if (ret) {
phy_power_off(ethqos->serdes_phy);
phy_exit(ethqos->serdes_phy);
@@ -675,20 +676,16 @@ static int ethqos_mac_finish_serdes(struct net_device *ndev, void *priv,
phy_interface_t interface)
{
struct qcom_ethqos *ethqos = priv;
- int speed, ret = 0;
+ int ret = 0;
qcom_ethqos_set_sgmii_loopback(ethqos, false);
- speed = SPEED_UNKNOWN;
- if (interface == PHY_INTERFACE_MODE_SGMII)
- speed = SPEED_1000;
- else if (interface == PHY_INTERFACE_MODE_2500BASEX)
- speed = SPEED_2500;
-
- if (speed != SPEED_UNKNOWN && speed != ethqos->serdes_speed) {
- ret = phy_set_speed(ethqos->serdes_phy, speed);
+ if (interface == PHY_INTERFACE_MODE_SGMII ||
+ interface == PHY_INTERFACE_MODE_2500BASEX) {
+ ret = phy_set_mode_ext(ethqos->serdes_phy, PHY_MODE_ETHERNET,
+ interface);
if (ret == 0)
- ethqos->serdes_speed = speed;
+ ethqos->serdes_mode = interface;
}
return ret;
@@ -819,7 +816,6 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(ethqos->serdes_phy),
"Failed to get serdes phy\n");
- ethqos->serdes_speed = SPEED_1000;
ethqos_set_clk_tx_rate(ethqos, NULL, plat_dat->phy_interface,
SPEED_1000);
@@ -843,6 +839,7 @@ static int qcom_ethqos_probe(struct platform_device *pdev)
plat_dat->host_dma_width = data->dma_addr_width;
if (ethqos->serdes_phy) {
+ ethqos->serdes_mode = PHY_INTERFACE_MODE_SGMII;
plat_dat->serdes_powerup = qcom_ethqos_serdes_powerup;
plat_dat->serdes_powerdown = qcom_ethqos_serdes_powerdown;
}
--
2.47.3
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH RESEND2 net-next 2/8] phy: qcom-sgmii-eth: add .set_mode() and .validate() methods
From: Russell King (Oracle) @ 2026-02-26 23:09 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, linux-arm-kernel, linux-arm-msm, linux-phy,
linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
Paolo Abeni, Vinod Koul
In-Reply-To: <aaDSJAc-x2-klvHJ@shell.armlinux.org.uk>
qcom-sgmii-eth is an Ethernet SerDes supporting only Ethernet mode
using SGMII, 1000BASE-X and 2500BASE-X.
Add an implementation of the .set_mode() method, which can be used
instead of or as well as the .set_speed() method. The Ethernet
interface modes mentioned above all have a fixed data rate, so
setting the mode is sufficient to fully specify the operating
parameters.
Add an implementation of the .validate() method, which will be
necessary to allow discovery of the SerDes capabilities for platform
independent SerDes support in the stmmac network driver.
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Acked-by: Vinod Koul <vkoul@kernel.org>
Tested-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 43 +++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
index 5b1c82459c12..4ea3dce7719f 100644
--- a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
+++ b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
@@ -7,6 +7,7 @@
#include <linux/ethtool.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/phy.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@@ -286,6 +287,37 @@ static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy)
return 0;
}
+static int qcom_dwmac_sgmii_phy_speed(enum phy_mode mode, int submode)
+{
+ if (mode != PHY_MODE_ETHERNET)
+ return -EINVAL;
+
+ if (submode == PHY_INTERFACE_MODE_SGMII ||
+ submode == PHY_INTERFACE_MODE_1000BASEX)
+ return SPEED_1000;
+
+ if (submode == PHY_INTERFACE_MODE_2500BASEX)
+ return SPEED_2500;
+
+ return -EINVAL;
+}
+
+static int qcom_dwmac_sgmii_phy_set_mode(struct phy *phy, enum phy_mode mode,
+ int submode)
+{
+ struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
+ int speed;
+
+ speed = qcom_dwmac_sgmii_phy_speed(mode, submode);
+ if (speed < 0)
+ return speed;
+
+ if (speed != data->speed)
+ data->speed = speed;
+
+ return qcom_dwmac_sgmii_phy_calibrate(phy);
+}
+
static int qcom_dwmac_sgmii_phy_set_speed(struct phy *phy, int speed)
{
struct qcom_dwmac_sgmii_phy_data *data = phy_get_drvdata(phy);
@@ -296,10 +328,21 @@ static int qcom_dwmac_sgmii_phy_set_speed(struct phy *phy, int speed)
return qcom_dwmac_sgmii_phy_calibrate(phy);
}
+static int qcom_dwmac_sgmii_phy_validate(struct phy *phy, enum phy_mode mode,
+ int submode,
+ union phy_configure_opts *opts)
+{
+ int ret = qcom_dwmac_sgmii_phy_speed(mode, submode);
+
+ return ret < 0 ? ret : 0;
+}
+
static const struct phy_ops qcom_dwmac_sgmii_phy_ops = {
.power_on = qcom_dwmac_sgmii_phy_power_on,
.power_off = qcom_dwmac_sgmii_phy_power_off,
+ .set_mode = qcom_dwmac_sgmii_phy_set_mode,
.set_speed = qcom_dwmac_sgmii_phy_set_speed,
+ .validate = qcom_dwmac_sgmii_phy_validate,
.calibrate = qcom_dwmac_sgmii_phy_calibrate,
.owner = THIS_MODULE,
};
--
2.47.3
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH RESEND2 net-next 1/8] net: stmmac: qcom-ethqos: move ethqos_set_serdes_speed()
From: Russell King (Oracle) @ 2026-02-26 23:09 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, linux-arm-kernel, linux-arm-msm, linux-phy,
linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
Paolo Abeni, Vinod Koul
In-Reply-To: <aaDSJAc-x2-klvHJ@shell.armlinux.org.uk>
Combine ethqos_set_serdes_speed() with ethqos_mac_finish_serdes() to
simplify the code.
Reviewed-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Tested-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
.../stmicro/stmmac/dwmac-qcom-ethqos.c | 22 +++++++++----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index ad5b5d950fff..57cbe800f652 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -591,14 +591,6 @@ static void ethqos_configure_rgmii(struct qcom_ethqos *ethqos,
ethqos_rgmii_macro_init(ethqos, speed);
}
-static void ethqos_set_serdes_speed(struct qcom_ethqos *ethqos, int speed)
-{
- if (ethqos->serdes_speed != speed) {
- phy_set_speed(ethqos->serdes_phy, speed);
- ethqos->serdes_speed = speed;
- }
-}
-
static void ethqos_pcs_set_inband(struct stmmac_priv *priv, bool enable)
{
stmmac_pcs_ctrl_ane(priv, enable, 0);
@@ -683,15 +675,23 @@ static int ethqos_mac_finish_serdes(struct net_device *ndev, void *priv,
phy_interface_t interface)
{
struct qcom_ethqos *ethqos = priv;
+ int speed, ret = 0;
qcom_ethqos_set_sgmii_loopback(ethqos, false);
+ speed = SPEED_UNKNOWN;
if (interface == PHY_INTERFACE_MODE_SGMII)
- ethqos_set_serdes_speed(ethqos, SPEED_1000);
+ speed = SPEED_1000;
else if (interface == PHY_INTERFACE_MODE_2500BASEX)
- ethqos_set_serdes_speed(ethqos, SPEED_2500);
+ speed = SPEED_2500;
- return 0;
+ if (speed != SPEED_UNKNOWN && speed != ethqos->serdes_speed) {
+ ret = phy_set_speed(ethqos->serdes_phy, speed);
+ if (ret == 0)
+ ethqos->serdes_speed = speed;
+ }
+
+ return ret;
}
static int ethqos_clks_config(void *priv, bool enabled)
--
2.47.3
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH RESEND2 net-next 0/8] net: stmmac: qcom-ethqos: further serdes reorganisation
From: Russell King (Oracle) @ 2026-02-26 23:07 UTC (permalink / raw)
To: Andrew Lunn
Cc: Alexandre Torgue, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, linux-arm-kernel, linux-arm-msm, linux-phy,
linux-stm32, Mohd Ayaan Anwar, Neil Armstrong, netdev,
Paolo Abeni, Vinod Koul
This is part 2 of the qcom-ethqos series, part 1 has now been merged.
This part of the series focuses on the generic PHY driver, but these
changes have dependencies on the ethernet driver, hence why
it will need to go via net-next. Furthermore, subsequent changes
depend on these patches.
The underlying ideas here are:
- get rid of the driver using phy_set_speed() with SPEED_1000 and
SPEED_2500 which makes no sense for an ethernet SerDes due to the
PCS 8B10B data encoding, which inflates the data rate at the SerDes
compared to the MAC. This is replaced with phy_set_mode_ext().
- allow phy_power_on() / phy_set_mode*() to be called in any order.
Mohd has tested this series, but it would be great to get acks/reviews
from the generic PHY maintainers.
.../ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 31 +++--------
drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 62 +++++++++++++++++-----
2 files changed, 57 insertions(+), 36 deletions(-)
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* [PATCH phy-fixes] phy: lynx-28g: skip CDR lock workaround for lanes disabled in the device tree
From: Vladimir Oltean @ 2026-02-26 18:28 UTC (permalink / raw)
To: linux-phy; +Cc: Vinod Koul, Neil Armstrong, Ioana Ciornei, linux-kernel
The blamed commit introduced support for specifying individual lanes as
OF nodes in the device, and these can have status = "disabled".
When that happens, for_each_available_child_of_node() skips them and
lynx_28g_probe_lane() -> devm_phy_create() is not called, so lane->phy
will be NULL. Yet it will be dereferenced in lynx_28g_cdr_lock_check(),
resulting in a crash.
This used to be well handled in v3 of that patch:
https://lore.kernel.org/linux-phy/20250926180505.760089-14-vladimir.oltean@nxp.com/
but until v5 was merged, the logic to support per-lane OF nodes was
split into a separate change, and the per-SoC compatible strings patch
was deferred to a "part 2" set. The splitting was done improperly, and
that handling of NULL lane->phy pointers was not integrated into the
proper commit.
Fixes: 7df7d58abbd6 ("phy: lynx-28g: support individual lanes as OF PHY providers")
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
This is a resend of patch 1/8 from:
https://patchwork.kernel.org/project/linux-phy/patch/20260114152111.625350-2-vladimir.oltean@nxp.com/
which was a fix for code which was in linux-phy/next at the time.
The merge window has passed, so it is now for linux-phy/fixes.
Note that further linux-phy/next changes depend on this, so please make
a note to merge 'fixes' into 'next' after the PR containing this gets
accepted.
Thanks!
drivers/phy/freescale/phy-fsl-lynx-28g.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/phy/freescale/phy-fsl-lynx-28g.c b/drivers/phy/freescale/phy-fsl-lynx-28g.c
index 0fcc0354e76b..518720b61539 100644
--- a/drivers/phy/freescale/phy-fsl-lynx-28g.c
+++ b/drivers/phy/freescale/phy-fsl-lynx-28g.c
@@ -1069,6 +1069,8 @@ static void lynx_28g_cdr_lock_check(struct work_struct *work)
for (i = 0; i < LYNX_28G_NUM_LANE; i++) {
lane = &priv->lane[i];
+ if (!lane->phy)
+ continue;
mutex_lock(&lane->phy->mutex);
--
2.43.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* [PATCH phy-fixes] phy: make PHY_COMMON_PROPS Kconfig symbol conditionally user-selectable
From: Vladimir Oltean @ 2026-02-26 15:33 UTC (permalink / raw)
To: linux-phy
Cc: Vinod Koul, Neil Armstrong, Vladimir Oltean, Bjørn Mork,
linux-kernel, Geert Uytterhoeven
Geert reports that enabling CONFIG_KUNIT_ALL_TESTS shouldn't enable
features that aren't enabled without it. That isn't what "*all* tests"
means, but as the prompt puts it, "All KUnit tests with satisfied
dependencies".
The impact is that enabling CONFIG_KUNIT_ALL_TESTS brings features which
cannot be disabled as built-in into the kernel.
Keep the pattern where consumer drivers have to "select PHY_COMMON_PROPS",
but if KUNIT_ALL_TESTS is enabled, also make PHY_COMMON_PROPS user
selectable, so it can be turned off.
Modify PHY_COMMON_PROPS_TEST to depend on PHY_COMMON_PROPS rather than
select it.
Fixes: e7556b59ba65 ("phy: add phy_get_rx_polarity() and phy_get_tx_polarity()")
Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
Closes: https://lore.kernel.org/linux-phy/CAMuHMdUBaoYKNj52gn8DQeZFZ42Cvm6xT6fvo0-_twNv1k3Jhg@mail.gmail.com/
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
drivers/phy/Kconfig | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 02467dfd4fb0..1875d5b784f6 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -6,7 +6,7 @@
menu "PHY Subsystem"
config PHY_COMMON_PROPS
- bool
+ bool "PHY common properties" if KUNIT_ALL_TESTS
help
This parses properties common between generic PHYs and Ethernet PHYs.
@@ -16,8 +16,7 @@ config PHY_COMMON_PROPS
config PHY_COMMON_PROPS_TEST
tristate "KUnit tests for PHY common props" if !KUNIT_ALL_TESTS
- select PHY_COMMON_PROPS
- depends on KUNIT
+ depends on KUNIT && PHY_COMMON_PROPS
default KUNIT_ALL_TESTS
help
This builds KUnit tests for the PHY common property API.
--
2.43.0
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
* Re: [PATCH v3 net-next 05/10] phy: add phy_get_rx_polarity() and phy_get_tx_polarity()
From: Vladimir Oltean @ 2026-02-26 15:21 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: netdev, devicetree, linux-phy, linux-kernel, linux-arm-kernel,
linux-mediatek, Daniel Golle, Horatiu Vultur, Bjørn Mork,
Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Vinod Koul, Neil Armstrong,
Matthias Brugger, AngeloGioacchino Del Regno, Eric Woudstra,
Marek Behún, Lee Jones, Patrice Chotard,
open list:KERNEL SELFTEST FRAMEWORK, KUnit Development
In-Reply-To: <CAMuHMdXKbiKUkP=+FDA_-Kd_qx1X6vzSuyPU+Tdd9MgR=Q5WMw@mail.gmail.com>
On Thu, Feb 26, 2026 at 04:13:59PM +0100, Geert Uytterhoeven wrote:
> Hi Vladimir,
>
> On Thu, 26 Feb 2026 at 16:10, Vladimir Oltean <vladimir.oltean@nxp.com> wrote:
> > On Thu, Feb 26, 2026 at 02:22:29PM +0100, Geert Uytterhoeven wrote:
> > > > +config PHY_COMMON_PROPS
> > > > + bool
> > > > + help
> > > > + This parses properties common between generic PHYs and Ethernet PHYs.
> > > > +
> > > > + Select this from consumer drivers to gain access to helpers for
> > > > + parsing properties from the
> > > > + Documentation/devicetree/bindings/phy/phy-common-props.yaml schema.
> > > > +
> > > > +config PHY_COMMON_PROPS_TEST
> > > > + tristate "KUnit tests for PHY common props" if !KUNIT_ALL_TESTS
> > > > + select PHY_COMMON_PROPS
> > >
> > > This select means that enabling KUNIT_ALL_TESTS also enables extra
> > > functionality, which may not be desirable in a production system.
> > > As PHY_COMMON_PROPS is bool, this extra functionality is even part of
> > > the base kernel if KUNIT_ALL_TESTS=m. Unfortunately PHY_COMMON_PROPS is
> > > invisible, so this cannot just be changed from "select" to "depends on".
> > > But perhaps PHY_COMMON_PROPS can be made visible if KUNIT_ALL_TESTS,
> > > so the select can be turned into a dependency?
> >
> > Is this what you're asking for?
> >
> > -- >8 --
> > diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> > index 02467dfd4fb0..1875d5b784f6 100644
> > --- a/drivers/phy/Kconfig
> > +++ b/drivers/phy/Kconfig
> > @@ -6,7 +6,7 @@
> > menu "PHY Subsystem"
> >
> > config PHY_COMMON_PROPS
> > - bool
> > + bool "PHY common properties" if KUNIT_ALL_TESTS
> > help
> > This parses properties common between generic PHYs and Ethernet PHYs.
> >
> > @@ -16,8 +16,7 @@ config PHY_COMMON_PROPS
> >
> > config PHY_COMMON_PROPS_TEST
> > tristate "KUnit tests for PHY common props" if !KUNIT_ALL_TESTS
> > - select PHY_COMMON_PROPS
> > - depends on KUNIT
> > + depends on KUNIT && PHY_COMMON_PROPS
> > default KUNIT_ALL_TESTS
> > help
> > This builds KUnit tests for the PHY common property API.
> > -- >8 --
>
> Yes, that would work. Do you think it is acceptable?
> Thanks!
Yes, I think it's fine. I misinterpreted what kunit_"all"_tests means,
then read its prompt which says "All KUnit tests with satisfied dependencies".
I'll send a patch.
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v3 net-next 05/10] phy: add phy_get_rx_polarity() and phy_get_tx_polarity()
From: Geert Uytterhoeven @ 2026-02-26 15:13 UTC (permalink / raw)
To: Vladimir Oltean
Cc: netdev, devicetree, linux-phy, linux-kernel, linux-arm-kernel,
linux-mediatek, Daniel Golle, Horatiu Vultur, Bjørn Mork,
Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Vinod Koul, Neil Armstrong,
Matthias Brugger, AngeloGioacchino Del Regno, Eric Woudstra,
Marek Behún, Lee Jones, Patrice Chotard,
open list:KERNEL SELFTEST FRAMEWORK, KUnit Development
In-Reply-To: <20260226151036.x4z4bdlxwgsqlkhs@skbuf>
Hi Vladimir,
On Thu, 26 Feb 2026 at 16:10, Vladimir Oltean <vladimir.oltean@nxp.com> wrote:
> On Thu, Feb 26, 2026 at 02:22:29PM +0100, Geert Uytterhoeven wrote:
> > > +config PHY_COMMON_PROPS
> > > + bool
> > > + help
> > > + This parses properties common between generic PHYs and Ethernet PHYs.
> > > +
> > > + Select this from consumer drivers to gain access to helpers for
> > > + parsing properties from the
> > > + Documentation/devicetree/bindings/phy/phy-common-props.yaml schema.
> > > +
> > > +config PHY_COMMON_PROPS_TEST
> > > + tristate "KUnit tests for PHY common props" if !KUNIT_ALL_TESTS
> > > + select PHY_COMMON_PROPS
> >
> > This select means that enabling KUNIT_ALL_TESTS also enables extra
> > functionality, which may not be desirable in a production system.
> > As PHY_COMMON_PROPS is bool, this extra functionality is even part of
> > the base kernel if KUNIT_ALL_TESTS=m. Unfortunately PHY_COMMON_PROPS is
> > invisible, so this cannot just be changed from "select" to "depends on".
> > But perhaps PHY_COMMON_PROPS can be made visible if KUNIT_ALL_TESTS,
> > so the select can be turned into a dependency?
>
> Is this what you're asking for?
>
> -- >8 --
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index 02467dfd4fb0..1875d5b784f6 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -6,7 +6,7 @@
> menu "PHY Subsystem"
>
> config PHY_COMMON_PROPS
> - bool
> + bool "PHY common properties" if KUNIT_ALL_TESTS
> help
> This parses properties common between generic PHYs and Ethernet PHYs.
>
> @@ -16,8 +16,7 @@ config PHY_COMMON_PROPS
>
> config PHY_COMMON_PROPS_TEST
> tristate "KUnit tests for PHY common props" if !KUNIT_ALL_TESTS
> - select PHY_COMMON_PROPS
> - depends on KUNIT
> + depends on KUNIT && PHY_COMMON_PROPS
> default KUNIT_ALL_TESTS
> help
> This builds KUnit tests for the PHY common property API.
> -- >8 --
Yes, that would work. Do you think it is acceptable?
Thanks!
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply
* Re: [PATCH v3 net-next 05/10] phy: add phy_get_rx_polarity() and phy_get_tx_polarity()
From: Vladimir Oltean @ 2026-02-26 15:10 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: netdev, devicetree, linux-phy, linux-kernel, linux-arm-kernel,
linux-mediatek, Daniel Golle, Horatiu Vultur, Bjørn Mork,
Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Vinod Koul, Neil Armstrong,
Matthias Brugger, AngeloGioacchino Del Regno, Eric Woudstra,
Marek Behún, Lee Jones, Patrice Chotard,
open list:KERNEL SELFTEST FRAMEWORK, KUnit Development
In-Reply-To: <CAMuHMdUBaoYKNj52gn8DQeZFZ42Cvm6xT6fvo0-_twNv1k3Jhg@mail.gmail.com>
Hi Geert,
On Thu, Feb 26, 2026 at 02:22:29PM +0100, Geert Uytterhoeven wrote:
> > +config PHY_COMMON_PROPS
> > + bool
> > + help
> > + This parses properties common between generic PHYs and Ethernet PHYs.
> > +
> > + Select this from consumer drivers to gain access to helpers for
> > + parsing properties from the
> > + Documentation/devicetree/bindings/phy/phy-common-props.yaml schema.
> > +
> > +config PHY_COMMON_PROPS_TEST
> > + tristate "KUnit tests for PHY common props" if !KUNIT_ALL_TESTS
> > + select PHY_COMMON_PROPS
>
> This select means that enabling KUNIT_ALL_TESTS also enables extra
> functionality, which may not be desirable in a production system.
> As PHY_COMMON_PROPS is bool, this extra functionality is even part of
> the base kernel if KUNIT_ALL_TESTS=m. Unfortunately PHY_COMMON_PROPS is
> invisible, so this cannot just be changed from "select" to "depends on".
> But perhaps PHY_COMMON_PROPS can be made visible if KUNIT_ALL_TESTS,
> so the select can be turned into a dependency?
Is this what you're asking for?
-- >8 --
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 02467dfd4fb0..1875d5b784f6 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -6,7 +6,7 @@
menu "PHY Subsystem"
config PHY_COMMON_PROPS
- bool
+ bool "PHY common properties" if KUNIT_ALL_TESTS
help
This parses properties common between generic PHYs and Ethernet PHYs.
@@ -16,8 +16,7 @@ config PHY_COMMON_PROPS
config PHY_COMMON_PROPS_TEST
tristate "KUnit tests for PHY common props" if !KUNIT_ALL_TESTS
- select PHY_COMMON_PROPS
- depends on KUNIT
+ depends on KUNIT && PHY_COMMON_PROPS
default KUNIT_ALL_TESTS
help
This builds KUnit tests for the PHY common property API.
-- >8 --
--
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox