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, ®_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], ®_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, ®_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), ®_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