2019-05-28 19:57:06 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2010-11-22 16:35:32 +03:00
/*
* AD7887 SPI ADC driver
*
2011-05-18 17:41:50 +04:00
* Copyright 2010 - 2011 Analog Devices Inc .
2010-11-22 16:35:32 +03:00
*/
# include <linux/device.h>
# include <linux/kernel.h>
# include <linux/slab.h>
# include <linux/sysfs.h>
# include <linux/spi/spi.h>
# include <linux/regulator/consumer.h>
# include <linux/err.h>
2011-07-03 23:49:50 +04:00
# include <linux/module.h>
2012-11-05 13:56:00 +04:00
# include <linux/interrupt.h>
2014-12-06 09:00:00 +03:00
# include <linux/bitops.h>
2010-11-22 16:35:32 +03:00
2012-04-25 18:54:58 +04:00
# include <linux/iio/iio.h>
# include <linux/iio/sysfs.h>
# include <linux/iio/buffer.h>
2011-08-12 20:08:43 +04:00
2012-11-05 13:56:00 +04:00
# include <linux/iio/trigger_consumer.h>
# include <linux/iio/triggered_buffer.h>
2010-11-22 16:35:32 +03:00
2012-11-05 13:56:00 +04:00
# include <linux/platform_data/ad7887.h>
2010-11-22 16:35:32 +03:00
2014-12-06 09:00:00 +03:00
# define AD7887_REF_DIS BIT(5) /* on-chip reference disable */
# define AD7887_DUAL BIT(4) /* dual-channel mode */
# define AD7887_CH_AIN1 BIT(3) /* convert on channel 1, DUAL=1 */
# define AD7887_CH_AIN0 0 /* convert on channel 0, DUAL=0,1 */
# define AD7887_PM_MODE1 0 /* CS based shutdown */
# define AD7887_PM_MODE2 1 /* full on */
# define AD7887_PM_MODE3 2 /* auto shutdown after conversion */
# define AD7887_PM_MODE4 3 /* standby mode */
2012-11-05 13:56:00 +04:00
enum ad7887_channels {
AD7887_CH0 ,
AD7887_CH0_CH1 ,
AD7887_CH1 ,
} ;
/**
* struct ad7887_chip_info - chip specifc information
* @ int_vref_mv : the internal reference voltage
2019-11-25 16:21:37 +03:00
* @ channels : channels specification
* @ num_channels : number of channels
* @ dual_channels : channels specification in dual mode
* @ num_dual_channels : number of channels in dual mode
2012-11-05 13:56:00 +04:00
*/
struct ad7887_chip_info {
u16 int_vref_mv ;
2019-11-25 16:21:37 +03:00
const struct iio_chan_spec * channels ;
unsigned int num_channels ;
const struct iio_chan_spec * dual_channels ;
unsigned int num_dual_channels ;
2012-11-05 13:56:00 +04:00
} ;
struct ad7887_state {
struct spi_device * spi ;
const struct ad7887_chip_info * chip_info ;
struct regulator * reg ;
struct spi_transfer xfer [ 4 ] ;
struct spi_message msg [ 3 ] ;
struct spi_message * ring_msg ;
2012-11-05 13:56:00 +04:00
unsigned char tx_cmd_buf [ 4 ] ;
2012-11-05 13:56:00 +04:00
/*
2022-05-08 20:55:57 +03:00
* DMA ( thus cache coherency maintenance ) may require the
2012-11-05 13:56:00 +04:00
* transfer buffers to live in their own cache lines .
* Buffer needs to be large enough to hold two 16 bit samples and a
* 64 bit aligned 64 bit timestamp .
*/
2022-05-08 20:55:57 +03:00
unsigned char data [ ALIGN ( 4 , sizeof ( s64 ) ) + sizeof ( s64 ) ] __aligned ( IIO_DMA_MINALIGN ) ;
2012-11-05 13:56:00 +04:00
} ;
enum ad7887_supported_device_ids {
ID_AD7887
} ;
static int ad7887_ring_preenable ( struct iio_dev * indio_dev )
{
struct ad7887_state * st = iio_priv ( indio_dev ) ;
/* We know this is a single long so can 'cheat' */
switch ( * indio_dev - > active_scan_mask ) {
case ( 1 < < 0 ) :
st - > ring_msg = & st - > msg [ AD7887_CH0 ] ;
break ;
case ( 1 < < 1 ) :
st - > ring_msg = & st - > msg [ AD7887_CH1 ] ;
/* Dummy read: push CH1 setting down to hardware */
spi_sync ( st - > spi , st - > ring_msg ) ;
break ;
case ( ( 1 < < 1 ) | ( 1 < < 0 ) ) :
st - > ring_msg = & st - > msg [ AD7887_CH0_CH1 ] ;
break ;
}
return 0 ;
}
static int ad7887_ring_postdisable ( struct iio_dev * indio_dev )
{
struct ad7887_state * st = iio_priv ( indio_dev ) ;
/* dummy read: restore default CH0 settin */
return spi_sync ( st - > spi , & st - > msg [ AD7887_CH0 ] ) ;
}
static irqreturn_t ad7887_trigger_handler ( int irq , void * p )
{
struct iio_poll_func * pf = p ;
struct iio_dev * indio_dev = pf - > indio_dev ;
struct ad7887_state * st = iio_priv ( indio_dev ) ;
int b_sent ;
b_sent = spi_sync ( st - > spi , st - > ring_msg ) ;
if ( b_sent )
goto done ;
2013-09-19 16:59:00 +04:00
iio_push_to_buffers_with_timestamp ( indio_dev , st - > data ,
2016-03-09 21:05:49 +03:00
iio_get_time_ns ( indio_dev ) ) ;
2012-11-05 13:56:00 +04:00
done :
iio_trigger_notify_done ( indio_dev - > trig ) ;
return IRQ_HANDLED ;
}
static const struct iio_buffer_setup_ops ad7887_ring_setup_ops = {
. preenable = & ad7887_ring_preenable ,
. postdisable = & ad7887_ring_postdisable ,
} ;
2010-11-22 16:35:32 +03:00
static int ad7887_scan_direct ( struct ad7887_state * st , unsigned ch )
{
int ret = spi_sync ( st - > spi , & st - > msg [ ch ] ) ;
if ( ret )
return ret ;
return ( st - > data [ ( ch * 2 ) ] < < 8 ) | st - > data [ ( ch * 2 ) + 1 ] ;
}
2011-10-06 20:14:37 +04:00
static int ad7887_read_raw ( struct iio_dev * indio_dev ,
2011-05-18 17:41:50 +04:00
struct iio_chan_spec const * chan ,
int * val ,
int * val2 ,
long m )
2010-11-22 16:35:32 +03:00
{
int ret ;
2011-10-06 20:14:37 +04:00
struct ad7887_state * st = iio_priv ( indio_dev ) ;
2010-11-22 16:35:32 +03:00
2011-05-18 17:41:50 +04:00
switch ( m ) {
2012-04-15 20:41:18 +04:00
case IIO_CHAN_INFO_RAW :
2016-05-24 22:18:43 +03:00
ret = iio_device_claim_direct_mode ( indio_dev ) ;
if ( ret )
return ret ;
ret = ad7887_scan_direct ( st , chan - > address ) ;
iio_device_release_direct_mode ( indio_dev ) ;
2011-05-18 17:41:50 +04:00
if ( ret < 0 )
return ret ;
2012-11-05 13:56:00 +04:00
* val = ret > > chan - > scan_type . shift ;
2014-12-06 09:00:00 +03:00
* val & = GENMASK ( chan - > scan_type . realbits - 1 , 0 ) ;
2011-05-18 17:41:50 +04:00
return IIO_VAL_INT ;
2011-10-26 20:41:36 +04:00
case IIO_CHAN_INFO_SCALE :
2012-11-05 13:56:00 +04:00
if ( st - > reg ) {
* val = regulator_get_voltage ( st - > reg ) ;
if ( * val < 0 )
return * val ;
* val / = 1000 ;
} else {
* val = st - > chip_info - > int_vref_mv ;
}
2012-11-05 13:56:00 +04:00
* val2 = chan - > scan_type . realbits ;
2012-11-05 13:56:00 +04:00
return IIO_VAL_FRACTIONAL_LOG2 ;
2011-05-18 17:41:50 +04:00
}
return - EINVAL ;
2010-11-22 16:35:32 +03:00
}
2019-11-25 16:21:37 +03:00
# define AD7887_CHANNEL(x) { \
. type = IIO_VOLTAGE , \
. indexed = 1 , \
. channel = ( x ) , \
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) , \
. info_mask_shared_by_type = BIT ( IIO_CHAN_INFO_SCALE ) , \
. address = ( x ) , \
. scan_index = ( x ) , \
. scan_type = { \
. sign = ' u ' , \
. realbits = 12 , \
. storagebits = 16 , \
. shift = 0 , \
. endianness = IIO_BE , \
} , \
}
static const struct iio_chan_spec ad7887_channels [ ] = {
AD7887_CHANNEL ( 0 ) ,
IIO_CHAN_SOFT_TIMESTAMP ( 1 ) ,
} ;
static const struct iio_chan_spec ad7887_dual_channels [ ] = {
AD7887_CHANNEL ( 0 ) ,
AD7887_CHANNEL ( 1 ) ,
IIO_CHAN_SOFT_TIMESTAMP ( 2 ) ,
} ;
2010-11-22 16:35:32 +03:00
static const struct ad7887_chip_info ad7887_chip_info_tbl [ ] = {
/*
* More devices added in future
*/
[ ID_AD7887 ] = {
2019-11-25 16:21:37 +03:00
. channels = ad7887_channels ,
. num_channels = ARRAY_SIZE ( ad7887_channels ) ,
. dual_channels = ad7887_dual_channels ,
. num_dual_channels = ARRAY_SIZE ( ad7887_dual_channels ) ,
2010-11-22 16:35:32 +03:00
. int_vref_mv = 2500 ,
} ,
} ;
2011-05-18 17:42:37 +04:00
static const struct iio_info ad7887_info = {
. read_raw = & ad7887_read_raw ,
} ;
2020-11-13 12:16:48 +03:00
static void ad7887_reg_disable ( void * data )
{
struct regulator * reg = data ;
regulator_disable ( reg ) ;
}
2012-12-22 01:21:43 +04:00
static int ad7887_probe ( struct spi_device * spi )
2010-11-22 16:35:32 +03:00
{
struct ad7887_platform_data * pdata = spi - > dev . platform_data ;
struct ad7887_state * st ;
2013-07-23 12:58:00 +04:00
struct iio_dev * indio_dev ;
2012-11-05 13:56:00 +04:00
uint8_t mode ;
2012-11-05 13:56:00 +04:00
int ret ;
2010-11-22 16:35:32 +03:00
2013-07-23 12:58:00 +04:00
indio_dev = devm_iio_device_alloc ( & spi - > dev , sizeof ( * st ) ) ;
2011-05-18 17:41:51 +04:00
if ( indio_dev = = NULL )
return - ENOMEM ;
st = iio_priv ( indio_dev ) ;
2010-11-22 16:35:32 +03:00
2020-10-02 11:27:23 +03:00
st - > reg = devm_regulator_get_optional ( & spi - > dev , " vref " ) ;
if ( IS_ERR ( st - > reg ) ) {
if ( PTR_ERR ( st - > reg ) ! = - ENODEV )
2013-07-23 12:58:00 +04:00
return PTR_ERR ( st - > reg ) ;
2012-11-05 13:56:00 +04:00
2020-10-02 11:27:23 +03:00
st - > reg = NULL ;
}
if ( st - > reg ) {
2010-11-22 16:35:32 +03:00
ret = regulator_enable ( st - > reg ) ;
if ( ret )
2013-07-23 12:58:00 +04:00
return ret ;
2020-11-13 12:16:48 +03:00
ret = devm_add_action_or_reset ( & spi - > dev , ad7887_reg_disable , st - > reg ) ;
if ( ret )
return ret ;
2010-11-22 16:35:32 +03:00
}
st - > chip_info =
& ad7887_chip_info_tbl [ spi_get_device_id ( spi ) - > driver_data ] ;
st - > spi = spi ;
2011-05-18 17:41:51 +04:00
indio_dev - > name = spi_get_device_id ( spi ) - > name ;
2011-05-18 17:42:37 +04:00
indio_dev - > info = & ad7887_info ;
2011-05-18 17:41:51 +04:00
indio_dev - > modes = INDIO_DIRECT_MODE ;
2010-11-22 16:35:32 +03:00
/* Setup default message */
2012-11-05 13:56:00 +04:00
mode = AD7887_PM_MODE4 ;
2020-10-02 11:27:23 +03:00
if ( ! st - > reg )
2012-11-05 13:56:00 +04:00
mode | = AD7887_REF_DIS ;
if ( pdata & & pdata - > en_dual )
mode | = AD7887_DUAL ;
st - > tx_cmd_buf [ 0 ] = AD7887_CH_AIN0 | mode ;
2010-11-22 16:35:32 +03:00
st - > xfer [ 0 ] . rx_buf = & st - > data [ 0 ] ;
st - > xfer [ 0 ] . tx_buf = & st - > tx_cmd_buf [ 0 ] ;
st - > xfer [ 0 ] . len = 2 ;
spi_message_init ( & st - > msg [ AD7887_CH0 ] ) ;
spi_message_add_tail ( & st - > xfer [ 0 ] , & st - > msg [ AD7887_CH0 ] ) ;
if ( pdata & & pdata - > en_dual ) {
2012-11-05 13:56:00 +04:00
st - > tx_cmd_buf [ 2 ] = AD7887_CH_AIN1 | mode ;
2010-11-22 16:35:32 +03:00
st - > xfer [ 1 ] . rx_buf = & st - > data [ 0 ] ;
st - > xfer [ 1 ] . tx_buf = & st - > tx_cmd_buf [ 2 ] ;
st - > xfer [ 1 ] . len = 2 ;
st - > xfer [ 2 ] . rx_buf = & st - > data [ 2 ] ;
2012-11-05 13:56:00 +04:00
st - > xfer [ 2 ] . tx_buf = & st - > tx_cmd_buf [ 0 ] ;
2010-11-22 16:35:32 +03:00
st - > xfer [ 2 ] . len = 2 ;
spi_message_init ( & st - > msg [ AD7887_CH0_CH1 ] ) ;
spi_message_add_tail ( & st - > xfer [ 1 ] , & st - > msg [ AD7887_CH0_CH1 ] ) ;
spi_message_add_tail ( & st - > xfer [ 2 ] , & st - > msg [ AD7887_CH0_CH1 ] ) ;
2012-11-05 13:56:00 +04:00
st - > xfer [ 3 ] . rx_buf = & st - > data [ 2 ] ;
st - > xfer [ 3 ] . tx_buf = & st - > tx_cmd_buf [ 2 ] ;
2010-11-22 16:35:32 +03:00
st - > xfer [ 3 ] . len = 2 ;
spi_message_init ( & st - > msg [ AD7887_CH1 ] ) ;
spi_message_add_tail ( & st - > xfer [ 3 ] , & st - > msg [ AD7887_CH1 ] ) ;
2019-11-25 16:21:37 +03:00
indio_dev - > channels = st - > chip_info - > dual_channels ;
indio_dev - > num_channels = st - > chip_info - > num_dual_channels ;
2010-11-22 16:35:32 +03:00
} else {
2019-11-25 16:21:37 +03:00
indio_dev - > channels = st - > chip_info - > channels ;
indio_dev - > num_channels = st - > chip_info - > num_channels ;
2011-05-18 17:41:50 +04:00
}
2010-11-22 16:35:32 +03:00
2020-11-13 12:16:48 +03:00
ret = devm_iio_triggered_buffer_setup ( & spi - > dev , indio_dev ,
& iio_pollfunc_store_time ,
2012-11-05 13:56:00 +04:00
& ad7887_trigger_handler , & ad7887_ring_setup_ops ) ;
2010-11-22 16:35:32 +03:00
if ( ret )
2020-11-13 12:16:48 +03:00
return ret ;
2011-05-18 17:41:51 +04:00
2020-11-13 12:16:48 +03:00
return devm_iio_device_register ( & spi - > dev , indio_dev ) ;
2010-11-22 16:35:32 +03:00
}
static const struct spi_device_id ad7887_id [ ] = {
{ " ad7887 " , ID_AD7887 } ,
{ }
} ;
2011-11-16 11:53:31 +04:00
MODULE_DEVICE_TABLE ( spi , ad7887_id ) ;
2010-11-22 16:35:32 +03:00
static struct spi_driver ad7887_driver = {
. driver = {
. name = " ad7887 " ,
} ,
. probe = ad7887_probe ,
. id_table = ad7887_id ,
} ;
2011-11-16 13:13:39 +04:00
module_spi_driver ( ad7887_driver ) ;
2010-11-22 16:35:32 +03:00
2018-08-14 14:23:17 +03:00
MODULE_AUTHOR ( " Michael Hennerich <michael.hennerich@analog.com> " ) ;
2010-11-22 16:35:32 +03:00
MODULE_DESCRIPTION ( " Analog Devices AD7887 ADC " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;