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/init.h>
51 #include <linux/slab.h>
54 #include <linux/interrupt.h>
55 #include <linux/completion.h>
56 #include <linux/gpio.h>
58 #define BMP085_CHIP_ID 0x55
59 #define BMP085_CALIBRATION_DATA_START 0xAA
60 #define BMP085_CALIBRATION_DATA_LENGTH 11 /* 16 bit values */
61 #define BMP085_CHIP_ID_REG 0xD0
62 #define BMP085_CTRL_REG 0xF4
63 #define BMP085_TEMP_MEASUREMENT 0x2E
64 #define BMP085_PRESSURE_MEASUREMENT 0x34
65 #define BMP085_CONVERSION_REGISTER_MSB 0xF6
66 #define BMP085_CONVERSION_REGISTER_LSB 0xF7
67 #define BMP085_CONVERSION_REGISTER_XLSB 0xF8
68 #define BMP085_TEMP_CONVERSION_TIME 5
70 struct bmp085_calibration_data
{
79 struct regmap
*regmap
;
81 struct bmp085_calibration_data calibration
;
82 u8 oversampling_setting
;
85 u32 temp_measurement_period
;
86 unsigned long last_temp_measurement
;
88 s32 b6
; /* calculated temperature correction coefficient */
90 struct completion done
;
93 static irqreturn_t
bmp085_eoc_isr(int irq
, void *devid
)
95 struct bmp085_data
*data
= devid
;
97 complete(&data
->done
);
102 static s32
bmp085_read_calibration_data(struct bmp085_data
*data
)
104 u16 tmp
[BMP085_CALIBRATION_DATA_LENGTH
];
105 struct bmp085_calibration_data
*cali
= &(data
->calibration
);
106 s32 status
= regmap_bulk_read(data
->regmap
,
107 BMP085_CALIBRATION_DATA_START
, (u8
*)tmp
,
108 (BMP085_CALIBRATION_DATA_LENGTH
<< 1));
112 cali
->AC1
= be16_to_cpu(tmp
[0]);
113 cali
->AC2
= be16_to_cpu(tmp
[1]);
114 cali
->AC3
= be16_to_cpu(tmp
[2]);
115 cali
->AC4
= be16_to_cpu(tmp
[3]);
116 cali
->AC5
= be16_to_cpu(tmp
[4]);
117 cali
->AC6
= be16_to_cpu(tmp
[5]);
118 cali
->B1
= be16_to_cpu(tmp
[6]);
119 cali
->B2
= be16_to_cpu(tmp
[7]);
120 cali
->MB
= be16_to_cpu(tmp
[8]);
121 cali
->MC
= be16_to_cpu(tmp
[9]);
122 cali
->MD
= be16_to_cpu(tmp
[10]);
126 static s32
bmp085_update_raw_temperature(struct bmp085_data
*data
)
131 mutex_lock(&data
->lock
);
133 init_completion(&data
->done
);
135 status
= regmap_write(data
->regmap
, BMP085_CTRL_REG
,
136 BMP085_TEMP_MEASUREMENT
);
139 "Error while requesting temperature measurement.\n");
142 wait_for_completion_timeout(&data
->done
, 1 + msecs_to_jiffies(
143 BMP085_TEMP_CONVERSION_TIME
));
145 status
= regmap_bulk_read(data
->regmap
, BMP085_CONVERSION_REGISTER_MSB
,
149 "Error while reading temperature measurement result\n");
152 data
->raw_temperature
= be16_to_cpu(tmp
);
153 data
->last_temp_measurement
= jiffies
;
154 status
= 0; /* everything ok, return 0 */
157 mutex_unlock(&data
->lock
);
161 static s32
bmp085_update_raw_pressure(struct bmp085_data
*data
)
166 mutex_lock(&data
->lock
);
168 init_completion(&data
->done
);
170 status
= regmap_write(data
->regmap
, BMP085_CTRL_REG
,
171 BMP085_PRESSURE_MEASUREMENT
+
172 (data
->oversampling_setting
<< 6));
175 "Error while requesting pressure measurement.\n");
179 /* wait for the end of conversion */
180 wait_for_completion_timeout(&data
->done
, 1 + msecs_to_jiffies(
181 2+(3 << data
->oversampling_setting
)));
182 /* copy data into a u32 (4 bytes), but skip the first byte. */
183 status
= regmap_bulk_read(data
->regmap
, BMP085_CONVERSION_REGISTER_MSB
,
187 "Error while reading pressure measurement results\n");
190 data
->raw_pressure
= be32_to_cpu((tmp
));
191 data
->raw_pressure
>>= (8-data
->oversampling_setting
);
192 status
= 0; /* everything ok, return 0 */
195 mutex_unlock(&data
->lock
);
200 * This function starts the temperature measurement and returns the value
201 * in tenth of a degree celsius.
203 static s32
bmp085_get_temperature(struct bmp085_data
*data
, int *temperature
)
205 struct bmp085_calibration_data
*cali
= &data
->calibration
;
209 status
= bmp085_update_raw_temperature(data
);
213 x1
= ((data
->raw_temperature
- cali
->AC6
) * cali
->AC5
) >> 15;
214 x2
= (cali
->MC
<< 11) / (x1
+ cali
->MD
);
215 data
->b6
= x1
+ x2
- 4000;
216 /* if NULL just update b6. Used for pressure only measurements */
217 if (temperature
!= NULL
)
218 *temperature
= (x1
+x2
+8) >> 4;
225 * This function starts the pressure measurement and returns the value
226 * in millibar. Since the pressure depends on the ambient temperature,
227 * a temperature measurement is executed according to the given temperature
228 * measurement period (default is 1 sec boundary). This period could vary
229 * and needs to be adjusted according to the sensor environment, i.e. if big
230 * temperature variations then the temperature needs to be read out often.
232 static s32
bmp085_get_pressure(struct bmp085_data
*data
, int *pressure
)
234 struct bmp085_calibration_data
*cali
= &data
->calibration
;
240 /* alt least every second force an update of the ambient temperature */
241 if ((data
->last_temp_measurement
== 0) ||
242 time_is_before_jiffies(data
->last_temp_measurement
+ 1*HZ
)) {
243 status
= bmp085_get_temperature(data
, NULL
);
248 status
= bmp085_update_raw_pressure(data
);
252 x1
= (data
->b6
* data
->b6
) >> 12;
256 x2
= cali
->AC2
* data
->b6
;
261 b3
= (((((s32
)cali
->AC1
) * 4 + x3
) << data
->oversampling_setting
) + 2);
264 x1
= (cali
->AC3
* data
->b6
) >> 13;
265 x2
= (cali
->B1
* ((data
->b6
* data
->b6
) >> 12)) >> 16;
266 x3
= (x1
+ x2
+ 2) >> 2;
267 b4
= (cali
->AC4
* (u32
)(x3
+ 32768)) >> 15;
269 b7
= ((u32
)data
->raw_pressure
- b3
) *
270 (50000 >> data
->oversampling_setting
);
271 p
= ((b7
< 0x80000000) ? ((b7
<< 1) / b4
) : ((b7
/ b4
) * 2));
275 x1
= (x1
* 3038) >> 16;
276 x2
= (-7357 * p
) >> 16;
277 p
+= (x1
+ x2
+ 3791) >> 4;
285 * This function sets the chip-internal oversampling. Valid values are 0..3.
286 * The chip will use 2^oversampling samples for internal averaging.
287 * This influences the measurement time and the accuracy; larger values
288 * increase both. The datasheet gives an overview on how measurement time,
289 * accuracy and noise correlate.
291 static void bmp085_set_oversampling(struct bmp085_data
*data
,
292 unsigned char oversampling
)
294 if (oversampling
> 3)
296 data
->oversampling_setting
= oversampling
;
300 * Returns the currently selected oversampling. Range: 0..3
302 static unsigned char bmp085_get_oversampling(struct bmp085_data
*data
)
304 return data
->oversampling_setting
;
307 /* sysfs callbacks */
308 static ssize_t
set_oversampling(struct device
*dev
,
309 struct device_attribute
*attr
,
310 const char *buf
, size_t count
)
312 struct bmp085_data
*data
= dev_get_drvdata(dev
);
313 unsigned long oversampling
;
314 int err
= kstrtoul(buf
, 10, &oversampling
);
317 mutex_lock(&data
->lock
);
318 bmp085_set_oversampling(data
, oversampling
);
319 mutex_unlock(&data
->lock
);
326 static ssize_t
show_oversampling(struct device
*dev
,
327 struct device_attribute
*attr
, char *buf
)
329 struct bmp085_data
*data
= dev_get_drvdata(dev
);
331 return sprintf(buf
, "%u\n", bmp085_get_oversampling(data
));
333 static DEVICE_ATTR(oversampling
, S_IWUSR
| S_IRUGO
,
334 show_oversampling
, set_oversampling
);
337 static ssize_t
show_temperature(struct device
*dev
,
338 struct device_attribute
*attr
, char *buf
)
342 struct bmp085_data
*data
= dev_get_drvdata(dev
);
344 status
= bmp085_get_temperature(data
, &temperature
);
348 return sprintf(buf
, "%d\n", temperature
);
350 static DEVICE_ATTR(temp0_input
, S_IRUGO
, show_temperature
, NULL
);
353 static ssize_t
show_pressure(struct device
*dev
,
354 struct device_attribute
*attr
, char *buf
)
358 struct bmp085_data
*data
= dev_get_drvdata(dev
);
360 status
= bmp085_get_pressure(data
, &pressure
);
364 return sprintf(buf
, "%d\n", pressure
);
366 static DEVICE_ATTR(pressure0_input
, S_IRUGO
, show_pressure
, NULL
);
369 static struct attribute
*bmp085_attributes
[] = {
370 &dev_attr_temp0_input
.attr
,
371 &dev_attr_pressure0_input
.attr
,
372 &dev_attr_oversampling
.attr
,
376 static const struct attribute_group bmp085_attr_group
= {
377 .attrs
= bmp085_attributes
,
380 int bmp085_detect(struct device
*dev
)
382 struct bmp085_data
*data
= dev_get_drvdata(dev
);
386 ret
= regmap_read(data
->regmap
, BMP085_CHIP_ID_REG
, &id
);
390 if (id
!= data
->chip_id
)
395 EXPORT_SYMBOL_GPL(bmp085_detect
);
397 static void bmp085_get_of_properties(struct bmp085_data
*data
)
400 struct device_node
*np
= data
->dev
->of_node
;
406 if (!of_property_read_u32(np
, "chip-id", &prop
))
407 data
->chip_id
= prop
& 0xff;
409 if (!of_property_read_u32(np
, "temp-measurement-period", &prop
))
410 data
->temp_measurement_period
= (prop
/100)*HZ
;
412 if (!of_property_read_u32(np
, "default-oversampling", &prop
))
413 data
->oversampling_setting
= prop
& 0xff;
417 static int bmp085_init_client(struct bmp085_data
*data
)
419 int status
= bmp085_read_calibration_data(data
);
424 /* default settings */
425 data
->chip_id
= BMP085_CHIP_ID
;
426 data
->last_temp_measurement
= 0;
427 data
->temp_measurement_period
= 1*HZ
;
428 data
->oversampling_setting
= 3;
430 bmp085_get_of_properties(data
);
432 mutex_init(&data
->lock
);
437 struct regmap_config bmp085_regmap_config
= {
441 EXPORT_SYMBOL_GPL(bmp085_regmap_config
);
443 int bmp085_probe(struct device
*dev
, struct regmap
*regmap
, int irq
)
445 struct bmp085_data
*data
;
448 data
= kzalloc(sizeof(struct bmp085_data
), GFP_KERNEL
);
454 dev_set_drvdata(dev
, data
);
456 data
->regmap
= regmap
;
460 err
= devm_request_irq(dev
, data
->irq
, bmp085_eoc_isr
,
461 IRQF_TRIGGER_RISING
, "bmp085",
467 /* Initialize the BMP085 chip */
468 err
= bmp085_init_client(data
);
472 err
= bmp085_detect(dev
);
474 dev_err(dev
, "%s: chip_id failed!\n", BMP085_NAME
);
478 /* Register sysfs hooks */
479 err
= sysfs_create_group(&dev
->kobj
, &bmp085_attr_group
);
483 dev_info(dev
, "Successfully initialized %s!\n", BMP085_NAME
);
492 EXPORT_SYMBOL_GPL(bmp085_probe
);
494 int bmp085_remove(struct device
*dev
)
496 struct bmp085_data
*data
= dev_get_drvdata(dev
);
498 sysfs_remove_group(&data
->dev
->kobj
, &bmp085_attr_group
);
503 EXPORT_SYMBOL_GPL(bmp085_remove
);
505 MODULE_AUTHOR("Christoph Mair <christoph.mair@gmail.com>");
506 MODULE_DESCRIPTION("BMP085 driver");
507 MODULE_LICENSE("GPL");