2019-05-24 13:04:09 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2010-11-22 13:15:23 +03:00
/*
* AD5446 SPI DAC driver
*
* Copyright 2010 Analog Devices Inc .
*/
# include <linux/interrupt.h>
# include <linux/workqueue.h>
# include <linux/device.h>
# include <linux/kernel.h>
# include <linux/slab.h>
# include <linux/sysfs.h>
# include <linux/list.h>
# include <linux/spi/spi.h>
2012-08-21 18:28:00 +04:00
# include <linux/i2c.h>
2010-11-22 13:15:23 +03:00
# include <linux/regulator/consumer.h>
# include <linux/err.h>
2011-07-03 23:49:50 +04:00
# include <linux/module.h>
2020-09-10 20:32:13 +03:00
# include <linux/mod_devicetable.h>
2010-11-22 13:15:23 +03:00
2012-04-25 18:54:58 +04:00
# include <linux/iio/iio.h>
# include <linux/iio/sysfs.h>
2010-11-22 13:15:23 +03:00
2020-04-21 03:31:25 +03:00
# include <asm/unaligned.h>
2012-08-21 18:28:00 +04:00
# define MODE_PWRDWN_1k 0x1
# define MODE_PWRDWN_100k 0x2
# define MODE_PWRDWN_TRISTATE 0x3
/**
* struct ad5446_state - driver instance specific data
2020-07-16 16:59:18 +03:00
* @ dev : this device
2012-08-21 18:28:00 +04:00
* @ chip_info : chip model specific constants , available modes etc
* @ reg : supply regulator
* @ vref_mv : actual reference voltage used
2020-07-16 16:59:18 +03:00
* @ cached_val : store / retrieve values during power down
* @ pwr_down_mode : power down mode ( 1 k , 100 k or tristate )
* @ pwr_down : true if the device is in power down
* @ lock : lock to protect the data buffer during write ops
2012-08-21 18:28:00 +04:00
*/
struct ad5446_state {
struct device * dev ;
const struct ad5446_chip_info * chip_info ;
struct regulator * reg ;
unsigned short vref_mv ;
unsigned cached_val ;
unsigned pwr_down_mode ;
unsigned pwr_down ;
2020-05-14 12:00:42 +03:00
struct mutex lock ;
2012-08-21 18:28:00 +04:00
} ;
/**
* struct ad5446_chip_info - chip specific information
* @ channel : channel spec for the DAC
* @ int_vref_mv : AD5620 / 40 / 60 : the internal reference voltage
* @ write : chip specific helper function to write to the register
*/
struct ad5446_chip_info {
struct iio_chan_spec channel ;
u16 int_vref_mv ;
int ( * write ) ( struct ad5446_state * st , unsigned val ) ;
} ;
2010-11-22 13:15:23 +03:00
2012-04-25 11:44:58 +04:00
static const char * const ad5446_powerdown_modes [ ] = {
2012-06-04 13:36:13 +04:00
" 1kohm_to_gnd " , " 100kohm_to_gnd " , " three_state "
2012-04-25 11:44:58 +04:00
} ;
2012-06-04 13:36:13 +04:00
static int ad5446_set_powerdown_mode ( struct iio_dev * indio_dev ,
const struct iio_chan_spec * chan , unsigned int mode )
2011-03-10 15:26:47 +03:00
{
2011-10-06 20:14:38 +04:00
struct ad5446_state * st = iio_priv ( indio_dev ) ;
2012-04-25 11:44:58 +04:00
2012-06-04 13:36:13 +04:00
st - > pwr_down_mode = mode + 1 ;
2011-03-10 15:26:47 +03:00
2012-06-04 13:36:13 +04:00
return 0 ;
2011-03-10 15:26:47 +03:00
}
2012-06-04 13:36:13 +04:00
static int ad5446_get_powerdown_mode ( struct iio_dev * indio_dev ,
const struct iio_chan_spec * chan )
2011-03-10 15:26:47 +03:00
{
2011-10-06 20:14:38 +04:00
struct ad5446_state * st = iio_priv ( indio_dev ) ;
2011-03-10 15:26:47 +03:00
2012-06-04 13:36:13 +04:00
return st - > pwr_down_mode - 1 ;
2011-03-10 15:26:47 +03:00
}
2012-06-04 13:36:13 +04:00
static const struct iio_enum ad5446_powerdown_mode_enum = {
. items = ad5446_powerdown_modes ,
. num_items = ARRAY_SIZE ( ad5446_powerdown_modes ) ,
. get = ad5446_get_powerdown_mode ,
. set = ad5446_set_powerdown_mode ,
} ;
2012-04-25 11:44:58 +04:00
static ssize_t ad5446_read_dac_powerdown ( struct iio_dev * indio_dev ,
2012-04-27 12:58:36 +04:00
uintptr_t private ,
2012-04-25 11:44:58 +04:00
const struct iio_chan_spec * chan ,
2011-03-10 15:26:47 +03:00
char * buf )
{
2011-10-06 20:14:38 +04:00
struct ad5446_state * st = iio_priv ( indio_dev ) ;
2011-03-10 15:26:47 +03:00
2021-03-20 10:14:05 +03:00
return sysfs_emit ( buf , " %d \n " , st - > pwr_down ) ;
2011-03-10 15:26:47 +03:00
}
2012-04-25 11:44:58 +04:00
static ssize_t ad5446_write_dac_powerdown ( struct iio_dev * indio_dev ,
2012-04-27 12:58:36 +04:00
uintptr_t private ,
2012-04-25 11:44:58 +04:00
const struct iio_chan_spec * chan ,
2011-03-10 15:26:47 +03:00
const char * buf , size_t len )
{
2011-10-06 20:14:38 +04:00
struct ad5446_state * st = iio_priv ( indio_dev ) ;
2012-04-25 11:44:59 +04:00
unsigned int shift ;
unsigned int val ;
2012-04-25 11:44:58 +04:00
bool powerdown ;
2011-03-10 15:26:47 +03:00
int ret ;
2022-04-09 13:58:12 +03:00
ret = kstrtobool ( buf , & powerdown ) ;
2011-03-10 15:26:47 +03:00
if ( ret )
return ret ;
2020-05-14 12:00:42 +03:00
mutex_lock ( & st - > lock ) ;
2012-04-25 11:44:58 +04:00
st - > pwr_down = powerdown ;
2011-03-10 15:26:47 +03:00
2012-04-25 11:44:59 +04:00
if ( st - > pwr_down ) {
shift = chan - > scan_type . realbits + chan - > scan_type . shift ;
val = st - > pwr_down_mode < < shift ;
} else {
val = st - > cached_val ;
}
2011-03-10 15:26:47 +03:00
2012-04-25 11:44:59 +04:00
ret = st - > chip_info - > write ( st , val ) ;
2020-05-14 12:00:42 +03:00
mutex_unlock ( & st - > lock ) ;
2011-03-10 15:26:47 +03:00
return ret ? ret : len ;
}
2012-08-21 18:28:00 +04:00
static const struct iio_chan_spec_ext_info ad5446_ext_info_powerdown [ ] = {
2012-04-25 11:44:58 +04:00
{
. name = " powerdown " ,
. read = ad5446_read_dac_powerdown ,
. write = ad5446_write_dac_powerdown ,
2013-09-08 17:57:00 +04:00
. shared = IIO_SEPARATE ,
2012-04-25 11:44:58 +04:00
} ,
2013-09-08 17:57:00 +04:00
IIO_ENUM ( " powerdown_mode " , IIO_SEPARATE , & ad5446_powerdown_mode_enum ) ,
2021-11-19 11:56:27 +03:00
IIO_ENUM_AVAILABLE ( " powerdown_mode " , IIO_SHARED_BY_TYPE , & ad5446_powerdown_mode_enum ) ,
2012-04-25 11:44:58 +04:00
{ } ,
2010-11-22 13:15:23 +03:00
} ;
2013-12-11 22:45:00 +04:00
# define _AD5446_CHANNEL(bits, storage, _shift, ext) { \
2011-11-15 19:31:22 +04:00
. type = IIO_VOLTAGE , \
. indexed = 1 , \
. output = 1 , \
. channel = 0 , \
2013-02-27 23:10:35 +04:00
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) , \
. info_mask_shared_by_type = BIT ( IIO_CHAN_INFO_SCALE ) , \
2013-12-11 22:45:00 +04:00
. scan_type = { \
. sign = ' u ' , \
. realbits = ( bits ) , \
. storagebits = ( storage ) , \
. shift = ( _shift ) , \
} , \
2012-04-25 11:44:58 +04:00
. ext_info = ( ext ) , \
2011-11-15 19:31:22 +04:00
}
2012-04-25 11:44:58 +04:00
# define AD5446_CHANNEL(bits, storage, shift) \
_AD5446_CHANNEL ( bits , storage , shift , NULL )
# define AD5446_CHANNEL_POWERDOWN(bits, storage, shift) \
2012-08-21 18:28:00 +04:00
_AD5446_CHANNEL ( bits , storage , shift , ad5446_ext_info_powerdown )
2010-11-22 13:15:23 +03:00
2011-11-15 19:31:22 +04:00
static int ad5446_read_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int * val ,
int * val2 ,
long m )
{
struct ad5446_state * st = iio_priv ( indio_dev ) ;
switch ( m ) {
2012-04-25 11:45:00 +04:00
case IIO_CHAN_INFO_RAW :
2022-04-06 13:56:20 +03:00
* val = st - > cached_val > > chan - > scan_type . shift ;
2012-04-25 11:45:00 +04:00
return IIO_VAL_INT ;
2011-11-15 19:31:22 +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-11-15 19:31:22 +04:00
}
return - EINVAL ;
}
static int ad5446_write_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int val ,
int val2 ,
long mask )
{
struct ad5446_state * st = iio_priv ( indio_dev ) ;
2012-04-25 11:44:52 +04:00
int ret = 0 ;
2011-11-15 19:31:22 +04:00
switch ( mask ) {
2012-04-15 20:41:19 +04:00
case IIO_CHAN_INFO_RAW :
2011-11-15 19:31:22 +04:00
if ( val > = ( 1 < < chan - > scan_type . realbits ) | | val < 0 )
return - EINVAL ;
val < < = chan - > scan_type . shift ;
2020-05-14 12:00:42 +03:00
mutex_lock ( & st - > lock ) ;
2011-11-15 19:31:22 +04:00
st - > cached_val = val ;
2012-04-25 11:44:54 +04:00
if ( ! st - > pwr_down )
2012-04-25 11:44:59 +04:00
ret = st - > chip_info - > write ( st , val ) ;
2020-05-14 12:00:42 +03:00
mutex_unlock ( & st - > lock ) ;
2011-11-15 19:31:22 +04:00
break ;
default :
ret = - EINVAL ;
}
return ret ;
}
2011-05-18 17:42:37 +04:00
static const struct iio_info ad5446_info = {
2012-01-29 15:07:02 +04:00
. read_raw = ad5446_read_raw ,
. write_raw = ad5446_write_raw ,
} ;
2012-12-22 01:21:43 +04:00
static int ad5446_probe ( struct device * dev , const char * name ,
const struct ad5446_chip_info * chip_info )
2010-11-22 13:15:23 +03:00
{
struct ad5446_state * st ;
2011-06-27 16:07:33 +04:00
struct iio_dev * indio_dev ;
struct regulator * reg ;
2010-11-22 13:15:23 +03:00
int ret , voltage_uv = 0 ;
2013-08-19 15:38:00 +04:00
reg = devm_regulator_get ( dev , " vcc " ) ;
2011-06-27 16:07:33 +04:00
if ( ! IS_ERR ( reg ) ) {
ret = regulator_enable ( reg ) ;
2010-11-22 13:15:23 +03:00
if ( ret )
2013-08-19 15:38:00 +04:00
return ret ;
2010-11-22 13:15:23 +03:00
2012-12-18 07:33:00 +04:00
ret = regulator_get_voltage ( reg ) ;
if ( ret < 0 )
goto error_disable_reg ;
voltage_uv = ret ;
2010-11-22 13:15:23 +03:00
}
2013-08-19 15:38:00 +04:00
indio_dev = devm_iio_device_alloc ( dev , sizeof ( * st ) ) ;
2011-06-27 16:07:33 +04:00
if ( indio_dev = = NULL ) {
ret = - ENOMEM ;
goto error_disable_reg ;
}
st = iio_priv ( indio_dev ) ;
2012-08-21 18:28:00 +04:00
st - > chip_info = chip_info ;
2010-11-22 13:15:23 +03:00
2012-08-21 18:28:00 +04:00
dev_set_drvdata ( dev , indio_dev ) ;
2011-06-27 16:07:33 +04:00
st - > reg = reg ;
2012-08-21 18:28:00 +04:00
st - > dev = dev ;
2010-11-22 13:15:23 +03:00
2012-08-21 18:28:00 +04:00
indio_dev - > name = name ;
2012-04-25 11:44:58 +04:00
indio_dev - > info = & ad5446_info ;
2011-06-27 16:07:33 +04:00
indio_dev - > modes = INDIO_DIRECT_MODE ;
2011-11-15 19:31:22 +04:00
indio_dev - > channels = & st - > chip_info - > channel ;
indio_dev - > num_channels = 1 ;
2010-11-22 13:15:23 +03:00
2020-05-14 12:00:42 +03:00
mutex_init ( & st - > lock ) ;
2012-06-04 13:36:13 +04:00
st - > pwr_down_mode = MODE_PWRDWN_1k ;
2012-04-25 11:44:56 +04:00
if ( st - > chip_info - > int_vref_mv )
2011-03-10 15:26:47 +03:00
st - > vref_mv = st - > chip_info - > int_vref_mv ;
2012-04-25 11:44:56 +04:00
else if ( voltage_uv )
st - > vref_mv = voltage_uv / 1000 ;
else
2012-08-21 18:28:00 +04:00
dev_warn ( dev , " reference voltage unspecified \n " ) ;
2010-11-22 13:15:23 +03:00
2011-06-27 16:07:33 +04:00
ret = iio_device_register ( indio_dev ) ;
2010-11-22 13:15:23 +03:00
if ( ret )
2013-08-19 15:38:00 +04:00
goto error_disable_reg ;
2010-11-22 13:15:23 +03:00
return 0 ;
error_disable_reg :
2011-06-27 16:07:33 +04:00
if ( ! IS_ERR ( reg ) )
regulator_disable ( reg ) ;
2010-11-22 13:15:23 +03:00
return ret ;
}
2021-10-13 23:32:16 +03:00
static void ad5446_remove ( struct device * dev )
2010-11-22 13:15:23 +03:00
{
2012-08-21 18:28:00 +04:00
struct iio_dev * indio_dev = dev_get_drvdata ( dev ) ;
2011-06-27 16:07:33 +04:00
struct ad5446_state * st = iio_priv ( indio_dev ) ;
2010-11-22 13:15:23 +03:00
iio_device_unregister ( indio_dev ) ;
2013-08-19 15:38:00 +04:00
if ( ! IS_ERR ( st - > reg ) )
2011-10-14 17:46:58 +04:00
regulator_disable ( st - > reg ) ;
2010-11-22 13:15:23 +03:00
}
2012-08-21 18:28:00 +04:00
# if IS_ENABLED(CONFIG_SPI_MASTER)
static int ad5446_write ( struct ad5446_state * st , unsigned val )
{
struct spi_device * spi = to_spi_device ( st - > dev ) ;
__be16 data = cpu_to_be16 ( val ) ;
return spi_write ( spi , & data , sizeof ( data ) ) ;
}
static int ad5660_write ( struct ad5446_state * st , unsigned val )
{
struct spi_device * spi = to_spi_device ( st - > dev ) ;
uint8_t data [ 3 ] ;
2020-04-21 03:31:25 +03:00
put_unaligned_be24 ( val , & data [ 0 ] ) ;
2012-08-21 18:28:00 +04:00
return spi_write ( spi , data , sizeof ( data ) ) ;
}
2020-07-16 16:59:18 +03:00
/*
2012-08-21 18:28:00 +04:00
* ad5446_supported_spi_device_ids :
* The AD5620 / 40 / 60 parts are available in different fixed internal reference
* voltage options . The actual part numbers may look differently
* ( and a bit cryptic ) , however this style is used to make clear which
* parts are supported here .
*/
enum ad5446_supported_spi_device_ids {
2012-09-04 13:10:00 +04:00
ID_AD5300 ,
ID_AD5310 ,
ID_AD5320 ,
2012-08-21 18:28:00 +04:00
ID_AD5444 ,
ID_AD5446 ,
ID_AD5450 ,
ID_AD5451 ,
ID_AD5541A ,
ID_AD5512A ,
ID_AD5553 ,
2019-11-06 12:47:21 +03:00
ID_AD5600 ,
2012-08-21 18:28:00 +04:00
ID_AD5601 ,
ID_AD5611 ,
ID_AD5621 ,
2013-09-23 18:19:00 +04:00
ID_AD5641 ,
2012-08-21 18:28:00 +04:00
ID_AD5620_2500 ,
ID_AD5620_1250 ,
ID_AD5640_2500 ,
ID_AD5640_1250 ,
ID_AD5660_2500 ,
ID_AD5660_1250 ,
ID_AD5662 ,
} ;
static const struct ad5446_chip_info ad5446_spi_chip_info [ ] = {
2012-09-04 13:10:00 +04:00
[ ID_AD5300 ] = {
. channel = AD5446_CHANNEL_POWERDOWN ( 8 , 16 , 4 ) ,
. write = ad5446_write ,
} ,
[ ID_AD5310 ] = {
. channel = AD5446_CHANNEL_POWERDOWN ( 10 , 16 , 2 ) ,
. write = ad5446_write ,
} ,
[ ID_AD5320 ] = {
. channel = AD5446_CHANNEL_POWERDOWN ( 12 , 16 , 0 ) ,
. write = ad5446_write ,
} ,
2012-08-21 18:28:00 +04:00
[ ID_AD5444 ] = {
. channel = AD5446_CHANNEL ( 12 , 16 , 2 ) ,
. write = ad5446_write ,
} ,
[ ID_AD5446 ] = {
. channel = AD5446_CHANNEL ( 14 , 16 , 0 ) ,
. write = ad5446_write ,
} ,
[ ID_AD5450 ] = {
. channel = AD5446_CHANNEL ( 8 , 16 , 6 ) ,
. write = ad5446_write ,
} ,
[ ID_AD5451 ] = {
. channel = AD5446_CHANNEL ( 10 , 16 , 4 ) ,
. write = ad5446_write ,
} ,
[ ID_AD5541A ] = {
. channel = AD5446_CHANNEL ( 16 , 16 , 0 ) ,
. write = ad5446_write ,
} ,
[ ID_AD5512A ] = {
. channel = AD5446_CHANNEL ( 12 , 16 , 4 ) ,
. write = ad5446_write ,
} ,
[ ID_AD5553 ] = {
. channel = AD5446_CHANNEL ( 14 , 16 , 0 ) ,
. write = ad5446_write ,
} ,
2019-11-06 12:47:21 +03:00
[ ID_AD5600 ] = {
. channel = AD5446_CHANNEL ( 16 , 16 , 0 ) ,
. write = ad5446_write ,
} ,
2012-08-21 18:28:00 +04:00
[ ID_AD5601 ] = {
. channel = AD5446_CHANNEL_POWERDOWN ( 8 , 16 , 6 ) ,
. write = ad5446_write ,
} ,
[ ID_AD5611 ] = {
. channel = AD5446_CHANNEL_POWERDOWN ( 10 , 16 , 4 ) ,
. write = ad5446_write ,
} ,
[ ID_AD5621 ] = {
. channel = AD5446_CHANNEL_POWERDOWN ( 12 , 16 , 2 ) ,
. write = ad5446_write ,
} ,
2013-09-23 18:19:00 +04:00
[ ID_AD5641 ] = {
. channel = AD5446_CHANNEL_POWERDOWN ( 14 , 16 , 0 ) ,
. write = ad5446_write ,
} ,
2012-08-21 18:28:00 +04:00
[ ID_AD5620_2500 ] = {
. channel = AD5446_CHANNEL_POWERDOWN ( 12 , 16 , 2 ) ,
. int_vref_mv = 2500 ,
. write = ad5446_write ,
} ,
[ ID_AD5620_1250 ] = {
. channel = AD5446_CHANNEL_POWERDOWN ( 12 , 16 , 2 ) ,
. int_vref_mv = 1250 ,
. write = ad5446_write ,
} ,
[ ID_AD5640_2500 ] = {
. channel = AD5446_CHANNEL_POWERDOWN ( 14 , 16 , 0 ) ,
. int_vref_mv = 2500 ,
. write = ad5446_write ,
} ,
[ ID_AD5640_1250 ] = {
. channel = AD5446_CHANNEL_POWERDOWN ( 14 , 16 , 0 ) ,
. int_vref_mv = 1250 ,
. write = ad5446_write ,
} ,
[ ID_AD5660_2500 ] = {
. channel = AD5446_CHANNEL_POWERDOWN ( 16 , 16 , 0 ) ,
. int_vref_mv = 2500 ,
. write = ad5660_write ,
} ,
[ ID_AD5660_1250 ] = {
. channel = AD5446_CHANNEL_POWERDOWN ( 16 , 16 , 0 ) ,
. int_vref_mv = 1250 ,
. write = ad5660_write ,
} ,
[ ID_AD5662 ] = {
. channel = AD5446_CHANNEL_POWERDOWN ( 16 , 16 , 0 ) ,
. write = ad5660_write ,
} ,
} ;
static const struct spi_device_id ad5446_spi_ids [ ] = {
2012-09-04 13:10:00 +04:00
{ " ad5300 " , ID_AD5300 } ,
{ " ad5310 " , ID_AD5310 } ,
{ " ad5320 " , ID_AD5320 } ,
2010-11-22 13:15:23 +03:00
{ " ad5444 " , ID_AD5444 } ,
{ " ad5446 " , ID_AD5446 } ,
2012-06-26 12:45:43 +04:00
{ " ad5450 " , ID_AD5450 } ,
{ " ad5451 " , ID_AD5451 } ,
{ " ad5452 " , ID_AD5444 } , /* ad5452 is compatible to the ad5444 */
{ " ad5453 " , ID_AD5446 } , /* ad5453 is compatible to the ad5446 */
2010-11-22 13:15:23 +03:00
{ " ad5512a " , ID_AD5512A } ,
2011-04-15 15:51:07 +04:00
{ " ad5541a " , ID_AD5541A } ,
2012-04-25 11:44:57 +04:00
{ " ad5542a " , ID_AD5541A } , /* ad5541a and ad5542a are compatible */
{ " ad5543 " , ID_AD5541A } , /* ad5541a and ad5543 are compatible */
2011-03-10 15:26:46 +03:00
{ " ad5553 " , ID_AD5553 } ,
2019-11-06 12:47:21 +03:00
{ " ad5600 " , ID_AD5600 } ,
2011-03-10 15:26:48 +03:00
{ " ad5601 " , ID_AD5601 } ,
{ " ad5611 " , ID_AD5611 } ,
{ " ad5621 " , ID_AD5621 } ,
2013-09-23 18:19:00 +04:00
{ " ad5641 " , ID_AD5641 } ,
2010-11-23 13:14:16 +03:00
{ " ad5620-2500 " , ID_AD5620_2500 } , /* AD5620/40/60: */
{ " ad5620-1250 " , ID_AD5620_1250 } , /* part numbers may look differently */
{ " ad5640-2500 " , ID_AD5640_2500 } ,
{ " ad5640-1250 " , ID_AD5640_1250 } ,
{ " ad5660-2500 " , ID_AD5660_2500 } ,
{ " ad5660-1250 " , ID_AD5660_1250 } ,
2012-04-25 11:45:01 +04:00
{ " ad5662 " , ID_AD5662 } ,
2017-09-05 12:44:00 +03:00
{ " dac081s101 " , ID_AD5300 } , /* compatible Texas Instruments chips */
{ " dac101s101 " , ID_AD5310 } ,
{ " dac121s101 " , ID_AD5320 } ,
2017-09-05 12:44:00 +03:00
{ " dac7512 " , ID_AD5320 } ,
2010-11-22 13:15:23 +03:00
{ }
} ;
2012-08-21 18:28:00 +04:00
MODULE_DEVICE_TABLE ( spi , ad5446_spi_ids ) ;
2017-09-05 12:44:00 +03:00
static const struct of_device_id ad5446_of_ids [ ] = {
{ . compatible = " ti,dac7512 " } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , ad5446_of_ids ) ;
2012-12-22 01:21:43 +04:00
static int ad5446_spi_probe ( struct spi_device * spi )
2012-08-21 18:28:00 +04:00
{
const struct spi_device_id * id = spi_get_device_id ( spi ) ;
return ad5446_probe ( & spi - > dev , id - > name ,
& ad5446_spi_chip_info [ id - > driver_data ] ) ;
}
2010-11-22 13:15:23 +03:00
2022-01-23 20:52:01 +03:00
static void ad5446_spi_remove ( struct spi_device * spi )
2012-08-21 18:28:00 +04:00
{
2021-10-13 23:32:16 +03:00
ad5446_remove ( & spi - > dev ) ;
2012-08-21 18:28:00 +04:00
}
static struct spi_driver ad5446_spi_driver = {
2010-11-22 13:15:23 +03:00
. driver = {
. name = " ad5446 " ,
2020-09-10 20:32:13 +03:00
. of_match_table = ad5446_of_ids ,
2010-11-22 13:15:23 +03:00
} ,
2012-08-21 18:28:00 +04:00
. probe = ad5446_spi_probe ,
2012-12-22 01:21:43 +04:00
. remove = ad5446_spi_remove ,
2012-08-21 18:28:00 +04:00
. id_table = ad5446_spi_ids ,
} ;
static int __init ad5446_spi_register_driver ( void )
{
return spi_register_driver ( & ad5446_spi_driver ) ;
}
static void ad5446_spi_unregister_driver ( void )
{
spi_unregister_driver ( & ad5446_spi_driver ) ;
}
# else
static inline int ad5446_spi_register_driver ( void ) { return 0 ; }
static inline void ad5446_spi_unregister_driver ( void ) { }
# endif
# if IS_ENABLED(CONFIG_I2C)
static int ad5622_write ( struct ad5446_state * st , unsigned val )
{
struct i2c_client * client = to_i2c_client ( st - > dev ) ;
__be16 data = cpu_to_be16 ( val ) ;
2021-09-29 21:57:55 +03:00
int ret ;
ret = i2c_master_send ( client , ( char * ) & data , sizeof ( data ) ) ;
if ( ret < 0 )
return ret ;
if ( ret ! = sizeof ( data ) )
return - EIO ;
2012-08-21 18:28:00 +04:00
2021-09-29 21:57:55 +03:00
return 0 ;
2012-08-21 18:28:00 +04:00
}
2020-07-16 16:59:18 +03:00
/*
2012-08-21 18:28:00 +04:00
* ad5446_supported_i2c_device_ids :
* The AD5620 / 40 / 60 parts are available in different fixed internal reference
* voltage options . The actual part numbers may look differently
* ( and a bit cryptic ) , however this style is used to make clear which
* parts are supported here .
*/
enum ad5446_supported_i2c_device_ids {
ID_AD5602 ,
ID_AD5612 ,
ID_AD5622 ,
} ;
static const struct ad5446_chip_info ad5446_i2c_chip_info [ ] = {
[ ID_AD5602 ] = {
. channel = AD5446_CHANNEL_POWERDOWN ( 8 , 16 , 4 ) ,
. write = ad5622_write ,
} ,
[ ID_AD5612 ] = {
. channel = AD5446_CHANNEL_POWERDOWN ( 10 , 16 , 2 ) ,
. write = ad5622_write ,
} ,
[ ID_AD5622 ] = {
. channel = AD5446_CHANNEL_POWERDOWN ( 12 , 16 , 0 ) ,
. write = ad5622_write ,
} ,
2010-11-22 13:15:23 +03:00
} ;
2012-08-21 18:28:00 +04:00
2022-11-19 01:36:58 +03:00
static int ad5446_i2c_probe ( struct i2c_client * i2c )
2012-08-21 18:28:00 +04:00
{
2022-11-19 01:36:58 +03:00
const struct i2c_device_id * id = i2c_client_get_device_id ( i2c ) ;
2012-08-21 18:28:00 +04:00
return ad5446_probe ( & i2c - > dev , id - > name ,
& ad5446_i2c_chip_info [ id - > driver_data ] ) ;
}
2022-08-15 11:02:30 +03:00
static void ad5446_i2c_remove ( struct i2c_client * i2c )
2012-08-21 18:28:00 +04:00
{
2021-10-13 23:32:16 +03:00
ad5446_remove ( & i2c - > dev ) ;
2012-08-21 18:28:00 +04:00
}
static const struct i2c_device_id ad5446_i2c_ids [ ] = {
2012-09-04 13:10:00 +04:00
{ " ad5301 " , ID_AD5602 } ,
{ " ad5311 " , ID_AD5612 } ,
{ " ad5321 " , ID_AD5622 } ,
2012-08-21 18:28:00 +04:00
{ " ad5602 " , ID_AD5602 } ,
{ " ad5612 " , ID_AD5612 } ,
{ " ad5622 " , ID_AD5622 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , ad5446_i2c_ids ) ;
static struct i2c_driver ad5446_i2c_driver = {
. driver = {
. name = " ad5446 " ,
} ,
2022-11-19 01:36:58 +03:00
. probe_new = ad5446_i2c_probe ,
2012-12-22 01:21:43 +04:00
. remove = ad5446_i2c_remove ,
2012-08-21 18:28:00 +04:00
. id_table = ad5446_i2c_ids ,
} ;
static int __init ad5446_i2c_register_driver ( void )
{
return i2c_add_driver ( & ad5446_i2c_driver ) ;
}
static void __exit ad5446_i2c_unregister_driver ( void )
{
i2c_del_driver ( & ad5446_i2c_driver ) ;
}
# else
static inline int ad5446_i2c_register_driver ( void ) { return 0 ; }
static inline void ad5446_i2c_unregister_driver ( void ) { }
# endif
static int __init ad5446_init ( void )
{
int ret ;
ret = ad5446_spi_register_driver ( ) ;
if ( ret )
return ret ;
ret = ad5446_i2c_register_driver ( ) ;
if ( ret ) {
ad5446_spi_unregister_driver ( ) ;
return ret ;
}
return 0 ;
}
module_init ( ad5446_init ) ;
static void __exit ad5446_exit ( void )
{
ad5446_i2c_unregister_driver ( ) ;
ad5446_spi_unregister_driver ( ) ;
}
module_exit ( ad5446_exit ) ;
2010-11-22 13:15:23 +03:00
2018-08-14 14:23:17 +03:00
MODULE_AUTHOR ( " Michael Hennerich <michael.hennerich@analog.com> " ) ;
2010-11-22 13:15:23 +03:00
MODULE_DESCRIPTION ( " Analog Devices AD5444/AD5446 DAC " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;