diff mbox series

[v2] usb: dwc3: Trigger a GCTL soft reset when switching modes in DRD

Message ID 20201021224619.20796-1-john.stultz@linaro.org (mailing list archive)
State Superseded
Headers show
Series [v2] usb: dwc3: Trigger a GCTL soft reset when switching modes in DRD | expand

Commit Message

John Stultz Oct. 21, 2020, 10:46 p.m. UTC
From: Yu Chen <chenyu56@huawei.com>

With the current dwc3 code on the HiKey960 we often see the
COREIDLE flag get stuck off in __dwc3_gadget_start(), which
seems to prevent the reset irq and causes the USB gadget to
fail to initialize.

We had seen occasional initialization failures with older
kernels but with recent 5.x era kernels it seemed to be becoming
much more common, so I dug back through some older trees and
realized I dropped this quirk from Yu Chen during upstreaming
as I couldn't provide a proper rational for it and it didn't
seem to be necessary. I now realize I was wrong.

After resubmitting the quirk Thinh Nguyen pointed out that it
shouldn't be a quirk and it is actually mentioned in the
programming guide that it should be done when switching modes
in DRD.

So, to avoid these !COREIDLE lockups seen on HiKey960, this
patch issues GCTL soft reset when switching modes if the
controller is in DRD mode.

Cc: Felipe Balbi <balbi@kernel.org>
Cc: Tejas Joglekar <tejas.joglekar@synopsys.com>
Cc: Yang Fei <fei.yang@intel.com>
Cc: YongQin Liu <yongqin.liu@linaro.org>
Cc: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
Cc: Thinh Nguyen <thinhn@synopsys.com>
Cc: Jun Li <lijun.kernel@gmail.com>
Cc: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org
Signed-off-by: Yu Chen <chenyu56@huawei.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
v2:
* Rework to always call the GCTL soft reset in DRD mode,
  rather then using a quirk as suggested by Thinh Nguyen

---
 drivers/usb/dwc3/core.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

Comments

Thinh Nguyen Oct. 22, 2020, 1:17 a.m. UTC | #1
John Stultz wrote:
> From: Yu Chen <chenyu56@huawei.com>
>
> With the current dwc3 code on the HiKey960 we often see the
> COREIDLE flag get stuck off in __dwc3_gadget_start(), which
> seems to prevent the reset irq and causes the USB gadget to
> fail to initialize.
>
> We had seen occasional initialization failures with older
> kernels but with recent 5.x era kernels it seemed to be becoming
> much more common, so I dug back through some older trees and
> realized I dropped this quirk from Yu Chen during upstreaming
> as I couldn't provide a proper rational for it and it didn't
> seem to be necessary. I now realize I was wrong.
>
> After resubmitting the quirk Thinh Nguyen pointed out that it
> shouldn't be a quirk and it is actually mentioned in the
> programming guide that it should be done when switching modes
> in DRD.
>
> So, to avoid these !COREIDLE lockups seen on HiKey960, this
> patch issues GCTL soft reset when switching modes if the
> controller is in DRD mode.
>
> Cc: Felipe Balbi <balbi@kernel.org>
> Cc: Tejas Joglekar <tejas.joglekar@synopsys.com>
> Cc: Yang Fei <fei.yang@intel.com>
> Cc: YongQin Liu <yongqin.liu@linaro.org>
> Cc: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
> Cc: Thinh Nguyen <thinhn@synopsys.com>
> Cc: Jun Li <lijun.kernel@gmail.com>
> Cc: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: linux-usb@vger.kernel.org
> Signed-off-by: Yu Chen <chenyu56@huawei.com>
> Signed-off-by: John Stultz <john.stultz@linaro.org>
> ---
> v2:
> * Rework to always call the GCTL soft reset in DRD mode,
>   rather then using a quirk as suggested by Thinh Nguyen
>
> ---
>  drivers/usb/dwc3/core.c | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
>
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index bdf0925da6b6..ca94f3a2a83c 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -114,10 +114,24 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
>  	dwc->current_dr_role = mode;
>  }
>  
> +static void dwc3_gctl_core_soft_reset(struct dwc3 *dwc)
> +{
> +	int reg;
> +
> +	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
> +	reg |= (DWC3_GCTL_CORESOFTRESET);
> +	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
> +
> +	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
> +	reg &= ~(DWC3_GCTL_CORESOFTRESET);
> +	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
> +}
> +
>  static void __dwc3_set_mode(struct work_struct *work)
>  {
>  	struct dwc3 *dwc = work_to_dwc(work);
>  	unsigned long flags;
> +	int hw_mode;
>  	int ret;
>  	u32 reg;
>  
> @@ -154,6 +168,11 @@ static void __dwc3_set_mode(struct work_struct *work)
>  		break;
>  	}
>  
> +	/* Execute a GCTL Core Soft Reset when switch mode in DRD*/
> +	hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
> +	if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD)
> +		dwc3_gctl_core_soft_reset(dwc);
> +

I think this should be done inside the spin_lock.

>  	spin_lock_irqsave(&dwc->lock, flags);
>  
>  	dwc3_set_prtcap(dwc, dwc->desired_dr_role);

The DRD mode change sequence should be like this if we want to switch
from host -> device according to the programming guide (for all DRD IPs):
1. Reset controller with GCTL.CoreSoftReset
2. Set GCTL.PrtCapDir(device)
3. Soft reset with DCTL.CSftRst
4. Then follow up with the initializing registers sequence

However, from code review, with this patch, it follows this sequence:
a. Soft reset with DCTL.CSftRst on driver probe
b. Reset controller with GCTL.CoreSoftReset
c. Set GCTL.PrtCapDir(device)
d. < missing DCTL.CSftRst >
e. Then follow up with initializing registers sequence

It may work, but it doesn't follow the programming guide.

For device -> host, it should be fine because the xHCI driver will do
USBCMD.HCRST during initialization.

BR,
Thinh
John Stultz Oct. 22, 2020, 2:21 a.m. UTC | #2
On Wed, Oct 21, 2020 at 6:17 PM Thinh Nguyen <Thinh.Nguyen@synopsys.com> wrote:
>
> John Stultz wrote:
> > From: Yu Chen <chenyu56@huawei.com>
> >
> > With the current dwc3 code on the HiKey960 we often see the
> > COREIDLE flag get stuck off in __dwc3_gadget_start(), which
> > seems to prevent the reset irq and causes the USB gadget to
> > fail to initialize.
> >
> > We had seen occasional initialization failures with older
> > kernels but with recent 5.x era kernels it seemed to be becoming
> > much more common, so I dug back through some older trees and
> > realized I dropped this quirk from Yu Chen during upstreaming
> > as I couldn't provide a proper rational for it and it didn't
> > seem to be necessary. I now realize I was wrong.
> >
> > After resubmitting the quirk Thinh Nguyen pointed out that it
> > shouldn't be a quirk and it is actually mentioned in the
> > programming guide that it should be done when switching modes
> > in DRD.
> >
> > So, to avoid these !COREIDLE lockups seen on HiKey960, this
> > patch issues GCTL soft reset when switching modes if the
> > controller is in DRD mode.
> >
> > Cc: Felipe Balbi <balbi@kernel.org>
> > Cc: Tejas Joglekar <tejas.joglekar@synopsys.com>
> > Cc: Yang Fei <fei.yang@intel.com>
> > Cc: YongQin Liu <yongqin.liu@linaro.org>
> > Cc: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
> > Cc: Thinh Nguyen <thinhn@synopsys.com>
> > Cc: Jun Li <lijun.kernel@gmail.com>
> > Cc: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > Cc: linux-usb@vger.kernel.org
> > Signed-off-by: Yu Chen <chenyu56@huawei.com>
> > Signed-off-by: John Stultz <john.stultz@linaro.org>
> > ---
> > v2:
> > * Rework to always call the GCTL soft reset in DRD mode,
> >   rather then using a quirk as suggested by Thinh Nguyen
> >
> > ---
> >  drivers/usb/dwc3/core.c | 19 +++++++++++++++++++
> >  1 file changed, 19 insertions(+)
> >
> > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> > index bdf0925da6b6..ca94f3a2a83c 100644
> > --- a/drivers/usb/dwc3/core.c
> > +++ b/drivers/usb/dwc3/core.c
> > @@ -114,10 +114,24 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
> >       dwc->current_dr_role = mode;
> >  }
> >
> > +static void dwc3_gctl_core_soft_reset(struct dwc3 *dwc)
> > +{
> > +     int reg;
> > +
> > +     reg = dwc3_readl(dwc->regs, DWC3_GCTL);
> > +     reg |= (DWC3_GCTL_CORESOFTRESET);
> > +     dwc3_writel(dwc->regs, DWC3_GCTL, reg);
> > +
> > +     reg = dwc3_readl(dwc->regs, DWC3_GCTL);
> > +     reg &= ~(DWC3_GCTL_CORESOFTRESET);
> > +     dwc3_writel(dwc->regs, DWC3_GCTL, reg);
> > +}
> > +
> >  static void __dwc3_set_mode(struct work_struct *work)
> >  {
> >       struct dwc3 *dwc = work_to_dwc(work);
> >       unsigned long flags;
> > +     int hw_mode;
> >       int ret;
> >       u32 reg;
> >
> > @@ -154,6 +168,11 @@ static void __dwc3_set_mode(struct work_struct *work)
> >               break;
> >       }
> >
> > +     /* Execute a GCTL Core Soft Reset when switch mode in DRD*/
> > +     hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
> > +     if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD)
> > +             dwc3_gctl_core_soft_reset(dwc);
> > +
>
> I think this should be done inside the spin_lock.
>
> >       spin_lock_irqsave(&dwc->lock, flags);
> >
> >       dwc3_set_prtcap(dwc, dwc->desired_dr_role);
>
> The DRD mode change sequence should be like this if we want to switch
> from host -> device according to the programming guide (for all DRD IPs):
> 1. Reset controller with GCTL.CoreSoftReset
> 2. Set GCTL.PrtCapDir(device)
> 3. Soft reset with DCTL.CSftRst
> 4. Then follow up with the initializing registers sequence
>
> However, from code review, with this patch, it follows this sequence:
> a. Soft reset with DCTL.CSftRst on driver probe
> b. Reset controller with GCTL.CoreSoftReset
> c. Set GCTL.PrtCapDir(device)
> d. < missing DCTL.CSftRst >
> e. Then follow up with initializing registers sequence
>
> It may work, but it doesn't follow the programming guide.

Much appreciated for the guidance here. I don't believe I have access
to the programming guide (unless its publicly available somewhere?),
so I'm just working with what I can experimentally figure out and
vendor patch history.

So I'll try to translate the above into the driver as best I can, but
again, I really appreciate your review and corrections here!

thanks
-john
Felipe Balbi Oct. 22, 2020, 7:54 a.m. UTC | #3
Hi,

John Stultz <john.stultz@linaro.org> writes:
> From: Yu Chen <chenyu56@huawei.com>
>
> With the current dwc3 code on the HiKey960 we often see the
> COREIDLE flag get stuck off in __dwc3_gadget_start(), which
> seems to prevent the reset irq and causes the USB gadget to
> fail to initialize.
>
> We had seen occasional initialization failures with older
> kernels but with recent 5.x era kernels it seemed to be becoming
> much more common, so I dug back through some older trees and
> realized I dropped this quirk from Yu Chen during upstreaming
> as I couldn't provide a proper rational for it and it didn't
> seem to be necessary. I now realize I was wrong.

This keeps coming back every few years. It has never been necessary so
far. Why is it necessary now? The only thing we need to do is verify
which registers are shadowed between host and peripheral roles and cache
only those registers.

A full soft reset will take a while and is likely to create other
issues.
Felipe Balbi Oct. 22, 2020, 7:58 a.m. UTC | #4
Hi,

Thinh Nguyen <Thinh.Nguyen@synopsys.com> writes:
> John Stultz wrote:
>>  static void __dwc3_set_mode(struct work_struct *work)
>>  {
>>  	struct dwc3 *dwc = work_to_dwc(work);
>>  	unsigned long flags;
>> +	int hw_mode;
>>  	int ret;
>>  	u32 reg;
>>  
>> @@ -154,6 +168,11 @@ static void __dwc3_set_mode(struct work_struct *work)
>>  		break;
>>  	}
>>  
>> +	/* Execute a GCTL Core Soft Reset when switch mode in DRD*/
>> +	hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
>> +	if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD)
>> +		dwc3_gctl_core_soft_reset(dwc);
>> +
>
> I think this should be done inside the spin_lock.
>
>>  	spin_lock_irqsave(&dwc->lock, flags);
>>  
>>  	dwc3_set_prtcap(dwc, dwc->desired_dr_role);
>
> The DRD mode change sequence should be like this if we want to switch
> from host -> device according to the programming guide (for all DRD IPs):
> 1. Reset controller with GCTL.CoreSoftReset
> 2. Set GCTL.PrtCapDir(device)
> 3. Soft reset with DCTL.CSftRst
> 4. Then follow up with the initializing registers sequence
>
> However, from code review, with this patch, it follows this sequence:
> a. Soft reset with DCTL.CSftRst on driver probe
> b. Reset controller with GCTL.CoreSoftReset
> c. Set GCTL.PrtCapDir(device)
> d. < missing DCTL.CSftRst >
> e. Then follow up with initializing registers sequence
>
> It may work, but it doesn't follow the programming guide.
>
> For device -> host, it should be fine because the xHCI driver will do
> USBCMD.HCRST during initialization.

The only reason why this is needed is because SNPS saves some die area
by mapping some host and peripheral register to the same physical area
in the die. I still think a full soft reset is unnecessary as we have
been running this driver without that soft reset for several years now.
John Stultz Oct. 22, 2020, 7:46 p.m. UTC | #5
On Thu, Oct 22, 2020 at 12:55 AM Felipe Balbi <balbi@kernel.org> wrote:
> John Stultz <john.stultz@linaro.org> writes:
> > From: Yu Chen <chenyu56@huawei.com>
> >
> > With the current dwc3 code on the HiKey960 we often see the
> > COREIDLE flag get stuck off in __dwc3_gadget_start(), which
> > seems to prevent the reset irq and causes the USB gadget to
> > fail to initialize.
> >
> > We had seen occasional initialization failures with older
> > kernels but with recent 5.x era kernels it seemed to be becoming
> > much more common, so I dug back through some older trees and
> > realized I dropped this quirk from Yu Chen during upstreaming
> > as I couldn't provide a proper rational for it and it didn't
> > seem to be necessary. I now realize I was wrong.
>
> This keeps coming back every few years. It has never been necessary so
> far. Why is it necessary now?

Sorry, I'm not totally sure I've got all the context here. If you mean
with regards to the HiKey960, it's because the HiKey960 had a somewhat
complicated vendor patch stack that others and I had been carrying
along and trying to upstream slowly over the last few years.  Since
that process of upstreaming required lots of rework, the patch set
changed over time fixing a number of issues and in this case (by
dropping the quirk) introducing others.

The usb functionality on the board was never perfect.  As I said in
the patch, we saw initialization issues *very* rarely with older
kernels - which I suspected was due to the oddball mux/hub driver that
had to be deeply reworked - so the issue was easy to overlook, except
the frequency of it had grown to be quite noticeable. So now that all
but the dts bits are upstream, I've been trying to spend occasional
free cycles figuring out what's wrong.

That's when I figured out it was the quirk fix I dropped.  But the
good news is so far with it I've not hit any initialization issues
(over a few hundred reboots).

> The only thing we need to do is verify
> which registers are shadowed between host and peripheral roles and cache
> only those registers.

Sorry, could you explain this a bit more? Again, I don't have access
to the hardware docs, so I'm just working with the source and any
vendor patches I can find.

> A full soft reset will take a while and is likely to create other
> issues.

I'm also fine with going back to the quirk approach if you think that
would be lower risk to other devices?

thanks
-john
Felipe Balbi Oct. 23, 2020, 7:02 a.m. UTC | #6
Hi,

John Stultz <john.stultz@linaro.org> writes:
> On Thu, Oct 22, 2020 at 12:55 AM Felipe Balbi <balbi@kernel.org> wrote:
>> John Stultz <john.stultz@linaro.org> writes:
>> > From: Yu Chen <chenyu56@huawei.com>
>> >
>> > With the current dwc3 code on the HiKey960 we often see the
>> > COREIDLE flag get stuck off in __dwc3_gadget_start(), which
>> > seems to prevent the reset irq and causes the USB gadget to
>> > fail to initialize.
>> >
>> > We had seen occasional initialization failures with older
>> > kernels but with recent 5.x era kernels it seemed to be becoming
>> > much more common, so I dug back through some older trees and
>> > realized I dropped this quirk from Yu Chen during upstreaming
>> > as I couldn't provide a proper rational for it and it didn't
>> > seem to be necessary. I now realize I was wrong.
>>
>> This keeps coming back every few years. It has never been necessary so
>> far. Why is it necessary now?
>
> Sorry, I'm not totally sure I've got all the context here. If you mean
> with regards to the HiKey960, it's because the HiKey960 had a somewhat

it's a general DWC3 thing. The databook claims that a soft reset is
necessary, but it turns out it isn't :-)

> complicated vendor patch stack that others and I had been carrying
> along and trying to upstream slowly over the last few years.  Since
> that process of upstreaming required lots of rework, the patch set
> changed over time fixing a number of issues and in this case (by
> dropping the quirk) introducing others.
>
> The usb functionality on the board was never perfect.  As I said in
> the patch, we saw initialization issues *very* rarely with older
> kernels - which I suspected was due to the oddball mux/hub driver that
> had to be deeply reworked - so the issue was easy to overlook, except
> the frequency of it had grown to be quite noticeable. So now that all
> but the dts bits are upstream, I've been trying to spend occasional
> free cycles figuring out what's wrong.
>
> That's when I figured out it was the quirk fix I dropped.  But the
> good news is so far with it I've not hit any initialization issues
> (over a few hundred reboots).

That's good :-)

>> The only thing we need to do is verify
>> which registers are shadowed between host and peripheral roles and cache
>> only those registers.
>
> Sorry, could you explain this a bit more? Again, I don't have access
> to the hardware docs, so I'm just working with the source and any
> vendor patches I can find.

Right, initialize it in gadget mode, then take a register dump (I think
our regdump facility in dwc3's debugfs is enough). Then flip to host
mode and take the same register dump. Now diff them. You'll see that
some registers get overwritten. The reason for that is that physically
some host and peripheral registers map to the same block of memory in
the IP. In other words, the address decoder in the Register File decodes
some addresses to the same physical block of memory. This was done, I
believe, to save die area by reducing gate count.

>> A full soft reset will take a while and is likely to create other
>> issues.
>
> I'm also fine with going back to the quirk approach if you think that
> would be lower risk to other devices?

I think the soft reset can have unexpected side effects here.
Thinh Nguyen Nov. 10, 2020, 11:59 p.m. UTC | #7
Hi,

Felipe Balbi wrote:
> Hi,
>
> Thinh Nguyen <Thinh.Nguyen@synopsys.com> writes:
>> John Stultz wrote:
>>>  static void __dwc3_set_mode(struct work_struct *work)
>>>  {
>>>  	struct dwc3 *dwc = work_to_dwc(work);
>>>  	unsigned long flags;
>>> +	int hw_mode;
>>>  	int ret;
>>>  	u32 reg;
>>>  
>>> @@ -154,6 +168,11 @@ static void __dwc3_set_mode(struct work_struct *work)
>>>  		break;
>>>  	}
>>>  
>>> +	/* Execute a GCTL Core Soft Reset when switch mode in DRD*/
>>> +	hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
>>> +	if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD)
>>> +		dwc3_gctl_core_soft_reset(dwc);
>>> +
>> I think this should be done inside the spin_lock.
>>
>>>  	spin_lock_irqsave(&dwc->lock, flags);
>>>  
>>>  	dwc3_set_prtcap(dwc, dwc->desired_dr_role);
>> The DRD mode change sequence should be like this if we want to switch
>> from host -> device according to the programming guide (for all DRD IPs):
>> 1. Reset controller with GCTL.CoreSoftReset
>> 2. Set GCTL.PrtCapDir(device)
>> 3. Soft reset with DCTL.CSftRst
>> 4. Then follow up with the initializing registers sequence
>>
>> However, from code review, with this patch, it follows this sequence:
>> a. Soft reset with DCTL.CSftRst on driver probe
>> b. Reset controller with GCTL.CoreSoftReset
>> c. Set GCTL.PrtCapDir(device)
>> d. < missing DCTL.CSftRst >
>> e. Then follow up with initializing registers sequence
>>
>> It may work, but it doesn't follow the programming guide.
>>
>> For device -> host, it should be fine because the xHCI driver will do
>> USBCMD.HCRST during initialization.
> The only reason why this is needed is because SNPS saves some die area
> by mapping some host and peripheral register to the same physical area
> in the die. I still think a full soft reset is unnecessary as we have
> been running this driver without that soft reset for several years now.
>

This isn't about whether to use GCTL or DCTL for Core Soft Reset (Please
correct me if I'm wrong because I think this is what you're referring
to). It's about the programming flow when switching modes.

Both step 1 and 3 are required. Because before step 1, if the host was
in normal working mode (e.g. attached to a device), then changing the
PrtCapDir directly to device mode is not advisable and HW may exhibit
unknown behavior. The proper way is to have step 1 through 4 in
sequence. Step 3 is required because some of the HW functionality is
dependent on the PrtCapDir setting before the driver intervention is
required for proper communication with the device. The HW may be in some
intermediate state while changing the PrtCapDir. So, it is required to
reset it to have a fresh start in device mode.

Though we may not see issues even if we eliminate the steps 1 and 3, it
is not advisable and we may have some impact under certain conditions.

One change needs to made for this patch is the driver needs to wait a
certain amount of time before clearing the GCTL.CoreSoftReset for the
PHY clock to start and stabilize.

BR,
Thinh
John Stultz Dec. 12, 2020, 2:04 a.m. UTC | #8
Hey Felipe,
  Sorry for taking so long to get back to this. :(

On Fri, Oct 23, 2020 at 12:02 AM Felipe Balbi <balbi@kernel.org> wrote:
> John Stultz <john.stultz@linaro.org> writes:
> > On Thu, Oct 22, 2020 at 12:55 AM Felipe Balbi <balbi@kernel.org> wrote:
> >> The only thing we need to do is verify
> >> which registers are shadowed between host and peripheral roles and cache
> >> only those registers.
> >
> > Sorry, could you explain this a bit more? Again, I don't have access
> > to the hardware docs, so I'm just working with the source and any
> > vendor patches I can find.
>
> Right, initialize it in gadget mode, then take a register dump (I think
> our regdump facility in dwc3's debugfs is enough). Then flip to host
> mode and take the same register dump. Now diff them. You'll see that
> some registers get overwritten. The reason for that is that physically
> some host and peripheral registers map to the same block of memory in
> the IP. In other words, the address decoder in the Register File decodes
> some addresses to the same physical block of memory. This was done, I
> believe, to save die area by reducing gate count.


Ok. So I've taken regdump in gadget mode, and then in host mode
against upstream, and then again with the patches.
Diffs below (along with all the captured regdump files attached).
Note, the problem when it occurs usually at bootup is that the device
doesn't properly enter gadget mode, so in this case things were
working (not exhibiting the failure) when I captured everything. If
you need a regdump when the problem occurs and the IP gets stuck w/
COREIDLE off, I can capture that too. Let me know

Again, I'm without any hw docs here, so I'm at a little bit of a loss
to understand how to use these diffs and your comment above about the
register file using the same memory to generate an alternative
solution to the patch I have (which is still working great in my
testing/usage).

Also, Thinh's recent feedback suggests it really is a programming flow
issue when switching modes, so I'm not sure how to move this forward.

Let me know what you suggest and I'm happy to take a stab at it.

thanks
-john


--- regdump.gadget      2020-12-12 01:08:56.643246612 +0000
+++ regdump.host        2020-12-12 01:16:40.195105355 +0000
@@ -2,9 +2,9 @@
 GSBUSCFG1 = 0x00000300
 GTXTHRCFG = 0x24080000
 GRXTHRCFG = 0x04400000
-GCTL = 0x00112004
+GCTL = 0x00111004
 GEVTEN = 0x00000000
-GSTS = 0x7e800000
+GSTS = 0x7e800001
 GUCTL1 = 0x0104018a
 GSNPSID = 0x5533300a
 GGPIO = 0x00000000
@@ -22,9 +22,9 @@
 GHWPARAMS5 = 0x04204108
 GHWPARAMS6 = 0x0feaec20
 GHWPARAMS7 = 0x04881e8d
-GDBGFIFOSPACE = 0x00420000
-GDBGLTSSM = 0x41090440
-GDBGBMU = 0x20300000
+GDBGFIFOSPACE = 0x00820000
+GDBGLTSSM = 0x48c90442
+GDBGBMU = 0x21210000
 GPRTBIMAP_HS0 = 0x00000000
 GPRTBIMAP_HS1 = 0x00000000
 GPRTBIMAP_FS0 = 0x00000000
@@ -93,22 +93,22 @@
 GUSB3PIPECTL(13) = 0x00000000
 GUSB3PIPECTL(14) = 0x00000000
 GUSB3PIPECTL(15) = 0x00000000
-GTXFIFOSIZ(0) = 0x00000042
-GTXFIFOSIZ(1) = 0x00420286
-GTXFIFOSIZ(2) = 0x02c80286
-GTXFIFOSIZ(3) = 0x054e0286
-GTXFIFOSIZ(4) = 0x07d40286
-GTXFIFOSIZ(5) = 0x0a5a0286
-GTXFIFOSIZ(6) = 0x0ce00286
-GTXFIFOSIZ(7) = 0x0f660286
-GTXFIFOSIZ(8) = 0x11ec0286
-GTXFIFOSIZ(9) = 0x14720286
-GTXFIFOSIZ(10) = 0x16f80286
-GTXFIFOSIZ(11) = 0x197e0103
-GTXFIFOSIZ(12) = 0x1a810103
-GTXFIFOSIZ(13) = 0x1b840103
-GTXFIFOSIZ(14) = 0x1c870103
-GTXFIFOSIZ(15) = 0x1d8a0103
+GTXFIFOSIZ(0) = 0x00000082
+GTXFIFOSIZ(1) = 0x00820184
+GTXFIFOSIZ(2) = 0x02060286
+GTXFIFOSIZ(3) = 0x048c0000
+GTXFIFOSIZ(4) = 0x048c0000
+GTXFIFOSIZ(5) = 0x048c0000
+GTXFIFOSIZ(6) = 0x048c0000
+GTXFIFOSIZ(7) = 0x048c0000
+GTXFIFOSIZ(8) = 0x048c0000
+GTXFIFOSIZ(9) = 0x048c0000
+GTXFIFOSIZ(10) = 0x048c0000
+GTXFIFOSIZ(11) = 0x048c0000
+GTXFIFOSIZ(12) = 0x048c0000
+GTXFIFOSIZ(13) = 0x048c0000
+GTXFIFOSIZ(14) = 0x048c0000
+GTXFIFOSIZ(15) = 0x048c0000
 GTXFIFOSIZ(16) = 0x00000000
 GTXFIFOSIZ(17) = 0x00000000
 GTXFIFOSIZ(18) = 0x00000000
@@ -125,9 +125,9 @@
 GTXFIFOSIZ(29) = 0x00000000
 GTXFIFOSIZ(30) = 0x00000000
 GTXFIFOSIZ(31) = 0x00000000
-GRXFIFOSIZ(0) = 0x00000285
-GRXFIFOSIZ(1) = 0x02850000
-GRXFIFOSIZ(2) = 0x02850000
+GRXFIFOSIZ(0) = 0x00000084
+GRXFIFOSIZ(1) = 0x00840184
+GRXFIFOSIZ(2) = 0x02080280
 GRXFIFOSIZ(3) = 0x00000000
 GRXFIFOSIZ(4) = 0x00000000
 GRXFIFOSIZ(5) = 0x00000000
@@ -157,148 +157,148 @@
 GRXFIFOSIZ(29) = 0x00000000
 GRXFIFOSIZ(30) = 0x00000000
 GRXFIFOSIZ(31) = 0x00000000
-GEVNTADRLO(0) = 0x41ae8000
+GEVNTADRLO(0) = 0x00000000
 GEVNTADRHI(0) = 0x00000000
-GEVNTSIZ(0) = 0x00001000
+GEVNTSIZ(0) = 0x80000000
 GEVNTCOUNT(0) = 0x00000000
 GHWPARAMS8 = 0x00000fea
 DCFG = 0x0052082c
-DCTL = 0x8cf00a00
-DEVTEN = 0x00001217
-DSTS = 0x00020000
+DCTL = 0x0cf00000
+DEVTEN = 0x00000000
+DSTS = 0x00cf36ec
 DGCMDPAR = 0x00000000
 DGCMD = 0x00000000
-DALEPENA = 0x0000000f
+DALEPENA = 0x00000000
 DEPCMDPAR2(0) = 0x00000000
-DEPCMDPAR1(0) = 0x42dac000
-DEPCMDPAR0(0) = 0x00000000
-DEPCMD(0) = 0x00000006
+DEPCMDPAR1(0) = 0x00000002
+DEPCMDPAR0(0) = 0x41af5001
+DEPCMD(0) = 0x00000000
 DEPCMDPAR2(1) = 0x00000000
-DEPCMDPAR1(1) = 0x42dac000
+DEPCMDPAR1(1) = 0x00000000
 DEPCMDPAR0(1) = 0x00000000
-DEPCMD(1) = 0x00010006
-DEPCMDPAR2(2) = 0x00000000
+DEPCMD(1) = 0x00000000
+DEPCMDPAR2(2) = 0x42dac000
 DEPCMDPAR1(2) = 0x00000000
-DEPCMDPAR0(2) = 0x00000000
-DEPCMD(2) = 0x00020007
+DEPCMDPAR0(2) = 0x0000007f
+DEPCMD(2) = 0x00000000
 DEPCMDPAR2(3) = 0x00000000
 DEPCMDPAR1(3) = 0x00000000
 DEPCMDPAR0(3) = 0x00000000
-DEPCMD(3) = 0x00030007
-DEPCMDPAR2(4) = 0x00000000
+DEPCMD(3) = 0x00000000
+DEPCMDPAR2(4) = 0x43686000
 DEPCMDPAR1(4) = 0x00000000
-DEPCMDPAR0(4) = 0x00000001
-DEPCMD(4) = 0x00050002
+DEPCMDPAR0(4) = 0x43685a48
+DEPCMD(4) = 0x00000000
 DEPCMDPAR2(5) = 0x00000000
 DEPCMDPAR1(5) = 0x00000000
-DEPCMDPAR0(5) = 0x00000001
-DEPCMD(5) = 0x00060002
+DEPCMDPAR0(5) = 0x00000000
+DEPCMD(5) = 0x00000000
 DEPCMDPAR2(6) = 0x00000000
 DEPCMDPAR1(6) = 0x00000000
-DEPCMDPAR0(6) = 0x00000001
-DEPCMD(6) = 0x00070002
+DEPCMDPAR0(6) = 0x00000000
+DEPCMD(6) = 0x00000000
 DEPCMDPAR2(7) = 0x00000000
 DEPCMDPAR1(7) = 0x00000000
-DEPCMDPAR0(7) = 0x00000001
-DEPCMD(7) = 0x00080002
+DEPCMDPAR0(7) = 0x00000000
+DEPCMD(7) = 0x00000000
 DEPCMDPAR2(8) = 0x00000000
 DEPCMDPAR1(8) = 0x00000000
-DEPCMDPAR0(8) = 0x00000001
-DEPCMD(8) = 0x00090002
+DEPCMDPAR0(8) = 0x00000000
+DEPCMD(8) = 0x00000000
 DEPCMDPAR2(9) = 0x00000000
 DEPCMDPAR1(9) = 0x00000000
-DEPCMDPAR0(9) = 0x00000001
-DEPCMD(9) = 0x000a0002
+DEPCMDPAR0(9) = 0x00000000
+DEPCMD(9) = 0x00000000
 DEPCMDPAR2(10) = 0x00000000
 DEPCMDPAR1(10) = 0x00000000
-DEPCMDPAR0(10) = 0x00000001
-DEPCMD(10) = 0x000b0002
+DEPCMDPAR0(10) = 0x00000000
+DEPCMD(10) = 0x00000000
 DEPCMDPAR2(11) = 0x00000000
 DEPCMDPAR1(11) = 0x00000000
-DEPCMDPAR0(11) = 0x00000001
-DEPCMD(11) = 0x000c0002
+DEPCMDPAR0(11) = 0x00000000
+DEPCMD(11) = 0x00000000
 DEPCMDPAR2(12) = 0x00000000
 DEPCMDPAR1(12) = 0x00000000
-DEPCMDPAR0(12) = 0x00000001
-DEPCMD(12) = 0x000d0002
+DEPCMDPAR0(12) = 0x00000000
+DEPCMD(12) = 0x00000000
 DEPCMDPAR2(13) = 0x00000000
 DEPCMDPAR1(13) = 0x00000000
-DEPCMDPAR0(13) = 0x00000001
-DEPCMD(13) = 0x000e0002
+DEPCMDPAR0(13) = 0x00000000
+DEPCMD(13) = 0x00000000
 DEPCMDPAR2(14) = 0x00000000
 DEPCMDPAR1(14) = 0x00000000
-DEPCMDPAR0(14) = 0x00000001
-DEPCMD(14) = 0x000f0002
+DEPCMDPAR0(14) = 0x00000000
+DEPCMD(14) = 0x00000000
 DEPCMDPAR2(15) = 0x00000000
 DEPCMDPAR1(15) = 0x00000000
-DEPCMDPAR0(15) = 0x00000001
-DEPCMD(15) = 0x00100002
+DEPCMDPAR0(15) = 0x00000000
+DEPCMD(15) = 0x00000000
 DEPCMDPAR2(16) = 0x00000000
 DEPCMDPAR1(16) = 0x00000000
-DEPCMDPAR0(16) = 0x00000001
-DEPCMD(16) = 0x00110002
+DEPCMDPAR0(16) = 0x00000000
+DEPCMD(16) = 0x00000000
 DEPCMDPAR2(17) = 0x00000000
 DEPCMDPAR1(17) = 0x00000000
-DEPCMDPAR0(17) = 0x00000001
-DEPCMD(17) = 0x00120002
+DEPCMDPAR0(17) = 0x00000000
+DEPCMD(17) = 0x00000000
 DEPCMDPAR2(18) = 0x00000000
 DEPCMDPAR1(18) = 0x00000000
-DEPCMDPAR0(18) = 0x00000001
-DEPCMD(18) = 0x00130002
+DEPCMDPAR0(18) = 0x00000000
+DEPCMD(18) = 0x00000000
 DEPCMDPAR2(19) = 0x00000000
 DEPCMDPAR1(19) = 0x00000000
-DEPCMDPAR0(19) = 0x00000001
-DEPCMD(19) = 0x00140002
+DEPCMDPAR0(19) = 0x00000000
+DEPCMD(19) = 0x00000000
 DEPCMDPAR2(20) = 0x00000000
 DEPCMDPAR1(20) = 0x00000000
-DEPCMDPAR0(20) = 0x00000001
-DEPCMD(20) = 0x00150002
+DEPCMDPAR0(20) = 0x00000000
+DEPCMD(20) = 0x00000000
 DEPCMDPAR2(21) = 0x00000000
 DEPCMDPAR1(21) = 0x00000000
-DEPCMDPAR0(21) = 0x00000001
-DEPCMD(21) = 0x00160002
+DEPCMDPAR0(21) = 0x00000000
+DEPCMD(21) = 0x00000000
 DEPCMDPAR2(22) = 0x00000000
 DEPCMDPAR1(22) = 0x00000000
-DEPCMDPAR0(22) = 0x00000001
-DEPCMD(22) = 0x00170002
+DEPCMDPAR0(22) = 0x00000000
+DEPCMD(22) = 0x00000000
 DEPCMDPAR2(23) = 0x00000000
 DEPCMDPAR1(23) = 0x00000000
-DEPCMDPAR0(23) = 0x00000001
-DEPCMD(23) = 0x00180002
+DEPCMDPAR0(23) = 0x00000000
+DEPCMD(23) = 0x00000000
 DEPCMDPAR2(24) = 0x00000000
 DEPCMDPAR1(24) = 0x00000000
-DEPCMDPAR0(24) = 0x00000001
-DEPCMD(24) = 0x00190002
+DEPCMDPAR0(24) = 0x00000000
+DEPCMD(24) = 0x00000000
 DEPCMDPAR2(25) = 0x00000000
 DEPCMDPAR1(25) = 0x00000000
-DEPCMDPAR0(25) = 0x00000001
-DEPCMD(25) = 0x001a0002
+DEPCMDPAR0(25) = 0x00000000
+DEPCMD(25) = 0x00000000
 DEPCMDPAR2(26) = 0x00000000
 DEPCMDPAR1(26) = 0x00000000
-DEPCMDPAR0(26) = 0x00000001
-DEPCMD(26) = 0x001b0002
+DEPCMDPAR0(26) = 0x00000000
+DEPCMD(26) = 0x00000000
 DEPCMDPAR2(27) = 0x00000000
 DEPCMDPAR1(27) = 0x00000000
-DEPCMDPAR0(27) = 0x00000001
-DEPCMD(27) = 0x001c0002
+DEPCMDPAR0(27) = 0x00000000
+DEPCMD(27) = 0x00000000
 DEPCMDPAR2(28) = 0x00000000
 DEPCMDPAR1(28) = 0x00000000
-DEPCMDPAR0(28) = 0x00000001
-DEPCMD(28) = 0x001d0002
+DEPCMDPAR0(28) = 0x00000000
+DEPCMD(28) = 0x00000000
 DEPCMDPAR2(29) = 0x00000000
 DEPCMDPAR1(29) = 0x00000000
-DEPCMDPAR0(29) = 0x00000001
-DEPCMD(29) = 0x001e0002
+DEPCMDPAR0(29) = 0x00000000
+DEPCMD(29) = 0x00000000
 DEPCMDPAR2(30) = 0x00000000
 DEPCMDPAR1(30) = 0x00000000
-DEPCMDPAR0(30) = 0x00000001
-DEPCMD(30) = 0x001f0002
+DEPCMDPAR0(30) = 0x00000000
+DEPCMD(30) = 0x00000000
 DEPCMDPAR2(31) = 0x00000000
 DEPCMDPAR1(31) = 0x00000000
-DEPCMDPAR0(31) = 0x00000001
-DEPCMD(31) = 0x00200002
+DEPCMDPAR0(31) = 0x00000000
+DEPCMD(31) = 0x00000000
 OCFG = 0x00000000
 OCTL = 0x00000040
-OEVT = 0x80000000
+OEVT = 0x00000000
 OEVTEN = 0x00000000
-OSTS = 0x0000201f
+OSTS = 0x0000000e


--- regdump.gadget-patched      2020-12-12 00:54:18.310990983 +0000
+++ regdump.host-patched        2020-12-12 00:55:04.566637171 +0000
@@ -2,9 +2,9 @@
 GSBUSCFG1 = 0x00000300
 GTXTHRCFG = 0x24080000
 GRXTHRCFG = 0x04400000
-GCTL = 0x00112004
+GCTL = 0x00111004
 GEVTEN = 0x00000000
-GSTS = 0x7e800000
+GSTS = 0x7e800001
 GUCTL1 = 0x0104018a
 GSNPSID = 0x5533300a
 GGPIO = 0x00000000
@@ -22,9 +22,9 @@
 GHWPARAMS5 = 0x04204108
 GHWPARAMS6 = 0x0feaec20
 GHWPARAMS7 = 0x04881e8d
-GDBGFIFOSPACE = 0x00420000
-GDBGLTSSM = 0x41090440
-GDBGBMU = 0x20300000
+GDBGFIFOSPACE = 0x00820000
+GDBGLTSSM = 0x48c90442
+GDBGBMU = 0x21210000
 GPRTBIMAP_HS0 = 0x00000000
 GPRTBIMAP_HS1 = 0x00000000
 GPRTBIMAP_FS0 = 0x00000000
@@ -93,22 +93,22 @@
 GUSB3PIPECTL(13) = 0x00000000
 GUSB3PIPECTL(14) = 0x00000000
 GUSB3PIPECTL(15) = 0x00000000
-GTXFIFOSIZ(0) = 0x00000042
-GTXFIFOSIZ(1) = 0x00420286
-GTXFIFOSIZ(2) = 0x02c80286
-GTXFIFOSIZ(3) = 0x054e0286
-GTXFIFOSIZ(4) = 0x07d40286
-GTXFIFOSIZ(5) = 0x0a5a0286
-GTXFIFOSIZ(6) = 0x0ce00286
-GTXFIFOSIZ(7) = 0x0f660286
-GTXFIFOSIZ(8) = 0x11ec0286
-GTXFIFOSIZ(9) = 0x14720286
-GTXFIFOSIZ(10) = 0x16f80286
-GTXFIFOSIZ(11) = 0x197e0103
-GTXFIFOSIZ(12) = 0x1a810103
-GTXFIFOSIZ(13) = 0x1b840103
-GTXFIFOSIZ(14) = 0x1c870103
-GTXFIFOSIZ(15) = 0x1d8a0103
+GTXFIFOSIZ(0) = 0x00000082
+GTXFIFOSIZ(1) = 0x00820184
+GTXFIFOSIZ(2) = 0x02060286
+GTXFIFOSIZ(3) = 0x048c0000
+GTXFIFOSIZ(4) = 0x048c0000
+GTXFIFOSIZ(5) = 0x048c0000
+GTXFIFOSIZ(6) = 0x048c0000
+GTXFIFOSIZ(7) = 0x048c0000
+GTXFIFOSIZ(8) = 0x048c0000
+GTXFIFOSIZ(9) = 0x048c0000
+GTXFIFOSIZ(10) = 0x048c0000
+GTXFIFOSIZ(11) = 0x048c0000
+GTXFIFOSIZ(12) = 0x048c0000
+GTXFIFOSIZ(13) = 0x048c0000
+GTXFIFOSIZ(14) = 0x048c0000
+GTXFIFOSIZ(15) = 0x048c0000
 GTXFIFOSIZ(16) = 0x00000000
 GTXFIFOSIZ(17) = 0x00000000
 GTXFIFOSIZ(18) = 0x00000000
@@ -125,9 +125,9 @@
 GTXFIFOSIZ(29) = 0x00000000
 GTXFIFOSIZ(30) = 0x00000000
 GTXFIFOSIZ(31) = 0x00000000
-GRXFIFOSIZ(0) = 0x00000285
-GRXFIFOSIZ(1) = 0x02850000
-GRXFIFOSIZ(2) = 0x02850000
+GRXFIFOSIZ(0) = 0x00000084
+GRXFIFOSIZ(1) = 0x00840184
+GRXFIFOSIZ(2) = 0x02080280
 GRXFIFOSIZ(3) = 0x00000000
 GRXFIFOSIZ(4) = 0x00000000
 GRXFIFOSIZ(5) = 0x00000000
@@ -157,148 +157,148 @@
 GRXFIFOSIZ(29) = 0x00000000
 GRXFIFOSIZ(30) = 0x00000000
 GRXFIFOSIZ(31) = 0x00000000
-GEVNTADRLO(0) = 0x41b55000
+GEVNTADRLO(0) = 0x00000000
 GEVNTADRHI(0) = 0x00000000
-GEVNTSIZ(0) = 0x00001000
+GEVNTSIZ(0) = 0x80000000
 GEVNTCOUNT(0) = 0x00000000
 GHWPARAMS8 = 0x00000fea
 DCFG = 0x0052082c
-DCTL = 0x8cf00a00
-DEVTEN = 0x00001217
-DSTS = 0x0083e818
+DCTL = 0x0cf00000
+DEVTEN = 0x00000000
+DSTS = 0x00cee2ac
 DGCMDPAR = 0x00000000
 DGCMD = 0x00000000
-DALEPENA = 0x0000000f
+DALEPENA = 0x00000000
 DEPCMDPAR2(0) = 0x00000000
-DEPCMDPAR1(0) = 0x425b4000
-DEPCMDPAR0(0) = 0x00000000
-DEPCMD(0) = 0x00000006
+DEPCMDPAR1(0) = 0x00000002
+DEPCMDPAR0(0) = 0x41b65001
+DEPCMD(0) = 0x00000000
 DEPCMDPAR2(1) = 0x00000000
-DEPCMDPAR1(1) = 0x425b4000
+DEPCMDPAR1(1) = 0x00000000
 DEPCMDPAR0(1) = 0x00000000
-DEPCMD(1) = 0x00010006
-DEPCMDPAR2(2) = 0x00000000
+DEPCMD(1) = 0x00000000
+DEPCMDPAR2(2) = 0x425b4000
 DEPCMDPAR1(2) = 0x00000000
-DEPCMDPAR0(2) = 0x00000000
-DEPCMD(2) = 0x00020007
+DEPCMDPAR0(2) = 0x0000007f
+DEPCMD(2) = 0x00000000
 DEPCMDPAR2(3) = 0x00000000
 DEPCMDPAR1(3) = 0x00000000
 DEPCMDPAR0(3) = 0x00000000
-DEPCMD(3) = 0x00030007
-DEPCMDPAR2(4) = 0x00000000
+DEPCMD(3) = 0x00000000
+DEPCMDPAR2(4) = 0x4164c000
 DEPCMDPAR1(4) = 0x00000000
-DEPCMDPAR0(4) = 0x00000001
-DEPCMD(4) = 0x00050002
+DEPCMDPAR0(4) = 0x4339da48
+DEPCMD(4) = 0x00000000
 DEPCMDPAR2(5) = 0x00000000
 DEPCMDPAR1(5) = 0x00000000
-DEPCMDPAR0(5) = 0x00000001
-DEPCMD(5) = 0x00060002
+DEPCMDPAR0(5) = 0x00000000
+DEPCMD(5) = 0x00000000
 DEPCMDPAR2(6) = 0x00000000
 DEPCMDPAR1(6) = 0x00000000
-DEPCMDPAR0(6) = 0x00000001
-DEPCMD(6) = 0x00070002
+DEPCMDPAR0(6) = 0x00000000
+DEPCMD(6) = 0x00000000
 DEPCMDPAR2(7) = 0x00000000
 DEPCMDPAR1(7) = 0x00000000
-DEPCMDPAR0(7) = 0x00000001
-DEPCMD(7) = 0x00080002
+DEPCMDPAR0(7) = 0x00000000
+DEPCMD(7) = 0x00000000
 DEPCMDPAR2(8) = 0x00000000
 DEPCMDPAR1(8) = 0x00000000
-DEPCMDPAR0(8) = 0x00000001
-DEPCMD(8) = 0x00090002
+DEPCMDPAR0(8) = 0x00000000
+DEPCMD(8) = 0x00000000
 DEPCMDPAR2(9) = 0x00000000
 DEPCMDPAR1(9) = 0x00000000
-DEPCMDPAR0(9) = 0x00000001
-DEPCMD(9) = 0x000a0002
+DEPCMDPAR0(9) = 0x00000000
+DEPCMD(9) = 0x00000000
 DEPCMDPAR2(10) = 0x00000000
 DEPCMDPAR1(10) = 0x00000000
-DEPCMDPAR0(10) = 0x00000001
-DEPCMD(10) = 0x000b0002
+DEPCMDPAR0(10) = 0x00000000
+DEPCMD(10) = 0x00000000
 DEPCMDPAR2(11) = 0x00000000
 DEPCMDPAR1(11) = 0x00000000
-DEPCMDPAR0(11) = 0x00000001
-DEPCMD(11) = 0x000c0002
+DEPCMDPAR0(11) = 0x00000000
+DEPCMD(11) = 0x00000000
 DEPCMDPAR2(12) = 0x00000000
 DEPCMDPAR1(12) = 0x00000000
-DEPCMDPAR0(12) = 0x00000001
-DEPCMD(12) = 0x000d0002
+DEPCMDPAR0(12) = 0x00000000
+DEPCMD(12) = 0x00000000
 DEPCMDPAR2(13) = 0x00000000
 DEPCMDPAR1(13) = 0x00000000
-DEPCMDPAR0(13) = 0x00000001
-DEPCMD(13) = 0x000e0002
+DEPCMDPAR0(13) = 0x00000000
+DEPCMD(13) = 0x00000000
 DEPCMDPAR2(14) = 0x00000000
 DEPCMDPAR1(14) = 0x00000000
-DEPCMDPAR0(14) = 0x00000001
-DEPCMD(14) = 0x000f0002
+DEPCMDPAR0(14) = 0x00000000
+DEPCMD(14) = 0x00000000
 DEPCMDPAR2(15) = 0x00000000
 DEPCMDPAR1(15) = 0x00000000
-DEPCMDPAR0(15) = 0x00000001
-DEPCMD(15) = 0x00100002
+DEPCMDPAR0(15) = 0x00000000
+DEPCMD(15) = 0x00000000
 DEPCMDPAR2(16) = 0x00000000
 DEPCMDPAR1(16) = 0x00000000
-DEPCMDPAR0(16) = 0x00000001
-DEPCMD(16) = 0x00110002
+DEPCMDPAR0(16) = 0x00000000
+DEPCMD(16) = 0x00000000
 DEPCMDPAR2(17) = 0x00000000
 DEPCMDPAR1(17) = 0x00000000
-DEPCMDPAR0(17) = 0x00000001
-DEPCMD(17) = 0x00120002
+DEPCMDPAR0(17) = 0x00000000
+DEPCMD(17) = 0x00000000
 DEPCMDPAR2(18) = 0x00000000
 DEPCMDPAR1(18) = 0x00000000
-DEPCMDPAR0(18) = 0x00000001
-DEPCMD(18) = 0x00130002
+DEPCMDPAR0(18) = 0x00000000
+DEPCMD(18) = 0x00000000
 DEPCMDPAR2(19) = 0x00000000
 DEPCMDPAR1(19) = 0x00000000
-DEPCMDPAR0(19) = 0x00000001
-DEPCMD(19) = 0x00140002
+DEPCMDPAR0(19) = 0x00000000
+DEPCMD(19) = 0x00000000
 DEPCMDPAR2(20) = 0x00000000
 DEPCMDPAR1(20) = 0x00000000
-DEPCMDPAR0(20) = 0x00000001
-DEPCMD(20) = 0x00150002
+DEPCMDPAR0(20) = 0x00000000
+DEPCMD(20) = 0x00000000
 DEPCMDPAR2(21) = 0x00000000
 DEPCMDPAR1(21) = 0x00000000
-DEPCMDPAR0(21) = 0x00000001
-DEPCMD(21) = 0x00160002
+DEPCMDPAR0(21) = 0x00000000
+DEPCMD(21) = 0x00000000
 DEPCMDPAR2(22) = 0x00000000
 DEPCMDPAR1(22) = 0x00000000
-DEPCMDPAR0(22) = 0x00000001
-DEPCMD(22) = 0x00170002
+DEPCMDPAR0(22) = 0x00000000
+DEPCMD(22) = 0x00000000
 DEPCMDPAR2(23) = 0x00000000
 DEPCMDPAR1(23) = 0x00000000
-DEPCMDPAR0(23) = 0x00000001
-DEPCMD(23) = 0x00180002
+DEPCMDPAR0(23) = 0x00000000
+DEPCMD(23) = 0x00000000
 DEPCMDPAR2(24) = 0x00000000
 DEPCMDPAR1(24) = 0x00000000
-DEPCMDPAR0(24) = 0x00000001
-DEPCMD(24) = 0x00190002
+DEPCMDPAR0(24) = 0x00000000
+DEPCMD(24) = 0x00000000
 DEPCMDPAR2(25) = 0x00000000
 DEPCMDPAR1(25) = 0x00000000
-DEPCMDPAR0(25) = 0x00000001
-DEPCMD(25) = 0x001a0002
+DEPCMDPAR0(25) = 0x00000000
+DEPCMD(25) = 0x00000000
 DEPCMDPAR2(26) = 0x00000000
 DEPCMDPAR1(26) = 0x00000000
-DEPCMDPAR0(26) = 0x00000001
-DEPCMD(26) = 0x001b0002
+DEPCMDPAR0(26) = 0x00000000
+DEPCMD(26) = 0x00000000
 DEPCMDPAR2(27) = 0x00000000
 DEPCMDPAR1(27) = 0x00000000
-DEPCMDPAR0(27) = 0x00000001
-DEPCMD(27) = 0x001c0002
+DEPCMDPAR0(27) = 0x00000000
+DEPCMD(27) = 0x00000000
 DEPCMDPAR2(28) = 0x00000000
 DEPCMDPAR1(28) = 0x00000000
-DEPCMDPAR0(28) = 0x00000001
-DEPCMD(28) = 0x001d0002
+DEPCMDPAR0(28) = 0x00000000
+DEPCMD(28) = 0x00000000
 DEPCMDPAR2(29) = 0x00000000
 DEPCMDPAR1(29) = 0x00000000
-DEPCMDPAR0(29) = 0x00000001
-DEPCMD(29) = 0x001e0002
+DEPCMDPAR0(29) = 0x00000000
+DEPCMD(29) = 0x00000000
 DEPCMDPAR2(30) = 0x00000000
 DEPCMDPAR1(30) = 0x00000000
-DEPCMDPAR0(30) = 0x00000001
-DEPCMD(30) = 0x001f0002
+DEPCMDPAR0(30) = 0x00000000
+DEPCMD(30) = 0x00000000
 DEPCMDPAR2(31) = 0x00000000
 DEPCMDPAR1(31) = 0x00000000
-DEPCMDPAR0(31) = 0x00000001
-DEPCMD(31) = 0x00200002
+DEPCMDPAR0(31) = 0x00000000
+DEPCMD(31) = 0x00000000
 OCFG = 0x00000000
 OCTL = 0x00000040
-OEVT = 0x80000000
+OEVT = 0x00000000
 OEVTEN = 0x00000000
-OSTS = 0x0000201f
+OSTS = 0x0000000e
diff mbox series

Patch

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index bdf0925da6b6..ca94f3a2a83c 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -114,10 +114,24 @@  void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
 	dwc->current_dr_role = mode;
 }
 
+static void dwc3_gctl_core_soft_reset(struct dwc3 *dwc)
+{
+	int reg;
+
+	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
+	reg |= (DWC3_GCTL_CORESOFTRESET);
+	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
+
+	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
+	reg &= ~(DWC3_GCTL_CORESOFTRESET);
+	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
+}
+
 static void __dwc3_set_mode(struct work_struct *work)
 {
 	struct dwc3 *dwc = work_to_dwc(work);
 	unsigned long flags;
+	int hw_mode;
 	int ret;
 	u32 reg;
 
@@ -154,6 +168,11 @@  static void __dwc3_set_mode(struct work_struct *work)
 		break;
 	}
 
+	/* Execute a GCTL Core Soft Reset when switch mode in DRD*/
+	hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
+	if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD)
+		dwc3_gctl_core_soft_reset(dwc);
+
 	spin_lock_irqsave(&dwc->lock, flags);
 
 	dwc3_set_prtcap(dwc, dwc->desired_dr_role);