2021-01-15 13:21:05 +02:00
// SPDX-License-Identifier: GPL-2.0-only
/*
* Analog Devices AD5766 , AD5767
* Digital to Analog Converters driver
* Copyright 2019 - 2020 Analog Devices Inc .
*/
# include <linux/bitfield.h>
2021-10-07 08:00:37 +00:00
# include <linux/bitops.h>
2021-01-15 13:21:05 +02:00
# include <linux/delay.h>
# include <linux/device.h>
# include <linux/gpio/consumer.h>
# include <linux/iio/iio.h>
2021-10-07 08:00:37 +00:00
# include <linux/iio/triggered_buffer.h>
# include <linux/iio/trigger_consumer.h>
2021-01-15 13:21:05 +02:00
# include <linux/module.h>
# include <linux/spi/spi.h>
# include <asm/unaligned.h>
# define AD5766_UPPER_WORD_SPI_MASK GENMASK(31, 16)
# define AD5766_LOWER_WORD_SPI_MASK GENMASK(15, 0)
# define AD5766_DITHER_SOURCE_MASK(ch) GENMASK(((2 * ch) + 1), (2 * ch))
# define AD5766_DITHER_SOURCE(ch, source) BIT((ch * 2) + source)
# define AD5766_DITHER_SCALE_MASK(x) AD5766_DITHER_SOURCE_MASK(x)
# define AD5766_DITHER_SCALE(ch, scale) (scale << (ch * 2))
# define AD5766_DITHER_ENABLE_MASK(ch) BIT(ch)
# define AD5766_DITHER_ENABLE(ch, state) ((!state) << ch)
# define AD5766_DITHER_INVERT_MASK(ch) BIT(ch)
# define AD5766_DITHER_INVERT(ch, state) (state << ch)
# define AD5766_CMD_NOP_MUX_OUT 0x00
# define AD5766_CMD_SDO_CNTRL 0x01
# define AD5766_CMD_WR_IN_REG(x) (0x10 | ((x) & GENMASK(3, 0)))
# define AD5766_CMD_WR_DAC_REG(x) (0x20 | ((x) & GENMASK(3, 0)))
# define AD5766_CMD_SW_LDAC 0x30
# define AD5766_CMD_SPAN_REG 0x40
# define AD5766_CMD_WR_PWR_DITHER 0x51
# define AD5766_CMD_WR_DAC_REG_ALL 0x60
# define AD5766_CMD_SW_FULL_RESET 0x70
# define AD5766_CMD_READBACK_REG(x) (0x80 | ((x) & GENMASK(3, 0)))
# define AD5766_CMD_DITHER_SIG_1 0x90
# define AD5766_CMD_DITHER_SIG_2 0xA0
# define AD5766_CMD_INV_DITHER 0xB0
# define AD5766_CMD_DITHER_SCALE_1 0xC0
# define AD5766_CMD_DITHER_SCALE_2 0xD0
# define AD5766_FULL_RESET_CODE 0x1234
enum ad5766_type {
ID_AD5766 ,
ID_AD5767 ,
} ;
enum ad5766_voltage_range {
AD5766_VOLTAGE_RANGE_M20V_0V ,
AD5766_VOLTAGE_RANGE_M16V_to_0V ,
AD5766_VOLTAGE_RANGE_M10V_to_0V ,
AD5766_VOLTAGE_RANGE_M12V_to_14V ,
AD5766_VOLTAGE_RANGE_M16V_to_10V ,
AD5766_VOLTAGE_RANGE_M10V_to_6V ,
AD5766_VOLTAGE_RANGE_M5V_to_5V ,
AD5766_VOLTAGE_RANGE_M10V_to_10V ,
} ;
/**
* struct ad5766_chip_info - chip specific information
* @ num_channels : number of channels
* @ channels : channel specification
*/
struct ad5766_chip_info {
unsigned int num_channels ;
const struct iio_chan_spec * channels ;
} ;
enum {
AD5766_DITHER_ENABLE ,
AD5766_DITHER_INVERT ,
AD5766_DITHER_SOURCE ,
} ;
/*
* Dither signal can also be scaled .
* Available dither scale strings corresponding to " dither_scale " field in
* " struct ad5766_state " .
*/
static const char * const ad5766_dither_scales [ ] = {
" 1 " ,
" 0.75 " ,
" 0.5 " ,
" 0.25 " ,
} ;
/**
* struct ad5766_state - driver instance specific data
* @ spi : SPI device
2021-03-23 06:52:15 +05:30
* @ lock : Lock used to restrict concurrent access to SPI device
2021-01-15 13:21:05 +02:00
* @ chip_info : Chip model specific constants
* @ gpio_reset : Reset GPIO , used to reset the device
* @ crt_range : Current selected output range
* @ dither_enable : Power enable bit for each channel dither block ( for
* example , D15 = DAC 15 , D8 = DAC 8 , and D0 = DAC 0 )
* 0 - Normal operation , 1 - Power down
* @ dither_invert : Inverts the dither signal applied to the selected DAC
* outputs
* @ dither_source : Selects between 2 possible sources :
* 1 : N0 , 2 : N1
* Two bits are used for each channel
* @ dither_scale : Two bits are used for each of the 16 channels :
* 0 : 1 SCALING , 1 : 0.75 SCALING , 2 : 0.5 SCALING ,
* 3 : 0.25 SCALING .
* @ data : SPI transfer buffers
*/
struct ad5766_state {
struct spi_device * spi ;
struct mutex lock ;
const struct ad5766_chip_info * chip_info ;
struct gpio_desc * gpio_reset ;
enum ad5766_voltage_range crt_range ;
u16 dither_enable ;
u16 dither_invert ;
u32 dither_source ;
u32 dither_scale ;
union {
u32 d32 ;
u16 w16 [ 2 ] ;
u8 b8 [ 4 ] ;
2022-05-08 18:56:33 +01:00
} data [ 3 ] __aligned ( IIO_DMA_MINALIGN ) ;
2021-01-15 13:21:05 +02:00
} ;
struct ad5766_span_tbl {
int min ;
int max ;
} ;
static const struct ad5766_span_tbl ad5766_span_tbl [ ] = {
[ AD5766_VOLTAGE_RANGE_M20V_0V ] = { - 20 , 0 } ,
[ AD5766_VOLTAGE_RANGE_M16V_to_0V ] = { - 16 , 0 } ,
[ AD5766_VOLTAGE_RANGE_M10V_to_0V ] = { - 10 , 0 } ,
[ AD5766_VOLTAGE_RANGE_M12V_to_14V ] = { - 12 , 14 } ,
[ AD5766_VOLTAGE_RANGE_M16V_to_10V ] = { - 16 , 10 } ,
[ AD5766_VOLTAGE_RANGE_M10V_to_6V ] = { - 10 , 6 } ,
[ AD5766_VOLTAGE_RANGE_M5V_to_5V ] = { - 5 , 5 } ,
[ AD5766_VOLTAGE_RANGE_M10V_to_10V ] = { - 10 , 10 } ,
} ;
static int __ad5766_spi_read ( struct ad5766_state * st , u8 dac , int * val )
{
int ret ;
struct spi_transfer xfers [ ] = {
{
. tx_buf = & st - > data [ 0 ] . d32 ,
. bits_per_word = 8 ,
. len = 3 ,
. cs_change = 1 ,
} , {
. tx_buf = & st - > data [ 1 ] . d32 ,
. rx_buf = & st - > data [ 2 ] . d32 ,
. bits_per_word = 8 ,
. len = 3 ,
} ,
} ;
st - > data [ 0 ] . d32 = AD5766_CMD_READBACK_REG ( dac ) ;
st - > data [ 1 ] . d32 = AD5766_CMD_NOP_MUX_OUT ;
ret = spi_sync_transfer ( st - > spi , xfers , ARRAY_SIZE ( xfers ) ) ;
if ( ret )
return ret ;
* val = st - > data [ 2 ] . w16 [ 1 ] ;
return ret ;
}
static int __ad5766_spi_write ( struct ad5766_state * st , u8 command , u16 data )
{
st - > data [ 0 ] . b8 [ 0 ] = command ;
put_unaligned_be16 ( data , & st - > data [ 0 ] . b8 [ 1 ] ) ;
return spi_write ( st - > spi , & st - > data [ 0 ] . b8 [ 0 ] , 3 ) ;
}
static int ad5766_read ( struct iio_dev * indio_dev , u8 dac , int * val )
{
struct ad5766_state * st = iio_priv ( indio_dev ) ;
int ret ;
mutex_lock ( & st - > lock ) ;
ret = __ad5766_spi_read ( st , dac , val ) ;
mutex_unlock ( & st - > lock ) ;
return ret ;
}
static int ad5766_write ( struct iio_dev * indio_dev , u8 dac , u16 data )
{
struct ad5766_state * st = iio_priv ( indio_dev ) ;
int ret ;
mutex_lock ( & st - > lock ) ;
ret = __ad5766_spi_write ( st , AD5766_CMD_WR_DAC_REG ( dac ) , data ) ;
mutex_unlock ( & st - > lock ) ;
return ret ;
}
static int ad5766_reset ( struct ad5766_state * st )
{
int ret ;
if ( st - > gpio_reset ) {
gpiod_set_value_cansleep ( st - > gpio_reset , 1 ) ;
ndelay ( 100 ) ; /* t_reset >= 100ns */
gpiod_set_value_cansleep ( st - > gpio_reset , 0 ) ;
} else {
ret = __ad5766_spi_write ( st , AD5766_CMD_SW_FULL_RESET ,
AD5766_FULL_RESET_CODE ) ;
if ( ret < 0 )
return ret ;
}
/*
* Minimum time between a reset and the subsequent successful write is
* typically 25 ns
*/
ndelay ( 25 ) ;
return 0 ;
}
static int ad5766_read_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int * val ,
int * val2 ,
long m )
{
struct ad5766_state * st = iio_priv ( indio_dev ) ;
int ret ;
switch ( m ) {
case IIO_CHAN_INFO_RAW :
ret = ad5766_read ( indio_dev , chan - > address , val ) ;
if ( ret )
return ret ;
return IIO_VAL_INT ;
case IIO_CHAN_INFO_OFFSET :
* val = ad5766_span_tbl [ st - > crt_range ] . min ;
return IIO_VAL_INT ;
case IIO_CHAN_INFO_SCALE :
* val = ad5766_span_tbl [ st - > crt_range ] . max -
ad5766_span_tbl [ st - > crt_range ] . min ;
* val2 = st - > chip_info - > channels [ 0 ] . scan_type . realbits ;
return IIO_VAL_FRACTIONAL_LOG2 ;
default :
return - EINVAL ;
}
}
static int ad5766_write_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int val ,
int val2 ,
long info )
{
switch ( info ) {
case IIO_CHAN_INFO_RAW :
{
const int max_val = GENMASK ( chan - > scan_type . realbits - 1 , 0 ) ;
if ( val > max_val | | val < 0 )
return - EINVAL ;
val < < = chan - > scan_type . shift ;
return ad5766_write ( indio_dev , chan - > address , val ) ;
}
default :
return - EINVAL ;
}
}
static const struct iio_info ad5766_info = {
. read_raw = ad5766_read_raw ,
. write_raw = ad5766_write_raw ,
} ;
static int ad5766_get_dither_source ( struct iio_dev * dev ,
const struct iio_chan_spec * chan )
{
struct ad5766_state * st = iio_priv ( dev ) ;
u32 source ;
source = st - > dither_source & AD5766_DITHER_SOURCE_MASK ( chan - > channel ) ;
source = source > > ( chan - > channel * 2 ) ;
source - = 1 ;
return source ;
}
static int ad5766_set_dither_source ( struct iio_dev * dev ,
const struct iio_chan_spec * chan ,
unsigned int source )
{
struct ad5766_state * st = iio_priv ( dev ) ;
uint16_t val ;
int ret ;
st - > dither_source & = ~ AD5766_DITHER_SOURCE_MASK ( chan - > channel ) ;
st - > dither_source | = AD5766_DITHER_SOURCE ( chan - > channel , source ) ;
val = FIELD_GET ( AD5766_LOWER_WORD_SPI_MASK , st - > dither_source ) ;
ret = ad5766_write ( dev , AD5766_CMD_DITHER_SIG_1 , val ) ;
if ( ret )
return ret ;
val = FIELD_GET ( AD5766_UPPER_WORD_SPI_MASK , st - > dither_source ) ;
return ad5766_write ( dev , AD5766_CMD_DITHER_SIG_2 , val ) ;
}
static int ad5766_get_dither_scale ( struct iio_dev * dev ,
const struct iio_chan_spec * chan )
{
struct ad5766_state * st = iio_priv ( dev ) ;
u32 scale ;
scale = st - > dither_scale & AD5766_DITHER_SCALE_MASK ( chan - > channel ) ;
return ( scale > > ( chan - > channel * 2 ) ) ;
}
static int ad5766_set_dither_scale ( struct iio_dev * dev ,
const struct iio_chan_spec * chan ,
unsigned int scale )
{
int ret ;
struct ad5766_state * st = iio_priv ( dev ) ;
uint16_t val ;
st - > dither_scale & = ~ AD5766_DITHER_SCALE_MASK ( chan - > channel ) ;
st - > dither_scale | = AD5766_DITHER_SCALE ( chan - > channel , scale ) ;
val = FIELD_GET ( AD5766_LOWER_WORD_SPI_MASK , st - > dither_scale ) ;
ret = ad5766_write ( dev , AD5766_CMD_DITHER_SCALE_1 , val ) ;
if ( ret )
return ret ;
val = FIELD_GET ( AD5766_UPPER_WORD_SPI_MASK , st - > dither_scale ) ;
return ad5766_write ( dev , AD5766_CMD_DITHER_SCALE_2 , val ) ;
}
static const struct iio_enum ad5766_dither_scale_enum = {
. items = ad5766_dither_scales ,
. num_items = ARRAY_SIZE ( ad5766_dither_scales ) ,
. set = ad5766_set_dither_scale ,
. get = ad5766_get_dither_scale ,
} ;
static ssize_t ad5766_read_ext ( struct iio_dev * indio_dev ,
uintptr_t private ,
const struct iio_chan_spec * chan ,
char * buf )
{
struct ad5766_state * st = iio_priv ( indio_dev ) ;
switch ( private ) {
case AD5766_DITHER_ENABLE :
return sprintf ( buf , " %u \n " ,
! ( st - > dither_enable & BIT ( chan - > channel ) ) ) ;
break ;
case AD5766_DITHER_INVERT :
return sprintf ( buf , " %u \n " ,
! ! ( st - > dither_invert & BIT ( chan - > channel ) ) ) ;
break ;
case AD5766_DITHER_SOURCE :
return sprintf ( buf , " %d \n " ,
ad5766_get_dither_source ( indio_dev , chan ) ) ;
default :
return - EINVAL ;
}
}
static ssize_t ad5766_write_ext ( struct iio_dev * indio_dev ,
uintptr_t private ,
const struct iio_chan_spec * chan ,
const char * buf , size_t len )
{
struct ad5766_state * st = iio_priv ( indio_dev ) ;
bool readin ;
int ret ;
ret = kstrtobool ( buf , & readin ) ;
if ( ret )
return ret ;
switch ( private ) {
case AD5766_DITHER_ENABLE :
st - > dither_enable & = ~ AD5766_DITHER_ENABLE_MASK ( chan - > channel ) ;
st - > dither_enable | = AD5766_DITHER_ENABLE ( chan - > channel ,
readin ) ;
ret = ad5766_write ( indio_dev , AD5766_CMD_WR_PWR_DITHER ,
st - > dither_enable ) ;
break ;
case AD5766_DITHER_INVERT :
st - > dither_invert & = ~ AD5766_DITHER_INVERT_MASK ( chan - > channel ) ;
st - > dither_invert | = AD5766_DITHER_INVERT ( chan - > channel ,
readin ) ;
ret = ad5766_write ( indio_dev , AD5766_CMD_INV_DITHER ,
st - > dither_invert ) ;
break ;
case AD5766_DITHER_SOURCE :
ret = ad5766_set_dither_source ( indio_dev , chan , readin ) ;
break ;
default :
return - EINVAL ;
}
return ret ? ret : len ;
}
# define _AD5766_CHAN_EXT_INFO(_name, _what, _shared) { \
. name = _name , \
. read = ad5766_read_ext , \
. write = ad5766_write_ext , \
. private = _what , \
. shared = _shared , \
}
static const struct iio_chan_spec_ext_info ad5766_ext_info [ ] = {
_AD5766_CHAN_EXT_INFO ( " dither_enable " , AD5766_DITHER_ENABLE ,
IIO_SEPARATE ) ,
_AD5766_CHAN_EXT_INFO ( " dither_invert " , AD5766_DITHER_INVERT ,
IIO_SEPARATE ) ,
_AD5766_CHAN_EXT_INFO ( " dither_source " , AD5766_DITHER_SOURCE ,
IIO_SEPARATE ) ,
IIO_ENUM ( " dither_scale " , IIO_SEPARATE , & ad5766_dither_scale_enum ) ,
2021-11-19 10:56:27 +02:00
IIO_ENUM_AVAILABLE ( " dither_scale " , IIO_SEPARATE ,
& ad5766_dither_scale_enum ) ,
2021-01-15 13:21:05 +02:00
{ }
} ;
# define AD576x_CHANNEL(_chan, _bits) { \
. type = IIO_VOLTAGE , \
. indexed = 1 , \
. output = 1 , \
. channel = ( _chan ) , \
. address = ( _chan ) , \
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) , \
. info_mask_shared_by_type = BIT ( IIO_CHAN_INFO_OFFSET ) | \
BIT ( IIO_CHAN_INFO_SCALE ) , \
2021-10-07 08:00:37 +00:00
. scan_index = ( _chan ) , \
2021-01-15 13:21:05 +02:00
. scan_type = { \
. sign = ' u ' , \
. realbits = ( _bits ) , \
. storagebits = 16 , \
. shift = 16 - ( _bits ) , \
} , \
. ext_info = ad5766_ext_info , \
}
# define DECLARE_AD576x_CHANNELS(_name, _bits) \
const struct iio_chan_spec _name [ ] = { \
AD576x_CHANNEL ( 0 , ( _bits ) ) , \
AD576x_CHANNEL ( 1 , ( _bits ) ) , \
AD576x_CHANNEL ( 2 , ( _bits ) ) , \
AD576x_CHANNEL ( 3 , ( _bits ) ) , \
AD576x_CHANNEL ( 4 , ( _bits ) ) , \
AD576x_CHANNEL ( 5 , ( _bits ) ) , \
AD576x_CHANNEL ( 6 , ( _bits ) ) , \
AD576x_CHANNEL ( 7 , ( _bits ) ) , \
AD576x_CHANNEL ( 8 , ( _bits ) ) , \
AD576x_CHANNEL ( 9 , ( _bits ) ) , \
AD576x_CHANNEL ( 10 , ( _bits ) ) , \
AD576x_CHANNEL ( 11 , ( _bits ) ) , \
AD576x_CHANNEL ( 12 , ( _bits ) ) , \
AD576x_CHANNEL ( 13 , ( _bits ) ) , \
AD576x_CHANNEL ( 14 , ( _bits ) ) , \
AD576x_CHANNEL ( 15 , ( _bits ) ) , \
}
static DECLARE_AD576x_CHANNELS ( ad5766_channels , 16 ) ;
static DECLARE_AD576x_CHANNELS ( ad5767_channels , 12 ) ;
static const struct ad5766_chip_info ad5766_chip_infos [ ] = {
[ ID_AD5766 ] = {
. num_channels = ARRAY_SIZE ( ad5766_channels ) ,
. channels = ad5766_channels ,
} ,
[ ID_AD5767 ] = {
. num_channels = ARRAY_SIZE ( ad5767_channels ) ,
. channels = ad5767_channels ,
} ,
} ;
static int ad5766_get_output_range ( struct ad5766_state * st )
{
int i , ret , min , max , tmp [ 2 ] ;
ret = device_property_read_u32_array ( & st - > spi - > dev ,
2021-10-07 08:00:34 +00:00
" output-range-microvolts " ,
2021-01-15 13:21:05 +02:00
tmp , 2 ) ;
if ( ret )
return ret ;
2021-10-07 08:00:34 +00:00
min = tmp [ 0 ] / 1000000 ;
max = tmp [ 1 ] / 1000000 ;
2021-01-15 13:21:05 +02:00
for ( i = 0 ; i < ARRAY_SIZE ( ad5766_span_tbl ) ; i + + ) {
if ( ad5766_span_tbl [ i ] . min ! = min | |
ad5766_span_tbl [ i ] . max ! = max )
continue ;
st - > crt_range = i ;
return 0 ;
}
return - EINVAL ;
}
static int ad5766_default_setup ( struct ad5766_state * st )
{
uint16_t val ;
int ret , i ;
/* Always issue a reset before writing to the span register. */
ret = ad5766_reset ( st ) ;
if ( ret )
return ret ;
ret = ad5766_get_output_range ( st ) ;
if ( ret )
return ret ;
/* Dither power down */
st - > dither_enable = GENMASK ( 15 , 0 ) ;
ret = __ad5766_spi_write ( st , AD5766_CMD_WR_PWR_DITHER ,
st - > dither_enable ) ;
if ( ret )
return ret ;
st - > dither_source = 0 ;
for ( i = 0 ; i < ARRAY_SIZE ( ad5766_channels ) ; i + + )
st - > dither_source | = AD5766_DITHER_SOURCE ( i , 0 ) ;
val = FIELD_GET ( AD5766_LOWER_WORD_SPI_MASK , st - > dither_source ) ;
ret = __ad5766_spi_write ( st , AD5766_CMD_DITHER_SIG_1 , val ) ;
if ( ret )
return ret ;
val = FIELD_GET ( AD5766_UPPER_WORD_SPI_MASK , st - > dither_source ) ;
ret = __ad5766_spi_write ( st , AD5766_CMD_DITHER_SIG_2 , val ) ;
if ( ret )
return ret ;
st - > dither_scale = 0 ;
val = FIELD_GET ( AD5766_LOWER_WORD_SPI_MASK , st - > dither_scale ) ;
ret = __ad5766_spi_write ( st , AD5766_CMD_DITHER_SCALE_1 , val ) ;
if ( ret )
return ret ;
val = FIELD_GET ( AD5766_UPPER_WORD_SPI_MASK , st - > dither_scale ) ;
ret = __ad5766_spi_write ( st , AD5766_CMD_DITHER_SCALE_2 , val ) ;
if ( ret )
return ret ;
st - > dither_invert = 0 ;
ret = __ad5766_spi_write ( st , AD5766_CMD_INV_DITHER , st - > dither_invert ) ;
if ( ret )
return ret ;
return __ad5766_spi_write ( st , AD5766_CMD_SPAN_REG , st - > crt_range ) ;
}
2021-10-07 08:00:37 +00:00
static irqreturn_t ad5766_trigger_handler ( int irq , void * p )
{
struct iio_poll_func * pf = p ;
struct iio_dev * indio_dev = pf - > indio_dev ;
struct iio_buffer * buffer = indio_dev - > buffer ;
struct ad5766_state * st = iio_priv ( indio_dev ) ;
int ret , ch , i ;
u16 data [ ARRAY_SIZE ( ad5766_channels ) ] ;
ret = iio_pop_from_buffer ( buffer , data ) ;
if ( ret )
goto done ;
i = 0 ;
mutex_lock ( & st - > lock ) ;
for_each_set_bit ( ch , indio_dev - > active_scan_mask ,
st - > chip_info - > num_channels - 1 )
__ad5766_spi_write ( st , AD5766_CMD_WR_IN_REG ( ch ) , data [ i + + ] ) ;
__ad5766_spi_write ( st , AD5766_CMD_SW_LDAC ,
* indio_dev - > active_scan_mask ) ;
mutex_unlock ( & st - > lock ) ;
done :
iio_trigger_notify_done ( indio_dev - > trig ) ;
return IRQ_HANDLED ;
}
2021-01-15 13:21:05 +02:00
static int ad5766_probe ( struct spi_device * spi )
{
enum ad5766_type type ;
struct iio_dev * indio_dev ;
struct ad5766_state * st ;
int ret ;
indio_dev = devm_iio_device_alloc ( & spi - > dev , sizeof ( * st ) ) ;
if ( ! indio_dev )
return - ENOMEM ;
st = iio_priv ( indio_dev ) ;
mutex_init ( & st - > lock ) ;
st - > spi = spi ;
type = spi_get_device_id ( spi ) - > driver_data ;
st - > chip_info = & ad5766_chip_infos [ type ] ;
indio_dev - > channels = st - > chip_info - > channels ;
indio_dev - > num_channels = st - > chip_info - > num_channels ;
indio_dev - > info = & ad5766_info ;
indio_dev - > name = spi_get_device_id ( spi ) - > name ;
indio_dev - > modes = INDIO_DIRECT_MODE ;
st - > gpio_reset = devm_gpiod_get_optional ( & st - > spi - > dev , " reset " ,
GPIOD_OUT_LOW ) ;
if ( IS_ERR ( st - > gpio_reset ) )
return PTR_ERR ( st - > gpio_reset ) ;
ret = ad5766_default_setup ( st ) ;
if ( ret )
return ret ;
2021-10-07 08:00:37 +00:00
/* Configure trigger buffer */
ret = devm_iio_triggered_buffer_setup_ext ( & spi - > dev , indio_dev , NULL ,
ad5766_trigger_handler ,
IIO_BUFFER_DIRECTION_OUT ,
NULL ,
NULL ) ;
if ( ret )
return ret ;
2021-01-15 13:21:05 +02:00
return devm_iio_device_register ( & spi - > dev , indio_dev ) ;
}
static const struct of_device_id ad5766_dt_match [ ] = {
{ . compatible = " adi,ad5766 " } ,
{ . compatible = " adi,ad5767 " } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , ad5766_dt_match ) ;
static const struct spi_device_id ad5766_spi_ids [ ] = {
{ " ad5766 " , ID_AD5766 } ,
{ " ad5767 " , ID_AD5767 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( spi , ad5766_spi_ids ) ;
static struct spi_driver ad5766_driver = {
. driver = {
. name = " ad5766 " ,
. of_match_table = ad5766_dt_match ,
} ,
. probe = ad5766_probe ,
. id_table = ad5766_spi_ids ,
} ;
module_spi_driver ( ad5766_driver ) ;
MODULE_AUTHOR ( " Denis-Gabriel Gheorghescu <denis.gheorghescu@analog.com> " ) ;
MODULE_DESCRIPTION ( " Analog Devices AD5766/AD5767 DACs " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;