diff options
author | Daniel Mack <zonque@gmail.com> | 2014-04-02 07:58:29 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2014-04-21 15:07:29 -0400 |
commit | 1d57de306e1f3e73c607811a974f6662162e5df6 (patch) | |
tree | b8d2eb8d5e8827ec4395ba39ab8c0c08511c234d /drivers/usb/musb/musb_dsps.c | |
parent | ca88fc2ef0d790a1da37804219102336f7622b97 (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.c | 25 |
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 | ||
538 | static 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 | |||
526 | static struct musb_platform_ops dsps_ops = { | 548 | static 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 | ||
537 | static u64 musb_dmamask = DMA_BIT_MASK(32); | 560 | static u64 musb_dmamask = DMA_BIT_MASK(32); |