[PATCH v2 2/6] phy: qcom: sgmii-eth: vote for both voltage rails with correct current loads
Mohd Ayaan Anwar <[email protected]> Tue, 04 Aug 2026 00:57:58 +0530
| Newsgroups | org.infradead.lists.linux-phy,org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <20260804-b4-sgmiieth_serdes_regulator-v2-2-c4bc688177dd@oss.qualcomm.com> |
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: 601d06277007 ("phy: qcom: add the SGMII SerDes PHY driver")
Signed-off-by: Mohd Ayaan Anwar <[email protected]>
---
drivers/phy/qualcomm/phy-qcom-sgmii-eth.c | 37 +++++++++++++++++++++++++++----
1 file changed, 33 insertions(+), 4 deletions(-)
diff --git a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
index f48faa2929a682be6024ee349fac6fd1b6464cb3..7137200c3f310a4d2642bb9bdbe3adb7589b2241 100644
--- a/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
+++ b/drivers/phy/qualcomm/phy-qcom-sgmii-eth.c
@@ -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);
--
2.34.1
--
linux-phy mailing list
[email protected]
https://lists.infradead.org/mailman/listinfo/linux-phy