usb: dwc2: Clear fifo_map when resetting core.

Switching from device mode to host mode by disconnecting
device cable core enters and exits form hibernation.
However, the fifo map remains not cleared. It results
to a WARNING (WARNING: CPU: 5 PID: 0 at drivers/usb/dwc2/
gadget.c:307 dwc2_hsotg_init_fifo+0x12/0x152 [dwc2])
if in host mode we disconnect the micro a to b host
cable. Because core reset occurs.

To avoid the WARNING, fifo_map should be cleared
in dwc2_core_reset() function by taking into account configs.
fifo_map must be cleared only if driver is configured in
"CONFIG_USB_DWC2_PERIPHERAL" or "CONFIG_USB_DWC2_DUAL_ROLE"
mode.

- Added "static inline void dwc2_clear_fifo_map()" helper
function to clear fifo_map with peripheral or dual role mode.

- Added a dummy version of "dwc2_clear_fifo_map()" helper
for host-only mode.

Acked-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
Signed-off-by: Artur Petrosyan <Arthur.Petrosyan@synopsys.com>
Link: https://lore.kernel.org/r/20210416124731.C500AA005D@mailhost.synopsys.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Artur Petrosyan 2021-04-16 16:47:30 +04:00 committed by Greg Kroah-Hartman
parent 4111d5f805
commit 238f65aeea
2 changed files with 19 additions and 0 deletions

View File

@ -470,6 +470,22 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait)
dwc2_writel(hsotg, greset, GRSTCTL);
}
/*
* Switching from device mode to host mode by disconnecting
* device cable core enters and exits form hibernation.
* However, the fifo map remains not cleared. It results
* to a WARNING (WARNING: CPU: 5 PID: 0 at drivers/usb/dwc2/
* gadget.c:307 dwc2_hsotg_init_fifo+0x12/0x152 [dwc2])
* if in host mode we disconnect the micro a to b host
* cable. Because core reset occurs.
* To avoid the WARNING, fifo_map should be cleared
* in dwc2_core_reset() function by taking into account configs.
* fifo_map must be cleared only if driver is configured in
* "CONFIG_USB_DWC2_PERIPHERAL" or "CONFIG_USB_DWC2_DUAL_ROLE"
* mode.
*/
dwc2_clear_fifo_map(hsotg);
/* Wait for AHB master IDLE state */
if (dwc2_hsotg_wait_bit_set(hsotg, GRSTCTL, GRSTCTL_AHBIDLE, 10000)) {
dev_warn(hsotg->dev, "%s: HANG! AHB Idle timeout GRSTCTL GRSTCTL_AHBIDLE\n",

View File

@ -1425,6 +1425,8 @@ int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg);
int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg);
void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg);
void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg);
static inline void dwc2_clear_fifo_map(struct dwc2_hsotg *hsotg)
{ hsotg->fifo_map = 0; }
#else
static inline int dwc2_hsotg_remove(struct dwc2_hsotg *dwc2)
{ return 0; }
@ -1469,6 +1471,7 @@ static inline int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg)
{ return 0; }
static inline void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg) {}
static inline void dwc2_gadget_program_ref_clk(struct dwc2_hsotg *hsotg) {}
static inline void dwc2_clear_fifo_map(struct dwc2_hsotg *hsotg) {}
#endif
#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)