* [PATCH] usb: dwc2: update reset method for host and device mode
@ 2024-03-28 13:14 Kongyang Liu
2024-04-16 8:50 ` Mattijs Korpershoek
2024-04-21 20:42 ` Marek Vasut
0 siblings, 2 replies; 6+ messages in thread
From: Kongyang Liu @ 2024-03-28 13:14 UTC (permalink / raw)
To: u-boot
Cc: Jonas Karlman, Lukasz Majewski, Marek Vasut, Mattijs Korpershoek,
Simon Glass, Teik Heng Chong, Tom Rini
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
--
2.41.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH] usb: dwc2: update reset method for host and device mode
2024-03-28 13:14 [PATCH] usb: dwc2: update reset method for host and device mode Kongyang Liu
@ 2024-04-16 8:50 ` Mattijs Korpershoek
2024-04-16 8:54 ` Mattijs Korpershoek
2024-04-21 20:42 ` Marek Vasut
1 sibling, 1 reply; 6+ messages in thread
From: Mattijs Korpershoek @ 2024-04-16 8:50 UTC (permalink / raw)
To: Kongyang Liu, u-boot
Cc: Jonas Karlman, Lukasz Majewski, Marek Vasut, Simon Glass,
Teik Heng Chong, Tom Rini
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/?id=65dc2e725286106f99c6f6b78e3d9c52c15f3a9c
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 &&
> + (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
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] usb: dwc2: update reset method for host and device mode
2024-04-16 8:50 ` Mattijs Korpershoek
@ 2024-04-16 8:54 ` Mattijs Korpershoek
0 siblings, 0 replies; 6+ messages in thread
From: Mattijs Korpershoek @ 2024-04-16 8:54 UTC (permalink / raw)
To: Marek Vasut, u-boot
Cc: Jonas Karlman, Lukasz Majewski, Simon Glass, Teik Heng Chong,
Tom Rini, Kongyang Liu
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/?id=65dc2e725286106f99c6f6b78e3d9c52c15f3a9c
>
> 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 &&
>> + (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
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] usb: dwc2: update reset method for host and device mode
2024-03-28 13:14 [PATCH] usb: dwc2: update reset method for host and device mode Kongyang Liu
2024-04-16 8:50 ` Mattijs Korpershoek
@ 2024-04-21 20:42 ` Marek Vasut
2024-04-22 5:31 ` Kongyang Liu
1 sibling, 1 reply; 6+ messages in thread
From: Marek Vasut @ 2024-04-21 20:42 UTC (permalink / raw)
To: Kongyang Liu, u-boot
Cc: Jonas Karlman, Lukasz Majewski, Mattijs Korpershoek, Simon Glass,
Teik Heng Chong, Tom Rini
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
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] usb: dwc2: update reset method for host and device mode
2024-04-21 20:42 ` Marek Vasut
@ 2024-04-22 5:31 ` Kongyang Liu
2024-04-22 23:11 ` Marek Vasut
0 siblings, 1 reply; 6+ messages in thread
From: Kongyang Liu @ 2024-04-22 5:31 UTC (permalink / raw)
To: Marek Vasut
Cc: u-boot, Jonas Karlman, Lukasz Majewski, Mattijs Korpershoek,
Simon Glass, Teik Heng Chong, Tom Rini
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
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] usb: dwc2: update reset method for host and device mode
2024-04-22 5:31 ` Kongyang Liu
@ 2024-04-22 23:11 ` Marek Vasut
0 siblings, 0 replies; 6+ messages in thread
From: Marek Vasut @ 2024-04-22 23:11 UTC (permalink / raw)
To: Kongyang Liu
Cc: u-boot, Jonas Karlman, Lukasz Majewski, Mattijs Korpershoek,
Simon Glass, Teik Heng Chong, Tom Rini
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.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2024-04-23 2:55 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-28 13:14 [PATCH] usb: dwc2: update reset method for host and device mode Kongyang Liu
2024-04-16 8:50 ` Mattijs Korpershoek
2024-04-16 8:54 ` Mattijs Korpershoek
2024-04-21 20:42 ` Marek Vasut
2024-04-22 5:31 ` Kongyang Liu
2024-04-22 23:11 ` Marek Vasut
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox