[PATCH] usb: dwc2: update reset method for host and device mode
Kongyang Liu
seashell11234455 at gmail.com
Thu Mar 28 14:14:03 CET 2024
Starting from version 4.20a, there has been a change in the reset method.
A new bit, GRSTCTL_CSFTRST_DONE, has been introduced in the GRSTCTL
register to indicate whether the reset has been completed.
Signed-off-by: Kongyang Liu <seashell11234455 at gmail.com>
---
drivers/usb/gadget/dwc2_udc_otg.c | 18 ++++++++++++++++--
drivers/usb/gadget/dwc2_udc_otg_regs.h | 19 +++++++++++++------
drivers/usb/host/dwc2.c | 19 ++++++++++++++++---
drivers/usb/host/dwc2.h | 6 ++++++
4 files changed, 51 insertions(+), 11 deletions(-)
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c
index 27082f5152..d1dd469a0f 100644
--- a/drivers/usb/gadget/dwc2_udc_otg.c
+++ b/drivers/usb/gadget/dwc2_udc_otg.c
@@ -42,7 +42,7 @@
#include <asm/unaligned.h>
#include <asm/io.h>
-#include <asm/mach-types.h>
+#include <wait_bit.h>
#include <power/regulator.h>
@@ -464,12 +464,26 @@ static void reconfig_usbd(struct dwc2_udc *dev)
{
/* 2. Soft-reset OTG Core and then unreset again. */
int i;
- unsigned int uTemp = writel(CORE_SOFT_RESET, ®->grstctl);
+ unsigned int uTemp;
uint32_t dflt_gusbcfg;
uint32_t rx_fifo_sz, tx_fifo_sz, np_tx_fifo_sz;
u32 max_hw_ep;
int pdata_hw_ep;
+ u32 snpsid, greset;
+
+ snpsid = readl(®->gsnpsid);
+ writel(CORE_SOFT_RESET, ®->grstctl);
+ if ((snpsid & SNPSID_VER_MASK) < (SNPSID_VER_420a & SNPSID_VER_MASK)) {
+ wait_for_bit_le32(®->grstctl, CORE_SOFT_RESET, false, 1000, false);
+ } else {
+ wait_for_bit_le32(®->grstctl, CORE_SOFT_RESET_DONE, true, 1000, false);
+ greset = readl(®->grstctl);
+ greset &= ~CORE_SOFT_RESET;
+ greset |= CORE_SOFT_RESET_DONE;
+ writel(greset, ®->grstctl);
+ }
+
debug("Resetting OTG controller\n");
dflt_gusbcfg =
diff --git a/drivers/usb/gadget/dwc2_udc_otg_regs.h b/drivers/usb/gadget/dwc2_udc_otg_regs.h
index 9ca6f42375..b3d9117033 100644
--- a/drivers/usb/gadget/dwc2_udc_otg_regs.h
+++ b/drivers/usb/gadget/dwc2_udc_otg_regs.h
@@ -63,24 +63,26 @@ struct dwc2_usbotg_reg {
u32 gnptxfsiz; /* Non-Periodic Transmit FIFO Size */
u8 res0[12];
u32 ggpio; /* 0x038 */
- u8 res1[20];
+ u8 res1[4];
+ u32 gsnpsid;
+ u8 res2[12];
u32 ghwcfg4; /* User HW Config4 */
- u8 res2[176];
+ u8 res3[176];
u32 dieptxf[15]; /* Device Periodic Transmit FIFO size register */
- u8 res3[1728];
+ u8 res4[1728];
/* Device Configuration */
u32 dcfg; /* Device Configuration Register */
u32 dctl; /* Device Control */
u32 dsts; /* Device Status */
- u8 res4[4];
+ u8 res5[4];
u32 diepmsk; /* Device IN Endpoint Common Interrupt Mask */
u32 doepmsk; /* Device OUT Endpoint Common Interrupt Mask */
u32 daint; /* Device All Endpoints Interrupt */
u32 daintmsk; /* Device All Endpoints Interrupt Mask */
- u8 res5[224];
+ u8 res6[224];
struct dwc2_dev_in_endp in_endp[16];
struct dwc2_dev_out_endp out_endp[16];
- u8 res6[768];
+ u8 res7[768];
struct ep_fifo ep[16];
};
@@ -118,6 +120,7 @@ struct dwc2_usbotg_reg {
/* DWC2_UDC_OTG_GRSTCTL */
#define AHB_MASTER_IDLE (1u<<31)
#define CORE_SOFT_RESET (0x1<<0)
+#define CORE_SOFT_RESET_DONE (0x1<<29)
/* DWC2_UDC_OTG_GINTSTS/DWC2_UDC_OTG_GINTMSK core interrupt register */
#define INT_RESUME (1u<<31)
@@ -285,6 +288,10 @@ struct dwc2_usbotg_reg {
#define DAINT_IN_EP_INT(x) (x << 0)
#define DAINT_OUT_EP_INT(x) (x << 16)
+/* DWC2_UDC_OTG_GSNPSID */
+#define SNPSID_VER_420a 0x4f54420a
+#define SNPSID_VER_MASK 0xffff
+
/* User HW Config4 */
#define GHWCFG4_NUM_IN_EPS_MASK (0xf << 26)
#define GHWCFG4_NUM_IN_EPS_SHIFT 26
diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
index 637eb2dd06..1baeff96ee 100644
--- a/drivers/usb/host/dwc2.c
+++ b/drivers/usb/host/dwc2.c
@@ -159,6 +159,7 @@ static void dwc_otg_core_reset(struct udevice *dev,
struct dwc2_core_regs *regs)
{
int ret;
+ u32 snpsid, greset;
/* Wait for AHB master IDLE state. */
ret = wait_for_bit_le32(®s->grstctl, DWC2_GRSTCTL_AHBIDLE,
@@ -167,9 +168,20 @@ static void dwc_otg_core_reset(struct udevice *dev,
dev_info(dev, "%s: Timeout!\n", __func__);
/* Core Soft Reset */
+ snpsid = readl(®s->gsnpsid);
writel(DWC2_GRSTCTL_CSFTRST, ®s->grstctl);
- ret = wait_for_bit_le32(®s->grstctl, DWC2_GRSTCTL_CSFTRST,
- false, 1000, false);
+ if ((snpsid & DWC2_SNPSID_VER_MASK) < (DWC2_SNPSID_DEVID_VER_420a & DWC2_SNPSID_VER_MASK)) {
+ ret = wait_for_bit_le32(®s->grstctl, DWC2_GRSTCTL_CSFTRST,
+ false, 1000, false);
+ } else {
+ ret = wait_for_bit_le32(®s->grstctl, DWC2_GRSTCTL_GSFTRST_DONE,
+ true, 1000, false);
+ greset = readl(®s->grstctl);
+ greset &= ~DWC2_GRSTCTL_CSFTRST;
+ greset |= DWC2_GRSTCTL_GSFTRST_DONE;
+ writel(greset, ®s->grstctl);
+ }
+
if (ret)
dev_info(dev, "%s: Timeout!\n", __func__);
@@ -1180,7 +1192,8 @@ static int dwc2_init_common(struct udevice *dev, struct dwc2_priv *priv)
snpsid >> 12 & 0xf, snpsid & 0xfff);
if ((snpsid & DWC2_SNPSID_DEVID_MASK) != DWC2_SNPSID_DEVID_VER_2xx &&
- (snpsid & DWC2_SNPSID_DEVID_MASK) != DWC2_SNPSID_DEVID_VER_3xx) {
+ (snpsid & DWC2_SNPSID_DEVID_MASK) != DWC2_SNPSID_DEVID_VER_3xx &&
+ (snpsid & DWC2_SNPSID_DEVID_MASK) != DWC2_SNPSID_DEVID_VER_4xx) {
dev_info(dev, "SNPSID invalid (not DWC2 OTG device): %08x\n",
snpsid);
return -ENODEV;
diff --git a/drivers/usb/host/dwc2.h b/drivers/usb/host/dwc2.h
index 6f022e33a1..e1f0f59b82 100644
--- a/drivers/usb/host/dwc2.h
+++ b/drivers/usb/host/dwc2.h
@@ -207,6 +207,8 @@ struct dwc2_core_regs {
#define DWC2_GRSTCTL_TXFFLSH_OFFSET 5
#define DWC2_GRSTCTL_TXFNUM_MASK (0x1F << 6)
#define DWC2_GRSTCTL_TXFNUM_OFFSET 6
+#define DWC2_GRSTCTL_GSFTRST_DONE (1 << 29)
+#define DWC2_GRSTCTL_GSFTRST_DONE_OFFSET 29
#define DWC2_GRSTCTL_DMAREQ (1 << 30)
#define DWC2_GRSTCTL_DMAREQ_OFFSET 30
#define DWC2_GRSTCTL_AHBIDLE (1 << 31)
@@ -739,8 +741,12 @@ struct dwc2_core_regs {
#define DWC2_PCGCCTL_DEEP_SLEEP_OFFSET 7
#define DWC2_SNPSID_DEVID_VER_2xx (0x4f542 << 12)
#define DWC2_SNPSID_DEVID_VER_3xx (0x4f543 << 12)
+#define DWC2_SNPSID_DEVID_VER_4xx (0x4f544 << 12)
+#define DWC2_SNPSID_DEVID_VER_420a 0x4f54420a
#define DWC2_SNPSID_DEVID_MASK (0xfffff << 12)
#define DWC2_SNPSID_DEVID_OFFSET 12
+#define DWC2_SNPSID_VER_MASK 0xffff
+#define DWC2_SNPSID_VER_OFFSET 0
/* Host controller specific */
#define DWC2_HC_PID_DATA0 0
--
2.41.0
More information about the U-Boot
mailing list