1 /* bmc150_magn.c - Driver for Bosch BMC150 magnetometer sensor */
2
3 /*
4 * Copyright (c) 2016 Intel Corporation
5 *
6 * This code is based on bmm050.c from:
7 * https://github.com/BoschSensortec/BMM050_driver
8 *
9 * SPDX-License-Identifier: Apache-2.0
10 */
11
12 #define DT_DRV_COMPAT bosch_bmc150_magn
13
14 #include <drivers/sensor.h>
15 #include <kernel.h>
16 #include <device.h>
17 #include <init.h>
18 #include <sys/byteorder.h>
19 #include <sys/__assert.h>
20
21 #include <drivers/gpio.h>
22 #include <logging/log.h>
23
24 #include "bmc150_magn.h"
25
26 LOG_MODULE_REGISTER(BMC150_MAGN, CONFIG_SENSOR_LOG_LEVEL);
27
28 static const struct {
29 int freq;
30 uint8_t reg_val;
31 } bmc150_magn_samp_freq_table[] = { {2, 0x01},
32 {6, 0x02},
33 {8, 0x03},
34 {10, 0x00},
35 {15, 0x04},
36 {20, 0x05},
37 {25, 0x06},
38 {30, 0x07} };
39
40 static const struct bmc150_magn_preset {
41 uint8_t rep_xy;
42 uint8_t rep_z;
43 uint8_t odr;
44 } bmc150_magn_presets_table[] = {
45 [LOW_POWER_PRESET] = {3, 3, 10},
46 [REGULAR_PRESET] = {9, 15, 10},
47 [ENHANCED_REGULAR_PRESET] = {15, 27, 10},
48 [HIGH_ACCURACY_PRESET] = {47, 83, 20}
49 };
50
bmc150_magn_set_power_mode(const struct device * dev,enum bmc150_magn_power_modes mode,int state)51 static int bmc150_magn_set_power_mode(const struct device *dev,
52 enum bmc150_magn_power_modes mode,
53 int state)
54 {
55 struct bmc150_magn_data *data = dev->data;
56 const struct bmc150_magn_config *config = dev->config;
57
58 switch (mode) {
59 case BMC150_MAGN_POWER_MODE_SUSPEND:
60 if (i2c_reg_update_byte(data->i2c_master,
61 config->i2c_slave_addr,
62 BMC150_MAGN_REG_POWER,
63 BMC150_MAGN_MASK_POWER_CTL,
64 !state) < 0) {
65 return -EIO;
66 }
67 k_busy_wait(USEC_PER_MSEC * 5U);
68
69 return 0;
70 case BMC150_MAGN_POWER_MODE_SLEEP:
71 return i2c_reg_update_byte(data->i2c_master,
72 config->i2c_slave_addr,
73 BMC150_MAGN_REG_OPMODE_ODR,
74 BMC150_MAGN_MASK_OPMODE,
75 BMC150_MAGN_MODE_SLEEP <<
76 BMC150_MAGN_SHIFT_OPMODE);
77 break;
78 case BMC150_MAGN_POWER_MODE_NORMAL:
79 return i2c_reg_update_byte(data->i2c_master,
80 config->i2c_slave_addr,
81 BMC150_MAGN_REG_OPMODE_ODR,
82 BMC150_MAGN_MASK_OPMODE,
83 BMC150_MAGN_MODE_NORMAL <<
84 BMC150_MAGN_SHIFT_OPMODE);
85 break;
86 }
87
88 return -ENOTSUP;
89 }
90
bmc150_magn_set_odr(const struct device * dev,uint8_t val)91 static int bmc150_magn_set_odr(const struct device *dev, uint8_t val)
92 {
93 struct bmc150_magn_data *data = dev->data;
94 const struct bmc150_magn_config *config = dev->config;
95 uint8_t i;
96
97 for (i = 0U; i < ARRAY_SIZE(bmc150_magn_samp_freq_table); ++i) {
98 if (val <= bmc150_magn_samp_freq_table[i].freq) {
99 return i2c_reg_update_byte(data->i2c_master,
100 config->i2c_slave_addr,
101 BMC150_MAGN_REG_OPMODE_ODR,
102 BMC150_MAGN_MASK_ODR,
103 bmc150_magn_samp_freq_table[i].
104 reg_val <<
105 BMC150_MAGN_SHIFT_ODR);
106 }
107 }
108
109 return -ENOTSUP;
110 }
111
112 #if defined(BMC150_MAGN_SET_ATTR)
bmc150_magn_read_rep_xy(const struct device * dev)113 static int bmc150_magn_read_rep_xy(const struct device *dev)
114 {
115 struct bmc150_magn_data *data = dev->data;
116 const struct bmc150_magn_config *config = dev->config;
117 uint8_t reg_val;
118
119 if (i2c_reg_read_byte(data->i2c_master, config->i2c_slave_addr,
120 BMC150_MAGN_REG_REP_XY, ®_val) < 0) {
121 return -EIO;
122 }
123
124 data->rep_xy = BMC150_MAGN_REGVAL_TO_REPXY((int)(reg_val));
125
126 return 0;
127 }
128
bmc150_magn_read_rep_z(const struct device * dev)129 static int bmc150_magn_read_rep_z(const struct device *dev)
130 {
131 struct bmc150_magn_data *data = dev->data;
132 const struct bmc150_magn_config *config = dev->config;
133 uint8_t reg_val;
134
135 if (i2c_reg_read_byte(data->i2c_master, config->i2c_slave_addr,
136 BMC150_MAGN_REG_REP_Z, ®_val) < 0) {
137 return -EIO;
138 }
139
140 data->rep_z = BMC150_MAGN_REGVAL_TO_REPZ((int)(reg_val));
141
142 return 0;
143 }
144
bmc150_magn_compute_max_odr(const struct device * dev,int rep_xy,int rep_z,int * max_odr)145 static int bmc150_magn_compute_max_odr(const struct device *dev, int rep_xy,
146 int rep_z, int *max_odr)
147 {
148 struct bmc150_magn_data *data = dev->data;
149
150 if (rep_xy == 0) {
151 if (data->rep_xy <= 0) {
152 if (bmc150_magn_read_rep_xy(dev) < 0) {
153 return -EIO;
154 }
155 }
156 rep_xy = data->rep_xy;
157 }
158
159 if (rep_z == 0) {
160 if (data->rep_z <= 0) {
161 if (bmc150_magn_read_rep_z(dev) < 0) {
162 return -EIO;
163 }
164 }
165 rep_z = data->rep_z;
166 }
167
168 *max_odr = 1000000 / (145 * rep_xy + 500 * rep_z + 980);
169
170 return 0;
171 }
172 #endif
173
174 #if defined(BMC150_MAGN_SET_ATTR_REP)
bmc150_magn_read_odr(const struct device * dev)175 static int bmc150_magn_read_odr(const struct device *dev)
176 {
177 struct bmc150_magn_data *data = dev->data;
178 const struct bmc150_magn_config *config = dev->config;
179 uint8_t i, odr_val, reg_val;
180
181 if (i2c_reg_read_byte(data->i2c_master, config->i2c_slave_addr,
182 BMC150_MAGN_REG_OPMODE_ODR, ®_val) < 0) {
183 return -EIO;
184 }
185
186 odr_val = (reg_val & BMC150_MAGN_MASK_ODR) >> BMC150_MAGN_SHIFT_ODR;
187
188 for (i = 0U; i < ARRAY_SIZE(bmc150_magn_samp_freq_table); ++i) {
189 if (bmc150_magn_samp_freq_table[i].reg_val == odr_val) {
190 data->odr = bmc150_magn_samp_freq_table[i].freq;
191 return 0;
192 }
193 }
194
195 return -ENOTSUP;
196 }
197 #endif
198
199 #if defined(CONFIG_BMC150_MAGN_SAMPLING_REP_XY)
bmc150_magn_write_rep_xy(const struct device * dev,int val)200 static int bmc150_magn_write_rep_xy(const struct device *dev, int val)
201 {
202 struct bmc150_magn_data *data = dev->data;
203 const struct bmc150_magn_config *config = dev->config;
204
205 if (i2c_reg_update_byte(data->i2c_master, config->i2c_slave_addr,
206 BMC150_MAGN_REG_REP_XY,
207 BMC150_MAGN_REG_REP_DATAMASK,
208 BMC150_MAGN_REPXY_TO_REGVAL(val)) < 0) {
209 return -EIO;
210 }
211
212 data->rep_xy = val;
213
214 return 0;
215 }
216 #endif
217
218 #if defined(CONFIG_BMC150_MAGN_SAMPLING_REP_Z)
bmc150_magn_write_rep_z(const struct device * dev,int val)219 static int bmc150_magn_write_rep_z(const struct device *dev, int val)
220 {
221 struct bmc150_magn_data *data = dev->data;
222 const struct bmc150_magn_config *config = dev->config;
223
224 if (i2c_reg_update_byte(data->i2c_master, config->i2c_slave_addr,
225 BMC150_MAGN_REG_REP_Z,
226 BMC150_MAGN_REG_REP_DATAMASK,
227 BMC150_MAGN_REPZ_TO_REGVAL(val)) < 0) {
228 return -EIO;
229 }
230
231 data->rep_z = val;
232
233 return 0;
234 }
235 #endif
236
237 /*
238 * Datasheet part 4.3.4, provided by Bosch here:
239 * https://github.com/BoschSensortec/BMM050_driver
240 */
bmc150_magn_compensate_xy(struct bmc150_magn_trim_regs * tregs,int16_t xy,uint16_t rhall,bool is_x)241 static int32_t bmc150_magn_compensate_xy(struct bmc150_magn_trim_regs *tregs,
242 int16_t xy, uint16_t rhall, bool is_x)
243 {
244 int8_t txy1, txy2;
245 int16_t val;
246
247 if (xy == BMC150_MAGN_XY_OVERFLOW_VAL) {
248 return INT32_MIN;
249 }
250
251 if (!rhall) {
252 rhall = tregs->xyz1;
253 }
254
255 if (is_x) {
256 txy1 = tregs->x1;
257 txy2 = tregs->x2;
258 } else {
259 txy1 = tregs->y1;
260 txy2 = tregs->y2;
261 }
262
263 val = ((int16_t)(((uint16_t)((((int32_t)tregs->xyz1) << 14) / rhall)) -
264 ((uint16_t)0x4000)));
265 val = ((int16_t)((((int32_t)xy) * ((((((((int32_t)tregs->xy2) *
266 ((((int32_t)val) * ((int32_t)val)) >> 7)) + (((int32_t)val) *
267 ((int32_t)(((int16_t)tregs->xy1) << 7)))) >> 9) +
268 ((int32_t)0x100000)) * ((int32_t)(((int16_t)txy2) +
269 ((int16_t)0xA0)))) >> 12)) >> 13)) + (((int16_t)txy1) << 3);
270
271 return (int32_t)val;
272 }
273
bmc150_magn_compensate_z(struct bmc150_magn_trim_regs * tregs,int16_t z,uint16_t rhall)274 static int32_t bmc150_magn_compensate_z(struct bmc150_magn_trim_regs *tregs,
275 int16_t z, uint16_t rhall)
276 {
277 int32_t val;
278
279 if (z == BMC150_MAGN_Z_OVERFLOW_VAL) {
280 return INT32_MIN;
281 }
282
283 val = (((((int32_t)(z - tregs->z4)) << 15) - ((((int32_t)tregs->z3) *
284 ((int32_t)(((int16_t)rhall) - ((int16_t)tregs->xyz1)))) >> 2)) /
285 (tregs->z2 + ((int16_t)(((((int32_t)tregs->z1) *
286 ((((int16_t)rhall) << 1))) + (1 << 15)) >> 16))));
287
288 return val;
289 }
290
bmc150_magn_sample_fetch(const struct device * dev,enum sensor_channel chan)291 static int bmc150_magn_sample_fetch(const struct device *dev,
292 enum sensor_channel chan)
293 {
294 struct bmc150_magn_data *data = dev->data;
295 const struct bmc150_magn_config *config = dev->config;
296 uint16_t values[BMC150_MAGN_AXIS_XYZR_MAX];
297 int16_t raw_x, raw_y, raw_z;
298 uint16_t rhall;
299
300 __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL ||
301 chan == SENSOR_CHAN_MAGN_XYZ);
302
303 if (i2c_burst_read(data->i2c_master, config->i2c_slave_addr,
304 BMC150_MAGN_REG_X_L, (uint8_t *)values,
305 sizeof(values)) < 0) {
306 LOG_ERR("failed to read sample");
307 return -EIO;
308 }
309
310 raw_x = (int16_t)sys_le16_to_cpu(values[BMC150_MAGN_AXIS_X]) >>
311 BMC150_MAGN_SHIFT_XY_L;
312 raw_y = (int16_t)sys_le16_to_cpu(values[BMC150_MAGN_AXIS_Y]) >>
313 BMC150_MAGN_SHIFT_XY_L;
314 raw_z = (int16_t)sys_le16_to_cpu(values[BMC150_MAGN_AXIS_Z]) >>
315 BMC150_MAGN_SHIFT_Z_L;
316 rhall = sys_le16_to_cpu(values[BMC150_MAGN_RHALL]) >>
317 BMC150_MAGN_SHIFT_RHALL_L;
318
319 data->sample_x = bmc150_magn_compensate_xy(&data->tregs, raw_x, rhall,
320 true);
321 data->sample_y = bmc150_magn_compensate_xy(&data->tregs, raw_y, rhall,
322 false);
323 data->sample_z = bmc150_magn_compensate_z(&data->tregs, raw_z, rhall);
324
325 return 0;
326 }
327
bmc150_magn_convert(struct sensor_value * val,int raw_val)328 static void bmc150_magn_convert(struct sensor_value *val, int raw_val)
329 {
330 /* val = raw_val / 1600 */
331 val->val1 = raw_val / 1600;
332 val->val2 = ((int32_t)raw_val * (1000000 / 1600)) % 1000000;
333 }
334
bmc150_magn_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)335 static int bmc150_magn_channel_get(const struct device *dev,
336 enum sensor_channel chan,
337 struct sensor_value *val)
338 {
339 struct bmc150_magn_data *data = dev->data;
340
341 switch (chan) {
342 case SENSOR_CHAN_MAGN_X:
343 bmc150_magn_convert(val, data->sample_x);
344 break;
345 case SENSOR_CHAN_MAGN_Y:
346 bmc150_magn_convert(val, data->sample_y);
347 break;
348 case SENSOR_CHAN_MAGN_Z:
349 bmc150_magn_convert(val, data->sample_z);
350 break;
351 case SENSOR_CHAN_MAGN_XYZ:
352 bmc150_magn_convert(val, data->sample_x);
353 bmc150_magn_convert(val + 1, data->sample_y);
354 bmc150_magn_convert(val + 2, data->sample_z);
355 break;
356 default:
357 return -EINVAL;
358 }
359
360 return 0;
361 }
362
363 #if defined(BMC150_MAGN_SET_ATTR_REP)
bmc150_magn_attr_set_rep(const struct device * dev,enum sensor_channel chan,const struct sensor_value * val)364 static inline int bmc150_magn_attr_set_rep(const struct device *dev,
365 enum sensor_channel chan,
366 const struct sensor_value *val)
367 {
368 struct bmc150_magn_data *data = dev->data;
369 int max_odr;
370
371 switch (chan) {
372 #if defined(CONFIG_BMC150_MAGN_SAMPLING_REP_XY)
373 case SENSOR_CHAN_MAGN_X:
374 case SENSOR_CHAN_MAGN_Y:
375 if (val->val1 < 1 || val->val1 > 511) {
376 return -EINVAL;
377 }
378
379 if (bmc150_magn_compute_max_odr(dev, val->val1, 0,
380 &max_odr) < 0) {
381 return -EIO;
382 }
383
384 if (data->odr <= 0) {
385 if (bmc150_magn_read_odr(dev) < 0) {
386 return -EIO;
387 }
388 }
389
390 if (data->odr > max_odr) {
391 return -EINVAL;
392 }
393
394 if (bmc150_magn_write_rep_xy(dev, val->val1) < 0) {
395 return -EIO;
396 }
397 break;
398 #endif
399 #if defined(CONFIG_BMC150_MAGN_SAMPLING_REP_Z)
400 case SENSOR_CHAN_MAGN_Z:
401 if (val->val1 < 1 || val->val1 > 256) {
402 return -EINVAL;
403 }
404
405 if (bmc150_magn_compute_max_odr(dev, 0, val->val1,
406 &max_odr) < 0) {
407 return -EIO;
408 }
409
410 if (data->odr <= 0) {
411 if (bmc150_magn_read_odr(dev) < 0) {
412 return -EIO;
413 }
414 }
415
416 if (data->odr > max_odr) {
417 return -EINVAL;
418 }
419
420 if (bmc150_magn_write_rep_z(dev, val->val1) < 0) {
421 return -EIO;
422 }
423 break;
424 #endif
425 default:
426 return -EINVAL;
427 }
428
429 return 0;
430 }
431 #endif
432
433 #if defined(BMC150_MAGN_SET_ATTR)
bmc150_magn_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)434 static int bmc150_magn_attr_set(const struct device *dev,
435 enum sensor_channel chan,
436 enum sensor_attribute attr,
437 const struct sensor_value *val)
438 {
439 struct bmc150_magn_data *data = dev->data;
440
441 switch (attr) {
442 #if defined(CONFIG_BMC150_MAGN_SAMPLING_RATE_RUNTIME)
443 case SENSOR_ATTR_SAMPLING_FREQUENCY:
444 if (data->max_odr <= 0) {
445 if (bmc150_magn_compute_max_odr(dev, 0, 0,
446 &data->max_odr) < 0) {
447 return -EIO;
448 }
449 }
450
451 if (data->max_odr < val->val1) {
452 LOG_ERR("not supported with current oversampling");
453 return -ENOTSUP;
454 }
455
456 if (bmc150_magn_set_odr(dev, (uint8_t)(val->val1)) < 0) {
457 return -EIO;
458 }
459 break;
460 #endif
461 #if defined(BMC150_MAGN_SET_ATTR_REP)
462 case SENSOR_ATTR_OVERSAMPLING:
463 bmc150_magn_attr_set_rep(dev, chan, val);
464 break;
465 #endif
466 default:
467 return -EINVAL;
468 }
469
470 return 0;
471 }
472 #endif
473
474 static const struct sensor_driver_api bmc150_magn_api_funcs = {
475 #if defined(BMC150_MAGN_SET_ATTR)
476 .attr_set = bmc150_magn_attr_set,
477 #endif
478 .sample_fetch = bmc150_magn_sample_fetch,
479 .channel_get = bmc150_magn_channel_get,
480 #if defined(CONFIG_BMC150_MAGN_TRIGGER_DRDY)
481 .trigger_set = bmc150_magn_trigger_set,
482 #endif
483 };
484
bmc150_magn_init_chip(const struct device * dev)485 static int bmc150_magn_init_chip(const struct device *dev)
486 {
487 struct bmc150_magn_data *data = dev->data;
488 const struct bmc150_magn_config *config = dev->config;
489 uint8_t chip_id;
490 struct bmc150_magn_preset preset;
491
492 bmc150_magn_set_power_mode(dev, BMC150_MAGN_POWER_MODE_NORMAL, 0);
493 bmc150_magn_set_power_mode(dev, BMC150_MAGN_POWER_MODE_SUSPEND, 1);
494
495 if (bmc150_magn_set_power_mode(dev, BMC150_MAGN_POWER_MODE_SUSPEND, 0)
496 < 0) {
497 LOG_ERR("failed to bring up device from suspend mode");
498 return -EIO;
499 }
500
501 if (i2c_reg_read_byte(data->i2c_master, config->i2c_slave_addr,
502 BMC150_MAGN_REG_CHIP_ID, &chip_id) < 0) {
503 LOG_ERR("failed reading chip id");
504 goto err_poweroff;
505 }
506 if (chip_id != BMC150_MAGN_CHIP_ID_VAL) {
507 LOG_ERR("invalid chip id 0x%x", chip_id);
508 goto err_poweroff;
509 }
510 LOG_ERR("chip id 0x%x", chip_id);
511
512 preset = bmc150_magn_presets_table[BMC150_MAGN_DEFAULT_PRESET];
513 if (bmc150_magn_set_odr(dev, preset.odr) < 0) {
514 LOG_ERR("failed to set ODR to %d",
515 preset.odr);
516 goto err_poweroff;
517 }
518
519 if (i2c_reg_write_byte(data->i2c_master, config->i2c_slave_addr,
520 BMC150_MAGN_REG_REP_XY,
521 BMC150_MAGN_REPXY_TO_REGVAL(preset.rep_xy))
522 < 0) {
523 LOG_ERR("failed to set REP XY to %d",
524 preset.rep_xy);
525 goto err_poweroff;
526 }
527
528 if (i2c_reg_write_byte(data->i2c_master, config->i2c_slave_addr,
529 BMC150_MAGN_REG_REP_Z,
530 BMC150_MAGN_REPZ_TO_REGVAL(preset.rep_z)) < 0) {
531 LOG_ERR("failed to set REP Z to %d",
532 preset.rep_z);
533 goto err_poweroff;
534 }
535
536 if (bmc150_magn_set_power_mode(dev, BMC150_MAGN_POWER_MODE_NORMAL, 1)
537 < 0) {
538 LOG_ERR("failed to power on device");
539 goto err_poweroff;
540 }
541
542 if (i2c_burst_read(data->i2c_master, config->i2c_slave_addr,
543 BMC150_MAGN_REG_TRIM_START, (uint8_t *)&data->tregs,
544 sizeof(data->tregs)) < 0) {
545 LOG_ERR("failed to read trim regs");
546 goto err_poweroff;
547 }
548
549 data->rep_xy = 0;
550 data->rep_z = 0;
551 data->odr = 0;
552 data->max_odr = 0;
553 data->sample_x = 0;
554 data->sample_y = 0;
555 data->sample_z = 0;
556
557 data->tregs.xyz1 = sys_le16_to_cpu(data->tregs.xyz1);
558 data->tregs.z1 = sys_le16_to_cpu(data->tregs.z1);
559 data->tregs.z2 = sys_le16_to_cpu(data->tregs.z2);
560 data->tregs.z3 = sys_le16_to_cpu(data->tregs.z3);
561 data->tregs.z4 = sys_le16_to_cpu(data->tregs.z4);
562
563 return 0;
564
565 err_poweroff:
566 bmc150_magn_set_power_mode(dev, BMC150_MAGN_POWER_MODE_NORMAL, 0);
567 bmc150_magn_set_power_mode(dev, BMC150_MAGN_POWER_MODE_SUSPEND, 1);
568 return -EIO;
569 }
570
bmc150_magn_init(const struct device * dev)571 static int bmc150_magn_init(const struct device *dev)
572 {
573 const struct bmc150_magn_config * const config =
574 dev->config;
575 struct bmc150_magn_data *data = dev->data;
576
577 data->i2c_master = device_get_binding(config->i2c_master_dev_name);
578 if (!data->i2c_master) {
579 LOG_ERR("i2c master not found: %s",
580 config->i2c_master_dev_name);
581 return -EINVAL;
582 }
583
584 if (bmc150_magn_init_chip(dev) < 0) {
585 LOG_ERR("failed to initialize chip");
586 return -EIO;
587 }
588
589 #if defined(CONFIG_BMC150_MAGN_TRIGGER_DRDY)
590 if (bmc150_magn_init_interrupt(dev) < 0) {
591 LOG_ERR("failed to initialize interrupts");
592 return -EINVAL;
593 }
594 #endif
595 return 0;
596 }
597
598 static const struct bmc150_magn_config bmc150_magn_config = {
599 #if defined(CONFIG_BMC150_MAGN_TRIGGER_DRDY)
600 .gpio_drdy_dev_name = DT_INST_GPIO_LABEL(0, drdy_gpios),
601 .gpio_drdy_int_pin = DT_INST_GPIO_PIN(0, drdy_gpios),
602 .gpio_drdy_int_flags = DT_INST_GPIO_FLAGS(0, drdy_gpios),
603 #endif
604 .i2c_master_dev_name = DT_INST_BUS_LABEL(0),
605 .i2c_slave_addr = BMC150_MAGN_I2C_ADDR,
606 };
607
608 static struct bmc150_magn_data bmc150_magn_data;
609
610 DEVICE_DT_INST_DEFINE(0, bmc150_magn_init, NULL,
611 &bmc150_magn_data, &bmc150_magn_config, POST_KERNEL,
612 CONFIG_SENSOR_INIT_PRIORITY, &bmc150_magn_api_funcs);
613