Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d2bba2e7 authored by Azhar Shaikh's avatar Azhar Shaikh
Browse files

usb: dwc3: Do pm_runtime_disable after removing children



When trying to remove the child, device core is trying to resume one last
time before unloading. All parents should be in active state before
resuming the child, but since dwc3_msm may be runtime suspended, removal
of child device could result in unclocked register access.
Hence do a pm_runtime_get_sync prior to removing children to ensure parent
is in active state. However sometimes pm_runtime_get_sync fails in case of
system suspend. In this case turn on the clocks manually.

CRs-fixed: 682513
Change-Id: I3b25a8d96a2efedd0235a53683fcb4d8659bc54f
Signed-off-by: default avatarAzhar Shaikh <azhars@codeaurora.org>
parent ff1ff8e0
Loading
Loading
Loading
Loading
+23 −3
Original line number Diff line number Diff line
@@ -3280,13 +3280,27 @@ static int dwc3_msm_remove_children(struct device *dev, void *data)
static int dwc3_msm_remove(struct platform_device *pdev)
{
	struct dwc3_msm	*mdwc = platform_get_drvdata(pdev);
	int ret_pm;

	if (cpu_to_affin)
		unregister_cpu_notifier(&mdwc->dwc3_cpu_notifier);

	pm_runtime_disable(mdwc->dev);
	pm_runtime_set_suspended(mdwc->dev);
	device_wakeup_disable(mdwc->dev);
	/*
	 * In case of system suspend, pm_runtime_get_sync fails.
	 * Hence turn ON the clocks manually.
	 */
	ret_pm = pm_runtime_get_sync(mdwc->dev);
	if (ret_pm < 0) {
		dev_err(mdwc->dev,
			"pm_runtime_get_sync failed with %d\n", ret_pm);
		clk_prepare_enable(mdwc->utmi_clk);
		clk_prepare_enable(mdwc->core_clk);
		clk_prepare_enable(mdwc->iface_clk);
		clk_prepare_enable(mdwc->sleep_clk);
		clk_prepare_enable(mdwc->hsphy_sleep_clk);
		clk_prepare_enable(mdwc->ref_clk);
		clk_prepare_enable(mdwc->xo_clk);
	}

	if (mdwc->ext_chg_device) {
		device_destroy(mdwc->ext_chg_class, mdwc->ext_chg_dev);
@@ -3308,6 +3322,12 @@ static int dwc3_msm_remove(struct platform_device *pdev)
	platform_device_put(mdwc->dwc3);
	device_for_each_child(&pdev->dev, NULL, dwc3_msm_remove_children);

	pm_runtime_disable(mdwc->dev);
	pm_runtime_barrier(mdwc->dev);
	pm_runtime_put_sync(mdwc->dev);
	pm_runtime_set_suspended(mdwc->dev);
	device_wakeup_disable(mdwc->dev);

	if (!IS_ERR_OR_NULL(mdwc->vbus_otg))
		regulator_disable(mdwc->vbus_otg);