1 /* Copyright (c) 2010 Christoph Mair <christoph.mair@gmail.com>
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #include <linux/module.h>
20 #include <linux/init.h>
21 #include <linux/i2c.h>
22 #include <linux/delay.h>
26 #define BMP085_I2C_ADDRESS 0x77
28 #define BMP085_CALIBRATION_DATA_START 0xAA
29 #define BMP085_CALIBRATION_DATA_LENGTH 22
31 #define BMP085_CHIP_ID_REG 0xD0
32 #define BMP085_VERSION_REG 0xD1
34 #define BMP085_CHIP_ID 0x55 /* 85 */
35 #define BMP085_CLIENT_NAME "bmp085"
38 /* Addresses to scan: 0x77 */
39 static const unsigned short normal_i2c[] = { BMP085_I2C_ADDRESS,
42 struct bmp085_calibration_data {
50 /* Each client has this additional data */
52 struct i2c_client *client;
53 unsigned char version;
54 struct bmp085_calibration_data calibration;
55 unsigned long raw_temperature;
56 unsigned long raw_pressure;
57 unsigned char oversampling_setting;
58 unsigned long next_temp_measurement;
59 long b6; /* calculated temperature correction coefficient */
63 static void bmp085_init_client(struct i2c_client *client);
66 static s32 bmp085_read_calibration_data(struct i2c_client *client)
68 u8 tmp[BMP085_CALIBRATION_DATA_LENGTH];
69 struct bmp085_data *data = i2c_get_clientdata(client);
70 struct bmp085_calibration_data *cali = &(data->calibration);
71 s32 status = i2c_smbus_read_i2c_block_data(client,
72 BMP085_CALIBRATION_DATA_START,
73 BMP085_CALIBRATION_DATA_LENGTH, tmp);
75 cali->AC1 = (tmp[0] << 8) | tmp[1];
76 cali->AC2 = (tmp[2] << 8) | tmp[3];
77 cali->AC3 = (tmp[4] << 8) | tmp[5];
78 cali->AC4 = (tmp[6] << 8) | tmp[7];
79 cali->AC5 = (tmp[8] << 8) | tmp[9];
80 cali->AC6 = (tmp[10] << 8) | tmp[11];
81 cali->B1 = (tmp[12] << 8) | tmp[13];
82 cali->B2 = (tmp[14] << 8) | tmp[15];
83 cali->MB = (tmp[16] << 8) | tmp[17];
84 cali->MC = (tmp[18] << 8) | tmp[19];
85 cali->MD = (tmp[20] << 8) | tmp[21];
90 static s32 bmp085_update_raw_temperature(struct bmp085_data *data)
93 s32 status = i2c_smbus_write_byte_data(data->client, 0xF4, 0x2E);
95 printk(KERN_INFO "bmp085: Error while requesting"
96 " temperature measurement.\n");
101 status = i2c_smbus_read_i2c_block_data(data->client, 0xF6, sizeof(tmp), tmp);
102 if (status != sizeof(tmp)) {
103 printk(KERN_INFO "bmp085: Error while requesting temperature"
104 " measurement (II): %d\n", status);
107 data->raw_temperature = (tmp[0] << 8) + tmp[1];
108 data->next_temp_measurement = jiffies+1*HZ;
112 static s32 bmp085_update_raw_pressure(struct bmp085_data *data)
117 status = i2c_smbus_write_byte_data(data->client, 0xF4, 0x34 + (data->oversampling_setting<<6));
119 printk(KERN_INFO "bmp085: Error while requesting pressure measurement.\n");
122 msleep(2+(3 << data->oversampling_setting<<1)); /* wait for the end of conversion */
124 status = i2c_smbus_read_i2c_block_data(data->client, 0xF6, sizeof(tmp), tmp);
125 if (status != sizeof(tmp)) {
126 printk(KERN_INFO "bmp085: Error while requesting pressure measurement (II): %d\n", status);
129 /* swap positions to correct the MSB/LSB positions */
130 data->raw_pressure = (tmp[0] << 16) | (tmp[1] << 8) | tmp[2];
131 data->raw_pressure = data->raw_pressure >> (8-data->oversampling_setting);
136 static s32 bmp085_get_temperature(struct bmp085_data *data)
138 struct bmp085_calibration_data *cali = &data->calibration;
141 if (data->next_temp_measurement < jiffies) {
142 bmp085_update_raw_temperature(data);
145 x1 = ((data->raw_temperature - cali->AC6) * cali->AC5) >> 15;
146 x2 = (cali->MC << 11) / (x1 + cali->MD);
147 data->b6 = x1 + x2 - 4000;
148 // printf("got raw temp: %ld; AC5: %d, AC6: %d, MC: %d, MD: %d\n", data->raw_temperature, cali->AC5, cali->AC6, cali->MC, cali->MD);
149 return ((x1+x2+8) >> 4);
153 static s32 bmp085_get_pressure(struct bmp085_data *data)
155 struct bmp085_calibration_data *cali = &data->calibration;
157 unsigned long b4, b7;
160 if (data->next_temp_measurement < jiffies) {
161 bmp085_get_temperature(data);
163 bmp085_update_raw_pressure(data);
165 // printf("raw_pressure: %ud, B6: %ld\n", data->raw_pressure, data->b6);
167 x1 = (data->b6 * data->b6) >> 12;
171 x2 = cali->AC2 * data->b6;
176 b3 = (((((long)cali->AC1) * 4 + x3) << data->oversampling_setting) + 2) >> 2;
178 // printf("x1: %ld, x2: %ld, x3: %ld, b3: %ld\n", x1, x2, x3, b3);
179 x1 = (cali->AC3 * data->b6) >> 13;
180 x2 = (cali->B1 * ((data->b6 * data->b6) >> 12)) >> 16;
181 x3 = (x1 + x2 + 2) >> 2;
182 b4 = (cali->AC4 * (unsigned long)(x3 + 32768)) >> 15;
184 // printf("x1: %ld, x2: %ld, x3: %ld, b4: %ld\n", x1, x2, x3, b4);
185 b7 = ((unsigned long)data->raw_pressure - b3) * (50000 >> data->oversampling_setting);
186 p = ((b7 < 0x80000000) ? ((b7 << 1) / b4) : ((b7 / b4) * 2));
190 x1 = (x1 * 3038) >> 16;
191 x2 = (-7357 * p) >> 16;
192 p += (x1 + x2 + 3791) >> 4;
197 static void bmp085_set_oversampling(struct bmp085_data *data, unsigned char oversampling)
199 if (oversampling> 3) {
202 data->oversampling_setting = oversampling;
206 static unsigned char bmp085_get_oversampling(struct bmp085_data *data)
208 return data->oversampling_setting;
217 /* sysfs callbacks */
218 static ssize_t set_oversampling(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
220 struct i2c_client *client = to_i2c_client(dev);
221 struct bmp085_data *data = i2c_get_clientdata(client);
222 bmp085_set_oversampling(data, simple_strtoul(buf, NULL, 10));
226 static ssize_t show_oversampling(struct device *dev, struct device_attribute *attr, char *buf)
228 struct i2c_client *client = to_i2c_client(dev);
229 struct bmp085_data *data = i2c_get_clientdata(client);
230 return sprintf(buf, "%u\n", bmp085_get_oversampling(data));
232 static DEVICE_ATTR(oversampling, S_IWUSR | S_IRUGO, show_oversampling, set_oversampling);
235 static ssize_t show_temperature(struct device *dev, struct device_attribute *attr, char *buf)
237 struct i2c_client *client = to_i2c_client(dev);
238 struct bmp085_data *data = i2c_get_clientdata(client);
239 return sprintf(buf, "%d\n", bmp085_get_temperature(data));
241 static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
244 static ssize_t show_pressure(struct device *dev, struct device_attribute *attr, char *buf)
246 struct i2c_client *client = to_i2c_client(dev);
247 struct bmp085_data *data = i2c_get_clientdata(client);
248 return sprintf(buf, "%d\n", bmp085_get_pressure(data));
250 static DEVICE_ATTR(pressure, S_IRUGO, show_pressure, NULL);
253 static struct attribute *bmp085_attributes[] = {
254 &dev_attr_temperature.attr,
255 &dev_attr_pressure.attr,
256 &dev_attr_oversampling.attr,
260 static const struct attribute_group bmp085_attr_group = {
261 .attrs = bmp085_attributes,
265 static int bmp085_probe(struct i2c_client *client,
266 const struct i2c_device_id *id)
268 struct bmp085_data *data;
271 if (client->addr != BMP085_I2C_ADDRESS)
274 if (i2c_smbus_read_byte_data(client, BMP085_CHIP_ID_REG) != BMP085_CHIP_ID)
277 data = kzalloc(sizeof(struct bmp085_data), GFP_KERNEL);
283 /* default settings after POR */
284 data->oversampling_setting = 0x00;
286 i2c_set_clientdata(client, data);
288 /* Initialize the BMP085 chip */
289 bmp085_init_client(client);
291 /* Register sysfs hooks */
292 err = sysfs_create_group(&client->dev.kobj, &bmp085_attr_group);
296 printk(KERN_INFO "succesfully initialized bmp085!\n");
305 static int bmp085_remove(struct i2c_client *client)
307 printk(KERN_INFO "bmp085 remove!\n");
308 sysfs_remove_group(&client->dev.kobj, &bmp085_attr_group);
309 kfree(i2c_get_clientdata(client));
313 /* Called when we have found a new HMC5843. */
314 static void bmp085_init_client(struct i2c_client *client)
316 struct bmp085_data *data = i2c_get_clientdata(client);
317 bmp085_read_calibration_data(client);
318 data->version = i2c_smbus_read_byte_data(client, BMP085_VERSION_REG);
319 data->next_temp_measurement = 0;
320 data->oversampling_setting = 3;
321 printk(KERN_INFO "BMP085 ver. %d.%d initialized\n", (data->version & 0x0F), (data->version & 0xF0) >> 4);
324 static const struct i2c_device_id bmp085_id[] = {
329 static struct i2c_driver bmp085_driver = {
334 .probe = bmp085_probe,
335 .remove = bmp085_remove,
336 .id_table = bmp085_id
338 // .detect = bmp085_detect
341 static int __init bmp085_init(void)
343 printk(KERN_INFO "init!\n");
344 return i2c_add_driver(&bmp085_driver);
347 static void __exit bmp085_exit(void)
349 printk(KERN_INFO "exit!\n");
350 i2c_del_driver(&bmp085_driver);
354 MODULE_AUTHOR("Christoph Mair <christoph.mair@gmail.com");
355 MODULE_DESCRIPTION("BMP085 driver");
356 MODULE_LICENSE("GPL");
358 module_init(bmp085_init);
359 module_exit(bmp085_exit);