aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio
diff options
context:
space:
mode:
authorTiberiu Breana <tiberiu.a.breana@intel.com>2016-05-16 07:58:23 -0400
committerJonathan Cameron <jic23@kernel.org>2016-05-21 15:06:50 -0400
commit194dc4c714132a63a7a731fe4debeccbdfab13e1 (patch)
tree4cf7bfca5467c807d14c81497f16cacd9151f569 /drivers/iio
parentba35f111aa6f386df33f950aeaea53a2bf040cc2 (diff)
iio: accel: Add triggered buffer support for BMA220
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/accel/bma220_spi.c65
1 files changed, 63 insertions, 2 deletions
diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c
index 7343575e84ba..1098d10df8e8 100644
--- a/drivers/iio/accel/bma220_spi.c
+++ b/drivers/iio/accel/bma220_spi.c
@@ -11,9 +11,12 @@
11#include <linux/acpi.h> 11#include <linux/acpi.h>
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/iio/buffer.h>
14#include <linux/iio/iio.h> 15#include <linux/iio/iio.h>
15#include <linux/iio/sysfs.h> 16#include <linux/iio/sysfs.h>
16#include <linux/spi/spi.h> 17#include <linux/spi/spi.h>
18#include <linux/iio/trigger_consumer.h>
19#include <linux/iio/triggered_buffer.h>
17 20
18#define BMA220_REG_ID 0x00 21#define BMA220_REG_ID 0x00
19#define BMA220_REG_ACCEL_X 0x02 22#define BMA220_REG_ACCEL_X 0x02
@@ -39,8 +42,22 @@
39 .channel2 = IIO_MOD_##axis, \ 42 .channel2 = IIO_MOD_##axis, \
40 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 43 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
41 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 44 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
45 .scan_index = index, \
46 .scan_type = { \
47 .sign = 's', \
48 .realbits = 6, \
49 .storagebits = 8, \
50 .shift = BMA220_DATA_SHIFT, \
51 .endianness = IIO_CPU, \
52 }, \
42} 53}
43 54
55enum bma220_axis {
56 AXIS_X,
57 AXIS_Y,
58 AXIS_Z,
59};
60
44static IIO_CONST_ATTR(in_accel_scale_available, BMA220_SCALE_AVAILABLE); 61static IIO_CONST_ATTR(in_accel_scale_available, BMA220_SCALE_AVAILABLE);
45 62
46static struct attribute *bma220_attributes[] = { 63static struct attribute *bma220_attributes[] = {
@@ -59,6 +76,7 @@ static const int bma220_scale_table[][4] = {
59struct bma220_data { 76struct bma220_data {
60 struct spi_device *spi_device; 77 struct spi_device *spi_device;
61 struct mutex lock; 78 struct mutex lock;
79 s8 buffer[16]; /* 3x8-bit channels + 5x8 padding + 8x8 timestamp */
62 u8 tx_buf[2] ____cacheline_aligned; 80 u8 tx_buf[2] ____cacheline_aligned;
63}; 81};
64 82
@@ -66,6 +84,7 @@ static const struct iio_chan_spec bma220_channels[] = {
66 BMA220_ACCEL_CHANNEL(0, BMA220_REG_ACCEL_X, X), 84 BMA220_ACCEL_CHANNEL(0, BMA220_REG_ACCEL_X, X),
67 BMA220_ACCEL_CHANNEL(1, BMA220_REG_ACCEL_Y, Y), 85 BMA220_ACCEL_CHANNEL(1, BMA220_REG_ACCEL_Y, Y),
68 BMA220_ACCEL_CHANNEL(2, BMA220_REG_ACCEL_Z, Z), 86 BMA220_ACCEL_CHANNEL(2, BMA220_REG_ACCEL_Z, Z),
87 IIO_CHAN_SOFT_TIMESTAMP(3),
69}; 88};
70 89
71static inline int bma220_read_reg(struct spi_device *spi, u8 reg) 90static inline int bma220_read_reg(struct spi_device *spi, u8 reg)
@@ -73,6 +92,35 @@ static inline int bma220_read_reg(struct spi_device *spi, u8 reg)
73 return spi_w8r8(spi, reg | BMA220_READ_MASK); 92 return spi_w8r8(spi, reg | BMA220_READ_MASK);
74} 93}
75 94
95static const unsigned long bma220_accel_scan_masks[] = {
96 BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
97 0
98};
99
100static irqreturn_t bma220_trigger_handler(int irq, void *p)
101{
102 int ret;
103 struct iio_poll_func *pf = p;
104 struct iio_dev *indio_dev = pf->indio_dev;
105 struct bma220_data *data = iio_priv(indio_dev);
106 struct spi_device *spi = data->spi_device;
107
108 mutex_lock(&data->lock);
109 data->tx_buf[0] = BMA220_REG_ACCEL_X | BMA220_READ_MASK;
110 ret = spi_write_then_read(spi, data->tx_buf, 1, data->buffer,
111 ARRAY_SIZE(bma220_channels) - 1);
112 if (ret < 0)
113 goto err;
114
115 iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
116 pf->timestamp);
117err:
118 mutex_unlock(&data->lock);
119 iio_trigger_notify_done(indio_dev->trig);
120
121 return IRQ_HANDLED;
122}
123
76static int bma220_read_raw(struct iio_dev *indio_dev, 124static int bma220_read_raw(struct iio_dev *indio_dev,
77 struct iio_chan_spec const *chan, 125 struct iio_chan_spec const *chan,
78 int *val, int *val2, long mask) 126 int *val, int *val2, long mask)
@@ -199,18 +247,30 @@ static int bma220_probe(struct spi_device *spi)
199 indio_dev->modes = INDIO_DIRECT_MODE; 247 indio_dev->modes = INDIO_DIRECT_MODE;
200 indio_dev->channels = bma220_channels; 248 indio_dev->channels = bma220_channels;
201 indio_dev->num_channels = ARRAY_SIZE(bma220_channels); 249 indio_dev->num_channels = ARRAY_SIZE(bma220_channels);
250 indio_dev->available_scan_masks = bma220_accel_scan_masks;
202 251
203 ret = bma220_init(data->spi_device); 252 ret = bma220_init(data->spi_device);
204 if (ret < 0) 253 if (ret < 0)
205 return ret; 254 return ret;
206 255
256 ret = iio_triggered_buffer_setup(indio_dev, NULL,
257 bma220_trigger_handler, NULL);
258 if (ret < 0) {
259 dev_err(&spi->dev, "iio triggered buffer setup failed\n");
260 goto err_suspend;
261 }
262
207 ret = iio_device_register(indio_dev); 263 ret = iio_device_register(indio_dev);
208 if (ret < 0) { 264 if (ret < 0) {
209 dev_err(&spi->dev, "iio_device_register failed\n"); 265 dev_err(&spi->dev, "iio_device_register failed\n");
210 return bma220_deinit(spi); 266 iio_triggered_buffer_cleanup(indio_dev);
267 goto err_suspend;
211 } 268 }
212 269
213 return ret; 270 return 0;
271
272err_suspend:
273 return bma220_deinit(spi);
214} 274}
215 275
216static int bma220_remove(struct spi_device *spi) 276static int bma220_remove(struct spi_device *spi)
@@ -218,6 +278,7 @@ static int bma220_remove(struct spi_device *spi)
218 struct iio_dev *indio_dev = spi_get_drvdata(spi); 278 struct iio_dev *indio_dev = spi_get_drvdata(spi);
219 279
220 iio_device_unregister(indio_dev); 280 iio_device_unregister(indio_dev);
281 iio_triggered_buffer_cleanup(indio_dev);
221 282
222 return bma220_deinit(spi); 283 return bma220_deinit(spi);
223} 284}