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
lis2dh_gpio_int1_callback(const struct device * dev,struct gpio_callback * cb,uint32_t pins)364 static void lis2dh_gpio_int1_callback(const struct device *dev,
365 struct gpio_callback *cb, uint32_t pins)
366 {
367 struct lis2dh_data *lis2dh =
368 CONTAINER_OF(cb, struct lis2dh_data, gpio_int1_cb);
369
370 ARG_UNUSED(pins);
371
372 atomic_set_bit(&lis2dh->trig_flags, TRIGGED_INT1);
373
374 /* int is level triggered so disable until processed */
375 setup_int1(lis2dh->dev, false);
376
377 #if defined(CONFIG_LIS2DH_TRIGGER_OWN_THREAD)
378 k_sem_give(&lis2dh->gpio_sem);
379 #elif defined(CONFIG_LIS2DH_TRIGGER_GLOBAL_THREAD)
380 k_work_submit(&lis2dh->work);
381 #endif
382 }
383
lis2dh_gpio_int2_callback(const struct device * dev,struct gpio_callback * cb,uint32_t pins)384 static void lis2dh_gpio_int2_callback(const struct device *dev,
385 struct gpio_callback *cb, uint32_t pins)
386 {
387 struct lis2dh_data *lis2dh =
388 CONTAINER_OF(cb, struct lis2dh_data, gpio_int2_cb);
389
390 ARG_UNUSED(pins);
391
392 atomic_set_bit(&lis2dh->trig_flags, TRIGGED_INT2);
393
394 /* int is level triggered so disable until processed */
395 setup_int2(lis2dh->dev, false);
396
397 #if defined(CONFIG_LIS2DH_TRIGGER_OWN_THREAD)
398 k_sem_give(&lis2dh->gpio_sem);
399 #elif defined(CONFIG_LIS2DH_TRIGGER_GLOBAL_THREAD)
400 k_work_submit(&lis2dh->work);
401 #endif
402 }
403
lis2dh_thread_cb(const struct device * dev)404 static void lis2dh_thread_cb(const struct device *dev)
405 {
406 struct lis2dh_data *lis2dh = dev->data;
407 const struct lis2dh_config *cfg = dev->config;
408 int status;
409
410 if (cfg->gpio_drdy.port &&
411 unlikely(atomic_test_and_clear_bit(&lis2dh->trig_flags,
412 START_TRIG_INT1))) {
413 status = lis2dh_start_trigger_int1(dev);
414
415 if (unlikely(status < 0)) {
416 LOG_ERR("lis2dh_start_trigger_int1: %d", status);
417 }
418 return;
419 }
420
421 if (cfg->gpio_int.port &&
422 unlikely(atomic_test_and_clear_bit(&lis2dh->trig_flags,
423 START_TRIG_INT2))) {
424 status = lis2dh_start_trigger_int2(dev);
425
426 if (unlikely(status < 0)) {
427 LOG_ERR("lis2dh_start_trigger_int2: %d", status);
428 }
429 return;
430 }
431
432 if (cfg->gpio_drdy.port &&
433 atomic_test_and_clear_bit(&lis2dh->trig_flags,
434 TRIGGED_INT1)) {
435 if (likely(lis2dh->handler_drdy != NULL)) {
436 lis2dh->handler_drdy(dev, lis2dh->trig_drdy);
437 }
438
439 /* Reactivate level triggered interrupt if handler did not
440 * disable itself
441 */
442 if (likely(lis2dh->handler_drdy != NULL)) {
443 setup_int1(dev, true);
444 }
445
446 return;
447 }
448
449 if (cfg->gpio_int.port &&
450 atomic_test_and_clear_bit(&lis2dh->trig_flags,
451 TRIGGED_INT2)) {
452 uint8_t reg_val = 0;
453
454 /* if necessary also clears an interrupt to de-assert int line */
455 status = lis2dh->hw_tf->read_reg(dev,
456 cfg->hw.anym_on_int1 ?
457 LIS2DH_REG_INT1_SRC :
458 LIS2DH_REG_INT2_SRC,
459 ®_val);
460 if (status < 0) {
461 LOG_ERR("clearing interrupt 2 failed: %d", status);
462 return;
463 }
464
465 if (likely(lis2dh->handler_anymotion != NULL) &&
466 (reg_val >> LIS2DH_INT_CFG_MODE_SHIFT)) {
467 lis2dh->handler_anymotion(dev, lis2dh->trig_anymotion);
468
469 LOG_DBG("@tick=%u int2_src=0x%x", k_cycle_get_32(), reg_val);
470 }
471
472 /* read click interrupt */
473 status = lis2dh->hw_tf->read_reg(dev, LIS2DH_REG_CLICK_SRC,
474 ®_val);
475 if (status < 0) {
476 LOG_ERR("clearing interrupt 2 failed: %d", status);
477 return;
478 }
479
480 if (likely(lis2dh->handler_tap != NULL) &&
481 (reg_val & LIS2DH_CLICK_SRC_SCLICK)) {
482 lis2dh->handler_tap(dev, lis2dh->trig_tap);
483
484 LOG_DBG("@tick=%u click_src=0x%x", k_cycle_get_32(), reg_val);
485 }
486
487 /* Reactivate level triggered interrupt if handler did not
488 * disable itself
489 */
490 if (lis2dh->handler_anymotion || lis2dh->handler_tap) {
491 setup_int2(dev, true);
492 }
493
494 return;
495 }
496 }
497
498 #ifdef CONFIG_LIS2DH_TRIGGER_OWN_THREAD
lis2dh_thread(void * p1,void * p2,void * p3)499 static void lis2dh_thread(void *p1, void *p2, void *p3)
500 {
501 ARG_UNUSED(p2);
502 ARG_UNUSED(p3);
503
504 struct lis2dh_data *lis2dh = p1;
505
506 while (1) {
507 k_sem_take(&lis2dh->gpio_sem, K_FOREVER);
508 lis2dh_thread_cb(lis2dh->dev);
509 }
510 }
511 #endif
512
513 #ifdef CONFIG_LIS2DH_TRIGGER_GLOBAL_THREAD
lis2dh_work_cb(struct k_work * work)514 static void lis2dh_work_cb(struct k_work *work)
515 {
516 struct lis2dh_data *lis2dh =
517 CONTAINER_OF(work, struct lis2dh_data, work);
518
519 lis2dh_thread_cb(lis2dh->dev);
520 }
521 #endif
522
lis2dh_init_interrupt(const struct device * dev)523 int lis2dh_init_interrupt(const struct device *dev)
524 {
525 struct lis2dh_data *lis2dh = dev->data;
526 const struct lis2dh_config *cfg = dev->config;
527 int status;
528 uint8_t raw[2];
529
530 lis2dh->dev = dev;
531
532 #if defined(CONFIG_LIS2DH_TRIGGER_OWN_THREAD)
533 k_sem_init(&lis2dh->gpio_sem, 0, K_SEM_MAX_LIMIT);
534
535 k_thread_create(&lis2dh->thread, lis2dh->thread_stack, CONFIG_LIS2DH_THREAD_STACK_SIZE,
536 lis2dh_thread, lis2dh, NULL, NULL,
537 K_PRIO_COOP(CONFIG_LIS2DH_THREAD_PRIORITY), 0, K_NO_WAIT);
538 #elif defined(CONFIG_LIS2DH_TRIGGER_GLOBAL_THREAD)
539 lis2dh->work.handler = lis2dh_work_cb;
540 #endif
541
542 /*
543 * Setup INT1 (for DRDY) if defined in DT
544 */
545
546 /* setup data ready gpio interrupt */
547 if (!gpio_is_ready_dt(&cfg->gpio_drdy)) {
548 /* API may return false even when ptr is NULL */
549 if (cfg->gpio_drdy.port != NULL) {
550 LOG_ERR("device %s is not ready", cfg->gpio_drdy.port->name);
551 return -ENODEV;
552 }
553
554 LOG_DBG("gpio_drdy not defined in DT");
555 status = 0;
556 goto check_gpio_int;
557 }
558
559 /* data ready int1 gpio configuration */
560 status = gpio_pin_configure_dt(&cfg->gpio_drdy, GPIO_INPUT);
561 if (status < 0) {
562 LOG_ERR("Could not configure %s.%02u",
563 cfg->gpio_drdy.port->name, cfg->gpio_drdy.pin);
564 return status;
565 }
566
567 gpio_init_callback(&lis2dh->gpio_int1_cb,
568 lis2dh_gpio_int1_callback,
569 BIT(cfg->gpio_drdy.pin));
570
571 status = gpio_add_callback(cfg->gpio_drdy.port, &lis2dh->gpio_int1_cb);
572 if (status < 0) {
573 LOG_ERR("Could not add gpio int1 callback");
574 return status;
575 }
576
577 LOG_INF("%s: int1 on %s.%02u", dev->name,
578 cfg->gpio_drdy.port->name,
579 cfg->gpio_drdy.pin);
580
581 check_gpio_int:
582 /*
583 * Setup Interrupt (for Any Motion) if defined in DT
584 */
585
586 /* setup any motion gpio interrupt */
587 if (!gpio_is_ready_dt(&cfg->gpio_int)) {
588 /* API may return false even when ptr is NULL */
589 if (cfg->gpio_int.port != NULL) {
590 LOG_ERR("device %s is not ready", cfg->gpio_int.port->name);
591 return -ENODEV;
592 }
593
594 LOG_DBG("gpio_int not defined in DT");
595 status = 0;
596 goto end;
597 }
598
599 /* any motion int2 gpio configuration */
600 status = gpio_pin_configure_dt(&cfg->gpio_int, GPIO_INPUT);
601 if (status < 0) {
602 LOG_ERR("Could not configure %s.%02u",
603 cfg->gpio_int.port->name, cfg->gpio_int.pin);
604 return status;
605 }
606
607 gpio_init_callback(&lis2dh->gpio_int2_cb,
608 lis2dh_gpio_int2_callback,
609 BIT(cfg->gpio_int.pin));
610
611 /* callback is going to be enabled by trigger setting function */
612 status = gpio_add_callback(cfg->gpio_int.port, &lis2dh->gpio_int2_cb);
613 if (status < 0) {
614 LOG_ERR("Could not add gpio int2 callback (%d)", status);
615 return status;
616 }
617
618 LOG_INF("%s: int2 on %s.%02u", dev->name,
619 cfg->gpio_int.port->name,
620 cfg->gpio_int.pin);
621
622 /* disable interrupt in case of warm (re)boot */
623 status = lis2dh->hw_tf->write_reg(dev,
624 cfg->hw.anym_on_int1 ?
625 LIS2DH_REG_INT1_CFG :
626 LIS2DH_REG_INT2_CFG,
627 0);
628 if (status < 0) {
629 LOG_ERR("Interrupt disable reg write failed (%d)", status);
630 return status;
631 }
632 status = lis2dh->hw_tf->write_reg(dev,
633 LIS2DH_REG_CFG_CLICK,
634 0);
635 if (status < 0) {
636 LOG_ERR("Interrupt disable reg write failed (%d)", status);
637 return status;
638 }
639
640 (void)memset(raw, 0, sizeof(raw));
641 status = lis2dh->hw_tf->write_data(dev,
642 cfg->hw.anym_on_int1 ?
643 LIS2DH_REG_INT1_THS :
644 LIS2DH_REG_INT2_THS,
645 raw, sizeof(raw));
646 if (status < 0) {
647 LOG_ERR("Burst write to THS failed (%d)", status);
648 return status;
649 }
650
651 if (cfg->hw.anym_latch) {
652 /* latch line interrupt */
653 status = lis2dh->hw_tf->write_reg(dev,
654 LIS2DH_REG_CTRL5,
655 cfg->hw.anym_on_int1 ?
656 LIS2DH_EN_LIR_INT1 :
657 LIS2DH_EN_LIR_INT2);
658 }
659
660 if (status < 0) {
661 LOG_ERR("enable reg write failed (%d)", status);
662 return status;
663 }
664
665 end:
666 return status;
667 }
668