* [PATCH v2 1/2] can: m_can: allow keeping the transceiver running in suspend
@ 2023-09-19 12:28 Martin Hundebøll
2023-09-19 12:28 ` [PATCH v2 2/2] can: tcan4x5x: support resuming from rx interrupt signal Martin Hundebøll
2023-09-29 14:25 ` [PATCH v2 1/2] can: m_can: allow keeping the transceiver running in suspend Markus Schneider-Pargmann
0 siblings, 2 replies; 4+ messages in thread
From: Martin Hundebøll @ 2023-09-19 12:28 UTC (permalink / raw)
To: linux-can
Cc: Martin Hundebøll, Chandrasekar Ramakrishnan,
Wolfgang Grandegger, Marc Kleine-Budde, Dong Aisheng, Dan Murphy
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@geanix.com>
---
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
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 2/2] can: tcan4x5x: support resuming from rx interrupt signal
2023-09-19 12:28 [PATCH v2 1/2] can: m_can: allow keeping the transceiver running in suspend Martin Hundebøll
@ 2023-09-19 12:28 ` Martin Hundebøll
2023-09-29 14:27 ` Markus Schneider-Pargmann
2023-09-29 14:25 ` [PATCH v2 1/2] can: m_can: allow keeping the transceiver running in suspend Markus Schneider-Pargmann
1 sibling, 1 reply; 4+ messages in thread
From: Martin Hundebøll @ 2023-09-19 12:28 UTC (permalink / raw)
To: linux-can
Cc: Martin Hundebøll, Chandrasekar Ramakrishnan,
Wolfgang Grandegger, Marc Kleine-Budde, Dong Aisheng, Dan Murphy
Implement the "wakeup-source" device tree property, so the chip is left
running when suspending, and its rx interrupt is used as a wakeup source
to resume operation.
Signed-off-by: Martin Hundebøll <martin@geanix.com>
---
Change since v1:
* Added `static` keyword to dev_pm_ops sturcture
drivers/net/can/m_can/tcan4x5x-core.c | 34 ++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/drivers/net/can/m_can/tcan4x5x-core.c b/drivers/net/can/m_can/tcan4x5x-core.c
index 8a4143809d33..ccb279af22bb 100644
--- a/drivers/net/can/m_can/tcan4x5x-core.c
+++ b/drivers/net/can/m_can/tcan4x5x-core.c
@@ -459,6 +459,9 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
goto out_power;
}
+ if (device_property_read_bool(&spi->dev, "wakeup-source"))
+ device_init_wakeup(&spi->dev, true);
+
ret = m_can_class_register(mcan_class);
if (ret) {
dev_err(&spi->dev, "Failed registering m_can device %pe\n",
@@ -487,6 +490,31 @@ static void tcan4x5x_can_remove(struct spi_device *spi)
m_can_class_free_dev(priv->cdev.net);
}
+static int __maybe_unused tcan4x5x_suspend(struct device *dev)
+{
+ struct spi_device *spi = to_spi_device(dev);
+
+ if (device_may_wakeup(dev)) {
+ enable_irq_wake(spi->irq);
+
+ return m_can_class_suspend(dev, true);
+ }
+
+ return m_can_class_suspend(dev, false);
+}
+
+static int __maybe_unused tcan4x5x_resume(struct device *dev)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ bool wake_source = device_may_wakeup(dev);
+ int ret = m_can_class_resume(dev, wake_source);
+
+ if (wake_source)
+ disable_irq_wake(spi->irq);
+
+ return ret;
+}
+
static const struct of_device_id tcan4x5x_of_match[] = {
{
.compatible = "ti,tcan4x5x",
@@ -505,11 +533,15 @@ static const struct spi_device_id tcan4x5x_id_table[] = {
};
MODULE_DEVICE_TABLE(spi, tcan4x5x_id_table);
+static const struct dev_pm_ops tcan4x5x_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(tcan4x5x_suspend, tcan4x5x_resume)
+};
+
static struct spi_driver tcan4x5x_can_driver = {
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = tcan4x5x_of_match,
- .pm = NULL,
+ .pm = &tcan4x5x_pm_ops,
},
.id_table = tcan4x5x_id_table,
.probe = tcan4x5x_can_probe,
--
2.42.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2 1/2] can: m_can: allow keeping the transceiver running in suspend
2023-09-19 12:28 [PATCH v2 1/2] can: m_can: allow keeping the transceiver running in suspend Martin Hundebøll
2023-09-19 12:28 ` [PATCH v2 2/2] can: tcan4x5x: support resuming from rx interrupt signal Martin Hundebøll
@ 2023-09-29 14:25 ` Markus Schneider-Pargmann
1 sibling, 0 replies; 4+ messages in thread
From: Markus Schneider-Pargmann @ 2023-09-29 14:25 UTC (permalink / raw)
To: Martin Hundebøll
Cc: linux-can, Chandrasekar Ramakrishnan, Wolfgang Grandegger,
Marc Kleine-Budde, Dong Aisheng, Dan Murphy
Hi Martin,
On Tue, Sep 19, 2023 at 02:28:32PM +0200, Martin Hundebøll wrote:
> 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.
As far as I know the wakeup-source property is static, so maybe it would
be possible to store a property in m_can_classdev instead of using a
function parameter?
Looking into m_can_classdev there is already a pm_clock_support field.
Maybe you can put one right next to it for wakeup source?
Best,
Markus
>
> Signed-off-by: Martin Hundebøll <martin@geanix.com>
> ---
>
> 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
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2 2/2] can: tcan4x5x: support resuming from rx interrupt signal
2023-09-19 12:28 ` [PATCH v2 2/2] can: tcan4x5x: support resuming from rx interrupt signal Martin Hundebøll
@ 2023-09-29 14:27 ` Markus Schneider-Pargmann
0 siblings, 0 replies; 4+ messages in thread
From: Markus Schneider-Pargmann @ 2023-09-29 14:27 UTC (permalink / raw)
To: Martin Hundebøll
Cc: linux-can, Chandrasekar Ramakrishnan, Wolfgang Grandegger,
Marc Kleine-Budde, Dong Aisheng, Dan Murphy
Hi Martin,
On Tue, Sep 19, 2023 at 02:28:33PM +0200, Martin Hundebøll wrote:
> Implement the "wakeup-source" device tree property, so the chip is left
> running when suspending, and its rx interrupt is used as a wakeup source
> to resume operation.
I think you need to add a patch in your series to update the binding
documentation in Documentation/devicetree/bindings/net/can/tcan4x5x.txt
with the wakeup-source property.
Best,
Markus
>
> Signed-off-by: Martin Hundebøll <martin@geanix.com>
> ---
>
> Change since v1:
> * Added `static` keyword to dev_pm_ops sturcture
>
> drivers/net/can/m_can/tcan4x5x-core.c | 34 ++++++++++++++++++++++++++-
> 1 file changed, 33 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/can/m_can/tcan4x5x-core.c b/drivers/net/can/m_can/tcan4x5x-core.c
> index 8a4143809d33..ccb279af22bb 100644
> --- a/drivers/net/can/m_can/tcan4x5x-core.c
> +++ b/drivers/net/can/m_can/tcan4x5x-core.c
> @@ -459,6 +459,9 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
> goto out_power;
> }
>
> + if (device_property_read_bool(&spi->dev, "wakeup-source"))
> + device_init_wakeup(&spi->dev, true);
> +
> ret = m_can_class_register(mcan_class);
> if (ret) {
> dev_err(&spi->dev, "Failed registering m_can device %pe\n",
> @@ -487,6 +490,31 @@ static void tcan4x5x_can_remove(struct spi_device *spi)
> m_can_class_free_dev(priv->cdev.net);
> }
>
> +static int __maybe_unused tcan4x5x_suspend(struct device *dev)
> +{
> + struct spi_device *spi = to_spi_device(dev);
> +
> + if (device_may_wakeup(dev)) {
> + enable_irq_wake(spi->irq);
> +
> + return m_can_class_suspend(dev, true);
> + }
> +
> + return m_can_class_suspend(dev, false);
> +}
> +
> +static int __maybe_unused tcan4x5x_resume(struct device *dev)
> +{
> + struct spi_device *spi = to_spi_device(dev);
> + bool wake_source = device_may_wakeup(dev);
> + int ret = m_can_class_resume(dev, wake_source);
> +
> + if (wake_source)
> + disable_irq_wake(spi->irq);
> +
> + return ret;
> +}
> +
> static const struct of_device_id tcan4x5x_of_match[] = {
> {
> .compatible = "ti,tcan4x5x",
> @@ -505,11 +533,15 @@ static const struct spi_device_id tcan4x5x_id_table[] = {
> };
> MODULE_DEVICE_TABLE(spi, tcan4x5x_id_table);
>
> +static const struct dev_pm_ops tcan4x5x_pm_ops = {
> + SET_SYSTEM_SLEEP_PM_OPS(tcan4x5x_suspend, tcan4x5x_resume)
> +};
> +
> static struct spi_driver tcan4x5x_can_driver = {
> .driver = {
> .name = KBUILD_MODNAME,
> .of_match_table = tcan4x5x_of_match,
> - .pm = NULL,
> + .pm = &tcan4x5x_pm_ops,
> },
> .id_table = tcan4x5x_id_table,
> .probe = tcan4x5x_can_probe,
> --
> 2.42.0
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2023-09-29 14:27 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-19 12:28 [PATCH v2 1/2] can: m_can: allow keeping the transceiver running in suspend Martin Hundebøll
2023-09-19 12:28 ` [PATCH v2 2/2] can: tcan4x5x: support resuming from rx interrupt signal Martin Hundebøll
2023-09-29 14:27 ` Markus Schneider-Pargmann
2023-09-29 14:25 ` [PATCH v2 1/2] can: m_can: allow keeping the transceiver running in suspend Markus Schneider-Pargmann
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.