]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/usb/musb/musb_dsps.c
Merge tag 'usb-for-v3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi...
[karo-tx-linux.git] / drivers / usb / musb / musb_dsps.c
index e2fd263585de3fb2d8cb5cab3e782eff5675a198..51beb13c7e1a4d4f9694a5469a12363751ef5d6b 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
 #include <linux/module.h>
-#include <linux/usb/usb_phy_gen_xceiv.h>
+#include <linux/usb/usb_phy_generic.h>
 #include <linux/platform_data/usb-omap.h>
 #include <linux/sizes.h>
 
@@ -329,9 +329,21 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
         * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
         * Also, DRVVBUS pulses for SRP (but not at 5V) ...
         */
-       if (is_host_active(musb) && usbintr & MUSB_INTR_BABBLE)
+       if (is_host_active(musb) && usbintr & MUSB_INTR_BABBLE) {
                pr_info("CAUTION: musb: Babble Interrupt Occurred\n");
 
+               /*
+                * When a babble condition occurs, the musb controller removes
+                * the session and is no longer in host mode. Hence, all
+                * devices connected to its root hub get disconnected.
+                *
+                * Hand this error down to the musb core isr, so it can
+                * recover.
+                */
+               musb->int_usb = MUSB_INTR_BABBLE | MUSB_INTR_DISCONNECT;
+               musb->int_tx = musb->int_rx = 0;
+       }
+
        if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
                int drvvbus = dsps_readl(reg_base, wrp->status);
                void __iomem *mregs = musb->mregs;
@@ -524,6 +536,16 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode)
        return 0;
 }
 
+static void dsps_musb_reset(struct musb *musb)
+{
+       struct device *dev = musb->controller;
+       struct dsps_glue *glue = dev_get_drvdata(dev->parent);
+       const struct dsps_musb_wrapper *wrp = glue->wrp;
+
+       dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset));
+       udelay(100);
+}
+
 static struct musb_platform_ops dsps_ops = {
        .init           = dsps_musb_init,
        .exit           = dsps_musb_exit,
@@ -533,6 +555,7 @@ static struct musb_platform_ops dsps_ops = {
 
        .try_idle       = dsps_musb_try_idle,
        .set_mode       = dsps_musb_set_mode,
+       .reset          = dsps_musb_reset,
 };
 
 static u64 musb_dmamask = DMA_BIT_MASK(32);
@@ -750,7 +773,7 @@ static const struct of_device_id musb_dsps_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, musb_dsps_of_match);
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int dsps_suspend(struct device *dev)
 {
        struct dsps_glue *glue = dev_get_drvdata(dev);