1 /*
2  * Copyright (c) 2023 Michal Morsisko
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT ti_tmag5170
8 
9 #include <zephyr/drivers/sensor.h>
10 #include <zephyr/logging/log.h>
11 #include <zephyr/kernel.h>
12 #include <zephyr/devicetree.h>
13 #include <zephyr/pm/device.h>
14 #include <zephyr/sys/byteorder.h>
15 #include <zephyr/sys/__assert.h>
16 
17 #if defined(CONFIG_TMAG5170_CRC)
18 #include <zephyr/sys/crc.h>
19 #endif
20 
21 #include "tmag5170.h"
22 
23 #define TMAG5170_REG_DEVICE_CONFIG	0x0U
24 #define TMAG5170_REG_SENSOR_CONFIG	0x1U
25 #define TMAG5170_REG_SYSTEM_CONFIG	0x2U
26 #define TMAG5170_REG_ALERT_CONFIG	0x3U
27 #define TMAG5170_REG_X_THRX_CONFIG	0x4U
28 #define TMAG5170_REG_Y_THRX_CONFIG	0x5U
29 #define TMAG5170_REG_Z_THRX_CONFIG	0x6U
30 #define TMAG5170_REG_T_THRX_CONFIG	0x7U
31 #define TMAG5170_REG_CONV_STATUS	0x8U
32 #define TMAG5170_REG_X_CH_RESULT	0x9U
33 #define TMAG5170_REG_Y_CH_RESULT	0xAU
34 #define TMAG5170_REG_Z_CH_RESULT	0xBU
35 #define TMAG5170_REG_TEMP_RESULT	0xCU
36 #define TMAG5170_REG_AFE_STATUS		0xDU
37 #define TMAG5170_REG_SYS_STATUS		0xEU
38 #define TMAG5170_REG_TEST_CONFIG	0xFU
39 #define TMAG5170_REG_OSC_MONITOR	0x10U
40 #define TMAG5170_REG_MAG_GAIN_CONFIG	0x11U
41 #define TMAG5170_REG_MAG_OFFSET_CONFIG	0x12U
42 #define TMAG5170_REG_ANGLE_RESULT	0x13U
43 #define TMAG5170_REG_MAGNITUDE_RESULT	0x14U
44 
45 #define TMAG5170_CONV_AVG_POS		12U
46 #define TMAG5170_CONV_AVG_MASK		(BIT_MASK(3U) << TMAG5170_CONV_AVG_POS)
47 #define TMAG5170_CONV_AVG_SET(value)	(((value) << TMAG5170_CONV_AVG_POS) &\
48 					TMAG5170_CONV_AVG_MASK)
49 
50 #define TMAG5170_MAG_TEMPCO_POS		8U
51 #define TMAG5170_MAG_TEMPCO_MASK	(BIT_MASK(2U) << TMAG5170_MAG_TEMPCO_POS)
52 #define TMAG5170_MAG_TEMPCO_SET(value)	(((value) << TMAG5170_MAG_TEMPCO_POS) &\
53 					TMAG5170_MAG_TEMPCO_MASK)
54 
55 #define TMAG5170_OPERATING_MODE_POS		4U
56 #define TMAG5170_OPERATING_MODE_MASK		(BIT_MASK(3U) << TMAG5170_OPERATING_MODE_POS)
57 #define TMAG5170_OPERATING_MODE_SET(value)	(((value) << TMAG5170_OPERATING_MODE_POS) &\
58 						TMAG5170_OPERATING_MODE_MASK)
59 
60 #define TMAG5170_T_CH_EN_POS		3U
61 #define TMAG5170_T_CH_EN_MASK		(BIT_MASK(1U) << TMAG5170_T_CH_EN_POS)
62 #define TMAG5170_T_CH_EN_SET(value)	(((value) << TMAG5170_T_CH_EN_POS) &\
63 					TMAG5170_T_CH_EN_MASK)
64 
65 #define TMAG5170_T_RATE_POS		2U
66 #define TMAG5170_T_RATE_MASK		(BIT_MASK(1U) << TMAG5170_T_RATE_POS)
67 #define TMAG5170_T_RATE_SET(value)	(((value) << TMAG5170_T_RATE_POS) &\
68 					TMAG5170_T_RATE_MASK)
69 
70 #define TMAG5170_ANGLE_EN_POS		14U
71 #define TMAG5170_ANGLE_EN_MASK		(BIT_MASK(2U) << TMAG5170_ANGLE_EN_POS)
72 #define TMAG5170_ANGLE_EN_SET(value)	(((value) << TMAG5170_ANGLE_EN_POS) &\
73 					TMAG5170_ANGLE_EN_MASK)
74 
75 #define TMAG5170_SLEEPTIME_POS	10U
76 #define TMAG5170_SLEEPTIME_MASK		(BIT_MASK(4U) << TMAG5170_SLEEPTIME_POS)
77 #define TMAG5170_SLEEPTIME_SET(value)	(((value) << TMAG5170_SLEEPTIME_POS) &\
78 					TMAG5170_SLEEPTIME_MASK)
79 
80 #define TMAG5170_MAG_CH_EN_POS	6U
81 #define TMAG5170_MAG_CH_EN_MASK		(BIT_MASK(4U) << TMAG5170_MAG_CH_EN_POS)
82 #define TMAG5170_MAG_CH_EN_SET(value)	(((value) << TMAG5170_MAG_CH_EN_POS) &\
83 					TMAG5170_MAG_CH_EN_MASK)
84 
85 #define TMAG5170_Z_RANGE_POS		4U
86 #define TMAG5170_Z_RANGE_MASK		(BIT_MASK(2U) << TMAG5170_Z_RANGE_POS)
87 #define TMAG5170_Z_RANGE_SET(value)	(((value) << TMAG5170_Z_RANGE_POS) &\
88 					TMAG5170_Z_RANGE_MASK)
89 
90 #define TMAG5170_Y_RANGE_POS		2U
91 #define TMAG5170_Y_RANGE_MASK		(BIT_MASK(2U) << TMAG5170_Y_RANGE_POS)
92 #define TMAG5170_Y_RANGE_SET(value)	(((value) << TMAG5170_Y_RANGE_POS) &\
93 					TMAG5170_Y_RANGE_MASK)
94 
95 #define TMAG5170_X_RANGE_POS		0U
96 #define TMAG5170_X_RANGE_MASK		(BIT_MASK(2U) << TMAG5170_X_RANGE_POS)
97 #define TMAG5170_X_RANGE_SET(value)	(((value) << TMAG5170_X_RANGE_POS) &\
98 					TMAG5170_X_RANGE_MASK)
99 
100 #define TMAG5170_RSLT_ALRT_POS		8U
101 #define TMAG5170_RSLT_ALRT_MASK		(BIT_MASK(1U) << TMAG5170_RSLT_ALRT_POS)
102 #define TMAG5170_RSLT_ALRT_SET(value)	(((value) << TMAG5170_RSLT_ALRT_POS) &\
103 					TMAG5170_RSLT_ALRT_MASK)
104 
105 #define TMAG5170_VER_POS	4U
106 #define TMAG5170_VER_MASK	(BIT_MASK(2U) << TMAG5170_VER_POS)
107 #define TMAG5170_VER_GET(value)	(((value) & TMAG5170_VER_MASK) >> TMAG5170_VER_POS)
108 
109 #define TMAG5170_A1_REV				0x0U
110 #define TMAG5170_A2_REV				0x1U
111 
112 #define TMAG5170_MAX_RANGE_50MT_IDX		0x0U
113 #define TMAG5170_MAX_RANGE_25MT_IDX		0x1U
114 #define TMAG5170_MAX_RANGE_100MT_IDX		0x2U
115 #define TMAG5170_MAX_RANGE_EXTEND_FACTOR	0x3U
116 
117 #define TMAG5170_CONFIGURATION_MODE		0x0U
118 #define TMAG5170_STAND_BY_MODE			0x1U
119 #define TMAG5170_ACTIVE_TRIGGER_MODE		0x3U
120 #define TMAG5170_SLEEP_MODE			0x5U
121 #define TMAG5170_DEEP_SLEEP_MODE		0x6U
122 
123 #define TMAG5170_MT_TO_GAUSS_RATIO		10U
124 #define TMAG5170_T_SENS_T0			25U
125 #define TMAG5170_T_ADC_T0			17522U
126 #define TMAG5170_T_ADC_RES			60U
127 
128 #define TMAG5170_CMD_TRIGGER_CONVERSION		BIT(0U)
129 
130 #define TMAG5170_CRC_SEED			0xFU
131 #define TMAG5170_CRC_POLY			0x3U
132 #define TMAG5170_SPI_BUFFER_LEN			4U
133 #define TMAG5170_SET_CRC(buf, crc)		((uint8_t *)(buf))[3] |= (crc & 0x0F)
134 #define TMAG5170_ZERO_CRC(buf)			((uint8_t *)(buf))[3] &= 0xF0
135 #define TMAG5170_GET_CRC(buf)			((uint8_t *)(buf))[3] & 0x0F
136 
137 LOG_MODULE_REGISTER(TMAG5170, CONFIG_SENSOR_LOG_LEVEL);
138 
tmag5170_transmit_raw(const struct tmag5170_dev_config * config,uint8_t * buffer_tx,uint8_t * buffer_rx)139 static int tmag5170_transmit_raw(const struct tmag5170_dev_config *config,
140 				 uint8_t *buffer_tx,
141 				 uint8_t *buffer_rx)
142 {
143 	const struct spi_buf tx_buf = {
144 		.buf = buffer_tx,
145 		.len = TMAG5170_SPI_BUFFER_LEN,
146 	};
147 
148 	const struct spi_buf_set tx = {
149 		.buffers = &tx_buf,
150 		.count = 1
151 	};
152 
153 	const struct spi_buf rx_buf = {
154 		.buf = buffer_rx,
155 		.len = TMAG5170_SPI_BUFFER_LEN,
156 	};
157 
158 	const struct spi_buf_set rx = {
159 		.buffers = &rx_buf,
160 		.count = 1
161 	};
162 
163 	int ret = spi_transceive_dt(&config->bus, &tx, &rx);
164 
165 	return ret;
166 }
167 
tmag5170_transmit(const struct device * dev,uint8_t * buffer_tx,uint8_t * buffer_rx)168 static int tmag5170_transmit(const struct device *dev, uint8_t *buffer_tx, uint8_t *buffer_rx)
169 {
170 #if defined(CONFIG_TMAG5170_CRC)
171 	TMAG5170_ZERO_CRC(buffer_tx);
172 	uint8_t crc = crc4_ti(TMAG5170_CRC_SEED, buffer_tx, TMAG5170_SPI_BUFFER_LEN);
173 
174 	TMAG5170_SET_CRC(buffer_tx, crc);
175 #endif
176 	int ret = tmag5170_transmit_raw(dev->config, buffer_tx, buffer_rx);
177 #if defined(CONFIG_TMAG5170_CRC)
178 	if (buffer_rx != NULL && ret == 0) {
179 		uint8_t read_crc = TMAG5170_GET_CRC(buffer_rx);
180 
181 		TMAG5170_ZERO_CRC(buffer_rx);
182 		crc = crc4_ti(TMAG5170_CRC_SEED, buffer_rx, TMAG5170_SPI_BUFFER_LEN);
183 		if (read_crc != crc) {
184 			return -EIO;
185 		}
186 	}
187 #endif
188 
189 	return ret;
190 }
191 
tmag5170_write_register(const struct device * dev,uint32_t reg,uint16_t data)192 static int tmag5170_write_register(const struct device *dev, uint32_t reg, uint16_t data)
193 {
194 	uint8_t buffer_tx[4] = { reg, (data >> 8) & 0xFF, data & 0xFF, 0x00U };
195 
196 	return tmag5170_transmit(dev, buffer_tx, NULL);
197 }
198 
tmag5170_read_register(const struct device * dev,uint32_t reg,uint16_t * output,uint8_t cmd)199 static int tmag5170_read_register(const struct device *dev,
200 				  uint32_t reg,
201 				  uint16_t *output,
202 				  uint8_t cmd)
203 {
204 	uint8_t buffer_tx[4] = { BIT(7) | reg, 0x00U, 0x00U, (cmd & BIT_MASK(4U)) << 4U };
205 	uint8_t buffer_rx[4] = { 0x00U };
206 
207 	int ret = tmag5170_transmit(dev, buffer_tx, buffer_rx);
208 
209 	*output = (buffer_rx[1] << 8) | buffer_rx[2];
210 
211 	return ret;
212 }
213 
tmag5170_convert_magn_reading_to_gauss(struct sensor_value * output,uint16_t chan_reading,uint8_t chan_range,uint8_t chip_revision)214 static int tmag5170_convert_magn_reading_to_gauss(struct sensor_value *output,
215 						  uint16_t chan_reading,
216 						  uint8_t chan_range,
217 						  uint8_t chip_revision)
218 {
219 	uint16_t max_range_mt = 0U;
220 
221 	if (chan_range == TMAG5170_MAX_RANGE_50MT_IDX) {
222 		max_range_mt = 50U;
223 	} else if (chan_range == TMAG5170_MAX_RANGE_25MT_IDX) {
224 		max_range_mt = 25U;
225 	} else if (chan_range == TMAG5170_MAX_RANGE_100MT_IDX) {
226 		max_range_mt = 100U;
227 	} else {
228 		return -ENOTSUP;
229 	}
230 
231 	if (chip_revision == TMAG5170_A2_REV) {
232 		max_range_mt *= TMAG5170_MAX_RANGE_EXTEND_FACTOR;
233 	}
234 
235 	max_range_mt *= 2U;
236 
237 	/* The sensor returns data in mT, we need to convert it to Gauss */
238 	uint32_t max_range_gauss = max_range_mt * TMAG5170_MT_TO_GAUSS_RATIO;
239 
240 	/* Convert from 2's complementary system */
241 	int64_t result = chan_reading - ((chan_reading & 0x8000) << 1);
242 
243 	result *= max_range_gauss;
244 
245 	/* Scale to increase accuracy */
246 	result *= 100000;
247 
248 	/* Divide as it is shown in datasheet */
249 	result /= 65536;
250 
251 	/* Remove scale from the final result */
252 	output->val1 = result / 100000;
253 	output->val2 = result % 100000;
254 
255 	return 0;
256 }
257 
tmag5170_convert_temp_reading_to_celsius(struct sensor_value * output,uint16_t chan_reading)258 static void tmag5170_convert_temp_reading_to_celsius(struct sensor_value *output,
259 						     uint16_t chan_reading)
260 {
261 	int32_t result = chan_reading - TMAG5170_T_ADC_T0;
262 
263 	result = (TMAG5170_T_SENS_T0 * 100000) + (100000 * result / (int32_t)TMAG5170_T_ADC_RES);
264 
265 	output->val1 = result / 100000;
266 	output->val2 = (result % 100000) * 10;
267 }
268 
tmag5170_covert_angle_reading_to_degrees(struct sensor_value * output,uint16_t chan_reading)269 static void tmag5170_covert_angle_reading_to_degrees(struct sensor_value *output,
270 						     uint16_t chan_reading)
271 {
272 	/* 12 MSBs store the integer part of the result,
273 	 * 4 LSBs store the fractional part of the result
274 	 */
275 	output->val1 = chan_reading >> 4;
276 	output->val2 = ((chan_reading & 0xF) * 1000000) / 16;
277 }
278 
tmag5170_sample_fetch(const struct device * dev,enum sensor_channel chan)279 static int tmag5170_sample_fetch(const struct device *dev,
280 				 enum sensor_channel chan)
281 {
282 	const struct tmag5170_dev_config *cfg = dev->config;
283 	struct tmag5170_data *drv_data = dev->data;
284 	int ret = 0;
285 
286 	if (cfg->operating_mode == TMAG5170_STAND_BY_MODE ||
287 	    cfg->operating_mode == TMAG5170_ACTIVE_TRIGGER_MODE) {
288 		uint16_t read_status;
289 
290 		tmag5170_read_register(dev,
291 				       TMAG5170_REG_SYS_STATUS,
292 				       &read_status,
293 				       TMAG5170_CMD_TRIGGER_CONVERSION);
294 
295 		/* Wait for the measurement to be ready.
296 		 * The waiting time will vary depending on the configuration
297 		 */
298 		k_sleep(K_MSEC(5U));
299 	}
300 
301 	switch (chan) {
302 	case SENSOR_CHAN_MAGN_X:
303 		ret = tmag5170_read_register(dev, TMAG5170_REG_X_CH_RESULT, &drv_data->x, 0U);
304 		break;
305 	case SENSOR_CHAN_MAGN_Y:
306 		ret = tmag5170_read_register(dev, TMAG5170_REG_Y_CH_RESULT, &drv_data->y, 0U);
307 		break;
308 	case SENSOR_CHAN_MAGN_Z:
309 		ret = tmag5170_read_register(dev, TMAG5170_REG_Z_CH_RESULT, &drv_data->z, 0U);
310 		break;
311 	case SENSOR_CHAN_MAGN_XYZ:
312 		ret = tmag5170_read_register(dev, TMAG5170_REG_X_CH_RESULT, &drv_data->x, 0U);
313 
314 		if (ret == 0) {
315 			ret = tmag5170_read_register(dev,
316 						     TMAG5170_REG_Y_CH_RESULT,
317 						     &drv_data->y,
318 						     0U);
319 		}
320 		if (ret == 0) {
321 			ret = tmag5170_read_register(dev,
322 						     TMAG5170_REG_Z_CH_RESULT,
323 						     &drv_data->z,
324 						     0U);
325 		}
326 		break;
327 	case SENSOR_CHAN_ROTATION:
328 		ret = tmag5170_read_register(dev,
329 					     TMAG5170_REG_ANGLE_RESULT,
330 					     &drv_data->angle,
331 					     0U);
332 		break;
333 	case SENSOR_CHAN_AMBIENT_TEMP:
334 		ret = tmag5170_read_register(dev,
335 					TMAG5170_REG_TEMP_RESULT,
336 					&drv_data->temperature,
337 					0U);
338 		break;
339 	case SENSOR_CHAN_ALL:
340 		ret = tmag5170_read_register(dev,
341 					     TMAG5170_REG_TEMP_RESULT,
342 					     &drv_data->temperature,
343 					     0U);
344 
345 		if (ret == 0) {
346 			ret = tmag5170_read_register(dev,
347 						     TMAG5170_REG_ANGLE_RESULT,
348 						     &drv_data->angle,
349 						     0U);
350 		}
351 
352 		if (ret == 0) {
353 			ret = tmag5170_read_register(dev,
354 						     TMAG5170_REG_X_CH_RESULT,
355 						     &drv_data->x,
356 						     0U);
357 		}
358 
359 		if (ret == 0) {
360 			ret = tmag5170_read_register(dev,
361 						     TMAG5170_REG_Y_CH_RESULT,
362 						     &drv_data->y,
363 						     0U);
364 		}
365 
366 		if (ret == 0) {
367 			ret = tmag5170_read_register(dev,
368 						     TMAG5170_REG_Z_CH_RESULT,
369 						     &drv_data->z,
370 						     0U);
371 		}
372 
373 		break;
374 	default:
375 		ret = -ENOTSUP;
376 		break;
377 	}
378 
379 	return ret;
380 }
381 
tmag5170_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)382 static int tmag5170_channel_get(const struct device *dev,
383 				enum sensor_channel chan,
384 				struct sensor_value *val)
385 {
386 	const struct tmag5170_dev_config *cfg = dev->config;
387 	struct tmag5170_data *drv_data = dev->data;
388 	int ret = 0;
389 
390 	switch (chan) {
391 	case SENSOR_CHAN_MAGN_XYZ:
392 		ret = tmag5170_convert_magn_reading_to_gauss(val,
393 							     drv_data->x,
394 							     cfg->x_range,
395 							     drv_data->chip_revision);
396 
397 		if (ret == 0) {
398 			ret = tmag5170_convert_magn_reading_to_gauss(val + 1,
399 								     drv_data->y,
400 								     cfg->y_range,
401 								     drv_data->chip_revision);
402 		}
403 
404 		if (ret == 0) {
405 			ret = tmag5170_convert_magn_reading_to_gauss(val + 2,
406 								     drv_data->z,
407 								     cfg->z_range,
408 								     drv_data->chip_revision);
409 		}
410 		break;
411 	case SENSOR_CHAN_MAGN_X:
412 		ret = tmag5170_convert_magn_reading_to_gauss(val,
413 							     drv_data->x,
414 							     cfg->x_range,
415 							     drv_data->chip_revision);
416 		break;
417 	case SENSOR_CHAN_MAGN_Y:
418 		ret = tmag5170_convert_magn_reading_to_gauss(val,
419 							     drv_data->y,
420 							     cfg->y_range,
421 							     drv_data->chip_revision);
422 		break;
423 	case SENSOR_CHAN_MAGN_Z:
424 		ret = tmag5170_convert_magn_reading_to_gauss(val,
425 							     drv_data->z,
426 							     cfg->z_range,
427 							     drv_data->chip_revision);
428 		break;
429 	case SENSOR_CHAN_ROTATION:
430 		tmag5170_covert_angle_reading_to_degrees(val, drv_data->angle);
431 		break;
432 	case SENSOR_CHAN_AMBIENT_TEMP:
433 		tmag5170_convert_temp_reading_to_celsius(val, drv_data->temperature);
434 		break;
435 	default:
436 		ret = -ENOTSUP;
437 		break;
438 	}
439 
440 	return ret;
441 }
442 
tmag5170_init_registers(const struct device * dev)443 static int tmag5170_init_registers(const struct device *dev)
444 {
445 	const struct tmag5170_dev_config *cfg = dev->config;
446 	struct tmag5170_data *drv_data = dev->data;
447 	uint16_t test_cfg_reg = 0U;
448 	int ret = 0;
449 
450 #if !defined(CONFIG_TMAG5170_CRC)
451 	const uint8_t disable_crc_packet[4] = { 0x0FU, 0x0U, 0x04U, 0x07U };
452 
453 	ret = tmag5170_transmit_raw(cfg, disable_crc_packet, NULL);
454 #endif
455 	if (ret == 0) {
456 		ret = tmag5170_read_register(dev, TMAG5170_REG_TEST_CONFIG, &test_cfg_reg, 0U);
457 	}
458 
459 	if (ret == 0) {
460 		drv_data->chip_revision = TMAG5170_VER_GET(test_cfg_reg);
461 
462 		ret = tmag5170_write_register(dev,
463 				TMAG5170_REG_SENSOR_CONFIG,
464 				TMAG5170_ANGLE_EN_SET(cfg->angle_measurement) |
465 				TMAG5170_SLEEPTIME_SET(cfg->sleep_time) |
466 				TMAG5170_MAG_CH_EN_SET(cfg->magnetic_channels) |
467 				TMAG5170_Z_RANGE_SET(cfg->z_range) |
468 				TMAG5170_Y_RANGE_SET(cfg->y_range) |
469 				TMAG5170_X_RANGE_SET(cfg->x_range));
470 	}
471 
472 #if defined(CONFIG_TMAG5170_TRIGGER)
473 	if (ret == 0) {
474 		ret = tmag5170_write_register(dev,
475 				TMAG5170_REG_ALERT_CONFIG,
476 				TMAG5170_RSLT_ALRT_SET(1U));
477 	}
478 #endif
479 	if (ret == 0) {
480 		ret = tmag5170_write_register(dev,
481 				TMAG5170_REG_DEVICE_CONFIG,
482 				TMAG5170_OPERATING_MODE_SET(cfg->operating_mode) |
483 				TMAG5170_CONV_AVG_SET(cfg->oversampling) |
484 				TMAG5170_MAG_TEMPCO_SET(cfg->magnet_type) |
485 				TMAG5170_T_CH_EN_SET(cfg->tempeature_measurement) |
486 				TMAG5170_T_RATE_SET(cfg->disable_temperature_oversampling));
487 	}
488 
489 	return ret;
490 }
491 
492 #ifdef CONFIG_PM_DEVICE
tmag5170_pm_action(const struct device * dev,enum pm_device_action action)493 static int tmag5170_pm_action(const struct device *dev,
494 			      enum pm_device_action action)
495 {
496 	int ret_val = 0;
497 
498 	switch (action) {
499 	case PM_DEVICE_ACTION_RESUME:
500 		tmag5170_write_register(dev,
501 					TMAG5170_REG_DEVICE_CONFIG,
502 					TMAG5170_OPERATING_MODE_SET(TMAG5170_CONFIGURATION_MODE));
503 		/* As per datasheet, waking up from deep-sleep can take up to 500us */
504 		k_sleep(K_USEC(500));
505 		ret_val = tmag5170_init_registers(dev);
506 		break;
507 	case PM_DEVICE_ACTION_SUSPEND:
508 		ret_val = tmag5170_write_register(dev,
509 					TMAG5170_REG_DEVICE_CONFIG,
510 					TMAG5170_OPERATING_MODE_SET(TMAG5170_DEEP_SLEEP_MODE));
511 		break;
512 	default:
513 		ret_val = -ENOTSUP;
514 	}
515 
516 	return ret_val;
517 }
518 #endif /* CONFIG_PM_DEVICE */
519 
520 static DEVICE_API(sensor, tmag5170_driver_api) = {
521 	.sample_fetch = tmag5170_sample_fetch,
522 	.channel_get = tmag5170_channel_get,
523 #if defined(CONFIG_TMAG5170_TRIGGER)
524 	.trigger_set = tmag5170_trigger_set
525 #endif
526 };
527 
tmag5170_init(const struct device * dev)528 static int tmag5170_init(const struct device *dev)
529 {
530 	const struct tmag5170_dev_config *cfg = dev->config;
531 	int ret = 0;
532 
533 	if (!spi_is_ready_dt(&cfg->bus)) {
534 		LOG_ERR("SPI dev %s not ready", cfg->bus.bus->name);
535 		return -ENODEV;
536 	}
537 
538 	ret = tmag5170_init_registers(dev);
539 	if (ret != 0) {
540 		return ret;
541 	}
542 
543 #if defined(CONFIG_TMAG5170_TRIGGER)
544 	if (cfg->int_gpio.port) {
545 		ret = tmag5170_trigger_init(dev);
546 	}
547 #endif
548 
549 	return ret;
550 }
551 
552 #define DEFINE_TMAG5170(_num)								   \
553 	static struct tmag5170_data tmag5170_data_##_num;				   \
554 	static const struct tmag5170_dev_config tmag5170_config_##_num = {		   \
555 		.bus = SPI_DT_SPEC_INST_GET(_num,					   \
556 					   SPI_OP_MODE_MASTER |				   \
557 					   SPI_TRANSFER_MSB |				   \
558 					   SPI_WORD_SET(32),				   \
559 					   0),						   \
560 		.magnetic_channels = DT_INST_ENUM_IDX(_num, magnetic_channels),		   \
561 		.x_range = DT_INST_ENUM_IDX(_num, x_range),				   \
562 		.y_range = DT_INST_ENUM_IDX(_num, y_range),				   \
563 		.z_range = DT_INST_ENUM_IDX(_num, z_range),				   \
564 		.operating_mode = DT_INST_PROP(_num, operating_mode),			   \
565 		.oversampling = DT_INST_ENUM_IDX(_num, oversampling),			   \
566 		.tempeature_measurement = DT_INST_PROP(_num, enable_temperature_channel),  \
567 		.magnet_type = DT_INST_ENUM_IDX(_num, magnet_type),			   \
568 		.angle_measurement = DT_INST_ENUM_IDX(_num, angle_measurement),		   \
569 		.disable_temperature_oversampling = DT_INST_PROP(_num,			   \
570 							disable_temperature_oversampling), \
571 		.sleep_time = DT_INST_ENUM_IDX(_num, sleep_time),			   \
572 		IF_ENABLED(CONFIG_TMAG5170_TRIGGER,					   \
573 			(.int_gpio = GPIO_DT_SPEC_INST_GET_OR(_num, int_gpios, { 0 }),))   \
574 	};										   \
575 	PM_DEVICE_DT_INST_DEFINE(_num, tmag5170_pm_action);				   \
576 											   \
577 	SENSOR_DEVICE_DT_INST_DEFINE(_num,						   \
578 				tmag5170_init,						   \
579 				PM_DEVICE_DT_INST_GET(_num),				   \
580 				&tmag5170_data_##_num,					   \
581 				&tmag5170_config_##_num,				   \
582 				POST_KERNEL,						   \
583 				CONFIG_SENSOR_INIT_PRIORITY,				   \
584 				&tmag5170_driver_api);
585 
586 DT_INST_FOREACH_STATUS_OKAY(DEFINE_TMAG5170)
587