diff mbox series

[v8,06/13] phy: tegra: xusb: Add sleepwalk and suspend/resume

Message ID 20210325164057.793954-7-thierry.reding@gmail.com
State Changes Requested
Headers show
Series Tegra XHCI controller ELPG support | expand

Commit Message

Thierry Reding March 25, 2021, 4:40 p.m. UTC
From: JC Kuo <jckuo@nvidia.com>

This commit adds sleepwalk/wake and suspend/resume interfaces
to Tegra XUSB PHY driver.

Tegra XUSB host controller driver makes use of sleepwalk functions
to enable/disable sleepwalk circuit which is in always-on partition
and can respond to USB resume signals when controller is not powered.
Sleepwalk can be enabled/disabled for any USB UPHY individually.

  - tegra_xusb_padctl_enable_phy_sleepwalk()
  - tegra_xusb_padctl_disable_phy_sleepwalk()

Tegra XUSB host controller driver makes use of wake functions to
enable/disable/query wake circuit which is in always-on partition
can wake system up when USB resume happens.
Wake circuit can be enabled/disabled for any USB PHY individually.

  - tegra_xusb_padctl_enable_phy_wake()
  - tegra_xusb_padctl_disable_phy_wake()
  - tegra_xusb_padctl_remote_wake_detected()

This commit also adds two system suspend stubs that can be used to
save and restore XUSB PADCTL context during system suspend and
resume.
  - tegra_xusb_padctl_suspend_noirq()
  - tegra_xusb_padctl_resume_noirq()

Signed-off-by: JC Kuo <jckuo@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/phy/tegra/xusb.c       | 82 ++++++++++++++++++++++++++++++++++
 drivers/phy/tegra/xusb.h       |  8 ++++
 include/linux/phy/tegra/xusb.h | 10 ++++-
 3 files changed, 99 insertions(+), 1 deletion(-)

Comments

Vinod Koul March 30, 2021, 2:23 p.m. UTC | #1
On 25-03-21, 17:40, Thierry Reding wrote:
> From: JC Kuo <jckuo@nvidia.com>
> 
> This commit adds sleepwalk/wake and suspend/resume interfaces
> to Tegra XUSB PHY driver.
> 
> Tegra XUSB host controller driver makes use of sleepwalk functions
> to enable/disable sleepwalk circuit which is in always-on partition
> and can respond to USB resume signals when controller is not powered.
> Sleepwalk can be enabled/disabled for any USB UPHY individually.
> 
>   - tegra_xusb_padctl_enable_phy_sleepwalk()
>   - tegra_xusb_padctl_disable_phy_sleepwalk()
> 
> Tegra XUSB host controller driver makes use of wake functions to
> enable/disable/query wake circuit which is in always-on partition
> can wake system up when USB resume happens.
> Wake circuit can be enabled/disabled for any USB PHY individually.
> 
>   - tegra_xusb_padctl_enable_phy_wake()
>   - tegra_xusb_padctl_disable_phy_wake()
>   - tegra_xusb_padctl_remote_wake_detected()
> 
> This commit also adds two system suspend stubs that can be used to
> save and restore XUSB PADCTL context during system suspend and
> resume.
>   - tegra_xusb_padctl_suspend_noirq()
>   - tegra_xusb_padctl_resume_noirq()

Acked-By: Vinod Koul <vkoul@kernel.org>
Thierry Reding March 31, 2021, 4:38 p.m. UTC | #2
On Tue, Mar 30, 2021 at 07:53:32PM +0530, Vinod Koul wrote:
> On 25-03-21, 17:40, Thierry Reding wrote:
> > From: JC Kuo <jckuo@nvidia.com>
> > 
> > This commit adds sleepwalk/wake and suspend/resume interfaces
> > to Tegra XUSB PHY driver.
> > 
> > Tegra XUSB host controller driver makes use of sleepwalk functions
> > to enable/disable sleepwalk circuit which is in always-on partition
> > and can respond to USB resume signals when controller is not powered.
> > Sleepwalk can be enabled/disabled for any USB UPHY individually.
> > 
> >   - tegra_xusb_padctl_enable_phy_sleepwalk()
> >   - tegra_xusb_padctl_disable_phy_sleepwalk()
> > 
> > Tegra XUSB host controller driver makes use of wake functions to
> > enable/disable/query wake circuit which is in always-on partition
> > can wake system up when USB resume happens.
> > Wake circuit can be enabled/disabled for any USB PHY individually.
> > 
> >   - tegra_xusb_padctl_enable_phy_wake()
> >   - tegra_xusb_padctl_disable_phy_wake()
> >   - tegra_xusb_padctl_remote_wake_detected()
> > 
> > This commit also adds two system suspend stubs that can be used to
> > save and restore XUSB PADCTL context during system suspend and
> > resume.
> >   - tegra_xusb_padctl_suspend_noirq()
> >   - tegra_xusb_padctl_resume_noirq()
> 
> Acked-By: Vinod Koul <vkoul@kernel.org>

Thanks. I didn't see an Acked-by on patches 7-9. Did I miss them or did
you not get around to that yet?

Thierry
Thierry Reding March 31, 2021, 4:45 p.m. UTC | #3
On Wed, Mar 31, 2021 at 06:38:39PM +0200, Thierry Reding wrote:
> On Tue, Mar 30, 2021 at 07:53:32PM +0530, Vinod Koul wrote:
> > On 25-03-21, 17:40, Thierry Reding wrote:
> > > From: JC Kuo <jckuo@nvidia.com>
> > > 
> > > This commit adds sleepwalk/wake and suspend/resume interfaces
> > > to Tegra XUSB PHY driver.
> > > 
> > > Tegra XUSB host controller driver makes use of sleepwalk functions
> > > to enable/disable sleepwalk circuit which is in always-on partition
> > > and can respond to USB resume signals when controller is not powered.
> > > Sleepwalk can be enabled/disabled for any USB UPHY individually.
> > > 
> > >   - tegra_xusb_padctl_enable_phy_sleepwalk()
> > >   - tegra_xusb_padctl_disable_phy_sleepwalk()
> > > 
> > > Tegra XUSB host controller driver makes use of wake functions to
> > > enable/disable/query wake circuit which is in always-on partition
> > > can wake system up when USB resume happens.
> > > Wake circuit can be enabled/disabled for any USB PHY individually.
> > > 
> > >   - tegra_xusb_padctl_enable_phy_wake()
> > >   - tegra_xusb_padctl_disable_phy_wake()
> > >   - tegra_xusb_padctl_remote_wake_detected()
> > > 
> > > This commit also adds two system suspend stubs that can be used to
> > > save and restore XUSB PADCTL context during system suspend and
> > > resume.
> > >   - tegra_xusb_padctl_suspend_noirq()
> > >   - tegra_xusb_padctl_resume_noirq()
> > 
> > Acked-By: Vinod Koul <vkoul@kernel.org>
> 
> Thanks. I didn't see an Acked-by on patches 7-9. Did I miss them or did
> you not get around to that yet?

Patch 10 is also missing an Acked-by, I think.

Thierry
Thierry Reding March 31, 2021, 4:52 p.m. UTC | #4
On Wed, Mar 31, 2021 at 06:45:25PM +0200, Thierry Reding wrote:
> On Wed, Mar 31, 2021 at 06:38:39PM +0200, Thierry Reding wrote:
> > On Tue, Mar 30, 2021 at 07:53:32PM +0530, Vinod Koul wrote:
> > > On 25-03-21, 17:40, Thierry Reding wrote:
> > > > From: JC Kuo <jckuo@nvidia.com>
> > > > 
> > > > This commit adds sleepwalk/wake and suspend/resume interfaces
> > > > to Tegra XUSB PHY driver.
> > > > 
> > > > Tegra XUSB host controller driver makes use of sleepwalk functions
> > > > to enable/disable sleepwalk circuit which is in always-on partition
> > > > and can respond to USB resume signals when controller is not powered.
> > > > Sleepwalk can be enabled/disabled for any USB UPHY individually.
> > > > 
> > > >   - tegra_xusb_padctl_enable_phy_sleepwalk()
> > > >   - tegra_xusb_padctl_disable_phy_sleepwalk()
> > > > 
> > > > Tegra XUSB host controller driver makes use of wake functions to
> > > > enable/disable/query wake circuit which is in always-on partition
> > > > can wake system up when USB resume happens.
> > > > Wake circuit can be enabled/disabled for any USB PHY individually.
> > > > 
> > > >   - tegra_xusb_padctl_enable_phy_wake()
> > > >   - tegra_xusb_padctl_disable_phy_wake()
> > > >   - tegra_xusb_padctl_remote_wake_detected()
> > > > 
> > > > This commit also adds two system suspend stubs that can be used to
> > > > save and restore XUSB PADCTL context during system suspend and
> > > > resume.
> > > >   - tegra_xusb_padctl_suspend_noirq()
> > > >   - tegra_xusb_padctl_resume_noirq()
> > > 
> > > Acked-By: Vinod Koul <vkoul@kernel.org>
> > 
> > Thanks. I didn't see an Acked-by on patches 7-9. Did I miss them or did
> > you not get around to that yet?
> 
> Patch 10 is also missing an Acked-by, I think.

Hang on, I've mixed these up. Patches 7 and 8 were for soc/tegra and
dt-bindings, respectively. Patches 9-11 were for the PHY subsystem, so
you may have missed them because they were not contiguous within the
series. The reason is that patch 9 depends on patch 7, though in
retrospect it might have been clearer to put 7 and 8 before the whole
set of the PHY patches.

Apologies for that. Could you take a look at 9 through 11? 9 and 11 are
pretty big, but it's really just the Tegra210 and Tegra186 specific
implementations of the functionality introduced in this patch.

I've also fixed up the modular build error that Nathan had pointed out
on patch 9. Let me know if you want me to resend that.

Thierry
diff mbox series

Patch

diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
index a34d304677bb..0aadac678191 100644
--- a/drivers/phy/tegra/xusb.c
+++ b/drivers/phy/tegra/xusb.c
@@ -1273,10 +1273,36 @@  static int tegra_xusb_padctl_remove(struct platform_device *pdev)
 	return err;
 }
 
+static int tegra_xusb_padctl_suspend_noirq(struct device *dev)
+{
+	struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev);
+
+	if (padctl->soc && padctl->soc->ops && padctl->soc->ops->suspend_noirq)
+		return padctl->soc->ops->suspend_noirq(padctl);
+
+	return 0;
+}
+
+static int tegra_xusb_padctl_resume_noirq(struct device *dev)
+{
+	struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev);
+
+	if (padctl->soc && padctl->soc->ops && padctl->soc->ops->resume_noirq)
+		return padctl->soc->ops->resume_noirq(padctl);
+
+	return 0;
+}
+
+static const struct dev_pm_ops tegra_xusb_padctl_pm_ops = {
+	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(tegra_xusb_padctl_suspend_noirq,
+				      tegra_xusb_padctl_resume_noirq)
+};
+
 static struct platform_driver tegra_xusb_padctl_driver = {
 	.driver = {
 		.name = "tegra-xusb-padctl",
 		.of_match_table = tegra_xusb_padctl_of_match,
+		.pm = &tegra_xusb_padctl_pm_ops,
 	},
 	.probe = tegra_xusb_padctl_probe,
 	.remove = tegra_xusb_padctl_remove,
@@ -1343,6 +1369,62 @@  int tegra_xusb_padctl_hsic_set_idle(struct tegra_xusb_padctl *padctl,
 }
 EXPORT_SYMBOL_GPL(tegra_xusb_padctl_hsic_set_idle);
 
+int tegra_xusb_padctl_enable_phy_sleepwalk(struct tegra_xusb_padctl *padctl, struct phy *phy,
+					   enum usb_device_speed speed)
+{
+	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
+
+	if (lane->pad->ops->enable_phy_sleepwalk)
+		return lane->pad->ops->enable_phy_sleepwalk(lane, speed);
+
+	return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL_GPL(tegra_xusb_padctl_enable_phy_sleepwalk);
+
+int tegra_xusb_padctl_disable_phy_sleepwalk(struct tegra_xusb_padctl *padctl, struct phy *phy)
+{
+	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
+
+	if (lane->pad->ops->disable_phy_sleepwalk)
+		return lane->pad->ops->disable_phy_sleepwalk(lane);
+
+	return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL_GPL(tegra_xusb_padctl_disable_phy_sleepwalk);
+
+int tegra_xusb_padctl_enable_phy_wake(struct tegra_xusb_padctl *padctl, struct phy *phy)
+{
+	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
+
+	if (lane->pad->ops->enable_phy_wake)
+		return lane->pad->ops->enable_phy_wake(lane);
+
+	return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL_GPL(tegra_xusb_padctl_enable_phy_wake);
+
+int tegra_xusb_padctl_disable_phy_wake(struct tegra_xusb_padctl *padctl, struct phy *phy)
+{
+	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
+
+	if (lane->pad->ops->disable_phy_wake)
+		return lane->pad->ops->disable_phy_wake(lane);
+
+	return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL_GPL(tegra_xusb_padctl_disable_phy_wake);
+
+bool tegra_xusb_padctl_remote_wake_detected(struct tegra_xusb_padctl *padctl, struct phy *phy)
+{
+	struct tegra_xusb_lane *lane = phy_get_drvdata(phy);
+
+	if (lane->pad->ops->remote_wake_detected)
+		return lane->pad->ops->remote_wake_detected(lane);
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(tegra_xusb_padctl_remote_wake_detected);
+
 int tegra_xusb_padctl_usb3_set_lfps_detect(struct tegra_xusb_padctl *padctl,
 					   unsigned int port, bool enable)
 {
diff --git a/drivers/phy/tegra/xusb.h b/drivers/phy/tegra/xusb.h
index e789d5ff4eb8..034f7a2c28d6 100644
--- a/drivers/phy/tegra/xusb.h
+++ b/drivers/phy/tegra/xusb.h
@@ -11,6 +11,7 @@ 
 #include <linux/mutex.h>
 #include <linux/workqueue.h>
 
+#include <linux/usb/ch9.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/role.h>
 
@@ -132,6 +133,11 @@  struct tegra_xusb_lane_ops {
 	void (*remove)(struct tegra_xusb_lane *lane);
 	void (*iddq_enable)(struct tegra_xusb_lane *lane);
 	void (*iddq_disable)(struct tegra_xusb_lane *lane);
+	int (*enable_phy_sleepwalk)(struct tegra_xusb_lane *lane, enum usb_device_speed speed);
+	int (*disable_phy_sleepwalk)(struct tegra_xusb_lane *lane);
+	int (*enable_phy_wake)(struct tegra_xusb_lane *lane);
+	int (*disable_phy_wake)(struct tegra_xusb_lane *lane);
+	bool (*remote_wake_detected)(struct tegra_xusb_lane *lane);
 };
 
 bool tegra_xusb_lane_check(struct tegra_xusb_lane *lane, const char *function);
@@ -396,6 +402,8 @@  struct tegra_xusb_padctl_ops {
 			 const struct tegra_xusb_padctl_soc *soc);
 	void (*remove)(struct tegra_xusb_padctl *padctl);
 
+	int (*suspend_noirq)(struct tegra_xusb_padctl *padctl);
+	int (*resume_noirq)(struct tegra_xusb_padctl *padctl);
 	int (*usb3_save_context)(struct tegra_xusb_padctl *padctl,
 				 unsigned int index);
 	int (*hsic_set_idle)(struct tegra_xusb_padctl *padctl,
diff --git a/include/linux/phy/tegra/xusb.h b/include/linux/phy/tegra/xusb.h
index 71d956935405..3a35e74cdc61 100644
--- a/include/linux/phy/tegra/xusb.h
+++ b/include/linux/phy/tegra/xusb.h
@@ -1,6 +1,6 @@ 
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2016, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2016-2020, NVIDIA CORPORATION.  All rights reserved.
  */
 
 #ifndef PHY_TEGRA_XUSB_H
@@ -8,6 +8,7 @@ 
 
 struct tegra_xusb_padctl;
 struct device;
+enum usb_device_speed;
 
 struct tegra_xusb_padctl *tegra_xusb_padctl_get(struct device *dev);
 void tegra_xusb_padctl_put(struct tegra_xusb_padctl *padctl);
@@ -23,4 +24,11 @@  int tegra_xusb_padctl_set_vbus_override(struct tegra_xusb_padctl *padctl,
 int tegra_phy_xusb_utmi_port_reset(struct phy *phy);
 int tegra_xusb_padctl_get_usb3_companion(struct tegra_xusb_padctl *padctl,
 					 unsigned int port);
+int tegra_xusb_padctl_enable_phy_sleepwalk(struct tegra_xusb_padctl *padctl, struct phy *phy,
+					   enum usb_device_speed speed);
+int tegra_xusb_padctl_disable_phy_sleepwalk(struct tegra_xusb_padctl *padctl, struct phy *phy);
+int tegra_xusb_padctl_enable_phy_wake(struct tegra_xusb_padctl *padctl, struct phy *phy);
+int tegra_xusb_padctl_disable_phy_wake(struct tegra_xusb_padctl *padctl, struct phy *phy);
+bool tegra_xusb_padctl_remote_wake_detected(struct tegra_xusb_padctl *padctl, struct phy *phy);
+
 #endif /* PHY_TEGRA_XUSB_H */