phy: qcom: sgmii-eth: vote for both voltage rails with correct current loads

The SerDes PHY has two voltage supply rails, vdda-0p9 and vdda-1p2,
that must both be enabled for calibration to succeed. Without them:

  qcom-dwmac-sgmii-phy 8909000.phy: QSERDES_COM_C_READY_STATUS timed-out
  qcom-ethqos 23040000.ethernet eth0: __stmmac_open: Serdes powerup failed

The driver relied solely on the PHY framework's implicit enable of
'phy-supply', which only voted for a single rail and set no current
load. Use devm_regulator_bulk_get_const() to acquire both supplies and
set the peak current loads (46 mA for vdda-0p9, 15 mA for vdda-1p2)
as required by the hardware.

Fixes: 601d062770 ("phy: qcom: add the SGMII SerDes PHY driver")
Signed-off-by: Mohd Ayaan Anwar <mohd.anwar@oss.qualcomm.com>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Link: https://patch.msgid.link/20260804-b4-sgmiieth_serdes_regulator-v2-2-c4bc688177dd@oss.qualcomm.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
Mohd Ayaan Anwar 2026-08-04 00:57:58 +05:30 committed by Vinod Koul
parent 3719850f1b
commit 4f81684a1d

View File

@ -11,6 +11,7 @@
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include "phy-qcom-qmp-pcs-sgmii.h"
#include "phy-qcom-qmp-qserdes-com-v5.h"
@ -26,7 +27,15 @@
#define QSERDES_PCS_SGMIIPHY_READY BIT(7)
#define QSERDES_COM_C_PLL_LOCKED BIT(1)
static const struct regulator_bulk_data qcom_dwmac_sgmii_phy_vregs[] = {
{ .supply = "vdda-0p9", .init_load_uA = 46000 },
{ .supply = "vdda-1p2", .init_load_uA = 15000 },
};
#define QCOM_SGMII_NUM_SUPPLIES ARRAY_SIZE(qcom_dwmac_sgmii_phy_vregs)
struct qcom_dwmac_sgmii_phy_data {
struct regulator_bulk_data *vregs;
struct regmap *regmap;
struct clk *refclk;
phy_interface_t interface;
@ -273,13 +282,24 @@ 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)
ret = regulator_bulk_enable(QCOM_SGMII_NUM_SUPPLIES, data->vregs);
if (ret)
return ret;
ret = clk_prepare_enable(data->refclk);
if (ret)
goto err_disable_regulators;
ret = qcom_dwmac_sgmii_phy_calibrate(phy);
if (ret < 0)
clk_disable_unprepare(data->refclk);
if (ret)
goto err_disable_clk;
return 0;
err_disable_clk:
clk_disable_unprepare(data->refclk);
err_disable_regulators:
regulator_bulk_disable(QCOM_SGMII_NUM_SUPPLIES, data->vregs);
return ret;
}
@ -296,6 +316,8 @@ static int qcom_dwmac_sgmii_phy_power_off(struct phy *phy)
clk_disable_unprepare(data->refclk);
regulator_bulk_disable(QCOM_SGMII_NUM_SUPPLIES, data->vregs);
return 0;
}
@ -357,6 +379,7 @@ static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev)
struct phy_provider *provider;
void __iomem *base;
struct phy *phy;
int ret;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
@ -381,6 +404,12 @@ static int qcom_dwmac_sgmii_phy_probe(struct platform_device *pdev)
if (IS_ERR(data->refclk))
return PTR_ERR(data->refclk);
ret = devm_regulator_bulk_get_const(dev, QCOM_SGMII_NUM_SUPPLIES,
qcom_dwmac_sgmii_phy_vregs,
&data->vregs);
if (ret)
return ret;
provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(provider))
return PTR_ERR(provider);