mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
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>
This commit is contained in:
@@ -26,6 +26,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>
|
||||
@@ -3465,6 +3466,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);
|
||||
|
||||
@@ -3524,6 +3543,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -654,6 +654,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);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
||||
Reference in New Issue
Block a user