From: Douglas Anderson <dianders@chromium.org>
To: Minas Harutyunyan <hminas@synopsys.com>,
Felipe Balbi <felipe.balbi@linux.intel.com>,
heiko@sntech.de
Cc: Alan Stern <stern@rowland.harvard.edu>,
Artur Petrosyan <Arthur.Petrosyan@synopsys.com>,
amstan@chromium.org, linux-rockchip@lists.infradead.org,
William Wu <william.wu@rock-chips.com>,
linux-usb@vger.kernel.org, Stefan Wahren <stefan.wahren@i2se.com>,
Randy Li <ayaka@soulik.info>,
zyw@rock-chips.com, mka@chromium.org, ryandcase@chromium.org,
Amelie Delaunay <amelie.delaunay@st.com>,
jwerner@chromium.org, Elaine Zhang <zhangqing@rock-chips.com>,
Douglas Anderson <dianders@chromium.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
linux-kernel@vger.kernel.org
Subject: [PATCH v3 2/3] USB: dwc2: Don't turn off the usbphy in suspend if wakeup is enabled
Date: Mon, 20 May 2019 10:56:04 -0700 [thread overview]
Message-ID: <20190520175605.2405-3-dianders@chromium.org> (raw)
In-Reply-To: <20190520175605.2405-1-dianders@chromium.org>
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>
---
For relevant prior discussion of this idea, see:
https://lkml.kernel.org/r/1436207224-21849-4-git-send-email-dianders@chromium.org
If I'm reading all the responses correctly folks were of the opinion
that this patch is still the right way to go.
Changes in v3:
- Fixed kbuild test robot error.
Changes in v2:
- Rebased to mainline atop rk3288 remote wake quirk series.
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 b50ec3714fd8..cc918fe7ddb8 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -5578,3 +5578,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.21.0.1020.gf2820cf01a-goog
next prev parent reply other threads:[~2019-05-20 17:56 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-05-20 17:56 [PATCH v3 0/3] USB: dwc2: Allow wakeup from suspend; enable for rk3288-veyron Douglas Anderson
2019-05-20 17:56 ` Douglas Anderson
2019-05-20 17:56 ` [PATCH v3 1/3] Documentation: dt-bindings: Add snps,need-phy-for-wake for dwc2 USB Douglas Anderson
2019-06-13 23:06 ` Rob Herring
2019-06-13 23:06 ` Rob Herring
2019-05-20 17:56 ` Douglas Anderson [this message]
2019-05-20 17:56 ` [PATCH v3 3/3] ARM: dts: rockchip: Allow wakeup from rk3288-veyron's dwc2 USB ports Douglas Anderson
2019-05-20 17:56 ` Douglas Anderson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190520175605.2405-3-dianders@chromium.org \
--to=dianders@chromium.org \
--cc=Arthur.Petrosyan@synopsys.com \
--cc=amelie.delaunay@st.com \
--cc=amstan@chromium.org \
--cc=ayaka@soulik.info \
--cc=felipe.balbi@linux.intel.com \
--cc=gregkh@linuxfoundation.org \
--cc=heiko@sntech.de \
--cc=hminas@synopsys.com \
--cc=jwerner@chromium.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-rockchip@lists.infradead.org \
--cc=linux-usb@vger.kernel.org \
--cc=mka@chromium.org \
--cc=ryandcase@chromium.org \
--cc=stefan.wahren@i2se.com \
--cc=stern@rowland.harvard.edu \
--cc=william.wu@rock-chips.com \
--cc=zhangqing@rock-chips.com \
--cc=zyw@rock-chips.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.