lis2dw12_trigger.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /* ST Microelectronics LIS2DW12 3-axis accelerometer driver
  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/lis2dw12.pdf
  9. */
  10. #define DT_DRV_COMPAT st_lis2dw12
  11. #include <kernel.h>
  12. #include <drivers/sensor.h>
  13. #include <drivers/gpio.h>
  14. #include <logging/log.h>
  15. #include "lis2dw12.h"
  16. LOG_MODULE_DECLARE(LIS2DW12, CONFIG_SENSOR_LOG_LEVEL);
  17. /**
  18. * lis2dw12_enable_int - enable selected int pin to generate interrupt
  19. */
  20. static int lis2dw12_enable_int(const struct device *dev,
  21. enum sensor_trigger_type type, int enable)
  22. {
  23. const struct lis2dw12_device_config *cfg = dev->config;
  24. stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
  25. lis2dw12_reg_t int_route;
  26. switch (type) {
  27. case SENSOR_TRIG_DATA_READY:
  28. if (cfg->int_pin == 1) {
  29. /* set interrupt for pin INT1 */
  30. lis2dw12_pin_int1_route_get(ctx,
  31. &int_route.ctrl4_int1_pad_ctrl);
  32. int_route.ctrl4_int1_pad_ctrl.int1_drdy = enable;
  33. return lis2dw12_pin_int1_route_set(ctx,
  34. &int_route.ctrl4_int1_pad_ctrl);
  35. } else {
  36. /* set interrupt for pin INT2 */
  37. lis2dw12_pin_int2_route_get(ctx,
  38. &int_route.ctrl5_int2_pad_ctrl);
  39. int_route.ctrl5_int2_pad_ctrl.int2_drdy = enable;
  40. return lis2dw12_pin_int2_route_set(ctx,
  41. &int_route.ctrl5_int2_pad_ctrl);
  42. }
  43. break;
  44. #ifdef CONFIG_LIS2DW12_TAP
  45. case SENSOR_TRIG_TAP:
  46. /* set interrupt for pin INT1 */
  47. lis2dw12_pin_int1_route_get(ctx,
  48. &int_route.ctrl4_int1_pad_ctrl);
  49. int_route.ctrl4_int1_pad_ctrl.int1_single_tap = enable;
  50. return lis2dw12_pin_int1_route_set(ctx,
  51. &int_route.ctrl4_int1_pad_ctrl);
  52. case SENSOR_TRIG_DOUBLE_TAP:
  53. /* set interrupt for pin INT1 */
  54. lis2dw12_pin_int1_route_get(ctx,
  55. &int_route.ctrl4_int1_pad_ctrl);
  56. int_route.ctrl4_int1_pad_ctrl.int1_tap = enable;
  57. return lis2dw12_pin_int1_route_set(ctx,
  58. &int_route.ctrl4_int1_pad_ctrl);
  59. #endif /* CONFIG_LIS2DW12_TAP */
  60. default:
  61. LOG_ERR("Unsupported trigger interrupt route %d", type);
  62. return -ENOTSUP;
  63. }
  64. }
  65. /**
  66. * lis2dw12_trigger_set - link external trigger to event data ready
  67. */
  68. int lis2dw12_trigger_set(const struct device *dev,
  69. const struct sensor_trigger *trig,
  70. sensor_trigger_handler_t handler)
  71. {
  72. const struct lis2dw12_device_config *cfg = dev->config;
  73. stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
  74. struct lis2dw12_data *lis2dw12 = dev->data;
  75. int16_t raw[3];
  76. int state = (handler != NULL) ? PROPERTY_ENABLE : PROPERTY_DISABLE;
  77. if (cfg->gpio_int.port == NULL) {
  78. LOG_ERR("trigger_set is not supported");
  79. return -ENOTSUP;
  80. }
  81. switch (trig->type) {
  82. case SENSOR_TRIG_DATA_READY:
  83. lis2dw12->drdy_handler = handler;
  84. if (state) {
  85. /* dummy read: re-trigger interrupt */
  86. lis2dw12_acceleration_raw_get(ctx, raw);
  87. }
  88. return lis2dw12_enable_int(dev, SENSOR_TRIG_DATA_READY, state);
  89. break;
  90. #ifdef CONFIG_LIS2DW12_TAP
  91. case SENSOR_TRIG_TAP:
  92. case SENSOR_TRIG_DOUBLE_TAP:
  93. /* check if tap detection is enabled */
  94. if ((cfg->tap_threshold[0] == 0) &&
  95. (cfg->tap_threshold[1] == 0) &&
  96. (cfg->tap_threshold[2] == 0)) {
  97. LOG_ERR("Unsupported sensor trigger");
  98. return -ENOTSUP;
  99. }
  100. /* Set single TAP trigger */
  101. if (trig->type == SENSOR_TRIG_TAP) {
  102. lis2dw12->tap_handler = handler;
  103. return lis2dw12_enable_int(dev, SENSOR_TRIG_TAP, state);
  104. }
  105. /* Set double TAP trigger */
  106. lis2dw12->double_tap_handler = handler;
  107. return lis2dw12_enable_int(dev, SENSOR_TRIG_DOUBLE_TAP, state);
  108. #endif /* CONFIG_LIS2DW12_TAP */
  109. default:
  110. LOG_ERR("Unsupported sensor trigger");
  111. return -ENOTSUP;
  112. }
  113. }
  114. static int lis2dw12_handle_drdy_int(const struct device *dev)
  115. {
  116. struct lis2dw12_data *data = dev->data;
  117. struct sensor_trigger drdy_trig = {
  118. .type = SENSOR_TRIG_DATA_READY,
  119. .chan = SENSOR_CHAN_ALL,
  120. };
  121. if (data->drdy_handler) {
  122. data->drdy_handler(dev, &drdy_trig);
  123. }
  124. return 0;
  125. }
  126. #ifdef CONFIG_LIS2DW12_TAP
  127. static int lis2dw12_handle_single_tap_int(const struct device *dev)
  128. {
  129. struct lis2dw12_data *data = dev->data;
  130. sensor_trigger_handler_t handler = data->tap_handler;
  131. struct sensor_trigger pulse_trig = {
  132. .type = SENSOR_TRIG_TAP,
  133. .chan = SENSOR_CHAN_ALL,
  134. };
  135. if (handler) {
  136. handler(dev, &pulse_trig);
  137. }
  138. return 0;
  139. }
  140. static int lis2dw12_handle_double_tap_int(const struct device *dev)
  141. {
  142. struct lis2dw12_data *data = dev->data;
  143. sensor_trigger_handler_t handler = data->double_tap_handler;
  144. struct sensor_trigger pulse_trig = {
  145. .type = SENSOR_TRIG_DOUBLE_TAP,
  146. .chan = SENSOR_CHAN_ALL,
  147. };
  148. if (handler) {
  149. handler(dev, &pulse_trig);
  150. }
  151. return 0;
  152. }
  153. #endif /* CONFIG_LIS2DW12_TAP */
  154. /**
  155. * lis2dw12_handle_interrupt - handle the drdy event
  156. * read data and call handler if registered any
  157. */
  158. static void lis2dw12_handle_interrupt(const struct device *dev)
  159. {
  160. const struct lis2dw12_device_config *cfg = dev->config;
  161. stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
  162. lis2dw12_all_sources_t sources;
  163. lis2dw12_all_sources_get(ctx, &sources);
  164. if (sources.status_dup.drdy) {
  165. lis2dw12_handle_drdy_int(dev);
  166. }
  167. #ifdef CONFIG_LIS2DW12_TAP
  168. if (sources.status_dup.single_tap) {
  169. lis2dw12_handle_single_tap_int(dev);
  170. }
  171. if (sources.status_dup.double_tap) {
  172. lis2dw12_handle_double_tap_int(dev);
  173. }
  174. #endif /* CONFIG_LIS2DW12_TAP */
  175. gpio_pin_interrupt_configure_dt(&cfg->gpio_int,
  176. GPIO_INT_EDGE_TO_ACTIVE);
  177. }
  178. static void lis2dw12_gpio_callback(const struct device *dev,
  179. struct gpio_callback *cb, uint32_t pins)
  180. {
  181. struct lis2dw12_data *lis2dw12 =
  182. CONTAINER_OF(cb, struct lis2dw12_data, gpio_cb);
  183. const struct lis2dw12_device_config *cfg = lis2dw12->dev->config;
  184. if ((pins & BIT(cfg->gpio_int.pin)) == 0U) {
  185. return;
  186. }
  187. gpio_pin_interrupt_configure_dt(&cfg->gpio_int, GPIO_INT_DISABLE);
  188. #if defined(CONFIG_LIS2DW12_TRIGGER_OWN_THREAD)
  189. k_sem_give(&lis2dw12->gpio_sem);
  190. #elif defined(CONFIG_LIS2DW12_TRIGGER_GLOBAL_THREAD)
  191. k_work_submit(&lis2dw12->work);
  192. #endif /* CONFIG_LIS2DW12_TRIGGER_OWN_THREAD */
  193. }
  194. #ifdef CONFIG_LIS2DW12_TRIGGER_OWN_THREAD
  195. static void lis2dw12_thread(struct lis2dw12_data *lis2dw12)
  196. {
  197. while (1) {
  198. k_sem_take(&lis2dw12->gpio_sem, K_FOREVER);
  199. lis2dw12_handle_interrupt(lis2dw12->dev);
  200. }
  201. }
  202. #endif /* CONFIG_LIS2DW12_TRIGGER_OWN_THREAD */
  203. #ifdef CONFIG_LIS2DW12_TRIGGER_GLOBAL_THREAD
  204. static void lis2dw12_work_cb(struct k_work *work)
  205. {
  206. struct lis2dw12_data *lis2dw12 =
  207. CONTAINER_OF(work, struct lis2dw12_data, work);
  208. lis2dw12_handle_interrupt(lis2dw12->dev);
  209. }
  210. #endif /* CONFIG_LIS2DW12_TRIGGER_GLOBAL_THREAD */
  211. #ifdef CONFIG_LIS2DW12_TAP
  212. static int lis2dw12_tap_init(const struct device *dev)
  213. {
  214. const struct lis2dw12_device_config *cfg = dev->config;
  215. stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
  216. LOG_DBG("TAP: tap mode is %d", cfg->tap_mode);
  217. if (lis2dw12_tap_mode_set(ctx, cfg->tap_mode) < 0) {
  218. LOG_ERR("Failed to select tap trigger mode");
  219. return -EIO;
  220. }
  221. LOG_DBG("TAP: ths_x is %02x", cfg->tap_threshold[0]);
  222. if (lis2dw12_tap_threshold_x_set(ctx, cfg->tap_threshold[0]) < 0) {
  223. LOG_ERR("Failed to set tap X axis threshold");
  224. return -EIO;
  225. }
  226. LOG_DBG("TAP: ths_y is %02x", cfg->tap_threshold[1]);
  227. if (lis2dw12_tap_threshold_y_set(ctx, cfg->tap_threshold[1]) < 0) {
  228. LOG_ERR("Failed to set tap Y axis threshold");
  229. return -EIO;
  230. }
  231. LOG_DBG("TAP: ths_z is %02x", cfg->tap_threshold[2]);
  232. if (lis2dw12_tap_threshold_z_set(ctx, cfg->tap_threshold[2]) < 0) {
  233. LOG_ERR("Failed to set tap Z axis threshold");
  234. return -EIO;
  235. }
  236. if (cfg->tap_threshold[0] > 0) {
  237. LOG_DBG("TAP: tap_x enabled");
  238. if (lis2dw12_tap_detection_on_x_set(ctx, 1) < 0) {
  239. LOG_ERR("Failed to set tap detection on X axis");
  240. return -EIO;
  241. }
  242. }
  243. if (cfg->tap_threshold[1] > 0) {
  244. LOG_DBG("TAP: tap_y enabled");
  245. if (lis2dw12_tap_detection_on_y_set(ctx, 1) < 0) {
  246. LOG_ERR("Failed to set tap detection on Y axis");
  247. return -EIO;
  248. }
  249. }
  250. if (cfg->tap_threshold[2] > 0) {
  251. LOG_DBG("TAP: tap_z enabled");
  252. if (lis2dw12_tap_detection_on_z_set(ctx, 1) < 0) {
  253. LOG_ERR("Failed to set tap detection on Z axis");
  254. return -EIO;
  255. }
  256. }
  257. LOG_DBG("TAP: shock is %02x", cfg->tap_shock);
  258. if (lis2dw12_tap_shock_set(ctx, cfg->tap_shock) < 0) {
  259. LOG_ERR("Failed to set tap shock duration");
  260. return -EIO;
  261. }
  262. LOG_DBG("TAP: latency is %02x", cfg->tap_latency);
  263. if (lis2dw12_tap_dur_set(ctx, cfg->tap_latency) < 0) {
  264. LOG_ERR("Failed to set tap latency");
  265. return -EIO;
  266. }
  267. LOG_DBG("TAP: quiet time is %02x", cfg->tap_quiet);
  268. if (lis2dw12_tap_quiet_set(ctx, cfg->tap_quiet) < 0) {
  269. LOG_ERR("Failed to set tap quiet time");
  270. return -EIO;
  271. }
  272. return 0;
  273. }
  274. #endif /* CONFIG_LIS2DW12_TAP */
  275. int lis2dw12_init_interrupt(const struct device *dev)
  276. {
  277. struct lis2dw12_data *lis2dw12 = dev->data;
  278. const struct lis2dw12_device_config *cfg = dev->config;
  279. stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
  280. int ret;
  281. /* setup data ready gpio interrupt (INT1 or INT2) */
  282. if (!device_is_ready(cfg->gpio_int.port)) {
  283. if (cfg->gpio_int.port) {
  284. LOG_ERR("%s: device %s is not ready", dev->name,
  285. cfg->gpio_int.port->name);
  286. return -ENODEV;
  287. }
  288. LOG_DBG("%s: gpio_int not defined in DT", dev->name);
  289. return 0;
  290. }
  291. lis2dw12->dev = dev;
  292. LOG_INF("%s: int-pin is on INT%d", dev->name, cfg->int_pin);
  293. #if defined(CONFIG_LIS2DW12_TRIGGER_OWN_THREAD)
  294. k_sem_init(&lis2dw12->gpio_sem, 0, K_SEM_MAX_LIMIT);
  295. k_thread_create(&lis2dw12->thread, lis2dw12->thread_stack,
  296. CONFIG_LIS2DW12_THREAD_STACK_SIZE,
  297. (k_thread_entry_t)lis2dw12_thread, lis2dw12,
  298. NULL, NULL, K_PRIO_COOP(CONFIG_LIS2DW12_THREAD_PRIORITY),
  299. 0, K_NO_WAIT);
  300. #elif defined(CONFIG_LIS2DW12_TRIGGER_GLOBAL_THREAD)
  301. lis2dw12->work.handler = lis2dw12_work_cb;
  302. #endif /* CONFIG_LIS2DW12_TRIGGER_OWN_THREAD */
  303. ret = gpio_pin_configure_dt(&cfg->gpio_int, GPIO_INPUT);
  304. if (ret < 0) {
  305. LOG_ERR("Could not configure gpio");
  306. return ret;
  307. }
  308. LOG_INF("%s: int on %s.%02u", dev->name, cfg->gpio_int.port->name,
  309. cfg->gpio_int.pin);
  310. gpio_init_callback(&lis2dw12->gpio_cb,
  311. lis2dw12_gpio_callback,
  312. BIT(cfg->gpio_int.pin));
  313. if (gpio_add_callback(cfg->gpio_int.port, &lis2dw12->gpio_cb) < 0) {
  314. LOG_DBG("Could not set gpio callback");
  315. return -EIO;
  316. }
  317. /* enable interrupt on int1/int2 in pulse mode */
  318. if (lis2dw12_int_notification_set(ctx, LIS2DW12_INT_PULSED)) {
  319. return -EIO;
  320. }
  321. #ifdef CONFIG_LIS2DW12_TAP
  322. ret = lis2dw12_tap_init(dev);
  323. if (ret < 0) {
  324. return ret;
  325. }
  326. #endif /* CONFIG_LIS2DW12_TAP */
  327. return gpio_pin_interrupt_configure_dt(&cfg->gpio_int,
  328. GPIO_INT_EDGE_TO_ACTIVE);
  329. }