All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bin Liu <b-liu@ti.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: <linux-usb@vger.kernel.org>, Bin Liu <b-liu@ti.com>
Subject: [PATCH 07/25] usb: musb: Add musb_set_host and peripheral and use them for omap2430
Date: Wed, 15 Jan 2020 07:25:29 -0600	[thread overview]
Message-ID: <20200115132547.364-8-b-liu@ti.com> (raw)
In-Reply-To: <20200115132547.364-1-b-liu@ti.com>

From: Tony Lindgren <tony@atomide.com>

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>
---
 drivers/usb/musb/musb_core.c | 103 +++++++++++++++++++++++++++++++++++
 drivers/usb/musb/musb_core.h |   3 +
 drivers/usb/musb/omap2430.c  |  71 ++++++++----------------
 3 files changed, 128 insertions(+), 49 deletions(-)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 48d95850152d..34090707d122 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -73,6 +73,7 @@
 #include <linux/prefetch.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/dma-mapping.h>
 #include <linux/usb.h>
 #include <linux/usb/of.h>
@@ -414,6 +415,108 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src)
 	return hw_ep->musb->io.write_fifo(hw_ep, len, src);
 }
 
+static u8 musb_read_devctl(struct musb *musb)
+{
+	return musb_readb(musb->mregs, MUSB_DEVCTL);
+}
+
+/**
+ * musb_set_host - set and initialize host mode
+ * @musb: musb controller driver data
+ *
+ * At least some musb revisions need to enable devctl session bit in
+ * peripheral mode to switch to host mode. Initializes things to host
+ * mode and sets A_IDLE. SoC glue needs to advance state further
+ * based on phy provided VBUS state.
+ *
+ * Note that the SoC glue code may need to wait for musb to settle
+ * on enable before calling this to avoid babble.
+ */
+int musb_set_host(struct musb *musb)
+{
+	int error = 0;
+	u8 devctl;
+
+	if (!musb)
+		return -EINVAL;
+
+	devctl = musb_read_devctl(musb);
+	if (!(devctl & MUSB_DEVCTL_BDEVICE)) {
+		dev_info(musb->controller,
+			 "%s: already in host mode: %02x\n",
+			 __func__, devctl);
+		goto init_data;
+	}
+
+	devctl |= MUSB_DEVCTL_SESSION;
+	musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+	error = readx_poll_timeout(musb_read_devctl, musb, devctl,
+				   !(devctl & MUSB_DEVCTL_BDEVICE), 5000,
+				   1000000);
+	if (error) {
+		dev_err(musb->controller, "%s: could not set host: %02x\n",
+			__func__, devctl);
+
+		return error;
+	}
+
+init_data:
+	musb->is_active = 1;
+	musb->xceiv->otg->state = OTG_STATE_A_IDLE;
+	MUSB_HST_MODE(musb);
+
+	return error;
+}
+EXPORT_SYMBOL_GPL(musb_set_host);
+
+/**
+ * musb_set_peripheral - set and initialize peripheral mode
+ * @musb: musb controller driver data
+ *
+ * Clears devctl session bit and initializes things for peripheral
+ * mode and sets B_IDLE. SoC glue needs to advance state further
+ * based on phy provided VBUS state.
+ */
+int musb_set_peripheral(struct musb *musb)
+{
+	int error = 0;
+	u8 devctl;
+
+	if (!musb)
+		return -EINVAL;
+
+	devctl = musb_read_devctl(musb);
+	if (devctl & MUSB_DEVCTL_BDEVICE) {
+		dev_info(musb->controller,
+			 "%s: already in peripheral mode: %02x\n",
+			 __func__, devctl);
+
+		goto init_data;
+	}
+
+	devctl &= ~MUSB_DEVCTL_SESSION;
+	musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+	error = readx_poll_timeout(musb_read_devctl, musb, devctl,
+				   devctl & MUSB_DEVCTL_BDEVICE, 5000,
+				   1000000);
+	if (error) {
+		dev_err(musb->controller, "%s: could not set periperal: %02x\n",
+			__func__, devctl);
+
+		return error;
+	}
+
+init_data:
+	musb->is_active = 0;
+	musb->xceiv->otg->state = OTG_STATE_B_IDLE;
+	MUSB_DEV_MODE(musb);
+
+	return error;
+}
+EXPORT_SYMBOL_GPL(musb_set_peripheral);
+
 /*-------------------------------------------------------------------------*/
 
 /* for high speed test mode; see USB 2.0 spec 7.1.20 */
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 04203b7126d5..8a13a46cd891 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -487,6 +487,9 @@ extern void musb_start(struct musb *musb);
 extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src);
 extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst);
 
+extern int musb_set_host(struct musb *musb);
+extern int musb_set_peripheral(struct musb *musb);
+
 extern void musb_load_testpacket(struct musb *);
 
 extern irqreturn_t musb_interrupt(struct musb *);
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));
 }
-- 
2.17.1


  parent reply	other threads:[~2020-01-15 13:25 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-15 13:25 [PATCH 00/25] musb patches for v5.6-rc1 Bin Liu
2020-01-15 13:25 ` [PATCH 01/25] usb: musb: core: Update the function description Bin Liu
2020-01-15 13:25 ` [PATCH 02/25] usb: musb: sunxi: propagate devicetree node to glue pdev Bin Liu
2020-01-15 13:25 ` [PATCH 03/25] usb: musb: jz4740: Drop dependency on NOP_USB_XCEIV Bin Liu
2020-01-15 13:25 ` [PATCH 04/25] usb: musb: omap2430: Get rid of musb .set_vbus for omap2430 glue Bin Liu
2020-01-15 13:25 ` [PATCH 05/25] usb: musb: omap2430: Wait on enable to avoid babble Bin Liu
2020-01-15 13:25 ` [PATCH 06/25] usb: musb: omap2430: Handle multiple ID ground interrupts Bin Liu
2020-01-15 13:25 ` Bin Liu [this message]
2020-01-15 13:25 ` [PATCH 08/25] usb: musb: omap2430: Clean up enable and remove devctl tinkering Bin Liu
2020-01-15 13:25 ` [PATCH 09/25] usb: musb: omap2430: Idle musb on init Bin Liu
2020-01-15 13:25 ` [PATCH 10/25] usb: musb: Get rid of omap2430_musb_set_vbus() Bin Liu
2020-01-15 13:25 ` [PATCH 11/25] usb: musb: jz4740: Suppress useless field in priv structure Bin Liu
2020-01-15 13:25 ` [PATCH 12/25] usb: musb: jz4740: Add local dev variable to clean up probe Bin Liu
2020-01-15 13:25 ` [PATCH 13/25] usb: musb: jz4740: Constify jz4740_musb_pdata struct Bin Liu
2020-01-15 13:25 ` [PATCH 14/25] usb: musb: jz4740: Rename platform_device field in priv struct Bin Liu
2020-01-15 13:25 ` [PATCH 15/25] usb: musb: jz4740: Comments fix Bin Liu
2020-01-15 13:25 ` [PATCH 16/25] usb: musb: jz4740: Whitespace and indentation fixes Bin Liu
2020-01-15 13:25 ` [PATCH 17/25] USB: musb: fix __iomem in trace functions Bin Liu
2020-01-15 13:25 ` [PATCH 18/25] usb: musb/ux500: Use dma_request_chan() instead dma_request_slave_channel() Bin Liu
2020-01-15 13:25 ` [PATCH 19/25] dt-bindings: usb: musb: Add support for MediaTek musb controller Bin Liu
2020-01-15 13:25 ` [PATCH 20/25] usb: musb: Add get/set toggle hooks Bin Liu
2020-01-15 13:25 ` [PATCH 21/25] usb: musb: Add noirq type of dma create interface Bin Liu
2020-01-15 13:25 ` [PATCH 22/25] usb: musb: Add musb_clearb/w() interface Bin Liu
2020-01-15 13:25 ` [PATCH 23/25] usb: musb: Add support for MediaTek musb controller Bin Liu
2020-01-15 13:25 ` [PATCH 24/25] usb: musb: davinci: Convert to use GPIO descriptor Bin Liu
2020-01-15 13:25 ` [PATCH 25/25] usb: musb: remove dummy driver musb_am335x.c Bin Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200115132547.364-8-b-liu@ti.com \
    --to=b-liu@ti.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-usb@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.