2019-05-20 10:19:02 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2011-01-12 13:41:59 +03:00
/*
* max517 . c - Support for Maxim MAX517 , MAX518 and MAX519
*
* Copyright ( C ) 2010 , 2011 Roland Stigge < stigge @ antcom . de >
*/
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/jiffies.h>
# include <linux/i2c.h>
# include <linux/err.h>
2012-04-25 18:54:58 +04:00
# include <linux/iio/iio.h>
# include <linux/iio/sysfs.h>
2012-06-04 13:36:28 +04:00
# include <linux/iio/dac/max517.h>
2011-01-12 13:41:59 +03:00
# define MAX517_DRV_NAME "max517"
/* Commands */
# define COMMAND_CHANNEL0 0x00
# define COMMAND_CHANNEL1 0x01 /* for MAX518 and MAX519 */
# define COMMAND_PD 0x08 /* Power Down */
enum max517_device_ids {
ID_MAX517 ,
ID_MAX518 ,
ID_MAX519 ,
2015-03-28 11:07:14 +03:00
ID_MAX520 ,
ID_MAX521 ,
2011-01-12 13:41:59 +03:00
} ;
struct max517_data {
2011-01-29 18:36:46 +03:00
struct i2c_client * client ;
2015-03-28 11:07:14 +03:00
unsigned short vref_mv [ 8 ] ;
2011-01-12 13:41:59 +03:00
} ;
/*
* channel : bit 0 : channel 1
* bit 1 : channel 2
* ( this way , it ' s possible to set both channels at once )
*/
2012-06-04 13:36:20 +04:00
static int max517_set_value ( struct iio_dev * indio_dev ,
long val , int channel )
2011-01-12 13:41:59 +03:00
{
2011-10-06 20:14:38 +04:00
struct max517_data * data = iio_priv ( indio_dev ) ;
2011-01-29 18:36:46 +03:00
struct i2c_client * client = data - > client ;
2012-06-04 13:36:20 +04:00
u8 outbuf [ 2 ] ;
2011-01-12 13:41:59 +03:00
int res ;
if ( val < 0 | | val > 255 )
return - EINVAL ;
2012-06-04 13:36:20 +04:00
outbuf [ 0 ] = channel ;
outbuf [ 1 ] = val ;
2011-01-12 13:41:59 +03:00
2012-06-04 13:36:20 +04:00
res = i2c_master_send ( client , outbuf , 2 ) ;
2011-01-12 13:41:59 +03:00
if ( res < 0 )
return res ;
2012-06-04 13:36:20 +04:00
else if ( res ! = 2 )
return - EIO ;
else
return 0 ;
2011-01-12 13:41:59 +03:00
}
2012-06-04 13:36:20 +04:00
static int max517_read_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int * val ,
int * val2 ,
long m )
2011-01-12 13:41:59 +03:00
{
2011-10-06 20:14:38 +04:00
struct max517_data * data = iio_priv ( indio_dev ) ;
2012-06-04 13:36:20 +04:00
switch ( m ) {
case IIO_CHAN_INFO_SCALE :
/* Corresponds to Vref / 2^(bits) */
2013-09-28 13:31:00 +04:00
* val = data - > vref_mv [ chan - > channel ] ;
* val2 = 8 ;
return IIO_VAL_FRACTIONAL_LOG2 ;
2012-06-04 13:36:20 +04:00
default :
break ;
}
return - EINVAL ;
2011-01-12 13:41:59 +03:00
}
2012-06-04 13:36:20 +04:00
static int max517_write_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan , int val , int val2 , long mask )
2011-01-12 13:41:59 +03:00
{
2012-06-04 13:36:20 +04:00
int ret ;
switch ( mask ) {
case IIO_CHAN_INFO_RAW :
ret = max517_set_value ( indio_dev , val , chan - > channel ) ;
break ;
default :
ret = - EINVAL ;
break ;
}
2011-01-12 13:41:59 +03:00
2012-06-04 13:36:20 +04:00
return ret ;
2011-01-12 13:41:59 +03:00
}
2018-08-11 11:47:09 +03:00
static int __maybe_unused max517_suspend ( struct device * dev )
2011-01-12 13:41:59 +03:00
{
u8 outbuf = COMMAND_PD ;
2012-02-20 22:37:05 +04:00
return i2c_master_send ( to_i2c_client ( dev ) , & outbuf , 1 ) ;
2011-01-12 13:41:59 +03:00
}
2018-08-11 11:47:09 +03:00
static int __maybe_unused max517_resume ( struct device * dev )
2011-01-12 13:41:59 +03:00
{
u8 outbuf = 0 ;
2012-02-20 22:37:05 +04:00
return i2c_master_send ( to_i2c_client ( dev ) , & outbuf , 1 ) ;
2011-01-12 13:41:59 +03:00
}
2012-02-20 22:37:05 +04:00
static SIMPLE_DEV_PM_OPS ( max517_pm_ops , max517_suspend , max517_resume ) ;
2011-05-18 17:42:37 +04:00
static const struct iio_info max517_info = {
2012-06-04 13:36:20 +04:00
. read_raw = max517_read_raw ,
. write_raw = max517_write_raw ,
2011-05-18 17:42:37 +04:00
} ;
2012-06-04 13:36:20 +04:00
# define MAX517_CHANNEL(chan) { \
. type = IIO_VOLTAGE , \
. indexed = 1 , \
. output = 1 , \
. channel = ( chan ) , \
2013-02-27 23:28:22 +04:00
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) | \
BIT ( IIO_CHAN_INFO_SCALE ) , \
2012-06-04 13:36:20 +04:00
}
static const struct iio_chan_spec max517_channels [ ] = {
MAX517_CHANNEL ( 0 ) ,
2015-03-28 11:07:14 +03:00
MAX517_CHANNEL ( 1 ) ,
MAX517_CHANNEL ( 2 ) ,
MAX517_CHANNEL ( 3 ) ,
MAX517_CHANNEL ( 4 ) ,
MAX517_CHANNEL ( 5 ) ,
MAX517_CHANNEL ( 6 ) ,
MAX517_CHANNEL ( 7 ) ,
2011-05-18 17:42:37 +04:00
} ;
2012-12-22 01:21:43 +04:00
static int max517_probe ( struct i2c_client * client ,
2011-01-12 13:41:59 +03:00
const struct i2c_device_id * id )
{
struct max517_data * data ;
2011-06-27 16:07:35 +04:00
struct iio_dev * indio_dev ;
2011-01-12 13:41:59 +03:00
struct max517_platform_data * platform_data = client - > dev . platform_data ;
2015-03-28 11:07:14 +03:00
int chan ;
2011-01-12 13:41:59 +03:00
2013-08-19 15:38:00 +04:00
indio_dev = devm_iio_device_alloc ( & client - > dev , sizeof ( * data ) ) ;
if ( ! indio_dev )
return - ENOMEM ;
2011-06-27 16:07:35 +04:00
data = iio_priv ( indio_dev ) ;
i2c_set_clientdata ( client , indio_dev ) ;
2011-01-29 18:36:46 +03:00
data - > client = client ;
2011-01-12 13:41:59 +03:00
/* establish that the iio_dev is a child of the i2c device */
2011-06-27 16:07:35 +04:00
indio_dev - > dev . parent = & client - > dev ;
2011-01-12 13:41:59 +03:00
2015-03-28 11:07:14 +03:00
switch ( id - > driver_data ) {
case ID_MAX521 :
indio_dev - > num_channels = 8 ;
break ;
case ID_MAX520 :
indio_dev - > num_channels = 4 ;
break ;
case ID_MAX519 :
case ID_MAX518 :
2012-06-04 13:36:20 +04:00
indio_dev - > num_channels = 2 ;
2015-03-28 11:07:14 +03:00
break ;
default : /* single channel for MAX517 */
indio_dev - > num_channels = 1 ;
break ;
}
2012-06-04 13:36:20 +04:00
indio_dev - > channels = max517_channels ;
2011-06-27 16:07:35 +04:00
indio_dev - > modes = INDIO_DIRECT_MODE ;
2012-06-04 13:36:20 +04:00
indio_dev - > info = & max517_info ;
2011-01-12 13:41:59 +03:00
/*
* Reference voltage on MAX518 and default is 5 V , else take vref_mv
* from platform_data
*/
2015-03-28 11:07:14 +03:00
for ( chan = 0 ; chan < indio_dev - > num_channels ; chan + + ) {
if ( id - > driver_data = = ID_MAX518 | | ! platform_data )
data - > vref_mv [ chan ] = 5000 ; /* mV */
else
data - > vref_mv [ chan ] = platform_data - > vref_mv [ chan ] ;
2011-01-12 13:41:59 +03:00
}
2013-10-24 15:53:00 +04:00
return iio_device_register ( indio_dev ) ;
2011-01-12 13:41:59 +03:00
}
2012-12-22 01:21:43 +04:00
static int max517_remove ( struct i2c_client * client )
2011-01-12 13:41:59 +03:00
{
2012-05-02 03:13:33 +04:00
iio_device_unregister ( i2c_get_clientdata ( client ) ) ;
2011-01-12 13:41:59 +03:00
return 0 ;
}
static const struct i2c_device_id max517_id [ ] = {
{ " max517 " , ID_MAX517 } ,
{ " max518 " , ID_MAX518 } ,
{ " max519 " , ID_MAX519 } ,
2015-03-28 11:07:14 +03:00
{ " max520 " , ID_MAX520 } ,
{ " max521 " , ID_MAX521 } ,
2011-01-12 13:41:59 +03:00
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , max517_id ) ;
static struct i2c_driver max517_driver = {
. driver = {
. name = MAX517_DRV_NAME ,
2018-08-11 11:47:09 +03:00
. pm = & max517_pm_ops ,
2011-01-12 13:41:59 +03:00
} ,
. probe = max517_probe ,
2012-12-22 01:21:43 +04:00
. remove = max517_remove ,
2011-01-12 13:41:59 +03:00
. id_table = max517_id ,
} ;
2011-11-16 13:13:38 +04:00
module_i2c_driver ( max517_driver ) ;
2011-01-12 13:41:59 +03:00
MODULE_AUTHOR ( " Roland Stigge <stigge@antcom.de> " ) ;
2015-03-28 11:07:14 +03:00
MODULE_DESCRIPTION ( " MAX517/518/519/520/521 8-bit DAC " ) ;
2011-01-12 13:41:59 +03:00
MODULE_LICENSE ( " GPL " ) ;