diff mbox

[2/4] usb: dwc3: Fix gadget pullup in SS mode

Message ID 1348054229-27362-3-git-send-email-kishon@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Kishon Vijay Abraham I Sept. 19, 2012, 11:30 a.m. UTC
From: Moiz Sonasath <m-sonasath@ti.com>

For the gadget pullup functionality to work in
SS mode it requires a particular sequence of
toggling the run-stop bit. Here is the required
sequence:

- Set DCTL[31]
- Clear DCTL[31]
- Clear OMAP5430_CONTROL_CORE__PHY_POWER_USB[14]
- Clear DCTL[8:5] = 0x00
- Set DCTL[8:5] = 0x05
- Wait 25 Ms
- Set DCTL[31]
- Set OMAP5430_CONTROL_CORE__PHY_POWER_USB[14]

Tested rigourously the gadget pull-up functionality
in bot HS and SS modes.

Signed-off-by: Moiz Sonasath <m-sonasath@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/usb/dwc3/gadget.c   |   21 +++++++++++++++------
 drivers/usb/phy/omap-usb3.c |   16 ++++++++++++++++
 include/linux/usb/phy.h     |   10 +++++++++-
 3 files changed, 40 insertions(+), 7 deletions(-)

Comments

Felipe Balbi Sept. 19, 2012, 11:53 a.m. UTC | #1
Hi,

On Wed, Sep 19, 2012 at 05:00:27PM +0530, Kishon Vijay Abraham I wrote:
> From: Moiz Sonasath <m-sonasath@ti.com>
> 
> For the gadget pullup functionality to work in
> SS mode it requires a particular sequence of
> toggling the run-stop bit. Here is the required
> sequence:
> 
> - Set DCTL[31]
> - Clear DCTL[31]
> - Clear OMAP5430_CONTROL_CORE__PHY_POWER_USB[14]
> - Clear DCTL[8:5] = 0x00
> - Set DCTL[8:5] = 0x05
> - Wait 25 Ms
> - Set DCTL[31]
> - Set OMAP5430_CONTROL_CORE__PHY_POWER_USB[14]
> 
> Tested rigourously the gadget pull-up functionality
> in bot HS and SS modes.
> 
> Signed-off-by: Moiz Sonasath <m-sonasath@ti.com>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>

this needs to split into three patches:

add new poweron field, implement it on omap-usb3, use it on
dwc3/gadget.c

btw, I don't think the changes to run_stop bit are necessary and if they
are, that'd either be a silicon errata or it would've been mentioned on
the databook. I don't remember seeing that on the databook so I'm
assuming that this is caused by a bad use of the PHY.

Why that mdelay(25) ? why 25 ms ? That's quite a long time, actually.

> ---
>  drivers/usb/dwc3/gadget.c   |   21 +++++++++++++++------
>  drivers/usb/phy/omap-usb3.c |   16 ++++++++++++++++
>  include/linux/usb/phy.h     |   10 +++++++++-
>  3 files changed, 40 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 58fdfad..bcc0102 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -49,6 +49,7 @@
>  
>  #include <linux/usb/ch9.h>
>  #include <linux/usb/gadget.h>
> +#include <linux/usb/otg.h>
>  
>  #include "core.h"
>  #include "gadget.h"
> @@ -1417,19 +1418,27 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
>  	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
>  	if (is_on) {
>  		if (dwc->revision <= DWC3_REVISION_187A) {
> -			reg &= ~DWC3_DCTL_TRGTULST_MASK;
> -			reg |= DWC3_DCTL_TRGTULST_RX_DET;
> +			reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
> +			dwc3_writel(dwc->regs, DWC3_DCTL, reg);
> +			reg |= DWC3_DCTL_ULSTCHNG_RX_DETECT;
> +			dwc3_writel(dwc->regs, DWC3_DCTL, reg);
> +			mdelay(25);
> +			reg |= DWC3_DCTL_RUN_STOP;
> +			dwc3_writel(dwc->regs, DWC3_DCTL, reg);
> +			usb_phy_poweron(dwc->usb3_phy);
>  		}
>  
> -		if (dwc->revision >= DWC3_REVISION_194A)
> +		if (dwc->revision >= DWC3_REVISION_194A) {
>  			reg &= ~DWC3_DCTL_KEEP_CONNECT;
> -		reg |= DWC3_DCTL_RUN_STOP;
> +			reg |= DWC3_DCTL_RUN_STOP;
> +			dwc3_writel(dwc->regs, DWC3_DCTL, reg);
> +		}
>  	} else {
>  		reg &= ~DWC3_DCTL_RUN_STOP;
> +		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
> +		usb_phy_shutdown(dwc->usb3_phy);
>  	}
>  
> -	dwc3_writel(dwc->regs, DWC3_DCTL, reg);

I'd prefer to hold all values on the variable and write only one.
Felipe Balbi Sept. 19, 2012, 4:04 p.m. UTC | #2
Hi,

On Wed, Sep 19, 2012 at 10:02:48AM -0500, Sonasath, Moiz wrote:
> Felipe,
> 
> On Wed, Sep 19, 2012 at 6:53 AM, Felipe Balbi <balbi@ti.com> wrote:
> 
> > Hi,
> >
> > On Wed, Sep 19, 2012 at 05:00:27PM +0530, Kishon Vijay Abraham I wrote:
> > > From: Moiz Sonasath <m-sonasath@ti.com>
> > >
> > > For the gadget pullup functionality to work in
> > > SS mode it requires a particular sequence of
> > > toggling the run-stop bit. Here is the required
> > > sequence:
> > >
> > > - Set DCTL[31]
> > > - Clear DCTL[31]
> > > - Clear OMAP5430_CONTROL_CORE__PHY_POWER_USB[14]
> > > - Clear DCTL[8:5] = 0x00
> > > - Set DCTL[8:5] = 0x05
> > > - Wait 25 Ms
> > > - Set DCTL[31]
> > > - Set OMAP5430_CONTROL_CORE__PHY_POWER_USB[14]
> > >
> > > Tested rigourously the gadget pull-up functionality
> > > in bot HS and SS modes.
> > >
> > > Signed-off-by: Moiz Sonasath <m-sonasath@ti.com>
> > > Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> >
> > this needs to split into three patches:
> >
> > add new poweron field, implement it on omap-usb3, use it on
> > dwc3/gadget.c
> >
> > btw, I don't think the changes to run_stop bit are necessary and if they
> > are, that'd either be a silicon errata or it would've been mentioned on
> > the databook. I don't remember seeing that on the databook so I'm
> > assuming that this is caused by a bad use of the PHY.
> >
> > Why that mdelay(25) ? why 25 ms ? That's quite a long time, actually.
> >
> 
> Felipe, This is infact a HW bug that the Si-Val team did accept and gave us
> this workaround sequence with the precise delay :-)
> 
> Supposedly this will be fixed in ES 2.0.

in that case this doesn't have to go to mainline since we're not
supporting ES1.0 in mainline :-)

at minimum this should've come with a proper revision check anyway.
Felipe Balbi Sept. 19, 2012, 5:24 p.m. UTC | #3
On Wed, Sep 19, 2012 at 11:50:53AM -0500, Sonasath, Moiz wrote:
> Felipe,
> 
> On Wed, Sep 19, 2012 at 11:04 AM, Felipe Balbi <balbi@ti.com> wrote:
> 
> > Hi,
> >
> > On Wed, Sep 19, 2012 at 10:02:48AM -0500, Sonasath, Moiz wrote:
> > > Felipe,
> > >
> > > On Wed, Sep 19, 2012 at 6:53 AM, Felipe Balbi <balbi@ti.com> wrote:
> > >
> > > > Hi,
> > > >
> > > > On Wed, Sep 19, 2012 at 05:00:27PM +0530, Kishon Vijay Abraham I wrote:
> > > > > From: Moiz Sonasath <m-sonasath@ti.com>
> > > > >
> > > > > For the gadget pullup functionality to work in
> > > > > SS mode it requires a particular sequence of
> > > > > toggling the run-stop bit. Here is the required
> > > > > sequence:
> > > > >
> > > > > - Set DCTL[31]
> > > > > - Clear DCTL[31]
> > > > > - Clear OMAP5430_CONTROL_CORE__PHY_POWER_USB[14]
> > > > > - Clear DCTL[8:5] = 0x00
> > > > > - Set DCTL[8:5] = 0x05
> > > > > - Wait 25 Ms
> > > > > - Set DCTL[31]
> > > > > - Set OMAP5430_CONTROL_CORE__PHY_POWER_USB[14]
> > > > >
> > > > > Tested rigourously the gadget pull-up functionality
> > > > > in bot HS and SS modes.
> > > > >
> > > > > Signed-off-by: Moiz Sonasath <m-sonasath@ti.com>
> > > > > Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> > > >
> > > > this needs to split into three patches:
> > > >
> > > > add new poweron field, implement it on omap-usb3, use it on
> > > > dwc3/gadget.c
> > > >
> > > > btw, I don't think the changes to run_stop bit are necessary and if
> > they
> > > > are, that'd either be a silicon errata or it would've been mentioned on
> > > > the databook. I don't remember seeing that on the databook so I'm
> > > > assuming that this is caused by a bad use of the PHY.
> > > >
> > > > Why that mdelay(25) ? why 25 ms ? That's quite a long time, actually.
> > > >
> > >
> > > Felipe, This is infact a HW bug that the Si-Val team did accept and gave
> > us
> > > this workaround sequence with the precise delay :-)
> > >
> > > Supposedly this will be fixed in ES 2.0.
> >
> > in that case this doesn't have to go to mainline since we're not
> > supporting ES1.0 in mainline :-)
> >
> > at minimum this should've come with a proper revision check anyway.
> >
> 
> Actually most of it is under a rev check :)

fair enough.

> Perhaps the last: usb_phy_shutdown(dwc->usb3_phy);
> in the else part should be in
> if (dwc->revision <= DWC3_REVISION_187A) check

Is this an OMAP errata or Synopsys errata ? If it's a Synopsys errata we
need to make sure to add the comment above the workaround, if it's an
OMAP errata, we can't apply the workaround to all users since they might
not need it, so we need a more clever scheme.

On top of that, if it's an ES1 errata, I rather not have this in
mainline since we won't support ES1 at all in mainline, which means this
workaround will be useless in a mainline kernel tree.
Felipe Balbi Sept. 19, 2012, 5:29 p.m. UTC | #4
Hi again,

On Wed, Sep 19, 2012 at 08:24:44PM +0300, Felipe Balbi wrote:
> > > at minimum this should've come with a proper revision check anyway.
> > >
> > 
> > Actually most of it is under a rev check :)
> 
> fair enough.

one extra comment here. That revision check is not related to the
silicon errata you mention. That revision check is there because the bit
definition of that particular register has changed a little bit, so
we're just handling a slightly different programming model between older
and newer revisions.
diff mbox

Patch

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 58fdfad..bcc0102 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -49,6 +49,7 @@ 
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
 
 #include "core.h"
 #include "gadget.h"
@@ -1417,19 +1418,27 @@  static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
 	if (is_on) {
 		if (dwc->revision <= DWC3_REVISION_187A) {
-			reg &= ~DWC3_DCTL_TRGTULST_MASK;
-			reg |= DWC3_DCTL_TRGTULST_RX_DET;
+			reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
+			dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+			reg |= DWC3_DCTL_ULSTCHNG_RX_DETECT;
+			dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+			mdelay(25);
+			reg |= DWC3_DCTL_RUN_STOP;
+			dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+			usb_phy_poweron(dwc->usb3_phy);
 		}
 
-		if (dwc->revision >= DWC3_REVISION_194A)
+		if (dwc->revision >= DWC3_REVISION_194A) {
 			reg &= ~DWC3_DCTL_KEEP_CONNECT;
-		reg |= DWC3_DCTL_RUN_STOP;
+			reg |= DWC3_DCTL_RUN_STOP;
+			dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+		}
 	} else {
 		reg &= ~DWC3_DCTL_RUN_STOP;
+		dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+		usb_phy_shutdown(dwc->usb3_phy);
 	}
 
-	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
-
 	do {
 		reg = dwc3_readl(dwc->regs, DWC3_DSTS);
 		if (is_on) {
diff --git a/drivers/usb/phy/omap-usb3.c b/drivers/usb/phy/omap-usb3.c
index 4dc84ca..26402d5 100644
--- a/drivers/usb/phy/omap-usb3.c
+++ b/drivers/usb/phy/omap-usb3.c
@@ -212,6 +212,20 @@  static int omap_usb3_init(struct usb_phy *x)
 	return 0;
 }
 
+static void omap_usb3_poweron(struct usb_phy *x)
+{
+	struct omap_usb *phy = phy_to_omapusb(x);
+
+	omap5_usb_phy_power(phy, 1);
+}
+
+static void omap_usb3_shutdown(struct usb_phy *x)
+{
+	struct omap_usb *phy = phy_to_omapusb(x);
+
+	omap5_usb_phy_power(phy, 0);
+}
+
 static int __devinit omap_usb3_probe(struct platform_device *pdev)
 {
 	struct omap_usb			*phy;
@@ -253,6 +267,8 @@  static int __devinit omap_usb3_probe(struct platform_device *pdev)
 	phy->phy.dev		= phy->dev;
 	phy->phy.label		= "omap-usb3";
 	phy->phy.init		= omap_usb3_init;
+	phy->phy.poweron	= omap_usb3_poweron;
+	phy->phy.shutdown	= omap_usb3_shutdown;
 	phy->phy.set_suspend	= omap_usb3_suspend;
 
 	phy->is_suspended	= 1;
diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h
index 06b5bae..aaa8e16 100644
--- a/include/linux/usb/phy.h
+++ b/include/linux/usb/phy.h
@@ -86,8 +86,9 @@  struct usb_phy {
 	/* to support controllers that have multiple transceivers */
 	struct list_head	head;
 
-	/* initialize/shutdown the OTG controller */
+	/* initialize/poweron/shutdown the OTG controller */
 	int	(*init)(struct usb_phy *x);
+	void    (*poweron)(struct usb_phy *x);
 	void	(*shutdown)(struct usb_phy *x);
 
 	/* effective for B devices, ignored for A-peripheral */
@@ -135,6 +136,13 @@  usb_phy_init(struct usb_phy *x)
 }
 
 static inline void
+usb_phy_poweron(struct usb_phy *x)
+{
+	if (x->poweron)
+		x->poweron(x);
+}
+
+static inline void
 usb_phy_shutdown(struct usb_phy *x)
 {
 	if (x->shutdown)