diff mbox

[v3,1/3] Input: omap-keypad: Enable wakeup capability for keypad.

Message ID 1375116311-13999-2-git-send-email-illia.smyrnov@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Illia Smyrnov July 29, 2013, 4:45 p.m. UTC
Enable/disable IRQ wake in suspend/resume handlers
to make the keypad wakeup capable.

Signed-off-by: Illia Smyrnov <illia.smyrnov@ti.com>
---
 drivers/input/keyboard/omap4-keypad.c |   43 +++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

Comments

Felipe Balbi July 29, 2013, 6:04 p.m. UTC | #1
Hi,

On Mon, Jul 29, 2013 at 07:45:09PM +0300, Illia Smyrnov wrote:
> Enable/disable IRQ wake in suspend/resume handlers
> to make the keypad wakeup capable.
> 
> Signed-off-by: Illia Smyrnov <illia.smyrnov@ti.com>
> ---
>  drivers/input/keyboard/omap4-keypad.c |   43 +++++++++++++++++++++++++++++++++
>  1 file changed, 43 insertions(+)
> 
> diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
> index 0244262..feab00f 100644
> --- a/drivers/input/keyboard/omap4-keypad.c
> +++ b/drivers/input/keyboard/omap4-keypad.c
> @@ -74,6 +74,7 @@ struct omap4_keypad {
>  	struct input_dev *input;
>  
>  	void __iomem *base;
> +	bool irq_wake_enabled;

this flag is a bit weird... but I can't find a better way to handle this
situation. In one way, you shouldn't prevent system suspend, so you can
error out in case enable_irq_wake() fails, otoh if enable_irq_wake()
fails and you return 0, on resume disable_irq_wake() will throw
unbalanced calls warning. Maybe someone else has a better idea.

> @@ -439,12 +444,50 @@ static const struct of_device_id omap_keypad_dt_match[] = {
>  MODULE_DEVICE_TABLE(of, omap_keypad_dt_match);
>  #endif
>  
> +#ifdef CONFIG_PM_SLEEP
> +static int omap4_keypad_suspend(struct device *dev)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);

you don't need to access the platform_device...

> +	struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);

... since this can become:

	struct omap4_keypad *keypad_data = dev_get_drvdata(dev);

> +	int error;
> +
> +	if (device_may_wakeup(&pdev->dev)) {
> +		error = enable_irq_wake(keypad_data->irq);
> +		if (!error)
> +			keypad_data->irq_wake_enabled = true;
> +	}
> +
> +	return 0;
> +}
> +
> +static int omap4_keypad_resume(struct device *dev)
> +{
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);

ditto, use dev_get_drvdata() instead.
Dmitry Torokhov July 29, 2013, 6:59 p.m. UTC | #2
On Monday, July 29, 2013 09:04:41 PM Felipe Balbi wrote:
> Hi,
> 
> On Mon, Jul 29, 2013 at 07:45:09PM +0300, Illia Smyrnov wrote:
> > Enable/disable IRQ wake in suspend/resume handlers
> > to make the keypad wakeup capable.
> > 
> > Signed-off-by: Illia Smyrnov <illia.smyrnov@ti.com>
> > ---
> > 
> >  drivers/input/keyboard/omap4-keypad.c |   43
> >  +++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
> > 
> > diff --git a/drivers/input/keyboard/omap4-keypad.c
> > b/drivers/input/keyboard/omap4-keypad.c index 0244262..feab00f 100644
> > --- a/drivers/input/keyboard/omap4-keypad.c
> > +++ b/drivers/input/keyboard/omap4-keypad.c
> > @@ -74,6 +74,7 @@ struct omap4_keypad {
> > 
> >  	struct input_dev *input;
> >  	
> >  	void __iomem *base;
> > 
> > +	bool irq_wake_enabled;
> 
> this flag is a bit weird... but I can't find a better way to handle this
> situation. In one way, you shouldn't prevent system suspend, so you can
> error out in case enable_irq_wake() fails, otoh if enable_irq_wake()
> fails and you return 0, on resume disable_irq_wake() will throw
> unbalanced calls warning. Maybe someone else has a better idea.
> 
> > @@ -439,12 +444,50 @@ static const struct of_device_id
> > omap_keypad_dt_match[] = {> 
> >  MODULE_DEVICE_TABLE(of, omap_keypad_dt_match);
> >  #endif
> > 
> > +#ifdef CONFIG_PM_SLEEP
> > +static int omap4_keypad_suspend(struct device *dev)
> > +{
> > +	struct platform_device *pdev = to_platform_device(dev);
> 
> you don't need to access the platform_device...
> 
> > +	struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
> 
> ... since this can become:
> 
> 	struct omap4_keypad *keypad_data = dev_get_drvdata(dev);

No, please use correct accessors for the objects. Platform drivers deal
with platform devices and I prefer using platform_get_drvdata() on them.

Thanks.
Felipe Balbi July 29, 2013, 7:13 p.m. UTC | #3
Hi,

On Mon, Jul 29, 2013 at 11:59:45AM -0700, Dmitry Torokhov wrote:
> > > @@ -439,12 +444,50 @@ static const struct of_device_id
> > > omap_keypad_dt_match[] = {> 
> > >  MODULE_DEVICE_TABLE(of, omap_keypad_dt_match);
> > >  #endif
> > > 
> > > +#ifdef CONFIG_PM_SLEEP
> > > +static int omap4_keypad_suspend(struct device *dev)
> > > +{
> > > +	struct platform_device *pdev = to_platform_device(dev);
> > 
> > you don't need to access the platform_device...
> > 
> > > +	struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
> > 
> > ... since this can become:
> > 
> > 	struct omap4_keypad *keypad_data = dev_get_drvdata(dev);
> 
> No, please use correct accessors for the objects. Platform drivers deal
> with platform devices and I prefer using platform_get_drvdata() on them.

The argument to this function is a struct device, you prefer to do some
pointer math to find the containing pdev, then deref that back to dev,
then to struct device_private and further to driver_data ?

Sounds like a waste of time IMHO. You already have the device pointer
anyway, why would you go through the trouble of calculating the
offsets for the containing struct platform_device ?
Dmitry Torokhov July 29, 2013, 7:59 p.m. UTC | #4
On Monday, July 29, 2013 10:13:24 PM Felipe Balbi wrote:
> Hi,
> 
> On Mon, Jul 29, 2013 at 11:59:45AM -0700, Dmitry Torokhov wrote:
> > > > @@ -439,12 +444,50 @@ static const struct of_device_id
> > > > omap_keypad_dt_match[] = {>
> > > > 
> > > >  MODULE_DEVICE_TABLE(of, omap_keypad_dt_match);
> > > >  #endif
> > > > 
> > > > +#ifdef CONFIG_PM_SLEEP
> > > > +static int omap4_keypad_suspend(struct device *dev)
> > > > +{
> > > > +	struct platform_device *pdev = to_platform_device(dev);
> > > 
> > > you don't need to access the platform_device...
> > > 
> > > > +	struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
> > > 
> > > ... since this can become:
> > > 	struct omap4_keypad *keypad_data = dev_get_drvdata(dev);
> > 
> > No, please use correct accessors for the objects. Platform drivers deal
> > with platform devices and I prefer using platform_get_drvdata() on them.
> 
> The argument to this function is a struct device, you prefer to do some
> pointer math to find the containing pdev, then deref that back to dev,
> then to struct device_private and further to driver_data ?
> 
> Sounds like a waste of time IMHO. You already have the device pointer
> anyway, why would you go through the trouble of calculating the
> offsets for the containing struct platform_device ?

This assumes knowledge of dev_get_drvdata() implementation and assumption
that it will stay the same. Unless I hear from device core guys that
<bus>_{get|set}_drvdata() methods are obsolete and will be eventually
removed I will require proper accessors being used.

Thanks!
Felipe Balbi July 29, 2013, 8:36 p.m. UTC | #5
Hi,

On Mon, Jul 29, 2013 at 12:59:23PM -0700, Dmitry Torokhov wrote:
> > > > > @@ -439,12 +444,50 @@ static const struct of_device_id
> > > > > omap_keypad_dt_match[] = {>
> > > > > 
> > > > >  MODULE_DEVICE_TABLE(of, omap_keypad_dt_match);
> > > > >  #endif
> > > > > 
> > > > > +#ifdef CONFIG_PM_SLEEP
> > > > > +static int omap4_keypad_suspend(struct device *dev)
> > > > > +{
> > > > > +	struct platform_device *pdev = to_platform_device(dev);
> > > > 
> > > > you don't need to access the platform_device...
> > > > 
> > > > > +	struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
> > > > 
> > > > ... since this can become:
> > > > 	struct omap4_keypad *keypad_data = dev_get_drvdata(dev);
> > > 
> > > No, please use correct accessors for the objects. Platform drivers deal
> > > with platform devices and I prefer using platform_get_drvdata() on them.
> > 
> > The argument to this function is a struct device, you prefer to do some
> > pointer math to find the containing pdev, then deref that back to dev,
> > then to struct device_private and further to driver_data ?
> > 
> > Sounds like a waste of time IMHO. You already have the device pointer
> > anyway, why would you go through the trouble of calculating the
> > offsets for the containing struct platform_device ?
> 
> This assumes knowledge of dev_get_drvdata() implementation and assumption
> that it will stay the same. Unless I hear from device core guys that
> <bus>_{get|set}_drvdata() methods are obsolete and will be eventually
> removed I will require proper accessors being used.

they're not obsolete and will never be removed. They're nothing but
helpers though. Instead of calling:

	dev_set_drvdata(&pdev->dev);

you call:

	platform_set_drvdata(pdev);

same is valid for every single bus, but in the end they all just wrap a
call dev_{set,get}_drvdata() internally. If you already have a struct
device pointer as argument, why waste cycles doing pointer math just to
go back to the same struct device pointer on the next call ?
Dmitry Torokhov July 29, 2013, 8:40 p.m. UTC | #6
On Monday, July 29, 2013 11:36:05 PM Felipe Balbi wrote:
> Hi,
> 
> On Mon, Jul 29, 2013 at 12:59:23PM -0700, Dmitry Torokhov wrote:
> > > > > > @@ -439,12 +444,50 @@ static const struct of_device_id
> > > > > > omap_keypad_dt_match[] = {>
> > > > > > 
> > > > > >  MODULE_DEVICE_TABLE(of, omap_keypad_dt_match);
> > > > > >  #endif
> > > > > > 
> > > > > > +#ifdef CONFIG_PM_SLEEP
> > > > > > +static int omap4_keypad_suspend(struct device *dev)
> > > > > > +{
> > > > > > +	struct platform_device *pdev = to_platform_device(dev);
> > > > > 
> > > > > you don't need to access the platform_device...
> > > > > 
> > > > > > +	struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
> > > > > 
> > > > > ... since this can become:
> > > > > 	struct omap4_keypad *keypad_data = dev_get_drvdata(dev);
> > > > 
> > > > No, please use correct accessors for the objects. Platform drivers
> > > > deal
> > > > with platform devices and I prefer using platform_get_drvdata() on
> > > > them.
> > > 
> > > The argument to this function is a struct device, you prefer to do some
> > > pointer math to find the containing pdev, then deref that back to dev,
> > > then to struct device_private and further to driver_data ?
> > > 
> > > Sounds like a waste of time IMHO. You already have the device pointer
> > > anyway, why would you go through the trouble of calculating the
> > > offsets for the containing struct platform_device ?
> > 
> > This assumes knowledge of dev_get_drvdata() implementation and assumption
> > that it will stay the same. Unless I hear from device core guys that
> > <bus>_{get|set}_drvdata() methods are obsolete and will be eventually
> > removed I will require proper accessors being used.
> 
> they're not obsolete and will never be removed. They're nothing but
> helpers though. Instead of calling:
> 
> 	dev_set_drvdata(&pdev->dev);
> 
> you call:
> 
> 	platform_set_drvdata(pdev);
> 
> same is valid for every single bus, but in the end they all just wrap a
> call dev_{set,get}_drvdata() internally. If you already have a struct
> device pointer as argument, why waste cycles doing pointer math just to
> go back to the same struct device pointer on the next call ?

Because I do not want to rely on the fact that what my driver set up
with platform_set_drvdata(pdev, XXX) is the same as what dev_get_drvdata()
will return *in the current implementation*. Software layers and all
that...
Felipe Balbi July 31, 2013, 9:49 a.m. UTC | #7
On Mon, Jul 29, 2013 at 01:40:28PM -0700, Dmitry Torokhov wrote:
> On Monday, July 29, 2013 11:36:05 PM Felipe Balbi wrote:
> > Hi,
> > 
> > On Mon, Jul 29, 2013 at 12:59:23PM -0700, Dmitry Torokhov wrote:
> > > > > > > @@ -439,12 +444,50 @@ static const struct of_device_id
> > > > > > > omap_keypad_dt_match[] = {>
> > > > > > > 
> > > > > > >  MODULE_DEVICE_TABLE(of, omap_keypad_dt_match);
> > > > > > >  #endif
> > > > > > > 
> > > > > > > +#ifdef CONFIG_PM_SLEEP
> > > > > > > +static int omap4_keypad_suspend(struct device *dev)
> > > > > > > +{
> > > > > > > +	struct platform_device *pdev = to_platform_device(dev);
> > > > > > 
> > > > > > you don't need to access the platform_device...
> > > > > > 
> > > > > > > +	struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
> > > > > > 
> > > > > > ... since this can become:
> > > > > > 	struct omap4_keypad *keypad_data = dev_get_drvdata(dev);
> > > > > 
> > > > > No, please use correct accessors for the objects. Platform drivers
> > > > > deal
> > > > > with platform devices and I prefer using platform_get_drvdata() on
> > > > > them.
> > > > 
> > > > The argument to this function is a struct device, you prefer to do some
> > > > pointer math to find the containing pdev, then deref that back to dev,
> > > > then to struct device_private and further to driver_data ?
> > > > 
> > > > Sounds like a waste of time IMHO. You already have the device pointer
> > > > anyway, why would you go through the trouble of calculating the
> > > > offsets for the containing struct platform_device ?
> > > 
> > > This assumes knowledge of dev_get_drvdata() implementation and assumption
> > > that it will stay the same. Unless I hear from device core guys that
> > > <bus>_{get|set}_drvdata() methods are obsolete and will be eventually
> > > removed I will require proper accessors being used.
> > 
> > they're not obsolete and will never be removed. They're nothing but
> > helpers though. Instead of calling:
> > 
> > 	dev_set_drvdata(&pdev->dev);
> > 
> > you call:
> > 
> > 	platform_set_drvdata(pdev);
> > 
> > same is valid for every single bus, but in the end they all just wrap a
> > call dev_{set,get}_drvdata() internally. If you already have a struct
> > device pointer as argument, why waste cycles doing pointer math just to
> > go back to the same struct device pointer on the next call ?
> 
> Because I do not want to rely on the fact that what my driver set up
> with platform_set_drvdata(pdev, XXX) is the same as what dev_get_drvdata()
> will return *in the current implementation*. Software layers and all
> that...

fair enough, your call. It's a waste of CPU anyway.
diff mbox

Patch

diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
index 0244262..feab00f 100644
--- a/drivers/input/keyboard/omap4-keypad.c
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -74,6 +74,7 @@  struct omap4_keypad {
 	struct input_dev *input;
 
 	void __iomem *base;
+	bool irq_wake_enabled;
 	unsigned int irq;
 
 	unsigned int rows;
@@ -380,6 +381,7 @@  static int omap4_keypad_probe(struct platform_device *pdev)
 		goto err_free_input;
 	}
 
+	device_init_wakeup(&pdev->dev, true);
 	pm_runtime_put_sync(&pdev->dev);
 
 	error = input_register_device(keypad_data->input);
@@ -393,6 +395,7 @@  static int omap4_keypad_probe(struct platform_device *pdev)
 
 err_pm_disable:
 	pm_runtime_disable(&pdev->dev);
+	device_init_wakeup(&pdev->dev, false);
 	free_irq(keypad_data->irq, keypad_data);
 err_free_keymap:
 	kfree(keypad_data->keymap);
@@ -418,6 +421,8 @@  static int omap4_keypad_remove(struct platform_device *pdev)
 
 	pm_runtime_disable(&pdev->dev);
 
+	device_init_wakeup(&pdev->dev, false);
+
 	input_unregister_device(keypad_data->input);
 
 	iounmap(keypad_data->base);
@@ -439,12 +444,50 @@  static const struct of_device_id omap_keypad_dt_match[] = {
 MODULE_DEVICE_TABLE(of, omap_keypad_dt_match);
 #endif
 
+#ifdef CONFIG_PM_SLEEP
+static int omap4_keypad_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
+	int error;
+
+	if (device_may_wakeup(&pdev->dev)) {
+		error = enable_irq_wake(keypad_data->irq);
+		if (!error)
+			keypad_data->irq_wake_enabled = true;
+	}
+
+	return 0;
+}
+
+static int omap4_keypad_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
+
+	if (device_may_wakeup(&pdev->dev) && keypad_data->irq_wake_enabled) {
+		disable_irq_wake(keypad_data->irq);
+		keypad_data->irq_wake_enabled = false;
+	}
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(omap4_keypad_pm_ops, omap4_keypad_suspend,
+				omap4_keypad_resume);
+
+#define OMAP4_KEYPAD_PM_OPS (&omap4_keypad_pm_ops)
+#else
+#define OMAP4_KEYPAD_PM_OPS NULL
+#endif
+
 static struct platform_driver omap4_keypad_driver = {
 	.probe		= omap4_keypad_probe,
 	.remove		= omap4_keypad_remove,
 	.driver		= {
 		.name	= "omap4-keypad",
 		.owner	= THIS_MODULE,
+		.pm	= OMAP4_KEYPAD_PM_OPS,
 		.of_match_table = of_match_ptr(omap_keypad_dt_match),
 	},
 };