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

2024-04-22 Thread Marek Vasut

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(>gsnpsid);
   writel(DWC2_GRSTCTL_CSFTRST, >grstctl);
- ret = wait_for_bit_le32(>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(>grstctl, DWC2_GRSTCTL_CSFTRST,
+ false, 1000, false);
+ } else {
+ ret = wait_for_bit_le32(>grstctl, DWC2_GRSTCTL_GSFTRST_DONE,
+ true, 1000, false);
+ greset = readl(>grstctl);
+ greset &= ~DWC2_GRSTCTL_CSFTRST;
+ greset |= DWC2_GRSTCTL_GSFTRST_DONE;
+ writel(greset, >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.


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

2024-04-22 Thread Kongyang Liu
Marek Vasut  于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(>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(>gsnpsid);
> >   writel(DWC2_GRSTCTL_CSFTRST, >grstctl);
> > - ret = wait_for_bit_le32(>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(>grstctl, DWC2_GRSTCTL_CSFTRST,
> > + false, 1000, false);
> > + } else {
> > + ret = wait_for_bit_le32(>grstctl, 
> > DWC2_GRSTCTL_GSFTRST_DONE,
> > + true, 1000, false);
> > + greset = readl(>grstctl);
> > + greset &= ~DWC2_GRSTCTL_CSFTRST;
> > + greset |= DWC2_GRSTCTL_GSFTRST_DONE;
> > + writel(greset, >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


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

2024-04-21 Thread Marek Vasut

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(>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(>gsnpsid);
writel(DWC2_GRSTCTL_CSFTRST, >grstctl);
-   ret = wait_for_bit_le32(>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(>grstctl, DWC2_GRSTCTL_CSFTRST,
+   false, 1000, false);
+   } else {
+   ret = wait_for_bit_le32(>grstctl, 
DWC2_GRSTCTL_GSFTRST_DONE,
+   true, 1000, false);
+   greset = readl(>grstctl);
+   greset &= ~DWC2_GRSTCTL_CSFTRST;
+   greset |= DWC2_GRSTCTL_GSFTRST_DONE;
+   writel(greset, >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


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

2024-04-16 Thread Mattijs Korpershoek
On mar., avril 16, 2024 at 10:50, Mattijs Korpershoek 
 wrote:

> Hi Kongyang,
>
> Thank you for the patch.
>
> On jeu., mars 28, 2024 at 21:14, Kongyang Liu  
> 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 
>
> 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 
>
> Also tested on VIM3 that I could use fastboot.
>
> Tested-by: Mattijs Korpershoek  # 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 
>>  #include 
>>  
>> -#include 
>> +#include 
>>  
>>  #include 
>>  
>> @@ -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 0x
>> +
>>  /* User HW Config4 */
>>  #define GHWCFG4_NUM_IN_EPS_MASK (0xf << 26)
>>  #define GHWCFG4_NUM_IN_EPS_SHIFT

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

2024-04-16 Thread Mattijs Korpershoek
Hi Kongyang,

Thank you for the patch.

On jeu., mars 28, 2024 at 21:14, Kongyang Liu  
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 

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 

Also tested on VIM3 that I could use fastboot.

Tested-by: Mattijs Korpershoek  # 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 
>  #include 
>  
> -#include 
> +#include 
>  
>  #include 
>  
> @@ -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  0x
> +
>  /* 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)
>  {
>