lps22hh_trigger.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /* ST Microelectronics LPS22HH pressure and temperature sensor
  2. *
  3. * Copyright (c) 2019 STMicroelectronics
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Datasheet:
  8. * https://www.st.com/resource/en/datasheet/lps22hh.pdf
  9. */
  10. #define DT_DRV_COMPAT st_lps22hh
  11. #include <kernel.h>
  12. #include <drivers/sensor.h>
  13. #include <drivers/gpio.h>
  14. #include <logging/log.h>
  15. #include "lps22hh.h"
  16. LOG_MODULE_DECLARE(LPS22HH, CONFIG_SENSOR_LOG_LEVEL);
  17. /**
  18. * lps22hh_enable_int - enable selected int pin to generate interrupt
  19. */
  20. static int lps22hh_enable_int(const struct device *dev, int enable)
  21. {
  22. struct lps22hh_data *lps22hh = dev->data;
  23. lps22hh_reg_t int_route;
  24. /* set interrupt */
  25. lps22hh_pin_int_route_get(lps22hh->ctx,
  26. &int_route.ctrl_reg3);
  27. int_route.ctrl_reg3.drdy = enable;
  28. return lps22hh_pin_int_route_set(lps22hh->ctx,
  29. &int_route.ctrl_reg3);
  30. }
  31. /**
  32. * lps22hh_trigger_set - link external trigger to event data ready
  33. */
  34. int lps22hh_trigger_set(const struct device *dev,
  35. const struct sensor_trigger *trig,
  36. sensor_trigger_handler_t handler)
  37. {
  38. struct lps22hh_data *lps22hh = dev->data;
  39. uint32_t raw_press;
  40. if (trig->chan == SENSOR_CHAN_ALL) {
  41. lps22hh->handler_drdy = handler;
  42. if (handler) {
  43. /* dummy read: re-trigger interrupt */
  44. if (lps22hh_pressure_raw_get(lps22hh->ctx,
  45. &raw_press) < 0) {
  46. LOG_DBG("Failed to read sample");
  47. return -EIO;
  48. }
  49. return lps22hh_enable_int(dev, 1);
  50. } else {
  51. return lps22hh_enable_int(dev, 0);
  52. }
  53. }
  54. return -ENOTSUP;
  55. }
  56. /**
  57. * lps22hh_handle_interrupt - handle the drdy event
  58. * read data and call handler if registered any
  59. */
  60. static void lps22hh_handle_interrupt(const struct device *dev)
  61. {
  62. struct lps22hh_data *lps22hh = dev->data;
  63. const struct lps22hh_config *cfg = dev->config;
  64. struct sensor_trigger drdy_trigger = {
  65. .type = SENSOR_TRIG_DATA_READY,
  66. };
  67. if (lps22hh->handler_drdy != NULL) {
  68. lps22hh->handler_drdy(dev, &drdy_trigger);
  69. }
  70. gpio_pin_interrupt_configure(lps22hh->gpio, cfg->drdy_pin,
  71. GPIO_INT_EDGE_TO_ACTIVE);
  72. }
  73. static void lps22hh_gpio_callback(const struct device *dev,
  74. struct gpio_callback *cb, uint32_t pins)
  75. {
  76. struct lps22hh_data *lps22hh =
  77. CONTAINER_OF(cb, struct lps22hh_data, gpio_cb);
  78. ARG_UNUSED(pins);
  79. const struct lps22hh_config *cfg = lps22hh->dev->config;
  80. gpio_pin_interrupt_configure(lps22hh->gpio, cfg->drdy_pin,
  81. GPIO_INT_DISABLE);
  82. #if defined(CONFIG_LPS22HH_TRIGGER_OWN_THREAD)
  83. k_sem_give(&lps22hh->gpio_sem);
  84. #elif defined(CONFIG_LPS22HH_TRIGGER_GLOBAL_THREAD)
  85. k_work_submit(&lps22hh->work);
  86. #endif /* CONFIG_LPS22HH_TRIGGER_OWN_THREAD */
  87. }
  88. #ifdef CONFIG_LPS22HH_TRIGGER_OWN_THREAD
  89. static void lps22hh_thread(struct lps22hh_data *lps22hh)
  90. {
  91. while (1) {
  92. k_sem_take(&lps22hh->gpio_sem, K_FOREVER);
  93. lps22hh_handle_interrupt(lps22hh->dev);
  94. }
  95. }
  96. #endif /* CONFIG_LPS22HH_TRIGGER_OWN_THREAD */
  97. #ifdef CONFIG_LPS22HH_TRIGGER_GLOBAL_THREAD
  98. static void lps22hh_work_cb(struct k_work *work)
  99. {
  100. struct lps22hh_data *lps22hh =
  101. CONTAINER_OF(work, struct lps22hh_data, work);
  102. lps22hh_handle_interrupt(lps22hh->dev);
  103. }
  104. #endif /* CONFIG_LPS22HH_TRIGGER_GLOBAL_THREAD */
  105. int lps22hh_init_interrupt(const struct device *dev)
  106. {
  107. struct lps22hh_data *lps22hh = dev->data;
  108. const struct lps22hh_config *cfg = dev->config;
  109. int ret;
  110. /* setup data ready gpio interrupt */
  111. lps22hh->gpio = device_get_binding(cfg->drdy_port);
  112. if (lps22hh->gpio == NULL) {
  113. LOG_DBG("Cannot get pointer to %s device", cfg->drdy_port);
  114. return -EINVAL;
  115. }
  116. #if defined(CONFIG_LPS22HH_TRIGGER_OWN_THREAD)
  117. k_sem_init(&lps22hh->gpio_sem, 0, K_SEM_MAX_LIMIT);
  118. k_thread_create(&lps22hh->thread, lps22hh->thread_stack,
  119. CONFIG_LPS22HH_THREAD_STACK_SIZE,
  120. (k_thread_entry_t)lps22hh_thread, lps22hh,
  121. NULL, NULL, K_PRIO_COOP(CONFIG_LPS22HH_THREAD_PRIORITY),
  122. 0, K_NO_WAIT);
  123. #elif defined(CONFIG_LPS22HH_TRIGGER_GLOBAL_THREAD)
  124. lps22hh->work.handler = lps22hh_work_cb;
  125. #endif /* CONFIG_LPS22HH_TRIGGER_OWN_THREAD */
  126. ret = gpio_pin_configure(lps22hh->gpio, cfg->drdy_pin,
  127. GPIO_INPUT | cfg->drdy_flags);
  128. if (ret < 0) {
  129. LOG_DBG("Could not configure gpio");
  130. return ret;
  131. }
  132. gpio_init_callback(&lps22hh->gpio_cb, lps22hh_gpio_callback,
  133. BIT(cfg->drdy_pin));
  134. if (gpio_add_callback(lps22hh->gpio, &lps22hh->gpio_cb) < 0) {
  135. LOG_DBG("Could not set gpio callback");
  136. return -EIO;
  137. }
  138. /* enable interrupt in pulse mode */
  139. if (lps22hh_int_notification_set(lps22hh->ctx,
  140. LPS22HH_INT_PULSED) < 0) {
  141. return -EIO;
  142. }
  143. return gpio_pin_interrupt_configure(lps22hh->gpio, cfg->drdy_pin,
  144. GPIO_INT_EDGE_TO_ACTIVE);
  145. }