Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp273909pxf; Thu, 8 Apr 2021 02:50:19 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzf8KNzSwYJT/mKwFy1KRWCFxeZfyzdM1y0h4FOdpx3N/0stshO3vEpjB4MfPBDaboWrQRp X-Received: by 2002:a05:6402:4405:: with SMTP id y5mr10339714eda.32.1617875419564; Thu, 08 Apr 2021 02:50:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1617875419; cv=none; d=google.com; s=arc-20160816; b=bD2WEzUR3ypRGwrXtuUoxwa+Atl1glbh9vnrRziUNCY2ESzpR6zw4Z8Tgool1ZqAwe FX/ECUqBmlMVvUIIGUWSZGdAPyvx9s8d7qv+bfspAKXafTuMDj7dRwQSkKbdt5a5f5qF SXwEu0cQo9SIH+vZcwiZ1Sv5l5A39oVUZ97iexVh+bVwCVq9k2Zd0hLMFPF08TSNLiAm VSH/Hx/e3FBa+HSongy+q+TkxqVNlTeeyF6ZRCGO5NdQBMSAtF2XEM1v1TVXF+obTfPs /A77k5d4hMsxL4YSNN2dTl5UvdPdw9JWwr9oN9IVJXiaNrQ98yAxgcTp7klXJYkZBYmm 1iNA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:message-id:cc:to:subject:from:references :in-reply-to:date:dkim-signature; bh=w+dpRrJjVuvKXysnwNkSujK7qRmZatXkvpBrN291PR8=; b=KQWjjeGvGXDcUDId7IcmkzmLIpyqNaAeQAPTCjBBW3Hg6jTMQmMoOcOQZRVF32hIXI ZZPohTAhss1syfquBgqGvTeMhCHKNKfVMQW/K5xMItpcB7DiefUb3TIxe7teYb5aIMTS 01PO/vJEQRayLS84hKqmH3aonl8mCyjzry7VC+Fr/zYoKlr7Ilm5xAOJUodek65ZwXnr usdHRXUTvq3O0nEBkhtHeaBwC1kv7sakECV/faBkKGb08iJSJcpYlzr7pRc/OD6IQ5e4 5pHuv2XgM89v+k/ixBvyswA13Fk/WMG7evyCa+1ohCSzgx0s6y4L7PlR2+7XcfMlaQR2 4iwQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@synopsys.com header.s=mail header.b=cBd4j+Ur; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=synopsys.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id e6si9006388edz.407.2021.04.08.02.49.56; Thu, 08 Apr 2021 02:50:19 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@synopsys.com header.s=mail header.b=cBd4j+Ur; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=synopsys.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231545AbhDHJqW (ORCPT + 99 others); Thu, 8 Apr 2021 05:46:22 -0400 Received: from smtprelay-out1.synopsys.com ([149.117.87.133]:36658 "EHLO smtprelay-out1.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231535AbhDHJqV (ORCPT ); Thu, 8 Apr 2021 05:46:21 -0400 Received: from mailhost.synopsys.com (mdc-mailhost2.synopsys.com [10.225.0.210]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by smtprelay-out1.synopsys.com (Postfix) with ESMTPS id 7489BC09B1; Thu, 8 Apr 2021 09:46:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1617875170; bh=FWpEAx8NEXX4eN+wdVxG3JT0O/qA+/18ZWtggy74EFI=; h=Date:In-Reply-To:References:From:Subject:To:Cc:From; b=cBd4j+UravxrJOMFTywrx+rtZ6uXkSuFrBM/WRR9zeoiY5telfvyKDe/VKkJKLmf4 HDL9TY/wuxXjbx009bvfWs0x2+2xH4I0IvT+S1UZCCJfB3Uwz8jRanOck55i8Z0yp4 OFJPE728qci5kYwa78maY/fQV7mgfdASMQsg6aZAiEcyXA5PduKzUWgDjemYlCRlSg eUyly2xfevdhbTEJliRoAC5DjXnZcWp2y0IsAVrN6OJR/A6alezV/Hc7If95vS82g9 Wv9dmXbvqDhwDGpWn0PImm9JYqj2o9kDeiMlfIH1/BE3ncZBPmKhjZpyf76wF4tCiT Ei3E8/ABuI5CQ== Received: from razpc-HP (razpc-hp.internal.synopsys.com [10.116.126.207]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by mailhost.synopsys.com (Postfix) with ESMTPSA id 1A9BAA0094; Thu, 8 Apr 2021 09:46:07 +0000 (UTC) Received: by razpc-HP (sSMTP sendmail emulation); Thu, 08 Apr 2021 13:46:06 +0400 Date: Thu, 08 Apr 2021 13:46:06 +0400 In-Reply-To: References: X-SNPS-Relay: synopsys.com From: Artur Petrosyan Subject: [PATCH v3 13/14] usb: dwc2: Fix partial power down exiting by system resume To: Felipe Balbi , Greg Kroah-Hartman , Minas Harutyunyan , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Douglas Anderson Cc: John Youn , Artur Petrosyan , Paul Zimmerman , , Kever Yang Message-Id: <20210408094607.1A9BAA0094@mailhost.synopsys.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Fixes the implementation of exiting from partial power down power saving mode when PC is resumed. Added port connection status checking which prevents exiting from Partial Power Down mode from _dwc2_hcd_resume() if not in Partial Power Down mode. Rearranged the implementation to get rid of many "if" statements. NOTE: Switch case statement is used for hibernation partial power down and clock gating mode determination. In this patch only Partial Power Down is implemented the Hibernation and clock gating implementations are planned to be added. Cc: Fixes: 6f6d70597c15 ("usb: dwc2: bus suspend/resume for hosts with DWC2_POWER_DOWN_PARAM_NONE") Signed-off-by: Artur Petrosyan --- Changes in v3: - None Changes in v2: - None drivers/usb/dwc2/hcd.c | 90 +++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 34030bafdff4..f096006df96f 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -4427,7 +4427,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd) { struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); unsigned long flags; - u32 pcgctl; + u32 hprt0; int ret = 0; spin_lock_irqsave(&hsotg->lock, flags); @@ -4438,11 +4438,40 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd) if (hsotg->lx_state != DWC2_L2) goto unlock; - if (hsotg->params.power_down > DWC2_POWER_DOWN_PARAM_PARTIAL) { + hprt0 = dwc2_read_hprt0(hsotg); + + /* + * Added port connection status checking which prevents exiting from + * Partial Power Down mode from _dwc2_hcd_resume() if not in Partial + * Power Down mode. + */ + if (hprt0 & HPRT0_CONNSTS) { + hsotg->lx_state = DWC2_L0; + goto unlock; + } + + switch (hsotg->params.power_down) { + case DWC2_POWER_DOWN_PARAM_PARTIAL: + ret = dwc2_exit_partial_power_down(hsotg, 0, true); + if (ret) + dev_err(hsotg->dev, + "exit partial_power_down failed\n"); + /* + * Set HW accessible bit before powering on the controller + * since an interrupt may rise. + */ + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + break; + case DWC2_POWER_DOWN_PARAM_HIBERNATION: + case DWC2_POWER_DOWN_PARAM_NONE: + default: hsotg->lx_state = DWC2_L0; goto unlock; } + /* Change Root port status, as port status change occurred after resume.*/ + hsotg->flags.b.port_suspend_change = 1; + /* * Enable power if not already done. * This must not be spinlocked since duration @@ -4454,52 +4483,25 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd) spin_lock_irqsave(&hsotg->lock, flags); } - if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_PARTIAL) { - /* - * Set HW accessible bit before powering on the controller - * since an interrupt may rise. - */ - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - - - /* Exit partial_power_down */ - ret = dwc2_exit_partial_power_down(hsotg, 0, true); - if (ret && (ret != -ENOTSUPP)) - dev_err(hsotg->dev, "exit partial_power_down failed\n"); - } else { - pcgctl = readl(hsotg->regs + PCGCTL); - pcgctl &= ~PCGCTL_STOPPCLK; - writel(pcgctl, hsotg->regs + PCGCTL); - } - - hsotg->lx_state = DWC2_L0; - + /* Enable external vbus supply after resuming the port. */ spin_unlock_irqrestore(&hsotg->lock, flags); + dwc2_vbus_supply_init(hsotg); - if (hsotg->bus_suspended) { - spin_lock_irqsave(&hsotg->lock, flags); - hsotg->flags.b.port_suspend_change = 1; - spin_unlock_irqrestore(&hsotg->lock, flags); - dwc2_port_resume(hsotg); - } else { - if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_PARTIAL) { - dwc2_vbus_supply_init(hsotg); - - /* Wait for controller to correctly update D+/D- level */ - usleep_range(3000, 5000); - } + /* Wait for controller to correctly update D+/D- level */ + usleep_range(3000, 5000); + spin_lock_irqsave(&hsotg->lock, flags); - /* - * Clear Port Enable and Port Status changes. - * Enable Port Power. - */ - dwc2_writel(hsotg, HPRT0_PWR | HPRT0_CONNDET | - HPRT0_ENACHG, HPRT0); - /* Wait for controller to detect Port Connect */ - usleep_range(5000, 7000); - } + /* + * Clear Port Enable and Port Status changes. + * Enable Port Power. + */ + dwc2_writel(hsotg, HPRT0_PWR | HPRT0_CONNDET | + HPRT0_ENACHG, HPRT0); - return ret; + /* Wait for controller to detect Port Connect */ + spin_unlock_irqrestore(&hsotg->lock, flags); + usleep_range(5000, 7000); + spin_lock_irqsave(&hsotg->lock, flags); unlock: spin_unlock_irqrestore(&hsotg->lock, flags); -- 2.25.1