diff options
| author | Riyad Abd <far023@motorola.com> | 2014-05-28 15:23:51 -0400 |
|---|---|---|
| committer | Riyad Abd <far023@motorola.com> | 2014-05-29 17:15:37 +0000 |
| commit | b2f0b362d75cb65a9a78451f8c7dd8eb94761306 (patch) | |
| tree | 2e836a4ffce86a5a10ab991df6bb192348444ee7 | |
| parent | c66cbe57cd16f9f170f1116f6646705b4e65f50f (diff) | |
| download | olio-linux-3.10-b2f0b362d75cb65a9a78451f8c7dd8eb94761306.tar.xz olio-linux-3.10-b2f0b362d75cb65a9a78451f8c7dd8eb94761306.zip | |
IKXCLOCK-1624: kernel: consecutive fastboot/adb fails
Change-Id: I428b91a1faeded005ad5efe4276774354b350b91
| -rw-r--r-- | drivers/usb/musb/musb_gadget.c | 10 | ||||
| -rw-r--r-- | drivers/usb/phy/phy-tusb.c | 8 | ||||
| -rw-r--r-- | include/linux/usb/phy.h | 13 |
3 files changed, 29 insertions, 2 deletions
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index c04b7fbb6b9..441eda17919 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1612,15 +1612,20 @@ static void musb_pullup(struct musb *musb, int is_on) u8 power; power = musb_readb(musb->mregs, MUSB_POWER); - if (is_on) + if (is_on) { + usb_phy_reset(musb->xceiv, 0); + mdelay(10); + usb_phy_reset(musb->xceiv, 1); power |= MUSB_POWER_SOFTCONN; - else + } else { power &= ~MUSB_POWER_SOFTCONN; + } /* FIXME if on, HdrcStart; if off, HdrcStop */ dev_dbg(musb->controller, "gadget D+ pullup %s\n", is_on ? "on" : "off"); + musb_writeb(musb->mregs, MUSB_POWER, power); } @@ -1663,6 +1668,7 @@ static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on) if (is_on != musb->softconnect) { musb->softconnect = is_on; + dev_dbg(musb->controller, "musb_gadget_pullup: %d", is_on); musb_pullup(musb, is_on); } diff --git a/drivers/usb/phy/phy-tusb.c b/drivers/usb/phy/phy-tusb.c index 25b081ce4a2..48f958510b3 100644 --- a/drivers/usb/phy/phy-tusb.c +++ b/drivers/usb/phy/phy-tusb.c @@ -148,6 +148,13 @@ static int tusb_enable(struct tusb_usb *tusb, bool enable) return 0; } +static int tusb_phy_reset(struct usb_phy *x, int enable) +{ + struct tusb_usb *tusb = dev_get_drvdata(x->dev); + + return tusb_enable(tusb, (bool)enable); +} + static int tusb_usb_set_vbus(struct usb_otg *otg, bool enabled) { return 0; @@ -325,6 +332,7 @@ static int tusb_usb_probe(struct platform_device *pdev) tusb->phy.dev = tusb->dev; tusb->phy.label = "tusb"; tusb->phy.set_suspend = tusb_set_suspend; + tusb->phy.hw_reset = tusb_phy_reset; tusb->phy.otg = otg; tusb->phy.type = USB_PHY_TYPE_USB2; tusb->phy.last_event = USB_EVENT_NONE; diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h index 6b5978f5763..586152a6829 100644 --- a/include/linux/usb/phy.h +++ b/include/linux/usb/phy.h @@ -94,6 +94,10 @@ struct usb_phy { /* enable/disable VBUS */ int (*set_vbus)(struct usb_phy *x, int on); + /* hold/unhold usb controller in reset */ + int (*hw_reset)(struct usb_phy *x, + int enable); + /* effective for B devices, ignored for A-peripheral */ int (*set_power)(struct usb_phy *x, unsigned mA); @@ -181,6 +185,15 @@ usb_phy_vbus_off(struct usb_phy *x) return x->set_vbus(x, false); } +static inline int +usb_phy_reset(struct usb_phy *x, int enable) +{ + if (!x->hw_reset) + return 0; + + return x->hw_reset(x, enable); +} + /* for usb host and peripheral controller drivers */ #if IS_ENABLED(CONFIG_USB_PHY) extern struct usb_phy *usb_get_phy(enum usb_phy_type type); |