summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0029-musb-support-disconnect-after-HNP-roleswitch.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0029-musb-support-disconnect-after-HNP-roleswitch.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0029-musb-support-disconnect-after-HNP-roleswitch.patch145
1 files changed, 145 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0029-musb-support-disconnect-after-HNP-roleswitch.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0029-musb-support-disconnect-after-HNP-roleswitch.patch
new file mode 100644
index 0000000000..fc34fb983e
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0029-musb-support-disconnect-after-HNP-roleswitch.patch
@@ -0,0 +1,145 @@
1From 4288b7df4ae6629a4fb14aca2c489da01d4d19c3 Mon Sep 17 00:00:00 2001
2From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
3Date: Tue, 31 Mar 2009 12:35:09 -0700
4Subject: [PATCH] musb: support disconnect after HNP roleswitch
5
6Adjust HNP state machines in MUSB driver so that they handle the
7case where the cable is disconnected. The A-side machine was
8very wrong (unrecoverable); the B-Side was much less so.
9
10 - A_PERIPHERAL ... as usual, the non-observability of the ID
11 pin through Mentor's registers makes trouble. We can't go
12 directly to A_WAIT_VFALL to end the session and start the
13 disconnect processing. We can however sense link suspending,
14 go to A_WAIT_BCON, and from there use OTG timeouts to finally
15 trigger that A_WAIT_VFALL transition. (Hoping that nobody
16 reconnects quickly to that port and notices the wrong state.)
17
18 - B_HOST ... actually clear the Host Request (HR) bit as the
19 messages say, disconnect the peripheral from the root hub,
20 and don't detour through a suspend state. (In some cases
21 this would eventually have cleaned up.)
22
23Also adjust the A_SUSPEND transition to respect the A_AIDL_BDIS
24timeout, so if HNP doesn't trigger quickly enough the A_WAIT_VFALL
25transition happens as it should.
26
27Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
28---
29 drivers/usb/musb/musb_core.c | 41 +++++++++++++++++++++++++++-----------
30 drivers/usb/musb/musb_gadget.c | 2 +
31 drivers/usb/musb/musb_virthub.c | 4 +++
32 3 files changed, 35 insertions(+), 12 deletions(-)
33
34diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
35index 9dc995a..5770ccb 100644
36--- a/drivers/usb/musb/musb_core.c
37+++ b/drivers/usb/musb/musb_core.c
38@@ -304,9 +304,11 @@ void musb_otg_timer_func(unsigned long data)
39 musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
40 musb->is_active = 0;
41 break;
42+ case OTG_STATE_A_SUSPEND:
43 case OTG_STATE_A_WAIT_BCON:
44- DBG(1, "HNP: a_wait_bcon timeout; back to a_host\n");
45- musb_hnp_stop(musb);
46+ DBG(1, "HNP: %s timeout\n", otg_state_string(musb));
47+ musb_set_vbus(musb, 0);
48+ musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
49 break;
50 default:
51 DBG(1, "HNP: Unhandled mode %s\n", otg_state_string(musb));
52@@ -324,15 +326,12 @@ void musb_hnp_stop(struct musb *musb)
53 void __iomem *mbase = musb->mregs;
54 u8 reg;
55
56+ DBG(1, "HNP: stop from %s\n", otg_state_string(musb));
57+
58 switch (musb->xceiv->state) {
59 case OTG_STATE_A_PERIPHERAL:
60- case OTG_STATE_A_WAIT_VFALL:
61- case OTG_STATE_A_WAIT_BCON:
62- DBG(1, "HNP: Switching back to A-host\n");
63 musb_g_disconnect(musb);
64- musb->xceiv->state = OTG_STATE_A_IDLE;
65- MUSB_HST_MODE(musb);
66- musb->is_active = 0;
67+ DBG(1, "HNP: back to %s\n", otg_state_string(musb));
68 break;
69 case OTG_STATE_B_HOST:
70 DBG(1, "HNP: Disabling HR\n");
71@@ -775,7 +774,16 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
72 #endif /* HOST */
73 #ifdef CONFIG_USB_MUSB_OTG
74 case OTG_STATE_B_HOST:
75- musb_hnp_stop(musb);
76+ /* REVISIT this behaves for "real disconnect"
77+ * cases; make sure the other transitions from
78+ * from B_HOST act right too. The B_HOST code
79+ * in hnp_stop() is currently not used...
80+ */
81+ musb_root_disconnect(musb);
82+ musb_to_hcd(musb)->self.is_b_host = 0;
83+ musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
84+ MUSB_DEV_MODE(musb);
85+ musb_g_disconnect(musb);
86 break;
87 case OTG_STATE_A_PERIPHERAL:
88 musb_hnp_stop(musb);
89@@ -807,10 +815,19 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
90 switch (musb->xceiv->state) {
91 #ifdef CONFIG_USB_MUSB_OTG
92 case OTG_STATE_A_PERIPHERAL:
93- /*
94- * We cannot stop HNP here, devctl BDEVICE might be
95- * still set.
96+ /* We also come here if the cable is removed, since
97+ * this silicon doesn't report ID-no-longer-grounded.
98+ *
99+ * We depend on T(a_wait_bcon) to shut us down, and
100+ * hope users don't do anything dicey during this
101+ * undesired detour through A_WAIT_BCON.
102 */
103+ musb_hnp_stop(musb);
104+ usb_hcd_resume_root_hub(musb_to_hcd(musb));
105+ musb_root_disconnect(musb);
106+ musb_platform_try_idle(musb, jiffies
107+ + msecs_to_jiffies(musb->a_wait_bcon
108+ ? : OTG_TIME_A_WAIT_BCON));
109 break;
110 #endif
111 case OTG_STATE_B_PERIPHERAL:
112diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
113index 7dd3d59..8b3c4e2 100644
114--- a/drivers/usb/musb/musb_gadget.c
115+++ b/drivers/usb/musb/musb_gadget.c
116@@ -1962,9 +1962,11 @@ void musb_g_disconnect(struct musb *musb)
117 DBG(2, "Unhandled disconnect %s, setting a_idle\n",
118 otg_state_string(musb));
119 musb->xceiv->state = OTG_STATE_A_IDLE;
120+ MUSB_HST_MODE(musb);
121 break;
122 case OTG_STATE_A_PERIPHERAL:
123 musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
124+ MUSB_HST_MODE(musb);
125 break;
126 case OTG_STATE_B_WAIT_ACON:
127 case OTG_STATE_B_HOST:
128diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
129index 14f7cf3..e8ef925 100644
130--- a/drivers/usb/musb/musb_virthub.c
131+++ b/drivers/usb/musb/musb_virthub.c
132@@ -83,6 +83,10 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend)
133 musb->xceiv->state = OTG_STATE_A_SUSPEND;
134 musb->is_active = is_otg_enabled(musb)
135 && musb->xceiv->host->b_hnp_enable;
136+ if (musb->is_active)
137+ mod_timer(&musb->otg_timer, jiffies
138+ + msecs_to_jiffies(
139+ OTG_TIME_A_AIDL_BDIS));
140 musb_platform_try_idle(musb, 0);
141 break;
142 #ifdef CONFIG_USB_MUSB_OTG
143--
1441.6.0.4
145