Received: by 2002:a25:ab43:0:0:0:0:0 with SMTP id u61csp7526234ybi; Wed, 5 Jun 2019 19:55:39 -0700 (PDT) X-Google-Smtp-Source: APXvYqzK5ywCJZmiE6QErpSF+01cxYwlGTo3YVypgPT+wUp5Dt7dtrG6iezZxf0kZM78JxiHxGsC X-Received: by 2002:a63:dd05:: with SMTP id t5mr1058333pgg.229.1559789739040; Wed, 05 Jun 2019 19:55:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1559789739; cv=none; d=google.com; s=arc-20160816; b=EVWOXiN8AE2ssF4u66/8X1PE8QiaO7EjBubyJtXbV9d8y9E64/X9zFySPLmmb41kTH vp2Ee4QMRE8tZa0nFR3thPbEeS0Fi0WzrM02ZTTLNBCl598fluqjMh8VUA9gPxJZIyC2 PwoH+UDyQSQOkksvXxCadsBG1K1uRrq/SvAxDqjWwESIjqE/BCMN8WwyBt7/Nu/G3W0O Z4ghEKpLipHMi0/DJqwDPhGcINf3X3fqn7UUQWAunwTvbCvpbJQPV0SK3rZGmgkt10CG 0zOV+MrOBQ9aZpk5aYkPZzDBAq/dzslvjDfF9LO2X+5Vsbnfcuu7/8K0+bfOMtJBoRJn I4kg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=tKGiHW81M3ALDBSsorAYqUpdh4csk+zkJolKIuT0SUg=; b=gyxB9hovLUp80JS3LsErNfnWn5HWReYMYjgkaUg4cc4506nT3eO7n6coRfH9HkN4Pw 5xeT9IL5eb/6bo831cbnJC4QMeS1trchWyIw6ZgPOZRPxI4Wr4m4KLyJJHlnHDM3B0Uo 2BFkRHml2aHdNDbZesNG94L5vgxAlN28rorRPYG781+Tiz7qHxS5Fy+GQJ28DeC25JHj jhaA/M/Y9EW5Ply1FZ2vXB95b26eAday0vNzIEyevEFGa+Ww9r86fYu5aMtTr61AewB9 NlcJ8hZp26EevccRHB/R82f86c6ky8HcDC5eGM6Q27/8lTQMflK3pjWlzT3FxAVawzUk Kp9g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=nxp.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t20si579355pgm.589.2019.06.05.19.55.22; Wed, 05 Jun 2019 19:55:39 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=nxp.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726735AbfFFCwp (ORCPT + 99 others); Wed, 5 Jun 2019 22:52:45 -0400 Received: from inva020.nxp.com ([92.121.34.13]:37692 "EHLO inva020.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726474AbfFFCwm (ORCPT ); Wed, 5 Jun 2019 22:52:42 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id A83011A0FA4; Thu, 6 Jun 2019 04:52:39 +0200 (CEST) Received: from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com [165.114.16.14]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 5911B1A00F6; Thu, 6 Jun 2019 04:52:35 +0200 (CEST) Received: from localhost.localdomain (mega.ap.freescale.net [10.192.208.232]) by invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id EE2D1402D5; Thu, 6 Jun 2019 10:52:29 +0800 (SGT) From: Ran Wang To: Greg Kroah-Hartman , Rob Herring , Mark Rutland , Felipe Balbi , Yang Li Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Ran Wang Subject: [RESEND][PATCH v3 2/2] usb: dwc3: Add workaround for host mode VBUS glitch when boot Date: Thu, 6 Jun 2019 10:54:18 +0800 Message-Id: <20190606025418.26313-2-ran.wang_1@nxp.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190606025418.26313-1-ran.wang_1@nxp.com> References: <20190606025418.26313-1-ran.wang_1@nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When DWC3 is set to host mode by programming register DWC3_GCTL, VBUS (or its control signal) will be turned on immediately on related Root Hub ports. Then, the VBUS is turned off for a little while(15us) when do xhci reset (conducted by xhci driver) and back to normal finally, we can observe a negative glitch of related signal happen. This VBUS glitch might cause some USB devices enumeration fail if kernel boot with them connected. Such as LS1012AFWRY/LS1043ARDB/LX2160AQDS /LS1088ARDB with Kingston 16GB USB2.0/Kingston USB3.0/JetFlash Transcend 4GB USB2.0 drives. The fail cases include enumerated as full-speed device or report wrong device descriptor, etc. One SW workaround which can fix this is by programing all xhci PORTSC[PP] to 0 to turn off VBUS immediately after setting host mode in DWC3 driver (per signal measurement result, it will be too late to do it in xhci-plat.c or xhci.c). Then, after xhci reset complete in xhci driver, PORTSC[PP]s' value will back to 1 automatically and VBUS on at that time, no glitch happen and normal enumeration process has no impact. Signed-off-by: Ran Wang --- Changes in v3: - Add macro PORT_REGS_SIZE to replace 0x10 - Change initial value of i to 0 for the for loop - Cosmetic changes Changes in v2: - Rename related property to 'snps,host-vbus-glitches' - Rename related dwc member to 'host_vbus_glitches' - Add member 'host_vbus_glitches' description in 'dwc3' drivers/usb/dwc3/core.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/dwc3/core.h | 12 +++++++++++ 2 files changed, 60 insertions(+), 0 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index a1b126f..dd80e3d 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -100,6 +100,42 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc) return 0; } +/* + * dwc3_power_of_all_roothub_ports - Power off all Root hub ports + * @dwc3: Pointer to our controller context structure + */ +static void dwc3_power_off_all_roothub_ports(struct dwc3 *dwc) +{ + int i, port_num; + u32 reg, op_regs_base, offset; + void __iomem *xhci_regs; + + /* xhci regs is not mapped yet, do it temperary here */ + if (dwc->xhci_resources[0].start) { + xhci_regs = ioremap(dwc->xhci_resources[0].start, + DWC3_XHCI_REGS_END); + if (IS_ERR(xhci_regs)) { + dev_err(dwc->dev, "Failed to ioremap xhci_regs\n"); + return; + } + + op_regs_base = HC_LENGTH(readl(xhci_regs)); + reg = readl(xhci_regs + XHCI_HCSPARAMS1); + port_num = HCS_MAX_PORTS(reg); + + for (i = 0; i < port_num; i++) { + offset = op_regs_base + XHCI_PORTSC_BASE + + PORT_REGS_SIZE * i; + reg = readl(xhci_regs + offset); + reg &= ~PORT_POWER; + writel(reg, xhci_regs + offset); + } + + iounmap(xhci_regs); + } else + dev_err(dwc->dev, "xhci base reg invalid\n"); +} + void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode) { u32 reg; @@ -109,6 +145,15 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode) reg |= DWC3_GCTL_PRTCAPDIR(mode); dwc3_writel(dwc->regs, DWC3_GCTL, reg); + /* + * We have to power off all Root hub ports immediately after DWC3 set + * to host mode to avoid VBUS glitch happen when xhci get reset later. + */ + if (dwc->host_vbus_glitches) { + if (mode == DWC3_GCTL_PRTCAP_HOST) + dwc3_power_off_all_roothub_ports(dwc); + } + dwc->current_dr_role = mode; } @@ -1306,6 +1351,9 @@ static void dwc3_get_properties(struct dwc3 *dwc) dwc->dis_metastability_quirk = device_property_read_bool(dev, "snps,dis_metastability_quirk"); + dwc->host_vbus_glitches = device_property_read_bool(dev, + "snps,host-vbus-glitches"); + dwc->lpm_nyet_threshold = lpm_nyet_threshold; dwc->tx_de_emphasis = tx_de_emphasis; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index df87641..c2dee0b 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -606,6 +606,15 @@ #define DWC3_OSTS_VBUSVLD BIT(1) #define DWC3_OSTS_CONIDSTS BIT(0) +/* Partial XHCI Register and Bit fields for quirk */ +#define XHCI_HCSPARAMS1 0x4 +#define XHCI_PORTSC_BASE 0x400 +#define PORT_REGS_SIZE 0x10 +#define PORT_POWER (1 << 9) +#define HCS_MAX_PORTS(p) (((p) >> 24) & 0x7f) +#define XHCI_HC_LENGTH(p) (((p)>>00)&0x00ff) +#define HC_LENGTH(p) XHCI_HC_LENGTH(p) + /* Structures */ struct dwc3_trb; @@ -1024,6 +1033,8 @@ struct dwc3_scratchpad_array { * 2 - No de-emphasis * 3 - Reserved * @dis_metastability_quirk: set to disable metastability quirk. + * @host-vbus-glitches: set to avoid vbus glitch during + * xhci reset. * @imod_interval: set the interrupt moderation interval in 250ns * increments or 0 to disable. */ @@ -1209,6 +1220,7 @@ struct dwc3 { unsigned tx_de_emphasis:2; unsigned dis_metastability_quirk:1; + unsigned host_vbus_glitches:1; u16 imod_interval; }; -- 1.7.1