1 /*
2  * Copyright (c) 2016 Freescale Semiconductor, Inc.
3  * Copyright (c) 2018 Phytec Messtechnik GmbH
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT nxp_fxos8700
9 
10 #include "fxos8700.h"
11 #include <zephyr/sys/util.h>
12 #include <zephyr/sys/__assert.h>
13 #include <zephyr/logging/log.h>
14 #include <stdlib.h>
15 
16 LOG_MODULE_REGISTER(FXOS8700, CONFIG_SENSOR_LOG_LEVEL);
17 
18 /* Convert the range (8g, 4g, 2g) to the encoded FS register field value */
19 #define RANGE2FS(x) (__builtin_ctz(x) - 1)
20 
21 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
22 #define DIR_READ(a)  ((a) & 0x7f)
23 #define DIR_WRITE(a) ((a) | BIT(7))
24 #define ADDR_7(a) ((a) & BIT(7))
25 
fxos8700_transceive(const struct device * dev,void * data,size_t length)26 int fxos8700_transceive(const struct device *dev,
27 				void *data, size_t length)
28 {
29 	const struct fxos8700_config *cfg = dev->config;
30 	const struct spi_buf buf = { .buf = data, .len = length };
31 	const struct spi_buf_set s = { .buffers = &buf, .count = 1 };
32 
33 	return spi_transceive_dt(&cfg->bus_cfg.spi, &s, &s);
34 }
35 
fxos8700_read_spi(const struct device * dev,uint8_t reg,void * data,size_t length)36 int fxos8700_read_spi(const struct device *dev,
37 		      uint8_t reg,
38 		      void *data,
39 		      size_t length)
40 {
41 	const struct fxos8700_config *cfg = dev->config;
42 
43 	/* Reads must clock out a dummy byte after sending the address. */
44 	uint8_t reg_buf[3] = { DIR_READ(reg), ADDR_7(reg), 0 };
45 	const struct spi_buf buf[2] = {
46 		{ .buf = reg_buf, .len = 3 },
47 		{ .buf = data, .len = length }
48 	};
49 	const struct spi_buf_set tx = { .buffers = buf, .count = 1 };
50 	const struct spi_buf_set rx = { .buffers = buf, .count = 2 };
51 
52 	return spi_transceive_dt(&cfg->bus_cfg.spi, &tx, &rx);
53 }
54 
fxos8700_byte_read_spi(const struct device * dev,uint8_t reg,uint8_t * byte)55 int fxos8700_byte_read_spi(const struct device *dev,
56 			   uint8_t reg,
57 			   uint8_t *byte)
58 {
59 	/* Reads must clock out a dummy byte after sending the address. */
60 	uint8_t data[] = { DIR_READ(reg), ADDR_7(reg), 0};
61 	int ret;
62 
63 	ret = fxos8700_transceive(dev, data, sizeof(data));
64 
65 	*byte = data[2];
66 
67 	return ret;
68 }
69 
fxos8700_byte_write_spi(const struct device * dev,uint8_t reg,uint8_t byte)70 int fxos8700_byte_write_spi(const struct device *dev,
71 			    uint8_t reg,
72 			    uint8_t byte)
73 {
74 	uint8_t data[] = { DIR_WRITE(reg), ADDR_7(reg), byte };
75 
76 	return fxos8700_transceive(dev, data, sizeof(data));
77 }
78 
fxos8700_reg_field_update_spi(const struct device * dev,uint8_t reg,uint8_t mask,uint8_t val)79 int fxos8700_reg_field_update_spi(const struct device *dev,
80 				  uint8_t reg,
81 				  uint8_t mask,
82 				  uint8_t val)
83 {
84 	uint8_t old_val;
85 
86 	if (fxos8700_byte_read_spi(dev, reg, &old_val) < 0) {
87 		return -EIO;
88 	}
89 
90 	return fxos8700_byte_write_spi(dev, reg, (old_val & ~mask) | (val & mask));
91 }
92 
93 static const struct fxos8700_io_ops fxos8700_spi_ops = {
94 	.read = fxos8700_read_spi,
95 	.byte_read = fxos8700_byte_read_spi,
96 	.byte_write = fxos8700_byte_write_spi,
97 	.reg_field_update = fxos8700_reg_field_update_spi,
98 };
99 #endif
100 
101 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
fxos8700_read_i2c(const struct device * dev,uint8_t reg,void * data,size_t length)102 int fxos8700_read_i2c(const struct device *dev,
103 		      uint8_t reg,
104 		      void *data,
105 		      size_t length)
106 {
107 	const struct fxos8700_config *config = dev->config;
108 
109 	return i2c_burst_read_dt(&config->bus_cfg.i2c, reg, data, length);
110 }
111 
fxos8700_byte_read_i2c(const struct device * dev,uint8_t reg,uint8_t * byte)112 int fxos8700_byte_read_i2c(const struct device *dev,
113 			   uint8_t reg,
114 			   uint8_t *byte)
115 {
116 	const struct fxos8700_config *config = dev->config;
117 
118 	return i2c_reg_read_byte_dt(&config->bus_cfg.i2c, reg, byte);
119 }
120 
fxos8700_byte_write_i2c(const struct device * dev,uint8_t reg,uint8_t byte)121 int fxos8700_byte_write_i2c(const struct device *dev,
122 			    uint8_t reg,
123 			    uint8_t byte)
124 {
125 	const struct fxos8700_config *config = dev->config;
126 
127 	return i2c_reg_write_byte_dt(&config->bus_cfg.i2c, reg, byte);
128 }
129 
fxos8700_reg_field_update_i2c(const struct device * dev,uint8_t reg,uint8_t mask,uint8_t val)130 int fxos8700_reg_field_update_i2c(const struct device *dev,
131 				  uint8_t reg,
132 				  uint8_t mask,
133 				  uint8_t val)
134 {
135 	const struct fxos8700_config *config = dev->config;
136 
137 	return i2c_reg_update_byte_dt(&config->bus_cfg.i2c, reg, mask, val);
138 }
139 static const struct fxos8700_io_ops fxos8700_i2c_ops = {
140 	.read = fxos8700_read_i2c,
141 	.byte_read = fxos8700_byte_read_i2c,
142 	.byte_write = fxos8700_byte_write_i2c,
143 	.reg_field_update = fxos8700_reg_field_update_i2c,
144 };
145 #endif
146 
fxos8700_set_odr(const struct device * dev,const struct sensor_value * val)147 static int fxos8700_set_odr(const struct device *dev,
148 		const struct sensor_value *val)
149 {
150 	const struct fxos8700_config *config = dev->config;
151 	uint8_t dr;
152 	enum fxos8700_power power;
153 
154 #ifdef CONFIG_FXOS8700_MODE_HYBRID
155 	/* ODR is halved in hybrid mode */
156 	if (val->val1 == 400 && val->val2 == 0) {
157 		dr = FXOS8700_CTRLREG1_DR_RATE_800;
158 	} else if (val->val1 == 200 && val->val2 == 0) {
159 		dr = FXOS8700_CTRLREG1_DR_RATE_400;
160 	} else if (val->val1 == 100 && val->val2 == 0) {
161 		dr = FXOS8700_CTRLREG1_DR_RATE_200;
162 	} else if (val->val1 == 50 && val->val2 == 0) {
163 		dr = FXOS8700_CTRLREG1_DR_RATE_100;
164 	} else if (val->val1 == 25 && val->val2 == 0) {
165 		dr = FXOS8700_CTRLREG1_DR_RATE_50;
166 	} else if (val->val1 == 6 && val->val2 == 250000) {
167 		dr = FXOS8700_CTRLREG1_DR_RATE_12_5;
168 	} else if (val->val1 == 3 && val->val2 == 125000) {
169 		dr = FXOS8700_CTRLREG1_DR_RATE_6_25;
170 	} else if (val->val1 == 0 && val->val2 == 781300) {
171 		dr = FXOS8700_CTRLREG1_DR_RATE_1_56;
172 	} else {
173 		return -EINVAL;
174 	}
175 #else
176 	if (val->val1 == 800 && val->val2 == 0) {
177 		dr = FXOS8700_CTRLREG1_DR_RATE_800;
178 	} else if (val->val1 == 400 && val->val2 == 0) {
179 		dr = FXOS8700_CTRLREG1_DR_RATE_400;
180 	} else if (val->val1 == 200 && val->val2 == 0) {
181 		dr = FXOS8700_CTRLREG1_DR_RATE_200;
182 	} else if (val->val1 == 100 && val->val2 == 0) {
183 		dr = FXOS8700_CTRLREG1_DR_RATE_100;
184 	} else if (val->val1 == 50 && val->val2 == 0) {
185 		dr = FXOS8700_CTRLREG1_DR_RATE_50;
186 	} else if (val->val1 == 12 && val->val2 == 500000) {
187 		dr = FXOS8700_CTRLREG1_DR_RATE_12_5;
188 	} else if (val->val1 == 6 && val->val2 == 250000) {
189 		dr = FXOS8700_CTRLREG1_DR_RATE_6_25;
190 	} else if (val->val1 == 1 && val->val2 == 562500) {
191 		dr = FXOS8700_CTRLREG1_DR_RATE_1_56;
192 	} else {
193 		return -EINVAL;
194 	}
195 #endif
196 
197 	LOG_DBG("Set ODR to 0x%x", dr);
198 
199 	/*
200 	 * Modify FXOS8700_REG_CTRLREG1 can only occur when the device
201 	 * is in standby mode. Get the current power mode to restore it later.
202 	 */
203 	if (fxos8700_get_power(dev, &power)) {
204 		LOG_ERR("Could not get power mode");
205 		return -EIO;
206 	}
207 
208 	/* Set standby power mode */
209 	if (fxos8700_set_power(dev, FXOS8700_POWER_STANDBY)) {
210 		LOG_ERR("Could not set standby");
211 		return -EIO;
212 	}
213 
214 	/* Change the attribute and restore power mode. */
215 	return config->ops->reg_field_update(dev, FXOS8700_REG_CTRLREG1,
216 				      FXOS8700_CTRLREG1_DR_MASK | FXOS8700_CTRLREG1_ACTIVE_MASK,
217 				      dr | power);
218 }
219 
fxos8700_set_mt_ths(const struct device * dev,const struct sensor_value * val)220 static int fxos8700_set_mt_ths(const struct device *dev,
221 			       const struct sensor_value *val)
222 {
223 #ifdef CONFIG_FXOS8700_MOTION
224 	const struct fxos8700_config *config = dev->config;
225 	uint64_t micro_ms2 = abs(val->val1 * 1000000LL + val->val2);
226 	uint64_t ths = micro_ms2 / FXOS8700_FF_MT_THS_SCALE;
227 
228 	if (ths > FXOS8700_FF_MT_THS_MASK) {
229 		LOG_ERR("Threshold value is out of range");
230 		return -EINVAL;
231 	}
232 
233 	LOG_DBG("Set FF_MT_THS to %d", (uint8_t)ths);
234 
235 	return config->ops->reg_field_update(dev, FXOS8700_REG_FF_MT_THS,
236 				      FXOS8700_FF_MT_THS_MASK, (uint8_t)ths);
237 #else
238 	return -ENOTSUP;
239 #endif
240 }
241 
fxos8700_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)242 static int fxos8700_attr_set(const struct device *dev,
243 			     enum sensor_channel chan,
244 			     enum sensor_attribute attr,
245 			     const struct sensor_value *val)
246 {
247 	if (chan != SENSOR_CHAN_ALL) {
248 		return -ENOTSUP;
249 	}
250 
251 	if (attr == SENSOR_ATTR_SAMPLING_FREQUENCY) {
252 		return fxos8700_set_odr(dev, val);
253 	} else if (attr == SENSOR_ATTR_SLOPE_TH) {
254 		return fxos8700_set_mt_ths(dev, val);
255 	} else {
256 		return -ENOTSUP;
257 	}
258 
259 	return 0;
260 }
261 
fxos8700_sample_fetch(const struct device * dev,enum sensor_channel chan)262 static int fxos8700_sample_fetch(const struct device *dev,
263 				 enum sensor_channel chan)
264 {
265 	const struct fxos8700_config *config = dev->config;
266 	struct fxos8700_data *data = dev->data;
267 	uint8_t buffer[FXOS8700_MAX_NUM_BYTES];
268 	uint8_t num_bytes;
269 	int16_t *raw;
270 	int ret = 0;
271 	int i;
272 
273 	if (chan != SENSOR_CHAN_ALL) {
274 		LOG_ERR("Unsupported sensor channel");
275 		return -ENOTSUP;
276 	}
277 
278 	k_sem_take(&data->sem, K_FOREVER);
279 
280 	/* Read all the channels in one I2C/SPI transaction. The number of bytes to
281 	 * read and the starting register address depend on the mode
282 	 * configuration (accel-only, mag-only, or hybrid).
283 	 */
284 	num_bytes = config->num_channels * FXOS8700_BYTES_PER_CHANNEL_NORMAL;
285 
286 	__ASSERT(num_bytes <= sizeof(buffer), "Too many bytes to read");
287 
288 	if (config->ops->read(dev, config->start_addr, buffer, num_bytes)) {
289 		LOG_ERR("Could not fetch sample");
290 		ret = -EIO;
291 		goto exit;
292 	}
293 
294 	/* Parse the buffer into raw channel data (16-bit integers). To save
295 	 * RAM, store the data in raw format and wait to convert to the
296 	 * normalized sensor_value type until later.
297 	 */
298 	__ASSERT(config->start_channel + config->num_channels
299 			<= ARRAY_SIZE(data->raw),
300 			"Too many channels");
301 
302 	raw = &data->raw[config->start_channel];
303 
304 	for (i = 0; i < num_bytes; i += 2) {
305 		*raw++ = (buffer[i] << 8) | (buffer[i+1]);
306 	}
307 
308 #ifdef CONFIG_FXOS8700_TEMP
309 	if (config->ops->byte_read(dev, FXOS8700_REG_TEMP,
310 				 &data->temp)) {
311 		LOG_ERR("Could not fetch temperature");
312 		ret = -EIO;
313 		goto exit;
314 	}
315 #endif
316 
317 exit:
318 	k_sem_give(&data->sem);
319 
320 	return ret;
321 }
322 
fxos8700_accel_convert(struct sensor_value * val,int16_t raw,uint8_t range)323 static void fxos8700_accel_convert(struct sensor_value *val, int16_t raw,
324 				   uint8_t range)
325 {
326 	uint8_t frac_bits;
327 	int64_t micro_ms2;
328 
329 	/* The range encoding is convenient to compute the number of fractional
330 	 * bits:
331 	 * - 2g mode (fs = 0) has 14 fractional bits
332 	 * - 4g mode (fs = 1) has 13 fractional bits
333 	 * - 8g mode (fs = 2) has 12 fractional bits
334 	 */
335 	frac_bits = 14 - RANGE2FS(range);
336 
337 	/* Convert units to micro m/s^2. Intermediate results before the shift
338 	 * are 40 bits wide.
339 	 */
340 	micro_ms2 = (raw * SENSOR_G) >> frac_bits;
341 
342 	/* The maximum possible value is 8g, which in units of micro m/s^2
343 	 * always fits into 32-bits. Cast down to int32_t so we can use a
344 	 * faster divide.
345 	 */
346 	val->val1 = (int32_t) micro_ms2 / 1000000;
347 	val->val2 = (int32_t) micro_ms2 % 1000000;
348 }
349 
fxos8700_magn_convert(struct sensor_value * val,int16_t raw)350 static void fxos8700_magn_convert(struct sensor_value *val, int16_t raw)
351 {
352 	int32_t micro_g;
353 
354 	/* Convert units to micro Gauss. Raw magnetic data always has a
355 	 * resolution of 0.1 uT/LSB, which is equivalent to 0.001 G/LSB.
356 	 */
357 	micro_g = raw * 1000;
358 
359 	val->val1 = micro_g / 1000000;
360 	val->val2 = micro_g % 1000000;
361 }
362 
363 #ifdef CONFIG_FXOS8700_TEMP
fxos8700_temp_convert(struct sensor_value * val,int8_t raw)364 static void fxos8700_temp_convert(struct sensor_value *val, int8_t raw)
365 {
366 	int32_t micro_c;
367 
368 	/* Convert units to micro Celsius. Raw temperature data always has a
369 	 * resolution of 0.96 deg C/LSB.
370 	 */
371 	micro_c = raw * 960 * 1000;
372 
373 	val->val1 = micro_c / 1000000;
374 	val->val2 = micro_c % 1000000;
375 }
376 #endif
377 
fxos8700_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)378 static int fxos8700_channel_get(const struct device *dev,
379 				enum sensor_channel chan,
380 				struct sensor_value *val)
381 {
382 	const struct fxos8700_config *config = dev->config;
383 	struct fxos8700_data *data = dev->data;
384 	int start_channel;
385 	int num_channels;
386 	int16_t *raw;
387 	int ret;
388 	int i;
389 
390 	k_sem_take(&data->sem, K_FOREVER);
391 
392 	/* Start with an error return code by default, then clear it if we find
393 	 * a supported sensor channel.
394 	 */
395 	ret = -ENOTSUP;
396 
397 	/* If we're in an accelerometer-enabled mode (accel-only or hybrid),
398 	 * then convert raw accelerometer data to the normalized sensor_value
399 	 * type.
400 	 */
401 	if (config->mode != FXOS8700_MODE_MAGN) {
402 		switch (chan) {
403 		case SENSOR_CHAN_ACCEL_X:
404 			start_channel = FXOS8700_CHANNEL_ACCEL_X;
405 			num_channels = 1;
406 			break;
407 		case SENSOR_CHAN_ACCEL_Y:
408 			start_channel = FXOS8700_CHANNEL_ACCEL_Y;
409 			num_channels = 1;
410 			break;
411 		case SENSOR_CHAN_ACCEL_Z:
412 			start_channel = FXOS8700_CHANNEL_ACCEL_Z;
413 			num_channels = 1;
414 			break;
415 		case SENSOR_CHAN_ACCEL_XYZ:
416 			start_channel = FXOS8700_CHANNEL_ACCEL_X;
417 			num_channels = 3;
418 			break;
419 		default:
420 			start_channel = 0;
421 			num_channels = 0;
422 			break;
423 		}
424 
425 		raw = &data->raw[start_channel];
426 		for (i = 0; i < num_channels; i++) {
427 			fxos8700_accel_convert(val++, *raw++, config->range);
428 		}
429 
430 		if (num_channels > 0) {
431 			ret = 0;
432 		}
433 	}
434 
435 	/* If we're in an magnetometer-enabled mode (mag-only or hybrid), then
436 	 * convert raw magnetometer data to the normalized sensor_value type.
437 	 */
438 	if (config->mode != FXOS8700_MODE_ACCEL) {
439 		switch (chan) {
440 		case SENSOR_CHAN_MAGN_X:
441 			start_channel = FXOS8700_CHANNEL_MAGN_X;
442 			num_channels = 1;
443 			break;
444 		case SENSOR_CHAN_MAGN_Y:
445 			start_channel = FXOS8700_CHANNEL_MAGN_Y;
446 			num_channels = 1;
447 			break;
448 		case SENSOR_CHAN_MAGN_Z:
449 			start_channel = FXOS8700_CHANNEL_MAGN_Z;
450 			num_channels = 1;
451 			break;
452 		case SENSOR_CHAN_MAGN_XYZ:
453 			start_channel = FXOS8700_CHANNEL_MAGN_X;
454 			num_channels = 3;
455 			break;
456 		default:
457 			start_channel = 0;
458 			num_channels = 0;
459 			break;
460 		}
461 
462 		raw = &data->raw[start_channel];
463 		for (i = 0; i < num_channels; i++) {
464 			fxos8700_magn_convert(val++, *raw++);
465 		}
466 
467 		if (num_channels > 0) {
468 			ret = 0;
469 		}
470 #ifdef CONFIG_FXOS8700_TEMP
471 		if (chan == SENSOR_CHAN_DIE_TEMP) {
472 			fxos8700_temp_convert(val, data->temp);
473 			ret = 0;
474 		}
475 #endif
476 	}
477 
478 	if (ret != 0) {
479 		LOG_ERR("Unsupported sensor channel");
480 	}
481 
482 	k_sem_give(&data->sem);
483 
484 	return ret;
485 }
486 
fxos8700_get_power(const struct device * dev,enum fxos8700_power * power)487 int fxos8700_get_power(const struct device *dev, enum fxos8700_power *power)
488 {
489 	const struct fxos8700_config *config = dev->config;
490 	uint8_t val;
491 
492 	if (config->ops->byte_read(dev, FXOS8700_REG_CTRLREG1, &val)) {
493 		LOG_ERR("Could not get power setting");
494 		return -EIO;
495 	}
496 	val &= FXOS8700_M_CTRLREG1_MODE_MASK;
497 	*power = val;
498 
499 	return 0;
500 }
501 
fxos8700_set_power(const struct device * dev,enum fxos8700_power power)502 int fxos8700_set_power(const struct device *dev, enum fxos8700_power power)
503 {
504 	const struct fxos8700_config *config = dev->config;
505 
506 	return config->ops->reg_field_update(dev, FXOS8700_REG_CTRLREG1,
507 				      FXOS8700_CTRLREG1_ACTIVE_MASK, power);
508 }
509 
fxos8700_init(const struct device * dev)510 static int fxos8700_init(const struct device *dev)
511 {
512 	const struct fxos8700_config *config = dev->config;
513 	struct fxos8700_data *data = dev->data;
514 	struct sensor_value odr = {.val1 = 6, .val2 = 250000};
515 
516 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
517 	if (config->inst_on_bus == FXOS8700_BUS_I2C) {
518 		if (!device_is_ready(config->bus_cfg.i2c.bus)) {
519 			LOG_ERR("I2C bus device not ready");
520 			return -ENODEV;
521 		}
522 	}
523 #endif
524 
525 #if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
526 	if (config->inst_on_bus == FXOS8700_BUS_SPI) {
527 		if (!device_is_ready(config->bus_cfg.spi.bus)) {
528 			LOG_ERR("SPI bus device not ready");
529 			return -ENODEV;
530 		}
531 	}
532 #endif
533 
534 	if (config->reset_gpio.port) {
535 		/* Pulse RST pin high to perform a hardware reset of
536 		 * the sensor.
537 		 */
538 
539 		if (!gpio_is_ready_dt(&config->reset_gpio)) {
540 			LOG_ERR("GPIO device not ready");
541 			return -ENODEV;
542 		}
543 
544 		gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE);
545 
546 		gpio_pin_set_dt(&config->reset_gpio, 1);
547 		/* The datasheet does not mention how long to pulse
548 		 * the RST pin high in order to reset. Stay on the
549 		 * safe side and pulse for 1 millisecond.
550 		 */
551 		k_busy_wait(USEC_PER_MSEC);
552 		gpio_pin_set_dt(&config->reset_gpio, 0);
553 	} else {
554 		/* Software reset the sensor. Upon issuing a software
555 		 * reset command over the I2C interface, the sensor
556 		 * immediately resets and does not send any
557 		 * acknowledgment (ACK) of the written byte to the
558 		 * master. Therefore, do not check the return code of
559 		 * the I2C transaction.
560 		 */
561 		config->ops->byte_write(dev, FXOS8700_REG_CTRLREG2,
562 				      FXOS8700_CTRLREG2_RST_MASK);
563 	}
564 
565 	/* The sensor requires us to wait 1 ms after a reset before
566 	 * attempting further communications.
567 	 */
568 	k_busy_wait(USEC_PER_MSEC);
569 
570 	/*
571 	 * Read the WHOAMI register to make sure we are talking to FXOS8700 or
572 	 * compatible device and not some other type of device that happens to
573 	 * have the same I2C address.
574 	 */
575 	if (config->ops->byte_read(dev, FXOS8700_REG_WHOAMI,
576 				 &data->whoami)) {
577 		LOG_ERR("Could not get WHOAMI value");
578 		return -EIO;
579 	}
580 
581 	switch (data->whoami) {
582 	case WHOAMI_ID_MMA8451:
583 	case WHOAMI_ID_MMA8652:
584 	case WHOAMI_ID_MMA8653:
585 		if (config->mode != FXOS8700_MODE_ACCEL) {
586 			LOG_ERR("Device 0x%x supports only "
587 				    "accelerometer mode",
588 				    data->whoami);
589 			return -EIO;
590 		}
591 		break;
592 	case WHOAMI_ID_FXOS8700:
593 		LOG_DBG("Device ID 0x%x", data->whoami);
594 		break;
595 	default:
596 		LOG_ERR("Unknown Device ID 0x%x", data->whoami);
597 		return -EIO;
598 	}
599 
600 	if (fxos8700_set_odr(dev, &odr)) {
601 		LOG_ERR("Could not set default data rate");
602 		return -EIO;
603 	}
604 
605 	if (config->ops->reg_field_update(dev, FXOS8700_REG_CTRLREG2,
606 				   FXOS8700_CTRLREG2_MODS_MASK,
607 				   config->power_mode)) {
608 		LOG_ERR("Could not set power scheme");
609 		return -EIO;
610 	}
611 
612 	/* Set the mode (accel-only, mag-only, or hybrid) */
613 	if (config->ops->reg_field_update(dev, FXOS8700_REG_M_CTRLREG1,
614 				   FXOS8700_M_CTRLREG1_MODE_MASK,
615 				   config->mode)) {
616 		LOG_ERR("Could not set mode");
617 		return -EIO;
618 	}
619 
620 	/* Set hybrid autoincrement so we can read accel and mag channels in
621 	 * one I2C/SPI transaction.
622 	 */
623 	if (config->ops->reg_field_update(dev, FXOS8700_REG_M_CTRLREG2,
624 				   FXOS8700_M_CTRLREG2_AUTOINC_MASK,
625 				   FXOS8700_M_CTRLREG2_AUTOINC_MASK)) {
626 		LOG_ERR("Could not set hybrid autoincrement");
627 		return -EIO;
628 	}
629 
630 	/* Set the full-scale range */
631 	if (config->ops->reg_field_update(dev, FXOS8700_REG_XYZ_DATA_CFG,
632 				   FXOS8700_XYZ_DATA_CFG_FS_MASK,
633 				   RANGE2FS(config->range))) {
634 		LOG_ERR("Could not set range");
635 		return -EIO;
636 	}
637 
638 	k_sem_init(&data->sem, 0, K_SEM_MAX_LIMIT);
639 
640 #if CONFIG_FXOS8700_TRIGGER
641 	if (fxos8700_trigger_init(dev)) {
642 		LOG_ERR("Could not initialize interrupts");
643 		return -EIO;
644 	}
645 #endif
646 
647 	/* Set active */
648 	if (fxos8700_set_power(dev, FXOS8700_POWER_ACTIVE)) {
649 		LOG_ERR("Could not set active");
650 		return -EIO;
651 	}
652 	k_sem_give(&data->sem);
653 
654 	LOG_DBG("Init complete");
655 
656 	return 0;
657 }
658 
659 static const struct sensor_driver_api fxos8700_driver_api = {
660 	.sample_fetch = fxos8700_sample_fetch,
661 	.channel_get = fxos8700_channel_get,
662 	.attr_set = fxos8700_attr_set,
663 #if CONFIG_FXOS8700_TRIGGER
664 	.trigger_set = fxos8700_trigger_set,
665 #endif
666 };
667 
668 #define FXOS8700_MODE_PROPS_ACCEL					\
669 	.mode = FXOS8700_MODE_ACCEL,					\
670 	.start_addr = FXOS8700_REG_OUTXMSB,				\
671 	.start_channel = FXOS8700_CHANNEL_ACCEL_X,			\
672 	.num_channels = FXOS8700_NUM_ACCEL_CHANNELS,
673 
674 #define FXOS8700_MODE_PROPS_MAGN					\
675 	.mode = FXOS8700_MODE_MAGN,					\
676 	.start_addr = FXOS8700_REG_M_OUTXMSB,				\
677 	.start_channel = FXOS8700_CHANNEL_MAGN_X,			\
678 	.num_channels = FXOS8700_NUM_MAG_CHANNELS,
679 
680 #define FXOS8700_MODE_PROPS_HYBRID					\
681 	.mode = FXOS8700_MODE_HYBRID,					\
682 	.start_addr = FXOS8700_REG_OUTXMSB,				\
683 	.start_channel = FXOS8700_CHANNEL_ACCEL_X,			\
684 	.num_channels = FXOS8700_NUM_HYBRID_CHANNELS,			\
685 
686 #define FXOS8700_MODE(n)						\
687 	COND_CODE_1(CONFIG_FXOS8700_MODE_ACCEL,				\
688 		    (FXOS8700_MODE_PROPS_ACCEL),			\
689 		    (COND_CODE_1(CONFIG_FXOS8700_MODE_MAGN,		\
690 		    (FXOS8700_MODE_PROPS_MAGN),				\
691 		    (FXOS8700_MODE_PROPS_HYBRID))))
692 
693 #define FXOS8700_RESET_PROPS(n)						\
694 	.reset_gpio = GPIO_DT_SPEC_INST_GET(n, reset_gpios),
695 
696 #define FXOS8700_RESET(n)						\
697 	COND_CODE_1(DT_INST_NODE_HAS_PROP(n, reset_gpios),		\
698 		    (FXOS8700_RESET_PROPS(n)),				\
699 		    ())
700 
701 #define FXOS8700_INTM_PROPS(n, m)					\
702 	.int_gpio = GPIO_DT_SPEC_INST_GET(n, int##m##_gpios),
703 
704 #define FXOS8700_INT_PROPS(n)						\
705 	COND_CODE_1(CONFIG_FXOS8700_DRDY_INT1,				\
706 		    (FXOS8700_INTM_PROPS(n, 1)),			\
707 		    (FXOS8700_INTM_PROPS(n, 2)))
708 
709 #define FXOS8700_INT(n)							\
710 	COND_CODE_1(CONFIG_FXOS8700_TRIGGER,				\
711 		    (FXOS8700_INT_PROPS(n)),				\
712 		    ())
713 
714 #define FXOS8700_PULSE_PROPS(n)						\
715 	.pulse_cfg = DT_INST_PROP(n, pulse_cfg),			\
716 	.pulse_ths[0] = DT_INST_PROP(n, pulse_thsx),			\
717 	.pulse_ths[1] = DT_INST_PROP(n, pulse_thsy),			\
718 	.pulse_ths[2] = DT_INST_PROP(n, pulse_thsz),			\
719 	.pulse_tmlt = DT_INST_PROP(n, pulse_tmlt),			\
720 	.pulse_ltcy = DT_INST_PROP(n, pulse_ltcy),			\
721 	.pulse_wind = DT_INST_PROP(n, pulse_wind),
722 
723 #define FXOS8700_PULSE(n)						\
724 	COND_CODE_1(CONFIG_FXOS8700_PULSE,				\
725 		    (FXOS8700_PULSE_PROPS(n)),				\
726 		    ())
727 
728 #define FXOS8700_MAG_VECM_PROPS(n)					\
729 	.mag_vecm_cfg = DT_INST_PROP(n, mag_vecm_cfg),			\
730 	.mag_vecm_ths[0] = DT_INST_PROP(n, mag_vecm_ths_msb),		\
731 	.mag_vecm_ths[1] = DT_INST_PROP(n, mag_vecm_ths_lsb),
732 
733 #define FXOS8700_MAG_VECM(n)						\
734 	COND_CODE_1(CONFIG_FXOS8700_MAG_VECM,				\
735 		    (FXOS8700_MAG_VECM_PROPS(n)),			\
736 		    ())
737 
738 #define FXOS8700_CONFIG_I2C(n)						\
739 		.bus_cfg = { .i2c = I2C_DT_SPEC_INST_GET(n) },		\
740 		.ops = &fxos8700_i2c_ops,				\
741 		.power_mode = DT_INST_PROP(n, power_mode),		\
742 		.range = DT_INST_PROP(n, range),			\
743 		.inst_on_bus = FXOS8700_BUS_I2C,
744 
745 #define FXOS8700_CONFIG_SPI(n)						\
746 		.bus_cfg = { .spi = SPI_DT_SPEC_INST_GET(n,		\
747 			SPI_OP_MODE_MASTER | SPI_WORD_SET(8), 0) },	\
748 		.ops = &fxos8700_spi_ops,				\
749 		.power_mode =  DT_INST_PROP(n, power_mode),		\
750 		.range = DT_INST_PROP(n, range),			\
751 		.inst_on_bus = FXOS8700_BUS_SPI,			\
752 
753 #define FXOS8700_SPI_OPERATION (SPI_WORD_SET(8) |			\
754 				SPI_OP_MODE_MASTER)			\
755 
756 #define FXOS8700_INIT(n)						\
757 	static const struct fxos8700_config fxos8700_config_##n = {	\
758 	COND_CODE_1(DT_INST_ON_BUS(n, spi),				\
759 		(FXOS8700_CONFIG_SPI(n)),				\
760 		(FXOS8700_CONFIG_I2C(n)))				\
761 		FXOS8700_RESET(n)					\
762 		FXOS8700_MODE(n)					\
763 		FXOS8700_INT(n)						\
764 		FXOS8700_PULSE(n)					\
765 		FXOS8700_MAG_VECM(n)					\
766 	};								\
767 									\
768 	static struct fxos8700_data fxos8700_data_##n;			\
769 									\
770 	SENSOR_DEVICE_DT_INST_DEFINE(n,					\
771 				     fxos8700_init,			\
772 				     NULL,				\
773 				     &fxos8700_data_##n,		\
774 				     &fxos8700_config_##n,		\
775 				     POST_KERNEL,			\
776 				     CONFIG_SENSOR_INIT_PRIORITY,	\
777 				     &fxos8700_driver_api);
778 
779 DT_INST_FOREACH_STATUS_OKAY(FXOS8700_INIT)
780