[Letux-kernel] [PATCH v2] phy-twl4030-usb: initialize charging-related stuff via pm_runtime

Andreas Kemnade andreas at kemnade.info
Thu Aug 25 00:27:59 CEST 2016

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

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 at kemnade.info>
 drivers/phy/phy-twl4030-usb.c | 16 +++++++++++-----
I am not 100% sure that this patch works properly in all situations
without the bugfix
phy-twl4030-usb: better handle musb_mailbox() failure
changes in v2:
comment on msleep()

 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c
index 567ad31..99647d9 100644
--- a/drivers/phy/phy-twl4030-usb.c
+++ b/drivers/phy/phy-twl4030-usb.c
@@ -470,6 +470,17 @@ static int __maybe_unused twl4030_usb_runtime_resume(struct device *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);
+	/*
+	 * 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;
@@ -490,11 +501,6 @@ static int twl4030_phy_power_on(struct phy *phy)
 	dev_dbg(twl->dev, "%s\n", __func__);
-	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;

More information about the Letux-kernel mailing list