staging:iio:lis3l02dq drop separate driver
Subsystems (3)
Jonathan Cameron
maintainerPATCH 1/1 staging:iio:lis3l02dq drop separate driver
Retire this venerable driver as the basic support is now in the generic st-sensors accelerometer driver.
There are a few missing features in the new driver:
* Threshold events.
* Access to the calibration adjustment registers (patch shortly)
In exchange it brings a cleaner and more maintainable code base that actually gets tested more than once every few years. I'll actually be suprised if anyone other than me has a board with one of these on that is running an up to date kernel.
--- drivers/staging/iio/accel/Kconfig | 14 - drivers/staging/iio/accel/Makefile | 4 - drivers/staging/iio/accel/lis3l02dq.h | 217 -------- drivers/staging/iio/accel/lis3l02dq_core.c | 814 ----------------------------- drivers/staging/iio/accel/lis3l02dq_ring.c | 428 --------------- 5 files changed, 1477 deletions(-)
drivers/staging/iio/accel/Kconfig +0 -14
@@ -51,20 +51,6 @@ config ADIS16240 To compile this driver as a module, say M here: the module will be called adis16240. -config LIS3L02DQ - tristate "ST Microelectronics LIS3L02DQ Accelerometer Driver" - depends on SPI - select IIO_TRIGGER if IIO_BUFFER - depends on !IIO_BUFFER || IIO_KFIFO_BUF - depends on GPIOLIB || COMPILE_TEST - help - Say Y here to build SPI support for the ST microelectronics - accelerometer. The driver supplies direct access via sysfs files - and an event interface via a character device. - - To compile this driver as a module, say M here: the module will be - called lis3l02dq. - config SCA3000 depends on IIO_BUFFER depends on SPI
drivers/staging/iio/accel/Makefile +0 -4
@@ -14,9 +14,5 @@ obj-$(CONFIG_ADIS16209) += adis16209.o adis16240-y := adis16240_core.o obj-$(CONFIG_ADIS16240) += adis16240.o -lis3l02dq-y := lis3l02dq_core.o -lis3l02dq-$(CONFIG_IIO_BUFFER) += lis3l02dq_ring.o -obj-$(CONFIG_LIS3L02DQ) += lis3l02dq.o - sca3000-y := sca3000_core.o sca3000_ring.o obj-$(CONFIG_SCA3000) += sca3000.o
drivers/staging/iio/accel/lis3l02dq.h deleted +0 -217
217 lines not on this page · raw message
drivers/staging/iio/accel/lis3l02dq_core.c deleted +0 -814
814 lines not on this page · raw message
drivers/staging/iio/accel/lis3l02dq_ring.c deleted +0 -428
428 lines not on this page · raw message
Signature · 1 line
2.9.0
Quoted 7 lines · Jonathan Cameron
Retire this venerable driver as the basic support is now in the generic st-sensors accelerometer driver.
There are a few missing features in the new driver:
* Threshold events.
* Access to the calibration adjustment registers (patch shortly)
Quoted 6 lines
In exchange it brings a cleaner and more maintainable code base that actually gets tested more than once every few years. I'll actually be suprised if anyone other than me has a board with one of these on that is running an up to date kernel.
Signed-off-by Jonathan Cameron <[email protected]>
This is more for info than expecting any comments. Just dropping a staging driver that is now 'more or less' covered by a non staging driver.
Applied to the togreg branch of iio.git - initially pushed out as testing for the autobuilders to see what I messed up.
Thanks,
Jonathan
Quoted 1,525 lines
--- drivers/staging/iio/accel/Kconfig | 14 - drivers/staging/iio/accel/Makefile | 4 - drivers/staging/iio/accel/lis3l02dq.h | 217 -------- drivers/staging/iio/accel/lis3l02dq_core.c | 814 ----------------------------- drivers/staging/iio/accel/lis3l02dq_ring.c | 428 --------------- 5 files changed, 1477 deletions(-)drivers/staging/iio/accel/Kconfig +0
-14@@ -51,20 +51,6 @@ config ADIS16240 To compile this driver as a module, say M here: the module will be called adis16240. -config LIS3L02DQ - tristate "ST Microelectronics LIS3L02DQ Accelerometer Driver" - depends on SPI - select IIO_TRIGGER if IIO_BUFFER - depends on !IIO_BUFFER || IIO_KFIFO_BUF - depends on GPIOLIB || COMPILE_TEST - help - Say Y here to build SPI support for the ST microelectronics - accelerometer. The driver supplies direct access via sysfs files - and an event interface via a character device. - - To compile this driver as a module, say M here: the module will be - called lis3l02dq. - config SCA3000 depends on IIO_BUFFER depends on SPIdrivers/staging/iio/accel/Makefile +0
-4@@ -14,9 +14,5 @@ obj-$(CONFIG_ADIS16209) += adis16209.o adis16240-y := adis16240_core.o obj-$(CONFIG_ADIS16240) += adis16240.o -lis3l02dq-y := lis3l02dq_core.o -lis3l02dq-$(CONFIG_IIO_BUFFER) += lis3l02dq_ring.o -obj-$(CONFIG_LIS3L02DQ) += lis3l02dq.o - sca3000-y := sca3000_core.o sca3000_ring.o obj-$(CONFIG_SCA3000) += sca3000.odrivers/staging/iio/accel/lis3l02dq.h deleted +0
-217@@ -1,217 +0,0 @@ -/* -* LISL02DQ.h -- support STMicroelectronics LISD02DQ -* 3d 2g Linear Accelerometers via SPI -* -* Copyright (c) 2007 Jonathan Cameron <[email protected]> -* -* Loosely based upon tle62x0.c -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 as -* published by the Free Software Foundation. -*/ - -#ifndef SPI_LIS3L02DQ_H_ -#define SPI_LIS3L02DQ_H_ -#define LIS3L02DQ_READ_REG (a) ((a) | 0x80) -#define LIS3L02DQ_WRITE_REG (a) a - -/* Calibration parameters */ -#define LIS3L02DQ_REG_OFFSET_X_ADDR 0x16 -#define LIS3L02DQ_REG_OFFSET_Y_ADDR 0x17 -#define LIS3L02DQ_REG_OFFSET_Z_ADDR 0x18 - -#define LIS3L02DQ_REG_GAIN_X_ADDR 0x19 -#define LIS3L02DQ_REG_GAIN_Y_ADDR 0x1A -#define LIS3L02DQ_REG_GAIN_Z_ADDR 0x1B - -/* Control Register (1 of 2) */ -#define LIS3L02DQ_REG_CTRL_1_ADDR 0x20 -/* Power ctrl - either bit set corresponds to on*/ -#define LIS3L02DQ_REG_CTRL_1_PD_ON 0xC0 - -/* Decimation Factor */ -#define LIS3L02DQ_DEC_MASK 0x30 -#define LIS3L02DQ_REG_CTRL_1_DF_128 0x00 -#define LIS3L02DQ_REG_CTRL_1_DF_64 0x10 -#define LIS3L02DQ_REG_CTRL_1_DF_32 0x20 -#define LIS3L02DQ_REG_CTRL_1_DF_8 (0x10 | 0x20) - -/* Self Test Enable */ -#define LIS3L02DQ_REG_CTRL_1_SELF_TEST_ON 0x08 - -/* Axes enable ctrls */ -#define LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE 0x04 -#define LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE 0x02 -#define LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE 0x01 - -/* Control Register (2 of 2) */ -#define LIS3L02DQ_REG_CTRL_2_ADDR 0x21 - -/* Block Data Update only after MSB and LSB read */ -#define LIS3L02DQ_REG_CTRL_2_BLOCK_UPDATE 0x40 - -/* Set to big endian output */ -#define LIS3L02DQ_REG_CTRL_2_BIG_ENDIAN 0x20 - -/* Reboot memory content */ -#define LIS3L02DQ_REG_CTRL_2_REBOOT_MEMORY 0x10 - -/* Interrupt Enable - applies data ready to the RDY pad */ -#define LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT 0x08 - -/* Enable Data Ready Generation - relationship with previous unclear in docs */ -#define LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION 0x04 - -/* SPI 3 wire mode */ -#define LIS3L02DQ_REG_CTRL_2_THREE_WIRE_SPI_MODE 0x02 - -/* Data alignment, default is 12 bit right justified -* - option for 16 bit left justified -*/ -#define LIS3L02DQ_REG_CTRL_2_DATA_ALIGNMENT_16_BIT_LEFT_JUSTIFIED 0x01 - -/* Interrupt related stuff */ -#define LIS3L02DQ_REG_WAKE_UP_CFG_ADDR 0x23 - -/* Switch from or combination of conditions to and */ -#define LIS3L02DQ_REG_WAKE_UP_CFG_BOOLEAN_AND 0x80 - -/* Latch interrupt request, -* if on ack must be given by reading the ack register -*/ -#define LIS3L02DQ_REG_WAKE_UP_CFG_LATCH_SRC 0x40 - -/* Z Interrupt on High (above threshold) */ -#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_HIGH 0x20 -/* Z Interrupt on Low */ -#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Z_LOW 0x10 -/* Y Interrupt on High */ -#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Y_HIGH 0x08 -/* Y Interrupt on Low */ -#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_Y_LOW 0x04 -/* X Interrupt on High */ -#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_X_HIGH 0x02 -/* X Interrupt on Low */ -#define LIS3L02DQ_REG_WAKE_UP_CFG_INTERRUPT_X_LOW 0x01 - -/* Register that gives description of what caused interrupt -* - latched if set in CFG_ADDRES -*/ -#define LIS3L02DQ_REG_WAKE_UP_SRC_ADDR 0x24 -/* top bit ignored */ -/* Interrupt Active */ -#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_ACTIVATED 0x40 -/* Interupts that have been triggered */ -#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_HIGH 0x20 -#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_LOW 0x10 -#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_HIGH 0x08 -#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_LOW 0x04 -#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_HIGH 0x02 -#define LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_LOW 0x01 - -#define LIS3L02DQ_REG_WAKE_UP_ACK_ADDR 0x25 - -/* Status register */ -#define LIS3L02DQ_REG_STATUS_ADDR 0x27 -/* XYZ axis data overrun - first is all overrun? */ -#define LIS3L02DQ_REG_STATUS_XYZ_OVERRUN 0x80 -#define LIS3L02DQ_REG_STATUS_Z_OVERRUN 0x40 -#define LIS3L02DQ_REG_STATUS_Y_OVERRUN 0x20 -#define LIS3L02DQ_REG_STATUS_X_OVERRUN 0x10 -/* XYZ new data available - first is all 3 available? */ -#define LIS3L02DQ_REG_STATUS_XYZ_NEW_DATA 0x08 -#define LIS3L02DQ_REG_STATUS_Z_NEW_DATA 0x04 -#define LIS3L02DQ_REG_STATUS_Y_NEW_DATA 0x02 -#define LIS3L02DQ_REG_STATUS_X_NEW_DATA 0x01 - -/* The accelerometer readings - low and high bytes. -* Form of high byte dependent on justification set in ctrl reg -*/ -#define LIS3L02DQ_REG_OUT_X_L_ADDR 0x28 -#define LIS3L02DQ_REG_OUT_X_H_ADDR 0x29 -#define LIS3L02DQ_REG_OUT_Y_L_ADDR 0x2A -#define LIS3L02DQ_REG_OUT_Y_H_ADDR 0x2B -#define LIS3L02DQ_REG_OUT_Z_L_ADDR 0x2C -#define LIS3L02DQ_REG_OUT_Z_H_ADDR 0x2D - -/* Threshold values for all axes and both above and below thresholds -* - i.e. there is only one value -*/ -#define LIS3L02DQ_REG_THS_L_ADDR 0x2E -#define LIS3L02DQ_REG_THS_H_ADDR 0x2F - -#define LIS3L02DQ_DEFAULT_CTRL1 (LIS3L02DQ_REG_CTRL_1_PD_ON \ - | LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE \ - | LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE \ - | LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE \ - | LIS3L02DQ_REG_CTRL_1_DF_128) - -#define LIS3L02DQ_DEFAULT_CTRL2 0 - -#define LIS3L02DQ_MAX_TX 12 -#define LIS3L02DQ_MAX_RX 12 -/** -* struct lis3l02dq_state - device instance specific data -* @us: actual spi_device -* @trig: data ready trigger registered with iio -* @buf_lock: mutex to protect tx and rx -* @tx: transmit buffer -* @rx: receive buffer -**/ -struct lis3l02dq_state { -struct spi_device *us; -struct iio_trigger *trig; -struct mutex buf_lock; -int gpio; -bool trigger_on; - -u8 tx[LIS3L02DQ_MAX_RX ]____cacheline_aligned ; -u8 rx[LIS3L02DQ_MAX_RX ]____cacheline_aligned ; -}; - -int lis3l02dq_spi_read_reg_8 (struct iio_dev *indio_dev, -u8 reg_address, -u8 *val); - -int lis3l02dq_spi_write_reg_8 (struct iio_dev *indio_dev, -u8 reg_address, -u8 val); - -int lis3l02dq_disable_all_events (struct iio_dev *indio_dev); - -#ifdef CONFIG_IIO_BUFFER -/* At the moment triggers are only used for buffer -* filling. This may change! -*/ -void lis3l02dq_remove_trigger (struct iio_dev *indio_dev); -int lis3l02dq_probe_trigger (struct iio_dev *indio_dev); - -int lis3l02dq_configure_buffer (struct iio_dev *indio_dev); -void lis3l02dq_unconfigure_buffer (struct iio_dev *indio_dev); - -irqreturn_t lis3l02dq_data_rdy_trig_poll (int irq,void *private); -#define lis3l02dq_th lis3l02dq_data_rdy_trig_poll - -#else /* CONFIG_IIO_BUFFER */ -#define lis3l02dq_th lis3l02dq_nobuffer - -static inline void lis3l02dq_remove_trigger (struct iio_dev *indio_dev) -{ -} - -static inline int lis3l02dq_probe_trigger (struct iio_dev *indio_dev) -{ -return 0 ; -} - -static int lis3l02dq_configure_buffer (struct iio_dev *indio_dev) -{ -return 0 ; -} - -static inline void lis3l02dq_unconfigure_buffer (struct iio_dev *indio_dev) -{ -} -#endif /* CONFIG_IIO_BUFFER */ -#endif /* SPI_LIS3L02DQ_H_ */ drivers/staging/iio/accel/lis3l02dq_core.c deleted +0
-814@@ -1,814 +0,0 @@ -/* -* lis3l02dq.c support STMicroelectronics LISD02DQ -* 3d 2g Linear Accelerometers via SPI -* -* Copyright (c) 2007 Jonathan Cameron <[email protected]> -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 as -* published by the Free Software Foundation. -* -* Settings: -* 16 bit left justified mode used. -*/ - -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/of_gpio.h> -#include <linux/mutex.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/module.h> - -#include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> -#include <linux/iio/events.h> -#include <linux/iio/buffer.h> - -#include "lis3l02dq.h" - -/* At the moment the spi framework doesn't allow global setting of cs_change. -* It's in the likely to be added comment at the top of spi.h. -* This means that use cannot be made of spi_write etc. -*/ -/* direct copy of the irq_default_primary_handler */ -#ifndef CONFIG_IIO_BUFFER -static irqreturn_t lis3l02dq_nobuffer (int irq,void *private) -{ -return IRQ_WAKE_THREAD ; -} -#endif - -/** -* lis3l02dq_spi_read_reg_8() - read single byte from a single register -* @indio_dev: iio_dev for this actual device -* @reg_address: the address of the register to be read -* @val: pass back the resulting value -**/ -int lis3l02dq_spi_read_reg_8 (struct iio_dev *indio_dev, -u8 reg_address,u8 *val) -{ -struct lis3l02dq_state *st =iio_priv (indio_dev); -int ret; -struct spi_transfer xfer = { - .tx_buf = st->tx, - .rx_buf = st->rx, - .bits_per_word =8 , - .len =2 , - }; - -mutex_lock (&st->buf_lock); - st->tx[0 ] =LIS3L02DQ_READ_REG (reg_address); - st->tx[1 ] =0 ; - - ret =spi_sync_transfer (st->us, &xfer,1 ); - *val = st->rx[1 ]; -mutex_unlock (&st->buf_lock); - -return ret; -} - -/** -* lis3l02dq_spi_write_reg_8() - write single byte to a register -* @indio_dev: iio_dev for this device -* @reg_address: the address of the register to be written -* @val: the value to write -**/ -int lis3l02dq_spi_write_reg_8 (struct iio_dev *indio_dev, -u8 reg_address, -u8 val) -{ -int ret; -struct lis3l02dq_state *st =iio_priv (indio_dev); - -mutex_lock (&st->buf_lock); - st->tx[0 ] =LIS3L02DQ_WRITE_REG (reg_address); - st->tx[1 ] = val; - ret =spi_write (st->us, st->tx,2 ); -mutex_unlock (&st->buf_lock); - -return ret; -} - -/** -* lisl302dq_spi_write_reg_s16() - write 2 bytes to a pair of registers -* @indio_dev: iio_dev for this device -* @lower_reg_address: the address of the lower of the two registers. -* Second register is assumed to have address one greater. -* @value: value to be written -**/ -static int lis3l02dq_spi_write_reg_s16 (struct iio_dev *indio_dev, -u8 lower_reg_address, -s16 value) -{ -int ret; -struct lis3l02dq_state *st =iio_priv (indio_dev); -struct spi_transfer xfers[] = { { - .tx_buf = st->tx, - .bits_per_word =8 , - .len =2 , - .cs_change =1 , - }, { - .tx_buf = st->tx +2 , - .bits_per_word =8 , - .len =2 , - }, - }; - -mutex_lock (&st->buf_lock); - st->tx[0 ] =LIS3L02DQ_WRITE_REG (lower_reg_address); - st->tx[1 ] = value &0xFF ; - st->tx[2 ] =LIS3L02DQ_WRITE_REG (lower_reg_address +1 ); - st->tx[3 ] = (value >>8 ) &0xFF ; - - ret =spi_sync_transfer (st->us, xfers,ARRAY_SIZE (xfers)); -mutex_unlock (&st->buf_lock); - -return ret; -} - -static int lis3l02dq_read_reg_s16 (struct iio_dev *indio_dev, -u8 lower_reg_address, -int *val) -{ -struct lis3l02dq_state *st =iio_priv (indio_dev); -int ret; -s16 tempval; -struct spi_transfer xfers[] = { { - .tx_buf = st->tx, - .rx_buf = st->rx, - .bits_per_word =8 , - .len =2 , - .cs_change =1 , - }, { - .tx_buf = st->tx +2 , - .rx_buf = st->rx +2 , - .bits_per_word =8 , - .len =2 , - }, - }; - -mutex_lock (&st->buf_lock); - st->tx[0 ] =LIS3L02DQ_READ_REG (lower_reg_address); - st->tx[1 ] =0 ; - st->tx[2 ] =LIS3L02DQ_READ_REG (lower_reg_address +1 ); - st->tx[3 ] =0 ; - - ret =spi_sync_transfer (st->us, xfers,ARRAY_SIZE (xfers)); -if (ret) { -dev_err (&st->us->dev,"problem when reading 16 bit register" ); - goto error_ret; - } - tempval = (s16)(st->rx[1 ]) | ((s16)(st->rx[3 ]) <<8 ); - - *val = tempval; -error_ret: -mutex_unlock (&st->buf_lock); -return ret; -} - -enum lis3l02dq_rm_ind { -LIS3L02DQ_ACCEL , -LIS3L02DQ_GAIN , -LIS3L02DQ_BIAS , -}; - -static u8 lis3l02dq_axis_map[3 ][3 ] = { - [LIS3L02DQ_ACCEL ] = {LIS3L02DQ_REG_OUT_X_L_ADDR , -LIS3L02DQ_REG_OUT_Y_L_ADDR , -LIS3L02DQ_REG_OUT_Z_L_ADDR }, - [LIS3L02DQ_GAIN ] = {LIS3L02DQ_REG_GAIN_X_ADDR , -LIS3L02DQ_REG_GAIN_Y_ADDR , -LIS3L02DQ_REG_GAIN_Z_ADDR }, - [LIS3L02DQ_BIAS ] = {LIS3L02DQ_REG_OFFSET_X_ADDR , -LIS3L02DQ_REG_OFFSET_Y_ADDR , -LIS3L02DQ_REG_OFFSET_Z_ADDR } -}; - -static int lis3l02dq_read_thresh (struct iio_dev *indio_dev, -const struct iio_chan_spec *chan, -enum iio_event_type type, -enum iio_event_direction dir, -enum iio_event_info info, -int *val,int *val2) -{ -int ret; - - ret =lis3l02dq_read_reg_s16 (indio_dev,LIS3L02DQ_REG_THS_L_ADDR , val); -if (ret) -return ret; -return IIO_VAL_INT ; -} - -static int lis3l02dq_write_thresh (struct iio_dev *indio_dev, -const struct iio_chan_spec *chan, -enum iio_event_type type, -enum iio_event_direction dir, -enum iio_event_info info, -int val,int val2) -{ -u16 value = val; - -return lis3l02dq_spi_write_reg_s16 (indio_dev, -LIS3L02DQ_REG_THS_L_ADDR , - value); -} - -static int lis3l02dq_write_raw (struct iio_dev *indio_dev, -struct iio_chan_spec const *chan, -int val, -int val2, -long mask) -{ -int ret = -EINVAL , reg; -u8 uval; -s8 sval; - -switch (mask) { -case IIO_CHAN_INFO_CALIBBIAS : -if (val >255 || val <-256 ) -return -EINVAL ; - sval = val; - reg = lis3l02dq_axis_map[LIS3L02DQ_BIAS ][chan->address]; - ret =lis3l02dq_spi_write_reg_8 (indio_dev, reg, sval); -break ; -case IIO_CHAN_INFO_CALIBSCALE : -if (val & ~0xFF ) -return -EINVAL ; - uval = val; - reg = lis3l02dq_axis_map[LIS3L02DQ_GAIN ][chan->address]; - ret =lis3l02dq_spi_write_reg_8 (indio_dev, reg, uval); -break ; - } -return ret; -} - -static int lis3l02dq_read_raw (struct iio_dev *indio_dev, -struct iio_chan_spec const *chan, -int *val, -int *val2, -long mask) -{ -u8 utemp; -s8 stemp; -ssize_t ret =0 ; -u8 reg; - -switch (mask) { -case IIO_CHAN_INFO_RAW : -/* Take the iio_dev status lock */ -mutex_lock (&indio_dev->mlock); -if (indio_dev->currentmode ==INDIO_BUFFER_TRIGGERED ) { - ret = -EBUSY ; - }else { - reg = lis3l02dq_axis_map - [LIS3L02DQ_ACCEL ][chan->address]; - ret =lis3l02dq_read_reg_s16 (indio_dev, reg, val); - } -mutex_unlock (&indio_dev->mlock); -if (ret <0 ) - goto error_ret; -return IIO_VAL_INT ; -case IIO_CHAN_INFO_SCALE : - *val =0 ; - *val2 =9580 ; -return IIO_VAL_INT_PLUS_MICRO ; -case IIO_CHAN_INFO_CALIBSCALE : - reg = lis3l02dq_axis_map[LIS3L02DQ_GAIN ][chan->address]; - ret =lis3l02dq_spi_read_reg_8 (indio_dev, reg, &utemp); -if (ret) - goto error_ret; -/* to match with what previous code does */ - *val = utemp; -return IIO_VAL_INT ; - -case IIO_CHAN_INFO_CALIBBIAS : - reg = lis3l02dq_axis_map[LIS3L02DQ_BIAS ][chan->address]; - ret =lis3l02dq_spi_read_reg_8 (indio_dev, reg, (u8 *)&stemp); -/* to match with what previous code does */ - *val = stemp; -return IIO_VAL_INT ; - } -error_ret: -return ret; -} - -static ssize_t lis3l02dq_read_frequency (struct device *dev, -struct device_attribute *attr, -char *buf) -{ -struct iio_dev *indio_dev =dev_to_iio_dev (dev); -int ret, len =0 ; -s8 t; - - ret =lis3l02dq_spi_read_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_1_ADDR , - (u8 *)&t); -if (ret) -return ret; - t &=LIS3L02DQ_DEC_MASK ; -switch (t) { -case LIS3L02DQ_REG_CTRL_1_DF_128 : - len =sprintf (buf,"280\n" ); -break ; -case LIS3L02DQ_REG_CTRL_1_DF_64 : - len =sprintf (buf,"560\n" ); -break ; -case LIS3L02DQ_REG_CTRL_1_DF_32 : - len =sprintf (buf,"1120\n" ); -break ; -case LIS3L02DQ_REG_CTRL_1_DF_8 : - len =sprintf (buf,"4480\n" ); -break ; - } -return len; -} - -static ssize_t lis3l02dq_write_frequency (struct device *dev, -struct device_attribute *attr, -const char *buf, -size_t len) -{ -struct iio_dev *indio_dev =dev_to_iio_dev (dev); -unsigned long val; -int ret; -u8 t; - - ret =kstrtoul (buf,10 , &val); -if (ret) -return ret; - -mutex_lock (&indio_dev->mlock); - ret =lis3l02dq_spi_read_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_1_ADDR , - &t); -if (ret) - goto error_ret_mutex; -/* Wipe the bits clean */ - t &= ~LIS3L02DQ_DEC_MASK ; -switch (val) { -case 280 : - t |=LIS3L02DQ_REG_CTRL_1_DF_128 ; -break ; -case 560 : - t |=LIS3L02DQ_REG_CTRL_1_DF_64 ; -break ; -case 1120 : - t |=LIS3L02DQ_REG_CTRL_1_DF_32 ; -break ; -case 4480 : - t |=LIS3L02DQ_REG_CTRL_1_DF_8 ; -break ; -default : - ret = -EINVAL ; - goto error_ret_mutex; - } - - ret =lis3l02dq_spi_write_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_1_ADDR , - t); - -error_ret_mutex: -mutex_unlock (&indio_dev->mlock); - -return ret ? ret : len; -} - -static int lis3l02dq_initial_setup (struct iio_dev *indio_dev) -{ -struct lis3l02dq_state *st =iio_priv (indio_dev); -int ret; -u8 val, valtest; - - st->us->mode =SPI_MODE_3 ; - -spi_setup (st->us); - - val =LIS3L02DQ_DEFAULT_CTRL1 ; -/* Write suitable defaults to ctrl1 */ - ret =lis3l02dq_spi_write_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_1_ADDR , - val); -if (ret) { -dev_err (&st->us->dev,"problem with setup control register 1" ); - goto err_ret; - } -/* Repeat as sometimes doesn't work first time? */ - ret =lis3l02dq_spi_write_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_1_ADDR , - val); -if (ret) { -dev_err (&st->us->dev,"problem with setup control register 1" ); - goto err_ret; - } - -/* -* Read back to check this has worked acts as loose test of correct -* chip -*/ - ret =lis3l02dq_spi_read_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_1_ADDR , - &valtest); -if (ret || (valtest != val)) { -dev_err (&indio_dev->dev, -"device not playing ball %d %d\n" , valtest, val); - ret = -EINVAL ; - goto err_ret; - } - - val =LIS3L02DQ_DEFAULT_CTRL2 ; - ret =lis3l02dq_spi_write_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_2_ADDR , - val); -if (ret) { -dev_err (&st->us->dev,"problem with setup control register 2" ); - goto err_ret; - } - - val =LIS3L02DQ_REG_WAKE_UP_CFG_LATCH_SRC ; - ret =lis3l02dq_spi_write_reg_8 (indio_dev, -LIS3L02DQ_REG_WAKE_UP_CFG_ADDR , - val); -if (ret) -dev_err (&st->us->dev,"problem with interrupt cfg register" ); -err_ret: - -return ret; -} - -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, - lis3l02dq_read_frequency, - lis3l02dq_write_frequency); - -static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("280 560 1120 4480"); - -static irqreturn_t lis3l02dq_event_handler (int irq,void *private) -{ -struct iio_dev *indio_dev = private; -u8 t; - -s64 timestamp =iio_get_time_ns (indio_dev); - -lis3l02dq_spi_read_reg_8 (indio_dev, -LIS3L02DQ_REG_WAKE_UP_SRC_ADDR , - &t); - -if (t &LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_HIGH ) -iio_push_event (indio_dev, -IIO_MOD_EVENT_CODE (IIO_ACCEL , -0 , -IIO_MOD_Z , -IIO_EV_TYPE_THRESH , -IIO_EV_DIR_RISING ), - timestamp); - -if (t &LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Z_LOW ) -iio_push_event (indio_dev, -IIO_MOD_EVENT_CODE (IIO_ACCEL , -0 , -IIO_MOD_Z , -IIO_EV_TYPE_THRESH , -IIO_EV_DIR_FALLING ), - timestamp); - -if (t &LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_HIGH ) -iio_push_event (indio_dev, -IIO_MOD_EVENT_CODE (IIO_ACCEL , -0 , -IIO_MOD_Y , -IIO_EV_TYPE_THRESH , -IIO_EV_DIR_RISING ), - timestamp); - -if (t &LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_Y_LOW ) -iio_push_event (indio_dev, -IIO_MOD_EVENT_CODE (IIO_ACCEL , -0 , -IIO_MOD_Y , -IIO_EV_TYPE_THRESH , -IIO_EV_DIR_FALLING ), - timestamp); - -if (t &LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_HIGH ) -iio_push_event (indio_dev, -IIO_MOD_EVENT_CODE (IIO_ACCEL , -0 , -IIO_MOD_X , -IIO_EV_TYPE_THRESH , -IIO_EV_DIR_RISING ), - timestamp); - -if (t &LIS3L02DQ_REG_WAKE_UP_SRC_INTERRUPT_X_LOW ) -iio_push_event (indio_dev, -IIO_MOD_EVENT_CODE (IIO_ACCEL , -0 , -IIO_MOD_X , -IIO_EV_TYPE_THRESH , -IIO_EV_DIR_FALLING ), - timestamp); - -/* Ack and allow for new interrupts */ -lis3l02dq_spi_read_reg_8 (indio_dev, -LIS3L02DQ_REG_WAKE_UP_ACK_ADDR , - &t); - -return IRQ_HANDLED ; -} - -static const struct iio_event_spec lis3l02dq_event[] = { - { - .type =IIO_EV_TYPE_THRESH , - .dir =IIO_EV_DIR_RISING , - .mask_separate =BIT (IIO_EV_INFO_ENABLE ), - .mask_shared_by_type =BIT (IIO_EV_INFO_VALUE ), - }, { - .type =IIO_EV_TYPE_THRESH , - .dir =IIO_EV_DIR_FALLING , - .mask_separate =BIT (IIO_EV_INFO_ENABLE ), - .mask_shared_by_type =BIT (IIO_EV_INFO_VALUE ), - } -}; - -#define LIS3L02DQ_CHAN (index, mod) \ - { \ - .type = IIO_ACCEL, \ - .modified = 1, \ - .channel2 = mod, \ - .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ - BIT(IIO_CHAN_INFO_CALIBSCALE) | \ - BIT(IIO_CHAN_INFO_CALIBBIAS), \ - .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ - .address = index, \ - .scan_index = index, \ - .scan_type = { \ - .sign = 's', \ - .realbits = 12, \ - .storagebits = 16, \ - }, \ - .event_spec = lis3l02dq_event, \ - .num_event_specs = ARRAY_SIZE(lis3l02dq_event), \ - } - -static const struct iio_chan_spec lis3l02dq_channels[] = { -LIS3L02DQ_CHAN (0 ,IIO_MOD_X ), -LIS3L02DQ_CHAN (1 ,IIO_MOD_Y ), -LIS3L02DQ_CHAN (2 ,IIO_MOD_Z ), -IIO_CHAN_SOFT_TIMESTAMP (3 ) -}; - -static int lis3l02dq_read_event_config (struct iio_dev *indio_dev, -const struct iio_chan_spec *chan, -enum iio_event_type type, -enum iio_event_direction dir) -{ -u8 val; -int ret; -u8 mask =1 << (chan->channel2 *2 + (dir ==IIO_EV_DIR_RISING )); - - ret =lis3l02dq_spi_read_reg_8 (indio_dev, -LIS3L02DQ_REG_WAKE_UP_CFG_ADDR , - &val); -if (ret <0 ) -return ret; - -return !!(val & mask); -} - -int lis3l02dq_disable_all_events (struct iio_dev *indio_dev) -{ -int ret; -u8 control, val; - - ret =lis3l02dq_spi_read_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_2_ADDR , - &control); - - control &= ~LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT ; - ret =lis3l02dq_spi_write_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_2_ADDR , - control); -if (ret) - goto error_ret; -/* Also for consistency clear the mask */ - ret =lis3l02dq_spi_read_reg_8 (indio_dev, -LIS3L02DQ_REG_WAKE_UP_CFG_ADDR , - &val); -if (ret) - goto error_ret; - val &= ~0x3f ; - - ret =lis3l02dq_spi_write_reg_8 (indio_dev, -LIS3L02DQ_REG_WAKE_UP_CFG_ADDR , - val); -if (ret) - goto error_ret; - - ret = control; -error_ret: -return ret; -} - -static int lis3l02dq_write_event_config (struct iio_dev *indio_dev, -const struct iio_chan_spec *chan, -enum iio_event_type type, -enum iio_event_direction dir, -int state) -{ -int ret =0 ; -u8 val, control; -u8 currentlyset; -bool changed = false; -u8 mask =1 << (chan->channel2 *2 + (dir ==IIO_EV_DIR_RISING )); - -mutex_lock (&indio_dev->mlock); -/* read current control */ - ret =lis3l02dq_spi_read_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_2_ADDR , - &control); -if (ret) - goto error_ret; - ret =lis3l02dq_spi_read_reg_8 (indio_dev, -LIS3L02DQ_REG_WAKE_UP_CFG_ADDR , - &val); -if (ret <0 ) - goto error_ret; - currentlyset = val & mask; - -if (!currentlyset && state) { - changed = true; - val |= mask; - }else if (currentlyset && !state) { - changed = true; - val &= ~mask; - } - -if (changed) { - ret =lis3l02dq_spi_write_reg_8 (indio_dev, -LIS3L02DQ_REG_WAKE_UP_CFG_ADDR , - val); -if (ret) - goto error_ret; - control = val &0x3f ? - (control |LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT ) : - (control & ~LIS3L02DQ_REG_CTRL_2_ENABLE_INTERRUPT ); - ret =lis3l02dq_spi_write_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_2_ADDR , - control); -if (ret) - goto error_ret; - } - -error_ret: -mutex_unlock (&indio_dev->mlock); -return ret; -} - -static struct attribute *lis3l02dq_attributes[] = { - &iio_dev_attr_sampling_frequency.dev_attr.attr, - &iio_const_attr_sampling_frequency_available.dev_attr.attr, -NULL -}; - -static const struct attribute_group lis3l02dq_attribute_group = { - .attrs = lis3l02dq_attributes, -}; - -static const struct iio_info lis3l02dq_info = { - .read_raw = &lis3l02dq_read_raw, - .write_raw = &lis3l02dq_write_raw, - .read_event_value = &lis3l02dq_read_thresh, - .write_event_value = &lis3l02dq_write_thresh, - .write_event_config = &lis3l02dq_write_event_config, - .read_event_config = &lis3l02dq_read_event_config, - .driver_module =THIS_MODULE , - .attrs = &lis3l02dq_attribute_group, -}; - -static int lis3l02dq_probe (struct spi_device *spi) -{ -int ret; -struct lis3l02dq_state *st; -struct iio_dev *indio_dev; - - indio_dev =devm_iio_device_alloc (&spi->dev,sizeof (*st)); -if (!indio_dev) -return -ENOMEM ; - st =iio_priv (indio_dev); -/* this is only used for removal purposes */ -spi_set_drvdata (spi, indio_dev); - - st->us = spi; - st->gpio =of_get_gpio (spi->dev.of_node,0 ); -mutex_init (&st->buf_lock); - indio_dev->name = spi->dev.driver->name; - indio_dev->dev.parent = &spi->dev; - indio_dev->info = &lis3l02dq_info; - indio_dev->channels = lis3l02dq_channels; - indio_dev->num_channels =ARRAY_SIZE (lis3l02dq_channels); - - indio_dev->modes =INDIO_DIRECT_MODE ; - - ret =lis3l02dq_configure_buffer (indio_dev); -if (ret) -return ret; - -if (spi->irq) { - ret =request_threaded_irq (st->us->irq, - &lis3l02dq_th, - &lis3l02dq_event_handler, -IRQF_TRIGGER_RISING , -"lis3l02dq" , - indio_dev); -if (ret) - goto error_unreg_buffer_funcs; - - ret =lis3l02dq_probe_trigger (indio_dev); -if (ret) - goto error_free_interrupt; - } - -/* Get the device into a sane initial state */ - ret =lis3l02dq_initial_setup (indio_dev); -if (ret) - goto error_remove_trigger; - - ret =iio_device_register (indio_dev); -if (ret) - goto error_remove_trigger; - -return 0 ; - -error_remove_trigger: -if (spi->irq) -lis3l02dq_remove_trigger (indio_dev); -error_free_interrupt: -if (spi->irq) -free_irq (st->us->irq, indio_dev); -error_unreg_buffer_funcs: -lis3l02dq_unconfigure_buffer (indio_dev); -return ret; -} - -/* Power down the device */ -static int lis3l02dq_stop_device (struct iio_dev *indio_dev) -{ -int ret; -struct lis3l02dq_state *st =iio_priv (indio_dev); -u8 val =0 ; - -mutex_lock (&indio_dev->mlock); - ret =lis3l02dq_spi_write_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_1_ADDR , - val); -if (ret) { -dev_err (&st->us->dev,"problem with turning device off: ctrl1" ); - goto err_ret; - } - - ret =lis3l02dq_spi_write_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_2_ADDR , - val); -if (ret) -dev_err (&st->us->dev,"problem with turning device off: ctrl2" ); -err_ret: -mutex_unlock (&indio_dev->mlock); -return ret; -} - -/* fixme, confirm ordering in this function */ -static int lis3l02dq_remove (struct spi_device *spi) -{ -struct iio_dev *indio_dev =spi_get_drvdata (spi); -struct lis3l02dq_state *st =iio_priv (indio_dev); - -iio_device_unregister (indio_dev); - -lis3l02dq_disable_all_events (indio_dev); -lis3l02dq_stop_device (indio_dev); - -if (spi->irq) -free_irq (st->us->irq, indio_dev); - -lis3l02dq_remove_trigger (indio_dev); -lis3l02dq_unconfigure_buffer (indio_dev); - -return 0 ; -} - -static struct spi_driver lis3l02dq_driver = { - .driver = { - .name ="lis3l02dq" , - }, - .probe = lis3l02dq_probe, - .remove = lis3l02dq_remove, -}; -module_spi_driver (lis3l02dq_driver); - -MODULE_AUTHOR ("Jonathan Cameron <[email protected]>" ); -MODULE_DESCRIPTION ("ST LIS3L02DQ Accelerometer SPI driver" ); -MODULE_LICENSE ("GPL v2" ); -MODULE_ALIAS ("spi:lis3l02dq" );drivers/staging/iio/accel/lis3l02dq_ring.c deleted +0
-428@@ -1,428 +0,0 @@ -#include <linux/interrupt.h> -#include <linux/gpio.h> -#include <linux/mutex.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/export.h> - -#include <linux/iio/iio.h> -#include <linux/iio/kfifo_buf.h> -#include <linux/iio/trigger.h> -#include <linux/iio/trigger_consumer.h> -#include "lis3l02dq.h" - -/** -* combine_8_to_16() utility function to munge two u8s into u16 -**/ -static inline u16 combine_8_to_16 (u8 lower,u8 upper) -{ -u16 _lower = lower; -u16 _upper = upper; - -return _lower | (_upper <<8 ); -} - -/** -* lis3l02dq_data_rdy_trig_poll() the event handler for the data rdy trig -**/ -irqreturn_t lis3l02dq_data_rdy_trig_poll (int irq,void *private) -{ -struct iio_dev *indio_dev = private; -struct lis3l02dq_state *st =iio_priv (indio_dev); - -if (st->trigger_on) { -iio_trigger_poll (st->trig); -return IRQ_HANDLED ; - } - -return IRQ_WAKE_THREAD ; -} - -static const u8 read_all_tx_array[] = { -LIS3L02DQ_READ_REG (LIS3L02DQ_REG_OUT_X_L_ADDR ),0 , -LIS3L02DQ_READ_REG (LIS3L02DQ_REG_OUT_X_H_ADDR ),0 , -LIS3L02DQ_READ_REG (LIS3L02DQ_REG_OUT_Y_L_ADDR ),0 , -LIS3L02DQ_READ_REG (LIS3L02DQ_REG_OUT_Y_H_ADDR ),0 , -LIS3L02DQ_READ_REG (LIS3L02DQ_REG_OUT_Z_L_ADDR ),0 , -LIS3L02DQ_READ_REG (LIS3L02DQ_REG_OUT_Z_H_ADDR ),0 , -}; - -/** -* lis3l02dq_read_all() Reads all channels currently selected -* @indio_dev: IIO device state -* @rx_array: (dma capable) receive array, must be at least -* 4*number of channels -**/ -static int lis3l02dq_read_all (struct iio_dev *indio_dev,u8 *rx_array) -{ -struct lis3l02dq_state *st =iio_priv (indio_dev); -struct spi_transfer *xfers; -struct spi_message msg; -int ret, i, j =0 ; - - xfers =kcalloc (bitmap_weight (indio_dev->active_scan_mask, - indio_dev->masklength) *2 , -sizeof (*xfers),GFP_KERNEL ); -if (!xfers) -return -ENOMEM ; - -mutex_lock (&st->buf_lock); - -for (i =0 ; i <ARRAY_SIZE (read_all_tx_array) /4 ; i++) -if (test_bit (i, indio_dev->active_scan_mask)) { -/* lower byte */ - xfers[j].tx_buf = st->tx + (2 * j); - st->tx[2 * j] = read_all_tx_array[i *4 ]; - st->tx[2 * j +1 ] =0 ; -if (rx_array) - xfers[j].rx_buf = rx_array + (j *2 ); - xfers[j].bits_per_word =8 ; - xfers[j].len =2 ; - xfers[j].cs_change =1 ; - j++; - -/* upper byte */ - xfers[j].tx_buf = st->tx + (2 * j); - st->tx[2 * j] = read_all_tx_array[i *4 +2 ]; - st->tx[2 * j +1 ] =0 ; -if (rx_array) - xfers[j].rx_buf = rx_array + (j *2 ); - xfers[j].bits_per_word =8 ; - xfers[j].len =2 ; - xfers[j].cs_change =1 ; - j++; - } - -/* After these are transmitted, the rx_buff should have -* values in alternate bytes -*/ -spi_message_init (&msg); -for (j =0 ; j <bitmap_weight (indio_dev->active_scan_mask, - indio_dev->masklength) *2 ; j++) -spi_message_add_tail (&xfers[j], &msg); - - ret =spi_sync (st->us, &msg); -mutex_unlock (&st->buf_lock); -kfree (xfers); - -return ret; -} - -static int lis3l02dq_get_buffer_element (struct iio_dev *indio_dev, -u8 *buf) -{ -int ret, i; -u8 *rx_array; -s16 *data = (s16 *)buf; -int scan_count =bitmap_weight (indio_dev->active_scan_mask, - indio_dev->masklength); - - rx_array =kcalloc (4 , scan_count,GFP_KERNEL ); -if (!rx_array) -return -ENOMEM ; - ret =lis3l02dq_read_all (indio_dev, rx_array); -if (ret <0 ) { -kfree (rx_array); -return ret; - } -for (i =0 ; i < scan_count; i++) - data[i] =combine_8_to_16 (rx_array[i *4 +1 ], - rx_array[i *4 +3 ]); -kfree (rx_array); - -return i *sizeof (data[0 ]); -} - -static irqreturn_t lis3l02dq_trigger_handler (int irq,void *p) -{ -struct iio_poll_func *pf = p; -struct iio_dev *indio_dev = pf->indio_dev; -int len =0 ; -char *data; - - data =kmalloc (indio_dev->scan_bytes,GFP_KERNEL ); -if (!data) - goto done; - -if (!bitmap_empty (indio_dev->active_scan_mask, indio_dev->masklength)) - len =lis3l02dq_get_buffer_element (indio_dev, data); - -iio_push_to_buffers_with_timestamp (indio_dev, data, pf->timestamp); - -kfree (data); -done: -iio_trigger_notify_done (indio_dev->trig); -return IRQ_HANDLED ; -} - -/* Caller responsible for locking as necessary. */ -static int -__lis3l02dq_write_data_ready_config (struct iio_dev *indio_dev,bool state) -{ -int ret; -u8 valold; -bool currentlyset; -struct lis3l02dq_state *st =iio_priv (indio_dev); - -/* Get the current event mask register */ - ret =lis3l02dq_spi_read_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_2_ADDR , - &valold); -if (ret) - goto error_ret; -/* Find out if data ready is already on */ - currentlyset - = valold &LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION ; - -/* Disable requested */ -if (!state && currentlyset) { -/* Disable the data ready signal */ - valold &= ~LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION ; - -/* The double write is to overcome a hardware bug? */ - ret =lis3l02dq_spi_write_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_2_ADDR , - valold); -if (ret) - goto error_ret; - ret =lis3l02dq_spi_write_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_2_ADDR , - valold); -if (ret) - goto error_ret; - st->trigger_on = false; -/* Enable requested */ - }else if (state && !currentlyset) { -/* If not set, enable requested -* first disable all events -*/ - ret =lis3l02dq_disable_all_events (indio_dev); -if (ret <0 ) - goto error_ret; - - valold = ret | -LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION ; - - st->trigger_on = true; - ret =lis3l02dq_spi_write_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_2_ADDR , - valold); -if (ret) - goto error_ret; - } - -return 0 ; -error_ret: -return ret; -} - -/** -* lis3l02dq_data_rdy_trigger_set_state() set datardy interrupt state -* -* If disabling the interrupt also does a final read to ensure it is clear. -* This is only important in some cases where the scan enable elements are -* switched before the buffer is reenabled. -**/ -static int lis3l02dq_data_rdy_trigger_set_state (struct iio_trigger *trig, -bool state) -{ -struct iio_dev *indio_dev =iio_trigger_get_drvdata (trig); -int ret =0 ; -u8 t; - -__lis3l02dq_write_data_ready_config (indio_dev, state); -if (!state) { -/* -* A possible quirk with the handler is currently worked around -* by ensuring outstanding read events are cleared. -*/ - ret =lis3l02dq_read_all (indio_dev,NULL ); - } -lis3l02dq_spi_read_reg_8 (indio_dev, -LIS3L02DQ_REG_WAKE_UP_SRC_ADDR , - &t); -return ret; -} - -/** -* lis3l02dq_trig_try_reen() try reenabling irq for data rdy trigger -* @trig: the datardy trigger -*/ -static int lis3l02dq_trig_try_reen (struct iio_trigger *trig) -{ -struct iio_dev *indio_dev =iio_trigger_get_drvdata (trig); -struct lis3l02dq_state *st =iio_priv (indio_dev); -int i; - -/* If gpio still high (or high again) -* In theory possible we will need to do this several times -*/ -for (i =0 ; i <5 ; i++) -if (gpio_get_value (st->gpio)) -lis3l02dq_read_all (indio_dev,NULL ); -else -break ; -if (i ==5 ) -pr_info ("Failed to clear the interrupt for lis3l02dq\n" ); - -/* irq reenabled so success! */ -return 0 ; -} - -static const struct iio_trigger_ops lis3l02dq_trigger_ops = { - .owner =THIS_MODULE , - .set_trigger_state = &lis3l02dq_data_rdy_trigger_set_state, - .try_reenable = &lis3l02dq_trig_try_reen, -}; - -int lis3l02dq_probe_trigger (struct iio_dev *indio_dev) -{ -int ret; -struct lis3l02dq_state *st =iio_priv (indio_dev); - - st->trig =iio_trigger_alloc ("lis3l02dq-dev%d" , indio_dev->id); -if (!st->trig) { - ret = -ENOMEM ; - goto error_ret; - } - - st->trig->dev.parent = &st->us->dev; - st->trig->ops = &lis3l02dq_trigger_ops; -iio_trigger_set_drvdata (st->trig, indio_dev); - ret =iio_trigger_register (st->trig); -if (ret) - goto error_free_trig; - -return 0 ; - -error_free_trig: -iio_trigger_free (st->trig); -error_ret: -return ret; -} - -void lis3l02dq_remove_trigger (struct iio_dev *indio_dev) -{ -struct lis3l02dq_state *st =iio_priv (indio_dev); - -iio_trigger_unregister (st->trig); -iio_trigger_free (st->trig); -} - -void lis3l02dq_unconfigure_buffer (struct iio_dev *indio_dev) -{ -iio_dealloc_pollfunc (indio_dev->pollfunc); -iio_kfifo_free (indio_dev->buffer); -} - -static int lis3l02dq_buffer_postenable (struct iio_dev *indio_dev) -{ -/* Disable unwanted channels otherwise the interrupt will not clear */ -u8 t; -int ret; -bool oneenabled = false; - - ret =lis3l02dq_spi_read_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_1_ADDR , - &t); -if (ret) - goto error_ret; - -if (test_bit (0 , indio_dev->active_scan_mask)) { - t |=LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE ; - oneenabled = true; - }else { - t &= ~LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE ; - } -if (test_bit (1 , indio_dev->active_scan_mask)) { - t |=LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE ; - oneenabled = true; - }else { - t &= ~LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE ; - } -if (test_bit (2 , indio_dev->active_scan_mask)) { - t |=LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE ; - oneenabled = true; - }else { - t &= ~LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE ; - } -if (!oneenabled)/* what happens in this case is unknown */ -return -EINVAL ; - ret =lis3l02dq_spi_write_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_1_ADDR , - t); -if (ret) - goto error_ret; - -return iio_triggered_buffer_postenable (indio_dev); -error_ret: -return ret; -} - -/* Turn all channels on again */ -static int lis3l02dq_buffer_predisable (struct iio_dev *indio_dev) -{ -u8 t; -int ret; - - ret =iio_triggered_buffer_predisable (indio_dev); -if (ret) - goto error_ret; - - ret =lis3l02dq_spi_read_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_1_ADDR , - &t); -if (ret) - goto error_ret; - t |=LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE | -LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE | -LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE ; - - ret =lis3l02dq_spi_write_reg_8 (indio_dev, -LIS3L02DQ_REG_CTRL_1_ADDR , - t); - -error_ret: -return ret; -} - -static const struct iio_buffer_setup_ops lis3l02dq_buffer_setup_ops = { - .postenable = &lis3l02dq_buffer_postenable, - .predisable = &lis3l02dq_buffer_predisable, -}; - -int lis3l02dq_configure_buffer (struct iio_dev *indio_dev) -{ -int ret; -struct iio_buffer *buffer; - - buffer =iio_kfifo_allocate (); -if (!buffer) -return -ENOMEM ; - -iio_device_attach_buffer (indio_dev, buffer); - - buffer->scan_timestamp = true; - indio_dev->setup_ops = &lis3l02dq_buffer_setup_ops; - -/* Functions are NULL as we set handler below */ - indio_dev->pollfunc =iio_alloc_pollfunc (&iio_pollfunc_store_time, - &lis3l02dq_trigger_handler, -0 , - indio_dev, -"lis3l02dq_consumer%d" , - indio_dev->id); - -if (!indio_dev->pollfunc) { - ret = -ENOMEM ; - goto error_iio_sw_rb_free; - } - - indio_dev->modes |=INDIO_BUFFER_TRIGGERED ; -return 0 ; - -error_iio_sw_rb_free: -iio_kfifo_free (indio_dev->buffer); -return ret; -}