aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio/pressure
diff options
context:
space:
mode:
authorTomasz Duszynski <tduszyns@gmail.com>2015-06-23 14:45:48 -0400
committerJonathan Cameron <jic23@kernel.org>2015-07-05 09:34:00 -0400
commit9690d81a02dc4eea78de1686c3bf23a8dd4c0f28 (patch)
treed4c0d6c0703927b9d0f4bf2d228833c676e25102 /drivers/iio/pressure
parent7cb46c2a0666547493132327ccfc0698d90e52f7 (diff)
iio: pressure: ms5611: add support for MS5607 temperature and pressure sensor
MS5607 is temperature and pressure sensor which hardware is similar to MS5611. Both sensors share command protocol and support both I2C and SPI serial protocols. They only differ in compensation algorithms. Signed-off-by: Tomasz Duszynski <tduszyns@gmail.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio/pressure')
-rw-r--r--drivers/iio/pressure/Kconfig2
-rw-r--r--drivers/iio/pressure/ms5611.h16
-rw-r--r--drivers/iio/pressure/ms5611_core.c76
-rw-r--r--drivers/iio/pressure/ms5611_i2c.c5
-rw-r--r--drivers/iio/pressure/ms5611_spi.c6
5 files changed, 88 insertions, 17 deletions
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
index b13ea6fd939d..4745179ff64b 100644
--- a/drivers/iio/pressure/Kconfig
+++ b/drivers/iio/pressure/Kconfig
@@ -56,7 +56,7 @@ config MS5611
56 tristate "Measurement Specialties MS5611 pressure sensor driver" 56 tristate "Measurement Specialties MS5611 pressure sensor driver"
57 help 57 help
58 Say Y here to build support for the Measurement Specialties 58 Say Y here to build support for the Measurement Specialties
59 MS5611 pressure and temperature sensor. 59 MS5611, MS5607 pressure and temperature sensors.
60 60
61 To compile this driver as a module, choose M here: the module will 61 To compile this driver as a module, choose M here: the module will
62 be called ms5611_core. 62 be called ms5611_core.
diff --git a/drivers/iio/pressure/ms5611.h b/drivers/iio/pressure/ms5611.h
index 099c6cdea43f..23b93c797dba 100644
--- a/drivers/iio/pressure/ms5611.h
+++ b/drivers/iio/pressure/ms5611.h
@@ -27,6 +27,18 @@
27 27
28#define MS5611_PROM_WORDS_NB 8 28#define MS5611_PROM_WORDS_NB 8
29 29
30enum {
31 MS5611,
32 MS5607,
33};
34
35struct ms5611_chip_info {
36 u16 prom[MS5611_PROM_WORDS_NB];
37
38 int (*temp_and_pressure_compensate)(struct ms5611_chip_info *chip_info,
39 s32 *temp, s32 *pressure);
40};
41
30struct ms5611_state { 42struct ms5611_state {
31 void *client; 43 void *client;
32 struct mutex lock; 44 struct mutex lock;
@@ -36,9 +48,9 @@ struct ms5611_state {
36 int (*read_adc_temp_and_pressure)(struct device *dev, 48 int (*read_adc_temp_and_pressure)(struct device *dev,
37 s32 *temp, s32 *pressure); 49 s32 *temp, s32 *pressure);
38 50
39 u16 prom[MS5611_PROM_WORDS_NB]; 51 struct ms5611_chip_info *chip_info;
40}; 52};
41 53
42int ms5611_probe(struct iio_dev *indio_dev, struct device *dev); 54int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, int type);
43 55
44#endif /* _MS5611_H */ 56#endif /* _MS5611_H */
diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c
index 1109513cdda9..2f3d9b4aca4e 100644
--- a/drivers/iio/pressure/ms5611_core.c
+++ b/drivers/iio/pressure/ms5611_core.c
@@ -9,6 +9,7 @@
9 * 9 *
10 * Data sheet: 10 * Data sheet:
11 * http://www.meas-spec.com/downloads/MS5611-01BA03.pdf 11 * http://www.meas-spec.com/downloads/MS5611-01BA03.pdf
12 * http://www.meas-spec.com/downloads/MS5607-02BA03.pdf
12 * 13 *
13 */ 14 */
14 15
@@ -50,7 +51,8 @@ static int ms5611_read_prom(struct iio_dev *indio_dev)
50 struct ms5611_state *st = iio_priv(indio_dev); 51 struct ms5611_state *st = iio_priv(indio_dev);
51 52
52 for (i = 0; i < MS5611_PROM_WORDS_NB; i++) { 53 for (i = 0; i < MS5611_PROM_WORDS_NB; i++) {
53 ret = st->read_prom_word(&indio_dev->dev, i, &st->prom[i]); 54 ret = st->read_prom_word(&indio_dev->dev,
55 i, &st->chip_info->prom[i]);
54 if (ret < 0) { 56 if (ret < 0) {
55 dev_err(&indio_dev->dev, 57 dev_err(&indio_dev->dev,
56 "failed to read prom at %d\n", i); 58 "failed to read prom at %d\n", i);
@@ -58,7 +60,7 @@ static int ms5611_read_prom(struct iio_dev *indio_dev)
58 } 60 }
59 } 61 }
60 62
61 if (!ms5611_prom_is_valid(st->prom, MS5611_PROM_WORDS_NB)) { 63 if (!ms5611_prom_is_valid(st->chip_info->prom, MS5611_PROM_WORDS_NB)) {
62 dev_err(&indio_dev->dev, "PROM integrity check failed\n"); 64 dev_err(&indio_dev->dev, "PROM integrity check failed\n");
63 return -ENODEV; 65 return -ENODEV;
64 } 66 }
@@ -70,22 +72,30 @@ static int ms5611_read_temp_and_pressure(struct iio_dev *indio_dev,
70 s32 *temp, s32 *pressure) 72 s32 *temp, s32 *pressure)
71{ 73{
72 int ret; 74 int ret;
73 s32 t, p;
74 s64 off, sens, dt;
75 struct ms5611_state *st = iio_priv(indio_dev); 75 struct ms5611_state *st = iio_priv(indio_dev);
76 76
77 ret = st->read_adc_temp_and_pressure(&indio_dev->dev, &t, &p); 77 ret = st->read_adc_temp_and_pressure(&indio_dev->dev, temp, pressure);
78 if (ret < 0) { 78 if (ret < 0) {
79 dev_err(&indio_dev->dev, 79 dev_err(&indio_dev->dev,
80 "failed to read temperature and pressure\n"); 80 "failed to read temperature and pressure\n");
81 return ret; 81 return ret;
82 } 82 }
83 83
84 dt = t - (st->prom[5] << 8); 84 return st->chip_info->temp_and_pressure_compensate(st->chip_info,
85 off = ((s64)st->prom[2] << 16) + ((st->prom[4] * dt) >> 7); 85 temp, pressure);
86 sens = ((s64)st->prom[1] << 15) + ((st->prom[3] * dt) >> 8); 86}
87
88static int ms5611_temp_and_pressure_compensate(struct ms5611_chip_info *chip_info,
89 s32 *temp, s32 *pressure)
90{
91 s32 t = *temp, p = *pressure;
92 s64 off, sens, dt;
87 93
88 t = 2000 + ((st->prom[6] * dt) >> 23); 94 dt = t - (chip_info->prom[5] << 8);
95 off = ((s64)chip_info->prom[2] << 16) + ((chip_info->prom[4] * dt) >> 7);
96 sens = ((s64)chip_info->prom[1] << 15) + ((chip_info->prom[3] * dt) >> 8);
97
98 t = 2000 + ((chip_info->prom[6] * dt) >> 23);
89 if (t < 2000) { 99 if (t < 2000) {
90 s64 off2, sens2, t2; 100 s64 off2, sens2, t2;
91 101
@@ -111,6 +121,42 @@ static int ms5611_read_temp_and_pressure(struct iio_dev *indio_dev,
111 return 0; 121 return 0;
112} 122}
113 123
124static int ms5607_temp_and_pressure_compensate(struct ms5611_chip_info *chip_info,
125 s32 *temp, s32 *pressure)
126{
127 s32 t = *temp, p = *pressure;
128 s64 off, sens, dt;
129
130 dt = t - (chip_info->prom[5] << 8);
131 off = ((s64)chip_info->prom[2] << 17) + ((chip_info->prom[4] * dt) >> 6);
132 sens = ((s64)chip_info->prom[1] << 16) + ((chip_info->prom[3] * dt) >> 7);
133
134 t = 2000 + ((chip_info->prom[6] * dt) >> 23);
135 if (t < 2000) {
136 s64 off2, sens2, t2;
137
138 t2 = (dt * dt) >> 31;
139 off2 = (61 * (t - 2000) * (t - 2000)) >> 4;
140 sens2 = off2 << 1;
141
142 if (t < -1500) {
143 s64 tmp = (t + 1500) * (t + 1500);
144
145 off2 += 15 * tmp;
146 sens2 += (8 * tmp);
147 }
148
149 t -= t2;
150 off -= off2;
151 sens -= sens2;
152 }
153
154 *temp = t;
155 *pressure = (((p * sens) >> 21) - off) >> 15;
156
157 return 0;
158}
159
114static int ms5611_reset(struct iio_dev *indio_dev) 160static int ms5611_reset(struct iio_dev *indio_dev)
115{ 161{
116 int ret; 162 int ret;
@@ -160,6 +206,15 @@ static int ms5611_read_raw(struct iio_dev *indio_dev,
160 return -EINVAL; 206 return -EINVAL;
161} 207}
162 208
209static struct ms5611_chip_info chip_info_tbl[] = {
210 [MS5611] = {
211 .temp_and_pressure_compensate = ms5611_temp_and_pressure_compensate,
212 },
213 [MS5607] = {
214 .temp_and_pressure_compensate = ms5607_temp_and_pressure_compensate,
215 }
216};
217
163static const struct iio_chan_spec ms5611_channels[] = { 218static const struct iio_chan_spec ms5611_channels[] = {
164 { 219 {
165 .type = IIO_PRESSURE, 220 .type = IIO_PRESSURE,
@@ -187,12 +242,13 @@ static int ms5611_init(struct iio_dev *indio_dev)
187 return ms5611_read_prom(indio_dev); 242 return ms5611_read_prom(indio_dev);
188} 243}
189 244
190int ms5611_probe(struct iio_dev *indio_dev, struct device *dev) 245int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, int type)
191{ 246{
192 int ret; 247 int ret;
193 struct ms5611_state *st = iio_priv(indio_dev); 248 struct ms5611_state *st = iio_priv(indio_dev);
194 249
195 mutex_init(&st->lock); 250 mutex_init(&st->lock);
251 st->chip_info = &chip_info_tbl[type];
196 indio_dev->dev.parent = dev; 252 indio_dev->dev.parent = dev;
197 indio_dev->name = dev->driver->name; 253 indio_dev->name = dev->driver->name;
198 indio_dev->info = &ms5611_info; 254 indio_dev->info = &ms5611_info;
diff --git a/drivers/iio/pressure/ms5611_i2c.c b/drivers/iio/pressure/ms5611_i2c.c
index 748fd9acaad8..9d504f17669b 100644
--- a/drivers/iio/pressure/ms5611_i2c.c
+++ b/drivers/iio/pressure/ms5611_i2c.c
@@ -104,11 +104,12 @@ static int ms5611_i2c_probe(struct i2c_client *client,
104 st->read_adc_temp_and_pressure = ms5611_i2c_read_adc_temp_and_pressure; 104 st->read_adc_temp_and_pressure = ms5611_i2c_read_adc_temp_and_pressure;
105 st->client = client; 105 st->client = client;
106 106
107 return ms5611_probe(indio_dev, &client->dev); 107 return ms5611_probe(indio_dev, &client->dev, id->driver_data);
108} 108}
109 109
110static const struct i2c_device_id ms5611_id[] = { 110static const struct i2c_device_id ms5611_id[] = {
111 { "ms5611", 0 }, 111 { "ms5611", MS5611 },
112 { "ms5607", MS5607 },
112 { } 113 { }
113}; 114};
114MODULE_DEVICE_TABLE(i2c, ms5611_id); 115MODULE_DEVICE_TABLE(i2c, ms5611_id);
diff --git a/drivers/iio/pressure/ms5611_spi.c b/drivers/iio/pressure/ms5611_spi.c
index 976726fd4e6c..08ee6e88c79f 100644
--- a/drivers/iio/pressure/ms5611_spi.c
+++ b/drivers/iio/pressure/ms5611_spi.c
@@ -103,11 +103,13 @@ static int ms5611_spi_probe(struct spi_device *spi)
103 st->read_adc_temp_and_pressure = ms5611_spi_read_adc_temp_and_pressure; 103 st->read_adc_temp_and_pressure = ms5611_spi_read_adc_temp_and_pressure;
104 st->client = spi; 104 st->client = spi;
105 105
106 return ms5611_probe(indio_dev, &spi->dev); 106 return ms5611_probe(indio_dev, &spi->dev,
107 spi_get_device_id(spi)->driver_data);
107} 108}
108 109
109static const struct spi_device_id ms5611_id[] = { 110static const struct spi_device_id ms5611_id[] = {
110 { "ms5611", 0 }, 111 { "ms5611", MS5611 },
112 { "ms5607", MS5607 },
111 { } 113 { }
112}; 114};
113MODULE_DEVICE_TABLE(spi, ms5611_id); 115MODULE_DEVICE_TABLE(spi, ms5611_id);