2022-11-06 17:59:28 +01:00
// SPDX-License-Identifier: GPL-2.0-only
/*
* Maxim MAX5522
* Dual , Ultra - Low - Power 10 - Bit , Voltage - Output DACs
*
* Copyright 2022 Timesys Corp .
*/
# include <linux/device.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/mod_devicetable.h>
# include <linux/regmap.h>
# include <linux/regulator/consumer.h>
# include <linux/slab.h>
# include <linux/spi/spi.h>
# include <linux/iio/iio.h>
# define MAX5522_MAX_ADDR 15
# define MAX5522_CTRL_NONE 0
# define MAX5522_CTRL_LOAD_IN_A 9
# define MAX5522_CTRL_LOAD_IN_B 10
# define MAX5522_REG_DATA(x) ((x) + MAX5522_CTRL_LOAD_IN_A)
struct max5522_chip_info {
const char * name ;
const struct iio_chan_spec * channels ;
unsigned int num_channels ;
} ;
struct max5522_state {
struct regmap * regmap ;
const struct max5522_chip_info * chip_info ;
unsigned short dac_cache [ 2 ] ;
struct regulator * vrefin_reg ;
} ;
# define MAX5522_CHANNEL(chan) { \
. type = IIO_VOLTAGE , \
. indexed = 1 , \
. output = 1 , \
. channel = chan , \
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) | \
BIT ( IIO_CHAN_INFO_SCALE ) , \
. scan_type = { \
. sign = ' u ' , \
. realbits = 10 , \
. storagebits = 16 , \
. shift = 2 , \
} \
}
2023-04-03 21:38:28 -04:00
static const struct iio_chan_spec max5522_channels [ ] = {
2022-11-06 17:59:28 +01:00
MAX5522_CHANNEL ( 0 ) ,
MAX5522_CHANNEL ( 1 ) ,
} ;
enum max5522_type {
ID_MAX5522 ,
} ;
static const struct max5522_chip_info max5522_chip_info_tbl [ ] = {
[ ID_MAX5522 ] = {
. name = " max5522 " ,
. channels = max5522_channels ,
. num_channels = 2 ,
} ,
} ;
static inline int max5522_info_to_reg ( struct iio_chan_spec const * chan )
{
return MAX5522_REG_DATA ( chan - > channel ) ;
}
static int max5522_read_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int * val , int * val2 , long info )
{
struct max5522_state * state = iio_priv ( indio_dev ) ;
int ret ;
switch ( info ) {
case IIO_CHAN_INFO_RAW :
* val = state - > dac_cache [ chan - > channel ] ;
return IIO_VAL_INT ;
case IIO_CHAN_INFO_SCALE :
ret = regulator_get_voltage ( state - > vrefin_reg ) ;
if ( ret < 0 )
return - EINVAL ;
* val = ret / 1000 ;
* val2 = 10 ;
return IIO_VAL_FRACTIONAL_LOG2 ;
default :
return - EINVAL ;
}
return - EINVAL ;
}
static int max5522_write_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int val , int val2 , long info )
{
struct max5522_state * state = iio_priv ( indio_dev ) ;
int rval ;
if ( val > 1023 | | val < 0 )
return - EINVAL ;
rval = regmap_write ( state - > regmap , max5522_info_to_reg ( chan ) ,
val < < chan - > scan_type . shift ) ;
if ( rval < 0 )
return rval ;
state - > dac_cache [ chan - > channel ] = val ;
return 0 ;
}
static const struct iio_info max5522_info = {
. read_raw = max5522_read_raw ,
. write_raw = max5522_write_raw ,
} ;
static const struct regmap_config max5522_regmap_config = {
. reg_bits = 4 ,
. val_bits = 12 ,
. max_register = MAX5522_MAX_ADDR ,
} ;
static int max5522_spi_probe ( struct spi_device * spi )
{
const struct spi_device_id * id = spi_get_device_id ( spi ) ;
struct iio_dev * indio_dev ;
struct max5522_state * state ;
int ret ;
indio_dev = devm_iio_device_alloc ( & spi - > dev , sizeof ( * state ) ) ;
if ( indio_dev = = NULL ) {
dev_err ( & spi - > dev , " failed to allocate iio device \n " ) ;
return - ENOMEM ;
}
state = iio_priv ( indio_dev ) ;
state - > chip_info = device_get_match_data ( & spi - > dev ) ;
if ( ! state - > chip_info ) {
state - > chip_info =
( struct max5522_chip_info * ) ( id - > driver_data ) ;
if ( ! state - > chip_info )
return - EINVAL ;
}
state - > vrefin_reg = devm_regulator_get ( & spi - > dev , " vrefin " ) ;
if ( IS_ERR ( state - > vrefin_reg ) )
return dev_err_probe ( & spi - > dev , PTR_ERR ( state - > vrefin_reg ) ,
" Vrefin regulator not specified \n " ) ;
ret = regulator_enable ( state - > vrefin_reg ) ;
if ( ret ) {
return dev_err_probe ( & spi - > dev , ret ,
" Failed to enable vref regulators \n " ) ;
}
state - > regmap = devm_regmap_init_spi ( spi , & max5522_regmap_config ) ;
if ( IS_ERR ( state - > regmap ) )
return PTR_ERR ( state - > regmap ) ;
indio_dev - > info = & max5522_info ;
indio_dev - > modes = INDIO_DIRECT_MODE ;
indio_dev - > channels = max5522_channels ;
indio_dev - > num_channels = ARRAY_SIZE ( max5522_channels ) ;
indio_dev - > name = max5522_chip_info_tbl [ ID_MAX5522 ] . name ;
return devm_iio_device_register ( & spi - > dev , indio_dev ) ;
}
static const struct spi_device_id max5522_ids [ ] = {
{ " max5522 " , ( kernel_ulong_t ) & max5522_chip_info_tbl [ ID_MAX5522 ] } ,
{ }
} ;
MODULE_DEVICE_TABLE ( spi , max5522_ids ) ;
static const struct of_device_id max5522_of_match [ ] = {
{
. compatible = " maxim,max5522 " ,
. data = & max5522_chip_info_tbl [ ID_MAX5522 ] ,
} ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , max5522_of_match ) ;
static struct spi_driver max5522_spi_driver = {
. driver = {
. name = " max5522 " ,
. of_match_table = max5522_of_match ,
} ,
. probe = max5522_spi_probe ,
. id_table = max5522_ids ,
} ;
module_spi_driver ( max5522_spi_driver ) ;
MODULE_AUTHOR ( " Angelo Dureghello <angelo.dureghello@timesys.com " ) ;
MODULE_DESCRIPTION ( " MAX5522 DAC driver " ) ;
MODULE_LICENSE ( " GPL " ) ;