usb: dwc3: fix logical errors and improve stability for rockchip platform
authorWu Liang feng <wulf@rock-chips.com>
Sat, 10 Sep 2016 05:37:08 +0000 (13:37 +0800)
committerHuang, Tao <huangtao@rock-chips.com>
Fri, 23 Sep 2016 07:03:29 +0000 (15:03 +0800)
1. put clks err handle at the end of probe.

2. register extcon notifier after dwc3 core initialized successfully.

3. try to get extcon cable state in probe, this can avoid to
   lose the first extcon state notifier.

4. fix pm runtime handle and disable clks in remove operation

Change-Id: I0bea71206801139efb37a835b65562c051a2072e
Signed-off-by: Wu Liang feng <wulf@rock-chips.com>
drivers/usb/dwc3/dwc3-rockchip.c

index 3c77bd3fed70cc6602540e07b7f076c35fc024b8..90c34c699e7ef502e5ad591c847ea7dc6f63ef2b 100644 (file)
@@ -117,12 +117,17 @@ static void dwc3_rockchip_otg_extcon_evt_work(struct work_struct *work)
                reset_control_assert(rockchip->otg_rst);
 
                ret = phy_power_on(dwc->usb2_generic_phy);
                reset_control_assert(rockchip->otg_rst);
 
                ret = phy_power_on(dwc->usb2_generic_phy);
-               if (ret < 0)
+               if (ret < 0) {
+                       reset_control_deassert(rockchip->otg_rst);
                        return;
                        return;
+               }
 
                ret = phy_power_on(dwc->usb3_generic_phy);
 
                ret = phy_power_on(dwc->usb3_generic_phy);
-               if (ret < 0)
+               if (ret < 0) {
+                       phy_power_off(dwc->usb2_generic_phy);
+                       reset_control_deassert(rockchip->otg_rst);
                        return;
                        return;
+               }
 
                reset_control_deassert(rockchip->otg_rst);
 
 
                reset_control_deassert(rockchip->otg_rst);
 
@@ -252,27 +257,20 @@ static int dwc3_rockchip_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, rockchip);
 
        rockchip->dev = dev;
        platform_set_drvdata(pdev, rockchip);
 
        rockchip->dev = dev;
-       rockchip->edev = NULL;
 
        for (i = 0; i < rockchip->num_clocks; i++) {
                struct clk      *clk;
 
                clk = of_clk_get(np, i);
                if (IS_ERR(clk)) {
 
        for (i = 0; i < rockchip->num_clocks; i++) {
                struct clk      *clk;
 
                clk = of_clk_get(np, i);
                if (IS_ERR(clk)) {
-                       while (--i >= 0)
-                               clk_put(rockchip->clks[i]);
-                       return PTR_ERR(clk);
+                       ret = PTR_ERR(clk);
+                       goto err0;
                }
 
                ret = clk_prepare_enable(clk);
                if (ret < 0) {
                }
 
                ret = clk_prepare_enable(clk);
                if (ret < 0) {
-                       while (--i >= 0) {
-                               clk_disable_unprepare(rockchip->clks[i]);
-                               clk_put(rockchip->clks[i]);
-                       }
                        clk_put(clk);
                        clk_put(clk);
-
-                       return ret;
+                       goto err0;
                }
 
                rockchip->clks[i] = clk;
                }
 
                rockchip->clks[i] = clk;
@@ -293,38 +291,38 @@ static int dwc3_rockchip_probe(struct platform_device *pdev)
                goto err1;
        }
 
                goto err1;
        }
 
-       ret = dwc3_rockchip_extcon_register(rockchip);
-       if (ret < 0)
-               goto err1;
-
        child = of_get_child_by_name(np, "dwc3");
        if (!child) {
                dev_err(dev, "failed to find dwc3 core node\n");
                ret = -ENODEV;
        child = of_get_child_by_name(np, "dwc3");
        if (!child) {
                dev_err(dev, "failed to find dwc3 core node\n");
                ret = -ENODEV;
-               goto err2;
+               goto err1;
        }
 
        /* Allocate and initialize the core */
        ret = of_platform_populate(np, NULL, NULL, dev);
        if (ret) {
                dev_err(dev, "failed to create dwc3 core\n");
        }
 
        /* Allocate and initialize the core */
        ret = of_platform_populate(np, NULL, NULL, dev);
        if (ret) {
                dev_err(dev, "failed to create dwc3 core\n");
-               goto err2;
+               goto err1;
        }
 
        child_pdev = of_find_device_by_node(child);
        if (!child_pdev) {
                dev_err(dev, "failed to find dwc3 core device\n");
                ret = -ENODEV;
        }
 
        child_pdev = of_find_device_by_node(child);
        if (!child_pdev) {
                dev_err(dev, "failed to find dwc3 core device\n");
                ret = -ENODEV;
-               goto err3;
+               goto err2;
        }
 
        rockchip->dwc = platform_get_drvdata(child_pdev);
        if (!rockchip->dwc) {
                dev_err(dev, "failed to get drvdata dwc3\n");
        }
 
        rockchip->dwc = platform_get_drvdata(child_pdev);
        if (!rockchip->dwc) {
                dev_err(dev, "failed to get drvdata dwc3\n");
-               ret = -ENODEV;
-               goto err3;
+               ret = -EPROBE_DEFER;
+               goto err2;
        }
 
        }
 
+       ret = dwc3_rockchip_extcon_register(rockchip);
+       if (ret < 0)
+               goto err2;
+
        if (rockchip->edev) {
                pm_runtime_set_autosuspend_delay(&child_pdev->dev,
                                                 DWC3_ROCKCHIP_AUTOSUSPEND_DELAY);
        if (rockchip->edev) {
                pm_runtime_set_autosuspend_delay(&child_pdev->dev,
                                                 DWC3_ROCKCHIP_AUTOSUSPEND_DELAY);
@@ -342,21 +340,27 @@ static int dwc3_rockchip_probe(struct platform_device *pdev)
                }
 
                pm_runtime_put_sync(dev);
                }
 
                pm_runtime_put_sync(dev);
+
+               if ((extcon_get_cable_state_(rockchip->edev,
+                                            EXTCON_USB) > 0) ||
+                   (extcon_get_cable_state_(rockchip->edev,
+                                            EXTCON_USB_HOST) > 0))
+                       schedule_work(&rockchip->otg_work);
        }
 
        return ret;
 
        }
 
        return ret;
 
-err3:
-       of_platform_depopulate(dev);
-
 err2:
 err2:
-       dwc3_rockchip_extcon_unregister(rockchip);
+       of_platform_depopulate(dev);
 
 err1:
        pm_runtime_put_sync(dev);
        pm_runtime_disable(dev);
 
 
 err1:
        pm_runtime_put_sync(dev);
        pm_runtime_disable(dev);
 
-       for (i = 0; i < rockchip->num_clocks; i++) {
+err0:
+       for (i = 0; i < rockchip->num_clocks && rockchip->clks[i]; i++) {
+               if (!pm_runtime_status_suspended(dev))
+                       clk_disable(rockchip->clks[i]);
                clk_unprepare(rockchip->clks[i]);
                clk_put(rockchip->clks[i]);
        }
                clk_unprepare(rockchip->clks[i]);
                clk_put(rockchip->clks[i]);
        }
@@ -374,10 +378,15 @@ static int dwc3_rockchip_remove(struct platform_device *pdev)
 
        of_platform_depopulate(dev);
 
 
        of_platform_depopulate(dev);
 
-       pm_runtime_put_sync(dev);
+       if (!rockchip->edev)
+               pm_runtime_put_sync(dev);
+
        pm_runtime_disable(dev);
        pm_runtime_disable(dev);
+       pm_runtime_set_suspended(dev);
 
        for (i = 0; i < rockchip->num_clocks; i++) {
 
        for (i = 0; i < rockchip->num_clocks; i++) {
+               if (!pm_runtime_status_suspended(dev))
+                       clk_disable(rockchip->clks[i]);
                clk_unprepare(rockchip->clks[i]);
                clk_put(rockchip->clks[i]);
        }
                clk_unprepare(rockchip->clks[i]);
                clk_put(rockchip->clks[i]);
        }