[PATCH v2 3/4] usb: chipidea: tegra: Avoid controller/PHY init if bus is externally controlled
From: Svyatoslav Ryhel <hidden>
Date: 2026-05-23 08:30:44
Also in:
linux-tegra, linux-usb, lkml
Subsystem:
chipidea usb high speed dual role controller, the rest, usb subsystem · Maintainers:
Peter Chen, Linus Torvalds, Greg Kroah-Hartman
If the USB controller and PHY are externally controlled, then the registration of the controller and the PHY initialization should be skipped, since these configurations must be done by the device that controls the bus to work correctly. Since USB PHY in Tegra controls clock gates required by the controller itself, Chipidea core PHY management is not suitable for Tegra. Signed-off-by: Svyatoslav Ryhel <redacted> --- drivers/usb/chipidea/ci_hdrc_tegra.c | 32 ++++++++++++++++++---------- 1 file changed, 21 insertions(+), 11 deletions(-)
diff --git a/drivers/usb/chipidea/ci_hdrc_tegra.c b/drivers/usb/chipidea/ci_hdrc_tegra.c
index 372788f0f970..a19cb3b33bf3 100644
--- a/drivers/usb/chipidea/ci_hdrc_tegra.c
+++ b/drivers/usb/chipidea/ci_hdrc_tegra.c@@ -32,6 +32,7 @@ struct tegra_usb { struct clk *clk; bool needs_double_reset; + bool externally_controlled; }; struct tegra_usb_soc_info {
@@ -312,6 +313,9 @@ static int tegra_usb_probe(struct platform_device *pdev) if (device_property_present(&pdev->dev, "nvidia,needs-double-reset")) usb->needs_double_reset = true; + if (device_property_present(&pdev->dev, "nvidia,external-control")) + usb->externally_controlled = true; + err = tegra_usb_reset_controller(&pdev->dev); if (err) { dev_err_probe(&pdev->dev, err, "failed to reset controller");
@@ -323,9 +327,11 @@ static int tegra_usb_probe(struct platform_device *pdev) * initialized, otherwise CPU will hang because clocks are gated. * PHY driver controls gating of internal USB clocks on Tegra. */ - err = usb_phy_init(usb->phy); - if (err) - goto fail_power_off; + if (!usb->externally_controlled) { + err = usb_phy_init(usb->phy); + if (err) + goto fail_power_off; + } /* setup and register ChipIdea HDRC device */ usb->soc = soc;
@@ -342,12 +348,14 @@ static int tegra_usb_probe(struct platform_device *pdev) if (of_usb_get_phy_mode(pdev->dev.of_node) == USBPHY_INTERFACE_MODE_ULPI) usb->data.flags &= ~CI_HDRC_SUPPORTS_RUNTIME_PM; - usb->dev = ci_hdrc_add_device(&pdev->dev, pdev->resource, - pdev->num_resources, &usb->data); - if (IS_ERR(usb->dev)) { - err = dev_err_probe(&pdev->dev, PTR_ERR(usb->dev), - "failed to add HDRC device"); - goto phy_shutdown; + if (!usb->externally_controlled) { + usb->dev = ci_hdrc_add_device(&pdev->dev, pdev->resource, + pdev->num_resources, &usb->data); + if (IS_ERR(usb->dev)) { + err = dev_err_probe(&pdev->dev, PTR_ERR(usb->dev), + "failed to add HDRC device"); + goto phy_shutdown; + } } return 0;
@@ -365,8 +373,10 @@ static void tegra_usb_remove(struct platform_device *pdev) { struct tegra_usb *usb = platform_get_drvdata(pdev); - ci_hdrc_remove_device(usb->dev); - usb_phy_shutdown(usb->phy); + if (!usb->externally_controlled) { + ci_hdrc_remove_device(usb->dev); + usb_phy_shutdown(usb->phy); + } pm_runtime_put_sync_suspend(&pdev->dev); pm_runtime_force_suspend(&pdev->dev);
--
2.51.0