summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAbhishek Aggarwal <aaggarwal@nvidia.com>2010-06-10 16:30:39 +0530
committerGary King <gking@nvidia.com>2010-06-10 08:51:04 -0700
commit3f056ef87f5256910945e4907ca52ec040be7fe5 (patch)
treeb4ecbd3cb7b1df3f16c98d104eee1d908e01c3f4 /drivers
parentaf2b1966f7042babc783e606685e76dc0650851d (diff)
usb gadget: preventing reg access after phy is powered down
The device was hanging on USB cable disconnect because fsl_ep_dequeue() function in fsl_udc_core.c was trying to access USB registers after the phy has been powered down. Fixed this by putting a check for vbus status and preventing the register access if the vbus status is 0. Bug: 696989 Change-Id: I802d6efa84b3cf20da736dfce1d546f044576b37 Reviewed-on: http://git-master/r/2394 Tested-by: Abhishek Aggarwal <aaggarwal@nvidia.com> Reviewed-by: Pavan Kunapuli <pkunapuli@nvidia.com> Tested-by: Pavan Kunapuli <pkunapuli@nvidia.com> Reviewed-by: Gary King <gking@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c38
1 files changed, 26 insertions, 12 deletions
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 1dc651b01ed1..0d132625e646 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -924,12 +924,19 @@ static int fsl_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
/* Stop the ep before we deal with the queue */
ep->stopped = 1;
ep_num = ep_index(ep);
- epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
- if (ep_is_in(ep))
- epctrl &= ~EPCTRL_TX_ENABLE;
- else
- epctrl &= ~EPCTRL_RX_ENABLE;
- fsl_writel(epctrl, &dr_regs->endptctrl[ep_num]);
+
+#if defined(CONFIG_ARCH_TEGRA)
+ /* Touch the registers if cable is connected and phy is on */
+ if (fsl_readl(&usb_sys_regs->vbus_wakeup) & USB_SYS_VBUS_STATUS)
+#endif
+ {
+ epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
+ if (ep_is_in(ep))
+ epctrl &= ~EPCTRL_TX_ENABLE;
+ else
+ epctrl &= ~EPCTRL_RX_ENABLE;
+ fsl_writel(epctrl, &dr_regs->endptctrl[ep_num]);
+ }
/* make sure it's actually queued on this endpoint */
list_for_each_entry(req, &ep->queue, queue) {
@@ -972,12 +979,19 @@ static int fsl_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
done(ep, req, -ECONNRESET);
/* Enable EP */
-out: epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
- if (ep_is_in(ep))
- epctrl |= EPCTRL_TX_ENABLE;
- else
- epctrl |= EPCTRL_RX_ENABLE;
- fsl_writel(epctrl, &dr_regs->endptctrl[ep_num]);
+out:
+#if defined(CONFIG_ARCH_TEGRA)
+ /* Touch the registers if cable is connected and phy is on */
+ if (fsl_readl(&usb_sys_regs->vbus_wakeup) & USB_SYS_VBUS_STATUS)
+#endif
+ {
+ epctrl = fsl_readl(&dr_regs->endptctrl[ep_num]);
+ if (ep_is_in(ep))
+ epctrl |= EPCTRL_TX_ENABLE;
+ else
+ epctrl |= EPCTRL_RX_ENABLE;
+ fsl_writel(epctrl, &dr_regs->endptctrl[ep_num]);
+ }
ep->stopped = stopped;
spin_unlock_irqrestore(&ep->udc->lock, flags);