From patchwork Mon Jul 16 10:25:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enric Balletbo i Serra X-Patchwork-Id: 10526409 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 96880601D2 for ; Mon, 16 Jul 2018 10:26:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 81EBF28A05 for ; Mon, 16 Jul 2018 10:26:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7637E28A39; Mon, 16 Jul 2018 10:26:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1A3F228A05 for ; Mon, 16 Jul 2018 10:26:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728687AbeGPKwl (ORCPT ); Mon, 16 Jul 2018 06:52:41 -0400 Received: from bhuna.collabora.co.uk ([46.235.227.227]:49066 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728025AbeGPKwl (ORCPT ); Mon, 16 Jul 2018 06:52:41 -0400 Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: eballetbo) with ESMTPSA id 5FBD826BEC9 From: Enric Balletbo i Serra To: linux-kernel@vger.kernel.org Cc: briannorris@chromium.org, kernel@collabora.com, heiko@sntech.de, Greg Kroah-Hartman , linux-usb@vger.kernel.org, Felipe Balbi Subject: [PATCH v2] usb: dwc3: of-simple: reset host controller at suspend/resume Date: Mon, 16 Jul 2018 12:25:47 +0200 Message-Id: <20180716102547.10092-1-enric.balletbo@collabora.com> X-Mailer: git-send-email 2.18.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP If we power off the SoC logic rail in S3, we can find that the Type-C PHY can't initialize correctly after system resume. We need to toggle the USB3-OTG reset before trying to initialize the PHY, or else it times out. phy phy-ff800000.phy.9: phy poweron failed --> -110 dwc3 fe900000.dwc3: failed to initialize core dwc3: probe of fe900000.dwc3 failed with error -110 Note that the RK3399 TRM suggests that we should keep the whole usb3 controller in reset for the duration of the Type-C PHY initialization. However, it's hard to assert the reset in the current framework of reset. We're still skeptical about that, and we haven't yet found a case where this seems to have mattered. This approach is much easier, it simply holds the USB3-OTG reset while device is supended. The dwc3 core is going to reinitialize the controller at suspend/resume anyway (including a "soft reset"), so it should be safe to do this. Signed-off-by: Enric Balletbo i Serra --- Dear all, Now that the usb3-phy otg port support for rk3399 has been merged [1] we found that suspend/resume is broken. The problem is well known for ChromeOS kernels, they solved it in a similar way adding a reset pulse on resume in the specific usb glue layer (dwc3-rockchip). In mainline, though, we use the dwc3-of-simple glue layer instead of a specific layer for rockchip. The patch is based on the Brian Norris work but slightly different, it holds the reset while device is suspended. It was tested on a Samsung Chromebook Plus with usbc docking station attached by doing different suspend/resume cycles and checking no usb devices has been lost. I am not sure this is the better way to solve this but I did not find any other way, and, as I am not sure this can be generic, the reset is only done on rockchip platforms. Best regards, Enric [1] bfdca1736ea76345071bbc5607d18928e54909ac ('arm64: dts: rockchip: add usb3-phy otg-port support for rk3399') Changes in v2: - Use a single of_device_is_compatible() call during probe to set a driver flag. drivers/usb/dwc3/dwc3-of-simple.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c index dbeff5e6ad14..40bf9e0bbc59 100644 --- a/drivers/usb/dwc3/dwc3-of-simple.c +++ b/drivers/usb/dwc3/dwc3-of-simple.c @@ -28,6 +28,7 @@ struct dwc3_of_simple { int num_clocks; struct reset_control *resets; bool pulse_resets; + bool need_reset; }; static int dwc3_of_simple_clk_init(struct dwc3_of_simple *simple, int count) @@ -93,6 +94,13 @@ static int dwc3_of_simple_probe(struct platform_device *pdev) platform_set_drvdata(pdev, simple); simple->dev = dev; + /* + * Some controllers need to toggle the usb3-otg reset before trying to + * initialize the PHY, otherwise the PHY times out. + */ + if (of_device_is_compatible(np, "rockchip,rk3399-dwc3")) + simple->need_reset = true; + if (of_device_is_compatible(np, "amlogic,meson-axg-dwc3") || of_device_is_compatible(np, "amlogic,meson-gxl-dwc3")) { shared_resets = true; @@ -201,9 +209,30 @@ static int dwc3_of_simple_runtime_resume(struct device *dev) return 0; } + +static int dwc3_of_simple_suspend(struct device *dev) +{ + struct dwc3_of_simple *simple = dev_get_drvdata(dev); + + if (simple->need_reset) + reset_control_assert(simple->resets); + + return 0; +} + +static int dwc3_of_simple_resume(struct device *dev) +{ + struct dwc3_of_simple *simple = dev_get_drvdata(dev); + + if (simple->need_reset) + reset_control_deassert(simple->resets); + + return 0; +} #endif static const struct dev_pm_ops dwc3_of_simple_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(dwc3_of_simple_suspend, dwc3_of_simple_resume) SET_RUNTIME_PM_OPS(dwc3_of_simple_runtime_suspend, dwc3_of_simple_runtime_resume, NULL) };