[PATCH v2 7/8] usb: dwc2: Unify flush and reset logic with v4.20a support
Liu Jude
liujh2818 at outlook.com
Thu Jan 2 10:35:13 CET 2025
On 2025/1/1 02:08, Marek Vasut wrote:
On 12/30/24 4:30 AM, Junhui Liu via B4 Relay wrote:
From: Kongyang Liu <seashell11234455 at gmail.com><mailto:seashell11234455 at gmail.com>
This patch merges flush and reset logic for both host and gadget code
into a common set of functions, reducing duplication. It also adds support
for the updated reset logic to compatible with core version since v4.20a.
This patch mainly refers to the patch in the kernel.
link: https://aus01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.kernel.org%2Fpub%2Fscm%2Flinux%2Fkernel%2Fgit%2Ftorvalds%2Flinux.git%2Fcommit%2F%3Fid%3D65dc2e725286106f99c6f6b78e3d9c52c15f3a9c&data=05%7C02%7C%7Cedbf27da9a1549ebe3d208dd29c6cb5a%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C638712655996909017%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=KBItz8KgYeDYVxFxg1ylYACf%2F%2FeGOxNmSVV3Ec9CEiM%3D&reserved=0<https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=65dc2e725286106f99c6f6b78e3d9c52c15f3a9c>
Signed-off-by: Kongyang Liu <seashell11234455 at gmail.com><mailto:seashell11234455 at gmail.com>
Signed-off-by: Junhui Liu <liujh2818 at outlook.com><mailto:liujh2818 at outlook.com>
---
drivers/usb/common/Makefile | 2 +
drivers/usb/common/dwc2_core.c | 103 +++++++++++++++++++++++++++++
drivers/usb/common/dwc2_core.h | 4 ++
drivers/usb/gadget/dwc2_udc_otg.c | 12 +---
drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c | 6 +-
drivers/usb/host/dwc2.c | 80 ++--------------------
6 files changed, 117 insertions(+), 90 deletions(-)
diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile
index 11cc4657a0f403b84b1b8336781e1893d9c7a8f1..73e5bc6d7fdca692276e119911b47db4bf03586a 100644
--- a/drivers/usb/common/Makefile
+++ b/drivers/usb/common/Makefile
@@ -4,6 +4,8 @@
#
obj-$(CONFIG_$(XPL_)DM_USB) += common.o
+obj-$(CONFIG_USB_DWC2) += dwc2_core.o
+obj-$(CONFIG_USB_GADGET_DWC2_OTG) += dwc2_core.o
obj-$(CONFIG_USB_ISP1760) += usb_urb.o
obj-$(CONFIG_USB_MUSB_HOST) += usb_urb.o
obj-$(CONFIG_USB_MUSB_GADGET) += usb_urb.o
diff --git a/drivers/usb/common/dwc2_core.c b/drivers/usb/common/dwc2_core.c
new file mode 100644
index 0000000000000000000000000000000000000000..323326e05d7b0318d883d4a3b8186b812c42f9ca
--- /dev/null
+++ b/drivers/usb/common/dwc2_core.c
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2024, Kongyang Liu <seashell11234455 at gmail.com><mailto:seashell11234455 at 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_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 -EBUSY;
Return -ETIMEDOUT or even better, return ret; to propagate the return value of wait_for_bit_le32() as-is , which is really -ETIMEDOUT if the wait times out.
Okay, I'll modify it to 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 -EBUSY;
DTTO, 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 -EBUSY;
DTTO, 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 -EBUSY;
DTTO, return ret;
+ }
+ }
+
+ return 0;
+}
+
+void 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__);
Should this function return an integer and an error code on failure ?
Sure, I think I will add return ret; here in the next version,
+ 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__);
+
+ /* Wait for 3 PHY Clocks */
+ udelay(1);
+}
+
+void 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__);
+
+ 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__);
+
+ /* Wait for 3 PHY Clocks */
+ udelay(1);
Shouldn't this delay be derived from the PHY clock frequency somehow ?
Are we sure 1us is always sufficient ?
According to the datasheet, the PHY clock can be set to 30/48/60MHz, so
1us is sufficient even for 30MHz. And it is 10 times 3 PHY clocks with
slowest clock, so I think 1us is acceptable.
Best regards,
Junhui Liu
+}
[...]
More information about the U-Boot
mailing list