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 					 &reg_val);
180 	status = lis2dh->hw_tf->read_reg(dev,
181 					 LIS2DH_REG_CLICK_SRC,
182 					 &reg_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 						 &reg_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 						 &reg_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 						 &reg_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