aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorJeffy Chen <jeffy.chen@rock-chips.com>2018-03-08 19:03:27 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2018-03-14 13:13:22 -0400
commit83fc580dcc2f0f36114477c4ac7adbe5c32329a3 (patch)
tree848ad4e17ccb5afa3e056de894955b4b6efd28d2 /drivers/input
parent7085123333e2ee2686086fc49bc3117bacd86105 (diff)
Input: gpio-keys - add support for wakeup event action
Add support for specifying event actions to trigger wakeup when using the gpio-keys input device as a wakeup source. This would allow the device to configure when to wakeup the system. For example a gpio-keys input device for pen insert, may only want to wakeup the system when ejecting the pen. Suggested-by: Brian Norris <briannorris@chromium.org> Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> Reviewed-by: Rob Herring <robh@kernel.org> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/keyboard/gpio_keys.c145
1 files changed, 131 insertions, 14 deletions
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 87e613dc33b8..052e37675086 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -30,6 +30,7 @@
30#include <linux/of.h> 30#include <linux/of.h>
31#include <linux/of_irq.h> 31#include <linux/of_irq.h>
32#include <linux/spinlock.h> 32#include <linux/spinlock.h>
33#include <dt-bindings/input/gpio-keys.h>
33 34
34struct gpio_button_data { 35struct gpio_button_data {
35 const struct gpio_keys_button *button; 36 const struct gpio_keys_button *button;
@@ -45,6 +46,7 @@ struct gpio_button_data {
45 unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */ 46 unsigned int software_debounce; /* in msecs, for GPIO-driven buttons */
46 47
47 unsigned int irq; 48 unsigned int irq;
49 unsigned int wakeup_trigger_type;
48 spinlock_t lock; 50 spinlock_t lock;
49 bool disabled; 51 bool disabled;
50 bool key_pressed; 52 bool key_pressed;
@@ -540,6 +542,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
540 } 542 }
541 543
542 if (bdata->gpiod) { 544 if (bdata->gpiod) {
545 bool active_low = gpiod_is_active_low(bdata->gpiod);
546
543 if (button->debounce_interval) { 547 if (button->debounce_interval) {
544 error = gpiod_set_debounce(bdata->gpiod, 548 error = gpiod_set_debounce(bdata->gpiod,
545 button->debounce_interval * 1000); 549 button->debounce_interval * 1000);
@@ -568,6 +572,24 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
568 isr = gpio_keys_gpio_isr; 572 isr = gpio_keys_gpio_isr;
569 irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; 573 irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
570 574
575 switch (button->wakeup_event_action) {
576 case EV_ACT_ASSERTED:
577 bdata->wakeup_trigger_type = active_low ?
578 IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING;
579 break;
580 case EV_ACT_DEASSERTED:
581 bdata->wakeup_trigger_type = active_low ?
582 IRQ_TYPE_EDGE_RISING : IRQ_TYPE_EDGE_FALLING;
583 break;
584 case EV_ACT_ANY:
585 /* fall through */
586 default:
587 /*
588 * For other cases, we are OK letting suspend/resume
589 * not reconfigure the trigger type.
590 */
591 break;
592 }
571 } else { 593 } else {
572 if (!button->irq) { 594 if (!button->irq) {
573 dev_err(dev, "Found button without gpio or irq\n"); 595 dev_err(dev, "Found button without gpio or irq\n");
@@ -586,6 +608,11 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
586 608
587 isr = gpio_keys_irq_isr; 609 isr = gpio_keys_irq_isr;
588 irqflags = 0; 610 irqflags = 0;
611
612 /*
613 * For IRQ buttons, there is no interrupt for release.
614 * So we don't need to reconfigure the trigger type for wakeup.
615 */
589 } 616 }
590 617
591 bdata->code = &ddata->keymap[idx]; 618 bdata->code = &ddata->keymap[idx];
@@ -718,6 +745,9 @@ gpio_keys_get_devtree_pdata(struct device *dev)
718 /* legacy name */ 745 /* legacy name */
719 fwnode_property_read_bool(child, "gpio-key,wakeup"); 746 fwnode_property_read_bool(child, "gpio-key,wakeup");
720 747
748 fwnode_property_read_u32(child, "wakeup-event-action",
749 &button->wakeup_event_action);
750
721 button->can_disable = 751 button->can_disable =
722 fwnode_property_read_bool(child, "linux,can-disable"); 752 fwnode_property_read_bool(child, "linux,can-disable");
723 753
@@ -845,19 +875,112 @@ static int gpio_keys_probe(struct platform_device *pdev)
845 return 0; 875 return 0;
846} 876}
847 877
878static int __maybe_unused
879gpio_keys_button_enable_wakeup(struct gpio_button_data *bdata)
880{
881 int error;
882
883 error = enable_irq_wake(bdata->irq);
884 if (error) {
885 dev_err(bdata->input->dev.parent,
886 "failed to configure IRQ %d as wakeup source: %d\n",
887 bdata->irq, error);
888 return error;
889 }
890
891 if (bdata->wakeup_trigger_type) {
892 error = irq_set_irq_type(bdata->irq,
893 bdata->wakeup_trigger_type);
894 if (error) {
895 dev_err(bdata->input->dev.parent,
896 "failed to set wakeup trigger %08x for IRQ %d: %d\n",
897 bdata->wakeup_trigger_type, bdata->irq, error);
898 disable_irq_wake(bdata->irq);
899 return error;
900 }
901 }
902
903 return 0;
904}
905
906static void __maybe_unused
907gpio_keys_button_disable_wakeup(struct gpio_button_data *bdata)
908{
909 int error;
910
911 /*
912 * The trigger type is always both edges for gpio-based keys and we do
913 * not support changing wakeup trigger for interrupt-based keys.
914 */
915 if (bdata->wakeup_trigger_type) {
916 error = irq_set_irq_type(bdata->irq, IRQ_TYPE_EDGE_BOTH);
917 if (error)
918 dev_warn(bdata->input->dev.parent,
919 "failed to restore interrupt trigger for IRQ %d: %d\n",
920 bdata->irq, error);
921 }
922
923 error = disable_irq_wake(bdata->irq);
924 if (error)
925 dev_warn(bdata->input->dev.parent,
926 "failed to disable IRQ %d as wake source: %d\n",
927 bdata->irq, error);
928}
929
930static int __maybe_unused
931gpio_keys_enable_wakeup(struct gpio_keys_drvdata *ddata)
932{
933 struct gpio_button_data *bdata;
934 int error;
935 int i;
936
937 for (i = 0; i < ddata->pdata->nbuttons; i++) {
938 bdata = &ddata->data[i];
939 if (bdata->button->wakeup) {
940 error = gpio_keys_button_enable_wakeup(bdata);
941 if (error)
942 goto err_out;
943 }
944 bdata->suspended = true;
945 }
946
947 return 0;
948
949err_out:
950 while (i--) {
951 bdata = &ddata->data[i];
952 if (bdata->button->wakeup)
953 gpio_keys_button_disable_wakeup(bdata);
954 bdata->suspended = false;
955 }
956
957 return error;
958}
959
960static void __maybe_unused
961gpio_keys_disable_wakeup(struct gpio_keys_drvdata *ddata)
962{
963 struct gpio_button_data *bdata;
964 int i;
965
966 for (i = 0; i < ddata->pdata->nbuttons; i++) {
967 bdata = &ddata->data[i];
968 bdata->suspended = false;
969 if (irqd_is_wakeup_set(irq_get_irq_data(bdata->irq)))
970 gpio_keys_button_disable_wakeup(bdata);
971 }
972}
973
848static int __maybe_unused gpio_keys_suspend(struct device *dev) 974static int __maybe_unused gpio_keys_suspend(struct device *dev)
849{ 975{
850 struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); 976 struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
851 struct input_dev *input = ddata->input; 977 struct input_dev *input = ddata->input;
852 int i; 978 int error;
853 979
854 if (device_may_wakeup(dev)) { 980 if (device_may_wakeup(dev)) {
855 for (i = 0; i < ddata->pdata->nbuttons; i++) { 981 error = gpio_keys_enable_wakeup(ddata);
856 struct gpio_button_data *bdata = &ddata->data[i]; 982 if (error)
857 if (bdata->button->wakeup) 983 return error;
858 enable_irq_wake(bdata->irq);
859 bdata->suspended = true;
860 }
861 } else { 984 } else {
862 mutex_lock(&input->mutex); 985 mutex_lock(&input->mutex);
863 if (input->users) 986 if (input->users)
@@ -873,15 +996,9 @@ static int __maybe_unused gpio_keys_resume(struct device *dev)
873 struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); 996 struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
874 struct input_dev *input = ddata->input; 997 struct input_dev *input = ddata->input;
875 int error = 0; 998 int error = 0;
876 int i;
877 999
878 if (device_may_wakeup(dev)) { 1000 if (device_may_wakeup(dev)) {
879 for (i = 0; i < ddata->pdata->nbuttons; i++) { 1001 gpio_keys_disable_wakeup(ddata);
880 struct gpio_button_data *bdata = &ddata->data[i];
881 if (bdata->button->wakeup)
882 disable_irq_wake(bdata->irq);
883 bdata->suspended = false;
884 }
885 } else { 1002 } else {
886 mutex_lock(&input->mutex); 1003 mutex_lock(&input->mutex);
887 if (input->users) 1004 if (input->users)