1 /*
2 * Copyright (c) 2023 deveritec GmbH
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT ti_tmag5273
8
9 #include "tmag5273.h"
10
11 #include <stdint.h>
12 #include <stdlib.h>
13
14 #include <zephyr/drivers/sensor/tmag5273.h>
15 #include <zephyr/dt-bindings/sensor/tmag5273.h>
16
17 #include <zephyr/device.h>
18 #include <zephyr/kernel.h>
19
20 #include <zephyr/drivers/gpio.h>
21 #include <zephyr/drivers/i2c.h>
22 #include <zephyr/drivers/sensor.h>
23 #include <zephyr/sys/byteorder.h>
24 #include <zephyr/sys/check.h>
25 #include <zephyr/sys/crc.h>
26 #include <zephyr/sys/util.h>
27
28 #include <zephyr/logging/log.h>
29 LOG_MODULE_REGISTER(TMAG5273, CONFIG_SENSOR_LOG_LEVEL);
30
31 #define CONV_FACTOR_MT_TO_GS 10
32
33 #define TMAG5273_CRC_DATA_BYTES 4
34 #define TMAG5273_CRC_I2C_SIZE COND_CODE_1(CONFIG_CRC, (1), (0))
35
36 /**
37 * @brief size of the buffer to read out all result data from the sensor
38 *
39 * Since the register counting is zero-based, one byte needs to be added to get the correct size.
40 * Also takes into account if CRC is enabled, which adds an additional byte for the CRC always
41 * located after the last read result byte.
42 */
43 #define TMAG5273_I2C_BUFFER_SIZE \
44 (TMAG5273_REG_RESULT_END - TMAG5273_REG_RESULT_BEGIN + 1 + TMAG5273_CRC_I2C_SIZE)
45
46 /** static configuration data */
47 struct tmag5273_config {
48 struct i2c_dt_spec i2c;
49
50 uint8_t mag_channel;
51 uint8_t axis;
52 bool temperature;
53
54 uint8_t meas_range;
55 uint8_t temperature_coefficient;
56 uint8_t angle_magnitude_axis;
57 uint8_t ch_mag_gain_correction;
58
59 uint8_t operation_mode;
60 uint8_t averaging;
61
62 bool trigger_conv_via_int;
63 bool low_noise_mode;
64 bool ignore_diag_fail;
65
66 struct gpio_dt_spec int_gpio;
67
68 #ifdef CONFIG_CRC
69 bool crc_enabled;
70 #endif
71 };
72
73 struct tmag5273_data {
74 uint8_t version; /** version as given by the sensor */
75 uint16_t conversion_time_us; /** time for one conversion */
76
77 int16_t x_sample; /** measured B-field @x-axis */
78 int16_t y_sample; /** measured B-field @y-axis */
79 int16_t z_sample; /** measured B-field @z-axis */
80 int16_t temperature_sample; /** measured temperature data */
81
82 uint16_t xyz_range; /** magnetic range for x/y/z-axis in mT */
83
84 int16_t angle_sample; /** measured angle in degree, if activated */
85 uint8_t magnitude_sample; /** Positive vector magnitude (can be >7 bit). */
86 };
87
88 /**
89 * @brief resets the DEVICE_STATUS register
90 *
91 * @param dev driver handle
92 * @retval see @ref i2c_reg_write_byte
93 */
tmag5273_reset_device_status(const struct device * dev)94 static int tmag5273_reset_device_status(const struct device *dev)
95 {
96 const struct tmag5273_config *drv_cfg = dev->config;
97
98 return i2c_reg_write_byte_dt(&drv_cfg->i2c, TMAG5273_REG_DEVICE_STATUS,
99 TMAG5273_RESET_DEVICE_STATUS);
100 }
101
102 /**
103 * @brief checks for DIAG_FAIL errors and reads out the DEVICE_STATUS register if necessary
104 *
105 * @param[in] drv_cfg driver instance configuration
106 * @param[out] device_status DEVICE_STATUS register if DIAG_FAIL is set
107 *
108 * @retval 0 on success
109 * @retval "!= 0" on error
110 * - \c -EIO on any set error device status bit
111 * - see @ref i2c_reg_read_byte for error codes
112 *
113 * @note
114 * If tmag5273_config.ignore_diag_fail is set
115 * - \a device_status will be always set to \c 0,
116 * - the function always returns \c 0.
117 */
tmag5273_check_device_status(const struct tmag5273_config * drv_cfg,uint8_t * device_status)118 static int tmag5273_check_device_status(const struct tmag5273_config *drv_cfg,
119 uint8_t *device_status)
120 {
121 int retval;
122
123 if (drv_cfg->ignore_diag_fail) {
124 *device_status = 0;
125 return 0;
126 }
127
128 retval = i2c_reg_read_byte_dt(&drv_cfg->i2c, TMAG5273_REG_CONV_STATUS, device_status);
129 if (retval < 0) {
130 LOG_ERR("error reading CONV_STATUS %d", retval);
131 return retval;
132 }
133
134 if ((*device_status & TMAG5273_DIAG_STATUS_MSK) != TMAG5273_DIAG_FAIL) {
135 /* no error */
136 *device_status = 0;
137 return 0;
138 }
139
140 retval = i2c_reg_read_byte_dt(&drv_cfg->i2c, TMAG5273_REG_DEVICE_STATUS, device_status);
141 if (retval < 0) {
142 LOG_ERR("error reading DEVICE_STATUS %d", retval);
143 return retval;
144 }
145
146 if ((*device_status & TMAG5273_VCC_UV_ER_MSK) == TMAG5273_VCC_UV_ERR) {
147 LOG_ERR("VCC under voltage detected");
148 }
149 #ifdef CONFIG_CRC
150 if (drv_cfg->crc_enabled &&
151 ((*device_status & TMAG5273_OTP_CRC_ER_MSK) == TMAG5273_OTP_CRC_ERR)) {
152 LOG_ERR("OTP CRC error detected");
153 }
154 #endif
155 if ((*device_status & TMAG5273_INT_ER_MSK) == TMAG5273_INT_ERR) {
156 LOG_ERR("INT pin error detected");
157 }
158
159 if ((*device_status & TMAG5273_OSC_ER_MSK) == TMAG5273_OSC_ERR) {
160 LOG_ERR("Oscillator error detected");
161 }
162
163 return -EIO;
164 }
165
166 /**
167 * @brief performs a trigger through the INT-pin
168 *
169 * @param drv_cfg driver instance configuration
170 *
171 * @retval 0 on success
172 * @retval see @ref gpio_pin_set_dt
173 */
tmag5273_dev_int_trigger(const struct tmag5273_config * drv_cfg)174 static inline int tmag5273_dev_int_trigger(const struct tmag5273_config *drv_cfg)
175 {
176 int retval;
177
178 retval = gpio_pin_configure_dt(&drv_cfg->int_gpio, GPIO_OUTPUT);
179 if (retval < 0) {
180 return retval;
181 }
182
183 retval = gpio_pin_set_dt(&drv_cfg->int_gpio, 1);
184 if (retval < 0) {
185 return retval;
186 }
187
188 retval = gpio_pin_set_dt(&drv_cfg->int_gpio, 0);
189 if (retval < 0) {
190 return retval;
191 }
192
193 retval = gpio_pin_configure_dt(&drv_cfg->int_gpio, GPIO_INPUT);
194 if (retval < 0) {
195 return retval;
196 }
197
198 return 0;
199 }
200
201 /** @brief returns the high measurement range based on the chip version */
tmag5273_range_high(uint8_t version)202 static inline uint16_t tmag5273_range_high(uint8_t version)
203 {
204 return (version == TMAG5273_VER_TMAG5273X1) ? TMAG5273_MEAS_RANGE_HIGH_MT_VER1
205 : TMAG5273_MEAS_RANGE_HIGH_MT_VER2;
206 }
207
208 /** @brief returns the low measurement range based on the chip version */
tmag5273_range_low(uint8_t version)209 static inline uint16_t tmag5273_range_low(uint8_t version)
210 {
211 return (version == TMAG5273_VER_TMAG5273X1) ? TMAG5273_MEAS_RANGE_LOW_MT_VER1
212 : TMAG5273_MEAS_RANGE_LOW_MT_VER2;
213 }
214
215 /**
216 * @brief update the measurement range of the X/Y/Z-axis
217 *
218 * @param dev handle to the sensor
219 * @param val value to be set
220 *
221 * @return see @ref i2c_reg_update_byte_dt
222 */
tmag5273_attr_set_xyz_meas_range(const struct device * dev,const struct sensor_value * val)223 static inline int tmag5273_attr_set_xyz_meas_range(const struct device *dev,
224 const struct sensor_value *val)
225 {
226 const struct tmag5273_config *drv_cfg = dev->config;
227 struct tmag5273_data *drv_data = dev->data;
228
229 const uint16_t range_high = tmag5273_range_high(drv_data->version);
230 const uint16_t range_low = tmag5273_range_low(drv_data->version);
231
232 int retval;
233 uint8_t regdata;
234 uint16_t range;
235
236 if (val->val1 >= range_high) {
237 regdata = TMAG5273_XYZ_MEAS_RANGE_HIGH;
238 range = range_high;
239 } else {
240 regdata = TMAG5273_XYZ_MEAS_RANGE_LOW;
241 range = range_low;
242 }
243
244 retval = i2c_reg_update_byte_dt(&drv_cfg->i2c, TMAG5273_REG_SENSOR_CONFIG_2,
245 TMAG5273_MEAS_RANGE_XYZ_MSK, regdata);
246 if (retval < 0) {
247 return retval;
248 }
249
250 drv_data->xyz_range = range;
251
252 return 0;
253 }
254
255 /**
256 * @brief returns the used measurement range of the X/Y/Z-axis
257 *
258 * @param dev handle to the sensor
259 * @param val return value
260 *
261 * @return \c 0 on success
262 * @return see @ref i2c_reg_read_byte_dt
263 */
tmag5273_attr_get_xyz_meas_range(const struct device * dev,struct sensor_value * val)264 static inline int tmag5273_attr_get_xyz_meas_range(const struct device *dev,
265 struct sensor_value *val)
266 {
267 const struct tmag5273_config *drv_cfg = dev->config;
268 struct tmag5273_data *drv_data = dev->data;
269
270 uint8_t regdata;
271 int retval;
272
273 retval = i2c_reg_read_byte_dt(&drv_cfg->i2c, TMAG5273_REG_SENSOR_CONFIG_2, ®data);
274 if (retval < 0) {
275 return retval;
276 }
277
278 if ((regdata & TMAG5273_MEAS_RANGE_XYZ_MSK) == TMAG5273_XYZ_MEAS_RANGE_HIGH) {
279 val->val1 = tmag5273_range_high(drv_data->version);
280 } else {
281 val->val1 = tmag5273_range_low(drv_data->version);
282 }
283
284 val->val2 = 0;
285
286 return 0;
287 }
288
289 /**
290 * set the X/Y/Z angle & magnitude calculation mode
291 *
292 * @param dev handle to the sensor
293 * @param val value to be set
294 *
295 * @return \c -ENOTSUP if unknown value
296 * @return see @ref i2c_reg_update_byte_dt
297 */
tmag5273_attr_set_xyz_calc(const struct device * dev,const struct sensor_value * val)298 static inline int tmag5273_attr_set_xyz_calc(const struct device *dev,
299 const struct sensor_value *val)
300 {
301 const struct tmag5273_config *drv_cfg = dev->config;
302 uint8_t regdata;
303 int retval;
304
305 switch (val->val1) {
306 case TMAG5273_ANGLE_CALC_NONE:
307 regdata = TMAG5273_ANGLE_EN_NONE;
308 break;
309 case TMAG5273_ANGLE_CALC_XY:
310 if (!(drv_cfg->axis & TMAG5273_MAG_CH_EN_X) ||
311 !(drv_cfg->axis & TMAG5273_MAG_CH_EN_Y)) {
312 return -ENOTSUP;
313 }
314 regdata = TMAG5273_ANGLE_EN_XY;
315 break;
316 case TMAG5273_ANGLE_CALC_YZ:
317 if (!(drv_cfg->axis & TMAG5273_MAG_CH_EN_Y) ||
318 !(drv_cfg->axis & TMAG5273_MAG_CH_EN_Z)) {
319 return -ENOTSUP;
320 }
321 regdata = TMAG5273_ANGLE_EN_YZ;
322 break;
323 case TMAG5273_ANGLE_CALC_XZ:
324 if (!(drv_cfg->axis & TMAG5273_MAG_CH_EN_X) ||
325 !(drv_cfg->axis & TMAG5273_MAG_CH_EN_Z)) {
326 return -ENOTSUP;
327 }
328 regdata = TMAG5273_ANGLE_EN_XZ;
329 break;
330 default:
331 LOG_ERR("unknown attribute value %d", val->val1);
332 return -ENOTSUP;
333 }
334
335 retval = i2c_reg_update_byte_dt(&drv_cfg->i2c, TMAG5273_REG_SENSOR_CONFIG_2,
336 TMAG5273_ANGLE_EN_MSK, regdata);
337 if (retval < 0) {
338 return retval;
339 }
340
341 return 0;
342 }
343
344 /**
345 * returns the X/Y/Z angle & magnitude calculation mode
346 *
347 * @param dev handle to the sensor
348 * @param val return value
349 *
350 * @return \c 0 on success
351 * @return see @ref i2c_reg_read_byte_dt
352 */
tmag5273_attr_get_xyz_calc(const struct device * dev,struct sensor_value * val)353 static inline int tmag5273_attr_get_xyz_calc(const struct device *dev, struct sensor_value *val)
354 {
355 const struct tmag5273_config *drv_cfg = dev->config;
356
357 uint8_t regdata;
358 int retval;
359
360 retval = i2c_reg_read_byte_dt(&drv_cfg->i2c, TMAG5273_REG_SENSOR_CONFIG_2, ®data);
361 if (retval < 0) {
362 return retval;
363 }
364
365 switch (regdata & TMAG5273_ANGLE_EN_MSK) {
366 case TMAG5273_ANGLE_EN_XY:
367 val->val1 = TMAG5273_ANGLE_CALC_XY;
368 break;
369 case TMAG5273_ANGLE_EN_YZ:
370 val->val1 = TMAG5273_ANGLE_CALC_YZ;
371 break;
372 case TMAG5273_ANGLE_EN_XZ:
373 val->val1 = TMAG5273_ANGLE_CALC_XZ;
374 break;
375 case TMAG5273_ANGLE_EN_NONE:
376 __fallthrough;
377 default:
378 val->val1 = TMAG5273_ANGLE_CALC_NONE;
379 }
380
381 val->val2 = 0;
382
383 return 0;
384 }
385
386 /** @brief returns the number of bytes readable per block for i2c burst reads */
tmag5273_get_fetch_block_size(const struct tmag5273_config * drv_cfg,uint8_t remaining_bytes)387 static inline uint8_t tmag5273_get_fetch_block_size(const struct tmag5273_config *drv_cfg,
388 uint8_t remaining_bytes)
389 {
390 #ifdef CONFIG_CRC
391 if (drv_cfg->crc_enabled && (remaining_bytes > TMAG5273_CRC_DATA_BYTES)) {
392 return TMAG5273_CRC_DATA_BYTES;
393 }
394 #endif
395 return remaining_bytes;
396 }
397
398 /** @brief returns the size of the CRC field if active */
tmag5273_get_crc_size(const struct tmag5273_config * drv_cfg)399 static inline uint8_t tmag5273_get_crc_size(const struct tmag5273_config *drv_cfg)
400 {
401 #ifdef CONFIG_CRC
402 if (drv_cfg->crc_enabled) {
403 return TMAG5273_CRC_I2C_SIZE;
404 }
405 #else
406 ARG_UNUSED(drv_cfg);
407 #endif
408 return 0;
409 }
410
tmag5273_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)411 static int tmag5273_attr_set(const struct device *dev, enum sensor_channel chan,
412 enum sensor_attribute attr, const struct sensor_value *val)
413 {
414 CHECKIF(dev == NULL) {
415 LOG_ERR("dev: NULL");
416 return -EINVAL;
417 }
418
419 CHECKIF(val == NULL) {
420 LOG_ERR("val: NULL");
421 return -EINVAL;
422 }
423
424 if (chan != SENSOR_CHAN_MAGN_XYZ) {
425 return -ENOTSUP;
426 }
427
428 const struct tmag5273_config *drv_cfg = dev->config;
429
430 int retval;
431
432 switch ((uint16_t)attr) {
433 case SENSOR_ATTR_FULL_SCALE:
434 if (drv_cfg->meas_range != TMAG5273_DT_AXIS_RANGE_RUNTIME) {
435 return -ENOTSUP;
436 }
437
438 retval = tmag5273_attr_set_xyz_meas_range(dev, val);
439 if (retval < 0) {
440 return retval;
441 }
442 break;
443 case TMAG5273_ATTR_ANGLE_MAG_AXIS:
444 if (drv_cfg->angle_magnitude_axis != TMAG5273_DT_ANGLE_MAG_RUNTIME) {
445 return -ENOTSUP;
446 }
447
448 retval = tmag5273_attr_set_xyz_calc(dev, val);
449 if (retval < 0) {
450 return retval;
451 }
452 break;
453 default:
454 LOG_ERR("unknown attribute %d", attr);
455 return -ENOTSUP;
456 }
457
458 return 0;
459 }
460
tmag5273_attr_get(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,struct sensor_value * val)461 static int tmag5273_attr_get(const struct device *dev, enum sensor_channel chan,
462 enum sensor_attribute attr, struct sensor_value *val)
463 {
464 CHECKIF(dev == NULL) {
465 LOG_ERR("dev: NULL");
466 return -EINVAL;
467 }
468
469 CHECKIF(val == NULL) {
470 LOG_ERR("val: NULL");
471 return -EINVAL;
472 }
473
474 if (chan != SENSOR_CHAN_MAGN_XYZ) {
475 return -ENOTSUP;
476 }
477
478 const struct tmag5273_config *drv_cfg = dev->config;
479
480 int retval;
481
482 switch ((uint16_t)attr) {
483 case SENSOR_ATTR_FULL_SCALE:
484 if (drv_cfg->meas_range != TMAG5273_DT_AXIS_RANGE_RUNTIME) {
485 return -ENOTSUP;
486 }
487
488 retval = tmag5273_attr_get_xyz_meas_range(dev, val);
489 if (retval < 0) {
490 return retval;
491 }
492 break;
493 case TMAG5273_ATTR_ANGLE_MAG_AXIS:
494 if (drv_cfg->angle_magnitude_axis != TMAG5273_DT_ANGLE_MAG_RUNTIME) {
495 return -ENOTSUP;
496 }
497
498 retval = tmag5273_attr_get_xyz_calc(dev, val);
499 if (retval < 0) {
500 return retval;
501 }
502 break;
503 default:
504 LOG_ERR("unknown attribute %d", attr);
505 return -ENOTSUP;
506 }
507
508 return 0;
509 }
510
tmag5273_sample_fetch(const struct device * dev,enum sensor_channel chan)511 static int tmag5273_sample_fetch(const struct device *dev, enum sensor_channel chan)
512 {
513 const struct tmag5273_config *drv_cfg = dev->config;
514 struct tmag5273_data *drv_data = dev->data;
515
516 int retval;
517
518 uint8_t i2c_buffer[TMAG5273_I2C_BUFFER_SIZE] = {0};
519
520 /* trigger a conversion and wait until done if in standby mode */
521 if (drv_cfg->operation_mode == TMAG5273_DT_OPER_MODE_STANDBY) {
522 if (drv_cfg->trigger_conv_via_int) {
523 retval = tmag5273_dev_int_trigger(drv_cfg);
524 if (retval < 0) {
525 return retval;
526 }
527 }
528
529 uint8_t conv_bit = TMAG5273_CONVERSION_START_BIT;
530
531 while ((i2c_buffer[0] & TMAG5273_RESULT_STATUS_MSK) !=
532 TMAG5273_CONVERSION_COMPLETE) {
533 retval = i2c_reg_read_byte_dt(
534 &drv_cfg->i2c, TMAG5273_REG_CONV_STATUS | conv_bit, &i2c_buffer[0]);
535
536 if (retval < 0) {
537 LOG_ERR("error reading conversion state %d", retval);
538 return retval;
539 }
540
541 conv_bit = 0;
542
543 k_usleep(drv_data->conversion_time_us);
544 }
545 }
546
547 /* read data */
548 uint8_t start_address, end_address;
549
550 switch ((int)chan) {
551 case SENSOR_CHAN_MAGN_X:
552 if (!(drv_cfg->axis & TMAG5273_MAG_CH_EN_X)) {
553 LOG_ERR("x-axis measurement deactivated");
554 return -ENOTSUP;
555 }
556 start_address = TMAG5273_REG_X_MSB_RESULT;
557 end_address = TMAG5273_REG_X_LSB_RESULT;
558 break;
559 case SENSOR_CHAN_MAGN_Y:
560 if (!(drv_cfg->axis & TMAG5273_MAG_CH_EN_Y)) {
561 LOG_ERR("y-axis measurement deactivated");
562 return -ENOTSUP;
563 }
564 start_address = TMAG5273_REG_Y_MSB_RESULT;
565 end_address = TMAG5273_REG_Y_LSB_RESULT;
566 break;
567 case SENSOR_CHAN_MAGN_Z:
568 if (!(drv_cfg->axis & TMAG5273_MAG_CH_EN_Z)) {
569 LOG_ERR("x-axis measurement deactivated");
570 return -ENOTSUP;
571 }
572 start_address = TMAG5273_REG_Z_MSB_RESULT;
573 end_address = TMAG5273_REG_Z_LSB_RESULT;
574 break;
575 case SENSOR_CHAN_MAGN_XYZ:
576 if (drv_cfg->axis == TMAG5273_MAG_CH_EN_NONE) {
577 LOG_ERR("xyz-axis measurement deactivated");
578 return -ENOTSUP;
579 }
580 start_address = TMAG5273_REG_X_MSB_RESULT;
581 end_address = TMAG5273_REG_Z_LSB_RESULT;
582 break;
583 case SENSOR_CHAN_DIE_TEMP:
584 if (!drv_cfg->temperature) {
585 LOG_ERR("temperature measurement deactivated");
586 return -ENOTSUP;
587 }
588 start_address = TMAG5273_REG_T_MSB_RESULT;
589 end_address = TMAG5273_REG_T_LSB_RESULT;
590 break;
591 case SENSOR_CHAN_ROTATION:
592 if (drv_cfg->angle_magnitude_axis == TMAG5273_ANGLE_CALC_NONE) {
593 LOG_ERR("axis measurement deactivated");
594 return -ENOTSUP;
595 }
596 start_address = TMAG5273_REG_ANGLE_MSB_RESULT;
597 end_address = TMAG5273_REG_ANGLE_LSB_RESULT;
598 break;
599 case TMAG5273_CHAN_MAGNITUDE:
600 case TMAG5273_CHAN_MAGNITUDE_MSB:
601 if (drv_cfg->angle_magnitude_axis == TMAG5273_ANGLE_CALC_NONE) {
602 LOG_ERR("axis measurement deactivated");
603 return -ENOTSUP;
604 }
605 start_address = end_address = TMAG5273_REG_MAGNITUDE_RESULT;
606 break;
607 case TMAG5273_CHAN_ANGLE_MAGNITUDE:
608 if (drv_cfg->angle_magnitude_axis == TMAG5273_ANGLE_CALC_NONE) {
609 LOG_ERR("axis measurement deactivated");
610 return -ENOTSUP;
611 }
612 start_address = TMAG5273_REG_ANGLE_MSB_RESULT;
613 end_address = TMAG5273_REG_MAGNITUDE_RESULT;
614 break;
615 case SENSOR_CHAN_ALL:
616 start_address = TMAG5273_REG_RESULT_BEGIN;
617 end_address = TMAG5273_REG_RESULT_END;
618 break;
619 default:
620 LOG_ERR("unknown sensor channel %d", chan);
621 return -EINVAL;
622 }
623
624 __ASSERT_NO_MSG(start_address >= TMAG5273_REG_RESULT_BEGIN);
625 __ASSERT_NO_MSG(end_address <= TMAG5273_REG_RESULT_END);
626 __ASSERT_NO_MSG(start_address <= end_address);
627
628 uint32_t nb_bytes = end_address - start_address + 1;
629
630 #ifdef CONFIG_CRC
631 /* if CRC is enabled multiples of TMAG5273_CRC_DATA_BYTES need to be read */
632 if (drv_cfg->crc_enabled && ((nb_bytes % TMAG5273_CRC_DATA_BYTES) != 0)) {
633 const uint8_t diff = TMAG5273_CRC_DATA_BYTES - (nb_bytes % TMAG5273_CRC_DATA_BYTES);
634
635 if ((start_address - diff) >= TMAG5273_REG_RESULT_BEGIN) {
636 start_address -= diff;
637 }
638
639 nb_bytes = (nb_bytes / TMAG5273_CRC_DATA_BYTES + 1) * TMAG5273_CRC_DATA_BYTES;
640 }
641
642 __ASSERT_NO_MSG((start_address + nb_bytes) <= (TMAG5273_REG_RESULT_END + 1));
643 #endif
644
645 uint8_t offset = start_address - TMAG5273_REG_RESULT_BEGIN;
646 const uint8_t crc_size = tmag5273_get_crc_size(drv_cfg);
647
648 while (nb_bytes) {
649 const uint8_t block_size = tmag5273_get_fetch_block_size(drv_cfg, nb_bytes);
650
651 __ASSERT((offset + block_size + crc_size) <= TMAG5273_I2C_BUFFER_SIZE,
652 "block_size would exceed available i2c buffer capacity");
653 __ASSERT(start_address <= end_address,
654 "start_address for reading after end address");
655
656 /* Note: crc_size needs to be read additionally, since it is appended on the end */
657 retval = i2c_burst_read_dt(&drv_cfg->i2c, start_address, &i2c_buffer[offset],
658 block_size + crc_size);
659
660 if (retval < 0) {
661 LOG_ERR("could not read result data %d", retval);
662 return -EIO;
663 }
664
665 #ifdef CONFIG_CRC
666 /* check data validity, if activated */
667 if (drv_cfg->crc_enabled) {
668 const uint8_t crc = crc8_ccitt(0xFF, &i2c_buffer[offset], block_size);
669
670 if (i2c_buffer[offset + block_size] != crc) {
671 LOG_ERR("invalid CRC value: 0x%X (expected: 0x%X)",
672 i2c_buffer[offset + block_size], crc);
673 return -EIO;
674 }
675 }
676 #endif
677
678 __ASSERT(nb_bytes >= block_size, "overflow on nb_bytes");
679
680 nb_bytes -= block_size;
681
682 offset += block_size;
683 start_address += block_size;
684 }
685
686 retval = tmag5273_check_device_status(
687 drv_cfg, &i2c_buffer[TMAG5273_REG_CONV_STATUS - TMAG5273_REG_RESULT_BEGIN]);
688 if (retval < 0) {
689 return retval;
690 }
691
692 bool all_channels = (chan == SENSOR_CHAN_ALL);
693 bool all_xyz = all_channels || (chan == SENSOR_CHAN_MAGN_XYZ);
694 bool all_angle_magnitude = all_channels || ((int)chan == TMAG5273_CHAN_ANGLE_MAGNITUDE);
695
696 if (all_xyz || (chan == SENSOR_CHAN_MAGN_X)) {
697 drv_data->x_sample = sys_get_be16(
698 &i2c_buffer[TMAG5273_REG_X_MSB_RESULT - TMAG5273_REG_RESULT_BEGIN]);
699 }
700
701 if (all_xyz || (chan == SENSOR_CHAN_MAGN_Y)) {
702 drv_data->y_sample = sys_get_be16(
703 &i2c_buffer[TMAG5273_REG_Y_MSB_RESULT - TMAG5273_REG_RESULT_BEGIN]);
704 }
705
706 if (all_xyz || (chan == SENSOR_CHAN_MAGN_Z)) {
707 drv_data->z_sample = sys_get_be16(
708 &i2c_buffer[TMAG5273_REG_Z_MSB_RESULT - TMAG5273_REG_RESULT_BEGIN]);
709 }
710
711 if (all_channels || (chan == SENSOR_CHAN_DIE_TEMP)) {
712 drv_data->temperature_sample = sys_get_be16(
713 &i2c_buffer[TMAG5273_REG_T_MSB_RESULT - TMAG5273_REG_RESULT_BEGIN]);
714 }
715
716 if (all_angle_magnitude || (chan == SENSOR_CHAN_ROTATION)) {
717 drv_data->angle_sample = sys_get_be16(
718 &i2c_buffer[TMAG5273_REG_ANGLE_MSB_RESULT - TMAG5273_REG_RESULT_BEGIN]);
719 }
720 if (all_angle_magnitude || ((int)chan == TMAG5273_CHAN_MAGNITUDE) ||
721 ((int)chan == TMAG5273_CHAN_MAGNITUDE_MSB)) {
722 drv_data->magnitude_sample =
723 i2c_buffer[TMAG5273_REG_MAGNITUDE_RESULT - TMAG5273_REG_RESULT_BEGIN];
724 }
725
726 return 0;
727 }
728
729 /**
730 * @brief calculates the b-field value in G based on the sensor value
731 *
732 * The calculation follows the formula
733 * @f[ B=\frac{-(D_{15} \cdot 2^{15}) + \sum_{i=0}^{14} D_i \cdot 2^i}{2^{16}} \cdot 2|B_R| @f]
734 * where
735 * - \em D denotes the bit of the input data,
736 * - \em Br represents the magnetic range in mT
737 *
738 * After the calculation, the value is scaled to Gauss (1 G == 0.1 mT).
739 *
740 * @param[in] raw_value data read from the device
741 * @param[in] range magnetic range of the selected axis (in mT)
742 * @param[out] b_field holds the result data after the operation
743 */
tmag5273_channel_b_field_convert(int64_t raw_value,const uint16_t range,struct sensor_value * b_field)744 static inline void tmag5273_channel_b_field_convert(int64_t raw_value, const uint16_t range,
745 struct sensor_value *b_field)
746 {
747 raw_value *= (range << 1) * CONV_FACTOR_MT_TO_GS;
748
749 /* calc integer part in mT and scale to G */
750 b_field->val1 = raw_value / (1 << 16);
751
752 /* calc remaining part (first mT digit + fractal part) and scale according to Zephyr.
753 * Ensure that always positive.
754 */
755 const int64_t raw_dec_part = (int64_t)b_field->val1 * (1 << 16);
756
757 b_field->val2 = ((raw_value - raw_dec_part) * 1000000) / (1 << 16);
758 }
759
760 /**
761 * @brief calculates the temperature value
762 *
763 * @param[in] raw_value data read from the device
764 * @param[out] temperature holds the result data after the operation
765 */
tmag5273_temperature_convert(int64_t raw_value,struct sensor_value * temperature)766 static inline void tmag5273_temperature_convert(int64_t raw_value, struct sensor_value *temperature)
767 {
768 const int64_t value =
769 (TMAG5273_TEMPERATURE_T_SENS_T0 +
770 ((raw_value - TMAG5273_TEMPERATURE_T_ADC_T0) / TMAG5273_TEMPERATURE_T_ADC_RES)) *
771 1000000;
772
773 temperature->val1 = value / 1000000;
774 temperature->val2 = value % 1000000;
775 }
776
777 /**
778 * @brief calculates the angle value between two axis
779 *
780 * @param[in] raw_value data read from the device
781 * @param[out] angle holds the result data after the operation
782 */
tmag5273_angle_convert(int16_t raw_value,struct sensor_value * angle)783 static inline void tmag5273_angle_convert(int16_t raw_value, struct sensor_value *angle)
784 {
785 angle->val1 = (raw_value >> 4) & 0x1FF;
786 angle->val2 = ((raw_value & 0xF) * 1000000) >> 1;
787 }
788
789 /**
790 * @brief calculates the magnitude value in G between two axis
791 *
792 * Note that \c MAGNITUDE_RESULT represents the MSB of the calculation,
793 * therefore it needs to be shifted.
794 *
795 * @param[in] raw_value data read from the device
796 * @param[out] magnitude holds the result data after the operation
797 */
tmag5273_magnitude_convert(uint8_t raw_value,const uint16_t range,struct sensor_value * magnitude)798 static inline void tmag5273_magnitude_convert(uint8_t raw_value, const uint16_t range,
799 struct sensor_value *magnitude)
800 {
801 tmag5273_channel_b_field_convert(raw_value << 8, range, magnitude);
802 }
803
tmag5273_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)804 static int tmag5273_channel_get(const struct device *dev, enum sensor_channel chan,
805 struct sensor_value *val)
806 {
807 CHECKIF(val == NULL) {
808 LOG_ERR("val: NULL");
809 return -EINVAL;
810 }
811
812 const struct tmag5273_config *drv_cfg = dev->config;
813 struct tmag5273_data *drv_data = dev->data;
814
815 int8_t val_offset = 0;
816
817 const bool all_mag_axis = (chan == SENSOR_CHAN_MAGN_XYZ) || (chan == SENSOR_CHAN_ALL);
818
819 if ((drv_cfg->axis & TMAG5273_MAG_CH_EN_X) &&
820 (all_mag_axis || (chan == SENSOR_CHAN_MAGN_X))) {
821 tmag5273_channel_b_field_convert(drv_data->x_sample, drv_data->xyz_range,
822 val + val_offset);
823 val_offset++;
824 }
825
826 if ((drv_cfg->axis & TMAG5273_MAG_CH_EN_Y) &&
827 (all_mag_axis || (chan == SENSOR_CHAN_MAGN_Y))) {
828 tmag5273_channel_b_field_convert(drv_data->y_sample, drv_data->xyz_range,
829 val + val_offset);
830 val_offset++;
831 }
832
833 if ((drv_cfg->axis & TMAG5273_MAG_CH_EN_Z) &&
834 (all_mag_axis || (chan == SENSOR_CHAN_MAGN_Z))) {
835 tmag5273_channel_b_field_convert(drv_data->z_sample, drv_data->xyz_range,
836 val + val_offset);
837 val_offset++;
838 }
839
840 if (drv_cfg->temperature && (chan == SENSOR_CHAN_DIE_TEMP)) {
841 tmag5273_temperature_convert(drv_data->temperature_sample, val + val_offset);
842 val_offset++;
843 }
844
845 if (drv_cfg->angle_magnitude_axis != TMAG5273_ANGLE_CALC_NONE) {
846 const bool all_calc_ch = (TMAG5273_CHAN_ANGLE_MAGNITUDE == (uint16_t)chan);
847
848 if (all_calc_ch || ((uint16_t)chan == SENSOR_CHAN_ROTATION)) {
849 tmag5273_angle_convert(drv_data->angle_sample, val + val_offset);
850 val_offset++;
851 }
852
853 if (all_calc_ch || ((uint16_t)chan == TMAG5273_CHAN_MAGNITUDE)) {
854 tmag5273_magnitude_convert(drv_data->magnitude_sample, drv_data->xyz_range,
855 val + val_offset);
856 val_offset++;
857 }
858
859 if (all_calc_ch || (uint16_t)chan == TMAG5273_CHAN_MAGNITUDE_MSB) {
860 val[val_offset].val1 = drv_data->magnitude_sample;
861 val[val_offset].val2 = 0;
862
863 val_offset++;
864 }
865 }
866
867 if (val_offset == 0) {
868 return -ENOTSUP;
869 }
870
871 return 0;
872 }
873
874 /**
875 * @brief sets the \c DEVICE_CONFIG_1 and \c DEVICE_CONFIG_2 registers
876 *
877 * @param dev handle to the current device instance
878 *
879 * @retval 0 if everything was okay
880 * @retval -EIO on communication errors
881 */
tmag5273_init_device_config(const struct device * dev)882 static inline int tmag5273_init_device_config(const struct device *dev)
883 {
884 const struct tmag5273_config *drv_cfg = dev->config;
885 struct tmag5273_data *drv_data = dev->data;
886 int retval;
887 uint8_t regdata;
888
889 /* REG_DEVICE_CONFIG_1 */
890 regdata = 0;
891
892 #ifdef CONFIG_CRC
893 if (drv_cfg->crc_enabled) {
894 regdata |= TMAG5273_CRC_ENABLE;
895 }
896 #endif
897
898 switch (drv_cfg->temperature_coefficient) {
899 case TMAG5273_DT_TEMP_COEFF_NDBFE:
900 regdata |= TMAG5273_MAGNET_TEMP_COEFF_NDBFE;
901 break;
902 case TMAG5273_DT_TEMP_COEFF_CERAMIC:
903 regdata |= TMAG5273_MAGNET_TEMP_COEFF_CERAMIC;
904 break;
905 case TMAG5273_DT_TEMP_COEFF_NONE:
906 __fallthrough;
907 default:
908 regdata |= TMAG5273_MAGNET_TEMP_COEFF_NONE;
909 break;
910 }
911
912 switch (drv_cfg->averaging) {
913 case TMAG5273_DT_AVERAGING_2X:
914 regdata |= TMAG5273_CONV_AVG_2;
915 break;
916 case TMAG5273_DT_AVERAGING_4X:
917 regdata |= TMAG5273_CONV_AVG_4;
918 break;
919 case TMAG5273_DT_AVERAGING_8X:
920 regdata |= TMAG5273_CONV_AVG_8;
921 break;
922 case TMAG5273_DT_AVERAGING_16X:
923 regdata |= TMAG5273_CONV_AVG_16;
924 break;
925 case TMAG5273_DT_AVERAGING_32X:
926 regdata |= TMAG5273_CONV_AVG_32;
927 break;
928 case TMAG5273_DT_AVERAGING_NONE:
929 __fallthrough;
930 default:
931 regdata |= TMAG5273_CONV_AVG_1;
932 break;
933 }
934
935 const int nb_captured_channels =
936 ((drv_cfg->mag_channel >= TMAG5273_DT_AXIS_XYZ)
937 ? 3
938 : POPCOUNT((drv_cfg->mag_channel & TMAG5273_DT_AXIS_XYZ))) +
939 (int)drv_cfg->temperature;
940
941 drv_data->conversion_time_us = TMAG5273_T_CONVERSION_US(
942 (FIELD_GET(TMAG5273_CONV_AVB_MSK, regdata)), (nb_captured_channels));
943
944 regdata |= TMAG5273_I2C_READ_MODE_STANDARD;
945
946 retval = i2c_reg_write_byte_dt(&drv_cfg->i2c, TMAG5273_REG_DEVICE_CONFIG_1, regdata);
947 if (retval < 0) {
948 LOG_ERR("error setting DEVICE_CONFIG_1 %d", retval);
949 return -EIO;
950 }
951
952 /* REG_DEVICE_CONFIG_2 */
953 regdata = 0;
954
955 if (drv_cfg->low_noise_mode) {
956 regdata |= TMAG5273_LP_LOWNOISE;
957 }
958
959 if (drv_cfg->trigger_conv_via_int) {
960 regdata |= TMAG5273_TRIGGER_MODE_INT;
961 }
962
963 if (drv_cfg->operation_mode == TMAG5273_DT_OPER_MODE_CONTINUOUS) {
964 regdata |= TMAG5273_OPERATING_MODE_CONTINUOUS;
965 }
966
967 /* Note: I2C glitch filter enabled by default */
968
969 retval = i2c_reg_write_byte_dt(&drv_cfg->i2c, TMAG5273_REG_DEVICE_CONFIG_2, regdata);
970 if (retval < 0) {
971 LOG_ERR("error setting DEVICE_CONFIG_2 %d", retval);
972 return -EIO;
973 }
974
975 return 0;
976 }
977
978 /**
979 * @brief sets the \c SENSOR_CONFIG_1 and \c SENSOR_CONFIG_2 registers
980 *
981 * @param drv_cfg configuration of the TMAG5273 instance
982 *
983 * @retval 0 if everything was okay
984 * @retval -EIO on communication errors
985 */
tmag5273_init_sensor_settings(const struct tmag5273_config * drv_cfg)986 static inline int tmag5273_init_sensor_settings(const struct tmag5273_config *drv_cfg)
987 {
988 int retval;
989 uint8_t regdata;
990
991 /* REG_SENSOR_CONFIG_1 */
992 regdata = drv_cfg->mag_channel << TMAG5273_MAG_CH_EN_POS;
993
994 retval = i2c_reg_write_byte_dt(&drv_cfg->i2c, TMAG5273_REG_SENSOR_CONFIG_1, regdata);
995 if (retval < 0) {
996 LOG_ERR("error setting SENSOR_CONFIG_1 %d", retval);
997 return -EIO;
998 }
999
1000 /* REG_SENSOR_CONFIG_2 */
1001 regdata = 0;
1002
1003 if (drv_cfg->ch_mag_gain_correction == TMAG5273_DT_CORRECTION_CH_2) {
1004 regdata |= TMAG5273_MAG_GAIN_CORRECTION_CH_2;
1005 }
1006
1007 switch (drv_cfg->angle_magnitude_axis) {
1008 case TMAG5273_DT_ANGLE_MAG_XY:
1009 regdata |= TMAG5273_ANGLE_EN_XY;
1010 break;
1011 case TMAG5273_DT_ANGLE_MAG_YZ:
1012 regdata |= TMAG5273_ANGLE_EN_YZ;
1013 break;
1014 case TMAG5273_DT_ANGLE_MAG_XZ:
1015 regdata |= TMAG5273_ANGLE_EN_XZ;
1016 break;
1017 case TMAG5273_DT_ANGLE_MAG_RUNTIME:
1018 case TMAG5273_DT_ANGLE_MAG_NONE:
1019 __fallthrough;
1020 default:
1021 regdata |= TMAG5273_ANGLE_EN_POS;
1022 break;
1023 }
1024
1025 if (drv_cfg->meas_range == TMAG5273_DT_AXIS_RANGE_LOW) {
1026 regdata |= TMAG5273_XYZ_MEAS_RANGE_LOW;
1027 } else {
1028 regdata |= TMAG5273_XYZ_MEAS_RANGE_HIGH;
1029 }
1030
1031 retval = i2c_reg_write_byte_dt(&drv_cfg->i2c, TMAG5273_REG_SENSOR_CONFIG_2, regdata);
1032 if (retval < 0) {
1033 LOG_ERR("error setting SENSOR_CONFIG_2 %d", retval);
1034 return -EIO;
1035 }
1036
1037 /* REG_T_CONFIG */
1038 regdata = 0;
1039
1040 if (drv_cfg->temperature) {
1041 regdata |= TMAG5273_T_CH_EN_ENABLED;
1042 }
1043
1044 retval = i2c_reg_write_byte_dt(&drv_cfg->i2c, TMAG5273_REG_T_CONFIG, regdata);
1045 if (retval < 0) {
1046 LOG_ERR("error setting SENSOR_CONFIG_2 %d", retval);
1047 return -EIO;
1048 }
1049
1050 return 0;
1051 }
1052
1053 /**
1054 * @brief initialize a TMAG5273 sensor
1055 *
1056 * @param dev handle to the device
1057 *
1058 * @retval 0 on success
1059 * @retval -EINVAL if bus label is invalid
1060 * @retval -EIO on communication errors
1061 */
tmag5273_init(const struct device * dev)1062 static int tmag5273_init(const struct device *dev)
1063 {
1064 const struct tmag5273_config *drv_cfg = dev->config;
1065 struct tmag5273_data *drv_data = dev->data;
1066 int retval;
1067 uint8_t regdata;
1068
1069 if (!i2c_is_ready_dt(&drv_cfg->i2c)) {
1070 LOG_ERR("could not get pointer to TMAG5273 I2C device");
1071 return -ENODEV;
1072 }
1073
1074 if (drv_cfg->trigger_conv_via_int) {
1075 if (!gpio_is_ready_dt(&drv_cfg->int_gpio)) {
1076 LOG_ERR("invalid int-gpio configuration");
1077 return -ENODEV;
1078 }
1079
1080 retval = gpio_pin_configure_dt(&drv_cfg->int_gpio, GPIO_INPUT);
1081 if (retval < 0) {
1082 LOG_ERR("cannot configure GPIO %d", retval);
1083 return -EINVAL;
1084 }
1085 }
1086
1087 retval = i2c_reg_read_byte_dt(&drv_cfg->i2c, TMAG5273_REG_DEVICE_CONFIG_2, ®data);
1088 if (retval < 0) {
1089 LOG_ERR("could not read device config 2 register %d", retval);
1090 return -EIO;
1091 }
1092
1093 LOG_DBG("operation mode: %d", (int)FIELD_GET(TMAG5273_OPERATING_MODE_MSK, regdata));
1094
1095 retval = i2c_reg_read_byte_dt(&drv_cfg->i2c, TMAG5273_REG_MANUFACTURER_ID_LSB, ®data);
1096 if (retval < 0) {
1097 return -EIO;
1098 }
1099
1100 if (regdata != TMAG5273_MANUFACTURER_ID_LSB) {
1101 LOG_ERR("unexpected manufacturer id LSB 0x%X", regdata);
1102 return -EINVAL;
1103 }
1104
1105 retval = i2c_reg_read_byte_dt(&drv_cfg->i2c, TMAG5273_REG_MANUFACTURER_ID_MSB, ®data);
1106 if (retval < 0) {
1107 LOG_ERR("could not read MSB of manufacturer id %d", retval);
1108 return -EIO;
1109 }
1110
1111 if (regdata != TMAG5273_MANUFACTURER_ID_MSB) {
1112 LOG_ERR("unexpected manufacturer id MSB 0x%X", regdata);
1113 return -EINVAL;
1114 }
1115
1116 (void)tmag5273_check_device_status(drv_cfg, ®data);
1117
1118 retval = tmag5273_reset_device_status(dev);
1119 if (retval < 0) {
1120 LOG_ERR("could not reset DEVICE_STATUS register %d", retval);
1121 return -EIO;
1122 }
1123
1124 retval = i2c_reg_read_byte_dt(&drv_cfg->i2c, TMAG5273_REG_DEVICE_ID, ®data);
1125 if (retval < 0) {
1126 LOG_ERR("could not read DEVICE_ID register %d", retval);
1127 return -EIO;
1128 }
1129
1130 drv_data->version = regdata & TMAG5273_VER_MSK;
1131
1132 /* magnetic measurement range based on version, apply correct one */
1133 if (drv_cfg->meas_range == TMAG5273_DT_AXIS_RANGE_LOW) {
1134 drv_data->xyz_range = tmag5273_range_low(drv_data->version);
1135 } else {
1136 drv_data->xyz_range = tmag5273_range_high(drv_data->version);
1137 }
1138
1139 regdata = TMAG5273_INT_MODE_NONE;
1140
1141 if (!drv_cfg->trigger_conv_via_int) {
1142 regdata |= TMAG5273_INT_MASK_INTB_PIN_MASKED;
1143 }
1144
1145 retval = i2c_reg_write_byte_dt(&drv_cfg->i2c, TMAG5273_REG_INT_CONFIG_1, regdata);
1146 if (retval < 0) {
1147 LOG_ERR("error deactivating interrupts %d", retval);
1148 return -EIO;
1149 }
1150
1151 /* set settings */
1152 retval = tmag5273_init_sensor_settings(drv_cfg);
1153 if (retval < 0) {
1154 LOG_ERR("error setting sensor configuration %d", retval);
1155 return retval;
1156 }
1157
1158 retval = tmag5273_init_device_config(dev);
1159 if (retval < 0) {
1160 LOG_ERR("error setting device configuration %d", retval);
1161 return retval;
1162 }
1163
1164 return 0;
1165 }
1166
1167 static const struct sensor_driver_api tmag5273_driver_api = {
1168 .attr_set = tmag5273_attr_set,
1169 .attr_get = tmag5273_attr_get,
1170 .sample_fetch = tmag5273_sample_fetch,
1171 .channel_get = tmag5273_channel_get,
1172 };
1173
1174 #define TMAG5273_DT_X_AXIS_BIT(axis_dts) \
1175 ((((axis_dts & TMAG5273_DT_AXIS_X) == TMAG5273_DT_AXIS_X) || \
1176 (axis_dts == TMAG5273_DT_AXIS_XYX) || (axis_dts == TMAG5273_DT_AXIS_YXY) || \
1177 (axis_dts == TMAG5273_DT_AXIS_XZX)) \
1178 ? TMAG5273_MAG_CH_EN_X \
1179 : 0)
1180
1181 #define TMAG5273_DT_Y_AXIS_BIT(axis_dts) \
1182 ((((axis_dts & TMAG5273_DT_AXIS_Y) == TMAG5273_DT_AXIS_Y) || \
1183 (axis_dts == TMAG5273_DT_AXIS_XYX) || (axis_dts == TMAG5273_DT_AXIS_YXY) || \
1184 (axis_dts == TMAG5273_DT_AXIS_YZY)) \
1185 ? TMAG5273_MAG_CH_EN_Y \
1186 : 0)
1187
1188 #define TMAG5273_DT_Z_AXIS_BIT(axis_dts) \
1189 ((((axis_dts & TMAG5273_DT_AXIS_Z) == TMAG5273_DT_AXIS_Z) || \
1190 (axis_dts == TMAG5273_DT_AXIS_YZY) || (axis_dts == TMAG5273_DT_AXIS_XZX)) \
1191 ? TMAG5273_MAG_CH_EN_Z \
1192 : 0)
1193
1194 /** Instantiation macro */
1195 #define TMAG5273_DEFINE(inst) \
1196 BUILD_ASSERT(IS_ENABLED(CONFIG_CRC) || (DT_INST_PROP(inst, crc_enabled) == 0), \
1197 "CRC support necessary"); \
1198 BUILD_ASSERT(!DT_INST_PROP(inst, trigger_conversion_via_int) || \
1199 DT_INST_NODE_HAS_PROP(inst, int_gpios), \
1200 "trigger-conversion-via-int requires int-gpios to be defined"); \
1201 static const struct tmag5273_config tmag5273_driver_cfg##inst = { \
1202 .i2c = I2C_DT_SPEC_INST_GET(inst), \
1203 .mag_channel = DT_INST_PROP(inst, axis), \
1204 .axis = (TMAG5273_DT_X_AXIS_BIT(DT_INST_PROP(inst, axis)) | \
1205 TMAG5273_DT_Y_AXIS_BIT(DT_INST_PROP(inst, axis)) | \
1206 TMAG5273_DT_Z_AXIS_BIT(DT_INST_PROP(inst, axis))), \
1207 .temperature = DT_INST_PROP(inst, temperature), \
1208 .meas_range = DT_INST_PROP(inst, range), \
1209 .temperature_coefficient = DT_INST_PROP(inst, temperature_coefficient), \
1210 .angle_magnitude_axis = DT_INST_PROP(inst, angle_magnitude_axis), \
1211 .ch_mag_gain_correction = DT_INST_PROP(inst, ch_mag_gain_correction), \
1212 .operation_mode = DT_INST_PROP(inst, operation_mode), \
1213 .averaging = DT_INST_PROP(inst, average_mode), \
1214 .trigger_conv_via_int = DT_INST_PROP(inst, trigger_conversion_via_int), \
1215 .low_noise_mode = DT_INST_PROP(inst, low_noise), \
1216 .ignore_diag_fail = DT_INST_PROP(inst, ignore_diag_fail), \
1217 .int_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, {0}), \
1218 IF_ENABLED(CONFIG_CRC, (.crc_enabled = DT_INST_PROP(inst, crc_enabled),))}; \
1219 static struct tmag5273_data tmag5273_driver_data##inst; \
1220 SENSOR_DEVICE_DT_INST_DEFINE(inst, tmag5273_init, NULL, &tmag5273_driver_data##inst, \
1221 &tmag5273_driver_cfg##inst, POST_KERNEL, \
1222 CONFIG_SENSOR_INIT_PRIORITY, &tmag5273_driver_api);
1223
1224 DT_INST_FOREACH_STATUS_OKAY(TMAG5273_DEFINE)
1225