136edc939SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2cc26ad45SPeter Meerwald /*
3cc26ad45SPeter Meerwald * mpl3115.c - Support for Freescale MPL3115A2 pressure/temperature sensor
4cc26ad45SPeter Meerwald *
5cc26ad45SPeter Meerwald * Copyright (c) 2013 Peter Meerwald <pmeerw@pmeerw.net>
6cc26ad45SPeter Meerwald *
7cc26ad45SPeter Meerwald * (7-bit I2C slave address 0x60)
8cc26ad45SPeter Meerwald *
9cc26ad45SPeter Meerwald * TODO: FIFO buffer, altimeter mode, oversampling, continuous mode,
10cc26ad45SPeter Meerwald * interrupts, user offset correction, raw mode
11cc26ad45SPeter Meerwald */
12cc26ad45SPeter Meerwald
13cc26ad45SPeter Meerwald #include <linux/module.h>
14cc26ad45SPeter Meerwald #include <linux/i2c.h>
15cc26ad45SPeter Meerwald #include <linux/iio/iio.h>
16cc26ad45SPeter Meerwald #include <linux/iio/sysfs.h>
17cc26ad45SPeter Meerwald #include <linux/iio/trigger_consumer.h>
18cc26ad45SPeter Meerwald #include <linux/iio/buffer.h>
19cc26ad45SPeter Meerwald #include <linux/iio/triggered_buffer.h>
20cc26ad45SPeter Meerwald #include <linux/delay.h>
21cc26ad45SPeter Meerwald
22cc26ad45SPeter Meerwald #define MPL3115_STATUS 0x00
23cc26ad45SPeter Meerwald #define MPL3115_OUT_PRESS 0x01 /* MSB first, 20 bit */
24cc26ad45SPeter Meerwald #define MPL3115_OUT_TEMP 0x04 /* MSB first, 12 bit */
25cc26ad45SPeter Meerwald #define MPL3115_WHO_AM_I 0x0c
26cc26ad45SPeter Meerwald #define MPL3115_CTRL_REG1 0x26
27cc26ad45SPeter Meerwald
28cc26ad45SPeter Meerwald #define MPL3115_DEVICE_ID 0xc4
29cc26ad45SPeter Meerwald
30cc26ad45SPeter Meerwald #define MPL3115_STATUS_PRESS_RDY BIT(2)
31cc26ad45SPeter Meerwald #define MPL3115_STATUS_TEMP_RDY BIT(1)
32cc26ad45SPeter Meerwald
33cc26ad45SPeter Meerwald #define MPL3115_CTRL_RESET BIT(2) /* software reset */
34cc26ad45SPeter Meerwald #define MPL3115_CTRL_OST BIT(1) /* initiate measurement */
35cc26ad45SPeter Meerwald #define MPL3115_CTRL_ACTIVE BIT(0) /* continuous measurement */
36cc26ad45SPeter Meerwald #define MPL3115_CTRL_OS_258MS (BIT(5) | BIT(4)) /* 64x oversampling */
37cc26ad45SPeter Meerwald
38cc26ad45SPeter Meerwald struct mpl3115_data {
39cc26ad45SPeter Meerwald struct i2c_client *client;
40cc26ad45SPeter Meerwald struct mutex lock;
41cc26ad45SPeter Meerwald u8 ctrl_reg1;
42cc26ad45SPeter Meerwald };
43cc26ad45SPeter Meerwald
mpl3115_request(struct mpl3115_data * data)44cc26ad45SPeter Meerwald static int mpl3115_request(struct mpl3115_data *data)
45cc26ad45SPeter Meerwald {
46cc26ad45SPeter Meerwald int ret, tries = 15;
47cc26ad45SPeter Meerwald
48cc26ad45SPeter Meerwald /* trigger measurement */
49cc26ad45SPeter Meerwald ret = i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1,
50cc26ad45SPeter Meerwald data->ctrl_reg1 | MPL3115_CTRL_OST);
51cc26ad45SPeter Meerwald if (ret < 0)
52cc26ad45SPeter Meerwald return ret;
53cc26ad45SPeter Meerwald
54cc26ad45SPeter Meerwald while (tries-- > 0) {
55cc26ad45SPeter Meerwald ret = i2c_smbus_read_byte_data(data->client, MPL3115_CTRL_REG1);
56cc26ad45SPeter Meerwald if (ret < 0)
57cc26ad45SPeter Meerwald return ret;
58cc26ad45SPeter Meerwald /* wait for data ready, i.e. OST cleared */
59cc26ad45SPeter Meerwald if (!(ret & MPL3115_CTRL_OST))
60cc26ad45SPeter Meerwald break;
61cc26ad45SPeter Meerwald msleep(20);
62cc26ad45SPeter Meerwald }
63cc26ad45SPeter Meerwald
64cc26ad45SPeter Meerwald if (tries < 0) {
65cc26ad45SPeter Meerwald dev_err(&data->client->dev, "data not ready\n");
66cc26ad45SPeter Meerwald return -EIO;
67cc26ad45SPeter Meerwald }
68cc26ad45SPeter Meerwald
69cc26ad45SPeter Meerwald return 0;
70cc26ad45SPeter Meerwald }
71cc26ad45SPeter Meerwald
mpl3115_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)72cc26ad45SPeter Meerwald static int mpl3115_read_raw(struct iio_dev *indio_dev,
73cc26ad45SPeter Meerwald struct iio_chan_spec const *chan,
74cc26ad45SPeter Meerwald int *val, int *val2, long mask)
75cc26ad45SPeter Meerwald {
76cc26ad45SPeter Meerwald struct mpl3115_data *data = iio_priv(indio_dev);
77cc26ad45SPeter Meerwald int ret;
78cc26ad45SPeter Meerwald
79cc26ad45SPeter Meerwald switch (mask) {
80cc26ad45SPeter Meerwald case IIO_CHAN_INFO_RAW:
81ac139805SAlison Schofield ret = iio_device_claim_direct_mode(indio_dev);
82ac139805SAlison Schofield if (ret)
83ac139805SAlison Schofield return ret;
84cc26ad45SPeter Meerwald
85cc26ad45SPeter Meerwald switch (chan->type) {
867721c73dSGwendal Grignou case IIO_PRESSURE: { /* in 0.25 pascal / LSB */
877721c73dSGwendal Grignou __be32 tmp = 0;
887721c73dSGwendal Grignou
89cc26ad45SPeter Meerwald mutex_lock(&data->lock);
90cc26ad45SPeter Meerwald ret = mpl3115_request(data);
91cc26ad45SPeter Meerwald if (ret < 0) {
92cc26ad45SPeter Meerwald mutex_unlock(&data->lock);
93ac139805SAlison Schofield break;
94cc26ad45SPeter Meerwald }
95cc26ad45SPeter Meerwald ret = i2c_smbus_read_i2c_block_data(data->client,
96cc26ad45SPeter Meerwald MPL3115_OUT_PRESS, 3, (u8 *) &tmp);
97cc26ad45SPeter Meerwald mutex_unlock(&data->lock);
98cc26ad45SPeter Meerwald if (ret < 0)
99ac139805SAlison Schofield break;
1007721c73dSGwendal Grignou *val = be32_to_cpu(tmp) >> chan->scan_type.shift;
101ac139805SAlison Schofield ret = IIO_VAL_INT;
102ac139805SAlison Schofield break;
1037721c73dSGwendal Grignou }
1047721c73dSGwendal Grignou case IIO_TEMP: { /* in 0.0625 celsius / LSB */
1057721c73dSGwendal Grignou __be16 tmp;
1067721c73dSGwendal Grignou
107cc26ad45SPeter Meerwald mutex_lock(&data->lock);
108cc26ad45SPeter Meerwald ret = mpl3115_request(data);
109cc26ad45SPeter Meerwald if (ret < 0) {
110cc26ad45SPeter Meerwald mutex_unlock(&data->lock);
111ac139805SAlison Schofield break;
112cc26ad45SPeter Meerwald }
113cc26ad45SPeter Meerwald ret = i2c_smbus_read_i2c_block_data(data->client,
114cc26ad45SPeter Meerwald MPL3115_OUT_TEMP, 2, (u8 *) &tmp);
115cc26ad45SPeter Meerwald mutex_unlock(&data->lock);
116cc26ad45SPeter Meerwald if (ret < 0)
117ac139805SAlison Schofield break;
1187721c73dSGwendal Grignou *val = sign_extend32(be16_to_cpu(tmp) >> chan->scan_type.shift,
1197721c73dSGwendal Grignou chan->scan_type.realbits - 1);
120ac139805SAlison Schofield ret = IIO_VAL_INT;
121ac139805SAlison Schofield break;
1227721c73dSGwendal Grignou }
123cc26ad45SPeter Meerwald default:
124ac139805SAlison Schofield ret = -EINVAL;
125ac139805SAlison Schofield break;
126cc26ad45SPeter Meerwald }
127ac139805SAlison Schofield
128ac139805SAlison Schofield iio_device_release_direct_mode(indio_dev);
129ac139805SAlison Schofield return ret;
130ac139805SAlison Schofield
131cc26ad45SPeter Meerwald case IIO_CHAN_INFO_SCALE:
132cc26ad45SPeter Meerwald switch (chan->type) {
133cc26ad45SPeter Meerwald case IIO_PRESSURE:
134cc26ad45SPeter Meerwald *val = 0;
135cc26ad45SPeter Meerwald *val2 = 250; /* want kilopascal */
136cc26ad45SPeter Meerwald return IIO_VAL_INT_PLUS_MICRO;
137cc26ad45SPeter Meerwald case IIO_TEMP:
138cc26ad45SPeter Meerwald *val = 0;
139cc26ad45SPeter Meerwald *val2 = 62500;
140cc26ad45SPeter Meerwald return IIO_VAL_INT_PLUS_MICRO;
141cc26ad45SPeter Meerwald default:
142cc26ad45SPeter Meerwald return -EINVAL;
143cc26ad45SPeter Meerwald }
144cc26ad45SPeter Meerwald }
145cc26ad45SPeter Meerwald return -EINVAL;
146cc26ad45SPeter Meerwald }
147cc26ad45SPeter Meerwald
mpl3115_trigger_handler(int irq,void * p)148cc26ad45SPeter Meerwald static irqreturn_t mpl3115_trigger_handler(int irq, void *p)
149cc26ad45SPeter Meerwald {
150cc26ad45SPeter Meerwald struct iio_poll_func *pf = p;
151cc26ad45SPeter Meerwald struct iio_dev *indio_dev = pf->indio_dev;
152cc26ad45SPeter Meerwald struct mpl3115_data *data = iio_priv(indio_dev);
153198cf32fSJonathan Cameron /*
154198cf32fSJonathan Cameron * 32-bit channel + 16-bit channel + padding + ts
155198cf32fSJonathan Cameron * Note that it is possible for only one of the first 2
156198cf32fSJonathan Cameron * channels to be enabled. If that happens, the first element
157198cf32fSJonathan Cameron * of the buffer may be either 16 or 32-bits. As such we cannot
158198cf32fSJonathan Cameron * use a simple structure definition to express this data layout.
159198cf32fSJonathan Cameron */
160198cf32fSJonathan Cameron u8 buffer[16] __aligned(8);
161cc26ad45SPeter Meerwald int ret, pos = 0;
162cc26ad45SPeter Meerwald
163cc26ad45SPeter Meerwald mutex_lock(&data->lock);
164cc26ad45SPeter Meerwald ret = mpl3115_request(data);
165cc26ad45SPeter Meerwald if (ret < 0) {
166cc26ad45SPeter Meerwald mutex_unlock(&data->lock);
167cc26ad45SPeter Meerwald goto done;
168cc26ad45SPeter Meerwald }
169cc26ad45SPeter Meerwald
170cc26ad45SPeter Meerwald memset(buffer, 0, sizeof(buffer));
171cc26ad45SPeter Meerwald if (test_bit(0, indio_dev->active_scan_mask)) {
172cc26ad45SPeter Meerwald ret = i2c_smbus_read_i2c_block_data(data->client,
173cc26ad45SPeter Meerwald MPL3115_OUT_PRESS, 3, &buffer[pos]);
174cc26ad45SPeter Meerwald if (ret < 0) {
175cc26ad45SPeter Meerwald mutex_unlock(&data->lock);
176cc26ad45SPeter Meerwald goto done;
177cc26ad45SPeter Meerwald }
178cc26ad45SPeter Meerwald pos += 4;
179cc26ad45SPeter Meerwald }
180cc26ad45SPeter Meerwald
181cc26ad45SPeter Meerwald if (test_bit(1, indio_dev->active_scan_mask)) {
182cc26ad45SPeter Meerwald ret = i2c_smbus_read_i2c_block_data(data->client,
183cc26ad45SPeter Meerwald MPL3115_OUT_TEMP, 2, &buffer[pos]);
184cc26ad45SPeter Meerwald if (ret < 0) {
185cc26ad45SPeter Meerwald mutex_unlock(&data->lock);
186cc26ad45SPeter Meerwald goto done;
187cc26ad45SPeter Meerwald }
188cc26ad45SPeter Meerwald }
189cc26ad45SPeter Meerwald mutex_unlock(&data->lock);
190cc26ad45SPeter Meerwald
191cc26ad45SPeter Meerwald iio_push_to_buffers_with_timestamp(indio_dev, buffer,
192bc2b7dabSGregor Boirie iio_get_time_ns(indio_dev));
193cc26ad45SPeter Meerwald
194cc26ad45SPeter Meerwald done:
195cc26ad45SPeter Meerwald iio_trigger_notify_done(indio_dev->trig);
196cc26ad45SPeter Meerwald return IRQ_HANDLED;
197cc26ad45SPeter Meerwald }
198cc26ad45SPeter Meerwald
199cc26ad45SPeter Meerwald static const struct iio_chan_spec mpl3115_channels[] = {
200cc26ad45SPeter Meerwald {
201cc26ad45SPeter Meerwald .type = IIO_PRESSURE,
202cc26ad45SPeter Meerwald .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
2039cf6cdbaSPeter Rosin .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
204cc26ad45SPeter Meerwald .scan_index = 0,
205cc26ad45SPeter Meerwald .scan_type = {
206d29f5929SPeter Meerwald .sign = 'u',
207cc26ad45SPeter Meerwald .realbits = 20,
208cc26ad45SPeter Meerwald .storagebits = 32,
209cc26ad45SPeter Meerwald .shift = 12,
210cc26ad45SPeter Meerwald .endianness = IIO_BE,
211cc26ad45SPeter Meerwald }
212cc26ad45SPeter Meerwald },
213cc26ad45SPeter Meerwald {
214cc26ad45SPeter Meerwald .type = IIO_TEMP,
215cc26ad45SPeter Meerwald .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
2169cf6cdbaSPeter Rosin .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
217cc26ad45SPeter Meerwald .scan_index = 1,
218cc26ad45SPeter Meerwald .scan_type = {
219cc26ad45SPeter Meerwald .sign = 's',
220cc26ad45SPeter Meerwald .realbits = 12,
221cc26ad45SPeter Meerwald .storagebits = 16,
222cc26ad45SPeter Meerwald .shift = 4,
223cc26ad45SPeter Meerwald .endianness = IIO_BE,
224cc26ad45SPeter Meerwald }
225cc26ad45SPeter Meerwald },
226cc26ad45SPeter Meerwald IIO_CHAN_SOFT_TIMESTAMP(2),
227cc26ad45SPeter Meerwald };
228cc26ad45SPeter Meerwald
229cc26ad45SPeter Meerwald static const struct iio_info mpl3115_info = {
230cc26ad45SPeter Meerwald .read_raw = &mpl3115_read_raw,
231cc26ad45SPeter Meerwald };
232cc26ad45SPeter Meerwald
mpl3115_probe(struct i2c_client * client)2330586ce78SUwe Kleine-König static int mpl3115_probe(struct i2c_client *client)
234cc26ad45SPeter Meerwald {
2350586ce78SUwe Kleine-König const struct i2c_device_id *id = i2c_client_get_device_id(client);
236cc26ad45SPeter Meerwald struct mpl3115_data *data;
237cc26ad45SPeter Meerwald struct iio_dev *indio_dev;
238cc26ad45SPeter Meerwald int ret;
239cc26ad45SPeter Meerwald
240cc26ad45SPeter Meerwald ret = i2c_smbus_read_byte_data(client, MPL3115_WHO_AM_I);
241cc26ad45SPeter Meerwald if (ret < 0)
242cc26ad45SPeter Meerwald return ret;
243cc26ad45SPeter Meerwald if (ret != MPL3115_DEVICE_ID)
244cc26ad45SPeter Meerwald return -ENODEV;
245cc26ad45SPeter Meerwald
246cc26ad45SPeter Meerwald indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
247cc26ad45SPeter Meerwald if (!indio_dev)
248cc26ad45SPeter Meerwald return -ENOMEM;
249cc26ad45SPeter Meerwald
250cc26ad45SPeter Meerwald data = iio_priv(indio_dev);
251cc26ad45SPeter Meerwald data->client = client;
252cc26ad45SPeter Meerwald mutex_init(&data->lock);
253cc26ad45SPeter Meerwald
254cc26ad45SPeter Meerwald i2c_set_clientdata(client, indio_dev);
255cc26ad45SPeter Meerwald indio_dev->info = &mpl3115_info;
256cc26ad45SPeter Meerwald indio_dev->name = id->name;
257cc26ad45SPeter Meerwald indio_dev->modes = INDIO_DIRECT_MODE;
258cc26ad45SPeter Meerwald indio_dev->channels = mpl3115_channels;
259cc26ad45SPeter Meerwald indio_dev->num_channels = ARRAY_SIZE(mpl3115_channels);
260cc26ad45SPeter Meerwald
261cc26ad45SPeter Meerwald /* software reset, I2C transfer is aborted (fails) */
262cc26ad45SPeter Meerwald i2c_smbus_write_byte_data(client, MPL3115_CTRL_REG1,
263cc26ad45SPeter Meerwald MPL3115_CTRL_RESET);
264cc26ad45SPeter Meerwald msleep(50);
265cc26ad45SPeter Meerwald
266cc26ad45SPeter Meerwald data->ctrl_reg1 = MPL3115_CTRL_OS_258MS;
267cc26ad45SPeter Meerwald ret = i2c_smbus_write_byte_data(client, MPL3115_CTRL_REG1,
268cc26ad45SPeter Meerwald data->ctrl_reg1);
269cc26ad45SPeter Meerwald if (ret < 0)
270cc26ad45SPeter Meerwald return ret;
271cc26ad45SPeter Meerwald
272cc26ad45SPeter Meerwald ret = iio_triggered_buffer_setup(indio_dev, NULL,
273cc26ad45SPeter Meerwald mpl3115_trigger_handler, NULL);
274cc26ad45SPeter Meerwald if (ret < 0)
275cc26ad45SPeter Meerwald return ret;
276cc26ad45SPeter Meerwald
277cc26ad45SPeter Meerwald ret = iio_device_register(indio_dev);
278cc26ad45SPeter Meerwald if (ret < 0)
279cc26ad45SPeter Meerwald goto buffer_cleanup;
280cc26ad45SPeter Meerwald return 0;
281cc26ad45SPeter Meerwald
282cc26ad45SPeter Meerwald buffer_cleanup:
283cc26ad45SPeter Meerwald iio_triggered_buffer_cleanup(indio_dev);
284cc26ad45SPeter Meerwald return ret;
285cc26ad45SPeter Meerwald }
286cc26ad45SPeter Meerwald
mpl3115_standby(struct mpl3115_data * data)287cc26ad45SPeter Meerwald static int mpl3115_standby(struct mpl3115_data *data)
288cc26ad45SPeter Meerwald {
289cc26ad45SPeter Meerwald return i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1,
290cc26ad45SPeter Meerwald data->ctrl_reg1 & ~MPL3115_CTRL_ACTIVE);
291cc26ad45SPeter Meerwald }
292cc26ad45SPeter Meerwald
mpl3115_remove(struct i2c_client * client)293ed5c2f5fSUwe Kleine-König static void mpl3115_remove(struct i2c_client *client)
294cc26ad45SPeter Meerwald {
295cc26ad45SPeter Meerwald struct iio_dev *indio_dev = i2c_get_clientdata(client);
296cc26ad45SPeter Meerwald
297cc26ad45SPeter Meerwald iio_device_unregister(indio_dev);
298cc26ad45SPeter Meerwald iio_triggered_buffer_cleanup(indio_dev);
299cc26ad45SPeter Meerwald mpl3115_standby(iio_priv(indio_dev));
300cc26ad45SPeter Meerwald }
301cc26ad45SPeter Meerwald
mpl3115_suspend(struct device * dev)302cc26ad45SPeter Meerwald static int mpl3115_suspend(struct device *dev)
303cc26ad45SPeter Meerwald {
304cc26ad45SPeter Meerwald return mpl3115_standby(iio_priv(i2c_get_clientdata(
305cc26ad45SPeter Meerwald to_i2c_client(dev))));
306cc26ad45SPeter Meerwald }
307cc26ad45SPeter Meerwald
mpl3115_resume(struct device * dev)308cc26ad45SPeter Meerwald static int mpl3115_resume(struct device *dev)
309cc26ad45SPeter Meerwald {
310cc26ad45SPeter Meerwald struct mpl3115_data *data = iio_priv(i2c_get_clientdata(
311cc26ad45SPeter Meerwald to_i2c_client(dev)));
312cc26ad45SPeter Meerwald
313cc26ad45SPeter Meerwald return i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1,
314cc26ad45SPeter Meerwald data->ctrl_reg1);
315cc26ad45SPeter Meerwald }
316cc26ad45SPeter Meerwald
317902b291fSJonathan Cameron static DEFINE_SIMPLE_DEV_PM_OPS(mpl3115_pm_ops, mpl3115_suspend,
318902b291fSJonathan Cameron mpl3115_resume);
319cc26ad45SPeter Meerwald
320cc26ad45SPeter Meerwald static const struct i2c_device_id mpl3115_id[] = {
321cc26ad45SPeter Meerwald { "mpl3115", 0 },
322cc26ad45SPeter Meerwald { }
323cc26ad45SPeter Meerwald };
324cc26ad45SPeter Meerwald MODULE_DEVICE_TABLE(i2c, mpl3115_id);
325cc26ad45SPeter Meerwald
32677496c07SJavier Martinez Canillas static const struct of_device_id mpl3115_of_match[] = {
32777496c07SJavier Martinez Canillas { .compatible = "fsl,mpl3115" },
32877496c07SJavier Martinez Canillas { }
32977496c07SJavier Martinez Canillas };
33077496c07SJavier Martinez Canillas MODULE_DEVICE_TABLE(of, mpl3115_of_match);
33177496c07SJavier Martinez Canillas
332cc26ad45SPeter Meerwald static struct i2c_driver mpl3115_driver = {
333cc26ad45SPeter Meerwald .driver = {
334cc26ad45SPeter Meerwald .name = "mpl3115",
33577496c07SJavier Martinez Canillas .of_match_table = mpl3115_of_match,
336902b291fSJonathan Cameron .pm = pm_sleep_ptr(&mpl3115_pm_ops),
337cc26ad45SPeter Meerwald },
338*7cf15f42SUwe Kleine-König .probe = mpl3115_probe,
339cc26ad45SPeter Meerwald .remove = mpl3115_remove,
340cc26ad45SPeter Meerwald .id_table = mpl3115_id,
341cc26ad45SPeter Meerwald };
342cc26ad45SPeter Meerwald module_i2c_driver(mpl3115_driver);
343cc26ad45SPeter Meerwald
344cc26ad45SPeter Meerwald MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
345cc26ad45SPeter Meerwald MODULE_DESCRIPTION("Freescale MPL3115 pressure/temperature driver");
346cc26ad45SPeter Meerwald MODULE_LICENSE("GPL");
347