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 					 &reg_val);
172 	status = lis2dh->hw_tf->read_reg(dev,
173 					 LIS2DH_REG_CLICK_SRC,
174 					 &reg_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 						 &reg_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 							 &reg_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 						 &reg_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