diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 8e4f5a2cd259..03b390b0fa5a 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -126,6 +126,18 @@ static void __dwc3_set_mode(struct work_struct *work) pm_runtime_get_sync(dwc->dev); +#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI) + if (dwc->desired_role_sw_mode == USB_DR_MODE_PERIPHERAL && + dwc->desired_role_sw_mode != dwc->current_role_sw_mode) + pm_runtime_get(dwc->dev); + else if ((dwc->desired_role_sw_mode == USB_DR_MODE_UNKNOWN || + dwc->desired_role_sw_mode == USB_DR_MODE_HOST) && + dwc->current_role_sw_mode == USB_DR_MODE_PERIPHERAL) + pm_runtime_put(dwc->dev); + + dwc->current_role_sw_mode = dwc->desired_role_sw_mode; +#endif + if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_OTG) dwc3_otg_update(dwc, 0); @@ -1664,6 +1676,9 @@ static int dwc3_probe(struct platform_device *pdev) if (dwc->dr_mode == USB_DR_MODE_OTG && of_device_is_compatible(dev->parent->of_node, "rockchip,rk3399-dwc3")) { +#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI) + pm_runtime_set_autosuspend_delay(dev, 100); +#endif pm_runtime_allow(dev); pm_runtime_put_sync_suspend(dev); } else { diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 2b44bb38bb7a..ed3fddbc5e04 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1010,6 +1010,8 @@ struct dwc3_scratchpad_array { * @role_sw: usb_role_switch handle * @role_switch_default_mode: default operation mode of controller while * usb role is USB_ROLE_NONE. + * @current_role_sw_mode: current usb role switch mode. + * @desired_role_sw_mode: desired usb role switch mode. * @usb_psy: pointer to power supply interface. * @usb2_phy: pointer to USB2 PHY * @usb3_phy: pointer to USB3 PHY @@ -1160,6 +1162,10 @@ struct dwc3 { enum usb_phy_interface hsphy_mode; struct usb_role_switch *role_sw; enum usb_dr_mode role_switch_default_mode; +#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI) + u32 current_role_sw_mode; + u32 desired_role_sw_mode; +#endif struct power_supply *usb_psy; diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c index e2b68bb770d1..f50255a71770 100644 --- a/drivers/usb/dwc3/drd.c +++ b/drivers/usb/dwc3/drd.c @@ -431,6 +431,15 @@ static int dwc3_drd_notifier(struct notifier_block *nb, { struct dwc3 *dwc = container_of(nb, struct dwc3, edev_nb); +#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI) + if (extcon_get_state(dwc->edev, EXTCON_USB)) + dwc->desired_role_sw_mode = USB_DR_MODE_PERIPHERAL; + else if (extcon_get_state(dwc->edev, EXTCON_USB_HOST)) + dwc->desired_role_sw_mode = USB_DR_MODE_HOST; + else + dwc->desired_role_sw_mode = USB_DR_MODE_UNKNOWN; +#endif + dwc3_set_mode(dwc, event ? DWC3_GCTL_PRTCAP_HOST : DWC3_GCTL_PRTCAP_DEVICE); @@ -491,6 +500,10 @@ static int dwc3_usb_role_switch_set(struct usb_role_switch *sw, struct dwc3 *dwc = usb_role_switch_get_drvdata(sw); u32 mode; +#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI) + dwc->desired_role_sw_mode = role; +#endif + switch (role) { case USB_ROLE_HOST: mode = DWC3_GCTL_PRTCAP_HOST;