aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrazvydas Ignotas <notasas@gmail.com>2013-03-24 17:36:53 +0200
committerFelipe Balbi <balbi@ti.com>2013-04-02 11:42:41 +0300
commitf65f4f40fb23b64a59adbe8629e8e7e6fea279cf (patch)
tree647535e5bb45b0c0e753e8baad0ff4c328ef0787
parent6b0cfc656f8a649fbfbe11e76e0aa301ee26879e (diff)
usb: phy: twl4030-usb: check if vbus is driven by twl itself
At least on pandora, STS_VBUS gets set even when VBUS is driven by twl itself. Reporting VBUS in this case confuses OMAP musb glue and charger driver, so check if OTG VBUS charge pump is on before reporting VBUS event to avoid this problem. Signed-off-by: Grazvydas Ignotas <notasas@gmail.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r--drivers/usb/phy/phy-twl4030-usb.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/drivers/usb/phy/phy-twl4030-usb.c b/drivers/usb/phy/phy-twl4030-usb.c
index 61fe7e29c9c..3f9858fbebc 100644
--- a/drivers/usb/phy/phy-twl4030-usb.c
+++ b/drivers/usb/phy/phy-twl4030-usb.c
@@ -248,6 +248,25 @@ twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
/*-------------------------------------------------------------------------*/
+static bool twl4030_is_driving_vbus(struct twl4030_usb *twl)
+{
+ int ret;
+
+ ret = twl4030_usb_read(twl, PHY_CLK_CTRL_STS);
+ if (ret < 0 || !(ret & PHY_DPLL_CLK))
+ /*
+ * if clocks are off, registers are not updated,
+ * but we can assume we don't drive VBUS in this case
+ */
+ return false;
+
+ ret = twl4030_usb_read(twl, ULPI_OTG_CTRL);
+ if (ret < 0)
+ return false;
+
+ return (ret & (ULPI_OTG_DRVVBUS | ULPI_OTG_CHRGVBUS)) ? true : false;
+}
+
static enum omap_musb_vbus_id_status
twl4030_usb_linkstat(struct twl4030_usb *twl)
{
@@ -270,13 +289,19 @@ static enum omap_musb_vbus_id_status
if (status < 0)
dev_err(twl->dev, "USB link status err %d\n", status);
else if (status & (BIT(7) | BIT(2))) {
- if (status & (BIT(7)))
- twl->vbus_supplied = true;
+ if (status & BIT(7)) {
+ if (twl4030_is_driving_vbus(twl))
+ status &= ~BIT(7);
+ else
+ twl->vbus_supplied = true;
+ }
if (status & BIT(2))
linkstat = OMAP_MUSB_ID_GROUND;
- else
+ else if (status & BIT(7))
linkstat = OMAP_MUSB_VBUS_VALID;
+ else
+ linkstat = OMAP_MUSB_VBUS_OFF;
} else {
if (twl->linkstat != OMAP_MUSB_UNKNOWN)
linkstat = OMAP_MUSB_VBUS_OFF;