Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933119AbeALEAh (ORCPT + 1 other); Thu, 11 Jan 2018 23:00:37 -0500 Received: from regular1.263xmail.com ([211.150.99.133]:42413 "EHLO regular1.263xmail.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932860AbeALEAg (ORCPT ); Thu, 11 Jan 2018 23:00:36 -0500 X-263anti-spam: KSV:0; X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-KSVirus-check: 0 X-ABS-CHECKED: 4 X-RL-SENDER: william.wu@rock-chips.com X-FST-TO: balbi@kernel.org X-SENDER-IP: 58.22.7.114 X-LOGIN-NAME: william.wu@rock-chips.com X-UNIQUE-TAG: <793af2666c295eef5330331d3347b947> X-ATTACHMENT-NUM: 0 X-DNS-TYPE: 0 From: William Wu To: balbi@kernel.org, gregkh@linuxfoundation.org Cc: heiko@sntech.de, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, linux-rockchip@lists.infradead.org, frank.wang@rock-chips.com, huangtao@rock-chips.com, dianders@google.com, briannorris@google.com, groeck@google.com, daniel.meng@rock-chips.com, John.Youn@synopsys.com, william.wu@rock-chips.com, lin.huang@rock-chips.com Subject: [PATCH] usb: dwc3: core: power on PHYs before initializing core Date: Fri, 12 Jan 2018 12:00:16 +0800 Message-Id: <1515729616-8639-1-git-send-email-william.wu@rock-chips.com> X-Mailer: git-send-email 2.0.0 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Return-Path: The dwc3_core_init() gets the PHYs and initializes the PHYs with the usb_phy_init() and phy_init() functions before initializing core, and power on the PHYs after core initialization is done. However, some platforms (e.g. Rockchip RK3399 DWC3 with Type-C USB3 PHY), it needs to do some special operation while power on the Type-C PHY before initializing DWC3 core. It's because that the RK3399 Type-C PHY requires to hold the DWC3 controller in reset state to keep the PIPE power state in P2 while configuring the Type-C PHY, otherwise, it may cause waiting for the PIPE ready timeout. In this case, if we power on the PHYs after the DWC3 core initialization is done, the core will be reset to uninitialized state after power on the PHYs. Fix this by powering on the PHYs before initializing core. And because the GUID register may also be reset in this case, so we need to configure the GUID register after powering on the PHYs. Signed-off-by: William Wu --- drivers/usb/dwc3/core.c | 46 ++++++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c32d2b9..4f5573f 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -741,12 +741,6 @@ static int dwc3_core_init(struct dwc3 *dwc) goto err0; } - /* - * Write Linux Version Code to our GUID register so it's easy to figure - * out which kernel version a bug was found. - */ - dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); - /* Handle USB2.0-only core configuration */ if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { @@ -762,34 +756,40 @@ static int dwc3_core_init(struct dwc3 *dwc) if (ret) goto err0; + usb_phy_set_suspend(dwc->usb2_phy, 0); + usb_phy_set_suspend(dwc->usb3_phy, 0); + ret = phy_power_on(dwc->usb2_generic_phy); + if (ret < 0) + goto err1; + + ret = phy_power_on(dwc->usb3_generic_phy); + if (ret < 0) + goto err2; + ret = dwc3_phy_setup(dwc); if (ret) - goto err0; + goto err3; + + /* + * Write Linux Version Code to our GUID register so it's easy to figure + * out which kernel version a bug was found. + */ + dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); dwc3_core_setup_global_control(dwc); dwc3_core_num_eps(dwc); ret = dwc3_setup_scratch_buffers(dwc); if (ret) - goto err1; + goto err3; /* Adjust Frame Length */ dwc3_frame_length_adjustment(dwc); - usb_phy_set_suspend(dwc->usb2_phy, 0); - usb_phy_set_suspend(dwc->usb3_phy, 0); - ret = phy_power_on(dwc->usb2_generic_phy); - if (ret < 0) - goto err2; - - ret = phy_power_on(dwc->usb3_generic_phy); - if (ret < 0) - goto err3; - ret = dwc3_event_buffers_setup(dwc); if (ret) { dev_err(dwc->dev, "failed to setup event buffers\n"); - goto err4; + goto err3; } /* @@ -821,17 +821,15 @@ static int dwc3_core_init(struct dwc3 *dwc) return 0; -err4: +err3: phy_power_off(dwc->usb3_generic_phy); -err3: +err2: phy_power_off(dwc->usb2_generic_phy); -err2: +err1: usb_phy_set_suspend(dwc->usb2_phy, 1); usb_phy_set_suspend(dwc->usb3_phy, 1); - -err1: usb_phy_shutdown(dwc->usb2_phy); usb_phy_shutdown(dwc->usb3_phy); phy_exit(dwc->usb2_generic_phy); -- 2.0.0