1 /* Driver for Infineon DPS310 temperature and pressure sensor */
2 
3 /*
4  * Copyright (c) 2019 Infineon Technologies AG
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #define DT_DRV_COMPAT infineon_dps310
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/drivers/sensor.h>
13 #include <zephyr/init.h>
14 #include <zephyr/sys/byteorder.h>
15 #include <zephyr/sys/util.h>
16 
17 #include <zephyr/drivers/i2c.h>
18 #include <zephyr/logging/log.h>
19 
20 LOG_MODULE_REGISTER(DPS310, CONFIG_SENSOR_LOG_LEVEL);
21 
22 /* Register addresses as in the datasheet */
23 #define IFX_DPS310_REG_ADDR_PSR_B2			(0x00)
24 #define IFX_DPS310_REG_ADDR_TMP_B2			(0x03)
25 #define IFX_DPS310_REG_ADDR_PRS_CFG			(0x06)
26 #define IFX_DPS310_REG_ADDR_TMP_CFG			(0x07)
27 #define IFX_DPS310_REG_ADDR_MEAS_CFG			(0x08)
28 #define IFX_DPS310_REG_ADDR_CFG_REG			(0x09)
29 #define IFX_DPS310_REG_ADDR_INT_STS			(0x0A)
30 #define IFX_DPS310_REG_ADDR_FIFO_STS			(0x0B)
31 #define IFX_DPS310_REG_ADDR_RESET			(0x0C)
32 #define IFX_DPS310_REG_ADDR_PRODUCT_ID			(0x0D)
33 #define IFX_DPS310_REG_ADDR_COEF_0			(0x10)
34 #define IFX_DPS310_REG_ADDR_COEF_SRCE			(0x28)
35 
36 enum {
37 	IFX_DPS310_MODE_IDLE			=	0x00,
38 	IFX_DPS310_MODE_COMMAND_PRESSURE	=	0x01,
39 	IFX_DPS310_MODE_COMMAND_TEMPERATURE	=	0x02,
40 	IFX_DPS310_MODE_BACKGROUND_PRESSURE	=	0x05,
41 	IFX_DPS310_MODE_BACKGROUND_TEMPERATURE	=	0x06,
42 	IFX_DPS310_MODE_BACKGROUND_ALL		=	0x07
43 };
44 
45 /* Bits in registers as in the datasheet */
46 #define IFX_DPS310_REG_ADDR_MEAS_CFG_PRS_RDY		(0x10)
47 #define IFX_DPS310_REG_ADDR_MEAS_CFG_TMP_RDY		(0x20)
48 /*
49  * If sensor is ready after self initialization
50  * bits 6 and 7 in register MEAS_CFG (0x08) should be "1"
51  */
52 #define IFX_DPS310_REG_ADDR_MEAS_CFG_SELF_INIT_OK	(0xC0)
53 #define IFX_DPS310_COEF_SRCE_MASK			(0x80)
54 #define IFX_DPS310_PRODUCT_ID				(0x10)
55 
56 /* Polling time in ms*/
57 #define POLL_TIME_MS					(K_MSEC(10))
58 /* Number of times to poll before timeout */
59 #define POLL_TRIES					3
60 
61 /*
62  * Measurement times in ms for different oversampling rates
63  * From Table 16 in the datasheet, rounded up for safety margin
64  */
65 enum {
66 	IFX_DPS310_MEAS_TIME_OSR_1	= 4,
67 	IFX_DPS310_MEAS_TIME_OSR_2	= 6,
68 	IFX_DPS310_MEAS_TIME_OSR_4	= 9,
69 	IFX_DPS310_MEAS_TIME_OSR_8	= 15,
70 	IFX_DPS310_MEAS_TIME_OSR_16	= 28,
71 	IFX_DPS310_MEAS_TIME_OSR_32	= 54,
72 	IFX_DPS310_MEAS_TIME_OSR_64	= 105,
73 	IFX_DPS310_MEAS_TIME_OSR_128	= 207
74 };
75 
76 /* Compensation scale factors from Table 9 in the datasheet */
77 enum {
78 	IFX_DPS310_SF_OSR_1		= 524288,
79 	IFX_DPS310_SF_OSR_2		= 1572864,
80 	IFX_DPS310_SF_OSR_4		= 3670016,
81 	IFX_DPS310_SF_OSR_8		= 7864320,
82 	IFX_DPS310_SF_OSR_16		= 253952,
83 	IFX_DPS310_SF_OSR_32		= 516096,
84 	IFX_DPS310_SF_OSR_64		= 1040384,
85 	IFX_DPS310_SF_OSR_128		= 2088960
86 };
87 
88 /*
89  * Oversampling and measurement rates configuration for pressure and temperature
90  * sensor According to Table 16 of the datasheet
91  */
92 enum {
93 	IFX_DPS310_RATE_1		= 0x00,
94 	IFX_DPS310_RATE_2		= 0x01,
95 	IFX_DPS310_RATE_4		= 0x02,
96 	IFX_DPS310_RATE_8		= 0x03,
97 	IFX_DPS310_RATE_16		= 0x04,
98 	IFX_DPS310_RATE_32		= 0x05,
99 	IFX_DPS310_RATE_64		= 0x06,
100 	IFX_DPS310_RATE_128		= 0x07
101 };
102 
103 /* Helper macro to set temperature and pressure config register */
104 #define CFG_REG(MEAS_RATE, OSR_RATE)                                           \
105 	((((MEAS_RATE)&0x07) << 4) | ((OSR_RATE)&0x07))
106 
107 /* Setup constants depending on temperature oversampling factor */
108 #if defined CONFIG_DPS310_TEMP_OSR_1X
109 #define IFX_DPS310_SF_TMP		IFX_DPS310_SF_OSR_1
110 #define IFX_DPS310_TMP_MEAS_TIME	IFX_DPS310_MEAS_TIME_OSR_1
111 #define IFX_DPS310_TMP_CFG		CFG_REG(IFX_DPS310_RATE_1, IFX_DPS310_RATE_1)
112 #define IFX_DPS310_T_SHIFT		0
113 #elif defined CONFIG_DPS310_TEMP_OSR_2X
114 #define IFX_DPS310_SF_TMP		IFX_DPS310_SF_OSR_2
115 #define IFX_DPS310_TMP_MEAS_TIME	IFX_DPS310_MEAS_TIME_OSR_2
116 #define IFX_DPS310_TMP_CFG		CFG_REG(IFX_DPS310_RATE_1, IFX_DPS310_RATE_2)
117 #define IFX_DPS310_T_SHIFT		0
118 #elif defined CONFIG_DPS310_TEMP_OSR_4X
119 #define IFX_DPS310_SF_TMP		IFX_DPS310_SF_OSR_4
120 #define IFX_DPS310_TMP_MEAS_TIME	IFX_DPS310_MEAS_TIME_OSR_4
121 #define IFX_DPS310_TMP_CFG		CFG_REG(IFX_DPS310_RATE_1, IFX_DPS310_RATE_4)
122 #define IFX_DPS310_T_SHIFT		0
123 #elif defined CONFIG_DPS310_TEMP_OSR_8X
124 #define IFX_DPS310_SF_TMP		IFX_DPS310_SF_OSR_8
125 #define IFX_DPS310_TMP_MEAS_TIME	IFX_DPS310_MEAS_TIME_OSR_8
126 #define IFX_DPS310_TMP_CFG		CFG_REG(IFX_DPS310_RATE_1, IFX_DPS310_RATE_8)
127 #define IFX_DPS310_T_SHIFT		0
128 #elif defined CONFIG_DPS310_TEMP_OSR_16X
129 #define IFX_DPS310_SF_TMP		IFX_DPS310_SF_OSR_16
130 #define IFX_DPS310_TMP_MEAS_TIME	IFX_DPS310_MEAS_TIME_OSR_16
131 #define IFX_DPS310_TMP_CFG		CFG_REG(IFX_DPS310_RATE_1, IFX_DPS310_RATE_16)
132 #define IFX_DPS310_T_SHIFT		1
133 #elif defined CONFIG_DPS310_TEMP_OSR_32X
134 #define IFX_DPS310_SF_TMP		IFX_DPS310_SF_OSR_32
135 #define IFX_DPS310_TMP_MEAS_TIME	IFX_DPS310_MEAS_TIME_OSR_32
136 #define IFX_DPS310_TMP_CFG		CFG_REG(IFX_DPS310_RATE_1, IFX_DPS310_RATE_32)
137 #define IFX_DPS310_T_SHIFT		1
138 #elif defined CONFIG_DPS310_TEMP_OSR_64X
139 #define IFX_DPS310_SF_TMP		IFX_DPS310_SF_OSR_64
140 #define IFX_DPS310_TMP_MEAS_TIME	IFX_DPS310_MEAS_TIME_OSR_64
141 #define IFX_DPS310_TMP_CFG		CFG_REG(IFX_DPS310_RATE_1, IFX_DPS310_RATE_64)
142 #define IFX_DPS310_T_SHIFT		1
143 #elif defined CONFIG_DPS310_TEMP_OSR_128X
144 #define IFX_DPS310_SF_TMP		IFX_DPS310_SF_OSR_128
145 #define IFX_DPS310_TMP_MEAS_TIME	IFX_DPS310_MEAS_TIME_OSR_128
146 #define IFX_DPS310_TMP_CFG		CFG_REG(IFX_DPS310_RATE_1, IFX_DPS310_RATE_128)
147 #define IFX_DPS310_T_SHIFT		1
148 #endif
149 
150 /* Setup constants depending on pressure oversampling factor */
151 #if defined CONFIG_DPS310_PRESS_OSR_1X
152 #define IFX_DPS310_SF_PSR		IFX_DPS310_SF_OSR_1
153 #define IFX_DPS310_PSR_MEAS_TIME	IFX_DPS310_MEAS_TIME_OSR_1
154 #define IFX_DPS310_PSR_CFG		CFG_REG(IFX_DPS310_RATE_1, IFX_DPS310_RATE_1)
155 #define IFX_DPS310_P_SHIFT		0
156 #elif defined CONFIG_DPS310_PRESS_OSR_2X
157 #define IFX_DPS310_SF_PSR		IFX_DPS310_SF_OSR_2
158 #define IFX_DPS310_PSR_MEAS_TIME	IFX_DPS310_MEAS_TIME_OSR_2
159 #define IFX_DPS310_PSR_CFG		CFG_REG(IFX_DPS310_RATE_1, IFX_DPS310_RATE_2)
160 #define IFX_DPS310_P_SHIFT		0
161 #elif defined CONFIG_DPS310_PRESS_OSR_4X
162 #define IFX_DPS310_SF_PSR		IFX_DPS310_SF_OSR_4
163 #define IFX_DPS310_PSR_MEAS_TIME	IFX_DPS310_MEAS_TIME_OSR_4
164 #define IFX_DPS310_PSR_CFG		CFG_REG(IFX_DPS310_RATE_1, IFX_DPS310_RATE_4)
165 #define IFX_DPS310_P_SHIFT		0
166 #elif defined CONFIG_DPS310_PRESS_OSR_8X
167 #define IFX_DPS310_SF_PSR		IFX_DPS310_SF_OSR_8
168 #define IFX_DPS310_PSR_MEAS_TIME	IFX_DPS310_MEAS_TIME_OSR_8
169 #define IFX_DPS310_PSR_CFG		CFG_REG(IFX_DPS310_RATE_1, IFX_DPS310_RATE_8)
170 #define IFX_DPS310_P_SHIFT		0
171 #elif defined CONFIG_DPS310_PRESS_OSR_16X
172 #define IFX_DPS310_SF_PSR		IFX_DPS310_SF_OSR_16
173 #define IFX_DPS310_PSR_MEAS_TIME	IFX_DPS310_MEAS_TIME_OSR_16
174 #define IFX_DPS310_PSR_CFG		CFG_REG(IFX_DPS310_RATE_1, IFX_DPS310_RATE_16)
175 #define IFX_DPS310_P_SHIFT		1
176 #elif defined CONFIG_DPS310_PRESS_OSR_32X
177 #define IFX_DPS310_SF_PSR		IFX_DPS310_SF_OSR_32
178 #define IFX_DPS310_PSR_MEAS_TIME	IFX_DPS310_MEAS_TIME_OSR_32
179 #define IFX_DPS310_PSR_CFG		CFG_REG(IFX_DPS310_RATE_1, IFX_DPS310_RATE_32)
180 #define IFX_DPS310_P_SHIFT		1
181 #elif defined CONFIG_DPS310_PRESS_OSR_64X
182 #define IFX_DPS310_SF_PSR		IFX_DPS310_SF_OSR_64
183 #define IFX_DPS310_PSR_MEAS_TIME	IFX_DPS310_MEAS_TIME_OSR_64
184 #define IFX_DPS310_PSR_CFG		CFG_REG(IFX_DPS310_RATE_1, IFX_DPS310_RATE_64)
185 #define IFX_DPS310_P_SHIFT		1
186 #elif defined CONFIG_DPS310_PRESS_OSR_128X
187 #define IFX_DPS310_SF_PSR		IFX_DPS310_SF_OSR_128
188 #define IFX_DPS310_PSR_MEAS_TIME	IFX_DPS310_MEAS_TIME_OSR_128
189 #define IFX_DPS310_PSR_CFG		CFG_REG(IFX_DPS310_RATE_1, IFX_DPS310_RATE_128)
190 #define IFX_DPS310_P_SHIFT		1
191 #endif
192 
193 #define DPS310_CFG_REG                                                         \
194 	(((IFX_DPS310_T_SHIFT & 0x01) << 3) |                                  \
195 	 ((IFX_DPS310_P_SHIFT & 0x01) << 2))
196 
197 #define HW_BUG_FIX_SEQUENCE_LEN	5
198 
199 #define POW_2_23_MINUS_1	BIT_MASK(23)
200 #define POW_2_24		BIT(24)
201 #define POW_2_15_MINUS_1	BIT_MASK(15)
202 #define POW_2_16		BIT(16)
203 #define POW_2_11_MINUS_1	BIT_MASK(11)
204 #define POW_2_12		BIT(12)
205 #define POW_2_20		BIT(20)
206 #define POW_2_19_MINUS_1	BIT_MASK(19)
207 
208 /* Needed because the values are referenced by pointer. */
209 static const uint8_t REG_ADDR_MEAS_CFG = IFX_DPS310_REG_ADDR_MEAS_CFG;
210 static const uint8_t REG_ADDR_CALIB_COEFF_0 = IFX_DPS310_REG_ADDR_COEF_0;
211 static const uint8_t REG_ADDR_TMP_B2 = IFX_DPS310_REG_ADDR_TMP_B2;
212 static const uint8_t REG_ADDR_PSR_B2 = IFX_DPS310_REG_ADDR_PSR_B2;
213 static const uint8_t REG_ADDR_COEF_SRCE = IFX_DPS310_REG_ADDR_COEF_SRCE;
214 
215 /* calibration coefficients */
216 struct dps310_cal_coeff {
217 	/* Pressure Sensor Calibration Coefficients */
218 	int32_t c00; /* 20bit */
219 	int32_t c10; /* 20bit */
220 	int16_t c01; /* 16bit */
221 	int16_t c11; /* 16bit */
222 	int16_t c20; /* 16bit */
223 	int16_t c21; /* 16bit */
224 	int16_t c30; /* 16bit */
225 	/* Temperature Sensor Calibration Coefficients */
226 	int16_t c0; /* 12bit */
227 	int16_t c1; /* 12bit */
228 };
229 
230 struct dps310_data {
231 	struct dps310_cal_coeff comp;
232 	/* Temperature Values */
233 	int32_t tmp_val1;
234 	int32_t tmp_val2;
235 	/* Last raw temperature value for temperature compensation */
236 	int32_t raw_tmp;
237 	/* Pressure Values */
238 	int32_t psr_val1;
239 	int32_t psr_val2;
240 };
241 
242 struct dps310_cfg {
243 	struct i2c_dt_spec i2c;
244 };
245 
246 /*
247  * Convert the bytes from calibration memory to calibration coefficients
248  * structure
249  */
dps310_calib_coeff_creation(const uint8_t raw_coef[18],struct dps310_cal_coeff * comp)250 static void dps310_calib_coeff_creation(const uint8_t raw_coef[18],
251 					struct dps310_cal_coeff *comp)
252 {
253 	/* Temperature sensor compensation values */
254 	comp->c0 = (((uint16_t)raw_coef[0]) << 4) + (raw_coef[1] >> 4);
255 	/* coefficient is 2nd compliment */
256 	if (comp->c0 > POW_2_11_MINUS_1) {
257 		comp->c0 = comp->c0 - POW_2_12;
258 	}
259 
260 	comp->c1 = (((uint16_t)(raw_coef[1] & 0x0F)) << 8) + raw_coef[2];
261 	/* coefficient is 2nd compliment */
262 	if (comp->c1 > POW_2_11_MINUS_1) {
263 		comp->c1 = comp->c1 - POW_2_12;
264 	}
265 
266 	/* Pressure sensor compensation values */
267 	comp->c00 = (((uint32_t)raw_coef[3]) << 12) + (((uint16_t)raw_coef[4]) << 4) +
268 		    (raw_coef[5] >> 4);
269 	/* coefficient is 2nd compliment */
270 	if (comp->c00 > POW_2_19_MINUS_1) {
271 		comp->c00 = comp->c00 - POW_2_20;
272 	}
273 
274 	comp->c10 = (((uint32_t)(raw_coef[5] & 0x0F)) << 16) +
275 		    (((uint16_t)raw_coef[6]) << 8) + raw_coef[7];
276 	/* coefficient is 2nd compliment */
277 	if (comp->c10 > POW_2_19_MINUS_1) {
278 		comp->c10 = comp->c10 - POW_2_20;
279 	}
280 
281 	comp->c01 = (int16_t) sys_get_be16(&raw_coef[8]);
282 	comp->c11 = (int16_t) sys_get_be16(&raw_coef[10]);
283 	comp->c20 = (int16_t) sys_get_be16(&raw_coef[12]);
284 	comp->c21 = (int16_t) sys_get_be16(&raw_coef[14]);
285 	comp->c30 = (int16_t) sys_get_be16(&raw_coef[16]);
286 }
287 
288 /* Poll one or multiple bits given by ready_mask in reg_addr */
poll_rdy(const struct device * dev,uint8_t reg_addr,uint8_t ready_mask)289 static bool poll_rdy(const struct device *dev, uint8_t reg_addr, uint8_t ready_mask)
290 {
291 	const struct dps310_cfg *config = dev->config;
292 	/* Try only a finite number of times */
293 	for (int i = 0; i < POLL_TRIES; i++) {
294 		uint8_t reg = 0;
295 		int res = i2c_reg_read_byte_dt(&config->i2c, reg_addr, &reg);
296 		if (res < 0) {
297 			LOG_WRN("I2C error: %d", res);
298 			return false;
299 		}
300 
301 		if ((reg & ready_mask) == ready_mask) {
302 			/* measurement is ready */
303 			return true;
304 		}
305 
306 		/* give the sensor more time */
307 		k_sleep(POLL_TIME_MS);
308 	}
309 
310 	return false;
311 }
312 
313 /* Trigger a temperature measurement and wait until the result is stored */
dps310_trigger_temperature(const struct device * dev)314 static bool dps310_trigger_temperature(const struct device *dev)
315 {
316 	const struct dps310_cfg *config = dev->config;
317 
318 	/* command to start temperature measurement */
319 	static const uint8_t tmp_meas_cmd[] = {
320 		IFX_DPS310_REG_ADDR_MEAS_CFG,
321 		IFX_DPS310_MODE_COMMAND_TEMPERATURE
322 	};
323 
324 	/* trigger temperature measurement */
325 	int res = i2c_write_dt(&config->i2c, tmp_meas_cmd, sizeof(tmp_meas_cmd));
326 	if (res < 0) {
327 		LOG_WRN("I2C error: %d", res);
328 		return false;
329 	}
330 
331 	/* give the sensor time to store measured values internally */
332 	k_msleep(IFX_DPS310_TMP_MEAS_TIME);
333 
334 	if (!poll_rdy(dev, IFX_DPS310_REG_ADDR_MEAS_CFG, IFX_DPS310_REG_ADDR_MEAS_CFG_TMP_RDY)) {
335 		LOG_DBG("Poll timeout for temperature");
336 		return false;
337 	}
338 
339 	return true;
340 }
341 
342 /* Trigger a pressure measurement and wait until the result is stored */
dps310_trigger_pressure(const struct device * dev)343 static bool dps310_trigger_pressure(const struct device *dev)
344 {
345 	const struct dps310_cfg *config = dev->config;
346 
347 	/* command to start pressure measurement */
348 	static const uint8_t psr_meas_cmd[] = {
349 		IFX_DPS310_REG_ADDR_MEAS_CFG,
350 		IFX_DPS310_MODE_COMMAND_PRESSURE
351 	};
352 
353 	/* trigger pressure measurement */
354 	int res = i2c_write_dt(&config->i2c, psr_meas_cmd, sizeof(psr_meas_cmd));
355 	if (res < 0) {
356 		LOG_WRN("I2C error: %d", res);
357 		return false;
358 	}
359 
360 	/* give the sensor time to store measured values internally */
361 	k_msleep(IFX_DPS310_PSR_MEAS_TIME);
362 
363 	if (!poll_rdy(dev, IFX_DPS310_REG_ADDR_MEAS_CFG, IFX_DPS310_REG_ADDR_MEAS_CFG_PRS_RDY)) {
364 		LOG_DBG("Poll timeout for pressure");
365 		return false;
366 	}
367 
368 	return true;
369 }
370 
371 /*
372  * function to fix a hardware problem on some devices
373  * you have this bug if you measure around 60°C when temperature is around 20°C
374  * call dps310_hw_bug_fix() directly in the init() function to fix this issue
375  */
dps310_hw_bug_fix(const struct device * dev)376 static void dps310_hw_bug_fix(const struct device *dev)
377 {
378 	const struct dps310_cfg *config = dev->config;
379 
380 	/* setup the necessary 5 sequences to fix the hw bug */
381 	static const uint8_t hw_bug_fix_sequence[HW_BUG_FIX_SEQUENCE_LEN][2] = {
382 		/*
383 		 * First write valid signature on 0x0e and 0x0f
384 		 * to unlock address 0x62
385 		 */
386 		{ 0x0E, 0xA5 },
387 		{ 0x0F, 0x96 },
388 		/* Then update high gain value for Temperature */
389 		{ 0x62, 0x02 },
390 		/* Finally lock back the location 0x62 */
391 		{ 0x0E, 0x00 },
392 		{ 0x0F, 0x00 }
393 	};
394 
395 	/* execute sequence for hw bug fix */
396 	for (int i = 0; i < HW_BUG_FIX_SEQUENCE_LEN; i++) {
397 		int res = i2c_write_dt(&config->i2c, hw_bug_fix_sequence[i], 2);
398 		if (res < 0) {
399 			LOG_WRN("I2C error: %d", res);
400 			return;
401 		}
402 	}
403 }
404 
405 /*
406  * Scale and compensate the raw temperature measurement value to micro °C
407  * The formula is based on the Chapter 4.9.2 in the datasheet and was
408  * modified to need only integer arithmetic.
409  */
dps310_scale_temperature(const struct device * dev,int32_t tmp_raw)410 static void dps310_scale_temperature(const struct device *dev, int32_t tmp_raw)
411 {
412 	struct dps310_data *data = dev->data;
413 	const struct dps310_cal_coeff *comp = &data->comp;
414 
415 	/* first term, rescaled to micro °C */
416 	int32_t tmp_p0 = (1000000 / 2) * comp->c0;
417 
418 	/* second term, rescaled to micro °C */
419 	int32_t tmp_p1 =
420 		(((int64_t)1000000) * comp->c1 * tmp_raw) / IFX_DPS310_SF_TMP;
421 
422 	/* calculate the temperature corresponding to the datasheet */
423 	int32_t tmp_final = tmp_p0 + tmp_p1; /* value is in micro °C */
424 
425 	/* store calculated value */
426 	data->tmp_val1 = tmp_final / 1000000;
427 	data->tmp_val2 = tmp_final % 1000000;
428 }
429 
430 /*
431  * Scale and temperature compensate the raw pressure measurement value to
432  * Kilopascal. The formula is based on the Chapter 4.9.1 in the datasheet.
433  */
dps310_scale_pressure(const struct device * dev,int32_t tmp_raw,int32_t psr_raw)434 static void dps310_scale_pressure(const struct device *dev, int32_t tmp_raw, int32_t psr_raw)
435 {
436 	struct dps310_data *data = dev->data;
437 	const struct dps310_cal_coeff *comp = &data->comp;
438 
439 	float psr = ((float)psr_raw) / IFX_DPS310_SF_PSR;
440 	float tmp = ((float)tmp_raw) / IFX_DPS310_SF_TMP;
441 
442 	/* scale according to formula from datasheet */
443 	float psr_final = comp->c00;
444 
445 	psr_final += psr * (comp->c10 + psr * (comp->c20 + psr * comp->c30));
446 	psr_final += tmp * comp->c01;
447 	psr_final += tmp * psr * (comp->c11 + psr * comp->c21);
448 
449 	/* rescale from Pascal to Kilopascal */
450 	psr_final /= 1000;
451 
452 	/* store calculated value */
453 	data->psr_val1 = psr_final;
454 	data->psr_val2 = (psr_final - data->psr_val1) * 1000000;
455 }
456 
457 /* Convert the raw sensor data to int32_t */
raw_to_int24(const uint8_t raw[3])458 static int32_t raw_to_int24(const uint8_t raw[3])
459 {
460 	/* convert from twos complement */
461 	int32_t res = (int32_t) sys_get_be24(raw);
462 
463 	if (res > POW_2_23_MINUS_1) {
464 		res -= POW_2_24;
465 	}
466 
467 	return res;
468 }
469 
470 /* perform a single measurement of temperature and pressure */
dps310_measure_tmp_psr(const struct device * dev)471 static bool dps310_measure_tmp_psr(const struct device *dev)
472 {
473 	struct dps310_data *data = dev->data;
474 	const struct dps310_cfg *config = dev->config;
475 
476 	if (!dps310_trigger_temperature(dev)) {
477 		return false;
478 	}
479 
480 	if (!dps310_trigger_pressure(dev)) {
481 		return false;
482 	}
483 
484 	/* memory for pressure and temperature raw values */
485 	uint8_t value_raw[6];
486 
487 	/* read pressure and temperature raw values in one continuous read */
488 	int res = i2c_write_read_dt(&config->i2c, &REG_ADDR_PSR_B2, 1,
489 				    &value_raw, sizeof(value_raw));
490 	if (res < 0) {
491 		LOG_WRN("I2C error: %d", res);
492 		return false;
493 	}
494 
495 	/* convert raw data to int */
496 	int32_t psr_raw = raw_to_int24(&value_raw[0]);
497 
498 	data->raw_tmp = raw_to_int24(&value_raw[3]);
499 
500 	dps310_scale_temperature(dev, data->raw_tmp);
501 	dps310_scale_pressure(dev, data->raw_tmp, psr_raw);
502 
503 	return true;
504 }
505 
506 /*
507  * perform a single pressure measurement
508  * uses the stored temperature value for sensor temperature compensation
509  * temperature must be measured regularly for good temperature compensation
510  */
dps310_measure_psr(const struct device * dev)511 static bool dps310_measure_psr(const struct device *dev)
512 {
513 	struct dps310_data *data = dev->data;
514 	const struct dps310_cfg *config = dev->config;
515 
516 	/* measure pressure */
517 	if (!dps310_trigger_pressure(dev)) {
518 		return false;
519 	}
520 
521 	/* memory for pressure raw value */
522 	uint8_t value_raw[3];
523 
524 	/* read pressure raw values in one continuous read */
525 	int res = i2c_write_read_dt(&config->i2c, &REG_ADDR_PSR_B2, 1,
526 				    &value_raw, sizeof(value_raw));
527 	if (res < 0) {
528 		LOG_WRN("I2C error: %d", res);
529 		return false;
530 	}
531 
532 	/* convert raw data to int */
533 	int32_t psr_raw = raw_to_int24(&value_raw[0]);
534 
535 	dps310_scale_pressure(dev, data->raw_tmp, psr_raw);
536 
537 	return true;
538 }
539 
540 /* perform a single temperature measurement */
dps310_measure_tmp(const struct device * dev)541 static bool dps310_measure_tmp(const struct device *dev)
542 {
543 	struct dps310_data *data = dev->data;
544 	const struct dps310_cfg *config = dev->config;
545 
546 	/* measure temperature */
547 	if (!dps310_trigger_temperature(dev)) {
548 		return false;
549 	}
550 
551 	/* memory for temperature raw value */
552 	uint8_t value_raw[3];
553 
554 	/* read temperature raw values in one continuous read */
555 	int res = i2c_write_read_dt(&config->i2c, &REG_ADDR_TMP_B2, 1,
556 				    &value_raw, sizeof(value_raw));
557 	if (res < 0) {
558 		LOG_WRN("I2C error: %d", res);
559 		return false;
560 	}
561 
562 	/* convert raw data to int */
563 	data->raw_tmp = raw_to_int24(&value_raw[0]);
564 
565 	dps310_scale_temperature(dev, data->raw_tmp);
566 
567 	return true;
568 }
569 
570 /* Initialize the sensor and apply the configuration */
dps310_init(const struct device * dev)571 static int dps310_init(const struct device *dev)
572 {
573 	struct dps310_data *data = dev->data;
574 	const struct dps310_cfg *config = dev->config;
575 
576 	if (!device_is_ready(config->i2c.bus)) {
577 		LOG_ERR("I2C bus device not ready");
578 		return -ENODEV;
579 	}
580 
581 	uint8_t product_id = 0;
582 	int res = i2c_reg_read_byte_dt(&config->i2c, IFX_DPS310_REG_ADDR_PRODUCT_ID, &product_id);
583 
584 	if (res < 0) {
585 		LOG_ERR("No device found");
586 		return -EINVAL;
587 	}
588 
589 	if (product_id != IFX_DPS310_PRODUCT_ID) {
590 		LOG_ERR("Device is not a DPS310");
591 		return -EINVAL;
592 	}
593 
594 	LOG_DBG("Init DPS310");
595 	/* give the sensor time to load the calibration data */
596 	k_sleep(K_MSEC(40));
597 
598 	/* wait for the sensor to load the calibration data */
599 	if (!poll_rdy(dev, REG_ADDR_MEAS_CFG, IFX_DPS310_REG_ADDR_MEAS_CFG_SELF_INIT_OK)) {
600 		LOG_DBG("Sensor not ready");
601 		return -EIO;
602 	}
603 
604 	/* read calibration coefficients */
605 	uint8_t raw_coef[18] = { 0 };
606 
607 	res = i2c_write_read_dt(&config->i2c, &REG_ADDR_CALIB_COEFF_0, 1, &raw_coef, 18);
608 	if (res < 0) {
609 		LOG_WRN("I2C error: %d", res);
610 		return -EIO;
611 	}
612 
613 	/* convert calibration coefficients */
614 	dps310_calib_coeff_creation(raw_coef, &data->comp);
615 
616 	/*
617 	 * check which temperature sensor was used for calibration and use it
618 	 * for measurements.
619 	 */
620 	uint8_t tmp_coef_srce = 0;
621 
622 	res = i2c_write_read_dt(&config->i2c, &REG_ADDR_COEF_SRCE, 1, &tmp_coef_srce,
623 				sizeof(tmp_coef_srce));
624 	if (res < 0) {
625 		LOG_WRN("I2C error: %d", res);
626 		return -EIO;
627 	}
628 
629 	/* clear all other bits */
630 	tmp_coef_srce &= IFX_DPS310_COEF_SRCE_MASK;
631 
632 	/* merge with temperature measurement configuration */
633 	tmp_coef_srce |= IFX_DPS310_TMP_CFG;
634 
635 	/* set complete configuration in one write */
636 	const uint8_t config_seq[] = {
637 		IFX_DPS310_REG_ADDR_PRS_CFG,	/* start register address */
638 		IFX_DPS310_PSR_CFG,		/* PSR_CFG */
639 		tmp_coef_srce,			/* TMP_CFG */
640 		0x00,				/* MEAS_CFG */
641 		DPS310_CFG_REG			/* CFG_REG */
642 	};
643 
644 	res = i2c_write_dt(&config->i2c, config_seq, sizeof(config_seq));
645 	if (res < 0) {
646 		LOG_WRN("I2C error: %d", res);
647 		return -EIO;
648 	}
649 
650 	dps310_hw_bug_fix(dev);
651 	dps310_measure_tmp_psr(dev);
652 
653 	LOG_DBG("Init OK");
654 	return 0;
655 }
656 
657 /* Do a measurement and fetch the data from the sensor */
dps310_sample_fetch(const struct device * dev,enum sensor_channel chan)658 static int dps310_sample_fetch(const struct device *dev,
659 			       enum sensor_channel chan)
660 {
661 	LOG_DBG("Fetching sample from DPS310");
662 
663 	switch (chan) {
664 	case SENSOR_CHAN_AMBIENT_TEMP:
665 		if (!dps310_measure_tmp(dev)) {
666 			LOG_ERR("Failed to measure temperature");
667 			return -EIO;
668 		}
669 		break;
670 	case SENSOR_CHAN_PRESS:
671 		if (!dps310_measure_psr(dev)) {
672 			LOG_ERR("Failed to measure pressure");
673 			return -EIO;
674 		}
675 		break;
676 	case SENSOR_CHAN_ALL:
677 		if (!dps310_measure_tmp_psr(dev)) {
678 			LOG_ERR("Failed to measure temperature and pressure");
679 			return -EIO;
680 		}
681 		break;
682 	default:
683 		return -EINVAL;
684 	}
685 
686 	return 0;
687 }
688 
689 /* Get the measurement data */
dps310_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)690 static int dps310_channel_get(const struct device *dev,
691 			      enum sensor_channel chan,
692 			      struct sensor_value *val)
693 {
694 	struct dps310_data *data = dev->data;
695 
696 	switch (chan) {
697 	case SENSOR_CHAN_AMBIENT_TEMP:
698 		val->val1 = data->tmp_val1;
699 		val->val2 = data->tmp_val2;
700 		break;
701 	case SENSOR_CHAN_PRESS:
702 		val->val1 = data->psr_val1;
703 		val->val2 = data->psr_val2;
704 		break;
705 	default:
706 		return -ENOTSUP;
707 	}
708 
709 	return 0;
710 }
711 
712 static const struct sensor_driver_api dps310_api_funcs = {
713 	.sample_fetch = dps310_sample_fetch,
714 	.channel_get = dps310_channel_get,
715 };
716 
717 #define DPS310_DEFINE(inst)								\
718 	static struct dps310_data dps310_data_##inst;					\
719 											\
720 	static const struct dps310_cfg dps310_cfg_##inst = {				\
721 		.i2c = I2C_DT_SPEC_INST_GET(inst),					\
722 	};										\
723 											\
724 	SENSOR_DEVICE_DT_INST_DEFINE(inst, dps310_init, NULL,				\
725 			      &dps310_data_##inst, &dps310_cfg_##inst, POST_KERNEL,	\
726 			      CONFIG_SENSOR_INIT_PRIORITY, &dps310_api_funcs);		\
727 
728 DT_INST_FOREACH_STATUS_OKAY(DPS310_DEFINE)
729