2011-02-24 14:32:45 +03:00
/*
* AD7298 SPI ADC driver
*
* Copyright 2011 Analog Devices Inc .
*
* Licensed under the GPL - 2.
*/
# 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>
# include <linux/delay.h>
2011-07-03 23:49:50 +04:00
# include <linux/module.h>
2012-11-15 17:15:00 +04:00
# include <linux/interrupt.h>
2011-02-24 14:32:45 +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>
2012-11-15 17:15:00 +04:00
# include <linux/iio/trigger_consumer.h>
# include <linux/iio/triggered_buffer.h>
2011-02-24 14:32:45 +03:00
2012-11-17 15:42:59 +04:00
# include <linux/platform_data/ad7298.h>
2011-02-24 14:32:45 +03:00
2012-11-15 17:15:00 +04:00
# define AD7298_WRITE (1 << 15) /* write to the control register */
# define AD7298_REPEAT (1 << 14) /* repeated conversion enable */
# define AD7298_CH(x) (1 << (13 - (x))) /* channel select */
# define AD7298_TSENSE (1 << 5) /* temperature conversion enable */
# define AD7298_EXTREF (1 << 2) /* external reference enable */
# define AD7298_TAVG (1 << 1) /* temperature sensor averaging enable */
# define AD7298_PDD (1 << 0) /* partial power down enable */
# define AD7298_MAX_CHAN 8
# define AD7298_BITS 12
# define AD7298_STORAGE_BITS 16
# define AD7298_INTREF_mV 2500
# define AD7298_CH_TEMP 9
# define RES_MASK(bits) ((1 << (bits)) - 1)
struct ad7298_state {
struct spi_device * spi ;
struct regulator * reg ;
unsigned ext_ref ;
struct spi_transfer ring_xfer [ 10 ] ;
struct spi_transfer scan_single_xfer [ 3 ] ;
struct spi_message ring_msg ;
struct spi_message scan_single_msg ;
/*
* DMA ( thus cache coherency maintenance ) requires the
* transfer buffers to live in their own cache lines .
*/
2012-11-21 22:24:26 +04:00
__be16 rx_buf [ 12 ] ____cacheline_aligned ;
__be16 tx_buf [ 2 ] ;
2012-11-15 17:15:00 +04:00
} ;
2012-04-13 13:42:54 +04:00
# define AD7298_V_CHAN(index) \
{ \
. type = IIO_VOLTAGE , \
. indexed = 1 , \
. channel = index , \
2013-02-27 23:04:29 +04:00
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) , \
. info_mask_shared_by_type = BIT ( IIO_CHAN_INFO_SCALE ) , \
2012-04-13 13:42:54 +04:00
. address = index , \
. scan_index = index , \
. scan_type = { \
. sign = ' u ' , \
. realbits = 12 , \
. storagebits = 16 , \
2012-11-15 17:15:00 +04:00
. endianness = IIO_BE , \
2012-04-13 13:42:54 +04:00
} , \
}
2012-08-09 11:51:00 +04:00
static const struct iio_chan_spec ad7298_channels [ ] = {
2012-04-13 13:42:54 +04:00
{
. type = IIO_TEMP ,
. indexed = 1 ,
. channel = 0 ,
2013-02-27 23:04:29 +04:00
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) |
BIT ( IIO_CHAN_INFO_SCALE ) |
BIT ( IIO_CHAN_INFO_OFFSET ) ,
2012-06-18 20:33:51 +04:00
. address = AD7298_CH_TEMP ,
. scan_index = - 1 ,
2012-04-13 13:42:54 +04:00
. scan_type = {
. sign = ' s ' ,
. realbits = 32 ,
. storagebits = 32 ,
} ,
} ,
AD7298_V_CHAN ( 0 ) ,
AD7298_V_CHAN ( 1 ) ,
AD7298_V_CHAN ( 2 ) ,
AD7298_V_CHAN ( 3 ) ,
AD7298_V_CHAN ( 4 ) ,
AD7298_V_CHAN ( 5 ) ,
AD7298_V_CHAN ( 6 ) ,
AD7298_V_CHAN ( 7 ) ,
2011-05-18 17:41:55 +04:00
IIO_CHAN_SOFT_TIMESTAMP ( 8 ) ,
} ;
2012-11-15 17:15:00 +04:00
/**
* ad7298_update_scan_mode ( ) setup the spi transfer buffer for the new scan mask
* */
static int ad7298_update_scan_mode ( struct iio_dev * indio_dev ,
const unsigned long * active_scan_mask )
{
struct ad7298_state * st = iio_priv ( indio_dev ) ;
int i , m ;
unsigned short command ;
int scan_count ;
/* Now compute overall size */
scan_count = bitmap_weight ( active_scan_mask , indio_dev - > masklength ) ;
command = AD7298_WRITE | st - > ext_ref ;
for ( i = 0 , m = AD7298_CH ( 0 ) ; i < AD7298_MAX_CHAN ; i + + , m > > = 1 )
if ( test_bit ( i , active_scan_mask ) )
command | = m ;
st - > tx_buf [ 0 ] = cpu_to_be16 ( command ) ;
/* build spi ring message */
st - > ring_xfer [ 0 ] . tx_buf = & st - > tx_buf [ 0 ] ;
st - > ring_xfer [ 0 ] . len = 2 ;
st - > ring_xfer [ 0 ] . cs_change = 1 ;
st - > ring_xfer [ 1 ] . tx_buf = & st - > tx_buf [ 1 ] ;
st - > ring_xfer [ 1 ] . len = 2 ;
st - > ring_xfer [ 1 ] . cs_change = 1 ;
spi_message_init ( & st - > ring_msg ) ;
spi_message_add_tail ( & st - > ring_xfer [ 0 ] , & st - > ring_msg ) ;
spi_message_add_tail ( & st - > ring_xfer [ 1 ] , & st - > ring_msg ) ;
for ( i = 0 ; i < scan_count ; i + + ) {
st - > ring_xfer [ i + 2 ] . rx_buf = & st - > rx_buf [ i ] ;
st - > ring_xfer [ i + 2 ] . len = 2 ;
st - > ring_xfer [ i + 2 ] . cs_change = 1 ;
spi_message_add_tail ( & st - > ring_xfer [ i + 2 ] , & st - > ring_msg ) ;
}
/* make sure last transfer cs_change is not set */
st - > ring_xfer [ i + 1 ] . cs_change = 0 ;
return 0 ;
}
/**
* ad7298_trigger_handler ( ) bh of trigger launched polling to ring buffer
*
* Currently there is no option in this driver to disable the saving of
* timestamps within the ring .
* */
static irqreturn_t ad7298_trigger_handler ( int irq , void * p )
{
struct iio_poll_func * pf = p ;
struct iio_dev * indio_dev = pf - > indio_dev ;
struct ad7298_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 - > rx_buf ,
iio_get_time_ns ( ) ) ;
2012-11-15 17:15:00 +04:00
done :
iio_trigger_notify_done ( indio_dev - > trig ) ;
return IRQ_HANDLED ;
}
2011-02-24 14:32:45 +03:00
static int ad7298_scan_direct ( struct ad7298_state * st , unsigned ch )
{
int ret ;
st - > tx_buf [ 0 ] = cpu_to_be16 ( AD7298_WRITE | st - > ext_ref |
( AD7298_CH ( 0 ) > > ch ) ) ;
ret = spi_sync ( st - > spi , & st - > scan_single_msg ) ;
if ( ret )
return ret ;
return be16_to_cpu ( st - > rx_buf [ 0 ] ) ;
}
2011-05-18 17:41:55 +04:00
static int ad7298_scan_temp ( struct ad7298_state * st , int * val )
2011-02-24 14:32:45 +03:00
{
2012-11-15 17:15:00 +04:00
int ret ;
2011-11-22 11:39:15 +04:00
__be16 buf ;
2011-02-24 14:32:45 +03:00
2011-11-22 11:39:15 +04:00
buf = cpu_to_be16 ( AD7298_WRITE | AD7298_TSENSE |
2011-05-18 17:41:55 +04:00
AD7298_TAVG | st - > ext_ref ) ;
2011-02-24 14:32:45 +03:00
2011-11-22 11:39:15 +04:00
ret = spi_write ( st - > spi , ( u8 * ) & buf , 2 ) ;
2011-05-18 17:41:55 +04:00
if ( ret )
2011-02-24 14:32:45 +03:00
return ret ;
2011-11-22 11:39:15 +04:00
buf = cpu_to_be16 ( 0 ) ;
2011-02-24 14:32:45 +03:00
2011-11-22 11:39:15 +04:00
ret = spi_write ( st - > spi , ( u8 * ) & buf , 2 ) ;
2011-05-18 17:41:55 +04:00
if ( ret )
return ret ;
2011-02-24 14:32:45 +03:00
usleep_range ( 101 , 1000 ) ; /* sleep > 100us */
2011-05-18 17:41:55 +04:00
2011-11-22 11:39:15 +04:00
ret = spi_read ( st - > spi , ( u8 * ) & buf , 2 ) ;
2011-05-18 17:41:55 +04:00
if ( ret )
return ret ;
2011-02-24 14:32:45 +03:00
2012-11-15 17:15:00 +04:00
* val = sign_extend32 ( be16_to_cpu ( buf ) , 11 ) ;
2011-02-24 14:32:45 +03:00
2012-11-15 17:15:00 +04:00
return 0 ;
}
static int ad7298_get_ref_voltage ( struct ad7298_state * st )
{
int vref ;
2011-02-24 14:32:45 +03:00
2012-11-15 17:15:00 +04:00
if ( st - > ext_ref ) {
vref = regulator_get_voltage ( st - > reg ) ;
if ( vref < 0 )
return vref ;
2011-02-24 14:32:45 +03:00
2012-11-15 17:15:00 +04:00
return vref / 1000 ;
2011-02-24 14:32:45 +03:00
} else {
2012-11-15 17:15:00 +04:00
return AD7298_INTREF_mV ;
2011-02-24 14:32:45 +03:00
}
2011-05-18 17:41:55 +04:00
}
2011-02-24 14:32:45 +03:00
2011-10-06 20:14:37 +04:00
static int ad7298_read_raw ( struct iio_dev * indio_dev ,
2011-05-18 17:41:55 +04:00
struct iio_chan_spec const * chan ,
int * val ,
int * val2 ,
long m )
2011-02-24 14:32:45 +03:00
{
2011-05-18 17:41:55 +04:00
int ret ;
2011-10-06 20:14:37 +04:00
struct ad7298_state * st = iio_priv ( indio_dev ) ;
2011-05-18 17:41:55 +04:00
switch ( m ) {
2012-04-15 20:41:18 +04:00
case IIO_CHAN_INFO_RAW :
2011-10-06 20:14:37 +04:00
mutex_lock ( & indio_dev - > mlock ) ;
2011-12-06 02:18:19 +04:00
if ( indio_dev - > currentmode = = INDIO_BUFFER_TRIGGERED ) {
ret = - EBUSY ;
2011-05-18 17:41:55 +04:00
} else {
if ( chan - > address = = AD7298_CH_TEMP )
ret = ad7298_scan_temp ( st , val ) ;
else
ret = ad7298_scan_direct ( st , chan - > address ) ;
}
2011-10-06 20:14:37 +04:00
mutex_unlock ( & indio_dev - > mlock ) ;
2011-05-18 17:41:55 +04:00
if ( ret < 0 )
return ret ;
if ( chan - > address ! = AD7298_CH_TEMP )
* val = ret & RES_MASK ( AD7298_BITS ) ;
return IIO_VAL_INT ;
2011-10-26 20:41:36 +04:00
case IIO_CHAN_INFO_SCALE :
switch ( chan - > type ) {
case IIO_VOLTAGE :
2012-11-15 17:15:00 +04:00
* val = ad7298_get_ref_voltage ( st ) ;
2012-11-15 17:15:00 +04:00
* val2 = chan - > scan_type . realbits ;
return IIO_VAL_FRACTIONAL_LOG2 ;
2011-10-26 20:41:36 +04:00
case IIO_TEMP :
2012-11-15 17:15:00 +04:00
* val = ad7298_get_ref_voltage ( st ) ;
* val2 = 10 ;
return IIO_VAL_FRACTIONAL ;
2011-10-26 20:41:36 +04:00
default :
return - EINVAL ;
}
2012-11-15 17:15:00 +04:00
case IIO_CHAN_INFO_OFFSET :
* val = 1093 - 2732500 / ad7298_get_ref_voltage ( st ) ;
return IIO_VAL_INT ;
2011-05-18 17:41:55 +04:00
}
return - EINVAL ;
2011-02-24 14:32:45 +03:00
}
2011-05-18 17:42:37 +04:00
static const struct iio_info ad7298_info = {
. read_raw = & ad7298_read_raw ,
2012-06-18 20:33:51 +04:00
. update_scan_mode = ad7298_update_scan_mode ,
2011-05-18 17:42:37 +04:00
. driver_module = THIS_MODULE ,
} ;
2012-12-22 01:21:43 +04:00
static int ad7298_probe ( struct spi_device * spi )
2011-02-24 14:32:45 +03:00
{
struct ad7298_platform_data * pdata = spi - > dev . platform_data ;
struct ad7298_state * st ;
2013-07-23 12:58:00 +04:00
struct iio_dev * indio_dev ;
2012-11-15 17:15:00 +04:00
int ret ;
2011-02-24 14:32:45 +03:00
2013-07-23 12:58:00 +04:00
indio_dev = devm_iio_device_alloc ( & spi - > dev , sizeof ( * st ) ) ;
2011-05-18 17:42:25 +04:00
if ( indio_dev = = NULL )
return - ENOMEM ;
st = iio_priv ( indio_dev ) ;
2011-02-24 14:32:45 +03:00
2012-11-15 17:15:00 +04:00
if ( pdata & & pdata - > ext_ref )
st - > ext_ref = AD7298_EXTREF ;
if ( st - > ext_ref ) {
2013-07-23 12:58:00 +04:00
st - > reg = devm_regulator_get ( & spi - > dev , " vref " ) ;
if ( IS_ERR ( st - > reg ) )
return PTR_ERR ( st - > reg ) ;
2011-02-24 14:32:45 +03:00
ret = regulator_enable ( st - > reg ) ;
if ( ret )
2013-07-23 12:58:00 +04:00
return ret ;
2011-02-24 14:32:45 +03:00
}
2011-05-18 17:42:25 +04:00
spi_set_drvdata ( spi , indio_dev ) ;
2011-02-24 14:32:45 +03:00
st - > spi = spi ;
2011-05-18 17:42:25 +04:00
indio_dev - > name = spi_get_device_id ( spi ) - > name ;
indio_dev - > dev . parent = & spi - > dev ;
indio_dev - > modes = INDIO_DIRECT_MODE ;
indio_dev - > channels = ad7298_channels ;
indio_dev - > num_channels = ARRAY_SIZE ( ad7298_channels ) ;
2011-05-18 17:42:37 +04:00
indio_dev - > info = & ad7298_info ;
2011-02-24 14:32:45 +03:00
/* Setup default message */
st - > scan_single_xfer [ 0 ] . tx_buf = & st - > tx_buf [ 0 ] ;
st - > scan_single_xfer [ 0 ] . len = 2 ;
st - > scan_single_xfer [ 0 ] . cs_change = 1 ;
st - > scan_single_xfer [ 1 ] . tx_buf = & st - > tx_buf [ 1 ] ;
st - > scan_single_xfer [ 1 ] . len = 2 ;
st - > scan_single_xfer [ 1 ] . cs_change = 1 ;
st - > scan_single_xfer [ 2 ] . rx_buf = & st - > rx_buf [ 0 ] ;
st - > scan_single_xfer [ 2 ] . len = 2 ;
spi_message_init ( & st - > scan_single_msg ) ;
spi_message_add_tail ( & st - > scan_single_xfer [ 0 ] , & st - > scan_single_msg ) ;
spi_message_add_tail ( & st - > scan_single_xfer [ 1 ] , & st - > scan_single_msg ) ;
spi_message_add_tail ( & st - > scan_single_xfer [ 2 ] , & st - > scan_single_msg ) ;
2012-11-15 17:15:00 +04:00
ret = iio_triggered_buffer_setup ( indio_dev , NULL ,
& ad7298_trigger_handler , NULL ) ;
2011-02-24 14:32:45 +03:00
if ( ret )
2011-05-18 17:42:25 +04:00
goto error_disable_reg ;
2011-02-24 14:32:45 +03:00
2011-09-02 20:14:40 +04:00
ret = iio_device_register ( indio_dev ) ;
if ( ret )
2012-06-18 20:33:51 +04:00
goto error_cleanup_ring ;
2011-05-18 17:42:25 +04:00
2011-02-24 14:32:45 +03:00
return 0 ;
error_cleanup_ring :
2012-11-15 17:15:00 +04:00
iio_triggered_buffer_cleanup ( indio_dev ) ;
2011-02-24 14:32:45 +03:00
error_disable_reg :
2012-11-15 17:15:00 +04:00
if ( st - > ext_ref )
2011-02-24 14:32:45 +03:00
regulator_disable ( st - > reg ) ;
2011-05-18 17:42:25 +04:00
2011-02-24 14:32:45 +03:00
return ret ;
}
2012-12-22 01:21:43 +04:00
static int ad7298_remove ( struct spi_device * spi )
2011-02-24 14:32:45 +03:00
{
2011-05-18 17:42:25 +04:00
struct iio_dev * indio_dev = spi_get_drvdata ( spi ) ;
struct ad7298_state * st = iio_priv ( indio_dev ) ;
2011-02-24 14:32:45 +03:00
2011-10-14 17:46:58 +04:00
iio_device_unregister ( indio_dev ) ;
2012-11-15 17:15:00 +04:00
iio_triggered_buffer_cleanup ( indio_dev ) ;
2013-07-23 12:58:00 +04:00
if ( st - > ext_ref )
2011-02-24 14:32:45 +03:00
regulator_disable ( st - > reg ) ;
2011-05-18 17:42:25 +04:00
2011-02-24 14:32:45 +03:00
return 0 ;
}
static const struct spi_device_id ad7298_id [ ] = {
{ " ad7298 " , 0 } ,
{ }
} ;
2011-11-16 11:53:31 +04:00
MODULE_DEVICE_TABLE ( spi , ad7298_id ) ;
2011-02-24 14:32:45 +03:00
static struct spi_driver ad7298_driver = {
. driver = {
. name = " ad7298 " ,
. owner = THIS_MODULE ,
} ,
. probe = ad7298_probe ,
2012-12-22 01:21:43 +04:00
. remove = ad7298_remove ,
2011-02-24 14:32:45 +03:00
. id_table = ad7298_id ,
} ;
2011-11-16 13:13:39 +04:00
module_spi_driver ( ad7298_driver ) ;
2011-02-24 14:32:45 +03:00
MODULE_AUTHOR ( " Michael Hennerich <hennerich@blackfin.uclinux.org> " ) ;
MODULE_DESCRIPTION ( " Analog Devices AD7298 ADC " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;