// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (c) 2024-2025, Kongyang Liu */ #include #include #include #include #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_FORCEDEVMODE)) 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; }