linux-arm-msm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Stephen Boyd <stephen.boyd@linaro.org>
To: linux-usb@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,
	Andy Gross <andy.gross@linaro.org>,
	Bjorn Andersson <bjorn.andersson@linaro.org>,
	Neil Armstrong <narmstrong@baylibre.com>,
	Arnd Bergmann <arnd@arndb.de>, Felipe Balbi <balbi@kernel.org>,
	Peter Chen <peter.chen@nxp.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Subject: [PATCH v5 11/23] usb: chipidea: Emulate OTGSC interrupt enable path
Date: Mon, 17 Oct 2016 18:56:24 -0700	[thread overview]
Message-ID: <20161018015636.11701-12-stephen.boyd@linaro.org> (raw)
In-Reply-To: <20161018015636.11701-1-stephen.boyd@linaro.org>

In the case of an extcon-usb-gpio device being used with the
chipidea driver we'll sometimes miss the BSVIS event in the OTGSC
register. Consider the case where we don't have a cable attached
and the id pin is indicating "host" mode. When we plug in the usb
cable for "device" mode a gpio goes high and indicates that we
should do the role switch and that vbus is high. When we're in
"host" mode the OTGSC register doesn't have BSVIE set.

The following scenario can happen:

CPU0
----
<extcon notifier chain>
 ci_cable_notifier()
  update id cable state
  ci_irq()
   if (ci->is_otg && (otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS)) { // true
    ci->id_event = true;
    ci_otg_queue_work()
     schedule()

<extcon notifier event> // same task as before
 ci_cable_notifier()
  update vbus cable state
   ci_irq()
    if (ci->is_otg && (otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS)) // false
   return IRQ_NONE

ci_otg_work() // switch task to the workqueue now
 if (ci->id_event)
  ci_handle_id_switch()
   ci_role_stop()
    host_stop()
   hw_wait_vbus_lower_bsv(ci); // this times out because vbus is already set
   ci_role_start()
    udc_id_switch_for_device()
     hw_write_otgsc(ci, OTGSC_BSVIS | OTGSC_BSVIE, OTGSC_BSVIS | OTGSC_BSVIE);

At this point, we don't replay the vbus connect event because the
vbus event has already happened. This causes things like gadget
instances to never see vbus appear, and thus the gadget is never
started. Furthermore, we see timeout messages like:

	timeout waiting for 0000800 in OTGSC

Let's workaround this by skiping the wait for BSV when we're
using an extcon for the vbus notification and let's properly
emulate the BSVIS event that would happen when we enable the
vbus interrupt while enabling "device" mode.

Cc: Peter Chen <peter.chen@nxp.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
 drivers/usb/chipidea/ci.h   |  2 ++
 drivers/usb/chipidea/core.c | 23 +++++++++++++++++------
 drivers/usb/chipidea/otg.c  | 31 ++++++++++++++++++++++++-------
 3 files changed, 43 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index 59e22389c10b..e099b8bc79e2 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -437,6 +437,8 @@ static inline void ci_ulpi_exit(struct ci_hdrc *ci) { }
 static inline int ci_ulpi_resume(struct ci_hdrc *ci) { return 0; }
 #endif
 
+irqreturn_t __ci_irq(int irq, struct ci_hdrc *ci);
+
 u32 hw_read_intr_enable(struct ci_hdrc *ci);
 
 u32 hw_read_intr_status(struct ci_hdrc *ci);
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 83bc2f2dd6a8..d1ae9a03e0fa 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -524,9 +524,8 @@ int hw_device_reset(struct ci_hdrc *ci)
 	return 0;
 }
 
-static irqreturn_t ci_irq(int irq, void *data)
+irqreturn_t __ci_irq(int irq, struct ci_hdrc *ci)
 {
-	struct ci_hdrc *ci = data;
 	irqreturn_t ret = IRQ_NONE;
 	u32 otgsc = 0;
 
@@ -570,9 +569,20 @@ static irqreturn_t ci_irq(int irq, void *data)
 		return IRQ_HANDLED;
 	}
 
-	/* Handle device/host interrupt */
-	if (ci->role != CI_ROLE_END)
-		ret = ci_role(ci)->irq(ci);
+	return ret;
+}
+
+static irqreturn_t ci_irq(int irq, void *data)
+{
+	irqreturn_t ret;
+	struct ci_hdrc *ci = data;
+
+	ret = __ci_irq(irq, ci);
+	if (ret == IRQ_NONE) {
+		/* Handle device/host interrupt */
+		if (ci->role != CI_ROLE_END)
+			ret = ci_role(ci)->irq(ci);
+	}
 
 	return ret;
 }
@@ -586,7 +596,8 @@ static int ci_cable_notifier(struct notifier_block *nb, unsigned long event,
 	cbl->connected = event;
 	cbl->changed = true;
 
-	ci_irq(ci->irq, ci);
+	__ci_irq(ci->irq, ci);
+
 	return NOTIFY_DONE;
 }
 
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
index 695f3fe3ae21..f4a21ade1901 100644
--- a/drivers/usb/chipidea/otg.c
+++ b/drivers/usb/chipidea/otg.c
@@ -84,36 +84,44 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask)
 void hw_write_otgsc(struct ci_hdrc *ci, u32 mask, u32 data)
 {
 	struct ci_hdrc_cable *cable;
+	bool raise_irq = false;
 
 	cable = &ci->platdata->vbus_extcon;
 	if (!IS_ERR(cable->edev)) {
-		if (data & mask & OTGSC_BSVIS)
-			cable->changed = false;
-
 		/* Don't enable vbus interrupt if using external notifier */
 		if (data & mask & OTGSC_BSVIE) {
+			if (cable->enabled == false && cable->changed == true)
+				raise_irq = true;
 			cable->enabled = true;
 			data &= ~OTGSC_BSVIE;
 		} else if (mask & OTGSC_BSVIE) {
 			cable->enabled = false;
 		}
+
+		if (data & mask & OTGSC_BSVIS && !raise_irq)
+			cable->changed = false;
 	}
 
 	cable = &ci->platdata->id_extcon;
 	if (!IS_ERR(cable->edev)) {
-		if (data & mask & OTGSC_IDIS)
-			cable->changed = false;
-
 		/* Don't enable id interrupt if using external notifier */
 		if (data & mask & OTGSC_IDIE) {
+			if (cable->enabled == false && cable->changed == true)
+				raise_irq = true;
 			cable->enabled = true;
 			data &= ~OTGSC_IDIE;
 		} else if (mask & OTGSC_IDIE) {
 			cable->enabled = false;
 		}
+
+		if (data & mask & OTGSC_IDIS && !raise_irq)
+			cable->changed = false;
 	}
 
 	hw_write(ci, OP_OTGSC, mask | OTGSC_INT_STATUS_BITS, data);
+
+	if (raise_irq)
+		__ci_irq(ci->irq, ci);
 }
 
 /**
@@ -175,7 +183,16 @@ static void ci_handle_id_switch(struct ci_hdrc *ci)
 
 		ci_role_stop(ci);
 
-		if (role == CI_ROLE_GADGET)
+		/*
+		 * BSV could be set "immediately" if we're using extcon for
+		 * VBUS because sometimes it's a single GPIO for ID and VBUS
+		 * like in the case of extcon-usb-gpio. In that case we ignore
+		 * waiting for a BSV transition. Really we can't tell when BSV
+		 * is low and the cable is connected, all we know is that the
+		 * BSV is high when we update BSV state.
+		 */
+		if (role == CI_ROLE_GADGET &&
+		    IS_ERR(ci->platdata->vbus_extcon.edev))
 			/*
 			 * wait vbus lower than OTGSC_BSV before connecting
 			 * to host
-- 
2.10.0.297.gf6727b0

  parent reply	other threads:[~2016-10-18  1:56 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-18  1:56 [PATCH v5 00/23] Support qcom's HSIC USB and rewrite USB2 HS support Stephen Boyd
2016-10-18  1:56 ` [PATCH v5 03/23] usb: ulpi: Support device discovery via DT Stephen Boyd
2016-10-18 16:44   ` Rob Herring
2016-11-11 11:02   ` Heikki Krogerus
2016-10-18  1:56 ` [PATCH v5 04/23] usb: chipidea: Only read/write OTGSC from one place Stephen Boyd
2016-10-18  1:56 ` [PATCH v5 05/23] usb: chipidea: Handle extcon events properly Stephen Boyd
2016-10-18  1:56 ` [PATCH v5 06/23] usb: chipidea: Add platform flag for wrapper phy management Stephen Boyd
2016-10-18  1:56 ` [PATCH v5 07/23] usb: chipidea: Notify events when switching host mode Stephen Boyd
2016-10-18  1:56 ` [PATCH v5 08/23] usb: chipidea: Remove locking in ci_udc_start() Stephen Boyd
2016-10-18  1:56 ` [PATCH v5 09/23] usb: chipidea: Add support for ULPI PHY bus Stephen Boyd
2016-10-18  1:56 ` [PATCH v5 10/23] usb: chipidea: Consolidate extcon notifiers Stephen Boyd
2016-10-18  1:56 ` Stephen Boyd [this message]
2016-10-19  1:15   ` [PATCH v5 11/23] usb: chipidea: Emulate OTGSC interrupt enable path Peter Chen
2016-10-19  1:53     ` Stephen Boyd
2016-10-19  8:02       ` Peter Chen
2016-10-20  6:55         ` Stephen Boyd
2016-10-20 10:10           ` Peter Chen
2016-10-20 20:36             ` Stephen Boyd
2016-10-21  2:14               ` Peter Chen
2016-10-21 17:57                 ` Stephen Boyd
2016-10-18  1:56 ` [PATCH v5 12/23] usb: chipidea: msm: Mark device as runtime pm active Stephen Boyd
2016-10-18  1:56 ` [PATCH v5 13/23] usb: chipidea: msm: Rely on core to override AHBBURST Stephen Boyd
2016-10-18  1:56 ` [PATCH v5 14/23] usb: chipidea: msm: Use hw_write_id_reg() instead of writel Stephen Boyd
2016-10-18  1:56 ` [PATCH v5 15/23] usb: chipidea: msm: Add proper clk and reset support Stephen Boyd
2016-10-18  1:56 ` [PATCH v5 16/23] usb: chipidea: msm: Mux over secondary phy at the right time Stephen Boyd
2016-10-18  1:56 ` [PATCH v5 17/23] usb: chipidea: msm: Restore wrapper settings after reset Stephen Boyd
2016-10-18  1:56 ` [PATCH v5 18/23] usb: chipidea: msm: Make platform data driver local instead of global Stephen Boyd
     [not found] ` <20161018015636.11701-1-stephen.boyd-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2016-10-18  1:56   ` [PATCH v5 01/23] of: device: Support loading a module with OF based modalias Stephen Boyd
2016-10-18  1:56   ` [PATCH v5 02/23] of: device: Export of_device_{get_modalias,uvent_modalias} to modules Stephen Boyd
     [not found]     ` <20161018015636.11701-3-stephen.boyd-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2016-10-18  5:20       ` [PATCH v5 02/23] of: device: Export of_device_{get_modalias, uvent_modalias} " Chen-Yu Tsai
2016-10-24 12:19     ` Chen-Yu Tsai
2016-10-24 19:48       ` Stephen Boyd
2016-10-25  1:16         ` Peter Chen
2016-11-04 20:51           ` Stephen Boyd
2016-11-07  1:29             ` Peter Chen
2016-11-07  1:56               ` Chen-Yu Tsai
     [not found]                 ` <CAGb2v66C15fU1b2+xNDV8Fv2kmmKXyUknA8=9wXztUcs8CNKLg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-11-10 21:42                   ` Rob Herring
2016-11-11  3:01                     ` Chen-Yu Tsai
2016-11-11  4:25                       ` Javier Martinez Canillas
2016-10-18  1:56   ` [PATCH v5 19/23] usb: chipidea: msm: Add reset controller for PHY POR bit Stephen Boyd
2016-10-18  1:56   ` [PATCH v5 20/23] usb: chipidea: msm: Handle phy power states Stephen Boyd
2016-10-18  1:56   ` [PATCH v5 23/23] phy: Add support for Qualcomm's USB HS phy Stephen Boyd
2016-10-18 16:46     ` Rob Herring
2016-10-18 16:47     ` Rob Herring
     [not found]     ` <20161018015636.11701-24-stephen.boyd-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2016-10-20 23:20       ` Stephen Boyd
2016-10-21  2:20         ` Peter Chen
2016-10-21 19:33           ` Stephen Boyd
2016-10-24  2:14             ` Peter Chen
2016-10-18  9:31   ` [PATCH v5 00/23] Support qcom's HSIC USB and rewrite USB2 HS support Peter Chen
2016-10-18 20:51     ` Stephen Boyd
2016-11-11  7:40       ` Peter Chen
2016-11-14 19:35         ` Stephen Boyd
2016-10-18  1:56 ` [PATCH v5 21/23] usb: chipidea: msm: Be silent on probe defer errors Stephen Boyd
2016-10-18  1:56 ` [PATCH v5 22/23] phy: Add support for Qualcomm's USB HSIC phy Stephen Boyd

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=20161018015636.11701-12-stephen.boyd@linaro.org \
    --to=stephen.boyd@linaro.org \
    --cc=andy.gross@linaro.org \
    --cc=arnd@arndb.de \
    --cc=balbi@kernel.org \
    --cc=bjorn.andersson@linaro.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=narmstrong@baylibre.com \
    --cc=peter.chen@nxp.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).