aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio
diff options
context:
space:
mode:
authorTiberiu Breana <tiberiu.a.breana@intel.com>2016-04-18 10:50:44 -0400
committerJonathan Cameron <jic23@kernel.org>2016-04-24 05:00:20 -0400
commit0d96d5ead3f7f1303a6a445051f29bba7c7f4e47 (patch)
tree05755b01d4b577a1e9e412e6d7d06f4875dba699 /drivers/iio
parent366a3270c1c5ce0a12d1451e2e2e6341385c331d (diff)
iio: humidity: Add triggered buffer support for AM2315
Signed-off-by: Tiberiu Breana <tiberiu.a.breana@intel.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r--drivers/iio/humidity/am2315.c81
1 files changed, 78 insertions, 3 deletions
diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c
index d392fc8a9d16..3be6d209a159 100644
--- a/drivers/iio/humidity/am2315.c
+++ b/drivers/iio/humidity/am2315.c
@@ -15,8 +15,11 @@
15#include <linux/i2c.h> 15#include <linux/i2c.h>
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/module.h> 17#include <linux/module.h>
18#include <linux/iio/buffer.h>
18#include <linux/iio/iio.h> 19#include <linux/iio/iio.h>
19#include <linux/iio/sysfs.h> 20#include <linux/iio/sysfs.h>
21#include <linux/iio/trigger_consumer.h>
22#include <linux/iio/triggered_buffer.h>
20 23
21#define AM2315_REG_HUM_MSB 0x00 24#define AM2315_REG_HUM_MSB 0x00
22#define AM2315_REG_HUM_LSB 0x01 25#define AM2315_REG_HUM_LSB 0x01
@@ -26,12 +29,14 @@
26#define AM2315_FUNCTION_READ 0x03 29#define AM2315_FUNCTION_READ 0x03
27#define AM2315_HUM_OFFSET 2 30#define AM2315_HUM_OFFSET 2
28#define AM2315_TEMP_OFFSET 4 31#define AM2315_TEMP_OFFSET 4
32#define AM2315_ALL_CHANNEL_MASK GENMASK(1, 0)
29 33
30#define AM2315_DRIVER_NAME "am2315" 34#define AM2315_DRIVER_NAME "am2315"
31 35
32struct am2315_data { 36struct am2315_data {
33 struct i2c_client *client; 37 struct i2c_client *client;
34 struct mutex lock; 38 struct mutex lock;
39 s16 buffer[8]; /* 2x16-bit channels + 2x16 padding + 4x16 timestamp */
35}; 40};
36 41
37struct am2315_sensor_data { 42struct am2315_sensor_data {
@@ -43,13 +48,28 @@ static const struct iio_chan_spec am2315_channels[] = {
43 { 48 {
44 .type = IIO_HUMIDITYRELATIVE, 49 .type = IIO_HUMIDITYRELATIVE,
45 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 50 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
46 BIT(IIO_CHAN_INFO_SCALE) 51 BIT(IIO_CHAN_INFO_SCALE),
52 .scan_index = 0,
53 .scan_type = {
54 .sign = 's',
55 .realbits = 16,
56 .storagebits = 16,
57 .endianness = IIO_CPU,
58 },
47 }, 59 },
48 { 60 {
49 .type = IIO_TEMP, 61 .type = IIO_TEMP,
50 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 62 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
51 BIT(IIO_CHAN_INFO_SCALE) 63 BIT(IIO_CHAN_INFO_SCALE),
64 .scan_index = 1,
65 .scan_type = {
66 .sign = 's',
67 .realbits = 16,
68 .storagebits = 16,
69 .endianness = IIO_CPU,
70 },
52 }, 71 },
72 IIO_CHAN_SOFT_TIMESTAMP(2),
53}; 73};
54 74
55/* CRC calculation algorithm, as specified in the datasheet (page 13). */ 75/* CRC calculation algorithm, as specified in the datasheet (page 13). */
@@ -134,6 +154,44 @@ exit_unlock:
134 return ret; 154 return ret;
135} 155}
136 156
157static irqreturn_t am2315_trigger_handler(int irq, void *p)
158{
159 int i;
160 int ret;
161 int bit;
162 struct iio_poll_func *pf = p;
163 struct iio_dev *indio_dev = pf->indio_dev;
164 struct am2315_data *data = iio_priv(indio_dev);
165 struct am2315_sensor_data sensor_data;
166
167 ret = am2315_read_data(data, &sensor_data);
168 if (ret < 0) {
169 mutex_unlock(&data->lock);
170 goto err;
171 }
172
173 mutex_lock(&data->lock);
174 if (*(indio_dev->active_scan_mask) == AM2315_ALL_CHANNEL_MASK) {
175 data->buffer[0] = sensor_data.hum_data;
176 data->buffer[1] = sensor_data.temp_data;
177 } else {
178 i = 0;
179 for_each_set_bit(bit, indio_dev->active_scan_mask,
180 indio_dev->masklength) {
181 data->buffer[i] = (bit ? sensor_data.temp_data :
182 sensor_data.hum_data);
183 i++;
184 }
185 }
186 mutex_unlock(&data->lock);
187
188 iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
189 pf->timestamp);
190err:
191 iio_trigger_notify_done(indio_dev->trig);
192 return IRQ_HANDLED;
193}
194
137static int am2315_read_raw(struct iio_dev *indio_dev, 195static int am2315_read_raw(struct iio_dev *indio_dev,
138 struct iio_chan_spec const *chan, 196 struct iio_chan_spec const *chan,
139 int *val, int *val2, long mask) 197 int *val, int *val2, long mask)
@@ -166,6 +224,7 @@ static const struct iio_info am2315_info = {
166static int am2315_probe(struct i2c_client *client, 224static int am2315_probe(struct i2c_client *client,
167 const struct i2c_device_id *id) 225 const struct i2c_device_id *id)
168{ 226{
227 int ret;
169 struct iio_dev *indio_dev; 228 struct iio_dev *indio_dev;
170 struct am2315_data *data; 229 struct am2315_data *data;
171 230
@@ -187,7 +246,22 @@ static int am2315_probe(struct i2c_client *client,
187 indio_dev->channels = am2315_channels; 246 indio_dev->channels = am2315_channels;
188 indio_dev->num_channels = ARRAY_SIZE(am2315_channels); 247 indio_dev->num_channels = ARRAY_SIZE(am2315_channels);
189 248
190 return iio_device_register(indio_dev); 249 ret = iio_triggered_buffer_setup(indio_dev, NULL,
250 am2315_trigger_handler, NULL);
251 if (ret < 0) {
252 dev_err(&client->dev, "iio triggered buffer setup failed\n");
253 return ret;
254 }
255
256 ret = iio_device_register(indio_dev);
257 if (ret < 0)
258 goto err_buffer_cleanup;
259
260 return 0;
261
262err_buffer_cleanup:
263 iio_triggered_buffer_cleanup(indio_dev);
264 return ret;
191} 265}
192 266
193static int am2315_remove(struct i2c_client *client) 267static int am2315_remove(struct i2c_client *client)
@@ -195,6 +269,7 @@ static int am2315_remove(struct i2c_client *client)
195 struct iio_dev *indio_dev = i2c_get_clientdata(client); 269 struct iio_dev *indio_dev = i2c_get_clientdata(client);
196 270
197 iio_device_unregister(indio_dev); 271 iio_device_unregister(indio_dev);
272 iio_triggered_buffer_cleanup(indio_dev);
198 273
199 return 0; 274 return 0;
200} 275}