2019-02-04 12:19:35 +03:00
// SPDX-License-Identifier: GPL-2.0
2011-06-10 17:40:49 +04:00
/*
* AD5686R , AD5685R , AD5684R Digital to analog converters driver
*
* Copyright 2011 Analog Devices Inc .
*/
# include <linux/interrupt.h>
# include <linux/fs.h>
# include <linux/device.h>
2011-07-03 23:49:50 +04:00
# include <linux/module.h>
2011-06-10 17:40:49 +04:00
# include <linux/kernel.h>
# include <linux/slab.h>
# include <linux/sysfs.h>
# include <linux/regulator/consumer.h>
2012-04-25 18:54:58 +04:00
# include <linux/iio/iio.h>
# include <linux/iio/sysfs.h>
2011-06-10 17:40:49 +04:00
2018-04-11 14:53:17 +03:00
# include "ad5686.h"
2011-06-10 17:40:49 +04:00
2012-06-04 13:36:17 +04:00
static const char * const ad5686_powerdown_modes [ ] = {
" 1kohm_to_gnd " ,
" 100kohm_to_gnd " ,
" three_state "
} ;
static int ad5686_get_powerdown_mode ( struct iio_dev * indio_dev ,
2018-04-11 14:51:51 +03:00
const struct iio_chan_spec * chan )
2011-06-10 17:40:49 +04:00
{
struct ad5686_state * st = iio_priv ( indio_dev ) ;
2012-06-04 13:36:17 +04:00
return ( ( st - > pwr_down_mode > > ( chan - > channel * 2 ) ) & 0x3 ) - 1 ;
2011-06-10 17:40:49 +04:00
}
2012-06-04 13:36:17 +04:00
static int ad5686_set_powerdown_mode ( struct iio_dev * indio_dev ,
2018-04-11 14:51:51 +03:00
const struct iio_chan_spec * chan ,
unsigned int mode )
2011-06-10 17:40:49 +04:00
{
struct ad5686_state * st = iio_priv ( indio_dev ) ;
2012-06-04 13:36:17 +04:00
st - > pwr_down_mode & = ~ ( 0x3 < < ( chan - > channel * 2 ) ) ;
st - > pwr_down_mode | = ( ( mode + 1 ) < < ( chan - > channel * 2 ) ) ;
2011-06-10 17:40:49 +04:00
2012-06-04 13:36:17 +04:00
return 0 ;
2011-06-10 17:40:49 +04:00
}
2012-06-04 13:36:17 +04:00
static const struct iio_enum ad5686_powerdown_mode_enum = {
. items = ad5686_powerdown_modes ,
. num_items = ARRAY_SIZE ( ad5686_powerdown_modes ) ,
. get = ad5686_get_powerdown_mode ,
. set = ad5686_set_powerdown_mode ,
} ;
static ssize_t ad5686_read_dac_powerdown ( struct iio_dev * indio_dev ,
2018-04-11 14:51:51 +03:00
uintptr_t private , const struct iio_chan_spec * chan , char * buf )
2011-06-10 17:40:49 +04:00
{
struct ad5686_state * st = iio_priv ( indio_dev ) ;
return sprintf ( buf , " %d \n " , ! ! ( st - > pwr_down_mask &
2018-04-11 14:51:51 +03:00
( 0x3 < < ( chan - > channel * 2 ) ) ) ) ;
2011-06-10 17:40:49 +04:00
}
2012-06-04 13:36:17 +04:00
static ssize_t ad5686_write_dac_powerdown ( struct iio_dev * indio_dev ,
2018-04-11 14:51:51 +03:00
uintptr_t private ,
const struct iio_chan_spec * chan ,
const char * buf ,
size_t len )
2011-06-10 17:40:49 +04:00
{
bool readin ;
int ret ;
struct ad5686_state * st = iio_priv ( indio_dev ) ;
2018-05-18 18:22:50 +03:00
unsigned int val , ref_bit_msk ;
2019-01-09 12:14:16 +03:00
u8 shift , address = 0 ;
2011-06-10 17:40:49 +04:00
ret = strtobool ( buf , & readin ) ;
if ( ret )
return ret ;
2012-10-18 18:43:00 +04:00
if ( readin )
2012-06-04 13:36:17 +04:00
st - > pwr_down_mask | = ( 0x3 < < ( chan - > channel * 2 ) ) ;
2011-06-10 17:40:49 +04:00
else
2012-06-04 13:36:17 +04:00
st - > pwr_down_mask & = ~ ( 0x3 < < ( chan - > channel * 2 ) ) ;
2011-06-10 17:40:49 +04:00
2018-05-18 18:22:50 +03:00
switch ( st - > chip_info - > regmap_type ) {
2018-12-06 16:38:30 +03:00
case AD5310_REGMAP :
shift = 9 ;
ref_bit_msk = AD5310_REF_BIT_MSK ;
break ;
iio:dac:ad5686: Add AD5681R/AD5682R/AD5683/AD5683R support
The AD5681R/AD5682R/AD5683/AD5683R are a family of one channel DACs with
12-bit, 14-bit and 16-bit precision respectively. The devices have either
no built-in reference, or built-in 2.5V reference.
These devices are similar to AD5691R/AD5692R/AD5693/AD5693R except
with a few notable differences:
* they use the SPI interface instead of I2C
* in the write control register, DB18 and DB17 are used for setting the
power mode, while DB16 is the REF bit. This is why a new regmap type
was defined and checked accordingly.
* the shift register is 24 bits wide, the first four bits are the command
bits followed by the data bits. As the data comprises of 20-bit, 18-bit
or 16-bit input code, this means that 4 LSB bits are don't care. This is
why the data needs to be shifted on the left with four bits. Therefore,
AD5683_REGMAP is checked inside a switch case in the ad5686_spi_write()
function. On the other hand, similar devices such as AD5693R family,
have the 4 MSB command bits followed by 4 don't care bits.
Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5683R_5682R_5681R_5683.pdf
Signed-off-by: Stefan Popa <stefan.popa@analog.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-05-18 18:23:34 +03:00
case AD5683_REGMAP :
shift = 13 ;
ref_bit_msk = AD5683_REF_BIT_MSK ;
break ;
2018-05-18 18:22:50 +03:00
case AD5686_REGMAP :
shift = 0 ;
ref_bit_msk = 0 ;
2019-01-09 12:14:16 +03:00
/* AD5674R/AD5679R have 16 channels and 2 powerdown registers */
if ( chan - > channel > 0x7 )
address = 0x8 ;
2018-05-18 18:22:50 +03:00
break ;
case AD5693_REGMAP :
shift = 13 ;
ref_bit_msk = AD5693_REF_BIT_MSK ;
break ;
default :
return - EINVAL ;
}
val = ( ( st - > pwr_down_mask & st - > pwr_down_mode ) < < shift ) ;
if ( ! st - > use_internal_vref )
val | = ref_bit_msk ;
2018-04-11 14:53:17 +03:00
2019-01-09 12:14:16 +03:00
ret = st - > write ( st , AD5686_CMD_POWERDOWN_DAC ,
address , val > > ( address * 2 ) ) ;
2011-06-10 17:40:49 +04:00
return ret ? ret : len ;
}
static int ad5686_read_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int * val ,
int * val2 ,
long m )
{
struct ad5686_state * st = iio_priv ( indio_dev ) ;
int ret ;
switch ( m ) {
2012-04-15 20:41:19 +04:00
case IIO_CHAN_INFO_RAW :
2020-05-14 12:19:38 +03:00
mutex_lock ( & st - > lock ) ;
2018-04-11 14:53:17 +03:00
ret = st - > read ( st , chan - > address ) ;
2020-05-14 12:19:38 +03:00
mutex_unlock ( & st - > lock ) ;
2011-06-10 17:40:49 +04:00
if ( ret < 0 )
return ret ;
2018-12-06 16:53:15 +03:00
* val = ( ret > > chan - > scan_type . shift ) &
GENMASK ( chan - > scan_type . realbits - 1 , 0 ) ;
2011-06-10 17:40:49 +04:00
return IIO_VAL_INT ;
2011-10-26 20:41:36 +04:00
case IIO_CHAN_INFO_SCALE :
2013-09-28 13:31:00 +04:00
* val = st - > vref_mv ;
* val2 = chan - > scan_type . realbits ;
return IIO_VAL_FRACTIONAL_LOG2 ;
2011-06-10 17:40:49 +04:00
}
return - EINVAL ;
}
static int ad5686_write_raw ( struct iio_dev * indio_dev ,
2018-04-11 14:51:51 +03:00
struct iio_chan_spec const * chan ,
int val ,
int val2 ,
long mask )
2011-06-10 17:40:49 +04:00
{
struct ad5686_state * st = iio_priv ( indio_dev ) ;
int ret ;
switch ( mask ) {
2012-04-15 20:41:19 +04:00
case IIO_CHAN_INFO_RAW :
2011-10-19 19:51:28 +04:00
if ( val > ( 1 < < chan - > scan_type . realbits ) | | val < 0 )
2011-06-10 17:40:49 +04:00
return - EINVAL ;
2020-05-14 12:19:38 +03:00
mutex_lock ( & st - > lock ) ;
2018-04-11 14:53:17 +03:00
ret = st - > write ( st ,
AD5686_CMD_WRITE_INPUT_N_UPDATE_N ,
chan - > address ,
val < < chan - > scan_type . shift ) ;
2020-05-14 12:19:38 +03:00
mutex_unlock ( & st - > lock ) ;
2011-06-10 17:40:49 +04:00
break ;
default :
ret = - EINVAL ;
}
return ret ;
}
static const struct iio_info ad5686_info = {
. read_raw = ad5686_read_raw ,
. write_raw = ad5686_write_raw ,
} ;
2012-06-04 13:36:17 +04:00
static const struct iio_chan_spec_ext_info ad5686_ext_info [ ] = {
{
. name = " powerdown " ,
. read = ad5686_read_dac_powerdown ,
. write = ad5686_write_dac_powerdown ,
2013-09-08 17:57:00 +04:00
. shared = IIO_SEPARATE ,
2012-06-04 13:36:17 +04:00
} ,
2013-09-08 17:57:00 +04:00
IIO_ENUM ( " powerdown_mode " , IIO_SEPARATE , & ad5686_powerdown_mode_enum ) ,
2012-06-04 13:36:17 +04:00
IIO_ENUM_AVAILABLE ( " powerdown_mode " , & ad5686_powerdown_mode_enum ) ,
{ } ,
} ;
2018-04-11 14:52:31 +03:00
# define AD5868_CHANNEL(chan, addr, bits, _shift) { \
2012-06-04 13:36:17 +04:00
. type = IIO_VOLTAGE , \
. indexed = 1 , \
. output = 1 , \
. channel = chan , \
2013-02-27 23:27:41 +04:00
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) , \
. info_mask_shared_by_type = BIT ( IIO_CHAN_INFO_SCALE ) , \
2018-04-11 14:52:31 +03:00
. address = addr , \
2013-12-11 22:45:00 +04:00
. scan_type = { \
. sign = ' u ' , \
. realbits = ( bits ) , \
. storagebits = 16 , \
. shift = ( _shift ) , \
} , \
2012-06-04 13:36:17 +04:00
. ext_info = ad5686_ext_info , \
}
2018-05-18 18:22:50 +03:00
# define DECLARE_AD5693_CHANNELS(name, bits, _shift) \
2020-05-27 00:02:21 +03:00
static const struct iio_chan_spec name [ ] = { \
2018-05-18 18:22:50 +03:00
AD5868_CHANNEL ( 0 , 0 , bits , _shift ) , \
}
2018-04-11 14:52:31 +03:00
# define DECLARE_AD5686_CHANNELS(name, bits, _shift) \
2020-05-27 00:02:21 +03:00
static const struct iio_chan_spec name [ ] = { \
2018-04-11 14:52:31 +03:00
AD5868_CHANNEL ( 0 , 1 , bits , _shift ) , \
AD5868_CHANNEL ( 1 , 2 , bits , _shift ) , \
AD5868_CHANNEL ( 2 , 4 , bits , _shift ) , \
AD5868_CHANNEL ( 3 , 8 , bits , _shift ) , \
}
2018-04-11 14:53:01 +03:00
# define DECLARE_AD5676_CHANNELS(name, bits, _shift) \
2020-05-27 00:02:21 +03:00
static const struct iio_chan_spec name [ ] = { \
2018-04-11 14:53:01 +03:00
AD5868_CHANNEL ( 0 , 0 , bits , _shift ) , \
AD5868_CHANNEL ( 1 , 1 , bits , _shift ) , \
AD5868_CHANNEL ( 2 , 2 , bits , _shift ) , \
AD5868_CHANNEL ( 3 , 3 , bits , _shift ) , \
AD5868_CHANNEL ( 4 , 4 , bits , _shift ) , \
AD5868_CHANNEL ( 5 , 5 , bits , _shift ) , \
AD5868_CHANNEL ( 6 , 6 , bits , _shift ) , \
AD5868_CHANNEL ( 7 , 7 , bits , _shift ) , \
}
2019-01-09 12:14:16 +03:00
# define DECLARE_AD5679_CHANNELS(name, bits, _shift) \
2020-05-27 00:02:21 +03:00
static const struct iio_chan_spec name [ ] = { \
2019-01-09 12:14:16 +03:00
AD5868_CHANNEL ( 0 , 0 , bits , _shift ) , \
AD5868_CHANNEL ( 1 , 1 , bits , _shift ) , \
AD5868_CHANNEL ( 2 , 2 , bits , _shift ) , \
AD5868_CHANNEL ( 3 , 3 , bits , _shift ) , \
AD5868_CHANNEL ( 4 , 4 , bits , _shift ) , \
AD5868_CHANNEL ( 5 , 5 , bits , _shift ) , \
AD5868_CHANNEL ( 6 , 6 , bits , _shift ) , \
AD5868_CHANNEL ( 7 , 7 , bits , _shift ) , \
AD5868_CHANNEL ( 8 , 8 , bits , _shift ) , \
AD5868_CHANNEL ( 9 , 9 , bits , _shift ) , \
AD5868_CHANNEL ( 10 , 10 , bits , _shift ) , \
AD5868_CHANNEL ( 11 , 11 , bits , _shift ) , \
AD5868_CHANNEL ( 12 , 12 , bits , _shift ) , \
AD5868_CHANNEL ( 13 , 13 , bits , _shift ) , \
AD5868_CHANNEL ( 14 , 14 , bits , _shift ) , \
AD5868_CHANNEL ( 15 , 15 , bits , _shift ) , \
}
2018-12-06 16:38:30 +03:00
DECLARE_AD5693_CHANNELS ( ad5310r_channels , 10 , 2 ) ;
2018-06-04 17:22:07 +03:00
DECLARE_AD5693_CHANNELS ( ad5311r_channels , 10 , 6 ) ;
2018-04-11 14:53:01 +03:00
DECLARE_AD5676_CHANNELS ( ad5672_channels , 12 , 4 ) ;
2019-01-09 12:14:16 +03:00
DECLARE_AD5679_CHANNELS ( ad5674r_channels , 12 , 4 ) ;
2018-04-11 14:53:01 +03:00
DECLARE_AD5676_CHANNELS ( ad5676_channels , 16 , 0 ) ;
2019-01-09 12:14:16 +03:00
DECLARE_AD5679_CHANNELS ( ad5679r_channels , 16 , 0 ) ;
2018-04-11 14:52:31 +03:00
DECLARE_AD5686_CHANNELS ( ad5684_channels , 12 , 4 ) ;
DECLARE_AD5686_CHANNELS ( ad5685r_channels , 14 , 2 ) ;
DECLARE_AD5686_CHANNELS ( ad5686_channels , 16 , 0 ) ;
2018-05-18 18:22:50 +03:00
DECLARE_AD5693_CHANNELS ( ad5693_channels , 16 , 0 ) ;
DECLARE_AD5693_CHANNELS ( ad5692r_channels , 14 , 2 ) ;
DECLARE_AD5693_CHANNELS ( ad5691r_channels , 12 , 4 ) ;
2018-04-11 14:52:31 +03:00
2012-06-04 13:36:17 +04:00
static const struct ad5686_chip_info ad5686_chip_info_tbl [ ] = {
2018-12-06 16:38:30 +03:00
[ ID_AD5310R ] = {
. channels = ad5310r_channels ,
. int_vref_mv = 2500 ,
. num_channels = 1 ,
. regmap_type = AD5310_REGMAP ,
} ,
2018-06-04 17:22:07 +03:00
[ ID_AD5311R ] = {
. channels = ad5311r_channels ,
. int_vref_mv = 2500 ,
. num_channels = 1 ,
. regmap_type = AD5693_REGMAP ,
} ,
2018-04-11 14:53:39 +03:00
[ ID_AD5671R ] = {
. channels = ad5672_channels ,
. int_vref_mv = 2500 ,
. num_channels = 8 ,
2018-05-18 18:22:50 +03:00
. regmap_type = AD5686_REGMAP ,
2018-04-11 14:53:39 +03:00
} ,
2018-04-11 14:53:01 +03:00
[ ID_AD5672R ] = {
. channels = ad5672_channels ,
. int_vref_mv = 2500 ,
. num_channels = 8 ,
2018-05-18 18:22:50 +03:00
. regmap_type = AD5686_REGMAP ,
2018-04-11 14:53:01 +03:00
} ,
2019-01-09 12:14:16 +03:00
[ ID_AD5674R ] = {
. channels = ad5674r_channels ,
. int_vref_mv = 2500 ,
. num_channels = 16 ,
. regmap_type = AD5686_REGMAP ,
} ,
2018-04-11 14:53:39 +03:00
[ ID_AD5675R ] = {
. channels = ad5676_channels ,
. int_vref_mv = 2500 ,
. num_channels = 8 ,
2018-05-18 18:22:50 +03:00
. regmap_type = AD5686_REGMAP ,
2018-04-11 14:53:39 +03:00
} ,
2018-04-11 14:53:01 +03:00
[ ID_AD5676 ] = {
. channels = ad5676_channels ,
. num_channels = 8 ,
2018-05-18 18:22:50 +03:00
. regmap_type = AD5686_REGMAP ,
2018-04-11 14:53:01 +03:00
} ,
[ ID_AD5676R ] = {
. channels = ad5676_channels ,
. int_vref_mv = 2500 ,
. num_channels = 8 ,
2018-05-18 18:22:50 +03:00
. regmap_type = AD5686_REGMAP ,
2018-04-11 14:53:01 +03:00
} ,
2019-01-09 12:14:16 +03:00
[ ID_AD5679R ] = {
. channels = ad5679r_channels ,
. int_vref_mv = 2500 ,
. num_channels = 16 ,
. regmap_type = AD5686_REGMAP ,
} ,
iio:dac:ad5686: Add AD5681R/AD5682R/AD5683/AD5683R support
The AD5681R/AD5682R/AD5683/AD5683R are a family of one channel DACs with
12-bit, 14-bit and 16-bit precision respectively. The devices have either
no built-in reference, or built-in 2.5V reference.
These devices are similar to AD5691R/AD5692R/AD5693/AD5693R except
with a few notable differences:
* they use the SPI interface instead of I2C
* in the write control register, DB18 and DB17 are used for setting the
power mode, while DB16 is the REF bit. This is why a new regmap type
was defined and checked accordingly.
* the shift register is 24 bits wide, the first four bits are the command
bits followed by the data bits. As the data comprises of 20-bit, 18-bit
or 16-bit input code, this means that 4 LSB bits are don't care. This is
why the data needs to be shifted on the left with four bits. Therefore,
AD5683_REGMAP is checked inside a switch case in the ad5686_spi_write()
function. On the other hand, similar devices such as AD5693R family,
have the 4 MSB command bits followed by 4 don't care bits.
Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5683R_5682R_5681R_5683.pdf
Signed-off-by: Stefan Popa <stefan.popa@analog.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-05-18 18:23:34 +03:00
[ ID_AD5681R ] = {
. channels = ad5691r_channels ,
. int_vref_mv = 2500 ,
. num_channels = 1 ,
. regmap_type = AD5683_REGMAP ,
} ,
[ ID_AD5682R ] = {
. channels = ad5692r_channels ,
. int_vref_mv = 2500 ,
. num_channels = 1 ,
. regmap_type = AD5683_REGMAP ,
} ,
[ ID_AD5683 ] = {
. channels = ad5693_channels ,
. num_channels = 1 ,
. regmap_type = AD5683_REGMAP ,
} ,
[ ID_AD5683R ] = {
. channels = ad5693_channels ,
. int_vref_mv = 2500 ,
. num_channels = 1 ,
. regmap_type = AD5683_REGMAP ,
} ,
2012-06-04 13:36:17 +04:00
[ ID_AD5684 ] = {
2018-04-11 14:52:31 +03:00
. channels = ad5684_channels ,
. num_channels = 4 ,
2018-05-18 18:22:50 +03:00
. regmap_type = AD5686_REGMAP ,
2018-04-11 14:53:01 +03:00
} ,
[ ID_AD5684R ] = {
. channels = ad5684_channels ,
2012-06-04 13:36:17 +04:00
. int_vref_mv = 2500 ,
2018-04-11 14:53:01 +03:00
. num_channels = 4 ,
2018-05-18 18:22:50 +03:00
. regmap_type = AD5686_REGMAP ,
2012-06-04 13:36:17 +04:00
} ,
2018-04-11 14:52:48 +03:00
[ ID_AD5685R ] = {
2018-04-11 14:52:31 +03:00
. channels = ad5685r_channels ,
2012-06-04 13:36:17 +04:00
. int_vref_mv = 2500 ,
2018-04-11 14:52:31 +03:00
. num_channels = 4 ,
2018-05-18 18:22:50 +03:00
. regmap_type = AD5686_REGMAP ,
2012-06-04 13:36:17 +04:00
} ,
[ ID_AD5686 ] = {
2018-04-11 14:52:31 +03:00
. channels = ad5686_channels ,
. num_channels = 4 ,
2018-05-18 18:22:50 +03:00
. regmap_type = AD5686_REGMAP ,
2018-04-11 14:53:01 +03:00
} ,
[ ID_AD5686R ] = {
. channels = ad5686_channels ,
2012-06-04 13:36:17 +04:00
. int_vref_mv = 2500 ,
2018-04-11 14:53:01 +03:00
. num_channels = 4 ,
2018-05-18 18:22:50 +03:00
. regmap_type = AD5686_REGMAP ,
} ,
[ ID_AD5691R ] = {
. channels = ad5691r_channels ,
. int_vref_mv = 2500 ,
. num_channels = 1 ,
. regmap_type = AD5693_REGMAP ,
} ,
[ ID_AD5692R ] = {
. channels = ad5692r_channels ,
. int_vref_mv = 2500 ,
. num_channels = 1 ,
. regmap_type = AD5693_REGMAP ,
} ,
[ ID_AD5693 ] = {
. channels = ad5693_channels ,
. num_channels = 1 ,
. regmap_type = AD5693_REGMAP ,
} ,
[ ID_AD5693R ] = {
. channels = ad5693_channels ,
. int_vref_mv = 2500 ,
. num_channels = 1 ,
. regmap_type = AD5693_REGMAP ,
2012-06-04 13:36:17 +04:00
} ,
2018-04-11 14:53:39 +03:00
[ ID_AD5694 ] = {
. channels = ad5684_channels ,
. num_channels = 4 ,
2018-05-18 18:22:50 +03:00
. regmap_type = AD5686_REGMAP ,
2018-04-11 14:53:39 +03:00
} ,
[ ID_AD5694R ] = {
. channels = ad5684_channels ,
. int_vref_mv = 2500 ,
. num_channels = 4 ,
2018-05-18 18:22:50 +03:00
. regmap_type = AD5686_REGMAP ,
2018-04-11 14:53:39 +03:00
} ,
[ ID_AD5696 ] = {
. channels = ad5686_channels ,
. num_channels = 4 ,
2018-05-18 18:22:50 +03:00
. regmap_type = AD5686_REGMAP ,
2018-04-11 14:53:39 +03:00
} ,
[ ID_AD5696R ] = {
. channels = ad5686_channels ,
. int_vref_mv = 2500 ,
. num_channels = 4 ,
2018-05-18 18:22:50 +03:00
. regmap_type = AD5686_REGMAP ,
2018-04-11 14:53:39 +03:00
} ,
2012-06-04 13:36:17 +04:00
} ;
2018-04-11 14:53:17 +03:00
int ad5686_probe ( struct device * dev ,
enum ad5686_supported_device_ids chip_type ,
const char * name , ad5686_write_func write ,
ad5686_read_func read )
2011-06-10 17:40:49 +04:00
{
struct ad5686_state * st ;
struct iio_dev * indio_dev ;
2018-05-18 18:22:50 +03:00
unsigned int val , ref_bit_msk ;
u8 cmd ;
int ret , i , voltage_uv = 0 ;
2011-06-10 17:40:49 +04:00
2018-04-11 14:53:17 +03:00
indio_dev = devm_iio_device_alloc ( dev , sizeof ( * st ) ) ;
2011-06-10 17:40:49 +04:00
if ( indio_dev = = NULL )
return - ENOMEM ;
st = iio_priv ( indio_dev ) ;
2018-04-11 14:53:17 +03:00
dev_set_drvdata ( dev , indio_dev ) ;
st - > dev = dev ;
st - > write = write ;
st - > read = read ;
2011-06-10 17:40:49 +04:00
2018-04-11 14:53:17 +03:00
st - > reg = devm_regulator_get_optional ( dev , " vcc " ) ;
2011-06-10 17:40:49 +04:00
if ( ! IS_ERR ( st - > reg ) ) {
ret = regulator_enable ( st - > reg ) ;
if ( ret )
2013-08-19 15:38:00 +04:00
return ret ;
2011-06-10 17:40:49 +04:00
2012-12-14 16:08:00 +04:00
ret = regulator_get_voltage ( st - > reg ) ;
if ( ret < 0 )
goto error_disable_reg ;
voltage_uv = ret ;
2011-06-10 17:40:49 +04:00
}
2018-04-11 14:53:17 +03:00
st - > chip_info = & ad5686_chip_info_tbl [ chip_type ] ;
2011-06-10 17:40:49 +04:00
if ( voltage_uv )
st - > vref_mv = voltage_uv / 1000 ;
else
st - > vref_mv = st - > chip_info - > int_vref_mv ;
2012-06-04 13:36:17 +04:00
/* Set all the power down mode for all channels to 1K pulldown */
2018-05-18 18:22:50 +03:00
for ( i = 0 ; i < st - > chip_info - > num_channels ; i + + )
st - > pwr_down_mode | = ( 0x01 < < ( i * 2 ) ) ;
2012-06-04 13:36:17 +04:00
2018-04-11 14:53:17 +03:00
indio_dev - > name = name ;
2011-06-10 17:40:49 +04:00
indio_dev - > info = & ad5686_info ;
indio_dev - > modes = INDIO_DIRECT_MODE ;
2018-04-11 14:52:31 +03:00
indio_dev - > channels = st - > chip_info - > channels ;
indio_dev - > num_channels = st - > chip_info - > num_channels ;
2011-06-10 17:40:49 +04:00
2020-05-14 12:19:38 +03:00
mutex_init ( & st - > lock ) ;
2018-05-18 18:22:50 +03:00
switch ( st - > chip_info - > regmap_type ) {
2018-12-06 16:38:30 +03:00
case AD5310_REGMAP :
cmd = AD5686_CMD_CONTROL_REG ;
ref_bit_msk = AD5310_REF_BIT_MSK ;
st - > use_internal_vref = ! voltage_uv ;
break ;
iio:dac:ad5686: Add AD5681R/AD5682R/AD5683/AD5683R support
The AD5681R/AD5682R/AD5683/AD5683R are a family of one channel DACs with
12-bit, 14-bit and 16-bit precision respectively. The devices have either
no built-in reference, or built-in 2.5V reference.
These devices are similar to AD5691R/AD5692R/AD5693/AD5693R except
with a few notable differences:
* they use the SPI interface instead of I2C
* in the write control register, DB18 and DB17 are used for setting the
power mode, while DB16 is the REF bit. This is why a new regmap type
was defined and checked accordingly.
* the shift register is 24 bits wide, the first four bits are the command
bits followed by the data bits. As the data comprises of 20-bit, 18-bit
or 16-bit input code, this means that 4 LSB bits are don't care. This is
why the data needs to be shifted on the left with four bits. Therefore,
AD5683_REGMAP is checked inside a switch case in the ad5686_spi_write()
function. On the other hand, similar devices such as AD5693R family,
have the 4 MSB command bits followed by 4 don't care bits.
Datasheet:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5683R_5682R_5681R_5683.pdf
Signed-off-by: Stefan Popa <stefan.popa@analog.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-05-18 18:23:34 +03:00
case AD5683_REGMAP :
cmd = AD5686_CMD_CONTROL_REG ;
ref_bit_msk = AD5683_REF_BIT_MSK ;
st - > use_internal_vref = ! voltage_uv ;
break ;
2018-05-18 18:22:50 +03:00
case AD5686_REGMAP :
cmd = AD5686_CMD_INTERNAL_REFER_SETUP ;
ref_bit_msk = 0 ;
break ;
case AD5693_REGMAP :
cmd = AD5686_CMD_CONTROL_REG ;
ref_bit_msk = AD5693_REF_BIT_MSK ;
st - > use_internal_vref = ! voltage_uv ;
break ;
default :
ret = - EINVAL ;
goto error_disable_reg ;
}
val = ( voltage_uv | ref_bit_msk ) ;
ret = st - > write ( st , cmd , 0 , ! ! val ) ;
2011-06-10 17:40:49 +04:00
if ( ret )
goto error_disable_reg ;
2011-09-02 20:14:40 +04:00
ret = iio_device_register ( indio_dev ) ;
if ( ret )
goto error_disable_reg ;
2011-06-10 17:40:49 +04:00
return 0 ;
error_disable_reg :
if ( ! IS_ERR ( st - > reg ) )
regulator_disable ( st - > reg ) ;
return ret ;
}
2018-04-11 14:53:17 +03:00
EXPORT_SYMBOL_GPL ( ad5686_probe ) ;
2011-06-10 17:40:49 +04:00
2018-04-11 14:53:17 +03:00
int ad5686_remove ( struct device * dev )
2011-06-10 17:40:49 +04:00
{
2018-04-11 14:53:17 +03:00
struct iio_dev * indio_dev = dev_get_drvdata ( dev ) ;
2011-06-10 17:40:49 +04:00
struct ad5686_state * st = iio_priv ( indio_dev ) ;
2011-10-14 17:46:58 +04:00
iio_device_unregister ( indio_dev ) ;
2013-08-19 15:38:00 +04:00
if ( ! IS_ERR ( st - > reg ) )
2011-08-30 15:41:19 +04:00
regulator_disable ( st - > reg ) ;
2011-06-10 17:40:49 +04:00
return 0 ;
}
2018-04-11 14:53:17 +03:00
EXPORT_SYMBOL_GPL ( ad5686_remove ) ;
2011-06-10 17:40:49 +04:00
2018-08-14 14:23:17 +03:00
MODULE_AUTHOR ( " Michael Hennerich <michael.hennerich@analog.com> " ) ;
2011-06-10 17:40:49 +04:00
MODULE_DESCRIPTION ( " Analog Devices AD5686/85/84 DAC " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;