2018-12-17 15:23:36 +03:00
// SPDX-License-Identifier: GPL-2.0
2011-02-22 23:46:18 +03:00
/*
* AD7606 SPI ADC driver
*
* Copyright 2011 Analog Devices Inc .
*/
2018-12-17 15:23:38 +03:00
# include <linux/delay.h>
2011-02-22 23:46:18 +03:00
# include <linux/device.h>
# include <linux/err.h>
2016-10-19 20:07:07 +03:00
# include <linux/gpio/consumer.h>
2018-12-17 15:23:38 +03:00
# include <linux/interrupt.h>
# include <linux/kernel.h>
2011-07-03 23:49:50 +04:00
# include <linux/module.h>
2018-12-17 15:23:38 +03:00
# include <linux/regulator/consumer.h>
# include <linux/sched.h>
# include <linux/slab.h>
# include <linux/sysfs.h>
2018-12-13 15:46:18 +03:00
# include <linux/util_macros.h>
2011-02-22 23:46:18 +03:00
2012-04-25 18:54:58 +04:00
# include <linux/iio/iio.h>
# include <linux/iio/buffer.h>
2018-12-17 15:23:38 +03:00
# include <linux/iio/sysfs.h>
2018-12-17 15:23:37 +03:00
# include <linux/iio/trigger.h>
2016-10-19 20:07:08 +03:00
# include <linux/iio/triggered_buffer.h>
2018-12-17 15:23:38 +03:00
# include <linux/iio/trigger_consumer.h>
2011-02-22 23:46:18 +03:00
# include "ad7606.h"
2018-09-13 11:44:09 +03:00
/*
* Scales are computed as 5000 / 32768 and 10000 / 32768 respectively ,
* so that when applied to the raw values they provide mV values
*/
2019-04-02 16:18:39 +03:00
static const unsigned int ad7606_scale_avail [ 2 ] = {
2018-12-13 15:46:18 +03:00
152588 , 305176
} ;
static const unsigned int ad7606_oversampling_avail [ 7 ] = {
1 , 2 , 4 , 8 , 16 , 32 , 64 ,
2017-01-07 14:10:23 +03:00
} ;
2019-04-02 16:18:40 +03:00
static const unsigned int ad7616_oversampling_avail [ 8 ] = {
1 , 2 , 4 , 8 , 16 , 32 , 64 , 128 ,
} ;
2016-10-19 20:07:08 +03:00
static int ad7606_reset ( struct ad7606_state * st )
2011-02-22 23:46:18 +03:00
{
2016-10-19 20:07:07 +03:00
if ( st - > gpio_reset ) {
gpiod_set_value ( st - > gpio_reset , 1 ) ;
2011-02-22 23:46:18 +03:00
ndelay ( 100 ) ; /* t_reset >= 100ns */
2016-10-19 20:07:07 +03:00
gpiod_set_value ( st - > gpio_reset , 0 ) ;
2011-02-22 23:46:18 +03:00
return 0 ;
}
return - ENODEV ;
}
2016-10-19 20:07:08 +03:00
static int ad7606_read_samples ( struct ad7606_state * st )
2016-10-19 20:07:02 +03:00
{
unsigned int num = st - > chip_info - > num_channels ;
u16 * data = st - > data ;
int ret ;
/*
* The frstdata signal is set to high while and after reading the sample
* of the first channel and low for all other channels . This can be used
* to check that the incoming data is correctly aligned . During normal
* operation the data should never become unaligned , but some glitch or
* electrostatic discharge might cause an extra read or clock cycle .
* Monitoring the frstdata signal allows to recover from such failure
* situations .
*/
2016-10-19 20:07:07 +03:00
if ( st - > gpio_frstdata ) {
2016-10-19 20:07:02 +03:00
ret = st - > bops - > read_block ( st - > dev , 1 , data ) ;
if ( ret )
return ret ;
2016-10-19 20:07:07 +03:00
if ( ! gpiod_get_value ( st - > gpio_frstdata ) ) {
2016-10-19 20:07:02 +03:00
ad7606_reset ( st ) ;
return - EIO ;
}
data + + ;
num - - ;
}
return st - > bops - > read_block ( st - > dev , num , data ) ;
}
2016-10-19 20:07:08 +03:00
static irqreturn_t ad7606_trigger_handler ( int irq , void * p )
{
struct iio_poll_func * pf = p ;
2018-12-17 15:23:37 +03:00
struct iio_dev * indio_dev = pf - > indio_dev ;
struct ad7606_state * st = iio_priv ( indio_dev ) ;
2016-10-19 20:07:08 +03:00
int ret ;
2018-12-17 15:23:37 +03:00
mutex_lock ( & st - > lock ) ;
2016-10-19 20:07:08 +03:00
ret = ad7606_read_samples ( st ) ;
if ( ret = = 0 )
iio_push_to_buffers_with_timestamp ( indio_dev , st - > data ,
iio_get_time_ns ( indio_dev ) ) ;
iio_trigger_notify_done ( indio_dev - > trig ) ;
2018-12-17 15:23:37 +03:00
/* The rising edge of the CONVST signal starts a new conversion. */
gpiod_set_value ( st - > gpio_convst , 1 ) ;
mutex_unlock ( & st - > lock ) ;
return IRQ_HANDLED ;
2016-10-19 20:07:08 +03:00
}
2016-03-26 22:50:24 +03:00
static int ad7606_scan_direct ( struct iio_dev * indio_dev , unsigned int ch )
2011-02-22 23:46:18 +03:00
{
2011-05-18 17:42:28 +04:00
struct ad7606_state * st = iio_priv ( indio_dev ) ;
2011-02-22 23:46:18 +03:00
int ret ;
2016-10-19 20:07:07 +03:00
gpiod_set_value ( st - > gpio_convst , 1 ) ;
2018-12-13 15:46:15 +03:00
ret = wait_for_completion_timeout ( & st - > completion ,
msecs_to_jiffies ( 1000 ) ) ;
if ( ! ret ) {
ret = - ETIMEDOUT ;
2011-02-22 23:46:18 +03:00
goto error_ret ;
2018-12-13 15:46:15 +03:00
}
2011-02-22 23:46:18 +03:00
2016-10-19 20:07:02 +03:00
ret = ad7606_read_samples ( st ) ;
if ( ret = = 0 )
ret = st - > data [ ch ] ;
2011-02-22 23:46:18 +03:00
error_ret :
2016-10-19 20:07:07 +03:00
gpiod_set_value ( st - > gpio_convst , 0 ) ;
2011-02-22 23:46:18 +03:00
return ret ;
}
2011-05-18 17:42:27 +04:00
static int ad7606_read_raw ( struct iio_dev * indio_dev ,
2011-05-18 17:42:00 +04:00
struct iio_chan_spec const * chan ,
int * val ,
int * val2 ,
long m )
2011-02-22 23:46:18 +03:00
{
int ret ;
2011-05-18 17:42:28 +04:00
struct ad7606_state * st = iio_priv ( indio_dev ) ;
2011-05-18 17:42:00 +04:00
switch ( m ) {
2012-04-15 20:41:18 +04:00
case IIO_CHAN_INFO_RAW :
2016-04-06 07:11:31 +03:00
ret = iio_device_claim_direct_mode ( indio_dev ) ;
if ( ret )
return ret ;
ret = ad7606_scan_direct ( indio_dev , chan - > address ) ;
iio_device_release_direct_mode ( indio_dev ) ;
2011-05-18 17:42:00 +04:00
if ( ret < 0 )
return ret ;
2015-10-14 21:14:15 +03:00
* val = ( short ) ret ;
2011-05-18 17:42:00 +04:00
return IIO_VAL_INT ;
2011-10-26 20:41:36 +04:00
case IIO_CHAN_INFO_SCALE :
2018-12-13 15:46:18 +03:00
* val = 0 ;
2019-04-02 16:18:39 +03:00
* val2 = st - > scale_avail [ st - > range ] ;
2017-01-07 14:10:23 +03:00
return IIO_VAL_INT_PLUS_MICRO ;
2016-10-08 19:05:40 +03:00
case IIO_CHAN_INFO_OVERSAMPLING_RATIO :
* val = st - > oversampling ;
return IIO_VAL_INT ;
2011-05-18 17:42:00 +04:00
}
return - EINVAL ;
2011-02-22 23:46:18 +03:00
}
2019-04-02 16:18:39 +03:00
static ssize_t ad7606_show_avail ( char * buf , const unsigned int * vals ,
unsigned int n , bool micros )
2011-02-22 23:46:18 +03:00
{
2019-04-02 16:18:39 +03:00
size_t len = 0 ;
int i ;
2016-10-19 20:06:59 +03:00
2019-04-02 16:18:39 +03:00
for ( i = 0 ; i < n ; i + + ) {
len + = scnprintf ( buf + len , PAGE_SIZE - len ,
micros ? " 0.%06u " : " %u " , vals [ i ] ) ;
}
2017-01-07 14:10:23 +03:00
buf [ len - 1 ] = ' \n ' ;
2011-02-22 23:46:18 +03:00
2017-01-07 14:10:23 +03:00
return len ;
2011-02-22 23:46:18 +03:00
}
2019-04-02 16:18:39 +03:00
static ssize_t in_voltage_scale_available_show ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
struct iio_dev * indio_dev = dev_to_iio_dev ( dev ) ;
struct ad7606_state * st = iio_priv ( indio_dev ) ;
return ad7606_show_avail ( buf , st - > scale_avail , st - > num_scales , true ) ;
}
2017-01-07 14:10:23 +03:00
static IIO_DEVICE_ATTR_RO ( in_voltage_scale_available , 0 ) ;
2011-02-22 23:46:18 +03:00
2016-10-08 19:05:40 +03:00
static int ad7606_write_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int val ,
int val2 ,
long mask )
2011-02-22 23:46:18 +03:00
{
2011-05-18 17:42:28 +04:00
struct ad7606_state * st = iio_priv ( indio_dev ) ;
2018-09-06 00:50:05 +03:00
DECLARE_BITMAP ( values , 3 ) ;
2018-12-13 15:46:18 +03:00
int i ;
2011-02-22 23:46:18 +03:00
2016-10-08 19:05:40 +03:00
switch ( mask ) {
2017-01-07 14:10:23 +03:00
case IIO_CHAN_INFO_SCALE :
2017-03-20 22:51:34 +03:00
mutex_lock ( & st - > lock ) ;
2019-04-02 16:18:39 +03:00
i = find_closest ( val2 , st - > scale_avail , st - > num_scales ) ;
2018-12-13 15:46:18 +03:00
gpiod_set_value ( st - > gpio_range , i ) ;
st - > range = i ;
2017-03-20 22:51:34 +03:00
mutex_unlock ( & st - > lock ) ;
2017-01-07 14:10:23 +03:00
2018-12-13 15:46:18 +03:00
return 0 ;
2016-10-08 19:05:40 +03:00
case IIO_CHAN_INFO_OVERSAMPLING_RATIO :
if ( val2 )
return - EINVAL ;
2019-04-02 16:18:39 +03:00
i = find_closest ( val , st - > oversampling_avail ,
st - > num_os_ratios ) ;
2011-02-22 23:46:18 +03:00
2018-12-13 15:46:18 +03:00
values [ 0 ] = i ;
2016-10-19 20:07:07 +03:00
2017-03-20 22:51:34 +03:00
mutex_lock ( & st - > lock ) ;
2018-12-13 15:46:18 +03:00
gpiod_set_array_value ( ARRAY_SIZE ( values ) , st - > gpio_os - > desc ,
st - > gpio_os - > info , values ) ;
2019-04-02 16:18:40 +03:00
/* AD7616 requires a reset to update value */
if ( st - > chip_info - > os_req_reset )
ad7606_reset ( st ) ;
2019-04-02 16:18:39 +03:00
st - > oversampling = st - > oversampling_avail [ i ] ;
2017-03-20 22:51:34 +03:00
mutex_unlock ( & st - > lock ) ;
2016-10-19 20:07:07 +03:00
2016-10-08 19:05:40 +03:00
return 0 ;
default :
return - EINVAL ;
2011-02-22 23:46:18 +03:00
}
}
2019-04-02 16:18:39 +03:00
static ssize_t ad7606_oversampling_ratio_avail ( struct device * dev ,
struct device_attribute * attr ,
char * buf )
{
struct iio_dev * indio_dev = dev_to_iio_dev ( dev ) ;
struct ad7606_state * st = iio_priv ( indio_dev ) ;
return ad7606_show_avail ( buf , st - > oversampling_avail ,
st - > num_os_ratios , false ) ;
}
static IIO_DEVICE_ATTR ( oversampling_ratio_available , 0444 ,
ad7606_oversampling_ratio_avail , NULL , 0 ) ;
2011-02-22 23:46:18 +03:00
2012-01-29 15:07:03 +04:00
static struct attribute * ad7606_attributes_os_and_range [ ] = {
2017-01-07 14:10:23 +03:00
& iio_dev_attr_in_voltage_scale_available . dev_attr . attr ,
2019-04-02 16:18:39 +03:00
& iio_dev_attr_oversampling_ratio_available . dev_attr . attr ,
2011-02-22 23:46:18 +03:00
NULL ,
} ;
2012-01-29 15:07:03 +04:00
static const struct attribute_group ad7606_attribute_group_os_and_range = {
. attrs = ad7606_attributes_os_and_range ,
} ;
2011-02-22 23:46:18 +03:00
2012-01-29 15:07:03 +04:00
static struct attribute * ad7606_attributes_os [ ] = {
2019-04-02 16:18:39 +03:00
& iio_dev_attr_oversampling_ratio_available . dev_attr . attr ,
2012-01-29 15:07:03 +04:00
NULL ,
} ;
2011-02-22 23:46:18 +03:00
2012-01-29 15:07:03 +04:00
static const struct attribute_group ad7606_attribute_group_os = {
. attrs = ad7606_attributes_os ,
} ;
static struct attribute * ad7606_attributes_range [ ] = {
2017-01-07 14:10:23 +03:00
& iio_dev_attr_in_voltage_scale_available . dev_attr . attr ,
2012-01-29 15:07:03 +04:00
NULL ,
} ;
static const struct attribute_group ad7606_attribute_group_range = {
. attrs = ad7606_attributes_range ,
2011-02-22 23:46:18 +03:00
} ;
2018-12-17 15:23:38 +03:00
# define AD760X_CHANNEL(num, mask) { \
2012-04-15 20:41:18 +04:00
. type = IIO_VOLTAGE , \
. indexed = 1 , \
. channel = num , \
. address = num , \
2013-02-27 23:37:28 +04:00
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) , \
. info_mask_shared_by_type = BIT ( IIO_CHAN_INFO_SCALE ) , \
2018-09-13 14:02:12 +03:00
. info_mask_shared_by_all = mask , \
2012-04-15 20:41:18 +04:00
. scan_index = num , \
2013-12-11 22:45:00 +04:00
. scan_type = { \
. sign = ' s ' , \
. realbits = 16 , \
. storagebits = 16 , \
. endianness = IIO_CPU , \
} , \
2018-12-17 15:23:38 +03:00
}
2011-09-30 13:05:38 +04:00
2018-09-13 14:02:12 +03:00
# define AD7605_CHANNEL(num) \
AD760X_CHANNEL ( num , 0 )
# define AD7606_CHANNEL(num) \
AD760X_CHANNEL ( num , BIT ( IIO_CHAN_INFO_OVERSAMPLING_RATIO ) )
static const struct iio_chan_spec ad7605_channels [ ] = {
IIO_CHAN_SOFT_TIMESTAMP ( 4 ) ,
AD7605_CHANNEL ( 0 ) ,
AD7605_CHANNEL ( 1 ) ,
AD7605_CHANNEL ( 2 ) ,
AD7605_CHANNEL ( 3 ) ,
} ;
2016-02-05 13:32:34 +03:00
static const struct iio_chan_spec ad7606_channels [ ] = {
IIO_CHAN_SOFT_TIMESTAMP ( 8 ) ,
2011-09-30 13:05:38 +04:00
AD7606_CHANNEL ( 0 ) ,
AD7606_CHANNEL ( 1 ) ,
AD7606_CHANNEL ( 2 ) ,
AD7606_CHANNEL ( 3 ) ,
AD7606_CHANNEL ( 4 ) ,
AD7606_CHANNEL ( 5 ) ,
AD7606_CHANNEL ( 6 ) ,
AD7606_CHANNEL ( 7 ) ,
2011-05-18 17:42:00 +04:00
} ;
2019-04-02 16:18:40 +03:00
/*
* The current assumption that this driver makes for AD7616 , is that it ' s
* working in Hardware Mode with Serial , Burst and Sequencer modes activated .
* To activate them , following pins must be pulled high :
* - SER / PAR
* - SEQEN
* And following pins must be pulled low :
* - WR / BURST
* - DB4 / SER1W
*/
static const struct iio_chan_spec ad7616_channels [ ] = {
IIO_CHAN_SOFT_TIMESTAMP ( 16 ) ,
AD7606_CHANNEL ( 0 ) ,
AD7606_CHANNEL ( 1 ) ,
AD7606_CHANNEL ( 2 ) ,
AD7606_CHANNEL ( 3 ) ,
AD7606_CHANNEL ( 4 ) ,
AD7606_CHANNEL ( 5 ) ,
AD7606_CHANNEL ( 6 ) ,
AD7606_CHANNEL ( 7 ) ,
AD7606_CHANNEL ( 8 ) ,
AD7606_CHANNEL ( 9 ) ,
AD7606_CHANNEL ( 10 ) ,
AD7606_CHANNEL ( 11 ) ,
AD7606_CHANNEL ( 12 ) ,
AD7606_CHANNEL ( 13 ) ,
AD7606_CHANNEL ( 14 ) ,
AD7606_CHANNEL ( 15 ) ,
} ;
2011-02-22 23:46:18 +03:00
static const struct ad7606_chip_info ad7606_chip_info_tbl [ ] = {
2018-12-17 15:23:38 +03:00
/* More devices added in future */
2018-09-13 14:02:12 +03:00
[ ID_AD7605_4 ] = {
. channels = ad7605_channels ,
. num_channels = 5 ,
} ,
2011-02-22 23:46:18 +03:00
[ ID_AD7606_8 ] = {
2016-02-05 13:32:34 +03:00
. channels = ad7606_channels ,
. num_channels = 9 ,
2019-04-02 16:18:39 +03:00
. oversampling_avail = ad7606_oversampling_avail ,
. oversampling_num = ARRAY_SIZE ( ad7606_oversampling_avail ) ,
2011-02-22 23:46:18 +03:00
} ,
[ ID_AD7606_6 ] = {
2016-02-05 13:32:34 +03:00
. channels = ad7606_channels ,
. num_channels = 7 ,
2019-04-02 16:18:39 +03:00
. oversampling_avail = ad7606_oversampling_avail ,
. oversampling_num = ARRAY_SIZE ( ad7606_oversampling_avail ) ,
2011-02-22 23:46:18 +03:00
} ,
[ ID_AD7606_4 ] = {
2016-02-05 13:32:34 +03:00
. channels = ad7606_channels ,
. num_channels = 5 ,
2019-04-02 16:18:39 +03:00
. oversampling_avail = ad7606_oversampling_avail ,
. oversampling_num = ARRAY_SIZE ( ad7606_oversampling_avail ) ,
2011-02-22 23:46:18 +03:00
} ,
2019-04-02 16:18:40 +03:00
[ ID_AD7616 ] = {
. channels = ad7616_channels ,
. num_channels = 17 ,
. oversampling_avail = ad7616_oversampling_avail ,
. oversampling_num = ARRAY_SIZE ( ad7616_oversampling_avail ) ,
. os_req_reset = true ,
} ,
2011-02-22 23:46:18 +03:00
} ;
static int ad7606_request_gpios ( struct ad7606_state * st )
{
2016-10-19 20:07:07 +03:00
struct device * dev = st - > dev ;
2011-02-22 23:46:18 +03:00
2018-12-13 15:46:19 +03:00
st - > gpio_convst = devm_gpiod_get ( dev , " adi,conversion-start " ,
2016-10-19 20:07:07 +03:00
GPIOD_OUT_LOW ) ;
if ( IS_ERR ( st - > gpio_convst ) )
return PTR_ERR ( st - > gpio_convst ) ;
2011-02-22 23:46:18 +03:00
2016-10-19 20:07:07 +03:00
st - > gpio_reset = devm_gpiod_get_optional ( dev , " reset " , GPIOD_OUT_LOW ) ;
if ( IS_ERR ( st - > gpio_reset ) )
return PTR_ERR ( st - > gpio_reset ) ;
2011-02-22 23:46:18 +03:00
2018-12-13 15:46:19 +03:00
st - > gpio_range = devm_gpiod_get_optional ( dev , " adi,range " ,
GPIOD_OUT_LOW ) ;
2016-10-19 20:07:07 +03:00
if ( IS_ERR ( st - > gpio_range ) )
return PTR_ERR ( st - > gpio_range ) ;
2011-02-22 23:46:18 +03:00
2016-10-19 20:07:07 +03:00
st - > gpio_standby = devm_gpiod_get_optional ( dev , " standby " ,
GPIOD_OUT_HIGH ) ;
if ( IS_ERR ( st - > gpio_standby ) )
return PTR_ERR ( st - > gpio_standby ) ;
2011-02-22 23:46:18 +03:00
2018-12-13 15:46:19 +03:00
st - > gpio_frstdata = devm_gpiod_get_optional ( dev , " adi,first-data " ,
2016-10-19 20:07:07 +03:00
GPIOD_IN ) ;
if ( IS_ERR ( st - > gpio_frstdata ) )
return PTR_ERR ( st - > gpio_frstdata ) ;
2011-02-22 23:46:18 +03:00
2019-04-02 16:18:39 +03:00
if ( ! st - > chip_info - > oversampling_num )
2018-09-13 14:02:12 +03:00
return 0 ;
2018-12-13 15:46:19 +03:00
st - > gpio_os = devm_gpiod_get_array_optional ( dev ,
" adi,oversampling-ratio " ,
2018-10-18 04:31:47 +03:00
GPIOD_OUT_LOW ) ;
2016-10-22 22:12:42 +03:00
return PTR_ERR_OR_ZERO ( st - > gpio_os ) ;
2011-02-22 23:46:18 +03:00
}
2018-12-17 15:23:37 +03:00
/*
* The BUSY signal indicates when conversions are in progress , so when a rising
* edge of CONVST is applied , BUSY goes logic high and transitions low at the
* end of the entire conversion process . The falling edge of the BUSY signal
* triggers this interrupt .
2011-02-22 23:46:18 +03:00
*/
static irqreturn_t ad7606_interrupt ( int irq , void * dev_id )
{
2011-05-18 17:42:01 +04:00
struct iio_dev * indio_dev = dev_id ;
struct ad7606_state * st = iio_priv ( indio_dev ) ;
2011-02-22 23:46:18 +03:00
2011-09-21 14:15:57 +04:00
if ( iio_buffer_enabled ( indio_dev ) ) {
2018-12-17 15:23:37 +03:00
gpiod_set_value ( st - > gpio_convst , 0 ) ;
iio_trigger_poll_chained ( st - > trig ) ;
2011-02-22 23:46:18 +03:00
} else {
2018-12-13 15:46:15 +03:00
complete ( & st - > completion ) ;
2011-02-22 23:46:18 +03:00
}
return IRQ_HANDLED ;
} ;
2018-12-17 15:23:37 +03:00
static int ad7606_validate_trigger ( struct iio_dev * indio_dev ,
struct iio_trigger * trig )
{
struct ad7606_state * st = iio_priv ( indio_dev ) ;
if ( st - > trig ! = trig )
return - EINVAL ;
return 0 ;
}
static int ad7606_buffer_postenable ( struct iio_dev * indio_dev )
{
struct ad7606_state * st = iio_priv ( indio_dev ) ;
iio_triggered_buffer_postenable ( indio_dev ) ;
gpiod_set_value ( st - > gpio_convst , 1 ) ;
return 0 ;
}
static int ad7606_buffer_predisable ( struct iio_dev * indio_dev )
{
struct ad7606_state * st = iio_priv ( indio_dev ) ;
gpiod_set_value ( st - > gpio_convst , 0 ) ;
return iio_triggered_buffer_predisable ( indio_dev ) ;
}
static const struct iio_buffer_setup_ops ad7606_buffer_ops = {
. postenable = & ad7606_buffer_postenable ,
. predisable = & ad7606_buffer_predisable ,
} ;
2012-01-29 15:07:03 +04:00
static const struct iio_info ad7606_info_no_os_or_range = {
2011-05-18 17:42:37 +04:00
. read_raw = & ad7606_read_raw ,
2018-12-17 15:23:37 +03:00
. validate_trigger = & ad7606_validate_trigger ,
2012-01-29 15:07:03 +04:00
} ;
static const struct iio_info ad7606_info_os_and_range = {
. read_raw = & ad7606_read_raw ,
2016-10-08 19:05:40 +03:00
. write_raw = & ad7606_write_raw ,
2012-01-29 15:07:03 +04:00
. attrs = & ad7606_attribute_group_os_and_range ,
2018-12-17 15:23:37 +03:00
. validate_trigger = & ad7606_validate_trigger ,
2012-01-29 15:07:03 +04:00
} ;
static const struct iio_info ad7606_info_os = {
. read_raw = & ad7606_read_raw ,
2016-10-08 19:05:40 +03:00
. write_raw = & ad7606_write_raw ,
2012-01-29 15:07:03 +04:00
. attrs = & ad7606_attribute_group_os ,
2018-12-17 15:23:37 +03:00
. validate_trigger = & ad7606_validate_trigger ,
2012-01-29 15:07:03 +04:00
} ;
static const struct iio_info ad7606_info_range = {
. read_raw = & ad7606_read_raw ,
2017-01-07 14:10:23 +03:00
. write_raw = & ad7606_write_raw ,
2012-01-29 15:07:03 +04:00
. attrs = & ad7606_attribute_group_range ,
2018-12-17 15:23:37 +03:00
. validate_trigger = & ad7606_validate_trigger ,
} ;
static const struct iio_trigger_ops ad7606_trigger_ops = {
. validate_device = iio_trigger_validate_own_device ,
2011-05-18 17:42:37 +04:00
} ;
2018-12-13 15:46:16 +03:00
static void ad7606_regulator_disable ( void * data )
{
struct ad7606_state * st = data ;
regulator_disable ( st - > reg ) ;
}
2016-10-19 20:07:04 +03:00
int ad7606_probe ( struct device * dev , int irq , void __iomem * base_address ,
const char * name , unsigned int id ,
const struct ad7606_bus_ops * bops )
2011-02-22 23:46:18 +03:00
{
struct ad7606_state * st ;
2011-09-02 20:14:40 +04:00
int ret ;
2013-08-31 21:12:00 +04:00
struct iio_dev * indio_dev ;
2011-02-22 23:46:18 +03:00
2013-08-31 21:12:00 +04:00
indio_dev = devm_iio_device_alloc ( dev , sizeof ( * st ) ) ;
if ( ! indio_dev )
2016-10-19 20:07:04 +03:00
return - ENOMEM ;
2011-02-22 23:46:18 +03:00
2011-05-18 17:42:01 +04:00
st = iio_priv ( indio_dev ) ;
2018-12-13 15:46:16 +03:00
dev_set_drvdata ( dev , indio_dev ) ;
2011-05-18 17:42:01 +04:00
2011-02-22 23:46:18 +03:00
st - > dev = dev ;
2017-03-20 22:51:34 +03:00
mutex_init ( & st - > lock ) ;
2011-02-22 23:46:18 +03:00
st - > bops = bops ;
st - > base_address = base_address ;
2017-01-07 14:10:23 +03:00
/* tied to logic low, analog input range is +/- 5V */
st - > range = 0 ;
2016-10-19 20:07:00 +03:00
st - > oversampling = 1 ;
2019-04-02 16:18:39 +03:00
st - > scale_avail = ad7606_scale_avail ;
st - > num_scales = ARRAY_SIZE ( ad7606_scale_avail ) ;
2011-02-22 23:46:18 +03:00
2016-10-20 16:08:22 +03:00
st - > reg = devm_regulator_get ( dev , " avcc " ) ;
2016-10-20 16:08:23 +03:00
if ( IS_ERR ( st - > reg ) )
return PTR_ERR ( st - > reg ) ;
ret = regulator_enable ( st - > reg ) ;
if ( ret ) {
dev_err ( dev , " Failed to enable specified AVcc supply \n " ) ;
return ret ;
2011-02-22 23:46:18 +03:00
}
2018-12-13 15:46:16 +03:00
ret = devm_add_action_or_reset ( dev , ad7606_regulator_disable , st ) ;
if ( ret )
return ret ;
2018-09-13 14:02:12 +03:00
st - > chip_info = & ad7606_chip_info_tbl [ id ] ;
2019-04-02 16:18:39 +03:00
if ( st - > chip_info - > oversampling_num ) {
st - > oversampling_avail = st - > chip_info - > oversampling_avail ;
st - > num_os_ratios = st - > chip_info - > oversampling_num ;
}
2016-10-19 20:07:07 +03:00
ret = ad7606_request_gpios ( st ) ;
if ( ret )
2018-12-13 15:46:16 +03:00
return ret ;
2016-10-19 20:07:07 +03:00
2011-05-18 17:42:01 +04:00
indio_dev - > dev . parent = dev ;
2016-10-19 20:07:07 +03:00
if ( st - > gpio_os ) {
if ( st - > gpio_range )
2012-01-29 15:07:03 +04:00
indio_dev - > info = & ad7606_info_os_and_range ;
else
indio_dev - > info = & ad7606_info_os ;
} else {
2016-10-19 20:07:07 +03:00
if ( st - > gpio_range )
2012-01-29 15:07:03 +04:00
indio_dev - > info = & ad7606_info_range ;
else
indio_dev - > info = & ad7606_info_no_os_or_range ;
}
2011-05-18 17:42:01 +04:00
indio_dev - > modes = INDIO_DIRECT_MODE ;
2016-10-19 20:06:57 +03:00
indio_dev - > name = name ;
2011-05-18 17:42:01 +04:00
indio_dev - > channels = st - > chip_info - > channels ;
indio_dev - > num_channels = st - > chip_info - > num_channels ;
2011-02-22 23:46:18 +03:00
2018-12-13 15:46:15 +03:00
init_completion ( & st - > completion ) ;
2011-02-22 23:46:18 +03:00
ret = ad7606_reset ( st ) ;
if ( ret )
dev_warn ( st - > dev , " failed to RESET: no RESET GPIO specified \n " ) ;
2018-12-17 15:23:37 +03:00
st - > trig = devm_iio_trigger_alloc ( dev , " %s-dev%d " ,
indio_dev - > name , indio_dev - > id ) ;
if ( ! st - > trig )
return - ENOMEM ;
st - > trig - > ops = & ad7606_trigger_ops ;
st - > trig - > dev . parent = dev ;
iio_trigger_set_drvdata ( st - > trig , indio_dev ) ;
ret = devm_iio_trigger_register ( dev , st - > trig ) ;
if ( ret )
return ret ;
indio_dev - > trig = iio_trigger_get ( st - > trig ) ;
ret = devm_request_threaded_irq ( dev , irq ,
NULL ,
& ad7606_interrupt ,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT ,
name , indio_dev ) ;
2011-02-22 23:46:18 +03:00
if ( ret )
2018-12-13 15:46:16 +03:00
return ret ;
2011-02-22 23:46:18 +03:00
2018-12-13 15:46:16 +03:00
ret = devm_iio_triggered_buffer_setup ( dev , indio_dev ,
2018-12-17 15:23:37 +03:00
& iio_pollfunc_store_time ,
2018-12-13 15:46:16 +03:00
& ad7606_trigger_handler ,
2018-12-17 15:23:37 +03:00
& ad7606_buffer_ops ) ;
2011-09-02 20:14:40 +04:00
if ( ret )
2018-12-13 15:46:16 +03:00
return ret ;
2011-02-22 23:46:18 +03:00
2018-12-13 15:46:16 +03:00
return devm_iio_device_register ( dev , indio_dev ) ;
2011-02-22 23:46:18 +03:00
}
2015-10-27 17:24:55 +03:00
EXPORT_SYMBOL_GPL ( ad7606_probe ) ;
2011-02-22 23:46:18 +03:00
2016-02-08 13:13:29 +03:00
# ifdef CONFIG_PM_SLEEP
static int ad7606_suspend ( struct device * dev )
2011-02-22 23:46:18 +03:00
{
2016-02-08 13:13:29 +03:00
struct iio_dev * indio_dev = dev_get_drvdata ( dev ) ;
2011-05-18 17:42:01 +04:00
struct ad7606_state * st = iio_priv ( indio_dev ) ;
2016-10-19 20:07:07 +03:00
if ( st - > gpio_standby ) {
gpiod_set_value ( st - > gpio_range , 1 ) ;
gpiod_set_value ( st - > gpio_standby , 0 ) ;
2011-02-22 23:46:18 +03:00
}
2016-02-08 13:13:29 +03:00
return 0 ;
2011-02-22 23:46:18 +03:00
}
2016-02-08 13:13:29 +03:00
static int ad7606_resume ( struct device * dev )
2011-02-22 23:46:18 +03:00
{
2016-02-08 13:13:29 +03:00
struct iio_dev * indio_dev = dev_get_drvdata ( dev ) ;
2011-05-18 17:42:01 +04:00
struct ad7606_state * st = iio_priv ( indio_dev ) ;
2016-10-19 20:07:07 +03:00
if ( st - > gpio_standby ) {
2017-01-07 14:10:23 +03:00
gpiod_set_value ( st - > gpio_range , st - > range ) ;
2016-10-19 20:07:07 +03:00
gpiod_set_value ( st - > gpio_standby , 1 ) ;
2011-02-22 23:46:18 +03:00
ad7606_reset ( st ) ;
}
2016-02-08 13:13:29 +03:00
return 0 ;
2011-02-22 23:46:18 +03:00
}
2016-02-08 13:13:29 +03:00
SIMPLE_DEV_PM_OPS ( ad7606_pm_ops , ad7606_suspend , ad7606_resume ) ;
EXPORT_SYMBOL_GPL ( ad7606_pm_ops ) ;
# endif
2011-02-22 23:46:18 +03:00
2018-08-14 14:23:17 +03:00
MODULE_AUTHOR ( " Michael Hennerich <michael.hennerich@analog.com> " ) ;
2011-02-22 23:46:18 +03:00
MODULE_DESCRIPTION ( " Analog Devices AD7606 ADC " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;