aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/musb_dsps.c
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2014-04-02 07:58:29 -0400
committerFelipe Balbi <balbi@ti.com>2014-04-21 15:07:29 -0400
commit1d57de306e1f3e73c607811a974f6662162e5df6 (patch)
treeb8d2eb8d5e8827ec4395ba39ab8c0c08511c234d /drivers/usb/musb/musb_dsps.c
parentca88fc2ef0d790a1da37804219102336f7622b97 (diff)
usb: musb: dsps: handle babble interrupts
When the dsps isr sees a babble error, pass it down to the core for fixup. Also, provide a .reset hook so the core can call us back. A babble interrupt error occured when a USB mass storage device ("CHIPSBNK v3.3.9.1", 1e3d:2093) was disconnected from a AM33xx host. Signed-off-by: Daniel Mack <zonque@gmail.com> Reported-by: Thomas Mellenthin <mellenthin@teufel.de> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/musb/musb_dsps.c')
-rw-r--r--drivers/usb/musb/musb_dsps.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 18882924d9d5..138d1dd86235 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -329,9 +329,21 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
329 * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set. 329 * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
330 * Also, DRVVBUS pulses for SRP (but not at 5V) ... 330 * Also, DRVVBUS pulses for SRP (but not at 5V) ...
331 */ 331 */
332 if (is_host_active(musb) && usbintr & MUSB_INTR_BABBLE) 332 if (is_host_active(musb) && usbintr & MUSB_INTR_BABBLE) {
333 pr_info("CAUTION: musb: Babble Interrupt Occurred\n"); 333 pr_info("CAUTION: musb: Babble Interrupt Occurred\n");
334 334
335 /*
336 * When a babble condition occurs, the musb controller removes
337 * the session and is no longer in host mode. Hence, all
338 * devices connected to its root hub get disconnected.
339 *
340 * Hand this error down to the musb core isr, so it can
341 * recover.
342 */
343 musb->int_usb = MUSB_INTR_BABBLE | MUSB_INTR_DISCONNECT;
344 musb->int_tx = musb->int_rx = 0;
345 }
346
335 if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) { 347 if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
336 int drvvbus = dsps_readl(reg_base, wrp->status); 348 int drvvbus = dsps_readl(reg_base, wrp->status);
337 void __iomem *mregs = musb->mregs; 349 void __iomem *mregs = musb->mregs;
@@ -523,6 +535,16 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode)
523 return 0; 535 return 0;
524} 536}
525 537
538static void dsps_musb_reset(struct musb *musb)
539{
540 struct device *dev = musb->controller;
541 struct dsps_glue *glue = dev_get_drvdata(dev->parent);
542 const struct dsps_musb_wrapper *wrp = glue->wrp;
543
544 dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset));
545 udelay(100);
546}
547
526static struct musb_platform_ops dsps_ops = { 548static struct musb_platform_ops dsps_ops = {
527 .init = dsps_musb_init, 549 .init = dsps_musb_init,
528 .exit = dsps_musb_exit, 550 .exit = dsps_musb_exit,
@@ -532,6 +554,7 @@ static struct musb_platform_ops dsps_ops = {
532 554
533 .try_idle = dsps_musb_try_idle, 555 .try_idle = dsps_musb_try_idle,
534 .set_mode = dsps_musb_set_mode, 556 .set_mode = dsps_musb_set_mode,
557 .reset = dsps_musb_reset,
535}; 558};
536 559
537static u64 musb_dmamask = DMA_BIT_MASK(32); 560static u64 musb_dmamask = DMA_BIT_MASK(32);