Input: gpio-keys - add suspend/resume support

This patch adds suspend/resume support and enables wakeup from
gpio_keys buttons.

Signed-off-by: Anti Sullin <anti.sullin@artecdesign.ee>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index b3069bc..3d6820b 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -55,6 +55,7 @@
 	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
 	struct input_dev *input;
 	int i, error;
+	int wakeup = 0;
 
 	input = input_allocate_device();
 	if (!input)
@@ -100,6 +101,9 @@
 			goto fail;
 		}
 
+		if (button->wakeup)
+			wakeup = 1;
+
 		input_set_capability(input, type, button->code);
 	}
 
@@ -111,6 +115,8 @@
 		goto fail;
 	}
 
+	device_init_wakeup(&pdev->dev, wakeup);
+
 	return 0;
 
  fail:
@@ -129,6 +135,8 @@
 	struct input_dev *input = platform_get_drvdata(pdev);
 	int i;
 
+	device_init_wakeup(&pdev->dev, 0);
+
 	for (i = 0; i < pdata->nbuttons; i++) {
 		int irq = gpio_to_irq(pdata->buttons[i].gpio);
 		free_irq(irq, pdev);
@@ -139,9 +147,53 @@
 	return 0;
 }
 
+
+#ifdef CONFIG_PM
+static int gpio_keys_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+	int i;
+
+	if (device_may_wakeup(&pdev->dev)) {
+		for (i = 0; i < pdata->nbuttons; i++) {
+			struct gpio_keys_button *button = &pdata->buttons[i];
+			if (button->wakeup) {
+				int irq = gpio_to_irq(button->gpio);
+				enable_irq_wake(irq);
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int gpio_keys_resume(struct platform_device *pdev)
+{
+	struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
+	int i;
+
+	if (device_may_wakeup(&pdev->dev)) {
+		for (i = 0; i < pdata->nbuttons; i++) {
+			struct gpio_keys_button *button = &pdata->buttons[i];
+			if (button->wakeup) {
+				int irq = gpio_to_irq(button->gpio);
+				disable_irq_wake(irq);
+			}
+		}
+	}
+
+	return 0;
+}
+#else
+#define gpio_keys_suspend	NULL
+#define gpio_keys_resume	NULL
+#endif
+
 struct platform_driver gpio_keys_device_driver = {
 	.probe		= gpio_keys_probe,
 	.remove		= __devexit_p(gpio_keys_remove),
+	.suspend	= gpio_keys_suspend,
+	.resume		= gpio_keys_resume,
 	.driver		= {
 		.name	= "gpio-keys",
 	}
diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h
index 265d178..c6d3a9d 100644
--- a/include/linux/gpio_keys.h
+++ b/include/linux/gpio_keys.h
@@ -8,6 +8,7 @@
 	int active_low;
 	char *desc;
 	int type;		/* input event type (EV_KEY, EV_SW) */
+	int wakeup;		/* configure the button as a wake-up source */
 };
 
 struct gpio_keys_platform_data {