2019-04-02 13:31:55 +03:00
// SPDX-License-Identifier: GPL-2.0+
2010-10-28 05:43:53 +04:00
/*
* AD7150 capacitive sensor driver supporting AD7150 / 1 / 6
*
2011-09-02 20:25:22 +04:00
* Copyright 2010 - 2011 Analog Devices Inc .
2021-03-14 21:15:09 +03:00
* Copyright 2021 Jonathan Cameron < Jonathan . Cameron @ huawei . com >
2010-10-28 05:43:53 +04:00
*/
2019-05-19 04:04:56 +03:00
# include <linux/bitfield.h>
2010-10-28 05:43:53 +04:00
# include <linux/device.h>
2021-03-14 21:15:01 +03:00
# include <linux/interrupt.h>
2021-03-14 21:14:59 +03:00
# include <linux/irq.h>
2021-03-14 21:15:01 +03:00
# include <linux/i2c.h>
# include <linux/kernel.h>
2011-07-03 23:49:50 +04:00
# include <linux/module.h>
2021-03-14 21:15:07 +03:00
# include <linux/mod_devicetable.h>
2021-03-14 21:15:06 +03:00
# include <linux/regulator/consumer.h>
2021-03-14 21:15:01 +03:00
# include <linux/slab.h>
2010-10-28 05:43:53 +04:00
2012-04-25 18:54:58 +04:00
# include <linux/iio/iio.h>
# include <linux/iio/sysfs.h>
# include <linux/iio/events.h>
2010-10-28 05:43:53 +04:00
2021-03-14 21:15:00 +03:00
# define AD7150_STATUS_REG 0
# define AD7150_STATUS_OUT1 BIT(3)
# define AD7150_STATUS_OUT2 BIT(5)
# define AD7150_CH1_DATA_HIGH_REG 1
# define AD7150_CH2_DATA_HIGH_REG 3
# define AD7150_CH1_AVG_HIGH_REG 5
# define AD7150_CH2_AVG_HIGH_REG 7
# define AD7150_CH1_SENSITIVITY_REG 9
# define AD7150_CH1_THR_HOLD_H_REG 9
# define AD7150_CH1_TIMEOUT_REG 10
# define AD7150_CH_TIMEOUT_RECEDING GENMASK(3, 0)
# define AD7150_CH_TIMEOUT_APPROACHING GENMASK(7, 4)
# define AD7150_CH1_SETUP_REG 11
# define AD7150_CH2_SENSITIVITY_REG 12
# define AD7150_CH2_THR_HOLD_H_REG 12
# define AD7150_CH2_TIMEOUT_REG 13
# define AD7150_CH2_SETUP_REG 14
# define AD7150_CFG_REG 15
# define AD7150_CFG_FIX BIT(7)
# define AD7150_CFG_THRESHTYPE_MSK GENMASK(6, 5)
# define AD7150_CFG_TT_NEG 0x0
# define AD7150_CFG_TT_POS 0x1
# define AD7150_CFG_TT_IN_WINDOW 0x2
# define AD7150_CFG_TT_OUT_WINDOW 0x3
# define AD7150_PD_TIMER_REG 16
# define AD7150_CH1_CAPDAC_REG 17
# define AD7150_CH2_CAPDAC_REG 18
# define AD7150_SN3_REG 19
# define AD7150_SN2_REG 20
# define AD7150_SN1_REG 21
# define AD7150_SN0_REG 22
# define AD7150_ID_REG 23
2021-03-14 21:14:53 +03:00
enum {
AD7150 ,
AD7151 ,
} ;
2011-09-02 20:25:20 +04:00
/**
* struct ad7150_chip_info - instance specific chip data
* @ client : i2c client for this device
* @ threshold : thresholds for simple capacitance value events
* @ thresh_sensitivity : threshold for simple capacitance offset
* from ' average ' value .
* @ thresh_timeout : a timeout , in samples from the moment an
* adaptive threshold event occurs to when the average
2021-03-14 21:14:51 +03:00
* value jumps to current value . Note made up of two fields ,
* 3 : 0 are for timeout receding - applies if below lower threshold
* 7 : 4 are for timeout approaching - applies if above upper threshold
2011-09-02 20:25:20 +04:00
* @ state_lock : ensure consistent state of this structure wrt the
* hardware .
2021-03-14 21:14:59 +03:00
* @ interrupts : one or two interrupt numbers depending on device type .
* @ int_enabled : is a given interrupt currently enabled .
* @ type : threshold type
* @ dir : threshold direction
2011-09-02 20:25:20 +04:00
*/
2010-10-28 05:43:53 +04:00
struct ad7150_chip_info {
struct i2c_client * client ;
2011-09-02 20:25:20 +04:00
u16 threshold [ 2 ] [ 2 ] ;
u8 thresh_sensitivity [ 2 ] [ 2 ] ;
u8 thresh_timeout [ 2 ] [ 2 ] ;
struct mutex state_lock ;
2021-03-14 21:14:59 +03:00
int interrupts [ 2 ] ;
bool int_enabled [ 2 ] ;
enum iio_event_type type ;
enum iio_event_direction dir ;
2010-10-28 05:43:53 +04:00
} ;
2011-09-02 20:25:20 +04:00
static const u8 ad7150_addresses [ ] [ 6 ] = {
2021-03-14 21:15:00 +03:00
{ AD7150_CH1_DATA_HIGH_REG , AD7150_CH1_AVG_HIGH_REG ,
AD7150_CH1_SETUP_REG , AD7150_CH1_THR_HOLD_H_REG ,
AD7150_CH1_SENSITIVITY_REG , AD7150_CH1_TIMEOUT_REG } ,
{ AD7150_CH2_DATA_HIGH_REG , AD7150_CH2_AVG_HIGH_REG ,
AD7150_CH2_SETUP_REG , AD7150_CH2_THR_HOLD_H_REG ,
AD7150_CH2_SENSITIVITY_REG , AD7150_CH2_TIMEOUT_REG } ,
2011-09-02 20:25:20 +04:00
} ;
2010-10-28 05:43:53 +04:00
2011-09-02 20:25:20 +04:00
static int ad7150_read_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int * val ,
int * val2 ,
long mask )
2010-10-28 05:43:53 +04:00
{
2011-09-02 20:25:20 +04:00
struct ad7150_chip_info * chip = iio_priv ( indio_dev ) ;
2018-10-05 11:04:44 +03:00
int channel = chan - > channel ;
2021-03-14 21:15:02 +03:00
int ret ;
2010-10-28 05:43:53 +04:00
2011-09-02 20:25:20 +04:00
switch ( mask ) {
2012-04-15 20:41:26 +04:00
case IIO_CHAN_INFO_RAW :
2021-03-14 21:14:48 +03:00
ret = i2c_smbus_read_word_swapped ( chip - > client ,
ad7150_addresses [ channel ] [ 0 ] ) ;
2011-09-02 20:25:20 +04:00
if ( ret < 0 )
return ret ;
2021-03-14 21:15:04 +03:00
* val = ret > > 4 ;
2021-03-14 21:14:48 +03:00
2011-09-02 20:25:20 +04:00
return IIO_VAL_INT ;
2011-10-26 20:41:36 +04:00
case IIO_CHAN_INFO_AVERAGE_RAW :
2021-03-14 21:14:48 +03:00
ret = i2c_smbus_read_word_swapped ( chip - > client ,
ad7150_addresses [ channel ] [ 1 ] ) ;
2011-09-02 20:25:20 +04:00
if ( ret < 0 )
return ret ;
2021-03-14 21:14:48 +03:00
* val = ret ;
2021-03-14 21:15:05 +03:00
return IIO_VAL_INT ;
case IIO_CHAN_INFO_SCALE :
/*
* Base units for capacitance are nano farads and the value
* calculated from the datasheet formula is in picofarad
* so multiply by 1000
*/
* val = 1000 ;
* val2 = 40944 > > 4 ; /* To match shift in _RAW */
return IIO_VAL_FRACTIONAL ;
case IIO_CHAN_INFO_OFFSET :
* val = - ( 12288 > > 4 ) ; /* To match shift in _RAW */
2021-03-14 21:14:56 +03:00
return IIO_VAL_INT ;
case IIO_CHAN_INFO_SAMP_FREQ :
/* Strangely same for both 1 and 2 chan parts */
* val = 100 ;
2011-09-02 20:25:20 +04:00
return IIO_VAL_INT ;
default :
return - EINVAL ;
2010-10-28 05:43:53 +04:00
}
}
2013-10-07 18:11:00 +04:00
static int ad7150_read_event_config ( struct iio_dev * indio_dev ,
2018-03-09 02:56:07 +03:00
const struct iio_chan_spec * chan ,
enum iio_event_type type ,
enum iio_event_direction dir )
2010-10-28 05:43:53 +04:00
{
2021-03-14 21:15:02 +03:00
struct ad7150_chip_info * chip = iio_priv ( indio_dev ) ;
2011-09-02 20:25:20 +04:00
u8 threshtype ;
2019-05-19 04:04:56 +03:00
bool thrfixed ;
2021-03-14 21:15:02 +03:00
int ret ;
2010-10-28 05:43:53 +04:00
2021-03-14 21:15:00 +03:00
ret = i2c_smbus_read_byte_data ( chip - > client , AD7150_CFG_REG ) ;
2011-09-02 20:25:20 +04:00
if ( ret < 0 )
return ret ;
2010-10-28 05:43:53 +04:00
2021-03-14 21:15:00 +03:00
threshtype = FIELD_GET ( AD7150_CFG_THRESHTYPE_MSK , ret ) ;
2019-05-19 04:04:56 +03:00
/*check if threshold mode is fixed or adaptive*/
thrfixed = FIELD_GET ( AD7150_CFG_FIX , ret ) ;
2011-09-02 20:25:20 +04:00
2013-10-07 18:11:00 +04:00
switch ( type ) {
2011-09-02 20:25:20 +04:00
case IIO_EV_TYPE_THRESH_ADAPTIVE :
2013-10-07 18:11:00 +04:00
if ( dir = = IIO_EV_DIR_RISING )
2021-03-14 21:15:00 +03:00
return ! thrfixed & & ( threshtype = = AD7150_CFG_TT_POS ) ;
return ! thrfixed & & ( threshtype = = AD7150_CFG_TT_NEG ) ;
2011-09-02 20:25:20 +04:00
case IIO_EV_TYPE_THRESH :
2013-10-07 18:11:00 +04:00
if ( dir = = IIO_EV_DIR_RISING )
2021-03-14 21:15:00 +03:00
return thrfixed & & ( threshtype = = AD7150_CFG_TT_POS ) ;
return thrfixed & & ( threshtype = = AD7150_CFG_TT_NEG ) ;
2013-10-07 18:11:00 +04:00
default :
break ;
2012-09-28 13:57:00 +04:00
}
2010-10-28 05:43:53 +04:00
return - EINVAL ;
}
2021-03-14 21:15:03 +03:00
/* state_lock should be held to ensure consistent state */
2013-10-07 18:11:00 +04:00
static int ad7150_write_event_params ( struct iio_dev * indio_dev ,
2015-12-29 14:27:31 +03:00
unsigned int chan ,
enum iio_event_type type ,
enum iio_event_direction dir )
2010-10-28 05:43:53 +04:00
{
2011-09-02 20:25:20 +04:00
struct ad7150_chip_info * chip = iio_priv ( indio_dev ) ;
2013-10-07 18:11:00 +04:00
int rising = ( dir = = IIO_EV_DIR_RISING ) ;
2021-03-14 21:14:59 +03:00
/* Only update value live, if parameter is in use */
if ( ( type ! = chip - > type ) | | ( dir ! = chip - > dir ) )
2011-09-02 20:25:20 +04:00
return 0 ;
2013-10-07 18:11:00 +04:00
switch ( type ) {
2011-09-02 20:25:20 +04:00
/* Note completely different from the adaptive versions */
2021-03-14 21:14:50 +03:00
case IIO_EV_TYPE_THRESH : {
u16 value = chip - > threshold [ rising ] [ chan ] ;
2021-03-14 21:14:48 +03:00
return i2c_smbus_write_word_swapped ( chip - > client ,
ad7150_addresses [ chan ] [ 3 ] ,
value ) ;
2021-03-14 21:14:50 +03:00
}
case IIO_EV_TYPE_THRESH_ADAPTIVE : {
int ret ;
u8 sens , timeout ;
2011-09-02 20:25:20 +04:00
sens = chip - > thresh_sensitivity [ rising ] [ chan ] ;
2021-03-14 21:14:50 +03:00
ret = i2c_smbus_write_byte_data ( chip - > client ,
ad7150_addresses [ chan ] [ 4 ] ,
sens ) ;
if ( ret )
return ret ;
2021-03-14 21:14:51 +03:00
/*
* Single timeout register contains timeouts for both
* directions .
*/
timeout = FIELD_PREP ( AD7150_CH_TIMEOUT_APPROACHING ,
chip - > thresh_timeout [ 1 ] [ chan ] ) ;
timeout | = FIELD_PREP ( AD7150_CH_TIMEOUT_RECEDING ,
chip - > thresh_timeout [ 0 ] [ chan ] ) ;
2021-03-14 21:14:50 +03:00
return i2c_smbus_write_byte_data ( chip - > client ,
ad7150_addresses [ chan ] [ 5 ] ,
timeout ) ;
}
2011-09-02 20:25:20 +04:00
default :
return - EINVAL ;
2012-09-28 13:57:00 +04:00
}
2010-10-28 05:43:53 +04:00
}
2011-09-02 20:25:20 +04:00
static int ad7150_write_event_config ( struct iio_dev * indio_dev ,
2015-12-29 14:27:31 +03:00
const struct iio_chan_spec * chan ,
enum iio_event_type type ,
enum iio_event_direction dir , int state )
2010-10-28 05:43:53 +04:00
{
2011-09-02 20:25:20 +04:00
struct ad7150_chip_info * chip = iio_priv ( indio_dev ) ;
2021-04-06 11:23:37 +03:00
int ret = 0 ;
2010-10-28 05:43:53 +04:00
2021-03-14 21:14:59 +03:00
/*
* There is only a single shared control and no on chip
* interrupt disables for the two interrupt lines .
* So , enabling will switch the events configured to enable
* whatever was most recently requested and if necessary enable_irq ( )
* the interrupt and any disable will disable_irq ( ) for that
* channels interrupt .
*/
if ( ! state ) {
if ( ( chip - > int_enabled [ chan - > channel ] ) & &
( type = = chip - > type ) & & ( dir = = chip - > dir ) ) {
disable_irq ( chip - > interrupts [ chan - > channel ] ) ;
chip - > int_enabled [ chan - > channel ] = false ;
}
2011-09-02 20:25:20 +04:00
return 0 ;
2021-03-14 21:14:59 +03:00
}
2011-09-02 20:25:20 +04:00
mutex_lock ( & chip - > state_lock ) ;
2021-03-14 21:14:59 +03:00
if ( ( type ! = chip - > type ) | | ( dir ! = chip - > dir ) ) {
2021-03-14 21:15:02 +03:00
int rising = ( dir = = IIO_EV_DIR_RISING ) ;
u8 thresh_type , cfg , fixed ;
2010-10-28 05:43:53 +04:00
2021-03-14 21:14:59 +03:00
/*
* Need to temporarily disable both interrupts if
* enabled - this is to avoid races around changing
* config and thresholds .
* Note enable / disable_irq ( ) are reference counted so
* no need to check if already enabled .
*/
disable_irq ( chip - > interrupts [ 0 ] ) ;
disable_irq ( chip - > interrupts [ 1 ] ) ;
2011-09-02 20:25:20 +04:00
2021-03-14 21:15:00 +03:00
ret = i2c_smbus_read_byte_data ( chip - > client , AD7150_CFG_REG ) ;
2021-03-14 21:14:59 +03:00
if ( ret < 0 )
goto error_ret ;
2010-10-28 05:43:53 +04:00
2021-03-14 21:15:00 +03:00
cfg = ret & ~ ( AD7150_CFG_THRESHTYPE_MSK | AD7150_CFG_FIX ) ;
2010-10-28 05:43:53 +04:00
2021-03-14 21:15:00 +03:00
if ( type = = IIO_EV_TYPE_THRESH_ADAPTIVE )
fixed = 0 ;
else
fixed = 1 ;
if ( rising )
thresh_type = AD7150_CFG_TT_POS ;
else
thresh_type = AD7150_CFG_TT_NEG ;
2010-10-28 05:43:53 +04:00
2021-03-14 21:15:00 +03:00
cfg | = FIELD_PREP ( AD7150_CFG_FIX , fixed ) |
FIELD_PREP ( AD7150_CFG_THRESHTYPE_MSK , thresh_type ) ;
2021-03-14 21:14:59 +03:00
2021-03-14 21:15:00 +03:00
ret = i2c_smbus_write_byte_data ( chip - > client , AD7150_CFG_REG ,
cfg ) ;
2021-03-14 21:14:59 +03:00
if ( ret < 0 )
goto error_ret ;
/*
* There is a potential race condition here , but not easy
* to close given we can ' t disable the interrupt at the
* chip side of things . Rely on the status bit .
*/
chip - > type = type ;
chip - > dir = dir ;
/* update control attributes */
ret = ad7150_write_event_params ( indio_dev , chan - > channel , type ,
dir ) ;
if ( ret )
goto error_ret ;
/* reenable any irq's we disabled whilst changing mode */
enable_irq ( chip - > interrupts [ 0 ] ) ;
enable_irq ( chip - > interrupts [ 1 ] ) ;
}
if ( ! chip - > int_enabled [ chan - > channel ] ) {
enable_irq ( chip - > interrupts [ chan - > channel ] ) ;
chip - > int_enabled [ chan - > channel ] = true ;
}
2010-10-28 05:43:53 +04:00
2011-09-02 20:25:20 +04:00
error_ret :
mutex_unlock ( & chip - > state_lock ) ;
2010-10-28 05:43:53 +04:00
2016-12-03 16:44:30 +03:00
return ret ;
2010-10-28 05:43:53 +04:00
}
2011-09-02 20:25:20 +04:00
static int ad7150_read_event_value ( struct iio_dev * indio_dev ,
2013-10-07 18:11:00 +04:00
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 )
2010-10-28 05:43:53 +04:00
{
2011-09-02 20:25:20 +04:00
struct ad7150_chip_info * chip = iio_priv ( indio_dev ) ;
2013-10-07 18:11:00 +04:00
int rising = ( dir = = IIO_EV_DIR_RISING ) ;
2010-10-28 05:43:53 +04:00
2011-09-02 20:25:20 +04:00
/* Complex register sharing going on here */
2021-03-14 21:14:58 +03:00
switch ( info ) {
case IIO_EV_INFO_VALUE :
switch ( type ) {
case IIO_EV_TYPE_THRESH_ADAPTIVE :
* val = chip - > thresh_sensitivity [ rising ] [ chan - > channel ] ;
return IIO_VAL_INT ;
case IIO_EV_TYPE_THRESH :
* val = chip - > threshold [ rising ] [ chan - > channel ] ;
return IIO_VAL_INT ;
default :
return - EINVAL ;
}
case IIO_EV_INFO_TIMEOUT :
* val = 0 ;
* val2 = chip - > thresh_timeout [ rising ] [ chan - > channel ] * 10000 ;
return IIO_VAL_INT_PLUS_MICRO ;
2011-09-02 20:25:20 +04:00
default :
return - EINVAL ;
2013-10-11 03:07:59 +04:00
}
2010-10-28 05:43:53 +04:00
}
2011-09-02 20:25:20 +04:00
static int ad7150_write_event_value ( struct iio_dev * indio_dev ,
2015-12-29 14:27:31 +03:00
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 )
2010-10-28 05:43:53 +04:00
{
int ret ;
2011-09-02 20:25:20 +04:00
struct ad7150_chip_info * chip = iio_priv ( indio_dev ) ;
2013-10-07 18:11:00 +04:00
int rising = ( dir = = IIO_EV_DIR_RISING ) ;
2011-09-02 20:25:20 +04:00
mutex_lock ( & chip - > state_lock ) ;
2021-03-14 21:14:58 +03:00
switch ( info ) {
case IIO_EV_INFO_VALUE :
switch ( type ) {
case IIO_EV_TYPE_THRESH_ADAPTIVE :
chip - > thresh_sensitivity [ rising ] [ chan - > channel ] = val ;
break ;
case IIO_EV_TYPE_THRESH :
chip - > threshold [ rising ] [ chan - > channel ] = val ;
break ;
default :
ret = - EINVAL ;
goto error_ret ;
}
2011-09-02 20:25:20 +04:00
break ;
2021-03-14 21:14:58 +03:00
case IIO_EV_INFO_TIMEOUT : {
/*
* Raw timeout is in cycles of 10 msecs as long as both
* channels are enabled .
* In terms of INT_PLUS_MICRO , that is in units of 10 , 000
*/
int timeout = val2 / 10000 ;
if ( val ! = 0 | | timeout < 0 | | timeout > 15 | | val2 % 10000 ) {
ret = - EINVAL ;
goto error_ret ;
}
chip - > thresh_timeout [ rising ] [ chan - > channel ] = timeout ;
2011-09-02 20:25:20 +04:00
break ;
2021-03-14 21:14:58 +03:00
}
2011-09-02 20:25:20 +04:00
default :
ret = - EINVAL ;
goto error_ret ;
2012-09-28 13:57:00 +04:00
}
2010-10-28 05:43:53 +04:00
2011-09-02 20:25:20 +04:00
/* write back if active */
2013-10-07 18:11:00 +04:00
ret = ad7150_write_event_params ( indio_dev , chan - > channel , type , dir ) ;
2010-10-28 05:43:53 +04:00
2011-09-02 20:25:20 +04:00
error_ret :
2011-10-06 10:17:00 +04:00
mutex_unlock ( & chip - > state_lock ) ;
2011-09-02 20:25:20 +04:00
return ret ;
2010-10-28 05:43:53 +04:00
}
2013-10-07 18:11:00 +04:00
static const struct iio_event_spec ad7150_events [ ] = {
{
. type = IIO_EV_TYPE_THRESH ,
. dir = IIO_EV_DIR_RISING ,
. mask_separate = BIT ( IIO_EV_INFO_VALUE ) |
BIT ( IIO_EV_INFO_ENABLE ) ,
} , {
. type = IIO_EV_TYPE_THRESH ,
. dir = IIO_EV_DIR_FALLING ,
. mask_separate = BIT ( IIO_EV_INFO_VALUE ) |
BIT ( IIO_EV_INFO_ENABLE ) ,
} , {
. type = IIO_EV_TYPE_THRESH_ADAPTIVE ,
. dir = IIO_EV_DIR_RISING ,
. mask_separate = BIT ( IIO_EV_INFO_VALUE ) |
2021-03-14 21:14:58 +03:00
BIT ( IIO_EV_INFO_ENABLE ) |
BIT ( IIO_EV_INFO_TIMEOUT ) ,
2013-10-07 18:11:00 +04:00
} , {
. type = IIO_EV_TYPE_THRESH_ADAPTIVE ,
. dir = IIO_EV_DIR_FALLING ,
. mask_separate = BIT ( IIO_EV_INFO_VALUE ) |
2021-03-14 21:14:58 +03:00
BIT ( IIO_EV_INFO_ENABLE ) |
BIT ( IIO_EV_INFO_TIMEOUT ) ,
2013-10-07 18:11:00 +04:00
} ,
} ;
2019-05-19 01:41:36 +03:00
# define AD7150_CAPACITANCE_CHAN(_chan) { \
. type = IIO_CAPACITANCE , \
. indexed = 1 , \
. channel = _chan , \
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) | \
BIT ( IIO_CHAN_INFO_AVERAGE_RAW ) , \
2021-03-14 21:15:05 +03:00
. info_mask_shared_by_type = BIT ( IIO_CHAN_INFO_SCALE ) | \
BIT ( IIO_CHAN_INFO_OFFSET ) , \
2021-03-14 21:14:56 +03:00
. info_mask_shared_by_all = BIT ( IIO_CHAN_INFO_SAMP_FREQ ) , \
2019-05-19 01:41:36 +03:00
. event_spec = ad7150_events , \
. num_event_specs = ARRAY_SIZE ( ad7150_events ) , \
}
2021-03-14 21:14:53 +03:00
# define AD7150_CAPACITANCE_CHAN_NO_IRQ(_chan) { \
. type = IIO_CAPACITANCE , \
. indexed = 1 , \
. channel = _chan , \
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) | \
BIT ( IIO_CHAN_INFO_AVERAGE_RAW ) , \
2021-03-14 21:15:05 +03:00
. info_mask_shared_by_type = BIT ( IIO_CHAN_INFO_SCALE ) | \
BIT ( IIO_CHAN_INFO_OFFSET ) , \
2021-03-14 21:14:56 +03:00
. info_mask_shared_by_all = BIT ( IIO_CHAN_INFO_SAMP_FREQ ) , \
2021-03-14 21:14:53 +03:00
}
2011-09-02 20:25:20 +04:00
static const struct iio_chan_spec ad7150_channels [ ] = {
2019-05-19 01:41:36 +03:00
AD7150_CAPACITANCE_CHAN ( 0 ) ,
2021-03-14 21:14:53 +03:00
AD7150_CAPACITANCE_CHAN ( 1 ) ,
} ;
static const struct iio_chan_spec ad7150_channels_no_irq [ ] = {
AD7150_CAPACITANCE_CHAN_NO_IRQ ( 0 ) ,
AD7150_CAPACITANCE_CHAN_NO_IRQ ( 1 ) ,
} ;
static const struct iio_chan_spec ad7151_channels [ ] = {
AD7150_CAPACITANCE_CHAN ( 0 ) ,
} ;
static const struct iio_chan_spec ad7151_channels_no_irq [ ] = {
AD7150_CAPACITANCE_CHAN_NO_IRQ ( 0 ) ,
2011-09-02 20:25:20 +04:00
} ;
2010-10-28 05:43:53 +04:00
2021-03-14 21:14:59 +03:00
static irqreturn_t __ad7150_event_handler ( void * private , u8 status_mask ,
int channel )
2010-10-28 05:43:53 +04:00
{
2011-05-18 17:41:08 +04:00
struct iio_dev * indio_dev = private ;
2011-06-27 16:07:21 +04:00
struct ad7150_chip_info * chip = iio_priv ( indio_dev ) ;
2016-03-09 21:05:49 +03:00
s64 timestamp = iio_get_time_ns ( indio_dev ) ;
2021-03-14 21:14:59 +03:00
int int_status ;
2010-10-28 05:43:53 +04:00
2021-03-14 21:15:00 +03:00
int_status = i2c_smbus_read_byte_data ( chip - > client , AD7150_STATUS_REG ) ;
2021-03-14 21:14:59 +03:00
if ( int_status < 0 )
2011-09-02 20:25:20 +04:00
return IRQ_HANDLED ;
2021-03-14 21:14:59 +03:00
if ( ! ( int_status & status_mask ) )
return IRQ_HANDLED ;
iio_push_event ( indio_dev ,
IIO_UNMOD_EVENT_CODE ( IIO_CAPACITANCE , channel ,
chip - > type , chip - > dir ) ,
timestamp ) ;
2011-09-02 20:25:20 +04:00
2011-05-18 17:41:08 +04:00
return IRQ_HANDLED ;
2010-10-28 05:43:53 +04:00
}
2021-03-14 21:14:59 +03:00
static irqreturn_t ad7150_event_handler_ch1 ( int irq , void * private )
{
return __ad7150_event_handler ( private , AD7150_STATUS_OUT1 , 0 ) ;
}
static irqreturn_t ad7150_event_handler_ch2 ( int irq , void * private )
{
return __ad7150_event_handler ( private , AD7150_STATUS_OUT2 , 1 ) ;
}
2021-03-14 21:14:58 +03:00
static IIO_CONST_ATTR ( in_capacitance_thresh_adaptive_timeout_available ,
" [0 0.01 0.15] " ) ;
2010-10-28 05:43:53 +04:00
static struct attribute * ad7150_event_attributes [ ] = {
2021-03-14 21:14:58 +03:00
& iio_const_attr_in_capacitance_thresh_adaptive_timeout_available
2011-09-02 20:25:20 +04:00
. dev_attr . attr ,
2010-10-28 05:43:53 +04:00
NULL ,
} ;
2016-10-01 22:15:15 +03:00
static const struct attribute_group ad7150_event_attribute_group = {
2010-10-28 05:43:53 +04:00
. attrs = ad7150_event_attributes ,
2011-08-30 15:32:45 +04:00
. name = " events " ,
2010-10-28 05:43:53 +04:00
} ;
2011-05-18 17:42:37 +04:00
static const struct iio_info ad7150_info = {
. event_attrs = & ad7150_event_attribute_group ,
2011-09-02 20:25:20 +04:00
. read_raw = & ad7150_read_raw ,
2013-12-07 14:45:00 +04:00
. read_event_config = & ad7150_read_event_config ,
. write_event_config = & ad7150_write_event_config ,
. read_event_value = & ad7150_read_event_value ,
. write_event_value = & ad7150_write_event_value ,
2011-05-18 17:42:37 +04:00
} ;
2011-09-02 20:25:20 +04:00
2021-03-14 21:14:53 +03:00
static const struct iio_info ad7150_info_no_irq = {
. read_raw = & ad7150_read_raw ,
} ;
2021-03-14 21:15:06 +03:00
static void ad7150_reg_disable ( void * data )
{
struct regulator * reg = data ;
regulator_disable ( reg ) ;
}
2012-11-19 22:21:57 +04:00
static int ad7150_probe ( struct i2c_client * client ,
2015-12-29 14:27:31 +03:00
const struct i2c_device_id * id )
2010-10-28 05:43:53 +04:00
{
2011-06-27 16:07:21 +04:00
struct ad7150_chip_info * chip ;
struct iio_dev * indio_dev ;
2021-03-14 21:15:06 +03:00
struct regulator * reg ;
2021-03-14 21:15:02 +03:00
int ret ;
2011-06-27 16:07:21 +04:00
2013-08-24 23:24:00 +04:00
indio_dev = devm_iio_device_alloc ( & client - > dev , sizeof ( * chip ) ) ;
if ( ! indio_dev )
return - ENOMEM ;
2021-03-14 21:14:55 +03:00
2011-06-27 16:07:21 +04:00
chip = iio_priv ( indio_dev ) ;
2011-09-02 20:25:20 +04:00
mutex_init ( & chip - > state_lock ) ;
2010-10-28 05:43:53 +04:00
chip - > client = client ;
2011-06-27 16:07:21 +04:00
indio_dev - > name = id - > name ;
2011-05-18 17:42:37 +04:00
2011-06-27 16:07:21 +04:00
indio_dev - > modes = INDIO_DIRECT_MODE ;
2010-10-28 05:43:53 +04:00
2021-03-14 21:15:06 +03:00
reg = devm_regulator_get ( & client - > dev , " vdd " ) ;
if ( IS_ERR ( reg ) )
return PTR_ERR ( reg ) ;
ret = regulator_enable ( reg ) ;
if ( ret )
return ret ;
ret = devm_add_action_or_reset ( & client - > dev , ad7150_reg_disable , reg ) ;
if ( ret )
return ret ;
2021-03-14 21:14:59 +03:00
chip - > interrupts [ 0 ] = fwnode_irq_get ( dev_fwnode ( & client - > dev ) , 0 ) ;
if ( chip - > interrupts [ 0 ] < 0 )
return chip - > interrupts [ 0 ] ;
if ( id - > driver_data = = AD7150 ) {
chip - > interrupts [ 1 ] = fwnode_irq_get ( dev_fwnode ( & client - > dev ) , 1 ) ;
if ( chip - > interrupts [ 1 ] < 0 )
return chip - > interrupts [ 1 ] ;
}
if ( chip - > interrupts [ 0 ] & &
( id - > driver_data = = AD7151 | | chip - > interrupts [ 1 ] ) ) {
irq_set_status_flags ( chip - > interrupts [ 0 ] , IRQ_NOAUTOEN ) ;
ret = devm_request_threaded_irq ( & client - > dev ,
chip - > interrupts [ 0 ] ,
NULL ,
& ad7150_event_handler_ch1 ,
IRQF_TRIGGER_RISING |
IRQF_ONESHOT ,
" ad7150_irq1 " ,
indio_dev ) ;
if ( ret )
return ret ;
2021-03-14 21:14:53 +03:00
indio_dev - > info = & ad7150_info ;
switch ( id - > driver_data ) {
case AD7150 :
indio_dev - > channels = ad7150_channels ;
indio_dev - > num_channels = ARRAY_SIZE ( ad7150_channels ) ;
2021-03-14 21:14:59 +03:00
irq_set_status_flags ( chip - > interrupts [ 1 ] , IRQ_NOAUTOEN ) ;
ret = devm_request_threaded_irq ( & client - > dev ,
chip - > interrupts [ 1 ] ,
NULL ,
& ad7150_event_handler_ch2 ,
IRQF_TRIGGER_RISING |
IRQF_ONESHOT ,
" ad7150_irq2 " ,
indio_dev ) ;
if ( ret )
return ret ;
2021-03-14 21:14:53 +03:00
break ;
case AD7151 :
indio_dev - > channels = ad7151_channels ;
indio_dev - > num_channels = ARRAY_SIZE ( ad7151_channels ) ;
break ;
default :
return - EINVAL ;
}
} else {
indio_dev - > info = & ad7150_info_no_irq ;
switch ( id - > driver_data ) {
case AD7150 :
indio_dev - > channels = ad7150_channels_no_irq ;
2021-03-14 21:14:59 +03:00
indio_dev - > num_channels =
ARRAY_SIZE ( ad7150_channels_no_irq ) ;
2021-03-14 21:14:53 +03:00
break ;
case AD7151 :
indio_dev - > channels = ad7151_channels_no_irq ;
2021-03-14 21:14:59 +03:00
indio_dev - > num_channels =
ARRAY_SIZE ( ad7151_channels_no_irq ) ;
2021-03-14 21:14:53 +03:00
break ;
default :
return - EINVAL ;
}
2010-10-28 05:43:53 +04:00
}
2021-03-14 21:14:55 +03:00
return devm_iio_device_register ( indio_dev - > dev . parent , indio_dev ) ;
2010-10-28 05:43:53 +04:00
}
static const struct i2c_device_id ad7150_id [ ] = {
2021-03-14 21:14:53 +03:00
{ " ad7150 " , AD7150 } ,
{ " ad7151 " , AD7151 } ,
{ " ad7156 " , AD7150 } ,
2010-10-28 05:43:53 +04:00
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , ad7150_id ) ;
2021-03-14 21:15:07 +03:00
static const struct of_device_id ad7150_of_match [ ] = {
{ " adi,ad7150 " } ,
{ " adi,ad7151 " } ,
{ " adi,ad7156 " } ,
{ }
} ;
2010-10-28 05:43:53 +04:00
static struct i2c_driver ad7150_driver = {
. driver = {
. name = " ad7150 " ,
2021-03-14 21:15:07 +03:00
. of_match_table = ad7150_of_match ,
2010-10-28 05:43:53 +04:00
} ,
. probe = ad7150_probe ,
. id_table = ad7150_id ,
} ;
2011-11-16 13:13:38 +04:00
module_i2c_driver ( ad7150_driver ) ;
2010-10-28 05:43:53 +04:00
MODULE_AUTHOR ( " Barry Song <21cnbao@gmail.com> " ) ;
2011-09-02 20:25:22 +04:00
MODULE_DESCRIPTION ( " Analog Devices AD7150/1/6 capacitive sensor driver " ) ;
2010-10-28 05:43:53 +04:00
MODULE_LICENSE ( " GPL v2 " ) ;