2019-05-30 02:57:44 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2017-03-28 19:34:48 +03:00
/*
* MAX1117 / MAX1118 / MAX1119 8 - bit , dual - channel ADCs driver
*
* Copyright ( c ) 2017 Akinobu Mita < akinobu . mita @ gmail . com >
*
* Datasheet : https : //datasheets.maximintegrated.com/en/ds/MAX1117-MAX1119.pdf
*
* SPI interface connections
*
* SPI MAXIM
* Master Direction MAX1117 / 8 / 9
* - - - - - - - - - - - - - - - - - - - - - - - - - -
* nCS - - > CNVST
* SCK - - > SCLK
* MISO < - - DOUT
* - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
# include <linux/module.h>
2020-06-28 15:36:42 +03:00
# include <linux/mod_devicetable.h>
2017-03-28 19:34:48 +03:00
# include <linux/spi/spi.h>
# include <linux/iio/iio.h>
# include <linux/iio/buffer.h>
# include <linux/iio/triggered_buffer.h>
# include <linux/iio/trigger_consumer.h>
# include <linux/regulator/consumer.h>
enum max1118_id {
max1117 ,
max1118 ,
max1119 ,
} ;
struct max1118 {
struct spi_device * spi ;
struct mutex lock ;
struct regulator * reg ;
2020-07-22 18:51:03 +03:00
/* Ensure natural alignment of buffer elements */
struct {
u8 channels [ 2 ] ;
s64 ts __aligned ( 8 ) ;
} scan ;
2017-03-28 19:34:48 +03:00
2022-05-08 20:56:05 +03:00
u8 data __aligned ( IIO_DMA_MINALIGN ) ;
2017-03-28 19:34:48 +03:00
} ;
# define MAX1118_CHANNEL(ch) \
{ \
. type = IIO_VOLTAGE , \
. indexed = 1 , \
. channel = ( ch ) , \
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) , \
. info_mask_shared_by_type = BIT ( IIO_CHAN_INFO_SCALE ) , \
. scan_index = ch , \
. scan_type = { \
. sign = ' u ' , \
. realbits = 8 , \
. storagebits = 8 , \
} , \
}
static const struct iio_chan_spec max1118_channels [ ] = {
MAX1118_CHANNEL ( 0 ) ,
MAX1118_CHANNEL ( 1 ) ,
IIO_CHAN_SOFT_TIMESTAMP ( 2 ) ,
} ;
2021-05-16 20:25:16 +03:00
static int max1118_read ( struct iio_dev * indio_dev , int channel )
2017-03-28 19:34:48 +03:00
{
struct max1118 * adc = iio_priv ( indio_dev ) ;
struct spi_transfer xfers [ ] = {
/*
* To select CH1 for conversion , CNVST pin must be brought high
* and low for a second time .
*/
{
. len = 0 ,
2020-02-27 15:25:15 +03:00
. delay = { /* > CNVST Low Time 100 ns */
. value = 1 ,
. unit = SPI_DELAY_UNIT_USECS
} ,
2017-03-28 19:34:48 +03:00
. cs_change = 1 ,
} ,
/*
* The acquisition interval begins with the falling edge of
* CNVST . The total acquisition and conversion process takes
* < 7.5 us .
*/
{
. len = 0 ,
2020-02-27 15:25:15 +03:00
. delay = {
. value = 8 ,
. unit = SPI_DELAY_UNIT_USECS
} ,
2017-03-28 19:34:48 +03:00
} ,
{
. rx_buf = & adc - > data ,
. len = 1 ,
} ,
} ;
int ret ;
if ( channel = = 0 )
2021-05-16 20:25:16 +03:00
ret = spi_sync_transfer ( adc - > spi , xfers + 1 , 2 ) ;
2017-03-28 19:34:48 +03:00
else
2021-05-16 20:25:16 +03:00
ret = spi_sync_transfer ( adc - > spi , xfers , 3 ) ;
2017-03-28 19:34:48 +03:00
if ( ret )
return ret ;
return adc - > data ;
}
2021-05-16 20:25:16 +03:00
static int max1118_get_vref_mV ( struct iio_dev * indio_dev )
2017-03-28 19:34:48 +03:00
{
struct max1118 * adc = iio_priv ( indio_dev ) ;
2021-05-16 20:25:16 +03:00
const struct spi_device_id * id = spi_get_device_id ( adc - > spi ) ;
2017-03-28 19:34:48 +03:00
int vref_uV ;
switch ( id - > driver_data ) {
case max1117 :
return 2048 ;
case max1119 :
return 4096 ;
case max1118 :
vref_uV = regulator_get_voltage ( adc - > reg ) ;
if ( vref_uV < 0 )
return vref_uV ;
return vref_uV / 1000 ;
}
return - ENODEV ;
}
static int max1118_read_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int * val , int * val2 , long mask )
{
struct max1118 * adc = iio_priv ( indio_dev ) ;
switch ( mask ) {
case IIO_CHAN_INFO_RAW :
mutex_lock ( & adc - > lock ) ;
2021-05-16 20:25:16 +03:00
* val = max1118_read ( indio_dev , chan - > channel ) ;
2017-03-28 19:34:48 +03:00
mutex_unlock ( & adc - > lock ) ;
if ( * val < 0 )
return * val ;
return IIO_VAL_INT ;
case IIO_CHAN_INFO_SCALE :
2021-05-16 20:25:16 +03:00
* val = max1118_get_vref_mV ( indio_dev ) ;
2017-03-28 19:34:48 +03:00
if ( * val < 0 )
return * val ;
* val2 = 8 ;
return IIO_VAL_FRACTIONAL_LOG2 ;
}
return - EINVAL ;
}
static const struct iio_info max1118_info = {
. read_raw = max1118_read_raw ,
} ;
static irqreturn_t max1118_trigger_handler ( int irq , void * p )
{
struct iio_poll_func * pf = p ;
struct iio_dev * indio_dev = pf - > indio_dev ;
struct max1118 * adc = iio_priv ( indio_dev ) ;
int scan_index ;
int i = 0 ;
mutex_lock ( & adc - > lock ) ;
for_each_set_bit ( scan_index , indio_dev - > active_scan_mask ,
indio_dev - > masklength ) {
const struct iio_chan_spec * scan_chan =
& indio_dev - > channels [ scan_index ] ;
2021-05-16 20:25:16 +03:00
int ret = max1118_read ( indio_dev , scan_chan - > channel ) ;
2017-03-28 19:34:48 +03:00
if ( ret < 0 ) {
dev_warn ( & adc - > spi - > dev ,
" failed to get conversion data \n " ) ;
goto out ;
}
2020-07-22 18:51:03 +03:00
adc - > scan . channels [ i ] = ret ;
2017-03-28 19:34:48 +03:00
i + + ;
}
2020-07-22 18:51:03 +03:00
iio_push_to_buffers_with_timestamp ( indio_dev , & adc - > scan ,
2017-03-28 19:34:48 +03:00
iio_get_time_ns ( indio_dev ) ) ;
out :
mutex_unlock ( & adc - > lock ) ;
iio_trigger_notify_done ( indio_dev - > trig ) ;
return IRQ_HANDLED ;
}
2021-05-16 20:25:15 +03:00
static void max1118_reg_disable ( void * reg )
{
regulator_disable ( reg ) ;
}
2017-03-28 19:34:48 +03:00
static int max1118_probe ( struct spi_device * spi )
{
struct iio_dev * indio_dev ;
struct max1118 * adc ;
const struct spi_device_id * id = spi_get_device_id ( spi ) ;
int ret ;
indio_dev = devm_iio_device_alloc ( & spi - > dev , sizeof ( * adc ) ) ;
if ( ! indio_dev )
return - ENOMEM ;
adc = iio_priv ( indio_dev ) ;
adc - > spi = spi ;
mutex_init ( & adc - > lock ) ;
if ( id - > driver_data = = max1118 ) {
adc - > reg = devm_regulator_get ( & spi - > dev , " vref " ) ;
2021-10-08 12:28:52 +03:00
if ( IS_ERR ( adc - > reg ) )
return dev_err_probe ( & spi - > dev , PTR_ERR ( adc - > reg ) ,
" failed to get vref regulator \n " ) ;
2017-03-28 19:34:48 +03:00
ret = regulator_enable ( adc - > reg ) ;
if ( ret )
return ret ;
2021-05-16 20:25:15 +03:00
ret = devm_add_action_or_reset ( & spi - > dev , max1118_reg_disable ,
adc - > reg ) ;
if ( ret )
return ret ;
2017-03-28 19:34:48 +03:00
}
indio_dev - > name = spi_get_device_id ( spi ) - > name ;
indio_dev - > info = & max1118_info ;
indio_dev - > modes = INDIO_DIRECT_MODE ;
indio_dev - > channels = max1118_channels ;
indio_dev - > num_channels = ARRAY_SIZE ( max1118_channels ) ;
/*
* To reinitiate a conversion on CH0 , it is necessary to allow for a
* conversion to be complete and all of the data to be read out . Once
* a conversion has been completed , the MAX1117 / MAX1118 / MAX1119 will go
* into AutoShutdown mode until the next conversion is initiated .
*/
2021-05-16 20:25:16 +03:00
max1118_read ( indio_dev , 0 ) ;
2017-03-28 19:34:48 +03:00
2021-05-16 20:25:15 +03:00
ret = devm_iio_triggered_buffer_setup ( & spi - > dev , indio_dev , NULL ,
max1118_trigger_handler , NULL ) ;
2017-03-28 19:34:48 +03:00
if ( ret )
2021-05-16 20:25:15 +03:00
return ret ;
2017-03-28 19:34:48 +03:00
2021-05-16 20:25:15 +03:00
return devm_iio_device_register ( & spi - > dev , indio_dev ) ;
2017-03-28 19:34:48 +03:00
}
static const struct spi_device_id max1118_id [ ] = {
{ " max1117 " , max1117 } ,
{ " max1118 " , max1118 } ,
{ " max1119 " , max1119 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( spi , max1118_id ) ;
static const struct of_device_id max1118_dt_ids [ ] = {
{ . compatible = " maxim,max1117 " } ,
{ . compatible = " maxim,max1118 " } ,
{ . compatible = " maxim,max1119 " } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , max1118_dt_ids ) ;
static struct spi_driver max1118_spi_driver = {
. driver = {
. name = " max1118 " ,
2020-06-28 15:36:42 +03:00
. of_match_table = max1118_dt_ids ,
2017-03-28 19:34:48 +03:00
} ,
. probe = max1118_probe ,
. id_table = max1118_id ,
} ;
module_spi_driver ( max1118_spi_driver ) ;
MODULE_AUTHOR ( " Akinobu Mita <akinobu.mita@gmail.com> " ) ;
MODULE_DESCRIPTION ( " MAXIM MAX1117/MAX1118/MAX1119 ADCs driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;