diff options
author | Abhishek Aggarwal <aaggarwal@nvidia.com> | 2010-06-10 16:30:39 +0530 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-06-10 08:51:04 -0700 |
commit | 3f056ef87f5256910945e4907ca52ec040be7fe5 (patch) | |
tree | b4ecbd3cb7b1df3f16c98d104eee1d908e01c3f4 /drivers | |
parent | af2b1966f7042babc783e606685e76dc0650851d (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.c | 38 |
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); |