Commit 0fe239bc authored by Douglas Anderson's avatar Douglas Anderson Committed by Felipe Balbi

usb: dwc2: Avoid double-reset at boot time

In (usb: dwc2: reset dwc2 core before dwc2_get_hwparams()) we added an
extra reset to the probe path for the dwc2 USB controllers.  This
allowed proper detection of parameters even if the firmware had already
used the USB part.

Unfortunately, this extra reset is quite slow and is affecting boot
speed.  We can avoid the double-reset by skipping the extra reset that
would happen just after the one we added.  Logic that explains why this
is safe:

* As of the CL mentioned above, we now always call dwc2_core_reset() in
  dwc2_driver_probe() before dwc2_hcd_init().

* The only caller of dwc2_hcd_init() is dwc2_driver_probe(), so we're
  guaranteed that dwc2_core_reset() was called before dwc2_hdc_init().

* dwc2_hdc_init() is the only caller that passes an irq other than -1 to
  dwc2_core_init().  Thus if dwc2_core_init() is called with an irq
  other than -1 we're guaranteed that dwc2_core_reset was called before
  dwc2_core_init().

...this allows us to remove the dwc2_core_reset() in dwc2_core_init() if
irq is not < 0.

Note that since "irq" wasn't used in the function dwc2_core_init()
anyway and since select_phy was always set at exactly the same times we
could avoid the reset, we remove "irq" and rename "select_phy" to
"initial_setup" and adjust the callers accordingly.
Signed-off-by: default avatarDouglas Anderson <dianders@chromium.org>
Signed-off-by: default avatarJohn Youn <johnyoun@synopsys.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent cebfdbf3
...@@ -765,11 +765,10 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg) ...@@ -765,11 +765,10 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg)
* dwc2_core_init() - Initializes the DWC_otg controller registers and * dwc2_core_init() - Initializes the DWC_otg controller registers and
* prepares the core for device mode or host mode operation * prepares the core for device mode or host mode operation
* *
* @hsotg: Programming view of the DWC_otg controller * @hsotg: Programming view of the DWC_otg controller
* @select_phy: If true then also set the Phy type * @initial_setup: If true then this is the first init for this instance.
* @irq: If >= 0, the irq to register
*/ */
int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq) int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup)
{ {
u32 usbcfg, otgctl; u32 usbcfg, otgctl;
int retval; int retval;
...@@ -791,18 +790,26 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq) ...@@ -791,18 +790,26 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq)
dwc2_writel(usbcfg, hsotg->regs + GUSBCFG); dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
/* Reset the Controller */ /*
retval = dwc2_core_reset(hsotg); * Reset the Controller
if (retval) { *
dev_err(hsotg->dev, "%s(): Reset failed, aborting\n", * We only need to reset the controller if this is a re-init.
__func__); * For the first init we know for sure that earlier code reset us (it
return retval; * needed to in order to properly detect various parameters).
*/
if (!initial_setup) {
retval = dwc2_core_reset(hsotg);
if (retval) {
dev_err(hsotg->dev, "%s(): Reset failed, aborting\n",
__func__);
return retval;
}
} }
/* /*
* This needs to happen in FS mode before any other programming occurs * This needs to happen in FS mode before any other programming occurs
*/ */
retval = dwc2_phy_init(hsotg, select_phy); retval = dwc2_phy_init(hsotg, initial_setup);
if (retval) if (retval)
return retval; return retval;
......
...@@ -918,7 +918,7 @@ extern void dwc2_read_packet(struct dwc2_hsotg *hsotg, u8 *dest, u16 bytes); ...@@ -918,7 +918,7 @@ extern void dwc2_read_packet(struct dwc2_hsotg *hsotg, u8 *dest, u16 bytes);
extern void dwc2_flush_tx_fifo(struct dwc2_hsotg *hsotg, const int num); extern void dwc2_flush_tx_fifo(struct dwc2_hsotg *hsotg, const int num);
extern void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg); extern void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg);
extern int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq); extern int dwc2_core_init(struct dwc2_hsotg *hsotg, bool initial_setup);
extern void dwc2_enable_global_interrupts(struct dwc2_hsotg *hcd); extern void dwc2_enable_global_interrupts(struct dwc2_hsotg *hcd);
extern void dwc2_disable_global_interrupts(struct dwc2_hsotg *hcd); extern void dwc2_disable_global_interrupts(struct dwc2_hsotg *hcd);
......
...@@ -1420,7 +1420,7 @@ static void dwc2_conn_id_status_change(struct work_struct *work) ...@@ -1420,7 +1420,7 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
dev_err(hsotg->dev, dev_err(hsotg->dev,
"Connection id status change timed out\n"); "Connection id status change timed out\n");
hsotg->op_state = OTG_STATE_B_PERIPHERAL; hsotg->op_state = OTG_STATE_B_PERIPHERAL;
dwc2_core_init(hsotg, false, -1); dwc2_core_init(hsotg, false);
dwc2_enable_global_interrupts(hsotg); dwc2_enable_global_interrupts(hsotg);
spin_lock_irqsave(&hsotg->lock, flags); spin_lock_irqsave(&hsotg->lock, flags);
dwc2_hsotg_core_init_disconnected(hsotg, false); dwc2_hsotg_core_init_disconnected(hsotg, false);
...@@ -1443,7 +1443,7 @@ static void dwc2_conn_id_status_change(struct work_struct *work) ...@@ -1443,7 +1443,7 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
hsotg->op_state = OTG_STATE_A_HOST; hsotg->op_state = OTG_STATE_A_HOST;
/* Initialize the Core for Host mode */ /* Initialize the Core for Host mode */
dwc2_core_init(hsotg, false, -1); dwc2_core_init(hsotg, false);
dwc2_enable_global_interrupts(hsotg); dwc2_enable_global_interrupts(hsotg);
dwc2_hcd_start(hsotg); dwc2_hcd_start(hsotg);
} }
...@@ -3120,7 +3120,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) ...@@ -3120,7 +3120,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
dwc2_disable_global_interrupts(hsotg); dwc2_disable_global_interrupts(hsotg);
/* Initialize the DWC_otg core, and select the Phy type */ /* Initialize the DWC_otg core, and select the Phy type */
retval = dwc2_core_init(hsotg, true, irq); retval = dwc2_core_init(hsotg, true);
if (retval) if (retval)
goto error2; goto error2;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment