16cfdb150STomasz Duszynski // SPDX-License-Identifier: GPL-2.0
2c0644160STomasz Duszynski /*
3c0644160STomasz Duszynski * MS5611 pressure and temperature sensor driver
4c0644160STomasz Duszynski *
5c0644160STomasz Duszynski * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com>
6c0644160STomasz Duszynski *
7c0644160STomasz Duszynski * Data sheet:
8c0644160STomasz Duszynski * http://www.meas-spec.com/downloads/MS5611-01BA03.pdf
99690d81aSTomasz Duszynski * http://www.meas-spec.com/downloads/MS5607-02BA03.pdf
10c0644160STomasz Duszynski *
11c0644160STomasz Duszynski */
12c0644160STomasz Duszynski
13c0644160STomasz Duszynski #include <linux/module.h>
14c0644160STomasz Duszynski #include <linux/iio/iio.h>
15c0644160STomasz Duszynski #include <linux/delay.h>
163145229fSGrégor Boirie #include <linux/regulator/consumer.h>
17c0644160STomasz Duszynski
18033691a9SGregor Boirie #include <linux/iio/sysfs.h>
19713bbb4eSDaniel Baluta #include <linux/iio/buffer.h>
20713bbb4eSDaniel Baluta #include <linux/iio/triggered_buffer.h>
21713bbb4eSDaniel Baluta #include <linux/iio/trigger_consumer.h>
22c0644160STomasz Duszynski #include "ms5611.h"
23c0644160STomasz Duszynski
24033691a9SGregor Boirie #define MS5611_INIT_OSR(_cmd, _conv_usec, _rate) \
25033691a9SGregor Boirie { .cmd = _cmd, .conv_usec = _conv_usec, .rate = _rate }
26033691a9SGregor Boirie
27033691a9SGregor Boirie static const struct ms5611_osr ms5611_avail_pressure_osr[] = {
28033691a9SGregor Boirie MS5611_INIT_OSR(0x40, 600, 256),
29033691a9SGregor Boirie MS5611_INIT_OSR(0x42, 1170, 512),
30033691a9SGregor Boirie MS5611_INIT_OSR(0x44, 2280, 1024),
31033691a9SGregor Boirie MS5611_INIT_OSR(0x46, 4540, 2048),
32033691a9SGregor Boirie MS5611_INIT_OSR(0x48, 9040, 4096)
33033691a9SGregor Boirie };
34033691a9SGregor Boirie
35033691a9SGregor Boirie static const struct ms5611_osr ms5611_avail_temp_osr[] = {
36033691a9SGregor Boirie MS5611_INIT_OSR(0x50, 600, 256),
37033691a9SGregor Boirie MS5611_INIT_OSR(0x52, 1170, 512),
38033691a9SGregor Boirie MS5611_INIT_OSR(0x54, 2280, 1024),
39033691a9SGregor Boirie MS5611_INIT_OSR(0x56, 4540, 2048),
40033691a9SGregor Boirie MS5611_INIT_OSR(0x58, 9040, 4096)
41033691a9SGregor Boirie };
42033691a9SGregor Boirie
43033691a9SGregor Boirie static const char ms5611_show_osr[] = "256 512 1024 2048 4096";
44033691a9SGregor Boirie
45033691a9SGregor Boirie static IIO_CONST_ATTR(oversampling_ratio_available, ms5611_show_osr);
46033691a9SGregor Boirie
47033691a9SGregor Boirie static struct attribute *ms5611_attributes[] = {
48033691a9SGregor Boirie &iio_const_attr_oversampling_ratio_available.dev_attr.attr,
49033691a9SGregor Boirie NULL,
50033691a9SGregor Boirie };
51033691a9SGregor Boirie
52033691a9SGregor Boirie static const struct attribute_group ms5611_attribute_group = {
53033691a9SGregor Boirie .attrs = ms5611_attributes,
54033691a9SGregor Boirie };
55033691a9SGregor Boirie
ms5611_prom_is_valid(u16 * prom,size_t len)56c0644160STomasz Duszynski static bool ms5611_prom_is_valid(u16 *prom, size_t len)
57c0644160STomasz Duszynski {
58c0644160STomasz Duszynski int i, j;
59c0644160STomasz Duszynski uint16_t crc = 0, crc_orig = prom[7] & 0x000F;
60c0644160STomasz Duszynski
61c0644160STomasz Duszynski prom[7] &= 0xFF00;
62c0644160STomasz Duszynski
63c0644160STomasz Duszynski for (i = 0; i < len * 2; i++) {
64c0644160STomasz Duszynski if (i % 2 == 1)
65c0644160STomasz Duszynski crc ^= prom[i >> 1] & 0x00FF;
66c0644160STomasz Duszynski else
67c0644160STomasz Duszynski crc ^= prom[i >> 1] >> 8;
68c0644160STomasz Duszynski
69c0644160STomasz Duszynski for (j = 0; j < 8; j++) {
70c0644160STomasz Duszynski if (crc & 0x8000)
71c0644160STomasz Duszynski crc = (crc << 1) ^ 0x3000;
72c0644160STomasz Duszynski else
73c0644160STomasz Duszynski crc <<= 1;
74c0644160STomasz Duszynski }
75c0644160STomasz Duszynski }
76c0644160STomasz Duszynski
77c0644160STomasz Duszynski crc = (crc >> 12) & 0x000F;
78c0644160STomasz Duszynski
79*fd39d966SAlexander Zangerl return crc == crc_orig;
80c0644160STomasz Duszynski }
81c0644160STomasz Duszynski
ms5611_read_prom(struct iio_dev * indio_dev)82c0644160STomasz Duszynski static int ms5611_read_prom(struct iio_dev *indio_dev)
83c0644160STomasz Duszynski {
84c0644160STomasz Duszynski int ret, i;
85c0644160STomasz Duszynski struct ms5611_state *st = iio_priv(indio_dev);
86c0644160STomasz Duszynski
87c0644160STomasz Duszynski for (i = 0; i < MS5611_PROM_WORDS_NB; i++) {
8817f442e7SMitja Spes ret = st->read_prom_word(st, i, &st->prom[i]);
89c0644160STomasz Duszynski if (ret < 0) {
90c0644160STomasz Duszynski dev_err(&indio_dev->dev,
91c0644160STomasz Duszynski "failed to read prom at %d\n", i);
92c0644160STomasz Duszynski return ret;
93c0644160STomasz Duszynski }
94c0644160STomasz Duszynski }
95c0644160STomasz Duszynski
9617f442e7SMitja Spes if (!ms5611_prom_is_valid(st->prom, MS5611_PROM_WORDS_NB)) {
97c0644160STomasz Duszynski dev_err(&indio_dev->dev, "PROM integrity check failed\n");
98c0644160STomasz Duszynski return -ENODEV;
99c0644160STomasz Duszynski }
100c0644160STomasz Duszynski
101c0644160STomasz Duszynski return 0;
102c0644160STomasz Duszynski }
103c0644160STomasz Duszynski
ms5611_read_temp_and_pressure(struct iio_dev * indio_dev,s32 * temp,s32 * pressure)104c0644160STomasz Duszynski static int ms5611_read_temp_and_pressure(struct iio_dev *indio_dev,
105c0644160STomasz Duszynski s32 *temp, s32 *pressure)
106c0644160STomasz Duszynski {
107c0644160STomasz Duszynski int ret;
108c0644160STomasz Duszynski struct ms5611_state *st = iio_priv(indio_dev);
109c0644160STomasz Duszynski
110dc19fa63SLars-Peter Clausen ret = st->read_adc_temp_and_pressure(st, temp, pressure);
111c0644160STomasz Duszynski if (ret < 0) {
112c0644160STomasz Duszynski dev_err(&indio_dev->dev,
113c0644160STomasz Duszynski "failed to read temperature and pressure\n");
114c0644160STomasz Duszynski return ret;
115c0644160STomasz Duszynski }
116c0644160STomasz Duszynski
11717f442e7SMitja Spes return st->compensate_temp_and_pressure(st, temp, pressure);
1189690d81aSTomasz Duszynski }
119c0644160STomasz Duszynski
ms5611_temp_and_pressure_compensate(struct ms5611_state * st,s32 * temp,s32 * pressure)12017f442e7SMitja Spes static int ms5611_temp_and_pressure_compensate(struct ms5611_state *st,
1219690d81aSTomasz Duszynski s32 *temp, s32 *pressure)
1229690d81aSTomasz Duszynski {
1239690d81aSTomasz Duszynski s32 t = *temp, p = *pressure;
1249690d81aSTomasz Duszynski s64 off, sens, dt;
1259690d81aSTomasz Duszynski
12617f442e7SMitja Spes dt = t - (st->prom[5] << 8);
12717f442e7SMitja Spes off = ((s64)st->prom[2] << 16) + ((st->prom[4] * dt) >> 7);
12817f442e7SMitja Spes sens = ((s64)st->prom[1] << 15) + ((st->prom[3] * dt) >> 8);
1299690d81aSTomasz Duszynski
13017f442e7SMitja Spes t = 2000 + ((st->prom[6] * dt) >> 23);
131c0644160STomasz Duszynski if (t < 2000) {
132c0644160STomasz Duszynski s64 off2, sens2, t2;
133c0644160STomasz Duszynski
134c0644160STomasz Duszynski t2 = (dt * dt) >> 31;
135c0644160STomasz Duszynski off2 = (5 * (t - 2000) * (t - 2000)) >> 1;
136c0644160STomasz Duszynski sens2 = off2 >> 1;
137c0644160STomasz Duszynski
138c0644160STomasz Duszynski if (t < -1500) {
139c0644160STomasz Duszynski s64 tmp = (t + 1500) * (t + 1500);
140c0644160STomasz Duszynski
141c0644160STomasz Duszynski off2 += 7 * tmp;
142c0644160STomasz Duszynski sens2 += (11 * tmp) >> 1;
143c0644160STomasz Duszynski }
144c0644160STomasz Duszynski
145c0644160STomasz Duszynski t -= t2;
146c0644160STomasz Duszynski off -= off2;
147c0644160STomasz Duszynski sens -= sens2;
148c0644160STomasz Duszynski }
149c0644160STomasz Duszynski
150c0644160STomasz Duszynski *temp = t;
151c0644160STomasz Duszynski *pressure = (((p * sens) >> 21) - off) >> 15;
152c0644160STomasz Duszynski
153c0644160STomasz Duszynski return 0;
154c0644160STomasz Duszynski }
155c0644160STomasz Duszynski
ms5607_temp_and_pressure_compensate(struct ms5611_state * st,s32 * temp,s32 * pressure)15617f442e7SMitja Spes static int ms5607_temp_and_pressure_compensate(struct ms5611_state *st,
1579690d81aSTomasz Duszynski s32 *temp, s32 *pressure)
1589690d81aSTomasz Duszynski {
1599690d81aSTomasz Duszynski s32 t = *temp, p = *pressure;
1609690d81aSTomasz Duszynski s64 off, sens, dt;
1619690d81aSTomasz Duszynski
16217f442e7SMitja Spes dt = t - (st->prom[5] << 8);
16317f442e7SMitja Spes off = ((s64)st->prom[2] << 17) + ((st->prom[4] * dt) >> 6);
16417f442e7SMitja Spes sens = ((s64)st->prom[1] << 16) + ((st->prom[3] * dt) >> 7);
1659690d81aSTomasz Duszynski
16617f442e7SMitja Spes t = 2000 + ((st->prom[6] * dt) >> 23);
1679690d81aSTomasz Duszynski if (t < 2000) {
168ce5b8fc1SGregor Boirie s64 off2, sens2, t2, tmp;
1699690d81aSTomasz Duszynski
1709690d81aSTomasz Duszynski t2 = (dt * dt) >> 31;
171ce5b8fc1SGregor Boirie tmp = (t - 2000) * (t - 2000);
172ce5b8fc1SGregor Boirie off2 = (61 * tmp) >> 4;
173ce5b8fc1SGregor Boirie sens2 = tmp << 1;
1749690d81aSTomasz Duszynski
1759690d81aSTomasz Duszynski if (t < -1500) {
176ce5b8fc1SGregor Boirie tmp = (t + 1500) * (t + 1500);
1779690d81aSTomasz Duszynski off2 += 15 * tmp;
178ce5b8fc1SGregor Boirie sens2 += 8 * tmp;
1799690d81aSTomasz Duszynski }
1809690d81aSTomasz Duszynski
1819690d81aSTomasz Duszynski t -= t2;
1829690d81aSTomasz Duszynski off -= off2;
1839690d81aSTomasz Duszynski sens -= sens2;
1849690d81aSTomasz Duszynski }
1859690d81aSTomasz Duszynski
1869690d81aSTomasz Duszynski *temp = t;
1879690d81aSTomasz Duszynski *pressure = (((p * sens) >> 21) - off) >> 15;
1889690d81aSTomasz Duszynski
1899690d81aSTomasz Duszynski return 0;
1909690d81aSTomasz Duszynski }
1919690d81aSTomasz Duszynski
ms5611_reset(struct iio_dev * indio_dev)192c0644160STomasz Duszynski static int ms5611_reset(struct iio_dev *indio_dev)
193c0644160STomasz Duszynski {
194c0644160STomasz Duszynski int ret;
195c0644160STomasz Duszynski struct ms5611_state *st = iio_priv(indio_dev);
196c0644160STomasz Duszynski
197dc19fa63SLars-Peter Clausen ret = st->reset(st);
198c0644160STomasz Duszynski if (ret < 0) {
199c0644160STomasz Duszynski dev_err(&indio_dev->dev, "failed to reset device\n");
200c0644160STomasz Duszynski return ret;
201c0644160STomasz Duszynski }
202c0644160STomasz Duszynski
203c0644160STomasz Duszynski usleep_range(3000, 4000);
204c0644160STomasz Duszynski
205c0644160STomasz Duszynski return 0;
206c0644160STomasz Duszynski }
207c0644160STomasz Duszynski
ms5611_trigger_handler(int irq,void * p)208713bbb4eSDaniel Baluta static irqreturn_t ms5611_trigger_handler(int irq, void *p)
209713bbb4eSDaniel Baluta {
210713bbb4eSDaniel Baluta struct iio_poll_func *pf = p;
211713bbb4eSDaniel Baluta struct iio_dev *indio_dev = pf->indio_dev;
212713bbb4eSDaniel Baluta struct ms5611_state *st = iio_priv(indio_dev);
2138db4afe1SJonathan Cameron /* Ensure buffer elements are naturally aligned */
2148db4afe1SJonathan Cameron struct {
2158db4afe1SJonathan Cameron s32 channels[2];
2168db4afe1SJonathan Cameron s64 ts __aligned(8);
2178db4afe1SJonathan Cameron } scan;
218713bbb4eSDaniel Baluta int ret;
219713bbb4eSDaniel Baluta
220713bbb4eSDaniel Baluta mutex_lock(&st->lock);
2218db4afe1SJonathan Cameron ret = ms5611_read_temp_and_pressure(indio_dev, &scan.channels[1],
2228db4afe1SJonathan Cameron &scan.channels[0]);
223713bbb4eSDaniel Baluta mutex_unlock(&st->lock);
224713bbb4eSDaniel Baluta if (ret < 0)
225713bbb4eSDaniel Baluta goto err;
226713bbb4eSDaniel Baluta
2278db4afe1SJonathan Cameron iio_push_to_buffers_with_timestamp(indio_dev, &scan,
228bc2b7dabSGregor Boirie iio_get_time_ns(indio_dev));
229713bbb4eSDaniel Baluta
230713bbb4eSDaniel Baluta err:
231713bbb4eSDaniel Baluta iio_trigger_notify_done(indio_dev->trig);
232713bbb4eSDaniel Baluta
233713bbb4eSDaniel Baluta return IRQ_HANDLED;
234713bbb4eSDaniel Baluta }
235713bbb4eSDaniel Baluta
ms5611_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)236c0644160STomasz Duszynski static int ms5611_read_raw(struct iio_dev *indio_dev,
237c0644160STomasz Duszynski struct iio_chan_spec const *chan,
238c0644160STomasz Duszynski int *val, int *val2, long mask)
239c0644160STomasz Duszynski {
240c0644160STomasz Duszynski int ret;
241c0644160STomasz Duszynski s32 temp, pressure;
242c0644160STomasz Duszynski struct ms5611_state *st = iio_priv(indio_dev);
243c0644160STomasz Duszynski
244c0644160STomasz Duszynski switch (mask) {
245c0644160STomasz Duszynski case IIO_CHAN_INFO_PROCESSED:
246c0644160STomasz Duszynski mutex_lock(&st->lock);
247c0644160STomasz Duszynski ret = ms5611_read_temp_and_pressure(indio_dev,
248c0644160STomasz Duszynski &temp, &pressure);
249c0644160STomasz Duszynski mutex_unlock(&st->lock);
250c0644160STomasz Duszynski if (ret < 0)
251c0644160STomasz Duszynski return ret;
252c0644160STomasz Duszynski
253c0644160STomasz Duszynski switch (chan->type) {
254c0644160STomasz Duszynski case IIO_TEMP:
255c0644160STomasz Duszynski *val = temp * 10;
256c0644160STomasz Duszynski return IIO_VAL_INT;
257c0644160STomasz Duszynski case IIO_PRESSURE:
258c0644160STomasz Duszynski *val = pressure / 1000;
259c0644160STomasz Duszynski *val2 = (pressure % 1000) * 1000;
260c0644160STomasz Duszynski return IIO_VAL_INT_PLUS_MICRO;
261c0644160STomasz Duszynski default:
262c0644160STomasz Duszynski return -EINVAL;
263c0644160STomasz Duszynski }
2641ad1ce9bSDaniel Baluta case IIO_CHAN_INFO_SCALE:
2651ad1ce9bSDaniel Baluta switch (chan->type) {
2661ad1ce9bSDaniel Baluta case IIO_TEMP:
2671ad1ce9bSDaniel Baluta *val = 10;
2681ad1ce9bSDaniel Baluta return IIO_VAL_INT;
2691ad1ce9bSDaniel Baluta case IIO_PRESSURE:
2701ad1ce9bSDaniel Baluta *val = 0;
2711ad1ce9bSDaniel Baluta *val2 = 1000;
2721ad1ce9bSDaniel Baluta return IIO_VAL_INT_PLUS_MICRO;
2731ad1ce9bSDaniel Baluta default:
2741ad1ce9bSDaniel Baluta return -EINVAL;
2751ad1ce9bSDaniel Baluta }
276033691a9SGregor Boirie case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
277033691a9SGregor Boirie if (chan->type != IIO_TEMP && chan->type != IIO_PRESSURE)
278033691a9SGregor Boirie break;
279033691a9SGregor Boirie mutex_lock(&st->lock);
280033691a9SGregor Boirie if (chan->type == IIO_TEMP)
281033691a9SGregor Boirie *val = (int)st->temp_osr->rate;
282033691a9SGregor Boirie else
283033691a9SGregor Boirie *val = (int)st->pressure_osr->rate;
284033691a9SGregor Boirie mutex_unlock(&st->lock);
285033691a9SGregor Boirie return IIO_VAL_INT;
286c0644160STomasz Duszynski }
287c0644160STomasz Duszynski
288c0644160STomasz Duszynski return -EINVAL;
289c0644160STomasz Duszynski }
290c0644160STomasz Duszynski
ms5611_find_osr(int rate,const struct ms5611_osr * osr,size_t count)291033691a9SGregor Boirie static const struct ms5611_osr *ms5611_find_osr(int rate,
292033691a9SGregor Boirie const struct ms5611_osr *osr,
293033691a9SGregor Boirie size_t count)
294033691a9SGregor Boirie {
295033691a9SGregor Boirie unsigned int r;
296033691a9SGregor Boirie
297033691a9SGregor Boirie for (r = 0; r < count; r++)
298033691a9SGregor Boirie if ((unsigned short)rate == osr[r].rate)
299033691a9SGregor Boirie break;
300033691a9SGregor Boirie if (r >= count)
301033691a9SGregor Boirie return NULL;
302033691a9SGregor Boirie return &osr[r];
303033691a9SGregor Boirie }
304033691a9SGregor Boirie
ms5611_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)305033691a9SGregor Boirie static int ms5611_write_raw(struct iio_dev *indio_dev,
306033691a9SGregor Boirie struct iio_chan_spec const *chan,
307033691a9SGregor Boirie int val, int val2, long mask)
308033691a9SGregor Boirie {
309033691a9SGregor Boirie struct ms5611_state *st = iio_priv(indio_dev);
310033691a9SGregor Boirie const struct ms5611_osr *osr = NULL;
3113bc1abcdSAlison Schofield int ret;
312033691a9SGregor Boirie
313033691a9SGregor Boirie if (mask != IIO_CHAN_INFO_OVERSAMPLING_RATIO)
314033691a9SGregor Boirie return -EINVAL;
315033691a9SGregor Boirie
316033691a9SGregor Boirie if (chan->type == IIO_TEMP)
317033691a9SGregor Boirie osr = ms5611_find_osr(val, ms5611_avail_temp_osr,
318033691a9SGregor Boirie ARRAY_SIZE(ms5611_avail_temp_osr));
319033691a9SGregor Boirie else if (chan->type == IIO_PRESSURE)
320033691a9SGregor Boirie osr = ms5611_find_osr(val, ms5611_avail_pressure_osr,
321033691a9SGregor Boirie ARRAY_SIZE(ms5611_avail_pressure_osr));
322033691a9SGregor Boirie if (!osr)
323033691a9SGregor Boirie return -EINVAL;
324033691a9SGregor Boirie
3253bc1abcdSAlison Schofield ret = iio_device_claim_direct_mode(indio_dev);
3263bc1abcdSAlison Schofield if (ret)
3273bc1abcdSAlison Schofield return ret;
328033691a9SGregor Boirie
3293bc1abcdSAlison Schofield mutex_lock(&st->lock);
330033691a9SGregor Boirie
331033691a9SGregor Boirie if (chan->type == IIO_TEMP)
332033691a9SGregor Boirie st->temp_osr = osr;
333033691a9SGregor Boirie else
334033691a9SGregor Boirie st->pressure_osr = osr;
335033691a9SGregor Boirie
336033691a9SGregor Boirie mutex_unlock(&st->lock);
3373bc1abcdSAlison Schofield iio_device_release_direct_mode(indio_dev);
3383bc1abcdSAlison Schofield
339033691a9SGregor Boirie return 0;
340033691a9SGregor Boirie }
341033691a9SGregor Boirie
342713bbb4eSDaniel Baluta static const unsigned long ms5611_scan_masks[] = {0x3, 0};
343713bbb4eSDaniel Baluta
344c0644160STomasz Duszynski static const struct iio_chan_spec ms5611_channels[] = {
345c0644160STomasz Duszynski {
346c0644160STomasz Duszynski .type = IIO_PRESSURE,
3471ad1ce9bSDaniel Baluta .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
348033691a9SGregor Boirie BIT(IIO_CHAN_INFO_SCALE) |
349033691a9SGregor Boirie BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
350713bbb4eSDaniel Baluta .scan_index = 0,
351713bbb4eSDaniel Baluta .scan_type = {
352713bbb4eSDaniel Baluta .sign = 's',
353713bbb4eSDaniel Baluta .realbits = 32,
354713bbb4eSDaniel Baluta .storagebits = 32,
355713bbb4eSDaniel Baluta .endianness = IIO_CPU,
356713bbb4eSDaniel Baluta },
357c0644160STomasz Duszynski },
358c0644160STomasz Duszynski {
359c0644160STomasz Duszynski .type = IIO_TEMP,
3601ad1ce9bSDaniel Baluta .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
361033691a9SGregor Boirie BIT(IIO_CHAN_INFO_SCALE) |
362033691a9SGregor Boirie BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
363713bbb4eSDaniel Baluta .scan_index = 1,
364713bbb4eSDaniel Baluta .scan_type = {
365713bbb4eSDaniel Baluta .sign = 's',
366713bbb4eSDaniel Baluta .realbits = 32,
367713bbb4eSDaniel Baluta .storagebits = 32,
368713bbb4eSDaniel Baluta .endianness = IIO_CPU,
369713bbb4eSDaniel Baluta },
370713bbb4eSDaniel Baluta },
371713bbb4eSDaniel Baluta IIO_CHAN_SOFT_TIMESTAMP(2),
372c0644160STomasz Duszynski };
373c0644160STomasz Duszynski
374c0644160STomasz Duszynski static const struct iio_info ms5611_info = {
375c0644160STomasz Duszynski .read_raw = &ms5611_read_raw,
376033691a9SGregor Boirie .write_raw = &ms5611_write_raw,
377033691a9SGregor Boirie .attrs = &ms5611_attribute_group,
378c0644160STomasz Duszynski };
379c0644160STomasz Duszynski
ms5611_init(struct iio_dev * indio_dev)380c0644160STomasz Duszynski static int ms5611_init(struct iio_dev *indio_dev)
381c0644160STomasz Duszynski {
382c0644160STomasz Duszynski int ret;
3833145229fSGrégor Boirie
3843145229fSGrégor Boirie /* Enable attached regulator if any. */
385122ef59aSJonathan Cameron ret = devm_regulator_get_enable(indio_dev->dev.parent, "vdd");
386122ef59aSJonathan Cameron if (ret)
3873145229fSGrégor Boirie return ret;
388c0644160STomasz Duszynski
389c0644160STomasz Duszynski ret = ms5611_reset(indio_dev);
390c0644160STomasz Duszynski if (ret < 0)
391122ef59aSJonathan Cameron return ret;
392c0644160STomasz Duszynski
393334ecdd0SGregor Boirie ret = ms5611_read_prom(indio_dev);
394334ecdd0SGregor Boirie if (ret < 0)
395122ef59aSJonathan Cameron return ret;
396334ecdd0SGregor Boirie
397334ecdd0SGregor Boirie return 0;
398c0644160STomasz Duszynski }
399c0644160STomasz Duszynski
ms5611_probe(struct iio_dev * indio_dev,struct device * dev,const char * name,int type)400eac635ebSGrégor Boirie int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
401eac635ebSGrégor Boirie const char *name, int type)
402c0644160STomasz Duszynski {
403c0644160STomasz Duszynski int ret;
404c0644160STomasz Duszynski struct ms5611_state *st = iio_priv(indio_dev);
405c0644160STomasz Duszynski
406c0644160STomasz Duszynski mutex_init(&st->lock);
40717f442e7SMitja Spes
40817f442e7SMitja Spes switch (type) {
40917f442e7SMitja Spes case MS5611:
41017f442e7SMitja Spes st->compensate_temp_and_pressure =
41117f442e7SMitja Spes ms5611_temp_and_pressure_compensate;
41217f442e7SMitja Spes break;
41317f442e7SMitja Spes case MS5607:
41417f442e7SMitja Spes st->compensate_temp_and_pressure =
41517f442e7SMitja Spes ms5607_temp_and_pressure_compensate;
41617f442e7SMitja Spes break;
41717f442e7SMitja Spes default:
41817f442e7SMitja Spes return -EINVAL;
41917f442e7SMitja Spes }
42017f442e7SMitja Spes
421033691a9SGregor Boirie st->temp_osr =
422033691a9SGregor Boirie &ms5611_avail_temp_osr[ARRAY_SIZE(ms5611_avail_temp_osr) - 1];
423033691a9SGregor Boirie st->pressure_osr =
424033691a9SGregor Boirie &ms5611_avail_pressure_osr[ARRAY_SIZE(ms5611_avail_pressure_osr)
425033691a9SGregor Boirie - 1];
426eac635ebSGrégor Boirie indio_dev->name = name;
427c0644160STomasz Duszynski indio_dev->info = &ms5611_info;
428c0644160STomasz Duszynski indio_dev->channels = ms5611_channels;
429c0644160STomasz Duszynski indio_dev->num_channels = ARRAY_SIZE(ms5611_channels);
430c0644160STomasz Duszynski indio_dev->modes = INDIO_DIRECT_MODE;
431713bbb4eSDaniel Baluta indio_dev->available_scan_masks = ms5611_scan_masks;
432c0644160STomasz Duszynski
433c0644160STomasz Duszynski ret = ms5611_init(indio_dev);
434c0644160STomasz Duszynski if (ret < 0)
435c0644160STomasz Duszynski return ret;
436c0644160STomasz Duszynski
437caa6693eSJonathan Cameron ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
438713bbb4eSDaniel Baluta ms5611_trigger_handler, NULL);
439713bbb4eSDaniel Baluta if (ret < 0) {
440713bbb4eSDaniel Baluta dev_err(dev, "iio triggered buffer setup failed\n");
441122ef59aSJonathan Cameron return ret;
442713bbb4eSDaniel Baluta }
443713bbb4eSDaniel Baluta
444caa6693eSJonathan Cameron ret = devm_iio_device_register(dev, indio_dev);
445713bbb4eSDaniel Baluta if (ret < 0) {
446713bbb4eSDaniel Baluta dev_err(dev, "unable to register iio device\n");
447caa6693eSJonathan Cameron return ret;
448713bbb4eSDaniel Baluta }
449713bbb4eSDaniel Baluta
450713bbb4eSDaniel Baluta return 0;
451c0644160STomasz Duszynski }
4521980d4a1SJonathan Cameron EXPORT_SYMBOL_NS(ms5611_probe, IIO_MS5611);
453c0644160STomasz Duszynski
454c0644160STomasz Duszynski MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>");
455c0644160STomasz Duszynski MODULE_DESCRIPTION("MS5611 core driver");
456c0644160STomasz Duszynski MODULE_LICENSE("GPL v2");
457