Linux USB
 help / color / mirror / Atom feed
From: Rob Weber <rob@gnarbox.com>
To: Alan Stern <stern@rowland.harvard.edu>
Cc: "Claus H. Stovgaard" <cst@phaseone.com>,
	"balbi@kernel.org" <balbi@kernel.org>,
	"linux-usb@vger.kernel.org" <linux-usb@vger.kernel.org>,
	"mnarani@xilinx.com" <mnarani@xilinx.com>,
	Michal Simek <michal.simek@xilinx.com>
Subject: Use device tree to disable U1/U2 in gadget devices based on DWC3
Date: Thu, 25 Apr 2019 13:11:03 -0700	[thread overview]
Message-ID: <20190425201103.GA26402@coops> (raw)

Hi Everyone,

On Wed, Apr 24, 2019 at 02:33:48PM -0400, Alan Stern wrote:
> On Wed, 24 Apr 2019, Claus H. Stovgaard wrote:
> 
> > Hi Balbi and other USB developers.
> > 
> > I am developing camera devices based on Xilinx ZynqMP, using the
> > gadget framework and the build-in dwc3 core of the ZynqMP as USB3
> > controller and the build-in Cirrus SERDES as phy.
> > Testing with a number of hosts and Windows 7, has shown sporadic
> > reconnects when leaving U2/U1, caused by failing link training, where
> > the host resets the bus. Sometime it also means it reconnect via
> > USB2.
> > 
> > So to overcome this, I will like to have the option for disabling
> > U1/U2 on the core when working with those hosts.
> > 
> > Currently I have made a hack in ep0.c where I return EINVAL in
> > dwc3_ep0_handle_u1 and dwc3_ep0_handle_u2 together with not setting
> > DWC3_DCTL_ACCEPTU1ENA and DWC3_DCTL_ACCEPTU2ENA in
> > dwc3_ep0_set_config
> > Will though prefer a solution possible to upstream, so was thinking
> > about adding two devicetree bindings.
> > 
> > * snps,u1_disable_as_gadget: When set the core will not enable U1 if
> > requested from host, nor initiate U1.
> > * snps,u2_disable_as_gadget: When set the core will not enable U2 if
> > requested from host, nor initiate U2.
> > 
> > If you think this might be something which can be upstreamed I will
> > prepare the code and send a patch for discussion.
> > On the other hand, if you think that disabling U1/U2 via device tree
> > as suggested should not be a feature no need for me to try making it
> > a feature.
> 
> Speaking as an interested bystander, I would first wonder why your
> hardware fails during link training.  If it is properly designed, that
> should not happen.  The fact that it does happen suggests your devices
> might also experience problems during normal data transport.

I was recently debugging a similar problem where my device would
improperly transition from U2 to U0. This caused the connection to reset
and the device to be re-enumerated as a USB2 device. Our design uses an
Intel CherryTrail z8550 SoC that has an internal dwc3 USB device
controller. I worked with Felipe a couple of weeks ago [1] to come up with
the same workaround you mentioned above. I disable device-initiated U1/U2
in ep0_set_config and also return -EINVAL when handling SetFeature
requests from the USB host. I've attached my patch for kernel 4.9.115
below for reference.

Although we have applied this workaround, we still have not identified a
root cause of the issue. Intel has no known errata related to the symptoms
we are experiencing. We've done quite a bit of analysis on our design and
are pretty confident we've followed all design guidelines for USB.

Cheers,
Rob Weber

[1] https://marc.info/?t=155349935600001&r=1&w=2
---
drivers/usb/dwc3/ep0.c | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)

--

diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 2331469f943d..78b75d65b435 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -433,10 +433,13 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
                return -EINVAL;

            reg = dwc3_readl(dwc->regs, DWC3_DCTL);
-            if (set)
-                reg |= DWC3_DCTL_INITU1ENA;
-            else
+            if (set) {
+                /* reg |= DWC3_DCTL_INITU1ENA; */
+                dwc3_trace(trace_dwc3_ep0, "GBX: Skipping U1 Enable");
+                return -EINVAL;
+            } else {
                reg &= ~DWC3_DCTL_INITU1ENA;
+            }
            dwc3_writel(dwc->regs, DWC3_DCTL, reg);
            break;

@@ -448,10 +451,13 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
                return -EINVAL;

            reg = dwc3_readl(dwc->regs, DWC3_DCTL);
-            if (set)
-                reg |= DWC3_DCTL_INITU2ENA;
-            else
+            if (set) {
+                /* reg |= DWC3_DCTL_INITU2ENA; */
+                dwc3_trace(trace_dwc3_ep0, "GBX: Skipping U2 Enable");
+                return -EINVAL;
+            } else {
                reg &= ~DWC3_DCTL_INITU2ENA;
+            }
            dwc3_writel(dwc->regs, DWC3_DCTL, reg);
            break;

@@ -567,7 +573,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
    enum usb_device_state state = dwc->gadget.state;
    u32 cfg;
    int ret;
-    u32 reg;
+    /* u32 reg; */

    cfg = le16_to_cpu(ctrl->wValue);

@@ -594,9 +600,9 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
             * Enable transition to U1/U2 state when
             * nothing is pending from application.
             */
-            reg = dwc3_readl(dwc->regs, DWC3_DCTL);
-            reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA);
-            dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+            /* reg = dwc3_readl(dwc->regs, DWC3_DCTL); */
+            /* reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA); */
+            /* dwc3_writel(dwc->regs, DWC3_DCTL, reg); */
        }
        break;


WARNING: multiple messages have this Message-ID (diff)
From: Rob Weber <rob@gnarbox.com>
To: Alan Stern <stern@rowland.harvard.edu>
Cc: "Claus H. Stovgaard" <cst@phaseone.com>,
	"balbi@kernel.org" <balbi@kernel.org>,
	"linux-usb@vger.kernel.org" <linux-usb@vger.kernel.org>,
	"mnarani@xilinx.com" <mnarani@xilinx.com>,
	Michal Simek <michal.simek@xilinx.com>
Subject: Re: Use device tree to disable U1/U2 in gadget devices based on DWC3
Date: Thu, 25 Apr 2019 13:11:03 -0700	[thread overview]
Message-ID: <20190425201103.GA26402@coops> (raw)
Message-ID: <20190425201103.xa0UURF4z2qQmFATCEQSKFsxcxDGy8IOpG5yF6cS4p0@z> (raw)
In-Reply-To: <Pine.LNX.4.44L0.1904241423540.1443-100000@iolanthe.rowland.org>

Hi Everyone,

On Wed, Apr 24, 2019 at 02:33:48PM -0400, Alan Stern wrote:
> On Wed, 24 Apr 2019, Claus H. Stovgaard wrote:
> 
> > Hi Balbi and other USB developers.
> > 
> > I am developing camera devices based on Xilinx ZynqMP, using the
> > gadget framework and the build-in dwc3 core of the ZynqMP as USB3
> > controller and the build-in Cirrus SERDES as phy.
> > Testing with a number of hosts and Windows 7, has shown sporadic
> > reconnects when leaving U2/U1, caused by failing link training, where
> > the host resets the bus. Sometime it also means it reconnect via
> > USB2.
> > 
> > So to overcome this, I will like to have the option for disabling
> > U1/U2 on the core when working with those hosts.
> > 
> > Currently I have made a hack in ep0.c where I return EINVAL in
> > dwc3_ep0_handle_u1 and dwc3_ep0_handle_u2 together with not setting
> > DWC3_DCTL_ACCEPTU1ENA and DWC3_DCTL_ACCEPTU2ENA in
> > dwc3_ep0_set_config
> > Will though prefer a solution possible to upstream, so was thinking
> > about adding two devicetree bindings.
> > 
> > * snps,u1_disable_as_gadget: When set the core will not enable U1 if
> > requested from host, nor initiate U1.
> > * snps,u2_disable_as_gadget: When set the core will not enable U2 if
> > requested from host, nor initiate U2.
> > 
> > If you think this might be something which can be upstreamed I will
> > prepare the code and send a patch for discussion.
> > On the other hand, if you think that disabling U1/U2 via device tree
> > as suggested should not be a feature no need for me to try making it
> > a feature.
> 
> Speaking as an interested bystander, I would first wonder why your
> hardware fails during link training.  If it is properly designed, that
> should not happen.  The fact that it does happen suggests your devices
> might also experience problems during normal data transport.

I was recently debugging a similar problem where my device would
improperly transition from U2 to U0. This caused the connection to reset
and the device to be re-enumerated as a USB2 device. Our design uses an
Intel CherryTrail z8550 SoC that has an internal dwc3 USB device
controller. I worked with Felipe a couple of weeks ago [1] to come up with
the same workaround you mentioned above. I disable device-initiated U1/U2
in ep0_set_config and also return -EINVAL when handling SetFeature
requests from the USB host. I've attached my patch for kernel 4.9.115
below for reference.

Although we have applied this workaround, we still have not identified a
root cause of the issue. Intel has no known errata related to the symptoms
we are experiencing. We've done quite a bit of analysis on our design and
are pretty confident we've followed all design guidelines for USB.

Cheers,
Rob Weber

[1] https://marc.info/?t=155349935600001&r=1&w=2

---
drivers/usb/dwc3/ep0.c | 26 ++++++++++++++++----------
1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 2331469f943d..78b75d65b435 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -433,10 +433,13 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
                return -EINVAL;

            reg = dwc3_readl(dwc->regs, DWC3_DCTL);
-            if (set)
-                reg |= DWC3_DCTL_INITU1ENA;
-            else
+            if (set) {
+                /* reg |= DWC3_DCTL_INITU1ENA; */
+                dwc3_trace(trace_dwc3_ep0, "GBX: Skipping U1 Enable");
+                return -EINVAL;
+            } else {
                reg &= ~DWC3_DCTL_INITU1ENA;
+            }
            dwc3_writel(dwc->regs, DWC3_DCTL, reg);
            break;

@@ -448,10 +451,13 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
                return -EINVAL;

            reg = dwc3_readl(dwc->regs, DWC3_DCTL);
-            if (set)
-                reg |= DWC3_DCTL_INITU2ENA;
-            else
+            if (set) {
+                /* reg |= DWC3_DCTL_INITU2ENA; */
+                dwc3_trace(trace_dwc3_ep0, "GBX: Skipping U2 Enable");
+                return -EINVAL;
+            } else {
                reg &= ~DWC3_DCTL_INITU2ENA;
+            }
            dwc3_writel(dwc->regs, DWC3_DCTL, reg);
            break;

@@ -567,7 +573,7 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
    enum usb_device_state state = dwc->gadget.state;
    u32 cfg;
    int ret;
-    u32 reg;
+    /* u32 reg; */

    cfg = le16_to_cpu(ctrl->wValue);

@@ -594,9 +600,9 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
             * Enable transition to U1/U2 state when
             * nothing is pending from application.
             */
-            reg = dwc3_readl(dwc->regs, DWC3_DCTL);
-            reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA);
-            dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+            /* reg = dwc3_readl(dwc->regs, DWC3_DCTL); */
+            /* reg |= (DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA); */
+            /* dwc3_writel(dwc->regs, DWC3_DCTL, reg); */
        }
        break;

--

         reply	other threads:[~2019-04-25 20:11 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-04-24 16:26 Use device tree to disable U1/U2 in gadget devices based on DWC3 Claus H. Stovgaard
2019-04-24 18:33 ` Alan Stern
2019-04-25 20:11   ` Rob Weber [this message]
2019-04-25 20:11     ` Rob Weber
2019-04-26 13:15     ` Claus H. Stovgaard
2019-04-26 13:15       ` Claus H. Stovgaard
2019-04-26 12:44   ` Claus H. Stovgaard

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190425201103.GA26402@coops \
    --to=rob@gnarbox.com \
    --cc=balbi@kernel.org \
    --cc=cst@phaseone.com \
    --cc=linux-usb@vger.kernel.org \
    --cc=michal.simek@xilinx.com \
    --cc=mnarani@xilinx.com \
    --cc=stern@rowland.harvard.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox