Merge tag 'pci-v5.18-changes-2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / drivers / iio / pressure / ms5611_core.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * MS5611 pressure and temperature sensor driver
4  *
5  * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com>
6  *
7  * Data sheet:
8  *  http://www.meas-spec.com/downloads/MS5611-01BA03.pdf
9  *  http://www.meas-spec.com/downloads/MS5607-02BA03.pdf
10  *
11  */
12
13 #include <linux/module.h>
14 #include <linux/iio/iio.h>
15 #include <linux/delay.h>
16 #include <linux/regulator/consumer.h>
17
18 #include <linux/iio/sysfs.h>
19 #include <linux/iio/buffer.h>
20 #include <linux/iio/triggered_buffer.h>
21 #include <linux/iio/trigger_consumer.h>
22 #include "ms5611.h"
23
24 #define MS5611_INIT_OSR(_cmd, _conv_usec, _rate) \
25         { .cmd = _cmd, .conv_usec = _conv_usec, .rate = _rate }
26
27 static const struct ms5611_osr ms5611_avail_pressure_osr[] = {
28         MS5611_INIT_OSR(0x40, 600,  256),
29         MS5611_INIT_OSR(0x42, 1170, 512),
30         MS5611_INIT_OSR(0x44, 2280, 1024),
31         MS5611_INIT_OSR(0x46, 4540, 2048),
32         MS5611_INIT_OSR(0x48, 9040, 4096)
33 };
34
35 static const struct ms5611_osr ms5611_avail_temp_osr[] = {
36         MS5611_INIT_OSR(0x50, 600,  256),
37         MS5611_INIT_OSR(0x52, 1170, 512),
38         MS5611_INIT_OSR(0x54, 2280, 1024),
39         MS5611_INIT_OSR(0x56, 4540, 2048),
40         MS5611_INIT_OSR(0x58, 9040, 4096)
41 };
42
43 static const char ms5611_show_osr[] = "256 512 1024 2048 4096";
44
45 static IIO_CONST_ATTR(oversampling_ratio_available, ms5611_show_osr);
46
47 static struct attribute *ms5611_attributes[] = {
48         &iio_const_attr_oversampling_ratio_available.dev_attr.attr,
49         NULL,
50 };
51
52 static const struct attribute_group ms5611_attribute_group = {
53         .attrs = ms5611_attributes,
54 };
55
56 static bool ms5611_prom_is_valid(u16 *prom, size_t len)
57 {
58         int i, j;
59         uint16_t crc = 0, crc_orig = prom[7] & 0x000F;
60
61         prom[7] &= 0xFF00;
62
63         for (i = 0; i < len * 2; i++) {
64                 if (i % 2 == 1)
65                         crc ^= prom[i >> 1] & 0x00FF;
66                 else
67                         crc ^= prom[i >> 1] >> 8;
68
69                 for (j = 0; j < 8; j++) {
70                         if (crc & 0x8000)
71                                 crc = (crc << 1) ^ 0x3000;
72                         else
73                                 crc <<= 1;
74                 }
75         }
76
77         crc = (crc >> 12) & 0x000F;
78
79         return crc_orig != 0x0000 && crc == crc_orig;
80 }
81
82 static int ms5611_read_prom(struct iio_dev *indio_dev)
83 {
84         int ret, i;
85         struct ms5611_state *st = iio_priv(indio_dev);
86
87         for (i = 0; i < MS5611_PROM_WORDS_NB; i++) {
88                 ret = st->read_prom_word(st, i, &st->chip_info->prom[i]);
89                 if (ret < 0) {
90                         dev_err(&indio_dev->dev,
91                                 "failed to read prom at %d\n", i);
92                         return ret;
93                 }
94         }
95
96         if (!ms5611_prom_is_valid(st->chip_info->prom, MS5611_PROM_WORDS_NB)) {
97                 dev_err(&indio_dev->dev, "PROM integrity check failed\n");
98                 return -ENODEV;
99         }
100
101         return 0;
102 }
103
104 static int ms5611_read_temp_and_pressure(struct iio_dev *indio_dev,
105                                          s32 *temp, s32 *pressure)
106 {
107         int ret;
108         struct ms5611_state *st = iio_priv(indio_dev);
109
110         ret = st->read_adc_temp_and_pressure(st, temp, pressure);
111         if (ret < 0) {
112                 dev_err(&indio_dev->dev,
113                         "failed to read temperature and pressure\n");
114                 return ret;
115         }
116
117         return st->chip_info->temp_and_pressure_compensate(st->chip_info,
118                                                            temp, pressure);
119 }
120
121 static int ms5611_temp_and_pressure_compensate(struct ms5611_chip_info *chip_info,
122                                                s32 *temp, s32 *pressure)
123 {
124         s32 t = *temp, p = *pressure;
125         s64 off, sens, dt;
126
127         dt = t - (chip_info->prom[5] << 8);
128         off = ((s64)chip_info->prom[2] << 16) + ((chip_info->prom[4] * dt) >> 7);
129         sens = ((s64)chip_info->prom[1] << 15) + ((chip_info->prom[3] * dt) >> 8);
130
131         t = 2000 + ((chip_info->prom[6] * dt) >> 23);
132         if (t < 2000) {
133                 s64 off2, sens2, t2;
134
135                 t2 = (dt * dt) >> 31;
136                 off2 = (5 * (t - 2000) * (t - 2000)) >> 1;
137                 sens2 = off2 >> 1;
138
139                 if (t < -1500) {
140                         s64 tmp = (t + 1500) * (t + 1500);
141
142                         off2 += 7 * tmp;
143                         sens2 += (11 * tmp) >> 1;
144                 }
145
146                 t -= t2;
147                 off -= off2;
148                 sens -= sens2;
149         }
150
151         *temp = t;
152         *pressure = (((p * sens) >> 21) - off) >> 15;
153
154         return 0;
155 }
156
157 static int ms5607_temp_and_pressure_compensate(struct ms5611_chip_info *chip_info,
158                                                s32 *temp, s32 *pressure)
159 {
160         s32 t = *temp, p = *pressure;
161         s64 off, sens, dt;
162
163         dt = t - (chip_info->prom[5] << 8);
164         off = ((s64)chip_info->prom[2] << 17) + ((chip_info->prom[4] * dt) >> 6);
165         sens = ((s64)chip_info->prom[1] << 16) + ((chip_info->prom[3] * dt) >> 7);
166
167         t = 2000 + ((chip_info->prom[6] * dt) >> 23);
168         if (t < 2000) {
169                 s64 off2, sens2, t2, tmp;
170
171                 t2 = (dt * dt) >> 31;
172                 tmp = (t - 2000) * (t - 2000);
173                 off2 = (61 * tmp) >> 4;
174                 sens2 = tmp << 1;
175
176                 if (t < -1500) {
177                         tmp = (t + 1500) * (t + 1500);
178                         off2 += 15 * tmp;
179                         sens2 += 8 * tmp;
180                 }
181
182                 t -= t2;
183                 off -= off2;
184                 sens -= sens2;
185         }
186
187         *temp = t;
188         *pressure = (((p * sens) >> 21) - off) >> 15;
189
190         return 0;
191 }
192
193 static int ms5611_reset(struct iio_dev *indio_dev)
194 {
195         int ret;
196         struct ms5611_state *st = iio_priv(indio_dev);
197
198         ret = st->reset(st);
199         if (ret < 0) {
200                 dev_err(&indio_dev->dev, "failed to reset device\n");
201                 return ret;
202         }
203
204         usleep_range(3000, 4000);
205
206         return 0;
207 }
208
209 static irqreturn_t ms5611_trigger_handler(int irq, void *p)
210 {
211         struct iio_poll_func *pf = p;
212         struct iio_dev *indio_dev = pf->indio_dev;
213         struct ms5611_state *st = iio_priv(indio_dev);
214         /* Ensure buffer elements are naturally aligned */
215         struct {
216                 s32 channels[2];
217                 s64 ts __aligned(8);
218         } scan;
219         int ret;
220
221         mutex_lock(&st->lock);
222         ret = ms5611_read_temp_and_pressure(indio_dev, &scan.channels[1],
223                                             &scan.channels[0]);
224         mutex_unlock(&st->lock);
225         if (ret < 0)
226                 goto err;
227
228         iio_push_to_buffers_with_timestamp(indio_dev, &scan,
229                                            iio_get_time_ns(indio_dev));
230
231 err:
232         iio_trigger_notify_done(indio_dev->trig);
233
234         return IRQ_HANDLED;
235 }
236
237 static int ms5611_read_raw(struct iio_dev *indio_dev,
238                            struct iio_chan_spec const *chan,
239                            int *val, int *val2, long mask)
240 {
241         int ret;
242         s32 temp, pressure;
243         struct ms5611_state *st = iio_priv(indio_dev);
244
245         switch (mask) {
246         case IIO_CHAN_INFO_PROCESSED:
247                 mutex_lock(&st->lock);
248                 ret = ms5611_read_temp_and_pressure(indio_dev,
249                                                     &temp, &pressure);
250                 mutex_unlock(&st->lock);
251                 if (ret < 0)
252                         return ret;
253
254                 switch (chan->type) {
255                 case IIO_TEMP:
256                         *val = temp * 10;
257                         return IIO_VAL_INT;
258                 case IIO_PRESSURE:
259                         *val = pressure / 1000;
260                         *val2 = (pressure % 1000) * 1000;
261                         return IIO_VAL_INT_PLUS_MICRO;
262                 default:
263                         return -EINVAL;
264                 }
265         case IIO_CHAN_INFO_SCALE:
266                 switch (chan->type) {
267                 case IIO_TEMP:
268                         *val = 10;
269                         return IIO_VAL_INT;
270                 case IIO_PRESSURE:
271                         *val = 0;
272                         *val2 = 1000;
273                         return IIO_VAL_INT_PLUS_MICRO;
274                 default:
275                         return -EINVAL;
276                 }
277         case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
278                 if (chan->type != IIO_TEMP && chan->type != IIO_PRESSURE)
279                         break;
280                 mutex_lock(&st->lock);
281                 if (chan->type == IIO_TEMP)
282                         *val = (int)st->temp_osr->rate;
283                 else
284                         *val = (int)st->pressure_osr->rate;
285                 mutex_unlock(&st->lock);
286                 return IIO_VAL_INT;
287         }
288
289         return -EINVAL;
290 }
291
292 static const struct ms5611_osr *ms5611_find_osr(int rate,
293                                                 const struct ms5611_osr *osr,
294                                                 size_t count)
295 {
296         unsigned int r;
297
298         for (r = 0; r < count; r++)
299                 if ((unsigned short)rate == osr[r].rate)
300                         break;
301         if (r >= count)
302                 return NULL;
303         return &osr[r];
304 }
305
306 static int ms5611_write_raw(struct iio_dev *indio_dev,
307                             struct iio_chan_spec const *chan,
308                             int val, int val2, long mask)
309 {
310         struct ms5611_state *st = iio_priv(indio_dev);
311         const struct ms5611_osr *osr = NULL;
312         int ret;
313
314         if (mask != IIO_CHAN_INFO_OVERSAMPLING_RATIO)
315                 return -EINVAL;
316
317         if (chan->type == IIO_TEMP)
318                 osr = ms5611_find_osr(val, ms5611_avail_temp_osr,
319                                       ARRAY_SIZE(ms5611_avail_temp_osr));
320         else if (chan->type == IIO_PRESSURE)
321                 osr = ms5611_find_osr(val, ms5611_avail_pressure_osr,
322                                       ARRAY_SIZE(ms5611_avail_pressure_osr));
323         if (!osr)
324                 return -EINVAL;
325
326         ret = iio_device_claim_direct_mode(indio_dev);
327         if (ret)
328                 return ret;
329
330         mutex_lock(&st->lock);
331
332         if (chan->type == IIO_TEMP)
333                 st->temp_osr = osr;
334         else
335                 st->pressure_osr = osr;
336
337         mutex_unlock(&st->lock);
338         iio_device_release_direct_mode(indio_dev);
339
340         return 0;
341 }
342
343 static const unsigned long ms5611_scan_masks[] = {0x3, 0};
344
345 static struct ms5611_chip_info chip_info_tbl[] = {
346         [MS5611] = {
347                 .temp_and_pressure_compensate = ms5611_temp_and_pressure_compensate,
348         },
349         [MS5607] = {
350                 .temp_and_pressure_compensate = ms5607_temp_and_pressure_compensate,
351         }
352 };
353
354 static const struct iio_chan_spec ms5611_channels[] = {
355         {
356                 .type = IIO_PRESSURE,
357                 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
358                         BIT(IIO_CHAN_INFO_SCALE) |
359                         BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
360                 .scan_index = 0,
361                 .scan_type = {
362                         .sign = 's',
363                         .realbits = 32,
364                         .storagebits = 32,
365                         .endianness = IIO_CPU,
366                 },
367         },
368         {
369                 .type = IIO_TEMP,
370                 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
371                         BIT(IIO_CHAN_INFO_SCALE) |
372                         BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
373                 .scan_index = 1,
374                 .scan_type = {
375                         .sign = 's',
376                         .realbits = 32,
377                         .storagebits = 32,
378                         .endianness = IIO_CPU,
379                 },
380         },
381         IIO_CHAN_SOFT_TIMESTAMP(2),
382 };
383
384 static const struct iio_info ms5611_info = {
385         .read_raw = &ms5611_read_raw,
386         .write_raw = &ms5611_write_raw,
387         .attrs = &ms5611_attribute_group,
388 };
389
390 static int ms5611_init(struct iio_dev *indio_dev)
391 {
392         int ret;
393         struct ms5611_state *st = iio_priv(indio_dev);
394
395         /* Enable attached regulator if any. */
396         st->vdd = devm_regulator_get(indio_dev->dev.parent, "vdd");
397         if (IS_ERR(st->vdd))
398                 return PTR_ERR(st->vdd);
399
400         ret = regulator_enable(st->vdd);
401         if (ret) {
402                 dev_err(indio_dev->dev.parent,
403                         "failed to enable Vdd supply: %d\n", ret);
404                 return ret;
405         }
406
407         ret = ms5611_reset(indio_dev);
408         if (ret < 0)
409                 goto err_regulator_disable;
410
411         ret = ms5611_read_prom(indio_dev);
412         if (ret < 0)
413                 goto err_regulator_disable;
414
415         return 0;
416
417 err_regulator_disable:
418         regulator_disable(st->vdd);
419         return ret;
420 }
421
422 static void ms5611_fini(const struct iio_dev *indio_dev)
423 {
424         const struct ms5611_state *st = iio_priv(indio_dev);
425
426         regulator_disable(st->vdd);
427 }
428
429 int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
430                  const char *name, int type)
431 {
432         int ret;
433         struct ms5611_state *st = iio_priv(indio_dev);
434
435         mutex_init(&st->lock);
436         st->chip_info = &chip_info_tbl[type];
437         st->temp_osr =
438                 &ms5611_avail_temp_osr[ARRAY_SIZE(ms5611_avail_temp_osr) - 1];
439         st->pressure_osr =
440                 &ms5611_avail_pressure_osr[ARRAY_SIZE(ms5611_avail_pressure_osr)
441                                            - 1];
442         indio_dev->name = name;
443         indio_dev->info = &ms5611_info;
444         indio_dev->channels = ms5611_channels;
445         indio_dev->num_channels = ARRAY_SIZE(ms5611_channels);
446         indio_dev->modes = INDIO_DIRECT_MODE;
447         indio_dev->available_scan_masks = ms5611_scan_masks;
448
449         ret = ms5611_init(indio_dev);
450         if (ret < 0)
451                 return ret;
452
453         ret = iio_triggered_buffer_setup(indio_dev, NULL,
454                                          ms5611_trigger_handler, NULL);
455         if (ret < 0) {
456                 dev_err(dev, "iio triggered buffer setup failed\n");
457                 goto err_fini;
458         }
459
460         ret = iio_device_register(indio_dev);
461         if (ret < 0) {
462                 dev_err(dev, "unable to register iio device\n");
463                 goto err_buffer_cleanup;
464         }
465
466         return 0;
467
468 err_buffer_cleanup:
469         iio_triggered_buffer_cleanup(indio_dev);
470 err_fini:
471         ms5611_fini(indio_dev);
472         return ret;
473 }
474 EXPORT_SYMBOL_NS(ms5611_probe, IIO_MS5611);
475
476 void ms5611_remove(struct iio_dev *indio_dev)
477 {
478         iio_device_unregister(indio_dev);
479         iio_triggered_buffer_cleanup(indio_dev);
480         ms5611_fini(indio_dev);
481 }
482 EXPORT_SYMBOL_NS(ms5611_remove, IIO_MS5611);
483
484 MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>");
485 MODULE_DESCRIPTION("MS5611 core driver");
486 MODULE_LICENSE("GPL v2");