diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2011-02-18 15:32:57 +0000 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2011-02-18 15:36:06 +0000 |
commit | 673abd92f999829bdd67d0273c43570a62123a63 (patch) | |
tree | 63132d1ffc1cb5bf50d244b184ca8d58a9cbc85c /meta/recipes-kernel/linux/linux-omap-2.6.29/musb | |
parent | fed61beb31c47e2d96af905a7047fe78d64c9bd0 (diff) | |
download | poky-673abd92f999829bdd67d0273c43570a62123a63.tar.gz |
conf/machine: Drop older machines with no recent updates
These are all moving to meta-extras. Ideally in the future machines
such as these will be maintained to topic specific layers as we move
to a more layer oriented model. If this causes a problem for anyone
please discuss it on the mailing list.
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap-2.6.29/musb')
29 files changed, 0 insertions, 4957 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0001-USB-musb-only-turn-off-vbus-in-OTG-hosts.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0001-USB-musb-only-turn-off-vbus-in-OTG-hosts.patch deleted file mode 100644 index a7898d1440..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0001-USB-musb-only-turn-off-vbus-in-OTG-hosts.patch +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | From a9199e8ab6d6fb105aa251d6bf2192e7eafac8ee Mon Sep 17 00:00:00 2001 | ||
2 | From: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org> | ||
3 | Date: Tue, 24 Mar 2009 17:22:53 -0700 | ||
4 | Subject: [PATCH] USB: musb: only turn off vbus in OTG hosts | ||
5 | |||
6 | Except on DaVinci, VBUS is now switched off as part of idling the | ||
7 | USB link (after a_wait_bcon) whenever a device is disconnected | ||
8 | from host. This is correct for OTG hosts, where either SRP or | ||
9 | an ID interrupt could turn VBUS on again. | ||
10 | |||
11 | However, for non-OTG hosts there's no way to turn VBUS on again, | ||
12 | so the host becomes unusable. And the procfs entry which once | ||
13 | allowed a manual workaround for this is now gone. | ||
14 | |||
15 | This patch adds an is_otg_enabled() check before scheduling the | ||
16 | switch-off timer in disconnect path, supporting a "classic host" | ||
17 | mode where SRP is unavailable. | ||
18 | |||
19 | [ dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: tweak patch description ] | ||
20 | |||
21 | Signed-off-by: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org> | ||
22 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
23 | Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org> | ||
24 | --- | ||
25 | drivers/usb/musb/musb_core.c | 2 +- | ||
26 | 1 files changed, 1 insertions(+), 1 deletions(-) | ||
27 | |||
28 | diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c | ||
29 | index af77e46..338cd16 100644 | ||
30 | --- a/drivers/usb/musb/musb_core.c | ||
31 | +++ b/drivers/usb/musb/musb_core.c | ||
32 | @@ -769,7 +769,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, | ||
33 | case OTG_STATE_A_SUSPEND: | ||
34 | usb_hcd_resume_root_hub(musb_to_hcd(musb)); | ||
35 | musb_root_disconnect(musb); | ||
36 | - if (musb->a_wait_bcon != 0) | ||
37 | + if (musb->a_wait_bcon != 0 && is_otg_enabled(musb)) | ||
38 | musb_platform_try_idle(musb, jiffies | ||
39 | + msecs_to_jiffies(musb->a_wait_bcon)); | ||
40 | break; | ||
41 | -- | ||
42 | 1.6.0.4 | ||
43 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0002-USB-composite-avoid-inconsistent-lock-state.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0002-USB-composite-avoid-inconsistent-lock-state.patch deleted file mode 100644 index 5cb7bcb065..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0002-USB-composite-avoid-inconsistent-lock-state.patch +++ /dev/null | |||
@@ -1,76 +0,0 @@ | |||
1 | From 83eb44b1c84f99d9a5c67612bd94b4ed7c43f64c Mon Sep 17 00:00:00 2001 | ||
2 | From: Felipe Balbi <felipe.balbi-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org> | ||
3 | Date: Tue, 24 Mar 2009 17:22:49 -0700 | ||
4 | Subject: [PATCH] USB: composite: avoid inconsistent lock state | ||
5 | |||
6 | Avoid the following INFO from lock debugging: | ||
7 | |||
8 | [ 369.126112] ================================= | ||
9 | [ 369.132063] [ INFO: inconsistent lock state ] | ||
10 | [ 369.136457] 2.6.28-maemo1 #1 | ||
11 | [ 369.139387] --------------------------------- | ||
12 | [ 369.143782] inconsistent {hardirq-on-W} -> {in-hardirq-W} usage. | ||
13 | [ 369.149855] swapper/0 [HC1[1]:SC0[0]:HE0:SE1] takes: | ||
14 | [ 369.154890] (&cdev->lock){+-..}, at: [<bf1979f0>] composite_disconnect+0x1c/0] | ||
15 | [ 369.163404] {hardirq-on-W} state was registered at: | ||
16 | [ 369.168348] [<c00788a8>] __lock_acquire+0x5d0/0x7d8 | ||
17 | [ 369.173506] [<c0078b14>] lock_acquire+0x64/0x78 | ||
18 | [ 369.178266] [<c0263a34>] _spin_lock+0x4c/0x80 | ||
19 | [ 369.182905] [<bf19597c>] usb_function_deactivate+0x20/0x70 [g_nokia] | ||
20 | [ 369.189527] [<bf1a0a88>] 0xbf1a0a88 | ||
21 | [ 369.193281] [<bf19f450>] 0xbf19f450 | ||
22 | [ 369.197004] [<bf19fa3c>] 0xbf19fa3c | ||
23 | [ 369.200758] [<bf1a03a0>] 0xbf1a03a0 | ||
24 | [ 369.204481] [<bf19f254>] 0xbf19f254 | ||
25 | [ 369.208204] [<bf1a0158>] 0xbf1a0158 | ||
26 | [ 369.211927] [<bf1a130c>] 0xbf1a130c | ||
27 | [ 369.215650] [<c01c21f0>] usb_gadget_register_driver+0x12c/0x28c | ||
28 | [ 369.221846] [<bf1a06bc>] 0xbf1a06bc | ||
29 | [ 369.225569] [<bf1a06e8>] 0xbf1a06e8 | ||
30 | [ 369.229322] [<c002c2dc>] __exception_text_end+0x64/0x19c | ||
31 | [ 369.234877] [<c0081628>] sys_init_module+0x9c/0x194 | ||
32 | [ 369.240004] [<c002c8e0>] ret_fast_syscall+0x0/0x2c | ||
33 | [ 369.245039] [<ffffffff>] 0xffffffff | ||
34 | [ 369.248793] irq event stamp: 218356 | ||
35 | [ 369.252302] hardirqs last enabled at (218355): [<c003a77c>] omap3_enter_idle+8 | ||
36 | [ 369.260420] hardirqs last disabled at (218356): [<c0264774>] __irq_svc+0x34/0x0 | ||
37 | [ 369.267927] softirqs last enabled at (218348): [<c00585a4>] __do_softirq+0x134 | ||
38 | [ 369.275892] softirqs last disabled at (218335): [<c005899c>] irq_exit+0x60/0xb0 | ||
39 | [ 369.283308] | ||
40 | [ 369.283308] other info that might help us debug this: | ||
41 | [ 369.289930] no locks held by swapper/0. | ||
42 | |||
43 | Cc: David Brownell <david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org> | ||
44 | Signed-off-by: Felipe Balbi <felipe.balbi-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org> | ||
45 | Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org> | ||
46 | --- | ||
47 | drivers/usb/gadget/composite.c | 5 +++-- | ||
48 | 1 files changed, 3 insertions(+), 2 deletions(-) | ||
49 | |||
50 | diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c | ||
51 | index 5d11c29..40f1da7 100644 | ||
52 | --- a/drivers/usb/gadget/composite.c | ||
53 | +++ b/drivers/usb/gadget/composite.c | ||
54 | @@ -149,16 +149,17 @@ done: | ||
55 | int usb_function_deactivate(struct usb_function *function) | ||
56 | { | ||
57 | struct usb_composite_dev *cdev = function->config->cdev; | ||
58 | + unsigned long flags; | ||
59 | int status = 0; | ||
60 | |||
61 | - spin_lock(&cdev->lock); | ||
62 | + spin_lock_irqsave(&cdev->lock, flags); | ||
63 | |||
64 | if (cdev->deactivations == 0) | ||
65 | status = usb_gadget_disconnect(cdev->gadget); | ||
66 | if (status == 0) | ||
67 | cdev->deactivations++; | ||
68 | |||
69 | - spin_unlock(&cdev->lock); | ||
70 | + spin_unlock_irqrestore(&cdev->lock, flags); | ||
71 | return status; | ||
72 | } | ||
73 | |||
74 | -- | ||
75 | 1.6.0.4 | ||
76 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0003-USB-musb-NAK-timeout-scheme-on-bulk-RX-endpoint.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0003-USB-musb-NAK-timeout-scheme-on-bulk-RX-endpoint.patch deleted file mode 100644 index fadad9e44a..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0003-USB-musb-NAK-timeout-scheme-on-bulk-RX-endpoint.patch +++ /dev/null | |||
@@ -1,218 +0,0 @@ | |||
1 | From ba7b26e69f4bb41f10be444c5fded853330f82b5 Mon Sep 17 00:00:00 2001 | ||
2 | From: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org> | ||
3 | Date: Tue, 24 Mar 2009 17:22:51 -0700 | ||
4 | Subject: [PATCH] USB: musb: NAK timeout scheme on bulk RX endpoint | ||
5 | |||
6 | Fixes endpoint starvation issue when more than one bulk QH is | ||
7 | multiplexed on the reserved bulk RX endpoint, which is normal | ||
8 | for cases like serial and ethernet adapters. | ||
9 | |||
10 | This patch sets the NAK timeout interval for such QHs, and when | ||
11 | a timeout triggers the next QH will be scheduled. (This resembles | ||
12 | the bulk scheduling done in hardware by EHCI, OHCI, and UHCI.) | ||
13 | |||
14 | This scheme doesn't work for devices which are connected to a | ||
15 | high to full speed tree (transaction translator) as there is | ||
16 | no NAK timeout interrupt from the musb controller from such | ||
17 | devices. | ||
18 | |||
19 | Tested with PIO, Inventra DMA, CPPI DMA. | ||
20 | |||
21 | [ dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: fold in start_urb() update; | ||
22 | clarify only for bulk RX; don't accidentally clear WZC bits ] | ||
23 | |||
24 | Signed-off-by: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org> | ||
25 | Cc: Felipe Balbi <felipe.balbi-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org> | ||
26 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
27 | Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org> | ||
28 | --- | ||
29 | drivers/usb/musb/musb_host.c | 112 ++++++++++++++++++++++++++++++++---------- | ||
30 | 1 files changed, 85 insertions(+), 27 deletions(-) | ||
31 | |||
32 | diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c | ||
33 | index 6dbbd07..bd1d5ae 100644 | ||
34 | --- a/drivers/usb/musb/musb_host.c | ||
35 | +++ b/drivers/usb/musb/musb_host.c | ||
36 | @@ -64,11 +64,8 @@ | ||
37 | * | ||
38 | * - DMA (Mentor/OMAP) ...has at least toggle update problems | ||
39 | * | ||
40 | - * - Still no traffic scheduling code to make NAKing for bulk or control | ||
41 | - * transfers unable to starve other requests; or to make efficient use | ||
42 | - * of hardware with periodic transfers. (Note that network drivers | ||
43 | - * commonly post bulk reads that stay pending for a long time; these | ||
44 | - * would make very visible trouble.) | ||
45 | + * - [23-feb-2009] minimal traffic scheduling to avoid bulk RX packet | ||
46 | + * starvation ... nothing yet for TX, interrupt, or bulk. | ||
47 | * | ||
48 | * - Not tested with HNP, but some SRP paths seem to behave. | ||
49 | * | ||
50 | @@ -88,11 +85,8 @@ | ||
51 | * | ||
52 | * CONTROL transfers all go through ep0. BULK ones go through dedicated IN | ||
53 | * and OUT endpoints ... hardware is dedicated for those "async" queue(s). | ||
54 | - * | ||
55 | * (Yes, bulk _could_ use more of the endpoints than that, and would even | ||
56 | - * benefit from it ... one remote device may easily be NAKing while others | ||
57 | - * need to perform transfers in that same direction. The same thing could | ||
58 | - * be done in software though, assuming dma cooperates.) | ||
59 | + * benefit from it.) | ||
60 | * | ||
61 | * INTERUPPT and ISOCHRONOUS transfers are scheduled to the other endpoints. | ||
62 | * So far that scheduling is both dumb and optimistic: the endpoint will be | ||
63 | @@ -201,8 +195,9 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) | ||
64 | len = urb->iso_frame_desc[0].length; | ||
65 | break; | ||
66 | default: /* bulk, interrupt */ | ||
67 | - buf = urb->transfer_buffer; | ||
68 | - len = urb->transfer_buffer_length; | ||
69 | + /* actual_length may be nonzero on retry paths */ | ||
70 | + buf = urb->transfer_buffer + urb->actual_length; | ||
71 | + len = urb->transfer_buffer_length - urb->actual_length; | ||
72 | } | ||
73 | |||
74 | DBG(4, "qh %p urb %p dev%d ep%d%s%s, hw_ep %d, %p/%d\n", | ||
75 | @@ -1045,7 +1040,8 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb) | ||
76 | |||
77 | /* NOTE: this code path would be a good place to PAUSE a | ||
78 | * control transfer, if another one is queued, so that | ||
79 | - * ep0 is more likely to stay busy. | ||
80 | + * ep0 is more likely to stay busy. That's already done | ||
81 | + * for bulk RX transfers. | ||
82 | * | ||
83 | * if (qh->ring.next != &musb->control), then | ||
84 | * we have a candidate... NAKing is *NOT* an error | ||
85 | @@ -1197,6 +1193,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) | ||
86 | /* NOTE: this code path would be a good place to PAUSE a | ||
87 | * transfer, if there's some other (nonperiodic) tx urb | ||
88 | * that could use this fifo. (dma complicates it...) | ||
89 | + * That's already done for bulk RX transfers. | ||
90 | * | ||
91 | * if (bulk && qh->ring.next != &musb->out_bulk), then | ||
92 | * we have a candidate... NAKing is *NOT* an error | ||
93 | @@ -1358,6 +1355,50 @@ finish: | ||
94 | |||
95 | #endif | ||
96 | |||
97 | +/* Schedule next QH from musb->in_bulk and move the current qh to | ||
98 | + * the end; avoids starvation for other endpoints. | ||
99 | + */ | ||
100 | +static void musb_bulk_rx_nak_timeout(struct musb *musb, struct musb_hw_ep *ep) | ||
101 | +{ | ||
102 | + struct dma_channel *dma; | ||
103 | + struct urb *urb; | ||
104 | + void __iomem *mbase = musb->mregs; | ||
105 | + void __iomem *epio = ep->regs; | ||
106 | + struct musb_qh *cur_qh, *next_qh; | ||
107 | + u16 rx_csr; | ||
108 | + | ||
109 | + musb_ep_select(mbase, ep->epnum); | ||
110 | + dma = is_dma_capable() ? ep->rx_channel : NULL; | ||
111 | + | ||
112 | + /* clear nak timeout bit */ | ||
113 | + rx_csr = musb_readw(epio, MUSB_RXCSR); | ||
114 | + rx_csr |= MUSB_RXCSR_H_WZC_BITS; | ||
115 | + rx_csr &= ~MUSB_RXCSR_DATAERROR; | ||
116 | + musb_writew(epio, MUSB_RXCSR, rx_csr); | ||
117 | + | ||
118 | + cur_qh = first_qh(&musb->in_bulk); | ||
119 | + if (cur_qh) { | ||
120 | + urb = next_urb(cur_qh); | ||
121 | + if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { | ||
122 | + dma->status = MUSB_DMA_STATUS_CORE_ABORT; | ||
123 | + musb->dma_controller->channel_abort(dma); | ||
124 | + urb->actual_length += dma->actual_len; | ||
125 | + dma->actual_len = 0L; | ||
126 | + } | ||
127 | + musb_save_toggle(ep, 1, urb); | ||
128 | + | ||
129 | + /* move cur_qh to end of queue */ | ||
130 | + list_move_tail(&cur_qh->ring, &musb->in_bulk); | ||
131 | + | ||
132 | + /* get the next qh from musb->in_bulk */ | ||
133 | + next_qh = first_qh(&musb->in_bulk); | ||
134 | + | ||
135 | + /* set rx_reinit and schedule the next qh */ | ||
136 | + ep->rx_reinit = 1; | ||
137 | + musb_start_urb(musb, 1, next_qh); | ||
138 | + } | ||
139 | +} | ||
140 | + | ||
141 | /* | ||
142 | * Service an RX interrupt for the given IN endpoint; docs cover bulk, iso, | ||
143 | * and high-bandwidth IN transfer cases. | ||
144 | @@ -1421,18 +1462,26 @@ void musb_host_rx(struct musb *musb, u8 epnum) | ||
145 | } else if (rx_csr & MUSB_RXCSR_DATAERROR) { | ||
146 | |||
147 | if (USB_ENDPOINT_XFER_ISOC != qh->type) { | ||
148 | - /* NOTE this code path would be a good place to PAUSE a | ||
149 | - * transfer, if there's some other (nonperiodic) rx urb | ||
150 | - * that could use this fifo. (dma complicates it...) | ||
151 | + DBG(6, "RX end %d NAK timeout\n", epnum); | ||
152 | + | ||
153 | + /* NOTE: NAKing is *NOT* an error, so we want to | ||
154 | + * continue. Except ... if there's a request for | ||
155 | + * another QH, use that instead of starving it. | ||
156 | * | ||
157 | - * if (bulk && qh->ring.next != &musb->in_bulk), then | ||
158 | - * we have a candidate... NAKing is *NOT* an error | ||
159 | + * Devices like Ethernet and serial adapters keep | ||
160 | + * reads posted at all times, which will starve | ||
161 | + * other devices without this logic. | ||
162 | */ | ||
163 | - DBG(6, "RX end %d NAK timeout\n", epnum); | ||
164 | + if (usb_pipebulk(urb->pipe) | ||
165 | + && qh->mux == 1 | ||
166 | + && !list_is_singular(&musb->in_bulk)) { | ||
167 | + musb_bulk_rx_nak_timeout(musb, hw_ep); | ||
168 | + return; | ||
169 | + } | ||
170 | musb_ep_select(mbase, epnum); | ||
171 | - musb_writew(epio, MUSB_RXCSR, | ||
172 | - MUSB_RXCSR_H_WZC_BITS | ||
173 | - | MUSB_RXCSR_H_REQPKT); | ||
174 | + rx_csr |= MUSB_RXCSR_H_WZC_BITS; | ||
175 | + rx_csr &= ~MUSB_RXCSR_DATAERROR; | ||
176 | + musb_writew(epio, MUSB_RXCSR, rx_csr); | ||
177 | |||
178 | goto finish; | ||
179 | } else { | ||
180 | @@ -1756,6 +1805,17 @@ static int musb_schedule( | ||
181 | head = &musb->in_bulk; | ||
182 | else | ||
183 | head = &musb->out_bulk; | ||
184 | + | ||
185 | + /* Enable bulk RX NAK timeout scheme when bulk requests are | ||
186 | + * multiplexed. This scheme doen't work in high speed to full | ||
187 | + * speed scenario as NAK interrupts are not coming from a | ||
188 | + * full speed device connected to a high speed device. | ||
189 | + * NAK timeout interval is 8 (128 uframe or 16ms) for HS and | ||
190 | + * 4 (8 frame or 8ms) for FS device. | ||
191 | + */ | ||
192 | + if (is_in && qh->dev) | ||
193 | + qh->intv_reg = | ||
194 | + (USB_SPEED_HIGH == qh->dev->speed) ? 8 : 4; | ||
195 | goto success; | ||
196 | } else if (best_end < 0) { | ||
197 | return -ENOSPC; | ||
198 | @@ -1888,13 +1948,11 @@ static int musb_urb_enqueue( | ||
199 | * | ||
200 | * The downside of disabling this is that transfer scheduling | ||
201 | * gets VERY unfair for nonperiodic transfers; a misbehaving | ||
202 | - * peripheral could make that hurt. Or for reads, one that's | ||
203 | - * perfectly normal: network and other drivers keep reads | ||
204 | - * posted at all times, having one pending for a week should | ||
205 | - * be perfectly safe. | ||
206 | + * peripheral could make that hurt. That's perfectly normal | ||
207 | + * for reads from network or serial adapters ... so we have | ||
208 | + * partial NAKlimit support for bulk RX. | ||
209 | * | ||
210 | - * The upside of disabling it is avoidng transfer scheduling | ||
211 | - * code to put this aside for while. | ||
212 | + * The upside of disabling it is simpler transfer scheduling. | ||
213 | */ | ||
214 | interval = 0; | ||
215 | } | ||
216 | -- | ||
217 | 1.6.0.4 | ||
218 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0004-USB-musb-rewrite-host-periodic-endpoint-allocation.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0004-USB-musb-rewrite-host-periodic-endpoint-allocation.patch deleted file mode 100644 index 438f11cf7a..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0004-USB-musb-rewrite-host-periodic-endpoint-allocation.patch +++ /dev/null | |||
@@ -1,106 +0,0 @@ | |||
1 | From 9ebf351bcd28a89a0b1ba8d0496fffbc72421611 Mon Sep 17 00:00:00 2001 | ||
2 | From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
3 | Date: Tue, 24 Mar 2009 17:22:50 -0700 | ||
4 | Subject: [PATCH] USB: musb: rewrite host periodic endpoint allocation | ||
5 | |||
6 | The current MUSB host code doesn't make use of all the available | ||
7 | FIFOs in for periodic transfers since it wrongly assumes the RX | ||
8 | and TX sides of any given hw_ep always share one FIFO. | ||
9 | |||
10 | Change: use 'in_qh' and 'out_qh' fields of the 'struct musb_hw_ep' | ||
11 | to check the endpoint's business; get rid of the now-unused 'periodic' | ||
12 | array in the 'struct musb'. Also optimize a loop induction variable | ||
13 | in the endpoint lookup code. | ||
14 | |||
15 | (Based on a previous patch from Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org>) | ||
16 | |||
17 | [ dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: clarify description and origin | ||
18 | of this fix; whitespace ] | ||
19 | |||
20 | Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
21 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
22 | Cc: Felipe Balbi <felipe.balbi-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org> | ||
23 | Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org> | ||
24 | --- | ||
25 | drivers/usb/musb/musb_core.h | 1 - | ||
26 | drivers/usb/musb/musb_host.c | 28 +++++++++++----------------- | ||
27 | 2 files changed, 11 insertions(+), 18 deletions(-) | ||
28 | |||
29 | diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h | ||
30 | index 630946a..adf1806 100644 | ||
31 | --- a/drivers/usb/musb/musb_core.h | ||
32 | +++ b/drivers/usb/musb/musb_core.h | ||
33 | @@ -331,7 +331,6 @@ struct musb { | ||
34 | struct list_head control; /* of musb_qh */ | ||
35 | struct list_head in_bulk; /* of musb_qh */ | ||
36 | struct list_head out_bulk; /* of musb_qh */ | ||
37 | - struct musb_qh *periodic[32]; /* tree of interrupt+iso */ | ||
38 | #endif | ||
39 | |||
40 | /* called with IRQs blocked; ON/nonzero implies starting a session, | ||
41 | diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c | ||
42 | index bd1d5ae..499c431 100644 | ||
43 | --- a/drivers/usb/musb/musb_host.c | ||
44 | +++ b/drivers/usb/musb/musb_host.c | ||
45 | @@ -390,7 +390,6 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) | ||
46 | * de-allocated if it's tracked and allocated; | ||
47 | * and where we'd update the schedule tree... | ||
48 | */ | ||
49 | - musb->periodic[ep->epnum] = NULL; | ||
50 | kfree(qh); | ||
51 | qh = NULL; | ||
52 | break; | ||
53 | @@ -1760,31 +1759,27 @@ static int musb_schedule( | ||
54 | |||
55 | /* else, periodic transfers get muxed to other endpoints */ | ||
56 | |||
57 | - /* FIXME this doesn't consider direction, so it can only | ||
58 | - * work for one half of the endpoint hardware, and assumes | ||
59 | - * the previous cases handled all non-shared endpoints... | ||
60 | - */ | ||
61 | - | ||
62 | - /* we know this qh hasn't been scheduled, so all we need to do | ||
63 | + /* | ||
64 | + * We know this qh hasn't been scheduled, so all we need to do | ||
65 | * is choose which hardware endpoint to put it on ... | ||
66 | * | ||
67 | * REVISIT what we really want here is a regular schedule tree | ||
68 | - * like e.g. OHCI uses, but for now musb->periodic is just an | ||
69 | - * array of the _single_ logical endpoint associated with a | ||
70 | - * given physical one (identity mapping logical->physical). | ||
71 | - * | ||
72 | - * that simplistic approach makes TT scheduling a lot simpler; | ||
73 | - * there is none, and thus none of its complexity... | ||
74 | + * like e.g. OHCI uses. | ||
75 | */ | ||
76 | best_diff = 4096; | ||
77 | best_end = -1; | ||
78 | |||
79 | - for (epnum = 1; epnum < musb->nr_endpoints; epnum++) { | ||
80 | + for (epnum = 1, hw_ep = musb->endpoints + 1; | ||
81 | + epnum < musb->nr_endpoints; | ||
82 | + epnum++, hw_ep++) { | ||
83 | int diff; | ||
84 | |||
85 | - if (musb->periodic[epnum]) | ||
86 | + if (is_in || hw_ep->is_shared_fifo) { | ||
87 | + if (hw_ep->in_qh != NULL) | ||
88 | + continue; | ||
89 | + } else if (hw_ep->out_qh != NULL) | ||
90 | continue; | ||
91 | - hw_ep = &musb->endpoints[epnum]; | ||
92 | + | ||
93 | if (hw_ep == musb->bulk_ep) | ||
94 | continue; | ||
95 | |||
96 | @@ -1824,7 +1819,6 @@ static int musb_schedule( | ||
97 | idle = 1; | ||
98 | qh->mux = 0; | ||
99 | hw_ep = musb->endpoints + best_end; | ||
100 | - musb->periodic[best_end] = qh; | ||
101 | DBG(4, "qh %p periodic slot %d\n", qh, best_end); | ||
102 | success: | ||
103 | if (head) { | ||
104 | -- | ||
105 | 1.6.0.4 | ||
106 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0005-USB-TWL-disable-VUSB-regulators-when-cable-unplugg.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0005-USB-TWL-disable-VUSB-regulators-when-cable-unplugg.patch deleted file mode 100644 index db3481b87b..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0005-USB-TWL-disable-VUSB-regulators-when-cable-unplugg.patch +++ /dev/null | |||
@@ -1,181 +0,0 @@ | |||
1 | From 60e7ce93befe795357db05001fe4caab522a421d Mon Sep 17 00:00:00 2001 | ||
2 | From: Jouni Hogander <jouni.hogander-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org> | ||
3 | Date: Tue, 24 Mar 2009 17:22:57 -0700 | ||
4 | Subject: [PATCH] USB: TWL: disable VUSB regulators when cable unplugged | ||
5 | |||
6 | This patch disables USB regulators VUSB1V5, VUSB1V8, and VUSB3V1 | ||
7 | when the USB cable is unplugged to reduce power consumption. | ||
8 | Added a depencency from twl4030 usb driver to TWL_REGULATOR. | ||
9 | |||
10 | Signed-off-by: Jouni Hogander <jouni.hogander-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org> | ||
11 | Signed-off-by: Kalle Jokiniemi <kalle.jokiniemi-sMOQStClEysAvxtiuMwx3w@public.gmane.org> | ||
12 | Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org> | ||
13 | --- | ||
14 | drivers/usb/otg/Kconfig | 2 +- | ||
15 | drivers/usb/otg/twl4030-usb.c | 73 ++++++++++++++++++++++++++++++++++++----- | ||
16 | 2 files changed, 65 insertions(+), 10 deletions(-) | ||
17 | |||
18 | diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig | ||
19 | index ee55b44..5790a5b 100644 | ||
20 | --- a/drivers/usb/otg/Kconfig | ||
21 | +++ b/drivers/usb/otg/Kconfig | ||
22 | @@ -43,7 +43,7 @@ config ISP1301_OMAP | ||
23 | |||
24 | config TWL4030_USB | ||
25 | tristate "TWL4030 USB Transceiver Driver" | ||
26 | - depends on TWL4030_CORE | ||
27 | + depends on TWL4030_CORE && REGULATOR_TWL4030 | ||
28 | select USB_OTG_UTILS | ||
29 | help | ||
30 | Enable this to support the USB OTG transceiver on TWL4030 | ||
31 | diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c | ||
32 | index 416e441..d9478d0 100644 | ||
33 | --- a/drivers/usb/otg/twl4030-usb.c | ||
34 | +++ b/drivers/usb/otg/twl4030-usb.c | ||
35 | @@ -34,6 +34,8 @@ | ||
36 | #include <linux/delay.h> | ||
37 | #include <linux/usb/otg.h> | ||
38 | #include <linux/i2c/twl4030.h> | ||
39 | +#include <linux/regulator/consumer.h> | ||
40 | +#include <linux/err.h> | ||
41 | |||
42 | |||
43 | /* Register defines */ | ||
44 | @@ -246,6 +248,11 @@ struct twl4030_usb { | ||
45 | struct otg_transceiver otg; | ||
46 | struct device *dev; | ||
47 | |||
48 | + /* TWL4030 internal USB regulator supplies */ | ||
49 | + struct regulator *usb1v5; | ||
50 | + struct regulator *usb1v8; | ||
51 | + struct regulator *usb3v1; | ||
52 | + | ||
53 | /* for vbus reporting with irqs disabled */ | ||
54 | spinlock_t lock; | ||
55 | |||
56 | @@ -434,6 +441,18 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) | ||
57 | |||
58 | pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); | ||
59 | if (on) { | ||
60 | + regulator_enable(twl->usb3v1); | ||
61 | + regulator_enable(twl->usb1v8); | ||
62 | + /* | ||
63 | + * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP | ||
64 | + * in twl4030) resets the VUSB_DEDICATED2 register. This reset | ||
65 | + * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to | ||
66 | + * SLEEP. We work around this by clearing the bit after usv3v1 | ||
67 | + * is re-activated. This ensures that VUSB3V1 is really active. | ||
68 | + */ | ||
69 | + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, | ||
70 | + VUSB_DEDICATED2); | ||
71 | + regulator_enable(twl->usb1v5); | ||
72 | pwr &= ~PHY_PWR_PHYPWD; | ||
73 | WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); | ||
74 | twl4030_usb_write(twl, PHY_CLK_CTRL, | ||
75 | @@ -443,6 +462,9 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) | ||
76 | } else { | ||
77 | pwr |= PHY_PWR_PHYPWD; | ||
78 | WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); | ||
79 | + regulator_disable(twl->usb1v5); | ||
80 | + regulator_disable(twl->usb1v8); | ||
81 | + regulator_disable(twl->usb3v1); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | @@ -468,7 +490,7 @@ static void twl4030_phy_resume(struct twl4030_usb *twl) | ||
86 | twl->asleep = 0; | ||
87 | } | ||
88 | |||
89 | -static void twl4030_usb_ldo_init(struct twl4030_usb *twl) | ||
90 | +static int twl4030_usb_ldo_init(struct twl4030_usb *twl) | ||
91 | { | ||
92 | /* Enable writing to power configuration registers */ | ||
93 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY); | ||
94 | @@ -480,20 +502,45 @@ static void twl4030_usb_ldo_init(struct twl4030_usb *twl) | ||
95 | /* input to VUSB3V1 LDO is from VBAT, not VBUS */ | ||
96 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); | ||
97 | |||
98 | - /* turn on 3.1V regulator */ | ||
99 | - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB3V1_DEV_GRP); | ||
100 | + /* Initialize 3.1V regulator */ | ||
101 | + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP); | ||
102 | + | ||
103 | + twl->usb3v1 = regulator_get(twl->dev, "usb3v1"); | ||
104 | + if (IS_ERR(twl->usb3v1)) | ||
105 | + return -ENODEV; | ||
106 | + | ||
107 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE); | ||
108 | |||
109 | - /* turn on 1.5V regulator */ | ||
110 | - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V5_DEV_GRP); | ||
111 | + /* Initialize 1.5V regulator */ | ||
112 | + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP); | ||
113 | + | ||
114 | + twl->usb1v5 = regulator_get(twl->dev, "usb1v5"); | ||
115 | + if (IS_ERR(twl->usb1v5)) | ||
116 | + goto fail1; | ||
117 | + | ||
118 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE); | ||
119 | |||
120 | - /* turn on 1.8V regulator */ | ||
121 | - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V8_DEV_GRP); | ||
122 | + /* Initialize 1.8V regulator */ | ||
123 | + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP); | ||
124 | + | ||
125 | + twl->usb1v8 = regulator_get(twl->dev, "usb1v8"); | ||
126 | + if (IS_ERR(twl->usb1v8)) | ||
127 | + goto fail2; | ||
128 | + | ||
129 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); | ||
130 | |||
131 | /* disable access to power configuration registers */ | ||
132 | twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY); | ||
133 | + | ||
134 | + return 0; | ||
135 | + | ||
136 | +fail2: | ||
137 | + regulator_put(twl->usb1v5); | ||
138 | + twl->usb1v5 = NULL; | ||
139 | +fail1: | ||
140 | + regulator_put(twl->usb3v1); | ||
141 | + twl->usb3v1 = NULL; | ||
142 | + return -ENODEV; | ||
143 | } | ||
144 | |||
145 | static ssize_t twl4030_usb_vbus_show(struct device *dev, | ||
146 | @@ -598,7 +645,7 @@ static int __init twl4030_usb_probe(struct platform_device *pdev) | ||
147 | { | ||
148 | struct twl4030_usb_data *pdata = pdev->dev.platform_data; | ||
149 | struct twl4030_usb *twl; | ||
150 | - int status; | ||
151 | + int status, err; | ||
152 | |||
153 | if (!pdata) { | ||
154 | dev_dbg(&pdev->dev, "platform_data not available\n"); | ||
155 | @@ -622,7 +669,12 @@ static int __init twl4030_usb_probe(struct platform_device *pdev) | ||
156 | /* init spinlock for workqueue */ | ||
157 | spin_lock_init(&twl->lock); | ||
158 | |||
159 | - twl4030_usb_ldo_init(twl); | ||
160 | + err = twl4030_usb_ldo_init(twl); | ||
161 | + if (err) { | ||
162 | + dev_err(&pdev->dev, "ldo init failed\n"); | ||
163 | + kfree(twl); | ||
164 | + return err; | ||
165 | + } | ||
166 | otg_set_transceiver(&twl->otg); | ||
167 | |||
168 | platform_set_drvdata(pdev, twl); | ||
169 | @@ -688,6 +740,9 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev) | ||
170 | twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); | ||
171 | |||
172 | twl4030_phy_power(twl, 0); | ||
173 | + regulator_put(twl->usb1v5); | ||
174 | + regulator_put(twl->usb1v8); | ||
175 | + regulator_put(twl->usb3v1); | ||
176 | |||
177 | kfree(twl); | ||
178 | |||
179 | -- | ||
180 | 1.6.0.4 | ||
181 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0006-USB-gadget-composite-device-level-suspend-resume-h.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0006-USB-gadget-composite-device-level-suspend-resume-h.patch deleted file mode 100644 index 3f49a4d636..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0006-USB-gadget-composite-device-level-suspend-resume-h.patch +++ /dev/null | |||
@@ -1,84 +0,0 @@ | |||
1 | From 7eef82d231578140c6000d04846a48bdaf341a65 Mon Sep 17 00:00:00 2001 | ||
2 | From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
3 | Date: Tue, 24 Mar 2009 17:23:19 -0700 | ||
4 | Subject: [PATCH] USB: gadget: composite device-level suspend/resume hooks | ||
5 | |||
6 | Address one open question in the composite gadget framework: | ||
7 | Yes, we should have device-level suspend/resume callbacks | ||
8 | in addition to the function-level ones. We have at least one | ||
9 | scenario (with gadget zero in OTG test mode) that's awkward | ||
10 | to handle without it. | ||
11 | |||
12 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
13 | Cc: Felipe Balbi <felipe.balbi-xNZwKgViW5gAvxtiuMwx3w@public.gmane.org> | ||
14 | Signed-off-by: Greg Kroah-Hartman <gregkh-l3A5Bk7waGM@public.gmane.org> | ||
15 | --- | ||
16 | drivers/usb/gadget/composite.c | 8 ++++++-- | ||
17 | include/linux/usb/composite.h | 8 ++++++++ | ||
18 | 2 files changed, 14 insertions(+), 2 deletions(-) | ||
19 | |||
20 | diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c | ||
21 | index 40f1da7..59e8523 100644 | ||
22 | --- a/drivers/usb/gadget/composite.c | ||
23 | +++ b/drivers/usb/gadget/composite.c | ||
24 | @@ -1014,7 +1014,7 @@ composite_suspend(struct usb_gadget *gadget) | ||
25 | struct usb_composite_dev *cdev = get_gadget_data(gadget); | ||
26 | struct usb_function *f; | ||
27 | |||
28 | - /* REVISIT: should we have config and device level | ||
29 | + /* REVISIT: should we have config level | ||
30 | * suspend/resume callbacks? | ||
31 | */ | ||
32 | DBG(cdev, "suspend\n"); | ||
33 | @@ -1024,6 +1024,8 @@ composite_suspend(struct usb_gadget *gadget) | ||
34 | f->suspend(f); | ||
35 | } | ||
36 | } | ||
37 | + if (composite->suspend) | ||
38 | + composite->suspend(cdev); | ||
39 | } | ||
40 | |||
41 | static void | ||
42 | @@ -1032,10 +1034,12 @@ composite_resume(struct usb_gadget *gadget) | ||
43 | struct usb_composite_dev *cdev = get_gadget_data(gadget); | ||
44 | struct usb_function *f; | ||
45 | |||
46 | - /* REVISIT: should we have config and device level | ||
47 | + /* REVISIT: should we have config level | ||
48 | * suspend/resume callbacks? | ||
49 | */ | ||
50 | DBG(cdev, "resume\n"); | ||
51 | + if (composite->resume) | ||
52 | + composite->resume(cdev); | ||
53 | if (cdev->config) { | ||
54 | list_for_each_entry(f, &cdev->config->functions, list) { | ||
55 | if (f->resume) | ||
56 | diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h | ||
57 | index 935c380..acd7b0f 100644 | ||
58 | --- a/include/linux/usb/composite.h | ||
59 | +++ b/include/linux/usb/composite.h | ||
60 | @@ -244,6 +244,10 @@ int usb_add_config(struct usb_composite_dev *, | ||
61 | * value; it should return zero on successful initialization. | ||
62 | * @unbind: Reverses @bind(); called as a side effect of unregistering | ||
63 | * this driver. | ||
64 | + * @suspend: Notifies when the host stops sending USB traffic, | ||
65 | + * after function notifications | ||
66 | + * @resume: Notifies configuration when the host restarts USB traffic, | ||
67 | + * before function notifications | ||
68 | * | ||
69 | * Devices default to reporting self powered operation. Devices which rely | ||
70 | * on bus powered operation should report this in their @bind() method. | ||
71 | @@ -268,6 +272,10 @@ struct usb_composite_driver { | ||
72 | |||
73 | int (*bind)(struct usb_composite_dev *); | ||
74 | int (*unbind)(struct usb_composite_dev *); | ||
75 | + | ||
76 | + /* global suspend hooks */ | ||
77 | + void (*suspend)(struct usb_composite_dev *); | ||
78 | + void (*resume)(struct usb_composite_dev *); | ||
79 | }; | ||
80 | |||
81 | extern int usb_composite_register(struct usb_composite_driver *); | ||
82 | -- | ||
83 | 1.6.0.4 | ||
84 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0007-usb-gadget-fix-ethernet-link-reports-to-ethtool.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0007-usb-gadget-fix-ethernet-link-reports-to-ethtool.patch deleted file mode 100644 index a89bc2ff5c..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0007-usb-gadget-fix-ethernet-link-reports-to-ethtool.patch +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
1 | From 00c4bd07a64061ec9ab9c35f5bf01ec6187138f4 Mon Sep 17 00:00:00 2001 | ||
2 | From: Jonathan McDowell <noodles-4QvXXjU8Dv4@public.gmane.org> | ||
3 | Date: Thu, 26 Mar 2009 00:45:27 -0700 | ||
4 | Subject: [PATCH] usb gadget: fix ethernet link reports to ethtool | ||
5 | |||
6 | The g_ether USB gadget driver currently decides whether or not there's a | ||
7 | link to report back for eth_get_link based on if the USB link speed is | ||
8 | set. The USB gadget speed is however often set even before the device is | ||
9 | enumerated. It seems more sensible to only report a "link" if we're | ||
10 | actually connected to a host that wants to talk to us. The patch below | ||
11 | does this for me - tested with the PXA27x UDC driver. | ||
12 | |||
13 | Signed-Off-By: Jonathan McDowell <noodles-4QvXXjU8Dv4@public.gmane.org> | ||
14 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
15 | --- | ||
16 | drivers/usb/gadget/u_ether.c | 8 +------- | ||
17 | 1 files changed, 1 insertions(+), 7 deletions(-) | ||
18 | |||
19 | diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c | ||
20 | index 96d65ca..4007770 100644 | ||
21 | --- a/drivers/usb/gadget/u_ether.c | ||
22 | +++ b/drivers/usb/gadget/u_ether.c | ||
23 | @@ -175,12 +175,6 @@ static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p) | ||
24 | strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof p->bus_info); | ||
25 | } | ||
26 | |||
27 | -static u32 eth_get_link(struct net_device *net) | ||
28 | -{ | ||
29 | - struct eth_dev *dev = netdev_priv(net); | ||
30 | - return dev->gadget->speed != USB_SPEED_UNKNOWN; | ||
31 | -} | ||
32 | - | ||
33 | /* REVISIT can also support: | ||
34 | * - WOL (by tracking suspends and issuing remote wakeup) | ||
35 | * - msglevel (implies updated messaging) | ||
36 | @@ -189,7 +183,7 @@ static u32 eth_get_link(struct net_device *net) | ||
37 | |||
38 | static struct ethtool_ops ops = { | ||
39 | .get_drvinfo = eth_get_drvinfo, | ||
40 | - .get_link = eth_get_link | ||
41 | + .get_link = ethtool_op_get_link, | ||
42 | }; | ||
43 | |||
44 | static void defer_kevent(struct eth_dev *dev, int flag) | ||
45 | -- | ||
46 | 1.6.0.4 | ||
47 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0008-usb-musb_host-minor-enqueue-locking-fix-v2.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0008-usb-musb_host-minor-enqueue-locking-fix-v2.patch deleted file mode 100644 index 8627825b5a..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0008-usb-musb_host-minor-enqueue-locking-fix-v2.patch +++ /dev/null | |||
@@ -1,60 +0,0 @@ | |||
1 | From c3b527a21104b6bb61558fba6c65aa80f63e0772 Mon Sep 17 00:00:00 2001 | ||
2 | From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
3 | Date: Thu, 26 Mar 2009 17:36:57 -0700 | ||
4 | Subject: [PATCH] usb: musb_host, minor enqueue locking fix (v2) | ||
5 | |||
6 | Someone noted that the enqueue path used an unlocked access | ||
7 | for usb_host_endpoint->hcpriv ... fix that, by being safe | ||
8 | and always accessing it under spinlock protection. | ||
9 | |||
10 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
11 | --- | ||
12 | drivers/usb/musb/musb_host.c | 17 ++++++++--------- | ||
13 | 1 files changed, 8 insertions(+), 9 deletions(-) | ||
14 | |||
15 | diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c | ||
16 | index 499c431..ff09595 100644 | ||
17 | --- a/drivers/usb/musb/musb_host.c | ||
18 | +++ b/drivers/usb/musb/musb_host.c | ||
19 | @@ -1841,7 +1841,7 @@ static int musb_urb_enqueue( | ||
20 | unsigned long flags; | ||
21 | struct musb *musb = hcd_to_musb(hcd); | ||
22 | struct usb_host_endpoint *hep = urb->ep; | ||
23 | - struct musb_qh *qh = hep->hcpriv; | ||
24 | + struct musb_qh *qh; | ||
25 | struct usb_endpoint_descriptor *epd = &hep->desc; | ||
26 | int ret; | ||
27 | unsigned type_reg; | ||
28 | @@ -1853,22 +1853,21 @@ static int musb_urb_enqueue( | ||
29 | |||
30 | spin_lock_irqsave(&musb->lock, flags); | ||
31 | ret = usb_hcd_link_urb_to_ep(hcd, urb); | ||
32 | + qh = ret ? NULL : hep->hcpriv; | ||
33 | + if (qh) | ||
34 | + urb->hcpriv = qh; | ||
35 | spin_unlock_irqrestore(&musb->lock, flags); | ||
36 | - if (ret) | ||
37 | - return ret; | ||
38 | |||
39 | /* DMA mapping was already done, if needed, and this urb is on | ||
40 | - * hep->urb_list ... so there's little to do unless hep wasn't | ||
41 | - * yet scheduled onto a live qh. | ||
42 | + * hep->urb_list now ... so we're done, unless hep wasn't yet | ||
43 | + * scheduled onto a live qh. | ||
44 | * | ||
45 | * REVISIT best to keep hep->hcpriv valid until the endpoint gets | ||
46 | * disabled, testing for empty qh->ring and avoiding qh setup costs | ||
47 | * except for the first urb queued after a config change. | ||
48 | */ | ||
49 | - if (qh) { | ||
50 | - urb->hcpriv = qh; | ||
51 | - return 0; | ||
52 | - } | ||
53 | + if (qh || ret) | ||
54 | + return ret; | ||
55 | |||
56 | /* Allocate and initialize qh, minimizing the work done each time | ||
57 | * hw_ep gets reprogrammed, or with irqs blocked. Then schedule it. | ||
58 | -- | ||
59 | 1.6.0.4 | ||
60 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0009-usb-musb_host-fix-ep0-fifo-flushing.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0009-usb-musb_host-fix-ep0-fifo-flushing.patch deleted file mode 100644 index 09fc0a17d0..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0009-usb-musb_host-fix-ep0-fifo-flushing.patch +++ /dev/null | |||
@@ -1,93 +0,0 @@ | |||
1 | From 48ce47b15bfd420982ee275c595a9139eb6fabf7 Mon Sep 17 00:00:00 2001 | ||
2 | From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
3 | Date: Thu, 26 Mar 2009 17:38:30 -0700 | ||
4 | Subject: [PATCH] usb: musb_host, fix ep0 fifo flushing | ||
5 | |||
6 | The MUSB host side can't share generic TX FIFO flush logic | ||
7 | with EP0; the EP0 TX status register bits are different | ||
8 | from those for other entpoints. | ||
9 | |||
10 | Resolve this issue by providing a new EP0-specific routine | ||
11 | to flush and reset the FIFO, which pays careful attention to | ||
12 | restrictions listed in the latest programmer's guide. This | ||
13 | gets rid of an open issue whereby the usbtest control write | ||
14 | test (#14) failed. | ||
15 | |||
16 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
17 | --- | ||
18 | drivers/usb/musb/musb_host.c | 38 +++++++++++++++++++++++++------------- | ||
19 | 1 files changed, 25 insertions(+), 13 deletions(-) | ||
20 | |||
21 | diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c | ||
22 | index ff09595..a5d75aa 100644 | ||
23 | --- a/drivers/usb/musb/musb_host.c | ||
24 | +++ b/drivers/usb/musb/musb_host.c | ||
25 | @@ -125,6 +125,29 @@ static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep) | ||
26 | } | ||
27 | } | ||
28 | |||
29 | +static void musb_h_ep0_flush_fifo(struct musb_hw_ep *ep) | ||
30 | +{ | ||
31 | + void __iomem *epio = ep->regs; | ||
32 | + u16 csr; | ||
33 | + int retries = 5; | ||
34 | + | ||
35 | + /* scrub any data left in the fifo */ | ||
36 | + do { | ||
37 | + csr = musb_readw(epio, MUSB_TXCSR); | ||
38 | + if (!(csr & (MUSB_CSR0_TXPKTRDY | MUSB_CSR0_RXPKTRDY))) | ||
39 | + break; | ||
40 | + musb_writew(epio, MUSB_TXCSR, MUSB_CSR0_FLUSHFIFO); | ||
41 | + csr = musb_readw(epio, MUSB_TXCSR); | ||
42 | + udelay(10); | ||
43 | + } while (--retries); | ||
44 | + | ||
45 | + WARN(!retries, "Could not flush host TX%d fifo: csr: %04x\n", | ||
46 | + ep->epnum, csr); | ||
47 | + | ||
48 | + /* and reset for the next transfer */ | ||
49 | + musb_writew(epio, MUSB_TXCSR, 0); | ||
50 | +} | ||
51 | + | ||
52 | /* | ||
53 | * Start transmit. Caller is responsible for locking shared resources. | ||
54 | * musb must be locked. | ||
55 | @@ -693,11 +716,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum, | ||
56 | musb_writew(epio, MUSB_TXCSR, csr); | ||
57 | csr = musb_readw(epio, MUSB_TXCSR); | ||
58 | } else { | ||
59 | - /* endpoint 0: just flush */ | ||
60 | - musb_writew(epio, MUSB_CSR0, | ||
61 | - csr | MUSB_CSR0_FLUSHFIFO); | ||
62 | - musb_writew(epio, MUSB_CSR0, | ||
63 | - csr | MUSB_CSR0_FLUSHFIFO); | ||
64 | + musb_h_ep0_flush_fifo(hw_ep); | ||
65 | } | ||
66 | |||
67 | /* target addr and (for multipoint) hub addr/port */ | ||
68 | @@ -1063,11 +1082,7 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb) | ||
69 | csr &= ~MUSB_CSR0_H_NAKTIMEOUT; | ||
70 | musb_writew(epio, MUSB_CSR0, csr); | ||
71 | } else { | ||
72 | - csr |= MUSB_CSR0_FLUSHFIFO; | ||
73 | - musb_writew(epio, MUSB_CSR0, csr); | ||
74 | - musb_writew(epio, MUSB_CSR0, csr); | ||
75 | - csr &= ~MUSB_CSR0_H_NAKTIMEOUT; | ||
76 | - musb_writew(epio, MUSB_CSR0, csr); | ||
77 | + musb_h_ep0_flush_fifo(hw_ep); | ||
78 | } | ||
79 | |||
80 | musb_writeb(epio, MUSB_NAKLIMIT0, 0); | ||
81 | @@ -1081,9 +1096,6 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb) | ||
82 | * SHOULD NEVER HAPPEN! */ | ||
83 | ERR("no URB for end 0\n"); | ||
84 | |||
85 | - musb_writew(epio, MUSB_CSR0, MUSB_CSR0_FLUSHFIFO); | ||
86 | - musb_writew(epio, MUSB_CSR0, MUSB_CSR0_FLUSHFIFO); | ||
87 | - musb_writew(epio, MUSB_CSR0, 0); | ||
88 | |||
89 | goto done; | ||
90 | } | ||
91 | -- | ||
92 | 1.6.0.4 | ||
93 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch deleted file mode 100644 index bcbe3bbe39..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0010-musb-sanitize-clearing-TXCSR-DMA-bits-take-2.patch +++ /dev/null | |||
@@ -1,361 +0,0 @@ | |||
1 | From c99f4a68268801a2e2ffbef9766c3ac89e4fb22c Mon Sep 17 00:00:00 2001 | ||
2 | From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
3 | Date: Thu, 26 Mar 2009 18:27:47 -0700 | ||
4 | Subject: [PATCH] musb: sanitize clearing TXCSR DMA bits (take 2) | ||
5 | |||
6 | The MUSB code clears TXCSR_DMAMODE incorrectly in several | ||
7 | places, either asserting that TXCSR_DMAENAB is clear (when | ||
8 | sometimes it isn't) or clearing both bits together. Recent | ||
9 | versions of the programmer's guide require DMAENAB to be | ||
10 | cleared first, although some older ones didn't. | ||
11 | |||
12 | Fix this and while at it: | ||
13 | |||
14 | - In musb_gadget::txstate(), stop clearing the AUTOSET | ||
15 | and DMAMODE bits for the CPPI case since they never | ||
16 | get set anyway (the former bit is reserved on DaVinci); | ||
17 | but do clear the DMAENAB bit on the DMA error path. | ||
18 | |||
19 | - In musb_host::musb_ep_program(), remove the duplicate | ||
20 | DMA controller specific code code clearing the TXCSR | ||
21 | previous state, add the code to clear TXCSR DMA bits | ||
22 | on the Inventra DMA error path, to replace such code | ||
23 | (executed late) on the PIO path. | ||
24 | |||
25 | - In musbhsdma::dma_channel_abort()/dma_controller_irq(), | ||
26 | add/use the 'offset' variable to avoid MUSB_EP_OFFSET() | ||
27 | invocations on every RXCSR/TXCSR access. | ||
28 | |||
29 | [dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: don't introduce CamelCase, | ||
30 | shrink diff] | ||
31 | |||
32 | Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
33 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
34 | --- | ||
35 | drivers/usb/musb/musb_gadget.c | 33 +++++++++++------ | ||
36 | drivers/usb/musb/musb_host.c | 79 ++++++++++++++++------------------------ | ||
37 | drivers/usb/musb/musbhsdma.c | 59 ++++++++++++++++++------------ | ||
38 | 3 files changed, 90 insertions(+), 81 deletions(-) | ||
39 | |||
40 | diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c | ||
41 | index c7ebd08..f79440c 100644 | ||
42 | --- a/drivers/usb/musb/musb_gadget.c | ||
43 | +++ b/drivers/usb/musb/musb_gadget.c | ||
44 | @@ -165,9 +165,15 @@ static void nuke(struct musb_ep *ep, const int status) | ||
45 | if (is_dma_capable() && ep->dma) { | ||
46 | struct dma_controller *c = ep->musb->dma_controller; | ||
47 | int value; | ||
48 | + | ||
49 | if (ep->is_in) { | ||
50 | + /* | ||
51 | + * The programming guide says that we must not clear | ||
52 | + * the DMAMODE bit before DMAENAB, so we only | ||
53 | + * clear it in the second write... | ||
54 | + */ | ||
55 | musb_writew(epio, MUSB_TXCSR, | ||
56 | - 0 | MUSB_TXCSR_FLUSHFIFO); | ||
57 | + MUSB_TXCSR_DMAMODE | MUSB_TXCSR_FLUSHFIFO); | ||
58 | musb_writew(epio, MUSB_TXCSR, | ||
59 | 0 | MUSB_TXCSR_FLUSHFIFO); | ||
60 | } else { | ||
61 | @@ -230,7 +236,7 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep) | ||
62 | | IN token(s) are recd from Host. | ||
63 | | -> DMA interrupt on completion | ||
64 | | calls TxAvail. | ||
65 | - | -> stop DMA, ~DmaEenab, | ||
66 | + | -> stop DMA, ~DMAENAB, | ||
67 | | -> set TxPktRdy for last short pkt or zlp | ||
68 | | -> Complete Request | ||
69 | | -> Continue next request (call txstate) | ||
70 | @@ -315,9 +321,17 @@ static void txstate(struct musb *musb, struct musb_request *req) | ||
71 | request->dma, request_size); | ||
72 | if (use_dma) { | ||
73 | if (musb_ep->dma->desired_mode == 0) { | ||
74 | - /* ASSERT: DMAENAB is clear */ | ||
75 | - csr &= ~(MUSB_TXCSR_AUTOSET | | ||
76 | - MUSB_TXCSR_DMAMODE); | ||
77 | + /* | ||
78 | + * We must not clear the DMAMODE bit | ||
79 | + * before the DMAENAB bit -- and the | ||
80 | + * latter doesn't always get cleared | ||
81 | + * before we get here... | ||
82 | + */ | ||
83 | + csr &= ~(MUSB_TXCSR_AUTOSET | ||
84 | + | MUSB_TXCSR_DMAENAB); | ||
85 | + musb_writew(epio, MUSB_TXCSR, csr | ||
86 | + | MUSB_TXCSR_P_WZC_BITS); | ||
87 | + csr &= ~MUSB_TXCSR_DMAMODE; | ||
88 | csr |= (MUSB_TXCSR_DMAENAB | | ||
89 | MUSB_TXCSR_MODE); | ||
90 | /* against programming guide */ | ||
91 | @@ -334,10 +348,7 @@ static void txstate(struct musb *musb, struct musb_request *req) | ||
92 | |||
93 | #elif defined(CONFIG_USB_TI_CPPI_DMA) | ||
94 | /* program endpoint CSR first, then setup DMA */ | ||
95 | - csr &= ~(MUSB_TXCSR_AUTOSET | ||
96 | - | MUSB_TXCSR_DMAMODE | ||
97 | - | MUSB_TXCSR_P_UNDERRUN | ||
98 | - | MUSB_TXCSR_TXPKTRDY); | ||
99 | + csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY); | ||
100 | csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_DMAENAB; | ||
101 | musb_writew(epio, MUSB_TXCSR, | ||
102 | (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN) | ||
103 | @@ -364,8 +375,8 @@ static void txstate(struct musb *musb, struct musb_request *req) | ||
104 | if (!use_dma) { | ||
105 | c->channel_release(musb_ep->dma); | ||
106 | musb_ep->dma = NULL; | ||
107 | - /* ASSERT: DMAENAB clear */ | ||
108 | - csr &= ~(MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE); | ||
109 | + csr &= ~MUSB_TXCSR_DMAENAB; | ||
110 | + musb_writew(epio, MUSB_TXCSR, csr); | ||
111 | /* invariant: prequest->buf is non-null */ | ||
112 | } | ||
113 | #elif defined(CONFIG_USB_TUSB_OMAP_DMA) | ||
114 | diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c | ||
115 | index a5d75aa..6591282 100644 | ||
116 | --- a/drivers/usb/musb/musb_host.c | ||
117 | +++ b/drivers/usb/musb/musb_host.c | ||
118 | @@ -590,10 +590,17 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep) | ||
119 | csr = musb_readw(ep->regs, MUSB_TXCSR); | ||
120 | if (csr & MUSB_TXCSR_MODE) { | ||
121 | musb_h_tx_flush_fifo(ep); | ||
122 | + csr = musb_readw(ep->regs, MUSB_TXCSR); | ||
123 | musb_writew(ep->regs, MUSB_TXCSR, | ||
124 | - MUSB_TXCSR_FRCDATATOG); | ||
125 | + csr | MUSB_TXCSR_FRCDATATOG); | ||
126 | } | ||
127 | - /* clear mode (and everything else) to enable Rx */ | ||
128 | + | ||
129 | + /* | ||
130 | + * Clear the MODE bit (and everything else) to enable Rx. | ||
131 | + * NOTE: we mustn't clear the DMAMODE bit before DMAENAB. | ||
132 | + */ | ||
133 | + if (csr & MUSB_TXCSR_DMAMODE) | ||
134 | + musb_writew(ep->regs, MUSB_TXCSR, MUSB_TXCSR_DMAMODE); | ||
135 | musb_writew(ep->regs, MUSB_TXCSR, 0); | ||
136 | |||
137 | /* scrub all previous state, clearing toggle */ | ||
138 | @@ -690,12 +697,17 @@ static void musb_ep_program(struct musb *musb, u8 epnum, | ||
139 | |||
140 | /* general endpoint setup */ | ||
141 | if (epnum) { | ||
142 | - /* ASSERT: TXCSR_DMAENAB was already cleared */ | ||
143 | - | ||
144 | /* flush all old state, set default */ | ||
145 | musb_h_tx_flush_fifo(hw_ep); | ||
146 | + | ||
147 | + /* | ||
148 | + * We must not clear the DMAMODE bit before or in | ||
149 | + * the same cycle with the DMAENAB bit, so we clear | ||
150 | + * the latter first... | ||
151 | + */ | ||
152 | csr &= ~(MUSB_TXCSR_H_NAKTIMEOUT | ||
153 | - | MUSB_TXCSR_DMAMODE | ||
154 | + | MUSB_TXCSR_AUTOSET | ||
155 | + | MUSB_TXCSR_DMAENAB | ||
156 | | MUSB_TXCSR_FRCDATATOG | ||
157 | | MUSB_TXCSR_H_RXSTALL | ||
158 | | MUSB_TXCSR_H_ERROR | ||
159 | @@ -703,16 +715,15 @@ static void musb_ep_program(struct musb *musb, u8 epnum, | ||
160 | ); | ||
161 | csr |= MUSB_TXCSR_MODE; | ||
162 | |||
163 | - if (usb_gettoggle(urb->dev, | ||
164 | - qh->epnum, 1)) | ||
165 | + if (usb_gettoggle(urb->dev, qh->epnum, 1)) | ||
166 | csr |= MUSB_TXCSR_H_WR_DATATOGGLE | ||
167 | | MUSB_TXCSR_H_DATATOGGLE; | ||
168 | else | ||
169 | csr |= MUSB_TXCSR_CLRDATATOG; | ||
170 | |||
171 | - /* twice in case of double packet buffering */ | ||
172 | musb_writew(epio, MUSB_TXCSR, csr); | ||
173 | /* REVISIT may need to clear FLUSHFIFO ... */ | ||
174 | + csr &= ~MUSB_TXCSR_DMAMODE; | ||
175 | musb_writew(epio, MUSB_TXCSR, csr); | ||
176 | csr = musb_readw(epio, MUSB_TXCSR); | ||
177 | } else { | ||
178 | @@ -755,34 +766,19 @@ static void musb_ep_program(struct musb *musb, u8 epnum, | ||
179 | |||
180 | #ifdef CONFIG_USB_INVENTRA_DMA | ||
181 | if (dma_channel) { | ||
182 | - | ||
183 | - /* clear previous state */ | ||
184 | - csr = musb_readw(epio, MUSB_TXCSR); | ||
185 | - csr &= ~(MUSB_TXCSR_AUTOSET | ||
186 | - | MUSB_TXCSR_DMAMODE | ||
187 | - | MUSB_TXCSR_DMAENAB); | ||
188 | - csr |= MUSB_TXCSR_MODE; | ||
189 | - musb_writew(epio, MUSB_TXCSR, | ||
190 | - csr | MUSB_TXCSR_MODE); | ||
191 | - | ||
192 | qh->segsize = min(len, dma_channel->max_len); | ||
193 | - | ||
194 | if (qh->segsize <= packet_sz) | ||
195 | dma_channel->desired_mode = 0; | ||
196 | else | ||
197 | dma_channel->desired_mode = 1; | ||
198 | |||
199 | - | ||
200 | if (dma_channel->desired_mode == 0) { | ||
201 | - csr &= ~(MUSB_TXCSR_AUTOSET | ||
202 | - | MUSB_TXCSR_DMAMODE); | ||
203 | + /* Against the programming guide */ | ||
204 | csr |= (MUSB_TXCSR_DMAENAB); | ||
205 | - /* against programming guide */ | ||
206 | } else | ||
207 | csr |= (MUSB_TXCSR_AUTOSET | ||
208 | | MUSB_TXCSR_DMAENAB | ||
209 | | MUSB_TXCSR_DMAMODE); | ||
210 | - | ||
211 | musb_writew(epio, MUSB_TXCSR, csr); | ||
212 | |||
213 | dma_ok = dma_controller->channel_program( | ||
214 | @@ -799,6 +795,17 @@ static void musb_ep_program(struct musb *musb, u8 epnum, | ||
215 | else | ||
216 | hw_ep->rx_channel = NULL; | ||
217 | dma_channel = NULL; | ||
218 | + | ||
219 | + /* | ||
220 | + * The programming guide says that we must | ||
221 | + * clear the DMAENAB bit before DMAMODE... | ||
222 | + */ | ||
223 | + csr = musb_readw(epio, MUSB_TXCSR); | ||
224 | + csr &= ~(MUSB_TXCSR_DMAENAB | ||
225 | + | MUSB_TXCSR_AUTOSET); | ||
226 | + musb_writew(epio, MUSB_TXCSR, csr); | ||
227 | + csr &= ~MUSB_TXCSR_DMAMODE; | ||
228 | + musb_writew(epio, MUSB_TXCSR, csr); | ||
229 | } | ||
230 | } | ||
231 | #endif | ||
232 | @@ -806,18 +813,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum, | ||
233 | /* candidate for DMA */ | ||
234 | if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) { | ||
235 | |||
236 | - /* program endpoint CSRs first, then setup DMA. | ||
237 | - * assume CPPI setup succeeds. | ||
238 | - * defer enabling dma. | ||
239 | - */ | ||
240 | - csr = musb_readw(epio, MUSB_TXCSR); | ||
241 | - csr &= ~(MUSB_TXCSR_AUTOSET | ||
242 | - | MUSB_TXCSR_DMAMODE | ||
243 | - | MUSB_TXCSR_DMAENAB); | ||
244 | - csr |= MUSB_TXCSR_MODE; | ||
245 | - musb_writew(epio, MUSB_TXCSR, | ||
246 | - csr | MUSB_TXCSR_MODE); | ||
247 | - | ||
248 | + /* Defer enabling DMA */ | ||
249 | dma_channel->actual_len = 0L; | ||
250 | qh->segsize = len; | ||
251 | |||
252 | @@ -846,20 +842,9 @@ static void musb_ep_program(struct musb *musb, u8 epnum, | ||
253 | } | ||
254 | |||
255 | if (load_count) { | ||
256 | - /* ASSERT: TXCSR_DMAENAB was already cleared */ | ||
257 | - | ||
258 | /* PIO to load FIFO */ | ||
259 | qh->segsize = load_count; | ||
260 | musb_write_fifo(hw_ep, load_count, buf); | ||
261 | - csr = musb_readw(epio, MUSB_TXCSR); | ||
262 | - csr &= ~(MUSB_TXCSR_DMAENAB | ||
263 | - | MUSB_TXCSR_DMAMODE | ||
264 | - | MUSB_TXCSR_AUTOSET); | ||
265 | - /* write CSR */ | ||
266 | - csr |= MUSB_TXCSR_MODE; | ||
267 | - | ||
268 | - if (epnum) | ||
269 | - musb_writew(epio, MUSB_TXCSR, csr); | ||
270 | } | ||
271 | |||
272 | /* re-enable interrupt */ | ||
273 | diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c | ||
274 | index 8662e9e..40709c3 100644 | ||
275 | --- a/drivers/usb/musb/musbhsdma.c | ||
276 | +++ b/drivers/usb/musb/musbhsdma.c | ||
277 | @@ -195,30 +195,32 @@ static int dma_channel_abort(struct dma_channel *channel) | ||
278 | void __iomem *mbase = musb_channel->controller->base; | ||
279 | |||
280 | u8 bchannel = musb_channel->idx; | ||
281 | + int offset; | ||
282 | u16 csr; | ||
283 | |||
284 | if (channel->status == MUSB_DMA_STATUS_BUSY) { | ||
285 | if (musb_channel->transmit) { | ||
286 | - | ||
287 | - csr = musb_readw(mbase, | ||
288 | - MUSB_EP_OFFSET(musb_channel->epnum, | ||
289 | - MUSB_TXCSR)); | ||
290 | - csr &= ~(MUSB_TXCSR_AUTOSET | | ||
291 | - MUSB_TXCSR_DMAENAB | | ||
292 | - MUSB_TXCSR_DMAMODE); | ||
293 | - musb_writew(mbase, | ||
294 | - MUSB_EP_OFFSET(musb_channel->epnum, MUSB_TXCSR), | ||
295 | - csr); | ||
296 | + offset = MUSB_EP_OFFSET(musb_channel->epnum, | ||
297 | + MUSB_TXCSR); | ||
298 | + | ||
299 | + /* | ||
300 | + * The programming guide says that we must clear | ||
301 | + * the DMAENAB bit before the DMAMODE bit... | ||
302 | + */ | ||
303 | + csr = musb_readw(mbase, offset); | ||
304 | + csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB); | ||
305 | + musb_writew(mbase, offset, csr); | ||
306 | + csr &= ~MUSB_TXCSR_DMAMODE; | ||
307 | + musb_writew(mbase, offset, csr); | ||
308 | } else { | ||
309 | - csr = musb_readw(mbase, | ||
310 | - MUSB_EP_OFFSET(musb_channel->epnum, | ||
311 | - MUSB_RXCSR)); | ||
312 | + offset = MUSB_EP_OFFSET(musb_channel->epnum, | ||
313 | + MUSB_RXCSR); | ||
314 | + | ||
315 | + csr = musb_readw(mbase, offset); | ||
316 | csr &= ~(MUSB_RXCSR_AUTOCLEAR | | ||
317 | MUSB_RXCSR_DMAENAB | | ||
318 | MUSB_RXCSR_DMAMODE); | ||
319 | - musb_writew(mbase, | ||
320 | - MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR), | ||
321 | - csr); | ||
322 | + musb_writew(mbase, offset, csr); | ||
323 | } | ||
324 | |||
325 | musb_writew(mbase, | ||
326 | @@ -296,14 +298,25 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) | ||
327 | && ((channel->desired_mode == 0) | ||
328 | || (channel->actual_len & | ||
329 | (musb_channel->max_packet_sz - 1))) | ||
330 | - ) { | ||
331 | + ) { | ||
332 | + u8 epnum = musb_channel->epnum; | ||
333 | + int offset = MUSB_EP_OFFSET(epnum, | ||
334 | + MUSB_TXCSR); | ||
335 | + u16 txcsr; | ||
336 | + | ||
337 | + /* | ||
338 | + * The programming guide says that we | ||
339 | + * must clear DMAENAB before DMAMODE. | ||
340 | + */ | ||
341 | + musb_ep_select(mbase, epnum); | ||
342 | + txcsr = musb_readw(mbase, offset); | ||
343 | + txcsr &= ~(MUSB_TXCSR_DMAENAB | ||
344 | + | MUSB_TXCSR_AUTOSET); | ||
345 | + musb_writew(mbase, offset, txcsr); | ||
346 | /* Send out the packet */ | ||
347 | - musb_ep_select(mbase, | ||
348 | - musb_channel->epnum); | ||
349 | - musb_writew(mbase, MUSB_EP_OFFSET( | ||
350 | - musb_channel->epnum, | ||
351 | - MUSB_TXCSR), | ||
352 | - MUSB_TXCSR_TXPKTRDY); | ||
353 | + txcsr &= ~MUSB_TXCSR_DMAMODE; | ||
354 | + txcsr |= MUSB_TXCSR_TXPKTRDY; | ||
355 | + musb_writew(mbase, offset, txcsr); | ||
356 | } else { | ||
357 | musb_dma_completion( | ||
358 | musb, | ||
359 | -- | ||
360 | 1.6.0.4 | ||
361 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch deleted file mode 100644 index 7d546e10b0..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0011-musb-fix-isochronous-TXDMA-take-2.patch +++ /dev/null | |||
@@ -1,417 +0,0 @@ | |||
1 | From 035cd4a26e9b1638b4b0419b98409026176563ca Mon Sep 17 00:00:00 2001 | ||
2 | From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
3 | Date: Thu, 26 Mar 2009 18:29:19 -0700 | ||
4 | Subject: [PATCH] musb: fix isochronous TXDMA (take 2) | ||
5 | |||
6 | Multi-frame isochronous TX URBs transfers in DMA mode never | ||
7 | complete with CPPI DMA because musb_host_tx() doesn't restart | ||
8 | DMA on the second frame, only emitting a debug message. | ||
9 | With Inventra DMA they complete, but in PIO mode. To fix: | ||
10 | |||
11 | - Factor out programming of the DMA transfer from | ||
12 | musb_ep_program() into musb_tx_dma_program(); | ||
13 | |||
14 | - Reorder the code at the end of musb_host_tx() to | ||
15 | facilitate the fallback to PIO iff DMA fails; | ||
16 | |||
17 | - Handle the buffer offset consistently for both | ||
18 | PIO and DMA modes; | ||
19 | |||
20 | - Add an argument to musb_ep_program() for the same | ||
21 | reason (it only worked correctly with non-zero | ||
22 | offset of the first frame in PIO mode); | ||
23 | |||
24 | - Set the completed isochronous frame descriptor's | ||
25 | 'actual_length' and 'status' fields correctly in | ||
26 | DMA mode. | ||
27 | |||
28 | Also, since CPPI reportedly doesn't like sending isochronous | ||
29 | packets in the RNDIS mode, change the criterion for this | ||
30 | mode to be used only for multi-packet transfers. (There's | ||
31 | no need for that mode in the single-packet case anyway.) | ||
32 | |||
33 | [ dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: split comment paragraph | ||
34 | into bullet list, shrink patch delta, style tweaks ] | ||
35 | |||
36 | Signed-off-by: Pavel Kiryukhin <pkiryukhin-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
37 | Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
38 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
39 | --- | ||
40 | drivers/usb/musb/cppi_dma.c | 1 + | ||
41 | drivers/usb/musb/musb_host.c | 227 +++++++++++++++++++----------------------- | ||
42 | 2 files changed, 105 insertions(+), 123 deletions(-) | ||
43 | |||
44 | diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c | ||
45 | index 569ef0f..ac7227c 100644 | ||
46 | --- a/drivers/usb/musb/cppi_dma.c | ||
47 | +++ b/drivers/usb/musb/cppi_dma.c | ||
48 | @@ -579,6 +579,7 @@ cppi_next_tx_segment(struct musb *musb, struct cppi_channel *tx) | ||
49 | * trigger the "send a ZLP?" confusion. | ||
50 | */ | ||
51 | rndis = (maxpacket & 0x3f) == 0 | ||
52 | + && length > maxpacket | ||
53 | && length < 0xffff | ||
54 | && (length % maxpacket) != 0; | ||
55 | |||
56 | diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c | ||
57 | index 6591282..f6e84a0 100644 | ||
58 | --- a/drivers/usb/musb/musb_host.c | ||
59 | +++ b/drivers/usb/musb/musb_host.c | ||
60 | @@ -96,8 +96,8 @@ | ||
61 | |||
62 | |||
63 | static void musb_ep_program(struct musb *musb, u8 epnum, | ||
64 | - struct urb *urb, unsigned int nOut, | ||
65 | - u8 *buf, u32 len); | ||
66 | + struct urb *urb, int is_out, | ||
67 | + u8 *buf, u32 offset, u32 len); | ||
68 | |||
69 | /* | ||
70 | * Clear TX fifo. Needed to avoid BABBLE errors. | ||
71 | @@ -189,9 +189,10 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) | ||
72 | { | ||
73 | u16 frame; | ||
74 | u32 len; | ||
75 | - void *buf; | ||
76 | void __iomem *mbase = musb->mregs; | ||
77 | struct urb *urb = next_urb(qh); | ||
78 | + void *buf = urb->transfer_buffer; | ||
79 | + u32 offset = 0; | ||
80 | struct musb_hw_ep *hw_ep = qh->hw_ep; | ||
81 | unsigned pipe = urb->pipe; | ||
82 | u8 address = usb_pipedevice(pipe); | ||
83 | @@ -214,7 +215,7 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) | ||
84 | case USB_ENDPOINT_XFER_ISOC: | ||
85 | qh->iso_idx = 0; | ||
86 | qh->frame = 0; | ||
87 | - buf = urb->transfer_buffer + urb->iso_frame_desc[0].offset; | ||
88 | + offset = urb->iso_frame_desc[0].offset; | ||
89 | len = urb->iso_frame_desc[0].length; | ||
90 | break; | ||
91 | default: /* bulk, interrupt */ | ||
92 | @@ -232,14 +233,14 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) | ||
93 | case USB_ENDPOINT_XFER_ISOC: s = "-iso"; break; | ||
94 | default: s = "-intr"; break; | ||
95 | }; s; }), | ||
96 | - epnum, buf, len); | ||
97 | + epnum, buf + offset, len); | ||
98 | |||
99 | /* Configure endpoint */ | ||
100 | if (is_in || hw_ep->is_shared_fifo) | ||
101 | hw_ep->in_qh = qh; | ||
102 | else | ||
103 | hw_ep->out_qh = qh; | ||
104 | - musb_ep_program(musb, epnum, urb, !is_in, buf, len); | ||
105 | + musb_ep_program(musb, epnum, urb, !is_in, buf, offset, len); | ||
106 | |||
107 | /* transmit may have more work: start it when it is time */ | ||
108 | if (is_in) | ||
109 | @@ -250,7 +251,6 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) | ||
110 | case USB_ENDPOINT_XFER_ISOC: | ||
111 | case USB_ENDPOINT_XFER_INT: | ||
112 | DBG(3, "check whether there's still time for periodic Tx\n"); | ||
113 | - qh->iso_idx = 0; | ||
114 | frame = musb_readw(mbase, MUSB_FRAME); | ||
115 | /* FIXME this doesn't implement that scheduling policy ... | ||
116 | * or handle framecounter wrapping | ||
117 | @@ -631,14 +631,68 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep) | ||
118 | ep->rx_reinit = 0; | ||
119 | } | ||
120 | |||
121 | +static bool musb_tx_dma_program(struct dma_controller *dma, | ||
122 | + struct musb_hw_ep *hw_ep, struct musb_qh *qh, | ||
123 | + struct urb *urb, u32 offset, u32 length) | ||
124 | +{ | ||
125 | + struct dma_channel *channel = hw_ep->tx_channel; | ||
126 | + void __iomem *epio = hw_ep->regs; | ||
127 | + u16 pkt_size = qh->maxpacket; | ||
128 | + u16 csr; | ||
129 | + u8 mode; | ||
130 | + | ||
131 | +#ifdef CONFIG_USB_INVENTRA_DMA | ||
132 | + if (length > channel->max_len) | ||
133 | + length = channel->max_len; | ||
134 | + | ||
135 | + csr = musb_readw(epio, MUSB_TXCSR); | ||
136 | + if (length > pkt_size) { | ||
137 | + mode = 1; | ||
138 | + csr |= MUSB_TXCSR_AUTOSET | ||
139 | + | MUSB_TXCSR_DMAMODE | ||
140 | + | MUSB_TXCSR_DMAENAB; | ||
141 | + } else { | ||
142 | + mode = 0; | ||
143 | + csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE); | ||
144 | + csr |= MUSB_TXCSR_DMAENAB; /* against programmer's guide */ | ||
145 | + } | ||
146 | + channel->desired_mode = mode; | ||
147 | + musb_writew(epio, MUSB_TXCSR, csr); | ||
148 | +#else | ||
149 | + if (!is_cppi_enabled() && !tusb_dma_omap()) | ||
150 | + return false; | ||
151 | + | ||
152 | + channel->actual_len = 0; | ||
153 | + | ||
154 | + /* | ||
155 | + * TX uses "RNDIS" mode automatically but needs help | ||
156 | + * to identify the zero-length-final-packet case. | ||
157 | + */ | ||
158 | + mode = (urb->transfer_flags & URB_ZERO_PACKET) ? 1 : 0; | ||
159 | +#endif | ||
160 | + | ||
161 | + qh->segsize = length; | ||
162 | + | ||
163 | + if (!dma->channel_program(channel, pkt_size, mode, | ||
164 | + urb->transfer_dma + offset, length)) { | ||
165 | + dma->channel_release(channel); | ||
166 | + hw_ep->tx_channel = NULL; | ||
167 | + | ||
168 | + csr = musb_readw(epio, MUSB_TXCSR); | ||
169 | + csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB); | ||
170 | + musb_writew(epio, MUSB_TXCSR, csr | MUSB_TXCSR_H_WZC_BITS); | ||
171 | + return false; | ||
172 | + } | ||
173 | + return true; | ||
174 | +} | ||
175 | |||
176 | /* | ||
177 | * Program an HDRC endpoint as per the given URB | ||
178 | * Context: irqs blocked, controller lock held | ||
179 | */ | ||
180 | static void musb_ep_program(struct musb *musb, u8 epnum, | ||
181 | - struct urb *urb, unsigned int is_out, | ||
182 | - u8 *buf, u32 len) | ||
183 | + struct urb *urb, int is_out, | ||
184 | + u8 *buf, u32 offset, u32 len) | ||
185 | { | ||
186 | struct dma_controller *dma_controller; | ||
187 | struct dma_channel *dma_channel; | ||
188 | @@ -764,82 +818,9 @@ static void musb_ep_program(struct musb *musb, u8 epnum, | ||
189 | else | ||
190 | load_count = min((u32) packet_sz, len); | ||
191 | |||
192 | -#ifdef CONFIG_USB_INVENTRA_DMA | ||
193 | - if (dma_channel) { | ||
194 | - qh->segsize = min(len, dma_channel->max_len); | ||
195 | - if (qh->segsize <= packet_sz) | ||
196 | - dma_channel->desired_mode = 0; | ||
197 | - else | ||
198 | - dma_channel->desired_mode = 1; | ||
199 | - | ||
200 | - if (dma_channel->desired_mode == 0) { | ||
201 | - /* Against the programming guide */ | ||
202 | - csr |= (MUSB_TXCSR_DMAENAB); | ||
203 | - } else | ||
204 | - csr |= (MUSB_TXCSR_AUTOSET | ||
205 | - | MUSB_TXCSR_DMAENAB | ||
206 | - | MUSB_TXCSR_DMAMODE); | ||
207 | - musb_writew(epio, MUSB_TXCSR, csr); | ||
208 | - | ||
209 | - dma_ok = dma_controller->channel_program( | ||
210 | - dma_channel, packet_sz, | ||
211 | - dma_channel->desired_mode, | ||
212 | - urb->transfer_dma, | ||
213 | - qh->segsize); | ||
214 | - if (dma_ok) { | ||
215 | - load_count = 0; | ||
216 | - } else { | ||
217 | - dma_controller->channel_release(dma_channel); | ||
218 | - if (is_out) | ||
219 | - hw_ep->tx_channel = NULL; | ||
220 | - else | ||
221 | - hw_ep->rx_channel = NULL; | ||
222 | - dma_channel = NULL; | ||
223 | - | ||
224 | - /* | ||
225 | - * The programming guide says that we must | ||
226 | - * clear the DMAENAB bit before DMAMODE... | ||
227 | - */ | ||
228 | - csr = musb_readw(epio, MUSB_TXCSR); | ||
229 | - csr &= ~(MUSB_TXCSR_DMAENAB | ||
230 | - | MUSB_TXCSR_AUTOSET); | ||
231 | - musb_writew(epio, MUSB_TXCSR, csr); | ||
232 | - csr &= ~MUSB_TXCSR_DMAMODE; | ||
233 | - musb_writew(epio, MUSB_TXCSR, csr); | ||
234 | - } | ||
235 | - } | ||
236 | -#endif | ||
237 | - | ||
238 | - /* candidate for DMA */ | ||
239 | - if ((is_cppi_enabled() || tusb_dma_omap()) && dma_channel) { | ||
240 | - | ||
241 | - /* Defer enabling DMA */ | ||
242 | - dma_channel->actual_len = 0L; | ||
243 | - qh->segsize = len; | ||
244 | - | ||
245 | - /* TX uses "rndis" mode automatically, but needs help | ||
246 | - * to identify the zero-length-final-packet case. | ||
247 | - */ | ||
248 | - dma_ok = dma_controller->channel_program( | ||
249 | - dma_channel, packet_sz, | ||
250 | - (urb->transfer_flags | ||
251 | - & URB_ZERO_PACKET) | ||
252 | - == URB_ZERO_PACKET, | ||
253 | - urb->transfer_dma, | ||
254 | - qh->segsize); | ||
255 | - if (dma_ok) { | ||
256 | - load_count = 0; | ||
257 | - } else { | ||
258 | - dma_controller->channel_release(dma_channel); | ||
259 | - hw_ep->tx_channel = NULL; | ||
260 | - dma_channel = NULL; | ||
261 | - | ||
262 | - /* REVISIT there's an error path here that | ||
263 | - * needs handling: can't do dma, but | ||
264 | - * there's no pio buffer address... | ||
265 | - */ | ||
266 | - } | ||
267 | - } | ||
268 | + if (dma_channel && musb_tx_dma_program(dma_controller, | ||
269 | + hw_ep, qh, urb, offset, len)) | ||
270 | + load_count = 0; | ||
271 | |||
272 | if (load_count) { | ||
273 | /* PIO to load FIFO */ | ||
274 | @@ -899,7 +880,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum, | ||
275 | dma_channel, packet_sz, | ||
276 | !(urb->transfer_flags | ||
277 | & URB_SHORT_NOT_OK), | ||
278 | - urb->transfer_dma, | ||
279 | + urb->transfer_dma + offset, | ||
280 | qh->segsize); | ||
281 | if (!dma_ok) { | ||
282 | dma_controller->channel_release( | ||
283 | @@ -1142,8 +1123,8 @@ void musb_host_tx(struct musb *musb, u8 epnum) | ||
284 | int pipe; | ||
285 | bool done = false; | ||
286 | u16 tx_csr; | ||
287 | - size_t wLength = 0; | ||
288 | - u8 *buf = NULL; | ||
289 | + size_t length = 0; | ||
290 | + size_t offset = 0; | ||
291 | struct urb *urb; | ||
292 | struct musb_hw_ep *hw_ep = musb->endpoints + epnum; | ||
293 | void __iomem *epio = hw_ep->regs; | ||
294 | @@ -1161,7 +1142,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) | ||
295 | /* with CPPI, DMA sometimes triggers "extra" irqs */ | ||
296 | if (!urb) { | ||
297 | DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr); | ||
298 | - goto finish; | ||
299 | + return; | ||
300 | } | ||
301 | |||
302 | pipe = urb->pipe; | ||
303 | @@ -1198,7 +1179,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) | ||
304 | musb_writew(epio, MUSB_TXCSR, | ||
305 | MUSB_TXCSR_H_WZC_BITS | ||
306 | | MUSB_TXCSR_TXPKTRDY); | ||
307 | - goto finish; | ||
308 | + return; | ||
309 | } | ||
310 | |||
311 | if (status) { | ||
312 | @@ -1230,29 +1211,28 @@ void musb_host_tx(struct musb *musb, u8 epnum) | ||
313 | /* second cppi case */ | ||
314 | if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { | ||
315 | DBG(4, "extra TX%d ready, csr %04x\n", epnum, tx_csr); | ||
316 | - goto finish; | ||
317 | - | ||
318 | + return; | ||
319 | } | ||
320 | |||
321 | - /* REVISIT this looks wrong... */ | ||
322 | if (!status || dma || usb_pipeisoc(pipe)) { | ||
323 | if (dma) | ||
324 | - wLength = dma->actual_len; | ||
325 | + length = dma->actual_len; | ||
326 | else | ||
327 | - wLength = qh->segsize; | ||
328 | - qh->offset += wLength; | ||
329 | + length = qh->segsize; | ||
330 | + qh->offset += length; | ||
331 | |||
332 | if (usb_pipeisoc(pipe)) { | ||
333 | struct usb_iso_packet_descriptor *d; | ||
334 | |||
335 | d = urb->iso_frame_desc + qh->iso_idx; | ||
336 | - d->actual_length = qh->segsize; | ||
337 | + d->actual_length = length; | ||
338 | + d->status = status; | ||
339 | if (++qh->iso_idx >= urb->number_of_packets) { | ||
340 | done = true; | ||
341 | } else { | ||
342 | d++; | ||
343 | - buf = urb->transfer_buffer + d->offset; | ||
344 | - wLength = d->length; | ||
345 | + offset = d->offset; | ||
346 | + length = d->length; | ||
347 | } | ||
348 | } else if (dma) { | ||
349 | done = true; | ||
350 | @@ -1265,10 +1245,8 @@ void musb_host_tx(struct musb *musb, u8 epnum) | ||
351 | & URB_ZERO_PACKET)) | ||
352 | done = true; | ||
353 | if (!done) { | ||
354 | - buf = urb->transfer_buffer | ||
355 | - + qh->offset; | ||
356 | - wLength = urb->transfer_buffer_length | ||
357 | - - qh->offset; | ||
358 | + offset = qh->offset; | ||
359 | + length = urb->transfer_buffer_length - offset; | ||
360 | } | ||
361 | } | ||
362 | } | ||
363 | @@ -1287,28 +1265,31 @@ void musb_host_tx(struct musb *musb, u8 epnum) | ||
364 | urb->status = status; | ||
365 | urb->actual_length = qh->offset; | ||
366 | musb_advance_schedule(musb, urb, hw_ep, USB_DIR_OUT); | ||
367 | + return; | ||
368 | + } else if (usb_pipeisoc(pipe) && dma) { | ||
369 | + if (musb_tx_dma_program(musb->dma_controller, hw_ep, qh, urb, | ||
370 | + offset, length)) | ||
371 | + return; | ||
372 | + } else if (tx_csr & MUSB_TXCSR_DMAENAB) { | ||
373 | + DBG(1, "not complete, but DMA enabled?\n"); | ||
374 | + return; | ||
375 | + } | ||
376 | |||
377 | - } else if (!(tx_csr & MUSB_TXCSR_DMAENAB)) { | ||
378 | - /* WARN_ON(!buf); */ | ||
379 | - | ||
380 | - /* REVISIT: some docs say that when hw_ep->tx_double_buffered, | ||
381 | - * (and presumably, fifo is not half-full) we should write TWO | ||
382 | - * packets before updating TXCSR ... other docs disagree ... | ||
383 | - */ | ||
384 | - /* PIO: start next packet in this URB */ | ||
385 | - if (wLength > qh->maxpacket) | ||
386 | - wLength = qh->maxpacket; | ||
387 | - musb_write_fifo(hw_ep, wLength, buf); | ||
388 | - qh->segsize = wLength; | ||
389 | - | ||
390 | - musb_ep_select(mbase, epnum); | ||
391 | - musb_writew(epio, MUSB_TXCSR, | ||
392 | - MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY); | ||
393 | - } else | ||
394 | - DBG(1, "not complete, but dma enabled?\n"); | ||
395 | + /* | ||
396 | + * PIO: start next packet in this URB. | ||
397 | + * | ||
398 | + * REVISIT: some docs say that when hw_ep->tx_double_buffered, | ||
399 | + * (and presumably, FIFO is not half-full) we should write *two* | ||
400 | + * packets before updating TXCSR; other docs disagree... | ||
401 | + */ | ||
402 | + if (length > qh->maxpacket) | ||
403 | + length = qh->maxpacket; | ||
404 | + musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset); | ||
405 | + qh->segsize = length; | ||
406 | |||
407 | -finish: | ||
408 | - return; | ||
409 | + musb_ep_select(mbase, epnum); | ||
410 | + musb_writew(epio, MUSB_TXCSR, | ||
411 | + MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY); | ||
412 | } | ||
413 | |||
414 | |||
415 | -- | ||
416 | 1.6.0.4 | ||
417 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0012-musb-fix-possible-panic-while-resuming.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0012-musb-fix-possible-panic-while-resuming.patch deleted file mode 100644 index 2bbde84c16..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0012-musb-fix-possible-panic-while-resuming.patch +++ /dev/null | |||
@@ -1,56 +0,0 @@ | |||
1 | From b9a61b80ea89d9d6d78a23d96a28df94fd612298 Mon Sep 17 00:00:00 2001 | ||
2 | From: Kim Kyuwon <q1.kim-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> | ||
3 | Date: Thu, 26 Mar 2009 18:56:51 -0700 | ||
4 | Subject: [PATCH] musb: fix possible panic while resuming | ||
5 | |||
6 | During driver resume processing, musb could cause a kernel panic. | ||
7 | Fix by enabling the clock earlier, with the resume_early method. | ||
8 | |||
9 | Signed-off-by: Kim Kyuwon <q1.kim-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> | ||
10 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
11 | --- | ||
12 | drivers/usb/musb/musb_core.c | 8 ++------ | ||
13 | 1 files changed, 2 insertions(+), 6 deletions(-) | ||
14 | |||
15 | diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c | ||
16 | index 338cd16..3019725 100644 | ||
17 | --- a/drivers/usb/musb/musb_core.c | ||
18 | +++ b/drivers/usb/musb/musb_core.c | ||
19 | @@ -2170,16 +2170,13 @@ static int musb_suspend(struct platform_device *pdev, pm_message_t message) | ||
20 | return 0; | ||
21 | } | ||
22 | |||
23 | -static int musb_resume(struct platform_device *pdev) | ||
24 | +static int musb_resume_early(struct platform_device *pdev) | ||
25 | { | ||
26 | - unsigned long flags; | ||
27 | struct musb *musb = dev_to_musb(&pdev->dev); | ||
28 | |||
29 | if (!musb->clock) | ||
30 | return 0; | ||
31 | |||
32 | - spin_lock_irqsave(&musb->lock, flags); | ||
33 | - | ||
34 | if (musb->set_clock) | ||
35 | musb->set_clock(musb->clock, 1); | ||
36 | else | ||
37 | @@ -2189,7 +2186,6 @@ static int musb_resume(struct platform_device *pdev) | ||
38 | * unless for some reason the whole soc powered down and we're | ||
39 | * not treating that as a whole-system restart (e.g. swsusp) | ||
40 | */ | ||
41 | - spin_unlock_irqrestore(&musb->lock, flags); | ||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | @@ -2207,7 +2203,7 @@ static struct platform_driver musb_driver = { | ||
46 | .remove = __devexit_p(musb_remove), | ||
47 | .shutdown = musb_shutdown, | ||
48 | .suspend = musb_suspend, | ||
49 | - .resume = musb_resume, | ||
50 | + .resume_early = musb_resume_early, | ||
51 | }; | ||
52 | |||
53 | /*-------------------------------------------------------------------------*/ | ||
54 | -- | ||
55 | 1.6.0.4 | ||
56 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0013-musb_host-refactor-musb_save_toggle-take-2.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0013-musb_host-refactor-musb_save_toggle-take-2.patch deleted file mode 100644 index 0202871d41..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0013-musb_host-refactor-musb_save_toggle-take-2.patch +++ /dev/null | |||
@@ -1,91 +0,0 @@ | |||
1 | From 2658f7c9029967501cd4d749364f2e02d02eebd5 Mon Sep 17 00:00:00 2001 | ||
2 | From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
3 | Date: Fri, 27 Mar 2009 12:54:21 -0700 | ||
4 | Subject: [PATCH] musb_host: refactor musb_save_toggle() (take 2) | ||
5 | |||
6 | Refactor musb_save_toggle() as follows: | ||
7 | |||
8 | - replace 'struct musb_hw_ep *ep' parameter by 'struct | ||
9 | musb_qh *qh' to avoid re-calculating this value | ||
10 | |||
11 | - move usb_settogle() call out of the *if* operator. | ||
12 | |||
13 | This is a net minor shrink of source and object code. | ||
14 | |||
15 | Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
16 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
17 | --- | ||
18 | drivers/usb/musb/musb_host.c | 35 ++++++++++++----------------------- | ||
19 | 1 files changed, 12 insertions(+), 23 deletions(-) | ||
20 | |||
21 | diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c | ||
22 | index f6e84a0..dc32ce4 100644 | ||
23 | --- a/drivers/usb/musb/musb_host.c | ||
24 | +++ b/drivers/usb/musb/musb_host.c | ||
25 | @@ -318,35 +318,24 @@ __acquires(musb->lock) | ||
26 | spin_lock(&musb->lock); | ||
27 | } | ||
28 | |||
29 | -/* for bulk/interrupt endpoints only */ | ||
30 | -static inline void | ||
31 | -musb_save_toggle(struct musb_hw_ep *ep, int is_in, struct urb *urb) | ||
32 | +/* For bulk/interrupt endpoints only */ | ||
33 | +static inline void musb_save_toggle(struct musb_qh *qh, int is_in, | ||
34 | + struct urb *urb) | ||
35 | { | ||
36 | - struct usb_device *udev = urb->dev; | ||
37 | + void __iomem *epio = qh->hw_ep->regs; | ||
38 | u16 csr; | ||
39 | - void __iomem *epio = ep->regs; | ||
40 | - struct musb_qh *qh; | ||
41 | |||
42 | - /* FIXME: the current Mentor DMA code seems to have | ||
43 | + /* | ||
44 | + * FIXME: the current Mentor DMA code seems to have | ||
45 | * problems getting toggle correct. | ||
46 | */ | ||
47 | |||
48 | - if (is_in || ep->is_shared_fifo) | ||
49 | - qh = ep->in_qh; | ||
50 | + if (is_in) | ||
51 | + csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE; | ||
52 | else | ||
53 | - qh = ep->out_qh; | ||
54 | + csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE; | ||
55 | |||
56 | - if (!is_in) { | ||
57 | - csr = musb_readw(epio, MUSB_TXCSR); | ||
58 | - usb_settoggle(udev, qh->epnum, 1, | ||
59 | - (csr & MUSB_TXCSR_H_DATATOGGLE) | ||
60 | - ? 1 : 0); | ||
61 | - } else { | ||
62 | - csr = musb_readw(epio, MUSB_RXCSR); | ||
63 | - usb_settoggle(udev, qh->epnum, 0, | ||
64 | - (csr & MUSB_RXCSR_H_DATATOGGLE) | ||
65 | - ? 1 : 0); | ||
66 | - } | ||
67 | + usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0); | ||
68 | } | ||
69 | |||
70 | /* caller owns controller lock, irqs are blocked */ | ||
71 | @@ -362,7 +351,7 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) | ||
72 | switch (qh->type) { | ||
73 | case USB_ENDPOINT_XFER_BULK: | ||
74 | case USB_ENDPOINT_XFER_INT: | ||
75 | - musb_save_toggle(ep, is_in, urb); | ||
76 | + musb_save_toggle(qh, is_in, urb); | ||
77 | break; | ||
78 | case USB_ENDPOINT_XFER_ISOC: | ||
79 | if (status == 0 && urb->error_count) | ||
80 | @@ -1362,7 +1351,7 @@ static void musb_bulk_rx_nak_timeout(struct musb *musb, struct musb_hw_ep *ep) | ||
81 | urb->actual_length += dma->actual_len; | ||
82 | dma->actual_len = 0L; | ||
83 | } | ||
84 | - musb_save_toggle(ep, 1, urb); | ||
85 | + musb_save_toggle(cur_qh, 1, urb); | ||
86 | |||
87 | /* move cur_qh to end of queue */ | ||
88 | list_move_tail(&cur_qh->ring, &musb->in_bulk); | ||
89 | -- | ||
90 | 1.6.0.4 | ||
91 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0014-musb_gadget-suppress-parasitic-TX-interrupts-with.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0014-musb_gadget-suppress-parasitic-TX-interrupts-with.patch deleted file mode 100644 index 08e08a8538..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0014-musb_gadget-suppress-parasitic-TX-interrupts-with.patch +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | From 7766f2ea909b73f56d21746485069e02839b75f1 Mon Sep 17 00:00:00 2001 | ||
2 | From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
3 | Date: Fri, 27 Mar 2009 12:53:32 -0700 | ||
4 | Subject: [PATCH] musb_gadget: suppress "parasitic" TX interrupts with CPPI | ||
5 | |||
6 | Suppress "parasitic" endpoint interrupts in the DMA mode | ||
7 | when using CPPI DMA driver; they're caused by the MUSB gadget | ||
8 | driver using the DMA request mode 0 instead of the mode 1. | ||
9 | |||
10 | Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
11 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
12 | --- | ||
13 | drivers/usb/musb/musb_gadget.c | 3 ++- | ||
14 | 1 files changed, 2 insertions(+), 1 deletions(-) | ||
15 | |||
16 | diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c | ||
17 | index f79440c..bc197b2 100644 | ||
18 | --- a/drivers/usb/musb/musb_gadget.c | ||
19 | +++ b/drivers/usb/musb/musb_gadget.c | ||
20 | @@ -349,7 +349,8 @@ static void txstate(struct musb *musb, struct musb_request *req) | ||
21 | #elif defined(CONFIG_USB_TI_CPPI_DMA) | ||
22 | /* program endpoint CSR first, then setup DMA */ | ||
23 | csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY); | ||
24 | - csr |= MUSB_TXCSR_MODE | MUSB_TXCSR_DMAENAB; | ||
25 | + csr |= MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE | | ||
26 | + MUSB_TXCSR_MODE; | ||
27 | musb_writew(epio, MUSB_TXCSR, | ||
28 | (MUSB_TXCSR_P_WZC_BITS & ~MUSB_TXCSR_P_UNDERRUN) | ||
29 | | csr); | ||
30 | -- | ||
31 | 1.6.0.4 | ||
32 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch deleted file mode 100644 index 7115b152d9..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0015-musb_gadget-fix-unhandled-endpoint-0-IRQs.patch +++ /dev/null | |||
@@ -1,202 +0,0 @@ | |||
1 | From 5424305125492a2417bde7c6d23ee4b84e25f6be Mon Sep 17 00:00:00 2001 | ||
2 | From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
3 | Date: Fri, 27 Mar 2009 12:52:43 -0700 | ||
4 | Subject: [PATCH] musb_gadget: fix unhandled endpoint 0 IRQs | ||
5 | |||
6 | The gadget EP0 code routinely ignores an interrupt at end of | ||
7 | the data phase because of musb_g_ep0_giveback() resetting the | ||
8 | state machine to "idle, waiting for SETUP" phase prematurely. | ||
9 | |||
10 | The driver also prematurely leaves the status phase on | ||
11 | receiving the SetupEnd interrupt. | ||
12 | |||
13 | As there were still unhandled endpoint 0 interrupts happening | ||
14 | from time to time after fixing these issues, there turned to | ||
15 | be yet another culprit: two distinct gadget states collapsed | ||
16 | into one. | ||
17 | |||
18 | The (missing) state that comes after STATUS IN/OUT states was | ||
19 | typically indiscernible from them since the corresponding | ||
20 | interrupts tend to happen within too little period of time | ||
21 | (due to only a zero-length status packet in between) and so | ||
22 | they got coalesced; yet this state is not the same as the next | ||
23 | one which is associated with the reception of a SETUP packet. | ||
24 | |||
25 | Adding this extra state seems to have fixed the rest of the | ||
26 | unhandled interrupts that generic_interrupt() and | ||
27 | davinci_interrupt() hid by faking their result and only | ||
28 | emitting a debug message -- so, stop doing that. | ||
29 | |||
30 | Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
31 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
32 | --- | ||
33 | drivers/usb/musb/davinci.c | 7 +---- | ||
34 | drivers/usb/musb/musb_core.c | 8 +----- | ||
35 | drivers/usb/musb/musb_core.h | 3 +- | ||
36 | drivers/usb/musb/musb_gadget_ep0.c | 45 +++++++++++++++++++++++++++++++---- | ||
37 | 4 files changed, 43 insertions(+), 20 deletions(-) | ||
38 | |||
39 | diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c | ||
40 | index 2dc7606..399c435 100644 | ||
41 | --- a/drivers/usb/musb/davinci.c | ||
42 | +++ b/drivers/usb/musb/davinci.c | ||
43 | @@ -357,12 +357,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) | ||
44 | |||
45 | spin_unlock_irqrestore(&musb->lock, flags); | ||
46 | |||
47 | - /* REVISIT we sometimes get unhandled IRQs | ||
48 | - * (e.g. ep0). not clear why... | ||
49 | - */ | ||
50 | - if (retval != IRQ_HANDLED) | ||
51 | - DBG(5, "unhandled? %08x\n", tmp); | ||
52 | - return IRQ_HANDLED; | ||
53 | + return retval; | ||
54 | } | ||
55 | |||
56 | int musb_platform_set_mode(struct musb *musb, u8 mode) | ||
57 | diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c | ||
58 | index 3019725..a1de43b 100644 | ||
59 | --- a/drivers/usb/musb/musb_core.c | ||
60 | +++ b/drivers/usb/musb/musb_core.c | ||
61 | @@ -1481,13 +1481,7 @@ static irqreturn_t generic_interrupt(int irq, void *__hci) | ||
62 | |||
63 | spin_unlock_irqrestore(&musb->lock, flags); | ||
64 | |||
65 | - /* REVISIT we sometimes get spurious IRQs on g_ep0 | ||
66 | - * not clear why... | ||
67 | - */ | ||
68 | - if (retval != IRQ_HANDLED) | ||
69 | - DBG(5, "spurious?\n"); | ||
70 | - | ||
71 | - return IRQ_HANDLED; | ||
72 | + return retval; | ||
73 | } | ||
74 | |||
75 | #else | ||
76 | diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h | ||
77 | index adf1806..f56a56c 100644 | ||
78 | --- a/drivers/usb/musb/musb_core.h | ||
79 | +++ b/drivers/usb/musb/musb_core.h | ||
80 | @@ -171,7 +171,8 @@ enum musb_h_ep0_state { | ||
81 | |||
82 | /* peripheral side ep0 states */ | ||
83 | enum musb_g_ep0_state { | ||
84 | - MUSB_EP0_STAGE_SETUP, /* idle, waiting for setup */ | ||
85 | + MUSB_EP0_STAGE_IDLE, /* idle, waiting for SETUP */ | ||
86 | + MUSB_EP0_STAGE_SETUP, /* received SETUP */ | ||
87 | MUSB_EP0_STAGE_TX, /* IN data */ | ||
88 | MUSB_EP0_STAGE_RX, /* OUT data */ | ||
89 | MUSB_EP0_STAGE_STATUSIN, /* (after OUT data) */ | ||
90 | diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c | ||
91 | index 3f5e30d..ec0e899 100644 | ||
92 | --- a/drivers/usb/musb/musb_gadget_ep0.c | ||
93 | +++ b/drivers/usb/musb/musb_gadget_ep0.c | ||
94 | @@ -4,6 +4,7 @@ | ||
95 | * Copyright 2005 Mentor Graphics Corporation | ||
96 | * Copyright (C) 2005-2006 by Texas Instruments | ||
97 | * Copyright (C) 2006-2007 Nokia Corporation | ||
98 | + * Copyright (C) 2008-2009 MontaVista Software, Inc. <source-Igf4POYTYCDQT0dZR+AlfA@public.gmane.org> | ||
99 | * | ||
100 | * This program is free software; you can redistribute it and/or | ||
101 | * modify it under the terms of the GNU General Public License | ||
102 | @@ -58,7 +59,8 @@ | ||
103 | static char *decode_ep0stage(u8 stage) | ||
104 | { | ||
105 | switch (stage) { | ||
106 | - case MUSB_EP0_STAGE_SETUP: return "idle"; | ||
107 | + case MUSB_EP0_STAGE_IDLE: return "idle"; | ||
108 | + case MUSB_EP0_STAGE_SETUP: return "setup"; | ||
109 | case MUSB_EP0_STAGE_TX: return "in"; | ||
110 | case MUSB_EP0_STAGE_RX: return "out"; | ||
111 | case MUSB_EP0_STAGE_ACKWAIT: return "wait"; | ||
112 | @@ -628,7 +630,7 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb) | ||
113 | musb_writew(regs, MUSB_CSR0, | ||
114 | csr & ~MUSB_CSR0_P_SENTSTALL); | ||
115 | retval = IRQ_HANDLED; | ||
116 | - musb->ep0_state = MUSB_EP0_STAGE_SETUP; | ||
117 | + musb->ep0_state = MUSB_EP0_STAGE_IDLE; | ||
118 | csr = musb_readw(regs, MUSB_CSR0); | ||
119 | } | ||
120 | |||
121 | @@ -636,7 +638,18 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb) | ||
122 | if (csr & MUSB_CSR0_P_SETUPEND) { | ||
123 | musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SVDSETUPEND); | ||
124 | retval = IRQ_HANDLED; | ||
125 | - musb->ep0_state = MUSB_EP0_STAGE_SETUP; | ||
126 | + /* Transition into the early status phase */ | ||
127 | + switch (musb->ep0_state) { | ||
128 | + case MUSB_EP0_STAGE_TX: | ||
129 | + musb->ep0_state = MUSB_EP0_STAGE_STATUSOUT; | ||
130 | + break; | ||
131 | + case MUSB_EP0_STAGE_RX: | ||
132 | + musb->ep0_state = MUSB_EP0_STAGE_STATUSIN; | ||
133 | + break; | ||
134 | + default: | ||
135 | + ERR("SetupEnd came in a wrong ep0stage %s", | ||
136 | + decode_ep0stage(musb->ep0_state)); | ||
137 | + } | ||
138 | csr = musb_readw(regs, MUSB_CSR0); | ||
139 | /* NOTE: request may need completion */ | ||
140 | } | ||
141 | @@ -697,11 +710,31 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb) | ||
142 | if (req) | ||
143 | musb_g_ep0_giveback(musb, req); | ||
144 | } | ||
145 | + | ||
146 | + /* | ||
147 | + * In case when several interrupts can get coalesced, | ||
148 | + * check to see if we've already received a SETUP packet... | ||
149 | + */ | ||
150 | + if (csr & MUSB_CSR0_RXPKTRDY) | ||
151 | + goto setup; | ||
152 | + | ||
153 | + retval = IRQ_HANDLED; | ||
154 | + musb->ep0_state = MUSB_EP0_STAGE_IDLE; | ||
155 | + break; | ||
156 | + | ||
157 | + case MUSB_EP0_STAGE_IDLE: | ||
158 | + /* | ||
159 | + * This state is typically (but not always) indiscernible | ||
160 | + * from the status states since the corresponding interrupts | ||
161 | + * tend to happen within too little period of time (with only | ||
162 | + * a zero-length packet in between) and so get coalesced... | ||
163 | + */ | ||
164 | retval = IRQ_HANDLED; | ||
165 | musb->ep0_state = MUSB_EP0_STAGE_SETUP; | ||
166 | /* FALLTHROUGH */ | ||
167 | |||
168 | case MUSB_EP0_STAGE_SETUP: | ||
169 | +setup: | ||
170 | if (csr & MUSB_CSR0_RXPKTRDY) { | ||
171 | struct usb_ctrlrequest setup; | ||
172 | int handled = 0; | ||
173 | @@ -783,7 +816,7 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb) | ||
174 | stall: | ||
175 | DBG(3, "stall (%d)\n", handled); | ||
176 | musb->ackpend |= MUSB_CSR0_P_SENDSTALL; | ||
177 | - musb->ep0_state = MUSB_EP0_STAGE_SETUP; | ||
178 | + musb->ep0_state = MUSB_EP0_STAGE_IDLE; | ||
179 | finish: | ||
180 | musb_writew(regs, MUSB_CSR0, | ||
181 | musb->ackpend); | ||
182 | @@ -803,7 +836,7 @@ finish: | ||
183 | /* "can't happen" */ | ||
184 | WARN_ON(1); | ||
185 | musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SENDSTALL); | ||
186 | - musb->ep0_state = MUSB_EP0_STAGE_SETUP; | ||
187 | + musb->ep0_state = MUSB_EP0_STAGE_IDLE; | ||
188 | break; | ||
189 | } | ||
190 | |||
191 | @@ -959,7 +992,7 @@ static int musb_g_ep0_halt(struct usb_ep *e, int value) | ||
192 | |||
193 | csr |= MUSB_CSR0_P_SENDSTALL; | ||
194 | musb_writew(regs, MUSB_CSR0, csr); | ||
195 | - musb->ep0_state = MUSB_EP0_STAGE_SETUP; | ||
196 | + musb->ep0_state = MUSB_EP0_STAGE_IDLE; | ||
197 | musb->ackpend = 0; | ||
198 | break; | ||
199 | default: | ||
200 | -- | ||
201 | 1.6.0.4 | ||
202 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0016-musb_host-factor-out-musb_ep_-get-set-_qh.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0016-musb_host-factor-out-musb_ep_-get-set-_qh.patch deleted file mode 100644 index a2f54ff47b..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0016-musb_host-factor-out-musb_ep_-get-set-_qh.patch +++ /dev/null | |||
@@ -1,146 +0,0 @@ | |||
1 | From f9ca8154cf395ec00129f12016697ef610a826ff Mon Sep 17 00:00:00 2001 | ||
2 | From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
3 | Date: Fri, 27 Mar 2009 12:55:16 -0700 | ||
4 | Subject: [PATCH] musb_host: factor out musb_ep_{get|set}_qh() | ||
5 | |||
6 | Factor out the often used code to get/set the active 'qh' | ||
7 | pointer for the hardware endpoint. Change the way the case | ||
8 | of a shared FIFO is handled by setting *both* 'in_qh' and | ||
9 | 'out_qh' fields of 'struct musb_hw_ep'. That seems more | ||
10 | consistent and makes getting to the current 'qh' easy when | ||
11 | the code knows the direction beforehand. | ||
12 | |||
13 | While at it, turn some assignments into intializers and | ||
14 | fix declaration style in the vicinity. | ||
15 | |||
16 | Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
17 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
18 | --- | ||
19 | drivers/usb/musb/musb_host.c | 56 ++++++++++++++++------------------------- | ||
20 | 1 files changed, 22 insertions(+), 34 deletions(-) | ||
21 | |||
22 | diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c | ||
23 | index dc32ce4..bc89079 100644 | ||
24 | --- a/drivers/usb/musb/musb_host.c | ||
25 | +++ b/drivers/usb/musb/musb_host.c | ||
26 | @@ -178,6 +178,19 @@ static inline void cppi_host_txdma_start(struct musb_hw_ep *ep) | ||
27 | musb_writew(ep->regs, MUSB_TXCSR, txcsr); | ||
28 | } | ||
29 | |||
30 | +static void musb_ep_set_qh(struct musb_hw_ep *ep, int is_in, struct musb_qh *qh) | ||
31 | +{ | ||
32 | + if (is_in != 0 || ep->is_shared_fifo) | ||
33 | + ep->in_qh = qh; | ||
34 | + if (is_in == 0 || ep->is_shared_fifo) | ||
35 | + ep->out_qh = qh; | ||
36 | +} | ||
37 | + | ||
38 | +static struct musb_qh *musb_ep_get_qh(struct musb_hw_ep *ep, int is_in) | ||
39 | +{ | ||
40 | + return is_in ? ep->in_qh : ep->out_qh; | ||
41 | +} | ||
42 | + | ||
43 | /* | ||
44 | * Start the URB at the front of an endpoint's queue | ||
45 | * end must be claimed from the caller. | ||
46 | @@ -207,7 +220,6 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) | ||
47 | case USB_ENDPOINT_XFER_CONTROL: | ||
48 | /* control transfers always start with SETUP */ | ||
49 | is_in = 0; | ||
50 | - hw_ep->out_qh = qh; | ||
51 | musb->ep0_stage = MUSB_EP0_START; | ||
52 | buf = urb->setup_packet; | ||
53 | len = 8; | ||
54 | @@ -236,10 +248,7 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) | ||
55 | epnum, buf + offset, len); | ||
56 | |||
57 | /* Configure endpoint */ | ||
58 | - if (is_in || hw_ep->is_shared_fifo) | ||
59 | - hw_ep->in_qh = qh; | ||
60 | - else | ||
61 | - hw_ep->out_qh = qh; | ||
62 | + musb_ep_set_qh(hw_ep, is_in, qh); | ||
63 | musb_ep_program(musb, epnum, urb, !is_in, buf, offset, len); | ||
64 | |||
65 | /* transmit may have more work: start it when it is time */ | ||
66 | @@ -374,11 +383,8 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) | ||
67 | else | ||
68 | ep->tx_reinit = 1; | ||
69 | |||
70 | - /* clobber old pointers to this qh */ | ||
71 | - if (is_in || ep->is_shared_fifo) | ||
72 | - ep->in_qh = NULL; | ||
73 | - else | ||
74 | - ep->out_qh = NULL; | ||
75 | + /* Clobber old pointers to this qh */ | ||
76 | + musb_ep_set_qh(ep, is_in, NULL); | ||
77 | qh->hep->hcpriv = NULL; | ||
78 | |||
79 | switch (qh->type) { | ||
80 | @@ -421,12 +427,7 @@ static void | ||
81 | musb_advance_schedule(struct musb *musb, struct urb *urb, | ||
82 | struct musb_hw_ep *hw_ep, int is_in) | ||
83 | { | ||
84 | - struct musb_qh *qh; | ||
85 | - | ||
86 | - if (is_in || hw_ep->is_shared_fifo) | ||
87 | - qh = hw_ep->in_qh; | ||
88 | - else | ||
89 | - qh = hw_ep->out_qh; | ||
90 | + struct musb_qh *qh = musb_ep_get_qh(hw_ep, is_in); | ||
91 | |||
92 | if (urb->status == -EINPROGRESS) | ||
93 | qh = musb_giveback(qh, urb, 0); | ||
94 | @@ -689,15 +690,8 @@ static void musb_ep_program(struct musb *musb, u8 epnum, | ||
95 | void __iomem *mbase = musb->mregs; | ||
96 | struct musb_hw_ep *hw_ep = musb->endpoints + epnum; | ||
97 | void __iomem *epio = hw_ep->regs; | ||
98 | - struct musb_qh *qh; | ||
99 | - u16 packet_sz; | ||
100 | - | ||
101 | - if (!is_out || hw_ep->is_shared_fifo) | ||
102 | - qh = hw_ep->in_qh; | ||
103 | - else | ||
104 | - qh = hw_ep->out_qh; | ||
105 | - | ||
106 | - packet_sz = qh->maxpacket; | ||
107 | + struct musb_qh *qh = musb_ep_get_qh(hw_ep, !is_out); | ||
108 | + u16 packet_sz = qh->maxpacket; | ||
109 | |||
110 | DBG(3, "%s hw%d urb %p spd%d dev%d ep%d%s " | ||
111 | "h_addr%02x h_port%02x bytes %d\n", | ||
112 | @@ -1114,17 +1108,14 @@ void musb_host_tx(struct musb *musb, u8 epnum) | ||
113 | u16 tx_csr; | ||
114 | size_t length = 0; | ||
115 | size_t offset = 0; | ||
116 | - struct urb *urb; | ||
117 | struct musb_hw_ep *hw_ep = musb->endpoints + epnum; | ||
118 | void __iomem *epio = hw_ep->regs; | ||
119 | - struct musb_qh *qh = hw_ep->is_shared_fifo ? hw_ep->in_qh | ||
120 | - : hw_ep->out_qh; | ||
121 | + struct musb_qh *qh = hw_ep->out_qh; | ||
122 | + struct urb *urb = next_urb(qh); | ||
123 | u32 status = 0; | ||
124 | void __iomem *mbase = musb->mregs; | ||
125 | struct dma_channel *dma; | ||
126 | |||
127 | - urb = next_urb(qh); | ||
128 | - | ||
129 | musb_ep_select(mbase, epnum); | ||
130 | tx_csr = musb_readw(epio, MUSB_TXCSR); | ||
131 | |||
132 | @@ -1741,10 +1732,7 @@ static int musb_schedule( | ||
133 | epnum++, hw_ep++) { | ||
134 | int diff; | ||
135 | |||
136 | - if (is_in || hw_ep->is_shared_fifo) { | ||
137 | - if (hw_ep->in_qh != NULL) | ||
138 | - continue; | ||
139 | - } else if (hw_ep->out_qh != NULL) | ||
140 | + if (musb_ep_get_qh(hw_ep, is_in) != NULL) | ||
141 | continue; | ||
142 | |||
143 | if (hw_ep == musb->bulk_ep) | ||
144 | -- | ||
145 | 1.6.0.4 | ||
146 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0017-musb_host-refactor-URB-giveback.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0017-musb_host-refactor-URB-giveback.patch deleted file mode 100644 index 4a520dff87..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0017-musb_host-refactor-URB-giveback.patch +++ /dev/null | |||
@@ -1,132 +0,0 @@ | |||
1 | From 013056a09afd324e729d64b9a0e66a004604e1d6 Mon Sep 17 00:00:00 2001 | ||
2 | From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
3 | Date: Fri, 27 Mar 2009 12:58:31 -0700 | ||
4 | Subject: [PATCH] musb_host: refactor URB giveback | ||
5 | |||
6 | As musb_advance_schedule() is now the only remaning | ||
7 | caller of musb_giveback() (and the only valid context | ||
8 | of such call), just fold the latter into the former | ||
9 | and then rename __musb_giveback() into musb_giveback(). | ||
10 | |||
11 | This is a net minor shrink. | ||
12 | |||
13 | Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
14 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
15 | --- | ||
16 | drivers/usb/musb/musb_host.c | 54 +++++++++++++++-------------------------- | ||
17 | 1 files changed, 20 insertions(+), 34 deletions(-) | ||
18 | |||
19 | diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c | ||
20 | index bc89079..e833959 100644 | ||
21 | --- a/drivers/usb/musb/musb_host.c | ||
22 | +++ b/drivers/usb/musb/musb_host.c | ||
23 | @@ -292,9 +292,8 @@ start: | ||
24 | } | ||
25 | } | ||
26 | |||
27 | -/* caller owns controller lock, irqs are blocked */ | ||
28 | -static void | ||
29 | -__musb_giveback(struct musb *musb, struct urb *urb, int status) | ||
30 | +/* Context: caller owns controller lock, IRQs are blocked */ | ||
31 | +static void musb_giveback(struct musb *musb, struct urb *urb, int status) | ||
32 | __releases(musb->lock) | ||
33 | __acquires(musb->lock) | ||
34 | { | ||
35 | @@ -347,14 +346,22 @@ static inline void musb_save_toggle(struct musb_qh *qh, int is_in, | ||
36 | usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0); | ||
37 | } | ||
38 | |||
39 | -/* caller owns controller lock, irqs are blocked */ | ||
40 | -static struct musb_qh * | ||
41 | -musb_giveback(struct musb_qh *qh, struct urb *urb, int status) | ||
42 | +/* | ||
43 | + * Advance this hardware endpoint's queue, completing the specified URB and | ||
44 | + * advancing to either the next URB queued to that qh, or else invalidating | ||
45 | + * that qh and advancing to the next qh scheduled after the current one. | ||
46 | + * | ||
47 | + * Context: caller owns controller lock, IRQs are blocked | ||
48 | + */ | ||
49 | +static void musb_advance_schedule(struct musb *musb, struct urb *urb, | ||
50 | + struct musb_hw_ep *hw_ep, int is_in) | ||
51 | { | ||
52 | + struct musb_qh *qh = musb_ep_get_qh(hw_ep, is_in); | ||
53 | struct musb_hw_ep *ep = qh->hw_ep; | ||
54 | - struct musb *musb = ep->musb; | ||
55 | - int is_in = usb_pipein(urb->pipe); | ||
56 | int ready = qh->is_ready; | ||
57 | + int status; | ||
58 | + | ||
59 | + status = (urb->status == -EINPROGRESS) ? 0 : urb->status; | ||
60 | |||
61 | /* save toggle eagerly, for paranoia */ | ||
62 | switch (qh->type) { | ||
63 | @@ -363,13 +370,13 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) | ||
64 | musb_save_toggle(qh, is_in, urb); | ||
65 | break; | ||
66 | case USB_ENDPOINT_XFER_ISOC: | ||
67 | - if (status == 0 && urb->error_count) | ||
68 | + if (urb->error_count) | ||
69 | status = -EXDEV; | ||
70 | break; | ||
71 | } | ||
72 | |||
73 | qh->is_ready = 0; | ||
74 | - __musb_giveback(musb, urb, status); | ||
75 | + musb_giveback(musb, urb, status); | ||
76 | qh->is_ready = ready; | ||
77 | |||
78 | /* reclaim resources (and bandwidth) ASAP; deschedule it, and | ||
79 | @@ -413,31 +420,10 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) | ||
80 | break; | ||
81 | } | ||
82 | } | ||
83 | - return qh; | ||
84 | -} | ||
85 | - | ||
86 | -/* | ||
87 | - * Advance this hardware endpoint's queue, completing the specified urb and | ||
88 | - * advancing to either the next urb queued to that qh, or else invalidating | ||
89 | - * that qh and advancing to the next qh scheduled after the current one. | ||
90 | - * | ||
91 | - * Context: caller owns controller lock, irqs are blocked | ||
92 | - */ | ||
93 | -static void | ||
94 | -musb_advance_schedule(struct musb *musb, struct urb *urb, | ||
95 | - struct musb_hw_ep *hw_ep, int is_in) | ||
96 | -{ | ||
97 | - struct musb_qh *qh = musb_ep_get_qh(hw_ep, is_in); | ||
98 | - | ||
99 | - if (urb->status == -EINPROGRESS) | ||
100 | - qh = musb_giveback(qh, urb, 0); | ||
101 | - else | ||
102 | - qh = musb_giveback(qh, urb, urb->status); | ||
103 | |||
104 | if (qh != NULL && qh->is_ready) { | ||
105 | DBG(4, "... next ep%d %cX urb %p\n", | ||
106 | - hw_ep->epnum, is_in ? 'R' : 'T', | ||
107 | - next_urb(qh)); | ||
108 | + hw_ep->epnum, is_in ? 'R' : 'T', next_urb(qh)); | ||
109 | musb_start_urb(musb, is_in, qh); | ||
110 | } | ||
111 | } | ||
112 | @@ -2080,7 +2066,7 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | ||
113 | |||
114 | ret = 0; | ||
115 | qh->is_ready = 0; | ||
116 | - __musb_giveback(musb, urb, 0); | ||
117 | + musb_giveback(musb, urb, 0); | ||
118 | qh->is_ready = ready; | ||
119 | |||
120 | /* If nothing else (usually musb_giveback) is using it | ||
121 | @@ -2164,7 +2150,7 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) | ||
122 | * will activate any of these as it advances. | ||
123 | */ | ||
124 | while (!list_empty(&hep->urb_list)) | ||
125 | - __musb_giveback(musb, next_urb(qh), -ESHUTDOWN); | ||
126 | + musb_giveback(musb, next_urb(qh), -ESHUTDOWN); | ||
127 | |||
128 | hep->hcpriv = NULL; | ||
129 | list_del(&qh->ring); | ||
130 | -- | ||
131 | 1.6.0.4 | ||
132 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0018-musb-split-out-CPPI-interrupt-handler.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0018-musb-split-out-CPPI-interrupt-handler.patch deleted file mode 100644 index bf3d6e7021..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0018-musb-split-out-CPPI-interrupt-handler.patch +++ /dev/null | |||
@@ -1,167 +0,0 @@ | |||
1 | From b91b067c531c9322f3719951b07303e790b13475 Mon Sep 17 00:00:00 2001 | ||
2 | From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
3 | Date: Fri, 27 Mar 2009 12:59:46 -0700 | ||
4 | Subject: [PATCH] musb: split out CPPI interrupt handler | ||
5 | |||
6 | As DaVinci DM646x has a dedicated CPPI DMA interrupt, replace | ||
7 | cppi_completion() (which has always been kind of layering | ||
8 | violation) by a complete CPPI interrupt handler. | ||
9 | |||
10 | [ dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org: only cppi_dma.c needs platform | ||
11 | device header, not cppi_dma.h ] | ||
12 | |||
13 | Signed-off-by: Dmitry Krivoschekov <dkrivoschekov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
14 | Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
15 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
16 | --- | ||
17 | drivers/usb/musb/cppi_dma.c | 34 +++++++++++++++++++++++++++++++--- | ||
18 | drivers/usb/musb/cppi_dma.h | 6 ++++-- | ||
19 | drivers/usb/musb/davinci.c | 14 ++++---------- | ||
20 | 3 files changed, 39 insertions(+), 15 deletions(-) | ||
21 | |||
22 | diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c | ||
23 | index ac7227c..6ff3c67 100644 | ||
24 | --- a/drivers/usb/musb/cppi_dma.c | ||
25 | +++ b/drivers/usb/musb/cppi_dma.c | ||
26 | @@ -6,6 +6,7 @@ | ||
27 | * The TUSB6020, using VLYNQ, has CPPI that looks much like DaVinci. | ||
28 | */ | ||
29 | |||
30 | +#include <linux/platform_device.h> | ||
31 | #include <linux/usb.h> | ||
32 | |||
33 | #include "musb_core.h" | ||
34 | @@ -1145,17 +1146,27 @@ static bool cppi_rx_scan(struct cppi *cppi, unsigned ch) | ||
35 | return completed; | ||
36 | } | ||
37 | |||
38 | -void cppi_completion(struct musb *musb, u32 rx, u32 tx) | ||
39 | +irqreturn_t cppi_interrupt(int irq, void *dev_id) | ||
40 | { | ||
41 | - void __iomem *tibase; | ||
42 | - int i, index; | ||
43 | + struct musb *musb = dev_id; | ||
44 | struct cppi *cppi; | ||
45 | + void __iomem *tibase; | ||
46 | struct musb_hw_ep *hw_ep = NULL; | ||
47 | + u32 rx, tx; | ||
48 | + int i, index; | ||
49 | |||
50 | cppi = container_of(musb->dma_controller, struct cppi, controller); | ||
51 | |||
52 | tibase = musb->ctrl_base; | ||
53 | |||
54 | + tx = musb_readl(tibase, DAVINCI_TXCPPI_MASKED_REG); | ||
55 | + rx = musb_readl(tibase, DAVINCI_RXCPPI_MASKED_REG); | ||
56 | + | ||
57 | + if (!tx && !rx) | ||
58 | + return IRQ_NONE; | ||
59 | + | ||
60 | + DBG(4, "CPPI IRQ Tx%x Rx%x\n", tx, rx); | ||
61 | + | ||
62 | /* process TX channels */ | ||
63 | for (index = 0; tx; tx = tx >> 1, index++) { | ||
64 | struct cppi_channel *tx_ch; | ||
65 | @@ -1293,6 +1304,8 @@ void cppi_completion(struct musb *musb, u32 rx, u32 tx) | ||
66 | |||
67 | /* write to CPPI EOI register to re-enable interrupts */ | ||
68 | musb_writel(tibase, DAVINCI_CPPI_EOI_REG, 0); | ||
69 | + | ||
70 | + return IRQ_HANDLED; | ||
71 | } | ||
72 | |||
73 | /* Instantiate a software object representing a DMA controller. */ | ||
74 | @@ -1300,6 +1313,9 @@ struct dma_controller *__init | ||
75 | dma_controller_create(struct musb *musb, void __iomem *mregs) | ||
76 | { | ||
77 | struct cppi *controller; | ||
78 | + struct device *dev = musb->controller; | ||
79 | + struct platform_device *pdev = to_platform_device(dev); | ||
80 | + int irq = platform_get_irq(pdev, 1); | ||
81 | |||
82 | controller = kzalloc(sizeof *controller, GFP_KERNEL); | ||
83 | if (!controller) | ||
84 | @@ -1330,6 +1346,15 @@ dma_controller_create(struct musb *musb, void __iomem *mregs) | ||
85 | return NULL; | ||
86 | } | ||
87 | |||
88 | + if (irq > 0) { | ||
89 | + if (request_irq(irq, cppi_interrupt, 0, "cppi-dma", musb)) { | ||
90 | + dev_err(dev, "request_irq %d failed!\n", irq); | ||
91 | + dma_controller_destroy(&controller->controller); | ||
92 | + return NULL; | ||
93 | + } | ||
94 | + controller->irq = irq; | ||
95 | + } | ||
96 | + | ||
97 | return &controller->controller; | ||
98 | } | ||
99 | |||
100 | @@ -1342,6 +1367,9 @@ void dma_controller_destroy(struct dma_controller *c) | ||
101 | |||
102 | cppi = container_of(c, struct cppi, controller); | ||
103 | |||
104 | + if (cppi->irq) | ||
105 | + free_irq(cppi->irq, cppi->musb); | ||
106 | + | ||
107 | /* assert: caller stopped the controller first */ | ||
108 | dma_pool_destroy(cppi->pool); | ||
109 | |||
110 | diff --git a/drivers/usb/musb/cppi_dma.h b/drivers/usb/musb/cppi_dma.h | ||
111 | index 729b407..8a39de3 100644 | ||
112 | --- a/drivers/usb/musb/cppi_dma.h | ||
113 | +++ b/drivers/usb/musb/cppi_dma.h | ||
114 | @@ -119,6 +119,8 @@ struct cppi { | ||
115 | void __iomem *mregs; /* Mentor regs */ | ||
116 | void __iomem *tibase; /* TI/CPPI regs */ | ||
117 | |||
118 | + int irq; | ||
119 | + | ||
120 | struct cppi_channel tx[4]; | ||
121 | struct cppi_channel rx[4]; | ||
122 | |||
123 | @@ -127,7 +129,7 @@ struct cppi { | ||
124 | struct list_head tx_complete; | ||
125 | }; | ||
126 | |||
127 | -/* irq handling hook */ | ||
128 | -extern void cppi_completion(struct musb *, u32 rx, u32 tx); | ||
129 | +/* CPPI IRQ handler */ | ||
130 | +extern irqreturn_t cppi_interrupt(int, void *); | ||
131 | |||
132 | #endif /* end of ifndef _CPPI_DMA_H_ */ | ||
133 | diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c | ||
134 | index 399c435..9fd74bf 100644 | ||
135 | --- a/drivers/usb/musb/davinci.c | ||
136 | +++ b/drivers/usb/musb/davinci.c | ||
137 | @@ -250,6 +250,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) | ||
138 | irqreturn_t retval = IRQ_NONE; | ||
139 | struct musb *musb = __hci; | ||
140 | void __iomem *tibase = musb->ctrl_base; | ||
141 | + struct cppi *cppi; | ||
142 | u32 tmp; | ||
143 | |||
144 | spin_lock_irqsave(&musb->lock, flags); | ||
145 | @@ -266,16 +267,9 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) | ||
146 | /* CPPI interrupts share the same IRQ line, but have their own | ||
147 | * mask, state, "vector", and EOI registers. | ||
148 | */ | ||
149 | - if (is_cppi_enabled()) { | ||
150 | - u32 cppi_tx = musb_readl(tibase, DAVINCI_TXCPPI_MASKED_REG); | ||
151 | - u32 cppi_rx = musb_readl(tibase, DAVINCI_RXCPPI_MASKED_REG); | ||
152 | - | ||
153 | - if (cppi_tx || cppi_rx) { | ||
154 | - DBG(4, "CPPI IRQ t%x r%x\n", cppi_tx, cppi_rx); | ||
155 | - cppi_completion(musb, cppi_rx, cppi_tx); | ||
156 | - retval = IRQ_HANDLED; | ||
157 | - } | ||
158 | - } | ||
159 | + cppi = container_of(musb->dma_controller, struct cppi, controller); | ||
160 | + if (is_cppi_enabled() && musb->dma_controller && !cppi->irq) | ||
161 | + retval = cppi_interrupt(irq, __hci); | ||
162 | |||
163 | /* ack and handle non-CPPI interrupts */ | ||
164 | tmp = musb_readl(tibase, DAVINCI_USB_INT_SRC_MASKED_REG); | ||
165 | -- | ||
166 | 1.6.0.4 | ||
167 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0019-musb_host-simplify-check-for-active-URB.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0019-musb_host-simplify-check-for-active-URB.patch deleted file mode 100644 index c0e57155c8..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0019-musb_host-simplify-check-for-active-URB.patch +++ /dev/null | |||
@@ -1,158 +0,0 @@ | |||
1 | From 69242ddd26151d45f46011cf7abc581b14699fb2 Mon Sep 17 00:00:00 2001 | ||
2 | From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
3 | Date: Fri, 27 Mar 2009 12:56:26 -0700 | ||
4 | Subject: [PATCH] musb_host: simplify check for active URB | ||
5 | |||
6 | The existance of the scheduling list shouldn't matter in | ||
7 | determining whether there's currectly an URB executing on a | ||
8 | hardware endpoint. What should actually matter is the 'in_qh' | ||
9 | or 'out_qh' fields of the 'struct musb_hw_ep' -- those are | ||
10 | set in musb_start_urb() and cleared in musb_giveback() when | ||
11 | the endpoint's URB list drains. Hence we should be able to | ||
12 | replace the big *switch* statements in musb_urb_dequeue() | ||
13 | and musb_h_disable() with mere musb_ep_get_qh() calls... | ||
14 | |||
15 | While at it, do some more changes: | ||
16 | |||
17 | - add 'is_in' variable to musb_urb_dequeue(); | ||
18 | |||
19 | - remove the unnecessary 'epnum' variable from musb_h_disable(); | ||
20 | |||
21 | - fix the comment style in the vicinity. | ||
22 | |||
23 | This is a minor shrink of source and object code. | ||
24 | |||
25 | Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
26 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
27 | --- | ||
28 | drivers/usb/musb/musb_host.c | 72 ++++++++--------------------------------- | ||
29 | 1 files changed, 14 insertions(+), 58 deletions(-) | ||
30 | |||
31 | diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c | ||
32 | index e833959..e121e0e 100644 | ||
33 | --- a/drivers/usb/musb/musb_host.c | ||
34 | +++ b/drivers/usb/musb/musb_host.c | ||
35 | @@ -2008,14 +2008,14 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | ||
36 | { | ||
37 | struct musb *musb = hcd_to_musb(hcd); | ||
38 | struct musb_qh *qh; | ||
39 | - struct list_head *sched; | ||
40 | unsigned long flags; | ||
41 | + int is_in = usb_pipein(urb->pipe); | ||
42 | int ret; | ||
43 | |||
44 | DBG(4, "urb=%p, dev%d ep%d%s\n", urb, | ||
45 | usb_pipedevice(urb->pipe), | ||
46 | usb_pipeendpoint(urb->pipe), | ||
47 | - usb_pipein(urb->pipe) ? "in" : "out"); | ||
48 | + is_in ? "in" : "out"); | ||
49 | |||
50 | spin_lock_irqsave(&musb->lock, flags); | ||
51 | ret = usb_hcd_check_unlink_urb(hcd, urb, status); | ||
52 | @@ -2026,45 +2026,23 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | ||
53 | if (!qh) | ||
54 | goto done; | ||
55 | |||
56 | - /* Any URB not actively programmed into endpoint hardware can be | ||
57 | + /* | ||
58 | + * Any URB not actively programmed into endpoint hardware can be | ||
59 | * immediately given back; that's any URB not at the head of an | ||
60 | * endpoint queue, unless someday we get real DMA queues. And even | ||
61 | * if it's at the head, it might not be known to the hardware... | ||
62 | * | ||
63 | - * Otherwise abort current transfer, pending dma, etc.; urb->status | ||
64 | + * Otherwise abort current transfer, pending DMA, etc.; urb->status | ||
65 | * has already been updated. This is a synchronous abort; it'd be | ||
66 | * OK to hold off until after some IRQ, though. | ||
67 | + * | ||
68 | + * NOTE: qh is invalid unless !list_empty(&hep->urb_list) | ||
69 | */ | ||
70 | - if (!qh->is_ready || urb->urb_list.prev != &qh->hep->urb_list) | ||
71 | - ret = -EINPROGRESS; | ||
72 | - else { | ||
73 | - switch (qh->type) { | ||
74 | - case USB_ENDPOINT_XFER_CONTROL: | ||
75 | - sched = &musb->control; | ||
76 | - break; | ||
77 | - case USB_ENDPOINT_XFER_BULK: | ||
78 | - if (qh->mux == 1) { | ||
79 | - if (usb_pipein(urb->pipe)) | ||
80 | - sched = &musb->in_bulk; | ||
81 | - else | ||
82 | - sched = &musb->out_bulk; | ||
83 | - break; | ||
84 | - } | ||
85 | - default: | ||
86 | - /* REVISIT when we get a schedule tree, periodic | ||
87 | - * transfers won't always be at the head of a | ||
88 | - * singleton queue... | ||
89 | - */ | ||
90 | - sched = NULL; | ||
91 | - break; | ||
92 | - } | ||
93 | - } | ||
94 | - | ||
95 | - /* NOTE: qh is invalid unless !list_empty(&hep->urb_list) */ | ||
96 | - if (ret < 0 || (sched && qh != first_qh(sched))) { | ||
97 | + if (!qh->is_ready | ||
98 | + || urb->urb_list.prev != &qh->hep->urb_list | ||
99 | + || musb_ep_get_qh(qh->hw_ep, is_in) != qh) { | ||
100 | int ready = qh->is_ready; | ||
101 | |||
102 | - ret = 0; | ||
103 | qh->is_ready = 0; | ||
104 | musb_giveback(musb, urb, 0); | ||
105 | qh->is_ready = ready; | ||
106 | @@ -2088,13 +2066,11 @@ done: | ||
107 | static void | ||
108 | musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) | ||
109 | { | ||
110 | - u8 epnum = hep->desc.bEndpointAddress; | ||
111 | + u8 is_in = hep->desc.bEndpointAddress & USB_DIR_IN; | ||
112 | unsigned long flags; | ||
113 | struct musb *musb = hcd_to_musb(hcd); | ||
114 | - u8 is_in = epnum & USB_DIR_IN; | ||
115 | struct musb_qh *qh; | ||
116 | struct urb *urb; | ||
117 | - struct list_head *sched; | ||
118 | |||
119 | spin_lock_irqsave(&musb->lock, flags); | ||
120 | |||
121 | @@ -2102,31 +2078,11 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) | ||
122 | if (qh == NULL) | ||
123 | goto exit; | ||
124 | |||
125 | - switch (qh->type) { | ||
126 | - case USB_ENDPOINT_XFER_CONTROL: | ||
127 | - sched = &musb->control; | ||
128 | - break; | ||
129 | - case USB_ENDPOINT_XFER_BULK: | ||
130 | - if (qh->mux == 1) { | ||
131 | - if (is_in) | ||
132 | - sched = &musb->in_bulk; | ||
133 | - else | ||
134 | - sched = &musb->out_bulk; | ||
135 | - break; | ||
136 | - } | ||
137 | - default: | ||
138 | - /* REVISIT when we get a schedule tree, periodic transfers | ||
139 | - * won't always be at the head of a singleton queue... | ||
140 | - */ | ||
141 | - sched = NULL; | ||
142 | - break; | ||
143 | - } | ||
144 | - | ||
145 | - /* NOTE: qh is invalid unless !list_empty(&hep->urb_list) */ | ||
146 | + /* NOTE: qh is invalid unless !list_empty(&hep->urb_list) */ | ||
147 | |||
148 | - /* kick first urb off the hardware, if needed */ | ||
149 | + /* Kick the first URB off the hardware, if needed */ | ||
150 | qh->is_ready = 0; | ||
151 | - if (!sched || qh == first_qh(sched)) { | ||
152 | + if (musb_ep_get_qh(qh->hw_ep, is_in) == qh) { | ||
153 | urb = next_urb(qh); | ||
154 | |||
155 | /* make software (then hardware) stop ASAP */ | ||
156 | -- | ||
157 | 1.6.0.4 | ||
158 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0020-musb_host-streamline-musb_cleanup_urb-calls.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0020-musb_host-streamline-musb_cleanup_urb-calls.patch deleted file mode 100644 index d89eaadd61..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0020-musb_host-streamline-musb_cleanup_urb-calls.patch +++ /dev/null | |||
@@ -1,58 +0,0 @@ | |||
1 | From d408894fa4263440ed8a9e68566bacea7e6f6bed Mon Sep 17 00:00:00 2001 | ||
2 | From: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
3 | Date: Fri, 27 Mar 2009 12:57:50 -0700 | ||
4 | Subject: [PATCH] musb_host: streamline musb_cleanup_urb() calls | ||
5 | |||
6 | The argument for the 'is_in' parameter of musb_cleanup_urb() | ||
7 | is always extracted from an URB that's passed to the function. | ||
8 | So that parameter is superfluous; remove it. | ||
9 | |||
10 | Signed-off-by: Sergei Shtylyov <sshtylyov-hkdhdckH98+B+jHODAdFcQ@public.gmane.org> | ||
11 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
12 | --- | ||
13 | drivers/usb/musb/musb_host.c | 9 +++++---- | ||
14 | 1 files changed, 5 insertions(+), 4 deletions(-) | ||
15 | |||
16 | diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c | ||
17 | index e121e0e..71e835e 100644 | ||
18 | --- a/drivers/usb/musb/musb_host.c | ||
19 | +++ b/drivers/usb/musb/musb_host.c | ||
20 | @@ -1950,14 +1950,15 @@ done: | ||
21 | * called with controller locked, irqs blocked | ||
22 | * that hardware queue advances to the next transfer, unless prevented | ||
23 | */ | ||
24 | -static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh, int is_in) | ||
25 | +static int musb_cleanup_urb(struct urb *urb, struct musb_qh *qh) | ||
26 | { | ||
27 | struct musb_hw_ep *ep = qh->hw_ep; | ||
28 | void __iomem *epio = ep->regs; | ||
29 | unsigned hw_end = ep->epnum; | ||
30 | void __iomem *regs = ep->musb->mregs; | ||
31 | - u16 csr; | ||
32 | + int is_in = usb_pipein(urb->pipe); | ||
33 | int status = 0; | ||
34 | + u16 csr; | ||
35 | |||
36 | musb_ep_select(regs, hw_end); | ||
37 | |||
38 | @@ -2056,7 +2057,7 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | ||
39 | kfree(qh); | ||
40 | } | ||
41 | } else | ||
42 | - ret = musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN); | ||
43 | + ret = musb_cleanup_urb(urb, qh); | ||
44 | done: | ||
45 | spin_unlock_irqrestore(&musb->lock, flags); | ||
46 | return ret; | ||
47 | @@ -2090,7 +2091,7 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) | ||
48 | urb->status = -ESHUTDOWN; | ||
49 | |||
50 | /* cleanup */ | ||
51 | - musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN); | ||
52 | + musb_cleanup_urb(urb, qh); | ||
53 | |||
54 | /* Then nuke all the others ... and advance the | ||
55 | * queue on hw_ep (e.g. bulk ring) when we're done. | ||
56 | -- | ||
57 | 1.6.0.4 | ||
58 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0021-twl4030-usb-fix-minor-reporting-goofage.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0021-twl4030-usb-fix-minor-reporting-goofage.patch deleted file mode 100644 index d9733f92b0..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0021-twl4030-usb-fix-minor-reporting-goofage.patch +++ /dev/null | |||
@@ -1,70 +0,0 @@ | |||
1 | From c4804e5a447275553c55bbb0ab1748954cb8fbfc Mon Sep 17 00:00:00 2001 | ||
2 | From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
3 | Date: Tue, 31 Mar 2009 12:26:10 -0700 | ||
4 | Subject: [PATCH] twl4030-usb: fix minor reporting goofage | ||
5 | |||
6 | Fix a reporting glitch in the twl4030 USB transceiver code. | ||
7 | It wasn't properly distinguishing the two types of active | ||
8 | USB link: ID grounded, vs not. In the current code that | ||
9 | distinction doesn't much matter; in the future this bugfix | ||
10 | should help support better USB controller communications. | ||
11 | |||
12 | Provide a comment sorting out some of the cryptic bits of | ||
13 | the manual: different sections use different names for | ||
14 | key signals, and the register definitions don't help much | ||
15 | without the explanations and diagrams. | ||
16 | |||
17 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
18 | --- | ||
19 | drivers/usb/otg/twl4030-usb.c | 26 +++++++++++++++++++------- | ||
20 | 1 files changed, 19 insertions(+), 7 deletions(-) | ||
21 | |||
22 | diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c | ||
23 | index d9478d0..f740390 100644 | ||
24 | --- a/drivers/usb/otg/twl4030-usb.c | ||
25 | +++ b/drivers/usb/otg/twl4030-usb.c | ||
26 | @@ -217,6 +217,7 @@ | ||
27 | |||
28 | /* In module TWL4030_MODULE_PM_MASTER */ | ||
29 | #define PROTECT_KEY 0x0E | ||
30 | +#define STS_HW_CONDITIONS 0x0F | ||
31 | |||
32 | /* In module TWL4030_MODULE_PM_RECEIVER */ | ||
33 | #define VUSB_DEDICATED1 0x7D | ||
34 | @@ -351,15 +352,26 @@ static enum linkstat twl4030_usb_linkstat(struct twl4030_usb *twl) | ||
35 | int status; | ||
36 | int linkstat = USB_LINK_UNKNOWN; | ||
37 | |||
38 | - /* STS_HW_CONDITIONS */ | ||
39 | - status = twl4030_readb(twl, TWL4030_MODULE_PM_MASTER, 0x0f); | ||
40 | + /* | ||
41 | + * For ID/VBUS sensing, see manual section 15.4.8 ... | ||
42 | + * except when using only battery backup power, two | ||
43 | + * comparators produce VBUS_PRES and ID_PRES signals, | ||
44 | + * which don't match docs elsewhere. But ... BIT(7) | ||
45 | + * and BIT(2) of STS_HW_CONDITIONS, respectively, do | ||
46 | + * seem to match up. If either is true the USB_PRES | ||
47 | + * signal is active, the OTG module is activated, and | ||
48 | + * its interrupt may be raised (may wake the system). | ||
49 | + */ | ||
50 | + status = twl4030_readb(twl, TWL4030_MODULE_PM_MASTER, | ||
51 | + STS_HW_CONDITIONS); | ||
52 | if (status < 0) | ||
53 | dev_err(twl->dev, "USB link status err %d\n", status); | ||
54 | - else if (status & BIT(7)) | ||
55 | - linkstat = USB_LINK_VBUS; | ||
56 | - else if (status & BIT(2)) | ||
57 | - linkstat = USB_LINK_ID; | ||
58 | - else | ||
59 | + else if (status & (BIT(7) | BIT(2))) { | ||
60 | + if (status & BIT(2)) | ||
61 | + linkstat = USB_LINK_ID; | ||
62 | + else | ||
63 | + linkstat = USB_LINK_VBUS; | ||
64 | + } else | ||
65 | linkstat = USB_LINK_NONE; | ||
66 | |||
67 | dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n", | ||
68 | -- | ||
69 | 1.6.0.4 | ||
70 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0022-musb-use-dma-mode-1-for-TX-if-transfer-size-equals.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0022-musb-use-dma-mode-1-for-TX-if-transfer-size-equals.patch deleted file mode 100644 index 16b5b9908b..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0022-musb-use-dma-mode-1-for-TX-if-transfer-size-equals.patch +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | From ba59a0812ba0e223bd0af8f4dea6c971b6289696 Mon Sep 17 00:00:00 2001 | ||
2 | From: Anand Gadiyar <gadiyar-l0cyMroinI0@public.gmane.org> | ||
3 | Date: Thu, 2 Apr 2009 12:07:08 -0700 | ||
4 | Subject: [PATCH] musb: use dma mode 1 for TX if transfer size equals maxpacket (v2) | ||
5 | |||
6 | Currently, with Inventra DMA, we use Mode 0 if transfer size is less | ||
7 | than or equal to the endpoint's maxpacket size. This requires that | ||
8 | we explicitly set TXPKTRDY for that transfer. | ||
9 | |||
10 | However the musb_g_tx code will not set TXPKTRDY twice if the last | ||
11 | transfer is exactly equal to maxpacket, even if request->zero is set. | ||
12 | Using Mode 1 will solve this; a better fix might be in musb_g_tx(). | ||
13 | |||
14 | Without this change, musb will not correctly send out a ZLP if the | ||
15 | last transfer is the maxpacket size and request->zero is set. | ||
16 | |||
17 | Signed-off-by: Anand Gadiyar <gadiyar-l0cyMroinI0@public.gmane.org> | ||
18 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
19 | --- | ||
20 | drivers/usb/musb/musb_gadget.c | 2 +- | ||
21 | 1 files changed, 1 insertions(+), 1 deletions(-) | ||
22 | |||
23 | diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c | ||
24 | index bc197b2..e8f920c 100644 | ||
25 | --- a/drivers/usb/musb/musb_gadget.c | ||
26 | +++ b/drivers/usb/musb/musb_gadget.c | ||
27 | @@ -310,7 +310,7 @@ static void txstate(struct musb *musb, struct musb_request *req) | ||
28 | /* setup DMA, then program endpoint CSR */ | ||
29 | request_size = min(request->length, | ||
30 | musb_ep->dma->max_len); | ||
31 | - if (request_size <= musb_ep->packet_sz) | ||
32 | + if (request_size < musb_ep->packet_sz) | ||
33 | musb_ep->dma->desired_mode = 0; | ||
34 | else | ||
35 | musb_ep->dma->desired_mode = 1; | ||
36 | -- | ||
37 | 1.6.0.4 | ||
38 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0023-musb-add-high-bandwidth-ISO-support.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0023-musb-add-high-bandwidth-ISO-support.patch deleted file mode 100644 index 3038dd171d..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0023-musb-add-high-bandwidth-ISO-support.patch +++ /dev/null | |||
@@ -1,187 +0,0 @@ | |||
1 | From 2e049a88b729ae2fdc0ecdabad1857810bd62737 Mon Sep 17 00:00:00 2001 | ||
2 | From: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org> | ||
3 | Date: Fri, 3 Apr 2009 16:16:17 -0700 | ||
4 | Subject: [PATCH] musb: add high bandwidth ISO support | ||
5 | |||
6 | Tested on OMAP3 host side with Creative (Live! Cam Optia) USB camera | ||
7 | which uses high bandwidth isochronous IN endpoints. FIFO mode 4 is | ||
8 | updated to provide the needed 4K endpoint buffer without breaking | ||
9 | the g_nokia composite gadget configuration. (This is the only | ||
10 | gadget driver known to use enough endpoints to notice the change.) | ||
11 | |||
12 | Signed-off-by: Ajay Kumar Gupta <ajay.gupta-l0cyMroinI0@public.gmane.org> | ||
13 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
14 | --- | ||
15 | drivers/usb/musb/musb_core.c | 19 ++++++++--------- | ||
16 | drivers/usb/musb/musb_core.h | 3 ++ | ||
17 | drivers/usb/musb/musb_host.c | 47 +++++++++++++++++++++++++++++++---------- | ||
18 | drivers/usb/musb/musb_host.h | 1 + | ||
19 | 4 files changed, 48 insertions(+), 22 deletions(-) | ||
20 | |||
21 | diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c | ||
22 | index a1de43b..d953305 100644 | ||
23 | --- a/drivers/usb/musb/musb_core.c | ||
24 | +++ b/drivers/usb/musb/musb_core.c | ||
25 | @@ -1068,14 +1068,13 @@ static struct fifo_cfg __initdata mode_4_cfg[] = { | ||
26 | { .hw_ep_num = 8, .style = FIFO_RX, .maxpacket = 512, }, | ||
27 | { .hw_ep_num = 9, .style = FIFO_TX, .maxpacket = 512, }, | ||
28 | { .hw_ep_num = 9, .style = FIFO_RX, .maxpacket = 512, }, | ||
29 | -{ .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 512, }, | ||
30 | -{ .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 512, }, | ||
31 | -{ .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 512, }, | ||
32 | -{ .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 512, }, | ||
33 | -{ .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 512, }, | ||
34 | -{ .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 512, }, | ||
35 | -{ .hw_ep_num = 13, .style = FIFO_TX, .maxpacket = 512, }, | ||
36 | -{ .hw_ep_num = 13, .style = FIFO_RX, .maxpacket = 512, }, | ||
37 | +{ .hw_ep_num = 10, .style = FIFO_TX, .maxpacket = 256, }, | ||
38 | +{ .hw_ep_num = 10, .style = FIFO_RX, .maxpacket = 64, }, | ||
39 | +{ .hw_ep_num = 11, .style = FIFO_TX, .maxpacket = 256, }, | ||
40 | +{ .hw_ep_num = 11, .style = FIFO_RX, .maxpacket = 64, }, | ||
41 | +{ .hw_ep_num = 12, .style = FIFO_TX, .maxpacket = 256, }, | ||
42 | +{ .hw_ep_num = 12, .style = FIFO_RX, .maxpacket = 64, }, | ||
43 | +{ .hw_ep_num = 13, .style = FIFO_RXTX, .maxpacket = 4096, }, | ||
44 | { .hw_ep_num = 14, .style = FIFO_RXTX, .maxpacket = 1024, }, | ||
45 | { .hw_ep_num = 15, .style = FIFO_RXTX, .maxpacket = 1024, }, | ||
46 | }; | ||
47 | @@ -1335,11 +1334,11 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb) | ||
48 | } | ||
49 | if (reg & MUSB_CONFIGDATA_HBRXE) { | ||
50 | strcat(aInfo, ", HB-ISO Rx"); | ||
51 | - strcat(aInfo, " (X)"); /* no driver support */ | ||
52 | + musb->hb_iso_rx = true; | ||
53 | } | ||
54 | if (reg & MUSB_CONFIGDATA_HBTXE) { | ||
55 | strcat(aInfo, ", HB-ISO Tx"); | ||
56 | - strcat(aInfo, " (X)"); /* no driver support */ | ||
57 | + musb->hb_iso_tx = true; | ||
58 | } | ||
59 | if (reg & MUSB_CONFIGDATA_SOFTCONE) | ||
60 | strcat(aInfo, ", SoftConn"); | ||
61 | diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h | ||
62 | index f56a56c..0ac4faf 100644 | ||
63 | --- a/drivers/usb/musb/musb_core.h | ||
64 | +++ b/drivers/usb/musb/musb_core.h | ||
65 | @@ -387,6 +387,9 @@ struct musb { | ||
66 | unsigned is_multipoint:1; | ||
67 | unsigned ignore_disconnect:1; /* during bus resets */ | ||
68 | |||
69 | + unsigned hb_iso_rx:1; /* high bandwidth iso rx? */ | ||
70 | + unsigned hb_iso_tx:1; /* high bandwidth iso tx? */ | ||
71 | + | ||
72 | #ifdef C_MP_TX | ||
73 | unsigned bulk_split:1; | ||
74 | #define can_bulk_split(musb,type) \ | ||
75 | diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c | ||
76 | index 71e835e..ece5122 100644 | ||
77 | --- a/drivers/usb/musb/musb_host.c | ||
78 | +++ b/drivers/usb/musb/musb_host.c | ||
79 | @@ -602,7 +602,8 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, struct musb_hw_ep *ep) | ||
80 | musb_writeb(ep->regs, MUSB_RXTYPE, qh->type_reg); | ||
81 | musb_writeb(ep->regs, MUSB_RXINTERVAL, qh->intv_reg); | ||
82 | /* NOTE: bulk combining rewrites high bits of maxpacket */ | ||
83 | - musb_writew(ep->regs, MUSB_RXMAXP, qh->maxpacket); | ||
84 | + musb_writew(ep->regs, MUSB_RXMAXP, | ||
85 | + qh->maxpacket | ((qh->hb_mult - 1) << 11)); | ||
86 | |||
87 | ep->rx_reinit = 0; | ||
88 | } | ||
89 | @@ -624,9 +625,10 @@ static bool musb_tx_dma_program(struct dma_controller *dma, | ||
90 | csr = musb_readw(epio, MUSB_TXCSR); | ||
91 | if (length > pkt_size) { | ||
92 | mode = 1; | ||
93 | - csr |= MUSB_TXCSR_AUTOSET | ||
94 | - | MUSB_TXCSR_DMAMODE | ||
95 | - | MUSB_TXCSR_DMAENAB; | ||
96 | + csr |= MUSB_TXCSR_DMAMODE | MUSB_TXCSR_DMAENAB; | ||
97 | + /* autoset shouldn't be set in high bandwidth */ | ||
98 | + if (qh->hb_mult == 1) | ||
99 | + csr |= MUSB_TXCSR_AUTOSET; | ||
100 | } else { | ||
101 | mode = 0; | ||
102 | csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAMODE); | ||
103 | @@ -1432,6 +1434,10 @@ void musb_host_rx(struct musb *musb, u8 epnum) | ||
104 | /* packet error reported later */ | ||
105 | iso_err = true; | ||
106 | } | ||
107 | + } else if (rx_csr & MUSB_RXCSR_INCOMPRX) { | ||
108 | + DBG(3, "end %d high bandwidth incomplete ISO packet RX\n", | ||
109 | + epnum); | ||
110 | + status = -EPROTO; | ||
111 | } | ||
112 | |||
113 | /* faults abort the transfer */ | ||
114 | @@ -1639,7 +1645,11 @@ void musb_host_rx(struct musb *musb, u8 epnum) | ||
115 | val &= ~MUSB_RXCSR_H_AUTOREQ; | ||
116 | else | ||
117 | val |= MUSB_RXCSR_H_AUTOREQ; | ||
118 | - val |= MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAENAB; | ||
119 | + val |= MUSB_RXCSR_DMAENAB; | ||
120 | + | ||
121 | + /* autoclear shouldn't be set in high bandwidth */ | ||
122 | + if (qh->hb_mult == 1) | ||
123 | + val |= MUSB_RXCSR_AUTOCLEAR; | ||
124 | |||
125 | musb_writew(epio, MUSB_RXCSR, | ||
126 | MUSB_RXCSR_H_WZC_BITS | val); | ||
127 | @@ -1725,9 +1735,10 @@ static int musb_schedule( | ||
128 | continue; | ||
129 | |||
130 | if (is_in) | ||
131 | - diff = hw_ep->max_packet_sz_rx - qh->maxpacket; | ||
132 | + diff = hw_ep->max_packet_sz_rx; | ||
133 | else | ||
134 | - diff = hw_ep->max_packet_sz_tx - qh->maxpacket; | ||
135 | + diff = hw_ep->max_packet_sz_tx; | ||
136 | + diff -= (qh->maxpacket * qh->hb_mult); | ||
137 | |||
138 | if (diff >= 0 && best_diff > diff) { | ||
139 | best_diff = diff; | ||
140 | @@ -1830,15 +1841,27 @@ static int musb_urb_enqueue( | ||
141 | qh->is_ready = 1; | ||
142 | |||
143 | qh->maxpacket = le16_to_cpu(epd->wMaxPacketSize); | ||
144 | + qh->type = usb_endpoint_type(epd); | ||
145 | |||
146 | - /* no high bandwidth support yet */ | ||
147 | - if (qh->maxpacket & ~0x7ff) { | ||
148 | - ret = -EMSGSIZE; | ||
149 | - goto done; | ||
150 | + /* Bits 11 & 12 of wMaxPacketSize encode high bandwidth multiplier. | ||
151 | + * Some musb cores don't support high bandwidth ISO transfers; and | ||
152 | + * we don't (yet!) support high bandwidth interrupt transfers. | ||
153 | + */ | ||
154 | + qh->hb_mult = 1 + ((qh->maxpacket >> 11) & 0x03); | ||
155 | + if (qh->hb_mult > 1) { | ||
156 | + int ok = (qh->type == USB_ENDPOINT_XFER_ISOC); | ||
157 | + | ||
158 | + if (ok) | ||
159 | + ok = (usb_pipein(urb->pipe) && musb->hb_iso_rx) | ||
160 | + || (usb_pipeout(urb->pipe) && musb->hb_iso_tx); | ||
161 | + if (!ok) { | ||
162 | + ret = -EMSGSIZE; | ||
163 | + goto done; | ||
164 | + } | ||
165 | + qh->maxpacket &= 0x7ff; | ||
166 | } | ||
167 | |||
168 | qh->epnum = usb_endpoint_num(epd); | ||
169 | - qh->type = usb_endpoint_type(epd); | ||
170 | |||
171 | /* NOTE: urb->dev->devnum is wrong during SET_ADDRESS */ | ||
172 | qh->addr_reg = (u8) usb_pipedevice(urb->pipe); | ||
173 | diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h | ||
174 | index 0b7fbcd..14b0077 100644 | ||
175 | --- a/drivers/usb/musb/musb_host.h | ||
176 | +++ b/drivers/usb/musb/musb_host.h | ||
177 | @@ -67,6 +67,7 @@ struct musb_qh { | ||
178 | u8 is_ready; /* safe to modify hw_ep */ | ||
179 | u8 type; /* XFERTYPE_* */ | ||
180 | u8 epnum; | ||
181 | + u8 hb_mult; /* high bandwidth pkts per uf */ | ||
182 | u16 maxpacket; | ||
183 | u16 frame; /* for periodic schedule */ | ||
184 | unsigned iso_idx; /* in urb->iso_frame_desc[] */ | ||
185 | -- | ||
186 | 1.6.0.4 | ||
187 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0024-USB-otg-adding-nop-usb-transceiver.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0024-USB-otg-adding-nop-usb-transceiver.patch deleted file mode 100644 index 67004d7ec6..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0024-USB-otg-adding-nop-usb-transceiver.patch +++ /dev/null | |||
@@ -1,259 +0,0 @@ | |||
1 | From de835357b3597af5304742cbd89771d70533292a Mon Sep 17 00:00:00 2001 | ||
2 | From: Ajay Kumar Gupta <ajay.gupta@ti.com> | ||
3 | Date: Fri, 6 Feb 2009 17:32:35 +0530 | ||
4 | Subject: [PATCH] USB: otg: adding nop usb transceiver | ||
5 | |||
6 | NOP transceiver is used by all the usb transceiver which are mostly | ||
7 | autonomous and doesn't require any programming or which are built | ||
8 | into the usb ip itself.NOP transceiver only allocates the memory | ||
9 | for struct xceiv and calls otg_set_transceiver() so function call | ||
10 | to otg_get_transceiver() will return a valid transceiver. | ||
11 | |||
12 | NOP transceiver device should be registered by calling | ||
13 | usb_nop_xceiv_register() from platform files. | ||
14 | |||
15 | Signed-off-by: Ajay Kumar Gupta <ajay.gupta@ti.com> | ||
16 | Cc: Felipe Balbi <felipe.balbi@nokia.com> | ||
17 | Cc: David Brownell <dbrownell@users.sourceforge.net> | ||
18 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | ||
19 | --- | ||
20 | drivers/usb/otg/Kconfig | 8 ++ | ||
21 | drivers/usb/otg/Makefile | 1 + | ||
22 | drivers/usb/otg/nop-usb-xceiv.c | 180 +++++++++++++++++++++++++++++++++++++++ | ||
23 | include/linux/usb/otg.h | 4 + | ||
24 | 4 files changed, 193 insertions(+), 0 deletions(-) | ||
25 | create mode 100644 drivers/usb/otg/nop-usb-xceiv.c | ||
26 | |||
27 | diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig | ||
28 | index 5790a5b..aa884d0 100644 | ||
29 | --- a/drivers/usb/otg/Kconfig | ||
30 | +++ b/drivers/usb/otg/Kconfig | ||
31 | @@ -51,4 +51,12 @@ config TWL4030_USB | ||
32 | This transceiver supports high and full speed devices plus, | ||
33 | in host mode, low speed. | ||
34 | |||
35 | +config NOP_USB_XCEIV | ||
36 | + tristate "NOP USB Transceiver Driver" | ||
37 | + select USB_OTG_UTILS | ||
38 | + help | ||
39 | + this driver is to be used by all the usb transceiver which are either | ||
40 | + built-in with usb ip or which are autonomous and doesn't require any | ||
41 | + phy programming such as ISP1x04 etc. | ||
42 | + | ||
43 | endif # USB || OTG | ||
44 | diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile | ||
45 | index d73c7cf..2081678 100644 | ||
46 | --- a/drivers/usb/otg/Makefile | ||
47 | +++ b/drivers/usb/otg/Makefile | ||
48 | @@ -9,6 +9,7 @@ obj-$(CONFIG_USB_OTG_UTILS) += otg.o | ||
49 | obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o | ||
50 | obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o | ||
51 | obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o | ||
52 | +obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o | ||
53 | |||
54 | ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG | ||
55 | ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG | ||
56 | diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c | ||
57 | new file mode 100644 | ||
58 | index 0000000..4b933f6 | ||
59 | --- /dev/null | ||
60 | +++ b/drivers/usb/otg/nop-usb-xceiv.c | ||
61 | @@ -0,0 +1,180 @@ | ||
62 | +/* | ||
63 | + * drivers/usb/otg/nop-usb-xceiv.c | ||
64 | + * | ||
65 | + * NOP USB transceiver for all USB transceiver which are either built-in | ||
66 | + * into USB IP or which are mostly autonomous. | ||
67 | + * | ||
68 | + * Copyright (C) 2009 Texas Instruments Inc | ||
69 | + * Author: Ajay Kumar Gupta <ajay.gupta@ti.com> | ||
70 | + * | ||
71 | + * This program is free software; you can redistribute it and/or modify | ||
72 | + * it under the terms of the GNU General Public License as published by | ||
73 | + * the Free Software Foundation; either version 2 of the License, or | ||
74 | + * (at your option) any later version. | ||
75 | + * | ||
76 | + * This program is distributed in the hope that it will be useful, | ||
77 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
78 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
79 | + * GNU General Public License for more details. | ||
80 | + * | ||
81 | + * You should have received a copy of the GNU General Public License | ||
82 | + * along with this program; if not, write to the Free Software | ||
83 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
84 | + * | ||
85 | + * Current status: | ||
86 | + * this is to add "nop" transceiver for all those phy which is | ||
87 | + * autonomous such as isp1504 etc. | ||
88 | + */ | ||
89 | + | ||
90 | +#include <linux/module.h> | ||
91 | +#include <linux/platform_device.h> | ||
92 | +#include <linux/dma-mapping.h> | ||
93 | +#include <linux/usb/otg.h> | ||
94 | + | ||
95 | +struct nop_usb_xceiv { | ||
96 | + struct otg_transceiver otg; | ||
97 | + struct device *dev; | ||
98 | +}; | ||
99 | + | ||
100 | +static u64 nop_xceiv_dmamask = DMA_32BIT_MASK; | ||
101 | + | ||
102 | +static struct platform_device nop_xceiv_device = { | ||
103 | + .name = "nop_usb_xceiv", | ||
104 | + .id = -1, | ||
105 | + .dev = { | ||
106 | + .dma_mask = &nop_xceiv_dmamask, | ||
107 | + .coherent_dma_mask = DMA_32BIT_MASK, | ||
108 | + .platform_data = NULL, | ||
109 | + }, | ||
110 | +}; | ||
111 | + | ||
112 | +void usb_nop_xceiv_register(void) | ||
113 | +{ | ||
114 | + if (platform_device_register(&nop_xceiv_device) < 0) { | ||
115 | + printk(KERN_ERR "Unable to register usb nop transceiver\n"); | ||
116 | + return; | ||
117 | + } | ||
118 | +} | ||
119 | + | ||
120 | +void usb_nop_xceiv_unregister(void) | ||
121 | +{ | ||
122 | + platform_device_unregister(&nop_xceiv_device); | ||
123 | +} | ||
124 | + | ||
125 | +static inline struct nop_usb_xceiv *xceiv_to_nop(struct otg_transceiver *x) | ||
126 | +{ | ||
127 | + return container_of(x, struct nop_usb_xceiv, otg); | ||
128 | +} | ||
129 | + | ||
130 | +static int nop_set_suspend(struct otg_transceiver *x, int suspend) | ||
131 | +{ | ||
132 | + return 0; | ||
133 | +} | ||
134 | + | ||
135 | +static int nop_set_peripheral(struct otg_transceiver *x, | ||
136 | + struct usb_gadget *gadget) | ||
137 | +{ | ||
138 | + struct nop_usb_xceiv *nop; | ||
139 | + | ||
140 | + if (!x) | ||
141 | + return -ENODEV; | ||
142 | + | ||
143 | + nop = xceiv_to_nop(x); | ||
144 | + | ||
145 | + if (!gadget) { | ||
146 | + nop->otg.gadget = NULL; | ||
147 | + return -ENODEV; | ||
148 | + } | ||
149 | + | ||
150 | + nop->otg.gadget = gadget; | ||
151 | + nop->otg.state = OTG_STATE_B_IDLE; | ||
152 | + return 0; | ||
153 | +} | ||
154 | + | ||
155 | +static int nop_set_host(struct otg_transceiver *x, struct usb_bus *host) | ||
156 | +{ | ||
157 | + struct nop_usb_xceiv *nop; | ||
158 | + | ||
159 | + if (!x) | ||
160 | + return -ENODEV; | ||
161 | + | ||
162 | + nop = xceiv_to_nop(x); | ||
163 | + | ||
164 | + if (!host) { | ||
165 | + nop->otg.host = NULL; | ||
166 | + return -ENODEV; | ||
167 | + } | ||
168 | + | ||
169 | + nop->otg.host = host; | ||
170 | + return 0; | ||
171 | +} | ||
172 | + | ||
173 | +static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) | ||
174 | +{ | ||
175 | + struct nop_usb_xceiv *nop; | ||
176 | + int err; | ||
177 | + | ||
178 | + nop = kzalloc(sizeof *nop, GFP_KERNEL); | ||
179 | + if (!nop) | ||
180 | + return -ENOMEM; | ||
181 | + | ||
182 | + nop->dev = &pdev->dev; | ||
183 | + nop->otg.dev = nop->dev; | ||
184 | + nop->otg.label = "nop-xceiv"; | ||
185 | + nop->otg.state = OTG_STATE_UNDEFINED; | ||
186 | + nop->otg.set_host = nop_set_host; | ||
187 | + nop->otg.set_peripheral = nop_set_peripheral; | ||
188 | + nop->otg.set_suspend = nop_set_suspend; | ||
189 | + | ||
190 | + err = otg_set_transceiver(&nop->otg); | ||
191 | + if (err) { | ||
192 | + dev_err(&pdev->dev, "can't register transceiver, err: %d\n", | ||
193 | + err); | ||
194 | + goto exit; | ||
195 | + } | ||
196 | + | ||
197 | + platform_set_drvdata(pdev, nop); | ||
198 | + | ||
199 | + return 0; | ||
200 | +exit: | ||
201 | + kfree(nop); | ||
202 | + return err; | ||
203 | +} | ||
204 | + | ||
205 | +static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev) | ||
206 | +{ | ||
207 | + struct nop_usb_xceiv *nop = platform_get_drvdata(pdev); | ||
208 | + | ||
209 | + otg_set_transceiver(NULL); | ||
210 | + | ||
211 | + platform_set_drvdata(pdev, NULL); | ||
212 | + kfree(nop); | ||
213 | + | ||
214 | + return 0; | ||
215 | +} | ||
216 | + | ||
217 | +static struct platform_driver nop_usb_xceiv_driver = { | ||
218 | + .probe = nop_usb_xceiv_probe, | ||
219 | + .remove = __devexit_p(nop_usb_xceiv_remove), | ||
220 | + .driver = { | ||
221 | + .name = "nop_usb_xceiv", | ||
222 | + .owner = THIS_MODULE, | ||
223 | + }, | ||
224 | +}; | ||
225 | + | ||
226 | +static int __init nop_usb_xceiv_init(void) | ||
227 | +{ | ||
228 | + return platform_driver_register(&nop_usb_xceiv_driver); | ||
229 | +} | ||
230 | +subsys_initcall(nop_usb_xceiv_init); | ||
231 | + | ||
232 | +static void __exit nop_usb_xceiv_exit(void) | ||
233 | +{ | ||
234 | + platform_driver_unregister(&nop_usb_xceiv_driver); | ||
235 | +} | ||
236 | +module_exit(nop_usb_xceiv_exit); | ||
237 | + | ||
238 | +MODULE_ALIAS("platform:nop_usb_xceiv"); | ||
239 | +MODULE_AUTHOR("Texas Instruments Inc"); | ||
240 | +MODULE_DESCRIPTION("NOP USB Transceiver driver"); | ||
241 | +MODULE_LICENSE("GPL"); | ||
242 | diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h | ||
243 | index 94df4fe..54f2424 100644 | ||
244 | --- a/include/linux/usb/otg.h | ||
245 | +++ b/include/linux/usb/otg.h | ||
246 | @@ -80,6 +80,10 @@ struct otg_transceiver { | ||
247 | |||
248 | /* for board-specific init logic */ | ||
249 | extern int otg_set_transceiver(struct otg_transceiver *); | ||
250 | +#ifdef CONFIG_NOP_USB_XCEIV | ||
251 | +extern void usb_nop_xceiv_register(void); | ||
252 | +extern void usb_nop_xceiv_unregister(void); | ||
253 | +#endif | ||
254 | |||
255 | |||
256 | /* for usb host and peripheral controller drivers */ | ||
257 | -- | ||
258 | 1.6.0.4 | ||
259 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0025-nop-usb-xceiv-behave-when-linked-as-a-module.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0025-nop-usb-xceiv-behave-when-linked-as-a-module.patch deleted file mode 100644 index 21fe7bea17..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0025-nop-usb-xceiv-behave-when-linked-as-a-module.patch +++ /dev/null | |||
@@ -1,90 +0,0 @@ | |||
1 | From ae4f027580168814f734cf3c41a662a7f10c744c Mon Sep 17 00:00:00 2001 | ||
2 | From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
3 | Date: Tue, 31 Mar 2009 12:28:31 -0700 | ||
4 | Subject: [PATCH] nop-usb-xceiv: behave when linked as a module | ||
5 | |||
6 | The NOP OTG transceiver driver needs to be usable from modules. | ||
7 | Make sure its symbols are always accessible at both compile and | ||
8 | link time, and make sure the device instance is allocated from | ||
9 | the heap so that device lifetime rules are obeyed. | ||
10 | |||
11 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
12 | --- | ||
13 | drivers/usb/otg/nop-usb-xceiv.c | 25 ++++++++++--------------- | ||
14 | include/linux/usb/otg.h | 4 ++-- | ||
15 | 2 files changed, 12 insertions(+), 17 deletions(-) | ||
16 | |||
17 | diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c | ||
18 | index 4b933f6..9ed5ea5 100644 | ||
19 | --- a/drivers/usb/otg/nop-usb-xceiv.c | ||
20 | +++ b/drivers/usb/otg/nop-usb-xceiv.c | ||
21 | @@ -22,8 +22,8 @@ | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | * | ||
24 | * Current status: | ||
25 | - * this is to add "nop" transceiver for all those phy which is | ||
26 | - * autonomous such as isp1504 etc. | ||
27 | + * This provides a "nop" transceiver for PHYs which are | ||
28 | + * autonomous such as isp1504, isp1707, etc. | ||
29 | */ | ||
30 | |||
31 | #include <linux/module.h> | ||
32 | @@ -36,30 +36,25 @@ struct nop_usb_xceiv { | ||
33 | struct device *dev; | ||
34 | }; | ||
35 | |||
36 | -static u64 nop_xceiv_dmamask = DMA_32BIT_MASK; | ||
37 | - | ||
38 | -static struct platform_device nop_xceiv_device = { | ||
39 | - .name = "nop_usb_xceiv", | ||
40 | - .id = -1, | ||
41 | - .dev = { | ||
42 | - .dma_mask = &nop_xceiv_dmamask, | ||
43 | - .coherent_dma_mask = DMA_32BIT_MASK, | ||
44 | - .platform_data = NULL, | ||
45 | - }, | ||
46 | -}; | ||
47 | +static struct platform_device *pd; | ||
48 | |||
49 | void usb_nop_xceiv_register(void) | ||
50 | { | ||
51 | - if (platform_device_register(&nop_xceiv_device) < 0) { | ||
52 | + if (pd) | ||
53 | + return; | ||
54 | + pd = platform_device_register_simple("nop_usb_xceiv", -1, NULL, 0); | ||
55 | + if (!pd) { | ||
56 | printk(KERN_ERR "Unable to register usb nop transceiver\n"); | ||
57 | return; | ||
58 | } | ||
59 | } | ||
60 | +EXPORT_SYMBOL(usb_nop_xceiv_register); | ||
61 | |||
62 | void usb_nop_xceiv_unregister(void) | ||
63 | { | ||
64 | - platform_device_unregister(&nop_xceiv_device); | ||
65 | + platform_device_unregister(pd); | ||
66 | } | ||
67 | +EXPORT_SYMBOL(usb_nop_xceiv_unregister); | ||
68 | |||
69 | static inline struct nop_usb_xceiv *xceiv_to_nop(struct otg_transceiver *x) | ||
70 | { | ||
71 | diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h | ||
72 | index 54f2424..7df8bae 100644 | ||
73 | --- a/include/linux/usb/otg.h | ||
74 | +++ b/include/linux/usb/otg.h | ||
75 | @@ -80,10 +80,10 @@ struct otg_transceiver { | ||
76 | |||
77 | /* for board-specific init logic */ | ||
78 | extern int otg_set_transceiver(struct otg_transceiver *); | ||
79 | -#ifdef CONFIG_NOP_USB_XCEIV | ||
80 | + | ||
81 | +/* sometimes transceivers are accessed only through e.g. ULPI */ | ||
82 | extern void usb_nop_xceiv_register(void); | ||
83 | extern void usb_nop_xceiv_unregister(void); | ||
84 | -#endif | ||
85 | |||
86 | |||
87 | /* for usb host and peripheral controller drivers */ | ||
88 | -- | ||
89 | 1.6.0.4 | ||
90 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0026-musb-proper-hookup-to-transceiver-drivers.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0026-musb-proper-hookup-to-transceiver-drivers.patch deleted file mode 100644 index 035a6c7676..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0026-musb-proper-hookup-to-transceiver-drivers.patch +++ /dev/null | |||
@@ -1,1109 +0,0 @@ | |||
1 | From 43ee46723ffa9dd43d611362064d235440aa04e7 Mon Sep 17 00:00:00 2001 | ||
2 | From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
3 | Date: Tue, 31 Mar 2009 12:30:04 -0700 | ||
4 | Subject: [PATCH] musb: proper hookup to transceiver drivers | ||
5 | |||
6 | Let the otg_transceiver in MUSB be managed by an external driver; | ||
7 | don't assume it's integrated. OMAP3 chips need it to be external, | ||
8 | and there may be ways to interact with the transceiver which add | ||
9 | functionality to the system. | ||
10 | |||
11 | Platform init code is responsible for setting up the transeciver, | ||
12 | probably using the NOP transceiver for integrated transceivers. | ||
13 | External ones will use whatever the board init code provided, | ||
14 | such as twl4030 or something more hands-off. | ||
15 | |||
16 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
17 | --- | ||
18 | drivers/usb/musb/Kconfig | 2 + | ||
19 | drivers/usb/musb/blackfin.c | 11 +++- | ||
20 | drivers/usb/musb/davinci.c | 33 +++++++++----- | ||
21 | drivers/usb/musb/musb_core.c | 96 +++++++++++++++++++++------------------ | ||
22 | drivers/usb/musb/musb_core.h | 2 +- | ||
23 | drivers/usb/musb/musb_gadget.c | 38 +++++++-------- | ||
24 | drivers/usb/musb/musb_host.c | 2 +- | ||
25 | drivers/usb/musb/musb_virthub.c | 20 ++++---- | ||
26 | drivers/usb/musb/omap2430.c | 62 +++++++++---------------- | ||
27 | drivers/usb/musb/tusb6010.c | 70 ++++++++++++++++++----------- | ||
28 | 10 files changed, 181 insertions(+), 155 deletions(-) | ||
29 | |||
30 | diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig | ||
31 | index 9985db0..9eea991 100644 | ||
32 | --- a/drivers/usb/musb/Kconfig | ||
33 | +++ b/drivers/usb/musb/Kconfig | ||
34 | @@ -10,6 +10,7 @@ comment "Enable Host or Gadget support to see Inventra options" | ||
35 | config USB_MUSB_HDRC | ||
36 | depends on (USB || USB_GADGET) && HAVE_CLK | ||
37 | depends on !SUPERH | ||
38 | + select NOP_USB_XCEIV if ARCH_DAVINCI | ||
39 | select TWL4030_USB if MACH_OMAP_3430SDP | ||
40 | select USB_OTG_UTILS | ||
41 | tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' | ||
42 | @@ -55,6 +56,7 @@ comment "Blackfin high speed USB Support" | ||
43 | config USB_TUSB6010 | ||
44 | boolean "TUSB 6010 support" | ||
45 | depends on USB_MUSB_HDRC && !USB_MUSB_SOC | ||
46 | + select NOP_USB_XCEIV | ||
47 | default y | ||
48 | help | ||
49 | The TUSB 6010 chip, from Texas Instruments, connects a discrete | ||
50 | diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c | ||
51 | index 7861348..f2f66eb 100644 | ||
52 | --- a/drivers/usb/musb/blackfin.c | ||
53 | +++ b/drivers/usb/musb/blackfin.c | ||
54 | @@ -143,7 +143,7 @@ static void musb_conn_timer_handler(unsigned long _musb) | ||
55 | u16 val; | ||
56 | |||
57 | spin_lock_irqsave(&musb->lock, flags); | ||
58 | - switch (musb->xceiv.state) { | ||
59 | + switch (musb->xceiv->state) { | ||
60 | case OTG_STATE_A_IDLE: | ||
61 | case OTG_STATE_A_WAIT_BCON: | ||
62 | /* Start a new session */ | ||
63 | @@ -154,7 +154,7 @@ static void musb_conn_timer_handler(unsigned long _musb) | ||
64 | val = musb_readw(musb->mregs, MUSB_DEVCTL); | ||
65 | if (!(val & MUSB_DEVCTL_BDEVICE)) { | ||
66 | gpio_set_value(musb->config->gpio_vrsel, 1); | ||
67 | - musb->xceiv.state = OTG_STATE_A_WAIT_BCON; | ||
68 | + musb->xceiv->state = OTG_STATE_A_WAIT_BCON; | ||
69 | } else { | ||
70 | gpio_set_value(musb->config->gpio_vrsel, 0); | ||
71 | |||
72 | @@ -247,6 +247,11 @@ int __init musb_platform_init(struct musb *musb) | ||
73 | } | ||
74 | gpio_direction_output(musb->config->gpio_vrsel, 0); | ||
75 | |||
76 | + usb_nop_xceiv_register(); | ||
77 | + musb->xceiv = otg_get_transceiver(); | ||
78 | + if (!musb->xceiv) | ||
79 | + return -ENODEV; | ||
80 | + | ||
81 | if (ANOMALY_05000346) { | ||
82 | bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value); | ||
83 | SSYNC(); | ||
84 | @@ -291,7 +296,7 @@ int __init musb_platform_init(struct musb *musb) | ||
85 | musb_conn_timer_handler, (unsigned long) musb); | ||
86 | } | ||
87 | if (is_peripheral_enabled(musb)) | ||
88 | - musb->xceiv.set_power = bfin_set_power; | ||
89 | + musb->xceiv->set_power = bfin_set_power; | ||
90 | |||
91 | musb->isr = blackfin_interrupt; | ||
92 | |||
93 | diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c | ||
94 | index 9fd74bf..81de742 100644 | ||
95 | --- a/drivers/usb/musb/davinci.c | ||
96 | +++ b/drivers/usb/musb/davinci.c | ||
97 | @@ -200,7 +200,7 @@ static void otg_timer(unsigned long _musb) | ||
98 | DBG(7, "poll devctl %02x (%s)\n", devctl, otg_state_string(musb)); | ||
99 | |||
100 | spin_lock_irqsave(&musb->lock, flags); | ||
101 | - switch (musb->xceiv.state) { | ||
102 | + switch (musb->xceiv->state) { | ||
103 | case OTG_STATE_A_WAIT_VFALL: | ||
104 | /* Wait till VBUS falls below SessionEnd (~0.2V); the 1.3 RTL | ||
105 | * seems to mis-handle session "start" otherwise (or in our | ||
106 | @@ -211,7 +211,7 @@ static void otg_timer(unsigned long _musb) | ||
107 | mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); | ||
108 | break; | ||
109 | } | ||
110 | - musb->xceiv.state = OTG_STATE_A_WAIT_VRISE; | ||
111 | + musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; | ||
112 | musb_writel(musb->ctrl_base, DAVINCI_USB_INT_SET_REG, | ||
113 | MUSB_INTR_VBUSERROR << DAVINCI_USB_USBINT_SHIFT); | ||
114 | break; | ||
115 | @@ -236,7 +236,7 @@ static void otg_timer(unsigned long _musb) | ||
116 | if (devctl & MUSB_DEVCTL_BDEVICE) | ||
117 | mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); | ||
118 | else | ||
119 | - musb->xceiv.state = OTG_STATE_A_IDLE; | ||
120 | + musb->xceiv->state = OTG_STATE_A_IDLE; | ||
121 | break; | ||
122 | default: | ||
123 | break; | ||
124 | @@ -310,21 +310,21 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) | ||
125 | * to stop registering in devctl. | ||
126 | */ | ||
127 | musb->int_usb &= ~MUSB_INTR_VBUSERROR; | ||
128 | - musb->xceiv.state = OTG_STATE_A_WAIT_VFALL; | ||
129 | + musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; | ||
130 | mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); | ||
131 | WARNING("VBUS error workaround (delay coming)\n"); | ||
132 | } else if (is_host_enabled(musb) && drvvbus) { | ||
133 | musb->is_active = 1; | ||
134 | MUSB_HST_MODE(musb); | ||
135 | - musb->xceiv.default_a = 1; | ||
136 | - musb->xceiv.state = OTG_STATE_A_WAIT_VRISE; | ||
137 | + musb->xceiv->default_a = 1; | ||
138 | + musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; | ||
139 | portstate(musb->port1_status |= USB_PORT_STAT_POWER); | ||
140 | del_timer(&otg_workaround); | ||
141 | } else { | ||
142 | musb->is_active = 0; | ||
143 | MUSB_DEV_MODE(musb); | ||
144 | - musb->xceiv.default_a = 0; | ||
145 | - musb->xceiv.state = OTG_STATE_B_IDLE; | ||
146 | + musb->xceiv->default_a = 0; | ||
147 | + musb->xceiv->state = OTG_STATE_B_IDLE; | ||
148 | portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); | ||
149 | } | ||
150 | |||
151 | @@ -346,7 +346,7 @@ static irqreturn_t davinci_interrupt(int irq, void *__hci) | ||
152 | |||
153 | /* poll for ID change */ | ||
154 | if (is_otg_enabled(musb) | ||
155 | - && musb->xceiv.state == OTG_STATE_B_IDLE) | ||
156 | + && musb->xceiv->state == OTG_STATE_B_IDLE) | ||
157 | mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); | ||
158 | |||
159 | spin_unlock_irqrestore(&musb->lock, flags); | ||
160 | @@ -365,6 +365,11 @@ int __init musb_platform_init(struct musb *musb) | ||
161 | void __iomem *tibase = musb->ctrl_base; | ||
162 | u32 revision; | ||
163 | |||
164 | + usb_nop_xceiv_register(); | ||
165 | + musb->xceiv = otg_get_transceiver(); | ||
166 | + if (!musb->xceiv) | ||
167 | + return -ENODEV; | ||
168 | + | ||
169 | musb->mregs += DAVINCI_BASE_OFFSET; | ||
170 | |||
171 | clk_enable(musb->clock); | ||
172 | @@ -372,7 +377,7 @@ int __init musb_platform_init(struct musb *musb) | ||
173 | /* returns zero if e.g. not clocked */ | ||
174 | revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG); | ||
175 | if (revision == 0) | ||
176 | - return -ENODEV; | ||
177 | + goto fail; | ||
178 | |||
179 | if (is_host_enabled(musb)) | ||
180 | setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); | ||
181 | @@ -396,6 +401,10 @@ int __init musb_platform_init(struct musb *musb) | ||
182 | |||
183 | musb->isr = davinci_interrupt; | ||
184 | return 0; | ||
185 | + | ||
186 | +fail: | ||
187 | + usb_nop_xceiv_unregister(); | ||
188 | + return -ENODEV; | ||
189 | } | ||
190 | |||
191 | int musb_platform_exit(struct musb *musb) | ||
192 | @@ -406,7 +415,7 @@ int musb_platform_exit(struct musb *musb) | ||
193 | davinci_source_power(musb, 0 /*off*/, 1); | ||
194 | |||
195 | /* delay, to avoid problems with module reload */ | ||
196 | - if (is_host_enabled(musb) && musb->xceiv.default_a) { | ||
197 | + if (is_host_enabled(musb) && musb->xceiv->default_a) { | ||
198 | int maxdelay = 30; | ||
199 | u8 devctl, warn = 0; | ||
200 | |||
201 | @@ -435,5 +444,7 @@ int musb_platform_exit(struct musb *musb) | ||
202 | |||
203 | clk_disable(musb->clock); | ||
204 | |||
205 | + usb_nop_xceiv_unregister(); | ||
206 | + | ||
207 | return 0; | ||
208 | } | ||
209 | diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c | ||
210 | index d953305..ac150af 100644 | ||
211 | --- a/drivers/usb/musb/musb_core.c | ||
212 | +++ b/drivers/usb/musb/musb_core.c | ||
213 | @@ -267,7 +267,7 @@ void musb_load_testpacket(struct musb *musb) | ||
214 | |||
215 | const char *otg_state_string(struct musb *musb) | ||
216 | { | ||
217 | - switch (musb->xceiv.state) { | ||
218 | + switch (musb->xceiv->state) { | ||
219 | case OTG_STATE_A_IDLE: return "a_idle"; | ||
220 | case OTG_STATE_A_WAIT_VRISE: return "a_wait_vrise"; | ||
221 | case OTG_STATE_A_WAIT_BCON: return "a_wait_bcon"; | ||
222 | @@ -302,11 +302,11 @@ void musb_otg_timer_func(unsigned long data) | ||
223 | unsigned long flags; | ||
224 | |||
225 | spin_lock_irqsave(&musb->lock, flags); | ||
226 | - switch (musb->xceiv.state) { | ||
227 | + switch (musb->xceiv->state) { | ||
228 | case OTG_STATE_B_WAIT_ACON: | ||
229 | DBG(1, "HNP: b_wait_acon timeout; back to b_peripheral\n"); | ||
230 | musb_g_disconnect(musb); | ||
231 | - musb->xceiv.state = OTG_STATE_B_PERIPHERAL; | ||
232 | + musb->xceiv->state = OTG_STATE_B_PERIPHERAL; | ||
233 | musb->is_active = 0; | ||
234 | break; | ||
235 | case OTG_STATE_A_WAIT_BCON: | ||
236 | @@ -331,20 +331,20 @@ void musb_hnp_stop(struct musb *musb) | ||
237 | void __iomem *mbase = musb->mregs; | ||
238 | u8 reg; | ||
239 | |||
240 | - switch (musb->xceiv.state) { | ||
241 | + switch (musb->xceiv->state) { | ||
242 | case OTG_STATE_A_PERIPHERAL: | ||
243 | case OTG_STATE_A_WAIT_VFALL: | ||
244 | case OTG_STATE_A_WAIT_BCON: | ||
245 | DBG(1, "HNP: Switching back to A-host\n"); | ||
246 | musb_g_disconnect(musb); | ||
247 | - musb->xceiv.state = OTG_STATE_A_IDLE; | ||
248 | + musb->xceiv->state = OTG_STATE_A_IDLE; | ||
249 | MUSB_HST_MODE(musb); | ||
250 | musb->is_active = 0; | ||
251 | break; | ||
252 | case OTG_STATE_B_HOST: | ||
253 | DBG(1, "HNP: Disabling HR\n"); | ||
254 | hcd->self.is_b_host = 0; | ||
255 | - musb->xceiv.state = OTG_STATE_B_PERIPHERAL; | ||
256 | + musb->xceiv->state = OTG_STATE_B_PERIPHERAL; | ||
257 | MUSB_DEV_MODE(musb); | ||
258 | reg = musb_readb(mbase, MUSB_POWER); | ||
259 | reg |= MUSB_POWER_SUSPENDM; | ||
260 | @@ -402,7 +402,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | ||
261 | |||
262 | if (devctl & MUSB_DEVCTL_HM) { | ||
263 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | ||
264 | - switch (musb->xceiv.state) { | ||
265 | + switch (musb->xceiv->state) { | ||
266 | case OTG_STATE_A_SUSPEND: | ||
267 | /* remote wakeup? later, GetPortStatus | ||
268 | * will stop RESUME signaling | ||
269 | @@ -425,12 +425,12 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | ||
270 | musb->rh_timer = jiffies | ||
271 | + msecs_to_jiffies(20); | ||
272 | |||
273 | - musb->xceiv.state = OTG_STATE_A_HOST; | ||
274 | + musb->xceiv->state = OTG_STATE_A_HOST; | ||
275 | musb->is_active = 1; | ||
276 | usb_hcd_resume_root_hub(musb_to_hcd(musb)); | ||
277 | break; | ||
278 | case OTG_STATE_B_WAIT_ACON: | ||
279 | - musb->xceiv.state = OTG_STATE_B_PERIPHERAL; | ||
280 | + musb->xceiv->state = OTG_STATE_B_PERIPHERAL; | ||
281 | musb->is_active = 1; | ||
282 | MUSB_DEV_MODE(musb); | ||
283 | break; | ||
284 | @@ -441,11 +441,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | ||
285 | } | ||
286 | #endif | ||
287 | } else { | ||
288 | - switch (musb->xceiv.state) { | ||
289 | + switch (musb->xceiv->state) { | ||
290 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | ||
291 | case OTG_STATE_A_SUSPEND: | ||
292 | /* possibly DISCONNECT is upcoming */ | ||
293 | - musb->xceiv.state = OTG_STATE_A_HOST; | ||
294 | + musb->xceiv->state = OTG_STATE_A_HOST; | ||
295 | usb_hcd_resume_root_hub(musb_to_hcd(musb)); | ||
296 | break; | ||
297 | #endif | ||
298 | @@ -490,7 +490,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | ||
299 | */ | ||
300 | musb_writeb(mbase, MUSB_DEVCTL, MUSB_DEVCTL_SESSION); | ||
301 | musb->ep0_stage = MUSB_EP0_START; | ||
302 | - musb->xceiv.state = OTG_STATE_A_IDLE; | ||
303 | + musb->xceiv->state = OTG_STATE_A_IDLE; | ||
304 | MUSB_HST_MODE(musb); | ||
305 | musb_set_vbus(musb, 1); | ||
306 | |||
307 | @@ -516,7 +516,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | ||
308 | * REVISIT: do delays from lots of DEBUG_KERNEL checks | ||
309 | * make trouble here, keeping VBUS < 4.4V ? | ||
310 | */ | ||
311 | - switch (musb->xceiv.state) { | ||
312 | + switch (musb->xceiv->state) { | ||
313 | case OTG_STATE_A_HOST: | ||
314 | /* recovery is dicey once we've gotten past the | ||
315 | * initial stages of enumeration, but if VBUS | ||
316 | @@ -602,11 +602,11 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | ||
317 | MUSB_HST_MODE(musb); | ||
318 | |||
319 | /* indicate new connection to OTG machine */ | ||
320 | - switch (musb->xceiv.state) { | ||
321 | + switch (musb->xceiv->state) { | ||
322 | case OTG_STATE_B_PERIPHERAL: | ||
323 | if (int_usb & MUSB_INTR_SUSPEND) { | ||
324 | DBG(1, "HNP: SUSPEND+CONNECT, now b_host\n"); | ||
325 | - musb->xceiv.state = OTG_STATE_B_HOST; | ||
326 | + musb->xceiv->state = OTG_STATE_B_HOST; | ||
327 | hcd->self.is_b_host = 1; | ||
328 | int_usb &= ~MUSB_INTR_SUSPEND; | ||
329 | } else | ||
330 | @@ -614,13 +614,13 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | ||
331 | break; | ||
332 | case OTG_STATE_B_WAIT_ACON: | ||
333 | DBG(1, "HNP: Waiting to switch to b_host state\n"); | ||
334 | - musb->xceiv.state = OTG_STATE_B_HOST; | ||
335 | + musb->xceiv->state = OTG_STATE_B_HOST; | ||
336 | hcd->self.is_b_host = 1; | ||
337 | break; | ||
338 | default: | ||
339 | if ((devctl & MUSB_DEVCTL_VBUS) | ||
340 | == (3 << MUSB_DEVCTL_VBUS_SHIFT)) { | ||
341 | - musb->xceiv.state = OTG_STATE_A_HOST; | ||
342 | + musb->xceiv->state = OTG_STATE_A_HOST; | ||
343 | hcd->self.is_b_host = 0; | ||
344 | } | ||
345 | break; | ||
346 | @@ -650,7 +650,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | ||
347 | } | ||
348 | } else if (is_peripheral_capable()) { | ||
349 | DBG(1, "BUS RESET as %s\n", otg_state_string(musb)); | ||
350 | - switch (musb->xceiv.state) { | ||
351 | + switch (musb->xceiv->state) { | ||
352 | #ifdef CONFIG_USB_OTG | ||
353 | case OTG_STATE_A_SUSPEND: | ||
354 | /* We need to ignore disconnect on suspend | ||
355 | @@ -673,12 +673,12 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | ||
356 | case OTG_STATE_B_WAIT_ACON: | ||
357 | DBG(1, "HNP: RESET (%s), to b_peripheral\n", | ||
358 | otg_state_string(musb)); | ||
359 | - musb->xceiv.state = OTG_STATE_B_PERIPHERAL; | ||
360 | + musb->xceiv->state = OTG_STATE_B_PERIPHERAL; | ||
361 | musb_g_reset(musb); | ||
362 | break; | ||
363 | #endif | ||
364 | case OTG_STATE_B_IDLE: | ||
365 | - musb->xceiv.state = OTG_STATE_B_PERIPHERAL; | ||
366 | + musb->xceiv->state = OTG_STATE_B_PERIPHERAL; | ||
367 | /* FALLTHROUGH */ | ||
368 | case OTG_STATE_B_PERIPHERAL: | ||
369 | musb_g_reset(musb); | ||
370 | @@ -763,7 +763,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, | ||
371 | MUSB_MODE(musb), devctl); | ||
372 | handled = IRQ_HANDLED; | ||
373 | |||
374 | - switch (musb->xceiv.state) { | ||
375 | + switch (musb->xceiv->state) { | ||
376 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | ||
377 | case OTG_STATE_A_HOST: | ||
378 | case OTG_STATE_A_SUSPEND: | ||
379 | @@ -805,7 +805,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, | ||
380 | otg_state_string(musb), devctl, power); | ||
381 | handled = IRQ_HANDLED; | ||
382 | |||
383 | - switch (musb->xceiv.state) { | ||
384 | + switch (musb->xceiv->state) { | ||
385 | #ifdef CONFIG_USB_MUSB_OTG | ||
386 | case OTG_STATE_A_PERIPHERAL: | ||
387 | /* | ||
388 | @@ -817,10 +817,10 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, | ||
389 | case OTG_STATE_B_PERIPHERAL: | ||
390 | musb_g_suspend(musb); | ||
391 | musb->is_active = is_otg_enabled(musb) | ||
392 | - && musb->xceiv.gadget->b_hnp_enable; | ||
393 | + && musb->xceiv->gadget->b_hnp_enable; | ||
394 | if (musb->is_active) { | ||
395 | #ifdef CONFIG_USB_MUSB_OTG | ||
396 | - musb->xceiv.state = OTG_STATE_B_WAIT_ACON; | ||
397 | + musb->xceiv->state = OTG_STATE_B_WAIT_ACON; | ||
398 | DBG(1, "HNP: Setting timer for b_ase0_brst\n"); | ||
399 | musb_otg_timer.data = (unsigned long)musb; | ||
400 | mod_timer(&musb_otg_timer, jiffies | ||
401 | @@ -834,9 +834,9 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, | ||
402 | + msecs_to_jiffies(musb->a_wait_bcon)); | ||
403 | break; | ||
404 | case OTG_STATE_A_HOST: | ||
405 | - musb->xceiv.state = OTG_STATE_A_SUSPEND; | ||
406 | + musb->xceiv->state = OTG_STATE_A_SUSPEND; | ||
407 | musb->is_active = is_otg_enabled(musb) | ||
408 | - && musb->xceiv.host->b_hnp_enable; | ||
409 | + && musb->xceiv->host->b_hnp_enable; | ||
410 | break; | ||
411 | case OTG_STATE_B_HOST: | ||
412 | /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */ | ||
413 | @@ -1681,7 +1681,7 @@ musb_vbus_store(struct device *dev, struct device_attribute *attr, | ||
414 | |||
415 | spin_lock_irqsave(&musb->lock, flags); | ||
416 | musb->a_wait_bcon = val; | ||
417 | - if (musb->xceiv.state == OTG_STATE_A_WAIT_BCON) | ||
418 | + if (musb->xceiv->state == OTG_STATE_A_WAIT_BCON) | ||
419 | musb->is_active = 0; | ||
420 | musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(val)); | ||
421 | spin_unlock_irqrestore(&musb->lock, flags); | ||
422 | @@ -1742,8 +1742,8 @@ static void musb_irq_work(struct work_struct *data) | ||
423 | struct musb *musb = container_of(data, struct musb, irq_work); | ||
424 | static int old_state; | ||
425 | |||
426 | - if (musb->xceiv.state != old_state) { | ||
427 | - old_state = musb->xceiv.state; | ||
428 | + if (musb->xceiv->state != old_state) { | ||
429 | + old_state = musb->xceiv->state; | ||
430 | sysfs_notify(&musb->controller->kobj, NULL, "mode"); | ||
431 | } | ||
432 | } | ||
433 | @@ -1840,7 +1840,7 @@ static void musb_free(struct musb *musb) | ||
434 | } | ||
435 | |||
436 | #ifdef CONFIG_USB_MUSB_OTG | ||
437 | - put_device(musb->xceiv.dev); | ||
438 | + put_device(musb->xceiv->dev); | ||
439 | #endif | ||
440 | |||
441 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | ||
442 | @@ -1921,10 +1921,18 @@ bad_config: | ||
443 | } | ||
444 | } | ||
445 | |||
446 | - /* assume vbus is off */ | ||
447 | - | ||
448 | - /* platform adjusts musb->mregs and musb->isr if needed, | ||
449 | - * and activates clocks | ||
450 | + /* The musb_platform_init() call: | ||
451 | + * - adjusts musb->mregs and musb->isr if needed, | ||
452 | + * - may initialize an integrated tranceiver | ||
453 | + * - initializes musb->xceiv, usually by otg_get_transceiver() | ||
454 | + * - activates clocks. | ||
455 | + * - stops powering VBUS | ||
456 | + * - assigns musb->board_set_vbus if host mode is enabled | ||
457 | + * | ||
458 | + * There are various transciever configurations. Blackfin, | ||
459 | + * DaVinci, TUSB60x0, and others integrate them. OMAP3 uses | ||
460 | + * external/discrete ones in various flavors (twl4030 family, | ||
461 | + * isp1504, non-OTG, etc) mostly hooking up through ULPI. | ||
462 | */ | ||
463 | musb->isr = generic_interrupt; | ||
464 | status = musb_platform_init(musb); | ||
465 | @@ -1992,17 +2000,17 @@ bad_config: | ||
466 | ? "DMA" : "PIO", | ||
467 | musb->nIrq); | ||
468 | |||
469 | -#ifdef CONFIG_USB_MUSB_HDRC_HCD | ||
470 | - /* host side needs more setup, except for no-host modes */ | ||
471 | - if (musb->board_mode != MUSB_PERIPHERAL) { | ||
472 | + /* host side needs more setup */ | ||
473 | + if (is_host_enabled(musb)) { | ||
474 | struct usb_hcd *hcd = musb_to_hcd(musb); | ||
475 | |||
476 | - if (musb->board_mode == MUSB_OTG) | ||
477 | + otg_set_host(musb->xceiv, &hcd->self); | ||
478 | + | ||
479 | + if (is_otg_enabled(musb)) | ||
480 | hcd->self.otg_port = 1; | ||
481 | - musb->xceiv.host = &hcd->self; | ||
482 | + musb->xceiv->host = &hcd->self; | ||
483 | hcd->power_budget = 2 * (plat->power ? : 250); | ||
484 | } | ||
485 | -#endif /* CONFIG_USB_MUSB_HDRC_HCD */ | ||
486 | |||
487 | /* For the host-only role, we can activate right away. | ||
488 | * (We expect the ID pin to be forcibly grounded!!) | ||
489 | @@ -2010,8 +2018,8 @@ bad_config: | ||
490 | */ | ||
491 | if (!is_otg_enabled(musb) && is_host_enabled(musb)) { | ||
492 | MUSB_HST_MODE(musb); | ||
493 | - musb->xceiv.default_a = 1; | ||
494 | - musb->xceiv.state = OTG_STATE_A_IDLE; | ||
495 | + musb->xceiv->default_a = 1; | ||
496 | + musb->xceiv->state = OTG_STATE_A_IDLE; | ||
497 | |||
498 | status = usb_add_hcd(musb_to_hcd(musb), -1, 0); | ||
499 | if (status) | ||
500 | @@ -2026,8 +2034,8 @@ bad_config: | ||
501 | |||
502 | } else /* peripheral is enabled */ { | ||
503 | MUSB_DEV_MODE(musb); | ||
504 | - musb->xceiv.default_a = 0; | ||
505 | - musb->xceiv.state = OTG_STATE_B_IDLE; | ||
506 | + musb->xceiv->default_a = 0; | ||
507 | + musb->xceiv->state = OTG_STATE_B_IDLE; | ||
508 | |||
509 | status = musb_gadget_setup(musb); | ||
510 | if (status) | ||
511 | diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h | ||
512 | index 0ac4faf..c3ee348 100644 | ||
513 | --- a/drivers/usb/musb/musb_core.h | ||
514 | +++ b/drivers/usb/musb/musb_core.h | ||
515 | @@ -356,7 +356,7 @@ struct musb { | ||
516 | u16 int_rx; | ||
517 | u16 int_tx; | ||
518 | |||
519 | - struct otg_transceiver xceiv; | ||
520 | + struct otg_transceiver *xceiv; | ||
521 | |||
522 | int nIrq; | ||
523 | unsigned irq_wake:1; | ||
524 | diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c | ||
525 | index e8f920c..2fbfba5 100644 | ||
526 | --- a/drivers/usb/musb/musb_gadget.c | ||
527 | +++ b/drivers/usb/musb/musb_gadget.c | ||
528 | @@ -1406,7 +1406,7 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget) | ||
529 | |||
530 | spin_lock_irqsave(&musb->lock, flags); | ||
531 | |||
532 | - switch (musb->xceiv.state) { | ||
533 | + switch (musb->xceiv->state) { | ||
534 | case OTG_STATE_B_PERIPHERAL: | ||
535 | /* NOTE: OTG state machine doesn't include B_SUSPENDED; | ||
536 | * that's part of the standard usb 1.1 state machine, and | ||
537 | @@ -1508,9 +1508,9 @@ static int musb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA) | ||
538 | { | ||
539 | struct musb *musb = gadget_to_musb(gadget); | ||
540 | |||
541 | - if (!musb->xceiv.set_power) | ||
542 | + if (!musb->xceiv->set_power) | ||
543 | return -EOPNOTSUPP; | ||
544 | - return otg_set_power(&musb->xceiv, mA); | ||
545 | + return otg_set_power(musb->xceiv, mA); | ||
546 | } | ||
547 | |||
548 | static int musb_gadget_pullup(struct usb_gadget *gadget, int is_on) | ||
549 | @@ -1733,11 +1733,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) | ||
550 | |||
551 | spin_lock_irqsave(&musb->lock, flags); | ||
552 | |||
553 | - /* REVISIT always use otg_set_peripheral(), handling | ||
554 | - * issues including the root hub one below ... | ||
555 | - */ | ||
556 | - musb->xceiv.gadget = &musb->g; | ||
557 | - musb->xceiv.state = OTG_STATE_B_IDLE; | ||
558 | + otg_set_peripheral(musb->xceiv, &musb->g); | ||
559 | musb->is_active = 1; | ||
560 | |||
561 | /* FIXME this ignores the softconnect flag. Drivers are | ||
562 | @@ -1749,6 +1745,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) | ||
563 | if (!is_otg_enabled(musb)) | ||
564 | musb_start(musb); | ||
565 | |||
566 | + otg_set_peripheral(musb->xceiv, &musb->g); | ||
567 | + | ||
568 | spin_unlock_irqrestore(&musb->lock, flags); | ||
569 | |||
570 | if (is_otg_enabled(musb)) { | ||
571 | @@ -1762,8 +1760,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) | ||
572 | if (retval < 0) { | ||
573 | DBG(1, "add_hcd failed, %d\n", retval); | ||
574 | spin_lock_irqsave(&musb->lock, flags); | ||
575 | - musb->xceiv.gadget = NULL; | ||
576 | - musb->xceiv.state = OTG_STATE_UNDEFINED; | ||
577 | + otg_set_peripheral(musb->xceiv, NULL); | ||
578 | musb->gadget_driver = NULL; | ||
579 | musb->g.dev.driver = NULL; | ||
580 | spin_unlock_irqrestore(&musb->lock, flags); | ||
581 | @@ -1846,8 +1843,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | ||
582 | |||
583 | (void) musb_gadget_vbus_draw(&musb->g, 0); | ||
584 | |||
585 | - musb->xceiv.state = OTG_STATE_UNDEFINED; | ||
586 | + musb->xceiv->state = OTG_STATE_UNDEFINED; | ||
587 | stop_activity(musb, driver); | ||
588 | + otg_set_peripheral(musb->xceiv, NULL); | ||
589 | |||
590 | DBG(3, "unregistering driver %s\n", driver->function); | ||
591 | spin_unlock_irqrestore(&musb->lock, flags); | ||
592 | @@ -1883,7 +1881,7 @@ EXPORT_SYMBOL(usb_gadget_unregister_driver); | ||
593 | void musb_g_resume(struct musb *musb) | ||
594 | { | ||
595 | musb->is_suspended = 0; | ||
596 | - switch (musb->xceiv.state) { | ||
597 | + switch (musb->xceiv->state) { | ||
598 | case OTG_STATE_B_IDLE: | ||
599 | break; | ||
600 | case OTG_STATE_B_WAIT_ACON: | ||
601 | @@ -1909,10 +1907,10 @@ void musb_g_suspend(struct musb *musb) | ||
602 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | ||
603 | DBG(3, "devctl %02x\n", devctl); | ||
604 | |||
605 | - switch (musb->xceiv.state) { | ||
606 | + switch (musb->xceiv->state) { | ||
607 | case OTG_STATE_B_IDLE: | ||
608 | if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) | ||
609 | - musb->xceiv.state = OTG_STATE_B_PERIPHERAL; | ||
610 | + musb->xceiv->state = OTG_STATE_B_PERIPHERAL; | ||
611 | break; | ||
612 | case OTG_STATE_B_PERIPHERAL: | ||
613 | musb->is_suspended = 1; | ||
614 | @@ -1958,22 +1956,22 @@ void musb_g_disconnect(struct musb *musb) | ||
615 | spin_lock(&musb->lock); | ||
616 | } | ||
617 | |||
618 | - switch (musb->xceiv.state) { | ||
619 | + switch (musb->xceiv->state) { | ||
620 | default: | ||
621 | #ifdef CONFIG_USB_MUSB_OTG | ||
622 | DBG(2, "Unhandled disconnect %s, setting a_idle\n", | ||
623 | otg_state_string(musb)); | ||
624 | - musb->xceiv.state = OTG_STATE_A_IDLE; | ||
625 | + musb->xceiv->state = OTG_STATE_A_IDLE; | ||
626 | break; | ||
627 | case OTG_STATE_A_PERIPHERAL: | ||
628 | - musb->xceiv.state = OTG_STATE_A_WAIT_VFALL; | ||
629 | + musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; | ||
630 | break; | ||
631 | case OTG_STATE_B_WAIT_ACON: | ||
632 | case OTG_STATE_B_HOST: | ||
633 | #endif | ||
634 | case OTG_STATE_B_PERIPHERAL: | ||
635 | case OTG_STATE_B_IDLE: | ||
636 | - musb->xceiv.state = OTG_STATE_B_IDLE; | ||
637 | + musb->xceiv->state = OTG_STATE_B_IDLE; | ||
638 | break; | ||
639 | case OTG_STATE_B_SRP_INIT: | ||
640 | break; | ||
641 | @@ -2029,10 +2027,10 @@ __acquires(musb->lock) | ||
642 | * or else after HNP, as A-Device | ||
643 | */ | ||
644 | if (devctl & MUSB_DEVCTL_BDEVICE) { | ||
645 | - musb->xceiv.state = OTG_STATE_B_PERIPHERAL; | ||
646 | + musb->xceiv->state = OTG_STATE_B_PERIPHERAL; | ||
647 | musb->g.is_a_peripheral = 0; | ||
648 | } else if (is_otg_enabled(musb)) { | ||
649 | - musb->xceiv.state = OTG_STATE_A_PERIPHERAL; | ||
650 | + musb->xceiv->state = OTG_STATE_A_PERIPHERAL; | ||
651 | musb->g.is_a_peripheral = 1; | ||
652 | } else | ||
653 | WARN_ON(1); | ||
654 | diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c | ||
655 | index ece5122..795dabe 100644 | ||
656 | --- a/drivers/usb/musb/musb_host.c | ||
657 | +++ b/drivers/usb/musb/musb_host.c | ||
658 | @@ -2169,7 +2169,7 @@ static int musb_bus_suspend(struct usb_hcd *hcd) | ||
659 | { | ||
660 | struct musb *musb = hcd_to_musb(hcd); | ||
661 | |||
662 | - if (musb->xceiv.state == OTG_STATE_A_SUSPEND) | ||
663 | + if (musb->xceiv->state == OTG_STATE_A_SUSPEND) | ||
664 | return 0; | ||
665 | |||
666 | if (is_host_active(musb) && musb->is_active) { | ||
667 | diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c | ||
668 | index e0e9ce5..7e7900f 100644 | ||
669 | --- a/drivers/usb/musb/musb_virthub.c | ||
670 | +++ b/drivers/usb/musb/musb_virthub.c | ||
671 | @@ -78,18 +78,18 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend) | ||
672 | DBG(3, "Root port suspended, power %02x\n", power); | ||
673 | |||
674 | musb->port1_status |= USB_PORT_STAT_SUSPEND; | ||
675 | - switch (musb->xceiv.state) { | ||
676 | + switch (musb->xceiv->state) { | ||
677 | case OTG_STATE_A_HOST: | ||
678 | - musb->xceiv.state = OTG_STATE_A_SUSPEND; | ||
679 | + musb->xceiv->state = OTG_STATE_A_SUSPEND; | ||
680 | musb->is_active = is_otg_enabled(musb) | ||
681 | - && musb->xceiv.host->b_hnp_enable; | ||
682 | + && musb->xceiv->host->b_hnp_enable; | ||
683 | musb_platform_try_idle(musb, 0); | ||
684 | break; | ||
685 | #ifdef CONFIG_USB_MUSB_OTG | ||
686 | case OTG_STATE_B_HOST: | ||
687 | - musb->xceiv.state = OTG_STATE_B_WAIT_ACON; | ||
688 | + musb->xceiv->state = OTG_STATE_B_WAIT_ACON; | ||
689 | musb->is_active = is_otg_enabled(musb) | ||
690 | - && musb->xceiv.host->b_hnp_enable; | ||
691 | + && musb->xceiv->host->b_hnp_enable; | ||
692 | musb_platform_try_idle(musb, 0); | ||
693 | break; | ||
694 | #endif | ||
695 | @@ -116,7 +116,7 @@ static void musb_port_reset(struct musb *musb, bool do_reset) | ||
696 | void __iomem *mbase = musb->mregs; | ||
697 | |||
698 | #ifdef CONFIG_USB_MUSB_OTG | ||
699 | - if (musb->xceiv.state == OTG_STATE_B_IDLE) { | ||
700 | + if (musb->xceiv->state == OTG_STATE_B_IDLE) { | ||
701 | DBG(2, "HNP: Returning from HNP; no hub reset from b_idle\n"); | ||
702 | musb->port1_status &= ~USB_PORT_STAT_RESET; | ||
703 | return; | ||
704 | @@ -186,14 +186,14 @@ void musb_root_disconnect(struct musb *musb) | ||
705 | usb_hcd_poll_rh_status(musb_to_hcd(musb)); | ||
706 | musb->is_active = 0; | ||
707 | |||
708 | - switch (musb->xceiv.state) { | ||
709 | + switch (musb->xceiv->state) { | ||
710 | case OTG_STATE_A_HOST: | ||
711 | case OTG_STATE_A_SUSPEND: | ||
712 | - musb->xceiv.state = OTG_STATE_A_WAIT_BCON; | ||
713 | + musb->xceiv->state = OTG_STATE_A_WAIT_BCON; | ||
714 | musb->is_active = 0; | ||
715 | break; | ||
716 | case OTG_STATE_A_WAIT_VFALL: | ||
717 | - musb->xceiv.state = OTG_STATE_B_IDLE; | ||
718 | + musb->xceiv->state = OTG_STATE_B_IDLE; | ||
719 | break; | ||
720 | default: | ||
721 | DBG(1, "host disconnect (%s)\n", otg_state_string(musb)); | ||
722 | @@ -332,7 +332,7 @@ int musb_hub_control( | ||
723 | musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16; | ||
724 | usb_hcd_poll_rh_status(musb_to_hcd(musb)); | ||
725 | /* NOTE: it might really be A_WAIT_BCON ... */ | ||
726 | - musb->xceiv.state = OTG_STATE_A_HOST; | ||
727 | + musb->xceiv->state = OTG_STATE_A_HOST; | ||
728 | } | ||
729 | |||
730 | put_unaligned(cpu_to_le32(musb->port1_status | ||
731 | diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c | ||
732 | index 901dffd..5f67b03 100644 | ||
733 | --- a/drivers/usb/musb/omap2430.c | ||
734 | +++ b/drivers/usb/musb/omap2430.c | ||
735 | @@ -62,17 +62,17 @@ static void musb_do_idle(unsigned long _musb) | ||
736 | |||
737 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | ||
738 | |||
739 | - switch (musb->xceiv.state) { | ||
740 | + switch (musb->xceiv->state) { | ||
741 | case OTG_STATE_A_WAIT_BCON: | ||
742 | devctl &= ~MUSB_DEVCTL_SESSION; | ||
743 | musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); | ||
744 | |||
745 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | ||
746 | if (devctl & MUSB_DEVCTL_BDEVICE) { | ||
747 | - musb->xceiv.state = OTG_STATE_B_IDLE; | ||
748 | + musb->xceiv->state = OTG_STATE_B_IDLE; | ||
749 | MUSB_DEV_MODE(musb); | ||
750 | } else { | ||
751 | - musb->xceiv.state = OTG_STATE_A_IDLE; | ||
752 | + musb->xceiv->state = OTG_STATE_A_IDLE; | ||
753 | MUSB_HST_MODE(musb); | ||
754 | } | ||
755 | break; | ||
756 | @@ -90,7 +90,7 @@ static void musb_do_idle(unsigned long _musb) | ||
757 | musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16; | ||
758 | usb_hcd_poll_rh_status(musb_to_hcd(musb)); | ||
759 | /* NOTE: it might really be A_WAIT_BCON ... */ | ||
760 | - musb->xceiv.state = OTG_STATE_A_HOST; | ||
761 | + musb->xceiv->state = OTG_STATE_A_HOST; | ||
762 | } | ||
763 | break; | ||
764 | #endif | ||
765 | @@ -98,9 +98,9 @@ static void musb_do_idle(unsigned long _musb) | ||
766 | case OTG_STATE_A_HOST: | ||
767 | devctl = musb_readb(musb->mregs, MUSB_DEVCTL); | ||
768 | if (devctl & MUSB_DEVCTL_BDEVICE) | ||
769 | - musb->xceiv.state = OTG_STATE_B_IDLE; | ||
770 | + musb->xceiv->state = OTG_STATE_B_IDLE; | ||
771 | else | ||
772 | - musb->xceiv.state = OTG_STATE_A_WAIT_BCON; | ||
773 | + musb->xceiv->state = OTG_STATE_A_WAIT_BCON; | ||
774 | #endif | ||
775 | default: | ||
776 | break; | ||
777 | @@ -119,7 +119,7 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout) | ||
778 | |||
779 | /* Never idle if active, or when VBUS timeout is not set as host */ | ||
780 | if (musb->is_active || ((musb->a_wait_bcon == 0) | ||
781 | - && (musb->xceiv.state == OTG_STATE_A_WAIT_BCON))) { | ||
782 | + && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) { | ||
783 | DBG(4, "%s active, deleting timer\n", otg_state_string(musb)); | ||
784 | del_timer(&musb_idle_timer); | ||
785 | last_timer = jiffies; | ||
786 | @@ -164,8 +164,8 @@ static void omap_set_vbus(struct musb *musb, int is_on) | ||
787 | |||
788 | if (is_on) { | ||
789 | musb->is_active = 1; | ||
790 | - musb->xceiv.default_a = 1; | ||
791 | - musb->xceiv.state = OTG_STATE_A_WAIT_VRISE; | ||
792 | + musb->xceiv->default_a = 1; | ||
793 | + musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; | ||
794 | devctl |= MUSB_DEVCTL_SESSION; | ||
795 | |||
796 | MUSB_HST_MODE(musb); | ||
797 | @@ -176,8 +176,8 @@ static void omap_set_vbus(struct musb *musb, int is_on) | ||
798 | * jumping right to B_IDLE... | ||
799 | */ | ||
800 | |||
801 | - musb->xceiv.default_a = 0; | ||
802 | - musb->xceiv.state = OTG_STATE_B_IDLE; | ||
803 | + musb->xceiv->default_a = 0; | ||
804 | + musb->xceiv->state = OTG_STATE_B_IDLE; | ||
805 | devctl &= ~MUSB_DEVCTL_SESSION; | ||
806 | |||
807 | MUSB_DEV_MODE(musb); | ||
808 | @@ -189,10 +189,6 @@ static void omap_set_vbus(struct musb *musb, int is_on) | ||
809 | otg_state_string(musb), | ||
810 | musb_readb(musb->mregs, MUSB_DEVCTL)); | ||
811 | } | ||
812 | -static int omap_set_power(struct otg_transceiver *x, unsigned mA) | ||
813 | -{ | ||
814 | - return 0; | ||
815 | -} | ||
816 | |||
817 | static int musb_platform_resume(struct musb *musb); | ||
818 | |||
819 | @@ -203,24 +199,6 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode) | ||
820 | devctl |= MUSB_DEVCTL_SESSION; | ||
821 | musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); | ||
822 | |||
823 | - switch (musb_mode) { | ||
824 | -#ifdef CONFIG_USB_MUSB_HDRC_HCD | ||
825 | - case MUSB_HOST: | ||
826 | - otg_set_host(&musb->xceiv, musb->xceiv.host); | ||
827 | - break; | ||
828 | -#endif | ||
829 | -#ifdef CONFIG_USB_GADGET_MUSB_HDRC | ||
830 | - case MUSB_PERIPHERAL: | ||
831 | - otg_set_peripheral(&musb->xceiv, musb->xceiv.gadget); | ||
832 | - break; | ||
833 | -#endif | ||
834 | -#ifdef CONFIG_USB_MUSB_OTG | ||
835 | - case MUSB_OTG: | ||
836 | - break; | ||
837 | -#endif | ||
838 | - default: | ||
839 | - return -EINVAL; | ||
840 | - } | ||
841 | return 0; | ||
842 | } | ||
843 | |||
844 | @@ -232,6 +210,16 @@ int __init musb_platform_init(struct musb *musb) | ||
845 | omap_cfg_reg(AE5_2430_USB0HS_STP); | ||
846 | #endif | ||
847 | |||
848 | + /* We require some kind of external transceiver, hooked | ||
849 | + * up through ULPI. TWL4030-family PMICs include one, | ||
850 | + * which needs a driver, drivers aren't always needed. | ||
851 | + */ | ||
852 | + musb->xceiv = otg_get_transceiver(); | ||
853 | + if (!musb->xceiv) { | ||
854 | + pr_err("HS USB OTG: no transceiver configured\n"); | ||
855 | + return -ENODEV; | ||
856 | + } | ||
857 | + | ||
858 | musb_platform_resume(musb); | ||
859 | |||
860 | l = omap_readl(OTG_SYSCONFIG); | ||
861 | @@ -258,8 +246,6 @@ int __init musb_platform_init(struct musb *musb) | ||
862 | |||
863 | if (is_host_enabled(musb)) | ||
864 | musb->board_set_vbus = omap_set_vbus; | ||
865 | - if (is_peripheral_enabled(musb)) | ||
866 | - musb->xceiv.set_power = omap_set_power; | ||
867 | musb->a_wait_bcon = MUSB_TIMEOUT_A_WAIT_BCON; | ||
868 | |||
869 | setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); | ||
870 | @@ -283,8 +269,7 @@ int musb_platform_suspend(struct musb *musb) | ||
871 | l |= ENABLEWAKEUP; /* enable wakeup */ | ||
872 | omap_writel(l, OTG_SYSCONFIG); | ||
873 | |||
874 | - if (musb->xceiv.set_suspend) | ||
875 | - musb->xceiv.set_suspend(&musb->xceiv, 1); | ||
876 | + otg_set_suspend(musb->xceiv, 1); | ||
877 | |||
878 | if (musb->set_clock) | ||
879 | musb->set_clock(musb->clock, 0); | ||
880 | @@ -301,8 +286,7 @@ static int musb_platform_resume(struct musb *musb) | ||
881 | if (!musb->clock) | ||
882 | return 0; | ||
883 | |||
884 | - if (musb->xceiv.set_suspend) | ||
885 | - musb->xceiv.set_suspend(&musb->xceiv, 0); | ||
886 | + otg_set_suspend(musb->xceiv, 0); | ||
887 | |||
888 | if (musb->set_clock) | ||
889 | musb->set_clock(musb->clock, 1); | ||
890 | diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c | ||
891 | index 9e20fd0..c473dec 100644 | ||
892 | --- a/drivers/usb/musb/tusb6010.c | ||
893 | +++ b/drivers/usb/musb/tusb6010.c | ||
894 | @@ -260,6 +260,8 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf) | ||
895 | tusb_fifo_read_unaligned(fifo, buf, len); | ||
896 | } | ||
897 | |||
898 | +static struct musb *the_musb; | ||
899 | + | ||
900 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | ||
901 | |||
902 | /* This is used by gadget drivers, and OTG transceiver logic, allowing | ||
903 | @@ -270,7 +272,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf) | ||
904 | */ | ||
905 | static int tusb_draw_power(struct otg_transceiver *x, unsigned mA) | ||
906 | { | ||
907 | - struct musb *musb = container_of(x, struct musb, xceiv); | ||
908 | + struct musb *musb = the_musb; | ||
909 | void __iomem *tbase = musb->ctrl_base; | ||
910 | u32 reg; | ||
911 | |||
912 | @@ -420,7 +422,7 @@ static void musb_do_idle(unsigned long _musb) | ||
913 | |||
914 | spin_lock_irqsave(&musb->lock, flags); | ||
915 | |||
916 | - switch (musb->xceiv.state) { | ||
917 | + switch (musb->xceiv->state) { | ||
918 | case OTG_STATE_A_WAIT_BCON: | ||
919 | if ((musb->a_wait_bcon != 0) | ||
920 | && (musb->idle_timeout == 0 | ||
921 | @@ -484,7 +486,7 @@ void musb_platform_try_idle(struct musb *musb, unsigned long timeout) | ||
922 | |||
923 | /* Never idle if active, or when VBUS timeout is not set as host */ | ||
924 | if (musb->is_active || ((musb->a_wait_bcon == 0) | ||
925 | - && (musb->xceiv.state == OTG_STATE_A_WAIT_BCON))) { | ||
926 | + && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) { | ||
927 | DBG(4, "%s active, deleting timer\n", otg_state_string(musb)); | ||
928 | del_timer(&musb_idle_timer); | ||
929 | last_timer = jiffies; | ||
930 | @@ -533,8 +535,8 @@ static void tusb_source_power(struct musb *musb, int is_on) | ||
931 | if (musb->set_clock) | ||
932 | musb->set_clock(musb->clock, 1); | ||
933 | timer = OTG_TIMER_MS(OTG_TIME_A_WAIT_VRISE); | ||
934 | - musb->xceiv.default_a = 1; | ||
935 | - musb->xceiv.state = OTG_STATE_A_WAIT_VRISE; | ||
936 | + musb->xceiv->default_a = 1; | ||
937 | + musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; | ||
938 | devctl |= MUSB_DEVCTL_SESSION; | ||
939 | |||
940 | conf |= TUSB_DEV_CONF_USB_HOST_MODE; | ||
941 | @@ -547,24 +549,24 @@ static void tusb_source_power(struct musb *musb, int is_on) | ||
942 | /* If ID pin is grounded, we want to be a_idle */ | ||
943 | otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); | ||
944 | if (!(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS)) { | ||
945 | - switch (musb->xceiv.state) { | ||
946 | + switch (musb->xceiv->state) { | ||
947 | case OTG_STATE_A_WAIT_VRISE: | ||
948 | case OTG_STATE_A_WAIT_BCON: | ||
949 | - musb->xceiv.state = OTG_STATE_A_WAIT_VFALL; | ||
950 | + musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; | ||
951 | break; | ||
952 | case OTG_STATE_A_WAIT_VFALL: | ||
953 | - musb->xceiv.state = OTG_STATE_A_IDLE; | ||
954 | + musb->xceiv->state = OTG_STATE_A_IDLE; | ||
955 | break; | ||
956 | default: | ||
957 | - musb->xceiv.state = OTG_STATE_A_IDLE; | ||
958 | + musb->xceiv->state = OTG_STATE_A_IDLE; | ||
959 | } | ||
960 | musb->is_active = 0; | ||
961 | - musb->xceiv.default_a = 1; | ||
962 | + musb->xceiv->default_a = 1; | ||
963 | MUSB_HST_MODE(musb); | ||
964 | } else { | ||
965 | musb->is_active = 0; | ||
966 | - musb->xceiv.default_a = 0; | ||
967 | - musb->xceiv.state = OTG_STATE_B_IDLE; | ||
968 | + musb->xceiv->default_a = 0; | ||
969 | + musb->xceiv->state = OTG_STATE_B_IDLE; | ||
970 | MUSB_DEV_MODE(musb); | ||
971 | } | ||
972 | |||
973 | @@ -675,7 +677,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) | ||
974 | else | ||
975 | default_a = is_host_enabled(musb); | ||
976 | DBG(2, "Default-%c\n", default_a ? 'A' : 'B'); | ||
977 | - musb->xceiv.default_a = default_a; | ||
978 | + musb->xceiv->default_a = default_a; | ||
979 | tusb_source_power(musb, default_a); | ||
980 | |||
981 | /* Don't allow idling immediately */ | ||
982 | @@ -687,7 +689,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) | ||
983 | if (int_src & TUSB_INT_SRC_VBUS_SENSE_CHNG) { | ||
984 | |||
985 | /* B-dev state machine: no vbus ~= disconnect */ | ||
986 | - if ((is_otg_enabled(musb) && !musb->xceiv.default_a) | ||
987 | + if ((is_otg_enabled(musb) && !musb->xceiv->default_a) | ||
988 | || !is_host_enabled(musb)) { | ||
989 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | ||
990 | /* ? musb_root_disconnect(musb); */ | ||
991 | @@ -702,9 +704,9 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) | ||
992 | |||
993 | if (otg_stat & TUSB_DEV_OTG_STAT_SESS_END) { | ||
994 | DBG(1, "Forcing disconnect (no interrupt)\n"); | ||
995 | - if (musb->xceiv.state != OTG_STATE_B_IDLE) { | ||
996 | + if (musb->xceiv->state != OTG_STATE_B_IDLE) { | ||
997 | /* INTR_DISCONNECT can hide... */ | ||
998 | - musb->xceiv.state = OTG_STATE_B_IDLE; | ||
999 | + musb->xceiv->state = OTG_STATE_B_IDLE; | ||
1000 | musb->int_usb |= MUSB_INTR_DISCONNECT; | ||
1001 | } | ||
1002 | musb->is_active = 0; | ||
1003 | @@ -718,7 +720,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) | ||
1004 | DBG(2, "vbus change, %s, otg %03x\n", | ||
1005 | otg_state_string(musb), otg_stat); | ||
1006 | |||
1007 | - switch (musb->xceiv.state) { | ||
1008 | + switch (musb->xceiv->state) { | ||
1009 | case OTG_STATE_A_IDLE: | ||
1010 | DBG(2, "Got SRP, turning on VBUS\n"); | ||
1011 | musb_set_vbus(musb, 1); | ||
1012 | @@ -766,7 +768,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) | ||
1013 | |||
1014 | DBG(4, "%s timer, %03x\n", otg_state_string(musb), otg_stat); | ||
1015 | |||
1016 | - switch (musb->xceiv.state) { | ||
1017 | + switch (musb->xceiv->state) { | ||
1018 | case OTG_STATE_A_WAIT_VRISE: | ||
1019 | /* VBUS has probably been valid for a while now, | ||
1020 | * but may well have bounced out of range a bit | ||
1021 | @@ -778,7 +780,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) | ||
1022 | DBG(2, "devctl %02x\n", devctl); | ||
1023 | break; | ||
1024 | } | ||
1025 | - musb->xceiv.state = OTG_STATE_A_WAIT_BCON; | ||
1026 | + musb->xceiv->state = OTG_STATE_A_WAIT_BCON; | ||
1027 | musb->is_active = 0; | ||
1028 | idle_timeout = jiffies | ||
1029 | + msecs_to_jiffies(musb->a_wait_bcon); | ||
1030 | @@ -1094,9 +1096,14 @@ int __init musb_platform_init(struct musb *musb) | ||
1031 | { | ||
1032 | struct platform_device *pdev; | ||
1033 | struct resource *mem; | ||
1034 | - void __iomem *sync; | ||
1035 | + void __iomem *sync = NULL; | ||
1036 | int ret; | ||
1037 | |||
1038 | + usb_nop_xceiv_register(); | ||
1039 | + musb->xceiv = otg_get_transceiver(); | ||
1040 | + if (!musb->xceiv) | ||
1041 | + return -ENODEV; | ||
1042 | + | ||
1043 | pdev = to_platform_device(musb->controller); | ||
1044 | |||
1045 | /* dma address for async dma */ | ||
1046 | @@ -1107,14 +1114,16 @@ int __init musb_platform_init(struct musb *musb) | ||
1047 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
1048 | if (!mem) { | ||
1049 | pr_debug("no sync dma resource?\n"); | ||
1050 | - return -ENODEV; | ||
1051 | + ret = -ENODEV; | ||
1052 | + goto done; | ||
1053 | } | ||
1054 | musb->sync = mem->start; | ||
1055 | |||
1056 | sync = ioremap(mem->start, mem->end - mem->start + 1); | ||
1057 | if (!sync) { | ||
1058 | pr_debug("ioremap for sync failed\n"); | ||
1059 | - return -ENOMEM; | ||
1060 | + ret = -ENOMEM; | ||
1061 | + goto done; | ||
1062 | } | ||
1063 | musb->sync_va = sync; | ||
1064 | |||
1065 | @@ -1127,28 +1136,37 @@ int __init musb_platform_init(struct musb *musb) | ||
1066 | if (ret) { | ||
1067 | printk(KERN_ERR "Could not start tusb6010 (%d)\n", | ||
1068 | ret); | ||
1069 | - return -ENODEV; | ||
1070 | + goto done; | ||
1071 | } | ||
1072 | musb->isr = tusb_interrupt; | ||
1073 | |||
1074 | if (is_host_enabled(musb)) | ||
1075 | musb->board_set_vbus = tusb_source_power; | ||
1076 | - if (is_peripheral_enabled(musb)) | ||
1077 | - musb->xceiv.set_power = tusb_draw_power; | ||
1078 | + if (is_peripheral_enabled(musb)) { | ||
1079 | + musb->xceiv->set_power = tusb_draw_power; | ||
1080 | + the_musb = musb; | ||
1081 | + } | ||
1082 | |||
1083 | setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); | ||
1084 | |||
1085 | +done: | ||
1086 | + if (ret < 0) { | ||
1087 | + if (sync) | ||
1088 | + iounmap(sync); | ||
1089 | + usb_nop_xceiv_unregister(); | ||
1090 | + } | ||
1091 | return ret; | ||
1092 | } | ||
1093 | |||
1094 | int musb_platform_exit(struct musb *musb) | ||
1095 | { | ||
1096 | del_timer_sync(&musb_idle_timer); | ||
1097 | + the_musb = NULL; | ||
1098 | |||
1099 | if (musb->board_set_power) | ||
1100 | musb->board_set_power(0); | ||
1101 | |||
1102 | iounmap(musb->sync_va); | ||
1103 | - | ||
1104 | + usb_nop_xceiv_unregister(); | ||
1105 | return 0; | ||
1106 | } | ||
1107 | -- | ||
1108 | 1.6.0.4 | ||
1109 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0027-musb-otg-timer-cleanup.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0027-musb-otg-timer-cleanup.patch deleted file mode 100644 index f41b766cfe..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0027-musb-otg-timer-cleanup.patch +++ /dev/null | |||
@@ -1,198 +0,0 @@ | |||
1 | From b4b8c1e7604784b9877f07400ff2a718118ef05c Mon Sep 17 00:00:00 2001 | ||
2 | From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
3 | Date: Tue, 31 Mar 2009 12:32:12 -0700 | ||
4 | Subject: [PATCH] musb: otg timer cleanup | ||
5 | |||
6 | Minor cleanup of OTG timer handling: | ||
7 | * unify decls for OTG time constants, in the core header | ||
8 | * set up and use that timer in a more normal way | ||
9 | * move to the driver struct, so it's usable outside core | ||
10 | |||
11 | And tighten use and setup of T(a_wait_bcon) so that if it's used, | ||
12 | it's always valid. (If that timer expires, the A-device will | ||
13 | stop powering VBUS. For non-OTG systems, that will be a surprise.) | ||
14 | No behavioral changes, other than more consistency when applying | ||
15 | that core HNP timeout. | ||
16 | |||
17 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
18 | --- | ||
19 | drivers/usb/musb/musb_core.c | 41 ++++++++++++++++++++++------------------- | ||
20 | drivers/usb/musb/musb_core.h | 14 +++++++++++--- | ||
21 | drivers/usb/musb/omap2430.c | 2 -- | ||
22 | 3 files changed, 33 insertions(+), 24 deletions(-) | ||
23 | |||
24 | diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c | ||
25 | index ac150af..05c5dd3 100644 | ||
26 | --- a/drivers/usb/musb/musb_core.c | ||
27 | +++ b/drivers/usb/musb/musb_core.c | ||
28 | @@ -112,6 +112,7 @@ | ||
29 | #include "davinci.h" | ||
30 | #endif | ||
31 | |||
32 | +#define TA_WAIT_BCON(m) max_t(int, (m)->a_wait_bcon, OTG_TIME_A_WAIT_BCON) | ||
33 | |||
34 | |||
35 | unsigned musb_debug; | ||
36 | @@ -288,12 +289,6 @@ const char *otg_state_string(struct musb *musb) | ||
37 | #ifdef CONFIG_USB_MUSB_OTG | ||
38 | |||
39 | /* | ||
40 | - * See also USB_OTG_1-3.pdf 6.6.5 Timers | ||
41 | - * REVISIT: Are the other timers done in the hardware? | ||
42 | - */ | ||
43 | -#define TB_ASE0_BRST 100 /* Min 3.125 ms */ | ||
44 | - | ||
45 | -/* | ||
46 | * Handles OTG hnp timeouts, such as b_ase0_brst | ||
47 | */ | ||
48 | void musb_otg_timer_func(unsigned long data) | ||
49 | @@ -320,10 +315,8 @@ void musb_otg_timer_func(unsigned long data) | ||
50 | spin_unlock_irqrestore(&musb->lock, flags); | ||
51 | } | ||
52 | |||
53 | -static DEFINE_TIMER(musb_otg_timer, musb_otg_timer_func, 0, 0); | ||
54 | - | ||
55 | /* | ||
56 | - * Stops the B-device HNP state. Caller must take care of locking. | ||
57 | + * Stops the HNP transition. Caller must take care of locking. | ||
58 | */ | ||
59 | void musb_hnp_stop(struct musb *musb) | ||
60 | { | ||
61 | @@ -661,11 +654,12 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | ||
62 | musb_g_reset(musb); | ||
63 | /* FALLTHROUGH */ | ||
64 | case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */ | ||
65 | - DBG(1, "HNP: Setting timer as %s\n", | ||
66 | - otg_state_string(musb)); | ||
67 | - musb_otg_timer.data = (unsigned long)musb; | ||
68 | - mod_timer(&musb_otg_timer, jiffies | ||
69 | - + msecs_to_jiffies(100)); | ||
70 | + /* never use invalid T(a_wait_bcon) */ | ||
71 | + DBG(1, "HNP: in %s, %d msec timeout\n", | ||
72 | + otg_state_string(musb), | ||
73 | + TA_WAIT_BCON(musb)); | ||
74 | + mod_timer(&musb->otg_timer, jiffies | ||
75 | + + msecs_to_jiffies(TA_WAIT_BCON(musb))); | ||
76 | break; | ||
77 | case OTG_STATE_A_PERIPHERAL: | ||
78 | musb_hnp_stop(musb); | ||
79 | @@ -822,9 +816,9 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, | ||
80 | #ifdef CONFIG_USB_MUSB_OTG | ||
81 | musb->xceiv->state = OTG_STATE_B_WAIT_ACON; | ||
82 | DBG(1, "HNP: Setting timer for b_ase0_brst\n"); | ||
83 | - musb_otg_timer.data = (unsigned long)musb; | ||
84 | - mod_timer(&musb_otg_timer, jiffies | ||
85 | - + msecs_to_jiffies(TB_ASE0_BRST)); | ||
86 | + mod_timer(&musb->otg_timer, jiffies | ||
87 | + + msecs_to_jiffies( | ||
88 | + OTG_TIME_B_ASE0_BRST)); | ||
89 | #endif | ||
90 | } | ||
91 | break; | ||
92 | @@ -1680,7 +1674,8 @@ musb_vbus_store(struct device *dev, struct device_attribute *attr, | ||
93 | } | ||
94 | |||
95 | spin_lock_irqsave(&musb->lock, flags); | ||
96 | - musb->a_wait_bcon = val; | ||
97 | + /* force T(a_wait_bcon) to be zero/unlimited *OR* valid */ | ||
98 | + musb->a_wait_bcon = val ? max_t(int, val, OTG_TIME_A_WAIT_BCON) : 0 ; | ||
99 | if (musb->xceiv->state == OTG_STATE_A_WAIT_BCON) | ||
100 | musb->is_active = 0; | ||
101 | musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(val)); | ||
102 | @@ -1699,10 +1694,13 @@ musb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
103 | |||
104 | spin_lock_irqsave(&musb->lock, flags); | ||
105 | val = musb->a_wait_bcon; | ||
106 | + /* FIXME get_vbus_status() is normally #defined as false... | ||
107 | + * and is effectively TUSB-specific. | ||
108 | + */ | ||
109 | vbus = musb_platform_get_vbus_status(musb); | ||
110 | spin_unlock_irqrestore(&musb->lock, flags); | ||
111 | |||
112 | - return sprintf(buf, "Vbus %s, timeout %lu\n", | ||
113 | + return sprintf(buf, "Vbus %s, timeout %lu msec\n", | ||
114 | vbus ? "on" : "off", val); | ||
115 | } | ||
116 | static DEVICE_ATTR(vbus, 0644, musb_vbus_show, musb_vbus_store); | ||
117 | @@ -1775,6 +1773,7 @@ allocate_instance(struct device *dev, | ||
118 | hcd->uses_new_polling = 1; | ||
119 | |||
120 | musb->vbuserr_retry = VBUSERR_RETRY_COUNT; | ||
121 | + musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON; | ||
122 | #else | ||
123 | musb = kzalloc(sizeof *musb, GFP_KERNEL); | ||
124 | if (!musb) | ||
125 | @@ -1969,6 +1968,10 @@ bad_config: | ||
126 | if (status < 0) | ||
127 | goto fail2; | ||
128 | |||
129 | +#ifdef CONFIG_USB_OTG | ||
130 | + setup_timer(&musb->otg_timer, musb_otg_timer_func, (unsigned long) musb); | ||
131 | +#endif | ||
132 | + | ||
133 | /* Init IRQ workqueue before request_irq */ | ||
134 | INIT_WORK(&musb->irq_work, musb_irq_work); | ||
135 | |||
136 | diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h | ||
137 | index c3ee348..cf3ccb0 100644 | ||
138 | --- a/drivers/usb/musb/musb_core.h | ||
139 | +++ b/drivers/usb/musb/musb_core.h | ||
140 | @@ -40,6 +40,7 @@ | ||
141 | #include <linux/interrupt.h> | ||
142 | #include <linux/smp_lock.h> | ||
143 | #include <linux/errno.h> | ||
144 | +#include <linux/timer.h> | ||
145 | #include <linux/clk.h> | ||
146 | #include <linux/device.h> | ||
147 | #include <linux/usb/ch9.h> | ||
148 | @@ -180,10 +181,15 @@ enum musb_g_ep0_state { | ||
149 | MUSB_EP0_STAGE_ACKWAIT, /* after zlp, before statusin */ | ||
150 | } __attribute__ ((packed)); | ||
151 | |||
152 | -/* OTG protocol constants */ | ||
153 | +/* | ||
154 | + * OTG protocol constants. See USB OTG 1.3 spec, | ||
155 | + * sections 5.5 "Device Timings" and 6.6.5 "Timers". | ||
156 | + */ | ||
157 | #define OTG_TIME_A_WAIT_VRISE 100 /* msec (max) */ | ||
158 | -#define OTG_TIME_A_WAIT_BCON 0 /* 0=infinite; min 1000 msec */ | ||
159 | -#define OTG_TIME_A_IDLE_BDIS 200 /* msec (min) */ | ||
160 | +#define OTG_TIME_A_WAIT_BCON 1100 /* min 1 second */ | ||
161 | +#define OTG_TIME_A_AIDL_BDIS 200 /* min 200 msec */ | ||
162 | +#define OTG_TIME_B_ASE0_BRST 100 /* min 3.125 ms */ | ||
163 | + | ||
164 | |||
165 | /*************************** REGISTER ACCESS ********************************/ | ||
166 | |||
167 | @@ -332,6 +338,8 @@ struct musb { | ||
168 | struct list_head control; /* of musb_qh */ | ||
169 | struct list_head in_bulk; /* of musb_qh */ | ||
170 | struct list_head out_bulk; /* of musb_qh */ | ||
171 | + | ||
172 | + struct timer_list otg_timer; | ||
173 | #endif | ||
174 | |||
175 | /* called with IRQs blocked; ON/nonzero implies starting a session, | ||
176 | diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c | ||
177 | index 5f67b03..3fbc807 100644 | ||
178 | --- a/drivers/usb/musb/omap2430.c | ||
179 | +++ b/drivers/usb/musb/omap2430.c | ||
180 | @@ -45,7 +45,6 @@ | ||
181 | #define get_cpu_rev() 2 | ||
182 | #endif | ||
183 | |||
184 | -#define MUSB_TIMEOUT_A_WAIT_BCON 1100 | ||
185 | |||
186 | static struct timer_list musb_idle_timer; | ||
187 | |||
188 | @@ -246,7 +245,6 @@ int __init musb_platform_init(struct musb *musb) | ||
189 | |||
190 | if (is_host_enabled(musb)) | ||
191 | musb->board_set_vbus = omap_set_vbus; | ||
192 | - musb->a_wait_bcon = MUSB_TIMEOUT_A_WAIT_BCON; | ||
193 | |||
194 | setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); | ||
195 | |||
196 | -- | ||
197 | 1.6.0.4 | ||
198 | |||
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0028-musb-make-initial-HNP-roleswitch-work-v2.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0028-musb-make-initial-HNP-roleswitch-work-v2.patch deleted file mode 100644 index 6269016223..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0028-musb-make-initial-HNP-roleswitch-work-v2.patch +++ /dev/null | |||
@@ -1,133 +0,0 @@ | |||
1 | From a637c5056ef52fbb7c41eb7537a9ec3d150231ad Mon Sep 17 00:00:00 2001 | ||
2 | From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
3 | Date: Thu, 2 Apr 2009 10:16:11 -0700 | ||
4 | Subject: [PATCH] musb: make initial HNP roleswitch work (v2) | ||
5 | |||
6 | Minor HNP bugfixes, so the initial role switch works: | ||
7 | |||
8 | - A-Device: | ||
9 | * disconnect-during-suspend enters A_PERIPHERAL state | ||
10 | * kill OTG timer after reset as A_PERIPHERAL ... | ||
11 | * ... and also pass that reset to the gadget | ||
12 | * once HNP succeeds, clear the "ignore_disconnect" flag | ||
13 | * from A_PERIPHERAL, disconnect transitions to A_WAIT_BCON | ||
14 | |||
15 | - B-Device: | ||
16 | * kill OTG timer on entry to B_HOST state (HNP succeeded) | ||
17 | * once HNP succeeds, clear "ignore_disconnect" flag | ||
18 | * kick the root hub only _after_ the state is adjusted | ||
19 | |||
20 | Other state transitions are left alone. Notably, exit paths from | ||
21 | the "roles have switched" state ... A_PERIPHERAL handling of that | ||
22 | stays seriously broken. | ||
23 | |||
24 | Signed-off-by: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
25 | --- | ||
26 | drivers/usb/musb/musb_core.c | 27 ++++++++++++++++----------- | ||
27 | drivers/usb/musb/musb_gadget.c | 2 +- | ||
28 | drivers/usb/musb/musb_virthub.c | 11 ++++++++++- | ||
29 | 3 files changed, 27 insertions(+), 13 deletions(-) | ||
30 | |||
31 | diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c | ||
32 | index 05c5dd3..9dc995a 100644 | ||
33 | --- a/drivers/usb/musb/musb_core.c | ||
34 | +++ b/drivers/usb/musb/musb_core.c | ||
35 | @@ -587,28 +587,23 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | ||
36 | if (devctl & MUSB_DEVCTL_LSDEV) | ||
37 | musb->port1_status |= USB_PORT_STAT_LOW_SPEED; | ||
38 | |||
39 | - if (hcd->status_urb) | ||
40 | - usb_hcd_poll_rh_status(hcd); | ||
41 | - else | ||
42 | - usb_hcd_resume_root_hub(hcd); | ||
43 | - | ||
44 | - MUSB_HST_MODE(musb); | ||
45 | - | ||
46 | /* indicate new connection to OTG machine */ | ||
47 | switch (musb->xceiv->state) { | ||
48 | case OTG_STATE_B_PERIPHERAL: | ||
49 | if (int_usb & MUSB_INTR_SUSPEND) { | ||
50 | DBG(1, "HNP: SUSPEND+CONNECT, now b_host\n"); | ||
51 | - musb->xceiv->state = OTG_STATE_B_HOST; | ||
52 | - hcd->self.is_b_host = 1; | ||
53 | int_usb &= ~MUSB_INTR_SUSPEND; | ||
54 | + goto b_host; | ||
55 | } else | ||
56 | DBG(1, "CONNECT as b_peripheral???\n"); | ||
57 | break; | ||
58 | case OTG_STATE_B_WAIT_ACON: | ||
59 | - DBG(1, "HNP: Waiting to switch to b_host state\n"); | ||
60 | + DBG(1, "HNP: CONNECT, now b_host\n"); | ||
61 | +b_host: | ||
62 | musb->xceiv->state = OTG_STATE_B_HOST; | ||
63 | hcd->self.is_b_host = 1; | ||
64 | + musb->ignore_disconnect = 0; | ||
65 | + del_timer(&musb->otg_timer); | ||
66 | break; | ||
67 | default: | ||
68 | if ((devctl & MUSB_DEVCTL_VBUS) | ||
69 | @@ -618,6 +613,14 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | ||
70 | } | ||
71 | break; | ||
72 | } | ||
73 | + | ||
74 | + /* poke the root hub */ | ||
75 | + MUSB_HST_MODE(musb); | ||
76 | + if (hcd->status_urb) | ||
77 | + usb_hcd_poll_rh_status(hcd); | ||
78 | + else | ||
79 | + usb_hcd_resume_root_hub(hcd); | ||
80 | + | ||
81 | DBG(1, "CONNECT (%s) devctl %02x\n", | ||
82 | otg_state_string(musb), devctl); | ||
83 | } | ||
84 | @@ -662,7 +665,9 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | ||
85 | + msecs_to_jiffies(TA_WAIT_BCON(musb))); | ||
86 | break; | ||
87 | case OTG_STATE_A_PERIPHERAL: | ||
88 | - musb_hnp_stop(musb); | ||
89 | + musb->ignore_disconnect = 0; | ||
90 | + del_timer(&musb->otg_timer); | ||
91 | + musb_g_reset(musb); | ||
92 | break; | ||
93 | case OTG_STATE_B_WAIT_ACON: | ||
94 | DBG(1, "HNP: RESET (%s), to b_peripheral\n", | ||
95 | diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c | ||
96 | index 2fbfba5..7dd3d59 100644 | ||
97 | --- a/drivers/usb/musb/musb_gadget.c | ||
98 | +++ b/drivers/usb/musb/musb_gadget.c | ||
99 | @@ -1964,7 +1964,7 @@ void musb_g_disconnect(struct musb *musb) | ||
100 | musb->xceiv->state = OTG_STATE_A_IDLE; | ||
101 | break; | ||
102 | case OTG_STATE_A_PERIPHERAL: | ||
103 | - musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; | ||
104 | + musb->xceiv->state = OTG_STATE_A_WAIT_BCON; | ||
105 | break; | ||
106 | case OTG_STATE_B_WAIT_ACON: | ||
107 | case OTG_STATE_B_HOST: | ||
108 | diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c | ||
109 | index 7e7900f..14f7cf3 100644 | ||
110 | --- a/drivers/usb/musb/musb_virthub.c | ||
111 | +++ b/drivers/usb/musb/musb_virthub.c | ||
112 | @@ -187,8 +187,17 @@ void musb_root_disconnect(struct musb *musb) | ||
113 | musb->is_active = 0; | ||
114 | |||
115 | switch (musb->xceiv->state) { | ||
116 | - case OTG_STATE_A_HOST: | ||
117 | case OTG_STATE_A_SUSPEND: | ||
118 | +#ifdef CONFIG_USB_MUSB_OTG | ||
119 | + if (is_otg_enabled(musb) | ||
120 | + && musb->xceiv->host->b_hnp_enable) { | ||
121 | + musb->xceiv->state = OTG_STATE_A_PERIPHERAL; | ||
122 | + musb->g.is_a_peripheral = 1; | ||
123 | + break; | ||
124 | + } | ||
125 | +#endif | ||
126 | + /* FALLTHROUGH */ | ||
127 | + case OTG_STATE_A_HOST: | ||
128 | musb->xceiv->state = OTG_STATE_A_WAIT_BCON; | ||
129 | musb->is_active = 0; | ||
130 | break; | ||
131 | -- | ||
132 | 1.6.0.4 | ||
133 | |||
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 deleted file mode 100644 index fc34fb983e..0000000000 --- a/meta/recipes-kernel/linux/linux-omap-2.6.29/musb/0029-musb-support-disconnect-after-HNP-roleswitch.patch +++ /dev/null | |||
@@ -1,145 +0,0 @@ | |||
1 | From 4288b7df4ae6629a4fb14aca2c489da01d4d19c3 Mon Sep 17 00:00:00 2001 | ||
2 | From: David Brownell <dbrownell-Rn4VEauK+AKRv+LV9MX5uipxlwaOVQ5f@public.gmane.org> | ||
3 | Date: Tue, 31 Mar 2009 12:35:09 -0700 | ||
4 | Subject: [PATCH] musb: support disconnect after HNP roleswitch | ||
5 | |||
6 | Adjust HNP state machines in MUSB driver so that they handle the | ||
7 | case where the cable is disconnected. The A-side machine was | ||
8 | very 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 | |||
23 | Also adjust the A_SUSPEND transition to respect the A_AIDL_BDIS | ||
24 | timeout, so if HNP doesn't trigger quickly enough the A_WAIT_VFALL | ||
25 | transition happens as it should. | ||
26 | |||
27 | Signed-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 | |||
34 | diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c | ||
35 | index 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: | ||
112 | diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c | ||
113 | index 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: | ||
128 | diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c | ||
129 | index 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 | -- | ||
144 | 1.6.0.4 | ||
145 | |||