1 /* Bosch BMA4xx 3-axis accelerometer driver
2  *
3  * Copyright (c) 2023 Google LLC
4  * Copyright (c) 2024 Croxel Inc.
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #define DT_DRV_COMPAT bosch_bma4xx
10 
11 #include <zephyr/init.h>
12 #include <zephyr/sys/byteorder.h>
13 #include <zephyr/sys/__assert.h>
14 #include <zephyr/logging/log.h>
15 #include <zephyr/pm/device.h>
16 #include <zephyr/rtio/work.h>
17 
18 LOG_MODULE_REGISTER(bma4xx, CONFIG_SENSOR_LOG_LEVEL);
19 #include "bma4xx.h"
20 
21 /**
22  * @brief Helper for converting m/s^2 offset values into register values
23  */
bma4xx_offset_to_reg_val(const struct sensor_value * val,uint8_t * reg_val)24 static int bma4xx_offset_to_reg_val(const struct sensor_value *val, uint8_t *reg_val)
25 {
26 	int32_t ug = sensor_ms2_to_ug(val);
27 
28 	if (ug < BMA4XX_OFFSET_MICROG_MIN || ug > BMA4XX_OFFSET_MICROG_MAX) {
29 		return -ERANGE;
30 	}
31 
32 	*reg_val = ug / BMA4XX_OFFSET_MICROG_PER_BIT;
33 	return 0;
34 }
35 
36 /**
37  * @brief Set the X, Y, or Z axis offsets.
38  */
bma4xx_attr_set_offset(const struct device * dev,enum sensor_channel chan,const struct sensor_value * val)39 static int bma4xx_attr_set_offset(const struct device *dev, enum sensor_channel chan,
40 				  const struct sensor_value *val)
41 {
42 	struct bma4xx_data *bma4xx = dev->data;
43 	uint8_t reg_addr;
44 	uint8_t reg_val[3];
45 	int rc;
46 
47 	switch (chan) {
48 	case SENSOR_CHAN_ACCEL_X:
49 	case SENSOR_CHAN_ACCEL_Y:
50 	case SENSOR_CHAN_ACCEL_Z:
51 		reg_addr = BMA4XX_REG_OFFSET_0 + (chan - SENSOR_CHAN_ACCEL_X);
52 		rc = bma4xx_offset_to_reg_val(val, &reg_val[0]);
53 		if (rc) {
54 			return rc;
55 		}
56 		return bma4xx->hw_ops->write_reg(dev, reg_addr, reg_val[0]);
57 	case SENSOR_CHAN_ACCEL_XYZ:
58 		/* Expect val to point to an array of three sensor_values */
59 		reg_addr = BMA4XX_REG_OFFSET_0;
60 		for (int i = 0; i < 3; i++) {
61 			rc = bma4xx_offset_to_reg_val(&val[i], &reg_val[i]);
62 			if (rc) {
63 				return rc;
64 			}
65 		}
66 		return bma4xx->hw_ops->write_data(dev, reg_addr, (uint8_t *)reg_val,
67 						  sizeof(reg_val));
68 	default:
69 		return -ENOTSUP;
70 	}
71 }
72 
73 static const uint32_t odr_to_reg_map[] = {
74 	0,          /* Invalid */
75 	781250,     /* 0.78125 Hz (25/32) => 0x1 */
76 	1562500,    /* 1.5625 Hz (25/16) => 0x2 */
77 	3125000,    /* 3.125 Hz (25/8) => 0x3 */
78 	6250000,    /* 6.25 Hz (25/4) => 0x4 */
79 	12500000,   /* 12.5 Hz (25/2) => 0x5 */
80 	25000000,   /* 25 Hz => 0x6 */
81 	50000000,   /* 50 Hz => 0x7*/
82 	100000000,  /* 100 Hz => 0x8*/
83 	200000000,  /* 200 Hz => 0x9*/
84 	400000000,  /* 400 Hz => 0xa*/
85 	800000000,  /* 800 Hz => 0xb*/
86 	1600000000, /* 1600 Hz => 0xc*/
87 };
88 
89 /**
90  * @brief Convert an ODR rate in Hz to a register value
91  */
bma4xx_odr_to_reg(uint32_t microhertz,uint8_t * reg_val)92 static int bma4xx_odr_to_reg(uint32_t microhertz, uint8_t *reg_val)
93 {
94 	if (microhertz == 0) {
95 		/* Illegal ODR value */
96 		return -ERANGE;
97 	}
98 
99 	for (uint8_t i = 0; i < ARRAY_SIZE(odr_to_reg_map); i++) {
100 		if (microhertz <= odr_to_reg_map[i]) {
101 			*reg_val = i;
102 			return 0;
103 		}
104 	}
105 
106 	/* Requested ODR too high */
107 	return -ERANGE;
108 }
109 
110 /**
111  * Set the sensor's acceleration offset (per axis). Use bma4xx_commit_nvm() to save these
112  * offsets to nonvolatile memory so they are automatically set during power-on-reset.
113  */
bma4xx_attr_set_odr(const struct device * dev,const struct sensor_value * val)114 static int bma4xx_attr_set_odr(const struct device *dev, const struct sensor_value *val)
115 {
116 	struct bma4xx_data *bma4xx = dev->data;
117 	int status;
118 	uint8_t reg_val;
119 
120 	/* Convert ODR Hz value to microhertz and round up to closest register setting */
121 	status = bma4xx_odr_to_reg(val->val1 * 1000000 + val->val2, &reg_val);
122 	if (status < 0) {
123 		return status;
124 	}
125 
126 	status = bma4xx->hw_ops->update_reg(dev, BMA4XX_REG_ACCEL_CONFIG, BMA4XX_MASK_ACC_CONF_ODR,
127 					    reg_val);
128 	if (status < 0) {
129 		return status;
130 	}
131 
132 	bma4xx->accel_odr = reg_val;
133 	return 0;
134 }
135 
136 static const uint32_t fs_to_reg_map[] = {
137 	2000000,  /* +/-2G => 0x0 */
138 	4000000,  /* +/-4G => 0x1 */
139 	8000000,  /* +/-8G => 0x2 */
140 	16000000, /* +/-16G => 0x3 */
141 };
142 
bma4xx_fs_to_reg(int32_t range_ug,uint8_t * reg_val)143 static int bma4xx_fs_to_reg(int32_t range_ug, uint8_t *reg_val)
144 {
145 	if (range_ug == 0) {
146 		/* Illegal value */
147 		return -ERANGE;
148 	}
149 
150 	range_ug = abs(range_ug);
151 
152 	for (uint8_t i = 0; i < 4; i++) {
153 		if (range_ug <= fs_to_reg_map[i]) {
154 			*reg_val = i;
155 			return 0;
156 		}
157 	}
158 
159 	/* Requested range too high */
160 	return -ERANGE;
161 }
162 
163 /**
164  * Set the sensor's full-scale range
165  */
bma4xx_attr_set_range(const struct device * dev,const struct sensor_value * val)166 static int bma4xx_attr_set_range(const struct device *dev, const struct sensor_value *val)
167 {
168 	struct bma4xx_data *bma4xx = dev->data;
169 	int status;
170 	uint8_t reg_val;
171 
172 	/* Convert m/s^2 to micro-G's and find closest register setting */
173 	status = bma4xx_fs_to_reg(sensor_ms2_to_ug(val), &reg_val);
174 	if (status < 0) {
175 		return status;
176 	}
177 
178 	status = bma4xx->hw_ops->update_reg(dev, BMA4XX_REG_ACCEL_RANGE, BMA4XX_MASK_ACC_RANGE,
179 					    reg_val);
180 	if (status < 0) {
181 		return status;
182 	}
183 
184 	bma4xx->accel_fs_range = reg_val;
185 	return 0;
186 }
187 
188 /**
189  * Set the sensor's bandwidth parameter (one of BMA4XX_BWP_*)
190  */
bma4xx_attr_set_bwp(const struct device * dev,const struct sensor_value * val)191 static int bma4xx_attr_set_bwp(const struct device *dev, const struct sensor_value *val)
192 {
193 	/* Require that `val2` is unused, and that `val1` is in range of a valid BWP */
194 	if (val->val2 || val->val1 < BMA4XX_BWP_OSR4_AVG1 || val->val1 > BMA4XX_BWP_RES_AVG128) {
195 		return -EINVAL;
196 	}
197 
198 	struct bma4xx_data *bma4xx = dev->data;
199 
200 	return bma4xx->hw_ops->update_reg(dev, BMA4XX_REG_ACCEL_CONFIG, BMA4XX_MASK_ACC_CONF_BWP,
201 					  (((uint8_t)val->val1) << BMA4XX_SHIFT_ACC_CONF_BWP));
202 }
203 
204 /**
205  * @brief Implement the sensor API attribute set method.
206  */
bma4xx_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)207 static int bma4xx_attr_set(const struct device *dev, enum sensor_channel chan,
208 			   enum sensor_attribute attr, const struct sensor_value *val)
209 {
210 	switch (attr) {
211 	case SENSOR_ATTR_SAMPLING_FREQUENCY:
212 		return bma4xx_attr_set_odr(dev, val);
213 	case SENSOR_ATTR_FULL_SCALE:
214 		return bma4xx_attr_set_range(dev, val);
215 	case SENSOR_ATTR_OFFSET:
216 		return bma4xx_attr_set_offset(dev, chan, val);
217 	case SENSOR_ATTR_CONFIGURATION:
218 		/* Use for setting the bandwidth parameter (BWP) */
219 		return bma4xx_attr_set_bwp(dev, val);
220 	default:
221 		return -ENOTSUP;
222 	}
223 }
224 
225 /**
226  * Internal device initialization function for both bus types.
227  */
bma4xx_chip_init(const struct device * dev)228 static int bma4xx_chip_init(const struct device *dev)
229 {
230 	struct bma4xx_data *bma4xx = dev->data;
231 	const struct bma4xx_config *cfg = dev->config;
232 	int status;
233 
234 	/* Sensor bus-specific initialization */
235 	status = cfg->bus_init(dev);
236 	if (status) {
237 		LOG_ERR("bus_init failed: %d", status);
238 		return status;
239 	}
240 
241 	/* Read Chip ID */
242 	status = bma4xx->hw_ops->read_reg(dev, BMA4XX_REG_CHIP_ID, &bma4xx->chip_id);
243 	if (status) {
244 		LOG_ERR("could not read chip_id: %d", status);
245 		return status;
246 	}
247 	LOG_DBG("chip_id is 0x%02x", bma4xx->chip_id);
248 
249 	if (bma4xx->chip_id != BMA4XX_CHIP_ID_BMA422) {
250 		LOG_WRN("Driver tested for BMA422. Check for unintended operation.");
251 	}
252 
253 	/* Issue soft reset command */
254 	status = bma4xx->hw_ops->write_reg(dev, BMA4XX_REG_CMD, BMA4XX_CMD_SOFT_RESET);
255 	if (status) {
256 		LOG_ERR("Could not soft-reset chip: %d", status);
257 		return status;
258 	}
259 
260 	k_sleep(K_USEC(1000));
261 
262 	/* Default is: range = +/-4G, ODR = 100 Hz, BWP = "NORM_AVG4" */
263 	bma4xx->accel_fs_range = BMA4XX_RANGE_4G;
264 	bma4xx->accel_bwp = BMA4XX_BWP_NORM_AVG4;
265 	bma4xx->accel_odr = BMA4XX_ODR_100;
266 
267 	/* Switch to performance power mode */
268 	status = bma4xx->hw_ops->update_reg(dev, BMA4XX_REG_ACCEL_CONFIG, BMA4XX_BIT_ACC_PERF_MODE,
269 					    BMA4XX_BIT_ACC_PERF_MODE);
270 	if (status) {
271 		LOG_ERR("Could not enable performance power save mode: %d", status);
272 		return status;
273 	}
274 
275 	/* Enable accelerometer */
276 	status = bma4xx->hw_ops->update_reg(dev, BMA4XX_REG_POWER_CTRL, BMA4XX_BIT_ACC_EN,
277 					    BMA4XX_BIT_ACC_EN);
278 	if (status) {
279 		LOG_ERR("Could not enable accel: %d", status);
280 		return status;
281 	}
282 
283 	return status;
284 }
285 
286 /*
287  * Sample fetch and conversion
288  */
289 
290 /**
291  * @brief Read accelerometer data from the BMA4xx
292  */
bma4xx_sample_fetch(const struct device * dev,int16_t * x,int16_t * y,int16_t * z)293 static int bma4xx_sample_fetch(const struct device *dev, int16_t *x, int16_t *y, int16_t *z)
294 {
295 	struct bma4xx_data *bma4xx = dev->data;
296 	uint8_t read_data[6];
297 	int status;
298 
299 	/* Burst read regs DATA_8 through DATA_13, which holds the accel readings */
300 	status = bma4xx->hw_ops->read_data(dev, BMA4XX_REG_DATA_8, (uint8_t *)&read_data,
301 					   BMA4XX_REG_DATA_13 - BMA4XX_REG_DATA_8 + 1);
302 	if (status < 0) {
303 		LOG_ERR("Cannot read accel data: %d", status);
304 		return status;
305 	}
306 
307 	LOG_DBG("Raw values [0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x]", read_data[0],
308 		read_data[1], read_data[2], read_data[3], read_data[4], read_data[5]);
309 	/* Values in accel_data[N] are left-aligned and will read 16x actual */
310 	*x = ((int16_t)read_data[1] << 4) | FIELD_GET(GENMASK(7, 4), read_data[0]);
311 	*y = ((int16_t)read_data[3] << 4) | FIELD_GET(GENMASK(7, 4), read_data[2]);
312 	*z = ((int16_t)read_data[5] << 4) | FIELD_GET(GENMASK(7, 4), read_data[4]);
313 
314 	LOG_DBG("XYZ reg vals are %d, %d, %d", *x, *y, *z);
315 
316 	return 0;
317 }
318 
319 #ifdef CONFIG_BMA4XX_TEMPERATURE
320 /**
321  * @brief Read temperature register on BMA4xx
322  */
bma4xx_temp_fetch(const struct device * dev,int8_t * temp)323 static int bma4xx_temp_fetch(const struct device *dev, int8_t *temp)
324 {
325 	struct bma4xx_data *bma4xx = dev->data;
326 	int status;
327 
328 	status = bma4xx->hw_ops->read_reg(dev, BMA4XX_REG_TEMPERATURE, temp);
329 	if (status) {
330 		LOG_ERR("could not read temp reg: %d", status);
331 		return status;
332 	}
333 
334 	LOG_DBG("temp reg val is %d", *temp);
335 	return 0;
336 }
337 #endif
338 
339 /*
340  * RTIO submit and encoding
341  */
342 
bma4xx_submit_one_shot(const struct device * dev,struct rtio_iodev_sqe * iodev_sqe)343 static void bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe)
344 {
345 	struct bma4xx_data *bma4xx = dev->data;
346 
347 	const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data;
348 	const struct sensor_chan_spec *const channels = cfg->channels;
349 	const size_t num_channels = cfg->count;
350 
351 	uint32_t min_buf_len = sizeof(struct bma4xx_encoded_data);
352 	struct bma4xx_encoded_data *edata;
353 	uint8_t *buf;
354 	uint32_t buf_len;
355 	int rc;
356 
357 	/* Get the buffer for the frame, it may be allocated dynamically by the rtio context */
358 	rc = rtio_sqe_rx_buf(iodev_sqe, min_buf_len, min_buf_len, &buf, &buf_len);
359 	if (rc != 0) {
360 		LOG_ERR("Failed to get a read buffer of size %u bytes", min_buf_len);
361 		rtio_iodev_sqe_err(iodev_sqe, rc);
362 		return;
363 	}
364 
365 	/* Prepare response */
366 	edata = (struct bma4xx_encoded_data *)buf;
367 	edata->header.is_fifo = false;
368 	edata->header.accel_fs = bma4xx->accel_fs_range;
369 	edata->header.timestamp = k_ticks_to_ns_floor64(k_uptime_ticks());
370 	edata->has_accel = 0;
371 	edata->has_temp = 0;
372 
373 	/* Determine what channels we need to fetch */
374 	for (int i = 0; i < num_channels; i++) {
375 		if (channels[i].chan_idx != 0) {
376 			LOG_ERR("Only channel index 0 supported");
377 			rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP);
378 			return;
379 		}
380 		switch (channels[i].chan_type) {
381 		case SENSOR_CHAN_ALL:
382 			edata->has_accel = 1;
383 #ifdef CONFIG_BMA4XX_TEMPERATURE
384 			edata->has_temp = 1;
385 #endif /* CONFIG_BMA4XX_TEMPERATURE */
386 			break;
387 		case SENSOR_CHAN_ACCEL_X:
388 		case SENSOR_CHAN_ACCEL_Y:
389 		case SENSOR_CHAN_ACCEL_Z:
390 		case SENSOR_CHAN_ACCEL_XYZ:
391 			edata->has_accel = 1;
392 			break;
393 #ifdef CONFIG_BMA4XX_TEMPERATURE
394 		case SENSOR_CHAN_DIE_TEMP:
395 			edata->has_temp = 1;
396 			break;
397 #endif /* CONFIG_BMA4XX_TEMPERATURE */
398 		default:
399 			LOG_ERR("Requested unsupported channel type %d, idx %d",
400 				channels[i].chan_type, channels[i].chan_idx);
401 			rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP);
402 			return;
403 		}
404 	}
405 
406 	if (edata->has_accel) {
407 		rc = bma4xx_sample_fetch(dev, &edata->accel_xyz[0], &edata->accel_xyz[1],
408 					 &edata->accel_xyz[2]);
409 		if (rc != 0) {
410 			LOG_ERR("Failed to fetch accel samples");
411 			rtio_iodev_sqe_err(iodev_sqe, rc);
412 			return;
413 		}
414 	}
415 
416 #ifdef CONFIG_BMA4XX_TEMPERATURE
417 	if (edata->has_temp) {
418 		rc = bma4xx_temp_fetch(dev, &edata->temp);
419 		if (rc != 0) {
420 			LOG_ERR("Failed to fetch temp sample");
421 			rtio_iodev_sqe_err(iodev_sqe, rc);
422 			return;
423 		}
424 	}
425 #endif /* CONFIG_BMA4XX_TEMPERATURE */
426 
427 	rtio_iodev_sqe_ok(iodev_sqe, 0);
428 }
429 
bma4xx_submit_sync(struct rtio_iodev_sqe * iodev_sqe)430 static void bma4xx_submit_sync(struct rtio_iodev_sqe *iodev_sqe)
431 {
432 	const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data;
433 	const struct device *dev = cfg->sensor;
434 
435 	/* TODO: Add streaming support */
436 	if (!cfg->is_streaming) {
437 		bma4xx_submit_one_shot(dev, iodev_sqe);
438 	} else {
439 		rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP);
440 	}
441 }
442 
bma4xx_submit(const struct device * dev,struct rtio_iodev_sqe * iodev_sqe)443 static void bma4xx_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe)
444 {
445 	struct rtio_work_req *req = rtio_work_req_alloc();
446 
447 	if (req == NULL) {
448 		LOG_ERR("RTIO work item allocation failed. Consider to increase "
449 			"CONFIG_RTIO_WORKQ_POOL_ITEMS.");
450 		rtio_iodev_sqe_err(iodev_sqe, -ENOMEM);
451 		return;
452 	}
453 
454 	rtio_work_req_submit(req, iodev_sqe, bma4xx_submit_sync);
455 }
456 
457 /*
458  * RTIO decoder
459  */
460 
bma4xx_decoder_get_frame_count(const uint8_t * buffer,struct sensor_chan_spec ch,uint16_t * frame_count)461 static int bma4xx_decoder_get_frame_count(const uint8_t *buffer, struct sensor_chan_spec ch,
462 					  uint16_t *frame_count)
463 {
464 	const struct bma4xx_encoded_data *edata = (const struct bma4xx_encoded_data *)buffer;
465 	const struct bma4xx_decoder_header *header = &edata->header;
466 
467 	if (ch.chan_idx != 0) {
468 		return -ENOTSUP;
469 	}
470 
471 	if (!header->is_fifo) {
472 		switch (ch.chan_type) {
473 		case SENSOR_CHAN_ACCEL_X:
474 		case SENSOR_CHAN_ACCEL_Y:
475 		case SENSOR_CHAN_ACCEL_Z:
476 		case SENSOR_CHAN_ACCEL_XYZ:
477 			*frame_count = edata->has_accel ? 1 : 0;
478 			return 0;
479 		case SENSOR_CHAN_DIE_TEMP:
480 			*frame_count = edata->has_temp ? 1 : 0;
481 			return 0;
482 		default:
483 			return -ENOTSUP;
484 		}
485 		return 0;
486 	}
487 
488 	/* FIFO (streaming) mode operation is not yet supported */
489 	return -ENOTSUP;
490 }
491 
bma4xx_decoder_get_size_info(struct sensor_chan_spec ch,size_t * base_size,size_t * frame_size)492 static int bma4xx_decoder_get_size_info(struct sensor_chan_spec ch, size_t *base_size,
493 					size_t *frame_size)
494 {
495 	switch (ch.chan_type) {
496 	case SENSOR_CHAN_ACCEL_X:
497 	case SENSOR_CHAN_ACCEL_Y:
498 	case SENSOR_CHAN_ACCEL_Z:
499 	case SENSOR_CHAN_ACCEL_XYZ:
500 		*base_size = sizeof(struct sensor_three_axis_data);
501 		*frame_size = sizeof(struct sensor_three_axis_sample_data);
502 		return 0;
503 	case SENSOR_CHAN_DIE_TEMP:
504 		*base_size = sizeof(struct sensor_q31_data);
505 		*frame_size = sizeof(struct sensor_q31_sample_data);
506 		return 0;
507 	default:
508 		return -ENOTSUP;
509 	}
510 }
511 
bma4xx_get_shift(struct sensor_chan_spec ch,uint8_t accel_fs,int8_t * shift)512 static int bma4xx_get_shift(struct sensor_chan_spec ch, uint8_t accel_fs, int8_t *shift)
513 {
514 	switch (ch.chan_type) {
515 	case SENSOR_CHAN_ACCEL_X:
516 	case SENSOR_CHAN_ACCEL_Y:
517 	case SENSOR_CHAN_ACCEL_Z:
518 	case SENSOR_CHAN_ACCEL_XYZ:
519 		switch (accel_fs) {
520 		case BMA4XX_RANGE_2G:
521 			/* 2 G's = 19.62 m/s^2. Use shift of 5 (+/-32) */
522 			*shift = 5;
523 			return 0;
524 		case BMA4XX_RANGE_4G:
525 			*shift = 6;
526 			return 0;
527 		case BMA4XX_RANGE_8G:
528 			*shift = 7;
529 			return 0;
530 		case BMA4XX_RANGE_16G:
531 			*shift = 8;
532 			return 0;
533 		default:
534 			return -EINVAL;
535 		}
536 	case SENSOR_CHAN_DIE_TEMP:
537 		*shift = BMA4XX_TEMP_SHIFT;
538 		return 0;
539 	default:
540 		return -EINVAL;
541 	}
542 }
543 
bma4xx_convert_raw_accel_to_q31(int16_t raw_val,q31_t * out)544 static void bma4xx_convert_raw_accel_to_q31(int16_t raw_val, q31_t *out)
545 {
546 	/* The full calculation is (assuming floating math):
547 	 *   value_ms2 = raw_value * range * 9.8065 / BIT(11)
548 	 * We can treat 'range * 9.8065' as a scale, the scale is calculated by first getting 1g
549 	 * represented as a q31 value with the same shift as our result:
550 	 *   1g = (9.8065 * BIT(31)) >> shift
551 	 * Next, we need to multiply it by our range in g, which for this driver is one of
552 	 * [2, 4, 8, 16] and maps to a left shift of [1, 2, 3, 4]:
553 	 *   1g <<= log2(range)
554 	 * Note we used a right shift by 'shift' and left shift by log2(range). 'shift' is
555 	 * [5, 6, 7, 8] for range values [2, 4, 8, 16] since it's the final shift in m/s2. It is
556 	 * calculated via:
557 	 *   shift = ceil(log2(range * 9.8065))
558 	 * This means that we can shorten the above 1g alterations to:
559 	 *   1g = (1g >> ceil(log2(range * 9.8065))) << log2(range)
560 	 * For the range values [2, 4, 8, 16], the following is true:
561 	 *   (x >> ceil(log2(range * 9.8065))) << log2(range)
562 	 *   = x >> 4
563 	 * Since the range cancels out in the right and left shift, we've now reduced the following:
564 	 *   range * 9.8065 = 9.8065 * BIT(31 - 4)
565 	 * All that's left is to divide by the bma4xx's maximum range BIT(11).
566 	 */
567 	const int64_t scale = (int64_t)(9.8065 * BIT64(31 - 4));
568 
569 	*out = CLAMP(((int64_t)raw_val * scale) >> 11, INT32_MIN, INT32_MAX);
570 }
571 
572 #ifdef CONFIG_BMA4XX_TEMPERATURE
573 /**
574  * @brief Convert the 8-bit temp register value into a Q31 celsius value
575  */
bma4xx_convert_raw_temp_to_q31(int8_t raw_val,q31_t * out)576 static void bma4xx_convert_raw_temp_to_q31(int8_t raw_val, q31_t *out)
577 {
578 	/* Value of 0 equals 23 degrees C. Each bit count equals 1 degree C */
579 
580 	int64_t intermediate =
581 		((int64_t)raw_val + 23) * ((int64_t)INT32_MAX + 1) / (1 << BMA4XX_TEMP_SHIFT);
582 
583 	*out = CLAMP(intermediate, INT32_MIN, INT32_MAX);
584 }
585 #endif /* CONFIG_BMA4XX_TEMPERATURE */
586 
bma4xx_one_shot_decode(const uint8_t * buffer,struct sensor_chan_spec ch,uint32_t * fit,uint16_t max_count,void * data_out)587 static int bma4xx_one_shot_decode(const uint8_t *buffer, struct sensor_chan_spec ch,
588 				  uint32_t *fit, uint16_t max_count, void *data_out)
589 {
590 	const struct bma4xx_encoded_data *edata = (const struct bma4xx_encoded_data *)buffer;
591 	const struct bma4xx_decoder_header *header = &edata->header;
592 	int rc;
593 
594 	if (*fit != 0) {
595 		return 0;
596 	}
597 	if (max_count == 0 || ch.chan_idx != 0) {
598 		return -EINVAL;
599 	}
600 
601 	switch (ch.chan_type) {
602 	case SENSOR_CHAN_ACCEL_X:
603 	case SENSOR_CHAN_ACCEL_Y:
604 	case SENSOR_CHAN_ACCEL_Z:
605 	case SENSOR_CHAN_ACCEL_XYZ: {
606 		if (!edata->has_accel) {
607 			return -ENODATA;
608 		}
609 
610 		struct sensor_three_axis_data *out = (struct sensor_three_axis_data *)data_out;
611 
612 		out->header.base_timestamp_ns = edata->header.timestamp;
613 		out->header.reading_count = 1;
614 		rc = bma4xx_get_shift((struct sensor_chan_spec){.chan_type = SENSOR_CHAN_ACCEL_XYZ,
615 								.chan_idx = 0},
616 				      header->accel_fs, &out->shift);
617 		if (rc != 0) {
618 			return -EINVAL;
619 		}
620 
621 		bma4xx_convert_raw_accel_to_q31(edata->accel_xyz[0], &out->readings[0].x);
622 		bma4xx_convert_raw_accel_to_q31(edata->accel_xyz[1], &out->readings[0].y);
623 		bma4xx_convert_raw_accel_to_q31(edata->accel_xyz[2], &out->readings[0].z);
624 
625 		*fit = 1;
626 		return 1;
627 	}
628 #ifdef CONFIG_BMA4XX_TEMPERATURE
629 	case SENSOR_CHAN_DIE_TEMP: {
630 		if (!edata->has_temp) {
631 			return -ENODATA;
632 		}
633 
634 		struct sensor_q31_data *out = (struct sensor_q31_data *)data_out;
635 
636 		out->header.base_timestamp_ns = edata->header.timestamp;
637 		out->header.reading_count = 1;
638 		rc = bma4xx_get_shift(SENSOR_CHAN_DIE_TEMP, 0, &out->shift);
639 		if (rc != 0) {
640 			return -EINVAL;
641 		}
642 
643 		bma4xx_convert_raw_temp_to_q31(edata->temp, &out->readings[0].temperature);
644 
645 		*fit = 1;
646 		return 1;
647 	}
648 #endif /* CONFIG_BMA4XX_TEMPERATURE */
649 	default:
650 		return -EINVAL;
651 	}
652 }
653 
bma4xx_decoder_decode(const uint8_t * buffer,struct sensor_chan_spec ch,uint32_t * fit,uint16_t max_count,void * data_out)654 static int bma4xx_decoder_decode(const uint8_t *buffer, struct sensor_chan_spec ch,
655 				 uint32_t *fit, uint16_t max_count,
656 				 void *data_out)
657 {
658 	const struct bma4xx_decoder_header *header = (const struct bma4xx_decoder_header *)buffer;
659 
660 	if (header->is_fifo) {
661 		/* FIFO (streaming) mode operation is not yet supported */
662 		return -ENOTSUP;
663 	}
664 
665 	return bma4xx_one_shot_decode(buffer, ch, fit, max_count, data_out);
666 }
667 
668 SENSOR_DECODER_API_DT_DEFINE() = {
669 	.get_frame_count = bma4xx_decoder_get_frame_count,
670 	.get_size_info = bma4xx_decoder_get_size_info,
671 	.decode = bma4xx_decoder_decode,
672 };
673 
bma4xx_get_decoder(const struct device * dev,const struct sensor_decoder_api ** decoder)674 static int bma4xx_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder)
675 {
676 	ARG_UNUSED(dev);
677 	*decoder = &SENSOR_DECODER_NAME();
678 
679 	return 0;
680 }
681 
682 /*
683  * Sensor driver API
684  */
685 
686 static DEVICE_API(sensor, bma4xx_driver_api) = {
687 	.attr_set = bma4xx_attr_set,
688 	.submit = bma4xx_submit,
689 	.get_decoder = bma4xx_get_decoder,
690 };
691 
692 /*
693  * Device instantiation macros
694  */
695 
696 /* Initializes a struct bma4xx_config for an instance on a SPI bus.
697  * SPI operation is not currently supported.
698  */
699 
700 #define BMA4XX_CONFIG_SPI(inst)                                                                    \
701 	{                                                                                          \
702 		.bus_cfg.spi = SPI_DT_SPEC_INST_GET(inst, 0, 0), .bus_init = &bma_spi_init,        \
703 	}
704 
705 /* Initializes a struct bma4xx_config for an instance on an I2C bus. */
706 #define BMA4XX_CONFIG_I2C(inst)                                                                    \
707 	{                                                                                          \
708 		.bus_cfg.i2c = I2C_DT_SPEC_INST_GET(inst), .bus_init = &bma4xx_i2c_init,           \
709 	}
710 
711 /*
712  * Main instantiation macro, which selects the correct bus-specific
713  * instantiation macros for the instance.
714  */
715 #define BMA4XX_DEFINE(inst)                                                                        \
716 	static struct bma4xx_data bma4xx_data_##inst;                                              \
717 	static const struct bma4xx_config bma4xx_config_##inst = COND_CODE_1(                      \
718 		DT_INST_ON_BUS(inst, spi), (BMA4XX_CONFIG_SPI(inst)), (BMA4XX_CONFIG_I2C(inst)));  \
719                                                                                                    \
720 	SENSOR_DEVICE_DT_INST_DEFINE(inst, bma4xx_chip_init, NULL, &bma4xx_data_##inst,            \
721 				     &bma4xx_config_##inst, POST_KERNEL,                           \
722 				     CONFIG_SENSOR_INIT_PRIORITY, &bma4xx_driver_api);
723 
724 DT_INST_FOREACH_STATUS_OKAY(BMA4XX_DEFINE)
725