phy-twl4030-usb: initialize charging-related stuff via pm_runtime
authorAndreas Kemnade <andreas@kemnade.info>
Wed, 24 Aug 2016 22:27:59 +0000 (00:27 +0200)
committerKishon Vijay Abraham I <kishon@ti.com>
Wed, 14 Sep 2016 05:29:12 +0000 (10:59 +0530)
twl4030_phy_power_on() initializes some bits which are required for
charging. As they are not set in twl4030_usb_runtime_resume()
a call to pm_runtime_get_sync() is not sufficient to enable charging.

This patch moves the initialization to twl4030_usb_runtime_resume()
so everything needed for charging is initialized upon
pm_runtime_get_sync().

That also gives improved possibilities to debug problems in that area
because the relevant parts can be checked separately. Charging can be
enabled without having the musb subsystem active.

As a side effect this hides some bugs in musb which causes
unbalanced calls to phy_power_off()/phy_power_on() so that
phy->power_count becomes -1.

The result is that e.g. the GTA04 phone (dm3730 + twl4030) works
finally as a usb gadget again and charging is working.

Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
Acked-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
drivers/phy/phy-twl4030-usb.c

index 81067b461098a304150acfc89581be7549440153..87e6334eab9309f85e8cb5308f96dec54de7f495 100644 (file)
@@ -440,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;
 }
 
@@ -460,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;