diff options
author | Wu Liang feng <wulf@rock-chips.com> | 2014-12-24 05:22:19 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-01-09 15:25:54 -0500 |
commit | 314b41b16a71ee824f55e2791fcb92997672da37 (patch) | |
tree | a9df21d88f343ee33f85b093a535fcb8780ebe98 /drivers/usb/host/ehci-hcd.c | |
parent | 96e418543d27212d73f2fec76490f833baa27e3b (diff) |
USB: ehci-platform: Support ehci reset after resume quirk
The Rockchip rk3288 EHCI controller doesn't properly detect
the case when a device is removed during suspend. Specifically,
when usb resume from suspend, the EHCI controller maintaining
the USB state (FLAG_CF is 1, Current Connect Status is 1),
but a USB device (like a USB camera on rk3288) may have been
disconnected actually.
Let's add a quirk to force ehci to go into the
usb_root_hub_lost_power() path and reset after resume.
This should generally reset the whole controller and all
ports and initialize everything cleanly again, and bring
the devices back up.
As part of this, rename the "hibernation" paramter of
ehci_resume() to force_reset since hibernation is simply
another case where we can't trust the autodetected status
and need to force a reset of devices.
Signed-off-by: Wu Liang feng <wulf@rock-chips.com>
Reviewed-by: Julius Werner <jwerner@google.com>
Reviewed-by: Doug Anderson <dianders@google.com>
Reviewed-by: Tomasz Figa <tfiga@google.com>
Reviewed-by: Pawel Osciak <posciak@google.com>
Reviewed-by: Sonny Rao <sonnyrao@google.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Tested-by: Doug Anderson <dianders@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 38bfeedae1d0..85e56d1abd23 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -1110,7 +1110,7 @@ int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup) | |||
1110 | EXPORT_SYMBOL_GPL(ehci_suspend); | 1110 | EXPORT_SYMBOL_GPL(ehci_suspend); |
1111 | 1111 | ||
1112 | /* Returns 0 if power was preserved, 1 if power was lost */ | 1112 | /* Returns 0 if power was preserved, 1 if power was lost */ |
1113 | int ehci_resume(struct usb_hcd *hcd, bool hibernated) | 1113 | int ehci_resume(struct usb_hcd *hcd, bool force_reset) |
1114 | { | 1114 | { |
1115 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 1115 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
1116 | 1116 | ||
@@ -1124,12 +1124,12 @@ int ehci_resume(struct usb_hcd *hcd, bool hibernated) | |||
1124 | return 0; /* Controller is dead */ | 1124 | return 0; /* Controller is dead */ |
1125 | 1125 | ||
1126 | /* | 1126 | /* |
1127 | * If CF is still set and we aren't resuming from hibernation | 1127 | * If CF is still set and reset isn't forced |
1128 | * then we maintained suspend power. | 1128 | * then we maintained suspend power. |
1129 | * Just undo the effect of ehci_suspend(). | 1129 | * Just undo the effect of ehci_suspend(). |
1130 | */ | 1130 | */ |
1131 | if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF && | 1131 | if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF && |
1132 | !hibernated) { | 1132 | !force_reset) { |
1133 | int mask = INTR_MASK; | 1133 | int mask = INTR_MASK; |
1134 | 1134 | ||
1135 | ehci_prepare_ports_for_controller_resume(ehci); | 1135 | ehci_prepare_ports_for_controller_resume(ehci); |