[PATCH] usb: dwc2: update reset method for host and device mode

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@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

Hi Kongyang,
Thank you for the patch.
On jeu., mars 28, 2024 at 21:14, Kongyang Liu seashell11234455@gmail.com wrote:
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@gmail.com
I've compared this with the equivalent Linux patch found here: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
Reviewed-by: Mattijs Korpershoek mkorpershoek@baylibre.com
Also tested on VIM3 that I could use fastboot.
Tested-by: Mattijs Korpershoek mkorpershoek@baylibre.com # on vim3
I will add the linux link in the commit message when applying. Please consider adding it yourself if you receive review comments that require sending a v2.
Thanks Mattijs
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 &&
dev_info(dev, "SNPSID invalid (not DWC2 OTG device): %08x\n", snpsid); return -ENODEV;(snpsid & DWC2_SNPSID_DEVID_MASK) != DWC2_SNPSID_DEVID_VER_4xx) {
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

On mar., avril 16, 2024 at 10:50, Mattijs Korpershoek mkorpershoek@baylibre.com wrote:
Hi Kongyang,
Thank you for the patch.
On jeu., mars 28, 2024 at 21:14, Kongyang Liu seashell11234455@gmail.com wrote:
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@gmail.com
I've compared this with the equivalent Linux patch found here: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
Reviewed-by: Mattijs Korpershoek mkorpershoek@baylibre.com
Also tested on VIM3 that I could use fastboot.
Tested-by: Mattijs Korpershoek mkorpershoek@baylibre.com # on vim3
I will add the linux link in the commit message when applying. Please consider adding it yourself if you receive review comments that require sending a v2.
Just noticed that this also touches the host part of the driver.
Marek, do you want to review/pick this up, or can this go through u-boot-dfu ?
Thanks Mattijs
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 &&
dev_info(dev, "SNPSID invalid (not DWC2 OTG device): %08x\n", snpsid); return -ENODEV;(snpsid & DWC2_SNPSID_DEVID_MASK) != DWC2_SNPSID_DEVID_VER_4xx) {
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

On 3/28/24 2:14 PM, Kongyang Liu wrote:
[...]
@@ -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;
Drop this newline
- u32 snpsid, greset;
- snpsid = readl(®->gsnpsid);
- writel(CORE_SOFT_RESET, ®->grstctl);
- if ((snpsid & SNPSID_VER_MASK) < (SNPSID_VER_420a & SNPSID_VER_MASK)) {
Can you use FIELD_GET()/FIELD_PREP() for this ?
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);
clrsetbits_le32()
[...]
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);
Same comments as above.
Maybe this should be pulled into dedicated function to avoid duplication?
- }
- 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) {
Try FIELD_GET/FIELD_PREP

Marek Vasut marex@denx.de 于2024年4月22日周一 04:45写道:
On 3/28/24 2:14 PM, Kongyang Liu wrote:
[...]
@@ -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;
Drop this newline
I will fix it
u32 snpsid, greset;
snpsid = readl(®->gsnpsid);
writel(CORE_SOFT_RESET, ®->grstctl);
if ((snpsid & SNPSID_VER_MASK) < (SNPSID_VER_420a & SNPSID_VER_MASK)) {
Can you use FIELD_GET()/FIELD_PREP() for this ?
I will fix it
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);
clrsetbits_le32()
I will fix it
[...]
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);
Same comments as above.
Maybe this should be pulled into dedicated function to avoid duplication?
For U-Boot, the dwc2 USB driver is split into two modules: host and gadget. Each has its own register definitions and definitions for register bits, which makes it difficult to extract a single function. Moreover, deciding where to place this function is also an issue.
}
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) {
Try FIELD_GET/FIELD_PREP
I will fix it
Best regards Kongyang Liu

On 4/22/24 7:31 AM, Kongyang Liu wrote:
[...]
@@ -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);
Same comments as above.
Maybe this should be pulled into dedicated function to avoid duplication?
For U-Boot, the dwc2 USB driver is split into two modules: host and gadget. Each has its own register definitions and definitions for register bits, which makes it difficult to extract a single function. Moreover, deciding where to place this function is also an issue.
There is drivers/usb/common/ for such code. The register macros can probably be unified into a single header too.
participants (3)
-
Kongyang Liu
-
Marek Vasut
-
Mattijs Korpershoek