From 47636fc5a2e74bcf99e2715bf43d7810bc21e167 Mon Sep 17 00:00:00 2001 From: Mayank Rana Date: Tue, 8 Oct 2019 12:14:45 -0700 Subject: [PATCH] usb: dwc3: Fix USB gadget initialization sequence This change fixes below issues: 1. registering UDC driver with udc core with dwc3 probe itself, so USB composition script can find UDC device while trying to select UDC. 2. creation of required USB endpoints related debugfs entries useful for debugging. 3. USB high speed only functionality fallback mechanism when USB super speed phy is not initialized. Change-Id: I893e6221ceb6af448695f5399e857be0c25f41b1 Signed-off-by: Mayank Rana Signed-off-by: Hemant Kumar Signed-off-by: Jack Pham --- drivers/usb/dwc3/core.c | 15 ++++++--- drivers/usb/dwc3/gadget.c | 70 +++++++++------------------------------ 2 files changed, 27 insertions(+), 58 deletions(-) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index ca2e25416017..c2c71532d358 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -950,6 +950,7 @@ int dwc3_core_init(struct dwc3 *dwc) } dwc3_cache_hwparams(dwc); + dwc3_check_params(dwc); ret = dwc3_get_dr_mode(dwc); if (ret) { ret = -EINVAL; @@ -1102,7 +1103,7 @@ int dwc3_core_init(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); } - dwc3_check_params(dwc); + dwc3_notify_event(dwc, DWC3_CONTROLLER_POST_RESET_EVENT, 0); return 0; @@ -1625,10 +1626,15 @@ static int dwc3_probe(struct platform_device *pdev) dwc3_event_buffers_cleanup(dwc); goto err3; } + } else if (dwc->dr_mode == USB_DR_MODE_OTG || + dwc->dr_mode == USB_DR_MODE_PERIPHERAL) { + ret = dwc3_gadget_init(dwc); + if (ret) { + dev_err(dwc->dev, "gadget init failed %d\n", ret); + goto err3; + } } - dwc3_debugfs_init(dwc); - dwc->dwc_ipc_log_ctxt = ipc_log_context_create(NUM_LOG_PAGES, dev_name(dwc->dev), 0); if (!dwc->dwc_ipc_log_ctxt) @@ -1639,6 +1645,7 @@ static int dwc3_probe(struct platform_device *pdev) count++; pm_runtime_allow(dev); + dwc3_debugfs_init(dwc); return 0; err3: @@ -1662,7 +1669,7 @@ static int dwc3_remove(struct platform_device *pdev) struct dwc3 *dwc = platform_get_drvdata(pdev); dwc3_debugfs_exit(dwc); - + dwc3_gadget_exit(dwc); pm_runtime_allow(&pdev->dev); pm_runtime_disable(&pdev->dev); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index f79d016b8c2b..efabf4226774 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1949,7 +1949,7 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc) static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) { - u32 reg; + u32 reg, reg1; u32 timeout = 1500; dbg_event(0xFF, "run_stop", is_on); @@ -1966,6 +1966,17 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) dwc3_event_buffers_setup(dwc); __dwc3_gadget_start(dwc); + reg1 = dwc3_readl(dwc->regs, DWC3_DCFG); + reg1 &= ~(DWC3_DCFG_SPEED_MASK); + + if (dwc->maximum_speed == USB_SPEED_SUPER_PLUS) + reg1 |= DWC3_DCFG_SUPERSPEED_PLUS; + else if (dwc->maximum_speed == USB_SPEED_HIGH) + reg1 |= DWC3_DCFG_HIGHSPEED; + else + reg1 |= DWC3_DCFG_SUPERSPEED; + dwc3_writel(dwc->regs, DWC3_DCFG, reg1); + reg |= DWC3_DCTL_RUN_STOP; if (dwc->has_hibernation) @@ -2385,7 +2396,7 @@ static void dwc3_gadget_config_params(struct usb_gadget *g, cpu_to_le16(DWC3_DEFAULT_U2_DEV_EXIT_LAT); } -static void dwc3_gadget_set_speed(struct usb_gadget *g, +static void __maybe_unused dwc3_gadget_set_speed(struct usb_gadget *g, enum usb_device_speed speed) { struct dwc3 *dwc = gadget_to_dwc(g); @@ -2455,7 +2466,6 @@ static const struct usb_gadget_ops dwc3_gadget_ops = { .pullup = dwc3_gadget_pullup, .udc_start = dwc3_gadget_start, .udc_stop = dwc3_gadget_stop, - .udc_set_speed = dwc3_gadget_set_speed, .get_config_params = dwc3_gadget_config_params, }; @@ -2480,52 +2490,7 @@ static int dwc3_gadget_init_control_endpoint(struct dwc3_ep *dep) return 0; } -static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep) -{ - struct dwc3 *dwc = dep->dwc; - int mdwidth; - int kbytes; - int size; - - mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0); - /* MDWIDTH is represented in bits, we need it in bytes */ - mdwidth /= 8; - - size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(dep->number >> 1)); - if (dwc3_is_usb31(dwc)) - size = DWC31_GTXFIFOSIZ_TXFDEF(size); - else - size = DWC3_GTXFIFOSIZ_TXFDEF(size); - - /* FIFO Depth is in MDWDITH bytes. Multiply */ - size *= mdwidth; - - kbytes = size / 1024; - if (kbytes == 0) - kbytes = 1; - - /* - * FIFO sizes account an extra MDWIDTH * (kbytes + 1) bytes for - * internal overhead. We don't really know how these are used, - * but documentation say it exists. - */ - size -= mdwidth * (kbytes + 1); - size /= kbytes; - - usb_ep_set_maxpacket_limit(&dep->endpoint, size); - - dep->endpoint.max_streams = 15; - dep->endpoint.ops = &dwc3_gadget_ep_ops; - list_add_tail(&dep->endpoint.ep_list, - &dwc->gadget.ep_list); - dep->endpoint.caps.type_iso = true; - dep->endpoint.caps.type_bulk = true; - dep->endpoint.caps.type_int = true; - - return dwc3_alloc_trb_pool(dep); -} - -static int dwc3_gadget_init_out_endpoint(struct dwc3_ep *dep) +static int dwc3_gadget_init_in_out_endpoint(struct dwc3_ep *dep) { struct dwc3 *dwc = dep->dwc; @@ -2572,10 +2537,8 @@ static int dwc3_gadget_init_endpoint(struct dwc3 *dwc, u8 epnum) if (num == 0) ret = dwc3_gadget_init_control_endpoint(dep); - else if (direction) - ret = dwc3_gadget_init_in_endpoint(dep); else - ret = dwc3_gadget_init_out_endpoint(dep); + ret = dwc3_gadget_init_in_out_endpoint(dep); if (ret) return ret; @@ -3816,6 +3779,7 @@ int dwc3_gadget_init(struct dwc3 *dwc) * sure we're starting from a well known location. */ + dwc->num_eps = DWC3_ENDPOINTS_NUM; ret = dwc3_gadget_init_endpoints(dwc, dwc->num_eps); if (ret) goto err3; @@ -3826,8 +3790,6 @@ int dwc3_gadget_init(struct dwc3 *dwc) goto err4; } - dwc3_gadget_set_speed(&dwc->gadget, dwc->maximum_speed); - return 0; err4: