1 /*
2 * Copyright (c) 2017 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT st_lis2dh
8
9 #include <zephyr/sys/util.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/logging/log.h>
12
13 #define START_TRIG_INT1 0
14 #define START_TRIG_INT2 1
15 #define TRIGGED_INT1 4
16 #define TRIGGED_INT2 5
17
18 LOG_MODULE_DECLARE(lis2dh, CONFIG_SENSOR_LOG_LEVEL);
19 #include "lis2dh.h"
20
21 static const gpio_flags_t gpio_int_cfg[5] = {
22 GPIO_INT_EDGE_BOTH,
23 GPIO_INT_EDGE_RISING,
24 GPIO_INT_EDGE_FALLING,
25 GPIO_INT_LEVEL_HIGH,
26 GPIO_INT_LEVEL_LOW,
27 };
28
setup_int1(const struct device * dev,bool enable)29 static inline void setup_int1(const struct device *dev,
30 bool enable)
31 {
32 const struct lis2dh_config *cfg = dev->config;
33
34 gpio_pin_interrupt_configure_dt(&cfg->gpio_drdy,
35 enable
36 ? gpio_int_cfg[cfg->int1_mode]
37 : GPIO_INT_DISABLE);
38 }
39
lis2dh_trigger_drdy_set(const struct device * dev,enum sensor_channel chan,sensor_trigger_handler_t handler,const struct sensor_trigger * trig)40 static int lis2dh_trigger_drdy_set(const struct device *dev,
41 enum sensor_channel chan,
42 sensor_trigger_handler_t handler,
43 const struct sensor_trigger *trig)
44 {
45 const struct lis2dh_config *cfg = dev->config;
46 struct lis2dh_data *lis2dh = dev->data;
47 int status;
48
49 if (cfg->gpio_drdy.port == NULL) {
50 LOG_ERR("trigger_set DRDY int not supported");
51 return -ENOTSUP;
52 }
53
54 setup_int1(dev, false);
55
56 /* cancel potentially pending trigger */
57 atomic_clear_bit(&lis2dh->trig_flags, TRIGGED_INT1);
58
59 status = lis2dh->hw_tf->update_reg(dev, LIS2DH_REG_CTRL3,
60 LIS2DH_EN_DRDY1_INT1, 0);
61
62 lis2dh->handler_drdy = handler;
63 lis2dh->trig_drdy = trig;
64 if ((handler == NULL) || (status < 0)) {
65 return status;
66 }
67
68 lis2dh->chan_drdy = chan;
69
70 /* serialize start of int1 in thread to synchronize output sampling
71 * and first interrupt. this avoids concurrent bus context access.
72 */
73 atomic_set_bit(&lis2dh->trig_flags, START_TRIG_INT1);
74 #if defined(CONFIG_LIS2DH_TRIGGER_OWN_THREAD)
75 k_sem_give(&lis2dh->gpio_sem);
76 #elif defined(CONFIG_LIS2DH_TRIGGER_GLOBAL_THREAD)
77 k_work_submit(&lis2dh->work);
78 #endif
79
80 return 0;
81 }
82
lis2dh_start_trigger_int1(const struct device * dev)83 static int lis2dh_start_trigger_int1(const struct device *dev)
84 {
85 int status;
86 uint8_t raw[LIS2DH_BUF_SZ];
87 uint8_t ctrl1 = 0U;
88 struct lis2dh_data *lis2dh = dev->data;
89
90 /* power down temporarily to align interrupt & data output sampling */
91 status = lis2dh->hw_tf->read_reg(dev, LIS2DH_REG_CTRL1, &ctrl1);
92 if (unlikely(status < 0)) {
93 return status;
94 }
95 status = lis2dh->hw_tf->write_reg(dev, LIS2DH_REG_CTRL1,
96 ctrl1 & ~LIS2DH_ODR_MASK);
97
98 if (unlikely(status < 0)) {
99 return status;
100 }
101
102 LOG_DBG("ctrl1=0x%x @tick=%u", ctrl1, k_cycle_get_32());
103
104 /* empty output data */
105 status = lis2dh->hw_tf->read_data(dev, LIS2DH_REG_STATUS,
106 raw, sizeof(raw));
107 if (unlikely(status < 0)) {
108 return status;
109 }
110
111 setup_int1(dev, true);
112
113 /* re-enable output sampling */
114 status = lis2dh->hw_tf->write_reg(dev, LIS2DH_REG_CTRL1, ctrl1);
115 if (unlikely(status < 0)) {
116 return status;
117 }
118
119 return lis2dh->hw_tf->update_reg(dev, LIS2DH_REG_CTRL3,
120 LIS2DH_EN_DRDY1_INT1,
121 LIS2DH_EN_DRDY1_INT1);
122 }
123
124 #define LIS2DH_ANYM_CFG (LIS2DH_INT_CFG_ZHIE_ZUPE | LIS2DH_INT_CFG_YHIE_YUPE |\
125 LIS2DH_INT_CFG_XHIE_XUPE)
126
setup_int2(const struct device * dev,bool enable)127 static inline void setup_int2(const struct device *dev,
128 bool enable)
129 {
130 const struct lis2dh_config *cfg = dev->config;
131
132 gpio_pin_interrupt_configure_dt(&cfg->gpio_int,
133 enable
134 ? gpio_int_cfg[cfg->int2_mode]
135 : GPIO_INT_DISABLE);
136 }
137
138 /* common handler for any motion and tap triggers */
lis2dh_trigger_anym_tap_set(const struct device * dev,sensor_trigger_handler_t handler,const struct sensor_trigger * trig)139 static int lis2dh_trigger_anym_tap_set(const struct device *dev,
140 sensor_trigger_handler_t handler,
141 const struct sensor_trigger *trig)
142 {
143 const struct lis2dh_config *cfg = dev->config;
144 struct lis2dh_data *lis2dh = dev->data;
145 int status;
146 uint8_t reg_val;
147
148 if (cfg->gpio_int.port == NULL) {
149 LOG_ERR("trigger_set AnyMotion int not supported");
150 return -ENOTSUP;
151 }
152
153 setup_int2(dev, false);
154
155 /* cancel potentially pending trigger */
156 atomic_clear_bit(&lis2dh->trig_flags, TRIGGED_INT2);
157
158 if (cfg->hw.anym_on_int1) {
159 status = lis2dh->hw_tf->update_reg(dev, LIS2DH_REG_CTRL3,
160 LIS2DH_EN_DRDY1_INT1, 0);
161 }
162
163 /* disable any movement interrupt events */
164 status = lis2dh->hw_tf->write_reg(dev,
165 cfg->hw.anym_on_int1 ?
166 LIS2DH_REG_INT1_CFG :
167 LIS2DH_REG_INT2_CFG,
168 0);
169 /* disable any click interrupt events */
170 status = lis2dh->hw_tf->write_reg(dev,
171 LIS2DH_REG_CFG_CLICK,
172 0);
173
174 /* make sure any pending interrupt is cleared */
175 status = lis2dh->hw_tf->read_reg(dev,
176 cfg->hw.anym_on_int1 ?
177 LIS2DH_REG_INT1_SRC :
178 LIS2DH_REG_INT2_SRC,
179 ®_val);
180 status = lis2dh->hw_tf->read_reg(dev,
181 LIS2DH_REG_CLICK_SRC,
182 ®_val);
183
184 if (trig->type == SENSOR_TRIG_DELTA) {
185 lis2dh->handler_anymotion = handler;
186 lis2dh->trig_anymotion = trig;
187 } else if (trig->type == SENSOR_TRIG_TAP) {
188 lis2dh->handler_tap = handler;
189 lis2dh->trig_tap = trig;
190 }
191
192 if ((handler == NULL) || (status < 0)) {
193 return status;
194 }
195
196 /* serialize start of int2 in thread to synchronize output sampling
197 * and first interrupt. this avoids concurrent bus context access.
198 */
199 atomic_set_bit(&lis2dh->trig_flags, START_TRIG_INT2);
200 #if defined(CONFIG_LIS2DH_TRIGGER_OWN_THREAD)
201 k_sem_give(&lis2dh->gpio_sem);
202 #elif defined(CONFIG_LIS2DH_TRIGGER_GLOBAL_THREAD)
203 k_work_submit(&lis2dh->work);
204 #endif
205 return 0;
206 }
207
lis2dh_trigger_anym_set(const struct device * dev,sensor_trigger_handler_t handler,const struct sensor_trigger * trig)208 static int lis2dh_trigger_anym_set(const struct device *dev,
209 sensor_trigger_handler_t handler,
210 const struct sensor_trigger *trig)
211 {
212 return lis2dh_trigger_anym_tap_set(dev, handler, trig);
213 }
214
lis2dh_trigger_tap_set(const struct device * dev,sensor_trigger_handler_t handler,const struct sensor_trigger * trig)215 static int lis2dh_trigger_tap_set(const struct device *dev,
216 sensor_trigger_handler_t handler,
217 const struct sensor_trigger *trig)
218 {
219 return lis2dh_trigger_anym_tap_set(dev, handler, trig);
220 }
221
lis2dh_start_trigger_int2(const struct device * dev)222 static int lis2dh_start_trigger_int2(const struct device *dev)
223 {
224 struct lis2dh_data *lis2dh = dev->data;
225 const struct lis2dh_config *cfg = dev->config;
226 int status = 0;
227 uint8_t reg = 0, mask = 0, val = 0;
228
229 setup_int2(dev, true);
230
231 bool has_anyt = (lis2dh->handler_tap != NULL);
232 bool has_anym = (lis2dh->handler_anymotion != NULL);
233
234 /* configure any motion interrupt */
235 reg = cfg->hw.anym_on_int1 ? LIS2DH_REG_INT1_CFG : LIS2DH_REG_INT2_CFG;
236 val = (cfg->hw.anym_mode << LIS2DH_INT_CFG_MODE_SHIFT) | LIS2DH_ANYM_CFG;
237 status = lis2dh->hw_tf->write_reg(dev, reg, val);
238 if (status < 0) {
239 LOG_ERR("Failed to configure any motion interrupt");
240 return status;
241 }
242
243 /* enable any motion detection on int line */
244 reg = cfg->hw.anym_on_int1 ? LIS2DH_REG_CTRL3 : LIS2DH_REG_CTRL6;
245 mask = cfg->hw.anym_on_int1 ? LIS2DH_EN_IA_INT1 : LIS2DH_EN_IA_INT2;
246 val = has_anym ? mask : 0;
247 status = lis2dh->hw_tf->update_reg(dev, reg, mask, val);
248 if (status < 0) {
249 LOG_ERR("Failed to enable any motion detection on int line");
250 return status;
251 }
252
253 /* configure tap interrupt on all axes */
254 reg = LIS2DH_REG_CFG_CLICK;
255 mask = LIS2DH_EN_CLICK_XS | LIS2DH_EN_CLICK_YS | LIS2DH_EN_CLICK_ZS;
256 val = has_anyt ? mask : 0;
257 status = lis2dh->hw_tf->update_reg(dev, reg, mask, val);
258 if (status < 0) {
259 LOG_ERR("Failed to configure tap interrupt");
260 return status;
261 }
262
263 /* set click detection on int line */
264 reg = cfg->hw.anym_on_int1 ? LIS2DH_REG_CTRL3 : LIS2DH_REG_CTRL6;
265 mask = cfg->hw.anym_on_int1 ? LIS2DH_EN_CLICK_INT1 : LIS2DH_EN_CLICK_INT2;
266 val = has_anyt ? mask : 0;
267 status = lis2dh->hw_tf->update_reg(dev, reg, mask, val);
268 if (status < 0) {
269 LOG_ERR("Failed to enable click detection on int line");
270 return status;
271 }
272 return 0;
273 }
274
lis2dh_trigger_set(const struct device * dev,const struct sensor_trigger * trig,sensor_trigger_handler_t handler)275 int lis2dh_trigger_set(const struct device *dev,
276 const struct sensor_trigger *trig,
277 sensor_trigger_handler_t handler)
278 {
279 if (trig->type == SENSOR_TRIG_DATA_READY &&
280 trig->chan == SENSOR_CHAN_ACCEL_XYZ) {
281 return lis2dh_trigger_drdy_set(dev, trig->chan, handler, trig);
282 } else if (trig->type == SENSOR_TRIG_DELTA) {
283 return lis2dh_trigger_anym_set(dev, handler, trig);
284 } else if (trig->type == SENSOR_TRIG_TAP) {
285 return lis2dh_trigger_tap_set(dev, handler, trig);
286 }
287
288 return -ENOTSUP;
289 }
290
lis2dh_acc_slope_config(const struct device * dev,enum sensor_attribute attr,const struct sensor_value * val)291 int lis2dh_acc_slope_config(const struct device *dev,
292 enum sensor_attribute attr,
293 const struct sensor_value *val)
294 {
295 struct lis2dh_data *lis2dh = dev->data;
296 const struct lis2dh_config *cfg = dev->config;
297 int status;
298
299 if (attr == SENSOR_ATTR_SLOPE_TH) {
300 uint8_t range_g, reg_val;
301 uint32_t slope_th_ums2;
302
303 status = lis2dh->hw_tf->read_reg(dev, LIS2DH_REG_CTRL4,
304 ®_val);
305 if (status < 0) {
306 return status;
307 }
308
309 /* fs reg value is in the range 0 (2g) - 3 (16g) */
310 range_g = 2 * (1 << ((LIS2DH_FS_MASK & reg_val)
311 >> LIS2DH_FS_SHIFT));
312
313 slope_th_ums2 = val->val1 * 1000000 + val->val2;
314
315 /* make sure the provided threshold does not exceed range */
316 if ((slope_th_ums2 - 1) > (range_g * SENSOR_G)) {
317 return -EINVAL;
318 }
319
320 /* 7 bit full range value */
321 reg_val = 128 / range_g * (slope_th_ums2 - 1) / SENSOR_G;
322
323 LOG_INF("int2_ths=0x%x range_g=%d ums2=%u", reg_val,
324 range_g, slope_th_ums2 - 1);
325
326 /* Configure threshold for the any motion recognition */
327 status = lis2dh->hw_tf->write_reg(dev,
328 cfg->hw.anym_on_int1 ?
329 LIS2DH_REG_INT1_THS :
330 LIS2DH_REG_INT2_THS,
331 reg_val);
332
333 /* Configure threshold for the Click recognition */
334 status = lis2dh->hw_tf->write_reg(dev,
335 LIS2DH_REG_CFG_CLICK_THS,
336 LIS2DH_CLICK_LIR | reg_val);
337 } else { /* SENSOR_ATTR_SLOPE_DUR */
338 /*
339 * slope duration is measured in number of samples:
340 * N/ODR where N is the register value
341 */
342 if (val->val1 < 0 || val->val1 > 127) {
343 return -ENOTSUP;
344 }
345
346 LOG_INF("int2_dur=0x%x", val->val1);
347
348 /* Configure time limit for the any motion recognition */
349 status = lis2dh->hw_tf->write_reg(dev,
350 cfg->hw.anym_on_int1 ?
351 LIS2DH_REG_INT1_DUR :
352 LIS2DH_REG_INT2_DUR,
353 val->val1);
354
355 /* Configure time limit for the Click recognition */
356 status = lis2dh->hw_tf->write_reg(dev,
357 LIS2DH_REG_TIME_LIMIT,
358 val->val1);
359 }
360
361 return status;
362 }
363
364 #ifdef CONFIG_LIS2DH_ACCEL_HP_FILTERS
lis2dh_acc_hp_filter_set(const struct device * dev,int32_t val)365 int lis2dh_acc_hp_filter_set(const struct device *dev, int32_t val)
366 {
367 struct lis2dh_data *lis2dh = dev->data;
368 int status;
369
370 status = lis2dh->hw_tf->update_reg(dev, LIS2DH_REG_CTRL2,
371 LIS2DH_HPIS_EN_MASK, val);
372 if (status < 0) {
373 LOG_ERR("Failed to set high pass filters");
374 }
375
376 return status;
377 }
378 #endif
379
lis2dh_gpio_int1_callback(const struct device * dev,struct gpio_callback * cb,uint32_t pins)380 static void lis2dh_gpio_int1_callback(const struct device *dev,
381 struct gpio_callback *cb, uint32_t pins)
382 {
383 struct lis2dh_data *lis2dh =
384 CONTAINER_OF(cb, struct lis2dh_data, gpio_int1_cb);
385
386 ARG_UNUSED(pins);
387
388 atomic_set_bit(&lis2dh->trig_flags, TRIGGED_INT1);
389
390 /* int is level triggered so disable until processed */
391 setup_int1(lis2dh->dev, false);
392
393 #if defined(CONFIG_LIS2DH_TRIGGER_OWN_THREAD)
394 k_sem_give(&lis2dh->gpio_sem);
395 #elif defined(CONFIG_LIS2DH_TRIGGER_GLOBAL_THREAD)
396 k_work_submit(&lis2dh->work);
397 #endif
398 }
399
lis2dh_gpio_int2_callback(const struct device * dev,struct gpio_callback * cb,uint32_t pins)400 static void lis2dh_gpio_int2_callback(const struct device *dev,
401 struct gpio_callback *cb, uint32_t pins)
402 {
403 struct lis2dh_data *lis2dh =
404 CONTAINER_OF(cb, struct lis2dh_data, gpio_int2_cb);
405
406 ARG_UNUSED(pins);
407
408 atomic_set_bit(&lis2dh->trig_flags, TRIGGED_INT2);
409
410 /* int is level triggered so disable until processed */
411 setup_int2(lis2dh->dev, false);
412
413 #if defined(CONFIG_LIS2DH_TRIGGER_OWN_THREAD)
414 k_sem_give(&lis2dh->gpio_sem);
415 #elif defined(CONFIG_LIS2DH_TRIGGER_GLOBAL_THREAD)
416 k_work_submit(&lis2dh->work);
417 #endif
418 }
419
lis2dh_thread_cb(const struct device * dev)420 static void lis2dh_thread_cb(const struct device *dev)
421 {
422 struct lis2dh_data *lis2dh = dev->data;
423 const struct lis2dh_config *cfg = dev->config;
424 int status;
425
426 if (cfg->gpio_drdy.port &&
427 unlikely(atomic_test_and_clear_bit(&lis2dh->trig_flags,
428 START_TRIG_INT1))) {
429 status = lis2dh_start_trigger_int1(dev);
430
431 if (unlikely(status < 0)) {
432 LOG_ERR("lis2dh_start_trigger_int1: %d", status);
433 }
434 return;
435 }
436
437 if (cfg->gpio_int.port &&
438 unlikely(atomic_test_and_clear_bit(&lis2dh->trig_flags,
439 START_TRIG_INT2))) {
440 status = lis2dh_start_trigger_int2(dev);
441
442 if (unlikely(status < 0)) {
443 LOG_ERR("lis2dh_start_trigger_int2: %d", status);
444 }
445 return;
446 }
447
448 if (cfg->gpio_drdy.port &&
449 atomic_test_and_clear_bit(&lis2dh->trig_flags,
450 TRIGGED_INT1)) {
451 if (likely(lis2dh->handler_drdy != NULL)) {
452 lis2dh->handler_drdy(dev, lis2dh->trig_drdy);
453 }
454
455 /* Reactivate level triggered interrupt if handler did not
456 * disable itself
457 */
458 if (likely(lis2dh->handler_drdy != NULL)) {
459 setup_int1(dev, true);
460 }
461
462 return;
463 }
464
465 if (cfg->gpio_int.port &&
466 atomic_test_and_clear_bit(&lis2dh->trig_flags,
467 TRIGGED_INT2)) {
468 uint8_t reg_val = 0;
469
470 /* if necessary also clears an interrupt to de-assert int line */
471 status = lis2dh->hw_tf->read_reg(dev,
472 cfg->hw.anym_on_int1 ?
473 LIS2DH_REG_INT1_SRC :
474 LIS2DH_REG_INT2_SRC,
475 ®_val);
476 if (status < 0) {
477 LOG_ERR("clearing interrupt 2 failed: %d", status);
478 return;
479 }
480
481 if (likely(lis2dh->handler_anymotion != NULL) &&
482 (reg_val >> LIS2DH_INT_CFG_MODE_SHIFT)) {
483 lis2dh->handler_anymotion(dev, lis2dh->trig_anymotion);
484
485 LOG_DBG("@tick=%u int2_src=0x%x", k_cycle_get_32(), reg_val);
486 }
487
488 /* read click interrupt */
489 status = lis2dh->hw_tf->read_reg(dev, LIS2DH_REG_CLICK_SRC,
490 ®_val);
491 if (status < 0) {
492 LOG_ERR("clearing interrupt 2 failed: %d", status);
493 return;
494 }
495
496 if (likely(lis2dh->handler_tap != NULL) &&
497 (reg_val & LIS2DH_CLICK_SRC_SCLICK)) {
498 lis2dh->handler_tap(dev, lis2dh->trig_tap);
499
500 LOG_DBG("@tick=%u click_src=0x%x", k_cycle_get_32(), reg_val);
501 }
502
503 /* Reactivate level triggered interrupt if handler did not
504 * disable itself
505 */
506 if (lis2dh->handler_anymotion || lis2dh->handler_tap) {
507 setup_int2(dev, true);
508 }
509
510 return;
511 }
512 }
513
514 #ifdef CONFIG_LIS2DH_TRIGGER_OWN_THREAD
lis2dh_thread(void * p1,void * p2,void * p3)515 static void lis2dh_thread(void *p1, void *p2, void *p3)
516 {
517 ARG_UNUSED(p2);
518 ARG_UNUSED(p3);
519
520 struct lis2dh_data *lis2dh = p1;
521
522 while (1) {
523 k_sem_take(&lis2dh->gpio_sem, K_FOREVER);
524 lis2dh_thread_cb(lis2dh->dev);
525 }
526 }
527 #endif
528
529 #ifdef CONFIG_LIS2DH_TRIGGER_GLOBAL_THREAD
lis2dh_work_cb(struct k_work * work)530 static void lis2dh_work_cb(struct k_work *work)
531 {
532 struct lis2dh_data *lis2dh =
533 CONTAINER_OF(work, struct lis2dh_data, work);
534
535 lis2dh_thread_cb(lis2dh->dev);
536 }
537 #endif
538
lis2dh_init_interrupt(const struct device * dev)539 int lis2dh_init_interrupt(const struct device *dev)
540 {
541 struct lis2dh_data *lis2dh = dev->data;
542 const struct lis2dh_config *cfg = dev->config;
543 int status;
544 uint8_t raw[2];
545
546 lis2dh->dev = dev;
547
548 #if defined(CONFIG_LIS2DH_TRIGGER_OWN_THREAD)
549 k_sem_init(&lis2dh->gpio_sem, 0, K_SEM_MAX_LIMIT);
550
551 k_thread_create(&lis2dh->thread, lis2dh->thread_stack, CONFIG_LIS2DH_THREAD_STACK_SIZE,
552 lis2dh_thread, lis2dh, NULL, NULL,
553 K_PRIO_COOP(CONFIG_LIS2DH_THREAD_PRIORITY), 0, K_NO_WAIT);
554 #elif defined(CONFIG_LIS2DH_TRIGGER_GLOBAL_THREAD)
555 lis2dh->work.handler = lis2dh_work_cb;
556 #endif
557
558 /*
559 * Setup INT1 (for DRDY) if defined in DT
560 */
561
562 /* setup data ready gpio interrupt */
563 if (!gpio_is_ready_dt(&cfg->gpio_drdy)) {
564 /* API may return false even when ptr is NULL */
565 if (cfg->gpio_drdy.port != NULL) {
566 LOG_ERR("device %s is not ready", cfg->gpio_drdy.port->name);
567 return -ENODEV;
568 }
569
570 LOG_DBG("gpio_drdy not defined in DT");
571 status = 0;
572 goto check_gpio_int;
573 }
574
575 /* data ready int1 gpio configuration */
576 status = gpio_pin_configure_dt(&cfg->gpio_drdy, GPIO_INPUT);
577 if (status < 0) {
578 LOG_ERR("Could not configure %s.%02u",
579 cfg->gpio_drdy.port->name, cfg->gpio_drdy.pin);
580 return status;
581 }
582
583 gpio_init_callback(&lis2dh->gpio_int1_cb,
584 lis2dh_gpio_int1_callback,
585 BIT(cfg->gpio_drdy.pin));
586
587 status = gpio_add_callback(cfg->gpio_drdy.port, &lis2dh->gpio_int1_cb);
588 if (status < 0) {
589 LOG_ERR("Could not add gpio int1 callback");
590 return status;
591 }
592
593 LOG_INF("%s: int1 on %s.%02u", dev->name,
594 cfg->gpio_drdy.port->name,
595 cfg->gpio_drdy.pin);
596
597 check_gpio_int:
598 /*
599 * Setup Interrupt (for Any Motion) if defined in DT
600 */
601
602 /* setup any motion gpio interrupt */
603 if (!gpio_is_ready_dt(&cfg->gpio_int)) {
604 /* API may return false even when ptr is NULL */
605 if (cfg->gpio_int.port != NULL) {
606 LOG_ERR("device %s is not ready", cfg->gpio_int.port->name);
607 return -ENODEV;
608 }
609
610 LOG_DBG("gpio_int not defined in DT");
611 status = 0;
612 goto end;
613 }
614
615 /* any motion int2 gpio configuration */
616 status = gpio_pin_configure_dt(&cfg->gpio_int, GPIO_INPUT);
617 if (status < 0) {
618 LOG_ERR("Could not configure %s.%02u",
619 cfg->gpio_int.port->name, cfg->gpio_int.pin);
620 return status;
621 }
622
623 gpio_init_callback(&lis2dh->gpio_int2_cb,
624 lis2dh_gpio_int2_callback,
625 BIT(cfg->gpio_int.pin));
626
627 /* callback is going to be enabled by trigger setting function */
628 status = gpio_add_callback(cfg->gpio_int.port, &lis2dh->gpio_int2_cb);
629 if (status < 0) {
630 LOG_ERR("Could not add gpio int2 callback (%d)", status);
631 return status;
632 }
633
634 LOG_INF("%s: int2 on %s.%02u", dev->name,
635 cfg->gpio_int.port->name,
636 cfg->gpio_int.pin);
637
638 /* disable interrupt in case of warm (re)boot */
639 status = lis2dh->hw_tf->write_reg(dev,
640 cfg->hw.anym_on_int1 ?
641 LIS2DH_REG_INT1_CFG :
642 LIS2DH_REG_INT2_CFG,
643 0);
644 if (status < 0) {
645 LOG_ERR("Interrupt disable reg write failed (%d)", status);
646 return status;
647 }
648 status = lis2dh->hw_tf->write_reg(dev,
649 LIS2DH_REG_CFG_CLICK,
650 0);
651 if (status < 0) {
652 LOG_ERR("Interrupt disable reg write failed (%d)", status);
653 return status;
654 }
655
656 (void)memset(raw, 0, sizeof(raw));
657 status = lis2dh->hw_tf->write_data(dev,
658 cfg->hw.anym_on_int1 ?
659 LIS2DH_REG_INT1_THS :
660 LIS2DH_REG_INT2_THS,
661 raw, sizeof(raw));
662 if (status < 0) {
663 LOG_ERR("Burst write to THS failed (%d)", status);
664 return status;
665 }
666
667 if (cfg->hw.anym_latch) {
668 /* latch line interrupt */
669 status = lis2dh->hw_tf->write_reg(dev,
670 LIS2DH_REG_CTRL5,
671 cfg->hw.anym_on_int1 ?
672 LIS2DH_EN_LIR_INT1 :
673 LIS2DH_EN_LIR_INT2);
674 }
675
676 if (status < 0) {
677 LOG_ERR("enable reg write failed (%d)", status);
678 return status;
679 }
680
681 end:
682 return status;
683 }
684