intrpt.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /*
  2. * intrpt.c - Handling GPIO with interrupts
  3. *
  4. * Based upon the RPi example by Stefan Wendler (devnull@kaltpost.de)
  5. * from:
  6. * https://github.com/wendlers/rpi-kmod-samples
  7. *
  8. * Press one button to turn on a LED and another to turn it off.
  9. */
  10. #include <linux/gpio.h>
  11. #include <linux/interrupt.h>
  12. #include <linux/kernel.h> /* for ARRAY_SIZE() */
  13. #include <linux/module.h>
  14. #include <linux/printk.h>
  15. static int button_irqs[] = { -1, -1 };
  16. /* Define GPIOs for LEDs.
  17. * TODO: Change the numbers for the GPIO on your board.
  18. */
  19. static struct gpio leds[] = { { 4, GPIOF_OUT_INIT_LOW, "LED 1" } };
  20. /* Define GPIOs for BUTTONS
  21. * TODO: Change the numbers for the GPIO on your board.
  22. */
  23. static struct gpio buttons[] = { { 17, GPIOF_IN, "LED 1 ON BUTTON" },
  24. { 18, GPIOF_IN, "LED 1 OFF BUTTON" } };
  25. /* interrupt function triggered when a button is pressed. */
  26. static irqreturn_t button_isr(int irq, void *data)
  27. {
  28. /* first button */
  29. if (irq == button_irqs[0] && !gpio_get_value(leds[0].gpio))
  30. gpio_set_value(leds[0].gpio, 1);
  31. /* second button */
  32. else if (irq == button_irqs[1] && gpio_get_value(leds[0].gpio))
  33. gpio_set_value(leds[0].gpio, 0);
  34. return IRQ_HANDLED;
  35. }
  36. static int __init intrpt_init(void)
  37. {
  38. int ret = 0;
  39. pr_info("%s\n", __func__);
  40. /* register LED gpios */
  41. ret = gpio_request_array(leds, ARRAY_SIZE(leds));
  42. if (ret) {
  43. pr_err("Unable to request GPIOs for LEDs: %d\n", ret);
  44. return ret;
  45. }
  46. /* register BUTTON gpios */
  47. ret = gpio_request_array(buttons, ARRAY_SIZE(buttons));
  48. if (ret) {
  49. pr_err("Unable to request GPIOs for BUTTONs: %d\n", ret);
  50. goto fail1;
  51. }
  52. pr_info("Current button1 value: %d\n", gpio_get_value(buttons[0].gpio));
  53. ret = gpio_to_irq(buttons[0].gpio);
  54. if (ret < 0) {
  55. pr_err("Unable to request IRQ: %d\n", ret);
  56. goto fail2;
  57. }
  58. button_irqs[0] = ret;
  59. pr_info("Successfully requested BUTTON1 IRQ # %d\n", button_irqs[0]);
  60. ret = request_irq(button_irqs[0], button_isr,
  61. IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
  62. "gpiomod#button1", NULL);
  63. if (ret) {
  64. pr_err("Unable to request IRQ: %d\n", ret);
  65. goto fail2;
  66. }
  67. ret = gpio_to_irq(buttons[1].gpio);
  68. if (ret < 0) {
  69. pr_err("Unable to request IRQ: %d\n", ret);
  70. goto fail2;
  71. }
  72. button_irqs[1] = ret;
  73. pr_info("Successfully requested BUTTON2 IRQ # %d\n", button_irqs[1]);
  74. ret = request_irq(button_irqs[1], button_isr,
  75. IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
  76. "gpiomod#button2", NULL);
  77. if (ret) {
  78. pr_err("Unable to request IRQ: %d\n", ret);
  79. goto fail3;
  80. }
  81. return 0;
  82. /* cleanup what has been setup so far */
  83. fail3:
  84. free_irq(button_irqs[0], NULL);
  85. fail2:
  86. gpio_free_array(buttons, ARRAY_SIZE(leds));
  87. fail1:
  88. gpio_free_array(leds, ARRAY_SIZE(leds));
  89. return ret;
  90. }
  91. static void __exit intrpt_exit(void)
  92. {
  93. int i;
  94. pr_info("%s\n", __func__);
  95. /* free irqs */
  96. free_irq(button_irqs[0], NULL);
  97. free_irq(button_irqs[1], NULL);
  98. /* turn all LEDs off */
  99. for (i = 0; i < ARRAY_SIZE(leds); i++)
  100. gpio_set_value(leds[i].gpio, 0);
  101. /* unregister */
  102. gpio_free_array(leds, ARRAY_SIZE(leds));
  103. gpio_free_array(buttons, ARRAY_SIZE(buttons));
  104. }
  105. module_init(intrpt_init);
  106. module_exit(intrpt_exit);
  107. MODULE_LICENSE("GPL");
  108. MODULE_DESCRIPTION("Handle some GPIO interrupts");