net: stmmac: qcom-ethqos: further serdes reorganisation
Subsystems (7)
v2 cover net: stmmac: qcom-ethqos: further serdes reorganisation
This is part 2 of the qcom-ethqos series, part 1 and patch 2 of part 2 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, although not in the resulting merge order.
Changes since resend2:
- Drop patch 2 as that is now applied
- Add Vinod's Acks, which were eventually sent in response to the first posting of this series.
.../ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 31 +++------ drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 73 ++++++++++------------ 2 files changed, 41 insertions(+), 63 deletions(-)
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
PATCH v2 1/7 net: stmmac: qcom-ethqos: move ethqos_set_serdes_speed()
Combine ethqos_set_serdes_speed() with ethqos_mac_finish_serdes() to simplify the code.
--- .../stmicro/stmmac/dwmac-qcom-ethqos.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-)
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +11 -11
@@ -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)
Signature · 1 line
2.47.3
PATCH v2 2/7 net: stmmac: qcom-ethqos: convert to use phy_set_mode_ext()
In reply to Russell King (Oracle)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().
--- .../stmicro/stmmac/dwmac-qcom-ethqos.c | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-)
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +10 -13
@@ -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; }
Signature · 1 line
2.47.3
Re: [PATCH net-next v2 2/7] net: stmmac: qcom-ethqos: convert to use phy_set_mode_ext()
Quoted 7 lines · Russell King (Oracle)
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 <[email protected]>Signed-off-by Russell King (Oracle) <[email protected]>
Ayaan
PATCH v2 3/7 phy: qcom-sgmii-eth: remove .set_speed() implementation
In reply to Russell King (Oracle)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
--- drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 11 ----------- 1 file changed, 11 deletions(-)
drivers/phy/qualcomm/phy-qcom-sgmii-eth.c +0 -11
@@ -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,
Signature · 1 line
2.47.3
PATCH v2 4/7 phy: qcom-sgmii-eth: use PHY interface mode for SerDes settings
In reply to Russell King (Oracle)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.
--- drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 41 ++++++++++++----------- 1 file changed, 21 insertions(+), 20 deletions(-)
drivers/phy/qualcomm/phy-qcom-sgmii-eth.c +21 -20
@@ -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))
Signature · 1 line
2.47.3
PATCH v2 5/7 phy: qcom-sgmii-eth: remove qcom_dwmac_sgmii_phy_interface()
In reply to Russell King (Oracle)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().
--- drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 27 +++++++++-------------- 1 file changed, 10 insertions(+), 17 deletions(-)
drivers/phy/qualcomm/phy-qcom-sgmii-eth.c +10 -17
@@ -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,
Signature · 1 line
2.47.3
PATCH v2 6/7 phy: qcom-sgmii-eth: relax order of .power_on() vs .set_mode*()
In reply to Russell King (Oracle)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.
--- drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
drivers/phy/qualcomm/phy-qcom-sgmii-eth.c +13 -1
@@ -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); }
Signature · 1 line
2.47.3
PATCH v2 7/7 net: stmmac: qcom-ethqos: remove phy_set_mode_ext() after phy_power_on()
In reply to Russell King (Oracle)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.
--- .../stmicro/stmmac/dwmac-qcom-ethqos.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-)
drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +2 -16
@@ -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; }
Signature · 1 line
2.47.3
Jakub Kicinski
maintainerQuoted 4 lines · On Tue, 3 Mar 2026 15:53:02 +0000 Russell King (Oracle) wrote:
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.
Hi Vinod, given the dependency on the existing stuff in net-next are you okay with patches 3-6 going to net-next without at tag you can pull?
This series was applied to netdev/net-next.git (main) by Jakub Kicinski <[email protected]>:
Hello:
This series was applied to netdev/net-next.git (main) by Jakub Kicinski <[email protected]>:
Quoted 9 lines · On Tue, 3 Mar 2026 15:53:02 +0000 you wrote:
This is part 2 of the qcom-ethqos series, part 1 and patch 2 of part 2 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.
[...]
Here is the summary with links:
- [net-next,v2,1/7] net: stmmac: qcom-ethqos: move ethqos_set_serdes_speed()
https://git.kernel.org/netdev/net-next/c/fc8ca5da896e - [net-next,v2,2/7] net: stmmac: qcom-ethqos: convert to use phy_set_mode_ext() https://git.kernel.org/netdev/net-next/c/4999e0a2ab34 - [net-next,v2,3/7] phy: qcom-sgmii-eth: remove .set_speed() implementation https://git.kernel.org/netdev/net-next/c/b7721597547d - [net-next,v2,4/7] phy: qcom-sgmii-eth: use PHY interface mode for SerDes settings https://git.kernel.org/netdev/net-next/c/d2b20acdaed8 - [net-next,v2,5/7] phy: qcom-sgmii-eth: remove qcom_dwmac_sgmii_phy_interface() https://git.kernel.org/netdev/net-next/c/f82210ce8cb8 - [net-next,v2,6/7] phy: qcom-sgmii-eth: relax order of .power_on() vs .set_mode*() https://git.kernel.org/netdev/net-next/c/ebe8b48b88ad - [net-next,v2,7/7] net: stmmac: qcom-ethqos: remove phy_set_mode_ext() after phy_power_on() https://git.kernel.org/netdev/net-next/c/038a8e8eb90d
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html