Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / drivers / phy / phy-twl4030-usb.c
index d9b10a3..87e6334 100644 (file)
@@ -172,6 +172,7 @@ struct twl4030_usb {
        int                     irq;
        enum musb_vbus_id_status linkstat;
        bool                    vbus_supplied;
+       bool                    musb_mailbox_pending;
 
        struct delayed_work     id_workaround_work;
 };
@@ -439,6 +440,17 @@ static int __maybe_unused twl4030_usb_runtime_resume(struct device *dev)
                          (PHY_CLK_CTRL_CLOCKGATING_EN |
                           PHY_CLK_CTRL_CLK32K_EN));
 
+       twl4030_i2c_access(twl, 1);
+       twl4030_usb_set_mode(twl, twl->usb_mode);
+       if (twl->usb_mode == T2_USB_MODE_ULPI)
+               twl4030_i2c_access(twl, 0);
+       /*
+        * According to the TPS65950 TRM, there has to be at least 50ms
+        * delay between setting POWER_CTRL_OTG_ENAB and enabling charging
+        * so wait here so that a fully enabled phy can be expected after
+        * resume
+        */
+       msleep(50);
        return 0;
 }
 
@@ -459,11 +471,6 @@ static int twl4030_phy_power_on(struct phy *phy)
 
        dev_dbg(twl->dev, "%s\n", __func__);
        pm_runtime_get_sync(twl->dev);
-       twl4030_i2c_access(twl, 1);
-       twl4030_usb_set_mode(twl, twl->usb_mode);
-       if (twl->usb_mode == T2_USB_MODE_ULPI)
-               twl4030_i2c_access(twl, 0);
-       twl->linkstat = MUSB_UNKNOWN;
        schedule_delayed_work(&twl->id_workaround_work, HZ);
 
        return 0;
@@ -569,9 +576,12 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
                        pm_runtime_mark_last_busy(twl->dev);
                        pm_runtime_put_autosuspend(twl->dev);
                }
+               twl->musb_mailbox_pending = true;
+       }
+       if (twl->musb_mailbox_pending) {
                err = musb_mailbox(status);
-               if (err)
-                       twl->linkstat = MUSB_UNKNOWN;
+               if (!err)
+                       twl->musb_mailbox_pending = false;
        }
 
        /* don't schedule during sleep - irq works right then */
@@ -676,6 +686,7 @@ static int twl4030_usb_probe(struct platform_device *pdev)
        twl->irq                = platform_get_irq(pdev, 0);
        twl->vbus_supplied      = false;
        twl->linkstat           = MUSB_UNKNOWN;
+       twl->musb_mailbox_pending = false;
 
        twl->phy.dev            = twl->dev;
        twl->phy.label          = "twl4030";