Message ID | 1415624983-22413-1-git-send-email-kever.yang@rock-chips.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Kever, On Mon, Nov 10, 2014 at 5:09 AM, Kever Yang <kever.yang@rock-chips.com> wrote: > Hcd controller needs bus_suspend/resume, dwc2 controller make > root hub generate suspend/resume signal with hprt0 register > when work in host mode. > After the root hub enter suspend, we can make controller enter > low power state with PCGCTL register. > > We also update the lx_state for hsotg state. > > This patch has tested on rk3288 with suspend/resume. > > Signed-off-by: Kever Yang <kever.yang@rock-chips.com> > Acked-by: Paul Zimmerman <paulz@synopsys.com> > --- > > Changes in v3: > - remove CONFIG_PM macro for bus_suspend/resume > - add PCGCTL operation for no device connect case > > Changes in v2: > - update commit message > - make dwc2 suspend/resume sourcecode work > > drivers/usb/dwc2/hcd.c | 88 +++++++++++++++++++++++++++++++++++++++++++------- > 1 file changed, 77 insertions(+), 11 deletions(-) I would certainly appreciate confirmation, but my inclination is to NAK this change due to the fact that it regresses functionality. I haven't done any serious review of it, but I've been testing it and it appears to break hotplug. Said another way, I did this: 1. Without this patch, I booted with a USB stick in. It was detected. I unplugged it, waited 5 seconds, and then plugged it back in. The USB stick was redetcted. 2. With this patch, I did the same thing. The USB not redected after plugging it back in. -Doug
Doug, On 11/13/2014 07:22 AM, Doug Anderson wrote: > Kever, > > On Mon, Nov 10, 2014 at 5:09 AM, Kever Yang <kever.yang@rock-chips.com> wrote: >> Hcd controller needs bus_suspend/resume, dwc2 controller make >> root hub generate suspend/resume signal with hprt0 register >> when work in host mode. >> After the root hub enter suspend, we can make controller enter >> low power state with PCGCTL register. >> >> We also update the lx_state for hsotg state. >> >> This patch has tested on rk3288 with suspend/resume. >> >> Signed-off-by: Kever Yang <kever.yang@rock-chips.com> >> Acked-by: Paul Zimmerman <paulz@synopsys.com> >> --- >> >> Changes in v3: >> - remove CONFIG_PM macro for bus_suspend/resume >> - add PCGCTL operation for no device connect case >> >> Changes in v2: >> - update commit message >> - make dwc2 suspend/resume sourcecode work >> >> drivers/usb/dwc2/hcd.c | 88 +++++++++++++++++++++++++++++++++++++++++++------- >> 1 file changed, 77 insertions(+), 11 deletions(-) > I would certainly appreciate confirmation, but my inclination is to > NAK this change due to the fact that it regresses functionality. I > haven't done any serious review of it, but I've been testing it and it > appears to break hotplug. > > Said another way, I did this: > > 1. Without this patch, I booted with a USB stick in. It was detected. > I unplugged it, waited 5 seconds, and then plugged it back in. The > USB stick was redetcted. > > 2. With this patch, I did the same thing. The USB not redected after > plugging it back in. With this patch, the dwc2 hcd/root hub will be auto suspend after device on port is disconnected, and it can't detect the device connect any more, I think that's the problem. I will figure out how to make dwc2 detect the device connect after auto suspend, or disable the auto suspend feature for the dwc2 hcd. - Kever
> I will figure out how to make dwc2 detect the device connect after auto > suspend, > or disable the auto suspend feature for the dwc2 hcd. I think auto-suspend of the root hub device (which is what calls bus_suspend, but is not the host controller device itself) is expected to always happen and not really meant to be disabled. I'm surprised that the controller would fail to come back up, though. Does removing the PCGCTL part make it work? That's the only thing I can think of (but then again the function should immediately return if the port is not in L0, so if there is nothing plugged in the suspend shouldn't really do anything). Another thing might be that the port connect interrupt does not correctly resume the root hub. I don't really know many details about how that works, and it seems pretty complicated. But I can see that all other HCDs seem to call usb_hcd_resume_root_hub() from their interrupt handlers, which we don't. There's also a usb_hcd_start_port_resume() in EHCI which I'm not familiar with, that seems to have been added recently. And finally, it seems that all normal host controllers (UHCI/OHCI/EHCI/XHCI) now do the usb_hcd->uses_new_polling thing (where you're supposed to call hcd_poll_rh_status() from the HCD code)... the old polling code still seems to be in place, but without any relevant driver using I wouldn't be so sure if it's still functional. +Alan who should know HCD/core interactions much better and might have some ideas what the DWC2 driver is still missing right now.
On Thu, 13 Nov 2014, Julius Werner wrote: > Another thing might be that the port connect interrupt does not > correctly resume the root hub. I don't really know many details about > how that works, and it seems pretty complicated. But I can see that > all other HCDs seem to call usb_hcd_resume_root_hub() from their > interrupt handlers, which we don't. There's also a That's how a root hub sends a wakeup request to the kernel. The controller issues an interrupt, and when the HCD's interrupt handler sees that the root hub is suspended, it calls usb_hcd_resume_root_hub() instead of trying to query the hardware (because in general you _can't_ query the hardware while it's in a low-power state). > usb_hcd_start_port_resume() in EHCI which I'm not familiar with, that > seems to have been added recently. usb_hcd_start_port_resume() and usb_hcd_end_port_resume() were added in order to fix a race. We want to avoid suspending a root hub if a downstream suspended device is currently being resumed. The HCD is supposed to call these two routines when it begins and ends resume signalling on any of its ports. This will prevent the core from suspending the root hub while the port resume is in progress. > And finally, it seems that all > normal host controllers (UHCI/OHCI/EHCI/XHCI) now do the > usb_hcd->uses_new_polling thing (where you're supposed to call > hcd_poll_rh_status() from the HCD code)... the old polling code still > seems to be in place, but without any relevant driver using I wouldn't > be so sure if it's still functional. It is functional. The difference between the old and new polling schemes isn't all that big. In the old scheme, the core polls for root hub status changes every 250 ms. With the new scheme, the core doesn't poll -- it relies on the HCD to call usb_hcd_poll_rh_status() whenever there's a status-change interrupt. There's also a flag the HCD can set to ask for polling even if it uses the new scheme. This helps in situations where the root-hub status-change interrupts aren't reliable (for example, if they are edge-triggered rather than level-triggered). > +Alan who should know HCD/core interactions much better and might have > some ideas what the DWC2 driver is still missing right now. I know essentially zero about the DWC2 driver. But I'm happy to help by explaining how the core mechanisms are intended to be used. Alan Stern
> From: jwerner@google.com [mailto:jwerner@google.com] On Behalf Of Julius Werner > Sent: Thursday, November 13, 2014 8:50 PM > > > I will figure out how to make dwc2 detect the device connect after auto > > suspend, > > or disable the auto suspend feature for the dwc2 hcd. > > I think auto-suspend of the root hub device (which is what calls > bus_suspend, but is not the host controller device itself) is expected > to always happen and not really meant to be disabled. I'm surprised > that the controller would fail to come back up, though. Does removing > the PCGCTL part make it work? That's the only thing I can think of > (but then again the function should immediately return if the port is > not in L0, so if there is nothing plugged in the suspend shouldn't > really do anything). Hi guys, I don't have any experience with suspend/resume on the dwc2 controller I'm afraid. One suggestion would be to look at our Synopsys vendor driver to see how it is handled there. That driver is part of the Raspberry Pi upstream kernel, which you can find at https://github.com/raspberrypi/linux. The driver is under drivers/usb/host/dwc_otg. In particular, in dwc_otg_cil_intr.c there is a function named dwc_otg_handle_wakeup_detected_intr() which might be of interest. Unfortunately, that driver code is rather convoluted, so it may be difficult to figure out exactly what the driver is doing.
On 11/14/2014 11:55 PM, Alan Stern wrote: > On Thu, 13 Nov 2014, Julius Werner wrote: > >> Another thing might be that the port connect interrupt does not >> correctly resume the root hub. I don't really know many details about >> how that works, and it seems pretty complicated. But I can see that >> all other HCDs seem to call usb_hcd_resume_root_hub() from their >> interrupt handlers, which we don't. There's also a > That's how a root hub sends a wakeup request to the kernel. The > controller issues an interrupt, and when the HCD's interrupt handler > sees that the root hub is suspended, it calls usb_hcd_resume_root_hub() > instead of trying to query the hardware (because in general you _can't_ > query the hardware while it's in a low-power state). Thanks Alan and Julius, just like what you have mentioned, the dwc2 miss the usb_hcd_resume_root_hub() when root hub is suspended and device connect detected. I have send another patch for that, hope it did the right thing. - Kever
> From: Kever Yang [mailto:kever.yang@rock-chips.com] > Sent: Wednesday, November 12, 2014 4:42 PM > > On 11/13/2014 07:22 AM, Doug Anderson wrote: > > Kever, > > > > On Mon, Nov 10, 2014 at 5:09 AM, Kever Yang <kever.yang@rock-chips.com> wrote: > >> Hcd controller needs bus_suspend/resume, dwc2 controller make > >> root hub generate suspend/resume signal with hprt0 register > >> when work in host mode. > >> After the root hub enter suspend, we can make controller enter > >> low power state with PCGCTL register. > >> > >> We also update the lx_state for hsotg state. > >> > >> This patch has tested on rk3288 with suspend/resume. > >> > >> Signed-off-by: Kever Yang <kever.yang@rock-chips.com> > >> Acked-by: Paul Zimmerman <paulz@synopsys.com> > >> --- > >> > >> Changes in v3: > >> - remove CONFIG_PM macro for bus_suspend/resume > >> - add PCGCTL operation for no device connect case > >> > >> Changes in v2: > >> - update commit message > >> - make dwc2 suspend/resume sourcecode work > >> > >> drivers/usb/dwc2/hcd.c | 88 +++++++++++++++++++++++++++++++++++++++++++------- > >> 1 file changed, 77 insertions(+), 11 deletions(-) > > I would certainly appreciate confirmation, but my inclination is to > > NAK this change due to the fact that it regresses functionality. I > > haven't done any serious review of it, but I've been testing it and it > > appears to break hotplug. > > > > Said another way, I did this: > > > > 1. Without this patch, I booted with a USB stick in. It was detected. > > I unplugged it, waited 5 seconds, and then plugged it back in. The > > USB stick was redetcted. > > > > 2. With this patch, I did the same thing. The USB not redected after > > plugging it back in. > With this patch, the dwc2 hcd/root hub will be auto suspend after device > on port is disconnected, and it can't detect the device connect any more, > I think that's the problem. > > I will figure out how to make dwc2 detect the device connect after auto > suspend, > or disable the auto suspend feature for the dwc2 hcd. Kever, This patch has made it into Linus' kernel as commit 0cf884e819e0, and it breaks disconnect/connect on at least the Altera SOCFPGA platform. I haven't been able to test it on any other platforms. You need to submit a patch to either fix this, or to only enable this feature for the Rock-chip platform. Otherwise the patch has to be reverted.
Hi Paul, I think you need this patch to fix the problem: usb: dwc2: resume root hub when device detect with suspend state https://patchwork.kernel.org/patch/5325111/ Thanks, - Kever On 01/06/2015 09:23 AM, Paul Zimmerman wrote: >> From: Kever Yang [mailto:kever.yang@rock-chips.com] >> Sent: Wednesday, November 12, 2014 4:42 PM >> >> On 11/13/2014 07:22 AM, Doug Anderson wrote: >>> Kever, >>> >>> On Mon, Nov 10, 2014 at 5:09 AM, Kever Yang <kever.yang@rock-chips.com> wrote: >>>> Hcd controller needs bus_suspend/resume, dwc2 controller make >>>> root hub generate suspend/resume signal with hprt0 register >>>> when work in host mode. >>>> After the root hub enter suspend, we can make controller enter >>>> low power state with PCGCTL register. >>>> >>>> We also update the lx_state for hsotg state. >>>> >>>> This patch has tested on rk3288 with suspend/resume. >>>> >>>> Signed-off-by: Kever Yang <kever.yang@rock-chips.com> >>>> Acked-by: Paul Zimmerman <paulz@synopsys.com> >>>> --- >>>> >>>> Changes in v3: >>>> - remove CONFIG_PM macro for bus_suspend/resume >>>> - add PCGCTL operation for no device connect case >>>> >>>> Changes in v2: >>>> - update commit message >>>> - make dwc2 suspend/resume sourcecode work >>>> >>>> drivers/usb/dwc2/hcd.c | 88 +++++++++++++++++++++++++++++++++++++++++++------- >>>> 1 file changed, 77 insertions(+), 11 deletions(-) >>> I would certainly appreciate confirmation, but my inclination is to >>> NAK this change due to the fact that it regresses functionality. I >>> haven't done any serious review of it, but I've been testing it and it >>> appears to break hotplug. >>> >>> Said another way, I did this: >>> >>> 1. Without this patch, I booted with a USB stick in. It was detected. >>> I unplugged it, waited 5 seconds, and then plugged it back in. The >>> USB stick was redetcted. >>> >>> 2. With this patch, I did the same thing. The USB not redected after >>> plugging it back in. >> With this patch, the dwc2 hcd/root hub will be auto suspend after device >> on port is disconnected, and it can't detect the device connect any more, >> I think that's the problem. >> >> I will figure out how to make dwc2 detect the device connect after auto >> suspend, >> or disable the auto suspend feature for the dwc2 hcd. > Kever, > > This patch has made it into Linus' kernel as commit 0cf884e819e0, and > it breaks disconnect/connect on at least the Altera SOCFPGA platform. > I haven't been able to test it on any other platforms. > > You need to submit a patch to either fix this, or to only enable this > feature for the Rock-chip platform. Otherwise the patch has to be > reverted. >
> From: Kever Yang [mailto:kever.yang@rock-chips.com] > Sent: Monday, January 05, 2015 5:42 PM > > Hi Paul, > > I think you need this patch to fix the problem: > > usb: dwc2: resume root hub when device detect with suspend state > https://patchwork.kernel.org/patch/5325111/ > > Thanks, > > - Kever > On 01/06/2015 09:23 AM, Paul Zimmerman wrote: > >> From: Kever Yang [mailto:kever.yang@rock-chips.com] > >> Sent: Wednesday, November 12, 2014 4:42 PM > >> > >> On 11/13/2014 07:22 AM, Doug Anderson wrote: > >>> Kever, > >>> > >>> On Mon, Nov 10, 2014 at 5:09 AM, Kever Yang <kever.yang@rock-chips.com> wrote: > >>>> Hcd controller needs bus_suspend/resume, dwc2 controller make > >>>> root hub generate suspend/resume signal with hprt0 register > >>>> when work in host mode. > >>>> After the root hub enter suspend, we can make controller enter > >>>> low power state with PCGCTL register. > >>>> > >>>> We also update the lx_state for hsotg state. > >>>> > >>>> This patch has tested on rk3288 with suspend/resume. > >>>> > >>>> Signed-off-by: Kever Yang <kever.yang@rock-chips.com> > >>>> Acked-by: Paul Zimmerman <paulz@synopsys.com> > >>>> --- > >>>> > >>>> Changes in v3: > >>>> - remove CONFIG_PM macro for bus_suspend/resume > >>>> - add PCGCTL operation for no device connect case > >>>> > >>>> Changes in v2: > >>>> - update commit message > >>>> - make dwc2 suspend/resume sourcecode work > >>>> > >>>> drivers/usb/dwc2/hcd.c | 88 +++++++++++++++++++++++++++++++++++++++++++------- > >>>> 1 file changed, 77 insertions(+), 11 deletions(-) > >>> I would certainly appreciate confirmation, but my inclination is to > >>> NAK this change due to the fact that it regresses functionality. I > >>> haven't done any serious review of it, but I've been testing it and it > >>> appears to break hotplug. > >>> > >>> Said another way, I did this: > >>> > >>> 1. Without this patch, I booted with a USB stick in. It was detected. > >>> I unplugged it, waited 5 seconds, and then plugged it back in. The > >>> USB stick was redetcted. > >>> > >>> 2. With this patch, I did the same thing. The USB not redected after > >>> plugging it back in. > >> With this patch, the dwc2 hcd/root hub will be auto suspend after device > >> on port is disconnected, and it can't detect the device connect any more, > >> I think that's the problem. > >> > >> I will figure out how to make dwc2 detect the device connect after auto > >> suspend, > >> or disable the auto suspend feature for the dwc2 hcd. > > Kever, > > > > This patch has made it into Linus' kernel as commit 0cf884e819e0, and > > it breaks disconnect/connect on at least the Altera SOCFPGA platform. > > I haven't been able to test it on any other platforms. > > > > You need to submit a patch to either fix this, or to only enable this > > feature for the Rock-chip platform. Otherwise the patch has to be > > reverted. Unfortunately, after applying that patch there is another problem. If I connect a device that causes an overcurrent condition to the root port, then the port is dead after that. No further devices are detected until after I reboot. I tried adding another call to usb_hcd_resume_root_hub() in the "if (hprt0 & HPRT0_OVRCURRCHG)" branch, but then an overcurrent condition causes a continuous stream of these messages: [ 133.348776] dwc2 ffb40000.usb: GetPortStatus wIndex=0x0001 flags=0x00000022 [ 133.355717] dwc2 ffb40000.usb: Overcurrent change detected [ 133.361179] dwc2 ffb40000.usb: HPRT0: 0x00020000 [ 133.365960] dwc2 ffb40000.usb: port_status=00080000 [ 133.373236] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0000 [ 133.380038] hub 1-0:1.0: hub_suspend [ 133.384237] usb usb1: bus auto-suspend, wakeup 1 [ 133.393631] dwc2 ffb40000.usb: DWC OTG HCD HUB STATUS DATA: Root port status changed [ 133.401341] dwc2 ffb40000.usb: port_connect_status_change: 0 [ 133.407157] dwc2 ffb40000.usb: port_reset_change: 0 [ 133.412186] dwc2 ffb40000.usb: port_enable_change: 0 [ 133.417310] dwc2 ffb40000.usb: port_suspend_change: 0 [ 133.422519] dwc2 ffb40000.usb: port_over_current_change: 1 [ 133.428154] usb usb1: suspend raced with wakeup event [ 133.433191] usb usb1: usb auto-resume [ 133.441522] hub 1-0:1.0: hub_resume [ 133.455505] dwc2 ffb40000.usb: GetPortStatus wIndex=0x0001 flags=0x00000022 [ 133.462443] dwc2 ffb40000.usb: Overcurrent change detected [ 133.467907] dwc2 ffb40000.usb: HPRT0: 0x00020000 [ 133.472684] dwc2 ffb40000.usb: port_status=00080000 [ 133.480088] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0000 [ 133.485578] hub 1-0:1.0: hub_suspend [ 133.489157] usb usb1: bus auto-suspend, wakeup 1 [ 133.493768] dwc2 ffb40000.usb: _dwc2_hcd_suspend() [ 133.498540] dwc2 ffb40000.usb: DWC OTG HCD HUB STATUS DATA: Root port status changed [ 133.506257] dwc2 ffb40000.usb: port_connect_status_change: 0 [ 133.512065] dwc2 ffb40000.usb: port_reset_change: 0 [ 133.517102] dwc2 ffb40000.usb: port_enable_change: 0 [ 133.522218] dwc2 ffb40000.usb: port_suspend_change: 0 [ 133.527428] dwc2 ffb40000.usb: port_over_current_change: 1 [ 133.533069] usb usb1: suspend raced with wakeup event [ 133.538098] usb usb1: usb auto-resume [ 133.546439] hub 1-0:1.0: hub_resume Any ideas?
On 01/05/2015 09:02 PM, Paul Zimmerman wrote: >> From: Kever Yang [mailto:kever.yang@rock-chips.com] >> Sent: Monday, January 05, 2015 5:42 PM >> >> Hi Paul, >> >> I think you need this patch to fix the problem: >> >> usb: dwc2: resume root hub when device detect with suspend state >> https://patchwork.kernel.org/patch/5325111/ This patch may have fixed hotplug when a device is connected directly to the USB port, but it does not seem to fix a hotplug when a device is connected to a hub. I booted the board up with a device connected to a 4-port hub, the device is detected, unplug the device from a hub, wait 5-sec, re-plug the device into hub. The device is not detected. >> >> Thanks, >> >> - Kever >> On 01/06/2015 09:23 AM, Paul Zimmerman wrote: >>>> From: Kever Yang [mailto:kever.yang@rock-chips.com] >>>> Sent: Wednesday, November 12, 2014 4:42 PM >>>> >>>> On 11/13/2014 07:22 AM, Doug Anderson wrote: >>>>> Kever, >>>>> >>>>> On Mon, Nov 10, 2014 at 5:09 AM, Kever Yang <kever.yang@rock-chips.com> wrote: >>>>>> Hcd controller needs bus_suspend/resume, dwc2 controller make >>>>>> root hub generate suspend/resume signal with hprt0 register >>>>>> when work in host mode. >>>>>> After the root hub enter suspend, we can make controller enter >>>>>> low power state with PCGCTL register. >>>>>> >>>>>> We also update the lx_state for hsotg state. >>>>>> >>>>>> This patch has tested on rk3288 with suspend/resume. >>>>>> >>>>>> Signed-off-by: Kever Yang <kever.yang@rock-chips.com> >>>>>> Acked-by: Paul Zimmerman <paulz@synopsys.com> >>>>>> --- >>>>>> >>>>>> Changes in v3: >>>>>> - remove CONFIG_PM macro for bus_suspend/resume >>>>>> - add PCGCTL operation for no device connect case >>>>>> >>>>>> Changes in v2: >>>>>> - update commit message >>>>>> - make dwc2 suspend/resume sourcecode work >>>>>> >>>>>> drivers/usb/dwc2/hcd.c | 88 +++++++++++++++++++++++++++++++++++++++++++------- >>>>>> 1 file changed, 77 insertions(+), 11 deletions(-) >>>>> I would certainly appreciate confirmation, but my inclination is to >>>>> NAK this change due to the fact that it regresses functionality. I >>>>> haven't done any serious review of it, but I've been testing it and it >>>>> appears to break hotplug. >>>>> >>>>> Said another way, I did this: >>>>> >>>>> 1. Without this patch, I booted with a USB stick in. It was detected. >>>>> I unplugged it, waited 5 seconds, and then plugged it back in. The >>>>> USB stick was redetcted. >>>>> >>>>> 2. With this patch, I did the same thing. The USB not redected after >>>>> plugging it back in. >>>> With this patch, the dwc2 hcd/root hub will be auto suspend after device >>>> on port is disconnected, and it can't detect the device connect any more, >>>> I think that's the problem. >>>> >>>> I will figure out how to make dwc2 detect the device connect after auto >>>> suspend, >>>> or disable the auto suspend feature for the dwc2 hcd. >>> Kever, >>> >>> This patch has made it into Linus' kernel as commit 0cf884e819e0, and >>> it breaks disconnect/connect on at least the Altera SOCFPGA platform. >>> I haven't been able to test it on any other platforms. >>> >>> You need to submit a patch to either fix this, or to only enable this >>> feature for the Rock-chip platform. Otherwise the patch has to be >>> reverted. > > Unfortunately, after applying that patch there is another problem. If I > connect a device that causes an overcurrent condition to the root port, > then the port is dead after that. No further devices are detected until > after I reboot. > > I tried adding another call to usb_hcd_resume_root_hub() in the > "if (hprt0 & HPRT0_OVRCURRCHG)" branch, but then an overcurrent > condition causes a continuous stream of these messages: > > [ 133.348776] dwc2 ffb40000.usb: GetPortStatus wIndex=0x0001 flags=0x00000022 > [ 133.355717] dwc2 ffb40000.usb: Overcurrent change detected > [ 133.361179] dwc2 ffb40000.usb: HPRT0: 0x00020000 > [ 133.365960] dwc2 ffb40000.usb: port_status=00080000 > [ 133.373236] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0000 > [ 133.380038] hub 1-0:1.0: hub_suspend > [ 133.384237] usb usb1: bus auto-suspend, wakeup 1 > [ 133.393631] dwc2 ffb40000.usb: DWC OTG HCD HUB STATUS DATA: Root port status changed > [ 133.401341] dwc2 ffb40000.usb: port_connect_status_change: 0 > [ 133.407157] dwc2 ffb40000.usb: port_reset_change: 0 > [ 133.412186] dwc2 ffb40000.usb: port_enable_change: 0 > [ 133.417310] dwc2 ffb40000.usb: port_suspend_change: 0 > [ 133.422519] dwc2 ffb40000.usb: port_over_current_change: 1 > [ 133.428154] usb usb1: suspend raced with wakeup event > [ 133.433191] usb usb1: usb auto-resume > [ 133.441522] hub 1-0:1.0: hub_resume > [ 133.455505] dwc2 ffb40000.usb: GetPortStatus wIndex=0x0001 flags=0x00000022 > [ 133.462443] dwc2 ffb40000.usb: Overcurrent change detected > [ 133.467907] dwc2 ffb40000.usb: HPRT0: 0x00020000 > [ 133.472684] dwc2 ffb40000.usb: port_status=00080000 > [ 133.480088] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0000 > [ 133.485578] hub 1-0:1.0: hub_suspend > [ 133.489157] usb usb1: bus auto-suspend, wakeup 1 > [ 133.493768] dwc2 ffb40000.usb: _dwc2_hcd_suspend() > [ 133.498540] dwc2 ffb40000.usb: DWC OTG HCD HUB STATUS DATA: Root port status changed > [ 133.506257] dwc2 ffb40000.usb: port_connect_status_change: 0 > [ 133.512065] dwc2 ffb40000.usb: port_reset_change: 0 > [ 133.517102] dwc2 ffb40000.usb: port_enable_change: 0 > [ 133.522218] dwc2 ffb40000.usb: port_suspend_change: 0 > [ 133.527428] dwc2 ffb40000.usb: port_over_current_change: 1 > [ 133.533069] usb usb1: suspend raced with wakeup event > [ 133.538098] usb usb1: usb auto-resume > [ 133.546439] hub 1-0:1.0: hub_resume > > Any ideas? > Dinh
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 0a0e6f0..7480078 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -1471,6 +1471,30 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex) } } +static void dwc2_port_resume(struct dwc2_hsotg *hsotg) +{ + u32 hprt0; + + /* After clear the Stop PHY clock bit, we should wait for a moment + * for PLL work stable with clock output. + */ + writel(0, hsotg->regs + PCGCTL); + usleep_range(2000, 4000); + + hprt0 = dwc2_read_hprt0(hsotg); + hprt0 |= HPRT0_RES; + writel(hprt0, hsotg->regs + HPRT0); + hprt0 &= ~HPRT0_SUSP; + /* according to USB2.0 Spec 7.1.7.7, the host must send the resume + * signal for at least 20ms + */ + usleep_range(20000, 25000); + + hprt0 &= ~HPRT0_RES; + writel(hprt0, hsotg->regs + HPRT0); + hsotg->lx_state = DWC2_L0; +} + /* Handles hub class-specific requests */ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, u16 wvalue, u16 windex, char *buf, u16 wlength) @@ -1516,17 +1540,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, case USB_PORT_FEAT_SUSPEND: dev_dbg(hsotg->dev, "ClearPortFeature USB_PORT_FEAT_SUSPEND\n"); - writel(0, hsotg->regs + PCGCTL); - usleep_range(20000, 40000); - - hprt0 = dwc2_read_hprt0(hsotg); - hprt0 |= HPRT0_RES; - writel(hprt0, hsotg->regs + HPRT0); - hprt0 &= ~HPRT0_SUSP; - usleep_range(100000, 150000); - - hprt0 &= ~HPRT0_RES; - writel(hprt0, hsotg->regs + HPRT0); + dwc2_port_resume(hsotg); break; case USB_PORT_FEAT_POWER: @@ -2299,6 +2313,55 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd) usleep_range(1000, 3000); } +static int _dwc2_hcd_suspend(struct usb_hcd *hcd) +{ + struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); + u32 hprt0; + + if (!((hsotg->op_state == OTG_STATE_B_HOST) || + (hsotg->op_state == OTG_STATE_A_HOST))) + return 0; + + /* TODO: We get into suspend from 'on' state, maybe we need to do + * something if we get here from DWC2_L1(LPM sleep) state one day. + */ + if (hsotg->lx_state != DWC2_L0) + return 0; + + hprt0 = dwc2_read_hprt0(hsotg); + if (hprt0 & HPRT0_CONNSTS) { + dwc2_port_suspend(hsotg, 1); + } else { + u32 pcgctl = readl(hsotg->regs + PCGCTL); + + pcgctl |= PCGCTL_STOPPCLK; + writel(pcgctl, hsotg->regs + PCGCTL); + } + + return 0; +} + +static int _dwc2_hcd_resume(struct usb_hcd *hcd) +{ + struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); + u32 hprt0; + + if (!((hsotg->op_state == OTG_STATE_B_HOST) || + (hsotg->op_state == OTG_STATE_A_HOST))) + return 0; + + if (hsotg->lx_state != DWC2_L2) + return 0; + + hprt0 = dwc2_read_hprt0(hsotg); + if ((hprt0 & HPRT0_CONNSTS) && (hprt0 & HPRT0_SUSP)) + dwc2_port_resume(hsotg); + else + writel(0, hsotg->regs + PCGCTL); + + return 0; +} + /* Returns the current frame number */ static int _dwc2_hcd_get_frame_number(struct usb_hcd *hcd) { @@ -2669,6 +2732,9 @@ static struct hc_driver dwc2_hc_driver = { .hub_status_data = _dwc2_hcd_hub_status_data, .hub_control = _dwc2_hcd_hub_control, .clear_tt_buffer_complete = _dwc2_hcd_clear_tt_buffer_complete, + + .bus_suspend = _dwc2_hcd_suspend, + .bus_resume = _dwc2_hcd_resume, }; /*