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) { + 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); - 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; - return clk_prepare_enable(data->refclk); + 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 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; + int ret; - speed = qcom_dwmac_sgmii_phy_speed(mode, submode); - if (speed < 0) - return speed; + ret = qcom_dwmac_sgmii_phy_validate(phy, mode, submode, NULL); + if (ret) + return ret; - if (speed != data->speed) - data->speed = speed; + if (submode != data->interface) + data->interface = submode; + + if (phy->power_count == 0) + return 0; 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) -{ - 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))