aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2014-11-14 18:57:09 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2014-12-16 00:45:52 -0500
commit97d86e07b71643086a6d22a60efae2fb095fa82a (patch)
tree04596c88d56e27f94c69fa54ef3ed8fbff9d235b
parent1d6a01365fd63fbf7c2709a183e2936728c8efad (diff)
Input: gpio_keys - allow separating gpio and irq in device tree
This change allows specify interrupt for buttons separately form gpio, potentially allowing to form several "clusters" of buttons on different interrupts. Button defined without both gpio and irq in device tree is a hared error instead of a warning now. Tested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
-rw-r--r--Documentation/devicetree/bindings/input/gpio-keys.txt10
-rw-r--r--drivers/input/keyboard/gpio_keys.c49
2 files changed, 33 insertions, 26 deletions
diff --git a/Documentation/devicetree/bindings/input/gpio-keys.txt b/Documentation/devicetree/bindings/input/gpio-keys.txt
index a4a38fcf2ed6..44b705767aca 100644
--- a/Documentation/devicetree/bindings/input/gpio-keys.txt
+++ b/Documentation/devicetree/bindings/input/gpio-keys.txt
@@ -10,12 +10,13 @@ Optional properties:
10Each button (key) is represented as a sub-node of "gpio-keys": 10Each button (key) is represented as a sub-node of "gpio-keys":
11Subnode properties: 11Subnode properties:
12 12
13 - gpios: OF device-tree gpio specification.
14 - interrupts: the interrupt line for that input.
13 - label: Descriptive name of the key. 15 - label: Descriptive name of the key.
14 - linux,code: Keycode to emit. 16 - linux,code: Keycode to emit.
15 17
16Required mutual exclusive subnode-properties: 18Note that either "interrupts" or "gpios" properties can be omitted, but not
17 - gpios: OF device-tree gpio specification. 19both at the same time. Specifying both properties is allowed.
18 - interrupts: the interrupt line for that input
19 20
20Optional subnode-properties: 21Optional subnode-properties:
21 - linux,input-type: Specify event type this button/key generates. 22 - linux,input-type: Specify event type this button/key generates.
@@ -23,6 +24,9 @@ Optional subnode-properties:
23 - debounce-interval: Debouncing interval time in milliseconds. 24 - debounce-interval: Debouncing interval time in milliseconds.
24 If not specified defaults to 5. 25 If not specified defaults to 5.
25 - gpio-key,wakeup: Boolean, button can wake-up the system. 26 - gpio-key,wakeup: Boolean, button can wake-up the system.
27 - linux,can-disable: Boolean, indicates that button is connected
28 to dedicated (not shared) interrupt which can be disabled to
29 suppress events from the button.
26 30
27Example nodes: 31Example nodes:
28 32
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index f44f05b70ee0..a5ece3ff19cb 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -470,15 +470,19 @@ static int gpio_keys_setup_key(struct platform_device *pdev,
470 button->debounce_interval; 470 button->debounce_interval;
471 } 471 }
472 472
473 irq = gpio_to_irq(button->gpio); 473 if (button->irq) {
474 if (irq < 0) { 474 bdata->irq = button->irq;
475 error = irq; 475 } else {
476 dev_err(dev, 476 irq = gpio_to_irq(button->gpio);
477 "Unable to get irq number for GPIO %d, error %d\n", 477 if (irq < 0) {
478 button->gpio, error); 478 error = irq;
479 return error; 479 dev_err(dev,
480 "Unable to get irq number for GPIO %d, error %d\n",
481 button->gpio, error);
482 return error;
483 }
484 bdata->irq = irq;
480 } 485 }
481 bdata->irq = irq;
482 486
483 INIT_WORK(&bdata->work, gpio_keys_gpio_work_func); 487 INIT_WORK(&bdata->work, gpio_keys_gpio_work_func);
484 setup_timer(&bdata->timer, 488 setup_timer(&bdata->timer,
@@ -618,33 +622,30 @@ gpio_keys_get_devtree_pdata(struct device *dev)
618 622
619 i = 0; 623 i = 0;
620 for_each_child_of_node(node, pp) { 624 for_each_child_of_node(node, pp) {
621 int gpio = -1;
622 enum of_gpio_flags flags; 625 enum of_gpio_flags flags;
623 626
624 button = &pdata->buttons[i++]; 627 button = &pdata->buttons[i++];
625 628
626 if (!of_find_property(pp, "gpios", NULL)) { 629 button->gpio = of_get_gpio_flags(pp, 0, &flags);
627 button->irq = irq_of_parse_and_map(pp, 0); 630 if (button->gpio < 0) {
628 if (button->irq == 0) { 631 error = button->gpio;
629 i--; 632 if (error != -ENOENT) {
630 pdata->nbuttons--;
631 dev_warn(dev, "Found button without gpios or irqs\n");
632 continue;
633 }
634 } else {
635 gpio = of_get_gpio_flags(pp, 0, &flags);
636 if (gpio < 0) {
637 error = gpio;
638 if (error != -EPROBE_DEFER) 633 if (error != -EPROBE_DEFER)
639 dev_err(dev, 634 dev_err(dev,
640 "Failed to get gpio flags, error: %d\n", 635 "Failed to get gpio flags, error: %d\n",
641 error); 636 error);
642 return ERR_PTR(error); 637 return ERR_PTR(error);
643 } 638 }
639 } else {
640 button->active_low = flags & OF_GPIO_ACTIVE_LOW;
644 } 641 }
645 642
646 button->gpio = gpio; 643 button->irq = irq_of_parse_and_map(pp, 0);
647 button->active_low = flags & OF_GPIO_ACTIVE_LOW; 644
645 if (!gpio_is_valid(button->gpio) && !button->irq) {
646 dev_err(dev, "Found button without gpios or irqs\n");
647 return ERR_PTR(-EINVAL);
648 }
648 649
649 if (of_property_read_u32(pp, "linux,code", &button->code)) { 650 if (of_property_read_u32(pp, "linux,code", &button->code)) {
650 dev_err(dev, "Button without keycode: 0x%x\n", 651 dev_err(dev, "Button without keycode: 0x%x\n",
@@ -659,6 +660,8 @@ gpio_keys_get_devtree_pdata(struct device *dev)
659 660
660 button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); 661 button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
661 662
663 button->can_disable = !!of_get_property(pp, "linux,can-disable", NULL);
664
662 if (of_property_read_u32(pp, "debounce-interval", 665 if (of_property_read_u32(pp, "debounce-interval",
663 &button->debounce_interval)) 666 &button->debounce_interval))
664 button->debounce_interval = 5; 667 button->debounce_interval = 5;