2018-11-23 22:23:10 -02:00
// SPDX-License-Identifier: GPL-2.0
2010-10-27 21:44:19 -04:00
/*
* ad2s90 . c simple support for the ADI Resolver to Digital Converters : AD2S90
*
* Copyright ( c ) 2010 - 2010 Analog Devices Inc .
*/
# include <linux/types.h>
# include <linux/mutex.h>
# include <linux/device.h>
# include <linux/spi/spi.h>
# include <linux/slab.h>
# include <linux/sysfs.h>
2011-07-03 15:49:50 -04:00
# include <linux/module.h>
2010-10-27 21:44:19 -04:00
2012-04-25 15:54:58 +01:00
# include <linux/iio/iio.h>
# include <linux/iio/sysfs.h>
2010-10-27 21:44:19 -04:00
2018-11-23 22:23:08 -02:00
/*
* Although chip ' s max frequency is 2 Mhz , it needs 600 ns between CS and the
* first falling edge of SCLK , so frequency should be at most 1 / ( 2 * 6e-7 )
*/
# define AD2S90_MAX_SPI_FREQ_HZ 830000
2010-10-27 21:44:19 -04:00
struct ad2s90_state {
2018-11-23 22:23:11 -02:00
struct mutex lock ; /* lock to protect rx buffer */
2010-10-27 21:44:19 -04:00
struct spi_device * sdev ;
2011-06-27 13:07:53 +01:00
u8 rx [ 2 ] ____cacheline_aligned ;
2010-10-27 21:44:19 -04:00
} ;
2011-10-05 15:27:58 +01:00
static int ad2s90_read_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan ,
int * val ,
int * val2 ,
long m )
2010-10-27 21:44:19 -04:00
{
int ret ;
2011-10-05 15:27:58 +01:00
struct ad2s90_state * st = iio_priv ( indio_dev ) ;
2010-10-27 21:44:19 -04:00
2018-11-03 19:49:48 -03:00
if ( chan - > type ! = IIO_ANGL )
return - EINVAL ;
2018-11-03 19:49:47 -03:00
switch ( m ) {
case IIO_CHAN_INFO_SCALE :
/* 2 * Pi / 2^12 */
* val = 6283 ; /* mV */
* val2 = 12 ;
return IIO_VAL_FRACTIONAL_LOG2 ;
case IIO_CHAN_INFO_RAW :
mutex_lock ( & st - > lock ) ;
ret = spi_read ( st - > sdev , st - > rx , 2 ) ;
if ( ret < 0 ) {
mutex_unlock ( & st - > lock ) ;
return ret ;
}
* val = ( ( ( u16 ) ( st - > rx [ 0 ] ) ) < < 4 ) | ( ( st - > rx [ 1 ] & 0xF0 ) > > 4 ) ;
2018-11-03 19:49:43 -03:00
mutex_unlock ( & st - > lock ) ;
2011-10-05 15:27:58 +01:00
2018-11-03 19:49:47 -03:00
return IIO_VAL_INT ;
default :
break ;
}
2010-10-27 21:44:19 -04:00
2018-11-03 19:49:47 -03:00
return - EINVAL ;
2010-10-27 21:44:19 -04:00
}
2011-05-18 14:42:37 +01:00
static const struct iio_info ad2s90_info = {
2017-03-11 19:56:43 +05:30
. read_raw = ad2s90_read_raw ,
2011-05-18 14:42:37 +01:00
} ;
2011-10-05 15:27:58 +01:00
static const struct iio_chan_spec ad2s90_chan = {
. type = IIO_ANGL ,
. indexed = 1 ,
. channel = 0 ,
2018-11-03 19:49:47 -03:00
. info_mask_separate = BIT ( IIO_CHAN_INFO_RAW ) | BIT ( IIO_CHAN_INFO_SCALE ) ,
2011-10-05 15:27:58 +01:00
} ;
2012-11-19 13:21:57 -05:00
static int ad2s90_probe ( struct spi_device * spi )
2010-10-27 21:44:19 -04:00
{
2011-06-27 13:07:53 +01:00
struct iio_dev * indio_dev ;
2010-10-27 21:44:19 -04:00
struct ad2s90_state * st ;
2018-11-23 22:23:08 -02:00
if ( spi - > max_speed_hz > AD2S90_MAX_SPI_FREQ_HZ ) {
dev_err ( & spi - > dev , " SPI CLK, %d Hz exceeds %d Hz \n " ,
spi - > max_speed_hz , AD2S90_MAX_SPI_FREQ_HZ ) ;
return - EINVAL ;
}
2013-09-11 10:55:00 +01:00
indio_dev = devm_iio_device_alloc ( & spi - > dev , sizeof ( * st ) ) ;
if ( ! indio_dev )
return - ENOMEM ;
2011-06-27 13:07:53 +01:00
st = iio_priv ( indio_dev ) ;
spi_set_drvdata ( spi , indio_dev ) ;
2010-10-27 21:44:19 -04:00
mutex_init ( & st - > lock ) ;
st - > sdev = spi ;
2011-06-27 13:07:53 +01:00
indio_dev - > info = & ad2s90_info ;
indio_dev - > modes = INDIO_DIRECT_MODE ;
2011-10-05 15:27:58 +01:00
indio_dev - > channels = & ad2s90_chan ;
indio_dev - > num_channels = 1 ;
2011-10-05 15:27:57 +01:00
indio_dev - > name = spi_get_device_id ( spi ) - > name ;
2010-10-27 21:44:19 -04:00
2018-11-03 19:49:46 -03:00
return devm_iio_device_register ( indio_dev - > dev . parent , indio_dev ) ;
2010-10-27 21:44:19 -04:00
}
2018-11-23 22:23:06 -02:00
static const struct of_device_id ad2s90_of_match [ ] = {
{ . compatible = " adi,ad2s90 " , } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , ad2s90_of_match ) ;
2011-10-05 15:27:57 +01:00
static const struct spi_device_id ad2s90_id [ ] = {
{ " ad2s90 " } ,
{ }
} ;
2011-11-16 08:53:31 +01:00
MODULE_DEVICE_TABLE ( spi , ad2s90_id ) ;
2011-10-05 15:27:57 +01:00
2010-10-27 21:44:19 -04:00
static struct spi_driver ad2s90_driver = {
. driver = {
2011-10-05 15:27:57 +01:00
. name = " ad2s90 " ,
2018-11-23 22:23:06 -02:00
. of_match_table = ad2s90_of_match ,
2010-10-27 21:44:19 -04:00
} ,
. probe = ad2s90_probe ,
2011-10-05 15:27:57 +01:00
. id_table = ad2s90_id ,
2010-10-27 21:44:19 -04:00
} ;
2011-11-16 10:13:39 +01:00
module_spi_driver ( ad2s90_driver ) ;
2010-10-27 21:44:19 -04:00
MODULE_AUTHOR ( " Graff Yang <graff.yang@gmail.com> " ) ;
MODULE_DESCRIPTION ( " Analog Devices AD2S90 Resolver to Digital SPI driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;