From patchwork Thu Nov 8 03:51:09 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thinh Nguyen X-Patchwork-Id: 10673429 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 91F8714E2 for ; Thu, 8 Nov 2018 03:51:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 824392C661 for ; Thu, 8 Nov 2018 03:51:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 76E982C67A; Thu, 8 Nov 2018 03:51:12 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham 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 1408A2C6E9 for ; Thu, 8 Nov 2018 03:51:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728702AbeKHNYh (ORCPT ); Thu, 8 Nov 2018 08:24:37 -0500 Received: from smtprelay.synopsys.com ([198.182.60.111]:34284 "EHLO smtprelay.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728499AbeKHNYh (ORCPT ); Thu, 8 Nov 2018 08:24:37 -0500 Received: from mailhost.synopsys.com (mailhost3.synopsys.com [10.12.238.238]) by smtprelay.synopsys.com (Postfix) with ESMTP id C366310C06BA; Wed, 7 Nov 2018 19:51:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1541649070; bh=Re2MOjyyqKAPg+jWRqb7Os+gYfNBt3BVuoQYAIlv/sE=; h=Date:In-Reply-To:References:From:Subject:To:CC:From; b=NhzSndEzrAocwHsQlIakacsFFWvEld1/UQNok2krNkzSvY7+B31ZdPODxfYKJxerF m1gqTghgyG6IOHNXtHudMcOBAeBeDkRlGL9vdUOKcxGk//8IZfi4iOSce6mav/fYui 3uNb/+BXBYtjn34o7bp3Fkv7ULqNv1zP3QzIA/MMnwui1Vu3R+8tt7+Jk9ocqhcuEW oSNW3tjYTSmRYV2mzfTj5zAW3qougrAUcmDs6hmw+8v3Xu6ZO5UVKa9e8zysABEm7P 8rAtW6aetuwmkGETRrv0myzywj3Cpd28veFrUi6zKrurhpHz7Xw3Q54slmIjLtGWdB 73HOC7X9WsE3g== Received: from US01WEHTC2.internal.synopsys.com (us01wehtc2-vip.internal.synopsys.com [10.12.239.238]) by mailhost.synopsys.com (Postfix) with ESMTP id B279E3EF2; Wed, 7 Nov 2018 19:51:10 -0800 (PST) Received: from US01WEHTC1.internal.synopsys.com (10.12.239.236) by US01WEHTC2.internal.synopsys.com (10.12.239.237) with Microsoft SMTP Server (TLS) id 14.3.408.0; Wed, 7 Nov 2018 19:51:10 -0800 Received: from te-lab16 (10.13.184.20) by us01wehtc1.internal.synopsys.com (10.12.239.236) with Microsoft SMTP Server (TLS) id 14.3.408.0; Wed, 7 Nov 2018 19:51:09 -0800 Received: by te-lab16 (sSMTP sendmail emulation); Wed, 07 Nov 2018 19:51:09 -0800 Date: Wed, 7 Nov 2018 19:51:09 -0800 Message-ID: <622262de3da148ecccbed5a82406421b213c997e.1541648784.git.thinhn@synopsys.com> In-Reply-To: References: From: Thinh Nguyen Subject: [PATCH v5 1/3] usb: dwc3: Track DWC_usb31 VERSIONTYPE To: Felipe Balbi , CC: John Youn MIME-Version: 1.0 X-Originating-IP: [10.13.184.20] 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 Add a new field to dwc3 structure to track VERSIONTYPE. The VERSIONTYPE is represented in ASCII in the 32-bit VERSIONTYPE register. In DWC_usb31, sub releases for each version are tracked with VERSIONTYPE such as "ea01" and "ea02". Signed-off-by: Thinh Nguyen --- drivers/usb/dwc3/core.c | 1 + drivers/usb/dwc3/core.h | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index becfbb87f791..437816ff8860 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -702,6 +702,7 @@ static bool dwc3_core_is_valid(struct dwc3 *dwc) /* Detected DWC_usb31 IP */ dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); dwc->revision |= DWC3_REVISION_IS_DWC31; + dwc->version_type = dwc3_readl(dwc->regs, DWC3_VER_TYPE); } else { return false; } diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 5bfb62533e0f..4573e1bfd56e 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -918,6 +918,7 @@ struct dwc3_scratchpad_array { * @u1u2: only used on revisions <1.83a for workaround * @maximum_speed: maximum speed requested (mainly for testing purposes) * @revision: revision register contents + * @version_type: VERSIONTYPE register contents, a sub release of a revision * @dr_mode: requested mode of operation * @current_dr_role: current role of operation when in dual-role mode * @desired_dr_role: desired role of operation when in dual-role mode @@ -1104,6 +1105,10 @@ struct dwc3 { #define DWC3_USB31_REVISION_110A (0x3131302a | DWC3_REVISION_IS_DWC31) #define DWC3_USB31_REVISION_120A (0x3132302a | DWC3_REVISION_IS_DWC31) + u32 version_type; + +#define DWC31_VERSIONTYPE_EA01 0x65613031 + enum dwc3_ep0_next ep0_next_event; enum dwc3_ep0_state ep0state; enum dwc3_link_state link_state; From patchwork Thu Nov 8 03:51:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thinh Nguyen X-Patchwork-Id: 10673431 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CEBB215E9 for ; Thu, 8 Nov 2018 03:51:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C00DC2C5E5 for ; Thu, 8 Nov 2018 03:51:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B42782C639; Thu, 8 Nov 2018 03:51:18 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham 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 557942C661 for ; Thu, 8 Nov 2018 03:51:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728746AbeKHNYo (ORCPT ); Thu, 8 Nov 2018 08:24:44 -0500 Received: from smtprelay2.synopsys.com ([198.182.60.111]:34294 "EHLO smtprelay.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728499AbeKHNYn (ORCPT ); Thu, 8 Nov 2018 08:24:43 -0500 Received: from mailhost.synopsys.com (mailhost3.synopsys.com [10.12.238.238]) by smtprelay.synopsys.com (Postfix) with ESMTP id 56ED710C0F63; Wed, 7 Nov 2018 19:51:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1541649077; bh=opCSGNTHEoFfYR0YpSiwWbv2x08SOqyC7kX5DoFPvMs=; h=Date:In-Reply-To:References:From:Subject:To:CC:From; b=UH5CcXgPgJpKnD7w1XBcdzUeg8Qq58wrYRX9Xn5GWzX2P/3m4VC883jKUYDpwVqlc tKGE/qrhmK0bTREjpodvpIxu8zxdy8SliuIH1neAy5k0MgR9ZCeftFiHLkADg0RNJ/ tHapxHPCdXU6WdSPWJzOmsNQNmBqZlSwFHH1gm5H6LKjFhEC32v9gY9lP76ymo2Eot 5LCkmJnGY5uIaEepsY6GmHHplmiCQ4NbbTNOJjcrNgkJRpfvqzVWErZOkiJCMBXp1U PAdhvwrjwtV++xBz2WTXrOfxGclHq2OpEuoH9S3F4ALEBduAJ0cfxkwEpQTzbwuBes lEzfzwsOCcFnw== Received: from US01WXQAHTC1.internal.synopsys.com (us01wxqahtc1.internal.synopsys.com [10.12.238.230]) by mailhost.synopsys.com (Postfix) with ESMTP id 3AB333F06; Wed, 7 Nov 2018 19:51:17 -0800 (PST) Received: from US01WEHTC1.internal.synopsys.com (10.12.239.236) by US01WXQAHTC1.internal.synopsys.com (10.12.238.230) with Microsoft SMTP Server (TLS) id 14.3.408.0; Wed, 7 Nov 2018 19:51:17 -0800 Received: from te-lab16 (10.13.184.20) by us01wehtc1.internal.synopsys.com (10.12.239.236) with Microsoft SMTP Server (TLS) id 14.3.408.0; Wed, 7 Nov 2018 19:51:15 -0800 Received: by te-lab16 (sSMTP sendmail emulation); Wed, 07 Nov 2018 19:51:15 -0800 Date: Wed, 7 Nov 2018 19:51:15 -0800 Message-ID: <49d57899abea493e72f1b516650a60ef25cdc06c.1541648784.git.thinhn@synopsys.com> In-Reply-To: References: From: Thinh Nguyen Subject: [PATCH v5 2/3] usb: dwc3: Add disabling of start_transfer failure quirk To: Felipe Balbi , , , Rob Herring , Mark Rutland CC: John Youn MIME-Version: 1.0 X-Originating-IP: [10.13.184.20] 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 DWC_usb31 peripheral v1.70a-ea06 and prior needs a SW workaround for isoc START TRANSFER command failure. However, some affected versions may have RTL patches to fix this without a SW workaround. Add this quirk to disable the SW workaround when it is not needed. Synopsys STAR 9001202023: Wrong microframe number for isochronous IN endpoints. Signed-off-by: Thinh Nguyen --- Documentation/devicetree/bindings/usb/dwc3.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt index 636630fb92d7..fc64db0a7a0a 100644 --- a/Documentation/devicetree/bindings/usb/dwc3.txt +++ b/Documentation/devicetree/bindings/usb/dwc3.txt @@ -37,6 +37,9 @@ Optional properties: - phy-names: from the *Generic PHY* bindings; supported names are "usb2-phy" or "usb3-phy". - resets: a single pair of phandle and reset specifier + - snps,dis-start-transfer-quirk: when set, disable isoc START TRANSFER command + failure SW work-around for DWC_usb31 version 1.70a-ea06 + and prior. - snps,usb3_lpm_capable: determines if platform is USB3 LPM capable - snps,disable_scramble_quirk: true when SW should disable data scrambling. Only really useful for FPGA builds. From patchwork Thu Nov 8 03:51:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thinh Nguyen X-Patchwork-Id: 10673433 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0278615E9 for ; Thu, 8 Nov 2018 03:51:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E66162C5E7 for ; Thu, 8 Nov 2018 03:51:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DAC0C2C6E9; Thu, 8 Nov 2018 03:51:25 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham 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 DA09E2C67A for ; Thu, 8 Nov 2018 03:51:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728760AbeKHNYu (ORCPT ); Thu, 8 Nov 2018 08:24:50 -0500 Received: from smtprelay2.synopsys.com ([198.182.60.111]:34300 "EHLO smtprelay.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728499AbeKHNYu (ORCPT ); Thu, 8 Nov 2018 08:24:50 -0500 Received: from mailhost.synopsys.com (mailhost2.synopsys.com [10.13.184.66]) by smtprelay.synopsys.com (Postfix) with ESMTP id BFE5E10C06BA; Wed, 7 Nov 2018 19:51:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1541649083; bh=cvGRcjXvjEv/vGI9+YJUtEyZq87vG7Vsp1pP3HlEEk0=; h=Date:In-Reply-To:References:From:Subject:To:CC:From; b=cEFil71+iOjxTXsyt81jrM6Wlp3eOoTDx59O5dY37araSGTsYf9pC3YIPZD9nVWMK lGOsUr5tKqpEOkB6SKMq3nhBpInesI9F2krA6k0TRvAHqsJn/2494/UNThjTz4XQmv 0NJR7CK6jjD30D+0EcmvF7ttPNGvPYr2YNzJMpbBNxIi21fJA3EDStl6SWttdlxIjs MGEgtBIsKBWaGWtNcL27HIiwJA/V1KFzeLR6d7PoMI5ICGP5b7Tx1OBX6sGjZ9JrwC 95BozGd58IjOP7uxSURkPQD7Jc0fDt5SC1gtSAyr+6i/48JV4YO9NMNkapNDYiutf9 iHFlHL4jBEp8Q== Received: from US01WEHTC3.internal.synopsys.com (us01wehtc3.internal.synopsys.com [10.15.84.232]) by mailhost.synopsys.com (Postfix) with ESMTP id B34233D8C; Wed, 7 Nov 2018 19:51:23 -0800 (PST) Received: from US01WEHTC1.internal.synopsys.com (10.12.239.236) by US01WEHTC3.internal.synopsys.com (10.15.84.232) with Microsoft SMTP Server (TLS) id 14.3.408.0; Wed, 7 Nov 2018 19:51:23 -0800 Received: from te-lab16 (10.13.184.20) by us01wehtc1.internal.synopsys.com (10.12.239.236) with Microsoft SMTP Server (TLS) id 14.3.408.0; Wed, 7 Nov 2018 19:51:22 -0800 Received: by te-lab16 (sSMTP sendmail emulation); Wed, 07 Nov 2018 19:51:22 -0800 Date: Wed, 7 Nov 2018 19:51:22 -0800 Message-ID: <4c1052cd63421a8d622e1e9baf81c36319ca3266.1541648784.git.thinhn@synopsys.com> In-Reply-To: References: From: Thinh Nguyen Subject: [PATCH v5 3/3] usb: dwc3: Add workaround for isoc start transfer failure To: Felipe Balbi , CC: John Youn MIME-Version: 1.0 X-Originating-IP: [10.13.184.20] 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 In DWC_usb31 version 1.70a-ea06 and prior, for highspeed and fullspeed isochronous IN, BIT[15:14] of the 16-bit microframe number reported by the XferNotReady event are invalid. The driver uses this number to schedule the isochronous transfer and passes it to the START TRANSFER command. Because this number is invalid, the command may fail. If BIT[15:14] matches the internal 16-bit microframe, the START TRANSFER command will pass and the transfer will start at the scheduled time, if it is off by 1, the command will still pass, but the transfer will start 2 seconds in the future. For all other conditions, the START TRANSFER command will fail with bus-expiry. In order to workaround this issue, we can test for the correct combination of BIT[15:14] by sending START TRANSFER commands with different values of BIT[15:14]: 'b00, 'b01, 'b10, and 'b11. Each combination is 2^14 uframe apart (or 2 seconds). 4 seconds into the future will result in a bus-expiry status. As the result, within the 4 possible combinations for BIT[15:14], there will be 2 successful and 2 failure START COMMAND status. One of the 2 successful command status will result in a 2-second delay start. The smaller BIT[15:14] value is the correct combination. Since there are only 4 outcomes and the results are ordered, we can simply test 2 START TRANSFER commands with BIT[15:14] combinations 'b00 and 'b01 to deduce the smaller successful combination. Let test0 = test status for combination 'b00 and test1 = test status for 'b01 of BIT[15:14]. The correct combination is as follow: if test0 fails and test1 passes, BIT[15:14] is 'b01 if test0 fails and test1 fails, BIT[15:14] is 'b10 if test0 passes and test1 fails, BIT[15:14] is 'b11 if test0 passes and test1 passes, BIT[15:14] is 'b00 Synopsys STAR 9001202023: Wrong microframe number for isochronous IN endpoints. Signed-off-by: Thinh Nguyen --- drivers/usb/dwc3/core.c | 2 + drivers/usb/dwc3/core.h | 14 +++++ drivers/usb/dwc3/gadget.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 437816ff8860..d8cb2b1342d8 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1245,6 +1245,8 @@ static void dwc3_get_properties(struct dwc3 *dwc) "snps,is-utmi-l1-suspend"); device_property_read_u8(dev, "snps,hird-threshold", &hird_threshold); + dwc->dis_start_transfer_quirk = device_property_read_bool(dev, + "snps,dis-start-transfer-quirk"); dwc->usb3_lpm_capable = device_property_read_bool(dev, "snps,usb3_lpm_capable"); device_property_read_u8(dev, "snps,rx-thr-num-pkt-prd", diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 4573e1bfd56e..ad2ca3f41f4f 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -656,6 +656,10 @@ struct dwc3_event_buffer { * @name: a human readable name e.g. ep1out-bulk * @direction: true for TX, false for RX * @stream_capable: true when streams are enabled + * @combo_num: the test combination BIT[15:14] of the frame number to test + * isochronous START TRANSFER command failure workaround + * @start_cmd_status: the status of testing START TRANSFER command with + * combo_num = 'b00 */ struct dwc3_ep { struct usb_ep endpoint; @@ -705,6 +709,10 @@ struct dwc3_ep { unsigned direction:1; unsigned stream_capable:1; + + /* For isochronous START TRANSFER workaround only */ + u8 combo_num; + int start_cmd_status; }; enum dwc3_phy { @@ -971,6 +979,8 @@ struct dwc3_scratchpad_array { * @pullups_connected: true when Run/Stop bit is set * @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround * @three_stage_setup: set if we perform a three phase setup + * @dis_start_transfer_quirk: set if start_transfer failure SW workaround is + * not needed for DWC_usb31 version 1.70a-ea06 and below * @usb3_lpm_capable: set if hadrware supports Link Power Management * @disable_scramble_quirk: set if we enable the disable scramble quirk * @u2exit_lfps_quirk: set if we enable u2exit lfps quirk @@ -1104,10 +1114,13 @@ struct dwc3 { #define DWC3_REVISION_IS_DWC31 0x80000000 #define DWC3_USB31_REVISION_110A (0x3131302a | DWC3_REVISION_IS_DWC31) #define DWC3_USB31_REVISION_120A (0x3132302a | DWC3_REVISION_IS_DWC31) +#define DWC3_USB31_REVISION_160A (0x3136302a | DWC3_REVISION_IS_DWC31) +#define DWC3_USB31_REVISION_170A (0x3137302a | DWC3_REVISION_IS_DWC31) u32 version_type; #define DWC31_VERSIONTYPE_EA01 0x65613031 +#define DWC31_VERSIONTYPE_EA06 0x65613036 enum dwc3_ep0_next ep0_next_event; enum dwc3_ep0_state ep0state; @@ -1150,6 +1163,7 @@ struct dwc3 { unsigned pullups_connected:1; unsigned setup_packet_pending:1; unsigned three_stage_setup:1; + unsigned dis_start_transfer_quirk:1; unsigned usb3_lpm_capable:1; unsigned disable_scramble_quirk:1; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 679c12e14522..6b438ae126b1 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1263,8 +1263,126 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc) return DWC3_DSTS_SOFFN(reg); } +/** + * dwc3_gadget_start_isoc_quirk - workaround invalid frame number + * @dep: isoc endpoint + * + * This function tests for the correct combination of BIT[15:14] from the 16-bit + * microframe number reported by the XferNotReady event for the future frame + * number to start the isoc transfer. + * + * In DWC_usb31 version 1.70a-ea06 and prior, for highspeed and fullspeed + * isochronous IN, BIT[15:14] of the 16-bit microframe number reported by the + * XferNotReady event are invalid. The driver uses this number to schedule the + * isochronous transfer and passes it to the START TRANSFER command. Because + * this number is invalid, the command may fail. If BIT[15:14] matches the + * internal 16-bit microframe, the START TRANSFER command will pass and the + * transfer will start at the scheduled time, if it is off by 1, the command + * will still pass, but the transfer will start 2 seconds in the future. For all + * other conditions, the START TRANSFER command will fail with bus-expiry. + * + * In order to workaround this issue, we can test for the correct combination of + * BIT[15:14] by sending START TRANSFER commands with different values of + * BIT[15:14]: 'b00, 'b01, 'b10, and 'b11. Each combination is 2^14 uframe apart + * (or 2 seconds). 4 seconds into the future will result in a bus-expiry status. + * As the result, within the 4 possible combinations for BIT[15:14], there will + * be 2 successful and 2 failure START COMMAND status. One of the 2 successful + * command status will result in a 2-second delay start. The smaller BIT[15:14] + * value is the correct combination. + * + * Since there are only 4 outcomes and the results are ordered, we can simply + * test 2 START TRANSFER commands with BIT[15:14] combinations 'b00 and 'b01 to + * deduce the smaller successful combination. + * + * Let test0 = test status for combination 'b00 and test1 = test status for 'b01 + * of BIT[15:14]. The correct combination is as follow: + * + * if test0 fails and test1 passes, BIT[15:14] is 'b01 + * if test0 fails and test1 fails, BIT[15:14] is 'b10 + * if test0 passes and test1 fails, BIT[15:14] is 'b11 + * if test0 passes and test1 passes, BIT[15:14] is 'b00 + * + * Synopsys STAR 9001202023: Wrong microframe number for isochronous IN + * endpoints. + */ +static void dwc3_gadget_start_isoc_quirk(struct dwc3_ep *dep) +{ + int cmd_status = 0; + bool test0; + bool test1; + + while (dep->combo_num < 2) { + struct dwc3_gadget_ep_cmd_params params; + u32 frame_number; + u32 cmd; + + /* Keep only the 14-bit frame number */ + frame_number = dep->frame_number & 0x3fff; + + /* + * Check if we can start isoc transfer on the next interval or + * 4 uframes in the future with BIT[15:14] as dep->combo_num + */ + frame_number |= dep->combo_num << 14; + frame_number += max_t(u32, 4, dep->interval); + + params.param0 = upper_32_bits(dep->dwc->bounce_addr); + params.param1 = lower_32_bits(dep->dwc->bounce_addr); + + cmd = DWC3_DEPCMD_STARTTRANSFER; + cmd |= DWC3_DEPCMD_PARAM(frame_number); + cmd_status = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); + + /* Redo if some other failure beside bus-expiry is received */ + if (cmd_status && cmd_status != -EAGAIN) { + dep->start_cmd_status = 0; + dep->combo_num = 0; + return; + } + + /* Store the first test status */ + if (dep->combo_num == 0) + dep->start_cmd_status = cmd_status; + + dep->combo_num++; + + /* + * End the transfer if the START_TRANSFER command is successful + * to wait for the next XferNotReady to test the command again + */ + if (cmd_status == 0) { + dwc3_stop_active_transfer(dep, true); + return; + } + } + + /* test0 and test1 are both completed at this point */ + test0 = (dep->start_cmd_status == 0); + test1 = (cmd_status == 0); + + if (!test0 && test1) + dep->combo_num = 1; + else if (!test0 && !test1) + dep->combo_num = 2; + else if (test0 && !test1) + dep->combo_num = 3; + else if (test0 && test1) + dep->combo_num = 0; + + dep->frame_number |= dep->combo_num << 14; + dep->frame_number += max_t(u32, 4, dep->interval); + + /* Reinitialize test variables */ + dep->start_cmd_status = 0; + dep->combo_num = 0; + + __dwc3_gadget_kick_transfer(dep); +} + static void __dwc3_gadget_start_isoc(struct dwc3_ep *dep) { + struct dwc3 *dwc = dep->dwc; + if (list_empty(&dep->pending_list)) { dev_info(dep->dwc->dev, "%s: ran out of requests\n", dep->name); @@ -1272,6 +1390,18 @@ static void __dwc3_gadget_start_isoc(struct dwc3_ep *dep) return; } + if (!dwc->dis_start_transfer_quirk && dwc3_is_usb31(dwc) && + (dwc->revision <= DWC3_USB31_REVISION_160A || + (dwc->revision == DWC3_USB31_REVISION_170A && + dwc->version_type >= DWC31_VERSIONTYPE_EA01 && + dwc->version_type <= DWC31_VERSIONTYPE_EA06))) { + + if (dwc->gadget.speed <= USB_SPEED_HIGH && dep->direction) { + dwc3_gadget_start_isoc_quirk(dep); + return; + } + } + dep->frame_number = DWC3_ALIGN_FRAME(dep); __dwc3_gadget_kick_transfer(dep); } @@ -2153,6 +2283,8 @@ static int dwc3_gadget_init_endpoint(struct dwc3 *dwc, u8 epnum) dep->direction = direction; dep->regs = dwc->regs + DWC3_DEP_BASE(epnum); dwc->eps[epnum] = dep; + dep->combo_num = 0; + dep->start_cmd_status = 0; snprintf(dep->name, sizeof(dep->name), "ep%u%s", num, direction ? "in" : "out");