]>
Commit | Line | Data |
---|---|---|
5fd54ace | 1 | // SPDX-License-Identifier: GPL-2.0 |
df2069ac CY |
2 | /* |
3 | * mtu3_gadget_ep0.c - MediaTek USB3 DRD peripheral driver ep0 handling | |
4 | * | |
5 | * Copyright (c) 2016 MediaTek Inc. | |
6 | * | |
7 | * Author: Chunfeng.Yun <chunfeng.yun@mediatek.com> | |
df2069ac CY |
8 | */ |
9 | ||
f3b28e5e | 10 | #include <linux/iopoll.h> |
fe7c994a CY |
11 | #include <linux/usb/composite.h> |
12 | ||
df2069ac | 13 | #include "mtu3.h" |
83374e03 CY |
14 | #include "mtu3_debug.h" |
15 | #include "mtu3_trace.h" | |
df2069ac CY |
16 | |
17 | /* ep0 is always mtu3->in_eps[0] */ | |
18 | #define next_ep0_request(mtu) next_request((mtu)->ep0) | |
19 | ||
20 | /* for high speed test mode; see USB 2.0 spec 7.1.20 */ | |
21 | static const u8 mtu3_test_packet[53] = { | |
22 | /* implicit SYNC then DATA0 to start */ | |
23 | ||
24 | /* JKJKJKJK x9 */ | |
25 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
26 | /* JJKKJJKK x8 */ | |
27 | 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, | |
28 | /* JJJJKKKK x8 */ | |
29 | 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, | |
30 | /* JJJJJJJKKKKKKK x8 */ | |
31 | 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
32 | /* JJJJJJJK x8 */ | |
33 | 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, | |
34 | /* JKKKKKKK x10, JK */ | |
35 | 0xfc, 0x7e, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0x7e, | |
36 | /* implicit CRC16 then EOP to end */ | |
37 | }; | |
38 | ||
39 | static char *decode_ep0_state(struct mtu3 *mtu) | |
40 | { | |
41 | switch (mtu->ep0_state) { | |
42 | case MU3D_EP0_STATE_SETUP: | |
43 | return "SETUP"; | |
44 | case MU3D_EP0_STATE_TX: | |
45 | return "IN"; | |
46 | case MU3D_EP0_STATE_RX: | |
47 | return "OUT"; | |
48 | case MU3D_EP0_STATE_TX_END: | |
49 | return "TX-END"; | |
50 | case MU3D_EP0_STATE_STALL: | |
51 | return "STALL"; | |
52 | default: | |
53 | return "??"; | |
54 | } | |
55 | } | |
56 | ||
57 | static void ep0_req_giveback(struct mtu3 *mtu, struct usb_request *req) | |
58 | { | |
59 | mtu3_req_complete(mtu->ep0, req, 0); | |
60 | } | |
61 | ||
62 | static int | |
63 | forward_to_driver(struct mtu3 *mtu, const struct usb_ctrlrequest *setup) | |
64 | __releases(mtu->lock) | |
65 | __acquires(mtu->lock) | |
66 | { | |
67 | int ret; | |
68 | ||
69 | if (!mtu->gadget_driver) | |
70 | return -EOPNOTSUPP; | |
71 | ||
72 | spin_unlock(&mtu->lock); | |
73 | ret = mtu->gadget_driver->setup(&mtu->g, setup); | |
74 | spin_lock(&mtu->lock); | |
75 | ||
76 | dev_dbg(mtu->dev, "%s ret %d\n", __func__, ret); | |
77 | return ret; | |
78 | } | |
79 | ||
80 | static void ep0_write_fifo(struct mtu3_ep *mep, const u8 *src, u16 len) | |
81 | { | |
82 | void __iomem *fifo = mep->mtu->mac_base + U3D_FIFO0; | |
83 | u16 index = 0; | |
84 | ||
85 | dev_dbg(mep->mtu->dev, "%s: ep%din, len=%d, buf=%p\n", | |
86 | __func__, mep->epnum, len, src); | |
87 | ||
88 | if (len >= 4) { | |
89 | iowrite32_rep(fifo, src, len >> 2); | |
90 | index = len & ~0x03; | |
91 | } | |
92 | if (len & 0x02) { | |
93 | writew(*(u16 *)&src[index], fifo); | |
94 | index += 2; | |
95 | } | |
96 | if (len & 0x01) | |
97 | writeb(src[index], fifo); | |
98 | } | |
99 | ||
100 | static void ep0_read_fifo(struct mtu3_ep *mep, u8 *dst, u16 len) | |
101 | { | |
102 | void __iomem *fifo = mep->mtu->mac_base + U3D_FIFO0; | |
103 | u32 value; | |
104 | u16 index = 0; | |
105 | ||
106 | dev_dbg(mep->mtu->dev, "%s: ep%dout len=%d buf=%p\n", | |
107 | __func__, mep->epnum, len, dst); | |
108 | ||
109 | if (len >= 4) { | |
110 | ioread32_rep(fifo, dst, len >> 2); | |
111 | index = len & ~0x03; | |
112 | } | |
113 | if (len & 0x3) { | |
114 | value = readl(fifo); | |
115 | memcpy(&dst[index], &value, len & 0x3); | |
116 | } | |
117 | ||
118 | } | |
119 | ||
120 | static void ep0_load_test_packet(struct mtu3 *mtu) | |
121 | { | |
122 | /* | |
123 | * because the length of test packet is less than max packet of HS ep0, | |
124 | * write it into fifo directly. | |
125 | */ | |
126 | ep0_write_fifo(mtu->ep0, mtu3_test_packet, sizeof(mtu3_test_packet)); | |
127 | } | |
128 | ||
129 | /* | |
130 | * A. send STALL for setup transfer without data stage: | |
131 | * set SENDSTALL and SETUPPKTRDY at the same time; | |
132 | * B. send STALL for other cases: | |
133 | * set SENDSTALL only. | |
134 | */ | |
135 | static void ep0_stall_set(struct mtu3_ep *mep0, bool set, u32 pktrdy) | |
136 | { | |
137 | struct mtu3 *mtu = mep0->mtu; | |
138 | void __iomem *mbase = mtu->mac_base; | |
139 | u32 csr; | |
140 | ||
141 | /* EP0_SENTSTALL is W1C */ | |
142 | csr = mtu3_readl(mbase, U3D_EP0CSR) & EP0_W1C_BITS; | |
143 | if (set) | |
144 | csr |= EP0_SENDSTALL | pktrdy; | |
145 | else | |
146 | csr = (csr & ~EP0_SENDSTALL) | EP0_SENTSTALL; | |
147 | mtu3_writel(mtu->mac_base, U3D_EP0CSR, csr); | |
148 | ||
fe7c994a | 149 | mtu->delayed_status = false; |
df2069ac CY |
150 | mtu->ep0_state = MU3D_EP0_STATE_SETUP; |
151 | ||
152 | dev_dbg(mtu->dev, "ep0: %s STALL, ep0_state: %s\n", | |
153 | set ? "SEND" : "CLEAR", decode_ep0_state(mtu)); | |
154 | } | |
155 | ||
71460342 CY |
156 | static void ep0_do_status_stage(struct mtu3 *mtu) |
157 | { | |
158 | void __iomem *mbase = mtu->mac_base; | |
159 | u32 value; | |
160 | ||
161 | value = mtu3_readl(mbase, U3D_EP0CSR) & EP0_W1C_BITS; | |
162 | mtu3_writel(mbase, U3D_EP0CSR, value | EP0_SETUPPKTRDY | EP0_DATAEND); | |
163 | } | |
164 | ||
df2069ac CY |
165 | static int ep0_queue(struct mtu3_ep *mep0, struct mtu3_request *mreq); |
166 | ||
167 | static void ep0_dummy_complete(struct usb_ep *ep, struct usb_request *req) | |
168 | {} | |
169 | ||
a29de31b CY |
170 | static void ep0_set_sel_complete(struct usb_ep *ep, struct usb_request *req) |
171 | { | |
172 | struct mtu3_request *mreq; | |
173 | struct mtu3 *mtu; | |
174 | struct usb_set_sel_req sel; | |
175 | ||
176 | memcpy(&sel, req->buf, sizeof(sel)); | |
177 | ||
178 | mreq = to_mtu3_request(req); | |
179 | mtu = mreq->mtu; | |
180 | dev_dbg(mtu->dev, "u1sel:%d, u1pel:%d, u2sel:%d, u2pel:%d\n", | |
181 | sel.u1_sel, sel.u1_pel, sel.u2_sel, sel.u2_pel); | |
182 | } | |
183 | ||
184 | /* queue data stage to handle 6 byte SET_SEL request */ | |
185 | static int ep0_set_sel(struct mtu3 *mtu, struct usb_ctrlrequest *setup) | |
186 | { | |
187 | int ret; | |
188 | u16 length = le16_to_cpu(setup->wLength); | |
189 | ||
190 | if (unlikely(length != 6)) { | |
191 | dev_err(mtu->dev, "%s wrong wLength:%d\n", | |
192 | __func__, length); | |
193 | return -EINVAL; | |
194 | } | |
195 | ||
196 | mtu->ep0_req.mep = mtu->ep0; | |
197 | mtu->ep0_req.request.length = 6; | |
198 | mtu->ep0_req.request.buf = mtu->setup_buf; | |
199 | mtu->ep0_req.request.complete = ep0_set_sel_complete; | |
200 | ret = ep0_queue(mtu->ep0, &mtu->ep0_req); | |
201 | ||
202 | return ret < 0 ? ret : 1; | |
203 | } | |
204 | ||
df2069ac CY |
205 | static int |
206 | ep0_get_status(struct mtu3 *mtu, const struct usb_ctrlrequest *setup) | |
207 | { | |
208 | struct mtu3_ep *mep = NULL; | |
209 | int handled = 1; | |
210 | u8 result[2] = {0, 0}; | |
211 | u8 epnum = 0; | |
212 | int is_in; | |
213 | ||
214 | switch (setup->bRequestType & USB_RECIP_MASK) { | |
215 | case USB_RECIP_DEVICE: | |
216 | result[0] = mtu->is_self_powered << USB_DEVICE_SELF_POWERED; | |
217 | result[0] |= mtu->may_wakeup << USB_DEVICE_REMOTE_WAKEUP; | |
4d79e042 CY |
218 | |
219 | if (mtu->g.speed >= USB_SPEED_SUPER) { | |
a29de31b CY |
220 | result[0] |= mtu->u1_enable << USB_DEV_STAT_U1_ENABLED; |
221 | result[0] |= mtu->u2_enable << USB_DEV_STAT_U2_ENABLED; | |
222 | } | |
223 | ||
224 | dev_dbg(mtu->dev, "%s result=%x, U1=%x, U2=%x\n", __func__, | |
225 | result[0], mtu->u1_enable, mtu->u2_enable); | |
226 | ||
df2069ac CY |
227 | break; |
228 | case USB_RECIP_INTERFACE: | |
229 | break; | |
230 | case USB_RECIP_ENDPOINT: | |
231 | epnum = (u8) le16_to_cpu(setup->wIndex); | |
232 | is_in = epnum & USB_DIR_IN; | |
233 | epnum &= USB_ENDPOINT_NUMBER_MASK; | |
234 | ||
235 | if (epnum >= mtu->num_eps) { | |
236 | handled = -EINVAL; | |
237 | break; | |
238 | } | |
239 | if (!epnum) | |
240 | break; | |
241 | ||
242 | mep = (is_in ? mtu->in_eps : mtu->out_eps) + epnum; | |
243 | if (!mep->desc) { | |
244 | handled = -EINVAL; | |
245 | break; | |
246 | } | |
247 | if (mep->flags & MTU3_EP_STALL) | |
248 | result[0] |= 1 << USB_ENDPOINT_HALT; | |
249 | ||
250 | break; | |
251 | default: | |
252 | /* class, vendor, etc ... delegate */ | |
253 | handled = 0; | |
254 | break; | |
255 | } | |
256 | ||
257 | if (handled > 0) { | |
258 | int ret; | |
259 | ||
260 | /* prepare a data stage for GET_STATUS */ | |
261 | dev_dbg(mtu->dev, "get_status=%x\n", *(u16 *)result); | |
262 | memcpy(mtu->setup_buf, result, sizeof(result)); | |
263 | mtu->ep0_req.mep = mtu->ep0; | |
264 | mtu->ep0_req.request.length = 2; | |
265 | mtu->ep0_req.request.buf = &mtu->setup_buf; | |
266 | mtu->ep0_req.request.complete = ep0_dummy_complete; | |
267 | ret = ep0_queue(mtu->ep0, &mtu->ep0_req); | |
268 | if (ret < 0) | |
269 | handled = ret; | |
270 | } | |
271 | return handled; | |
272 | } | |
273 | ||
274 | static int handle_test_mode(struct mtu3 *mtu, struct usb_ctrlrequest *setup) | |
275 | { | |
276 | void __iomem *mbase = mtu->mac_base; | |
277 | int handled = 1; | |
f3b28e5e | 278 | u32 value; |
df2069ac CY |
279 | |
280 | switch (le16_to_cpu(setup->wIndex) >> 8) { | |
281 | case TEST_J: | |
282 | dev_dbg(mtu->dev, "TEST_J\n"); | |
283 | mtu->test_mode_nr = TEST_J_MODE; | |
284 | break; | |
285 | case TEST_K: | |
286 | dev_dbg(mtu->dev, "TEST_K\n"); | |
287 | mtu->test_mode_nr = TEST_K_MODE; | |
288 | break; | |
289 | case TEST_SE0_NAK: | |
290 | dev_dbg(mtu->dev, "TEST_SE0_NAK\n"); | |
291 | mtu->test_mode_nr = TEST_SE0_NAK_MODE; | |
292 | break; | |
293 | case TEST_PACKET: | |
294 | dev_dbg(mtu->dev, "TEST_PACKET\n"); | |
295 | mtu->test_mode_nr = TEST_PACKET_MODE; | |
296 | break; | |
297 | default: | |
298 | handled = -EINVAL; | |
299 | goto out; | |
300 | } | |
301 | ||
302 | mtu->test_mode = true; | |
303 | ||
304 | /* no TX completion interrupt, and need restart platform after test */ | |
305 | if (mtu->test_mode_nr == TEST_PACKET_MODE) | |
306 | ep0_load_test_packet(mtu); | |
307 | ||
f3b28e5e | 308 | /* send status before entering test mode. */ |
71460342 | 309 | ep0_do_status_stage(mtu); |
f3b28e5e CY |
310 | |
311 | /* wait for ACK status sent by host */ | |
3d7678e2 | 312 | readl_poll_timeout_atomic(mbase + U3D_EP0CSR, value, |
f3b28e5e CY |
313 | !(value & EP0_DATAEND), 100, 5000); |
314 | ||
df2069ac CY |
315 | mtu3_writel(mbase, U3D_USB2_TEST_MODE, mtu->test_mode_nr); |
316 | ||
317 | mtu->ep0_state = MU3D_EP0_STATE_SETUP; | |
318 | ||
319 | out: | |
320 | return handled; | |
321 | } | |
322 | ||
323 | static int ep0_handle_feature_dev(struct mtu3 *mtu, | |
324 | struct usb_ctrlrequest *setup, bool set) | |
325 | { | |
a29de31b | 326 | void __iomem *mbase = mtu->mac_base; |
df2069ac | 327 | int handled = -EINVAL; |
a29de31b | 328 | u32 lpc; |
df2069ac CY |
329 | |
330 | switch (le16_to_cpu(setup->wValue)) { | |
331 | case USB_DEVICE_REMOTE_WAKEUP: | |
332 | mtu->may_wakeup = !!set; | |
333 | handled = 1; | |
334 | break; | |
335 | case USB_DEVICE_TEST_MODE: | |
336 | if (!set || (mtu->g.speed != USB_SPEED_HIGH) || | |
337 | (le16_to_cpu(setup->wIndex) & 0xff)) | |
338 | break; | |
339 | ||
340 | handled = handle_test_mode(mtu, setup); | |
341 | break; | |
a29de31b | 342 | case USB_DEVICE_U1_ENABLE: |
4d79e042 CY |
343 | if (mtu->g.speed < USB_SPEED_SUPER || |
344 | mtu->g.state != USB_STATE_CONFIGURED) | |
a29de31b CY |
345 | break; |
346 | ||
347 | lpc = mtu3_readl(mbase, U3D_LINK_POWER_CONTROL); | |
348 | if (set) | |
e8029724 | 349 | lpc |= SW_U1_REQUEST_ENABLE; |
a29de31b | 350 | else |
e8029724 | 351 | lpc &= ~SW_U1_REQUEST_ENABLE; |
a29de31b CY |
352 | mtu3_writel(mbase, U3D_LINK_POWER_CONTROL, lpc); |
353 | ||
354 | mtu->u1_enable = !!set; | |
355 | handled = 1; | |
356 | break; | |
357 | case USB_DEVICE_U2_ENABLE: | |
4d79e042 CY |
358 | if (mtu->g.speed < USB_SPEED_SUPER || |
359 | mtu->g.state != USB_STATE_CONFIGURED) | |
a29de31b CY |
360 | break; |
361 | ||
362 | lpc = mtu3_readl(mbase, U3D_LINK_POWER_CONTROL); | |
363 | if (set) | |
e8029724 | 364 | lpc |= SW_U2_REQUEST_ENABLE; |
a29de31b | 365 | else |
e8029724 | 366 | lpc &= ~SW_U2_REQUEST_ENABLE; |
a29de31b CY |
367 | mtu3_writel(mbase, U3D_LINK_POWER_CONTROL, lpc); |
368 | ||
369 | mtu->u2_enable = !!set; | |
370 | handled = 1; | |
371 | break; | |
df2069ac CY |
372 | default: |
373 | handled = -EINVAL; | |
374 | break; | |
375 | } | |
376 | return handled; | |
377 | } | |
378 | ||
379 | static int ep0_handle_feature(struct mtu3 *mtu, | |
380 | struct usb_ctrlrequest *setup, bool set) | |
381 | { | |
382 | struct mtu3_ep *mep; | |
383 | int handled = -EINVAL; | |
384 | int is_in; | |
385 | u16 value; | |
386 | u16 index; | |
387 | u8 epnum; | |
388 | ||
389 | value = le16_to_cpu(setup->wValue); | |
390 | index = le16_to_cpu(setup->wIndex); | |
391 | ||
392 | switch (setup->bRequestType & USB_RECIP_MASK) { | |
393 | case USB_RECIP_DEVICE: | |
394 | handled = ep0_handle_feature_dev(mtu, setup, set); | |
395 | break; | |
a29de31b CY |
396 | case USB_RECIP_INTERFACE: |
397 | /* superspeed only */ | |
4d79e042 CY |
398 | if (value == USB_INTRF_FUNC_SUSPEND && |
399 | mtu->g.speed >= USB_SPEED_SUPER) { | |
a29de31b CY |
400 | /* |
401 | * forward the request because function drivers | |
402 | * should handle it | |
403 | */ | |
404 | handled = 0; | |
405 | } | |
406 | break; | |
df2069ac CY |
407 | case USB_RECIP_ENDPOINT: |
408 | epnum = index & USB_ENDPOINT_NUMBER_MASK; | |
409 | if (epnum == 0 || epnum >= mtu->num_eps || | |
410 | value != USB_ENDPOINT_HALT) | |
411 | break; | |
412 | ||
413 | is_in = index & USB_DIR_IN; | |
414 | mep = (is_in ? mtu->in_eps : mtu->out_eps) + epnum; | |
415 | if (!mep->desc) | |
416 | break; | |
417 | ||
418 | handled = 1; | |
419 | /* ignore request if endpoint is wedged */ | |
420 | if (mep->wedged) | |
421 | break; | |
422 | ||
423 | mtu3_ep_stall_set(mep, set); | |
424 | break; | |
425 | default: | |
426 | /* class, vendor, etc ... delegate */ | |
427 | handled = 0; | |
428 | break; | |
429 | } | |
430 | return handled; | |
431 | } | |
432 | ||
433 | /* | |
434 | * handle all control requests can be handled | |
435 | * returns: | |
436 | * negative errno - error happened | |
437 | * zero - need delegate SETUP to gadget driver | |
438 | * positive - already handled | |
439 | */ | |
440 | static int handle_standard_request(struct mtu3 *mtu, | |
441 | struct usb_ctrlrequest *setup) | |
442 | { | |
443 | void __iomem *mbase = mtu->mac_base; | |
444 | enum usb_device_state state = mtu->g.state; | |
445 | int handled = -EINVAL; | |
446 | u32 dev_conf; | |
447 | u16 value; | |
448 | ||
449 | value = le16_to_cpu(setup->wValue); | |
450 | ||
451 | /* the gadget driver handles everything except what we must handle */ | |
452 | switch (setup->bRequest) { | |
453 | case USB_REQ_SET_ADDRESS: | |
454 | /* change it after the status stage */ | |
455 | mtu->address = (u8) (value & 0x7f); | |
456 | dev_dbg(mtu->dev, "set address to 0x%x\n", mtu->address); | |
457 | ||
458 | dev_conf = mtu3_readl(mbase, U3D_DEVICE_CONF); | |
459 | dev_conf &= ~DEV_ADDR_MSK; | |
460 | dev_conf |= DEV_ADDR(mtu->address); | |
461 | mtu3_writel(mbase, U3D_DEVICE_CONF, dev_conf); | |
462 | ||
463 | if (mtu->address) | |
464 | usb_gadget_set_state(&mtu->g, USB_STATE_ADDRESS); | |
465 | else | |
466 | usb_gadget_set_state(&mtu->g, USB_STATE_DEFAULT); | |
467 | ||
468 | handled = 1; | |
469 | break; | |
470 | case USB_REQ_SET_CONFIGURATION: | |
471 | if (state == USB_STATE_ADDRESS) { | |
472 | usb_gadget_set_state(&mtu->g, | |
473 | USB_STATE_CONFIGURED); | |
474 | } else if (state == USB_STATE_CONFIGURED) { | |
475 | /* | |
476 | * USB2 spec sec 9.4.7, if wValue is 0 then dev | |
477 | * is moved to addressed state | |
478 | */ | |
479 | if (!value) | |
480 | usb_gadget_set_state(&mtu->g, | |
481 | USB_STATE_ADDRESS); | |
482 | } | |
483 | handled = 0; | |
484 | break; | |
485 | case USB_REQ_CLEAR_FEATURE: | |
486 | handled = ep0_handle_feature(mtu, setup, 0); | |
487 | break; | |
488 | case USB_REQ_SET_FEATURE: | |
489 | handled = ep0_handle_feature(mtu, setup, 1); | |
490 | break; | |
491 | case USB_REQ_GET_STATUS: | |
492 | handled = ep0_get_status(mtu, setup); | |
493 | break; | |
a29de31b CY |
494 | case USB_REQ_SET_SEL: |
495 | handled = ep0_set_sel(mtu, setup); | |
496 | break; | |
df2069ac CY |
497 | case USB_REQ_SET_ISOCH_DELAY: |
498 | handled = 1; | |
499 | break; | |
500 | default: | |
501 | /* delegate SET_CONFIGURATION, etc */ | |
502 | handled = 0; | |
503 | } | |
504 | ||
505 | return handled; | |
506 | } | |
507 | ||
508 | /* receive an data packet (OUT) */ | |
509 | static void ep0_rx_state(struct mtu3 *mtu) | |
510 | { | |
511 | struct mtu3_request *mreq; | |
512 | struct usb_request *req; | |
513 | void __iomem *mbase = mtu->mac_base; | |
514 | u32 maxp; | |
515 | u32 csr; | |
516 | u16 count = 0; | |
517 | ||
518 | dev_dbg(mtu->dev, "%s\n", __func__); | |
519 | ||
520 | csr = mtu3_readl(mbase, U3D_EP0CSR) & EP0_W1C_BITS; | |
521 | mreq = next_ep0_request(mtu); | |
522 | req = &mreq->request; | |
523 | ||
524 | /* read packet and ack; or stall because of gadget driver bug */ | |
525 | if (req) { | |
526 | void *buf = req->buf + req->actual; | |
527 | unsigned int len = req->length - req->actual; | |
528 | ||
529 | /* read the buffer */ | |
530 | count = mtu3_readl(mbase, U3D_RXCOUNT0); | |
531 | if (count > len) { | |
532 | req->status = -EOVERFLOW; | |
533 | count = len; | |
534 | } | |
535 | ep0_read_fifo(mtu->ep0, buf, count); | |
536 | req->actual += count; | |
537 | csr |= EP0_RXPKTRDY; | |
538 | ||
539 | maxp = mtu->g.ep0->maxpacket; | |
540 | if (count < maxp || req->actual == req->length) { | |
541 | mtu->ep0_state = MU3D_EP0_STATE_SETUP; | |
542 | dev_dbg(mtu->dev, "ep0 state: %s\n", | |
543 | decode_ep0_state(mtu)); | |
544 | ||
545 | csr |= EP0_DATAEND; | |
546 | } else { | |
547 | req = NULL; | |
548 | } | |
549 | } else { | |
550 | csr |= EP0_RXPKTRDY | EP0_SENDSTALL; | |
551 | dev_dbg(mtu->dev, "%s: SENDSTALL\n", __func__); | |
552 | } | |
553 | ||
554 | mtu3_writel(mbase, U3D_EP0CSR, csr); | |
555 | ||
556 | /* give back the request if have received all data */ | |
557 | if (req) | |
558 | ep0_req_giveback(mtu, req); | |
559 | ||
560 | } | |
561 | ||
562 | /* transmitting to the host (IN) */ | |
563 | static void ep0_tx_state(struct mtu3 *mtu) | |
564 | { | |
565 | struct mtu3_request *mreq = next_ep0_request(mtu); | |
566 | struct usb_request *req; | |
567 | u32 csr; | |
568 | u8 *src; | |
288ee3c3 | 569 | u32 count; |
df2069ac CY |
570 | u32 maxp; |
571 | ||
572 | dev_dbg(mtu->dev, "%s\n", __func__); | |
573 | ||
574 | if (!mreq) | |
575 | return; | |
576 | ||
577 | maxp = mtu->g.ep0->maxpacket; | |
578 | req = &mreq->request; | |
579 | ||
580 | /* load the data */ | |
581 | src = (u8 *)req->buf + req->actual; | |
582 | count = min(maxp, req->length - req->actual); | |
583 | if (count) | |
584 | ep0_write_fifo(mtu->ep0, src, count); | |
585 | ||
586 | dev_dbg(mtu->dev, "%s act=%d, len=%d, cnt=%d, maxp=%d zero=%d\n", | |
587 | __func__, req->actual, req->length, count, maxp, req->zero); | |
588 | ||
589 | req->actual += count; | |
590 | ||
591 | if ((count < maxp) | |
592 | || ((req->actual == req->length) && !req->zero)) | |
593 | mtu->ep0_state = MU3D_EP0_STATE_TX_END; | |
594 | ||
595 | /* send it out, triggering a "txpktrdy cleared" irq */ | |
596 | csr = mtu3_readl(mtu->mac_base, U3D_EP0CSR) & EP0_W1C_BITS; | |
597 | mtu3_writel(mtu->mac_base, U3D_EP0CSR, csr | EP0_TXPKTRDY); | |
598 | ||
599 | dev_dbg(mtu->dev, "%s ep0csr=0x%x\n", __func__, | |
600 | mtu3_readl(mtu->mac_base, U3D_EP0CSR)); | |
601 | } | |
602 | ||
603 | static void ep0_read_setup(struct mtu3 *mtu, struct usb_ctrlrequest *setup) | |
604 | { | |
605 | struct mtu3_request *mreq; | |
606 | u32 count; | |
607 | u32 csr; | |
608 | ||
609 | csr = mtu3_readl(mtu->mac_base, U3D_EP0CSR) & EP0_W1C_BITS; | |
610 | count = mtu3_readl(mtu->mac_base, U3D_RXCOUNT0); | |
611 | ||
612 | ep0_read_fifo(mtu->ep0, (u8 *)setup, count); | |
613 | ||
614 | dev_dbg(mtu->dev, "SETUP req%02x.%02x v%04x i%04x l%04x\n", | |
615 | setup->bRequestType, setup->bRequest, | |
616 | le16_to_cpu(setup->wValue), le16_to_cpu(setup->wIndex), | |
617 | le16_to_cpu(setup->wLength)); | |
618 | ||
619 | /* clean up any leftover transfers */ | |
620 | mreq = next_ep0_request(mtu); | |
621 | if (mreq) | |
622 | ep0_req_giveback(mtu, &mreq->request); | |
623 | ||
624 | if (le16_to_cpu(setup->wLength) == 0) { | |
625 | ; /* no data stage, nothing to do */ | |
626 | } else if (setup->bRequestType & USB_DIR_IN) { | |
627 | mtu3_writel(mtu->mac_base, U3D_EP0CSR, | |
628 | csr | EP0_SETUPPKTRDY | EP0_DPHTX); | |
629 | mtu->ep0_state = MU3D_EP0_STATE_TX; | |
630 | } else { | |
631 | mtu3_writel(mtu->mac_base, U3D_EP0CSR, | |
632 | (csr | EP0_SETUPPKTRDY) & (~EP0_DPHTX)); | |
633 | mtu->ep0_state = MU3D_EP0_STATE_RX; | |
634 | } | |
635 | } | |
636 | ||
637 | static int ep0_handle_setup(struct mtu3 *mtu) | |
638 | __releases(mtu->lock) | |
639 | __acquires(mtu->lock) | |
640 | { | |
641 | struct usb_ctrlrequest setup; | |
642 | struct mtu3_request *mreq; | |
df2069ac CY |
643 | int handled = 0; |
644 | ||
645 | ep0_read_setup(mtu, &setup); | |
83374e03 | 646 | trace_mtu3_handle_setup(&setup); |
df2069ac CY |
647 | |
648 | if ((setup.bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) | |
649 | handled = handle_standard_request(mtu, &setup); | |
650 | ||
651 | dev_dbg(mtu->dev, "handled %d, ep0_state: %s\n", | |
652 | handled, decode_ep0_state(mtu)); | |
653 | ||
654 | if (handled < 0) | |
655 | goto stall; | |
656 | else if (handled > 0) | |
657 | goto finish; | |
658 | ||
659 | handled = forward_to_driver(mtu, &setup); | |
660 | if (handled < 0) { | |
661 | stall: | |
662 | dev_dbg(mtu->dev, "%s stall (%d)\n", __func__, handled); | |
663 | ||
664 | ep0_stall_set(mtu->ep0, true, | |
665 | le16_to_cpu(setup.wLength) ? 0 : EP0_SETUPPKTRDY); | |
666 | ||
667 | return 0; | |
668 | } | |
669 | ||
670 | finish: | |
671 | if (mtu->test_mode) { | |
672 | ; /* nothing to do */ | |
fe7c994a CY |
673 | } else if (handled == USB_GADGET_DELAYED_STATUS) { |
674 | /* handle the delay STATUS phase till receive ep_queue on ep0 */ | |
675 | mtu->delayed_status = true; | |
df2069ac CY |
676 | } else if (le16_to_cpu(setup.wLength) == 0) { /* no data stage */ |
677 | ||
71460342 | 678 | ep0_do_status_stage(mtu); |
df2069ac CY |
679 | /* complete zlp request directly */ |
680 | mreq = next_ep0_request(mtu); | |
681 | if (mreq && !mreq->request.length) | |
682 | ep0_req_giveback(mtu, &mreq->request); | |
683 | } | |
684 | ||
685 | return 0; | |
686 | } | |
687 | ||
688 | irqreturn_t mtu3_ep0_isr(struct mtu3 *mtu) | |
689 | { | |
690 | void __iomem *mbase = mtu->mac_base; | |
691 | struct mtu3_request *mreq; | |
692 | u32 int_status; | |
693 | irqreturn_t ret = IRQ_NONE; | |
694 | u32 csr; | |
695 | u32 len; | |
696 | ||
697 | int_status = mtu3_readl(mbase, U3D_EPISR); | |
698 | int_status &= mtu3_readl(mbase, U3D_EPIER); | |
699 | mtu3_writel(mbase, U3D_EPISR, int_status); /* W1C */ | |
700 | ||
701 | /* only handle ep0's */ | |
94552090 | 702 | if (!(int_status & (EP0ISR | SETUPENDISR))) |
df2069ac CY |
703 | return IRQ_NONE; |
704 | ||
94552090 CY |
705 | /* abort current SETUP, and process new one */ |
706 | if (int_status & SETUPENDISR) | |
707 | mtu->ep0_state = MU3D_EP0_STATE_SETUP; | |
708 | ||
df2069ac CY |
709 | csr = mtu3_readl(mbase, U3D_EP0CSR); |
710 | ||
711 | dev_dbg(mtu->dev, "%s csr=0x%x\n", __func__, csr); | |
712 | ||
713 | /* we sent a stall.. need to clear it now.. */ | |
714 | if (csr & EP0_SENTSTALL) { | |
715 | ep0_stall_set(mtu->ep0, false, 0); | |
716 | csr = mtu3_readl(mbase, U3D_EP0CSR); | |
717 | ret = IRQ_HANDLED; | |
718 | } | |
719 | dev_dbg(mtu->dev, "ep0_state: %s\n", decode_ep0_state(mtu)); | |
83374e03 | 720 | mtu3_dbg_trace(mtu->dev, "ep0_state %s", decode_ep0_state(mtu)); |
df2069ac CY |
721 | |
722 | switch (mtu->ep0_state) { | |
723 | case MU3D_EP0_STATE_TX: | |
724 | /* irq on clearing txpktrdy */ | |
725 | if ((csr & EP0_FIFOFULL) == 0) { | |
726 | ep0_tx_state(mtu); | |
727 | ret = IRQ_HANDLED; | |
728 | } | |
729 | break; | |
730 | case MU3D_EP0_STATE_RX: | |
731 | /* irq on set rxpktrdy */ | |
732 | if (csr & EP0_RXPKTRDY) { | |
733 | ep0_rx_state(mtu); | |
734 | ret = IRQ_HANDLED; | |
735 | } | |
736 | break; | |
737 | case MU3D_EP0_STATE_TX_END: | |
738 | mtu3_writel(mbase, U3D_EP0CSR, | |
739 | (csr & EP0_W1C_BITS) | EP0_DATAEND); | |
740 | ||
741 | mreq = next_ep0_request(mtu); | |
742 | if (mreq) | |
743 | ep0_req_giveback(mtu, &mreq->request); | |
744 | ||
745 | mtu->ep0_state = MU3D_EP0_STATE_SETUP; | |
746 | ret = IRQ_HANDLED; | |
747 | dev_dbg(mtu->dev, "ep0_state: %s\n", decode_ep0_state(mtu)); | |
748 | break; | |
749 | case MU3D_EP0_STATE_SETUP: | |
750 | if (!(csr & EP0_SETUPPKTRDY)) | |
751 | break; | |
752 | ||
753 | len = mtu3_readl(mbase, U3D_RXCOUNT0); | |
754 | if (len != 8) { | |
755 | dev_err(mtu->dev, "SETUP packet len %d != 8 ?\n", len); | |
756 | break; | |
757 | } | |
758 | ||
759 | ep0_handle_setup(mtu); | |
760 | ret = IRQ_HANDLED; | |
761 | break; | |
762 | default: | |
763 | /* can't happen */ | |
764 | ep0_stall_set(mtu->ep0, true, 0); | |
765 | WARN_ON(1); | |
766 | break; | |
767 | } | |
768 | ||
769 | return ret; | |
770 | } | |
771 | ||
772 | ||
773 | static int mtu3_ep0_enable(struct usb_ep *ep, | |
774 | const struct usb_endpoint_descriptor *desc) | |
775 | { | |
776 | /* always enabled */ | |
777 | return -EINVAL; | |
778 | } | |
779 | ||
780 | static int mtu3_ep0_disable(struct usb_ep *ep) | |
781 | { | |
782 | /* always enabled */ | |
783 | return -EINVAL; | |
784 | } | |
785 | ||
786 | static int ep0_queue(struct mtu3_ep *mep, struct mtu3_request *mreq) | |
787 | { | |
788 | struct mtu3 *mtu = mep->mtu; | |
789 | ||
790 | mreq->mtu = mtu; | |
791 | mreq->request.actual = 0; | |
792 | mreq->request.status = -EINPROGRESS; | |
793 | ||
794 | dev_dbg(mtu->dev, "%s %s (ep0_state: %s), len#%d\n", __func__, | |
795 | mep->name, decode_ep0_state(mtu), mreq->request.length); | |
796 | ||
df2069ac CY |
797 | switch (mtu->ep0_state) { |
798 | case MU3D_EP0_STATE_SETUP: | |
799 | case MU3D_EP0_STATE_RX: /* control-OUT data */ | |
800 | case MU3D_EP0_STATE_TX: /* control-IN data */ | |
801 | break; | |
802 | default: | |
803 | dev_err(mtu->dev, "%s, error in ep0 state %s\n", __func__, | |
804 | decode_ep0_state(mtu)); | |
805 | return -EINVAL; | |
806 | } | |
807 | ||
fe7c994a | 808 | if (mtu->delayed_status) { |
fe7c994a CY |
809 | |
810 | mtu->delayed_status = false; | |
71460342 | 811 | ep0_do_status_stage(mtu); |
fe7c994a CY |
812 | /* needn't giveback the request for handling delay STATUS */ |
813 | return 0; | |
814 | } | |
815 | ||
816 | if (!list_empty(&mep->req_list)) | |
817 | return -EBUSY; | |
818 | ||
df2069ac CY |
819 | list_add_tail(&mreq->list, &mep->req_list); |
820 | ||
821 | /* sequence #1, IN ... start writing the data */ | |
822 | if (mtu->ep0_state == MU3D_EP0_STATE_TX) | |
823 | ep0_tx_state(mtu); | |
824 | ||
825 | return 0; | |
826 | } | |
827 | ||
828 | static int mtu3_ep0_queue(struct usb_ep *ep, | |
829 | struct usb_request *req, gfp_t gfp) | |
830 | { | |
831 | struct mtu3_ep *mep; | |
832 | struct mtu3_request *mreq; | |
833 | struct mtu3 *mtu; | |
834 | unsigned long flags; | |
835 | int ret = 0; | |
836 | ||
837 | if (!ep || !req) | |
838 | return -EINVAL; | |
839 | ||
840 | mep = to_mtu3_ep(ep); | |
841 | mtu = mep->mtu; | |
842 | mreq = to_mtu3_request(req); | |
843 | ||
844 | spin_lock_irqsave(&mtu->lock, flags); | |
845 | ret = ep0_queue(mep, mreq); | |
846 | spin_unlock_irqrestore(&mtu->lock, flags); | |
847 | return ret; | |
848 | } | |
849 | ||
850 | static int mtu3_ep0_dequeue(struct usb_ep *ep, struct usb_request *req) | |
851 | { | |
852 | /* we just won't support this */ | |
853 | return -EINVAL; | |
854 | } | |
855 | ||
856 | static int mtu3_ep0_halt(struct usb_ep *ep, int value) | |
857 | { | |
858 | struct mtu3_ep *mep; | |
859 | struct mtu3 *mtu; | |
860 | unsigned long flags; | |
861 | int ret = 0; | |
862 | ||
863 | if (!ep || !value) | |
864 | return -EINVAL; | |
865 | ||
866 | mep = to_mtu3_ep(ep); | |
867 | mtu = mep->mtu; | |
868 | ||
869 | dev_dbg(mtu->dev, "%s\n", __func__); | |
870 | ||
871 | spin_lock_irqsave(&mtu->lock, flags); | |
872 | ||
873 | if (!list_empty(&mep->req_list)) { | |
874 | ret = -EBUSY; | |
875 | goto cleanup; | |
876 | } | |
877 | ||
878 | switch (mtu->ep0_state) { | |
879 | /* | |
880 | * stalls are usually issued after parsing SETUP packet, either | |
881 | * directly in irq context from setup() or else later. | |
882 | */ | |
883 | case MU3D_EP0_STATE_TX: | |
884 | case MU3D_EP0_STATE_TX_END: | |
885 | case MU3D_EP0_STATE_RX: | |
886 | case MU3D_EP0_STATE_SETUP: | |
887 | ep0_stall_set(mtu->ep0, true, 0); | |
888 | break; | |
889 | default: | |
890 | dev_dbg(mtu->dev, "ep0 can't halt in state %s\n", | |
891 | decode_ep0_state(mtu)); | |
892 | ret = -EINVAL; | |
893 | } | |
894 | ||
895 | cleanup: | |
896 | spin_unlock_irqrestore(&mtu->lock, flags); | |
897 | return ret; | |
898 | } | |
899 | ||
900 | const struct usb_ep_ops mtu3_ep0_ops = { | |
901 | .enable = mtu3_ep0_enable, | |
902 | .disable = mtu3_ep0_disable, | |
903 | .alloc_request = mtu3_alloc_request, | |
904 | .free_request = mtu3_free_request, | |
905 | .queue = mtu3_ep0_queue, | |
906 | .dequeue = mtu3_ep0_dequeue, | |
907 | .set_halt = mtu3_ep0_halt, | |
908 | }; |