diff options
author | Felipe Balbi <felipe.balbi@nokia.com> | 2008-07-24 05:27:36 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-08-13 20:33:00 -0400 |
commit | 550a7375fe720924241f0eb76e4a5c1a3eb8c32f (patch) | |
tree | bf973b43f6248e085557dcc268ad04d6e438d030 /drivers/usb/musb/musb_gadget_ep0.c | |
parent | f331e40ee8e4861e1d82310b1af7cf75de7370ac (diff) |
USB: Add MUSB and TUSB support
This patch adds support for MUSB and TUSB controllers
integrated into omap2430 and davinci. It also adds support
for external tusb6010 controller.
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: Tony Lindgren <tony@atomide.com>
Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/musb/musb_gadget_ep0.c')
-rw-r--r-- | drivers/usb/musb/musb_gadget_ep0.c | 981 |
1 files changed, 981 insertions, 0 deletions
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c new file mode 100644 index 000000000000..48d7d3ccb243 --- /dev/null +++ b/drivers/usb/musb/musb_gadget_ep0.c | |||
@@ -0,0 +1,981 @@ | |||
1 | /* | ||
2 | * MUSB OTG peripheral driver ep0 handling | ||
3 | * | ||
4 | * Copyright 2005 Mentor Graphics Corporation | ||
5 | * Copyright (C) 2005-2006 by Texas Instruments | ||
6 | * Copyright (C) 2006-2007 Nokia Corporation | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED | ||
23 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
24 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
25 | * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
28 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
29 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
32 | * | ||
33 | */ | ||
34 | |||
35 | #include <linux/kernel.h> | ||
36 | #include <linux/list.h> | ||
37 | #include <linux/timer.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/init.h> | ||
40 | #include <linux/device.h> | ||
41 | #include <linux/interrupt.h> | ||
42 | |||
43 | #include "musb_core.h" | ||
44 | |||
45 | /* ep0 is always musb->endpoints[0].ep_in */ | ||
46 | #define next_ep0_request(musb) next_in_request(&(musb)->endpoints[0]) | ||
47 | |||
48 | /* | ||
49 | * locking note: we use only the controller lock, for simpler correctness. | ||
50 | * It's always held with IRQs blocked. | ||
51 | * | ||
52 | * It protects the ep0 request queue as well as ep0_state, not just the | ||
53 | * controller and indexed registers. And that lock stays held unless it | ||
54 | * needs to be dropped to allow reentering this driver ... like upcalls to | ||
55 | * the gadget driver, or adjusting endpoint halt status. | ||
56 | */ | ||
57 | |||
58 | static char *decode_ep0stage(u8 stage) | ||
59 | { | ||
60 | switch (stage) { | ||
61 | case MUSB_EP0_STAGE_SETUP: return "idle"; | ||
62 | case MUSB_EP0_STAGE_TX: return "in"; | ||
63 | case MUSB_EP0_STAGE_RX: return "out"; | ||
64 | case MUSB_EP0_STAGE_ACKWAIT: return "wait"; | ||
65 | case MUSB_EP0_STAGE_STATUSIN: return "in/status"; | ||
66 | case MUSB_EP0_STAGE_STATUSOUT: return "out/status"; | ||
67 | default: return "?"; | ||
68 | } | ||
69 | } | ||
70 | |||
71 | /* handle a standard GET_STATUS request | ||
72 | * Context: caller holds controller lock | ||
73 | */ | ||
74 | static int service_tx_status_request( | ||
75 | struct musb *musb, | ||
76 | const struct usb_ctrlrequest *ctrlrequest) | ||
77 | { | ||
78 | void __iomem *mbase = musb->mregs; | ||
79 | int handled = 1; | ||
80 | u8 result[2], epnum = 0; | ||
81 | const u8 recip = ctrlrequest->bRequestType & USB_RECIP_MASK; | ||
82 | |||
83 | result[1] = 0; | ||
84 | |||
85 | switch (recip) { | ||
86 | case USB_RECIP_DEVICE: | ||
87 | result[0] = musb->is_self_powered << USB_DEVICE_SELF_POWERED; | ||
88 | result[0] |= musb->may_wakeup << USB_DEVICE_REMOTE_WAKEUP; | ||
89 | #ifdef CONFIG_USB_MUSB_OTG | ||
90 | if (musb->g.is_otg) { | ||
91 | result[0] |= musb->g.b_hnp_enable | ||
92 | << USB_DEVICE_B_HNP_ENABLE; | ||
93 | result[0] |= musb->g.a_alt_hnp_support | ||
94 | << USB_DEVICE_A_ALT_HNP_SUPPORT; | ||
95 | result[0] |= musb->g.a_hnp_support | ||
96 | << USB_DEVICE_A_HNP_SUPPORT; | ||
97 | } | ||
98 | #endif | ||
99 | break; | ||
100 | |||
101 | case USB_RECIP_INTERFACE: | ||
102 | result[0] = 0; | ||
103 | break; | ||
104 | |||
105 | case USB_RECIP_ENDPOINT: { | ||
106 | int is_in; | ||
107 | struct musb_ep *ep; | ||
108 | u16 tmp; | ||
109 | void __iomem *regs; | ||
110 | |||
111 | epnum = (u8) ctrlrequest->wIndex; | ||
112 | if (!epnum) { | ||
113 | result[0] = 0; | ||
114 | break; | ||
115 | } | ||
116 | |||
117 | is_in = epnum & USB_DIR_IN; | ||
118 | if (is_in) { | ||
119 | epnum &= 0x0f; | ||
120 | ep = &musb->endpoints[epnum].ep_in; | ||
121 | } else { | ||
122 | ep = &musb->endpoints[epnum].ep_out; | ||
123 | } | ||
124 | regs = musb->endpoints[epnum].regs; | ||
125 | |||
126 | if (epnum >= MUSB_C_NUM_EPS || !ep->desc) { | ||
127 | handled = -EINVAL; | ||
128 | break; | ||
129 | } | ||
130 | |||
131 | musb_ep_select(mbase, epnum); | ||
132 | if (is_in) | ||
133 | tmp = musb_readw(regs, MUSB_TXCSR) | ||
134 | & MUSB_TXCSR_P_SENDSTALL; | ||
135 | else | ||
136 | tmp = musb_readw(regs, MUSB_RXCSR) | ||
137 | & MUSB_RXCSR_P_SENDSTALL; | ||
138 | musb_ep_select(mbase, 0); | ||
139 | |||
140 | result[0] = tmp ? 1 : 0; | ||
141 | } break; | ||
142 | |||
143 | default: | ||
144 | /* class, vendor, etc ... delegate */ | ||
145 | handled = 0; | ||
146 | break; | ||
147 | } | ||
148 | |||
149 | /* fill up the fifo; caller updates csr0 */ | ||
150 | if (handled > 0) { | ||
151 | u16 len = le16_to_cpu(ctrlrequest->wLength); | ||
152 | |||
153 | if (len > 2) | ||
154 | len = 2; | ||
155 | musb_write_fifo(&musb->endpoints[0], len, result); | ||
156 | } | ||
157 | |||
158 | return handled; | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * handle a control-IN request, the end0 buffer contains the current request | ||
163 | * that is supposed to be a standard control request. Assumes the fifo to | ||
164 | * be at least 2 bytes long. | ||
165 | * | ||
166 | * @return 0 if the request was NOT HANDLED, | ||
167 | * < 0 when error | ||
168 | * > 0 when the request is processed | ||
169 | * | ||
170 | * Context: caller holds controller lock | ||
171 | */ | ||
172 | static int | ||
173 | service_in_request(struct musb *musb, const struct usb_ctrlrequest *ctrlrequest) | ||
174 | { | ||
175 | int handled = 0; /* not handled */ | ||
176 | |||
177 | if ((ctrlrequest->bRequestType & USB_TYPE_MASK) | ||
178 | == USB_TYPE_STANDARD) { | ||
179 | switch (ctrlrequest->bRequest) { | ||
180 | case USB_REQ_GET_STATUS: | ||
181 | handled = service_tx_status_request(musb, | ||
182 | ctrlrequest); | ||
183 | break; | ||
184 | |||
185 | /* case USB_REQ_SYNC_FRAME: */ | ||
186 | |||
187 | default: | ||
188 | break; | ||
189 | } | ||
190 | } | ||
191 | return handled; | ||
192 | } | ||
193 | |||
194 | /* | ||
195 | * Context: caller holds controller lock | ||
196 | */ | ||
197 | static void musb_g_ep0_giveback(struct musb *musb, struct usb_request *req) | ||
198 | { | ||
199 | musb_g_giveback(&musb->endpoints[0].ep_in, req, 0); | ||
200 | musb->ep0_state = MUSB_EP0_STAGE_SETUP; | ||
201 | } | ||
202 | |||
203 | /* | ||
204 | * Tries to start B-device HNP negotiation if enabled via sysfs | ||
205 | */ | ||
206 | static inline void musb_try_b_hnp_enable(struct musb *musb) | ||
207 | { | ||
208 | void __iomem *mbase = musb->mregs; | ||
209 | u8 devctl; | ||
210 | |||
211 | DBG(1, "HNP: Setting HR\n"); | ||
212 | devctl = musb_readb(mbase, MUSB_DEVCTL); | ||
213 | musb_writeb(mbase, MUSB_DEVCTL, devctl | MUSB_DEVCTL_HR); | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * Handle all control requests with no DATA stage, including standard | ||
218 | * requests such as: | ||
219 | * USB_REQ_SET_CONFIGURATION, USB_REQ_SET_INTERFACE, unrecognized | ||
220 | * always delegated to the gadget driver | ||
221 | * USB_REQ_SET_ADDRESS, USB_REQ_CLEAR_FEATURE, USB_REQ_SET_FEATURE | ||
222 | * always handled here, except for class/vendor/... features | ||
223 | * | ||
224 | * Context: caller holds controller lock | ||
225 | */ | ||
226 | static int | ||
227 | service_zero_data_request(struct musb *musb, | ||
228 | struct usb_ctrlrequest *ctrlrequest) | ||
229 | __releases(musb->lock) | ||
230 | __acquires(musb->lock) | ||
231 | { | ||
232 | int handled = -EINVAL; | ||
233 | void __iomem *mbase = musb->mregs; | ||
234 | const u8 recip = ctrlrequest->bRequestType & USB_RECIP_MASK; | ||
235 | |||
236 | /* the gadget driver handles everything except what we MUST handle */ | ||
237 | if ((ctrlrequest->bRequestType & USB_TYPE_MASK) | ||
238 | == USB_TYPE_STANDARD) { | ||
239 | switch (ctrlrequest->bRequest) { | ||
240 | case USB_REQ_SET_ADDRESS: | ||
241 | /* change it after the status stage */ | ||
242 | musb->set_address = true; | ||
243 | musb->address = (u8) (ctrlrequest->wValue & 0x7f); | ||
244 | handled = 1; | ||
245 | break; | ||
246 | |||
247 | case USB_REQ_CLEAR_FEATURE: | ||
248 | switch (recip) { | ||
249 | case USB_RECIP_DEVICE: | ||
250 | if (ctrlrequest->wValue | ||
251 | != USB_DEVICE_REMOTE_WAKEUP) | ||
252 | break; | ||
253 | musb->may_wakeup = 0; | ||
254 | handled = 1; | ||
255 | break; | ||
256 | case USB_RECIP_INTERFACE: | ||
257 | break; | ||
258 | case USB_RECIP_ENDPOINT:{ | ||
259 | const u8 num = ctrlrequest->wIndex & 0x0f; | ||
260 | struct musb_ep *musb_ep; | ||
261 | |||
262 | if (num == 0 | ||
263 | || num >= MUSB_C_NUM_EPS | ||
264 | || ctrlrequest->wValue | ||
265 | != USB_ENDPOINT_HALT) | ||
266 | break; | ||
267 | |||
268 | if (ctrlrequest->wIndex & USB_DIR_IN) | ||
269 | musb_ep = &musb->endpoints[num].ep_in; | ||
270 | else | ||
271 | musb_ep = &musb->endpoints[num].ep_out; | ||
272 | if (!musb_ep->desc) | ||
273 | break; | ||
274 | |||
275 | /* REVISIT do it directly, no locking games */ | ||
276 | spin_unlock(&musb->lock); | ||
277 | musb_gadget_set_halt(&musb_ep->end_point, 0); | ||
278 | spin_lock(&musb->lock); | ||
279 | |||
280 | /* select ep0 again */ | ||
281 | musb_ep_select(mbase, 0); | ||
282 | handled = 1; | ||
283 | } break; | ||
284 | default: | ||
285 | /* class, vendor, etc ... delegate */ | ||
286 | handled = 0; | ||
287 | break; | ||
288 | } | ||
289 | break; | ||
290 | |||
291 | case USB_REQ_SET_FEATURE: | ||
292 | switch (recip) { | ||
293 | case USB_RECIP_DEVICE: | ||
294 | handled = 1; | ||
295 | switch (ctrlrequest->wValue) { | ||
296 | case USB_DEVICE_REMOTE_WAKEUP: | ||
297 | musb->may_wakeup = 1; | ||
298 | break; | ||
299 | case USB_DEVICE_TEST_MODE: | ||
300 | if (musb->g.speed != USB_SPEED_HIGH) | ||
301 | goto stall; | ||
302 | if (ctrlrequest->wIndex & 0xff) | ||
303 | goto stall; | ||
304 | |||
305 | switch (ctrlrequest->wIndex >> 8) { | ||
306 | case 1: | ||
307 | pr_debug("TEST_J\n"); | ||
308 | /* TEST_J */ | ||
309 | musb->test_mode_nr = | ||
310 | MUSB_TEST_J; | ||
311 | break; | ||
312 | case 2: | ||
313 | /* TEST_K */ | ||
314 | pr_debug("TEST_K\n"); | ||
315 | musb->test_mode_nr = | ||
316 | MUSB_TEST_K; | ||
317 | break; | ||
318 | case 3: | ||
319 | /* TEST_SE0_NAK */ | ||
320 | pr_debug("TEST_SE0_NAK\n"); | ||
321 | musb->test_mode_nr = | ||
322 | MUSB_TEST_SE0_NAK; | ||
323 | break; | ||
324 | case 4: | ||
325 | /* TEST_PACKET */ | ||
326 | pr_debug("TEST_PACKET\n"); | ||
327 | musb->test_mode_nr = | ||
328 | MUSB_TEST_PACKET; | ||
329 | break; | ||
330 | default: | ||
331 | goto stall; | ||
332 | } | ||
333 | |||
334 | /* enter test mode after irq */ | ||
335 | if (handled > 0) | ||
336 | musb->test_mode = true; | ||
337 | break; | ||
338 | #ifdef CONFIG_USB_MUSB_OTG | ||
339 | case USB_DEVICE_B_HNP_ENABLE: | ||
340 | if (!musb->g.is_otg) | ||
341 | goto stall; | ||
342 | musb->g.b_hnp_enable = 1; | ||
343 | musb_try_b_hnp_enable(musb); | ||
344 | break; | ||
345 | case USB_DEVICE_A_HNP_SUPPORT: | ||
346 | if (!musb->g.is_otg) | ||
347 | goto stall; | ||
348 | musb->g.a_hnp_support = 1; | ||
349 | break; | ||
350 | case USB_DEVICE_A_ALT_HNP_SUPPORT: | ||
351 | if (!musb->g.is_otg) | ||
352 | goto stall; | ||
353 | musb->g.a_alt_hnp_support = 1; | ||
354 | break; | ||
355 | #endif | ||
356 | stall: | ||
357 | default: | ||
358 | handled = -EINVAL; | ||
359 | break; | ||
360 | } | ||
361 | break; | ||
362 | |||
363 | case USB_RECIP_INTERFACE: | ||
364 | break; | ||
365 | |||
366 | case USB_RECIP_ENDPOINT:{ | ||
367 | const u8 epnum = | ||
368 | ctrlrequest->wIndex & 0x0f; | ||
369 | struct musb_ep *musb_ep; | ||
370 | struct musb_hw_ep *ep; | ||
371 | void __iomem *regs; | ||
372 | int is_in; | ||
373 | u16 csr; | ||
374 | |||
375 | if (epnum == 0 | ||
376 | || epnum >= MUSB_C_NUM_EPS | ||
377 | || ctrlrequest->wValue | ||
378 | != USB_ENDPOINT_HALT) | ||
379 | break; | ||
380 | |||
381 | ep = musb->endpoints + epnum; | ||
382 | regs = ep->regs; | ||
383 | is_in = ctrlrequest->wIndex & USB_DIR_IN; | ||
384 | if (is_in) | ||
385 | musb_ep = &ep->ep_in; | ||
386 | else | ||
387 | musb_ep = &ep->ep_out; | ||
388 | if (!musb_ep->desc) | ||
389 | break; | ||
390 | |||
391 | musb_ep_select(mbase, epnum); | ||
392 | if (is_in) { | ||
393 | csr = musb_readw(regs, | ||
394 | MUSB_TXCSR); | ||
395 | if (csr & MUSB_TXCSR_FIFONOTEMPTY) | ||
396 | csr |= MUSB_TXCSR_FLUSHFIFO; | ||
397 | csr |= MUSB_TXCSR_P_SENDSTALL | ||
398 | | MUSB_TXCSR_CLRDATATOG | ||
399 | | MUSB_TXCSR_P_WZC_BITS; | ||
400 | musb_writew(regs, MUSB_TXCSR, | ||
401 | csr); | ||
402 | } else { | ||
403 | csr = musb_readw(regs, | ||
404 | MUSB_RXCSR); | ||
405 | csr |= MUSB_RXCSR_P_SENDSTALL | ||
406 | | MUSB_RXCSR_FLUSHFIFO | ||
407 | | MUSB_RXCSR_CLRDATATOG | ||
408 | | MUSB_TXCSR_P_WZC_BITS; | ||
409 | musb_writew(regs, MUSB_RXCSR, | ||
410 | csr); | ||
411 | } | ||
412 | |||
413 | /* select ep0 again */ | ||
414 | musb_ep_select(mbase, 0); | ||
415 | handled = 1; | ||
416 | } break; | ||
417 | |||
418 | default: | ||
419 | /* class, vendor, etc ... delegate */ | ||
420 | handled = 0; | ||
421 | break; | ||
422 | } | ||
423 | break; | ||
424 | default: | ||
425 | /* delegate SET_CONFIGURATION, etc */ | ||
426 | handled = 0; | ||
427 | } | ||
428 | } else | ||
429 | handled = 0; | ||
430 | return handled; | ||
431 | } | ||
432 | |||
433 | /* we have an ep0out data packet | ||
434 | * Context: caller holds controller lock | ||
435 | */ | ||
436 | static void ep0_rxstate(struct musb *musb) | ||
437 | { | ||
438 | void __iomem *regs = musb->control_ep->regs; | ||
439 | struct usb_request *req; | ||
440 | u16 tmp; | ||
441 | |||
442 | req = next_ep0_request(musb); | ||
443 | |||
444 | /* read packet and ack; or stall because of gadget driver bug: | ||
445 | * should have provided the rx buffer before setup() returned. | ||
446 | */ | ||
447 | if (req) { | ||
448 | void *buf = req->buf + req->actual; | ||
449 | unsigned len = req->length - req->actual; | ||
450 | |||
451 | /* read the buffer */ | ||
452 | tmp = musb_readb(regs, MUSB_COUNT0); | ||
453 | if (tmp > len) { | ||
454 | req->status = -EOVERFLOW; | ||
455 | tmp = len; | ||
456 | } | ||
457 | musb_read_fifo(&musb->endpoints[0], tmp, buf); | ||
458 | req->actual += tmp; | ||
459 | tmp = MUSB_CSR0_P_SVDRXPKTRDY; | ||
460 | if (tmp < 64 || req->actual == req->length) { | ||
461 | musb->ep0_state = MUSB_EP0_STAGE_STATUSIN; | ||
462 | tmp |= MUSB_CSR0_P_DATAEND; | ||
463 | } else | ||
464 | req = NULL; | ||
465 | } else | ||
466 | tmp = MUSB_CSR0_P_SVDRXPKTRDY | MUSB_CSR0_P_SENDSTALL; | ||
467 | |||
468 | |||
469 | /* Completion handler may choose to stall, e.g. because the | ||
470 | * message just received holds invalid data. | ||
471 | */ | ||
472 | if (req) { | ||
473 | musb->ackpend = tmp; | ||
474 | musb_g_ep0_giveback(musb, req); | ||
475 | if (!musb->ackpend) | ||
476 | return; | ||
477 | musb->ackpend = 0; | ||
478 | } | ||
479 | musb_writew(regs, MUSB_CSR0, tmp); | ||
480 | } | ||
481 | |||
482 | /* | ||
483 | * transmitting to the host (IN), this code might be called from IRQ | ||
484 | * and from kernel thread. | ||
485 | * | ||
486 | * Context: caller holds controller lock | ||
487 | */ | ||
488 | static void ep0_txstate(struct musb *musb) | ||
489 | { | ||
490 | void __iomem *regs = musb->control_ep->regs; | ||
491 | struct usb_request *request = next_ep0_request(musb); | ||
492 | u16 csr = MUSB_CSR0_TXPKTRDY; | ||
493 | u8 *fifo_src; | ||
494 | u8 fifo_count; | ||
495 | |||
496 | if (!request) { | ||
497 | /* WARN_ON(1); */ | ||
498 | DBG(2, "odd; csr0 %04x\n", musb_readw(regs, MUSB_CSR0)); | ||
499 | return; | ||
500 | } | ||
501 | |||
502 | /* load the data */ | ||
503 | fifo_src = (u8 *) request->buf + request->actual; | ||
504 | fifo_count = min((unsigned) MUSB_EP0_FIFOSIZE, | ||
505 | request->length - request->actual); | ||
506 | musb_write_fifo(&musb->endpoints[0], fifo_count, fifo_src); | ||
507 | request->actual += fifo_count; | ||
508 | |||
509 | /* update the flags */ | ||
510 | if (fifo_count < MUSB_MAX_END0_PACKET | ||
511 | || request->actual == request->length) { | ||
512 | musb->ep0_state = MUSB_EP0_STAGE_STATUSOUT; | ||
513 | csr |= MUSB_CSR0_P_DATAEND; | ||
514 | } else | ||
515 | request = NULL; | ||
516 | |||
517 | /* report completions as soon as the fifo's loaded; there's no | ||
518 | * win in waiting till this last packet gets acked. (other than | ||
519 | * very precise fault reporting, needed by USB TMC; possible with | ||
520 | * this hardware, but not usable from portable gadget drivers.) | ||
521 | */ | ||
522 | if (request) { | ||
523 | musb->ackpend = csr; | ||
524 | musb_g_ep0_giveback(musb, request); | ||
525 | if (!musb->ackpend) | ||
526 | return; | ||
527 | musb->ackpend = 0; | ||
528 | } | ||
529 | |||
530 | /* send it out, triggering a "txpktrdy cleared" irq */ | ||
531 | musb_writew(regs, MUSB_CSR0, csr); | ||
532 | } | ||
533 | |||
534 | /* | ||
535 | * Read a SETUP packet (struct usb_ctrlrequest) from the hardware. | ||
536 | * Fields are left in USB byte-order. | ||
537 | * | ||
538 | * Context: caller holds controller lock. | ||
539 | */ | ||
540 | static void | ||
541 | musb_read_setup(struct musb *musb, struct usb_ctrlrequest *req) | ||
542 | { | ||
543 | struct usb_request *r; | ||
544 | void __iomem *regs = musb->control_ep->regs; | ||
545 | |||
546 | musb_read_fifo(&musb->endpoints[0], sizeof *req, (u8 *)req); | ||
547 | |||
548 | /* NOTE: earlier 2.6 versions changed setup packets to host | ||
549 | * order, but now USB packets always stay in USB byte order. | ||
550 | */ | ||
551 | DBG(3, "SETUP req%02x.%02x v%04x i%04x l%d\n", | ||
552 | req->bRequestType, | ||
553 | req->bRequest, | ||
554 | le16_to_cpu(req->wValue), | ||
555 | le16_to_cpu(req->wIndex), | ||
556 | le16_to_cpu(req->wLength)); | ||
557 | |||
558 | /* clean up any leftover transfers */ | ||
559 | r = next_ep0_request(musb); | ||
560 | if (r) | ||
561 | musb_g_ep0_giveback(musb, r); | ||
562 | |||
563 | /* For zero-data requests we want to delay the STATUS stage to | ||
564 | * avoid SETUPEND errors. If we read data (OUT), delay accepting | ||
565 | * packets until there's a buffer to store them in. | ||
566 | * | ||
567 | * If we write data, the controller acts happier if we enable | ||
568 | * the TX FIFO right away, and give the controller a moment | ||
569 | * to switch modes... | ||
570 | */ | ||
571 | musb->set_address = false; | ||
572 | musb->ackpend = MUSB_CSR0_P_SVDRXPKTRDY; | ||
573 | if (req->wLength == 0) { | ||
574 | if (req->bRequestType & USB_DIR_IN) | ||
575 | musb->ackpend |= MUSB_CSR0_TXPKTRDY; | ||
576 | musb->ep0_state = MUSB_EP0_STAGE_ACKWAIT; | ||
577 | } else if (req->bRequestType & USB_DIR_IN) { | ||
578 | musb->ep0_state = MUSB_EP0_STAGE_TX; | ||
579 | musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SVDRXPKTRDY); | ||
580 | while ((musb_readw(regs, MUSB_CSR0) | ||
581 | & MUSB_CSR0_RXPKTRDY) != 0) | ||
582 | cpu_relax(); | ||
583 | musb->ackpend = 0; | ||
584 | } else | ||
585 | musb->ep0_state = MUSB_EP0_STAGE_RX; | ||
586 | } | ||
587 | |||
588 | static int | ||
589 | forward_to_driver(struct musb *musb, const struct usb_ctrlrequest *ctrlrequest) | ||
590 | __releases(musb->lock) | ||
591 | __acquires(musb->lock) | ||
592 | { | ||
593 | int retval; | ||
594 | if (!musb->gadget_driver) | ||
595 | return -EOPNOTSUPP; | ||
596 | spin_unlock(&musb->lock); | ||
597 | retval = musb->gadget_driver->setup(&musb->g, ctrlrequest); | ||
598 | spin_lock(&musb->lock); | ||
599 | return retval; | ||
600 | } | ||
601 | |||
602 | /* | ||
603 | * Handle peripheral ep0 interrupt | ||
604 | * | ||
605 | * Context: irq handler; we won't re-enter the driver that way. | ||
606 | */ | ||
607 | irqreturn_t musb_g_ep0_irq(struct musb *musb) | ||
608 | { | ||
609 | u16 csr; | ||
610 | u16 len; | ||
611 | void __iomem *mbase = musb->mregs; | ||
612 | void __iomem *regs = musb->endpoints[0].regs; | ||
613 | irqreturn_t retval = IRQ_NONE; | ||
614 | |||
615 | musb_ep_select(mbase, 0); /* select ep0 */ | ||
616 | csr = musb_readw(regs, MUSB_CSR0); | ||
617 | len = musb_readb(regs, MUSB_COUNT0); | ||
618 | |||
619 | DBG(4, "csr %04x, count %d, myaddr %d, ep0stage %s\n", | ||
620 | csr, len, | ||
621 | musb_readb(mbase, MUSB_FADDR), | ||
622 | decode_ep0stage(musb->ep0_state)); | ||
623 | |||
624 | /* I sent a stall.. need to acknowledge it now.. */ | ||
625 | if (csr & MUSB_CSR0_P_SENTSTALL) { | ||
626 | musb_writew(regs, MUSB_CSR0, | ||
627 | csr & ~MUSB_CSR0_P_SENTSTALL); | ||
628 | retval = IRQ_HANDLED; | ||
629 | musb->ep0_state = MUSB_EP0_STAGE_SETUP; | ||
630 | csr = musb_readw(regs, MUSB_CSR0); | ||
631 | } | ||
632 | |||
633 | /* request ended "early" */ | ||
634 | if (csr & MUSB_CSR0_P_SETUPEND) { | ||
635 | musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SVDSETUPEND); | ||
636 | retval = IRQ_HANDLED; | ||
637 | musb->ep0_state = MUSB_EP0_STAGE_SETUP; | ||
638 | csr = musb_readw(regs, MUSB_CSR0); | ||
639 | /* NOTE: request may need completion */ | ||
640 | } | ||
641 | |||
642 | /* docs from Mentor only describe tx, rx, and idle/setup states. | ||
643 | * we need to handle nuances around status stages, and also the | ||
644 | * case where status and setup stages come back-to-back ... | ||
645 | */ | ||
646 | switch (musb->ep0_state) { | ||
647 | |||
648 | case MUSB_EP0_STAGE_TX: | ||
649 | /* irq on clearing txpktrdy */ | ||
650 | if ((csr & MUSB_CSR0_TXPKTRDY) == 0) { | ||
651 | ep0_txstate(musb); | ||
652 | retval = IRQ_HANDLED; | ||
653 | } | ||
654 | break; | ||
655 | |||
656 | case MUSB_EP0_STAGE_RX: | ||
657 | /* irq on set rxpktrdy */ | ||
658 | if (csr & MUSB_CSR0_RXPKTRDY) { | ||
659 | ep0_rxstate(musb); | ||
660 | retval = IRQ_HANDLED; | ||
661 | } | ||
662 | break; | ||
663 | |||
664 | case MUSB_EP0_STAGE_STATUSIN: | ||
665 | /* end of sequence #2 (OUT/RX state) or #3 (no data) */ | ||
666 | |||
667 | /* update address (if needed) only @ the end of the | ||
668 | * status phase per usb spec, which also guarantees | ||
669 | * we get 10 msec to receive this irq... until this | ||
670 | * is done we won't see the next packet. | ||
671 | */ | ||
672 | if (musb->set_address) { | ||
673 | musb->set_address = false; | ||
674 | musb_writeb(mbase, MUSB_FADDR, musb->address); | ||
675 | } | ||
676 | |||
677 | /* enter test mode if needed (exit by reset) */ | ||
678 | else if (musb->test_mode) { | ||
679 | DBG(1, "entering TESTMODE\n"); | ||
680 | |||
681 | if (MUSB_TEST_PACKET == musb->test_mode_nr) | ||
682 | musb_load_testpacket(musb); | ||
683 | |||
684 | musb_writeb(mbase, MUSB_TESTMODE, | ||
685 | musb->test_mode_nr); | ||
686 | } | ||
687 | /* FALLTHROUGH */ | ||
688 | |||
689 | case MUSB_EP0_STAGE_STATUSOUT: | ||
690 | /* end of sequence #1: write to host (TX state) */ | ||
691 | { | ||
692 | struct usb_request *req; | ||
693 | |||
694 | req = next_ep0_request(musb); | ||
695 | if (req) | ||
696 | musb_g_ep0_giveback(musb, req); | ||
697 | } | ||
698 | retval = IRQ_HANDLED; | ||
699 | musb->ep0_state = MUSB_EP0_STAGE_SETUP; | ||
700 | /* FALLTHROUGH */ | ||
701 | |||
702 | case MUSB_EP0_STAGE_SETUP: | ||
703 | if (csr & MUSB_CSR0_RXPKTRDY) { | ||
704 | struct usb_ctrlrequest setup; | ||
705 | int handled = 0; | ||
706 | |||
707 | if (len != 8) { | ||
708 | ERR("SETUP packet len %d != 8 ?\n", len); | ||
709 | break; | ||
710 | } | ||
711 | musb_read_setup(musb, &setup); | ||
712 | retval = IRQ_HANDLED; | ||
713 | |||
714 | /* sometimes the RESET won't be reported */ | ||
715 | if (unlikely(musb->g.speed == USB_SPEED_UNKNOWN)) { | ||
716 | u8 power; | ||
717 | |||
718 | printk(KERN_NOTICE "%s: peripheral reset " | ||
719 | "irq lost!\n", | ||
720 | musb_driver_name); | ||
721 | power = musb_readb(mbase, MUSB_POWER); | ||
722 | musb->g.speed = (power & MUSB_POWER_HSMODE) | ||
723 | ? USB_SPEED_HIGH : USB_SPEED_FULL; | ||
724 | |||
725 | } | ||
726 | |||
727 | switch (musb->ep0_state) { | ||
728 | |||
729 | /* sequence #3 (no data stage), includes requests | ||
730 | * we can't forward (notably SET_ADDRESS and the | ||
731 | * device/endpoint feature set/clear operations) | ||
732 | * plus SET_CONFIGURATION and others we must | ||
733 | */ | ||
734 | case MUSB_EP0_STAGE_ACKWAIT: | ||
735 | handled = service_zero_data_request( | ||
736 | musb, &setup); | ||
737 | |||
738 | /* status stage might be immediate */ | ||
739 | if (handled > 0) { | ||
740 | musb->ackpend |= MUSB_CSR0_P_DATAEND; | ||
741 | musb->ep0_state = | ||
742 | MUSB_EP0_STAGE_STATUSIN; | ||
743 | } | ||
744 | break; | ||
745 | |||
746 | /* sequence #1 (IN to host), includes GET_STATUS | ||
747 | * requests that we can't forward, GET_DESCRIPTOR | ||
748 | * and others that we must | ||
749 | */ | ||
750 | case MUSB_EP0_STAGE_TX: | ||
751 | handled = service_in_request(musb, &setup); | ||
752 | if (handled > 0) { | ||
753 | musb->ackpend = MUSB_CSR0_TXPKTRDY | ||
754 | | MUSB_CSR0_P_DATAEND; | ||
755 | musb->ep0_state = | ||
756 | MUSB_EP0_STAGE_STATUSOUT; | ||
757 | } | ||
758 | break; | ||
759 | |||
760 | /* sequence #2 (OUT from host), always forward */ | ||
761 | default: /* MUSB_EP0_STAGE_RX */ | ||
762 | break; | ||
763 | } | ||
764 | |||
765 | DBG(3, "handled %d, csr %04x, ep0stage %s\n", | ||
766 | handled, csr, | ||
767 | decode_ep0stage(musb->ep0_state)); | ||
768 | |||
769 | /* unless we need to delegate this to the gadget | ||
770 | * driver, we know how to wrap this up: csr0 has | ||
771 | * not yet been written. | ||
772 | */ | ||
773 | if (handled < 0) | ||
774 | goto stall; | ||
775 | else if (handled > 0) | ||
776 | goto finish; | ||
777 | |||
778 | handled = forward_to_driver(musb, &setup); | ||
779 | if (handled < 0) { | ||
780 | musb_ep_select(mbase, 0); | ||
781 | stall: | ||
782 | DBG(3, "stall (%d)\n", handled); | ||
783 | musb->ackpend |= MUSB_CSR0_P_SENDSTALL; | ||
784 | musb->ep0_state = MUSB_EP0_STAGE_SETUP; | ||
785 | finish: | ||
786 | musb_writew(regs, MUSB_CSR0, | ||
787 | musb->ackpend); | ||
788 | musb->ackpend = 0; | ||
789 | } | ||
790 | } | ||
791 | break; | ||
792 | |||
793 | case MUSB_EP0_STAGE_ACKWAIT: | ||
794 | /* This should not happen. But happens with tusb6010 with | ||
795 | * g_file_storage and high speed. Do nothing. | ||
796 | */ | ||
797 | retval = IRQ_HANDLED; | ||
798 | break; | ||
799 | |||
800 | default: | ||
801 | /* "can't happen" */ | ||
802 | WARN_ON(1); | ||
803 | musb_writew(regs, MUSB_CSR0, MUSB_CSR0_P_SENDSTALL); | ||
804 | musb->ep0_state = MUSB_EP0_STAGE_SETUP; | ||
805 | break; | ||
806 | } | ||
807 | |||
808 | return retval; | ||
809 | } | ||
810 | |||
811 | |||
812 | static int | ||
813 | musb_g_ep0_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *desc) | ||
814 | { | ||
815 | /* always enabled */ | ||
816 | return -EINVAL; | ||
817 | } | ||
818 | |||
819 | static int musb_g_ep0_disable(struct usb_ep *e) | ||
820 | { | ||
821 | /* always enabled */ | ||
822 | return -EINVAL; | ||
823 | } | ||
824 | |||
825 | static int | ||
826 | musb_g_ep0_queue(struct usb_ep *e, struct usb_request *r, gfp_t gfp_flags) | ||
827 | { | ||
828 | struct musb_ep *ep; | ||
829 | struct musb_request *req; | ||
830 | struct musb *musb; | ||
831 | int status; | ||
832 | unsigned long lockflags; | ||
833 | void __iomem *regs; | ||
834 | |||
835 | if (!e || !r) | ||
836 | return -EINVAL; | ||
837 | |||
838 | ep = to_musb_ep(e); | ||
839 | musb = ep->musb; | ||
840 | regs = musb->control_ep->regs; | ||
841 | |||
842 | req = to_musb_request(r); | ||
843 | req->musb = musb; | ||
844 | req->request.actual = 0; | ||
845 | req->request.status = -EINPROGRESS; | ||
846 | req->tx = ep->is_in; | ||
847 | |||
848 | spin_lock_irqsave(&musb->lock, lockflags); | ||
849 | |||
850 | if (!list_empty(&ep->req_list)) { | ||
851 | status = -EBUSY; | ||
852 | goto cleanup; | ||
853 | } | ||
854 | |||
855 | switch (musb->ep0_state) { | ||
856 | case MUSB_EP0_STAGE_RX: /* control-OUT data */ | ||
857 | case MUSB_EP0_STAGE_TX: /* control-IN data */ | ||
858 | case MUSB_EP0_STAGE_ACKWAIT: /* zero-length data */ | ||
859 | status = 0; | ||
860 | break; | ||
861 | default: | ||
862 | DBG(1, "ep0 request queued in state %d\n", | ||
863 | musb->ep0_state); | ||
864 | status = -EINVAL; | ||
865 | goto cleanup; | ||
866 | } | ||
867 | |||
868 | /* add request to the list */ | ||
869 | list_add_tail(&(req->request.list), &(ep->req_list)); | ||
870 | |||
871 | DBG(3, "queue to %s (%s), length=%d\n", | ||
872 | ep->name, ep->is_in ? "IN/TX" : "OUT/RX", | ||
873 | req->request.length); | ||
874 | |||
875 | musb_ep_select(musb->mregs, 0); | ||
876 | |||
877 | /* sequence #1, IN ... start writing the data */ | ||
878 | if (musb->ep0_state == MUSB_EP0_STAGE_TX) | ||
879 | ep0_txstate(musb); | ||
880 | |||
881 | /* sequence #3, no-data ... issue IN status */ | ||
882 | else if (musb->ep0_state == MUSB_EP0_STAGE_ACKWAIT) { | ||
883 | if (req->request.length) | ||
884 | status = -EINVAL; | ||
885 | else { | ||
886 | musb->ep0_state = MUSB_EP0_STAGE_STATUSIN; | ||
887 | musb_writew(regs, MUSB_CSR0, | ||
888 | musb->ackpend | MUSB_CSR0_P_DATAEND); | ||
889 | musb->ackpend = 0; | ||
890 | musb_g_ep0_giveback(ep->musb, r); | ||
891 | } | ||
892 | |||
893 | /* else for sequence #2 (OUT), caller provides a buffer | ||
894 | * before the next packet arrives. deferred responses | ||
895 | * (after SETUP is acked) are racey. | ||
896 | */ | ||
897 | } else if (musb->ackpend) { | ||
898 | musb_writew(regs, MUSB_CSR0, musb->ackpend); | ||
899 | musb->ackpend = 0; | ||
900 | } | ||
901 | |||
902 | cleanup: | ||
903 | spin_unlock_irqrestore(&musb->lock, lockflags); | ||
904 | return status; | ||
905 | } | ||
906 | |||
907 | static int musb_g_ep0_dequeue(struct usb_ep *ep, struct usb_request *req) | ||
908 | { | ||
909 | /* we just won't support this */ | ||
910 | return -EINVAL; | ||
911 | } | ||
912 | |||
913 | static int musb_g_ep0_halt(struct usb_ep *e, int value) | ||
914 | { | ||
915 | struct musb_ep *ep; | ||
916 | struct musb *musb; | ||
917 | void __iomem *base, *regs; | ||
918 | unsigned long flags; | ||
919 | int status; | ||
920 | u16 csr; | ||
921 | |||
922 | if (!e || !value) | ||
923 | return -EINVAL; | ||
924 | |||
925 | ep = to_musb_ep(e); | ||
926 | musb = ep->musb; | ||
927 | base = musb->mregs; | ||
928 | regs = musb->control_ep->regs; | ||
929 | status = 0; | ||
930 | |||
931 | spin_lock_irqsave(&musb->lock, flags); | ||
932 | |||
933 | if (!list_empty(&ep->req_list)) { | ||
934 | status = -EBUSY; | ||
935 | goto cleanup; | ||
936 | } | ||
937 | |||
938 | musb_ep_select(base, 0); | ||
939 | csr = musb->ackpend; | ||
940 | |||
941 | switch (musb->ep0_state) { | ||
942 | |||
943 | /* Stalls are usually issued after parsing SETUP packet, either | ||
944 | * directly in irq context from setup() or else later. | ||
945 | */ | ||
946 | case MUSB_EP0_STAGE_TX: /* control-IN data */ | ||
947 | case MUSB_EP0_STAGE_ACKWAIT: /* STALL for zero-length data */ | ||
948 | case MUSB_EP0_STAGE_RX: /* control-OUT data */ | ||
949 | csr = musb_readw(regs, MUSB_CSR0); | ||
950 | /* FALLTHROUGH */ | ||
951 | |||
952 | /* It's also OK to issue stalls during callbacks when a non-empty | ||
953 | * DATA stage buffer has been read (or even written). | ||
954 | */ | ||
955 | case MUSB_EP0_STAGE_STATUSIN: /* control-OUT status */ | ||
956 | case MUSB_EP0_STAGE_STATUSOUT: /* control-IN status */ | ||
957 | |||
958 | csr |= MUSB_CSR0_P_SENDSTALL; | ||
959 | musb_writew(regs, MUSB_CSR0, csr); | ||
960 | musb->ep0_state = MUSB_EP0_STAGE_SETUP; | ||
961 | musb->ackpend = 0; | ||
962 | break; | ||
963 | default: | ||
964 | DBG(1, "ep0 can't halt in state %d\n", musb->ep0_state); | ||
965 | status = -EINVAL; | ||
966 | } | ||
967 | |||
968 | cleanup: | ||
969 | spin_unlock_irqrestore(&musb->lock, flags); | ||
970 | return status; | ||
971 | } | ||
972 | |||
973 | const struct usb_ep_ops musb_g_ep0_ops = { | ||
974 | .enable = musb_g_ep0_enable, | ||
975 | .disable = musb_g_ep0_disable, | ||
976 | .alloc_request = musb_alloc_request, | ||
977 | .free_request = musb_free_request, | ||
978 | .queue = musb_g_ep0_queue, | ||
979 | .dequeue = musb_g_ep0_dequeue, | ||
980 | .set_halt = musb_g_ep0_halt, | ||
981 | }; | ||