|
@@ -1,164 +0,0 @@
|
|
|
-From c846b03ff767149d75d4d8dca6d3d4945a21074a Mon Sep 17 00:00:00 2001
|
|
|
-From: Douglas Anderson <dianders@chromium.org>
|
|
|
-Date: Mon, 20 May 2019 10:56:04 -0700
|
|
|
-Subject: [PATCH 51/53] USB: dwc2: Don't turn off the usbphy in suspend if
|
|
|
- wakeup is enabled
|
|
|
-
|
|
|
-If the 'snps,need-phy-for-wake' is set in the device tree then:
|
|
|
-
|
|
|
-- We know that we can wakeup, so call device_set_wakeup_capable().
|
|
|
- The USB core will use this knowledge to enable wakeup by default.
|
|
|
-- We know that we should keep the PHY on during suspend if something
|
|
|
- on our root hub needs remote wakeup. This requires the patch (USB:
|
|
|
- Export usb_wakeup_enabled_descendants()). Note that we don't keep
|
|
|
- the PHY on at suspend time if it's not needed because it would be a
|
|
|
- power draw.
|
|
|
-
|
|
|
-If we later find some users of dwc2 that can support wakeup without
|
|
|
-keeping the PHY on we may want to add a way to call
|
|
|
-device_set_wakeup_capable() without keeping the PHY on at suspend
|
|
|
-time.
|
|
|
-
|
|
|
-Signed-off-by: Douglas Anderson <dianders@chromium.org>
|
|
|
-Signed-off-by: Chris Zhong <zyw@rock-chips.com>
|
|
|
-Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
|
|
|
----
|
|
|
- drivers/usb/dwc2/core.h | 8 ++++++++
|
|
|
- drivers/usb/dwc2/hcd.c | 19 +++++++++++++++++++
|
|
|
- drivers/usb/dwc2/platform.c | 23 ++++++++++++++++++++---
|
|
|
- 3 files changed, 47 insertions(+), 3 deletions(-)
|
|
|
-
|
|
|
-diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
|
|
|
-index 152ac41dfb2d..d08d070a0fb6 100644
|
|
|
---- a/drivers/usb/dwc2/core.h
|
|
|
-+++ b/drivers/usb/dwc2/core.h
|
|
|
-@@ -861,6 +861,9 @@ struct dwc2_hregs_backup {
|
|
|
- * @hibernated: True if core is hibernated
|
|
|
- * @reset_phy_on_wake: Quirk saying that we should assert PHY reset on a
|
|
|
- * remote wakeup.
|
|
|
-+ * @phy_off_for_suspend: Status of whether we turned the PHY off at suspend.
|
|
|
-+ * @need_phy_for_wake: Quirk saying that we should keep the PHY on at
|
|
|
-+ * suspend if we need USB to wake us up.
|
|
|
- * @frame_number: Frame number read from the core. For both device
|
|
|
- * and host modes. The value ranges are from 0
|
|
|
- * to HFNUM_MAX_FRNUM.
|
|
|
-@@ -1049,6 +1052,8 @@ struct dwc2_hsotg {
|
|
|
- unsigned int ll_hw_enabled:1;
|
|
|
- unsigned int hibernated:1;
|
|
|
- unsigned int reset_phy_on_wake:1;
|
|
|
-+ unsigned int need_phy_for_wake:1;
|
|
|
-+ unsigned int phy_off_for_suspend:1;
|
|
|
- u16 frame_number;
|
|
|
-
|
|
|
- struct phy *phy;
|
|
|
-@@ -1438,6 +1443,7 @@ int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg);
|
|
|
- int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg);
|
|
|
- int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg,
|
|
|
- int rem_wakeup, int reset);
|
|
|
-+bool dwc2_host_can_poweroff_phy(struct dwc2_hsotg *dwc2);
|
|
|
- static inline void dwc2_host_schedule_phy_reset(struct dwc2_hsotg *hsotg)
|
|
|
- { schedule_work(&hsotg->phy_reset_work); }
|
|
|
- #else
|
|
|
-@@ -1463,6 +1469,8 @@ static inline int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg)
|
|
|
- static inline int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg,
|
|
|
- int rem_wakeup, int reset)
|
|
|
- { return 0; }
|
|
|
-+static inline bool dwc2_host_can_poweroff_phy(struct dwc2_hsotg *dwc2)
|
|
|
-+{ return false; }
|
|
|
- static inline void dwc2_host_schedule_phy_reset(struct dwc2_hsotg *hsotg) {}
|
|
|
-
|
|
|
- #endif
|
|
|
-diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
|
|
|
-index 2192a2873c7c..4c78a390c958 100644
|
|
|
---- a/drivers/usb/dwc2/hcd.c
|
|
|
-+++ b/drivers/usb/dwc2/hcd.c
|
|
|
-@@ -5587,3 +5587,22 @@ int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup,
|
|
|
- dev_dbg(hsotg->dev, "Host hibernation restore complete\n");
|
|
|
- return ret;
|
|
|
- }
|
|
|
-+
|
|
|
-+bool dwc2_host_can_poweroff_phy(struct dwc2_hsotg *dwc2)
|
|
|
-+{
|
|
|
-+ struct usb_device *root_hub = dwc2_hsotg_to_hcd(dwc2)->self.root_hub;
|
|
|
-+
|
|
|
-+ /* If the controller isn't allowed to wakeup then we can power off. */
|
|
|
-+ if (!device_may_wakeup(dwc2->dev))
|
|
|
-+ return true;
|
|
|
-+
|
|
|
-+ /*
|
|
|
-+ * We don't want to power off the PHY if something under the
|
|
|
-+ * root hub has wakeup enabled.
|
|
|
-+ */
|
|
|
-+ if (usb_wakeup_enabled_descendants(root_hub))
|
|
|
-+ return false;
|
|
|
-+
|
|
|
-+ /* No reason to keep the PHY powered, so allow poweroff */
|
|
|
-+ return true;
|
|
|
-+}
|
|
|
-diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
|
|
|
-index d10a7f8daec3..3e6c3c8a32ff 100644
|
|
|
---- a/drivers/usb/dwc2/platform.c
|
|
|
-+++ b/drivers/usb/dwc2/platform.c
|
|
|
-@@ -447,6 +447,10 @@ static int dwc2_driver_probe(struct platform_device *dev)
|
|
|
- if (retval)
|
|
|
- goto error;
|
|
|
-
|
|
|
-+ hsotg->need_phy_for_wake =
|
|
|
-+ of_property_read_bool(dev->dev.of_node,
|
|
|
-+ "snps,need-phy-for-wake");
|
|
|
-+
|
|
|
- /*
|
|
|
- * Reset before dwc2_get_hwparams() then it could get power-on real
|
|
|
- * reset value form registers.
|
|
|
-@@ -478,6 +482,14 @@ static int dwc2_driver_probe(struct platform_device *dev)
|
|
|
- hsotg->gadget_enabled = 1;
|
|
|
- }
|
|
|
-
|
|
|
-+ /*
|
|
|
-+ * If we need PHY for wakeup we must be wakeup capable.
|
|
|
-+ * When we have a device that can wake without the PHY we
|
|
|
-+ * can adjust this condition.
|
|
|
-+ */
|
|
|
-+ if (hsotg->need_phy_for_wake)
|
|
|
-+ device_set_wakeup_capable(&dev->dev, true);
|
|
|
-+
|
|
|
- hsotg->reset_phy_on_wake =
|
|
|
- of_property_read_bool(dev->dev.of_node,
|
|
|
- "snps,reset-phy-on-wake");
|
|
|
-@@ -516,13 +528,17 @@ static int dwc2_driver_probe(struct platform_device *dev)
|
|
|
- static int __maybe_unused dwc2_suspend(struct device *dev)
|
|
|
- {
|
|
|
- struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
|
|
|
-+ bool is_device_mode = dwc2_is_device_mode(dwc2);
|
|
|
- int ret = 0;
|
|
|
-
|
|
|
-- if (dwc2_is_device_mode(dwc2))
|
|
|
-+ if (is_device_mode)
|
|
|
- dwc2_hsotg_suspend(dwc2);
|
|
|
-
|
|
|
-- if (dwc2->ll_hw_enabled)
|
|
|
-+ if (dwc2->ll_hw_enabled &&
|
|
|
-+ (is_device_mode || dwc2_host_can_poweroff_phy(dwc2))) {
|
|
|
- ret = __dwc2_lowlevel_hw_disable(dwc2);
|
|
|
-+ dwc2->phy_off_for_suspend = true;
|
|
|
-+ }
|
|
|
-
|
|
|
- return ret;
|
|
|
- }
|
|
|
-@@ -532,11 +548,12 @@ static int __maybe_unused dwc2_resume(struct device *dev)
|
|
|
- struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
|
|
|
- int ret = 0;
|
|
|
-
|
|
|
-- if (dwc2->ll_hw_enabled) {
|
|
|
-+ if (dwc2->phy_off_for_suspend && dwc2->ll_hw_enabled) {
|
|
|
- ret = __dwc2_lowlevel_hw_enable(dwc2);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
- }
|
|
|
-+ dwc2->phy_off_for_suspend = false;
|
|
|
-
|
|
|
- if (dwc2_is_device_mode(dwc2))
|
|
|
- ret = dwc2_hsotg_resume(dwc2);
|
|
|
---
|
|
|
-2.11.0
|
|
|
-
|