1
0

intrpt.c 3.4 KB

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