summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2026-03-05 18:43:08 -0800
committerJakub Kicinski <kuba@kernel.org>2026-03-05 18:43:09 -0800
commit2a13309fa840fa7d651e6df0e174023003829461 (patch)
treec53f6ab3be46358f9b438ec51399a0d574b0ba2b
parent46cb1fcdb75b2dab2f3ed62caad04fe939549943 (diff)
parent038a8e8eb90d4dd06ce6bda825970c71af09f4b0 (diff)
Merge branch 'net-stmmac-qcom-ethqos-further-serdes-reorganisation'
Russell King says: ==================== 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. ==================== Link: https://patch.msgid.link/aacD3osfaZkLsGxm@shell.armlinux.org.uk Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c31
-rw-r--r--drivers/phy/qualcomm/phy-qcom-sgmii-eth.c73
2 files changed, 41 insertions, 63 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..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;
- int serdes_speed;
phy_interface_t phy_mode;
const struct ethqos_emac_por *rgmii_por;
@@ -591,14 +590,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);
@@ -656,16 +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_speed(ethqos->serdes_phy, ethqos->serdes_speed);
- if (ret) {
- phy_power_off(ethqos->serdes_phy);
+ if (ret)
phy_exit(ethqos->serdes_phy);
- }
return ret;
}
@@ -683,15 +666,16 @@ static int ethqos_mac_finish_serdes(struct net_device *ndev, void *priv,
phy_interface_t interface)
{
struct qcom_ethqos *ethqos = priv;
+ int ret = 0;
qcom_ethqos_set_sgmii_loopback(ethqos, false);
- if (interface == PHY_INTERFACE_MODE_SGMII)
- ethqos_set_serdes_speed(ethqos, SPEED_1000);
- else if (interface == PHY_INTERFACE_MODE_2500BASEX)
- ethqos_set_serdes_speed(ethqos, SPEED_2500);
+ if (interface == PHY_INTERFACE_MODE_SGMII ||
+ interface == PHY_INTERFACE_MODE_2500BASEX)
+ ret = phy_set_mode_ext(ethqos->serdes_phy, PHY_MODE_ETHERNET,
+ interface);
- return 0;
+ return ret;
}
static int ethqos_clks_config(void *priv, bool enabled)
@@ -819,7 +803,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);
diff --git a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
index 4ea3dce7719f..f48faa2929a6 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,
@@ -268,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;
+
+ ret = qcom_dwmac_sgmii_phy_calibrate(phy);
+ if (ret < 0)
+ clk_disable_unprepare(data->refclk);
- return clk_prepare_enable(data->refclk);
+ return ret;
}
static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy)
@@ -287,17 +299,17 @@ 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_validate(struct phy *phy, enum phy_mode mode,
+ int submode,
+ union phy_configure_opts *opts)
{
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 0;
return -EINVAL;
}
@@ -306,42 +318,25 @@ 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;
+ int ret;
- if (speed != data->speed)
- data->speed = speed;
-
- return qcom_dwmac_sgmii_phy_calibrate(phy);
-}
+ ret = qcom_dwmac_sgmii_phy_validate(phy, mode, submode, NULL);
+ if (ret)
+ return ret;
-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 (submode != data->interface)
+ data->interface = submode;
- if (speed != data->speed)
- data->speed = speed;
+ if (phy->power_count == 0)
+ return 0;
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,
@@ -367,7 +362,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))