diff options
| author | Tomasz Duszynski <tduszyns@gmail.com> | 2015-03-14 16:29:31 -0400 |
|---|---|---|
| committer | Jonathan Cameron <jic23@kernel.org> | 2015-03-15 07:47:46 -0400 |
| commit | c0644160a8b5e56b3c3896d77ac3d50d41fa9336 (patch) | |
| tree | 9cd8486122d69d05455b20b7e831758e55917514 | |
| parent | 8b0544263761adbc7308f6910cdcc0d601782cb1 (diff) | |
iio: pressure: add support for MS5611 pressure and temperature sensor
Add support for Measurement Specialities MS5611 pressure
and temperature sensor.
Signed-off-by: Tomasz Duszynski <tduszyns@gmail.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
| -rw-r--r-- | drivers/iio/pressure/Kconfig | 27 | ||||
| -rw-r--r-- | drivers/iio/pressure/Makefile | 3 | ||||
| -rw-r--r-- | drivers/iio/pressure/ms5611.h | 44 | ||||
| -rw-r--r-- | drivers/iio/pressure/ms5611_core.c | 215 | ||||
| -rw-r--r-- | drivers/iio/pressure/ms5611_i2c.c | 128 | ||||
| -rw-r--r-- | drivers/iio/pressure/ms5611_spi.c | 127 |
6 files changed, 544 insertions, 0 deletions
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig index a3be53792072..fa6295041947 100644 --- a/drivers/iio/pressure/Kconfig +++ b/drivers/iio/pressure/Kconfig | |||
| @@ -52,6 +52,33 @@ config MPL3115 | |||
| 52 | To compile this driver as a module, choose M here: the module | 52 | To compile this driver as a module, choose M here: the module |
| 53 | will be called mpl3115. | 53 | will be called mpl3115. |
| 54 | 54 | ||
| 55 | config MS5611 | ||
| 56 | tristate "Measurement Specialities MS5611 pressure sensor driver" | ||
| 57 | help | ||
| 58 | Say Y here to build support for the Measurement Specialities | ||
| 59 | MS5611 pressure and temperature sensor. | ||
| 60 | |||
| 61 | To compile this driver as a module, choose M here: the module will | ||
| 62 | be called ms5611_core. | ||
| 63 | |||
| 64 | config MS5611_I2C | ||
| 65 | tristate "support I2C bus connection" | ||
| 66 | depends on I2C && MS5611 | ||
| 67 | help | ||
| 68 | Say Y here to build I2C bus support for MS5611. | ||
| 69 | |||
| 70 | To compile this driver as a module, choose M here: the module will | ||
| 71 | be called ms5611_i2c. | ||
| 72 | |||
| 73 | config MS5611_SPI | ||
| 74 | tristate "support SPI bus connection" | ||
| 75 | depends on SPI_MASTER && MS5611 | ||
| 76 | help | ||
| 77 | Say Y here to build SPI bus support for MS5611. | ||
| 78 | |||
| 79 | To compile this driver as a module, choose M here: the module will | ||
| 80 | be called ms5611_spi. | ||
| 81 | |||
| 55 | config IIO_ST_PRESS | 82 | config IIO_ST_PRESS |
| 56 | tristate "STMicroelectronics pressure sensor Driver" | 83 | tristate "STMicroelectronics pressure sensor Driver" |
| 57 | depends on (I2C || SPI_MASTER) && SYSFS | 84 | depends on (I2C || SPI_MASTER) && SYSFS |
diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile index 88011f2ae00e..a4f98f8d90ed 100644 --- a/drivers/iio/pressure/Makefile +++ b/drivers/iio/pressure/Makefile | |||
| @@ -7,6 +7,9 @@ obj-$(CONFIG_BMP280) += bmp280.o | |||
| 7 | obj-$(CONFIG_HID_SENSOR_PRESS) += hid-sensor-press.o | 7 | obj-$(CONFIG_HID_SENSOR_PRESS) += hid-sensor-press.o |
| 8 | obj-$(CONFIG_MPL115) += mpl115.o | 8 | obj-$(CONFIG_MPL115) += mpl115.o |
| 9 | obj-$(CONFIG_MPL3115) += mpl3115.o | 9 | obj-$(CONFIG_MPL3115) += mpl3115.o |
| 10 | obj-$(CONFIG_MS5611) += ms5611_core.o | ||
| 11 | obj-$(CONFIG_MS5611_I2C) += ms5611_i2c.o | ||
| 12 | obj-$(CONFIG_MS5611_SPI) += ms5611_spi.o | ||
| 10 | obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o | 13 | obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o |
| 11 | st_pressure-y := st_pressure_core.o | 14 | st_pressure-y := st_pressure_core.o |
| 12 | st_pressure-$(CONFIG_IIO_BUFFER) += st_pressure_buffer.o | 15 | st_pressure-$(CONFIG_IIO_BUFFER) += st_pressure_buffer.o |
diff --git a/drivers/iio/pressure/ms5611.h b/drivers/iio/pressure/ms5611.h new file mode 100644 index 000000000000..099c6cdea43f --- /dev/null +++ b/drivers/iio/pressure/ms5611.h | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | /* | ||
| 2 | * MS5611 pressure and temperature sensor driver | ||
| 3 | * | ||
| 4 | * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef _MS5611_H | ||
| 13 | #define _MS5611_H | ||
| 14 | |||
| 15 | #include <linux/device.h> | ||
| 16 | #include <linux/iio/iio.h> | ||
| 17 | #include <linux/mutex.h> | ||
| 18 | |||
| 19 | #define MS5611_RESET 0x1e | ||
| 20 | #define MS5611_READ_ADC 0x00 | ||
| 21 | #define MS5611_READ_PROM_WORD 0xA0 | ||
| 22 | #define MS5611_START_TEMP_CONV 0x58 | ||
| 23 | #define MS5611_START_PRESSURE_CONV 0x48 | ||
| 24 | |||
| 25 | #define MS5611_CONV_TIME_MIN 9040 | ||
| 26 | #define MS5611_CONV_TIME_MAX 10000 | ||
| 27 | |||
| 28 | #define MS5611_PROM_WORDS_NB 8 | ||
| 29 | |||
| 30 | struct ms5611_state { | ||
| 31 | void *client; | ||
| 32 | struct mutex lock; | ||
| 33 | |||
| 34 | int (*reset)(struct device *dev); | ||
| 35 | int (*read_prom_word)(struct device *dev, int index, u16 *word); | ||
| 36 | int (*read_adc_temp_and_pressure)(struct device *dev, | ||
| 37 | s32 *temp, s32 *pressure); | ||
| 38 | |||
| 39 | u16 prom[MS5611_PROM_WORDS_NB]; | ||
| 40 | }; | ||
| 41 | |||
| 42 | int ms5611_probe(struct iio_dev *indio_dev, struct device *dev); | ||
| 43 | |||
| 44 | #endif /* _MS5611_H */ | ||
diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c new file mode 100644 index 000000000000..e42c8531d9b3 --- /dev/null +++ b/drivers/iio/pressure/ms5611_core.c | |||
| @@ -0,0 +1,215 @@ | |||
| 1 | /* | ||
| 2 | * MS5611 pressure and temperature sensor driver | ||
| 3 | * | ||
| 4 | * Copyright (c) Tomasz Duszynski <tduszyns@gmail.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * Data sheet: | ||
| 11 | * http://www.meas-spec.com/downloads/MS5611-01BA03.pdf | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/iio/iio.h> | ||
| 17 | #include <linux/delay.h> | ||
| 18 | |||
| 19 | #include "ms5611.h" | ||
| 20 | |||
| 21 | static bool ms5611_prom_is_valid(u16 *prom, size_t len) | ||
| 22 | { | ||
| 23 | int i, j; | ||
| 24 | uint16_t crc = 0, crc_orig = prom[7] & 0x000F; | ||
| 25 | |||
| 26 | prom[7] &= 0xFF00; | ||
| 27 | |||
| 28 | for (i = 0; i < len * 2; i++) { | ||
| 29 | if (i % 2 == 1) | ||
| 30 | crc ^= prom[i >> 1] & 0x00FF; | ||
| 31 | else | ||
| 32 | crc ^= prom[i >> 1] >> 8; | ||
| 33 | |||
| 34 | for (j = 0; j < 8; j++) { | ||
| 35 | if (crc & 0x8000) | ||
| 36 | crc = (crc << 1) ^ 0x3000; | ||
| 37 | else | ||
| 38 | crc <<= 1; | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | crc = (crc >> 12) & 0x000F; | ||
| 43 | |||
| 44 | return crc_orig != 0x0000 && crc == crc_orig; | ||
| 45 | } | ||
| 46 | |||
| 47 | static int ms5611_read_prom(struct iio_dev *indio_dev) | ||
| 48 | { | ||
| 49 | int ret, i; | ||
| 50 | struct ms5611_state *st = iio_priv(indio_dev); | ||
| 51 | |||
| 52 | for (i = 0; i < MS5611_PROM_WORDS_NB; i++) { | ||
| 53 | ret = st->read_prom_word(&indio_dev->dev, i, &st->prom[i]); | ||
| 54 | if (ret < 0) { | ||
| 55 | dev_err(&indio_dev->dev, | ||
| 56 | "failed to read prom at %d\n", i); | ||
| 57 | return ret; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | if (!ms5611_prom_is_valid(st->prom, MS5611_PROM_WORDS_NB)) { | ||
| 62 | dev_err(&indio_dev->dev, "PROM integrity check failed\n"); | ||
| 63 | return -ENODEV; | ||
| 64 | } | ||
| 65 | |||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | static int ms5611_read_temp_and_pressure(struct iio_dev *indio_dev, | ||
| 70 | s32 *temp, s32 *pressure) | ||
| 71 | { | ||
| 72 | int ret; | ||
| 73 | s32 t, p; | ||
| 74 | s64 off, sens, dt; | ||
| 75 | struct ms5611_state *st = iio_priv(indio_dev); | ||
| 76 | |||
| 77 | ret = st->read_adc_temp_and_pressure(&indio_dev->dev, &t, &p); | ||
| 78 | if (ret < 0) { | ||
| 79 | dev_err(&indio_dev->dev, | ||
| 80 | "failed to read temperature and pressure\n"); | ||
| 81 | return ret; | ||
| 82 | } | ||
| 83 | |||
| 84 | dt = t - (st->prom[5] << 8); | ||
| 85 | off = ((s64)st->prom[2] << 16) + ((st->prom[4] * dt) >> 7); | ||
| 86 | sens = ((s64)st->prom[1] << 15) + ((st->prom[3] * dt) >> 8); | ||
| 87 | |||
| 88 | t = 2000 + ((st->prom[6] * dt) >> 23); | ||
| 89 | if (t < 2000) { | ||
| 90 | s64 off2, sens2, t2; | ||
| 91 | |||
| 92 | t2 = (dt * dt) >> 31; | ||
| 93 | off2 = (5 * (t - 2000) * (t - 2000)) >> 1; | ||
| 94 | sens2 = off2 >> 1; | ||
| 95 | |||
| 96 | if (t < -1500) { | ||
| 97 | s64 tmp = (t + 1500) * (t + 1500); | ||
| 98 | |||
| 99 | off2 += 7 * tmp; | ||
| 100 | sens2 += (11 * tmp) >> 1; | ||
| 101 | } | ||
| 102 | |||
| 103 | t -= t2; | ||
| 104 | off -= off2; | ||
| < | |||
