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 >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# 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 ,
} ;
struct max517_data {
2011-01-29 18:36:46 +03:00
struct i2c_client * client ;
2011-01-12 13:41:59 +03:00
unsigned short vref_mv [ 2 ] ;
} ;
/*
* 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
}
2012-02-20 22:37:05 +04:00
# ifdef CONFIG_PM_SLEEP
static int 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
}
2012-02-20 22:37:05 +04:00
static int 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 ) ;
# define MAX517_PM_OPS (&max517_pm_ops)
# else
# define MAX517_PM_OPS NULL
# endif
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
. driver_module = THIS_MODULE ,
} ;
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 ) ,
MAX517_CHANNEL ( 1 )
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 ;
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
2012-06-04 13:36:20 +04:00
/* reduced channel set for MAX517 */
2011-01-12 13:41:59 +03:00
if ( id - > driver_data = = ID_MAX517 )
2012-06-04 13:36:20 +04:00
indio_dev - > num_channels = 1 ;
2011-01-12 13:41:59 +03:00
else
2012-06-04 13:36:20 +04:00
indio_dev - > num_channels = 2 ;
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
*/
if ( id - > driver_data = = ID_MAX518 | | ! platform_data ) {
data - > vref_mv [ 0 ] = data - > vref_mv [ 1 ] = 5000 ; /* mV */
} else {
data - > vref_mv [ 0 ] = platform_data - > vref_mv [ 0 ] ;
data - > vref_mv [ 1 ] = platform_data - > vref_mv [ 1 ] ;
}
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 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , max517_id ) ;
static struct i2c_driver max517_driver = {
. driver = {
. name = MAX517_DRV_NAME ,
2012-02-20 22:37:05 +04: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> " ) ;
MODULE_DESCRIPTION ( " MAX517/MAX518/MAX519 8-bit DAC " ) ;
MODULE_LICENSE ( " GPL " ) ;