1 /*
2  * Copyright 2020 Google LLC
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Emulator for the Bosch BMI160 accelerometer / gyro. This supports basic
7  * init and reading of canned samples. It supports both I2C and SPI buses.
8  */
9 
10 #define DT_DRV_COMPAT bosch_bmi160
11 
12 #define LOG_LEVEL CONFIG_SPI_LOG_LEVEL
13 #include <zephyr/logging/log.h>
14 LOG_MODULE_REGISTER(bosch_bmi160);
15 
16 #include <zephyr/sys/byteorder.h>
17 #include <bmi160.h>
18 #include <zephyr/device.h>
19 #include <zephyr/drivers/emul.h>
20 #include <zephyr/drivers/emul_sensor.h>
21 #include <zephyr/drivers/i2c.h>
22 #include <zephyr/drivers/i2c_emul.h>
23 #include <zephyr/drivers/spi.h>
24 #include <zephyr/drivers/spi_emul.h>
25 #include <zephyr/sys/util.h>
26 
27 /** Run-time data used by the emulator */
28 struct bmi160_emul_data {
29 	uint8_t pmu_status;
30 	/** Current register to read (address) */
31 	uint32_t cur_reg;
32 };
33 
34 /** Static configuration for the emulator */
35 struct bmi160_emul_cfg {
36 	/** Chip registers */
37 	uint8_t *reg;
38 	union {
39 		/** Unit address (chip select ordinal) of emulator */
40 		uint16_t chipsel;
41 		/** I2C address of emulator */
42 		uint16_t addr;
43 	};
44 };
45 
46 /* Names for the PMU components */
47 static const char *const pmu_name[] = {"acc", "gyr", "mag", "INV"};
48 
emul_bmi160_get_reg_value(const struct emul * target,int reg_number,uint8_t * out,size_t count)49 int emul_bmi160_get_reg_value(const struct emul *target, int reg_number, uint8_t *out, size_t count)
50 {
51 	const struct bmi160_emul_cfg *cfg = target->cfg;
52 
53 	if (reg_number < 0 || reg_number + count > BMI160_REG_COUNT) {
54 		return -EINVAL;
55 	}
56 
57 	memcpy(out, cfg->reg + reg_number, count);
58 	return 0;
59 }
60 
reg_write(const struct emul * target,int regn,int val)61 static void reg_write(const struct emul *target, int regn, int val)
62 {
63 	struct bmi160_emul_data *data = target->data;
64 	const struct bmi160_emul_cfg *cfg = target->cfg;
65 
66 	LOG_DBG("write %x = %x", regn, val);
67 	cfg->reg[regn] = val;
68 	switch (regn) {
69 	case BMI160_REG_ACC_CONF:
70 		LOG_DBG("   * acc conf");
71 		break;
72 	case BMI160_REG_ACC_RANGE:
73 		LOG_DBG("   * acc range");
74 		break;
75 	case BMI160_REG_GYR_CONF:
76 		LOG_DBG("   * gyr conf");
77 		break;
78 	case BMI160_REG_GYR_RANGE:
79 		LOG_DBG("   * gyr range");
80 		break;
81 	case BMI160_REG_CMD:
82 		switch (val) {
83 		case BMI160_CMD_SOFT_RESET:
84 			LOG_DBG("   * soft reset");
85 			break;
86 		default:
87 			if ((val & BMI160_CMD_PMU_BIT) == BMI160_CMD_PMU_BIT) {
88 				int which = (val & BMI160_CMD_PMU_MASK) >> BMI160_CMD_PMU_SHIFT;
89 				int shift;
90 				int pmu_val = val & BMI160_CMD_PMU_VAL_MASK;
91 
92 				switch (which) {
93 				case 0:
94 					shift = BMI160_PMU_STATUS_ACC_POS;
95 					break;
96 				case 1:
97 					shift = BMI160_PMU_STATUS_GYR_POS;
98 					break;
99 				case 2:
100 				default:
101 					shift = BMI160_PMU_STATUS_MAG_POS;
102 					break;
103 				}
104 				data->pmu_status &= 3 << shift;
105 				data->pmu_status |= pmu_val << shift;
106 				LOG_DBG("   * pmu %s = %x, new status %x", pmu_name[which], pmu_val,
107 					data->pmu_status);
108 			} else {
109 				LOG_DBG("Unknown command %x", val);
110 			}
111 			break;
112 		}
113 		break;
114 	default:
115 		LOG_DBG("Unknown write %x", regn);
116 	}
117 }
118 
reg_read(const struct emul * target,int regn)119 static int reg_read(const struct emul *target, int regn)
120 {
121 	struct bmi160_emul_data *data = target->data;
122 	const struct bmi160_emul_cfg *cfg = target->cfg;
123 	int val;
124 
125 	LOG_DBG("read %x =", regn);
126 	val = cfg->reg[regn];
127 	switch (regn) {
128 	case BMI160_REG_CHIPID:
129 		LOG_DBG("   * get chipid");
130 		break;
131 	case BMI160_REG_PMU_STATUS:
132 		LOG_DBG("   * get pmu");
133 		val = data->pmu_status;
134 		break;
135 	case BMI160_REG_STATUS:
136 		LOG_DBG("   * status");
137 		val |= BMI160_DATA_READY_BIT_MASK;
138 		break;
139 	case BMI160_REG_ACC_CONF:
140 		LOG_DBG("   * acc conf");
141 		break;
142 	case BMI160_REG_GYR_CONF:
143 		LOG_DBG("   * gyr conf");
144 		break;
145 	case BMI160_SPI_START:
146 		LOG_DBG("   * Bus start");
147 		break;
148 	case BMI160_REG_ACC_RANGE:
149 		LOG_DBG("   * acc range");
150 		break;
151 	case BMI160_REG_GYR_RANGE:
152 		LOG_DBG("   * gyr range");
153 		break;
154 	default:
155 		LOG_DBG("Unknown read %x", regn);
156 	}
157 	LOG_DBG("       = %x", val);
158 
159 	return val;
160 }
161 
162 #if BMI160_BUS_SPI
bmi160_emul_io_spi(const struct emul * target,const struct spi_config * config,const struct spi_buf_set * tx_bufs,const struct spi_buf_set * rx_bufs)163 static int bmi160_emul_io_spi(const struct emul *target, const struct spi_config *config,
164 			      const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs)
165 {
166 	struct bmi160_emul_data *data;
167 	const struct spi_buf *tx, *txd, *rxd;
168 	unsigned int regn, val;
169 	int count;
170 
171 	ARG_UNUSED(config);
172 
173 	data = target->data;
174 
175 	__ASSERT_NO_MSG(tx_bufs || rx_bufs);
176 	__ASSERT_NO_MSG(!tx_bufs || !rx_bufs || tx_bufs->count == rx_bufs->count);
177 	count = tx_bufs ? tx_bufs->count : rx_bufs->count;
178 
179 	if (count != 2) {
180 		LOG_DBG("Unknown tx_bufs->count %d", count);
181 		return -EIO;
182 	}
183 	tx = tx_bufs->buffers;
184 	txd = &tx_bufs->buffers[1];
185 	rxd = rx_bufs ? &rx_bufs->buffers[1] : NULL;
186 
187 	if (tx->len != 1) {
188 		LOG_DBG("Unknown tx->len %d", tx->len);
189 		return -EIO;
190 	}
191 
192 	regn = *(uint8_t *)tx->buf;
193 	if ((regn & BMI160_REG_READ) && rxd == NULL) {
194 		LOG_ERR("Cannot read without rxd");
195 		return -EPERM;
196 	}
197 
198 	if (txd->len == 1) {
199 		if (regn & BMI160_REG_READ) {
200 			regn &= BMI160_REG_MASK;
201 			val = reg_read(target, regn);
202 			*(uint8_t *)rxd->buf = val;
203 		} else {
204 			val = *(uint8_t *)txd->buf;
205 			reg_write(target, regn, val);
206 		}
207 	} else {
208 		if (regn & BMI160_REG_READ) {
209 			regn &= BMI160_REG_MASK;
210 			for (int i = 0; i < txd->len; ++i) {
211 				((uint8_t *)rxd->buf)[i] = reg_read(target, regn + i);
212 			}
213 		} else {
214 			LOG_ERR("Unknown sample write");
215 			return -EIO;
216 		}
217 	}
218 
219 	return 0;
220 }
221 #endif
222 
223 #if BMI160_BUS_I2C
bmi160_emul_transfer_i2c(const struct emul * target,struct i2c_msg * msgs,int num_msgs,int addr)224 static int bmi160_emul_transfer_i2c(const struct emul *target, struct i2c_msg *msgs, int num_msgs,
225 				    int addr)
226 {
227 	struct bmi160_emul_data *data;
228 
229 	data = target->data;
230 
231 	__ASSERT_NO_MSG(msgs && num_msgs);
232 
233 	i2c_dump_msgs_rw(target->dev, msgs, num_msgs, addr, false);
234 	switch (num_msgs) {
235 	case 2:
236 		if (msgs->flags & I2C_MSG_READ) {
237 			LOG_ERR("Unexpected read");
238 			return -EIO;
239 		}
240 		if (msgs->len != 1) {
241 			LOG_ERR("Unexpected msg0 length %d", msgs->len);
242 			return -EIO;
243 		}
244 		data->cur_reg = msgs->buf[0];
245 
246 		/* Now process the 'read' part of the message */
247 		msgs++;
248 		if (msgs->flags & I2C_MSG_READ) {
249 			for (int i = 0; i < msgs->len; ++i) {
250 				msgs->buf[i] = reg_read(target, data->cur_reg + i);
251 			}
252 		} else {
253 			if (msgs->len != 1) {
254 				LOG_ERR("Unexpected msg1 length %d", msgs->len);
255 			}
256 			reg_write(target, data->cur_reg, msgs->buf[0]);
257 		}
258 		break;
259 	default:
260 		LOG_ERR("Invalid number of messages: %d", num_msgs);
261 		return -EIO;
262 	}
263 
264 	return 0;
265 }
266 #endif
267 
268 /* Device instantiation */
269 
270 #if BMI160_BUS_SPI
271 static struct spi_emul_api bmi160_emul_api_spi = {
272 	.io = bmi160_emul_io_spi,
273 };
274 #endif
275 
276 #if BMI160_BUS_I2C
277 static struct i2c_emul_api bmi160_emul_api_i2c = {
278 	.transfer = bmi160_emul_transfer_i2c,
279 };
280 #endif
281 
bmi160_emul_backend_set_channel(const struct emul * target,struct sensor_chan_spec ch,const q31_t * value,int8_t shift)282 static int bmi160_emul_backend_set_channel(const struct emul *target, struct sensor_chan_spec ch,
283 					   const q31_t *value, int8_t shift)
284 {
285 	const struct bmi160_emul_cfg *cfg = target->cfg;
286 	int64_t intermediate = *value;
287 	q31_t scale;
288 	int8_t scale_shift = 0;
289 	int reg_lsb;
290 
291 	switch (ch.chan_type) {
292 	case SENSOR_CHAN_ACCEL_X:
293 	case SENSOR_CHAN_ACCEL_Y:
294 	case SENSOR_CHAN_ACCEL_Z:
295 		reg_lsb = BMI160_REG_DATA_ACC_X + (ch.chan_type - SENSOR_CHAN_ACCEL_X) * 2;
296 		scale = 0x4e7404ea;
297 
298 		switch (FIELD_GET(GENMASK(3, 0), cfg->reg[BMI160_REG_ACC_RANGE])) {
299 		case BMI160_ACC_RANGE_4G:
300 			scale_shift = 6;
301 			break;
302 		case BMI160_ACC_RANGE_8G:
303 			scale_shift = 7;
304 			break;
305 		case BMI160_ACC_RANGE_16G:
306 			scale_shift = 8;
307 			break;
308 		default:
309 			scale_shift = 5;
310 			break;
311 		}
312 		break;
313 	case SENSOR_CHAN_GYRO_X:
314 	case SENSOR_CHAN_GYRO_Y:
315 	case SENSOR_CHAN_GYRO_Z:
316 		reg_lsb = BMI160_REG_DATA_GYR_X + (ch.chan_type - SENSOR_CHAN_GYRO_X) * 2;
317 		scale = 0x45d02bea;
318 
319 		switch (FIELD_GET(GENMASK(2, 0), cfg->reg[BMI160_REG_GYR_RANGE])) {
320 		case BMI160_GYR_RANGE_2000DPS:
321 			scale_shift = 6;
322 			break;
323 		case BMI160_GYR_RANGE_1000DPS:
324 			scale_shift = 5;
325 			break;
326 		case BMI160_GYR_RANGE_500DPS:
327 			scale_shift = 4;
328 			break;
329 		case BMI160_GYR_RANGE_250DPS:
330 			scale_shift = 3;
331 			break;
332 		case BMI160_GYR_RANGE_125DPS:
333 			scale_shift = 2;
334 			break;
335 		default:
336 			return -EINVAL;
337 		}
338 		break;
339 	case SENSOR_CHAN_DIE_TEMP:
340 		reg_lsb = BMI160_REG_TEMPERATURE0;
341 		scale = 0x8000;
342 		scale_shift = 7;
343 		break;
344 	default:
345 		return -EINVAL;
346 	}
347 
348 	if (shift < scale_shift) {
349 		/* Original value doesn't have enough int bits, fix it */
350 		intermediate >>= scale_shift - shift;
351 	} else if (shift > 0 && shift > scale_shift) {
352 		/* Original value might be out-of-bounds, fix it (we're going to lose precision) */
353 		intermediate <<= shift - scale_shift;
354 	}
355 
356 	if (ch.chan_type == SENSOR_CHAN_DIE_TEMP) {
357 		/* Need to subtract 23C */
358 		intermediate -= INT64_C(23) << (31 - scale_shift);
359 	}
360 
361 	intermediate =
362 		CLAMP(DIV_ROUND_CLOSEST(intermediate * INT16_MAX, scale), INT16_MIN, INT16_MAX);
363 
364 	cfg->reg[reg_lsb] = FIELD_GET(GENMASK64(7, 0), intermediate);
365 	cfg->reg[reg_lsb + 1] = FIELD_GET(GENMASK64(15, 8), intermediate);
366 	return 0;
367 }
368 
bmi160_emul_backend_get_sample_range(const struct emul * target,struct sensor_chan_spec ch,q31_t * lower,q31_t * upper,q31_t * epsilon,int8_t * shift)369 static int bmi160_emul_backend_get_sample_range(const struct emul *target,
370 						struct sensor_chan_spec ch, q31_t *lower,
371 						q31_t *upper, q31_t *epsilon, int8_t *shift)
372 {
373 	const struct bmi160_emul_cfg *cfg = target->cfg;
374 
375 	switch (ch.chan_type) {
376 	case SENSOR_CHAN_ACCEL_X:
377 	case SENSOR_CHAN_ACCEL_Y:
378 	case SENSOR_CHAN_ACCEL_Z:
379 	case SENSOR_CHAN_ACCEL_XYZ: {
380 		uint8_t acc_range = cfg->reg[BMI160_REG_ACC_RANGE];
381 
382 		switch (acc_range) {
383 		case BMI160_ACC_RANGE_2G:
384 			*shift = 5;
385 			break;
386 		case BMI160_ACC_RANGE_4G:
387 			*shift = 6;
388 			break;
389 		case BMI160_ACC_RANGE_8G:
390 			*shift = 7;
391 			break;
392 		case BMI160_ACC_RANGE_16G:
393 			*shift = 8;
394 			break;
395 		default:
396 			return -EINVAL;
397 		}
398 		int64_t intermediate = ((int64_t)(2 * 9.80665 * INT32_MAX)) >> 5;
399 
400 		*upper = intermediate;
401 		*lower = -(*upper);
402 		*epsilon = intermediate * 2 / (1 << (16 - *shift));
403 		return 0;
404 	}
405 	case SENSOR_CHAN_GYRO_X:
406 	case SENSOR_CHAN_GYRO_Y:
407 	case SENSOR_CHAN_GYRO_Z:
408 	case SENSOR_CHAN_GYRO_XYZ: {
409 		uint8_t gyro_range = cfg->reg[BMI160_REG_GYR_RANGE];
410 
411 		switch (gyro_range) {
412 		case BMI160_GYR_RANGE_125DPS:
413 			*shift = 2;
414 			break;
415 		case BMI160_GYR_RANGE_250DPS:
416 			*shift = 3;
417 			break;
418 		case BMI160_GYR_RANGE_500DPS:
419 			*shift = 4;
420 			break;
421 		case BMI160_GYR_RANGE_1000DPS:
422 			*shift = 5;
423 			break;
424 		case BMI160_GYR_RANGE_2000DPS:
425 			*shift = 6;
426 			break;
427 		default:
428 			return -EINVAL;
429 		}
430 
431 		int64_t intermediate = (int64_t)(125 * 3.141592654 * INT32_MAX / 180) >> 2;
432 
433 		*upper = intermediate;
434 		*lower = -(*upper);
435 		*epsilon = intermediate * 2 / (1 << (16 - *shift));
436 		return 0;
437 	}
438 	default:
439 		return -EINVAL;
440 	}
441 }
442 
bmi160_emul_backend_set_offset(const struct emul * target,struct sensor_chan_spec ch,const q31_t * values,int8_t shift)443 static int bmi160_emul_backend_set_offset(const struct emul *target, struct sensor_chan_spec ch,
444 					  const q31_t *values, int8_t shift)
445 {
446 	if (ch.chan_type != SENSOR_CHAN_ACCEL_XYZ && ch.chan_type != SENSOR_CHAN_GYRO_XYZ) {
447 		return -EINVAL;
448 	}
449 
450 	const struct bmi160_emul_cfg *cfg = target->cfg;
451 	q31_t scale;
452 	int8_t scale_shift = 0;
453 
454 	if (values[0] == 0 && values[1] == 0 && values[2] == 0) {
455 		if (ch.chan_type == SENSOR_CHAN_ACCEL_XYZ) {
456 			cfg->reg[BMI160_REG_OFFSET_EN] &= ~BIT(BMI160_ACC_OFS_EN_POS);
457 		} else {
458 			cfg->reg[BMI160_REG_OFFSET_EN] &= ~BIT(BMI160_GYR_OFS_EN_POS);
459 		}
460 	} else {
461 		if (ch.chan_type == SENSOR_CHAN_ACCEL_XYZ) {
462 			cfg->reg[BMI160_REG_OFFSET_EN] |= BIT(BMI160_ACC_OFS_EN_POS);
463 		} else {
464 			cfg->reg[BMI160_REG_OFFSET_EN] |= BIT(BMI160_GYR_OFS_EN_POS);
465 		}
466 	}
467 
468 	if (ch.chan_type == SENSOR_CHAN_ACCEL_XYZ) {
469 		/*
470 		 * bits = (values[i]mps2 / 9.80665g/mps2) / 0.0039g
471 		 *      = values[i] / 0.038245935mps2/bit
472 		 * 0.038245935 in Q31 format is 0x4e53e28 with shift 0
473 		 */
474 		scale = 0x4e53e28;
475 	} else {
476 		/*
477 		 * bits = (values[i]rad/s * 180 / pi) / 0.061deg/s
478 		 *      = values[i] / 0.001064651rad/s
479 		 */
480 		scale = 0x22e2f0;
481 	}
482 
483 	for (int i = 0; i < 3; ++i) {
484 		int64_t intermediate = values[i];
485 
486 		if (shift > scale_shift) {
487 			/* Input uses a bigger scale, we need to increase its value to match */
488 			intermediate <<= (shift - scale_shift);
489 		} else if (shift < scale_shift) {
490 			/* Scale uses a bigger shift, we need to decrease its value to match */
491 			scale >>= (scale_shift - shift);
492 		}
493 
494 		int64_t reg_value = intermediate / scale;
495 
496 		__ASSERT_NO_MSG(ch.chan_type != SENSOR_CHAN_ACCEL_XYZ ||
497 				(reg_value >= INT8_MIN && reg_value <= INT8_MAX));
498 		__ASSERT_NO_MSG(ch.chan_type != SENSOR_CHAN_GYRO_XYZ ||
499 				(reg_value >= -0x1ff - 1 && reg_value <= 0x1ff));
500 		if (ch.chan_type == SENSOR_CHAN_ACCEL_XYZ) {
501 			cfg->reg[BMI160_REG_OFFSET_ACC_X + i] = reg_value & 0xff;
502 		} else {
503 			cfg->reg[BMI160_REG_OFFSET_GYR_X + i] = reg_value & 0xff;
504 			cfg->reg[BMI160_REG_OFFSET_EN] =
505 				(cfg->reg[BMI160_REG_OFFSET_EN] & ~GENMASK(i * 2 + 1, i * 2)) |
506 				(reg_value & GENMASK(9, 8));
507 		}
508 	}
509 
510 	return 0;
511 }
512 
bmi160_emul_backend_set_attribute(const struct emul * target,struct sensor_chan_spec ch,enum sensor_attribute attribute,const void * value)513 static int bmi160_emul_backend_set_attribute(const struct emul *target, struct sensor_chan_spec ch,
514 					     enum sensor_attribute attribute, const void *value)
515 {
516 	if (attribute == SENSOR_ATTR_OFFSET &&
517 	    (ch.chan_type == SENSOR_CHAN_ACCEL_XYZ || ch.chan_type == SENSOR_CHAN_GYRO_XYZ)) {
518 		const struct sensor_three_axis_attribute *attribute_value = value;
519 
520 		return bmi160_emul_backend_set_offset(target, ch, attribute_value->values,
521 						      attribute_value->shift);
522 	}
523 	return -EINVAL;
524 }
525 
bmi160_emul_backend_get_attribute_metadata(const struct emul * target,struct sensor_chan_spec ch,enum sensor_attribute attribute,q31_t * min,q31_t * max,q31_t * increment,int8_t * shift)526 static int bmi160_emul_backend_get_attribute_metadata(const struct emul *target,
527 						      struct sensor_chan_spec ch,
528 						      enum sensor_attribute attribute, q31_t *min,
529 						      q31_t *max, q31_t *increment, int8_t *shift)
530 {
531 	ARG_UNUSED(target);
532 	switch (ch.chan_type) {
533 	case SENSOR_CHAN_ACCEL_X:
534 	case SENSOR_CHAN_ACCEL_Y:
535 	case SENSOR_CHAN_ACCEL_Z:
536 	case SENSOR_CHAN_ACCEL_XYZ:
537 		if (attribute == SENSOR_ATTR_OFFSET) {
538 			/* Offset uses 3.9mg per bit in an 8 bit register:
539 			 *   0.0039g * 9.8065m/s2: yields the increment in SI units
540 			 *   * INT8_MIN (or MAX) : yields the minimum (or maximum) values
541 			 *   * INT32_MAX >> 3    : converts to q31 format within range [-8, 8]
542 			 */
543 			*min = (q31_t)((int64_t)(0.0039 * 9.8065 * INT8_MIN * INT32_MAX) >> 3);
544 			*max = (q31_t)((int64_t)(0.0039 * 9.8065 * INT8_MAX * INT32_MAX) >> 3);
545 			*increment = (q31_t)((int64_t)(0.0039 * 9.8065 * INT32_MAX) >> 3);
546 			*shift = 3;
547 			return 0;
548 		}
549 		return -EINVAL;
550 	case SENSOR_CHAN_GYRO_X:
551 	case SENSOR_CHAN_GYRO_Y:
552 	case SENSOR_CHAN_GYRO_Z:
553 	case SENSOR_CHAN_GYRO_XYZ:
554 		if (attribute == SENSOR_ATTR_OFFSET) {
555 			/* Offset uses 0.061deg/s per bit in an 10 bit register:
556 			 *   0.061deg/s * pi / 180: yields the increment in SI units
557 			 *   * INT10_MIN (or MAX) : yields the minimum (or maximum) values
558 			 *   * INT32_MAX          : converts to q31 format within range [-1, 1]
559 			 */
560 			*min = (q31_t)(0.061 * 3.141593 / 180.0 * -512 * INT32_MAX);
561 			*max = (q31_t)(0.061 * 3.141593 / 180.0 * 511 * INT32_MAX);
562 			*increment = (q31_t)(0.061 * 3.141593 / 180.0 * INT32_MAX);
563 			*shift = 0;
564 			return 0;
565 		}
566 		return -EINVAL;
567 	default:
568 		return -EINVAL;
569 	}
570 }
571 
572 static const struct emul_sensor_driver_api backend_api = {
573 	.set_channel = bmi160_emul_backend_set_channel,
574 	.get_sample_range = bmi160_emul_backend_get_sample_range,
575 	.set_attribute = bmi160_emul_backend_set_attribute,
576 	.get_attribute_metadata = bmi160_emul_backend_get_attribute_metadata,
577 };
578 
emul_bosch_bmi160_init(const struct emul * target,const struct device * parent)579 static int emul_bosch_bmi160_init(const struct emul *target, const struct device *parent)
580 {
581 	const struct bmi160_emul_cfg *cfg = target->cfg;
582 	struct bmi160_emul_data *data = target->data;
583 	uint8_t *reg = cfg->reg;
584 
585 	ARG_UNUSED(parent);
586 
587 	data->pmu_status = 0;
588 
589 	reg[BMI160_REG_CHIPID] = BMI160_CHIP_ID;
590 
591 	return 0;
592 }
593 
594 #define BMI160_EMUL_DATA(n)                                                                        \
595 	static uint8_t bmi160_emul_reg_##n[BMI160_REG_COUNT];                                      \
596 	static struct bmi160_emul_data bmi160_emul_data_##n;
597 
598 #define BMI160_EMUL_DEFINE(n, bus_api)                                                             \
599 	EMUL_DT_INST_DEFINE(n, emul_bosch_bmi160_init, &bmi160_emul_data_##n,                      \
600 			    &bmi160_emul_cfg_##n, &bus_api, &backend_api)
601 
602 /* Instantiation macros used when a device is on a SPI bus */
603 #define BMI160_EMUL_SPI(n)                                                                         \
604 	BMI160_EMUL_DATA(n)                                                                        \
605 	static const struct bmi160_emul_cfg bmi160_emul_cfg_##n = {                                \
606 		.reg = bmi160_emul_reg_##n, .chipsel = DT_INST_REG_ADDR(n)};                       \
607 	BMI160_EMUL_DEFINE(n, bmi160_emul_api_spi)
608 
609 #define BMI160_EMUL_I2C(n)                                                                         \
610 	BMI160_EMUL_DATA(n)                                                                        \
611 	static const struct bmi160_emul_cfg bmi160_emul_cfg_##n = {.reg = bmi160_emul_reg_##n,     \
612 								   .addr = DT_INST_REG_ADDR(n)};   \
613 	BMI160_EMUL_DEFINE(n, bmi160_emul_api_i2c)
614 
615 /*
616  * Main instantiation macro. Use of COND_CODE_1() selects the right
617  * bus-specific macro at preprocessor time.
618  */
619 #define BMI160_EMUL(n)                                                                             \
620 	COND_CODE_1(DT_INST_ON_BUS(n, spi), (BMI160_EMUL_SPI(n)), (BMI160_EMUL_I2C(n)))
621 
622 DT_INST_FOREACH_STATUS_OKAY(BMI160_EMUL)
623