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 
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 						 &reg_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 						 &reg_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