summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorWu Liang feng <wulf@rock-chips.com>2016-09-10 13:37:08 +0800
committerHuang, Tao <huangtao@rock-chips.com>2016-09-23 15:03:29 +0800
commit8f2c7e7cd70bc19b61060dd0273f3ab37b044469 (patch)
tree5c9b8f25c25490b773ee70a61b12568a0cbeac71 /drivers
parent756d9ad54889396db40c1bca2ece8b9c07f0888d (diff)
usb: dwc3: fix logical errors and improve stability for rockchip platform
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/dwc3/dwc3-rockchip.c63
1 files changed, 36 insertions, 27 deletions
diff --git a/drivers/usb/dwc3/dwc3-rockchip.c b/drivers/usb/dwc3/dwc3-rockchip.c
index 3c77bd3fed70..90c34c699e7e 100644
--- a/drivers/usb/dwc3/dwc3-rockchip.c
+++ b/drivers/usb/dwc3/dwc3-rockchip.c
@@ -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);
- if (ret < 0)
+ if (ret < 0) {
+ reset_control_deassert(rockchip->otg_rst);
return;
+ }
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;
+ }
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;
- rockchip->edev = NULL;
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) {
- while (--i >= 0) {
- clk_disable_unprepare(rockchip->clks[i]);
- clk_put(rockchip->clks[i]);
- }
clk_put(clk);
-
- return ret;
+ goto err0;
}
rockchip->clks[i] = clk;
@@ -293,38 +291,38 @@ static int dwc3_rockchip_probe(struct platform_device *pdev)
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;
- 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");
- 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;
- goto err3;
+ goto err2;
}
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);
@@ -342,21 +340,27 @@ static int dwc3_rockchip_probe(struct platform_device *pdev)
}
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;
-err3:
- of_platform_depopulate(dev);
-
err2:
- dwc3_rockchip_extcon_unregister(rockchip);
+ of_platform_depopulate(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]);
}
@@ -374,10 +378,15 @@ static int dwc3_rockchip_remove(struct platform_device *pdev)
of_platform_depopulate(dev);
- pm_runtime_put_sync(dev);
+ if (!rockchip->edev)
+ pm_runtime_put_sync(dev);
+
pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);
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]);
}