Fix common misspellings
[linux-2.6.git] / drivers / misc / bmp085.c
1 /*  Copyright (c) 2010  Christoph Mair <christoph.mair@gmail.com>
2
3     This driver supports the bmp085 digital barometric pressure
4     and temperature sensor from Bosch Sensortec. The datasheet
5     is available from their website:
6     http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP085-DS000-05.pdf
7
8     A pressure measurement is issued by reading from pressure0_input.
9     The return value ranges from 30000 to 110000 pascal with a resulution
10     of 1 pascal (0.01 millibar) which enables measurements from 9000m above
11     to 500m below sea level.
12
13     The temperature can be read from temp0_input. Values range from
14     -400 to 850 representing the ambient temperature in degree celsius
15     multiplied by 10.The resolution is 0.1 celsius.
16
17     Because ambient pressure is temperature dependent, a temperature
18     measurement will be executed automatically even if the user is reading
19     from pressure0_input. This happens if the last temperature measurement
20     has been executed more then one second ago.
21
22     To decrease RMS noise from pressure measurements, the bmp085 can
23     autonomously calculate the average of up to eight samples. This is
24     set up by writing to the oversampling sysfs file. Accepted values
25     are 0, 1, 2 and 3. 2^x when x is the value written to this file
26     specifies the number of samples used to calculate the ambient pressure.
27     RMS noise is specified with six pascal (without averaging) and decreases
28     down to 3 pascal when using an oversampling setting of 3.
29
30     This program is free software; you can redistribute it and/or modify
31     it under the terms of the GNU General Public License as published by
32     the Free Software Foundation; either version 2 of the License, or
33     (at your option) any later version.
34
35     This program is distributed in the hope that it will be useful,
36     but WITHOUT ANY WARRANTY; without even the implied warranty of
37     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38     GNU General Public License for more details.
39
40     You should have received a copy of the GNU General Public License
41     along with this program; if not, write to the Free Software
42     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
43 */
44
45
46 #include <linux/module.h>
47 #include <linux/init.h>
48 #include <linux/i2c.h>
49 #include <linux/slab.h>
50 #include <linux/delay.h>
51
52
53 #define BMP085_I2C_ADDRESS              0x77
54 #define BMP085_CHIP_ID                  0x55
55
56 #define BMP085_CALIBRATION_DATA_START   0xAA
57 #define BMP085_CALIBRATION_DATA_LENGTH  11      /* 16 bit values */
58 #define BMP085_CHIP_ID_REG              0xD0
59 #define BMP085_VERSION_REG              0xD1
60 #define BMP085_CTRL_REG                 0xF4
61 #define BMP085_TEMP_MEASUREMENT         0x2E
62 #define BMP085_PRESSURE_MEASUREMENT     0x34
63 #define BMP085_CONVERSION_REGISTER_MSB  0xF6
64 #define BMP085_CONVERSION_REGISTER_LSB  0xF7
65 #define BMP085_CONVERSION_REGISTER_XLSB 0xF8
66 #define BMP085_TEMP_CONVERSION_TIME     5
67
68 #define BMP085_CLIENT_NAME              "bmp085"
69
70
71 static const unsigned short normal_i2c[] = { BMP085_I2C_ADDRESS,
72                                                         I2C_CLIENT_END };
73
74 struct bmp085_calibration_data {
75         s16 AC1, AC2, AC3;
76         u16 AC4, AC5, AC6;
77         s16 B1, B2;
78         s16 MB, MC, MD;
79 };
80
81
82 /* Each client has this additional data */
83 struct bmp085_data {
84         struct i2c_client *client;
85         struct mutex lock;
86         struct bmp085_calibration_data calibration;
87         u32 raw_temperature;
88         u32 raw_pressure;
89         unsigned char oversampling_setting;
90         u32 last_temp_measurement;
91         s32 b6; /* calculated temperature correction coefficient */
92 };
93
94
95 static s32 bmp085_read_calibration_data(struct i2c_client *client)
96 {
97         u16 tmp[BMP085_CALIBRATION_DATA_LENGTH];
98         struct bmp085_data *data = i2c_get_clientdata(client);
99         struct bmp085_calibration_data *cali = &(data->calibration);
100         s32 status = i2c_smbus_read_i2c_block_data(client,
101                                 BMP085_CALIBRATION_DATA_START,
102                                 BMP085_CALIBRATION_DATA_LENGTH*sizeof(u16),
103                                 (u8 *)tmp);
104         if (status < 0)
105                 return status;
106
107         if (status != BMP085_CALIBRATION_DATA_LENGTH*sizeof(u16))
108                 return -EIO;
109
110         cali->AC1 =  be16_to_cpu(tmp[0]);
111         cali->AC2 =  be16_to_cpu(tmp[1]);
112         cali->AC3 =  be16_to_cpu(tmp[2]);
113         cali->AC4 =  be16_to_cpu(tmp[3]);
114         cali->AC5 =  be16_to_cpu(tmp[4]);
115         cali->AC6 = be16_to_cpu(tmp[5]);
116         cali->B1 = be16_to_cpu(tmp[6]);
117         cali->B2 = be16_to_cpu(tmp[7]);
118         cali->MB = be16_to_cpu(tmp[8]);
119         cali->MC = be16_to_cpu(tmp[9]);
120         cali->MD = be16_to_cpu(tmp[10]);
121         return 0;
122 }
123
124
125 static s32 bmp085_update_raw_temperature(struct bmp085_data *data)
126 {
127         u16 tmp;
128         s32 status;
129
130         mutex_lock(&data->lock);
131         status = i2c_smbus_write_byte_data(data->client, BMP085_CTRL_REG,
132                                                 BMP085_TEMP_MEASUREMENT);
133         if (status != 0) {
134                 dev_err(&data->client->dev,
135                         "Error while requesting temperature measurement.\n");
136                 goto exit;
137         }
138         msleep(BMP085_TEMP_CONVERSION_TIME);
139
140         status = i2c_smbus_read_i2c_block_data(data->client,
141                 BMP085_CONVERSION_REGISTER_MSB, sizeof(tmp), (u8 *)&tmp);
142         if (status < 0)
143                 goto exit;
144         if (status != sizeof(tmp)) {
145                 dev_err(&data->client->dev,
146                         "Error while reading temperature measurement result\n");
147                 status = -EIO;
148                 goto exit;
149         }
150         data->raw_temperature = be16_to_cpu(tmp);
151         data->last_temp_measurement = jiffies;
152         status = 0;     /* everything ok, return 0 */
153
154 exit:
155         mutex_unlock(&data->lock);
156         return status;
157 }
158
159 static s32 bmp085_update_raw_pressure(struct bmp085_data *data)
160 {
161         u32 tmp = 0;
162         s32 status;
163
164         mutex_lock(&data->lock);
165         status = i2c_smbus_write_byte_data(data->client, BMP085_CTRL_REG,
166                 BMP085_PRESSURE_MEASUREMENT + (data->oversampling_setting<<6));
167         if (status != 0) {
168                 dev_err(&data->client->dev,
169                         "Error while requesting pressure measurement.\n");
170                 goto exit;
171         }
172
173         /* wait for the end of conversion */
174         msleep(2+(3 << data->oversampling_setting));
175
176         /* copy data into a u32 (4 bytes), but skip the first byte. */
177         status = i2c_smbus_read_i2c_block_data(data->client,
178                         BMP085_CONVERSION_REGISTER_MSB, 3, ((u8 *)&tmp)+1);
179         if (status < 0)
180                 goto exit;
181         if (status != 3) {
182                 dev_err(&data->client->dev,
183                         "Error while reading pressure measurement results\n");
184                 status = -EIO;
185                 goto exit;
186         }
187         data->raw_pressure = be32_to_cpu((tmp));
188         data->raw_pressure >>= (8-data->oversampling_setting);
189         status = 0;     /* everything ok, return 0 */
190
191 exit:
192         mutex_unlock(&data->lock);
193         return status;
194 }
195
196
197 /*
198  * This function starts the temperature measurement and returns the value
199  * in tenth of a degree celsius.
200  */
201 static s32 bmp085_get_temperature(struct bmp085_data *data, int *temperature)
202 {
203         struct bmp085_calibration_data *cali = &data->calibration;
204         long x1, x2;
205         int status;
206
207         status = bmp085_update_raw_temperature(data);
208         if (status != 0)
209                 goto exit;
210
211         x1 = ((data->raw_temperature - cali->AC6) * cali->AC5) >> 15;
212         x2 = (cali->MC << 11) / (x1 + cali->MD);
213         data->b6 = x1 + x2 - 4000;
214         /* if NULL just update b6. Used for pressure only measurements */
215         if (temperature != NULL)
216                 *temperature = (x1+x2+8) >> 4;
217
218 exit:
219         return status;;
220 }
221
222 /*
223  * This function starts the pressure measurement and returns the value
224  * in millibar. Since the pressure depends on the ambient temperature,
225  * a temperature measurement is executed if the last known value is older
226  * than one second.
227  */
228 static s32 bmp085_get_pressure(struct bmp085_data *data, int *pressure)
229 {
230         struct bmp085_calibration_data *cali = &data->calibration;
231         s32 x1, x2, x3, b3;
232         u32 b4, b7;
233         s32 p;
234         int status;
235
236         /* alt least every second force an update of the ambient temperature */
237         if (data->last_temp_measurement + 1*HZ < jiffies) {
238                 status = bmp085_get_temperature(data, NULL);
239                 if (status != 0)
240                         goto exit;
241         }
242
243         status = bmp085_update_raw_pressure(data);
244         if (status != 0)
245                 goto exit;
246
247         x1 = (data->b6 * data->b6) >> 12;
248         x1 *= cali->B2;
249         x1 >>= 11;
250
251         x2 = cali->AC2 * data->b6;
252         x2 >>= 11;
253
254         x3 = x1 + x2;
255
256         b3 = (((((s32)cali->AC1) * 4 + x3) << data->oversampling_setting) + 2);
257         b3 >>= 2;
258
259         x1 = (cali->AC3 * data->b6) >> 13;
260         x2 = (cali->B1 * ((data->b6 * data->b6) >> 12)) >> 16;
261         x3 = (x1 + x2 + 2) >> 2;
262         b4 = (cali->AC4 * (u32)(x3 + 32768)) >> 15;
263
264         b7 = ((u32)data->raw_pressure - b3) *
265                                         (50000 >> data->oversampling_setting);
266         p = ((b7 < 0x80000000) ? ((b7 << 1) / b4) : ((b7 / b4) * 2));
267
268         x1 = p >> 8;
269         x1 *= x1;
270         x1 = (x1 * 3038) >> 16;
271         x2 = (-7357 * p) >> 16;
272         p += (x1 + x2 + 3791) >> 4;
273
274         *pressure = p;
275
276 exit:
277         return status;
278 }
279
280 /*
281  * This function sets the chip-internal oversampling. Valid values are 0..3.
282  * The chip will use 2^oversampling samples for internal averaging.
283  * This influences the measurement time and the accuracy; larger values
284  * increase both. The datasheet gives on overview on how measurement time,
285  * accuracy and noise correlate.
286  */
287 static void bmp085_set_oversampling(struct bmp085_data *data,
288                                                 unsigned char oversampling)
289 {
290         if (oversampling > 3)
291                 oversampling = 3;
292         data->oversampling_setting = oversampling;
293 }
294
295 /*
296  * Returns the currently selected oversampling. Range: 0..3
297  */
298 static unsigned char bmp085_get_oversampling(struct bmp085_data *data)
299 {
300         return data->oversampling_setting;
301 }
302
303 /* sysfs callbacks */
304 static ssize_t set_oversampling(struct device *dev,
305                                 struct device_attribute *attr,
306                                 const char *buf, size_t count)
307 {
308         struct i2c_client *client = to_i2c_client(dev);
309         struct bmp085_data *data = i2c_get_clientdata(client);
310         unsigned long oversampling;
311         int success = strict_strtoul(buf, 10, &oversampling);
312         if (success == 0) {
313                 bmp085_set_oversampling(data, oversampling);
314                 return count;
315         }
316         return success;
317 }
318
319 static ssize_t show_oversampling(struct device *dev,
320                                  struct device_attribute *attr, char *buf)
321 {
322         struct i2c_client *client = to_i2c_client(dev);
323         struct bmp085_data *data = i2c_get_clientdata(client);
324         return sprintf(buf, "%u\n", bmp085_get_oversampling(data));
325 }
326 static DEVICE_ATTR(oversampling, S_IWUSR | S_IRUGO,
327                                         show_oversampling, set_oversampling);
328
329
330 static ssize_t show_temperature(struct device *dev,
331                                 struct device_attribute *attr, char *buf)
332 {
333         int temperature;
334         int status;
335         struct i2c_client *client = to_i2c_client(dev);
336         struct bmp085_data *data = i2c_get_clientdata(client);
337
338         status = bmp085_get_temperature(data, &temperature);
339         if (status != 0)
340                 return status;
341         else
342                 return sprintf(buf, "%d\n", temperature);
343 }
344 static DEVICE_ATTR(temp0_input, S_IRUGO, show_temperature, NULL);
345
346
347 static ssize_t show_pressure(struct device *dev,
348                              struct device_attribute *attr, char *buf)
349 {
350         int pressure;
351         int status;
352         struct i2c_client *client = to_i2c_client(dev);
353         struct bmp085_data *data = i2c_get_clientdata(client);
354
355         status = bmp085_get_pressure(data, &pressure);
356         if (status != 0)
357                 return status;
358         else
359                 return sprintf(buf, "%d\n", pressure);
360 }
361 static DEVICE_ATTR(pressure0_input, S_IRUGO, show_pressure, NULL);
362
363
364 static struct attribute *bmp085_attributes[] = {
365         &dev_attr_temp0_input.attr,
366         &dev_attr_pressure0_input.attr,
367         &dev_attr_oversampling.attr,
368         NULL
369 };
370
371 static const struct attribute_group bmp085_attr_group = {
372         .attrs = bmp085_attributes,
373 };
374
375 static int bmp085_detect(struct i2c_client *client, struct i2c_board_info *info)
376 {
377         if (client->addr != BMP085_I2C_ADDRESS)
378                 return -ENODEV;
379
380         if (i2c_smbus_read_byte_data(client, BMP085_CHIP_ID_REG) != BMP085_CHIP_ID)
381                 return -ENODEV;
382
383         return 0;
384 }
385
386 static int bmp085_init_client(struct i2c_client *client)
387 {
388         unsigned char version;
389         int status;
390         struct bmp085_data *data = i2c_get_clientdata(client);
391         data->client = client;
392         status = bmp085_read_calibration_data(client);
393         if (status != 0)
394                 goto exit;
395         version = i2c_smbus_read_byte_data(client, BMP085_VERSION_REG);
396         data->last_temp_measurement = 0;
397         data->oversampling_setting = 3;
398         mutex_init(&data->lock);
399         dev_info(&data->client->dev, "BMP085 ver. %d.%d found.\n",
400                         (version & 0x0F), (version & 0xF0) >> 4);
401 exit:
402         return status;
403 }
404
405 static int __devinit bmp085_probe(struct i2c_client *client,
406                          const struct i2c_device_id *id)
407 {
408         struct bmp085_data *data;
409         int err = 0;
410
411         data = kzalloc(sizeof(struct bmp085_data), GFP_KERNEL);
412         if (!data) {
413                 err = -ENOMEM;
414                 goto exit;
415         }
416
417         /* default settings after POR */
418         data->oversampling_setting = 0x00;
419
420         i2c_set_clientdata(client, data);
421
422         /* Initialize the BMP085 chip */
423         err = bmp085_init_client(client);
424         if (err != 0)
425                 goto exit_free;
426
427         /* Register sysfs hooks */
428         err = sysfs_create_group(&client->dev.kobj, &bmp085_attr_group);
429         if (err)
430                 goto exit_free;
431
432         dev_info(&data->client->dev, "Successfully initialized bmp085!\n");
433         goto exit;
434
435 exit_free:
436         kfree(data);
437 exit:
438         return err;
439 }
440
441 static int __devexit bmp085_remove(struct i2c_client *client)
442 {
443         sysfs_remove_group(&client->dev.kobj, &bmp085_attr_group);
444         kfree(i2c_get_clientdata(client));
445         return 0;
446 }
447
448 static const struct i2c_device_id bmp085_id[] = {
449         { "bmp085", 0 },
450         { }
451 };
452 MODULE_DEVICE_TABLE(i2c, bmp085_id);
453
454 static struct i2c_driver bmp085_driver = {
455         .driver = {
456                 .owner = THIS_MODULE,
457                 .name   = "bmp085"
458         },
459         .id_table       = bmp085_id,
460         .probe          = bmp085_probe,
461         .remove         = __devexit_p(bmp085_remove),
462
463         .detect         = bmp085_detect,
464         .address_list   = normal_i2c
465 };
466
467 static int __init bmp085_init(void)
468 {
469         return i2c_add_driver(&bmp085_driver);
470 }
471
472 static void __exit bmp085_exit(void)
473 {
474         i2c_del_driver(&bmp085_driver);
475 }
476
477
478 MODULE_AUTHOR("Christoph Mair <christoph.mair@gmail.com");
479 MODULE_DESCRIPTION("BMP085 driver");
480 MODULE_LICENSE("GPL");
481
482 module_init(bmp085_init);
483 module_exit(bmp085_exit);