aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAkinobu Mita <akinobu.mita@gmail.com>2016-01-15 11:00:03 -0500
committerJonathan Cameron <jic23@kernel.org>2016-01-30 11:27:12 -0500
commitc984b9cbbd17d3eb602de3802e25d975182474fa (patch)
tree742d2eda34d7889d63f8d263947f17a87e22af03
parent0b767b31889539fbc31383469317264ebee3cf08 (diff)
iio: pressure: mpl115: support MPL115A1
mpl115 driver currently supports i2c interface (MPL115A2). There is also SPI version (MPL115A1). The difference between them is only physical transport so we can easily support both while sharing most of the code. Split the driver into a core support module and one module each for I2C and SPI support. Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Cc: Jonathan Cameron <jic23@kernel.org> Cc: Hartmut Knaack <knaack.h@gmx.de> Cc: Lars-Peter Clausen <lars@metafoo.de> Cc: Peter Meerwald <pmeerw@pmeerw.net> Cc: linux-iio@vger.kernel.org Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r--drivers/iio/pressure/Kconfig17
-rw-r--r--drivers/iio/pressure/Makefile2
-rw-r--r--drivers/iio/pressure/mpl115.c65
-rw-r--r--drivers/iio/pressure/mpl115.h24
-rw-r--r--drivers/iio/pressure/mpl115_i2c.c67
-rw-r--r--drivers/iio/pressure/mpl115_spi.c106
6 files changed, 242 insertions, 39 deletions
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
index 6f2e7c9ac23e..e8f60dbf646e 100644
--- a/drivers/iio/pressure/Kconfig
+++ b/drivers/iio/pressure/Kconfig
@@ -31,14 +31,29 @@ config HID_SENSOR_PRESS
31 will be called hid-sensor-press. 31 will be called hid-sensor-press.
32 32
33config MPL115 33config MPL115
34 tristate
35
36config MPL115_I2C
34 tristate "Freescale MPL115A2 pressure sensor driver" 37 tristate "Freescale MPL115A2 pressure sensor driver"
35 depends on I2C 38 depends on I2C
39 select MPL115
36 help 40 help
37 Say yes here to build support for the Freescale MPL115A2 41 Say yes here to build support for the Freescale MPL115A2
38 pressure sensor connected via I2C. 42 pressure sensor connected via I2C.
39 43
40 To compile this driver as a module, choose M here: the module 44 To compile this driver as a module, choose M here: the module
41 will be called mpl115. 45 will be called mpl115_i2c.
46
47config MPL115_SPI
48 tristate "Freescale MPL115A1 pressure sensor driver"
49 depends on SPI_MASTER
50 select MPL115
51 help
52 Say yes here to build support for the Freescale MPL115A1
53 pressure sensor connected via SPI.
54
55 To compile this driver as a module, choose M here: the module
56 will be called mpl115_spi.
42 57
43config MPL3115 58config MPL3115
44 tristate "Freescale MPL3115A2 pressure sensor driver" 59 tristate "Freescale MPL3115A2 pressure sensor driver"
diff --git a/drivers/iio/pressure/Makefile b/drivers/iio/pressure/Makefile
index 46571c96823f..d336af14f3fe 100644
--- a/drivers/iio/pressure/Makefile
+++ b/drivers/iio/pressure/Makefile
@@ -6,6 +6,8 @@
6obj-$(CONFIG_BMP280) += bmp280.o 6obj-$(CONFIG_BMP280) += bmp280.o
7obj-$(CONFIG_HID_SENSOR_PRESS) += hid-sensor-press.o 7obj-$(CONFIG_HID_SENSOR_PRESS) += hid-sensor-press.o
8obj-$(CONFIG_MPL115) += mpl115.o 8obj-$(CONFIG_MPL115) += mpl115.o
9obj-$(CONFIG_MPL115_I2C) += mpl115_i2c.o
10obj-$(CONFIG_MPL115_SPI) += mpl115_spi.o
9obj-$(CONFIG_MPL3115) += mpl3115.o 11obj-$(CONFIG_MPL3115) += mpl3115.o
10obj-$(CONFIG_MS5611) += ms5611_core.o 12obj-$(CONFIG_MS5611) += ms5611_core.o
11obj-$(CONFIG_MS5611_I2C) += ms5611_i2c.o 13obj-$(CONFIG_MS5611_I2C) += ms5611_i2c.o
diff --git a/drivers/iio/pressure/mpl115.c b/drivers/iio/pressure/mpl115.c
index 3e1e33535fe1..138344ca3ffd 100644
--- a/drivers/iio/pressure/mpl115.c
+++ b/drivers/iio/pressure/mpl115.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * mpl115.c - Support for Freescale MPL115A2 pressure/temperature sensor 2 * mpl115.c - Support for Freescale MPL115A pressure/temperature sensor
3 * 3 *
4 * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net> 4 * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
5 * 5 *
@@ -7,17 +7,16 @@
7 * the GNU General Public License. See the file COPYING in the main 7 * the GNU General Public License. See the file COPYING in the main
8 * directory of this archive for more details. 8 * directory of this archive for more details.
9 * 9 *
10 * (7-bit I2C slave address 0x60)
11 *
12 * TODO: shutdown pin 10 * TODO: shutdown pin
13 * 11 *
14 */ 12 */
15 13
16#include <linux/module.h> 14#include <linux/module.h>
17#include <linux/i2c.h>
18#include <linux/iio/iio.h> 15#include <linux/iio/iio.h>
19#include <linux/delay.h> 16#include <linux/delay.h>
20 17
18#include "mpl115.h"
19
21#define MPL115_PADC 0x00 /* pressure ADC output value, MSB first, 10 bit */ 20#define MPL115_PADC 0x00 /* pressure ADC output value, MSB first, 10 bit */
22#define MPL115_TADC 0x02 /* temperature ADC output value, MSB first, 10 bit */ 21#define MPL115_TADC 0x02 /* temperature ADC output value, MSB first, 10 bit */
23#define MPL115_A0 0x04 /* 12 bit integer, 3 bit fraction */ 22#define MPL115_A0 0x04 /* 12 bit integer, 3 bit fraction */
@@ -27,16 +26,18 @@
27#define MPL115_CONVERT 0x12 /* convert temperature and pressure */ 26#define MPL115_CONVERT 0x12 /* convert temperature and pressure */
28 27
29struct mpl115_data { 28struct mpl115_data {
30 struct i2c_client *client; 29 struct device *dev;
31 struct mutex lock; 30 struct mutex lock;
32 s16 a0; 31 s16 a0;
33 s16 b1, b2; 32 s16 b1, b2;
34 s16 c12; 33 s16 c12;
34 const struct mpl115_ops *ops;
35}; 35};
36 36
37static int mpl115_request(struct mpl115_data *data) 37static int mpl115_request(struct mpl115_data *data)
38{ 38{
39 int ret = i2c_smbus_write_byte_data(data->client, MPL115_CONVERT, 0); 39 int ret = data->ops->write(data->dev, MPL115_CONVERT, 0);
40
40 if (ret < 0) 41 if (ret < 0)
41 return ret; 42 return ret;
42 43
@@ -57,12 +58,12 @@ static int mpl115_comp_pressure(struct mpl115_data *data, int *val, int *val2)
57 if (ret < 0) 58 if (ret < 0)
58 goto done; 59 goto done;
59 60
60 ret = i2c_smbus_read_word_swapped(data->client, MPL115_PADC); 61 ret = data->ops->read(data->dev, MPL115_PADC);
61 if (ret < 0) 62 if (ret < 0)
62 goto done; 63 goto done;
63 padc = ret >> 6; 64 padc = ret >> 6;
64 65
65 ret = i2c_smbus_read_word_swapped(data->client, MPL115_TADC); 66 ret = data->ops->read(data->dev, MPL115_TADC);
66 if (ret < 0) 67 if (ret < 0)
67 goto done; 68 goto done;
68 tadc = ret >> 6; 69 tadc = ret >> 6;
@@ -90,7 +91,7 @@ static int mpl115_read_temp(struct mpl115_data *data)
90 ret = mpl115_request(data); 91 ret = mpl115_request(data);
91 if (ret < 0) 92 if (ret < 0)
92 goto done; 93 goto done;
93 ret = i2c_smbus_read_word_swapped(data->client, MPL115_TADC); 94 ret = data->ops->read(data->dev, MPL115_TADC);
94done: 95done:
95 mutex_unlock(&data->lock); 96 mutex_unlock(&data->lock);
96 return ret; 97 return ret;
@@ -145,65 +146,53 @@ static const struct iio_info mpl115_info = {
145 .driver_module = THIS_MODULE, 146 .driver_module = THIS_MODULE,
146}; 147};
147 148
148static int mpl115_probe(struct i2c_client *client, 149int mpl115_probe(struct device *dev, const char *name,
149 const struct i2c_device_id *id) 150 const struct mpl115_ops *ops)
150{ 151{
151 struct mpl115_data *data; 152 struct mpl115_data *data;
152 struct iio_dev *indio_dev; 153 struct iio_dev *indio_dev;
153 int ret; 154 int ret;
154 155
155 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) 156 indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
156 return -ENODEV;
157
158 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
159 if (!indio_dev) 157 if (!indio_dev)
160 return -ENOMEM; 158 return -ENOMEM;
161 159
162 data = iio_priv(indio_dev); 160 data = iio_priv(indio_dev);
163 data->client = client; 161 data->dev = dev;
162 data->ops = ops;
164 mutex_init(&data->lock); 163 mutex_init(&data->lock);
165 164
166 indio_dev->info = &mpl115_info; 165 indio_dev->info = &mpl115_info;
167 indio_dev->name = id->name; 166 indio_dev->name = name;
168 indio_dev->dev.parent = &client->dev; 167 indio_dev->dev.parent = dev;
169 indio_dev->modes = INDIO_DIRECT_MODE; 168 indio_dev->modes = INDIO_DIRECT_MODE;
170 indio_dev->channels = mpl115_channels; 169 indio_dev->channels = mpl115_channels;
171 indio_dev->num_channels = ARRAY_SIZE(mpl115_channels); 170 indio_dev->num_channels = ARRAY_SIZE(mpl115_channels);
172 171
173 ret = i2c_smbus_read_word_swapped(data->client, MPL115_A0); 172 ret = data->ops->init(data->dev);
173 if (ret)
174 return ret;
175
176 ret = data->ops->read(data->dev, MPL115_A0);
174 if (ret < 0) 177 if (ret < 0)
175 return ret; 178 return ret;
176 data->a0 = ret; 179 data->a0 = ret;
177 ret = i2c_smbus_read_word_swapped(data->client, MPL115_B1); 180 ret = data->ops->read(data->dev, MPL115_B1);
178 if (ret < 0) 181 if (ret < 0)
179 return ret; 182 return ret;
180 data->b1 = ret; 183 data->b1 = ret;
181 ret = i2c_smbus_read_word_swapped(data->client, MPL115_B2); 184 ret = data->ops->read(data->dev, MPL115_B2);
182 if (ret < 0) 185 if (ret < 0)
183 return ret; 186 return ret;
184 data->b2 = ret; 187 data->b2 = ret;
185 ret = i2c_smbus_read_word_swapped(data->client, MPL115_C12); 188 ret = data->ops->read(data->dev, MPL115_C12);
186 if (ret < 0) 189 if (ret < 0)
187 return ret; 190 return ret;
188 data->c12 = ret; 191 data->c12 = ret;
189 192
190 return devm_iio_device_register(&client->dev, indio_dev); 193 return devm_iio_device_register(dev, indio_dev);
191} 194}
192 195EXPORT_SYMBOL_GPL(mpl115_probe);
193static const struct i2c_device_id mpl115_id[] = {
194 { "mpl115", 0 },
195 { }
196};
197MODULE_DEVICE_TABLE(i2c, mpl115_id);
198
199static struct i2c_driver mpl115_driver = {
200 .driver = {
201 .name = "mpl115",
202 },
203 .probe = mpl115_probe,
204 .id_table = mpl115_id,
205};
206module_i2c_driver(mpl115_driver);
207 196
208MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); 197MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
209MODULE_DESCRIPTION("Freescale MPL115 pressure/temperature driver"); 198MODULE_DESCRIPTION("Freescale MPL115 pressure/temperature driver");
diff --git a/drivers/iio/pressure/mpl115.h b/drivers/iio/pressure/mpl115.h
new file mode 100644
index 000000000000..01b652774dc3
--- /dev/null
+++ b/drivers/iio/pressure/mpl115.h
@@ -0,0 +1,24 @@
1/*
2 * Freescale MPL115A pressure/temperature sensor
3 *
4 * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
5 * Copyright (c) 2016 Akinobu Mita <akinobu.mita@gmail.com>
6 *
7 * This file is subject to the terms and conditions of version 2 of
8 * the GNU General Public License. See the file COPYING in the main
9 * directory of this archive for more details.
10 */
11
12#ifndef _MPL115_H_
13#define _MPL115_H_
14
15struct mpl115_ops {
16 int (*init)(struct device *);
17 int (*read)(struct device *, u8);
18 int (*write)(struct device *, u8, u8);
19};
20
21int mpl115_probe(struct device *dev, const char *name,
22 const struct mpl115_ops *ops);
23
24#endif
diff --git a/drivers/iio/pressure/mpl115_i2c.c b/drivers/iio/pressure/mpl115_i2c.c
new file mode 100644
index 000000000000..9ea055c3f89e
--- /dev/null
+++ b/drivers/iio/pressure/mpl115_i2c.c
@@ -0,0 +1,67 @@
1/*
2 * Freescale MPL115A2 pressure/temperature sensor
3 *
4 * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
5 *
6 * This file is subject to the terms and conditions of version 2 of
7 * the GNU General Public License. See the file COPYING in the main
8 * directory of this archive for more details.
9 *
10 * (7-bit I2C slave address 0x60)
11 *
12 * Datasheet: http://www.nxp.com/files/sensors/doc/data_sheet/MPL115A2.pdf
13 */
14
15#include <linux/module.h>
16#include <linux/i2c.h>
17
18#include "mpl115.h"
19
20static int mpl115_i2c_init(struct device *dev)
21{
22 return 0;
23}
24
25static int mpl115_i2c_read(struct device *dev, u8 address)
26{
27 return i2c_smbus_read_word_swapped(to_i2c_client(dev), address);
28}
29
30static int mpl115_i2c_write(struct device *dev, u8 address, u8 value)
31{
32 return i2c_smbus_write_byte_data(to_i2c_client(dev), address, value);
33}
34
35static const struct mpl115_ops mpl115_i2c_ops = {
36 .init = mpl115_i2c_init,
37 .read = mpl115_i2c_read,
38 .write = mpl115_i2c_write,
39};
40
41static int mpl115_i2c_probe(struct i2c_client *client,
42 const struct i2c_device_id *id)
43{
44 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
45 return -ENODEV;
46
47 return mpl115_probe(&client->dev, id->name, &mpl115_i2c_ops);
48}
49
50static const struct i2c_device_id mpl115_i2c_id[] = {
51 { "mpl115", 0 },
52 { }
53};
54MODULE_DEVICE_TABLE(i2c, mpl115_i2c_id);
55
56static struct i2c_driver mpl115_i2c_driver = {
57 .driver = {
58 .name = "mpl115",
59 },
60 .probe = mpl115_i2c_probe,
61 .id_table = mpl115_i2c_id,
62};
63module_i2c_driver(mpl115_i2c_driver);
64
65MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
66MODULE_DESCRIPTION("Freescale MPL115A2 pressure/temperature driver");
67MODULE_LICENSE("GPL");
diff --git a/drivers/iio/pressure/mpl115_spi.c b/drivers/iio/pressure/mpl115_spi.c
new file mode 100644
index 000000000000..9ebf55f5b3aa
--- /dev/null
+++ b/drivers/iio/pressure/mpl115_spi.c
@@ -0,0 +1,106 @@
1/*
2 * Freescale MPL115A1 pressure/temperature sensor
3 *
4 * Copyright (c) 2016 Akinobu Mita <akinobu.mita@gmail.com>
5 *
6 * This file is subject to the terms and conditions of version 2 of
7 * the GNU General Public License. See the file COPYING in the main
8 * directory of this archive for more details.
9 *
10 * Datasheet: http://www.nxp.com/files/sensors/doc/data_sheet/MPL115A1.pdf
11 */
12
13#include <linux/module.h>
14#include <linux/spi/spi.h>
15
16#include "mpl115.h"
17
18#define MPL115_SPI_WRITE(address) ((address) << 1)
19#define MPL115_SPI_READ(address) (0x80 | (address) << 1)
20
21struct mpl115_spi_buf {
22 u8 tx[4];
23 u8 rx[4];
24};
25
26static int mpl115_spi_init(struct device *dev)
27{
28 struct spi_device *spi = to_spi_device(dev);
29 struct mpl115_spi_buf *buf;
30
31 buf = devm_kzalloc(dev, sizeof(*buf), GFP_KERNEL);
32 if (!buf)
33 return -ENOMEM;
34
35 spi_set_drvdata(spi, buf);
36
37 return 0;
38}
39
40static int mpl115_spi_read(struct device *dev, u8 address)
41{
42 struct spi_device *spi = to_spi_device(dev);
43 struct mpl115_spi_buf *buf = spi_get_drvdata(spi);
44 struct spi_transfer xfer = {
45 .tx_buf = buf->tx,
46 .rx_buf = buf->rx,
47 .len = 4,
48 };
49 int ret;
50
51 buf->tx[0] = MPL115_SPI_READ(address);
52 buf->tx[2] = MPL115_SPI_READ(address + 1);
53
54 ret = spi_sync_transfer(spi, &xfer, 1);
55 if (ret)
56 return ret;
57
58 return (buf->rx[1] << 8) | buf->rx[3];
59}
60
61static int mpl115_spi_write(struct device *dev, u8 address, u8 value)
62{
63 struct spi_device *spi = to_spi_device(dev);
64 struct mpl115_spi_buf *buf = spi_get_drvdata(spi);
65 struct spi_transfer xfer = {
66 .tx_buf = buf->tx,
67 .len = 2,
68 };
69
70 buf->tx[0] = MPL115_SPI_WRITE(address);
71 buf->tx[1] = value;
72
73 return spi_sync_transfer(spi, &xfer, 1);
74}
75
76static const struct mpl115_ops mpl115_spi_ops = {
77 .init = mpl115_spi_init,
78 .read = mpl115_spi_read,
79 .write = mpl115_spi_write,
80};
81
82static int mpl115_spi_probe(struct spi_device *spi)
83{
84 const struct spi_device_id *id = spi_get_device_id(spi);
85
86 return mpl115_probe(&spi->dev, id->name, &mpl115_spi_ops);
87}
88
89static const struct spi_device_id mpl115_spi_ids[] = {
90 { "mpl115", 0 },
91 {}
92};
93MODULE_DEVICE_TABLE(spi, mpl115_spi_ids);
94
95static struct spi_driver mpl115_spi_driver = {
96 .driver = {
97 .name = "mpl115",
98 },
99 .probe = mpl115_spi_probe,
100 .id_table = mpl115_spi_ids,
101};
102module_spi_driver(mpl115_spi_driver);
103
104MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");
105MODULE_DESCRIPTION("Freescale MPL115A1 pressure/temperature driver");
106MODULE_LICENSE("GPL");