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