* [PATCH] serdev: Add support for wakeup-source
@ 2025-02-13 14:34 Loic Poulain
2025-03-21 13:24 ` Neeraj Sanjay Kale
2025-04-08 13:09 ` Rob Herring
0 siblings, 2 replies; 4+ messages in thread
From: Loic Poulain @ 2025-02-13 14:34 UTC (permalink / raw)
To: robh; +Cc: jirislaby, gregkh, linux-serial, Loic Poulain
This brings support for dedicated interrupt as wakeup source into the
serdev core, similarly to the I2C bus, and aligned with the documentation:
Documentation/devicetree/bindings/power/wakeup-source.txt
As an example, this can be used for bluetooth serial devices with dedicated
controller-to-host wakeup pin.
Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
---
drivers/tty/serdev/core.c | 48 +++++++++++++++++++++++++++++++++++++--
include/linux/serdev.h | 1 +
2 files changed, 47 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index ebf0bbc2cff2..2d016fa546ca 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -13,8 +13,10 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/of_irq.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
+#include <linux/pm_wakeirq.h>
#include <linux/property.h>
#include <linux/sched.h>
#include <linux/serdev.h>
@@ -164,6 +166,9 @@ int serdev_device_open(struct serdev_device *serdev)
goto err_close;
}
+ if (serdev->wakeup_source)
+ device_wakeup_enable(&serdev->dev);
+
return 0;
err_close:
@@ -181,6 +186,9 @@ void serdev_device_close(struct serdev_device *serdev)
if (!ctrl || !ctrl->ops->close)
return;
+ if (serdev->wakeup_source)
+ device_wakeup_disable(&serdev->dev);
+
pm_runtime_put(&ctrl->dev);
ctrl->ops->close(ctrl);
@@ -406,18 +414,52 @@ int serdev_device_break_ctl(struct serdev_device *serdev, int break_state)
}
EXPORT_SYMBOL_GPL(serdev_device_break_ctl);
+static int serdev_wakeup_attach(struct device *dev)
+{
+ int wakeirq;
+
+ if (!of_property_read_bool(dev->of_node, "wakeup-source"))
+ return 0;
+
+ to_serdev_device(dev)->wakeup_source = true;
+
+ device_set_wakeup_capable(dev, true);
+
+ wakeirq = of_irq_get_byname(dev->of_node, "wakeup");
+ if (wakeirq == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ else if (wakeirq > 0)
+ return dev_pm_set_dedicated_wake_irq(dev, wakeirq);
+
+ return 0;
+}
+
+static void serdev_wakeup_detach(struct device *dev)
+{
+ device_init_wakeup(dev, false);
+ dev_pm_clear_wake_irq(dev);
+}
+
static int serdev_drv_probe(struct device *dev)
{
const struct serdev_device_driver *sdrv = to_serdev_device_driver(dev->driver);
int ret;
- ret = dev_pm_domain_attach(dev, true);
+ ret = serdev_wakeup_attach(dev);
if (ret)
return ret;
+ ret = dev_pm_domain_attach(dev, true);
+ if (ret) {
+ serdev_wakeup_detach(dev);
+ return ret;
+ }
+
ret = sdrv->probe(to_serdev_device(dev));
- if (ret)
+ if (ret) {
dev_pm_domain_detach(dev, true);
+ serdev_wakeup_detach(dev);
+ }
return ret;
}
@@ -429,6 +471,8 @@ static void serdev_drv_remove(struct device *dev)
sdrv->remove(to_serdev_device(dev));
dev_pm_domain_detach(dev, true);
+
+ serdev_wakeup_detach(dev);
}
static const struct bus_type serdev_bus_type = {
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index ff78efc1f60d..2b3ee7b2c141 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -47,6 +47,7 @@ struct serdev_device {
const struct serdev_device_ops *ops;
struct completion write_comp;
struct mutex write_lock;
+ bool wakeup_source;
};
static inline struct serdev_device *to_serdev_device(struct device *d)
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] serdev: Add support for wakeup-source
2025-02-13 14:34 [PATCH] serdev: Add support for wakeup-source Loic Poulain
@ 2025-03-21 13:24 ` Neeraj Sanjay Kale
2025-04-07 13:29 ` Neeraj Sanjay Kale
2025-04-08 13:09 ` Rob Herring
1 sibling, 1 reply; 4+ messages in thread
From: Neeraj Sanjay Kale @ 2025-03-21 13:24 UTC (permalink / raw)
To: Loic Poulain
Cc: robh, jirislaby, gregkh, linux-serial, manjeet.gupta,
amitkumar.karwar
Hi Loic,
Thank you for the patch.
I have verified this patch with btnxpuart driver and I am able to wakeup the host with a GPIO interrupt signal from BT controller.
Tested-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
Thanks,
Neeraj
On Thu, Feb 13, 2025 at 03:34:30PM +0100, Loic Poulain wrote:
> This brings support for dedicated interrupt as wakeup source into the
> serdev core, similarly to the I2C bus, and aligned with the documentation:
> Documentation/devicetree/bindings/power/wakeup-source.txt
>
> As an example, this can be used for bluetooth serial devices with dedicated
> controller-to-host wakeup pin.
>
> Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> ---
> drivers/tty/serdev/core.c | 48 +++++++++++++++++++++++++++++++++++++--
> include/linux/serdev.h | 1 +
> 2 files changed, 47 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
> index ebf0bbc2cff2..2d016fa546ca 100644
> --- a/drivers/tty/serdev/core.c
> +++ b/drivers/tty/serdev/core.c
> @@ -13,8 +13,10 @@
> #include <linux/module.h>
> #include <linux/of.h>
> #include <linux/of_device.h>
> +#include <linux/of_irq.h>
> #include <linux/pm_domain.h>
> #include <linux/pm_runtime.h>
> +#include <linux/pm_wakeirq.h>
> #include <linux/property.h>
> #include <linux/sched.h>
> #include <linux/serdev.h>
> @@ -164,6 +166,9 @@ int serdev_device_open(struct serdev_device *serdev)
> goto err_close;
> }
>
> + if (serdev->wakeup_source)
> + device_wakeup_enable(&serdev->dev);
> +
> return 0;
>
> err_close:
> @@ -181,6 +186,9 @@ void serdev_device_close(struct serdev_device *serdev)
> if (!ctrl || !ctrl->ops->close)
> return;
>
> + if (serdev->wakeup_source)
> + device_wakeup_disable(&serdev->dev);
> +
> pm_runtime_put(&ctrl->dev);
>
> ctrl->ops->close(ctrl);
> @@ -406,18 +414,52 @@ int serdev_device_break_ctl(struct serdev_device *serdev, int break_state)
> }
> EXPORT_SYMBOL_GPL(serdev_device_break_ctl);
>
> +static int serdev_wakeup_attach(struct device *dev)
> +{
> + int wakeirq;
> +
> + if (!of_property_read_bool(dev->of_node, "wakeup-source"))
> + return 0;
> +
> + to_serdev_device(dev)->wakeup_source = true;
> +
> + device_set_wakeup_capable(dev, true);
> +
> + wakeirq = of_irq_get_byname(dev->of_node, "wakeup");
> + if (wakeirq == -EPROBE_DEFER)
> + return -EPROBE_DEFER;
> + else if (wakeirq > 0)
> + return dev_pm_set_dedicated_wake_irq(dev, wakeirq);
> +
> + return 0;
> +}
> +
> +static void serdev_wakeup_detach(struct device *dev)
> +{
> + device_init_wakeup(dev, false);
> + dev_pm_clear_wake_irq(dev);
> +}
> +
> static int serdev_drv_probe(struct device *dev)
> {
> const struct serdev_device_driver *sdrv = to_serdev_device_driver(dev->driver);
> int ret;
>
> - ret = dev_pm_domain_attach(dev, true);
> + ret = serdev_wakeup_attach(dev);
> if (ret)
> return ret;
>
> + ret = dev_pm_domain_attach(dev, true);
> + if (ret) {
> + serdev_wakeup_detach(dev);
> + return ret;
> + }
> +
> ret = sdrv->probe(to_serdev_device(dev));
> - if (ret)
> + if (ret) {
> dev_pm_domain_detach(dev, true);
> + serdev_wakeup_detach(dev);
> + }
>
> return ret;
> }
> @@ -429,6 +471,8 @@ static void serdev_drv_remove(struct device *dev)
> sdrv->remove(to_serdev_device(dev));
>
> dev_pm_domain_detach(dev, true);
> +
> + serdev_wakeup_detach(dev);
> }
>
> static const struct bus_type serdev_bus_type = {
> diff --git a/include/linux/serdev.h b/include/linux/serdev.h
> index ff78efc1f60d..2b3ee7b2c141 100644
> --- a/include/linux/serdev.h
> +++ b/include/linux/serdev.h
> @@ -47,6 +47,7 @@ struct serdev_device {
> const struct serdev_device_ops *ops;
> struct completion write_comp;
> struct mutex write_lock;
> + bool wakeup_source;
> };
>
> static inline struct serdev_device *to_serdev_device(struct device *d)
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [PATCH] serdev: Add support for wakeup-source
2025-03-21 13:24 ` Neeraj Sanjay Kale
@ 2025-04-07 13:29 ` Neeraj Sanjay Kale
0 siblings, 0 replies; 4+ messages in thread
From: Neeraj Sanjay Kale @ 2025-04-07 13:29 UTC (permalink / raw)
To: robh@kernel.org, jirislaby@kernel.org, gregkh@linuxfoundation.org
Cc: linux-serial@vger.kernel.org, Manjeet Gupta, Amitkumar Karwar,
Sherry Sun, Loic Poulain
Hello maintainers,
This patch is in review for quite some time, and it's an important feature which we would like to have support for, in the NXP BT UART driver.
If there are no further review comments, can you please help approve this?
Thanks,
Neeraj
> Hi Loic,
>
> Thank you for the patch.
>
> I have verified this patch with btnxpuart driver and I am able to wakeup the
> host with a GPIO interrupt signal from BT controller.
>
> Tested-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
>
> Thanks,
> Neeraj
>
> On Thu, Feb 13, 2025 at 03:34:30PM +0100, Loic Poulain wrote:
> > This brings support for dedicated interrupt as wakeup source into the
> > serdev core, similarly to the I2C bus, and aligned with the documentation:
> > Documentation/devicetree/bindings/power/wakeup-source.txt
> >
> > As an example, this can be used for bluetooth serial devices with
> > dedicated controller-to-host wakeup pin.
> >
> > Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> > ---
> > drivers/tty/serdev/core.c | 48
> +++++++++++++++++++++++++++++++++++++--
> > include/linux/serdev.h | 1 +
> > 2 files changed, 47 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
> > index ebf0bbc2cff2..2d016fa546ca 100644
> > --- a/drivers/tty/serdev/core.c
> > +++ b/drivers/tty/serdev/core.c
> > @@ -13,8 +13,10 @@
> > #include <linux/module.h>
> > #include <linux/of.h>
> > #include <linux/of_device.h>
> > +#include <linux/of_irq.h>
> > #include <linux/pm_domain.h>
> > #include <linux/pm_runtime.h>
> > +#include <linux/pm_wakeirq.h>
> > #include <linux/property.h>
> > #include <linux/sched.h>
> > #include <linux/serdev.h>
> > @@ -164,6 +166,9 @@ int serdev_device_open(struct serdev_device
> *serdev)
> > goto err_close;
> > }
> >
> > + if (serdev->wakeup_source)
> > + device_wakeup_enable(&serdev->dev);
> > +
> > return 0;
> >
> > err_close:
> > @@ -181,6 +186,9 @@ void serdev_device_close(struct serdev_device
> *serdev)
> > if (!ctrl || !ctrl->ops->close)
> > return;
> >
> > + if (serdev->wakeup_source)
> > + device_wakeup_disable(&serdev->dev);
> > +
> > pm_runtime_put(&ctrl->dev);
> >
> > ctrl->ops->close(ctrl);
> > @@ -406,18 +414,52 @@ int serdev_device_break_ctl(struct serdev_device
> > *serdev, int break_state) }
> > EXPORT_SYMBOL_GPL(serdev_device_break_ctl);
> >
> > +static int serdev_wakeup_attach(struct device *dev) {
> > + int wakeirq;
> > +
> > + if (!of_property_read_bool(dev->of_node, "wakeup-source"))
> > + return 0;
> > +
> > + to_serdev_device(dev)->wakeup_source = true;
> > +
> > + device_set_wakeup_capable(dev, true);
> > +
> > + wakeirq = of_irq_get_byname(dev->of_node, "wakeup");
> > + if (wakeirq == -EPROBE_DEFER)
> > + return -EPROBE_DEFER;
> > + else if (wakeirq > 0)
> > + return dev_pm_set_dedicated_wake_irq(dev, wakeirq);
> > +
> > + return 0;
> > +}
> > +
> > +static void serdev_wakeup_detach(struct device *dev) {
> > + device_init_wakeup(dev, false);
> > + dev_pm_clear_wake_irq(dev);
> > +}
> > +
> > static int serdev_drv_probe(struct device *dev) {
> > const struct serdev_device_driver *sdrv =
> to_serdev_device_driver(dev->driver);
> > int ret;
> >
> > - ret = dev_pm_domain_attach(dev, true);
> > + ret = serdev_wakeup_attach(dev);
> > if (ret)
> > return ret;
> >
> > + ret = dev_pm_domain_attach(dev, true);
> > + if (ret) {
> > + serdev_wakeup_detach(dev);
> > + return ret;
> > + }
> > +
> > ret = sdrv->probe(to_serdev_device(dev));
> > - if (ret)
> > + if (ret) {
> > dev_pm_domain_detach(dev, true);
> > + serdev_wakeup_detach(dev);
> > + }
> >
> > return ret;
> > }
> > @@ -429,6 +471,8 @@ static void serdev_drv_remove(struct device *dev)
> > sdrv->remove(to_serdev_device(dev));
> >
> > dev_pm_domain_detach(dev, true);
> > +
> > + serdev_wakeup_detach(dev);
> > }
> >
> > static const struct bus_type serdev_bus_type = { diff --git
> > a/include/linux/serdev.h b/include/linux/serdev.h index
> > ff78efc1f60d..2b3ee7b2c141 100644
> > --- a/include/linux/serdev.h
> > +++ b/include/linux/serdev.h
> > @@ -47,6 +47,7 @@ struct serdev_device {
> > const struct serdev_device_ops *ops;
> > struct completion write_comp;
> > struct mutex write_lock;
> > + bool wakeup_source;
> > };
> >
> > static inline struct serdev_device *to_serdev_device(struct device
> > *d)
> > --
> > 2.34.1
> >
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] serdev: Add support for wakeup-source
2025-02-13 14:34 [PATCH] serdev: Add support for wakeup-source Loic Poulain
2025-03-21 13:24 ` Neeraj Sanjay Kale
@ 2025-04-08 13:09 ` Rob Herring
1 sibling, 0 replies; 4+ messages in thread
From: Rob Herring @ 2025-04-08 13:09 UTC (permalink / raw)
To: Loic Poulain; +Cc: jirislaby, gregkh, linux-serial
On Thu, Feb 13, 2025 at 8:34 AM Loic Poulain <loic.poulain@linaro.org> wrote:
>
> This brings support for dedicated interrupt as wakeup source into the
> serdev core, similarly to the I2C bus, and aligned with the documentation:
> Documentation/devicetree/bindings/power/wakeup-source.txt
Don't add new references to old documentation.
The difference I think is I2C has some defined mechanisms for wakeup.
We don't have anything in platform devices, SPI, etc., so why serdev?
A "wakeup" IRQ is also a suggestion more than a hard requirement of
how wakeup is implemented.
Rob
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-04-08 13:09 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-13 14:34 [PATCH] serdev: Add support for wakeup-source Loic Poulain
2025-03-21 13:24 ` Neeraj Sanjay Kale
2025-04-07 13:29 ` Neeraj Sanjay Kale
2025-04-08 13:09 ` Rob Herring
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox