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