diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-11-14 18:57:09 -0500 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-12-16 00:45:52 -0500 |
| commit | 97d86e07b71643086a6d22a60efae2fb095fa82a (patch) | |
| tree | 04596c88d56e27f94c69fa54ef3ed8fbff9d235b | |
| parent | 1d6a01365fd63fbf7c2709a183e2936728c8efad (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.txt | 10 | ||||
| -rw-r--r-- | drivers/input/keyboard/gpio_keys.c | 49 |
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: | |||
| 10 | Each button (key) is represented as a sub-node of "gpio-keys": | 10 | Each button (key) is represented as a sub-node of "gpio-keys": |
| 11 | Subnode properties: | 11 | Subnode 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 | ||
| 16 | Required mutual exclusive subnode-properties: | 18 | Note that either "interrupts" or "gpios" properties can be omitted, but not |
| 17 | - gpios: OF device-tree gpio specification. | 19 | both at the same time. Specifying both properties is allowed. |
| 18 | - interrupts: the interrupt line for that input | ||
| 19 | 20 | ||
| 20 | Optional subnode-properties: | 21 | Optional 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 | ||
| 27 | Example nodes: | 31 | Example 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; |
