1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | // Copyright IBM Corp 2019 |
3 | /* |
4 | * The DPS310 is a barometric pressure and temperature sensor. |
5 | * Currently only reading a single temperature is supported by |
6 | * this driver. |
7 | * |
8 | * https://www.infineon.com/dgdl/?fileId=5546d462576f34750157750826c42242 |
9 | * |
10 | * Temperature calculation: |
11 | * c0 * 0.5 + c1 * T_raw / kT °C |
12 | * |
13 | * TODO: |
14 | * - Optionally support the FIFO |
15 | */ |
16 | |
17 | #include <linux/i2c.h> |
18 | #include <linux/limits.h> |
19 | #include <linux/math64.h> |
20 | #include <linux/module.h> |
21 | #include <linux/regmap.h> |
22 | |
23 | #include <linux/iio/iio.h> |
24 | #include <linux/iio/sysfs.h> |
25 | |
26 | #define DPS310_DEV_NAME "dps310" |
27 | |
28 | #define DPS310_PRS_B0 0x00 |
29 | #define DPS310_PRS_B1 0x01 |
30 | #define DPS310_PRS_B2 0x02 |
31 | #define DPS310_TMP_B0 0x03 |
32 | #define DPS310_TMP_B1 0x04 |
33 | #define DPS310_TMP_B2 0x05 |
34 | #define DPS310_PRS_CFG 0x06 |
35 | #define DPS310_PRS_RATE_BITS GENMASK(6, 4) |
36 | #define DPS310_PRS_PRC_BITS GENMASK(3, 0) |
37 | #define DPS310_TMP_CFG 0x07 |
38 | #define DPS310_TMP_RATE_BITS GENMASK(6, 4) |
39 | #define DPS310_TMP_PRC_BITS GENMASK(3, 0) |
40 | #define DPS310_TMP_EXT BIT(7) |
41 | #define DPS310_MEAS_CFG 0x08 |
42 | #define DPS310_MEAS_CTRL_BITS GENMASK(2, 0) |
43 | #define DPS310_PRS_EN BIT(0) |
44 | #define DPS310_TEMP_EN BIT(1) |
45 | #define DPS310_BACKGROUND BIT(2) |
46 | #define DPS310_PRS_RDY BIT(4) |
47 | #define DPS310_TMP_RDY BIT(5) |
48 | #define DPS310_SENSOR_RDY BIT(6) |
49 | #define DPS310_COEF_RDY BIT(7) |
50 | #define DPS310_CFG_REG 0x09 |
51 | #define DPS310_INT_HL BIT(7) |
52 | #define DPS310_TMP_SHIFT_EN BIT(3) |
53 | #define DPS310_PRS_SHIFT_EN BIT(4) |
54 | #define DPS310_FIFO_EN BIT(5) |
55 | #define DPS310_SPI_EN BIT(6) |
56 | #define DPS310_RESET 0x0c |
57 | #define DPS310_RESET_MAGIC 0x09 |
58 | #define DPS310_COEF_BASE 0x10 |
59 | |
60 | /* Make sure sleep time is <= 30ms for usleep_range */ |
61 | #define DPS310_POLL_SLEEP_US(t) min(30000, (t) / 8) |
62 | /* Silently handle error in rate value here */ |
63 | #define DPS310_POLL_TIMEOUT_US(rc) ((rc) <= 0 ? 1000000 : 1000000 / (rc)) |
64 | |
65 | #define DPS310_PRS_BASE DPS310_PRS_B0 |
66 | #define DPS310_TMP_BASE DPS310_TMP_B0 |
67 | |
68 | /* |
69 | * These values (defined in the spec) indicate how to scale the raw register |
70 | * values for each level of precision available. |
71 | */ |
72 | static const int scale_factors[] = { |
73 | 524288, |
74 | 1572864, |
75 | 3670016, |
76 | 7864320, |
77 | 253952, |
78 | 516096, |
79 | 1040384, |
80 | 2088960, |
81 | }; |
82 | |
83 | struct dps310_data { |
84 | struct i2c_client *client; |
85 | struct regmap *regmap; |
86 | struct mutex lock; /* Lock for sequential HW access functions */ |
87 | |
88 | s32 c0, c1; |
89 | s32 c00, c10, c20, c30, c01, c11, c21; |
90 | s32 pressure_raw; |
91 | s32 temp_raw; |
92 | bool timeout_recovery_failed; |
93 | }; |
94 | |
95 | static const struct iio_chan_spec dps310_channels[] = { |
96 | { |
97 | .type = IIO_TEMP, |
98 | .info_mask_separate = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) | |
99 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
100 | BIT(IIO_CHAN_INFO_PROCESSED), |
101 | }, |
102 | { |
103 | .type = IIO_PRESSURE, |
104 | .info_mask_separate = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO) | |
105 | BIT(IIO_CHAN_INFO_SAMP_FREQ) | |
106 | BIT(IIO_CHAN_INFO_PROCESSED), |
107 | }, |
108 | }; |
109 | |
110 | /* To be called after checking the COEF_RDY bit in MEAS_CFG */ |
111 | static int dps310_get_coefs(struct dps310_data *data) |
112 | { |
113 | int rc; |
114 | u8 coef[18]; |
115 | u32 c0, c1; |
116 | u32 c00, c10, c20, c30, c01, c11, c21; |
117 | |
118 | /* Read all sensor calibration coefficients from the COEF registers. */ |
119 | rc = regmap_bulk_read(map: data->regmap, DPS310_COEF_BASE, val: coef, |
120 | val_count: sizeof(coef)); |
121 | if (rc < 0) |
122 | return rc; |
123 | |
124 | /* |
125 | * Calculate temperature calibration coefficients c0 and c1. The |
126 | * numbers are 12-bit 2's complement numbers. |
127 | */ |
128 | c0 = (coef[0] << 4) | (coef[1] >> 4); |
129 | data->c0 = sign_extend32(value: c0, index: 11); |
130 | |
131 | c1 = ((coef[1] & GENMASK(3, 0)) << 8) | coef[2]; |
132 | data->c1 = sign_extend32(value: c1, index: 11); |
133 | |
134 | /* |
135 | * Calculate pressure calibration coefficients. c00 and c10 are 20 bit |
136 | * 2's complement numbers, while the rest are 16 bit 2's complement |
137 | * numbers. |
138 | */ |
139 | c00 = (coef[3] << 12) | (coef[4] << 4) | (coef[5] >> 4); |
140 | data->c00 = sign_extend32(value: c00, index: 19); |
141 | |
142 | c10 = ((coef[5] & GENMASK(3, 0)) << 16) | (coef[6] << 8) | coef[7]; |
143 | data->c10 = sign_extend32(value: c10, index: 19); |
144 | |
145 | c01 = (coef[8] << 8) | coef[9]; |
146 | data->c01 = sign_extend32(value: c01, index: 15); |
147 | |
148 | c11 = (coef[10] << 8) | coef[11]; |
149 | data->c11 = sign_extend32(value: c11, index: 15); |
150 | |
151 | c20 = (coef[12] << 8) | coef[13]; |
152 | data->c20 = sign_extend32(value: c20, index: 15); |
153 | |
154 | c21 = (coef[14] << 8) | coef[15]; |
155 | data->c21 = sign_extend32(value: c21, index: 15); |
156 | |
157 | c30 = (coef[16] << 8) | coef[17]; |
158 | data->c30 = sign_extend32(value: c30, index: 15); |
159 | |
160 | return 0; |
161 | } |
162 | |
163 | /* |
164 | * Some versions of the chip will read temperatures in the ~60C range when |
165 | * it's actually ~20C. This is the manufacturer recommended workaround |
166 | * to correct the issue. The registers used below are undocumented. |
167 | */ |
168 | static int dps310_temp_workaround(struct dps310_data *data) |
169 | { |
170 | int rc; |
171 | int reg; |
172 | |
173 | rc = regmap_read(map: data->regmap, reg: 0x32, val: ®); |
174 | if (rc) |
175 | return rc; |
176 | |
177 | /* |
178 | * If bit 1 is set then the device is okay, and the workaround does not |
179 | * need to be applied |
180 | */ |
181 | if (reg & BIT(1)) |
182 | return 0; |
183 | |
184 | rc = regmap_write(map: data->regmap, reg: 0x0e, val: 0xA5); |
185 | if (rc) |
186 | return rc; |
187 | |
188 | rc = regmap_write(map: data->regmap, reg: 0x0f, val: 0x96); |
189 | if (rc) |
190 | return rc; |
191 | |
192 | rc = regmap_write(map: data->regmap, reg: 0x62, val: 0x02); |
193 | if (rc) |
194 | return rc; |
195 | |
196 | rc = regmap_write(map: data->regmap, reg: 0x0e, val: 0x00); |
197 | if (rc) |
198 | return rc; |
199 | |
200 | return regmap_write(map: data->regmap, reg: 0x0f, val: 0x00); |
201 | } |
202 | |
203 | static int dps310_startup(struct dps310_data *data) |
204 | { |
205 | int rc; |
206 | int ready; |
207 | |
208 | /* |
209 | * Set up pressure sensor in single sample, one measurement per second |
210 | * mode |
211 | */ |
212 | rc = regmap_write(map: data->regmap, DPS310_PRS_CFG, val: 0); |
213 | if (rc) |
214 | return rc; |
215 | |
216 | /* |
217 | * Set up external (MEMS) temperature sensor in single sample, one |
218 | * measurement per second mode |
219 | */ |
220 | rc = regmap_write(map: data->regmap, DPS310_TMP_CFG, DPS310_TMP_EXT); |
221 | if (rc) |
222 | return rc; |
223 | |
224 | /* Temp and pressure shifts are disabled when PRC <= 8 */ |
225 | rc = regmap_write_bits(map: data->regmap, DPS310_CFG_REG, |
226 | DPS310_PRS_SHIFT_EN | DPS310_TMP_SHIFT_EN, val: 0); |
227 | if (rc) |
228 | return rc; |
229 | |
230 | /* MEAS_CFG doesn't update correctly unless first written with 0 */ |
231 | rc = regmap_write_bits(map: data->regmap, DPS310_MEAS_CFG, |
232 | DPS310_MEAS_CTRL_BITS, val: 0); |
233 | if (rc) |
234 | return rc; |
235 | |
236 | /* Turn on temperature and pressure measurement in the background */ |
237 | rc = regmap_write_bits(map: data->regmap, DPS310_MEAS_CFG, |
238 | DPS310_MEAS_CTRL_BITS, DPS310_PRS_EN | |
239 | DPS310_TEMP_EN | DPS310_BACKGROUND); |
240 | if (rc) |
241 | return rc; |
242 | |
243 | /* |
244 | * Calibration coefficients required for reporting temperature. |
245 | * They are available 40ms after the device has started |
246 | */ |
247 | rc = regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG, ready, |
248 | ready & DPS310_COEF_RDY, 10000, 40000); |
249 | if (rc) |
250 | return rc; |
251 | |
252 | rc = dps310_get_coefs(data); |
253 | if (rc) |
254 | return rc; |
255 | |
256 | return dps310_temp_workaround(data); |
257 | } |
258 | |
259 | static int dps310_get_pres_precision(struct dps310_data *data) |
260 | { |
261 | int rc; |
262 | int val; |
263 | |
264 | rc = regmap_read(map: data->regmap, DPS310_PRS_CFG, val: &val); |
265 | if (rc < 0) |
266 | return rc; |
267 | |
268 | return BIT(val & GENMASK(2, 0)); |
269 | } |
270 | |
271 | static int dps310_get_temp_precision(struct dps310_data *data) |
272 | { |
273 | int rc; |
274 | int val; |
275 | |
276 | rc = regmap_read(map: data->regmap, DPS310_TMP_CFG, val: &val); |
277 | if (rc < 0) |
278 | return rc; |
279 | |
280 | /* |
281 | * Scale factor is bottom 4 bits of the register, but 1111 is |
282 | * reserved so just grab bottom three |
283 | */ |
284 | return BIT(val & GENMASK(2, 0)); |
285 | } |
286 | |
287 | /* Called with lock held */ |
288 | static int dps310_set_pres_precision(struct dps310_data *data, int val) |
289 | { |
290 | int rc; |
291 | u8 shift_en; |
292 | |
293 | if (val < 0 || val > 128) |
294 | return -EINVAL; |
295 | |
296 | shift_en = val >= 16 ? DPS310_PRS_SHIFT_EN : 0; |
297 | rc = regmap_write_bits(map: data->regmap, DPS310_CFG_REG, |
298 | DPS310_PRS_SHIFT_EN, val: shift_en); |
299 | if (rc) |
300 | return rc; |
301 | |
302 | return regmap_update_bits(map: data->regmap, DPS310_PRS_CFG, |
303 | DPS310_PRS_PRC_BITS, ilog2(val)); |
304 | } |
305 | |
306 | /* Called with lock held */ |
307 | static int dps310_set_temp_precision(struct dps310_data *data, int val) |
308 | { |
309 | int rc; |
310 | u8 shift_en; |
311 | |
312 | if (val < 0 || val > 128) |
313 | return -EINVAL; |
314 | |
315 | shift_en = val >= 16 ? DPS310_TMP_SHIFT_EN : 0; |
316 | rc = regmap_write_bits(map: data->regmap, DPS310_CFG_REG, |
317 | DPS310_TMP_SHIFT_EN, val: shift_en); |
318 | if (rc) |
319 | return rc; |
320 | |
321 | return regmap_update_bits(map: data->regmap, DPS310_TMP_CFG, |
322 | DPS310_TMP_PRC_BITS, ilog2(val)); |
323 | } |
324 | |
325 | /* Called with lock held */ |
326 | static int dps310_set_pres_samp_freq(struct dps310_data *data, int freq) |
327 | { |
328 | u8 val; |
329 | |
330 | if (freq < 0 || freq > 128) |
331 | return -EINVAL; |
332 | |
333 | val = ilog2(freq) << 4; |
334 | |
335 | return regmap_update_bits(map: data->regmap, DPS310_PRS_CFG, |
336 | DPS310_PRS_RATE_BITS, val); |
337 | } |
338 | |
339 | /* Called with lock held */ |
340 | static int dps310_set_temp_samp_freq(struct dps310_data *data, int freq) |
341 | { |
342 | u8 val; |
343 | |
344 | if (freq < 0 || freq > 128) |
345 | return -EINVAL; |
346 | |
347 | val = ilog2(freq) << 4; |
348 | |
349 | return regmap_update_bits(map: data->regmap, DPS310_TMP_CFG, |
350 | DPS310_TMP_RATE_BITS, val); |
351 | } |
352 | |
353 | static int dps310_get_pres_samp_freq(struct dps310_data *data) |
354 | { |
355 | int rc; |
356 | int val; |
357 | |
358 | rc = regmap_read(map: data->regmap, DPS310_PRS_CFG, val: &val); |
359 | if (rc < 0) |
360 | return rc; |
361 | |
362 | return BIT((val & DPS310_PRS_RATE_BITS) >> 4); |
363 | } |
364 | |
365 | static int dps310_get_temp_samp_freq(struct dps310_data *data) |
366 | { |
367 | int rc; |
368 | int val; |
369 | |
370 | rc = regmap_read(map: data->regmap, DPS310_TMP_CFG, val: &val); |
371 | if (rc < 0) |
372 | return rc; |
373 | |
374 | return BIT((val & DPS310_TMP_RATE_BITS) >> 4); |
375 | } |
376 | |
377 | static int dps310_get_pres_k(struct dps310_data *data) |
378 | { |
379 | int rc = dps310_get_pres_precision(data); |
380 | |
381 | if (rc < 0) |
382 | return rc; |
383 | |
384 | return scale_factors[ilog2(rc)]; |
385 | } |
386 | |
387 | static int dps310_get_temp_k(struct dps310_data *data) |
388 | { |
389 | int rc = dps310_get_temp_precision(data); |
390 | |
391 | if (rc < 0) |
392 | return rc; |
393 | |
394 | return scale_factors[ilog2(rc)]; |
395 | } |
396 | |
397 | static int dps310_reset_wait(struct dps310_data *data) |
398 | { |
399 | int rc; |
400 | |
401 | rc = regmap_write(map: data->regmap, DPS310_RESET, DPS310_RESET_MAGIC); |
402 | if (rc) |
403 | return rc; |
404 | |
405 | /* Wait for device chip access: 15ms in specification */ |
406 | usleep_range(min: 15000, max: 55000); |
407 | return 0; |
408 | } |
409 | |
410 | static int dps310_reset_reinit(struct dps310_data *data) |
411 | { |
412 | int rc; |
413 | |
414 | rc = dps310_reset_wait(data); |
415 | if (rc) |
416 | return rc; |
417 | |
418 | return dps310_startup(data); |
419 | } |
420 | |
421 | static int dps310_ready_status(struct dps310_data *data, int ready_bit, int timeout) |
422 | { |
423 | int sleep = DPS310_POLL_SLEEP_US(timeout); |
424 | int ready; |
425 | |
426 | return regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG, ready, ready & ready_bit, |
427 | sleep, timeout); |
428 | } |
429 | |
430 | static int dps310_ready(struct dps310_data *data, int ready_bit, int timeout) |
431 | { |
432 | int rc; |
433 | |
434 | rc = dps310_ready_status(data, ready_bit, timeout); |
435 | if (rc) { |
436 | if (rc == -ETIMEDOUT && !data->timeout_recovery_failed) { |
437 | /* Reset and reinitialize the chip. */ |
438 | if (dps310_reset_reinit(data)) { |
439 | data->timeout_recovery_failed = true; |
440 | } else { |
441 | /* Try again to get sensor ready status. */ |
442 | if (dps310_ready_status(data, ready_bit, timeout)) |
443 | data->timeout_recovery_failed = true; |
444 | else |
445 | return 0; |
446 | } |
447 | } |
448 | |
449 | return rc; |
450 | } |
451 | |
452 | data->timeout_recovery_failed = false; |
453 | return 0; |
454 | } |
455 | |
456 | static int dps310_read_pres_raw(struct dps310_data *data) |
457 | { |
458 | int rc; |
459 | int rate; |
460 | int timeout; |
461 | s32 raw; |
462 | u8 val[3]; |
463 | |
464 | if (mutex_lock_interruptible(&data->lock)) |
465 | return -EINTR; |
466 | |
467 | rate = dps310_get_pres_samp_freq(data); |
468 | timeout = DPS310_POLL_TIMEOUT_US(rate); |
469 | |
470 | /* Poll for sensor readiness; base the timeout upon the sample rate. */ |
471 | rc = dps310_ready(data, DPS310_PRS_RDY, timeout); |
472 | if (rc) |
473 | goto done; |
474 | |
475 | rc = regmap_bulk_read(map: data->regmap, DPS310_PRS_BASE, val, val_count: sizeof(val)); |
476 | if (rc < 0) |
477 | goto done; |
478 | |
479 | raw = (val[0] << 16) | (val[1] << 8) | val[2]; |
480 | data->pressure_raw = sign_extend32(value: raw, index: 23); |
481 | |
482 | done: |
483 | mutex_unlock(lock: &data->lock); |
484 | return rc; |
485 | } |
486 | |
487 | /* Called with lock held */ |
488 | static int dps310_read_temp_ready(struct dps310_data *data) |
489 | { |
490 | int rc; |
491 | u8 val[3]; |
492 | s32 raw; |
493 | |
494 | rc = regmap_bulk_read(map: data->regmap, DPS310_TMP_BASE, val, val_count: sizeof(val)); |
495 | if (rc < 0) |
496 | return rc; |
497 | |
498 | raw = (val[0] << 16) | (val[1] << 8) | val[2]; |
499 | data->temp_raw = sign_extend32(value: raw, index: 23); |
500 | |
501 | return 0; |
502 | } |
503 | |
504 | static int dps310_read_temp_raw(struct dps310_data *data) |
505 | { |
506 | int rc; |
507 | int rate; |
508 | int timeout; |
509 | |
510 | if (mutex_lock_interruptible(&data->lock)) |
511 | return -EINTR; |
512 | |
513 | rate = dps310_get_temp_samp_freq(data); |
514 | timeout = DPS310_POLL_TIMEOUT_US(rate); |
515 | |
516 | /* Poll for sensor readiness; base the timeout upon the sample rate. */ |
517 | rc = dps310_ready(data, DPS310_TMP_RDY, timeout); |
518 | if (rc) |
519 | goto done; |
520 | |
521 | rc = dps310_read_temp_ready(data); |
522 | |
523 | done: |
524 | mutex_unlock(lock: &data->lock); |
525 | return rc; |
526 | } |
527 | |
528 | static bool dps310_is_writeable_reg(struct device *dev, unsigned int reg) |
529 | { |
530 | switch (reg) { |
531 | case DPS310_PRS_CFG: |
532 | case DPS310_TMP_CFG: |
533 | case DPS310_MEAS_CFG: |
534 | case DPS310_CFG_REG: |
535 | case DPS310_RESET: |
536 | /* No documentation available on the registers below */ |
537 | case 0x0e: |
538 | case 0x0f: |
539 | case 0x62: |
540 | return true; |
541 | default: |
542 | return false; |
543 | } |
544 | } |
545 | |
546 | static bool dps310_is_volatile_reg(struct device *dev, unsigned int reg) |
547 | { |
548 | switch (reg) { |
549 | case DPS310_PRS_B0: |
550 | case DPS310_PRS_B1: |
551 | case DPS310_PRS_B2: |
552 | case DPS310_TMP_B0: |
553 | case DPS310_TMP_B1: |
554 | case DPS310_TMP_B2: |
555 | case DPS310_MEAS_CFG: |
556 | case 0x32: /* No documentation available on this register */ |
557 | return true; |
558 | default: |
559 | return false; |
560 | } |
561 | } |
562 | |
563 | static int dps310_write_raw(struct iio_dev *iio, |
564 | struct iio_chan_spec const *chan, int val, |
565 | int val2, long mask) |
566 | { |
567 | int rc; |
568 | struct dps310_data *data = iio_priv(indio_dev: iio); |
569 | |
570 | if (mutex_lock_interruptible(&data->lock)) |
571 | return -EINTR; |
572 | |
573 | switch (mask) { |
574 | case IIO_CHAN_INFO_SAMP_FREQ: |
575 | switch (chan->type) { |
576 | case IIO_PRESSURE: |
577 | rc = dps310_set_pres_samp_freq(data, freq: val); |
578 | break; |
579 | |
580 | case IIO_TEMP: |
581 | rc = dps310_set_temp_samp_freq(data, freq: val); |
582 | break; |
583 | |
584 | default: |
585 | rc = -EINVAL; |
586 | break; |
587 | } |
588 | break; |
589 | |
590 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: |
591 | switch (chan->type) { |
592 | case IIO_PRESSURE: |
593 | rc = dps310_set_pres_precision(data, val); |
594 | break; |
595 | |
596 | case IIO_TEMP: |
597 | rc = dps310_set_temp_precision(data, val); |
598 | break; |
599 | |
600 | default: |
601 | rc = -EINVAL; |
602 | break; |
603 | } |
604 | break; |
605 | |
606 | default: |
607 | rc = -EINVAL; |
608 | break; |
609 | } |
610 | |
611 | mutex_unlock(lock: &data->lock); |
612 | return rc; |
613 | } |
614 | |
615 | static int dps310_calculate_pressure(struct dps310_data *data) |
616 | { |
617 | int i; |
618 | int rc; |
619 | int t_ready; |
620 | int kpi = dps310_get_pres_k(data); |
621 | int kti = dps310_get_temp_k(data); |
622 | s64 rem = 0ULL; |
623 | s64 pressure = 0ULL; |
624 | s64 p; |
625 | s64 t; |
626 | s64 denoms[7]; |
627 | s64 nums[7]; |
628 | s64 rems[7]; |
629 | s64 kp; |
630 | s64 kt; |
631 | |
632 | if (kpi < 0) |
633 | return kpi; |
634 | |
635 | if (kti < 0) |
636 | return kti; |
637 | |
638 | kp = (s64)kpi; |
639 | kt = (s64)kti; |
640 | |
641 | /* Refresh temp if it's ready, otherwise just use the latest value */ |
642 | if (mutex_trylock(lock: &data->lock)) { |
643 | rc = regmap_read(map: data->regmap, DPS310_MEAS_CFG, val: &t_ready); |
644 | if (rc >= 0 && t_ready & DPS310_TMP_RDY) |
645 | dps310_read_temp_ready(data); |
646 | |
647 | mutex_unlock(lock: &data->lock); |
648 | } |
649 | |
650 | p = (s64)data->pressure_raw; |
651 | t = (s64)data->temp_raw; |
652 | |
653 | /* Section 4.9.1 of the DPS310 spec; algebra'd to avoid underflow */ |
654 | nums[0] = (s64)data->c00; |
655 | denoms[0] = 1LL; |
656 | nums[1] = p * (s64)data->c10; |
657 | denoms[1] = kp; |
658 | nums[2] = p * p * (s64)data->c20; |
659 | denoms[2] = kp * kp; |
660 | nums[3] = p * p * p * (s64)data->c30; |
661 | denoms[3] = kp * kp * kp; |
662 | nums[4] = t * (s64)data->c01; |
663 | denoms[4] = kt; |
664 | nums[5] = t * p * (s64)data->c11; |
665 | denoms[5] = kp * kt; |
666 | nums[6] = t * p * p * (s64)data->c21; |
667 | denoms[6] = kp * kp * kt; |
668 | |
669 | /* Kernel lacks a div64_s64_rem function; denoms are all positive */ |
670 | for (i = 0; i < 7; ++i) { |
671 | u64 irem; |
672 | |
673 | if (nums[i] < 0LL) { |
674 | pressure -= div64_u64_rem(dividend: -nums[i], divisor: denoms[i], remainder: &irem); |
675 | rems[i] = -irem; |
676 | } else { |
677 | pressure += div64_u64_rem(dividend: nums[i], divisor: denoms[i], remainder: &irem); |
678 | rems[i] = (s64)irem; |
679 | } |
680 | } |
681 | |
682 | /* Increase precision and calculate the remainder sum */ |
683 | for (i = 0; i < 7; ++i) |
684 | rem += div64_s64(dividend: (s64)rems[i] * 1000000000LL, divisor: denoms[i]); |
685 | |
686 | pressure += div_s64(dividend: rem, divisor: 1000000000LL); |
687 | if (pressure < 0LL) |
688 | return -ERANGE; |
689 | |
690 | return (int)min_t(s64, pressure, INT_MAX); |
691 | } |
692 | |
693 | static int dps310_read_pressure(struct dps310_data *data, int *val, int *val2, |
694 | long mask) |
695 | { |
696 | int rc; |
697 | |
698 | switch (mask) { |
699 | case IIO_CHAN_INFO_SAMP_FREQ: |
700 | rc = dps310_get_pres_samp_freq(data); |
701 | if (rc < 0) |
702 | return rc; |
703 | |
704 | *val = rc; |
705 | return IIO_VAL_INT; |
706 | |
707 | case IIO_CHAN_INFO_PROCESSED: |
708 | rc = dps310_read_pres_raw(data); |
709 | if (rc) |
710 | return rc; |
711 | |
712 | rc = dps310_calculate_pressure(data); |
713 | if (rc < 0) |
714 | return rc; |
715 | |
716 | *val = rc; |
717 | *val2 = 1000; /* Convert Pa to KPa per IIO ABI */ |
718 | return IIO_VAL_FRACTIONAL; |
719 | |
720 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: |
721 | rc = dps310_get_pres_precision(data); |
722 | if (rc < 0) |
723 | return rc; |
724 | |
725 | *val = rc; |
726 | return IIO_VAL_INT; |
727 | |
728 | default: |
729 | return -EINVAL; |
730 | } |
731 | } |
732 | |
733 | static int dps310_calculate_temp(struct dps310_data *data) |
734 | { |
735 | s64 c0; |
736 | s64 t; |
737 | int kt = dps310_get_temp_k(data); |
738 | |
739 | if (kt < 0) |
740 | return kt; |
741 | |
742 | /* Obtain inverse-scaled offset */ |
743 | c0 = div_s64(dividend: (s64)kt * (s64)data->c0, divisor: 2); |
744 | |
745 | /* Add the offset to the unscaled temperature */ |
746 | t = c0 + ((s64)data->temp_raw * (s64)data->c1); |
747 | |
748 | /* Convert to milliCelsius and scale the temperature */ |
749 | return (int)div_s64(dividend: t * 1000LL, divisor: kt); |
750 | } |
751 | |
752 | static int dps310_read_temp(struct dps310_data *data, int *val, int *val2, |
753 | long mask) |
754 | { |
755 | int rc; |
756 | |
757 | switch (mask) { |
758 | case IIO_CHAN_INFO_SAMP_FREQ: |
759 | rc = dps310_get_temp_samp_freq(data); |
760 | if (rc < 0) |
761 | return rc; |
762 | |
763 | *val = rc; |
764 | return IIO_VAL_INT; |
765 | |
766 | case IIO_CHAN_INFO_PROCESSED: |
767 | rc = dps310_read_temp_raw(data); |
768 | if (rc) |
769 | return rc; |
770 | |
771 | rc = dps310_calculate_temp(data); |
772 | if (rc < 0) |
773 | return rc; |
774 | |
775 | *val = rc; |
776 | return IIO_VAL_INT; |
777 | |
778 | case IIO_CHAN_INFO_OVERSAMPLING_RATIO: |
779 | rc = dps310_get_temp_precision(data); |
780 | if (rc < 0) |
781 | return rc; |
782 | |
783 | *val = rc; |
784 | return IIO_VAL_INT; |
785 | |
786 | default: |
787 | return -EINVAL; |
788 | } |
789 | } |
790 | |
791 | static int dps310_read_raw(struct iio_dev *iio, |
792 | struct iio_chan_spec const *chan, |
793 | int *val, int *val2, long mask) |
794 | { |
795 | struct dps310_data *data = iio_priv(indio_dev: iio); |
796 | |
797 | switch (chan->type) { |
798 | case IIO_PRESSURE: |
799 | return dps310_read_pressure(data, val, val2, mask); |
800 | |
801 | case IIO_TEMP: |
802 | return dps310_read_temp(data, val, val2, mask); |
803 | |
804 | default: |
805 | return -EINVAL; |
806 | } |
807 | } |
808 | |
809 | static void dps310_reset(void *action_data) |
810 | { |
811 | struct dps310_data *data = action_data; |
812 | |
813 | dps310_reset_wait(data); |
814 | } |
815 | |
816 | static const struct regmap_config dps310_regmap_config = { |
817 | .reg_bits = 8, |
818 | .val_bits = 8, |
819 | .writeable_reg = dps310_is_writeable_reg, |
820 | .volatile_reg = dps310_is_volatile_reg, |
821 | .cache_type = REGCACHE_RBTREE, |
822 | .max_register = 0x62, /* No documentation available on this register */ |
823 | }; |
824 | |
825 | static const struct iio_info dps310_info = { |
826 | .read_raw = dps310_read_raw, |
827 | .write_raw = dps310_write_raw, |
828 | }; |
829 | |
830 | static int dps310_probe(struct i2c_client *client) |
831 | { |
832 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
833 | struct dps310_data *data; |
834 | struct iio_dev *iio; |
835 | int rc; |
836 | |
837 | iio = devm_iio_device_alloc(parent: &client->dev, sizeof_priv: sizeof(*data)); |
838 | if (!iio) |
839 | return -ENOMEM; |
840 | |
841 | data = iio_priv(indio_dev: iio); |
842 | data->client = client; |
843 | mutex_init(&data->lock); |
844 | |
845 | iio->name = id->name; |
846 | iio->channels = dps310_channels; |
847 | iio->num_channels = ARRAY_SIZE(dps310_channels); |
848 | iio->info = &dps310_info; |
849 | iio->modes = INDIO_DIRECT_MODE; |
850 | |
851 | data->regmap = devm_regmap_init_i2c(client, &dps310_regmap_config); |
852 | if (IS_ERR(ptr: data->regmap)) |
853 | return PTR_ERR(ptr: data->regmap); |
854 | |
855 | /* Register to run the device reset when the device is removed */ |
856 | rc = devm_add_action_or_reset(&client->dev, dps310_reset, data); |
857 | if (rc) |
858 | return rc; |
859 | |
860 | rc = dps310_startup(data); |
861 | if (rc) |
862 | return rc; |
863 | |
864 | rc = devm_iio_device_register(&client->dev, iio); |
865 | if (rc) |
866 | return rc; |
867 | |
868 | i2c_set_clientdata(client, data: iio); |
869 | |
870 | return 0; |
871 | } |
872 | |
873 | static const struct i2c_device_id dps310_id[] = { |
874 | { DPS310_DEV_NAME, 0 }, |
875 | {} |
876 | }; |
877 | MODULE_DEVICE_TABLE(i2c, dps310_id); |
878 | |
879 | static const struct acpi_device_id dps310_acpi_match[] = { |
880 | { "IFX3100" }, |
881 | {} |
882 | }; |
883 | MODULE_DEVICE_TABLE(acpi, dps310_acpi_match); |
884 | |
885 | static struct i2c_driver dps310_driver = { |
886 | .driver = { |
887 | .name = DPS310_DEV_NAME, |
888 | .acpi_match_table = dps310_acpi_match, |
889 | }, |
890 | .probe = dps310_probe, |
891 | .id_table = dps310_id, |
892 | }; |
893 | module_i2c_driver(dps310_driver); |
894 | |
895 | MODULE_AUTHOR("Joel Stanley <joel@jms.id.au>" ); |
896 | MODULE_DESCRIPTION("Infineon DPS310 pressure and temperature sensor" ); |
897 | MODULE_LICENSE("GPL v2" ); |
898 | |