|
@@ -16,6 +16,8 @@
|
|
|
*
|
|
|
*/
|
|
|
|
|
|
+#include <linux/usb/composite.h>
|
|
|
+
|
|
|
#include "mtu3.h"
|
|
|
|
|
|
/* ep0 is always mtu3->in_eps[0] */
|
|
@@ -150,6 +152,7 @@ static void ep0_stall_set(struct mtu3_ep *mep0, bool set, u32 pktrdy)
|
|
|
csr = (csr & ~EP0_SENDSTALL) | EP0_SENTSTALL;
|
|
|
mtu3_writel(mtu->mac_base, U3D_EP0CSR, csr);
|
|
|
|
|
|
+ mtu->delayed_status = false;
|
|
|
mtu->ep0_state = MU3D_EP0_STATE_SETUP;
|
|
|
|
|
|
dev_dbg(mtu->dev, "ep0: %s STALL, ep0_state: %s\n",
|
|
@@ -656,6 +659,9 @@ stall:
|
|
|
finish:
|
|
|
if (mtu->test_mode) {
|
|
|
; /* nothing to do */
|
|
|
+ } else if (handled == USB_GADGET_DELAYED_STATUS) {
|
|
|
+ /* handle the delay STATUS phase till receive ep_queue on ep0 */
|
|
|
+ mtu->delayed_status = true;
|
|
|
} else if (le16_to_cpu(setup.wLength) == 0) { /* no data stage */
|
|
|
|
|
|
mtu3_writel(mbase, U3D_EP0CSR,
|
|
@@ -775,9 +781,6 @@ static int ep0_queue(struct mtu3_ep *mep, struct mtu3_request *mreq)
|
|
|
dev_dbg(mtu->dev, "%s %s (ep0_state: %s), len#%d\n", __func__,
|
|
|
mep->name, decode_ep0_state(mtu), mreq->request.length);
|
|
|
|
|
|
- if (!list_empty(&mep->req_list))
|
|
|
- return -EBUSY;
|
|
|
-
|
|
|
switch (mtu->ep0_state) {
|
|
|
case MU3D_EP0_STATE_SETUP:
|
|
|
case MU3D_EP0_STATE_RX: /* control-OUT data */
|
|
@@ -789,6 +792,20 @@ static int ep0_queue(struct mtu3_ep *mep, struct mtu3_request *mreq)
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ if (mtu->delayed_status) {
|
|
|
+ u32 csr;
|
|
|
+
|
|
|
+ mtu->delayed_status = false;
|
|
|
+ csr = mtu3_readl(mtu->mac_base, U3D_EP0CSR) & EP0_W1C_BITS;
|
|
|
+ csr |= EP0_SETUPPKTRDY | EP0_DATAEND;
|
|
|
+ mtu3_writel(mtu->mac_base, U3D_EP0CSR, csr);
|
|
|
+ /* needn't giveback the request for handling delay STATUS */
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!list_empty(&mep->req_list))
|
|
|
+ return -EBUSY;
|
|
|
+
|
|
|
list_add_tail(&mreq->list, &mep->req_list);
|
|
|
|
|
|
/* sequence #1, IN ... start writing the data */
|