[PATCH v2 1/2] can: m_can: allow keeping the transceiver running in suspend

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add a flag to the suspend class function that leaves the chip in a
running state with rx interrupt enabled, so that m_can device driver can
configure and use the interrupt as a wakeup source.

Signed-off-by: Martin Hundebøll <martin@xxxxxxxxxx>
---

Changes since v1:
 * Fixed comment formatting
 * Updated m_can_class_{suspend,resume} calls in m_can_pci.c too
 * Skipped calling m_can_start() when resuming a wake-source device

 drivers/net/can/m_can/m_can.c          | 26 +++++++++++++++++++-------
 drivers/net/can/m_can/m_can.h          |  4 ++--
 drivers/net/can/m_can/m_can_pci.c      |  4 ++--
 drivers/net/can/m_can/m_can_platform.c |  4 ++--
 4 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index 16ecc11c7f62..ec345f6fd6b0 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -2113,7 +2113,7 @@ void m_can_class_unregister(struct m_can_classdev *cdev)
 }
 EXPORT_SYMBOL_GPL(m_can_class_unregister);
 
-int m_can_class_suspend(struct device *dev)
+int m_can_class_suspend(struct device *dev, bool is_wake_source)
 {
 	struct m_can_classdev *cdev = dev_get_drvdata(dev);
 	struct net_device *ndev = cdev->net;
@@ -2121,7 +2121,15 @@ int m_can_class_suspend(struct device *dev)
 	if (netif_running(ndev)) {
 		netif_stop_queue(ndev);
 		netif_device_detach(ndev);
-		m_can_stop(ndev);
+
+		/* leave the chip running with rx interrupt enabled if it used
+		 * as a wake-up source.
+		 */
+		if (is_wake_source)
+			m_can_write(cdev, M_CAN_IE, IR_RF0N);
+		else
+			m_can_stop(ndev);
+
 		m_can_clk_stop(cdev);
 	}
 
@@ -2133,7 +2141,7 @@ int m_can_class_suspend(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(m_can_class_suspend);
 
-int m_can_class_resume(struct device *dev)
+int m_can_class_resume(struct device *dev, bool is_wake_source)
 {
 	struct m_can_classdev *cdev = dev_get_drvdata(dev);
 	struct net_device *ndev = cdev->net;
@@ -2148,11 +2156,15 @@ int m_can_class_resume(struct device *dev)
 		ret = m_can_clk_start(cdev);
 		if (ret)
 			return ret;
-		ret  = m_can_start(ndev);
-		if (ret) {
-			m_can_clk_stop(cdev);
 
-			return ret;
+		if (is_wake_source) {
+			m_can_write(cdev, M_CAN_IE, cdev->active_interrupts);
+		} else {
+			ret  = m_can_start(ndev);
+			if (ret) {
+				m_can_clk_stop(cdev);
+				return ret;
+			}
 		}
 
 		netif_device_attach(ndev);
diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h
index 520e14277dff..5d86bcf66e83 100644
--- a/drivers/net/can/m_can/m_can.h
+++ b/drivers/net/can/m_can/m_can.h
@@ -105,6 +105,6 @@ int m_can_class_get_clocks(struct m_can_classdev *cdev);
 int m_can_init_ram(struct m_can_classdev *priv);
 int m_can_check_mram_cfg(struct m_can_classdev *cdev, u32 mram_max_size);
 
-int m_can_class_suspend(struct device *dev);
-int m_can_class_resume(struct device *dev);
+int m_can_class_suspend(struct device *dev, bool is_wake_source);
+int m_can_class_resume(struct device *dev, bool is_wake_source);
 #endif	/* _CAN_M_H_ */
diff --git a/drivers/net/can/m_can/m_can_pci.c b/drivers/net/can/m_can/m_can_pci.c
index f2219aa2824b..7ffbe06d96d0 100644
--- a/drivers/net/can/m_can/m_can_pci.c
+++ b/drivers/net/can/m_can/m_can_pci.c
@@ -169,12 +169,12 @@ static void m_can_pci_remove(struct pci_dev *pci)
 
 static __maybe_unused int m_can_pci_suspend(struct device *dev)
 {
-	return m_can_class_suspend(dev);
+	return m_can_class_suspend(dev, false);
 }
 
 static __maybe_unused int m_can_pci_resume(struct device *dev)
 {
-	return m_can_class_resume(dev);
+	return m_can_class_resume(dev, false);
 }
 
 static SIMPLE_DEV_PM_OPS(m_can_pci_pm_ops,
diff --git a/drivers/net/can/m_can/m_can_platform.c b/drivers/net/can/m_can/m_can_platform.c
index cdb28d6a092c..e49bef50d52c 100644
--- a/drivers/net/can/m_can/m_can_platform.c
+++ b/drivers/net/can/m_can/m_can_platform.c
@@ -169,12 +169,12 @@ static int m_can_plat_probe(struct platform_device *pdev)
 
 static __maybe_unused int m_can_suspend(struct device *dev)
 {
-	return m_can_class_suspend(dev);
+	return m_can_class_suspend(dev, false);
 }
 
 static __maybe_unused int m_can_resume(struct device *dev)
 {
-	return m_can_class_resume(dev);
+	return m_can_class_resume(dev, false);
 }
 
 static void m_can_plat_remove(struct platform_device *pdev)
-- 
2.42.0




[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux