1 /* Copyright (c) 2010 Christoph Mair <christoph.mair@gmail.com>
2 * Copyright (c) 2012 Bosch Sensortec GmbH
3 * Copyright (c) 2012 Unixphere AB
5 * This driver supports the bmp085 and bmp18x digital barometric pressure
6 * and temperature sensors from Bosch Sensortec. The datasheets
7 * are available from their website:
8 * http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP085-DS000-05.pdf
9 * http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP180-DS000-07.pdf
11 * A pressure measurement is issued by reading from pressure0_input.
12 * The return value ranges from 30000 to 110000 pascal with a resulution
13 * of 1 pascal (0.01 millibar) which enables measurements from 9000m above
14 * to 500m below sea level.
16 * The temperature can be read from temp0_input. Values range from
17 * -400 to 850 representing the ambient temperature in degree celsius
18 * multiplied by 10.The resolution is 0.1 celsius.
20 * Because ambient pressure is temperature dependent, a temperature
21 * measurement will be executed automatically even if the user is reading
22 * from pressure0_input. This happens if the last temperature measurement
23 * has been executed more then one second ago.
25 * To decrease RMS noise from pressure measurements, the bmp085 can
26 * autonomously calculate the average of up to eight samples. This is
27 * set up by writing to the oversampling sysfs file. Accepted values
28 * are 0, 1, 2 and 3. 2^x when x is the value written to this file
29 * specifies the number of samples used to calculate the ambient pressure.
30 * RMS noise is specified with six pascal (without averaging) and decreases
31 * down to 3 pascal when using an oversampling setting of 3.
33 * This program is free software; you can redistribute it and/or modify
34 * it under the terms of the GNU General Public License as published by
35 * the Free Software Foundation; either version 2 of the License, or
36 * (at your option) any later version.
38 * This program is distributed in the hope that it will be useful,
39 * but WITHOUT ANY WARRANTY; without even the implied warranty of
40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41 * GNU General Public License for more details.
43 * You should have received a copy of the GNU General Public License
44 * along with this program; if not, write to the Free Software
45 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
48 #include <linux/module.h>
49 #include <linux/device.h>
50 #include <linux/slab.h>
53 #include <linux/interrupt.h>
54 #include <linux/completion.h>
55 #include <linux/gpio.h>
57 #define BMP085_CHIP_ID 0x55
58 #define BMP085_CALIBRATION_DATA_START 0xAA
59 #define BMP085_CALIBRATION_DATA_LENGTH 11 /* 16 bit values */
60 #define BMP085_CHIP_ID_REG 0xD0
61 #define BMP085_CTRL_REG 0xF4
62 #define BMP085_TEMP_MEASUREMENT 0x2E
63 #define BMP085_PRESSURE_MEASUREMENT 0x34
64 #define BMP085_CONVERSION_REGISTER_MSB 0xF6
65 #define BMP085_CONVERSION_REGISTER_LSB 0xF7
66 #define BMP085_CONVERSION_REGISTER_XLSB 0xF8
67 #define BMP085_TEMP_CONVERSION_TIME 5
69 struct bmp085_calibration_data
{
78 struct regmap
*regmap
;
80 struct bmp085_calibration_data calibration
;
81 u8 oversampling_setting
;
84 u32 temp_measurement_period
;
85 unsigned long last_temp_measurement
;
87 s32 b6
; /* calculated temperature correction coefficient */
89 struct completion done
;
92 static irqreturn_t
bmp085_eoc_isr(int irq
, void *devid
)
94 struct bmp085_data
*data
= devid
;
96 complete(&data
->done
);
101 static s32
bmp085_read_calibration_data(struct bmp085_data
*data
)
103 u16 tmp
[BMP085_CALIBRATION_DATA_LENGTH
];
104 struct bmp085_calibration_data
*cali
= &(data
->calibration
);
105 s32 status
= regmap_bulk_read(data
->regmap
,
106 BMP085_CALIBRATION_DATA_START
, (u8
*)tmp
,
107 (BMP085_CALIBRATION_DATA_LENGTH
<< 1));
111 cali
->AC1
= be16_to_cpu(tmp
[0]);
112 cali
->AC2
= be16_to_cpu(tmp
[1]);
113 cali
->AC3
= be16_to_cpu(tmp
[2]);
114 cali
->AC4
= be16_to_cpu(tmp
[3]);
115 cali
->AC5
= be16_to_cpu(tmp
[4]);
116 cali
->AC6
= be16_to_cpu(tmp
[5]);
117 cali
->B1
= be16_to_cpu(tmp
[6]);
118 cali
->B2
= be16_to_cpu(tmp
[7]);
119 cali
->MB
= be16_to_cpu(tmp
[8]);
120 cali
->MC
= be16_to_cpu(tmp
[9]);
121 cali
->MD
= be16_to_cpu(tmp
[10]);
125 static s32
bmp085_update_raw_temperature(struct bmp085_data
*data
)
130 mutex_lock(&data
->lock
);
132 init_completion(&data
->done
);
134 status
= regmap_write(data
->regmap
, BMP085_CTRL_REG
,
135 BMP085_TEMP_MEASUREMENT
);
138 "Error while requesting temperature measurement.\n");
141 wait_for_completion_timeout(&data
->done
, 1 + msecs_to_jiffies(
142 BMP085_TEMP_CONVERSION_TIME
));
144 status
= regmap_bulk_read(data
->regmap
, BMP085_CONVERSION_REGISTER_MSB
,
148 "Error while reading temperature measurement result\n");
151 data
->raw_temperature
= be16_to_cpu(tmp
);
152 data
->last_temp_measurement
= jiffies
;
153 status
= 0; /* everything ok, return 0 */
156 mutex_unlock(&data
->lock
);
160 static s32
bmp085_update_raw_pressure(struct bmp085_data
*data
)
165 mutex_lock(&data
->lock
);
167 init_completion(&data
->done
);
169 status
= regmap_write(data
->regmap
, BMP085_CTRL_REG
,
170 BMP085_PRESSURE_MEASUREMENT
+
171 (data
->oversampling_setting
<< 6));
174 "Error while requesting pressure measurement.\n");
178 /* wait for the end of conversion */
179 wait_for_completion_timeout(&data
->done
, 1 + msecs_to_jiffies(
180 2+(3 << data
->oversampling_setting
)));
181 /* copy data into a u32 (4 bytes), but skip the first byte. */
182 status
= regmap_bulk_read(data
->regmap
, BMP085_CONVERSION_REGISTER_MSB
,
186 "Error while reading pressure measurement results\n");
189 data
->raw_pressure
= be32_to_cpu((tmp
));
190 data
->raw_pressure
>>= (8-data
->oversampling_setting
);
191 status
= 0; /* everything ok, return 0 */
194 mutex_unlock(&data
->lock
);
199 * This function starts the temperature measurement and returns the value
200 * in tenth of a degree celsius.
202 static s32
bmp085_get_temperature(struct bmp085_data
*data
, int *temperature
)
204 struct bmp085_calibration_data
*cali
= &data
->calibration
;
208 status
= bmp085_update_raw_temperature(data
);
212 x1
= ((data
->raw_temperature
- cali
->AC6
) * cali
->AC5
) >> 15;
213 x2
= (cali
->MC
<< 11) / (x1
+ cali
->MD
);
214 data
->b6
= x1
+ x2
- 4000;
215 /* if NULL just update b6. Used for pressure only measurements */
216 if (temperature
!= NULL
)
217 *temperature
= (x1
+x2
+8) >> 4;
224 * This function starts the pressure measurement and returns the value
225 * in millibar. Since the pressure depends on the ambient temperature,
226 * a temperature measurement is executed according to the given temperature
227 * measurement period (default is 1 sec boundary). This period could vary
228 * and needs to be adjusted according to the sensor environment, i.e. if big
229 * temperature variations then the temperature needs to be read out often.
231 static s32
bmp085_get_pressure(struct bmp085_data
*data
, int *pressure
)
233 struct bmp085_calibration_data
*cali
= &data
->calibration
;
239 /* alt least every second force an update of the ambient temperature */
240 if ((data
->last_temp_measurement
== 0) ||
241 time_is_before_jiffies(data
->last_temp_measurement
+ 1*HZ
)) {
242 status
= bmp085_get_temperature(data
, NULL
);
247 status
= bmp085_update_raw_pressure(data
);
251 x1
= (data
->b6
* data
->b6
) >> 12;
255 x2
= cali
->AC2
* data
->b6
;
260 b3
= (((((s32
)cali
->AC1
) * 4 + x3
) << data
->oversampling_setting
) + 2);
263 x1
= (cali
->AC3
* data
->b6
) >> 13;
264 x2
= (cali
->B1
* ((data
->b6
* data
->b6
) >> 12)) >> 16;
265 x3
= (x1
+ x2
+ 2) >> 2;
266 b4
= (cali
->AC4
* (u32
)(x3
+ 32768)) >> 15;
268 b7
= ((u32
)data
->raw_pressure
- b3
) *
269 (50000 >> data
->oversampling_setting
);
270 p
= ((b7
< 0x80000000) ? ((b7
<< 1) / b4
) : ((b7
/ b4
) * 2));
274 x1
= (x1
* 3038) >> 16;
275 x2
= (-7357 * p
) >> 16;
276 p
+= (x1
+ x2
+ 3791) >> 4;
284 * This function sets the chip-internal oversampling. Valid values are 0..3.
285 * The chip will use 2^oversampling samples for internal averaging.
286 * This influences the measurement time and the accuracy; larger values
287 * increase both. The datasheet gives an overview on how measurement time,
288 * accuracy and noise correlate.
290 static void bmp085_set_oversampling(struct bmp085_data
*data
,
291 unsigned char oversampling
)
293 if (oversampling
> 3)
295 data
->oversampling_setting
= oversampling
;
299 * Returns the currently selected oversampling. Range: 0..3
301 static unsigned char bmp085_get_oversampling(struct bmp085_data
*data
)
303 return data
->oversampling_setting
;
306 /* sysfs callbacks */
307 static ssize_t
set_oversampling(struct device
*dev
,
308 struct device_attribute
*attr
,
309 const char *buf
, size_t count
)
311 struct bmp085_data
*data
= dev_get_drvdata(dev
);
312 unsigned long oversampling
;
313 int err
= kstrtoul(buf
, 10, &oversampling
);
316 mutex_lock(&data
->lock
);
317 bmp085_set_oversampling(data
, oversampling
);
318 mutex_unlock(&data
->lock
);
325 static ssize_t
show_oversampling(struct device
*dev
,
326 struct device_attribute
*attr
, char *buf
)
328 struct bmp085_data
*data
= dev_get_drvdata(dev
);
330 return sprintf(buf
, "%u\n", bmp085_get_oversampling(data
));
332 static DEVICE_ATTR(oversampling
, S_IWUSR
| S_IRUGO
,
333 show_oversampling
, set_oversampling
);
336 static ssize_t
show_temperature(struct device
*dev
,
337 struct device_attribute
*attr
, char *buf
)
341 struct bmp085_data
*data
= dev_get_drvdata(dev
);
343 status
= bmp085_get_temperature(data
, &temperature
);
347 return sprintf(buf
, "%d\n", temperature
);
349 static DEVICE_ATTR(temp0_input
, S_IRUGO
, show_temperature
, NULL
);
352 static ssize_t
show_pressure(struct device
*dev
,
353 struct device_attribute
*attr
, char *buf
)
357 struct bmp085_data
*data
= dev_get_drvdata(dev
);
359 status
= bmp085_get_pressure(data
, &pressure
);
363 return sprintf(buf
, "%d\n", pressure
);
365 static DEVICE_ATTR(pressure0_input
, S_IRUGO
, show_pressure
, NULL
);
368 static struct attribute
*bmp085_attributes
[] = {
369 &dev_attr_temp0_input
.attr
,
370 &dev_attr_pressure0_input
.attr
,
371 &dev_attr_oversampling
.attr
,
375 static const struct attribute_group bmp085_attr_group
= {
376 .attrs
= bmp085_attributes
,
379 int bmp085_detect(struct device
*dev
)
381 struct bmp085_data
*data
= dev_get_drvdata(dev
);
385 ret
= regmap_read(data
->regmap
, BMP085_CHIP_ID_REG
, &id
);
389 if (id
!= data
->chip_id
)
394 EXPORT_SYMBOL_GPL(bmp085_detect
);
396 static void bmp085_get_of_properties(struct bmp085_data
*data
)
399 struct device_node
*np
= data
->dev
->of_node
;
405 if (!of_property_read_u32(np
, "chip-id", &prop
))
406 data
->chip_id
= prop
& 0xff;
408 if (!of_property_read_u32(np
, "temp-measurement-period", &prop
))
409 data
->temp_measurement_period
= (prop
/100)*HZ
;
411 if (!of_property_read_u32(np
, "default-oversampling", &prop
))
412 data
->oversampling_setting
= prop
& 0xff;
416 static int bmp085_init_client(struct bmp085_data
*data
)
418 int status
= bmp085_read_calibration_data(data
);
423 /* default settings */
424 data
->chip_id
= BMP085_CHIP_ID
;
425 data
->last_temp_measurement
= 0;
426 data
->temp_measurement_period
= 1*HZ
;
427 data
->oversampling_setting
= 3;
429 bmp085_get_of_properties(data
);
431 mutex_init(&data
->lock
);
436 struct regmap_config bmp085_regmap_config
= {
440 EXPORT_SYMBOL_GPL(bmp085_regmap_config
);
442 int bmp085_probe(struct device
*dev
, struct regmap
*regmap
, int irq
)
444 struct bmp085_data
*data
;
447 data
= kzalloc(sizeof(struct bmp085_data
), GFP_KERNEL
);
453 dev_set_drvdata(dev
, data
);
455 data
->regmap
= regmap
;
459 err
= devm_request_irq(dev
, data
->irq
, bmp085_eoc_isr
,
460 IRQF_TRIGGER_RISING
, "bmp085",
466 /* Initialize the BMP085 chip */
467 err
= bmp085_init_client(data
);
471 err
= bmp085_detect(dev
);
473 dev_err(dev
, "%s: chip_id failed!\n", BMP085_NAME
);
477 /* Register sysfs hooks */
478 err
= sysfs_create_group(&dev
->kobj
, &bmp085_attr_group
);
482 dev_info(dev
, "Successfully initialized %s!\n", BMP085_NAME
);
491 EXPORT_SYMBOL_GPL(bmp085_probe
);
493 int bmp085_remove(struct device
*dev
)
495 struct bmp085_data
*data
= dev_get_drvdata(dev
);
497 sysfs_remove_group(&data
->dev
->kobj
, &bmp085_attr_group
);
502 EXPORT_SYMBOL_GPL(bmp085_remove
);
504 MODULE_AUTHOR("Christoph Mair <christoph.mair@gmail.com>");
505 MODULE_DESCRIPTION("BMP085 driver");
506 MODULE_LICENSE("GPL");