public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCHv2 0/3] Add support for bmp18x to bmp085
@ 2012-03-06 21:08 Eric Andersson
  2012-03-06 21:08 ` [PATCHv2 1/3] misc: clean up bmp085 driver Eric Andersson
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Eric Andersson @ 2012-03-06 21:08 UTC (permalink / raw)
  To: linux-kernel
  Cc: gregkh, alan, arnd, zhengguang.guo, peter.moeller, Eric Andersson

Hi,

This is version 2 of the patch-set that adds support for Bosch Sensortec's
bmp18x pressure sensors.

The patches have been restructured some to incremently expand the existing bmp085
driver. The last patch renames the bmp085 driver to bmp18x simply because the bmp18x
series obsoletes the old bmp085 chips.

--
Best regards,
 Eric

 http://www.unixphere.com

Eric Andersson (3):
  misc: clean up bmp085 driver
  misc: add support for bmp18x chips in bmp085 driver
  misc: rename bmp085 to bmp18x

 drivers/misc/Kconfig       |   38 +++-
 drivers/misc/Makefile      |    4 +-
 drivers/misc/bmp085-i2c.c  |  133 ++++++++++++
 drivers/misc/bmp085.c      |  483 -----------------------------------------
 drivers/misc/bmp18x-i2c.c  |  133 ++++++++++++
 drivers/misc/bmp18x-spi.c  |  139 ++++++++++++
 drivers/misc/bmp18x.c      |  510 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/i2c/bmp18x.h |   62 ++++++
 8 files changed, 1009 insertions(+), 493 deletions(-)
 create mode 100644 drivers/misc/bmp085-i2c.c
 delete mode 100644 drivers/misc/bmp085.c
 create mode 100644 drivers/misc/bmp18x-i2c.c
 create mode 100644 drivers/misc/bmp18x-spi.c
 create mode 100644 drivers/misc/bmp18x.c
 create mode 100644 include/linux/i2c/bmp18x.h

-- 
1.7.3.4


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCHv2 1/3] misc: clean up bmp085 driver
  2012-03-06 21:08 [PATCHv2 0/3] Add support for bmp18x to bmp085 Eric Andersson
@ 2012-03-06 21:08 ` Eric Andersson
  2012-03-06 21:20   ` Arnd Bergmann
  2012-03-06 21:08 ` [PATCHv2 2/3] misc: add support for bmp18x chips to the " Eric Andersson
  2012-03-06 21:08 ` [PATCHv2 3/3] misc: rename bmp085 to bmp18x Eric Andersson
  2 siblings, 1 reply; 12+ messages in thread
From: Eric Andersson @ 2012-03-06 21:08 UTC (permalink / raw)
  To: linux-kernel
  Cc: gregkh, alan, arnd, zhengguang.guo, peter.moeller, Eric Andersson

This patch includes various cleaning of the bmp085 driver including:
- Addition of platform_data and header file
- Implement pm functions
- Whitespaces and alignment fixes
- Minor typos
- Consistency fixes

Reviewed-by: Stefan Nilsson <stefan.nilsson@unixphere.com>
Signed-off-by: Eric Andersson <eric.andersson@unixphere.com>
---
 drivers/misc/bmp085.c      |  178 ++++++++++++++++++++++++++++----------------
 include/linux/i2c/bmp085.h |   43 +++++++++++
 2 files changed, 158 insertions(+), 63 deletions(-)
 create mode 100644 include/linux/i2c/bmp085.h

diff --git a/drivers/misc/bmp085.c b/drivers/misc/bmp085.c
index b29a2be..5978094 100644
--- a/drivers/misc/bmp085.c
+++ b/drivers/misc/bmp085.c
@@ -1,4 +1,6 @@
 /*  Copyright (c) 2010  Christoph Mair <christoph.mair@gmail.com>
+    Copyright (c) 2012  Bosch Sensortec GmbH
+    Copyright (c) 2012  Unixphere AB
 
     This driver supports the bmp085 digital barometric pressure
     and temperature sensor from Bosch Sensortec. The datasheet
@@ -42,13 +44,13 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-
 #include <linux/module.h>
+#include <linux/device.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-
+#include <linux/i2c/bmp085.h>
 
 #define BMP085_I2C_ADDRESS		0x77
 #define BMP085_CHIP_ID			0x55
@@ -56,7 +58,6 @@
 #define BMP085_CALIBRATION_DATA_START	0xAA
 #define BMP085_CALIBRATION_DATA_LENGTH	11	/* 16 bit values */
 #define BMP085_CHIP_ID_REG		0xD0
-#define BMP085_VERSION_REG		0xD1
 #define BMP085_CTRL_REG			0xF4
 #define BMP085_TEMP_MEASUREMENT		0x2E
 #define BMP085_PRESSURE_MEASUREMENT	0x34
@@ -65,9 +66,6 @@
 #define BMP085_CONVERSION_REGISTER_XLSB	0xF8
 #define BMP085_TEMP_CONVERSION_TIME	5
 
-#define BMP085_CLIENT_NAME		"bmp085"
-
-
 static const unsigned short normal_i2c[] = { BMP085_I2C_ADDRESS,
 							I2C_CLIENT_END };
 
@@ -78,20 +76,18 @@ struct bmp085_calibration_data {
 	s16 MB, MC, MD;
 };
 
-
-/* Each client has this additional data */
 struct bmp085_data {
-	struct i2c_client *client;
-	struct mutex lock;
-	struct bmp085_calibration_data calibration;
-	u32 raw_temperature;
-	u32 raw_pressure;
-	unsigned char oversampling_setting;
-	u32 last_temp_measurement;
-	s32 b6; /* calculated temperature correction coefficient */
+	struct	i2c_client *client;
+	struct	mutex lock;
+	struct	bmp085_calibration_data calibration;
+	u8	oversampling_setting;
+	u32	raw_temperature;
+	u32	raw_pressure;
+	u32	temp_measurement_period;
+	u32	last_temp_measurement;
+	s32	b6; /* calculated temperature correction coefficient */
 };
 
-
 static s32 bmp085_read_calibration_data(struct i2c_client *client)
 {
 	u16 tmp[BMP085_CALIBRATION_DATA_LENGTH];
@@ -99,12 +95,12 @@ static s32 bmp085_read_calibration_data(struct i2c_client *client)
 	struct bmp085_calibration_data *cali = &(data->calibration);
 	s32 status = i2c_smbus_read_i2c_block_data(client,
 				BMP085_CALIBRATION_DATA_START,
-				BMP085_CALIBRATION_DATA_LENGTH*sizeof(u16),
+				(BMP085_CALIBRATION_DATA_LENGTH << 1),
 				(u8 *)tmp);
 	if (status < 0)
 		return status;
 
-	if (status != BMP085_CALIBRATION_DATA_LENGTH*sizeof(u16))
+	if (status != (BMP085_CALIBRATION_DATA_LENGTH << 1))
 		return -EIO;
 
 	cali->AC1 =  be16_to_cpu(tmp[0]);
@@ -121,7 +117,6 @@ static s32 bmp085_read_calibration_data(struct i2c_client *client)
 	return 0;
 }
 
-
 static s32 bmp085_update_raw_temperature(struct bmp085_data *data)
 {
 	u16 tmp;
@@ -129,8 +124,8 @@ static s32 bmp085_update_raw_temperature(struct bmp085_data *data)
 
 	mutex_lock(&data->lock);
 	status = i2c_smbus_write_byte_data(data->client, BMP085_CTRL_REG,
-						BMP085_TEMP_MEASUREMENT);
-	if (status != 0) {
+				   BMP085_TEMP_MEASUREMENT);
+	if (status < 0) {
 		dev_err(&data->client->dev,
 			"Error while requesting temperature measurement.\n");
 		goto exit;
@@ -163,8 +158,9 @@ static s32 bmp085_update_raw_pressure(struct bmp085_data *data)
 
 	mutex_lock(&data->lock);
 	status = i2c_smbus_write_byte_data(data->client, BMP085_CTRL_REG,
-		BMP085_PRESSURE_MEASUREMENT + (data->oversampling_setting<<6));
-	if (status != 0) {
+			BMP085_PRESSURE_MEASUREMENT +
+			(data->oversampling_setting << 6));
+	if (status < 0) {
 		dev_err(&data->client->dev,
 			"Error while requesting pressure measurement.\n");
 		goto exit;
@@ -193,7 +189,6 @@ exit:
 	return status;
 }
 
-
 /*
  * This function starts the temperature measurement and returns the value
  * in tenth of a degree celsius.
@@ -205,7 +200,7 @@ static s32 bmp085_get_temperature(struct bmp085_data *data, int *temperature)
 	int status;
 
 	status = bmp085_update_raw_temperature(data);
-	if (status != 0)
+	if (status < 0)
 		goto exit;
 
 	x1 = ((data->raw_temperature - cali->AC6) * cali->AC5) >> 15;
@@ -222,8 +217,10 @@ exit:
 /*
  * This function starts the pressure measurement and returns the value
  * in millibar. Since the pressure depends on the ambient temperature,
- * a temperature measurement is executed if the last known value is older
- * than one second.
+ * a temperature measurement is executed according to the given temperature
+ * measurememt period (default is 1 sec boundary). This period could vary
+ * and needs to be adjusted according to the sensor environment, i.e. if big
+ * temperature variations then the temperature needs to be read out often.
  */
 static s32 bmp085_get_pressure(struct bmp085_data *data, int *pressure)
 {
@@ -233,16 +230,17 @@ static s32 bmp085_get_pressure(struct bmp085_data *data, int *pressure)
 	s32 p;
 	int status;
 
-	/* alt least every second force an update of the ambient temperature */
-	if (data->last_temp_measurement + 1*HZ < jiffies) {
+	/* update the ambient temperature according to the given meas. period */
+	if (data->last_temp_measurement +
+			data->temp_measurement_period < jiffies) {
 		status = bmp085_get_temperature(data, NULL);
-		if (status != 0)
-			goto exit;
+		if (status < 0)
+			return status;
 	}
 
 	status = bmp085_update_raw_pressure(data);
-	if (status != 0)
-		goto exit;
+	if (status < 0)
+		return status;
 
 	x1 = (data->b6 * data->b6) >> 12;
 	x1 *= cali->B2;
@@ -273,15 +271,14 @@ static s32 bmp085_get_pressure(struct bmp085_data *data, int *pressure)
 
 	*pressure = p;
 
-exit:
-	return status;
+	return 0;
 }
 
 /*
  * This function sets the chip-internal oversampling. Valid values are 0..3.
  * The chip will use 2^oversampling samples for internal averaging.
  * This influences the measurement time and the accuracy; larger values
- * increase both. The datasheet gives on overview on how measurement time,
+ * increase both. The datasheet gives an overview on how measurement time,
  * accuracy and noise correlate.
  */
 static void bmp085_set_oversampling(struct bmp085_data *data,
@@ -308,12 +305,16 @@ static ssize_t set_oversampling(struct device *dev,
 	struct i2c_client *client = to_i2c_client(dev);
 	struct bmp085_data *data = i2c_get_clientdata(client);
 	unsigned long oversampling;
-	int success = strict_strtoul(buf, 10, &oversampling);
-	if (success == 0) {
+	int err = kstrtoul(buf, 10, &oversampling);
+
+	if (err == 0) {
+		mutex_lock(&data->lock);
 		bmp085_set_oversampling(data, oversampling);
+		mutex_unlock(&data->lock);
 		return count;
 	}
-	return success;
+
+	return err;
 }
 
 static ssize_t show_oversampling(struct device *dev,
@@ -321,6 +322,7 @@ static ssize_t show_oversampling(struct device *dev,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct bmp085_data *data = i2c_get_clientdata(client);
+
 	return sprintf(buf, "%u\n", bmp085_get_oversampling(data));
 }
 static DEVICE_ATTR(oversampling, S_IWUSR | S_IRUGO,
@@ -336,7 +338,7 @@ static ssize_t show_temperature(struct device *dev,
 	struct bmp085_data *data = i2c_get_clientdata(client);
 
 	status = bmp085_get_temperature(data, &temperature);
-	if (status != 0)
+	if (status < 0)
 		return status;
 	else
 		return sprintf(buf, "%d\n", temperature);
@@ -353,7 +355,7 @@ static ssize_t show_pressure(struct device *dev,
 	struct bmp085_data *data = i2c_get_clientdata(client);
 
 	status = bmp085_get_pressure(data, &pressure);
-	if (status != 0)
+	if (status < 0)
 		return status;
 	else
 		return sprintf(buf, "%d\n", pressure);
@@ -385,43 +387,58 @@ static int bmp085_detect(struct i2c_client *client, struct i2c_board_info *info)
 
 static int bmp085_init_client(struct i2c_client *client)
 {
-	unsigned char version;
-	int status;
 	struct bmp085_data *data = i2c_get_clientdata(client);
+	struct bmp085_platform_data *pdata = client->dev.platform_data;
+	int status = bmp085_read_calibration_data(client);
+
+	if (status < 0)
+		return status;
+
 	data->client = client;
-	status = bmp085_read_calibration_data(client);
-	if (status != 0)
-		goto exit;
-	version = i2c_smbus_read_byte_data(client, BMP085_VERSION_REG);
 	data->last_temp_measurement = 0;
-	data->oversampling_setting = 3;
+	data->temp_measurement_period =
+		pdata ? (pdata->temp_measurement_period/1000)*HZ : 1*HZ;
+	data->oversampling_setting = pdata ? pdata->default_oversampling : 3;
 	mutex_init(&data->lock);
-	dev_info(&data->client->dev, "BMP085 ver. %d.%d found.\n",
-			(version & 0x0F), (version & 0xF0) >> 4);
-exit:
-	return status;
+
+	return 0;
 }
 
 static int __devinit bmp085_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id)
+			const struct i2c_device_id *id)
 {
 	struct bmp085_data *data;
+	struct bmp085_platform_data *pdata = client->dev.platform_data;
+	u8 chip_id = (pdata && pdata->chip_id) ? pdata->chip_id :
+						 BMP085_CHIP_ID;
 	int err = 0;
 
+	if (pdata && pdata->init_hw) {
+		err = pdata->init_hw(&client->dev);
+		if (err) {
+			dev_err(&client->dev, "%s: init_hw failed!\n",
+				BMP085_NAME);
+			return err;
+		}
+	}
+
 	data = kzalloc(sizeof(struct bmp085_data), GFP_KERNEL);
 	if (!data) {
 		err = -ENOMEM;
 		goto exit;
 	}
 
-	/* default settings after POR */
-	data->oversampling_setting = 0x00;
-
 	i2c_set_clientdata(client, data);
 
+	if (i2c_smbus_read_byte_data(client, BMP085_CHIP_ID_REG) != chip_id) {
+		dev_err(&client->dev, "%s: chip_id failed!\n", BMP085_NAME);
+		err = -ENODEV;
+		goto exit_free;
+	}
+
 	/* Initialize the BMP085 chip */
 	err = bmp085_init_client(client);
-	if (err != 0)
+	if (err < 0)
 		goto exit_free;
 
 	/* Register sysfs hooks */
@@ -429,22 +446,57 @@ static int __devinit bmp085_probe(struct i2c_client *client,
 	if (err)
 		goto exit_free;
 
-	dev_info(&data->client->dev, "Successfully initialized bmp085!\n");
-	goto exit;
+	dev_info(&client->dev, "Succesfully initialized bmp085!\n");
+	return 0;
 
 exit_free:
 	kfree(data);
 exit:
+	if (pdata && pdata->deinit_hw)
+		pdata->deinit_hw(&client->dev);
 	return err;
 }
 
 static int __devexit bmp085_remove(struct i2c_client *client)
 {
+	struct bmp085_data *data = i2c_get_clientdata(client);
+	struct bmp085_platform_data *pdata = client->dev.platform_data;
+
 	sysfs_remove_group(&client->dev.kobj, &bmp085_attr_group);
-	kfree(i2c_get_clientdata(client));
+
+	if (pdata && pdata->deinit_hw)
+		pdata->deinit_hw(&client->dev);
+
+	kfree(data);
+
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int bmp085_suspend(struct device *dev)
+{
+	struct bmp085_platform_data *pdata = dev->platform_data;
+
+	if (pdata && pdata->deinit_hw)
+		pdata->deinit_hw(dev);
+
+	return 0;
+}
+
+static int bmp085_resume(struct device *dev)
+{
+	struct bmp085_platform_data *pdata = dev->platform_data;
+
+	if (pdata && pdata->init_hw)
+		return pdata->init_hw(dev);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(bmp085_pm_ops, bmp085_suspend,
+			 bmp085_resume);
+
 static const struct i2c_device_id bmp085_id[] = {
 	{ "bmp085", 0 },
 	{ }
@@ -454,7 +506,8 @@ MODULE_DEVICE_TABLE(i2c, bmp085_id);
 static struct i2c_driver bmp085_driver = {
 	.driver = {
 		.owner = THIS_MODULE,
-		.name	= "bmp085"
+		.name	= "bmp085",
+		.pm	= &bmp085_pm_ops,
 	},
 	.id_table	= bmp085_id,
 	.probe		= bmp085_probe,
@@ -474,7 +527,6 @@ static void __exit bmp085_exit(void)
 	i2c_del_driver(&bmp085_driver);
 }
 
-
 MODULE_AUTHOR("Christoph Mair <christoph.mair@gmail.com");
 MODULE_DESCRIPTION("BMP085 driver");
 MODULE_LICENSE("GPL");
diff --git a/include/linux/i2c/bmp085.h b/include/linux/i2c/bmp085.h
new file mode 100644
index 0000000..e6fc752
--- /dev/null
+++ b/include/linux/i2c/bmp085.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2012  Bosch Sensortec GmbH
+ * Copyright (c) 2012  Unixphere AB
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _BMP085_H
+#define _BMP085_H
+
+#define BMP085_NAME "bmp085"
+
+/**
+ * struct bmp085_platform_data - represents platform data for the bmp085 driver
+ * @chip_id: Configurable chip id for non-default chip revisions
+ * @default_oversampling: Default oversampling value to be used at startup,
+ * value range is 0-3 with rising sensitivity.
+ * @temp_measurement_period: Temperature measurement period (milliseconds), set
+ * to zero if unsure.
+ * @init_hw: Callback for hw specific startup
+ * @deinit_hw: Callback for hw specific shutdown
+ */
+struct bmp085_platform_data {
+	u8	chip_id;
+	u8	default_oversampling;
+	u32	temp_measurement_period;
+	int	(*init_hw)(struct device *dev);
+	void	(*deinit_hw)(struct device *dev);
+};
+
+#endif
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCHv2 2/3] misc: add support for bmp18x chips to the bmp085 driver
  2012-03-06 21:08 [PATCHv2 0/3] Add support for bmp18x to bmp085 Eric Andersson
  2012-03-06 21:08 ` [PATCHv2 1/3] misc: clean up bmp085 driver Eric Andersson
@ 2012-03-06 21:08 ` Eric Andersson
  2012-03-06 21:27   ` Arnd Bergmann
  2012-03-06 21:08 ` [PATCHv2 3/3] misc: rename bmp085 to bmp18x Eric Andersson
  2 siblings, 1 reply; 12+ messages in thread
From: Eric Andersson @ 2012-03-06 21:08 UTC (permalink / raw)
  To: linux-kernel
  Cc: gregkh, alan, arnd, zhengguang.guo, peter.moeller, Eric Andersson

The bmp18x chip family comes in an I2C respectively SPI variant.
Hence, the bmp085 driver was split to support both buses.

Tested-by: Zhengguang Guo <zhengguang.guo@bosch-sensortec.com>
Reviewed-by: Stefan Nilsson <stefan.nilsson@unixphere.com>
Signed-off-by: Eric Andersson <eric.andersson@unixphere.com>
---
 drivers/misc/Kconfig       |   26 ++++++-
 drivers/misc/Makefile      |    2 +
 drivers/misc/bmp085-i2c.c  |  132 ++++++++++++++++++++++++++++++++++
 drivers/misc/bmp085-spi.c  |  140 +++++++++++++++++++++++++++++++++++++
 drivers/misc/bmp085.c      |  167 +++++++++++++++++++-------------------------
 include/linux/i2c/bmp085.h |   22 ++++++-
 6 files changed, 391 insertions(+), 98 deletions(-)
 create mode 100644 drivers/misc/bmp085-i2c.c
 create mode 100644 drivers/misc/bmp085-spi.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index c779509..9bf65c3 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -453,14 +453,34 @@ config ARM_CHARLCD
 
 config BMP085
 	tristate "BMP085 digital pressure sensor"
-	depends on I2C && SYSFS
+	depends on (I2C || SPI_MASTER) && SYSFS
 	help
-	  If you say yes here you get support for the Bosch Sensortec
-	  BMP085 digital pressure sensor.
+	  Say Y here if you want support for Bosch Sensortec's digital
+	  pressure sensors BMP085 and BMP18x.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called bmp085.
 
+config BMP085_I2C
+	tristate "support I2C bus connection"
+	depends on BMP085 && I2C
+	help
+	  Say Y here if you want to support Bosch Sensortec's digital pressure
+	  sensor hooked to an I2C bus.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bmp085-i2c.
+
+config BMP085_SPI
+	tristate "support SPI bus connection"
+	depends on BMP085 && SPI_MASTER
+	help
+	  Say Y here if you want to support Bosch Sensortec's digital pressure
+	  sensor hooked to an SPI bus.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bmp085-spi.
+
 config PCH_PHUB
 	tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) PHUB"
 	depends on PCI
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 3e1d801..509d056 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -11,6 +11,8 @@ obj-$(CONFIG_ATMEL_PWM)		+= atmel_pwm.o
 obj-$(CONFIG_ATMEL_SSC)		+= atmel-ssc.o
 obj-$(CONFIG_ATMEL_TCLIB)	+= atmel_tclib.o
 obj-$(CONFIG_BMP085)		+= bmp085.o
+obj-$(CONFIG_BMP085_I2C)	+= bmp085-i2c.o
+obj-$(CONFIG_BMP085_SPI)	+= bmp085-spi.o
 obj-$(CONFIG_ICS932S401)	+= ics932s401.o
 obj-$(CONFIG_LKDTM)		+= lkdtm.o
 obj-$(CONFIG_TIFM_CORE)       	+= tifm_core.o
diff --git a/drivers/misc/bmp085-i2c.c b/drivers/misc/bmp085-i2c.c
new file mode 100644
index 0000000..1e8eabf
--- /dev/null
+++ b/drivers/misc/bmp085-i2c.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2012  Bosch Sensortec GmbH
+ * Copyright (c) 2012  Unixphere AB
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c/bmp085.h>
+
+static const unsigned short normal_i2c[] = { BMP085_I2C_ADDRESS,
+							I2C_CLIENT_END };
+
+static int bmp085_i2c_read_block(void *client, u8 reg, int len, char *buf)
+{
+	return i2c_smbus_read_i2c_block_data(client, reg, len, buf);
+}
+
+static int bmp085_i2c_read_byte(void *client, u8 reg)
+{
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int bmp085_i2c_write_byte(void *client, u8 reg, u8 value)
+{
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static const struct bmp085_bus_ops bmp085_i2c_bus_ops = {
+	.read_block	= bmp085_i2c_read_block,
+	.read_byte	= bmp085_i2c_read_byte,
+	.write_byte	= bmp085_i2c_write_byte
+};
+
+static int bmp085_i2c_detect(struct i2c_client *client,
+			     struct i2c_board_info *info)
+{
+	if (client->addr != BMP085_I2C_ADDRESS)
+		return -ENODEV;
+
+	return bmp085_detect(&client->dev);
+}
+
+static int __devinit bmp085_i2c_probe(struct i2c_client *client,
+				      const struct i2c_device_id *id)
+{
+	struct bmp085_data_bus data_bus = {
+		.bops = &bmp085_i2c_bus_ops,
+		.client = client
+	};
+
+	return bmp085_probe(&client->dev, &data_bus);
+}
+
+static void bmp085_i2c_shutdown(struct i2c_client *client)
+{
+	bmp085_disable(&client->dev);
+}
+
+static int bmp085_i2c_remove(struct i2c_client *client)
+{
+	return bmp085_remove(&client->dev);
+}
+
+#ifdef CONFIG_PM
+static int bmp085_i2c_suspend(struct device *dev)
+{
+	return bmp085_disable(dev);
+}
+
+static int bmp085_i2c_resume(struct device *dev)
+{
+	return bmp085_enable(dev);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(bmp085_i2c_pm_ops, bmp085_i2c_suspend,
+			 bmp085_i2c_resume);
+
+static const struct i2c_device_id bmp085_id[] = {
+	{ BMP085_NAME, 0 },
+	{ "bmp085", 0 },
+	{ "bmp180", 0 },
+	{ "bmp181", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, bmp085_id);
+
+static struct i2c_driver bmp085_i2c_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= BMP085_NAME,
+		.pm	= &bmp085_i2c_pm_ops,
+	},
+	.id_table	= bmp085_id,
+	.probe		= bmp085_i2c_probe,
+	.shutdown	= bmp085_i2c_shutdown,
+	.remove		= __devexit_p(bmp085_i2c_remove),
+
+	.detect		= bmp085_i2c_detect,
+	.address_list	= normal_i2c
+};
+
+static int __init bmp085_i2c_init(void)
+{
+	return i2c_add_driver(&bmp085_i2c_driver);
+}
+
+static void __exit bmp085_i2c_exit(void)
+{
+	i2c_del_driver(&bmp085_i2c_driver);
+}
+
+MODULE_AUTHOR("Eric Andersson <eric.andersson@unixphere.com>");
+MODULE_DESCRIPTION("BMP085 I2C bus driver");
+MODULE_LICENSE("GPL");
+
+module_init(bmp085_i2c_init);
+module_exit(bmp085_i2c_exit);
diff --git a/drivers/misc/bmp085-spi.c b/drivers/misc/bmp085-spi.c
new file mode 100644
index 0000000..a4772ac
--- /dev/null
+++ b/drivers/misc/bmp085-spi.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2012  Bosch Sensortec GmbH
+ * Copyright (c) 2012  Unixphere AB
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c/bmp085.h>
+
+static int bmp085_spi_write_byte(void *client, u8 reg, u8 value)
+{
+	u8 data[2] = { reg, value };
+	return spi_write(client, data, 2);
+}
+
+static int bmp085_spi_read_block(void *client, u8 reg, int len, char *buf)
+{
+	int err = bmp085_spi_write_byte(client, reg, 0);
+
+	if (err < 0)
+		return err;
+
+	return spi_read(client, buf, len);
+}
+
+static int bmp085_spi_read_byte(void *client, u8 reg)
+{
+	u8 data;
+	int err = bmp085_spi_write_byte(client, reg, 0);
+
+	if (err < 0)
+		return err;
+
+	err = spi_read(client, &data, 1);
+	if (err < 0)
+		return err;
+
+	return data;
+}
+
+static const struct bmp085_bus_ops bmp085_spi_bus_ops = {
+	.read_block	= bmp085_spi_read_block,
+	.read_byte	= bmp085_spi_read_byte,
+	.write_byte	= bmp085_spi_write_byte
+};
+
+static int __devinit bmp085_spi_probe(struct spi_device *client)
+{
+	int err;
+	struct bmp085_data_bus data_bus = {
+		.bops = &bmp085_spi_bus_ops,
+		.client = client
+	};
+
+	client->bits_per_word = 8;
+	err = spi_setup(client);
+	if (err < 0) {
+		dev_err(&client->dev, "spi_setup failed!\n");
+		return err;
+	}
+
+	return bmp085_probe(&client->dev, &data_bus);
+}
+
+static void bmp085_spi_shutdown(struct spi_device *client)
+{
+	bmp085_disable(&client->dev);
+}
+
+static int bmp085_spi_remove(struct spi_device *client)
+{
+	return bmp085_remove(&client->dev);
+}
+
+#ifdef CONFIG_PM
+static int bmp085_spi_suspend(struct device *dev)
+{
+	return bmp085_disable(dev);
+}
+
+static int bmp085_spi_resume(struct device *dev)
+{
+	return bmp085_enable(dev);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(bmp085_spi_pm_ops, bmp085_spi_suspend,
+					    bmp085_spi_resume);
+
+static const struct spi_device_id bmp085_id[] = {
+	{ BMP085_NAME, 0 },
+	{ "bmp085", 0 },
+	{ "bmp180", 0 },
+	{ "bmp181", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, bmp085_id);
+
+static struct spi_driver bmp085_spi_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= BMP085_NAME,
+		.pm	= &bmp085_spi_pm_ops,
+	},
+	.id_table	= bmp085_id,
+	.probe		= bmp085_spi_probe,
+	.shutdown	= bmp085_spi_shutdown,
+	.remove		= __devexit_p(bmp085_spi_remove)
+};
+
+static int __init bmp085_spi_init(void)
+{
+	return spi_register_driver(&bmp085_spi_driver);
+}
+
+static void __exit bmp085_spi_exit(void)
+{
+	spi_unregister_driver(&bmp085_spi_driver);
+}
+
+MODULE_AUTHOR("Eric Andersson <eric.andersson@unixphere.com>");
+MODULE_DESCRIPTION("BMP085 SPI bus driver");
+MODULE_LICENSE("GPL");
+
+module_init(bmp085_spi_init);
+module_exit(bmp085_spi_exit);
diff --git a/drivers/misc/bmp085.c b/drivers/misc/bmp085.c
index 5978094..78406d7 100644
--- a/drivers/misc/bmp085.c
+++ b/drivers/misc/bmp085.c
@@ -3,9 +3,10 @@
     Copyright (c) 2012  Unixphere AB
 
     This driver supports the bmp085 digital barometric pressure
-    and temperature sensor from Bosch Sensortec. The datasheet
-    is available from their website:
+    and temperature sensor from Bosch Sensortec. The datasheets
+    are available from their website:
     http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP085-DS000-05.pdf
+    http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP180-DS000-07.pdf
 
     A pressure measurement is issued by reading from pressure0_input.
     The return value ranges from 30000 to 110000 pascal with a resulution
@@ -47,12 +48,10 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/init.h>
-#include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/i2c/bmp085.h>
 
-#define BMP085_I2C_ADDRESS		0x77
 #define BMP085_CHIP_ID			0x55
 
 #define BMP085_CALIBRATION_DATA_START	0xAA
@@ -66,9 +65,6 @@
 #define BMP085_CONVERSION_REGISTER_XLSB	0xF8
 #define BMP085_TEMP_CONVERSION_TIME	5
 
-static const unsigned short normal_i2c[] = { BMP085_I2C_ADDRESS,
-							I2C_CLIENT_END };
-
 struct bmp085_calibration_data {
 	s16 AC1, AC2, AC3;
 	u16 AC4, AC5, AC6;
@@ -77,7 +73,8 @@ struct bmp085_calibration_data {
 };
 
 struct bmp085_data {
-	struct	i2c_client *client;
+	struct	bmp085_data_bus data_bus;
+	struct	device *dev;
 	struct	mutex lock;
 	struct	bmp085_calibration_data calibration;
 	u8	oversampling_setting;
@@ -88,13 +85,29 @@ struct bmp085_data {
 	s32	b6; /* calculated temperature correction coefficient */
 };
 
-static s32 bmp085_read_calibration_data(struct i2c_client *client)
+static inline int bmp085_read_block(struct bmp085_data *data, u8 reg, int len,
+				    char *buf)
+{
+	return data->data_bus.bops->read_block(data->data_bus.client, reg,
+					       len, buf);
+}
+
+static inline int bmp085_read_byte(struct bmp085_data *data, u8 reg)
+{
+	return data->data_bus.bops->read_byte(data->data_bus.client, reg);
+}
+
+static inline int bmp085_write_byte(struct bmp085_data *data, u8 reg, u8 value)
+{
+	return data->data_bus.bops->write_byte(data->data_bus.client, reg,
+					       value);
+}
+
+static s32 bmp085_read_calibration_data(struct bmp085_data *data)
 {
 	u16 tmp[BMP085_CALIBRATION_DATA_LENGTH];
-	struct bmp085_data *data = i2c_get_clientdata(client);
 	struct bmp085_calibration_data *cali = &(data->calibration);
-	s32 status = i2c_smbus_read_i2c_block_data(client,
-				BMP085_CALIBRATION_DATA_START,
+	s32 status = bmp085_read_block(data, BMP085_CALIBRATION_DATA_START,
 				(BMP085_CALIBRATION_DATA_LENGTH << 1),
 				(u8 *)tmp);
 	if (status < 0)
@@ -123,21 +136,21 @@ static s32 bmp085_update_raw_temperature(struct bmp085_data *data)
 	s32 status;
 
 	mutex_lock(&data->lock);
-	status = i2c_smbus_write_byte_data(data->client, BMP085_CTRL_REG,
+	status = bmp085_write_byte(data, BMP085_CTRL_REG,
 				   BMP085_TEMP_MEASUREMENT);
 	if (status < 0) {
-		dev_err(&data->client->dev,
+		dev_err(data->dev,
 			"Error while requesting temperature measurement.\n");
 		goto exit;
 	}
 	msleep(BMP085_TEMP_CONVERSION_TIME);
 
-	status = i2c_smbus_read_i2c_block_data(data->client,
-		BMP085_CONVERSION_REGISTER_MSB, sizeof(tmp), (u8 *)&tmp);
+	status = bmp085_read_block(data, BMP085_CONVERSION_REGISTER_MSB,
+				   sizeof(tmp), (u8 *)&tmp);
 	if (status < 0)
 		goto exit;
 	if (status != sizeof(tmp)) {
-		dev_err(&data->client->dev,
+		dev_err(data->dev,
 			"Error while reading temperature measurement result\n");
 		status = -EIO;
 		goto exit;
@@ -157,11 +170,11 @@ static s32 bmp085_update_raw_pressure(struct bmp085_data *data)
 	s32 status;
 
 	mutex_lock(&data->lock);
-	status = i2c_smbus_write_byte_data(data->client, BMP085_CTRL_REG,
+	status = bmp085_write_byte(data, BMP085_CTRL_REG,
 			BMP085_PRESSURE_MEASUREMENT +
 			(data->oversampling_setting << 6));
 	if (status < 0) {
-		dev_err(&data->client->dev,
+		dev_err(data->dev,
 			"Error while requesting pressure measurement.\n");
 		goto exit;
 	}
@@ -170,12 +183,12 @@ static s32 bmp085_update_raw_pressure(struct bmp085_data *data)
 	msleep(2+(3 << data->oversampling_setting));
 
 	/* copy data into a u32 (4 bytes), but skip the first byte. */
-	status = i2c_smbus_read_i2c_block_data(data->client,
-			BMP085_CONVERSION_REGISTER_MSB, 3, ((u8 *)&tmp)+1);
+	status = bmp085_read_block(data, BMP085_CONVERSION_REGISTER_MSB, 3,
+				   ((u8 *)&tmp)+1);
 	if (status < 0)
 		goto exit;
 	if (status != 3) {
-		dev_err(&data->client->dev,
+		dev_err(data->dev,
 			"Error while reading pressure measurement results\n");
 		status = -EIO;
 		goto exit;
@@ -302,8 +315,7 @@ static ssize_t set_oversampling(struct device *dev,
 				struct device_attribute *attr,
 				const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct bmp085_data *data = i2c_get_clientdata(client);
+	struct bmp085_data *data = dev_get_drvdata(dev);
 	unsigned long oversampling;
 	int err = kstrtoul(buf, 10, &oversampling);
 
@@ -320,8 +332,7 @@ static ssize_t set_oversampling(struct device *dev,
 static ssize_t show_oversampling(struct device *dev,
 				 struct device_attribute *attr, char *buf)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct bmp085_data *data = i2c_get_clientdata(client);
+	struct bmp085_data *data = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%u\n", bmp085_get_oversampling(data));
 }
@@ -334,8 +345,7 @@ static ssize_t show_temperature(struct device *dev,
 {
 	int temperature;
 	int status;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct bmp085_data *data = i2c_get_clientdata(client);
+	struct bmp085_data *data = dev_get_drvdata(dev);
 
 	status = bmp085_get_temperature(data, &temperature);
 	if (status < 0)
@@ -351,8 +361,7 @@ static ssize_t show_pressure(struct device *dev,
 {
 	int pressure;
 	int status;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct bmp085_data *data = i2c_get_clientdata(client);
+	struct bmp085_data *data = dev_get_drvdata(dev);
 
 	status = bmp085_get_pressure(data, &pressure);
 	if (status < 0)
@@ -374,27 +383,28 @@ static const struct attribute_group bmp085_attr_group = {
 	.attrs = bmp085_attributes,
 };
 
-static int bmp085_detect(struct i2c_client *client, struct i2c_board_info *info)
+int bmp085_detect(struct device *dev)
 {
-	if (client->addr != BMP085_I2C_ADDRESS)
-		return -ENODEV;
+	struct bmp085_data *data = dev_get_drvdata(dev);
+	struct bmp085_platform_data *pdata = dev->platform_data;
+	u8 chip_id = (pdata && pdata->chip_id) ? pdata->chip_id :
+						 BMP085_CHIP_ID;
 
-	if (i2c_smbus_read_byte_data(client, BMP085_CHIP_ID_REG) != BMP085_CHIP_ID)
+	if (bmp085_read_byte(data, BMP085_CHIP_ID_REG) != chip_id)
 		return -ENODEV;
 
 	return 0;
 }
+EXPORT_SYMBOL(bmp085_detect);
 
-static int bmp085_init_client(struct i2c_client *client)
+static int bmp085_init_client(struct bmp085_data *data,
+			      struct bmp085_platform_data *pdata)
 {
-	struct bmp085_data *data = i2c_get_clientdata(client);
-	struct bmp085_platform_data *pdata = client->dev.platform_data;
-	int status = bmp085_read_calibration_data(client);
+	int status = bmp085_read_calibration_data(data);
 
 	if (status < 0)
 		return status;
 
-	data->client = client;
 	data->last_temp_measurement = 0;
 	data->temp_measurement_period =
 		pdata ? (pdata->temp_measurement_period/1000)*HZ : 1*HZ;
@@ -404,19 +414,18 @@ static int bmp085_init_client(struct i2c_client *client)
 	return 0;
 }
 
-static int __devinit bmp085_probe(struct i2c_client *client,
-			const struct i2c_device_id *id)
+__devinit int bmp085_probe(struct device *dev, struct bmp085_data_bus *data_bus)
 {
 	struct bmp085_data *data;
-	struct bmp085_platform_data *pdata = client->dev.platform_data;
+	struct bmp085_platform_data *pdata = dev->platform_data;
 	u8 chip_id = (pdata && pdata->chip_id) ? pdata->chip_id :
 						 BMP085_CHIP_ID;
 	int err = 0;
 
 	if (pdata && pdata->init_hw) {
-		err = pdata->init_hw(&client->dev);
+		err = pdata->init_hw(dev);
 		if (err) {
-			dev_err(&client->dev, "%s: init_hw failed!\n",
+			dev_err(dev, "%s: init_hw failed!\n",
 				BMP085_NAME);
 			return err;
 		}
@@ -428,52 +437,56 @@ static int __devinit bmp085_probe(struct i2c_client *client,
 		goto exit;
 	}
 
-	i2c_set_clientdata(client, data);
+	dev_set_drvdata(dev, data);
+	data->data_bus = *data_bus;
+	data->dev = dev;
 
-	if (i2c_smbus_read_byte_data(client, BMP085_CHIP_ID_REG) != chip_id) {
-		dev_err(&client->dev, "%s: chip_id failed!\n", BMP085_NAME);
+	if (bmp085_read_byte(data, BMP085_CHIP_ID_REG) != chip_id) {
+		dev_err(dev, "%s: chip_id failed!\n", BMP085_NAME);
 		err = -ENODEV;
 		goto exit_free;
 	}
 
 	/* Initialize the BMP085 chip */
-	err = bmp085_init_client(client);
+	err = bmp085_init_client(data, pdata);
 	if (err < 0)
 		goto exit_free;
 
 	/* Register sysfs hooks */
-	err = sysfs_create_group(&client->dev.kobj, &bmp085_attr_group);
+	err = sysfs_create_group(&dev->kobj, &bmp085_attr_group);
 	if (err)
 		goto exit_free;
 
-	dev_info(&client->dev, "Succesfully initialized bmp085!\n");
+	dev_info(dev, "Succesfully initialized bmp085!\n");
 	return 0;
 
 exit_free:
 	kfree(data);
 exit:
 	if (pdata && pdata->deinit_hw)
-		pdata->deinit_hw(&client->dev);
+		pdata->deinit_hw(dev);
 	return err;
 }
+EXPORT_SYMBOL(bmp085_probe);
 
-static int __devexit bmp085_remove(struct i2c_client *client)
+int bmp085_remove(struct device *dev)
 {
-	struct bmp085_data *data = i2c_get_clientdata(client);
-	struct bmp085_platform_data *pdata = client->dev.platform_data;
+	struct bmp085_data *data = dev_get_drvdata(dev);
+	struct bmp085_platform_data *pdata = dev->platform_data;
 
-	sysfs_remove_group(&client->dev.kobj, &bmp085_attr_group);
+	sysfs_remove_group(&dev->kobj, &bmp085_attr_group);
 
 	if (pdata && pdata->deinit_hw)
-		pdata->deinit_hw(&client->dev);
+		pdata->deinit_hw(dev);
 
 	kfree(data);
 
 	return 0;
 }
+EXPORT_SYMBOL(bmp085_remove);
 
 #ifdef CONFIG_PM
-static int bmp085_suspend(struct device *dev)
+int bmp085_disable(struct device *dev)
 {
 	struct bmp085_platform_data *pdata = dev->platform_data;
 
@@ -482,8 +495,9 @@ static int bmp085_suspend(struct device *dev)
 
 	return 0;
 }
+EXPORT_SYMBOL(bmp085_disable);
 
-static int bmp085_resume(struct device *dev)
+int bmp085_enable(struct device *dev)
 {
 	struct bmp085_platform_data *pdata = dev->platform_data;
 
@@ -492,44 +506,9 @@ static int bmp085_resume(struct device *dev)
 
 	return 0;
 }
+EXPORT_SYMBOL(bmp085_enable);
 #endif
 
-static SIMPLE_DEV_PM_OPS(bmp085_pm_ops, bmp085_suspend,
-			 bmp085_resume);
-
-static const struct i2c_device_id bmp085_id[] = {
-	{ "bmp085", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, bmp085_id);
-
-static struct i2c_driver bmp085_driver = {
-	.driver = {
-		.owner = THIS_MODULE,
-		.name	= "bmp085",
-		.pm	= &bmp085_pm_ops,
-	},
-	.id_table	= bmp085_id,
-	.probe		= bmp085_probe,
-	.remove		= __devexit_p(bmp085_remove),
-
-	.detect		= bmp085_detect,
-	.address_list	= normal_i2c
-};
-
-static int __init bmp085_init(void)
-{
-	return i2c_add_driver(&bmp085_driver);
-}
-
-static void __exit bmp085_exit(void)
-{
-	i2c_del_driver(&bmp085_driver);
-}
-
 MODULE_AUTHOR("Christoph Mair <christoph.mair@gmail.com");
 MODULE_DESCRIPTION("BMP085 driver");
 MODULE_LICENSE("GPL");
-
-module_init(bmp085_init);
-module_exit(bmp085_exit);
diff --git a/include/linux/i2c/bmp085.h b/include/linux/i2c/bmp085.h
index e6fc752..ee6e398 100644
--- a/include/linux/i2c/bmp085.h
+++ b/include/linux/i2c/bmp085.h
@@ -20,7 +20,8 @@
 #ifndef _BMP085_H
 #define _BMP085_H
 
-#define BMP085_NAME "bmp085"
+#define BMP085_NAME		"bmp085"
+#define BMP085_I2C_ADDRESS	0x77
 
 /**
  * struct bmp085_platform_data - represents platform data for the bmp085 driver
@@ -40,4 +41,23 @@ struct bmp085_platform_data {
 	void	(*deinit_hw)(struct device *dev);
 };
 
+struct bmp085_bus_ops {
+	int	(*read_block)(void *client, u8 reg, int len, char *buf);
+	int	(*read_byte)(void *client, u8 reg);
+	int	(*write_byte)(void *client, u8 reg, u8 value);
+};
+
+struct bmp085_data_bus {
+	const struct bmp085_bus_ops	*bops;
+	void	*client;
+};
+
+int bmp085_probe(struct device *dev, struct bmp085_data_bus *data_bus);
+int bmp085_remove(struct device *dev);
+int bmp085_detect(struct device *dev);
+#ifdef CONFIG_PM
+int bmp085_enable(struct device *dev);
+int bmp085_disable(struct device *dev);
+#endif
+
 #endif
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCHv2 3/3] misc: rename bmp085 to bmp18x
  2012-03-06 21:08 [PATCHv2 0/3] Add support for bmp18x to bmp085 Eric Andersson
  2012-03-06 21:08 ` [PATCHv2 1/3] misc: clean up bmp085 driver Eric Andersson
  2012-03-06 21:08 ` [PATCHv2 2/3] misc: add support for bmp18x chips to the " Eric Andersson
@ 2012-03-06 21:08 ` Eric Andersson
  2012-03-06 21:14   ` Arnd Bergmann
  2012-03-06 21:37   ` Alan Cox
  2 siblings, 2 replies; 12+ messages in thread
From: Eric Andersson @ 2012-03-06 21:08 UTC (permalink / raw)
  To: linux-kernel
  Cc: gregkh, alan, arnd, zhengguang.guo, peter.moeller, Eric Andersson

The bmp085 chip has been deprecated by the newer bmp18x chip family from
Bosch Sensortec.

Reviewed-by: Stefan Nilsson <stefan.nilsson@unixphere.com>
Signed-off-by: Eric Andersson <eric.andersson@unixphere.com>
---
 drivers/misc/Kconfig       |   18 +-
 drivers/misc/Makefile      |    6 +-
 drivers/misc/bmp085.c      |  514 --------------------------------------------
 drivers/misc/bmp18x-i2c.c  |  132 +++++++++++
 drivers/misc/bmp18x-spi.c  |  140 ++++++++++++
 drivers/misc/bmp18x.c      |  512 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/i2c/bmp085.h |   63 ------
 include/linux/i2c/bmp18x.h |   63 ++++++
 8 files changed, 859 insertions(+), 589 deletions(-)
 delete mode 100644 drivers/misc/bmp085.c
 create mode 100644 drivers/misc/bmp18x-i2c.c
 create mode 100644 drivers/misc/bmp18x-spi.c
 create mode 100644 drivers/misc/bmp18x.c
 delete mode 100644 include/linux/i2c/bmp085.h
 create mode 100644 include/linux/i2c/bmp18x.h

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 9bf65c3..00a8701 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -451,35 +451,35 @@ config ARM_CHARLCD
 	  line and the Linux version on the second line, but that's
 	  still useful.
 
-config BMP085
-	tristate "BMP085 digital pressure sensor"
+config BMP18X
+	tristate "BMP18X digital pressure sensor"
 	depends on (I2C || SPI_MASTER) && SYSFS
 	help
 	  Say Y here if you want support for Bosch Sensortec's digital
 	  pressure sensors BMP085 and BMP18x.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called bmp085.
+	  module will be called bmp18x.
 
-config BMP085_I2C
+config BMP18X_I2C
 	tristate "support I2C bus connection"
-	depends on BMP085 && I2C
+	depends on BMP18X && I2C
 	help
 	  Say Y here if you want to support Bosch Sensortec's digital pressure
 	  sensor hooked to an I2C bus.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called bmp085-i2c.
+	  module will be called bmp18x-i2c.
 
-config BMP085_SPI
+config BMP18X_SPI
 	tristate "support SPI bus connection"
-	depends on BMP085 && SPI_MASTER
+	depends on BMP18X && SPI_MASTER
 	help
 	  Say Y here if you want to support Bosch Sensortec's digital pressure
 	  sensor hooked to an SPI bus.
 
 	  To compile this driver as a module, choose M here: the
-	  module will be called bmp085-spi.
+	  module will be called bmp18x-spi.
 
 config PCH_PHUB
 	tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) PHUB"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 509d056..1cfa82c 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -10,9 +10,9 @@ obj-$(CONFIG_INTEL_MID_PTI)	+= pti.o
 obj-$(CONFIG_ATMEL_PWM)		+= atmel_pwm.o
 obj-$(CONFIG_ATMEL_SSC)		+= atmel-ssc.o
 obj-$(CONFIG_ATMEL_TCLIB)	+= atmel_tclib.o
-obj-$(CONFIG_BMP085)		+= bmp085.o
-obj-$(CONFIG_BMP085_I2C)	+= bmp085-i2c.o
-obj-$(CONFIG_BMP085_SPI)	+= bmp085-spi.o
+obj-$(CONFIG_BMP18X)		+= bmp18x.o
+obj-$(CONFIG_BMP18X_I2C)	+= bmp18x-i2c.o
+obj-$(CONFIG_BMP18X_SPI)	+= bmp18x-spi.o
 obj-$(CONFIG_ICS932S401)	+= ics932s401.o
 obj-$(CONFIG_LKDTM)		+= lkdtm.o
 obj-$(CONFIG_TIFM_CORE)       	+= tifm_core.o
diff --git a/drivers/misc/bmp085.c b/drivers/misc/bmp085.c
deleted file mode 100644
index 78406d7..0000000
--- a/drivers/misc/bmp085.c
+++ /dev/null
@@ -1,514 +0,0 @@
-/*  Copyright (c) 2010  Christoph Mair <christoph.mair@gmail.com>
-    Copyright (c) 2012  Bosch Sensortec GmbH
-    Copyright (c) 2012  Unixphere AB
-
-    This driver supports the bmp085 digital barometric pressure
-    and temperature sensor from Bosch Sensortec. The datasheets
-    are available from their website:
-    http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP085-DS000-05.pdf
-    http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP180-DS000-07.pdf
-
-    A pressure measurement is issued by reading from pressure0_input.
-    The return value ranges from 30000 to 110000 pascal with a resulution
-    of 1 pascal (0.01 millibar) which enables measurements from 9000m above
-    to 500m below sea level.
-
-    The temperature can be read from temp0_input. Values range from
-    -400 to 850 representing the ambient temperature in degree celsius
-    multiplied by 10.The resolution is 0.1 celsius.
-
-    Because ambient pressure is temperature dependent, a temperature
-    measurement will be executed automatically even if the user is reading
-    from pressure0_input. This happens if the last temperature measurement
-    has been executed more then one second ago.
-
-    To decrease RMS noise from pressure measurements, the bmp085 can
-    autonomously calculate the average of up to eight samples. This is
-    set up by writing to the oversampling sysfs file. Accepted values
-    are 0, 1, 2 and 3. 2^x when x is the value written to this file
-    specifies the number of samples used to calculate the ambient pressure.
-    RMS noise is specified with six pascal (without averaging) and decreases
-    down to 3 pascal when using an oversampling setting of 3.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/i2c/bmp085.h>
-
-#define BMP085_CHIP_ID			0x55
-
-#define BMP085_CALIBRATION_DATA_START	0xAA
-#define BMP085_CALIBRATION_DATA_LENGTH	11	/* 16 bit values */
-#define BMP085_CHIP_ID_REG		0xD0
-#define BMP085_CTRL_REG			0xF4
-#define BMP085_TEMP_MEASUREMENT		0x2E
-#define BMP085_PRESSURE_MEASUREMENT	0x34
-#define BMP085_CONVERSION_REGISTER_MSB	0xF6
-#define BMP085_CONVERSION_REGISTER_LSB	0xF7
-#define BMP085_CONVERSION_REGISTER_XLSB	0xF8
-#define BMP085_TEMP_CONVERSION_TIME	5
-
-struct bmp085_calibration_data {
-	s16 AC1, AC2, AC3;
-	u16 AC4, AC5, AC6;
-	s16 B1, B2;
-	s16 MB, MC, MD;
-};
-
-struct bmp085_data {
-	struct	bmp085_data_bus data_bus;
-	struct	device *dev;
-	struct	mutex lock;
-	struct	bmp085_calibration_data calibration;
-	u8	oversampling_setting;
-	u32	raw_temperature;
-	u32	raw_pressure;
-	u32	temp_measurement_period;
-	u32	last_temp_measurement;
-	s32	b6; /* calculated temperature correction coefficient */
-};
-
-static inline int bmp085_read_block(struct bmp085_data *data, u8 reg, int len,
-				    char *buf)
-{
-	return data->data_bus.bops->read_block(data->data_bus.client, reg,
-					       len, buf);
-}
-
-static inline int bmp085_read_byte(struct bmp085_data *data, u8 reg)
-{
-	return data->data_bus.bops->read_byte(data->data_bus.client, reg);
-}
-
-static inline int bmp085_write_byte(struct bmp085_data *data, u8 reg, u8 value)
-{
-	return data->data_bus.bops->write_byte(data->data_bus.client, reg,
-					       value);
-}
-
-static s32 bmp085_read_calibration_data(struct bmp085_data *data)
-{
-	u16 tmp[BMP085_CALIBRATION_DATA_LENGTH];
-	struct bmp085_calibration_data *cali = &(data->calibration);
-	s32 status = bmp085_read_block(data, BMP085_CALIBRATION_DATA_START,
-				(BMP085_CALIBRATION_DATA_LENGTH << 1),
-				(u8 *)tmp);
-	if (status < 0)
-		return status;
-
-	if (status != (BMP085_CALIBRATION_DATA_LENGTH << 1))
-		return -EIO;
-
-	cali->AC1 =  be16_to_cpu(tmp[0]);
-	cali->AC2 =  be16_to_cpu(tmp[1]);
-	cali->AC3 =  be16_to_cpu(tmp[2]);
-	cali->AC4 =  be16_to_cpu(tmp[3]);
-	cali->AC5 =  be16_to_cpu(tmp[4]);
-	cali->AC6 = be16_to_cpu(tmp[5]);
-	cali->B1 = be16_to_cpu(tmp[6]);
-	cali->B2 = be16_to_cpu(tmp[7]);
-	cali->MB = be16_to_cpu(tmp[8]);
-	cali->MC = be16_to_cpu(tmp[9]);
-	cali->MD = be16_to_cpu(tmp[10]);
-	return 0;
-}
-
-static s32 bmp085_update_raw_temperature(struct bmp085_data *data)
-{
-	u16 tmp;
-	s32 status;
-
-	mutex_lock(&data->lock);
-	status = bmp085_write_byte(data, BMP085_CTRL_REG,
-				   BMP085_TEMP_MEASUREMENT);
-	if (status < 0) {
-		dev_err(data->dev,
-			"Error while requesting temperature measurement.\n");
-		goto exit;
-	}
-	msleep(BMP085_TEMP_CONVERSION_TIME);
-
-	status = bmp085_read_block(data, BMP085_CONVERSION_REGISTER_MSB,
-				   sizeof(tmp), (u8 *)&tmp);
-	if (status < 0)
-		goto exit;
-	if (status != sizeof(tmp)) {
-		dev_err(data->dev,
-			"Error while reading temperature measurement result\n");
-		status = -EIO;
-		goto exit;
-	}
-	data->raw_temperature = be16_to_cpu(tmp);
-	data->last_temp_measurement = jiffies;
-	status = 0;	/* everything ok, return 0 */
-
-exit:
-	mutex_unlock(&data->lock);
-	return status;
-}
-
-static s32 bmp085_update_raw_pressure(struct bmp085_data *data)
-{
-	u32 tmp = 0;
-	s32 status;
-
-	mutex_lock(&data->lock);
-	status = bmp085_write_byte(data, BMP085_CTRL_REG,
-			BMP085_PRESSURE_MEASUREMENT +
-			(data->oversampling_setting << 6));
-	if (status < 0) {
-		dev_err(data->dev,
-			"Error while requesting pressure measurement.\n");
-		goto exit;
-	}
-
-	/* wait for the end of conversion */
-	msleep(2+(3 << data->oversampling_setting));
-
-	/* copy data into a u32 (4 bytes), but skip the first byte. */
-	status = bmp085_read_block(data, BMP085_CONVERSION_REGISTER_MSB, 3,
-				   ((u8 *)&tmp)+1);
-	if (status < 0)
-		goto exit;
-	if (status != 3) {
-		dev_err(data->dev,
-			"Error while reading pressure measurement results\n");
-		status = -EIO;
-		goto exit;
-	}
-	data->raw_pressure = be32_to_cpu((tmp));
-	data->raw_pressure >>= (8-data->oversampling_setting);
-	status = 0;	/* everything ok, return 0 */
-
-exit:
-	mutex_unlock(&data->lock);
-	return status;
-}
-
-/*
- * This function starts the temperature measurement and returns the value
- * in tenth of a degree celsius.
- */
-static s32 bmp085_get_temperature(struct bmp085_data *data, int *temperature)
-{
-	struct bmp085_calibration_data *cali = &data->calibration;
-	long x1, x2;
-	int status;
-
-	status = bmp085_update_raw_temperature(data);
-	if (status < 0)
-		goto exit;
-
-	x1 = ((data->raw_temperature - cali->AC6) * cali->AC5) >> 15;
-	x2 = (cali->MC << 11) / (x1 + cali->MD);
-	data->b6 = x1 + x2 - 4000;
-	/* if NULL just update b6. Used for pressure only measurements */
-	if (temperature != NULL)
-		*temperature = (x1+x2+8) >> 4;
-
-exit:
-	return status;
-}
-
-/*
- * This function starts the pressure measurement and returns the value
- * in millibar. Since the pressure depends on the ambient temperature,
- * a temperature measurement is executed according to the given temperature
- * measurememt period (default is 1 sec boundary). This period could vary
- * and needs to be adjusted according to the sensor environment, i.e. if big
- * temperature variations then the temperature needs to be read out often.
- */
-static s32 bmp085_get_pressure(struct bmp085_data *data, int *pressure)
-{
-	struct bmp085_calibration_data *cali = &data->calibration;
-	s32 x1, x2, x3, b3;
-	u32 b4, b7;
-	s32 p;
-	int status;
-
-	/* update the ambient temperature according to the given meas. period */
-	if (data->last_temp_measurement +
-			data->temp_measurement_period < jiffies) {
-		status = bmp085_get_temperature(data, NULL);
-		if (status < 0)
-			return status;
-	}
-
-	status = bmp085_update_raw_pressure(data);
-	if (status < 0)
-		return status;
-
-	x1 = (data->b6 * data->b6) >> 12;
-	x1 *= cali->B2;
-	x1 >>= 11;
-
-	x2 = cali->AC2 * data->b6;
-	x2 >>= 11;
-
-	x3 = x1 + x2;
-
-	b3 = (((((s32)cali->AC1) * 4 + x3) << data->oversampling_setting) + 2);
-	b3 >>= 2;
-
-	x1 = (cali->AC3 * data->b6) >> 13;
-	x2 = (cali->B1 * ((data->b6 * data->b6) >> 12)) >> 16;
-	x3 = (x1 + x2 + 2) >> 2;
-	b4 = (cali->AC4 * (u32)(x3 + 32768)) >> 15;
-
-	b7 = ((u32)data->raw_pressure - b3) *
-					(50000 >> data->oversampling_setting);
-	p = ((b7 < 0x80000000) ? ((b7 << 1) / b4) : ((b7 / b4) * 2));
-
-	x1 = p >> 8;
-	x1 *= x1;
-	x1 = (x1 * 3038) >> 16;
-	x2 = (-7357 * p) >> 16;
-	p += (x1 + x2 + 3791) >> 4;
-
-	*pressure = p;
-
-	return 0;
-}
-
-/*
- * This function sets the chip-internal oversampling. Valid values are 0..3.
- * The chip will use 2^oversampling samples for internal averaging.
- * This influences the measurement time and the accuracy; larger values
- * increase both. The datasheet gives an overview on how measurement time,
- * accuracy and noise correlate.
- */
-static void bmp085_set_oversampling(struct bmp085_data *data,
-						unsigned char oversampling)
-{
-	if (oversampling > 3)
-		oversampling = 3;
-	data->oversampling_setting = oversampling;
-}
-
-/*
- * Returns the currently selected oversampling. Range: 0..3
- */
-static unsigned char bmp085_get_oversampling(struct bmp085_data *data)
-{
-	return data->oversampling_setting;
-}
-
-/* sysfs callbacks */
-static ssize_t set_oversampling(struct device *dev,
-				struct device_attribute *attr,
-				const char *buf, size_t count)
-{
-	struct bmp085_data *data = dev_get_drvdata(dev);
-	unsigned long oversampling;
-	int err = kstrtoul(buf, 10, &oversampling);
-
-	if (err == 0) {
-		mutex_lock(&data->lock);
-		bmp085_set_oversampling(data, oversampling);
-		mutex_unlock(&data->lock);
-		return count;
-	}
-
-	return err;
-}
-
-static ssize_t show_oversampling(struct device *dev,
-				 struct device_attribute *attr, char *buf)
-{
-	struct bmp085_data *data = dev_get_drvdata(dev);
-
-	return sprintf(buf, "%u\n", bmp085_get_oversampling(data));
-}
-static DEVICE_ATTR(oversampling, S_IWUSR | S_IRUGO,
-					show_oversampling, set_oversampling);
-
-
-static ssize_t show_temperature(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	int temperature;
-	int status;
-	struct bmp085_data *data = dev_get_drvdata(dev);
-
-	status = bmp085_get_temperature(data, &temperature);
-	if (status < 0)
-		return status;
-	else
-		return sprintf(buf, "%d\n", temperature);
-}
-static DEVICE_ATTR(temp0_input, S_IRUGO, show_temperature, NULL);
-
-
-static ssize_t show_pressure(struct device *dev,
-			     struct device_attribute *attr, char *buf)
-{
-	int pressure;
-	int status;
-	struct bmp085_data *data = dev_get_drvdata(dev);
-
-	status = bmp085_get_pressure(data, &pressure);
-	if (status < 0)
-		return status;
-	else
-		return sprintf(buf, "%d\n", pressure);
-}
-static DEVICE_ATTR(pressure0_input, S_IRUGO, show_pressure, NULL);
-
-
-static struct attribute *bmp085_attributes[] = {
-	&dev_attr_temp0_input.attr,
-	&dev_attr_pressure0_input.attr,
-	&dev_attr_oversampling.attr,
-	NULL
-};
-
-static const struct attribute_group bmp085_attr_group = {
-	.attrs = bmp085_attributes,
-};
-
-int bmp085_detect(struct device *dev)
-{
-	struct bmp085_data *data = dev_get_drvdata(dev);
-	struct bmp085_platform_data *pdata = dev->platform_data;
-	u8 chip_id = (pdata && pdata->chip_id) ? pdata->chip_id :
-						 BMP085_CHIP_ID;
-
-	if (bmp085_read_byte(data, BMP085_CHIP_ID_REG) != chip_id)
-		return -ENODEV;
-
-	return 0;
-}
-EXPORT_SYMBOL(bmp085_detect);
-
-static int bmp085_init_client(struct bmp085_data *data,
-			      struct bmp085_platform_data *pdata)
-{
-	int status = bmp085_read_calibration_data(data);
-
-	if (status < 0)
-		return status;
-
-	data->last_temp_measurement = 0;
-	data->temp_measurement_period =
-		pdata ? (pdata->temp_measurement_period/1000)*HZ : 1*HZ;
-	data->oversampling_setting = pdata ? pdata->default_oversampling : 3;
-	mutex_init(&data->lock);
-
-	return 0;
-}
-
-__devinit int bmp085_probe(struct device *dev, struct bmp085_data_bus *data_bus)
-{
-	struct bmp085_data *data;
-	struct bmp085_platform_data *pdata = dev->platform_data;
-	u8 chip_id = (pdata && pdata->chip_id) ? pdata->chip_id :
-						 BMP085_CHIP_ID;
-	int err = 0;
-
-	if (pdata && pdata->init_hw) {
-		err = pdata->init_hw(dev);
-		if (err) {
-			dev_err(dev, "%s: init_hw failed!\n",
-				BMP085_NAME);
-			return err;
-		}
-	}
-
-	data = kzalloc(sizeof(struct bmp085_data), GFP_KERNEL);
-	if (!data) {
-		err = -ENOMEM;
-		goto exit;
-	}
-
-	dev_set_drvdata(dev, data);
-	data->data_bus = *data_bus;
-	data->dev = dev;
-
-	if (bmp085_read_byte(data, BMP085_CHIP_ID_REG) != chip_id) {
-		dev_err(dev, "%s: chip_id failed!\n", BMP085_NAME);
-		err = -ENODEV;
-		goto exit_free;
-	}
-
-	/* Initialize the BMP085 chip */
-	err = bmp085_init_client(data, pdata);
-	if (err < 0)
-		goto exit_free;
-
-	/* Register sysfs hooks */
-	err = sysfs_create_group(&dev->kobj, &bmp085_attr_group);
-	if (err)
-		goto exit_free;
-
-	dev_info(dev, "Succesfully initialized bmp085!\n");
-	return 0;
-
-exit_free:
-	kfree(data);
-exit:
-	if (pdata && pdata->deinit_hw)
-		pdata->deinit_hw(dev);
-	return err;
-}
-EXPORT_SYMBOL(bmp085_probe);
-
-int bmp085_remove(struct device *dev)
-{
-	struct bmp085_data *data = dev_get_drvdata(dev);
-	struct bmp085_platform_data *pdata = dev->platform_data;
-
-	sysfs_remove_group(&dev->kobj, &bmp085_attr_group);
-
-	if (pdata && pdata->deinit_hw)
-		pdata->deinit_hw(dev);
-
-	kfree(data);
-
-	return 0;
-}
-EXPORT_SYMBOL(bmp085_remove);
-
-#ifdef CONFIG_PM
-int bmp085_disable(struct device *dev)
-{
-	struct bmp085_platform_data *pdata = dev->platform_data;
-
-	if (pdata && pdata->deinit_hw)
-		pdata->deinit_hw(dev);
-
-	return 0;
-}
-EXPORT_SYMBOL(bmp085_disable);
-
-int bmp085_enable(struct device *dev)
-{
-	struct bmp085_platform_data *pdata = dev->platform_data;
-
-	if (pdata && pdata->init_hw)
-		return pdata->init_hw(dev);
-
-	return 0;
-}
-EXPORT_SYMBOL(bmp085_enable);
-#endif
-
-MODULE_AUTHOR("Christoph Mair <christoph.mair@gmail.com");
-MODULE_DESCRIPTION("BMP085 driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/misc/bmp18x-i2c.c b/drivers/misc/bmp18x-i2c.c
new file mode 100644
index 0000000..5d35cce
--- /dev/null
+++ b/drivers/misc/bmp18x-i2c.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2012  Bosch Sensortec GmbH
+ * Copyright (c) 2012  Unixphere AB
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c/bmp18x.h>
+
+static const unsigned short normal_i2c[] = { BMP18X_I2C_ADDRESS,
+							I2C_CLIENT_END };
+
+static int bmp18x_i2c_read_block(void *client, u8 reg, int len, char *buf)
+{
+	return i2c_smbus_read_i2c_block_data(client, reg, len, buf);
+}
+
+static int bmp18x_i2c_read_byte(void *client, u8 reg)
+{
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int bmp18x_i2c_write_byte(void *client, u8 reg, u8 value)
+{
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+static const struct bmp18x_bus_ops bmp18x_i2c_bus_ops = {
+	.read_block	= bmp18x_i2c_read_block,
+	.read_byte	= bmp18x_i2c_read_byte,
+	.write_byte	= bmp18x_i2c_write_byte
+};
+
+static int bmp18x_i2c_detect(struct i2c_client *client,
+			     struct i2c_board_info *info)
+{
+	if (client->addr != BMP18X_I2C_ADDRESS)
+		return -ENODEV;
+
+	return bmp18x_detect(&client->dev);
+}
+
+static int __devinit bmp18x_i2c_probe(struct i2c_client *client,
+				      const struct i2c_device_id *id)
+{
+	struct bmp18x_data_bus data_bus = {
+		.bops = &bmp18x_i2c_bus_ops,
+		.client = client
+	};
+
+	return bmp18x_probe(&client->dev, &data_bus);
+}
+
+static void bmp18x_i2c_shutdown(struct i2c_client *client)
+{
+	bmp18x_disable(&client->dev);
+}
+
+static int bmp18x_i2c_remove(struct i2c_client *client)
+{
+	return bmp18x_remove(&client->dev);
+}
+
+#ifdef CONFIG_PM
+static int bmp18x_i2c_suspend(struct device *dev)
+{
+	return bmp18x_disable(dev);
+}
+
+static int bmp18x_i2c_resume(struct device *dev)
+{
+	return bmp18x_enable(dev);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(bmp18x_i2c_pm_ops, bmp18x_i2c_suspend,
+			 bmp18x_i2c_resume);
+
+static const struct i2c_device_id bmp18x_id[] = {
+	{ BMP18X_NAME, 0 },
+	{ "bmp085", 0 },
+	{ "bmp180", 0 },
+	{ "bmp181", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, bmp18x_id);
+
+static struct i2c_driver bmp18x_i2c_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= BMP18X_NAME,
+		.pm	= &bmp18x_i2c_pm_ops,
+	},
+	.id_table	= bmp18x_id,
+	.probe		= bmp18x_i2c_probe,
+	.shutdown	= bmp18x_i2c_shutdown,
+	.remove		= __devexit_p(bmp18x_i2c_remove),
+
+	.detect		= bmp18x_i2c_detect,
+	.address_list	= normal_i2c
+};
+
+static int __init bmp18x_i2c_init(void)
+{
+	return i2c_add_driver(&bmp18x_i2c_driver);
+}
+
+static void __exit bmp18x_i2c_exit(void)
+{
+	i2c_del_driver(&bmp18x_i2c_driver);
+}
+
+MODULE_AUTHOR("Eric Andersson <eric.andersson@unixphere.com>");
+MODULE_DESCRIPTION("BMP18X I2C bus driver");
+MODULE_LICENSE("GPL");
+
+module_init(bmp18x_i2c_init);
+module_exit(bmp18x_i2c_exit);
diff --git a/drivers/misc/bmp18x-spi.c b/drivers/misc/bmp18x-spi.c
new file mode 100644
index 0000000..b263a60
--- /dev/null
+++ b/drivers/misc/bmp18x-spi.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2012  Bosch Sensortec GmbH
+ * Copyright (c) 2012  Unixphere AB
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c/bmp18x.h>
+
+static int bmp18x_spi_write_byte(void *client, u8 reg, u8 value)
+{
+	u8 data[2] = { reg, value };
+	return spi_write(client, data, 2);
+}
+
+static int bmp18x_spi_read_block(void *client, u8 reg, int len, char *buf)
+{
+	int err = bmp18x_spi_write_byte(client, reg, 0);
+
+	if (err < 0)
+		return err;
+
+	return spi_read(client, buf, len);
+}
+
+static int bmp18x_spi_read_byte(void *client, u8 reg)
+{
+	u8 data;
+	int err = bmp18x_spi_write_byte(client, reg, 0);
+
+	if (err < 0)
+		return err;
+
+	err = spi_read(client, &data, 1);
+	if (err < 0)
+		return err;
+
+	return data;
+}
+
+static const struct bmp18x_bus_ops bmp18x_spi_bus_ops = {
+	.read_block	= bmp18x_spi_read_block,
+	.read_byte	= bmp18x_spi_read_byte,
+	.write_byte	= bmp18x_spi_write_byte
+};
+
+static int __devinit bmp18x_spi_probe(struct spi_device *client)
+{
+	int err;
+	struct bmp18x_data_bus data_bus = {
+		.bops = &bmp18x_spi_bus_ops,
+		.client = client
+	};
+
+	client->bits_per_word = 8;
+	err = spi_setup(client);
+	if (err < 0) {
+		dev_err(&client->dev, "spi_setup failed!\n");
+		return err;
+	}
+
+	return bmp18x_probe(&client->dev, &data_bus);
+}
+
+static void bmp18x_spi_shutdown(struct spi_device *client)
+{
+	bmp18x_disable(&client->dev);
+}
+
+static int bmp18x_spi_remove(struct spi_device *client)
+{
+	return bmp18x_remove(&client->dev);
+}
+
+#ifdef CONFIG_PM
+static int bmp18x_spi_suspend(struct device *dev)
+{
+	return bmp18x_disable(dev);
+}
+
+static int bmp18x_spi_resume(struct device *dev)
+{
+	return bmp18x_enable(dev);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(bmp18x_spi_pm_ops, bmp18x_spi_suspend,
+					    bmp18x_spi_resume);
+
+static const struct spi_device_id bmp18x_id[] = {
+	{ BMP18X_NAME, 0 },
+	{ "bmp085", 0 },
+	{ "bmp180", 0 },
+	{ "bmp181", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, bmp18x_id);
+
+static struct spi_driver bmp18x_spi_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= BMP18X_NAME,
+		.pm	= &bmp18x_spi_pm_ops,
+	},
+	.id_table	= bmp18x_id,
+	.probe		= bmp18x_spi_probe,
+	.shutdown	= bmp18x_spi_shutdown,
+	.remove		= __devexit_p(bmp18x_spi_remove)
+};
+
+static int __init bmp18x_spi_init(void)
+{
+	return spi_register_driver(&bmp18x_spi_driver);
+}
+
+static void __exit bmp18x_spi_exit(void)
+{
+	spi_unregister_driver(&bmp18x_spi_driver);
+}
+
+MODULE_AUTHOR("Eric Andersson <eric.andersson@unixphere.com>");
+MODULE_DESCRIPTION("BMP18X SPI bus driver");
+MODULE_LICENSE("GPL");
+
+module_init(bmp18x_spi_init);
+module_exit(bmp18x_spi_exit);
diff --git a/drivers/misc/bmp18x.c b/drivers/misc/bmp18x.c
new file mode 100644
index 0000000..d8205f1
--- /dev/null
+++ b/drivers/misc/bmp18x.c
@@ -0,0 +1,512 @@
+/*  Copyright (c) 2010  Christoph Mair <christoph.mair@gmail.com>
+    Copyright (c) 2012  Bosch Sensortec GmbH
+    Copyright (c) 2012  Unixphere AB
+
+    This driver supports the bmp18x digital barometric pressure
+    and temperature sensor from Bosch Sensortec. The datasheets
+    are available from their website:
+    http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP085-DS000-05.pdf
+    http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP180-DS000-07.pdf
+
+    A pressure measurement is issued by reading from pressure0_input.
+    The return value ranges from 30000 to 110000 pascal with a resulution
+    of 1 pascal (0.01 millibar) which enables measurements from 9000m above
+    to 500m below sea level.
+
+    The temperature can be read from temp0_input. Values range from
+    -400 to 850 representing the ambient temperature in degree celsius
+    multiplied by 10.The resolution is 0.1 celsius.
+
+    Because ambient pressure is temperature dependent, a temperature
+    measurement will be executed automatically even if the user is reading
+    from pressure0_input. This happens if the last temperature measurement
+    has been executed more then one second ago.
+
+    To decrease RMS noise from pressure measurements, the bmp18x can
+    autonomously calculate the average of up to eight samples. This is
+    set up by writing to the oversampling sysfs file. Accepted values
+    are 0, 1, 2 and 3. 2^x when x is the value written to this file
+    specifies the number of samples used to calculate the ambient pressure.
+    RMS noise is specified with six pascal (without averaging) and decreases
+    down to 3 pascal when using an oversampling setting of 3.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c/bmp18x.h>
+
+#define BMP18X_CHIP_ID			0x55
+
+#define BMP18X_CALIBRATION_DATA_START	0xAA
+#define BMP18X_CALIBRATION_DATA_LENGTH	11	/* 16 bit values */
+#define BMP18X_CHIP_ID_REG		0xD0
+#define BMP18X_CTRL_REG			0xF4
+#define BMP18X_TEMP_MEASUREMENT		0x2E
+#define BMP18X_PRESSURE_MEASUREMENT	0x34
+#define BMP18X_CONVERSION_REGISTER_MSB	0xF6
+#define BMP18X_CONVERSION_REGISTER_LSB	0xF7
+#define BMP18X_CONVERSION_REGISTER_XLSB	0xF8
+#define BMP18X_TEMP_CONVERSION_TIME	5
+
+struct bmp18x_calibration_data {
+	s16 AC1, AC2, AC3;
+	u16 AC4, AC5, AC6;
+	s16 B1, B2;
+	s16 MB, MC, MD;
+};
+
+struct bmp18x_data {
+	struct	bmp18x_data_bus data_bus;
+	struct	device *dev;
+	struct	mutex lock;
+	struct	bmp18x_calibration_data calibration;
+	u8	oversampling_setting;
+	u32	raw_temperature;
+	u32	raw_pressure;
+	u32	temp_measurement_period;
+	u32	last_temp_measurement;
+	s32	b6; /* calculated temperature correction coefficient */
+};
+
+static inline int bmp18x_read_block(struct bmp18x_data *data, u8 reg, int len,
+				    char *buf)
+{
+	return data->data_bus.bops->read_block(data->data_bus.client, reg,
+					       len, buf);
+}
+
+static inline int bmp18x_read_byte(struct bmp18x_data *data, u8 reg)
+{
+	return data->data_bus.bops->read_byte(data->data_bus.client, reg);
+}
+
+static inline int bmp18x_write_byte(struct bmp18x_data *data, u8 reg, u8 value)
+{
+	return data->data_bus.bops->write_byte(data->data_bus.client, reg,
+					       value);
+}
+
+static s32 bmp18x_read_calibration_data(struct bmp18x_data *data)
+{
+	u16 tmp[BMP18X_CALIBRATION_DATA_LENGTH];
+	struct bmp18x_calibration_data *cali = &(data->calibration);
+	s32 status = bmp18x_read_block(data, BMP18X_CALIBRATION_DATA_START,
+				(BMP18X_CALIBRATION_DATA_LENGTH << 1),
+				(u8 *)tmp);
+	if (status < 0)
+		return status;
+
+	if (status != (BMP18X_CALIBRATION_DATA_LENGTH << 1))
+		return -EIO;
+
+	cali->AC1 =  be16_to_cpu(tmp[0]);
+	cali->AC2 =  be16_to_cpu(tmp[1]);
+	cali->AC3 =  be16_to_cpu(tmp[2]);
+	cali->AC4 =  be16_to_cpu(tmp[3]);
+	cali->AC5 =  be16_to_cpu(tmp[4]);
+	cali->AC6 = be16_to_cpu(tmp[5]);
+	cali->B1 = be16_to_cpu(tmp[6]);
+	cali->B2 = be16_to_cpu(tmp[7]);
+	cali->MB = be16_to_cpu(tmp[8]);
+	cali->MC = be16_to_cpu(tmp[9]);
+	cali->MD = be16_to_cpu(tmp[10]);
+	return 0;
+}
+
+static s32 bmp18x_update_raw_temperature(struct bmp18x_data *data)
+{
+	u16 tmp;
+	s32 status;
+
+	mutex_lock(&data->lock);
+	status = bmp18x_write_byte(data, BMP18X_CTRL_REG,
+				   BMP18X_TEMP_MEASUREMENT);
+	if (status < 0) {
+		dev_err(data->dev,
+			"Error while requesting temperature measurement.\n");
+		goto exit;
+	}
+	msleep(BMP18X_TEMP_CONVERSION_TIME);
+
+	status = bmp18x_read_block(data, BMP18X_CONVERSION_REGISTER_MSB,
+				   sizeof(tmp), (u8 *)&tmp);
+	if (status < 0)
+		goto exit;
+	if (status != sizeof(tmp)) {
+		dev_err(data->dev,
+			"Error while reading temperature measurement result\n");
+		status = -EIO;
+		goto exit;
+	}
+	data->raw_temperature = be16_to_cpu(tmp);
+	data->last_temp_measurement = jiffies;
+	status = 0;	/* everything ok, return 0 */
+
+exit:
+	mutex_unlock(&data->lock);
+	return status;
+}
+
+static s32 bmp18x_update_raw_pressure(struct bmp18x_data *data)
+{
+	u32 tmp = 0;
+	s32 status;
+
+	mutex_lock(&data->lock);
+	status = bmp18x_write_byte(data, BMP18X_CTRL_REG,
+			BMP18X_PRESSURE_MEASUREMENT +
+			(data->oversampling_setting << 6));
+	if (status < 0) {
+		dev_err(data->dev,
+			"Error while requesting pressure measurement.\n");
+		goto exit;
+	}
+
+	/* wait for the end of conversion */
+	msleep(2+(3 << data->oversampling_setting));
+
+	/* copy data into a u32 (4 bytes), but skip the first byte. */
+	status = bmp18x_read_block(data, BMP18X_CONVERSION_REGISTER_MSB, 3,
+				   ((u8 *)&tmp)+1);
+	if (status < 0)
+		goto exit;
+	if (status != 3) {
+		dev_err(data->dev,
+			"Error while reading pressure measurement results\n");
+		status = -EIO;
+		goto exit;
+	}
+	data->raw_pressure = be32_to_cpu((tmp));
+	data->raw_pressure >>= (8-data->oversampling_setting);
+	status = 0;	/* everything ok, return 0 */
+
+exit:
+	mutex_unlock(&data->lock);
+	return status;
+}
+
+/*
+ * This function starts the temperature measurement and returns the value
+ * in tenth of a degree celsius.
+ */
+static s32 bmp18x_get_temperature(struct bmp18x_data *data, int *temperature)
+{
+	struct bmp18x_calibration_data *cali = &data->calibration;
+	long x1, x2;
+	int status;
+
+	status = bmp18x_update_raw_temperature(data);
+	if (status < 0)
+		goto exit;
+
+	x1 = ((data->raw_temperature - cali->AC6) * cali->AC5) >> 15;
+	x2 = (cali->MC << 11) / (x1 + cali->MD);
+	data->b6 = x1 + x2 - 4000;
+	/* if NULL just update b6. Used for pressure only measurements */
+	if (temperature != NULL)
+		*temperature = (x1+x2+8) >> 4;
+
+exit:
+	return status;
+}
+
+/*
+ * This function starts the pressure measurement and returns the value
+ * in millibar. Since the pressure depends on the ambient temperature,
+ * a temperature measurement is executed according to the given temperature
+ * measurememt period (default is 1 sec boundary). This period could vary
+ * and needs to be adjusted according to the sensor environment, i.e. if big
+ * temperature variations then the temperature needs to be read out often.
+ */
+static s32 bmp18x_get_pressure(struct bmp18x_data *data, int *pressure)
+{
+	struct bmp18x_calibration_data *cali = &data->calibration;
+	s32 x1, x2, x3, b3;
+	u32 b4, b7;
+	s32 p;
+	int status;
+
+	/* update the ambient temperature according to the given meas. period */
+	if (data->last_temp_measurement +
+			data->temp_measurement_period < jiffies) {
+		status = bmp18x_get_temperature(data, NULL);
+		if (status < 0)
+			return status;
+	}
+
+	status = bmp18x_update_raw_pressure(data);
+	if (status < 0)
+		return status;
+
+	x1 = (data->b6 * data->b6) >> 12;
+	x1 *= cali->B2;
+	x1 >>= 11;
+
+	x2 = cali->AC2 * data->b6;
+	x2 >>= 11;
+
+	x3 = x1 + x2;
+
+	b3 = (((((s32)cali->AC1) * 4 + x3) << data->oversampling_setting) + 2);
+	b3 >>= 2;
+
+	x1 = (cali->AC3 * data->b6) >> 13;
+	x2 = (cali->B1 * ((data->b6 * data->b6) >> 12)) >> 16;
+	x3 = (x1 + x2 + 2) >> 2;
+	b4 = (cali->AC4 * (u32)(x3 + 32768)) >> 15;
+
+	b7 = ((u32)data->raw_pressure - b3) *
+					(50000 >> data->oversampling_setting);
+	p = ((b7 < 0x80000000) ? ((b7 << 1) / b4) : ((b7 / b4) * 2));
+
+	x1 = p >> 8;
+	x1 *= x1;
+	x1 = (x1 * 3038) >> 16;
+	x2 = (-7357 * p) >> 16;
+	p += (x1 + x2 + 3791) >> 4;
+
+	*pressure = p;
+
+	return 0;
+}
+
+/*
+ * This function sets the chip-internal oversampling. Valid values are 0..3.
+ * The chip will use 2^oversampling samples for internal averaging.
+ * This influences the measurement time and the accuracy; larger values
+ * increase both. The datasheet gives an overview on how measurement time,
+ * accuracy and noise correlate.
+ */
+static void bmp18x_set_oversampling(struct bmp18x_data *data,
+						unsigned char oversampling)
+{
+	if (oversampling > 3)
+		oversampling = 3;
+	data->oversampling_setting = oversampling;
+}
+
+/*
+ * Returns the currently selected oversampling. Range: 0..3
+ */
+static unsigned char bmp18x_get_oversampling(struct bmp18x_data *data)
+{
+	return data->oversampling_setting;
+}
+
+/* sysfs callbacks */
+static ssize_t set_oversampling(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+	unsigned long oversampling;
+	int err = kstrtoul(buf, 10, &oversampling);
+
+	if (err == 0) {
+		mutex_lock(&data->lock);
+		bmp18x_set_oversampling(data, oversampling);
+		mutex_unlock(&data->lock);
+		return count;
+	}
+
+	return err;
+}
+
+static ssize_t show_oversampling(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%u\n", bmp18x_get_oversampling(data));
+}
+static DEVICE_ATTR(oversampling, S_IWUSR | S_IRUGO,
+					show_oversampling, set_oversampling);
+
+
+static ssize_t show_temperature(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int temperature;
+	int status;
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+
+	status = bmp18x_get_temperature(data, &temperature);
+	if (status < 0)
+		return status;
+	else
+		return sprintf(buf, "%d\n", temperature);
+}
+static DEVICE_ATTR(temp0_input, S_IRUGO, show_temperature, NULL);
+
+
+static ssize_t show_pressure(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	int pressure;
+	int status;
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+
+	status = bmp18x_get_pressure(data, &pressure);
+	if (status < 0)
+		return status;
+	else
+		return sprintf(buf, "%d\n", pressure);
+}
+static DEVICE_ATTR(pressure0_input, S_IRUGO, show_pressure, NULL);
+
+
+static struct attribute *bmp18x_attributes[] = {
+	&dev_attr_temp0_input.attr,
+	&dev_attr_pressure0_input.attr,
+	&dev_attr_oversampling.attr,
+	NULL
+};
+
+static const struct attribute_group bmp18x_attr_group = {
+	.attrs = bmp18x_attributes,
+};
+
+int bmp18x_detect(struct device *dev)
+{
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+	struct bmp18x_platform_data *pdata = dev->platform_data;
+	u8 chip_id = (pdata && pdata->chip_id) ? pdata->chip_id :
+						 BMP18X_CHIP_ID;
+
+	if (bmp18x_read_byte(data, BMP18X_CHIP_ID_REG) != chip_id)
+		return -ENODEV;
+
+	return 0;
+}
+EXPORT_SYMBOL(bmp18x_detect);
+
+static int bmp18x_init_client(struct bmp18x_data *data,
+			      struct bmp18x_platform_data *pdata)
+{
+	int status = bmp18x_read_calibration_data(data);
+
+	if (status < 0)
+		return status;
+
+	data->last_temp_measurement = 0;
+	data->temp_measurement_period =
+		pdata ? (pdata->temp_measurement_period/1000)*HZ : 1*HZ;
+	data->oversampling_setting = pdata ? pdata->default_oversampling : 3;
+	mutex_init(&data->lock);
+
+	return 0;
+}
+
+__devinit int bmp18x_probe(struct device *dev, struct bmp18x_data_bus *data_bus)
+{
+	struct bmp18x_data *data;
+	struct bmp18x_platform_data *pdata = dev->platform_data;
+	int err = 0;
+
+	if (pdata && pdata->init_hw) {
+		err = pdata->init_hw(dev);
+		if (err) {
+			dev_err(dev, "%s: init_hw failed!\n",
+				BMP18X_NAME);
+			return err;
+		}
+	}
+
+	data = kzalloc(sizeof(struct bmp18x_data), GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	dev_set_drvdata(dev, data);
+	data->data_bus = *data_bus;
+	data->dev = dev;
+
+	err = bmp18x_detect(dev);
+	if (err < 0) {
+		dev_err(dev, "%s: chip_id failed!\n", BMP18X_NAME);
+		goto exit_free;
+	}
+
+	/* Initialize the BMP18X chip */
+	err = bmp18x_init_client(data, pdata);
+	if (err < 0)
+		goto exit_free;
+
+	/* Register sysfs hooks */
+	err = sysfs_create_group(&dev->kobj, &bmp18x_attr_group);
+	if (err)
+		goto exit_free;
+
+	dev_info(dev, "Succesfully initialized bmp18x!\n");
+	return 0;
+
+exit_free:
+	kfree(data);
+exit:
+	if (pdata && pdata->deinit_hw)
+		pdata->deinit_hw(dev);
+	return err;
+}
+EXPORT_SYMBOL(bmp18x_probe);
+
+int bmp18x_remove(struct device *dev)
+{
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+	struct bmp18x_platform_data *pdata = dev->platform_data;
+
+	sysfs_remove_group(&dev->kobj, &bmp18x_attr_group);
+
+	if (pdata && pdata->deinit_hw)
+		pdata->deinit_hw(dev);
+
+	kfree(data);
+
+	return 0;
+}
+EXPORT_SYMBOL(bmp18x_remove);
+
+#ifdef CONFIG_PM
+int bmp18x_disable(struct device *dev)
+{
+	struct bmp18x_platform_data *pdata = dev->platform_data;
+
+	if (pdata && pdata->deinit_hw)
+		pdata->deinit_hw(dev);
+
+	return 0;
+}
+EXPORT_SYMBOL(bmp18x_disable);
+
+int bmp18x_enable(struct device *dev)
+{
+	struct bmp18x_platform_data *pdata = dev->platform_data;
+
+	if (pdata && pdata->init_hw)
+		return pdata->init_hw(dev);
+
+	return 0;
+}
+EXPORT_SYMBOL(bmp18x_enable);
+#endif
+
+MODULE_AUTHOR("Eric Andersson <eric.andersson@unixphere.com>");
+MODULE_DESCRIPTION("BMP18X driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/i2c/bmp085.h b/include/linux/i2c/bmp085.h
deleted file mode 100644
index ee6e398..0000000
--- a/include/linux/i2c/bmp085.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2012  Bosch Sensortec GmbH
- * Copyright (c) 2012  Unixphere AB
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _BMP085_H
-#define _BMP085_H
-
-#define BMP085_NAME		"bmp085"
-#define BMP085_I2C_ADDRESS	0x77
-
-/**
- * struct bmp085_platform_data - represents platform data for the bmp085 driver
- * @chip_id: Configurable chip id for non-default chip revisions
- * @default_oversampling: Default oversampling value to be used at startup,
- * value range is 0-3 with rising sensitivity.
- * @temp_measurement_period: Temperature measurement period (milliseconds), set
- * to zero if unsure.
- * @init_hw: Callback for hw specific startup
- * @deinit_hw: Callback for hw specific shutdown
- */
-struct bmp085_platform_data {
-	u8	chip_id;
-	u8	default_oversampling;
-	u32	temp_measurement_period;
-	int	(*init_hw)(struct device *dev);
-	void	(*deinit_hw)(struct device *dev);
-};
-
-struct bmp085_bus_ops {
-	int	(*read_block)(void *client, u8 reg, int len, char *buf);
-	int	(*read_byte)(void *client, u8 reg);
-	int	(*write_byte)(void *client, u8 reg, u8 value);
-};
-
-struct bmp085_data_bus {
-	const struct bmp085_bus_ops	*bops;
-	void	*client;
-};
-
-int bmp085_probe(struct device *dev, struct bmp085_data_bus *data_bus);
-int bmp085_remove(struct device *dev);
-int bmp085_detect(struct device *dev);
-#ifdef CONFIG_PM
-int bmp085_enable(struct device *dev);
-int bmp085_disable(struct device *dev);
-#endif
-
-#endif
diff --git a/include/linux/i2c/bmp18x.h b/include/linux/i2c/bmp18x.h
new file mode 100644
index 0000000..f08d82e
--- /dev/null
+++ b/include/linux/i2c/bmp18x.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2012  Bosch Sensortec GmbH
+ * Copyright (c) 2012  Unixphere AB
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _BMP18X_H
+#define _BMP18X_H
+
+#define BMP18X_NAME		"bmp085"
+#define BMP18X_I2C_ADDRESS	0x77
+
+/**
+ * struct bmp18x_platform_data - represents platform data for the bmp18x driver
+ * @chip_id: Configurable chip id for non-default chip revisions
+ * @default_oversampling: Default oversampling value to be used at startup,
+ * value range is 0-3 with rising sensitivity.
+ * @temp_measurement_period: Temperature measurement period (milliseconds), set
+ * to zero if unsure.
+ * @init_hw: Callback for hw specific startup
+ * @deinit_hw: Callback for hw specific shutdown
+ */
+struct bmp18x_platform_data {
+	u8	chip_id;
+	u8	default_oversampling;
+	u32	temp_measurement_period;
+	int	(*init_hw)(struct device *dev);
+	void	(*deinit_hw)(struct device *dev);
+};
+
+struct bmp18x_bus_ops {
+	int	(*read_block)(void *client, u8 reg, int len, char *buf);
+	int	(*read_byte)(void *client, u8 reg);
+	int	(*write_byte)(void *client, u8 reg, u8 value);
+};
+
+struct bmp18x_data_bus {
+	const struct bmp18x_bus_ops	*bops;
+	void	*client;
+};
+
+int bmp18x_probe(struct device *dev, struct bmp18x_data_bus *data_bus);
+int bmp18x_remove(struct device *dev);
+int bmp18x_detect(struct device *dev);
+#ifdef CONFIG_PM
+int bmp18x_enable(struct device *dev);
+int bmp18x_disable(struct device *dev);
+#endif
+
+#endif
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCHv2 3/3] misc: rename bmp085 to bmp18x
  2012-03-06 21:08 ` [PATCHv2 3/3] misc: rename bmp085 to bmp18x Eric Andersson
@ 2012-03-06 21:14   ` Arnd Bergmann
  2012-03-06 21:37   ` Alan Cox
  1 sibling, 0 replies; 12+ messages in thread
From: Arnd Bergmann @ 2012-03-06 21:14 UTC (permalink / raw)
  To: Eric Andersson; +Cc: linux-kernel, gregkh, alan, zhengguang.guo, peter.moeller

On Tuesday 06 March 2012, Eric Andersson wrote:
> The bmp085 chip has been deprecated by the newer bmp18x chip family from
> Bosch Sensortec.
> 
> Reviewed-by: Stefan Nilsson <stefan.nilsson@unixphere.com>
> Signed-off-by: Eric Andersson <eric.andersson@unixphere.com>
> ---
>  drivers/misc/Kconfig       |   18 +-
>  drivers/misc/Makefile      |    6 +-
>  drivers/misc/bmp085.c      |  514 --------------------------------------------
>  drivers/misc/bmp18x-i2c.c  |  132 +++++++++++
>  drivers/misc/bmp18x-spi.c  |  140 ++++++++++++
>  drivers/misc/bmp18x.c      |  512 +++++++++++++++++++++++++++++++++++++++++++
>  include/linux/i2c/bmp085.h |   63 ------
>  include/linux/i2c/bmp18x.h |   63 ++++++
>  8 files changed, 859 insertions(+), 589 deletions(-)

Please use 'git format-patch -M' when sending a rename patch, to make it obvious
that there are no code changes in the rename. It's a bit suspicous that
the files are different size and that you remove one .c file but add three
other ones.

You should also try give a better explanation why the rename is actually a
good idea. Simply listing the old model as deprecated does not sound like
a strong enough reason, given that some people might rely on the existing
name in user space interfaces.

	Arnd

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCHv2 1/3] misc: clean up bmp085 driver
  2012-03-06 21:08 ` [PATCHv2 1/3] misc: clean up bmp085 driver Eric Andersson
@ 2012-03-06 21:20   ` Arnd Bergmann
  2012-03-12 22:53     ` Eric Andersson
  0 siblings, 1 reply; 12+ messages in thread
From: Arnd Bergmann @ 2012-03-06 21:20 UTC (permalink / raw)
  To: Eric Andersson; +Cc: linux-kernel, gregkh, alan, zhengguang.guo, peter.moeller

On Tuesday 06 March 2012, Eric Andersson wrote:
> This patch includes various cleaning of the bmp085 driver including:
> - Addition of platform_data and header file
> - Implement pm functions
> - Whitespaces and alignment fixes
> - Minor typos
> - Consistency fixes
> 
> Reviewed-by: Stefan Nilsson <stefan.nilsson@unixphere.com>
> Signed-off-by: Eric Andersson <eric.andersson@unixphere.com>

Most of the cleanups look good, just a few things that stick out:

>  static int __devinit bmp085_probe(struct i2c_client *client,
> -			 const struct i2c_device_id *id)
> +			const struct i2c_device_id *id)
>  {
>  	struct bmp085_data *data;
> +	struct bmp085_platform_data *pdata = client->dev.platform_data;
> +	u8 chip_id = (pdata && pdata->chip_id) ? pdata->chip_id :
> +						 BMP085_CHIP_ID;
>  	int err = 0;
>  
> +	if (pdata && pdata->init_hw) {
> +		err = pdata->init_hw(&client->dev);
> +		if (err) {
> +			dev_err(&client->dev, "%s: init_hw failed!\n",
> +				BMP085_NAME);
> +			return err;
> +		}
> +	}
> +

The addition of platform_data does not look like a cleanup to me,
it's a significant change in the interface to the platform, so I
would put it into a separate patch.

> +	if (i2c_smbus_read_byte_data(client, BMP085_CHIP_ID_REG) != chip_id) {
> +		dev_err(&client->dev, "%s: chip_id failed!\n", BMP085_NAME);
> +		err = -ENODEV;
> +		goto exit_free;
> +	}
> +

This part looks like it belongs into the second patch where you add support
for more than one chip id.

> diff --git a/include/linux/i2c/bmp085.h b/include/linux/i2c/bmp085.h
> new file mode 100644
> index 0000000..e6fc752
> --- /dev/null
> +++ b/include/linux/i2c/bmp085.h

Since this file only adds platform_data, I think it should go into
include/linux/platform_data/, not include/linux/i2c, and it should
be in the same patch as the change to use the platform data when you
split that out.

Also, which platforms are actually using this driver? I could
not find any platform that defines a bmp085 platform_device. If this
is for new ARM platforms, I would rather not add platform_data at
all because those platforms will have to use device tree properties
rather than platform_data to pass initialization data.

	Arnd

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCHv2 2/3] misc: add support for bmp18x chips to the bmp085 driver
  2012-03-06 21:08 ` [PATCHv2 2/3] misc: add support for bmp18x chips to the " Eric Andersson
@ 2012-03-06 21:27   ` Arnd Bergmann
  2012-03-06 22:17     ` Eric Andersson
  0 siblings, 1 reply; 12+ messages in thread
From: Arnd Bergmann @ 2012-03-06 21:27 UTC (permalink / raw)
  To: Eric Andersson, Mark Brown
  Cc: linux-kernel, gregkh, alan, zhengguang.guo, peter.moeller

On Tuesday 06 March 2012, Eric Andersson wrote:
> The bmp18x chip family comes in an I2C respectively SPI variant.
> Hence, the bmp085 driver was split to support both buses.
> 
> Tested-by: Zhengguang Guo <zhengguang.guo@bosch-sensortec.com>
> Reviewed-by: Stefan Nilsson <stefan.nilsson@unixphere.com>
> Signed-off-by: Eric Andersson <eric.andersson@unixphere.com>

(adding Mark Brown to Cc)

I don't know much about regmap, but your description sounds like you
should be using it here, to simplify the differences between i2c and
spi in your driver instead of implementing your own abstraction
layer.

>  config BMP085
>  	tristate "BMP085 digital pressure sensor"
> -	depends on I2C && SYSFS
> +	depends on (I2C || SPI_MASTER) && SYSFS
>  	help
> -	  If you say yes here you get support for the Bosch Sensortec
> -	  BMP085 digital pressure sensor.
> +	  Say Y here if you want support for Bosch Sensortec's digital
> +	  pressure sensors BMP085 and BMP18x.
>  
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called bmp085.
>  
> +config BMP085_I2C
> +	tristate "support I2C bus connection"
> +	depends on BMP085 && I2C
> +	help
> +	  Say Y here if you want to support Bosch Sensortec's digital pressure
> +	  sensor hooked to an I2C bus.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called bmp085-i2c.
> +
> +config BMP085_SPI
> +	tristate "support SPI bus connection"
> +	depends on BMP085 && SPI_MASTER
> +	help
> +	  Say Y here if you want to support Bosch Sensortec's digital pressure
> +	  sensor hooked to an SPI bus.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called bmp085-spi.
> +

IMHO this would be better expressed if you make CONFIG_BMP085 a hidden
option that is selected when either BMP085_I2C or BMP085_SPI are enabled.
Otherwise you make it possible to build just the base driver but neither
of the front-ends, which is a bit pointless.

>  }
> +EXPORT_SYMBOL(bmp085_probe);
>  

When you add internal symbols inside of your driver, best always use
EXPORT_SYMBOL_GPL. There is little practical difference here, but it
helps to get used to just always pick that as a default.

	Arnd

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCHv2 3/3] misc: rename bmp085 to bmp18x
  2012-03-06 21:08 ` [PATCHv2 3/3] misc: rename bmp085 to bmp18x Eric Andersson
  2012-03-06 21:14   ` Arnd Bergmann
@ 2012-03-06 21:37   ` Alan Cox
  1 sibling, 0 replies; 12+ messages in thread
From: Alan Cox @ 2012-03-06 21:37 UTC (permalink / raw)
  To: Eric Andersson; +Cc: linux-kernel, gregkh, arnd, zhengguang.guo, peter.moeller

On Tue,  6 Mar 2012 22:08:04 +0100
Eric Andersson <eric.andersson@unixphere.com> wrote:

> The bmp085 chip has been deprecated by the newer bmp18x chip family from
> Bosch Sensortec.

And yo risk breaking existing systems by renaming it. Are you going to
rename it again when the 285, 385, 485 come out ?

By all means change the description but leave the Kconfig and module name
alone. It's gratuitious breakage and config file frobbing otherwise.

Alan

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCHv2 2/3] misc: add support for bmp18x chips to the bmp085 driver
  2012-03-06 21:27   ` Arnd Bergmann
@ 2012-03-06 22:17     ` Eric Andersson
  2012-03-07  0:03       ` Mark Brown
  0 siblings, 1 reply; 12+ messages in thread
From: Eric Andersson @ 2012-03-06 22:17 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Mark Brown, linux-kernel, gregkh, alan, zhengguang.guo,
	peter.moeller, Stefan Nilsson

On 21:27 Tue 06 Mar     , Arnd Bergmann wrote:
> On Tuesday 06 March 2012, Eric Andersson wrote:
> > The bmp18x chip family comes in an I2C respectively SPI variant.
> > Hence, the bmp085 driver was split to support both buses.
> > 
> > Tested-by: Zhengguang Guo <zhengguang.guo@bosch-sensortec.com>
> > Reviewed-by: Stefan Nilsson <stefan.nilsson@unixphere.com>
> > Signed-off-by: Eric Andersson <eric.andersson@unixphere.com>
> 
> (adding Mark Brown to Cc)
> 
> I don't know much about regmap, but your description sounds like you
> should be using it here, to simplify the differences between i2c and
> spi in your driver instead of implementing your own abstraction
> layer.
> 
> >  config BMP085
> >  	tristate "BMP085 digital pressure sensor"
> > -	depends on I2C && SYSFS
> > +	depends on (I2C || SPI_MASTER) && SYSFS
> >  	help
> > -	  If you say yes here you get support for the Bosch Sensortec
> > -	  BMP085 digital pressure sensor.
> > +	  Say Y here if you want support for Bosch Sensortec's digital
> > +	  pressure sensors BMP085 and BMP18x.
> >  
> >  	  To compile this driver as a module, choose M here: the
> >  	  module will be called bmp085.
> >  
> > +config BMP085_I2C
> > +	tristate "support I2C bus connection"
> > +	depends on BMP085 && I2C
> > +	help
> > +	  Say Y here if you want to support Bosch Sensortec's digital pressure
> > +	  sensor hooked to an I2C bus.
> > +
> > +	  To compile this driver as a module, choose M here: the
> > +	  module will be called bmp085-i2c.
> > +
> > +config BMP085_SPI
> > +	tristate "support SPI bus connection"
> > +	depends on BMP085 && SPI_MASTER
> > +	help
> > +	  Say Y here if you want to support Bosch Sensortec's digital pressure
> > +	  sensor hooked to an SPI bus.
> > +
> > +	  To compile this driver as a module, choose M here: the
> > +	  module will be called bmp085-spi.
> > +
> 
> IMHO this would be better expressed if you make CONFIG_BMP085 a hidden
> option that is selected when either BMP085_I2C or BMP085_SPI are enabled.
> Otherwise you make it possible to build just the base driver but neither
> of the front-ends, which is a bit pointless.

This setup is inspired from other drivers such as ad525x_dpot.c and
ad714x.c, which also have their own bus abstraction. If regmap is a more
generic way of solving this I am all for it!

-- 
Best regards,
 Eric

http://www.unixphere.com

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCHv2 2/3] misc: add support for bmp18x chips to the bmp085 driver
  2012-03-06 22:17     ` Eric Andersson
@ 2012-03-07  0:03       ` Mark Brown
  0 siblings, 0 replies; 12+ messages in thread
From: Mark Brown @ 2012-03-07  0:03 UTC (permalink / raw)
  To: Eric Andersson
  Cc: Arnd Bergmann, linux-kernel, gregkh, alan, zhengguang.guo,
	peter.moeller, Stefan Nilsson

[-- Attachment #1: Type: text/plain, Size: 1944 bytes --]

On Tue, Mar 06, 2012 at 11:17:52PM +0100, Eric Andersson wrote:
> On 21:27 Tue 06 Mar     , Arnd Bergmann wrote:

> > I don't know much about regmap, but your description sounds like you
> > should be using it here, to simplify the differences between i2c and
> > spi in your driver instead of implementing your own abstraction
> > layer.

regmap provides I2C and SPI register I/O for most devices using those
buses (and will do more buses in future I expect) and also provides
diagnostic (things like register I/O logging and register map dumps) and
optional cache infrastructure on top of that very cheaply (so you can
easily do things like avoid the read part of read/modify/write cycles or
restore the register state on resume).  The win is partly getting the
infrastructure and partly the fact that all the code for formatting the
data for the bus is factored out from the individual driver, usually
there's a substantial code saving.

> > IMHO this would be better expressed if you make CONFIG_BMP085 a hidden
> > option that is selected when either BMP085_I2C or BMP085_SPI are enabled.
> > Otherwise you make it possible to build just the base driver but neither
> > of the front-ends, which is a bit pointless.

> This setup is inspired from other drivers such as ad525x_dpot.c and
> ad714x.c, which also have their own bus abstraction. If regmap is a more
> generic way of solving this I am all for it!

The idiom Arnd describes is the more normal one for the reasons he
mentions - see for example what most MFDs that have this problem do.

You'll need the same setup even with regmap since you'll need to
register I2C and SPI drivers.  What you save is all the register I/O
code - often the I2C and SPI specific code gets reduced to just calling
regmap_init_X().  The regmap subsystem only appeared in 3.1 so lots of
drivers predate it and could benefit from using it, we're starting to
see conversions happening in some subsystems.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCHv2 1/3] misc: clean up bmp085 driver
  2012-03-06 21:20   ` Arnd Bergmann
@ 2012-03-12 22:53     ` Eric Andersson
  2012-03-13 12:04       ` Arnd Bergmann
  0 siblings, 1 reply; 12+ messages in thread
From: Eric Andersson @ 2012-03-12 22:53 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-kernel, gregkh, alan, zhengguang.guo, peter.moeller,
	Stefan Nilsson

On 21:20 Tue 06 Mar     , Arnd Bergmann wrote:
> On Tuesday 06 March 2012, Eric Andersson wrote:
> > This patch includes various cleaning of the bmp085 driver including:
> > - Addition of platform_data and header file
> > - Implement pm functions
> > - Whitespaces and alignment fixes
> > - Minor typos
> > - Consistency fixes
> > 
> > Reviewed-by: Stefan Nilsson <stefan.nilsson@unixphere.com>
> > Signed-off-by: Eric Andersson <eric.andersson@unixphere.com>
> 
> Most of the cleanups look good, just a few things that stick out:
> 
> >  static int __devinit bmp085_probe(struct i2c_client *client,
> > -			 const struct i2c_device_id *id)
> > +			const struct i2c_device_id *id)
> >  {
> >  	struct bmp085_data *data;
> > +	struct bmp085_platform_data *pdata = client->dev.platform_data;
> > +	u8 chip_id = (pdata && pdata->chip_id) ? pdata->chip_id :
> > +						 BMP085_CHIP_ID;
> >  	int err = 0;
> >  
> > +	if (pdata && pdata->init_hw) {
> > +		err = pdata->init_hw(&client->dev);
> > +		if (err) {
> > +			dev_err(&client->dev, "%s: init_hw failed!\n",
> > +				BMP085_NAME);
> > +			return err;
> > +		}
> > +	}
> > +
> 
> The addition of platform_data does not look like a cleanup to me,
> it's a significant change in the interface to the platform, so I
> would put it into a separate patch.

Yes, I agree.

> > +	if (i2c_smbus_read_byte_data(client, BMP085_CHIP_ID_REG) != chip_id) {
> > +		dev_err(&client->dev, "%s: chip_id failed!\n", BMP085_NAME);
> > +		err = -ENODEV;
> > +		goto exit_free;
> > +	}
> > +
> 
> This part looks like it belongs into the second patch where you add support
> for more than one chip id.
> 
> > diff --git a/include/linux/i2c/bmp085.h b/include/linux/i2c/bmp085.h
> > new file mode 100644
> > index 0000000..e6fc752
> > --- /dev/null
> > +++ b/include/linux/i2c/bmp085.h
> 
> Since this file only adds platform_data, I think it should go into
> include/linux/platform_data/, not include/linux/i2c, and it should
> be in the same patch as the change to use the platform data when you
> split that out.
> 
> Also, which platforms are actually using this driver? I could
> not find any platform that defines a bmp085 platform_device. If this
> is for new ARM platforms, I would rather not add platform_data at
> all because those platforms will have to use device tree properties
> rather than platform_data to pass initialization data.

Platform device? This is a pressure sensor connected as a peripheral
device to the i2c bus. I don't think you will find any platform that
uses this "by default" in the tree.

Of course I can add of_get_property() calls, but what is actually the
long-term plan here for peripheral devices? Should they all abandon their
platform data in favor of devicetree? How should the callbacks in platform
data be handled, in my case pdata->init_hw()?

-- 
Best regards,
 Eric

http://www.unixphere.com

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCHv2 1/3] misc: clean up bmp085 driver
  2012-03-12 22:53     ` Eric Andersson
@ 2012-03-13 12:04       ` Arnd Bergmann
  0 siblings, 0 replies; 12+ messages in thread
From: Arnd Bergmann @ 2012-03-13 12:04 UTC (permalink / raw)
  To: Eric Andersson
  Cc: linux-kernel, gregkh, alan, zhengguang.guo, peter.moeller,
	Stefan Nilsson

On Monday 12 March 2012, Eric Andersson wrote:
> > > diff --git a/include/linux/i2c/bmp085.h b/include/linux/i2c/bmp085.h
> > > new file mode 100644
> > > index 0000000..e6fc752
> > > --- /dev/null
> > > +++ b/include/linux/i2c/bmp085.h
> > 
> > Since this file only adds platform_data, I think it should go into
> > include/linux/platform_data/, not include/linux/i2c, and it should
> > be in the same patch as the change to use the platform data when you
> > split that out.
> > 
> > Also, which platforms are actually using this driver? I could
> > not find any platform that defines a bmp085 platform_device. If this
> > is for new ARM platforms, I would rather not add platform_data at
> > all because those platforms will have to use device tree properties
> > rather than platform_data to pass initialization data.
> 
> Platform device? This is a pressure sensor connected as a peripheral
> device to the i2c bus. I don't think you will find any platform that
> uses this "by default" in the tree.
> 
> Of course I can add of_get_property() calls, but what is actually the
> long-term plan here for peripheral devices? Should they all abandon their
> platform data in favor of devicetree? 

Yes, that is definitely the plan. The current method does not scale,
because right now you have to modify the kernel sources any time you
have a slightly different combination of devices in the system, which
especially in cases of user-pluggable i2c devices is not a good
design.

> How should the callbacks in platform data be handled, in my case
> pdata->init_hw()?

This depends a lot on what the individual callback does. In my experience,
90% of these callbacks can and should just get removed because they
are not necessary and the same functionality can be expressed by generalizing
the setup procedure, e.g. by calling into the regulator, gpio, clock
or pinmux frameworks from the device probe() function.

In the few cases where this is not possible, some of the approaches
I can think of (again, case by case) include:

* educate the hardware designers so they do things in a more maintainable
  way in the future, hope that the current design goes away.

* add a special case in the driver using something like
  if (machine_is_compatible("something,weird"))
	do_weird_setup(dev);

* use auxdata for the machine to supply a platform_data structure in
  addition to the device tree.

* Don't support the board in the mainline kernel, but require the
  user to keep using a private patch (this is the status quo, because
  right now they need a private patch to add the board file).

	Arnd


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2012-03-13 12:10 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-06 21:08 [PATCHv2 0/3] Add support for bmp18x to bmp085 Eric Andersson
2012-03-06 21:08 ` [PATCHv2 1/3] misc: clean up bmp085 driver Eric Andersson
2012-03-06 21:20   ` Arnd Bergmann
2012-03-12 22:53     ` Eric Andersson
2012-03-13 12:04       ` Arnd Bergmann
2012-03-06 21:08 ` [PATCHv2 2/3] misc: add support for bmp18x chips to the " Eric Andersson
2012-03-06 21:27   ` Arnd Bergmann
2012-03-06 22:17     ` Eric Andersson
2012-03-07  0:03       ` Mark Brown
2012-03-06 21:08 ` [PATCHv2 3/3] misc: rename bmp085 to bmp18x Eric Andersson
2012-03-06 21:14   ` Arnd Bergmann
2012-03-06 21:37   ` Alan Cox

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox