public inbox for linux-tegra@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] USB: ehci: tegra: fix USB1 port reset issue
@ 2011-04-17  8:58 Mike Rapoport
       [not found] ` <1303030705-20810-1-git-send-email-mike-UTxiZqZC01RS1MOuV/RT9w@public.gmane.org>
  0 siblings, 1 reply; 3+ messages in thread
From: Mike Rapoport @ 2011-04-17  8:58 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA, Jim Lin, Olof Johansson,
	Mike Rapoport

From: Jim Lin <jilin-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

Tegra USB1 port needs to issue Port Reset twice internally, otherwise it
fails to enumerate devices attached to it

Signed-off-by: Jim Lin <jilin-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Olof Johansson <olofj-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

[ squash two patches into one and minor style cleanups ]

Signed-off-by: Mike Rapoport <mike-UTxiZqZC01RS1MOuV/RT9w@public.gmane.org>
---
 drivers/usb/host/ehci-tegra.c |   72 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 72 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index a516af2..7359bcb 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -58,6 +58,71 @@ static void tegra_ehci_power_down(struct usb_hcd *hcd)
 	clk_disable(tegra->emc_clk);
 }
 
+static int tegra_ehci_internal_port_reset(
+	struct ehci_hcd	*ehci,
+	u32 __iomem	*portsc_reg
+)
+{
+	u32		temp;
+	unsigned long	flags;
+	int		retval = 0;
+	int		i, tries;
+	u32		saved_usbintr;
+
+	spin_lock_irqsave(&ehci->lock, flags);
+	saved_usbintr = ehci_readl(ehci, &ehci->regs->intr_enable);
+	/* disable USB interrupt */
+	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+	spin_unlock_irqrestore(&ehci->lock, flags);
+
+	/*
+	 * Here we have to do Port Reset at most twice for
+	 * Port Enable bit to be set.
+	 */
+	for (i = 0; i < 2; i++) {
+		temp = ehci_readl(ehci, portsc_reg);
+		temp |= PORT_RESET;
+		ehci_writel(ehci, temp, portsc_reg);
+		mdelay(10);
+		temp &= ~PORT_RESET;
+		ehci_writel(ehci, temp, portsc_reg);
+		mdelay(1);
+		tries = 100;
+		do {
+			mdelay(1);
+			/*
+			 * Up to this point, Port Enable bit is
+			 * expected to be set after 2 ms waiting.
+			 * USB1 usually takes extra 45 ms, for safety,
+			 * we take 100 ms as timeout.
+			 */
+			temp = ehci_readl(ehci, portsc_reg);
+		} while (!(temp & PORT_PE) && tries--);
+		if (temp & PORT_PE)
+			break;
+	}
+	if (i == 2)
+		retval = -ETIMEDOUT;
+
+	/*
+	 * Clear Connect Status Change bit if it's set.
+	 * We can't clear PORT_PEC. It will also cause PORT_PE to be cleared.
+	 */
+	if (temp & PORT_CSC)
+		ehci_writel(ehci, PORT_CSC, portsc_reg);
+
+	/*
+	 * Write to clear any interrupt status bits that might be set
+	 * during port reset.
+	 */
+	temp = ehci_readl(ehci, &ehci->regs->status);
+	ehci_writel(ehci, temp, &ehci->regs->status);
+
+	/* restore original interrupt enable bits */
+	ehci_writel(ehci, saved_usbintr, &ehci->regs->intr_enable);
+	return retval;
+}
+
 static int tegra_ehci_hub_control(
 	struct usb_hcd	*hcd,
 	u16		typeReq,
@@ -121,6 +186,13 @@ static int tegra_ehci_hub_control(
 		goto done;
 	}
 
+	/* For USB1 port we need to issue Port Reset twice internally */
+	if (tegra->phy->instance == 0 &&
+	   (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_RESET)) {
+		spin_unlock_irqrestore(&ehci->lock, flags);
+		return tegra_ehci_internal_port_reset(ehci, status_reg);
+	}
+
 	/*
 	 * Tegra host controller will time the resume operation to clear the bit
 	 * when the port control state switches to HS or FS Idle. This behavior
-- 
1.7.3.1

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] USB: ehci: tegra: fix USB1 port reset issue
       [not found] ` <1303030705-20810-1-git-send-email-mike-UTxiZqZC01RS1MOuV/RT9w@public.gmane.org>
@ 2011-04-27  7:13   ` Mike Rapoport
       [not found]     ` <4DB7C211.80308-UTxiZqZC01RS1MOuV/RT9w@public.gmane.org>
  0 siblings, 1 reply; 3+ messages in thread
From: Mike Rapoport @ 2011-04-27  7:13 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA, Jim Lin, Olof Johansson,
	Mike Rapoport

Greg,

Any comments on this?

On 04/17/11 11:58, Mike Rapoport wrote:
> From: Jim Lin <jilin-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> 
> Tegra USB1 port needs to issue Port Reset twice internally, otherwise it
> fails to enumerate devices attached to it
> 
> Signed-off-by: Jim Lin <jilin-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
> Signed-off-by: Olof Johansson <olofj-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
> 
> [ squash two patches into one and minor style cleanups ]
> 
> Signed-off-by: Mike Rapoport <mike-UTxiZqZC01RS1MOuV/RT9w@public.gmane.org>
> ---
>  drivers/usb/host/ehci-tegra.c |   72 +++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 72 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
> index a516af2..7359bcb 100644
> --- a/drivers/usb/host/ehci-tegra.c
> +++ b/drivers/usb/host/ehci-tegra.c
> @@ -58,6 +58,71 @@ static void tegra_ehci_power_down(struct usb_hcd *hcd)
>  	clk_disable(tegra->emc_clk);
>  }
>  
> +static int tegra_ehci_internal_port_reset(
> +	struct ehci_hcd	*ehci,
> +	u32 __iomem	*portsc_reg
> +)
> +{
> +	u32		temp;
> +	unsigned long	flags;
> +	int		retval = 0;
> +	int		i, tries;
> +	u32		saved_usbintr;
> +
> +	spin_lock_irqsave(&ehci->lock, flags);
> +	saved_usbintr = ehci_readl(ehci, &ehci->regs->intr_enable);
> +	/* disable USB interrupt */
> +	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
> +	spin_unlock_irqrestore(&ehci->lock, flags);
> +
> +	/*
> +	 * Here we have to do Port Reset at most twice for
> +	 * Port Enable bit to be set.
> +	 */
> +	for (i = 0; i < 2; i++) {
> +		temp = ehci_readl(ehci, portsc_reg);
> +		temp |= PORT_RESET;
> +		ehci_writel(ehci, temp, portsc_reg);
> +		mdelay(10);
> +		temp &= ~PORT_RESET;
> +		ehci_writel(ehci, temp, portsc_reg);
> +		mdelay(1);
> +		tries = 100;
> +		do {
> +			mdelay(1);
> +			/*
> +			 * Up to this point, Port Enable bit is
> +			 * expected to be set after 2 ms waiting.
> +			 * USB1 usually takes extra 45 ms, for safety,
> +			 * we take 100 ms as timeout.
> +			 */
> +			temp = ehci_readl(ehci, portsc_reg);
> +		} while (!(temp & PORT_PE) && tries--);
> +		if (temp & PORT_PE)
> +			break;
> +	}
> +	if (i == 2)
> +		retval = -ETIMEDOUT;
> +
> +	/*
> +	 * Clear Connect Status Change bit if it's set.
> +	 * We can't clear PORT_PEC. It will also cause PORT_PE to be cleared.
> +	 */
> +	if (temp & PORT_CSC)
> +		ehci_writel(ehci, PORT_CSC, portsc_reg);
> +
> +	/*
> +	 * Write to clear any interrupt status bits that might be set
> +	 * during port reset.
> +	 */
> +	temp = ehci_readl(ehci, &ehci->regs->status);
> +	ehci_writel(ehci, temp, &ehci->regs->status);
> +
> +	/* restore original interrupt enable bits */
> +	ehci_writel(ehci, saved_usbintr, &ehci->regs->intr_enable);
> +	return retval;
> +}
> +
>  static int tegra_ehci_hub_control(
>  	struct usb_hcd	*hcd,
>  	u16		typeReq,
> @@ -121,6 +186,13 @@ static int tegra_ehci_hub_control(
>  		goto done;
>  	}
>  
> +	/* For USB1 port we need to issue Port Reset twice internally */
> +	if (tegra->phy->instance == 0 &&
> +	   (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_RESET)) {
> +		spin_unlock_irqrestore(&ehci->lock, flags);
> +		return tegra_ehci_internal_port_reset(ehci, status_reg);
> +	}
> +
>  	/*
>  	 * Tegra host controller will time the resume operation to clear the bit
>  	 * when the port control state switches to HS or FS Idle. This behavior


-- 
Sincerely yours,
Mike.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] USB: ehci: tegra: fix USB1 port reset issue
       [not found]     ` <4DB7C211.80308-UTxiZqZC01RS1MOuV/RT9w@public.gmane.org>
@ 2011-04-27 23:27       ` Greg KH
  0 siblings, 0 replies; 3+ messages in thread
From: Greg KH @ 2011-04-27 23:27 UTC (permalink / raw)
  To: Mike Rapoport
  Cc: Greg Kroah-Hartman, linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA, Jim Lin, Olof Johansson

On Wed, Apr 27, 2011 at 10:13:21AM +0300, Mike Rapoport wrote:
> Greg,
> 
> Any comments on this?

It's in my queue, sorry, I have a whole lot of things going on at the
moment in my "real life", I will get to this eventually, it's not
lost...

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-04-27 23:27 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-17  8:58 [PATCH] USB: ehci: tegra: fix USB1 port reset issue Mike Rapoport
     [not found] ` <1303030705-20810-1-git-send-email-mike-UTxiZqZC01RS1MOuV/RT9w@public.gmane.org>
2011-04-27  7:13   ` Mike Rapoport
     [not found]     ` <4DB7C211.80308-UTxiZqZC01RS1MOuV/RT9w@public.gmane.org>
2011-04-27 23:27       ` Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox