mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 13:14:02 +02:00
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:
parent
3719850f1b
commit
4f81684a1d
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user