13017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald/*
23017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald * mpl115.c - Support for Freescale MPL115A2 pressure/temperature sensor
33017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald *
43017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
53017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald *
63017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald * This file is subject to the terms and conditions of version 2 of
73017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald * the GNU General Public License.  See the file COPYING in the main
83017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald * directory of this archive for more details.
93017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald *
103017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald * (7-bit I2C slave address 0x60)
113017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald *
123017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald * TODO: shutdown pin
133017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald *
143017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald */
153017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
163017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald#include <linux/module.h>
173017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald#include <linux/i2c.h>
183017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald#include <linux/iio/iio.h>
193017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald#include <linux/delay.h>
203017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
213017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald#define MPL115_PADC 0x00 /* pressure ADC output value, MSB first, 10 bit */
223017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald#define MPL115_TADC 0x02 /* temperature ADC output value, MSB first, 10 bit */
233017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald#define MPL115_A0 0x04 /* 12 bit integer, 3 bit fraction */
243017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald#define MPL115_B1 0x06 /* 2 bit integer, 13 bit fraction */
253017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald#define MPL115_B2 0x08 /* 1 bit integer, 14 bit fraction */
263017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald#define MPL115_C12 0x0a /* 0 bit integer, 13 bit fraction */
273017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald#define MPL115_CONVERT 0x12 /* convert temperature and pressure */
283017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
293017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwaldstruct mpl115_data {
303017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	struct i2c_client *client;
313017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	struct mutex lock;
323017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	s16 a0;
333017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	s16 b1, b2;
343017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	s16 c12;
353017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald};
363017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
373017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwaldstatic int mpl115_request(struct mpl115_data *data)
383017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald{
393017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	int ret = i2c_smbus_write_byte_data(data->client, MPL115_CONVERT, 0);
403017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	if (ret < 0)
413017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		return ret;
423017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
433017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	usleep_range(3000, 4000);
443017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
453017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	return 0;
463017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald}
473017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
483017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwaldstatic int mpl115_comp_pressure(struct mpl115_data *data, int *val, int *val2)
493017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald{
503017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	int ret;
513017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	u16 padc, tadc;
523017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	int a1, y1, pcomp;
533017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	unsigned kpa;
543017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
553017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	mutex_lock(&data->lock);
563017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	ret = mpl115_request(data);
573017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	if (ret < 0)
583017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		goto done;
593017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
603017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	ret = i2c_smbus_read_word_swapped(data->client, MPL115_PADC);
613017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	if (ret < 0)
623017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		goto done;
633017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	padc = ret >> 6;
643017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
653017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	ret = i2c_smbus_read_word_swapped(data->client, MPL115_TADC);
663017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	if (ret < 0)
673017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		goto done;
683017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	tadc = ret >> 6;
693017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
703017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	/* see Freescale AN3785 */
713017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	a1 = data->b1 + ((data->c12 * tadc) >> 11);
723017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	y1 = (data->a0 << 10) + a1 * padc;
733017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
743017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	/* compensated pressure with 4 fractional bits */
753017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	pcomp = (y1 + ((data->b2 * (int) tadc) >> 1)) >> 9;
763017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
773017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	kpa = pcomp * (115 - 50) / 1023 + (50 << 4);
783017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	*val = kpa >> 4;
793017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	*val2 = (kpa & 15) * (1000000 >> 4);
803017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwalddone:
813017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	mutex_unlock(&data->lock);
823017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	return ret;
833017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald}
843017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
853017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwaldstatic int mpl115_read_temp(struct mpl115_data *data)
863017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald{
873017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	int ret;
883017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
893017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	mutex_lock(&data->lock);
903017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	ret = mpl115_request(data);
913017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	if (ret < 0)
923017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		goto done;
933017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	ret = i2c_smbus_read_word_swapped(data->client, MPL115_TADC);
943017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwalddone:
953017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	mutex_unlock(&data->lock);
963017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	return ret;
973017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald}
983017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
993017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwaldstatic int mpl115_read_raw(struct iio_dev *indio_dev,
1003017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald			    struct iio_chan_spec const *chan,
1013017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald			    int *val, int *val2, long mask)
1023017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald{
1033017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	struct mpl115_data *data = iio_priv(indio_dev);
1043017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	int ret;
1053017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
1063017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	switch (mask) {
1073017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	case IIO_CHAN_INFO_PROCESSED:
1083017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		ret = mpl115_comp_pressure(data, val, val2);
1093017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		if (ret < 0)
1103017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald			return ret;
1113017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		return IIO_VAL_INT_PLUS_MICRO;
1123017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	case IIO_CHAN_INFO_RAW:
1133017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		/* temperature -5.35 C / LSB, 472 LSB is 25 C */
1143017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		ret = mpl115_read_temp(data);
1153017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		if (ret < 0)
1163017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald			return ret;
1173017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		*val = ret >> 6;
1183017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		return IIO_VAL_INT;
1193017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	case IIO_CHAN_INFO_OFFSET:
1203017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		*val = 605;
1213017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		*val2 = 750000;
1223017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		return IIO_VAL_INT_PLUS_MICRO;
1233017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	case IIO_CHAN_INFO_SCALE:
1243017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		*val = -186;
1253017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		*val2 = 915888;
1263017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		return IIO_VAL_INT_PLUS_MICRO;
1273017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	}
1283017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	return -EINVAL;
1293017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald}
1303017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
1313017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwaldstatic const struct iio_chan_spec mpl115_channels[] = {
1323017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	{
1333017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		.type = IIO_PRESSURE,
1343017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
1353017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	},
1363017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	{
1373017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		.type = IIO_TEMP,
1383017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
1393017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald			BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE),
1403017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	},
1413017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald};
1423017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
1433017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwaldstatic const struct iio_info mpl115_info = {
1443017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	.read_raw = &mpl115_read_raw,
1453017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	.driver_module = THIS_MODULE,
1463017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald};
1473017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
1483017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwaldstatic int mpl115_probe(struct i2c_client *client,
1493017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald			 const struct i2c_device_id *id)
1503017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald{
1513017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	struct mpl115_data *data;
1523017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	struct iio_dev *indio_dev;
1533017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	int ret;
1543017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
1553017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
1563017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		return -ENODEV;
1573017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
1583017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
1593017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	if (!indio_dev)
1603017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		return -ENOMEM;
1613017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
1623017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	data = iio_priv(indio_dev);
1633017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	data->client = client;
1643017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	mutex_init(&data->lock);
1653017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
1663017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	i2c_set_clientdata(client, indio_dev);
1673017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	indio_dev->info = &mpl115_info;
1683017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	indio_dev->name = id->name;
1693017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	indio_dev->dev.parent = &client->dev;
1703017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	indio_dev->modes = INDIO_DIRECT_MODE;
1713017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	indio_dev->channels = mpl115_channels;
1723017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	indio_dev->num_channels = ARRAY_SIZE(mpl115_channels);
1733017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
1743017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	ret = i2c_smbus_read_word_swapped(data->client, MPL115_A0);
1753017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	if (ret < 0)
1763017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		return ret;
1773017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	data->a0 = ret;
1783017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	ret = i2c_smbus_read_word_swapped(data->client, MPL115_B1);
1793017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	if (ret < 0)
1803017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		return ret;
1813017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	data->b1 = ret;
1823017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	ret = i2c_smbus_read_word_swapped(data->client, MPL115_B2);
1833017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	if (ret < 0)
1843017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		return ret;
1853017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	data->b2 = ret;
1863017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	ret = i2c_smbus_read_word_swapped(data->client, MPL115_C12);
1873017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	if (ret < 0)
1883017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		return ret;
1893017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	data->c12 = ret;
1903017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
1913017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	return devm_iio_device_register(&client->dev, indio_dev);
1923017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald}
1933017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
1943017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwaldstatic const struct i2c_device_id mpl115_id[] = {
1953017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	{ "mpl115", 0 },
1963017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	{ }
1973017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald};
1983017d90e8931fbd5dbde06b4e793aebb141e4977Peter MeerwaldMODULE_DEVICE_TABLE(i2c, mpl115_id);
1993017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
2003017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwaldstatic struct i2c_driver mpl115_driver = {
2013017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	.driver = {
2023017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald		.name	= "mpl115",
2033017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	},
2043017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	.probe = mpl115_probe,
2053017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald	.id_table = mpl115_id,
2063017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald};
2073017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwaldmodule_i2c_driver(mpl115_driver);
2083017d90e8931fbd5dbde06b4e793aebb141e4977Peter Meerwald
2093017d90e8931fbd5dbde06b4e793aebb141e4977Peter MeerwaldMODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
2103017d90e8931fbd5dbde06b4e793aebb141e4977Peter MeerwaldMODULE_DESCRIPTION("Freescale MPL115 pressure/temperature driver");
2113017d90e8931fbd5dbde06b4e793aebb141e4977Peter MeerwaldMODULE_LICENSE("GPL");
212