diff options
Diffstat (limited to 'drivers/usb/dwc3/ep0.c')
-rw-r--r-- | drivers/usb/dwc3/ep0.c | 782 |
1 files changed, 782 insertions, 0 deletions
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c new file mode 100644 index 000000000000..4698fe013769 --- /dev/null +++ b/drivers/usb/dwc3/ep0.c | |||
@@ -0,0 +1,782 @@ | |||
1 | /** | ||
2 | * ep0.c - DesignWare USB3 DRD Controller Endpoint 0 Handling | ||
3 | * | ||
4 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Authors: Felipe Balbi <balbi@ti.com>, | ||
8 | * Sebastian Andrzej Siewior <bigeasy@linutronix.de> | ||
9 | * | ||
10 | * Redistribution and use in source and binary forms, with or without | ||
11 | * modification, are permitted provided that the following conditions | ||
12 | * are met: | ||
13 | * 1. Redistributions of source code must retain the above copyright | ||
14 | * notice, this list of conditions, and the following disclaimer, | ||
15 | * without modification. | ||
16 | * 2. Redistributions in binary form must reproduce the above copyright | ||
17 | * notice, this list of conditions and the following disclaimer in the | ||
18 | * documentation and/or other materials provided with the distribution. | ||
19 | * 3. The names of the above-listed copyright holders may not be used | ||
20 | * to endorse or promote products derived from this software without | ||
21 | * specific prior written permission. | ||
22 | * | ||
23 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
24 | * GNU General Public License ("GPL") version 2, as published by the Free | ||
25 | * Software Foundation. | ||
26 | * | ||
27 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
28 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | ||
29 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
30 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | ||
31 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
32 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
33 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
34 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
35 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
36 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
37 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
38 | */ | ||
39 | |||
40 | #include <linux/kernel.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/spinlock.h> | ||
43 | #include <linux/platform_device.h> | ||
44 | #include <linux/pm_runtime.h> | ||
45 | #include <linux/interrupt.h> | ||
46 | #include <linux/io.h> | ||
47 | #include <linux/list.h> | ||
48 | #include <linux/dma-mapping.h> | ||
49 | |||
50 | #include <linux/usb/ch9.h> | ||
51 | #include <linux/usb/gadget.h> | ||
52 | |||
53 | #include "core.h" | ||
54 | #include "gadget.h" | ||
55 | #include "io.h" | ||
56 | |||
57 | static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, | ||
58 | const struct dwc3_event_depevt *event); | ||
59 | |||
60 | static const char *dwc3_ep0_state_string(enum dwc3_ep0_state state) | ||
61 | { | ||
62 | switch (state) { | ||
63 | case EP0_UNCONNECTED: | ||
64 | return "Unconnected"; | ||
65 | case EP0_IDLE: | ||
66 | return "Idle"; | ||
67 | case EP0_IN_DATA_PHASE: | ||
68 | return "IN Data Phase"; | ||
69 | case EP0_OUT_DATA_PHASE: | ||
70 | return "OUT Data Phase"; | ||
71 | case EP0_IN_WAIT_GADGET: | ||
72 | return "IN Wait Gadget"; | ||
73 | case EP0_OUT_WAIT_GADGET: | ||
74 | return "OUT Wait Gadget"; | ||
75 | case EP0_IN_WAIT_NRDY: | ||
76 | return "IN Wait NRDY"; | ||
77 | case EP0_OUT_WAIT_NRDY: | ||
78 | return "OUT Wait NRDY"; | ||
79 | case EP0_IN_STATUS_PHASE: | ||
80 | return "IN Status Phase"; | ||
81 | case EP0_OUT_STATUS_PHASE: | ||
82 | return "OUT Status Phase"; | ||
83 | case EP0_STALL: | ||
84 | return "Stall"; | ||
85 | default: | ||
86 | return "UNKNOWN"; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma, | ||
91 | u32 len) | ||
92 | { | ||
93 | struct dwc3_gadget_ep_cmd_params params; | ||
94 | struct dwc3_trb_hw *trb_hw; | ||
95 | struct dwc3_trb trb; | ||
96 | struct dwc3_ep *dep; | ||
97 | |||
98 | int ret; | ||
99 | |||
100 | dep = dwc->eps[epnum]; | ||
101 | |||
102 | trb_hw = dwc->ep0_trb; | ||
103 | memset(&trb, 0, sizeof(trb)); | ||
104 | |||
105 | switch (dwc->ep0state) { | ||
106 | case EP0_IDLE: | ||
107 | trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP; | ||
108 | break; | ||
109 | |||
110 | case EP0_IN_WAIT_NRDY: | ||
111 | case EP0_OUT_WAIT_NRDY: | ||
112 | case EP0_IN_STATUS_PHASE: | ||
113 | case EP0_OUT_STATUS_PHASE: | ||
114 | if (dwc->three_stage_setup) | ||
115 | trb.trbctl = DWC3_TRBCTL_CONTROL_STATUS3; | ||
116 | else | ||
117 | trb.trbctl = DWC3_TRBCTL_CONTROL_STATUS2; | ||
118 | |||
119 | if (dwc->ep0state == EP0_IN_WAIT_NRDY) | ||
120 | dwc->ep0state = EP0_IN_STATUS_PHASE; | ||
121 | else if (dwc->ep0state == EP0_OUT_WAIT_NRDY) | ||
122 | dwc->ep0state = EP0_OUT_STATUS_PHASE; | ||
123 | break; | ||
124 | |||
125 | case EP0_IN_WAIT_GADGET: | ||
126 | dwc->ep0state = EP0_IN_WAIT_NRDY; | ||
127 | return 0; | ||
128 | break; | ||
129 | |||
130 | case EP0_OUT_WAIT_GADGET: | ||
131 | dwc->ep0state = EP0_OUT_WAIT_NRDY; | ||
132 | return 0; | ||
133 | |||
134 | break; | ||
135 | |||
136 | case EP0_IN_DATA_PHASE: | ||
137 | case EP0_OUT_DATA_PHASE: | ||
138 | trb.trbctl = DWC3_TRBCTL_CONTROL_DATA; | ||
139 | break; | ||
140 | |||
141 | default: | ||
142 | dev_err(dwc->dev, "%s() can't in state %d\n", __func__, | ||
143 | dwc->ep0state); | ||
144 | return -EINVAL; | ||
145 | } | ||
146 | |||
147 | trb.bplh = buf_dma; | ||
148 | trb.length = len; | ||
149 | |||
150 | trb.hwo = 1; | ||
151 | trb.lst = 1; | ||
152 | trb.ioc = 1; | ||
153 | trb.isp_imi = 1; | ||
154 | |||
155 | dwc3_trb_to_hw(&trb, trb_hw); | ||
156 | |||
157 | memset(¶ms, 0, sizeof(params)); | ||
158 | params.param0.depstrtxfer.transfer_desc_addr_high = | ||
159 | upper_32_bits(dwc->ep0_trb_addr); | ||
160 | params.param1.depstrtxfer.transfer_desc_addr_low = | ||
161 | lower_32_bits(dwc->ep0_trb_addr); | ||
162 | |||
163 | ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, | ||
164 | DWC3_DEPCMD_STARTTRANSFER, ¶ms); | ||
165 | if (ret < 0) { | ||
166 | dev_dbg(dwc->dev, "failed to send STARTTRANSFER command\n"); | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | dep->res_trans_idx = dwc3_gadget_ep_get_transfer_index(dwc, | ||
171 | dep->number); | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, | ||
177 | struct dwc3_request *req) | ||
178 | { | ||
179 | struct dwc3 *dwc = dep->dwc; | ||
180 | int ret; | ||
181 | |||
182 | req->request.actual = 0; | ||
183 | req->request.status = -EINPROGRESS; | ||
184 | req->direction = dep->direction; | ||
185 | req->epnum = dep->number; | ||
186 | |||
187 | list_add_tail(&req->list, &dep->request_list); | ||
188 | dwc3_map_buffer_to_dma(req); | ||
189 | |||
190 | ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma, | ||
191 | req->request.length); | ||
192 | if (ret < 0) { | ||
193 | list_del(&req->list); | ||
194 | dwc3_unmap_buffer_from_dma(req); | ||
195 | } | ||
196 | |||
197 | return ret; | ||
198 | } | ||
199 | |||
200 | int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, | ||
201 | gfp_t gfp_flags) | ||
202 | { | ||
203 | struct dwc3_request *req = to_dwc3_request(request); | ||
204 | struct dwc3_ep *dep = to_dwc3_ep(ep); | ||
205 | struct dwc3 *dwc = dep->dwc; | ||
206 | |||
207 | unsigned long flags; | ||
208 | |||
209 | int ret; | ||
210 | |||
211 | switch (dwc->ep0state) { | ||
212 | case EP0_IN_DATA_PHASE: | ||
213 | case EP0_IN_WAIT_GADGET: | ||
214 | case EP0_IN_WAIT_NRDY: | ||
215 | case EP0_IN_STATUS_PHASE: | ||
216 | dep = dwc->eps[1]; | ||
217 | break; | ||
218 | |||
219 | case EP0_OUT_DATA_PHASE: | ||
220 | case EP0_OUT_WAIT_GADGET: | ||
221 | case EP0_OUT_WAIT_NRDY: | ||
222 | case EP0_OUT_STATUS_PHASE: | ||
223 | dep = dwc->eps[0]; | ||
224 | break; | ||
225 | default: | ||
226 | return -EINVAL; | ||
227 | } | ||
228 | |||
229 | spin_lock_irqsave(&dwc->lock, flags); | ||
230 | if (!dep->desc) { | ||
231 | dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n", | ||
232 | request, dep->name); | ||
233 | ret = -ESHUTDOWN; | ||
234 | goto out; | ||
235 | } | ||
236 | |||
237 | /* we share one TRB for ep0/1 */ | ||
238 | if (!list_empty(&dwc->eps[0]->request_list) || | ||
239 | !list_empty(&dwc->eps[1]->request_list) || | ||
240 | dwc->ep0_status_pending) { | ||
241 | ret = -EBUSY; | ||
242 | goto out; | ||
243 | } | ||
244 | |||
245 | dev_vdbg(dwc->dev, "queueing request %p to %s length %d, state '%s'\n", | ||
246 | request, dep->name, request->length, | ||
247 | dwc3_ep0_state_string(dwc->ep0state)); | ||
248 | |||
249 | ret = __dwc3_gadget_ep0_queue(dep, req); | ||
250 | |||
251 | out: | ||
252 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
253 | |||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc) | ||
258 | { | ||
259 | /* stall is always issued on EP0 */ | ||
260 | __dwc3_gadget_ep_set_halt(dwc->eps[0], 1); | ||
261 | dwc->eps[0]->flags &= ~DWC3_EP_STALL; | ||
262 | dwc->ep0state = EP0_IDLE; | ||
263 | dwc3_ep0_out_start(dwc); | ||
264 | } | ||
265 | |||
266 | void dwc3_ep0_out_start(struct dwc3 *dwc) | ||
267 | { | ||
268 | struct dwc3_ep *dep; | ||
269 | int ret; | ||
270 | |||
271 | dep = dwc->eps[0]; | ||
272 | |||
273 | ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8); | ||
274 | WARN_ON(ret < 0); | ||
275 | } | ||
276 | |||
277 | /* | ||
278 | * Send a zero length packet for the status phase of the control transfer | ||
279 | */ | ||
280 | static void dwc3_ep0_do_setup_status(struct dwc3 *dwc, | ||
281 | const struct dwc3_event_depevt *event) | ||
282 | { | ||
283 | struct dwc3_ep *dep; | ||
284 | int ret; | ||
285 | u32 epnum; | ||
286 | |||
287 | epnum = event->endpoint_number; | ||
288 | dep = dwc->eps[epnum]; | ||
289 | |||
290 | if (epnum) | ||
291 | dwc->ep0state = EP0_IN_STATUS_PHASE; | ||
292 | else | ||
293 | dwc->ep0state = EP0_OUT_STATUS_PHASE; | ||
294 | |||
295 | /* | ||
296 | * Not sure Why I need a buffer for a zero transfer. Maybe the | ||
297 | * HW reacts strange on a NULL pointer | ||
298 | */ | ||
299 | ret = dwc3_ep0_start_trans(dwc, epnum, dwc->ctrl_req_addr, 0); | ||
300 | if (ret) { | ||
301 | dev_dbg(dwc->dev, "failed to start transfer, stalling\n"); | ||
302 | dwc3_ep0_stall_and_restart(dwc); | ||
303 | } | ||
304 | } | ||
305 | |||
306 | static struct dwc3_ep *dwc3_wIndex_to_dep(struct dwc3 *dwc, __le16 wIndex_le) | ||
307 | { | ||
308 | struct dwc3_ep *dep; | ||
309 | u32 windex = le16_to_cpu(wIndex_le); | ||
310 | u32 epnum; | ||
311 | |||
312 | epnum = (windex & USB_ENDPOINT_NUMBER_MASK) << 1; | ||
313 | if ((windex & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) | ||
314 | epnum |= 1; | ||
315 | |||
316 | dep = dwc->eps[epnum]; | ||
317 | if (dep->flags & DWC3_EP_ENABLED) | ||
318 | return dep; | ||
319 | |||
320 | return NULL; | ||
321 | } | ||
322 | |||
323 | static void dwc3_ep0_send_status_response(struct dwc3 *dwc) | ||
324 | { | ||
325 | u32 epnum; | ||
326 | |||
327 | if (dwc->ep0state == EP0_IN_DATA_PHASE) | ||
328 | epnum = 1; | ||
329 | else | ||
330 | epnum = 0; | ||
331 | |||
332 | dwc3_ep0_start_trans(dwc, epnum, dwc->ctrl_req_addr, | ||
333 | dwc->ep0_usb_req.length); | ||
334 | dwc->ep0_status_pending = 1; | ||
335 | } | ||
336 | |||
337 | /* | ||
338 | * ch 9.4.5 | ||
339 | */ | ||
340 | static int dwc3_ep0_handle_status(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) | ||
341 | { | ||
342 | struct dwc3_ep *dep; | ||
343 | u32 recip; | ||
344 | u16 usb_status = 0; | ||
345 | __le16 *response_pkt; | ||
346 | |||
347 | recip = ctrl->bRequestType & USB_RECIP_MASK; | ||
348 | switch (recip) { | ||
349 | case USB_RECIP_DEVICE: | ||
350 | /* | ||
351 | * We are self-powered. U1/U2/LTM will be set later | ||
352 | * once we handle this states. RemoteWakeup is 0 on SS | ||
353 | */ | ||
354 | usb_status |= dwc->is_selfpowered << USB_DEVICE_SELF_POWERED; | ||
355 | break; | ||
356 | |||
357 | case USB_RECIP_INTERFACE: | ||
358 | /* | ||
359 | * Function Remote Wake Capable D0 | ||
360 | * Function Remote Wakeup D1 | ||
361 | */ | ||
362 | break; | ||
363 | |||
364 | case USB_RECIP_ENDPOINT: | ||
365 | dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex); | ||
366 | if (!dep) | ||
367 | return -EINVAL; | ||
368 | |||
369 | if (dep->flags & DWC3_EP_STALL) | ||
370 | usb_status = 1 << USB_ENDPOINT_HALT; | ||
371 | break; | ||
372 | default: | ||
373 | return -EINVAL; | ||
374 | }; | ||
375 | |||
376 | response_pkt = (__le16 *) dwc->setup_buf; | ||
377 | *response_pkt = cpu_to_le16(usb_status); | ||
378 | dwc->ep0_usb_req.length = sizeof(*response_pkt); | ||
379 | dwc3_ep0_send_status_response(dwc); | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | static int dwc3_ep0_handle_feature(struct dwc3 *dwc, | ||
385 | struct usb_ctrlrequest *ctrl, int set) | ||
386 | { | ||
387 | struct dwc3_ep *dep; | ||
388 | u32 recip; | ||
389 | u32 wValue; | ||
390 | u32 wIndex; | ||
391 | u32 reg; | ||
392 | int ret; | ||
393 | u32 mode; | ||
394 | |||
395 | wValue = le16_to_cpu(ctrl->wValue); | ||
396 | wIndex = le16_to_cpu(ctrl->wIndex); | ||
397 | recip = ctrl->bRequestType & USB_RECIP_MASK; | ||
398 | switch (recip) { | ||
399 | case USB_RECIP_DEVICE: | ||
400 | |||
401 | /* | ||
402 | * 9.4.1 says only only for SS, in AddressState only for | ||
403 | * default control pipe | ||
404 | */ | ||
405 | switch (wValue) { | ||
406 | case USB_DEVICE_U1_ENABLE: | ||
407 | case USB_DEVICE_U2_ENABLE: | ||
408 | case USB_DEVICE_LTM_ENABLE: | ||
409 | if (dwc->dev_state != DWC3_CONFIGURED_STATE) | ||
410 | return -EINVAL; | ||
411 | if (dwc->speed != DWC3_DSTS_SUPERSPEED) | ||
412 | return -EINVAL; | ||
413 | } | ||
414 | |||
415 | /* XXX add U[12] & LTM */ | ||
416 | switch (wValue) { | ||
417 | case USB_DEVICE_REMOTE_WAKEUP: | ||
418 | break; | ||
419 | case USB_DEVICE_U1_ENABLE: | ||
420 | break; | ||
421 | case USB_DEVICE_U2_ENABLE: | ||
422 | break; | ||
423 | case USB_DEVICE_LTM_ENABLE: | ||
424 | break; | ||
425 | |||
426 | case USB_DEVICE_TEST_MODE: | ||
427 | if ((wIndex & 0xff) != 0) | ||
428 | return -EINVAL; | ||
429 | if (!set) | ||
430 | return -EINVAL; | ||
431 | |||
432 | mode = wIndex >> 8; | ||
433 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); | ||
434 | reg &= ~DWC3_DCTL_TSTCTRL_MASK; | ||
435 | |||
436 | switch (mode) { | ||
437 | case TEST_J: | ||
438 | case TEST_K: | ||
439 | case TEST_SE0_NAK: | ||
440 | case TEST_PACKET: | ||
441 | case TEST_FORCE_EN: | ||
442 | reg |= mode << 1; | ||
443 | break; | ||
444 | default: | ||
445 | return -EINVAL; | ||
446 | } | ||
447 | dwc3_writel(dwc->regs, DWC3_DCTL, reg); | ||
448 | break; | ||
449 | default: | ||
450 | return -EINVAL; | ||
451 | } | ||
452 | break; | ||
453 | |||
454 | case USB_RECIP_INTERFACE: | ||
455 | switch (wValue) { | ||
456 | case USB_INTRF_FUNC_SUSPEND: | ||
457 | if (wIndex & USB_INTRF_FUNC_SUSPEND_LP) | ||
458 | /* XXX enable Low power suspend */ | ||
459 | ; | ||
460 | if (wIndex & USB_INTRF_FUNC_SUSPEND_RW) | ||
461 | /* XXX enable remote wakeup */ | ||
462 | ; | ||
463 | break; | ||
464 | default: | ||
465 | return -EINVAL; | ||
466 | } | ||
467 | break; | ||
468 | |||
469 | case USB_RECIP_ENDPOINT: | ||
470 | switch (wValue) { | ||
471 | case USB_ENDPOINT_HALT: | ||
472 | |||
473 | dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex); | ||
474 | if (!dep) | ||
475 | return -EINVAL; | ||
476 | ret = __dwc3_gadget_ep_set_halt(dep, set); | ||
477 | if (ret) | ||
478 | return -EINVAL; | ||
479 | break; | ||
480 | default: | ||
481 | return -EINVAL; | ||
482 | } | ||
483 | break; | ||
484 | |||
485 | default: | ||
486 | return -EINVAL; | ||
487 | }; | ||
488 | |||
489 | dwc->ep0state = EP0_IN_WAIT_NRDY; | ||
490 | |||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) | ||
495 | { | ||
496 | int ret = 0; | ||
497 | u32 addr; | ||
498 | u32 reg; | ||
499 | |||
500 | addr = le16_to_cpu(ctrl->wValue); | ||
501 | if (addr > 127) | ||
502 | return -EINVAL; | ||
503 | |||
504 | switch (dwc->dev_state) { | ||
505 | case DWC3_DEFAULT_STATE: | ||
506 | case DWC3_ADDRESS_STATE: | ||
507 | /* | ||
508 | * Not sure if we should program DevAddr now or later | ||
509 | */ | ||
510 | reg = dwc3_readl(dwc->regs, DWC3_DCFG); | ||
511 | reg &= ~(DWC3_DCFG_DEVADDR_MASK); | ||
512 | reg |= DWC3_DCFG_DEVADDR(addr); | ||
513 | dwc3_writel(dwc->regs, DWC3_DCFG, reg); | ||
514 | |||
515 | if (addr) | ||
516 | dwc->dev_state = DWC3_ADDRESS_STATE; | ||
517 | else | ||
518 | dwc->dev_state = DWC3_DEFAULT_STATE; | ||
519 | break; | ||
520 | |||
521 | case DWC3_CONFIGURED_STATE: | ||
522 | ret = -EINVAL; | ||
523 | break; | ||
524 | } | ||
525 | dwc->ep0state = EP0_IN_WAIT_NRDY; | ||
526 | return ret; | ||
527 | } | ||
528 | |||
529 | static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) | ||
530 | { | ||
531 | int ret; | ||
532 | |||
533 | spin_unlock(&dwc->lock); | ||
534 | ret = dwc->gadget_driver->setup(&dwc->gadget, ctrl); | ||
535 | spin_lock(&dwc->lock); | ||
536 | return ret; | ||
537 | } | ||
538 | |||
539 | static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) | ||
540 | { | ||
541 | u32 cfg; | ||
542 | int ret; | ||
543 | |||
544 | cfg = le16_to_cpu(ctrl->wValue); | ||
545 | |||
546 | switch (dwc->dev_state) { | ||
547 | case DWC3_DEFAULT_STATE: | ||
548 | return -EINVAL; | ||
549 | break; | ||
550 | |||
551 | case DWC3_ADDRESS_STATE: | ||
552 | ret = dwc3_ep0_delegate_req(dwc, ctrl); | ||
553 | /* if the cfg matches and the cfg is non zero */ | ||
554 | if (!ret && cfg) | ||
555 | dwc->dev_state = DWC3_CONFIGURED_STATE; | ||
556 | break; | ||
557 | |||
558 | case DWC3_CONFIGURED_STATE: | ||
559 | ret = dwc3_ep0_delegate_req(dwc, ctrl); | ||
560 | if (!cfg) | ||
561 | dwc->dev_state = DWC3_ADDRESS_STATE; | ||
562 | break; | ||
563 | } | ||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) | ||
568 | { | ||
569 | int ret; | ||
570 | |||
571 | switch (ctrl->bRequest) { | ||
572 | case USB_REQ_GET_STATUS: | ||
573 | dev_vdbg(dwc->dev, "USB_REQ_GET_STATUS\n"); | ||
574 | ret = dwc3_ep0_handle_status(dwc, ctrl); | ||
575 | break; | ||
576 | case USB_REQ_CLEAR_FEATURE: | ||
577 | dev_vdbg(dwc->dev, "USB_REQ_CLEAR_FEATURE\n"); | ||
578 | ret = dwc3_ep0_handle_feature(dwc, ctrl, 0); | ||
579 | break; | ||
580 | case USB_REQ_SET_FEATURE: | ||
581 | dev_vdbg(dwc->dev, "USB_REQ_SET_FEATURE\n"); | ||
582 | ret = dwc3_ep0_handle_feature(dwc, ctrl, 1); | ||
583 | break; | ||
584 | case USB_REQ_SET_ADDRESS: | ||
585 | dev_vdbg(dwc->dev, "USB_REQ_SET_ADDRESS\n"); | ||
586 | ret = dwc3_ep0_set_address(dwc, ctrl); | ||
587 | break; | ||
588 | case USB_REQ_SET_CONFIGURATION: | ||
589 | dev_vdbg(dwc->dev, "USB_REQ_SET_CONFIGURATION\n"); | ||
590 | ret = dwc3_ep0_set_config(dwc, ctrl); | ||
591 | break; | ||
592 | default: | ||
593 | dev_vdbg(dwc->dev, "Forwarding to gadget driver\n"); | ||
594 | ret = dwc3_ep0_delegate_req(dwc, ctrl); | ||
595 | break; | ||
596 | }; | ||
597 | |||
598 | return ret; | ||
599 | } | ||
600 | |||
601 | static void dwc3_ep0_inspect_setup(struct dwc3 *dwc, | ||
602 | const struct dwc3_event_depevt *event) | ||
603 | { | ||
604 | struct usb_ctrlrequest *ctrl = dwc->ctrl_req; | ||
605 | int ret; | ||
606 | u32 len; | ||
607 | |||
608 | if (!dwc->gadget_driver) | ||
609 | goto err; | ||
610 | |||
611 | len = le16_to_cpu(ctrl->wLength); | ||
612 | if (!len) { | ||
613 | dwc->ep0state = EP0_IN_WAIT_GADGET; | ||
614 | dwc->three_stage_setup = 0; | ||
615 | } else { | ||
616 | dwc->three_stage_setup = 1; | ||
617 | if (ctrl->bRequestType & USB_DIR_IN) | ||
618 | dwc->ep0state = EP0_IN_DATA_PHASE; | ||
619 | else | ||
620 | dwc->ep0state = EP0_OUT_DATA_PHASE; | ||
621 | } | ||
622 | |||
623 | if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) | ||
624 | ret = dwc3_ep0_std_request(dwc, ctrl); | ||
625 | else | ||
626 | ret = dwc3_ep0_delegate_req(dwc, ctrl); | ||
627 | |||
628 | if (ret >= 0) | ||
629 | return; | ||
630 | |||
631 | err: | ||
632 | dwc3_ep0_stall_and_restart(dwc); | ||
633 | } | ||
634 | |||
635 | static void dwc3_ep0_complete_data(struct dwc3 *dwc, | ||
636 | const struct dwc3_event_depevt *event) | ||
637 | { | ||
638 | struct dwc3_request *r = NULL; | ||
639 | struct usb_request *ur; | ||
640 | struct dwc3_trb trb; | ||
641 | struct dwc3_ep *dep; | ||
642 | u32 transfered; | ||
643 | u8 epnum; | ||
644 | |||
645 | epnum = event->endpoint_number; | ||
646 | dep = dwc->eps[epnum]; | ||
647 | |||
648 | if (!dwc->ep0_status_pending) { | ||
649 | r = next_request(&dep->request_list); | ||
650 | ur = &r->request; | ||
651 | } else { | ||
652 | ur = &dwc->ep0_usb_req; | ||
653 | dwc->ep0_status_pending = 0; | ||
654 | } | ||
655 | |||
656 | dwc3_trb_to_nat(dwc->ep0_trb, &trb); | ||
657 | |||
658 | transfered = ur->length - trb.length; | ||
659 | ur->actual += transfered; | ||
660 | |||
661 | if ((epnum & 1) && ur->actual < ur->length) { | ||
662 | /* for some reason we did not get everything out */ | ||
663 | |||
664 | dwc3_ep0_stall_and_restart(dwc); | ||
665 | dwc3_gadget_giveback(dep, r, -ECONNRESET); | ||
666 | } else { | ||
667 | /* | ||
668 | * handle the case where we have to send a zero packet. This | ||
669 | * seems to be case when req.length > maxpacket. Could it be? | ||
670 | */ | ||
671 | /* The transfer is complete, wait for HOST */ | ||
672 | if (epnum & 1) | ||
673 | dwc->ep0state = EP0_IN_WAIT_NRDY; | ||
674 | else | ||
675 | dwc->ep0state = EP0_OUT_WAIT_NRDY; | ||
676 | |||
677 | if (r) | ||
678 | dwc3_gadget_giveback(dep, r, 0); | ||
679 | } | ||
680 | } | ||
681 | |||
682 | static void dwc3_ep0_complete_req(struct dwc3 *dwc, | ||
683 | const struct dwc3_event_depevt *event) | ||
684 | { | ||
685 | struct dwc3_request *r; | ||
686 | struct dwc3_ep *dep; | ||
687 | u8 epnum; | ||
688 | |||
689 | epnum = event->endpoint_number; | ||
690 | dep = dwc->eps[epnum]; | ||
691 | |||
692 | if (!list_empty(&dep->request_list)) { | ||
693 | r = next_request(&dep->request_list); | ||
694 | |||
695 | dwc3_gadget_giveback(dep, r, 0); | ||
696 | } | ||
697 | |||
698 | dwc->ep0state = EP0_IDLE; | ||
699 | dwc3_ep0_out_start(dwc); | ||
700 | } | ||
701 | |||
702 | static void dwc3_ep0_xfer_complete(struct dwc3 *dwc, | ||
703 | const struct dwc3_event_depevt *event) | ||
704 | { | ||
705 | switch (dwc->ep0state) { | ||
706 | case EP0_IDLE: | ||
707 | dwc3_ep0_inspect_setup(dwc, event); | ||
708 | break; | ||
709 | |||
710 | case EP0_IN_DATA_PHASE: | ||
711 | case EP0_OUT_DATA_PHASE: | ||
712 | dwc3_ep0_complete_data(dwc, event); | ||
713 | break; | ||
714 | |||
715 | case EP0_IN_STATUS_PHASE: | ||
716 | case EP0_OUT_STATUS_PHASE: | ||
717 | dwc3_ep0_complete_req(dwc, event); | ||
718 | break; | ||
719 | |||
720 | case EP0_IN_WAIT_NRDY: | ||
721 | case EP0_OUT_WAIT_NRDY: | ||
722 | case EP0_IN_WAIT_GADGET: | ||
723 | case EP0_OUT_WAIT_GADGET: | ||
724 | case EP0_UNCONNECTED: | ||
725 | case EP0_STALL: | ||
726 | break; | ||
727 | } | ||
728 | } | ||
729 | |||
730 | static void dwc3_ep0_xfernotready(struct dwc3 *dwc, | ||
731 | const struct dwc3_event_depevt *event) | ||
732 | { | ||
733 | switch (dwc->ep0state) { | ||
734 | case EP0_IN_WAIT_GADGET: | ||
735 | dwc->ep0state = EP0_IN_WAIT_NRDY; | ||
736 | break; | ||
737 | case EP0_OUT_WAIT_GADGET: | ||
738 | dwc->ep0state = EP0_OUT_WAIT_NRDY; | ||
739 | break; | ||
740 | |||
741 | case EP0_IN_WAIT_NRDY: | ||
742 | case EP0_OUT_WAIT_NRDY: | ||
743 | dwc3_ep0_do_setup_status(dwc, event); | ||
744 | break; | ||
745 | |||
746 | case EP0_IDLE: | ||
747 | case EP0_IN_STATUS_PHASE: | ||
748 | case EP0_OUT_STATUS_PHASE: | ||
749 | case EP0_IN_DATA_PHASE: | ||
750 | case EP0_OUT_DATA_PHASE: | ||
751 | case EP0_UNCONNECTED: | ||
752 | case EP0_STALL: | ||
753 | break; | ||
754 | } | ||
755 | } | ||
756 | |||
757 | void dwc3_ep0_interrupt(struct dwc3 *dwc, | ||
758 | const const struct dwc3_event_depevt *event) | ||
759 | { | ||
760 | u8 epnum = event->endpoint_number; | ||
761 | |||
762 | dev_dbg(dwc->dev, "%s while ep%d%s in state '%s'\n", | ||
763 | dwc3_ep_event_string(event->endpoint_event), | ||
764 | epnum, (epnum & 1) ? "in" : "out", | ||
765 | dwc3_ep0_state_string(dwc->ep0state)); | ||
766 | |||
767 | switch (event->endpoint_event) { | ||
768 | case DWC3_DEPEVT_XFERCOMPLETE: | ||
769 | dwc3_ep0_xfer_complete(dwc, event); | ||
770 | break; | ||
771 | |||
772 | case DWC3_DEPEVT_XFERNOTREADY: | ||
773 | dwc3_ep0_xfernotready(dwc, event); | ||
774 | break; | ||
775 | |||
776 | case DWC3_DEPEVT_XFERINPROGRESS: | ||
777 | case DWC3_DEPEVT_RXTXFIFOEVT: | ||
778 | case DWC3_DEPEVT_STREAMEVT: | ||
779 | case DWC3_DEPEVT_EPCMDCMPLT: | ||
780 | break; | ||
781 | } | ||
782 | } | ||