forked from luck/tmp_suning_uos_patched
usb: dwc3: Set the ClearPendIN bit on Clear Stall EP command
As of core revision 2.60a the recommended programming model is to set the ClearPendIN bit when issuing a Clear Stall EP command for IN endpoints. This is to prevent an issue where some (non-compliant) hosts may not send ACK TPs for pending IN transfers due to a mishandled error condition. Synopsys STAR 9000614252. Signed-off-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
This commit is contained in:
parent
27a0faafdc
commit
50c763f8c1
@ -402,6 +402,7 @@
|
||||
#define DWC3_DEPCMD_GET_RSC_IDX(x) (((x) >> DWC3_DEPCMD_PARAM_SHIFT) & 0x7f)
|
||||
#define DWC3_DEPCMD_STATUS(x) (((x) >> 12) & 0x0F)
|
||||
#define DWC3_DEPCMD_HIPRI_FORCERM (1 << 11)
|
||||
#define DWC3_DEPCMD_CLEARPENDIN (1 << 11)
|
||||
#define DWC3_DEPCMD_CMDACT (1 << 10)
|
||||
#define DWC3_DEPCMD_CMDIOC (1 << 8)
|
||||
|
||||
|
@ -347,6 +347,28 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dwc3_send_clear_stall_ep_cmd(struct dwc3_ep *dep)
|
||||
{
|
||||
struct dwc3 *dwc = dep->dwc;
|
||||
struct dwc3_gadget_ep_cmd_params params;
|
||||
u32 cmd = DWC3_DEPCMD_CLEARSTALL;
|
||||
|
||||
/*
|
||||
* As of core revision 2.60a the recommended programming model
|
||||
* is to set the ClearPendIN bit when issuing a Clear Stall EP
|
||||
* command for IN endpoints. This is to prevent an issue where
|
||||
* some (non-compliant) hosts may not send ACK TPs for pending
|
||||
* IN transfers due to a mishandled error condition. Synopsys
|
||||
* STAR 9000614252.
|
||||
*/
|
||||
if (dep->direction && (dwc->revision >= DWC3_REVISION_260A))
|
||||
cmd |= DWC3_DEPCMD_CLEARPENDIN;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
|
||||
return dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms);
|
||||
}
|
||||
|
||||
static dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep,
|
||||
struct dwc3_trb *trb)
|
||||
{
|
||||
@ -1314,8 +1336,7 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
|
||||
else
|
||||
dep->flags |= DWC3_EP_STALL;
|
||||
} else {
|
||||
ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
|
||||
DWC3_DEPCMD_CLEARSTALL, ¶ms);
|
||||
ret = dwc3_send_clear_stall_ep_cmd(dep);
|
||||
if (ret)
|
||||
dev_err(dwc->dev, "failed to clear STALL on %s\n",
|
||||
dep->name);
|
||||
@ -2247,7 +2268,6 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
|
||||
|
||||
for (epnum = 1; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
|
||||
struct dwc3_ep *dep;
|
||||
struct dwc3_gadget_ep_cmd_params params;
|
||||
int ret;
|
||||
|
||||
dep = dwc->eps[epnum];
|
||||
@ -2259,9 +2279,7 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
|
||||
|
||||
dep->flags &= ~DWC3_EP_STALL;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
ret = dwc3_send_gadget_ep_cmd(dwc, dep->number,
|
||||
DWC3_DEPCMD_CLEARSTALL, ¶ms);
|
||||
ret = dwc3_send_clear_stall_ep_cmd(dep);
|
||||
WARN_ON_ONCE(ret);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user