summaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/omap2430.c
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2020-01-15 07:25:29 -0600
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-01-15 14:46:55 +0100
commit93dc256871297071a24f7f9ce0abfddfff15094d (patch)
treec106922fba4fd3221f7491baf6c7d868d09fb01f /drivers/usb/musb/omap2430.c
parent15f1122f92c02f654037d8fb98164b785207b7af (diff)
downloadlinux-93dc256871297071a24f7f9ce0abfddfff15094d.tar.bz2
usb: musb: Add musb_set_host and peripheral and use them for omap2430
At least some revisions of musb core need to set devctl session bit in peripheral mode to force musb to host mode. And we have places clearing the devctl session bit. Let's add a generic function to do this, and use it for omap2430. This should get us a bit closer to completely removing devctl register tinkering in the SoC glue code. Before making use of this code for the other glue layers, things need to be tested carefully as there may be a approximately a 200 ms delay needed between powering up musb and calling musb_set_host() to avoid. Otherwise the system hangs at least with omap2430 glue layer. Acked-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: Tony Lindgren <tony@atomide.com> [b-liu@ti.com: fixed "line over 80 characters" warning] Signed-off-by: Bin Liu <b-liu@ti.com> Link: https://lore.kernel.org/r/20200115132547.364-8-b-liu@ti.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/musb/omap2430.c')
-rw-r--r--drivers/usb/musb/omap2430.c71
1 files changed, 22 insertions, 49 deletions
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index e572ee624128..9c1b72a4b12f 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -38,65 +38,38 @@ struct omap2430_glue {
static struct omap2430_glue *_glue;
+/*
+ * HDRC controls CPEN, but beware current surges during device connect.
+ * They can trigger transient overcurrent conditions that must be ignored.
+ *
+ * Note that we're skipping A_WAIT_VFALL -> A_IDLE and jumping right to B_IDLE
+ * as set by musb_set_peripheral().
+ */
static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
{
- struct usb_otg *otg = musb->xceiv->otg;
- u8 devctl;
- unsigned long timeout = jiffies + msecs_to_jiffies(1000);
- /* HDRC controls CPEN, but beware current surges during device
- * connect. They can trigger transient overcurrent conditions
- * that must be ignored.
- */
-
- devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+ struct usb_otg *otg = musb->xceiv->otg;
+ int error;
if (is_on) {
- if (musb->xceiv->otg->state == OTG_STATE_A_IDLE) {
- int loops = 100;
- /* start the session */
- devctl |= MUSB_DEVCTL_SESSION;
- musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
- /*
- * Wait for the musb to set as A device to enable the
- * VBUS
- */
- while (musb_readb(musb->mregs, MUSB_DEVCTL) &
- MUSB_DEVCTL_BDEVICE) {
-
- mdelay(5);
- cpu_relax();
-
- if (time_after(jiffies, timeout)
- || loops-- <= 0) {
- dev_err(musb->controller,
- "configured as A device timeout");
- break;
- }
+ switch (musb->xceiv->otg->state) {
+ case OTG_STATE_A_IDLE:
+ error = musb_set_host(musb);
+ if (!error) {
+ musb->xceiv->otg->state =
+ OTG_STATE_A_WAIT_VRISE;
+ otg_set_vbus(otg, 1);
}
-
+ break;
+ default:
otg_set_vbus(otg, 1);
- } else {
- musb->is_active = 1;
- musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
- devctl |= MUSB_DEVCTL_SESSION;
- MUSB_HST_MODE(musb);
+ break;
}
} else {
- musb->is_active = 0;
-
- /* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and
- * jumping right to B_IDLE...
- */
-
- musb->xceiv->otg->state = OTG_STATE_B_IDLE;
- devctl &= ~MUSB_DEVCTL_SESSION;
-
- MUSB_DEV_MODE(musb);
+ error = musb_set_peripheral(musb);
+ otg_set_vbus(otg, 0);
}
- musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
- dev_dbg(musb->controller, "VBUS %s, devctl %02x "
- /* otg %3x conf %08x prcm %08x */ "\n",
+ dev_dbg(musb->controller, "VBUS %s, devctl %02x\n",
usb_otg_state_string(musb->xceiv->otg->state),
musb_readb(musb->mregs, MUSB_DEVCTL));
}