1 /* bmm150.c - Driver for Bosch BMM150 Geomagnetic Sensor */
2
3 /*
4 * Copyright (c) 2017 Intel Corporation
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <zephyr/logging/log.h>
10 #include "bmm150.h"
11
12 LOG_MODULE_REGISTER(BMM150, CONFIG_SENSOR_LOG_LEVEL);
13
14 static const struct {
15 int freq;
16 uint8_t reg_val;
17 } bmm150_samp_freq_table[] = { { 2, 0x01 },
18 { 6, 0x02 },
19 { 8, 0x03 },
20 { 10, 0x00 },
21 { 15, 0x04 },
22 { 20, 0x05 },
23 { 25, 0x06 },
24 { 30, 0x07 } };
25
26 static const struct bmm150_preset {
27 uint8_t rep_xy;
28 uint8_t rep_z;
29 uint8_t odr;
30 } bmm150_presets_table[] = {
31 [BMM150_LOW_POWER_PRESET] = { 3, 3, 10 },
32 [BMM150_REGULAR_PRESET] = { 9, 15, 10 },
33 [BMM150_ENHANCED_REGULAR_PRESET] = { 15, 27, 10 },
34 [BMM150_HIGH_ACCURACY_PRESET] = { 47, 83, 20 }
35 };
36
bmm150_bus_check(const struct device * dev)37 static inline int bmm150_bus_check(const struct device *dev)
38 {
39 const struct bmm150_config *cfg = dev->config;
40
41 return cfg->bus_io->check(&cfg->bus);
42 }
43
bmm150_reg_read(const struct device * dev,uint8_t start,uint8_t * buf,int size)44 static inline int bmm150_reg_read(const struct device *dev,
45 uint8_t start, uint8_t *buf, int size)
46 {
47 const struct bmm150_config *cfg = dev->config;
48
49 return cfg->bus_io->read(&cfg->bus, start, buf, size);
50 }
51
bmm150_reg_write(const struct device * dev,uint8_t reg,uint8_t val)52 static inline int bmm150_reg_write(const struct device *dev, uint8_t reg,
53 uint8_t val)
54 {
55 const struct bmm150_config *cfg = dev->config;
56
57 return cfg->bus_io->write(&cfg->bus, reg, val);
58 }
59
bmm150_reg_update_byte(const struct device * dev,uint8_t reg,uint8_t mask,uint8_t value)60 int bmm150_reg_update_byte(const struct device *dev, uint8_t reg,
61 uint8_t mask, uint8_t value)
62 {
63 int ret = 0;
64 uint8_t old_value, new_value;
65
66 ret = bmm150_reg_read(dev, reg, &old_value, 1);
67
68 if (ret < 0) {
69 goto failed;
70 }
71
72 new_value = (old_value & ~mask) | (value & mask);
73
74 if (new_value == old_value) {
75 return 0;
76 }
77
78 return bmm150_reg_write(dev, reg, new_value);
79 failed:
80 return ret;
81 }
82
bmm150_set_power_mode(const struct device * dev,enum bmm150_power_modes mode,int state)83 static int bmm150_set_power_mode(const struct device *dev,
84 enum bmm150_power_modes mode,
85 int state)
86 {
87 switch (mode) {
88 case BMM150_POWER_MODE_SUSPEND:
89 if (bmm150_reg_update_byte(dev,
90 BMM150_REG_POWER,
91 BMM150_MASK_POWER_CTL,
92 !state) < 0) {
93 return -EIO;
94 }
95 k_busy_wait(USEC_PER_MSEC * 5U);
96
97 return 0;
98 case BMM150_POWER_MODE_SLEEP:
99 return bmm150_reg_update_byte(dev,
100 BMM150_REG_OPMODE_ODR,
101 BMM150_MASK_OPMODE,
102 BMM150_MODE_SLEEP <<
103 BMM150_SHIFT_OPMODE);
104 break;
105 case BMM150_POWER_MODE_NORMAL:
106 return bmm150_reg_update_byte(dev,
107 BMM150_REG_OPMODE_ODR,
108 BMM150_MASK_OPMODE,
109 BMM150_MODE_NORMAL <<
110 BMM150_SHIFT_OPMODE);
111 break;
112 }
113
114 return -ENOTSUP;
115
116 }
117
bmm150_set_odr(const struct device * dev,uint8_t val)118 static int bmm150_set_odr(const struct device *dev, uint8_t val)
119 {
120 uint8_t i;
121
122 for (i = 0U; i < ARRAY_SIZE(bmm150_samp_freq_table); ++i) {
123 if (val <= bmm150_samp_freq_table[i].freq) {
124 return bmm150_reg_update_byte(dev,
125 BMM150_REG_OPMODE_ODR,
126 BMM150_MASK_ODR,
127 (bmm150_samp_freq_table[i].reg_val <<
128 BMM150_SHIFT_ODR));
129 }
130 }
131 return -ENOTSUP;
132 }
133
134 #if defined(BMM150_SET_ATTR)
bmm150_read_rep_xy(const struct device * dev)135 static int bmm150_read_rep_xy(const struct device *dev)
136 {
137 struct bmm150_data *data = dev->driver->data;
138 const struct bmm150_config *config = dev->config;
139 uint8_t reg_val;
140
141 if (bmm150_reg_read(dev, BMM150_REG_REP_XY, ®_val, 1) < 0) {
142 return -EIO;
143 }
144
145 data->rep_xy = BMM150_REGVAL_TO_REPXY((uint8_t)(reg_val));
146
147 return 0;
148 }
149
bmm150_read_rep_z(const struct device * dev)150 static int bmm150_read_rep_z(const struct device *dev)
151 {
152 struct bmm150_data *data = dev->data;
153 const struct bmm150_config *config = dev->config;
154 uint8_t reg_val;
155
156 if (bmm150_reg_read(dev, BMM150_REG_REP_Z, ®_val, 1) < 0) {
157 return -EIO;
158 }
159
160 data->rep_z = BMM150_REGVAL_TO_REPZ((int)(reg_val));
161
162 return 0;
163 }
164
bmm150_compute_max_odr(const struct device * dev,int rep_xy,int rep_z,int * max_odr)165 static int bmm150_compute_max_odr(const struct device *dev, int rep_xy,
166 int rep_z, int *max_odr)
167 {
168 struct bmm150_data *data = dev->data;
169
170 if (rep_xy == 0) {
171 if (data->rep_xy <= 0) {
172 if (bmm150_read_rep_xy(dev) < 0) {
173 return -EIO;
174 }
175 }
176 rep_xy = data->rep_xy;
177 }
178
179 if (rep_z == 0) {
180 if (data->rep_z <= 0) {
181 if (bmm150_read_rep_z(dev) < 0) {
182 return -EIO;
183 }
184 }
185 rep_z = data->rep_z;
186 }
187
188 /* Equation reference Datasheet 4.2.4 */
189 *max_odr = 1000000 / (145 * rep_xy + 500 * rep_z + 980);
190
191 return 0;
192 }
193 #endif
194
195 #if defined(BMM150_SET_ATTR_REP)
bmm150_read_odr(const struct device * dev)196 static int bmm150_read_odr(const struct device *dev)
197 {
198 struct bmm150_data *data = dev->data;
199 const struct bmm150_config *config = dev->config;
200 uint8_t i, odr_val, reg_val;
201
202 if (bmm150_reg_read(dev, BMM150_REG_OPMODE_ODR, ®_val, 1) < 0) {
203 return -EIO;
204 }
205
206 odr_val = (reg_val & BMM150_MASK_ODR) >> BMM150_SHIFT_ODR;
207
208 for (i = 0U; i < ARRAY_SIZE(bmm150_samp_freq_table); ++i) {
209 if (bmm150_samp_freq_table[i].reg_val == odr_val) {
210 data->odr = bmm150_samp_freq_table[i].freq;
211 return 0;
212 }
213 }
214
215 return -ENOTSUP;
216 }
217 #endif
218
219 #if defined(CONFIG_BMM150_SAMPLING_REP_XY)
bmm150_write_rep_xy(const struct device * dev,int val)220 static int bmm150_write_rep_xy(const struct device *dev, int val)
221 {
222 struct bmm150_data *data = dev->data;
223 const struct bmm150_config *config = dev->config;
224
225 if (bmm150_reg_update_byte(dev,
226 BMM150_REG_REP_XY,
227 BMM150_REG_REP_DATAMASK,
228 BMM150_REPXY_TO_REGVAL(val)) < 0) {
229 return -EIO;
230 }
231
232 data->rep_xy = val;
233
234 return 0;
235 }
236 #endif
237
238 #if defined(CONFIG_BMM150_SAMPLING_REP_Z)
bmm150_write_rep_z(const struct device * dev,int val)239 static int bmm150_write_rep_z(const struct device *dev, int val)
240 {
241 struct bmm150_data *data = dev->data;
242 const struct bmm150_config *config = dev->config;
243
244 if (bmm150_reg_update_byte(dev,
245 BMM150_REG_REP_Z,
246 BMM150_REG_REP_DATAMASK,
247 BMM150_REPZ_TO_REGVAL(val)) < 0) {
248 return -EIO;
249 }
250
251 data->rep_z = val;
252
253 return 0;
254 }
255 #endif
256
257 /* Reference Datasheet 4.3.2 */
bmm150_compensate_xy(struct bmm150_trim_regs * tregs,int16_t xy,uint16_t rhall,bool is_x)258 static int32_t bmm150_compensate_xy(struct bmm150_trim_regs *tregs,
259 int16_t xy, uint16_t rhall, bool is_x)
260 {
261 int8_t txy1, txy2;
262 int16_t val;
263 uint16_t prevalue;
264 int32_t temp1, temp2, temp3;
265
266 if (xy == BMM150_XY_OVERFLOW_VAL) {
267 return INT32_MIN;
268 }
269
270 if (!rhall) {
271 rhall = tregs->xyz1;
272 }
273
274 if (is_x) {
275 txy1 = tregs->x1;
276 txy2 = tregs->x2;
277 } else {
278 txy1 = tregs->y1;
279 txy2 = tregs->y2;
280 }
281
282 prevalue = (uint16_t)((((int32_t)tregs->xyz1) << 14) / rhall);
283
284 val = (int16_t)((prevalue) - ((uint16_t)0x4000));
285
286 temp1 = (((int32_t)tregs->xy2) * ((((int32_t)val) * ((int32_t)val)) >> 7));
287
288 temp2 = ((int32_t)val) * ((int32_t)(((int16_t)tregs->xy1) << 7));
289
290 temp3 = (((((temp1 + temp2) >> 9) +
291 ((int32_t)0x100000)) * ((int32_t)(((int16_t)txy2) +
292 ((int16_t)0xA0)))) >> 12);
293
294 val = ((int16_t)((((int32_t)xy) * temp3) >> 13)) + (((int16_t)txy1) << 3);
295
296 return (int32_t)val;
297 }
298
bmm150_compensate_z(struct bmm150_trim_regs * tregs,int16_t z,uint16_t rhall)299 static int32_t bmm150_compensate_z(struct bmm150_trim_regs *tregs,
300 int16_t z, uint16_t rhall)
301 {
302 int32_t val, temp1, temp2;
303 int16_t temp3;
304
305 if (z == BMM150_Z_OVERFLOW_VAL) {
306 return INT32_MIN;
307 }
308
309 temp1 = (((int32_t)(z - tregs->z4)) << 15);
310
311 temp2 = ((((int32_t)tregs->z3) *
312 ((int32_t)(((int16_t)rhall) - ((int16_t)tregs->xyz1)))) >> 2);
313
314 temp3 = ((int16_t)(((((int32_t)tregs->z1) *
315 ((((int16_t)rhall) << 1))) + (1 << 15)) >> 16));
316
317 val = ((temp1 - temp2) / (tregs->z2 + temp3));
318
319 return val;
320 }
321
bmm150_sample_fetch(const struct device * dev,enum sensor_channel chan)322 static int bmm150_sample_fetch(const struct device *dev,
323 enum sensor_channel chan)
324 {
325
326 struct bmm150_data *drv_data = dev->data;
327 uint16_t values[BMM150_AXIS_XYZR_MAX];
328 int16_t raw_x, raw_y, raw_z;
329 uint16_t rhall;
330
331 __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL ||
332 chan == SENSOR_CHAN_MAGN_XYZ);
333
334 if (bmm150_reg_read(dev, BMM150_REG_X_L, (uint8_t *)values, sizeof(values)) < 0) {
335 LOG_ERR("failed to read sample");
336 return -EIO;
337 }
338
339 raw_x = (int16_t)sys_le16_to_cpu(values[BMM150_AXIS_X]) >>
340 BMM150_SHIFT_XY_L;
341 raw_y = (int16_t)sys_le16_to_cpu(values[BMM150_AXIS_Y]) >>
342 BMM150_SHIFT_XY_L;
343 raw_z = (int16_t)sys_le16_to_cpu(values[BMM150_AXIS_Z]) >>
344 BMM150_SHIFT_Z_L;
345
346 rhall = sys_le16_to_cpu(values[BMM150_RHALL]) >>
347 BMM150_SHIFT_RHALL_L;
348
349 drv_data->sample_x = bmm150_compensate_xy(&drv_data->tregs,
350 raw_x, rhall, true);
351 drv_data->sample_y = bmm150_compensate_xy(&drv_data->tregs,
352 raw_y, rhall, false);
353 drv_data->sample_z = bmm150_compensate_z(&drv_data->tregs,
354 raw_z, rhall);
355
356 return 0;
357 }
358
359 /*
360 * Datasheet specify raw units are 16 LSB/uT and this function converts it to
361 * Gauss
362 */
bmm150_convert(struct sensor_value * val,int raw_val)363 static void bmm150_convert(struct sensor_value *val, int raw_val)
364 {
365 /* val = raw_val / 1600 */
366 val->val1 = raw_val / 1600;
367 val->val2 = ((int32_t)raw_val * (1000000 / 1600)) % 1000000;
368 }
369
bmm150_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)370 static int bmm150_channel_get(const struct device *dev,
371 enum sensor_channel chan,
372 struct sensor_value *val)
373 {
374 struct bmm150_data *drv_data = dev->data;
375
376 switch (chan) {
377 case SENSOR_CHAN_MAGN_X:
378 bmm150_convert(val, drv_data->sample_x);
379 break;
380 case SENSOR_CHAN_MAGN_Y:
381 bmm150_convert(val, drv_data->sample_y);
382 break;
383 case SENSOR_CHAN_MAGN_Z:
384 bmm150_convert(val, drv_data->sample_z);
385 break;
386 case SENSOR_CHAN_MAGN_XYZ:
387 bmm150_convert(val, drv_data->sample_x);
388 bmm150_convert(val + 1, drv_data->sample_y);
389 bmm150_convert(val + 2, drv_data->sample_z);
390 break;
391 default:
392 return -EINVAL;
393 }
394
395 return 0;
396 }
397
398 #if defined(BMM150_SET_ATTR_REP)
bmm150_attr_set_rep(const struct device * dev,enum sensor_channel chan,const struct sensor_value * val)399 static inline int bmm150_attr_set_rep(const struct device *dev,
400 enum sensor_channel chan,
401 const struct sensor_value *val)
402 {
403 struct bmm150_data *data = dev->data;
404 int max_odr;
405
406 switch (chan) {
407 #if defined(CONFIG_BMM150_SAMPLING_REP_XY)
408 case SENSOR_CHAN_MAGN_X:
409 case SENSOR_CHAN_MAGN_Y:
410 if (val->val1 < 1 || val->val1 > 511) {
411 return -EINVAL;
412 }
413
414 if (bmm150_compute_max_odr(dev, val->val1, 0,
415 &max_odr) < 0) {
416 return -EIO;
417 }
418
419 if (data->odr <= 0) {
420 if (bmm150_read_odr(dev) < 0) {
421 return -EIO;
422 }
423 }
424
425 if (data->odr > max_odr) {
426 return -EINVAL;
427 }
428
429 if (bmm150_write_rep_xy(dev, val->val1) < 0) {
430 return -EIO;
431 }
432 break;
433 #endif
434
435 #if defined(CONFIG_BMM150_SAMPLING_REP_Z)
436 case SENSOR_CHAN_MAGN_Z:
437 if (val->val1 < 1 || val->val1 > 256) {
438 return -EINVAL;
439 }
440
441 if (bmm150_compute_max_odr(dev, 0, val->val1,
442 &max_odr) < 0) {
443 return -EIO;
444 }
445
446 if (data->odr <= 0) {
447 if (bmm150_read_odr(dev) < 0) {
448 return -EIO;
449 }
450 }
451
452 if (data->odr > max_odr) {
453 return -EINVAL;
454 }
455
456 if (bmm150_write_rep_z(dev, val->val1) < 0) {
457 return -EIO;
458 }
459 break;
460 #endif
461 default:
462 return -EINVAL;
463 }
464
465 return 0;
466 }
467 #endif
468
469 #if defined(BMM150_SET_ATTR)
bmm150_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)470 static int bmm150_attr_set(const struct device *dev,
471 enum sensor_channel chan,
472 enum sensor_attribute attr,
473 const struct sensor_value *val)
474 {
475 struct bmm150_magn_data *data = dev->data;
476
477 switch (attr) {
478 #if defined(CONFIG_BMM150_SAMPLING_RATE_RUNTIME)
479 case SENSOR_ATTR_SAMPLING_FREQUENCY:
480 if (data->max_odr <= 0) {
481 if (bmm150_compute_max_odr(dev, 0, 0,
482 &data->max_odr) < 0) {
483 return -EIO;
484 }
485 }
486
487 if (data->max_odr < val->val1) {
488 LOG_ERR("not supported with current oversampling");
489 return -ENOTSUP;
490 }
491
492 if (bmm150_set_odr(dev, (uint8_t)(val->val1)) < 0) {
493 return -EIO;
494 }
495 break;
496 #endif
497 #if defined(BMM150_SET_ATTR_REP)
498 case SENSOR_ATTR_OVERSAMPLING:
499 bmm150_attr_set_rep(dev, chan, val);
500 break;
501 #endif
502 default:
503 return -EINVAL;
504 }
505
506 return 0;
507 }
508 #endif
509
510 static const struct sensor_driver_api bmm150_api_funcs = {
511 #if defined(BMM150_SET_ATTR)
512 .attr_set = bmm150_attr_set,
513 #endif
514 .sample_fetch = bmm150_sample_fetch,
515 .channel_get = bmm150_channel_get,
516 };
517
bmm150_init_chip(const struct device * dev)518 static int bmm150_init_chip(const struct device *dev)
519 {
520 struct bmm150_data *data = dev->data;
521 uint8_t chip_id;
522 struct bmm150_preset preset;
523
524 /* Soft reset chip */
525 if (bmm150_reg_update_byte(dev, BMM150_REG_POWER, BMM150_MASK_SOFT_RESET,
526 BMM150_SOFT_RESET) < 0) {
527 LOG_ERR("failed reset chip");
528 goto err_poweroff;
529 }
530
531 /* Sleep for 1ms after software reset */
532 k_sleep(K_MSEC(1));
533
534 /* Suspend mode to sleep mode */
535 if (bmm150_set_power_mode(dev, BMM150_POWER_MODE_SUSPEND, 0)
536 < 0) {
537 LOG_ERR("failed to bring up device from suspend mode");
538 return -EIO;
539 }
540
541 /* Sleep for 3ms from suspend to sleep mode */
542 k_sleep(K_MSEC(3));
543
544 /* Read chip ID */
545 if (bmm150_reg_read(dev, BMM150_REG_CHIP_ID, &chip_id, 1) < 0) {
546 LOG_ERR("failed reading chip id");
547 goto err_poweroff;
548 }
549
550 if (chip_id != BMM150_CHIP_ID_VAL) {
551 LOG_ERR("invalid chip id 0x%x", chip_id);
552 goto err_poweroff;
553 }
554
555 /* Setting preset mode */
556 preset = bmm150_presets_table[BMM150_DEFAULT_PRESET];
557 if (bmm150_set_odr(dev, preset.odr) < 0) {
558 LOG_ERR("failed to set ODR to %d",
559 preset.odr);
560 goto err_poweroff;
561 }
562
563 if (bmm150_reg_write(dev, BMM150_REG_REP_XY, BMM150_REPXY_TO_REGVAL(preset.rep_xy))
564 < 0) {
565 LOG_ERR("failed to set REP XY to %d",
566 preset.rep_xy);
567 goto err_poweroff;
568 }
569
570 if (bmm150_reg_write(dev, BMM150_REG_REP_Z, BMM150_REPZ_TO_REGVAL(preset.rep_z)) < 0) {
571 LOG_ERR("failed to set REP Z to %d",
572 preset.rep_z);
573 goto err_poweroff;
574 }
575
576 /* Set chip normal mode */
577 if (bmm150_set_power_mode(dev, BMM150_POWER_MODE_NORMAL, 1)
578 < 0) {
579 LOG_ERR("failed to power on device");
580 }
581
582 /* Reads the trim registers of the sensor */
583 if (bmm150_reg_read(dev, BMM150_REG_TRIM_START, (uint8_t *)&data->tregs,
584 sizeof(data->tregs)) < 0) {
585 LOG_ERR("failed to read trim regs");
586 goto err_poweroff;
587 }
588
589 data->rep_xy = 0;
590 data->rep_z = 0;
591 data->odr = 0;
592 data->max_odr = 0;
593 data->sample_x = 0;
594 data->sample_y = 0;
595 data->sample_z = 0;
596
597 data->tregs.xyz1 = sys_le16_to_cpu(data->tregs.xyz1);
598 data->tregs.z1 = sys_le16_to_cpu(data->tregs.z1);
599 data->tregs.z2 = sys_le16_to_cpu(data->tregs.z2);
600 data->tregs.z3 = sys_le16_to_cpu(data->tregs.z3);
601 data->tregs.z4 = sys_le16_to_cpu(data->tregs.z4);
602
603 return 0;
604
605 err_poweroff:
606 bmm150_set_power_mode(dev, BMM150_POWER_MODE_NORMAL, 0);
607 bmm150_set_power_mode(dev, BMM150_POWER_MODE_SUSPEND, 1);
608 return -EIO;
609 }
610
bmm150_init(const struct device * dev)611 static int bmm150_init(const struct device *dev)
612 {
613 int err = 0;
614
615 err = bmm150_bus_check(dev);
616 if (err < 0) {
617 LOG_DBG("bus check failed: %d", err);
618 return err;
619 }
620
621 if (bmm150_init_chip(dev) < 0) {
622 LOG_ERR("failed to initialize chip");
623 return -EIO;
624 }
625
626 return 0;
627 }
628
629 /* Initializes a struct bmm150_config for an instance on a SPI bus. */
630 #define BMM150_CONFIG_SPI(inst) \
631 .bus.spi = SPI_DT_SPEC_INST_GET(inst, BMM150_SPI_OPERATION, 0), \
632 .bus_io = &bmm150_bus_io_spi,
633
634 /* Initializes a struct bmm150_config for an instance on an I2C bus. */
635 #define BMM150_CONFIG_I2C(inst) \
636 .bus.i2c = I2C_DT_SPEC_INST_GET(inst), \
637 .bus_io = &bmm150_bus_io_i2c,
638
639 #define BMM150_BUS_CFG(inst) \
640 COND_CODE_1(DT_INST_ON_BUS(inst, i2c), \
641 (BMM150_CONFIG_I2C(inst)), \
642 (BMM150_CONFIG_SPI(inst)))
643
644 /*
645 * Main instantiation macro, which selects the correct bus-specific
646 * instantiation macros for the instance.
647 */
648 #define BMM150_DEFINE(inst) \
649 static struct bmm150_data bmm150_data_##inst; \
650 static const struct bmm150_config bmm150_config_##inst = { \
651 BMM150_BUS_CFG(inst) \
652 }; \
653 SENSOR_DEVICE_DT_INST_DEFINE(inst, \
654 bmm150_init, NULL, \
655 &bmm150_data_##inst, \
656 &bmm150_config_##inst, \
657 POST_KERNEL, \
658 CONFIG_SENSOR_INIT_PRIORITY, \
659 &bmm150_api_funcs);
660
661 /* Create the struct device for every status "okay" node in the devicetree. */
662 DT_INST_FOREACH_STATUS_OKAY(BMM150_DEFINE)
663