usb: dwc2: power on/off phy for otg mode

The commit dc71e51944 ("usb: dwc2: make otg manage lowlevel
hw on its own") aimed to control the clk and phy power for
otg mode, but it also introduced lost of new problems, so we
revert it.

This patch only controls phy power for otg mode, it can fix
the dwc2 udc start fail issue with the following error log:

dwc2_hsotg_init_fifo: timeout flushing fifos (GRSTCTL=80000430)
dwc2_core_reset() HANG! Soft Reset GRSTCTL=80000001
bound driver configfs-gadget
dwc2_core_reset() HANG! Soft Reset GRSTCTL=80000001

Change-Id: Id6996aecab7f0aaaf12530b7a377144e23ef1667
Signed-off-by: William Wu <william.wu@rock-chips.com>
Signed-off-by: Frank Wang <frank.wang@rock-chips.com>
This commit is contained in:
William Wu
2018-03-07 18:13:37 +08:00
committed by Frank Wang
parent a068d93125
commit 6e6adab8f7
2 changed files with 45 additions and 0 deletions

View File

@@ -23,6 +23,7 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/of_platform.h>
#include <linux/platform_data/s3c-hsotg.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
@@ -4473,6 +4474,24 @@ static int dwc2_hsotg_udc_start(struct usb_gadget *gadget,
goto err;
}
if (hsotg->dr_mode == USB_DR_MODE_OTG) {
struct platform_device *pdev = to_platform_device(hsotg->dev);
if (hsotg->uphy) {
ret = usb_phy_init(hsotg->uphy);
} else if (hsotg->plat && hsotg->plat->phy_init) {
ret = hsotg->plat->phy_init(pdev,
hsotg->plat->phy_type);
} else {
ret = phy_power_on(hsotg->phy);
if (ret == 0)
ret = phy_init(hsotg->phy);
}
if (ret)
goto err;
}
if (!IS_ERR_OR_NULL(hsotg->uphy))
otg_set_peripheral(hsotg->uphy->otg, &hsotg->gadget);
@@ -4532,6 +4551,19 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget)
if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
dwc2_lowlevel_hw_disable(hsotg);
if (hsotg->dr_mode == USB_DR_MODE_OTG) {
struct platform_device *pdev = to_platform_device(hsotg->dev);
if (hsotg->uphy) {
usb_phy_shutdown(hsotg->uphy);
} else if (hsotg->plat && hsotg->plat->phy_exit) {
hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
} else {
phy_exit(hsotg->phy);
phy_power_off(hsotg->phy);
}
}
return 0;
}

View File

@@ -599,6 +599,19 @@ static int dwc2_driver_probe(struct platform_device *dev)
if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
dwc2_lowlevel_hw_disable(hsotg);
if (hsotg->dr_mode == USB_DR_MODE_OTG) {
struct platform_device *pdev = to_platform_device(hsotg->dev);
if (hsotg->uphy) {
usb_phy_shutdown(hsotg->uphy);
} else if (hsotg->plat && hsotg->plat->phy_exit) {
hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
} else {
phy_exit(hsotg->phy);
phy_power_off(hsotg->phy);
}
}
#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \
IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
/* Postponed adding a new gadget to the udc class driver list */