1 /*
2  * Copyright (c) 2022 Badgerd Technologies B.V.
3  * Copyright (c) 2023 Metratec GmbH
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include "bmp581.h"
9 
10 #include <math.h>
11 
12 #include <zephyr/device.h>
13 #include <zephyr/drivers/gpio.h>
14 #include <zephyr/drivers/i2c.h>
15 #include <zephyr/drivers/sensor.h>
16 #include <zephyr/init.h>
17 #include <zephyr/logging/log.h>
18 #include <zephyr/sys/check.h>
19 
20 LOG_MODULE_REGISTER(bmp581, CONFIG_SENSOR_LOG_LEVEL);
21 
22 #if DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 0
23 #warning "BMP581 driver enabled without any devices"
24 #endif
25 
26 static int power_up_check(const struct device *dev);
27 static int get_nvm_status(uint8_t *nvm_status, const struct device *dev);
28 static int get_interrupt_status(uint8_t *int_status, const struct device *dev);
29 static int validate_chip_id(struct bmp581_data *drv);
30 static int get_osr_odr_press_config(struct bmp581_osr_odr_press_config *osr_odr_press_cfg,
31 				    const struct device *dev);
32 static int set_osr_config(const struct sensor_value *osr, enum sensor_channel chan,
33 			  const struct device *dev);
34 static int set_odr_config(const struct sensor_value *odr, const struct device *dev);
35 static int soft_reset(const struct device *dev);
36 static int set_iir_config(const struct sensor_value *iir, const struct device *dev);
37 static int get_power_mode(enum bmp5_powermode *powermode, const struct device *dev);
38 static int set_power_mode(enum bmp5_powermode powermode, const struct device *dev);
39 
set_power_mode(enum bmp5_powermode powermode,const struct device * dev)40 static int set_power_mode(enum bmp5_powermode powermode, const struct device *dev)
41 {
42 	struct bmp581_config *conf = (struct bmp581_config *)dev->config;
43 	int ret = BMP5_OK;
44 	uint8_t odr = 0;
45 	enum bmp5_powermode current_powermode;
46 
47 	CHECKIF(dev == NULL) {
48 		return -EINVAL;
49 	}
50 
51 	ret = get_power_mode(&current_powermode, dev);
52 	if (ret != BMP5_OK) {
53 		LOG_ERR("Couldnt set the power mode because something went wrong when getting the "
54 			"current power mode.");
55 		return ret;
56 	}
57 
58 	if (current_powermode != BMP5_POWERMODE_STANDBY) {
59 		/*
60 		 * Device should be set to standby before transitioning to forced mode or normal
61 		 * mode or continuous mode.
62 		 */
63 
64 		ret = i2c_reg_read_byte_dt(&conf->i2c, BMP5_REG_ODR_CONFIG, &odr);
65 		if (ret == BMP5_OK) {
66 			/* Setting deep_dis = 1(BMP5_DEEP_DISABLED) disables the deep standby mode
67 			 */
68 			odr = BMP5_SET_BITSLICE(odr, BMP5_DEEP_DISABLE, BMP5_DEEP_DISABLED);
69 			odr = BMP5_SET_BITS_POS_0(odr, BMP5_POWERMODE, BMP5_POWERMODE_STANDBY);
70 			ret = i2c_reg_write_byte_dt(&conf->i2c, BMP5_REG_ODR_CONFIG, odr);
71 
72 			if (ret != BMP5_OK) {
73 				LOG_DBG("Failed to set power mode to BMP5_POWERMODE_STANDBY.");
74 				return ret;
75 			}
76 		}
77 	}
78 
79 	/* lets update the power mode */
80 	switch (powermode) {
81 	case BMP5_POWERMODE_STANDBY:
82 		/* this change is already done so we can just return */
83 		ret = BMP5_OK;
84 		break;
85 	case BMP5_POWERMODE_DEEP_STANDBY:
86 		LOG_DBG("Setting power mode to DEEP STANDBY is not supported, current power mode "
87 			"is BMP5_POWERMODE_STANDBY.");
88 		ret = -ENOTSUP;
89 		break;
90 	case BMP5_POWERMODE_NORMAL:
91 	case BMP5_POWERMODE_FORCED:
92 	case BMP5_POWERMODE_CONTINUOUS:
93 		odr = BMP5_SET_BITSLICE(odr, BMP5_DEEP_DISABLE, BMP5_DEEP_DISABLED);
94 		odr = BMP5_SET_BITS_POS_0(odr, BMP5_POWERMODE, powermode);
95 		ret = i2c_reg_write_byte_dt(&conf->i2c, BMP5_REG_ODR_CONFIG, odr);
96 		break;
97 	default:
98 		/* invalid power mode */
99 		ret = -EINVAL;
100 		break;
101 	}
102 
103 	return ret;
104 }
105 
get_power_mode(enum bmp5_powermode * powermode,const struct device * dev)106 static int get_power_mode(enum bmp5_powermode *powermode, const struct device *dev)
107 {
108 	struct bmp581_config *conf = (struct bmp581_config *)dev->config;
109 	int ret = BMP5_OK;
110 
111 	CHECKIF(powermode == NULL || dev == NULL) {
112 		return -EINVAL;
113 	}
114 
115 	uint8_t reg = 0;
116 	uint8_t raw_power_mode = 0;
117 
118 	ret = i2c_reg_read_byte_dt(&conf->i2c, BMP5_REG_ODR_CONFIG, &reg);
119 	if (ret != BMP5_OK) {
120 		LOG_DBG("Failed to read odr config to get power mode!");
121 		return ret;
122 	}
123 
124 	raw_power_mode = BMP5_GET_BITS_POS_0(reg, BMP5_POWERMODE);
125 
126 	switch (raw_power_mode) {
127 	case BMP5_POWERMODE_STANDBY: {
128 		/* Getting deep disable status */
129 		uint8_t deep_dis = BMP5_GET_BITSLICE(reg, BMP5_DEEP_DISABLE);
130 
131 		/* Checking deepstandby status only when powermode is in standby mode */
132 
133 		/* If deep_dis = 0(BMP5_DEEP_ENABLED) then deepstandby mode is enabled.
134 		 * If deep_dis = 1(BMP5_DEEP_DISABLED) then deepstandby mode is disabled
135 		 */
136 		if (deep_dis == BMP5_DEEP_ENABLED) {
137 			/* TODO: check if it is really deep standby */
138 			*powermode = BMP5_POWERMODE_DEEP_STANDBY;
139 		} else {
140 			*powermode = BMP5_POWERMODE_STANDBY;
141 		}
142 
143 		break;
144 	}
145 	case BMP5_POWERMODE_NORMAL:
146 		*powermode = BMP5_POWERMODE_NORMAL;
147 		break;
148 	case BMP5_POWERMODE_FORCED:
149 		*powermode = BMP5_POWERMODE_FORCED;
150 		break;
151 	case BMP5_POWERMODE_CONTINUOUS:
152 		*powermode = BMP5_POWERMODE_CONTINUOUS;
153 		break;
154 	default:
155 		/* invalid power mode */
156 		ret = -EINVAL;
157 		LOG_DBG("Something went wrong invalid powermode!");
158 		break;
159 	}
160 
161 	return ret;
162 }
163 
power_up_check(const struct device * dev)164 static int power_up_check(const struct device *dev)
165 {
166 	int8_t rslt = 0;
167 	uint8_t nvm_status = 0;
168 
169 	CHECKIF(dev == NULL) {
170 		return -EINVAL;
171 	}
172 
173 	rslt = get_nvm_status(&nvm_status, dev);
174 
175 	if (rslt == BMP5_OK) {
176 		/* Check if nvm_rdy status = 1 and nvm_err status = 0 to proceed */
177 		if ((nvm_status & BMP5_INT_NVM_RDY) && (!(nvm_status & BMP5_INT_NVM_ERR))) {
178 			rslt = BMP5_OK;
179 		} else {
180 			rslt = -EFAULT;
181 		}
182 	}
183 
184 	return rslt;
185 }
186 
get_interrupt_status(uint8_t * int_status,const struct device * dev)187 static int get_interrupt_status(uint8_t *int_status, const struct device *dev)
188 {
189 	struct bmp581_config *conf = (struct bmp581_config *)dev->config;
190 
191 	CHECKIF(int_status == NULL || dev == NULL) {
192 		return -EINVAL;
193 	}
194 
195 	return i2c_reg_read_byte_dt(&conf->i2c, BMP5_REG_INT_STATUS, int_status);
196 }
197 
get_nvm_status(uint8_t * nvm_status,const struct device * dev)198 static int get_nvm_status(uint8_t *nvm_status, const struct device *dev)
199 {
200 	struct bmp581_config *conf = (struct bmp581_config *)dev->config;
201 
202 	CHECKIF(nvm_status == NULL || dev == NULL) {
203 		return -EINVAL;
204 	}
205 
206 	return i2c_reg_read_byte_dt(&conf->i2c, BMP5_REG_STATUS, nvm_status);
207 }
208 
validate_chip_id(struct bmp581_data * drv)209 static int validate_chip_id(struct bmp581_data *drv)
210 {
211 	int8_t rslt = 0;
212 
213 	CHECKIF(drv == NULL) {
214 		return -EINVAL;
215 	}
216 
217 	if ((drv->chip_id == BMP5_CHIP_ID_PRIM) || (drv->chip_id == BMP5_CHIP_ID_SEC)) {
218 		rslt = BMP5_OK;
219 	} else {
220 		drv->chip_id = 0;
221 		rslt = -ENODEV;
222 	}
223 
224 	return rslt;
225 }
226 
227 /*!
228  *  This API gets the configuration for oversampling of temperature, oversampling of
229  *  pressure and ODR configuration along with pressure enable.
230  */
get_osr_odr_press_config(struct bmp581_osr_odr_press_config * osr_odr_press_cfg,const struct device * dev)231 static int get_osr_odr_press_config(struct bmp581_osr_odr_press_config *osr_odr_press_cfg,
232 				    const struct device *dev)
233 {
234 	struct bmp581_config *conf = (struct bmp581_config *)dev->config;
235 
236 	/* Variable to store the function result */
237 	int8_t rslt = 0;
238 
239 	/* Variable to store OSR and ODR config */
240 	uint8_t reg_data[2] = {0};
241 
242 	CHECKIF(osr_odr_press_cfg == NULL || dev == NULL) {
243 		return -EINVAL;
244 	}
245 
246 	/* Get OSR and ODR configuration in burst read */
247 	rslt = i2c_burst_read_dt(&conf->i2c, BMP5_REG_OSR_CONFIG, reg_data, 2);
248 
249 	if (rslt == BMP5_OK) {
250 		osr_odr_press_cfg->osr_t = BMP5_GET_BITS_POS_0(reg_data[0], BMP5_TEMP_OS);
251 		osr_odr_press_cfg->osr_p = BMP5_GET_BITSLICE(reg_data[0], BMP5_PRESS_OS);
252 		osr_odr_press_cfg->press_en = BMP5_GET_BITSLICE(reg_data[0], BMP5_PRESS_EN);
253 		osr_odr_press_cfg->odr = BMP5_GET_BITSLICE(reg_data[1], BMP5_ODR);
254 	}
255 
256 	return rslt;
257 }
258 
set_osr_config(const struct sensor_value * osr,enum sensor_channel chan,const struct device * dev)259 static int set_osr_config(const struct sensor_value *osr, enum sensor_channel chan,
260 			  const struct device *dev)
261 {
262 	CHECKIF(osr == NULL || dev == NULL) {
263 		return -EINVAL;
264 	}
265 
266 	struct bmp581_data *drv = (struct bmp581_data *)dev->data;
267 	struct bmp581_config *conf = (struct bmp581_config *)dev->config;
268 	int ret = 0;
269 
270 	uint8_t oversampling = osr->val1;
271 	uint8_t press_en = osr->val2 != 0; /* if it is not 0 then pressure is enabled */
272 	uint8_t osr_val = 0;
273 
274 	ret = i2c_reg_read_byte_dt(&conf->i2c, BMP5_REG_OSR_CONFIG, &osr_val);
275 	if (ret == BMP5_OK) {
276 		switch (chan) {
277 		case SENSOR_CHAN_ALL:
278 			osr_val = BMP5_SET_BITS_POS_0(osr_val, BMP5_TEMP_OS, oversampling);
279 			osr_val = BMP5_SET_BITSLICE(osr_val, BMP5_PRESS_OS, oversampling);
280 			osr_val = BMP5_SET_BITSLICE(osr_val, BMP5_PRESS_EN, press_en);
281 			break;
282 		case SENSOR_CHAN_PRESS:
283 			osr_val = BMP5_SET_BITSLICE(osr_val, BMP5_PRESS_OS, oversampling);
284 			osr_val = BMP5_SET_BITSLICE(osr_val, BMP5_PRESS_EN, press_en);
285 			break;
286 		case SENSOR_CHAN_AMBIENT_TEMP:
287 			osr_val = BMP5_SET_BITS_POS_0(osr_val, BMP5_TEMP_OS, oversampling);
288 			break;
289 		default:
290 			ret = -ENOTSUP;
291 			break;
292 		}
293 
294 		if (ret == BMP5_OK) {
295 			ret = i2c_reg_write_byte_dt(&conf->i2c, BMP5_REG_OSR_CONFIG, osr_val);
296 			get_osr_odr_press_config(&drv->osr_odr_press_config, dev);
297 		}
298 	}
299 
300 	return ret;
301 }
302 
set_odr_config(const struct sensor_value * odr,const struct device * dev)303 static int set_odr_config(const struct sensor_value *odr, const struct device *dev)
304 {
305 	CHECKIF(odr == NULL || dev == NULL) {
306 		return -EINVAL;
307 	}
308 
309 	struct bmp581_data *drv = (struct bmp581_data *)dev->data;
310 	struct bmp581_config *conf = (struct bmp581_config *)dev->config;
311 	int ret = 0;
312 	uint8_t odr_val = 0;
313 
314 	ret = i2c_reg_read_byte_dt(&conf->i2c, BMP5_REG_ODR_CONFIG, &odr_val);
315 	if (ret != BMP5_OK) {
316 		return ret;
317 	}
318 	odr_val = BMP5_SET_BITSLICE(odr_val, BMP5_ODR, odr->val1);
319 	ret = i2c_reg_write_byte_dt(&conf->i2c, BMP5_REG_ODR_CONFIG, odr_val);
320 	get_osr_odr_press_config(&drv->osr_odr_press_config, dev);
321 
322 	return ret;
323 }
324 
soft_reset(const struct device * dev)325 static int soft_reset(const struct device *dev)
326 {
327 	struct bmp581_config *conf = (struct bmp581_config *)dev->config;
328 	int ret = 0;
329 	const uint8_t reset_cmd = BMP5_SOFT_RESET_CMD;
330 	uint8_t int_status = 0;
331 
332 	CHECKIF(dev == NULL) {
333 		return -EINVAL;
334 	}
335 
336 	ret = i2c_reg_write_byte_dt(&conf->i2c, BMP5_REG_CMD, reset_cmd);
337 
338 	if (ret == BMP5_OK) {
339 		k_usleep(BMP5_DELAY_US_SOFT_RESET);
340 		ret = get_interrupt_status(&int_status, dev);
341 		if (ret == BMP5_OK) {
342 			if (int_status & BMP5_INT_ASSERTED_POR_SOFTRESET_COMPLETE) {
343 				ret = BMP5_OK;
344 			} else {
345 				ret = -EFAULT;
346 			}
347 		}
348 	} else {
349 		LOG_DBG("Failed perform soft-reset.");
350 	}
351 
352 	return ret;
353 }
354 
bmp581_sample_fetch(const struct device * dev,enum sensor_channel chan)355 static int bmp581_sample_fetch(const struct device *dev, enum sensor_channel chan)
356 {
357 	CHECKIF(dev == NULL) {
358 		return -EINVAL;
359 	}
360 
361 	if (chan != SENSOR_CHAN_ALL) {
362 		return -ENOTSUP;
363 	}
364 
365 	struct bmp581_data *drv = (struct bmp581_data *)dev->data;
366 	struct bmp581_config *conf = (struct bmp581_config *)dev->config;
367 	uint8_t data[6];
368 	int ret = 0;
369 
370 	ret = i2c_burst_read_dt(&conf->i2c, BMP5_REG_TEMP_DATA_XLSB, data, 6);
371 	if (ret == BMP5_OK) {
372 		/* convert raw sensor data to sensor_value. Shift the decimal part by 1 decimal
373 		 * place to compensate for the conversion in sensor_value_to_double()
374 		 */
375 		drv->last_sample.temperature.val1 = data[2];
376 		drv->last_sample.temperature.val2 = (data[1] << 8 | data[0]) * 10;
377 
378 		if (drv->osr_odr_press_config.press_en == BMP5_ENABLE) {
379 			uint32_t raw_pressure = (uint32_t)((uint32_t)(data[5] << 16) |
380 							   (uint16_t)(data[4] << 8) | data[3]);
381 			/* convert raw sensor data to sensor_value. Shift the decimal part by
382 			 * 4 decimal places to compensate for the conversion in
383 			 * sensor_value_to_double()
384 			 */
385 			drv->last_sample.pressure.val1 = raw_pressure >> 6;
386 			drv->last_sample.pressure.val2 = (raw_pressure & BIT_MASK(6)) * 10000;
387 		} else {
388 			drv->last_sample.pressure.val1 = 0;
389 			drv->last_sample.pressure.val2 = 0;
390 		}
391 	}
392 
393 	return ret;
394 }
395 
bmp581_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)396 static int bmp581_channel_get(const struct device *dev, enum sensor_channel chan,
397 			      struct sensor_value *val)
398 {
399 	CHECKIF(dev == NULL || val == NULL) {
400 		return -EINVAL;
401 	}
402 
403 	struct bmp581_data *drv = (struct bmp581_data *)dev->data;
404 
405 	switch (chan) {
406 	case SENSOR_CHAN_PRESS:
407 		/* returns pressure in Pa */
408 		*val = drv->last_sample.pressure;
409 		return BMP5_OK;
410 	case SENSOR_CHAN_AMBIENT_TEMP:
411 		/* returns temperature in Celcius */
412 		*val = drv->last_sample.temperature;
413 		return BMP5_OK;
414 	default:
415 		return -ENOTSUP;
416 	}
417 }
418 
set_iir_config(const struct sensor_value * iir,const struct device * dev)419 static int set_iir_config(const struct sensor_value *iir, const struct device *dev)
420 {
421 	struct bmp581_config *conf = (struct bmp581_config *)dev->config;
422 	int ret = BMP5_OK;
423 
424 	CHECKIF((iir == NULL) | (dev == NULL)) {
425 		return -EINVAL;
426 	}
427 
428 	/* Variable to store existing powermode */
429 	enum bmp5_powermode prev_powermode;
430 
431 	ret = get_power_mode(&prev_powermode, dev);
432 	if (ret != BMP5_OK) {
433 		LOG_DBG("Not able to get current power mode.");
434 		return ret;
435 	}
436 	/* IIR configuration is writable only during STANDBY mode(as per datasheet) */
437 	set_power_mode(BMP5_POWERMODE_STANDBY, dev);
438 
439 	/* update IIR config */
440 	uint8_t dsp_config[2];
441 
442 	ret = i2c_burst_read_dt(&conf->i2c, BMP5_REG_DSP_CONFIG, dsp_config, 2);
443 	if (ret != BMP5_OK) {
444 		LOG_DBG("Failed to read dsp config register.");
445 		return ret;
446 	}
447 	/* Put IIR filtered values in data registers */
448 	dsp_config[0] = BMP5_SET_BITSLICE(dsp_config[0], BMP5_SHDW_SET_IIR_TEMP, BMP5_ENABLE);
449 	dsp_config[0] = BMP5_SET_BITSLICE(dsp_config[0], BMP5_SHDW_SET_IIR_PRESS, BMP5_ENABLE);
450 
451 	/* Configure IIR filter */
452 	dsp_config[1] = iir->val1;
453 	dsp_config[1] = BMP5_SET_BITSLICE(dsp_config[1], BMP5_SET_IIR_PRESS, iir->val2);
454 
455 	/* Set IIR configuration */
456 	ret = i2c_burst_write_dt(&conf->i2c, BMP5_REG_DSP_CONFIG, dsp_config, 2);
457 
458 	if (ret != BMP5_OK) {
459 		LOG_DBG("Failed to configure IIR filter.");
460 		return ret;
461 	}
462 
463 	/* Restore previous power mode if it is not standby already */
464 	if (prev_powermode != BMP5_POWERMODE_STANDBY) {
465 		ret = set_power_mode(prev_powermode, dev);
466 	}
467 
468 	return ret;
469 }
470 
bmp581_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)471 static int bmp581_attr_set(const struct device *dev, enum sensor_channel chan,
472 			   enum sensor_attribute attr, const struct sensor_value *val)
473 {
474 	CHECKIF(dev == NULL || val == NULL) {
475 		return -EINVAL;
476 	}
477 
478 	int ret;
479 
480 	switch ((int)attr) {
481 	case SENSOR_ATTR_SAMPLING_FREQUENCY:
482 		ret = set_odr_config(val, dev);
483 		break;
484 	case SENSOR_ATTR_OVERSAMPLING:
485 		ret = set_osr_config(val, chan, dev);
486 		break;
487 	case BMP5_ATTR_POWER_MODE: {
488 		enum bmp5_powermode powermode = (enum bmp5_powermode)val->val1;
489 
490 		ret = set_power_mode(powermode, dev);
491 		break;
492 	}
493 	case BMP5_ATTR_IIR_CONFIG:
494 		ret = set_iir_config(val, dev);
495 		break;
496 	default:
497 		ret = -ENOTSUP;
498 		break;
499 	}
500 	return ret;
501 }
502 
bmp581_init(const struct device * dev)503 static int bmp581_init(const struct device *dev)
504 {
505 	CHECKIF(dev == NULL) {
506 		return -EINVAL;
507 	}
508 
509 	struct bmp581_data *drv = (struct bmp581_data *)dev->data;
510 	struct bmp581_config *conf = (struct bmp581_config *)dev->config;
511 	int ret = -1;
512 
513 	/* Reset the chip id. */
514 	drv->chip_id = 0;
515 	memset(&drv->osr_odr_press_config, 0, sizeof(drv->osr_odr_press_config));
516 	memset(&drv->last_sample, 0, sizeof(drv->last_sample));
517 
518 	soft_reset(dev);
519 
520 	ret = i2c_reg_read_byte_dt(&conf->i2c, BMP5_REG_CHIP_ID, &drv->chip_id);
521 	if (ret != BMP5_OK) {
522 		return ret;
523 	}
524 
525 	if (drv->chip_id != 0) {
526 		ret = power_up_check(dev);
527 		if (ret == BMP5_OK) {
528 			ret = validate_chip_id(drv);
529 			if (ret != BMP5_OK) {
530 				LOG_ERR("Unexpected chip id (%x). Expected (%x or %x)",
531 					drv->chip_id, BMP5_CHIP_ID_PRIM, BMP5_CHIP_ID_SEC);
532 			}
533 		}
534 	} else {
535 		/* that means something went wrong */
536 		LOG_ERR("Unexpected chip id (%x). Expected (%x or %x)", drv->chip_id,
537 			BMP5_CHIP_ID_PRIM, BMP5_CHIP_ID_SEC);
538 		return -EINVAL;
539 	}
540 	return ret;
541 }
542 
543 static const struct sensor_driver_api bmp581_driver_api = {.sample_fetch = bmp581_sample_fetch,
544 							   .channel_get = bmp581_channel_get,
545 							   .attr_set = bmp581_attr_set};
546 
547 #define BMP581_CONFIG(i)                                                                           \
548 	static const struct bmp581_config bmp581_config_##i = {                                    \
549 		.i2c = I2C_DT_SPEC_INST_GET(i),                                                    \
550 	}
551 
552 #define BMP581_INIT(i)                                                                             \
553 	static struct bmp581_data bmp581_data_##i;                                                 \
554 	BMP581_CONFIG(i);                                                                          \
555                                                                                                    \
556 	SENSOR_DEVICE_DT_INST_DEFINE(i, bmp581_init, NULL, &bmp581_data_##i, &bmp581_config_##i,   \
557 				     POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,                     \
558 				     &bmp581_driver_api);
559 
560 DT_INST_FOREACH_STATUS_OKAY(BMP581_INIT)
561