diff options
Diffstat (limited to 'drivers/usb/dwc3/gadget.c')
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 83 |
1 files changed, 77 insertions, 6 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 70715eeededd..9d64dd02c57e 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -298,11 +298,76 @@ static const char *dwc3_gadget_ep_cmd_string(u8 cmd) | |||
298 | } | 298 | } |
299 | } | 299 | } |
300 | 300 | ||
301 | static const char *dwc3_gadget_generic_cmd_string(u8 cmd) | ||
302 | { | ||
303 | switch (cmd) { | ||
304 | case DWC3_DGCMD_SET_LMP: | ||
305 | return "Set LMP"; | ||
306 | case DWC3_DGCMD_SET_PERIODIC_PAR: | ||
307 | return "Set Periodic Parameters"; | ||
308 | case DWC3_DGCMD_XMIT_FUNCTION: | ||
309 | return "Transmit Function Wake Device Notification"; | ||
310 | case DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO: | ||
311 | return "Set Scratchpad Buffer Array Address Lo"; | ||
312 | case DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI: | ||
313 | return "Set Scratchpad Buffer Array Address Hi"; | ||
314 | case DWC3_DGCMD_SELECTED_FIFO_FLUSH: | ||
315 | return "Selected FIFO Flush"; | ||
316 | case DWC3_DGCMD_ALL_FIFO_FLUSH: | ||
317 | return "All FIFO Flush"; | ||
318 | case DWC3_DGCMD_SET_ENDPOINT_NRDY: | ||
319 | return "Set Endpoint NRDY"; | ||
320 | case DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK: | ||
321 | return "Run SoC Bus Loopback Test"; | ||
322 | default: | ||
323 | return "UNKNOWN"; | ||
324 | } | ||
325 | } | ||
326 | |||
327 | static const char *dwc3_gadget_link_string(enum dwc3_link_state link_state) | ||
328 | { | ||
329 | switch (link_state) { | ||
330 | case DWC3_LINK_STATE_U0: | ||
331 | return "U0"; | ||
332 | case DWC3_LINK_STATE_U1: | ||
333 | return "U1"; | ||
334 | case DWC3_LINK_STATE_U2: | ||
335 | return "U2"; | ||
336 | case DWC3_LINK_STATE_U3: | ||
337 | return "U3"; | ||
338 | case DWC3_LINK_STATE_SS_DIS: | ||
339 | return "SS.Disabled"; | ||
340 | case DWC3_LINK_STATE_RX_DET: | ||
341 | return "RX.Detect"; | ||
342 | case DWC3_LINK_STATE_SS_INACT: | ||
343 | return "SS.Inactive"; | ||
344 | case DWC3_LINK_STATE_POLL: | ||
345 | return "Polling"; | ||
346 | case DWC3_LINK_STATE_RECOV: | ||
347 | return "Recovery"; | ||
348 | case DWC3_LINK_STATE_HRESET: | ||
349 | return "Hot Reset"; | ||
350 | case DWC3_LINK_STATE_CMPLY: | ||
351 | return "Compliance"; | ||
352 | case DWC3_LINK_STATE_LPBK: | ||
353 | return "Loopback"; | ||
354 | case DWC3_LINK_STATE_RESET: | ||
355 | return "Reset"; | ||
356 | case DWC3_LINK_STATE_RESUME: | ||
357 | return "Resume"; | ||
358 | default: | ||
359 | return "UNKNOWN link state\n"; | ||
360 | } | ||
361 | } | ||
362 | |||
301 | int dwc3_send_gadget_generic_command(struct dwc3 *dwc, int cmd, u32 param) | 363 | int dwc3_send_gadget_generic_command(struct dwc3 *dwc, int cmd, u32 param) |
302 | { | 364 | { |
303 | u32 timeout = 500; | 365 | u32 timeout = 500; |
304 | u32 reg; | 366 | u32 reg; |
305 | 367 | ||
368 | dev_vdbg(dwc->dev, "generic cmd '%s' [%d] param %08x\n", | ||
369 | dwc3_gadget_generic_cmd_string(cmd), cmd, param); | ||
370 | |||
306 | dwc3_writel(dwc->regs, DWC3_DGCMDPAR, param); | 371 | dwc3_writel(dwc->regs, DWC3_DGCMDPAR, param); |
307 | dwc3_writel(dwc->regs, DWC3_DGCMD, cmd | DWC3_DGCMD_CMDACT); | 372 | dwc3_writel(dwc->regs, DWC3_DGCMD, cmd | DWC3_DGCMD_CMDACT); |
308 | 373 | ||
@@ -332,9 +397,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, | |||
332 | u32 timeout = 500; | 397 | u32 timeout = 500; |
333 | u32 reg; | 398 | u32 reg; |
334 | 399 | ||
335 | dev_vdbg(dwc->dev, "%s: cmd '%s' params %08x %08x %08x\n", | 400 | dev_vdbg(dwc->dev, "%s: cmd '%s' [%d] params %08x %08x %08x\n", |
336 | dep->name, | 401 | dep->name, |
337 | dwc3_gadget_ep_cmd_string(cmd), params->param0, | 402 | dwc3_gadget_ep_cmd_string(cmd), cmd, params->param0, |
338 | params->param1, params->param2); | 403 | params->param1, params->param2); |
339 | 404 | ||
340 | dwc3_writel(dwc->regs, DWC3_DEPCMDPAR0(ep), params->param0); | 405 | dwc3_writel(dwc->regs, DWC3_DEPCMDPAR0(ep), params->param0); |
@@ -515,7 +580,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, | |||
515 | { | 580 | { |
516 | struct dwc3 *dwc = dep->dwc; | 581 | struct dwc3 *dwc = dep->dwc; |
517 | u32 reg; | 582 | u32 reg; |
518 | int ret = -ENOMEM; | 583 | int ret; |
519 | 584 | ||
520 | dev_vdbg(dwc->dev, "Enabling %s\n", dep->name); | 585 | dev_vdbg(dwc->dev, "Enabling %s\n", dep->name); |
521 | 586 | ||
@@ -604,6 +669,10 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) | |||
604 | 669 | ||
605 | dwc3_remove_requests(dwc, dep); | 670 | dwc3_remove_requests(dwc, dep); |
606 | 671 | ||
672 | /* make sure HW endpoint isn't stalled */ | ||
673 | if (dep->flags & DWC3_EP_STALL) | ||
674 | __dwc3_gadget_ep_set_halt(dep, 0); | ||
675 | |||
607 | reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); | 676 | reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); |
608 | reg &= ~DWC3_DALEPENA_EP(dep->number); | 677 | reg &= ~DWC3_DALEPENA_EP(dep->number); |
609 | dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); | 678 | dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); |
@@ -2441,8 +2510,6 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc, | |||
2441 | } | 2510 | } |
2442 | } | 2511 | } |
2443 | 2512 | ||
2444 | dwc->link_state = next; | ||
2445 | |||
2446 | switch (next) { | 2513 | switch (next) { |
2447 | case DWC3_LINK_STATE_U1: | 2514 | case DWC3_LINK_STATE_U1: |
2448 | if (dwc->speed == USB_SPEED_SUPER) | 2515 | if (dwc->speed == USB_SPEED_SUPER) |
@@ -2460,7 +2527,11 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc, | |||
2460 | break; | 2527 | break; |
2461 | } | 2528 | } |
2462 | 2529 | ||
2463 | dev_vdbg(dwc->dev, "%s link %d\n", __func__, dwc->link_state); | 2530 | dev_vdbg(dwc->dev, "link change: %s [%d] -> %s [%d]\n", |
2531 | dwc3_gadget_link_string(dwc->link_state), | ||
2532 | dwc->link_state, dwc3_gadget_link_string(next), next); | ||
2533 | |||
2534 | dwc->link_state = next; | ||
2464 | } | 2535 | } |
2465 | 2536 | ||
2466 | static void dwc3_gadget_hibernation_interrupt(struct dwc3 *dwc, | 2537 | static void dwc3_gadget_hibernation_interrupt(struct dwc3 *dwc, |