mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-12-20 08:52:12 +01:00
Use GUSBCFG_FORCEHOSTMODE to detected the HOST forced mode as it is done
in the Linux driver drivers/usb/dwc2/core.c:dwc2_core_reset().
The host polling must be executed only if the current mode is host,
either due to the force HOST mode (which persists after core reset)
or the connector id pin.
The GUSBCFG_FORCEDEVMODE bits is used to force the device mode (for
example used on STM32MP1x platform) and when it is activated the DWC2 reset
failed with the trace:
"dwc2_core_reset: Waiting for GINTSTS_CURMODE_HOST timeout"
Fixes: c5d685b8993c ("usb: dwc2: Unify flush and reset logic with v4.20a support")
Signed-off-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
Reviewed-by: Junhui Liu <junhui.liu@pigmoral.tech>
Tested-by: Patrice Chotard <patrice.chotard@foss.st.com>
Reviewed-by: Marek Vasut <marek.vasut@mailbox.org>
132 lines
3.5 KiB
C
132 lines
3.5 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Copyright (c) 2024-2025, Kongyang Liu <seashell11234455@gmail.com>
|
|
*/
|
|
|
|
#include <linux/bitfield.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/io.h>
|
|
#include <wait_bit.h>
|
|
|
|
#include "dwc2_core.h"
|
|
|
|
int dwc2_core_reset(struct dwc2_core_regs *regs)
|
|
{
|
|
u32 snpsid;
|
|
int ret;
|
|
bool host_mode = false;
|
|
|
|
if (!(readl(®s->global_regs.gotgctl) & GOTGCTL_CONID_B) ||
|
|
(readl(®s->global_regs.gusbcfg) & GUSBCFG_FORCEHOSTMODE))
|
|
host_mode = true;
|
|
|
|
/* Core Soft Reset */
|
|
snpsid = readl(®s->global_regs.gsnpsid);
|
|
writel(GRSTCTL_CSFTRST, ®s->global_regs.grstctl);
|
|
if (FIELD_GET(GSNPSID_VER_MASK, snpsid) < 0x420a) {
|
|
ret = wait_for_bit_le32(®s->global_regs.grstctl, GRSTCTL_CSFTRST,
|
|
false, 1000, false);
|
|
if (ret) {
|
|
log_warning("%s: Waiting for GRSTCTL_CSFTRST timeout\n", __func__);
|
|
return ret;
|
|
}
|
|
} else {
|
|
ret = wait_for_bit_le32(®s->global_regs.grstctl, GRSTCTL_CSFTRST_DONE,
|
|
true, 1000, false);
|
|
if (ret) {
|
|
log_warning("%s: Waiting for GRSTCTL_CSFTRST_DONE timeout\n", __func__);
|
|
return ret;
|
|
}
|
|
clrsetbits_le32(®s->global_regs.grstctl, GRSTCTL_CSFTRST, GRSTCTL_CSFTRST_DONE);
|
|
}
|
|
|
|
/* Wait for AHB master IDLE state. */
|
|
ret = wait_for_bit_le32(®s->global_regs.grstctl, GRSTCTL_AHBIDLE,
|
|
true, 1000, false);
|
|
if (ret) {
|
|
log_warning("%s: Waiting for GRSTCTL_AHBIDLE timeout\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
if (host_mode) {
|
|
ret = wait_for_bit_le32(®s->global_regs.gintsts, GINTSTS_CURMODE_HOST,
|
|
host_mode, 1000, false);
|
|
if (ret) {
|
|
log_warning("%s: Waiting for GINTSTS_CURMODE_HOST timeout\n", __func__);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dwc2_flush_tx_fifo(struct dwc2_core_regs *regs, const int num)
|
|
{
|
|
int ret;
|
|
|
|
log_debug("Flush Tx FIFO %d\n", num);
|
|
|
|
/* Wait for AHB master IDLE state */
|
|
ret = wait_for_bit_le32(®s->global_regs.grstctl, GRSTCTL_AHBIDLE, true, 1000, false);
|
|
if (ret) {
|
|
log_warning("%s: Waiting for GRSTCTL_AHBIDLE timeout\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
writel(GRSTCTL_TXFFLSH | FIELD_PREP(GRSTCTL_TXFNUM_MASK, num), ®s->global_regs.grstctl);
|
|
|
|
ret = wait_for_bit_le32(®s->global_regs.grstctl, GRSTCTL_TXFFLSH, false, 1000, false);
|
|
if (ret) {
|
|
log_warning("%s: Waiting for GRSTCTL_TXFFLSH timeout\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Wait for at least 3 PHY clocks.
|
|
*
|
|
* The PHY clock frequency can be configured to 6/30/48/60 MHz
|
|
* based on the speed mode. A fixed delay of 1us ensures that the
|
|
* wait time is sufficient even at the lowest PHY clock frequency
|
|
* (6 MHz), where 1us corresponds to twice the duration of 3 PHY
|
|
* clocks.
|
|
*/
|
|
udelay(1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int dwc2_flush_rx_fifo(struct dwc2_core_regs *regs)
|
|
{
|
|
int ret;
|
|
|
|
log_debug("Flush Rx FIFO\n");
|
|
|
|
/* Wait for AHB master IDLE state */
|
|
ret = wait_for_bit_le32(®s->global_regs.grstctl, GRSTCTL_AHBIDLE, true, 1000, false);
|
|
if (ret) {
|
|
log_warning("%s: Waiting for GRSTCTL_AHBIDLE timeout\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
writel(GRSTCTL_RXFFLSH, ®s->global_regs.grstctl);
|
|
|
|
ret = wait_for_bit_le32(®s->global_regs.grstctl, GRSTCTL_RXFFLSH, false, 1000, false);
|
|
if (ret) {
|
|
log_warning("%s: Waiting for GRSTCTL_RXFFLSH timeout\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Wait for at least 3 PHY clocks.
|
|
*
|
|
* The PHY clock frequency can be configured to 6/30/48/60 MHz
|
|
* based on the speed mode. A fixed delay of 1us ensures that the
|
|
* wait time is sufficient even at the lowest PHY clock frequency
|
|
* (6 MHz), where 1us corresponds to twice the duration of 3 PHY
|
|
* clocks.
|
|
*/
|
|
udelay(1);
|
|
|
|
return 0;
|
|
}
|