Linux Audio

Check our new training course

Loading...
v3.1
  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
 71static const unsigned short normal_i2c[] = { BMP085_I2C_ADDRESS,
 72							I2C_CLIENT_END };
 73
 74struct 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 */
 83struct 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
 95static 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
125static 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
154exit:
155	mutex_unlock(&data->lock);
156	return status;
157}
158
159static 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
191exit:
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 */
201static 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
218exit:
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 */
228static 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
276exit:
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 */
287static 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 */
298static unsigned char bmp085_get_oversampling(struct bmp085_data *data)
299{
300	return data->oversampling_setting;
301}
302
303/* sysfs callbacks */
304static 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
319static 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}
326static DEVICE_ATTR(oversampling, S_IWUSR | S_IRUGO,
327					show_oversampling, set_oversampling);
328
329
330static 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}
344static DEVICE_ATTR(temp0_input, S_IRUGO, show_temperature, NULL);
345
346
347static 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}
361static DEVICE_ATTR(pressure0_input, S_IRUGO, show_pressure, NULL);
362
363
364static 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
371static const struct attribute_group bmp085_attr_group = {
372	.attrs = bmp085_attributes,
373};
374
375static 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
386static 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);
401exit:
402	return status;
403}
404
405static 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
435exit_free:
436	kfree(data);
437exit:
438	return err;
439}
 
440
441static 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
448static const struct i2c_device_id bmp085_id[] = {
449	{ "bmp085", 0 },
450	{ }
451};
452MODULE_DEVICE_TABLE(i2c, bmp085_id);
453
454static 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
467static int __init bmp085_init(void)
468{
469	return i2c_add_driver(&bmp085_driver);
470}
471
472static void __exit bmp085_exit(void)
473{
474	i2c_del_driver(&bmp085_driver);
475}
 
476
477
478MODULE_AUTHOR("Christoph Mair <christoph.mair@gmail.com");
479MODULE_DESCRIPTION("BMP085 driver");
480MODULE_LICENSE("GPL");
481
482module_init(bmp085_init);
483module_exit(bmp085_exit);
v3.5.6
  1/*  Copyright (c) 2010  Christoph Mair <christoph.mair@gmail.com>
  2 *  Copyright (c) 2012  Bosch Sensortec GmbH
  3 *  Copyright (c) 2012  Unixphere AB
  4 *
  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
 10 *
 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.
 15 *
 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.
 19 *
 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.
 24 *
 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.
 32 *
 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.
 37 *
 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.
 42 *
 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.
 46 */
 47
 48#include <linux/module.h>
 49#include <linux/device.h>
 50#include <linux/init.h>
 
 51#include <linux/slab.h>
 52#include <linux/delay.h>
 53#include <linux/of.h>
 54#include "bmp085.h"
 55
 
 
 56#define BMP085_CHIP_ID			0x55
 
 57#define BMP085_CALIBRATION_DATA_START	0xAA
 58#define BMP085_CALIBRATION_DATA_LENGTH	11	/* 16 bit values */
 59#define BMP085_CHIP_ID_REG		0xD0
 
 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
 
 
 
 
 
 
 68struct bmp085_calibration_data {
 69	s16 AC1, AC2, AC3;
 70	u16 AC4, AC5, AC6;
 71	s16 B1, B2;
 72	s16 MB, MC, MD;
 73};
 74
 
 
 75struct bmp085_data {
 76	struct	device *dev;
 77	struct  regmap *regmap;
 78	struct	mutex lock;
 79	struct	bmp085_calibration_data calibration;
 80	u8	oversampling_setting;
 81	u32	raw_temperature;
 82	u32	raw_pressure;
 83	u32	temp_measurement_period;
 84	unsigned long last_temp_measurement;
 85	u8	chip_id;
 86	s32	b6; /* calculated temperature correction coefficient */
 87};
 88
 89static s32 bmp085_read_calibration_data(struct bmp085_data *data)
 
 90{
 91	u16 tmp[BMP085_CALIBRATION_DATA_LENGTH];
 
 92	struct bmp085_calibration_data *cali = &(data->calibration);
 93	s32 status = regmap_bulk_read(data->regmap,
 94				BMP085_CALIBRATION_DATA_START, (u8 *)tmp,
 95				(BMP085_CALIBRATION_DATA_LENGTH << 1));
 
 96	if (status < 0)
 97		return status;
 98
 
 
 
 99	cali->AC1 =  be16_to_cpu(tmp[0]);
100	cali->AC2 =  be16_to_cpu(tmp[1]);
101	cali->AC3 =  be16_to_cpu(tmp[2]);
102	cali->AC4 =  be16_to_cpu(tmp[3]);
103	cali->AC5 =  be16_to_cpu(tmp[4]);
104	cali->AC6 = be16_to_cpu(tmp[5]);
105	cali->B1 = be16_to_cpu(tmp[6]);
106	cali->B2 = be16_to_cpu(tmp[7]);
107	cali->MB = be16_to_cpu(tmp[8]);
108	cali->MC = be16_to_cpu(tmp[9]);
109	cali->MD = be16_to_cpu(tmp[10]);
110	return 0;
111}
112
 
113static s32 bmp085_update_raw_temperature(struct bmp085_data *data)
114{
115	u16 tmp;
116	s32 status;
117
118	mutex_lock(&data->lock);
119	status = regmap_write(data->regmap, BMP085_CTRL_REG,
120			      BMP085_TEMP_MEASUREMENT);
121	if (status < 0) {
122		dev_err(data->dev,
123			"Error while requesting temperature measurement.\n");
124		goto exit;
125	}
126	msleep(BMP085_TEMP_CONVERSION_TIME);
127
128	status = regmap_bulk_read(data->regmap, BMP085_CONVERSION_REGISTER_MSB,
129				 &tmp, sizeof(tmp));
130	if (status < 0) {
131		dev_err(data->dev,
 
 
132			"Error while reading temperature measurement result\n");
 
133		goto exit;
134	}
135	data->raw_temperature = be16_to_cpu(tmp);
136	data->last_temp_measurement = jiffies;
137	status = 0;	/* everything ok, return 0 */
138
139exit:
140	mutex_unlock(&data->lock);
141	return status;
142}
143
144static s32 bmp085_update_raw_pressure(struct bmp085_data *data)
145{
146	u32 tmp = 0;
147	s32 status;
148
149	mutex_lock(&data->lock);
150	status = regmap_write(data->regmap, BMP085_CTRL_REG,
151			BMP085_PRESSURE_MEASUREMENT +
152			(data->oversampling_setting << 6));
153	if (status < 0) {
154		dev_err(data->dev,
155			"Error while requesting pressure measurement.\n");
156		goto exit;
157	}
158
159	/* wait for the end of conversion */
160	msleep(2+(3 << data->oversampling_setting));
161
162	/* copy data into a u32 (4 bytes), but skip the first byte. */
163	status = regmap_bulk_read(data->regmap, BMP085_CONVERSION_REGISTER_MSB,
164				 ((u8 *)&tmp)+1, 3);
165	if (status < 0) {
166		dev_err(data->dev,
 
 
167			"Error while reading pressure measurement results\n");
 
168		goto exit;
169	}
170	data->raw_pressure = be32_to_cpu((tmp));
171	data->raw_pressure >>= (8-data->oversampling_setting);
172	status = 0;	/* everything ok, return 0 */
173
174exit:
175	mutex_unlock(&data->lock);
176	return status;
177}
178
 
179/*
180 * This function starts the temperature measurement and returns the value
181 * in tenth of a degree celsius.
182 */
183static s32 bmp085_get_temperature(struct bmp085_data *data, int *temperature)
184{
185	struct bmp085_calibration_data *cali = &data->calibration;
186	long x1, x2;
187	int status;
188
189	status = bmp085_update_raw_temperature(data);
190	if (status < 0)
191		goto exit;
192
193	x1 = ((data->raw_temperature - cali->AC6) * cali->AC5) >> 15;
194	x2 = (cali->MC << 11) / (x1 + cali->MD);
195	data->b6 = x1 + x2 - 4000;
196	/* if NULL just update b6. Used for pressure only measurements */
197	if (temperature != NULL)
198		*temperature = (x1+x2+8) >> 4;
199
200exit:
201	return status;
202}
203
204/*
205 * This function starts the pressure measurement and returns the value
206 * in millibar. Since the pressure depends on the ambient temperature,
207 * a temperature measurement is executed according to the given temperature
208 * measurement period (default is 1 sec boundary). This period could vary
209 * and needs to be adjusted according to the sensor environment, i.e. if big
210 * temperature variations then the temperature needs to be read out often.
211 */
212static s32 bmp085_get_pressure(struct bmp085_data *data, int *pressure)
213{
214	struct bmp085_calibration_data *cali = &data->calibration;
215	s32 x1, x2, x3, b3;
216	u32 b4, b7;
217	s32 p;
218	int status;
219
220	/* alt least every second force an update of the ambient temperature */
221	if ((data->last_temp_measurement == 0) ||
222	    time_is_before_jiffies(data->last_temp_measurement + 1*HZ)) {
223		status = bmp085_get_temperature(data, NULL);
224		if (status < 0)
225			return status;
226	}
227
228	status = bmp085_update_raw_pressure(data);
229	if (status < 0)
230		return status;
231
232	x1 = (data->b6 * data->b6) >> 12;
233	x1 *= cali->B2;
234	x1 >>= 11;
235
236	x2 = cali->AC2 * data->b6;
237	x2 >>= 11;
238
239	x3 = x1 + x2;
240
241	b3 = (((((s32)cali->AC1) * 4 + x3) << data->oversampling_setting) + 2);
242	b3 >>= 2;
243
244	x1 = (cali->AC3 * data->b6) >> 13;
245	x2 = (cali->B1 * ((data->b6 * data->b6) >> 12)) >> 16;
246	x3 = (x1 + x2 + 2) >> 2;
247	b4 = (cali->AC4 * (u32)(x3 + 32768)) >> 15;
248
249	b7 = ((u32)data->raw_pressure - b3) *
250					(50000 >> data->oversampling_setting);
251	p = ((b7 < 0x80000000) ? ((b7 << 1) / b4) : ((b7 / b4) * 2));
252
253	x1 = p >> 8;
254	x1 *= x1;
255	x1 = (x1 * 3038) >> 16;
256	x2 = (-7357 * p) >> 16;
257	p += (x1 + x2 + 3791) >> 4;
258
259	*pressure = p;
260
261	return 0;
 
262}
263
264/*
265 * This function sets the chip-internal oversampling. Valid values are 0..3.
266 * The chip will use 2^oversampling samples for internal averaging.
267 * This influences the measurement time and the accuracy; larger values
268 * increase both. The datasheet gives an overview on how measurement time,
269 * accuracy and noise correlate.
270 */
271static void bmp085_set_oversampling(struct bmp085_data *data,
272						unsigned char oversampling)
273{
274	if (oversampling > 3)
275		oversampling = 3;
276	data->oversampling_setting = oversampling;
277}
278
279/*
280 * Returns the currently selected oversampling. Range: 0..3
281 */
282static unsigned char bmp085_get_oversampling(struct bmp085_data *data)
283{
284	return data->oversampling_setting;
285}
286
287/* sysfs callbacks */
288static ssize_t set_oversampling(struct device *dev,
289				struct device_attribute *attr,
290				const char *buf, size_t count)
291{
292	struct bmp085_data *data = dev_get_drvdata(dev);
 
293	unsigned long oversampling;
294	int err = kstrtoul(buf, 10, &oversampling);
295
296	if (err == 0) {
297		mutex_lock(&data->lock);
298		bmp085_set_oversampling(data, oversampling);
299		mutex_unlock(&data->lock);
300		return count;
301	}
302
303	return err;
304}
305
306static ssize_t show_oversampling(struct device *dev,
307				 struct device_attribute *attr, char *buf)
308{
309	struct bmp085_data *data = dev_get_drvdata(dev);
310
311	return sprintf(buf, "%u\n", bmp085_get_oversampling(data));
312}
313static DEVICE_ATTR(oversampling, S_IWUSR | S_IRUGO,
314					show_oversampling, set_oversampling);
315
316
317static ssize_t show_temperature(struct device *dev,
318				struct device_attribute *attr, char *buf)
319{
320	int temperature;
321	int status;
322	struct bmp085_data *data = dev_get_drvdata(dev);
 
323
324	status = bmp085_get_temperature(data, &temperature);
325	if (status < 0)
326		return status;
327	else
328		return sprintf(buf, "%d\n", temperature);
329}
330static DEVICE_ATTR(temp0_input, S_IRUGO, show_temperature, NULL);
331
332
333static ssize_t show_pressure(struct device *dev,
334			     struct device_attribute *attr, char *buf)
335{
336	int pressure;
337	int status;
338	struct bmp085_data *data = dev_get_drvdata(dev);
 
339
340	status = bmp085_get_pressure(data, &pressure);
341	if (status < 0)
342		return status;
343	else
344		return sprintf(buf, "%d\n", pressure);
345}
346static DEVICE_ATTR(pressure0_input, S_IRUGO, show_pressure, NULL);
347
348
349static struct attribute *bmp085_attributes[] = {
350	&dev_attr_temp0_input.attr,
351	&dev_attr_pressure0_input.attr,
352	&dev_attr_oversampling.attr,
353	NULL
354};
355
356static const struct attribute_group bmp085_attr_group = {
357	.attrs = bmp085_attributes,
358};
359
360int bmp085_detect(struct device *dev)
361{
362	struct bmp085_data *data = dev_get_drvdata(dev);
363	unsigned int id;
364	int ret;
365
366	ret = regmap_read(data->regmap, BMP085_CHIP_ID_REG, &id);
367	if (ret < 0)
368		return ret;
369
370	if (id != data->chip_id)
371		return -ENODEV;
372
373	return 0;
374}
375EXPORT_SYMBOL_GPL(bmp085_detect);
376
377static void __init bmp085_get_of_properties(struct bmp085_data *data)
378{
379#ifdef CONFIG_OF
380	struct device_node *np = data->dev->of_node;
381	u32 prop;
382
383	if (!np)
384		return;
385
386	if (!of_property_read_u32(np, "chip-id", &prop))
387		data->chip_id = prop & 0xff;
388
389	if (!of_property_read_u32(np, "temp-measurement-period", &prop))
390		data->temp_measurement_period = (prop/100)*HZ;
391
392	if (!of_property_read_u32(np, "default-oversampling", &prop))
393		data->oversampling_setting = prop & 0xff;
394#endif
395}
396
397static int bmp085_init_client(struct bmp085_data *data)
398{
399	int status = bmp085_read_calibration_data(data);
400
401	if (status < 0)
402		return status;
403
404	/* default settings */
405	data->chip_id = BMP085_CHIP_ID;
406	data->last_temp_measurement = 0;
407	data->temp_measurement_period = 1*HZ;
408	data->oversampling_setting = 3;
409
410	bmp085_get_of_properties(data);
411
412	mutex_init(&data->lock);
413
414	return 0;
 
 
415}
416
417struct regmap_config bmp085_regmap_config = {
418	.reg_bits = 8,
419	.val_bits = 8
420};
421EXPORT_SYMBOL_GPL(bmp085_regmap_config);
422
423__devinit int bmp085_probe(struct device *dev, struct regmap *regmap)
424{
425	struct bmp085_data *data;
426	int err = 0;
427
428	data = kzalloc(sizeof(struct bmp085_data), GFP_KERNEL);
429	if (!data) {
430		err = -ENOMEM;
431		goto exit;
432	}
433
434	dev_set_drvdata(dev, data);
435	data->dev = dev;
436	data->regmap = regmap;
 
437
438	/* Initialize the BMP085 chip */
439	err = bmp085_init_client(data);
440	if (err < 0)
441		goto exit_free;
442
443	err = bmp085_detect(dev);
444	if (err < 0) {
445		dev_err(dev, "%s: chip_id failed!\n", BMP085_NAME);
446		goto exit_free;
447	}
448
449	/* Register sysfs hooks */
450	err = sysfs_create_group(&dev->kobj, &bmp085_attr_group);
451	if (err)
452		goto exit_free;
453
454	dev_info(dev, "Successfully initialized %s!\n", BMP085_NAME);
455
456	return 0;
457
458exit_free:
459	kfree(data);
460exit:
461	return err;
462}
463EXPORT_SYMBOL_GPL(bmp085_probe);
464
465int bmp085_remove(struct device *dev)
466{
467	struct bmp085_data *data = dev_get_drvdata(dev);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
468
469	sysfs_remove_group(&data->dev->kobj, &bmp085_attr_group);
470	kfree(data);
 
 
 
 
 
 
471
472	return 0;
 
 
473}
474EXPORT_SYMBOL_GPL(bmp085_remove);
475
476MODULE_AUTHOR("Christoph Mair <christoph.mair@gmail.com>");
 
477MODULE_DESCRIPTION("BMP085 driver");
478MODULE_LICENSE("GPL");