From patchwork Fri Sep 29 13:06:28 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jon Hunter X-Patchwork-Id: 819911 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-tegra-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3y3X102tJSz9ryk for ; Fri, 29 Sep 2017 23:08:04 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752048AbdI2NIC (ORCPT ); Fri, 29 Sep 2017 09:08:02 -0400 Received: from hqemgate14.nvidia.com ([216.228.121.143]:12497 "EHLO hqemgate14.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751349AbdI2NIC (ORCPT ); Fri, 29 Sep 2017 09:08:02 -0400 Received: from hqpgpgate102.nvidia.com (Not Verified[216.228.121.13]) by hqemgate14.nvidia.com id ; Fri, 29 Sep 2017 06:07:31 -0700 Received: from HQMAIL105.nvidia.com ([172.20.161.6]) by hqpgpgate102.nvidia.com (PGP Universal service); Fri, 29 Sep 2017 06:07:37 -0700 X-PGP-Universal: processed; by hqpgpgate102.nvidia.com on Fri, 29 Sep 2017 06:07:37 -0700 Received: from HQMAIL108.nvidia.com (172.18.146.13) by HQMAIL105.nvidia.com (172.20.187.12) with Microsoft SMTP Server (TLS) id 15.0.1293.2; Fri, 29 Sep 2017 13:06:32 +0000 Received: from hqnvemgw01.nvidia.com (172.20.150.20) by HQMAIL108.nvidia.com (172.18.146.13) with Microsoft SMTP Server id 15.0.1293.2 via Frontend Transport; Fri, 29 Sep 2017 13:06:33 +0000 Received: from moonraker.nvidia.com (Not Verified[10.21.132.144]) by hqnvemgw01.nvidia.com with Trustwave SEG (v7, 5, 5, 8150) id ; Fri, 29 Sep 2017 06:06:32 -0700 From: Jon Hunter To: Felipe Balbi , Thierry Reding CC: , , Jon Hunter Subject: [PATCH] usb: phy: tegra: Fix phy suspend for UDC Date: Fri, 29 Sep 2017 14:06:28 +0100 Message-ID: <1506690388-23112-1-git-send-email-jonathanh@nvidia.com> X-Mailer: git-send-email 2.7.4 X-NVConfidentiality: public MIME-Version: 1.0 Sender: linux-tegra-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-tegra@vger.kernel.org Commit dfebb5f43a78 ("usb: chipidea: Add support for Tegra20/30/114/124") added UDC support for Tegra but with UDC support enabled, is was found that Tegra30, Tegra114 and Tegra124 would hang on entry to suspend. The hang occurred during the suspend of the USB PHY when the Tegra PHY driver attempted to disable the PHY clock. The problem is that before the Tegra PHY driver is suspended, the chipidea driver already disabled the PHY clock and when the Tegra PHY driver suspended, it could not read DEVLC register and caused the device to hang. The Tegra USB PHY driver is used by both the Tegra EHCI driver and now the chipidea UDC driver and so simply removing the disabling of the PHY clock from the USB PHY driver would not work for the Tegra EHCI driver. Fortunately, the status of the USB PHY clock can be read from the USB_SUSP_CTRL register and therefore, to workaround this issue, simply poll the register prior to disabling the clock in USB PHY driver to see if clock gating has already been initiated. Please note that it can take a few uS for the clock to disable and so simply reading this status register once on entry is not sufficient. Please note that no issues are seen with Tegra20 because it has a slightly different PHY to Tegra30/114/124. Signed-off-by: Jon Hunter --- drivers/usb/phy/phy-tegra-usb.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index 5fe4a5704bde..c8fff99bd16e 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c @@ -329,6 +329,14 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy) unsigned long val; void __iomem *base = phy->regs; + /* + * The USB driver may have already initiated the phy clock + * disable so wait to see if the clock turns off and if not + * then proceed with gating the clock. + */ + if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) == 0) + return; + if (phy->is_legacy_phy) { val = readl(base + USB_SUSP_CTRL); val |= USB_SUSP_SET;