1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Cadence USBSS DRD Driver - gadget side. |
4 | * |
5 | * Copyright (C) 2018 Cadence Design Systems. |
6 | * Copyright (C) 2017-2018 NXP |
7 | * |
8 | * Authors: Pawel Jez <pjez@cadence.com>, |
9 | * Pawel Laszczak <pawell@cadence.com> |
10 | * Peter Chen <peter.chen@nxp.com> |
11 | */ |
12 | |
13 | #include <linux/usb/composite.h> |
14 | #include <linux/iopoll.h> |
15 | |
16 | #include "cdns3-gadget.h" |
17 | #include "cdns3-trace.h" |
18 | |
19 | static struct usb_endpoint_descriptor cdns3_gadget_ep0_desc = { |
20 | .bLength = USB_DT_ENDPOINT_SIZE, |
21 | .bDescriptorType = USB_DT_ENDPOINT, |
22 | .bmAttributes = USB_ENDPOINT_XFER_CONTROL, |
23 | }; |
24 | |
25 | /** |
26 | * cdns3_ep0_run_transfer - Do transfer on default endpoint hardware |
27 | * @priv_dev: extended gadget object |
28 | * @dma_addr: physical address where data is/will be stored |
29 | * @length: data length |
30 | * @erdy: set it to 1 when ERDY packet should be sent - |
31 | * exit from flow control state |
32 | * @zlp: add zero length packet |
33 | */ |
34 | static void cdns3_ep0_run_transfer(struct cdns3_device *priv_dev, |
35 | dma_addr_t dma_addr, |
36 | unsigned int length, int erdy, int zlp) |
37 | { |
38 | struct cdns3_usb_regs __iomem *regs = priv_dev->regs; |
39 | struct cdns3_endpoint *priv_ep = priv_dev->eps[0]; |
40 | |
41 | priv_ep->trb_pool[0].buffer = cpu_to_le32(TRB_BUFFER(dma_addr)); |
42 | priv_ep->trb_pool[0].length = cpu_to_le32(TRB_LEN(length)); |
43 | |
44 | if (zlp) { |
45 | priv_ep->trb_pool[0].control = cpu_to_le32(TRB_CYCLE | TRB_TYPE(TRB_NORMAL)); |
46 | priv_ep->trb_pool[1].buffer = cpu_to_le32(TRB_BUFFER(dma_addr)); |
47 | priv_ep->trb_pool[1].length = cpu_to_le32(TRB_LEN(0)); |
48 | priv_ep->trb_pool[1].control = cpu_to_le32(TRB_CYCLE | TRB_IOC | |
49 | TRB_TYPE(TRB_NORMAL)); |
50 | } else { |
51 | priv_ep->trb_pool[0].control = cpu_to_le32(TRB_CYCLE | TRB_IOC | |
52 | TRB_TYPE(TRB_NORMAL)); |
53 | priv_ep->trb_pool[1].control = 0; |
54 | } |
55 | |
56 | trace_cdns3_prepare_trb(priv_ep, trb: priv_ep->trb_pool); |
57 | |
58 | cdns3_select_ep(priv_dev, ep: priv_dev->ep0_data_dir); |
59 | |
60 | writel(EP_STS_TRBERR, addr: ®s->ep_sts); |
61 | writel(EP_TRADDR_TRADDR(priv_ep->trb_pool_dma), addr: ®s->ep_traddr); |
62 | trace_cdns3_doorbell_ep0(ep_name: priv_dev->ep0_data_dir ? "ep0in" : "ep0out" , |
63 | readl(addr: ®s->ep_traddr)); |
64 | |
65 | /* TRB should be prepared before starting transfer. */ |
66 | writel(EP_CMD_DRDY, addr: ®s->ep_cmd); |
67 | |
68 | /* Resume controller before arming transfer. */ |
69 | __cdns3_gadget_wakeup(priv_dev); |
70 | |
71 | if (erdy) |
72 | writel(EP_CMD_ERDY, addr: &priv_dev->regs->ep_cmd); |
73 | } |
74 | |
75 | /** |
76 | * cdns3_ep0_delegate_req - Returns status of handling setup packet |
77 | * Setup is handled by gadget driver |
78 | * @priv_dev: extended gadget object |
79 | * @ctrl_req: pointer to received setup packet |
80 | * |
81 | * Returns zero on success or negative value on failure |
82 | */ |
83 | static int cdns3_ep0_delegate_req(struct cdns3_device *priv_dev, |
84 | struct usb_ctrlrequest *ctrl_req) |
85 | { |
86 | int ret; |
87 | |
88 | spin_unlock(lock: &priv_dev->lock); |
89 | priv_dev->setup_pending = 1; |
90 | ret = priv_dev->gadget_driver->setup(&priv_dev->gadget, ctrl_req); |
91 | priv_dev->setup_pending = 0; |
92 | spin_lock(lock: &priv_dev->lock); |
93 | return ret; |
94 | } |
95 | |
96 | static void cdns3_prepare_setup_packet(struct cdns3_device *priv_dev) |
97 | { |
98 | priv_dev->ep0_data_dir = 0; |
99 | priv_dev->ep0_stage = CDNS3_SETUP_STAGE; |
100 | cdns3_ep0_run_transfer(priv_dev, dma_addr: priv_dev->setup_dma, |
101 | length: sizeof(struct usb_ctrlrequest), erdy: 0, zlp: 0); |
102 | } |
103 | |
104 | static void cdns3_ep0_complete_setup(struct cdns3_device *priv_dev, |
105 | u8 send_stall, u8 send_erdy) |
106 | { |
107 | struct cdns3_endpoint *priv_ep = priv_dev->eps[0]; |
108 | struct usb_request *request; |
109 | |
110 | request = cdns3_next_request(list: &priv_ep->pending_req_list); |
111 | if (request) |
112 | list_del_init(entry: &request->list); |
113 | |
114 | if (send_stall) { |
115 | trace_cdns3_halt(ep_priv: priv_ep, halt: send_stall, flush: 0); |
116 | /* set_stall on ep0 */ |
117 | cdns3_select_ep(priv_dev, ep: 0x00); |
118 | writel(EP_CMD_SSTALL, addr: &priv_dev->regs->ep_cmd); |
119 | } else { |
120 | cdns3_prepare_setup_packet(priv_dev); |
121 | } |
122 | |
123 | priv_dev->ep0_stage = CDNS3_SETUP_STAGE; |
124 | writel(val: (send_erdy ? EP_CMD_ERDY : 0) | EP_CMD_REQ_CMPL, |
125 | addr: &priv_dev->regs->ep_cmd); |
126 | } |
127 | |
128 | /** |
129 | * cdns3_req_ep0_set_configuration - Handling of SET_CONFIG standard USB request |
130 | * @priv_dev: extended gadget object |
131 | * @ctrl_req: pointer to received setup packet |
132 | * |
133 | * Returns 0 if success, USB_GADGET_DELAYED_STATUS on deferred status stage, |
134 | * error code on error |
135 | */ |
136 | static int cdns3_req_ep0_set_configuration(struct cdns3_device *priv_dev, |
137 | struct usb_ctrlrequest *ctrl_req) |
138 | { |
139 | enum usb_device_state device_state = priv_dev->gadget.state; |
140 | u32 config = le16_to_cpu(ctrl_req->wValue); |
141 | int result = 0; |
142 | |
143 | switch (device_state) { |
144 | case USB_STATE_ADDRESS: |
145 | result = cdns3_ep0_delegate_req(priv_dev, ctrl_req); |
146 | |
147 | if (result || !config) |
148 | goto reset_config; |
149 | |
150 | break; |
151 | case USB_STATE_CONFIGURED: |
152 | result = cdns3_ep0_delegate_req(priv_dev, ctrl_req); |
153 | if (!config && !result) |
154 | goto reset_config; |
155 | |
156 | break; |
157 | default: |
158 | return -EINVAL; |
159 | } |
160 | |
161 | return 0; |
162 | |
163 | reset_config: |
164 | if (result != USB_GADGET_DELAYED_STATUS) |
165 | cdns3_hw_reset_eps_config(priv_dev); |
166 | |
167 | usb_gadget_set_state(gadget: &priv_dev->gadget, |
168 | state: USB_STATE_ADDRESS); |
169 | |
170 | return result; |
171 | } |
172 | |
173 | /** |
174 | * cdns3_req_ep0_set_address - Handling of SET_ADDRESS standard USB request |
175 | * @priv_dev: extended gadget object |
176 | * @ctrl_req: pointer to received setup packet |
177 | * |
178 | * Returns 0 if success, error code on error |
179 | */ |
180 | static int cdns3_req_ep0_set_address(struct cdns3_device *priv_dev, |
181 | struct usb_ctrlrequest *ctrl_req) |
182 | { |
183 | enum usb_device_state device_state = priv_dev->gadget.state; |
184 | u32 reg; |
185 | u32 addr; |
186 | |
187 | addr = le16_to_cpu(ctrl_req->wValue); |
188 | |
189 | if (addr > USB_DEVICE_MAX_ADDRESS) { |
190 | dev_err(priv_dev->dev, |
191 | "Device address (%d) cannot be greater than %d\n" , |
192 | addr, USB_DEVICE_MAX_ADDRESS); |
193 | return -EINVAL; |
194 | } |
195 | |
196 | if (device_state == USB_STATE_CONFIGURED) { |
197 | dev_err(priv_dev->dev, |
198 | "can't set_address from configured state\n" ); |
199 | return -EINVAL; |
200 | } |
201 | |
202 | reg = readl(addr: &priv_dev->regs->usb_cmd); |
203 | |
204 | writel(val: reg | USB_CMD_FADDR(addr) | USB_CMD_SET_ADDR, |
205 | addr: &priv_dev->regs->usb_cmd); |
206 | |
207 | usb_gadget_set_state(gadget: &priv_dev->gadget, |
208 | state: (addr ? USB_STATE_ADDRESS : USB_STATE_DEFAULT)); |
209 | |
210 | return 0; |
211 | } |
212 | |
213 | /** |
214 | * cdns3_req_ep0_get_status - Handling of GET_STATUS standard USB request |
215 | * @priv_dev: extended gadget object |
216 | * @ctrl: pointer to received setup packet |
217 | * |
218 | * Returns 0 if success, error code on error |
219 | */ |
220 | static int cdns3_req_ep0_get_status(struct cdns3_device *priv_dev, |
221 | struct usb_ctrlrequest *ctrl) |
222 | { |
223 | struct cdns3_endpoint *priv_ep; |
224 | __le16 *response_pkt; |
225 | u16 usb_status = 0; |
226 | u32 recip; |
227 | u8 index; |
228 | |
229 | recip = ctrl->bRequestType & USB_RECIP_MASK; |
230 | |
231 | switch (recip) { |
232 | case USB_RECIP_DEVICE: |
233 | /* self powered */ |
234 | if (priv_dev->is_selfpowered) |
235 | usb_status = BIT(USB_DEVICE_SELF_POWERED); |
236 | |
237 | if (priv_dev->wake_up_flag) |
238 | usb_status |= BIT(USB_DEVICE_REMOTE_WAKEUP); |
239 | |
240 | if (priv_dev->gadget.speed != USB_SPEED_SUPER) |
241 | break; |
242 | |
243 | if (priv_dev->u1_allowed) |
244 | usb_status |= BIT(USB_DEV_STAT_U1_ENABLED); |
245 | |
246 | if (priv_dev->u2_allowed) |
247 | usb_status |= BIT(USB_DEV_STAT_U2_ENABLED); |
248 | |
249 | break; |
250 | case USB_RECIP_INTERFACE: |
251 | return cdns3_ep0_delegate_req(priv_dev, ctrl_req: ctrl); |
252 | case USB_RECIP_ENDPOINT: |
253 | index = cdns3_ep_addr_to_index(le16_to_cpu(ctrl->wIndex)); |
254 | priv_ep = priv_dev->eps[index]; |
255 | |
256 | /* check if endpoint is stalled or stall is pending */ |
257 | cdns3_select_ep(priv_dev, le16_to_cpu(ctrl->wIndex)); |
258 | if (EP_STS_STALL(readl(&priv_dev->regs->ep_sts)) || |
259 | (priv_ep->flags & EP_STALL_PENDING)) |
260 | usb_status = BIT(USB_ENDPOINT_HALT); |
261 | break; |
262 | default: |
263 | return -EINVAL; |
264 | } |
265 | |
266 | response_pkt = (__le16 *)priv_dev->setup_buf; |
267 | *response_pkt = cpu_to_le16(usb_status); |
268 | |
269 | cdns3_ep0_run_transfer(priv_dev, dma_addr: priv_dev->setup_dma, |
270 | length: sizeof(*response_pkt), erdy: 1, zlp: 0); |
271 | return 0; |
272 | } |
273 | |
274 | static int cdns3_ep0_feature_handle_device(struct cdns3_device *priv_dev, |
275 | struct usb_ctrlrequest *ctrl, |
276 | int set) |
277 | { |
278 | enum usb_device_state state; |
279 | enum usb_device_speed speed; |
280 | int ret = 0; |
281 | u32 wValue; |
282 | u16 tmode; |
283 | |
284 | wValue = le16_to_cpu(ctrl->wValue); |
285 | state = priv_dev->gadget.state; |
286 | speed = priv_dev->gadget.speed; |
287 | |
288 | switch (wValue) { |
289 | case USB_DEVICE_REMOTE_WAKEUP: |
290 | priv_dev->wake_up_flag = !!set; |
291 | break; |
292 | case USB_DEVICE_U1_ENABLE: |
293 | if (state != USB_STATE_CONFIGURED || speed != USB_SPEED_SUPER) |
294 | return -EINVAL; |
295 | |
296 | priv_dev->u1_allowed = !!set; |
297 | break; |
298 | case USB_DEVICE_U2_ENABLE: |
299 | if (state != USB_STATE_CONFIGURED || speed != USB_SPEED_SUPER) |
300 | return -EINVAL; |
301 | |
302 | priv_dev->u2_allowed = !!set; |
303 | break; |
304 | case USB_DEVICE_LTM_ENABLE: |
305 | ret = -EINVAL; |
306 | break; |
307 | case USB_DEVICE_TEST_MODE: |
308 | if (state != USB_STATE_CONFIGURED || speed > USB_SPEED_HIGH) |
309 | return -EINVAL; |
310 | |
311 | tmode = le16_to_cpu(ctrl->wIndex); |
312 | |
313 | if (!set || (tmode & 0xff) != 0) |
314 | return -EINVAL; |
315 | |
316 | tmode >>= 8; |
317 | switch (tmode) { |
318 | case USB_TEST_J: |
319 | case USB_TEST_K: |
320 | case USB_TEST_SE0_NAK: |
321 | case USB_TEST_PACKET: |
322 | cdns3_set_register_bit(ptr: &priv_dev->regs->usb_cmd, |
323 | USB_CMD_STMODE | |
324 | USB_STS_TMODE_SEL(tmode - 1)); |
325 | break; |
326 | default: |
327 | ret = -EINVAL; |
328 | } |
329 | break; |
330 | default: |
331 | ret = -EINVAL; |
332 | } |
333 | |
334 | return ret; |
335 | } |
336 | |
337 | static int cdns3_ep0_feature_handle_intf(struct cdns3_device *priv_dev, |
338 | struct usb_ctrlrequest *ctrl, |
339 | int set) |
340 | { |
341 | u32 wValue; |
342 | int ret = 0; |
343 | |
344 | wValue = le16_to_cpu(ctrl->wValue); |
345 | |
346 | switch (wValue) { |
347 | case USB_INTRF_FUNC_SUSPEND: |
348 | break; |
349 | default: |
350 | ret = -EINVAL; |
351 | } |
352 | |
353 | return ret; |
354 | } |
355 | |
356 | static int cdns3_ep0_feature_handle_endpoint(struct cdns3_device *priv_dev, |
357 | struct usb_ctrlrequest *ctrl, |
358 | int set) |
359 | { |
360 | struct cdns3_endpoint *priv_ep; |
361 | int ret = 0; |
362 | u8 index; |
363 | |
364 | if (le16_to_cpu(ctrl->wValue) != USB_ENDPOINT_HALT) |
365 | return -EINVAL; |
366 | |
367 | if (!(le16_to_cpu(ctrl->wIndex) & ~USB_DIR_IN)) |
368 | return 0; |
369 | |
370 | index = cdns3_ep_addr_to_index(le16_to_cpu(ctrl->wIndex)); |
371 | priv_ep = priv_dev->eps[index]; |
372 | |
373 | cdns3_select_ep(priv_dev, le16_to_cpu(ctrl->wIndex)); |
374 | |
375 | if (set) |
376 | __cdns3_gadget_ep_set_halt(priv_ep); |
377 | else if (!(priv_ep->flags & EP_WEDGE)) |
378 | ret = __cdns3_gadget_ep_clear_halt(priv_ep); |
379 | |
380 | cdns3_select_ep(priv_dev, ep: 0x00); |
381 | |
382 | return ret; |
383 | } |
384 | |
385 | /** |
386 | * cdns3_req_ep0_handle_feature - |
387 | * Handling of GET/SET_FEATURE standard USB request |
388 | * |
389 | * @priv_dev: extended gadget object |
390 | * @ctrl: pointer to received setup packet |
391 | * @set: must be set to 1 for SET_FEATURE request |
392 | * |
393 | * Returns 0 if success, error code on error |
394 | */ |
395 | static int cdns3_req_ep0_handle_feature(struct cdns3_device *priv_dev, |
396 | struct usb_ctrlrequest *ctrl, |
397 | int set) |
398 | { |
399 | int ret = 0; |
400 | u32 recip; |
401 | |
402 | recip = ctrl->bRequestType & USB_RECIP_MASK; |
403 | |
404 | switch (recip) { |
405 | case USB_RECIP_DEVICE: |
406 | ret = cdns3_ep0_feature_handle_device(priv_dev, ctrl, set); |
407 | break; |
408 | case USB_RECIP_INTERFACE: |
409 | ret = cdns3_ep0_feature_handle_intf(priv_dev, ctrl, set); |
410 | break; |
411 | case USB_RECIP_ENDPOINT: |
412 | ret = cdns3_ep0_feature_handle_endpoint(priv_dev, ctrl, set); |
413 | break; |
414 | default: |
415 | return -EINVAL; |
416 | } |
417 | |
418 | return ret; |
419 | } |
420 | |
421 | /** |
422 | * cdns3_req_ep0_set_sel - Handling of SET_SEL standard USB request |
423 | * @priv_dev: extended gadget object |
424 | * @ctrl_req: pointer to received setup packet |
425 | * |
426 | * Returns 0 if success, error code on error |
427 | */ |
428 | static int cdns3_req_ep0_set_sel(struct cdns3_device *priv_dev, |
429 | struct usb_ctrlrequest *ctrl_req) |
430 | { |
431 | if (priv_dev->gadget.state < USB_STATE_ADDRESS) |
432 | return -EINVAL; |
433 | |
434 | if (le16_to_cpu(ctrl_req->wLength) != 6) { |
435 | dev_err(priv_dev->dev, "Set SEL should be 6 bytes, got %d\n" , |
436 | ctrl_req->wLength); |
437 | return -EINVAL; |
438 | } |
439 | |
440 | cdns3_ep0_run_transfer(priv_dev, dma_addr: priv_dev->setup_dma, length: 6, erdy: 1, zlp: 0); |
441 | return 0; |
442 | } |
443 | |
444 | /** |
445 | * cdns3_req_ep0_set_isoch_delay - |
446 | * Handling of GET_ISOCH_DELAY standard USB request |
447 | * @priv_dev: extended gadget object |
448 | * @ctrl_req: pointer to received setup packet |
449 | * |
450 | * Returns 0 if success, error code on error |
451 | */ |
452 | static int cdns3_req_ep0_set_isoch_delay(struct cdns3_device *priv_dev, |
453 | struct usb_ctrlrequest *ctrl_req) |
454 | { |
455 | if (ctrl_req->wIndex || ctrl_req->wLength) |
456 | return -EINVAL; |
457 | |
458 | priv_dev->isoch_delay = le16_to_cpu(ctrl_req->wValue); |
459 | |
460 | return 0; |
461 | } |
462 | |
463 | /** |
464 | * cdns3_ep0_standard_request - Handling standard USB requests |
465 | * @priv_dev: extended gadget object |
466 | * @ctrl_req: pointer to received setup packet |
467 | * |
468 | * Returns 0 if success, error code on error |
469 | */ |
470 | static int cdns3_ep0_standard_request(struct cdns3_device *priv_dev, |
471 | struct usb_ctrlrequest *ctrl_req) |
472 | { |
473 | int ret; |
474 | |
475 | switch (ctrl_req->bRequest) { |
476 | case USB_REQ_SET_ADDRESS: |
477 | ret = cdns3_req_ep0_set_address(priv_dev, ctrl_req); |
478 | break; |
479 | case USB_REQ_SET_CONFIGURATION: |
480 | ret = cdns3_req_ep0_set_configuration(priv_dev, ctrl_req); |
481 | break; |
482 | case USB_REQ_GET_STATUS: |
483 | ret = cdns3_req_ep0_get_status(priv_dev, ctrl: ctrl_req); |
484 | break; |
485 | case USB_REQ_CLEAR_FEATURE: |
486 | ret = cdns3_req_ep0_handle_feature(priv_dev, ctrl: ctrl_req, set: 0); |
487 | break; |
488 | case USB_REQ_SET_FEATURE: |
489 | ret = cdns3_req_ep0_handle_feature(priv_dev, ctrl: ctrl_req, set: 1); |
490 | break; |
491 | case USB_REQ_SET_SEL: |
492 | ret = cdns3_req_ep0_set_sel(priv_dev, ctrl_req); |
493 | break; |
494 | case USB_REQ_SET_ISOCH_DELAY: |
495 | ret = cdns3_req_ep0_set_isoch_delay(priv_dev, ctrl_req); |
496 | break; |
497 | default: |
498 | ret = cdns3_ep0_delegate_req(priv_dev, ctrl_req); |
499 | break; |
500 | } |
501 | |
502 | return ret; |
503 | } |
504 | |
505 | static void __pending_setup_status_handler(struct cdns3_device *priv_dev) |
506 | { |
507 | struct usb_request *request = priv_dev->pending_status_request; |
508 | |
509 | if (priv_dev->status_completion_no_call && request && |
510 | request->complete) { |
511 | request->complete(&priv_dev->eps[0]->endpoint, request); |
512 | priv_dev->status_completion_no_call = 0; |
513 | } |
514 | } |
515 | |
516 | void cdns3_pending_setup_status_handler(struct work_struct *work) |
517 | { |
518 | struct cdns3_device *priv_dev = container_of(work, struct cdns3_device, |
519 | pending_status_wq); |
520 | unsigned long flags; |
521 | |
522 | spin_lock_irqsave(&priv_dev->lock, flags); |
523 | __pending_setup_status_handler(priv_dev); |
524 | spin_unlock_irqrestore(lock: &priv_dev->lock, flags); |
525 | } |
526 | |
527 | /** |
528 | * cdns3_ep0_setup_phase - Handling setup USB requests |
529 | * @priv_dev: extended gadget object |
530 | */ |
531 | static void cdns3_ep0_setup_phase(struct cdns3_device *priv_dev) |
532 | { |
533 | struct usb_ctrlrequest *ctrl = priv_dev->setup_buf; |
534 | struct cdns3_endpoint *priv_ep = priv_dev->eps[0]; |
535 | int result; |
536 | |
537 | priv_dev->ep0_data_dir = ctrl->bRequestType & USB_DIR_IN; |
538 | |
539 | trace_cdns3_ctrl_req(ctrl); |
540 | |
541 | if (!list_empty(head: &priv_ep->pending_req_list)) { |
542 | struct usb_request *request; |
543 | |
544 | request = cdns3_next_request(list: &priv_ep->pending_req_list); |
545 | priv_ep->dir = priv_dev->ep0_data_dir; |
546 | cdns3_gadget_giveback(priv_ep, to_cdns3_request(request), |
547 | status: -ECONNRESET); |
548 | } |
549 | |
550 | if (le16_to_cpu(ctrl->wLength)) |
551 | priv_dev->ep0_stage = CDNS3_DATA_STAGE; |
552 | else |
553 | priv_dev->ep0_stage = CDNS3_STATUS_STAGE; |
554 | |
555 | if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) |
556 | result = cdns3_ep0_standard_request(priv_dev, ctrl_req: ctrl); |
557 | else |
558 | result = cdns3_ep0_delegate_req(priv_dev, ctrl_req: ctrl); |
559 | |
560 | if (result == USB_GADGET_DELAYED_STATUS) |
561 | return; |
562 | |
563 | if (result < 0) |
564 | cdns3_ep0_complete_setup(priv_dev, send_stall: 1, send_erdy: 1); |
565 | else if (priv_dev->ep0_stage == CDNS3_STATUS_STAGE) |
566 | cdns3_ep0_complete_setup(priv_dev, send_stall: 0, send_erdy: 1); |
567 | } |
568 | |
569 | static void cdns3_transfer_completed(struct cdns3_device *priv_dev) |
570 | { |
571 | struct cdns3_endpoint *priv_ep = priv_dev->eps[0]; |
572 | |
573 | if (!list_empty(head: &priv_ep->pending_req_list)) { |
574 | struct usb_request *request; |
575 | |
576 | trace_cdns3_complete_trb(priv_ep, trb: priv_ep->trb_pool); |
577 | request = cdns3_next_request(list: &priv_ep->pending_req_list); |
578 | |
579 | request->actual = |
580 | TRB_LEN(le32_to_cpu(priv_ep->trb_pool->length)); |
581 | |
582 | priv_ep->dir = priv_dev->ep0_data_dir; |
583 | cdns3_gadget_giveback(priv_ep, to_cdns3_request(request), status: 0); |
584 | } |
585 | |
586 | cdns3_ep0_complete_setup(priv_dev, send_stall: 0, send_erdy: 0); |
587 | } |
588 | |
589 | /** |
590 | * cdns3_check_new_setup - Check if controller receive new SETUP packet. |
591 | * @priv_dev: extended gadget object |
592 | * |
593 | * The SETUP packet can be kept in on-chip memory or in system memory. |
594 | */ |
595 | static bool cdns3_check_new_setup(struct cdns3_device *priv_dev) |
596 | { |
597 | u32 ep_sts_reg; |
598 | |
599 | cdns3_select_ep(priv_dev, USB_DIR_OUT); |
600 | ep_sts_reg = readl(addr: &priv_dev->regs->ep_sts); |
601 | |
602 | return !!(ep_sts_reg & (EP_STS_SETUP | EP_STS_STPWAIT)); |
603 | } |
604 | |
605 | /** |
606 | * cdns3_check_ep0_interrupt_proceed - Processes interrupt related to endpoint 0 |
607 | * @priv_dev: extended gadget object |
608 | * @dir: USB_DIR_IN for IN direction, USB_DIR_OUT for OUT direction |
609 | */ |
610 | void cdns3_check_ep0_interrupt_proceed(struct cdns3_device *priv_dev, int dir) |
611 | { |
612 | u32 ep_sts_reg; |
613 | |
614 | cdns3_select_ep(priv_dev, ep: dir); |
615 | |
616 | ep_sts_reg = readl(addr: &priv_dev->regs->ep_sts); |
617 | writel(val: ep_sts_reg, addr: &priv_dev->regs->ep_sts); |
618 | |
619 | trace_cdns3_ep0_irq(priv_dev, ep_sts: ep_sts_reg); |
620 | |
621 | __pending_setup_status_handler(priv_dev); |
622 | |
623 | if (ep_sts_reg & EP_STS_SETUP) |
624 | priv_dev->wait_for_setup = 1; |
625 | |
626 | if (priv_dev->wait_for_setup && ep_sts_reg & EP_STS_IOC) { |
627 | priv_dev->wait_for_setup = 0; |
628 | cdns3_ep0_setup_phase(priv_dev); |
629 | } else if ((ep_sts_reg & EP_STS_IOC) || (ep_sts_reg & EP_STS_ISP)) { |
630 | priv_dev->ep0_data_dir = dir; |
631 | cdns3_transfer_completed(priv_dev); |
632 | } |
633 | |
634 | if (ep_sts_reg & EP_STS_DESCMIS) { |
635 | if (dir == 0 && !priv_dev->setup_pending) |
636 | cdns3_prepare_setup_packet(priv_dev); |
637 | } |
638 | } |
639 | |
640 | /** |
641 | * cdns3_gadget_ep0_enable |
642 | * @ep: pointer to endpoint zero object |
643 | * @desc: pointer to usb endpoint descriptor |
644 | * |
645 | * Function shouldn't be called by gadget driver, |
646 | * endpoint 0 is allways active |
647 | */ |
648 | static int cdns3_gadget_ep0_enable(struct usb_ep *ep, |
649 | const struct usb_endpoint_descriptor *desc) |
650 | { |
651 | return -EINVAL; |
652 | } |
653 | |
654 | /** |
655 | * cdns3_gadget_ep0_disable |
656 | * @ep: pointer to endpoint zero object |
657 | * |
658 | * Function shouldn't be called by gadget driver, |
659 | * endpoint 0 is allways active |
660 | */ |
661 | static int cdns3_gadget_ep0_disable(struct usb_ep *ep) |
662 | { |
663 | return -EINVAL; |
664 | } |
665 | |
666 | /** |
667 | * cdns3_gadget_ep0_set_halt |
668 | * @ep: pointer to endpoint zero object |
669 | * @value: 1 for set stall, 0 for clear stall |
670 | * |
671 | * Returns 0 |
672 | */ |
673 | static int cdns3_gadget_ep0_set_halt(struct usb_ep *ep, int value) |
674 | { |
675 | /* TODO */ |
676 | return 0; |
677 | } |
678 | |
679 | /** |
680 | * cdns3_gadget_ep0_queue - Transfer data on endpoint zero |
681 | * @ep: pointer to endpoint zero object |
682 | * @request: pointer to request object |
683 | * @gfp_flags: gfp flags |
684 | * |
685 | * Returns 0 on success, error code elsewhere |
686 | */ |
687 | static int cdns3_gadget_ep0_queue(struct usb_ep *ep, |
688 | struct usb_request *request, |
689 | gfp_t gfp_flags) |
690 | { |
691 | struct cdns3_endpoint *priv_ep = ep_to_cdns3_ep(ep); |
692 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; |
693 | unsigned long flags; |
694 | int ret = 0; |
695 | u8 zlp = 0; |
696 | int i; |
697 | |
698 | spin_lock_irqsave(&priv_dev->lock, flags); |
699 | trace_cdns3_ep0_queue(dev_priv: priv_dev, request); |
700 | |
701 | /* cancel the request if controller receive new SETUP packet. */ |
702 | if (cdns3_check_new_setup(priv_dev)) { |
703 | spin_unlock_irqrestore(lock: &priv_dev->lock, flags); |
704 | return -ECONNRESET; |
705 | } |
706 | |
707 | /* send STATUS stage. Should be called only for SET_CONFIGURATION */ |
708 | if (priv_dev->ep0_stage == CDNS3_STATUS_STAGE) { |
709 | u32 val; |
710 | |
711 | cdns3_select_ep(priv_dev, ep: 0x00); |
712 | |
713 | /* |
714 | * Configure all non-control EPs which are not enabled by class driver |
715 | */ |
716 | for (i = 0; i < CDNS3_ENDPOINTS_MAX_COUNT; i++) { |
717 | priv_ep = priv_dev->eps[i]; |
718 | if (priv_ep && priv_ep->flags & EP_CLAIMED && |
719 | !(priv_ep->flags & EP_ENABLED)) |
720 | cdns3_ep_config(priv_ep, enable: 0); |
721 | } |
722 | |
723 | cdns3_set_hw_configuration(priv_dev); |
724 | cdns3_ep0_complete_setup(priv_dev, send_stall: 0, send_erdy: 1); |
725 | /* wait until configuration set */ |
726 | ret = readl_poll_timeout_atomic(&priv_dev->regs->usb_sts, val, |
727 | val & USB_STS_CFGSTS_MASK, 1, 100); |
728 | if (ret == -ETIMEDOUT) |
729 | dev_warn(priv_dev->dev, "timeout for waiting configuration set\n" ); |
730 | |
731 | request->actual = 0; |
732 | priv_dev->status_completion_no_call = true; |
733 | priv_dev->pending_status_request = request; |
734 | usb_gadget_set_state(gadget: &priv_dev->gadget, state: USB_STATE_CONFIGURED); |
735 | spin_unlock_irqrestore(lock: &priv_dev->lock, flags); |
736 | |
737 | /* |
738 | * Since there is no completion interrupt for status stage, |
739 | * it needs to call ->completion in software after |
740 | * ep0_queue is back. |
741 | */ |
742 | queue_work(wq: system_freezable_wq, work: &priv_dev->pending_status_wq); |
743 | return ret; |
744 | } |
745 | |
746 | if (!list_empty(head: &priv_ep->pending_req_list)) { |
747 | dev_err(priv_dev->dev, |
748 | "can't handle multiple requests for ep0\n" ); |
749 | spin_unlock_irqrestore(lock: &priv_dev->lock, flags); |
750 | return -EBUSY; |
751 | } |
752 | |
753 | ret = usb_gadget_map_request_by_dev(dev: priv_dev->sysdev, req: request, |
754 | is_in: priv_dev->ep0_data_dir); |
755 | if (ret) { |
756 | spin_unlock_irqrestore(lock: &priv_dev->lock, flags); |
757 | dev_err(priv_dev->dev, "failed to map request\n" ); |
758 | return -EINVAL; |
759 | } |
760 | |
761 | request->status = -EINPROGRESS; |
762 | list_add_tail(new: &request->list, head: &priv_ep->pending_req_list); |
763 | |
764 | if (request->zero && request->length && |
765 | (request->length % ep->maxpacket == 0)) |
766 | zlp = 1; |
767 | |
768 | cdns3_ep0_run_transfer(priv_dev, dma_addr: request->dma, length: request->length, erdy: 1, zlp); |
769 | |
770 | spin_unlock_irqrestore(lock: &priv_dev->lock, flags); |
771 | |
772 | return ret; |
773 | } |
774 | |
775 | /** |
776 | * cdns3_gadget_ep_set_wedge - Set wedge on selected endpoint |
777 | * @ep: endpoint object |
778 | * |
779 | * Returns 0 |
780 | */ |
781 | int cdns3_gadget_ep_set_wedge(struct usb_ep *ep) |
782 | { |
783 | struct cdns3_endpoint *priv_ep = ep_to_cdns3_ep(ep); |
784 | struct cdns3_device *priv_dev = priv_ep->cdns3_dev; |
785 | |
786 | dev_dbg(priv_dev->dev, "Wedge for %s\n" , ep->name); |
787 | cdns3_gadget_ep_set_halt(ep, value: 1); |
788 | priv_ep->flags |= EP_WEDGE; |
789 | |
790 | return 0; |
791 | } |
792 | |
793 | static const struct usb_ep_ops cdns3_gadget_ep0_ops = { |
794 | .enable = cdns3_gadget_ep0_enable, |
795 | .disable = cdns3_gadget_ep0_disable, |
796 | .alloc_request = cdns3_gadget_ep_alloc_request, |
797 | .free_request = cdns3_gadget_ep_free_request, |
798 | .queue = cdns3_gadget_ep0_queue, |
799 | .dequeue = cdns3_gadget_ep_dequeue, |
800 | .set_halt = cdns3_gadget_ep0_set_halt, |
801 | .set_wedge = cdns3_gadget_ep_set_wedge, |
802 | }; |
803 | |
804 | /** |
805 | * cdns3_ep0_config - Configures default endpoint |
806 | * @priv_dev: extended gadget object |
807 | * |
808 | * Functions sets parameters: maximal packet size and enables interrupts |
809 | */ |
810 | void cdns3_ep0_config(struct cdns3_device *priv_dev) |
811 | { |
812 | struct cdns3_usb_regs __iomem *regs; |
813 | struct cdns3_endpoint *priv_ep; |
814 | u32 max_packet_size = 64; |
815 | u32 ep_cfg; |
816 | |
817 | regs = priv_dev->regs; |
818 | |
819 | if (priv_dev->gadget.speed == USB_SPEED_SUPER) |
820 | max_packet_size = 512; |
821 | |
822 | priv_ep = priv_dev->eps[0]; |
823 | |
824 | if (!list_empty(head: &priv_ep->pending_req_list)) { |
825 | struct usb_request *request; |
826 | |
827 | request = cdns3_next_request(list: &priv_ep->pending_req_list); |
828 | list_del_init(entry: &request->list); |
829 | } |
830 | |
831 | priv_dev->u1_allowed = 0; |
832 | priv_dev->u2_allowed = 0; |
833 | |
834 | priv_dev->gadget.ep0->maxpacket = max_packet_size; |
835 | cdns3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(max_packet_size); |
836 | |
837 | /* init ep out */ |
838 | cdns3_select_ep(priv_dev, USB_DIR_OUT); |
839 | |
840 | if (priv_dev->dev_ver >= DEV_VER_V3) { |
841 | cdns3_set_register_bit(ptr: &priv_dev->regs->dtrans, |
842 | BIT(0) | BIT(16)); |
843 | cdns3_set_register_bit(ptr: &priv_dev->regs->tdl_from_trb, |
844 | BIT(0) | BIT(16)); |
845 | } |
846 | |
847 | ep_cfg = EP_CFG_ENABLE | EP_CFG_MAXPKTSIZE(max_packet_size); |
848 | |
849 | if (!(priv_ep->flags & EP_CONFIGURED)) |
850 | writel(val: ep_cfg, addr: ®s->ep_cfg); |
851 | |
852 | writel(EP_STS_EN_SETUPEN | EP_STS_EN_DESCMISEN | EP_STS_EN_TRBERREN, |
853 | addr: ®s->ep_sts_en); |
854 | |
855 | /* init ep in */ |
856 | cdns3_select_ep(priv_dev, USB_DIR_IN); |
857 | |
858 | if (!(priv_ep->flags & EP_CONFIGURED)) |
859 | writel(val: ep_cfg, addr: ®s->ep_cfg); |
860 | |
861 | priv_ep->flags |= EP_CONFIGURED; |
862 | |
863 | writel(EP_STS_EN_SETUPEN | EP_STS_EN_TRBERREN, addr: ®s->ep_sts_en); |
864 | |
865 | cdns3_set_register_bit(ptr: ®s->usb_conf, USB_CONF_U1DS | USB_CONF_U2DS); |
866 | } |
867 | |
868 | /** |
869 | * cdns3_init_ep0 - Initializes software endpoint 0 of gadget |
870 | * @priv_dev: extended gadget object |
871 | * @priv_ep: extended endpoint object |
872 | * |
873 | * Returns 0 on success else error code. |
874 | */ |
875 | int cdns3_init_ep0(struct cdns3_device *priv_dev, |
876 | struct cdns3_endpoint *priv_ep) |
877 | { |
878 | sprintf(buf: priv_ep->name, fmt: "ep0" ); |
879 | |
880 | /* fill linux fields */ |
881 | priv_ep->endpoint.ops = &cdns3_gadget_ep0_ops; |
882 | priv_ep->endpoint.maxburst = 1; |
883 | usb_ep_set_maxpacket_limit(ep: &priv_ep->endpoint, |
884 | CDNS3_EP0_MAX_PACKET_LIMIT); |
885 | priv_ep->endpoint.address = 0; |
886 | priv_ep->endpoint.caps.type_control = 1; |
887 | priv_ep->endpoint.caps.dir_in = 1; |
888 | priv_ep->endpoint.caps.dir_out = 1; |
889 | priv_ep->endpoint.name = priv_ep->name; |
890 | priv_ep->endpoint.desc = &cdns3_gadget_ep0_desc; |
891 | priv_dev->gadget.ep0 = &priv_ep->endpoint; |
892 | priv_ep->type = USB_ENDPOINT_XFER_CONTROL; |
893 | |
894 | return cdns3_allocate_trb_pool(priv_ep); |
895 | } |
896 | |