diff options
Diffstat (limited to 'drivers/input/keyboard/gpio_keys.c')
-rw-r--r-- | drivers/input/keyboard/gpio_keys.c | 166 |
1 files changed, 139 insertions, 27 deletions
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 6e6145b9a4c1..ce281d152275 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * Driver for keys on GPIO lines capable of generating interrupts. | 2 | * Driver for keys on GPIO lines capable of generating interrupts. |
3 | * | 3 | * |
4 | * Copyright 2005 Phil Blundell | 4 | * Copyright 2005 Phil Blundell |
5 | * Copyright 2010, 2011 David Jander <david@protonic.nl> | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -25,6 +26,8 @@ | |||
25 | #include <linux/gpio_keys.h> | 26 | #include <linux/gpio_keys.h> |
26 | #include <linux/workqueue.h> | 27 | #include <linux/workqueue.h> |
27 | #include <linux/gpio.h> | 28 | #include <linux/gpio.h> |
29 | #include <linux/of_platform.h> | ||
30 | #include <linux/of_gpio.h> | ||
28 | 31 | ||
29 | struct gpio_button_data { | 32 | struct gpio_button_data { |
30 | struct gpio_keys_button *button; | 33 | struct gpio_keys_button *button; |
@@ -415,7 +418,7 @@ static int __devinit gpio_keys_setup_key(struct platform_device *pdev, | |||
415 | if (!button->can_disable) | 418 | if (!button->can_disable) |
416 | irqflags |= IRQF_SHARED; | 419 | irqflags |= IRQF_SHARED; |
417 | 420 | ||
418 | error = request_any_context_irq(irq, gpio_keys_isr, irqflags, desc, bdata); | 421 | error = request_threaded_irq(irq, NULL, gpio_keys_isr, irqflags, desc, bdata); |
419 | if (error < 0) { | 422 | if (error < 0) { |
420 | dev_err(dev, "Unable to claim irq %d; error %d\n", | 423 | dev_err(dev, "Unable to claim irq %d; error %d\n", |
421 | irq, error); | 424 | irq, error); |
@@ -445,15 +448,120 @@ static void gpio_keys_close(struct input_dev *input) | |||
445 | ddata->disable(input->dev.parent); | 448 | ddata->disable(input->dev.parent); |
446 | } | 449 | } |
447 | 450 | ||
451 | /* | ||
452 | * Handlers for alternative sources of platform_data | ||
453 | */ | ||
454 | #ifdef CONFIG_OF | ||
455 | /* | ||
456 | * Translate OpenFirmware node properties into platform_data | ||
457 | */ | ||
458 | static int gpio_keys_get_devtree_pdata(struct device *dev, | ||
459 | struct gpio_keys_platform_data *pdata) | ||
460 | { | ||
461 | struct device_node *node, *pp; | ||
462 | int i; | ||
463 | struct gpio_keys_button *buttons; | ||
464 | const u32 *reg; | ||
465 | int len; | ||
466 | |||
467 | node = dev->of_node; | ||
468 | if (node == NULL) | ||
469 | return -ENODEV; | ||
470 | |||
471 | memset(pdata, 0, sizeof *pdata); | ||
472 | |||
473 | pdata->rep = !!of_get_property(node, "autorepeat", &len); | ||
474 | |||
475 | /* First count the subnodes */ | ||
476 | pdata->nbuttons = 0; | ||
477 | pp = NULL; | ||
478 | while ((pp = of_get_next_child(node, pp))) | ||
479 | pdata->nbuttons++; | ||
480 | |||
481 | if (pdata->nbuttons == 0) | ||
482 | return -ENODEV; | ||
483 | |||
484 | buttons = kzalloc(pdata->nbuttons * (sizeof *buttons), GFP_KERNEL); | ||
485 | if (!buttons) | ||
486 | return -ENODEV; | ||
487 | |||
488 | pp = NULL; | ||
489 | i = 0; | ||
490 | while ((pp = of_get_next_child(node, pp))) { | ||
491 | enum of_gpio_flags flags; | ||
492 | |||
493 | if (!of_find_property(pp, "gpios", NULL)) { | ||
494 | pdata->nbuttons--; | ||
495 | dev_warn(dev, "Found button without gpios\n"); | ||
496 | continue; | ||
497 | } | ||
498 | buttons[i].gpio = of_get_gpio_flags(pp, 0, &flags); | ||
499 | buttons[i].active_low = flags & OF_GPIO_ACTIVE_LOW; | ||
500 | |||
501 | reg = of_get_property(pp, "linux,code", &len); | ||
502 | if (!reg) { | ||
503 | dev_err(dev, "Button without keycode: 0x%x\n", buttons[i].gpio); | ||
504 | goto out_fail; | ||
505 | } | ||
506 | buttons[i].code = be32_to_cpup(reg); | ||
507 | |||
508 | buttons[i].desc = of_get_property(pp, "label", &len); | ||
509 | |||
510 | reg = of_get_property(pp, "linux,input-type", &len); | ||
511 | buttons[i].type = reg ? be32_to_cpup(reg) : EV_KEY; | ||
512 | |||
513 | buttons[i].wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); | ||
514 | |||
515 | reg = of_get_property(pp, "debounce-interval", &len); | ||
516 | buttons[i].debounce_interval = reg ? be32_to_cpup(reg) : 5; | ||
517 | |||
518 | i++; | ||
519 | } | ||
520 | |||
521 | pdata->buttons = buttons; | ||
522 | |||
523 | return 0; | ||
524 | |||
525 | out_fail: | ||
526 | kfree(buttons); | ||
527 | return -ENODEV; | ||
528 | } | ||
529 | |||
530 | static struct of_device_id gpio_keys_of_match[] = { | ||
531 | { .compatible = "gpio-keys", }, | ||
532 | { }, | ||
533 | }; | ||
534 | MODULE_DEVICE_TABLE(of, gpio_keys_of_match); | ||
535 | |||
536 | #else | ||
537 | |||
538 | static int gpio_keys_get_devtree_pdata(struct device *dev, | ||
539 | struct gpio_keys_platform_data *altp) | ||
540 | { | ||
541 | return -ENODEV; | ||
542 | } | ||
543 | |||
544 | #define gpio_keys_of_match NULL | ||
545 | |||
546 | #endif | ||
547 | |||
448 | static int __devinit gpio_keys_probe(struct platform_device *pdev) | 548 | static int __devinit gpio_keys_probe(struct platform_device *pdev) |
449 | { | 549 | { |
450 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | 550 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; |
451 | struct gpio_keys_drvdata *ddata; | 551 | struct gpio_keys_drvdata *ddata; |
452 | struct device *dev = &pdev->dev; | 552 | struct device *dev = &pdev->dev; |
553 | struct gpio_keys_platform_data alt_pdata; | ||
453 | struct input_dev *input; | 554 | struct input_dev *input; |
454 | int i, error; | 555 | int i, error; |
455 | int wakeup = 0; | 556 | int wakeup = 0; |
456 | 557 | ||
558 | if (!pdata) { | ||
559 | error = gpio_keys_get_devtree_pdata(dev, &alt_pdata); | ||
560 | if (error) | ||
561 | return error; | ||
562 | pdata = &alt_pdata; | ||
563 | } | ||
564 | |||
457 | ddata = kzalloc(sizeof(struct gpio_keys_drvdata) + | 565 | ddata = kzalloc(sizeof(struct gpio_keys_drvdata) + |
458 | pdata->nbuttons * sizeof(struct gpio_button_data), | 566 | pdata->nbuttons * sizeof(struct gpio_button_data), |
459 | GFP_KERNEL); | 567 | GFP_KERNEL); |
@@ -544,13 +652,15 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
544 | fail1: | 652 | fail1: |
545 | input_free_device(input); | 653 | input_free_device(input); |
546 | kfree(ddata); | 654 | kfree(ddata); |
655 | /* If we have no platform_data, we allocated buttons dynamically. */ | ||
656 | if (!pdev->dev.platform_data) | ||
657 | kfree(pdata->buttons); | ||
547 | 658 | ||
548 | return error; | 659 | return error; |
549 | } | 660 | } |
550 | 661 | ||
551 | static int __devexit gpio_keys_remove(struct platform_device *pdev) | 662 | static int __devexit gpio_keys_remove(struct platform_device *pdev) |
552 | { | 663 | { |
553 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | ||
554 | struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); | 664 | struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); |
555 | struct input_dev *input = ddata->input; | 665 | struct input_dev *input = ddata->input; |
556 | int i; | 666 | int i; |
@@ -559,31 +669,39 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
559 | 669 | ||
560 | device_init_wakeup(&pdev->dev, 0); | 670 | device_init_wakeup(&pdev->dev, 0); |
561 | 671 | ||
562 | for (i = 0; i < pdata->nbuttons; i++) { | 672 | for (i = 0; i < ddata->n_buttons; i++) { |
563 | int irq = gpio_to_irq(pdata->buttons[i].gpio); | 673 | int irq = gpio_to_irq(ddata->data[i].button->gpio); |
564 | free_irq(irq, &ddata->data[i]); | 674 | free_irq(irq, &ddata->data[i]); |
565 | if (ddata->data[i].timer_debounce) | 675 | if (ddata->data[i].timer_debounce) |
566 | del_timer_sync(&ddata->data[i].timer); | 676 | del_timer_sync(&ddata->data[i].timer); |
567 | cancel_work_sync(&ddata->data[i].work); | 677 | cancel_work_sync(&ddata->data[i].work); |
568 | gpio_free(pdata->buttons[i].gpio); | 678 | gpio_free(ddata->data[i].button->gpio); |
569 | } | 679 | } |
570 | 680 | ||
571 | input_unregister_device(input); | 681 | input_unregister_device(input); |
572 | 682 | ||
683 | /* | ||
684 | * If we had no platform_data, we allocated buttons dynamically, and | ||
685 | * must free them here. ddata->data[0].button is the pointer to the | ||
686 | * beginning of the allocated array. | ||
687 | */ | ||
688 | if (!pdev->dev.platform_data) | ||
689 | kfree(ddata->data[0].button); | ||
690 | |||
691 | kfree(ddata); | ||
692 | |||
573 | return 0; | 693 | return 0; |
574 | } | 694 | } |
575 | 695 | ||
576 | 696 | #ifdef CONFIG_PM_SLEEP | |
577 | #ifdef CONFIG_PM | ||
578 | static int gpio_keys_suspend(struct device *dev) | 697 | static int gpio_keys_suspend(struct device *dev) |
579 | { | 698 | { |
580 | struct platform_device *pdev = to_platform_device(dev); | 699 | struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); |
581 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | ||
582 | int i; | 700 | int i; |
583 | 701 | ||
584 | if (device_may_wakeup(&pdev->dev)) { | 702 | if (device_may_wakeup(dev)) { |
585 | for (i = 0; i < pdata->nbuttons; i++) { | 703 | for (i = 0; i < ddata->n_buttons; i++) { |
586 | struct gpio_keys_button *button = &pdata->buttons[i]; | 704 | struct gpio_keys_button *button = ddata->data[i].button; |
587 | if (button->wakeup) { | 705 | if (button->wakeup) { |
588 | int irq = gpio_to_irq(button->gpio); | 706 | int irq = gpio_to_irq(button->gpio); |
589 | enable_irq_wake(irq); | 707 | enable_irq_wake(irq); |
@@ -596,15 +714,13 @@ static int gpio_keys_suspend(struct device *dev) | |||
596 | 714 | ||
597 | static int gpio_keys_resume(struct device *dev) | 715 | static int gpio_keys_resume(struct device *dev) |
598 | { | 716 | { |
599 | struct platform_device *pdev = to_platform_device(dev); | 717 | struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); |
600 | struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); | ||
601 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | ||
602 | int i; | 718 | int i; |
603 | 719 | ||
604 | for (i = 0; i < pdata->nbuttons; i++) { | 720 | for (i = 0; i < ddata->n_buttons; i++) { |
605 | 721 | ||
606 | struct gpio_keys_button *button = &pdata->buttons[i]; | 722 | struct gpio_keys_button *button = ddata->data[i].button; |
607 | if (button->wakeup && device_may_wakeup(&pdev->dev)) { | 723 | if (button->wakeup && device_may_wakeup(dev)) { |
608 | int irq = gpio_to_irq(button->gpio); | 724 | int irq = gpio_to_irq(button->gpio); |
609 | disable_irq_wake(irq); | 725 | disable_irq_wake(irq); |
610 | } | 726 | } |
@@ -615,22 +731,18 @@ static int gpio_keys_resume(struct device *dev) | |||
615 | 731 | ||
616 | return 0; | 732 | return 0; |
617 | } | 733 | } |
618 | |||
619 | static const struct dev_pm_ops gpio_keys_pm_ops = { | ||
620 | .suspend = gpio_keys_suspend, | ||
621 | .resume = gpio_keys_resume, | ||
622 | }; | ||
623 | #endif | 734 | #endif |
624 | 735 | ||
736 | static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume); | ||
737 | |||
625 | static struct platform_driver gpio_keys_device_driver = { | 738 | static struct platform_driver gpio_keys_device_driver = { |
626 | .probe = gpio_keys_probe, | 739 | .probe = gpio_keys_probe, |
627 | .remove = __devexit_p(gpio_keys_remove), | 740 | .remove = __devexit_p(gpio_keys_remove), |
628 | .driver = { | 741 | .driver = { |
629 | .name = "gpio-keys", | 742 | .name = "gpio-keys", |
630 | .owner = THIS_MODULE, | 743 | .owner = THIS_MODULE, |
631 | #ifdef CONFIG_PM | ||
632 | .pm = &gpio_keys_pm_ops, | 744 | .pm = &gpio_keys_pm_ops, |
633 | #endif | 745 | .of_match_table = gpio_keys_of_match, |
634 | } | 746 | } |
635 | }; | 747 | }; |
636 | 748 | ||
@@ -644,10 +756,10 @@ static void __exit gpio_keys_exit(void) | |||
644 | platform_driver_unregister(&gpio_keys_device_driver); | 756 | platform_driver_unregister(&gpio_keys_device_driver); |
645 | } | 757 | } |
646 | 758 | ||
647 | module_init(gpio_keys_init); | 759 | late_initcall(gpio_keys_init); |
648 | module_exit(gpio_keys_exit); | 760 | module_exit(gpio_keys_exit); |
649 | 761 | ||
650 | MODULE_LICENSE("GPL"); | 762 | MODULE_LICENSE("GPL"); |
651 | MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>"); | 763 | MODULE_AUTHOR("Phil Blundell <pb@handhelds.org>"); |
652 | MODULE_DESCRIPTION("Keyboard driver for CPU GPIOs"); | 764 | MODULE_DESCRIPTION("Keyboard driver for GPIOs"); |
653 | MODULE_ALIAS("platform:gpio-keys"); | 765 | MODULE_ALIAS("platform:gpio-keys"); |