Re: [PATCH] iio: Add Freescale MPL115A2 pressure / temperature sensor driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On May 2, 2014 9:02:24 AM GMT+01:00, Peter Meerwald <pmeerw@xxxxxxxxxx> wrote:
>I2C-controlled sensor with 10-bit pressure and temperature measurement
>
>datasheet:
>http://cache.freescale.com/files/sensors/doc/data_sheet/MPL3115A2.pdf
>
>Signed-off-by: Peter Meerwald <pmeerw@xxxxxxxxxx>
No remove when not using devm version of iio_device_register ?
>---
> drivers/iio/pressure/Kconfig  |  10 ++
> drivers/iio/pressure/Makefile |   1 +
>drivers/iio/pressure/mpl115.c | 211
>++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 222 insertions(+)
> create mode 100644 drivers/iio/pressure/mpl115.c
>
>diff --git a/drivers/iio/pressure/Kconfig
>b/drivers/iio/pressure/Kconfig
>index d88ff17..ffac8ac 100644
>--- a/drivers/iio/pressure/Kconfig
>+++ b/drivers/iio/pressure/Kconfig
>@@ -19,6 +19,16 @@ config HID_SENSOR_PRESS
>          To compile this driver as a module, choose M here: the module
>           will be called hid-sensor-press.
> 
>+config MPL115
>+	tristate "Freescale MPL115A2 pressure sensor driver"
>+	depends on I2C
>+	help
>+	  Say yes here to build support for the Freescale MPL115A2
>+	  pressure sensor connected via I2C.
>+
>+          To compile this driver as a module, choose M here: the
>module
>+          will be called mpl115.
>+
> config MPL3115
> 	tristate "Freescale MPL3115A2 pressure sensor driver"
> 	depends on I2C
>diff --git a/drivers/iio/pressure/Makefile
>b/drivers/iio/pressure/Makefile
>index 4a57bf6..c53d250 100644
>--- a/drivers/iio/pressure/Makefile
>+++ b/drivers/iio/pressure/Makefile
>@@ -4,6 +4,7 @@
> 
> # When adding new entries keep the list in alphabetical order
> obj-$(CONFIG_HID_SENSOR_PRESS)   += hid-sensor-press.o
>+obj-$(CONFIG_MPL115) += mpl115.o
> obj-$(CONFIG_MPL3115) += mpl3115.o
> obj-$(CONFIG_IIO_ST_PRESS) += st_pressure.o
> st_pressure-y := st_pressure_core.o
>diff --git a/drivers/iio/pressure/mpl115.c
>b/drivers/iio/pressure/mpl115.c
>new file mode 100644
>index 0000000..8229a40
>--- /dev/null
>+++ b/drivers/iio/pressure/mpl115.c
>@@ -0,0 +1,211 @@
>+/*
>+ * mpl115.c - Support for Freescale MPL115A2 pressure/temperature
>sensor
>+ *
>+ * Copyright (c) 2014 Peter Meerwald <pmeerw@xxxxxxxxxx>
>+ *
>+ * This file is subject to the terms and conditions of version 2 of
>+ * the GNU General Public License.  See the file COPYING in the main
>+ * directory of this archive for more details.
>+ *
>+ * (7-bit I2C slave address 0x60)
>+ *
>+ * TODO: shutdown pin
>+ *
>+ */
>+
>+#include <linux/module.h>
>+#include <linux/i2c.h>
>+#include <linux/iio/iio.h>
>+#include <linux/delay.h>
>+
>+#define MPL115_PADC 0x00 /* pressure ADC output value, MSB first, 10
>bit */
>+#define MPL115_TADC 0x02 /* temperature ADC output value, MSB first,
>10 bit */
>+#define MPL115_A0 0x04 /* 12 bit integer, 3 bit fraction */
>+#define MPL115_B1 0x06 /* 2 bit integer, 13 bit fraction */
>+#define MPL115_B2 0x08 /* 1 bit integer, 14 bit fraction */
>+#define MPL115_C12 0x0a /* 0 bit integer, 13 bit fraction */
>+#define MPL115_CONVERT 0x12 /* convert temperature and pressure */
>+
>+struct mpl115_data {
>+	struct i2c_client *client;
>+	struct mutex lock;
>+	s16 a0;
>+	s16 b1, b2;
>+	s16 c12;
>+};
>+
>+static int mpl115_request(struct mpl115_data *data)
>+{
>+	int ret = i2c_smbus_write_byte_data(data->client, MPL115_CONVERT, 0);
>+	if (ret < 0)
>+		return ret;
>+
>+	usleep_range(3000, 4000);
>+
>+	return 0;
>+}
>+
>+static int mpl115_comp_pressure(struct mpl115_data *data, int *val,
>int *val2)
>+{
>+	int ret;
>+	u16 padc, tadc;
>+	int a1, y1, pcomp;
>+	unsigned kpa;
>+
>+	mutex_lock(&data->lock);
>+	ret = mpl115_request(data);
>+	if (ret < 0)
>+		goto done;
>+
>+	ret = i2c_smbus_read_word_swapped(data->client, MPL115_PADC);
>+	if (ret < 0)
>+		goto done;
>+	padc = ret >> 6;
>+
>+	ret = i2c_smbus_read_word_swapped(data->client, MPL115_TADC);
>+	if (ret < 0)
>+		goto done;
>+	tadc = ret >> 6;
>+
>+	/* see Freescale AN3785 */
>+	a1 = data->b1 + ((data->c12 * tadc) >> 11);
>+	y1 = (data->a0 << 10) + a1 * padc;
>+
>+	/* compensated pressure with 4 fractional bits */
>+	pcomp = (y1 + ((data->b2 * (int) tadc) >> 1)) >> 9;
>+
>+	kpa = pcomp * (115 - 50) / 1023 + (50 << 4);
>+	*val = kpa >> 4;
>+	*val2 = (kpa & 15) * (1000000 >> 4);
>+done:
>+	mutex_unlock(&data->lock);
>+	return ret;
>+}
>+
>+static int mpl115_read_temp(struct mpl115_data *data)
>+{
>+	int ret;
>+
>+	mutex_lock(&data->lock);
>+	ret = mpl115_request(data);
>+	if (ret < 0)
>+		goto done;
>+	ret = i2c_smbus_read_word_swapped(data->client, MPL115_TADC);
>+done:
>+	mutex_unlock(&data->lock);
>+	return ret;
>+}
>+
>+static int mpl115_read_raw(struct iio_dev *indio_dev,
>+			    struct iio_chan_spec const *chan,
>+			    int *val, int *val2, long mask)
>+{
>+	struct mpl115_data *data = iio_priv(indio_dev);
>+	int ret;
>+
>+	switch (mask) {
>+	case IIO_CHAN_INFO_PROCESSED:
>+		ret = mpl115_comp_pressure(data, val, val2);
>+		if (ret < 0)
>+			return ret;
>+		return IIO_VAL_INT_PLUS_MICRO;
>+	case IIO_CHAN_INFO_RAW:
>+		/* temperature -5.35 C / LSB, 472 LSB is 25 C */
>+		ret = mpl115_read_temp(data);
>+		if (ret < 0)
>+			return ret;
>+		*val = ret >> 6;
>+		return IIO_VAL_INT;
>+	case IIO_CHAN_INFO_OFFSET:
>+		*val = 605;
>+		*val2 = 750000;
>+		return IIO_VAL_INT_PLUS_MICRO;
>+	case IIO_CHAN_INFO_SCALE:
>+		*val = -186;
>+		*val2 = 915888;
>+		return IIO_VAL_INT_PLUS_MICRO;
>+	}
>+	return -EINVAL;
>+}
>+
>+static const struct iio_chan_spec mpl115_channels[] = {
>+	{
>+		.type = IIO_PRESSURE,
>+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
>+	},
>+	{
>+		.type = IIO_TEMP,
>+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
>+			BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE),
>+	},
>+};
>+
>+static const struct iio_info mpl115_info = {
>+	.read_raw = &mpl115_read_raw,
>+	.driver_module = THIS_MODULE,
>+};
>+
>+static int mpl115_probe(struct i2c_client *client,
>+			 const struct i2c_device_id *id)
>+{
>+	struct mpl115_data *data;
>+	struct iio_dev *indio_dev;
>+	int ret;
>+
>+	if (!i2c_check_functionality(client->adapter,
>I2C_FUNC_SMBUS_WORD_DATA))
>+		return -ENODEV;
>+
>+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
>+	if (!indio_dev)
>+		return -ENOMEM;
>+
>+	data = iio_priv(indio_dev);
>+	data->client = client;
>+	mutex_init(&data->lock);
>+
>+	i2c_set_clientdata(client, indio_dev);
>+	indio_dev->info = &mpl115_info;
>+	indio_dev->name = id->name;
>+	indio_dev->dev.parent = &client->dev;
>+	indio_dev->modes = INDIO_DIRECT_MODE;
>+	indio_dev->channels = mpl115_channels;
>+	indio_dev->num_channels = ARRAY_SIZE(mpl115_channels);
>+
>+	ret = i2c_smbus_read_word_swapped(data->client, MPL115_A0);
>+	if (ret < 0)
>+		return ret;
>+	data->a0 = ret;
>+	ret = i2c_smbus_read_word_swapped(data->client, MPL115_B1);
>+	if (ret < 0)
>+		return ret;
>+	data->b1 = ret;
>+	ret = i2c_smbus_read_word_swapped(data->client, MPL115_B2);
>+	if (ret < 0)
>+		return ret;
>+	data->b2 = ret;
>+	ret = i2c_smbus_read_word_swapped(data->client, MPL115_C12);
>+	if (ret < 0)
>+		return ret;
>+	data->c12 = ret;
>+
>+	return iio_device_register(indio_dev);
>+}
>+
>+static const struct i2c_device_id mpl115_id[] = {
>+	{ "mpl115", 0 },
>+	{ }
>+};
>+MODULE_DEVICE_TABLE(i2c, mpl115_id);
>+
>+static struct i2c_driver mpl115_driver = {
>+	.driver = {
>+		.name	= "mpl115",
>+	},
>+	.probe = mpl115_probe,
>+	.id_table = mpl115_id,
>+};
>+module_i2c_driver(mpl115_driver);
>+
>+MODULE_AUTHOR("Peter Meerwald <pmeerw@xxxxxxxxxx>");
>+MODULE_DESCRIPTION("Freescale MPL115 pressure/temperature driver");
>+MODULE_LICENSE("GPL");

-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.
--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux