Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 20 additions & 6 deletions drivers/phy/qualcomm/phy-qcom-qmp-combo.c
Original file line number Diff line number Diff line change
Expand Up @@ -4934,10 +4934,16 @@ static int qmp_combo_probe(struct platform_device *pdev)
if (ret)
goto err_node_put;

/*
* Enable runtime PM before creating the PHYs, phy_create() only enables
* it on the PHY devices if already enabled on the parent. Hold a usage
* reference so callbacks cannot run until the PHY is ready.
*/
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
ret = devm_pm_runtime_enable(dev);
if (ret)
goto err_node_put;
goto err_pm_put;
/*
* Prevent runtime pm from being ON by default. Users can enable
* it using power/control in sysfs.
Expand All @@ -4946,14 +4952,13 @@ static int qmp_combo_probe(struct platform_device *pdev)

ret = qmp_combo_register_clocks(qmp, usb_np, dp_np);
if (ret)
goto err_node_put;

goto err_pm_put;

qmp->usb_phy = devm_phy_create(dev, usb_np, &qmp_combo_usb_phy_ops);
if (IS_ERR(qmp->usb_phy)) {
ret = PTR_ERR(qmp->usb_phy);
dev_err(dev, "failed to create USB PHY: %d\n", ret);
goto err_node_put;
goto err_pm_put;
}

phy_set_drvdata(qmp->usb_phy, qmp);
Expand All @@ -4962,7 +4967,7 @@ static int qmp_combo_probe(struct platform_device *pdev)
if (IS_ERR(qmp->dp_phy)) {
ret = PTR_ERR(qmp->dp_phy);
dev_err(dev, "failed to create DP PHY: %d\n", ret);
goto err_node_put;
goto err_pm_put;
}

phy_set_drvdata(qmp->dp_phy, qmp);
Expand All @@ -4972,11 +4977,20 @@ static int qmp_combo_probe(struct platform_device *pdev)
else
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);

if (IS_ERR(phy_provider)) {
ret = PTR_ERR(phy_provider);
goto err_pm_put;
}

of_node_put(usb_np);
of_node_put(dp_np);

return PTR_ERR_OR_ZERO(phy_provider);
pm_runtime_put(dev);

return 0;

err_pm_put:
pm_runtime_put_noidle(dev);
err_node_put:
of_node_put(usb_np);
of_node_put(dp_np);
Expand Down
36 changes: 29 additions & 7 deletions drivers/phy/qualcomm/phy-qcom-qmp-usb-legacy.c
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,8 @@ struct qmp_usb {

enum phy_mode mode;

bool phy_initialized;

struct phy *phy;

struct clk_fixed_rate pipe_clk_fixed;
Expand Down Expand Up @@ -895,6 +897,7 @@ static int qmp_usb_legacy_power_off(struct phy *phy)

static int qmp_usb_legacy_enable(struct phy *phy)
{
struct qmp_usb *qmp = phy_get_drvdata(phy);
int ret;

ret = qmp_usb_legacy_init(phy);
Expand All @@ -904,14 +907,19 @@ static int qmp_usb_legacy_enable(struct phy *phy)
ret = qmp_usb_legacy_power_on(phy);
if (ret)
qmp_usb_legacy_exit(phy);
else
qmp->phy_initialized = true;

return ret;
}

static int qmp_usb_legacy_disable(struct phy *phy)
{
struct qmp_usb *qmp = phy_get_drvdata(phy);
int ret;

qmp->phy_initialized = false;

ret = qmp_usb_legacy_power_off(phy);
if (ret)
return ret;
Expand Down Expand Up @@ -988,7 +996,7 @@ static int __maybe_unused qmp_usb_legacy_runtime_suspend(struct device *dev)

dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qmp->mode);

if (!qmp->phy->init_count) {
if (!qmp->phy_initialized) {
dev_vdbg(dev, "PHY not initialized, bailing out\n");
return 0;
}
Expand All @@ -1009,7 +1017,7 @@ static int __maybe_unused qmp_usb_legacy_runtime_resume(struct device *dev)

dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qmp->mode);

if (!qmp->phy->init_count) {
if (!qmp->phy_initialized) {
dev_vdbg(dev, "PHY not initialized, bailing out\n");
return 0;
}
Expand Down Expand Up @@ -1277,10 +1285,16 @@ static int qmp_usb_legacy_probe(struct platform_device *pdev)
if (ret)
goto err_node_put;

/*
* Enable runtime PM before creating the PHY, phy_create() only enables
* it on the PHY device if already enabled on the parent. Hold a usage
* reference so callbacks cannot run before qmp->phy is assigned.
*/
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
ret = devm_pm_runtime_enable(dev);
if (ret)
goto err_node_put;
goto err_pm_put;
/*
* Prevent runtime pm from being ON by default. Users can enable
* it using power/control in sysfs.
Expand All @@ -1289,23 +1303,31 @@ static int qmp_usb_legacy_probe(struct platform_device *pdev)

ret = phy_pipe_clk_register(qmp, np);
if (ret)
goto err_node_put;
goto err_pm_put;

qmp->phy = devm_phy_create(dev, np, &qmp_usb_legacy_phy_ops);
if (IS_ERR(qmp->phy)) {
ret = PTR_ERR(qmp->phy);
dev_err(dev, "failed to create PHY: %d\n", ret);
goto err_node_put;
goto err_pm_put;
}

phy_set_drvdata(qmp->phy, qmp);

phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(phy_provider)) {
ret = PTR_ERR(phy_provider);
goto err_pm_put;
}

of_node_put(np);

phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
pm_runtime_put(dev);

return PTR_ERR_OR_ZERO(phy_provider);
return 0;

err_pm_put:
pm_runtime_put_noidle(dev);
err_node_put:
of_node_put(np);
return ret;
Expand Down
36 changes: 29 additions & 7 deletions drivers/phy/qualcomm/phy-qcom-qmp-usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1434,6 +1434,8 @@ struct qmp_usb {

enum phy_mode mode;

bool phy_initialized;

struct phy *phy;

struct clk_fixed_rate pipe_clk_fixed;
Expand Down Expand Up @@ -2009,6 +2011,7 @@ static int qmp_usb_power_off(struct phy *phy)

static int qmp_usb_enable(struct phy *phy)
{
struct qmp_usb *qmp = phy_get_drvdata(phy);
int ret;

ret = qmp_usb_init(phy);
Expand All @@ -2018,14 +2021,19 @@ static int qmp_usb_enable(struct phy *phy)
ret = qmp_usb_power_on(phy);
if (ret)
qmp_usb_exit(phy);
else
qmp->phy_initialized = true;

return ret;
}

static int qmp_usb_disable(struct phy *phy)
{
struct qmp_usb *qmp = phy_get_drvdata(phy);
int ret;

qmp->phy_initialized = false;

ret = qmp_usb_power_off(phy);
if (ret)
return ret;
Expand Down Expand Up @@ -2101,7 +2109,7 @@ static int __maybe_unused qmp_usb_runtime_suspend(struct device *dev)

dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qmp->mode);

if (!qmp->phy->init_count) {
if (!qmp->phy_initialized) {
dev_vdbg(dev, "PHY not initialized, bailing out\n");
return 0;
}
Expand All @@ -2121,7 +2129,7 @@ static int __maybe_unused qmp_usb_runtime_resume(struct device *dev)

dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qmp->mode);

if (!qmp->phy->init_count) {
if (!qmp->phy_initialized) {
dev_vdbg(dev, "PHY not initialized, bailing out\n");
return 0;
}
Expand Down Expand Up @@ -2411,10 +2419,16 @@ static int qmp_usb_probe(struct platform_device *pdev)
if (ret)
goto err_node_put;

/*
* Enable runtime PM before creating the PHY, phy_create() only enables
* it on the PHY device if already enabled on the parent. Hold a usage
* reference so callbacks cannot run before qmp->phy is assigned.
*/
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
ret = devm_pm_runtime_enable(dev);
if (ret)
goto err_node_put;
goto err_pm_put;
/*
* Prevent runtime pm from being ON by default. Users can enable
* it using power/control in sysfs.
Expand All @@ -2423,23 +2437,31 @@ static int qmp_usb_probe(struct platform_device *pdev)

ret = phy_pipe_clk_register(qmp, np);
if (ret)
goto err_node_put;
goto err_pm_put;

qmp->phy = devm_phy_create(dev, np, &qmp_usb_phy_ops);
if (IS_ERR(qmp->phy)) {
ret = PTR_ERR(qmp->phy);
dev_err(dev, "failed to create PHY: %d\n", ret);
goto err_node_put;
goto err_pm_put;
}

phy_set_drvdata(qmp->phy, qmp);

phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(phy_provider)) {
ret = PTR_ERR(phy_provider);
goto err_pm_put;
}

of_node_put(np);

phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
pm_runtime_put(dev);

return PTR_ERR_OR_ZERO(phy_provider);
return 0;

err_pm_put:
pm_runtime_put_noidle(dev);
err_node_put:
of_node_put(np);
return ret;
Expand Down
26 changes: 20 additions & 6 deletions drivers/phy/qualcomm/phy-qcom-qmp-usbc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1959,10 +1959,16 @@ static int qmp_usbc_probe(struct platform_device *pdev)
if (ret)
goto err_node_put;

/*
* Enable runtime PM before creating the PHYs, phy_create() only enables
* it on the PHY devices if already enabled on the parent. Hold a usage
* reference so callbacks cannot run until the PHY is ready.
*/
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
ret = devm_pm_runtime_enable(dev);
if (ret)
goto err_node_put;
goto err_pm_put;
/*
* Prevent runtime pm from being ON by default. Users can enable
* it using power/control in sysfs.
Expand All @@ -1971,13 +1977,13 @@ static int qmp_usbc_probe(struct platform_device *pdev)

ret = qmp_usbc_register_clocks(qmp, np);
if (ret)
goto err_node_put;
goto err_pm_put;

qmp->usb_phy = devm_phy_create(dev, np, &qmp_usbc_usb_phy_ops);
if (IS_ERR(qmp->usb_phy)) {
ret = PTR_ERR(qmp->usb_phy);
dev_err(dev, "failed to create PHY: %d\n", ret);
goto err_node_put;
goto err_pm_put;
}

phy_set_drvdata(qmp->usb_phy, qmp);
Expand All @@ -1987,17 +1993,25 @@ static int qmp_usbc_probe(struct platform_device *pdev)
if (IS_ERR(qmp->dp_phy)) {
ret = PTR_ERR(qmp->dp_phy);
dev_err(dev, "failed to create PHY: %d\n", ret);
goto err_node_put;
goto err_pm_put;
}
phy_set_drvdata(qmp->dp_phy, qmp);
}

phy_provider = devm_of_phy_provider_register(dev, qmp_usbc_phy_xlate);
if (IS_ERR(phy_provider)) {
ret = PTR_ERR(phy_provider);
goto err_pm_put;
}

of_node_put(np);

phy_provider = devm_of_phy_provider_register(dev, qmp_usbc_phy_xlate);
pm_runtime_put(dev);

return PTR_ERR_OR_ZERO(phy_provider);
return 0;

err_pm_put:
pm_runtime_put_noidle(dev);
err_node_put:
of_node_put(np);
return ret;
Expand Down
26 changes: 20 additions & 6 deletions drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
Original file line number Diff line number Diff line change
Expand Up @@ -599,8 +599,18 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev)
return dev_err_probe(dev, ret,
"failed to get regulator supplies\n");

/*
* Enable runtime PM before creating the PHY, phy_create() only enables
* it on the PHY device if already enabled on the parent. Hold a usage
* reference so callbacks cannot run before the PHY is ready.
*/
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
ret = devm_pm_runtime_enable(dev);
if (ret) {
pm_runtime_put_noidle(dev);
return ret;
}
/*
* Prevent runtime pm from being ON by default. Users can enable
* it using power/control in sysfs.
Expand All @@ -611,6 +621,7 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev)
if (IS_ERR(generic_phy)) {
ret = PTR_ERR(generic_phy);
dev_err(dev, "failed to create phy, %d\n", ret);
pm_runtime_put_noidle(dev);
return ret;
}
hsphy->phy = generic_phy;
Expand All @@ -620,12 +631,15 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev)
qcom_snps_hsphy_read_override_param_seq(dev);

phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (!IS_ERR(phy_provider))
dev_dbg(dev, "Registered Qcom-SNPS HS phy\n");
else
pm_runtime_disable(dev);
if (IS_ERR(phy_provider)) {
pm_runtime_put_noidle(dev);
return PTR_ERR(phy_provider);
}

return PTR_ERR_OR_ZERO(phy_provider);
dev_dbg(dev, "Registered Qcom-SNPS HS phy\n");
pm_runtime_put(dev);

return 0;
}

static struct platform_driver qcom_snps_hsphy_driver = {
Expand Down