staging: iio: push the main buffer chrdev down to the top level.
[deliverable/linux.git] / drivers / staging / iio / accel / lis3l02dq_core.c
CommitLineData
66533b48
JC
1/*
2 * lis3l02dq.c support STMicroelectronics LISD02DQ
3 * 3d 2g Linear Accelerometers via SPI
4 *
5 * Copyright (c) 2007 Jonathan Cameron <jic23@cam.ac.uk>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * Settings:
12 * 16 bit left justified mode used.
13 */
14
15#include <linux/interrupt.h>
16#include <linux/irq.h>
17#include <linux/gpio.h>
66533b48
JC
18#include <linux/mutex.h>
19#include <linux/device.h>
20#include <linux/kernel.h>
21#include <linux/spi/spi.h>
5a0e3ad6 22#include <linux/slab.h>
66533b48 23#include <linux/sysfs.h>
99c97852 24#include <linux/module.h>
66533b48
JC
25
26#include "../iio.h"
27#include "../sysfs.h"
2662051e 28#include "../ring_generic.h"
73bce12e 29
66533b48
JC
30#include "lis3l02dq.h"
31
32/* At the moment the spi framework doesn't allow global setting of cs_change.
33 * It's in the likely to be added comment at the top of spi.h.
34 * This means that use cannot be made of spi_write etc.
35 */
d731aea0
JC
36/* direct copy of the irq_default_primary_handler */
37#ifndef CONFIG_IIO_RING_BUFFER
38static irqreturn_t lis3l02dq_noring(int irq, void *private)
39{
40 return IRQ_WAKE_THREAD;
41}
42#endif
66533b48 43
1b076b52
JC
44/**
45 * lis3l02dq_spi_read_reg_8() - read single byte from a single register
46 * @indio_dev: iio_dev for this actual device
47 * @reg_address: the address of the register to be read
48 * @val: pass back the resulting value
49 **/
50int lis3l02dq_spi_read_reg_8(struct iio_dev *indio_dev,
51 u8 reg_address, u8 *val)
66533b48 52{
7b2fdd19 53 struct lis3l02dq_state *st = iio_priv(indio_dev);
66533b48 54 struct spi_message msg;
f3736416 55 int ret;
66533b48
JC
56 struct spi_transfer xfer = {
57 .tx_buf = st->tx,
58 .rx_buf = st->rx,
59 .bits_per_word = 8,
60 .len = 2,
66533b48
JC
61 };
62
63 mutex_lock(&st->buf_lock);
64 st->tx[0] = LIS3L02DQ_READ_REG(reg_address);
65 st->tx[1] = 0;
66
67 spi_message_init(&msg);
68 spi_message_add_tail(&xfer, &msg);
69 ret = spi_sync(st->us, &msg);
70 *val = st->rx[1];
71 mutex_unlock(&st->buf_lock);
72
73 return ret;
74}
75
76/**
77 * lis3l02dq_spi_write_reg_8() - write single byte to a register
1b076b52 78 * @indio_dev: iio_dev for this device
25985edc 79 * @reg_address: the address of the register to be written
66533b48
JC
80 * @val: the value to write
81 **/
1b076b52 82int lis3l02dq_spi_write_reg_8(struct iio_dev *indio_dev,
66533b48 83 u8 reg_address,
7df86302 84 u8 val)
66533b48
JC
85{
86 int ret;
7b2fdd19 87 struct lis3l02dq_state *st = iio_priv(indio_dev);
66533b48
JC
88
89 mutex_lock(&st->buf_lock);
90 st->tx[0] = LIS3L02DQ_WRITE_REG(reg_address);
7df86302 91 st->tx[1] = val;
1b076b52 92 ret = spi_write(st->us, st->tx, 2);
66533b48
JC
93 mutex_unlock(&st->buf_lock);
94
95 return ret;
96}
97
98/**
99 * lisl302dq_spi_write_reg_s16() - write 2 bytes to a pair of registers
1b076b52
JC
100 * @indio_dev: iio_dev for this device
101 * @lower_reg_address: the address of the lower of the two registers.
102 * Second register is assumed to have address one greater.
103 * @value: value to be written
66533b48 104 **/
1b076b52 105static int lis3l02dq_spi_write_reg_s16(struct iio_dev *indio_dev,
66533b48
JC
106 u8 lower_reg_address,
107 s16 value)
108{
109 int ret;
110 struct spi_message msg;
7b2fdd19 111 struct lis3l02dq_state *st = iio_priv(indio_dev);
66533b48
JC
112 struct spi_transfer xfers[] = { {
113 .tx_buf = st->tx,
114 .bits_per_word = 8,
115 .len = 2,
116 .cs_change = 1,
117 }, {
118 .tx_buf = st->tx + 2,
119 .bits_per_word = 8,
120 .len = 2,
66533b48
JC
121 },
122 };
123
124 mutex_lock(&st->buf_lock);
125 st->tx[0] = LIS3L02DQ_WRITE_REG(lower_reg_address);
126 st->tx[1] = value & 0xFF;
127 st->tx[2] = LIS3L02DQ_WRITE_REG(lower_reg_address + 1);
128 st->tx[3] = (value >> 8) & 0xFF;
129
130 spi_message_init(&msg);
131 spi_message_add_tail(&xfers[0], &msg);
132 spi_message_add_tail(&xfers[1], &msg);
133 ret = spi_sync(st->us, &msg);
134 mutex_unlock(&st->buf_lock);
135
136 return ret;
137}
138
1b076b52 139static int lis3l02dq_read_reg_s16(struct iio_dev *indio_dev,
f3736416
JC
140 u8 lower_reg_address,
141 int *val)
66533b48 142{
7b2fdd19 143 struct lis3l02dq_state *st = iio_priv(indio_dev);
1b076b52 144
66533b48 145 struct spi_message msg;
66533b48 146 int ret;
f3736416 147 s16 tempval;
66533b48
JC
148 struct spi_transfer xfers[] = { {
149 .tx_buf = st->tx,
150 .rx_buf = st->rx,
151 .bits_per_word = 8,
152 .len = 2,
153 .cs_change = 1,
154 }, {
155 .tx_buf = st->tx + 2,
156 .rx_buf = st->rx + 2,
157 .bits_per_word = 8,
158 .len = 2,
66533b48
JC
159 },
160 };
161
162 mutex_lock(&st->buf_lock);
163 st->tx[0] = LIS3L02DQ_READ_REG(lower_reg_address);
164 st->tx[1] = 0;
f3736416 165 st->tx[2] = LIS3L02DQ_READ_REG(lower_reg_address + 1);
66533b48
JC
166 st->tx[3] = 0;
167
168 spi_message_init(&msg);
169 spi_message_add_tail(&xfers[0], &msg);
170 spi_message_add_tail(&xfers[1], &msg);
171 ret = spi_sync(st->us, &msg);
172 if (ret) {
173 dev_err(&st->us->dev, "problem when reading 16 bit register");
174 goto error_ret;
175 }
f3736416 176 tempval = (s16)(st->rx[1]) | ((s16)(st->rx[3]) << 8);
66533b48 177
f3736416 178 *val = tempval;
66533b48
JC
179error_ret:
180 mutex_unlock(&st->buf_lock);
181 return ret;
182}
183
f3736416
JC
184enum lis3l02dq_rm_ind {
185 LIS3L02DQ_ACCEL,
186 LIS3L02DQ_GAIN,
187 LIS3L02DQ_BIAS,
188};
66533b48 189
f3736416
JC
190static u8 lis3l02dq_axis_map[3][3] = {
191 [LIS3L02DQ_ACCEL] = { LIS3L02DQ_REG_OUT_X_L_ADDR,
192 LIS3L02DQ_REG_OUT_Y_L_ADDR,
193 LIS3L02DQ_REG_OUT_Z_L_ADDR },
194 [LIS3L02DQ_GAIN] = { LIS3L02DQ_REG_GAIN_X_ADDR,
195 LIS3L02DQ_REG_GAIN_Y_ADDR,
196 LIS3L02DQ_REG_GAIN_Z_ADDR },
197 [LIS3L02DQ_BIAS] = { LIS3L02DQ_REG_OFFSET_X_ADDR,
198 LIS3L02DQ_REG_OFFSET_Y_ADDR,
199 LIS3L02DQ_REG_OFFSET_Z_ADDR }
200};
66533b48 201
f3736416
JC
202static int lis3l02dq_read_thresh(struct iio_dev *indio_dev,
203 int e,
204 int *val)
66533b48 205{
1b076b52 206 return lis3l02dq_read_reg_s16(indio_dev, LIS3L02DQ_REG_THS_L_ADDR, val);
66533b48
JC
207}
208
f3736416
JC
209static int lis3l02dq_write_thresh(struct iio_dev *indio_dev,
210 int event_code,
211 int val)
66533b48 212{
f3736416 213 u16 value = val;
1b076b52 214 return lis3l02dq_spi_write_reg_s16(indio_dev,
f3736416
JC
215 LIS3L02DQ_REG_THS_L_ADDR,
216 value);
66533b48
JC
217}
218
1e8fa5b8
JC
219static int lis3l02dq_write_raw(struct iio_dev *indio_dev,
220 struct iio_chan_spec const *chan,
221 int val,
222 int val2,
223 long mask)
224{
225 int ret = -EINVAL, reg;
226 u8 uval;
227 s8 sval;
228 switch (mask) {
229 case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
230 if (val > 255 || val < -256)
231 return -EINVAL;
232 sval = val;
233 reg = lis3l02dq_axis_map[LIS3L02DQ_BIAS][chan->address];
7df86302 234 ret = lis3l02dq_spi_write_reg_8(indio_dev, reg, sval);
1e8fa5b8
JC
235 break;
236 case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
237 if (val & ~0xFF)
238 return -EINVAL;
239 uval = val;
240 reg = lis3l02dq_axis_map[LIS3L02DQ_GAIN][chan->address];
7df86302 241 ret = lis3l02dq_spi_write_reg_8(indio_dev, reg, uval);
1e8fa5b8
JC
242 break;
243 }
244 return ret;
245}
246
f3736416
JC
247static int lis3l02dq_read_raw(struct iio_dev *indio_dev,
248 struct iio_chan_spec const *chan,
249 int *val,
250 int *val2,
251 long mask)
66533b48 252{
f3736416
JC
253 u8 utemp;
254 s8 stemp;
255 ssize_t ret = 0;
f3736416 256 u8 reg;
1b076b52 257
f3736416
JC
258 switch (mask) {
259 case 0:
260 /* Take the iio_dev status lock */
261 mutex_lock(&indio_dev->mlock);
262 if (indio_dev->currentmode == INDIO_RING_TRIGGERED)
263 ret = lis3l02dq_read_accel_from_ring(indio_dev->ring,
264 chan->scan_index,
265 val);
266 else {
267 reg = lis3l02dq_axis_map
268 [LIS3L02DQ_ACCEL][chan->address];
1b076b52 269 ret = lis3l02dq_read_reg_s16(indio_dev, reg, val);
f3736416
JC
270 }
271 mutex_unlock(&indio_dev->mlock);
272 return IIO_VAL_INT;
273 case (1 << IIO_CHAN_INFO_SCALE_SHARED):
274 *val = 0;
275 *val2 = 9580;
276 return IIO_VAL_INT_PLUS_MICRO;
277 case (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE):
278 reg = lis3l02dq_axis_map[LIS3L02DQ_GAIN][chan->address];
1b076b52 279 ret = lis3l02dq_spi_read_reg_8(indio_dev, reg, &utemp);
f3736416
JC
280 if (ret)
281 goto error_ret;
282 /* to match with what previous code does */
283 *val = utemp;
284 return IIO_VAL_INT;
285
286 case (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE):
287 reg = lis3l02dq_axis_map[LIS3L02DQ_BIAS][chan->address];
1b076b52 288 ret = lis3l02dq_spi_read_reg_8(indio_dev, reg, (u8 *)&stemp);
f3736416
JC
289 /* to match with what previous code does */
290 *val = stemp;
291 return IIO_VAL_INT;
292 }
66533b48 293error_ret:
f3736416 294 return ret;
66533b48
JC
295}
296
297static ssize_t lis3l02dq_read_frequency(struct device *dev,
298 struct device_attribute *attr,
299 char *buf)
300{
1b076b52 301 struct iio_dev *indio_dev = dev_get_drvdata(dev);
66533b48
JC
302 int ret, len = 0;
303 s8 t;
1b076b52 304 ret = lis3l02dq_spi_read_reg_8(indio_dev,
66533b48
JC
305 LIS3L02DQ_REG_CTRL_1_ADDR,
306 (u8 *)&t);
307 if (ret)
308 return ret;
309 t &= LIS3L02DQ_DEC_MASK;
310 switch (t) {
311 case LIS3L02DQ_REG_CTRL_1_DF_128:
312 len = sprintf(buf, "280\n");
313 break;
314 case LIS3L02DQ_REG_CTRL_1_DF_64:
315 len = sprintf(buf, "560\n");
316 break;
317 case LIS3L02DQ_REG_CTRL_1_DF_32:
318 len = sprintf(buf, "1120\n");
319 break;
320 case LIS3L02DQ_REG_CTRL_1_DF_8:
321 len = sprintf(buf, "4480\n");
322 break;
323 }
324 return len;
325}
326
327static ssize_t lis3l02dq_write_frequency(struct device *dev,
328 struct device_attribute *attr,
329 const char *buf,
330 size_t len)
331{
332 struct iio_dev *indio_dev = dev_get_drvdata(dev);
333 long val;
334 int ret;
335 u8 t;
336
337 ret = strict_strtol(buf, 10, &val);
338 if (ret)
339 return ret;
340
341 mutex_lock(&indio_dev->mlock);
1b076b52 342 ret = lis3l02dq_spi_read_reg_8(indio_dev,
66533b48
JC
343 LIS3L02DQ_REG_CTRL_1_ADDR,
344 &t);
345 if (ret)
346 goto error_ret_mutex;
347 /* Wipe the bits clean */
348 t &= ~LIS3L02DQ_DEC_MASK;
349 switch (val) {
350 case 280:
351 t |= LIS3L02DQ_REG_CTRL_1_DF_128;
352 break;
353 case 560:
354 t |= LIS3L02DQ_REG_CTRL_1_DF_64;
355 break;
356 case 1120:
357 t |= LIS3L02DQ_REG_CTRL_1_DF_32;
358 break;
359 case 4480:
360 t |= LIS3L02DQ_REG_CTRL_1_DF_8;
361 break;
362 default:
363 ret = -EINVAL;
364 goto error_ret_mutex;
95cd17c9 365 }
66533b48 366
1b076b52 367 ret = lis3l02dq_spi_write_reg_8(indio_dev,
66533b48 368 LIS3L02DQ_REG_CTRL_1_ADDR,
7df86302 369 t);
66533b48
JC
370
371error_ret_mutex:
372 mutex_unlock(&indio_dev->mlock);
373
374 return ret ? ret : len;
375}
376
7b2fdd19 377static int lis3l02dq_initial_setup(struct iio_dev *indio_dev)
66533b48 378{
7b2fdd19 379 struct lis3l02dq_state *st = iio_priv(indio_dev);
66533b48
JC
380 int ret;
381 u8 val, valtest;
382
383 st->us->mode = SPI_MODE_3;
384
385 spi_setup(st->us);
386
387 val = LIS3L02DQ_DEFAULT_CTRL1;
388 /* Write suitable defaults to ctrl1 */
7b2fdd19 389 ret = lis3l02dq_spi_write_reg_8(indio_dev,
66533b48 390 LIS3L02DQ_REG_CTRL_1_ADDR,
7df86302 391 val);
66533b48
JC
392 if (ret) {
393 dev_err(&st->us->dev, "problem with setup control register 1");
394 goto err_ret;
395 }
396 /* Repeat as sometimes doesn't work first time?*/
7b2fdd19 397 ret = lis3l02dq_spi_write_reg_8(indio_dev,
66533b48 398 LIS3L02DQ_REG_CTRL_1_ADDR,
7df86302 399 val);
66533b48
JC
400 if (ret) {
401 dev_err(&st->us->dev, "problem with setup control register 1");
402 goto err_ret;
403 }
404
405 /* Read back to check this has worked acts as loose test of correct
406 * chip */
7b2fdd19 407 ret = lis3l02dq_spi_read_reg_8(indio_dev,
66533b48
JC
408 LIS3L02DQ_REG_CTRL_1_ADDR,
409 &valtest);
410 if (ret || (valtest != val)) {
7b2fdd19 411 dev_err(&indio_dev->dev,
1b076b52 412 "device not playing ball %d %d\n", valtest, val);
66533b48
JC
413 ret = -EINVAL;
414 goto err_ret;
415 }
416
417 val = LIS3L02DQ_DEFAULT_CTRL2;
7b2fdd19 418 ret = lis3l02dq_spi_write_reg_8(indio_dev,
66533b48 419 LIS3L02DQ_REG_CTRL_2_ADDR,
7df86302 420 val);
66533b48
JC
421 if (ret) {
422 dev_err(&st->us->dev, "problem with setup control register 2");
423 goto err_ret;
424 }
425
426 val = LIS3L02DQ_REG_WAKE_UP_CFG_LATCH_SRC;
7b2fdd19 427 ret = lis3l02dq_spi_write_reg_8(indio_dev,
66533b48 428 LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
7df86302 429 val);
66533b48
JC
430 if (ret)
431 dev_err(&st->us->dev, "problem with interrupt cfg register");
432err_ret:
433
434 return ret;
435}
436
66533b48
JC
437static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
438 lis3l02dq_read_frequency,
439 lis3l02dq_write_frequency);
440
f3fb0011 441static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("280 560 1120 4480");
66533b48 442
aaf370db 443static irqreturn_t lis3l02dq_event_handler(int irq, void *private)
66533b48 444{
aaf370db 445 struct iio_dev *indio_dev = private;
461be806
JC
446 u8 t;
447
448 s64 timestamp = iio_get_time_ns();
449
7b2fdd19 450 lis3l02dq_spi_read_reg_8(indio_dev,
461be806
JC
451 LIS3L02DQ_REG_WAKE_UP_SRC_ADDR,
452 &t);
66533b48 453
461be806 454 if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_HIGH)
7b2fdd19 455 iio_push_event(indio_dev, 0,
c4b14d99 456 IIO_MOD_EVENT_CODE(IIO_ACCEL,
461be806 457 0,
c4b14d99 458 IIO_MOD_Z,
461be806
JC
459 IIO_EV_TYPE_THRESH,
460 IIO_EV_DIR_RISING),
461 timestamp);
462
463 if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_LOW)
7b2fdd19 464 iio_push_event(indio_dev, 0,
c4b14d99 465 IIO_MOD_EVENT_CODE(IIO_ACCEL,
461be806 466 0,
c4b14d99 467 IIO_MOD_Z,
461be806
JC
468 IIO_EV_TYPE_THRESH,
469 IIO_EV_DIR_FALLING),
470 timestamp);
471
472 if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_HIGH)
7b2fdd19 473 iio_push_event(indio_dev, 0,
c4b14d99 474 IIO_MOD_EVENT_CODE(IIO_ACCEL,
461be806 475 0,
c4b14d99 476 IIO_MOD_Y,
461be806
JC
477 IIO_EV_TYPE_THRESH,
478 IIO_EV_DIR_RISING),
479 timestamp);
480
481 if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_LOW)
7b2fdd19 482 iio_push_event(indio_dev, 0,
c4b14d99 483 IIO_MOD_EVENT_CODE(IIO_ACCEL,
461be806 484 0,
c4b14d99 485 IIO_MOD_Y,
461be806
JC
486 IIO_EV_TYPE_THRESH,
487 IIO_EV_DIR_FALLING),
488 timestamp);
489
490 if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_HIGH)
7b2fdd19 491 iio_push_event(indio_dev, 0,
c4b14d99 492 IIO_MOD_EVENT_CODE(IIO_ACCEL,
461be806 493 0,
c4b14d99 494 IIO_MOD_X,
461be806
JC
495 IIO_EV_TYPE_THRESH,
496 IIO_EV_DIR_RISING),
497 timestamp);
498
499 if (t & LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_LOW)
7b2fdd19 500 iio_push_event(indio_dev, 0,
c4b14d99 501 IIO_MOD_EVENT_CODE(IIO_ACCEL,
461be806 502 0,
c4b14d99 503 IIO_MOD_X,
461be806
JC
504 IIO_EV_TYPE_THRESH,
505 IIO_EV_DIR_FALLING),
506 timestamp);
507
508 /* Ack and allow for new interrupts */
7b2fdd19 509 lis3l02dq_spi_read_reg_8(indio_dev,
461be806
JC
510 LIS3L02DQ_REG_WAKE_UP_ACK_ADDR,
511 &t);
66533b48 512
1e3345bc 513 return IRQ_HANDLED;
66533b48
JC
514}
515
f3736416
JC
516#define LIS3L02DQ_INFO_MASK \
517 ((1 << IIO_CHAN_INFO_SCALE_SHARED) | \
518 (1 << IIO_CHAN_INFO_CALIBSCALE_SEPARATE) | \
519 (1 << IIO_CHAN_INFO_CALIBBIAS_SEPARATE))
520
521#define LIS3L02DQ_EVENT_MASK \
522 (IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) | \
523 IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING))
524
525static struct iio_chan_spec lis3l02dq_channels[] = {
526 IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_X, LIS3L02DQ_INFO_MASK,
aaf370db 527 0, 0, IIO_ST('s', 12, 16, 0), LIS3L02DQ_EVENT_MASK),
f3736416 528 IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Y, LIS3L02DQ_INFO_MASK,
aaf370db 529 1, 1, IIO_ST('s', 12, 16, 0), LIS3L02DQ_EVENT_MASK),
f3736416 530 IIO_CHAN(IIO_ACCEL, 1, 0, 0, NULL, 0, IIO_MOD_Z, LIS3L02DQ_INFO_MASK,
aaf370db 531 2, 2, IIO_ST('s', 12, 16, 0), LIS3L02DQ_EVENT_MASK),
f3736416
JC
532 IIO_CHAN_SOFT_TIMESTAMP(3)
533};
534
535
536static ssize_t lis3l02dq_read_event_config(struct iio_dev *indio_dev,
537 int event_code)
538{
539
540 u8 val;
541 int ret;
542 u8 mask = (1 << (IIO_EVENT_CODE_EXTRACT_MODIFIER(event_code)*2 +
543 (IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
544 IIO_EV_DIR_RISING)));
1b076b52 545 ret = lis3l02dq_spi_read_reg_8(indio_dev,
66533b48 546 LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
f3736416
JC
547 &val);
548 if (ret < 0)
549 return ret;
550
551 return !!(val & mask);
552}
66533b48 553
1e3345bc
JC
554int lis3l02dq_disable_all_events(struct iio_dev *indio_dev)
555{
1e3345bc
JC
556 int ret;
557 u8 control, val;
1e3345bc
JC
558
559 ret = lis3l02dq_spi_read_reg_8(indio_dev,
560 LIS3L02DQ_REG_CTRL_2_ADDR,
561 &control);
562
1e3345bc
JC
563 control &= ~LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT;
564 ret = lis3l02dq_spi_write_reg_8(indio_dev,
565 LIS3L02DQ_REG_CTRL_2_ADDR,
7df86302 566 control);
1e3345bc
JC
567 if (ret)
568 goto error_ret;
569 /* Also for consistency clear the mask */
570 ret = lis3l02dq_spi_read_reg_8(indio_dev,
571 LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
572 &val);
573 if (ret)
574 goto error_ret;
575 val &= ~0x3f;
576
577 ret = lis3l02dq_spi_write_reg_8(indio_dev,
578 LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
7df86302 579 val);
1e3345bc
JC
580 if (ret)
581 goto error_ret;
582
1e3345bc
JC
583 ret = control;
584error_ret:
585 return ret;
586}
587
f3736416
JC
588static int lis3l02dq_write_event_config(struct iio_dev *indio_dev,
589 int event_code,
f3736416
JC
590 int state)
591{
592 int ret = 0;
593 u8 val, control;
594 u8 currentlyset;
595 bool changed = false;
596 u8 mask = (1 << (IIO_EVENT_CODE_EXTRACT_MODIFIER(event_code)*2 +
597 (IIO_EVENT_CODE_EXTRACT_DIR(event_code) ==
598 IIO_EV_DIR_RISING)));
599
600 mutex_lock(&indio_dev->mlock);
66533b48 601 /* read current control */
1b076b52 602 ret = lis3l02dq_spi_read_reg_8(indio_dev,
66533b48 603 LIS3L02DQ_REG_CTRL_2_ADDR,
f3736416 604 &control);
66533b48 605 if (ret)
f3736416 606 goto error_ret;
1b076b52 607 ret = lis3l02dq_spi_read_reg_8(indio_dev,
f3736416
JC
608 LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
609 &val);
610 if (ret < 0)
611 goto error_ret;
612 currentlyset = val & mask;
613
614 if (!currentlyset && state) {
615 changed = true;
616 val |= mask;
f3736416
JC
617 } else if (currentlyset && !state) {
618 changed = true;
619 val &= ~mask;
66533b48 620 }
1e3345bc 621
66533b48 622 if (changed) {
1b076b52 623 ret = lis3l02dq_spi_write_reg_8(indio_dev,
66533b48 624 LIS3L02DQ_REG_WAKE_UP_CFG_ADDR,
7df86302 625 val);
66533b48 626 if (ret)
f3736416 627 goto error_ret;
1e3345bc 628 control = val & 0x3f ?
f3736416
JC
629 (control | LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT) :
630 (control & ~LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT);
1b076b52 631 ret = lis3l02dq_spi_write_reg_8(indio_dev,
f3736416 632 LIS3L02DQ_REG_CTRL_2_ADDR,
7df86302 633 control);
1e3345bc
JC
634 if (ret)
635 goto error_ret;
66533b48 636 }
66533b48 637
f3736416
JC
638error_ret:
639 mutex_unlock(&indio_dev->mlock);
640 return ret;
66533b48
JC
641}
642
66533b48 643static struct attribute *lis3l02dq_attributes[] = {
66533b48 644 &iio_dev_attr_sampling_frequency.dev_attr.attr,
f3fb0011 645 &iio_const_attr_sampling_frequency_available.dev_attr.attr,
66533b48
JC
646 NULL
647};
648
649static const struct attribute_group lis3l02dq_attribute_group = {
650 .attrs = lis3l02dq_attributes,
651};
652
6fe8135f
JC
653static const struct iio_info lis3l02dq_info = {
654 .num_interrupt_lines = 1,
655 .read_raw = &lis3l02dq_read_raw,
656 .write_raw = &lis3l02dq_write_raw,
657 .read_event_value = &lis3l02dq_read_thresh,
658 .write_event_value = &lis3l02dq_write_thresh,
659 .write_event_config = &lis3l02dq_write_event_config,
660 .read_event_config = &lis3l02dq_read_event_config,
661 .driver_module = THIS_MODULE,
662 .attrs = &lis3l02dq_attribute_group,
663};
664
66533b48
JC
665static int __devinit lis3l02dq_probe(struct spi_device *spi)
666{
667 int ret, regdone = 0;
7b2fdd19
JC
668 struct lis3l02dq_state *st;
669 struct iio_dev *indio_dev;
670
671 indio_dev = iio_allocate_device(sizeof *st);
672 if (indio_dev == NULL) {
673 ret = -ENOMEM;
66533b48
JC
674 goto error_ret;
675 }
7b2fdd19 676 st = iio_priv(indio_dev);
66533b48 677 /* this is only used tor removal purposes */
8016934c 678 spi_set_drvdata(spi, indio_dev);
66533b48 679
66533b48
JC
680 st->us = spi;
681 mutex_init(&st->buf_lock);
7b2fdd19
JC
682 indio_dev->name = spi->dev.driver->name;
683 indio_dev->dev.parent = &spi->dev;
6fe8135f 684 indio_dev->info = &lis3l02dq_info;
7b2fdd19
JC
685 indio_dev->channels = lis3l02dq_channels;
686 indio_dev->num_channels = ARRAY_SIZE(lis3l02dq_channels);
6fe8135f 687
7b2fdd19
JC
688 indio_dev->modes = INDIO_DIRECT_MODE;
689
690 ret = lis3l02dq_configure_ring(indio_dev);
66533b48
JC
691 if (ret)
692 goto error_free_dev;
693
7b2fdd19 694 ret = iio_device_register(indio_dev);
66533b48
JC
695 if (ret)
696 goto error_unreg_ring_funcs;
697 regdone = 1;
698
1aa04278 699 ret = iio_ring_buffer_register_ex(indio_dev, 0,
f3736416
JC
700 lis3l02dq_channels,
701 ARRAY_SIZE(lis3l02dq_channels));
66533b48
JC
702 if (ret) {
703 printk(KERN_ERR "failed to initialize the ring\n");
704 goto error_unreg_ring_funcs;
705 }
706
707 if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) {
d731aea0
JC
708 ret = request_threaded_irq(st->us->irq,
709 &lis3l02dq_th,
710 &lis3l02dq_event_handler,
711 IRQF_TRIGGER_RISING,
712 "lis3l02dq",
7b2fdd19 713 indio_dev);
66533b48 714 if (ret)
aaf370db 715 goto error_uninitialize_ring;
d731aea0 716
7b2fdd19 717 ret = lis3l02dq_probe_trigger(indio_dev);
d731aea0
JC
718 if (ret)
719 goto error_free_interrupt;
66533b48
JC
720 }
721
722 /* Get the device into a sane initial state */
7b2fdd19 723 ret = lis3l02dq_initial_setup(indio_dev);
66533b48
JC
724 if (ret)
725 goto error_remove_trigger;
726 return 0;
727
728error_remove_trigger:
7b2fdd19
JC
729 if (indio_dev->modes & INDIO_RING_TRIGGERED)
730 lis3l02dq_remove_trigger(indio_dev);
d731aea0
JC
731error_free_interrupt:
732 if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
7b2fdd19 733 free_irq(st->us->irq, indio_dev);
66533b48 734error_uninitialize_ring:
1aa04278 735 iio_ring_buffer_unregister(indio_dev);
66533b48 736error_unreg_ring_funcs:
7b2fdd19 737 lis3l02dq_unconfigure_ring(indio_dev);
66533b48
JC
738error_free_dev:
739 if (regdone)
7b2fdd19 740 iio_device_unregister(indio_dev);
66533b48 741 else
7b2fdd19 742 iio_free_device(indio_dev);
66533b48
JC
743error_ret:
744 return ret;
745}
746
747/* Power down the device */
748static int lis3l02dq_stop_device(struct iio_dev *indio_dev)
749{
750 int ret;
7b2fdd19 751 struct lis3l02dq_state *st = iio_priv(indio_dev);
66533b48
JC
752 u8 val = 0;
753
754 mutex_lock(&indio_dev->mlock);
1b076b52 755 ret = lis3l02dq_spi_write_reg_8(indio_dev,
66533b48 756 LIS3L02DQ_REG_CTRL_1_ADDR,
7df86302 757 val);
66533b48
JC
758 if (ret) {
759 dev_err(&st->us->dev, "problem with turning device off: ctrl1");
760 goto err_ret;
761 }
762
1b076b52 763 ret = lis3l02dq_spi_write_reg_8(indio_dev,
66533b48 764 LIS3L02DQ_REG_CTRL_2_ADDR,
7df86302 765 val);
66533b48
JC
766 if (ret)
767 dev_err(&st->us->dev, "problem with turning device off: ctrl2");
768err_ret:
769 mutex_unlock(&indio_dev->mlock);
770 return ret;
771}
772
773/* fixme, confirm ordering in this function */
774static int lis3l02dq_remove(struct spi_device *spi)
775{
776 int ret;
7b2fdd19
JC
777 struct iio_dev *indio_dev = spi_get_drvdata(spi);
778 struct lis3l02dq_state *st = iio_priv(indio_dev);
779
1e3345bc
JC
780 ret = lis3l02dq_disable_all_events(indio_dev);
781 if (ret)
782 goto err_ret;
66533b48
JC
783
784 ret = lis3l02dq_stop_device(indio_dev);
785 if (ret)
786 goto err_ret;
787
d731aea0
JC
788 if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
789 free_irq(st->us->irq, indio_dev);
790
66533b48 791 lis3l02dq_remove_trigger(indio_dev);
1aa04278 792 iio_ring_buffer_unregister(indio_dev);
66533b48
JC
793 lis3l02dq_unconfigure_ring(indio_dev);
794 iio_device_unregister(indio_dev);
66533b48
JC
795
796 return 0;
797
798err_ret:
799 return ret;
800}
801
802static struct spi_driver lis3l02dq_driver = {
803 .driver = {
804 .name = "lis3l02dq",
805 .owner = THIS_MODULE,
806 },
807 .probe = lis3l02dq_probe,
808 .remove = __devexit_p(lis3l02dq_remove),
809};
810
811static __init int lis3l02dq_init(void)
812{
813 return spi_register_driver(&lis3l02dq_driver);
814}
815module_init(lis3l02dq_init);
816
817static __exit void lis3l02dq_exit(void)
818{
819 spi_unregister_driver(&lis3l02dq_driver);
820}
821module_exit(lis3l02dq_exit);
822
823MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
824MODULE_DESCRIPTION("ST LIS3L02DQ Accelerometer SPI driver");
825MODULE_LICENSE("GPL v2");
This page took 0.260439 seconds and 5 git commands to generate.