2019-05-24 13:04:09 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2012-11-13 17:28:00 +04:00
/*
* Common library for ADIS16XXX devices
*
* Copyright 2012 Analog Devices Inc .
* Author : Lars - Peter Clausen < lars @ metafoo . de >
*/
# include <linux/delay.h>
2020-02-10 16:26:03 +03:00
# include <linux/gpio/consumer.h>
2012-11-13 17:28:00 +04:00
# include <linux/mutex.h>
# include <linux/device.h>
# include <linux/kernel.h>
# include <linux/spi/spi.h>
# include <linux/module.h>
# include <asm/unaligned.h>
# include <linux/iio/iio.h>
2012-11-13 17:28:00 +04:00
# include <linux/iio/imu/adis.h>
2012-11-13 17:28:00 +04:00
# define ADIS_MSC_CTRL_DATA_RDY_EN BIT(2)
# define ADIS_MSC_CTRL_DATA_RDY_POL_HIGH BIT(1)
# define ADIS_MSC_CTRL_DATA_RDY_DIO2 BIT(0)
# define ADIS_GLOB_CMD_SW_RESET BIT(7)
2019-11-22 16:24:12 +03:00
/**
* __adis_write_reg ( ) - write N bytes to register ( unlocked version )
* @ adis : The adis device
* @ reg : The address of the lower of the two registers
* @ value : The value to write to device ( up to 4 bytes )
* @ size : The size of the @ value ( in bytes )
*/
2022-01-22 16:09:05 +03:00
int __adis_write_reg ( struct adis * adis , unsigned int reg , unsigned int value ,
unsigned int size )
2012-11-13 17:28:00 +04:00
{
2012-11-20 17:36:00 +04:00
unsigned int page = reg / ADIS_PAGE_SIZE ;
2012-11-20 17:36:00 +04:00
int ret , i ;
2012-11-13 17:28:00 +04:00
struct spi_message msg ;
struct spi_transfer xfers [ ] = {
{
. tx_buf = adis - > tx ,
. bits_per_word = 8 ,
. len = 2 ,
. cs_change = 1 ,
2019-12-10 17:07:55 +03:00
. delay . value = adis - > data - > write_delay ,
. delay . unit = SPI_DELAY_UNIT_USECS ,
2019-09-26 13:51:31 +03:00
. cs_change_delay . value = adis - > data - > cs_change_delay ,
. cs_change_delay . unit = SPI_DELAY_UNIT_USECS ,
2012-11-13 17:28:00 +04:00
} , {
. tx_buf = adis - > tx + 2 ,
. bits_per_word = 8 ,
. len = 2 ,
2012-11-20 17:36:00 +04:00
. cs_change = 1 ,
2019-12-10 17:07:55 +03:00
. delay . value = adis - > data - > write_delay ,
. delay . unit = SPI_DELAY_UNIT_USECS ,
2019-09-26 13:51:31 +03:00
. cs_change_delay . value = adis - > data - > cs_change_delay ,
. cs_change_delay . unit = SPI_DELAY_UNIT_USECS ,
2012-11-20 17:36:00 +04:00
} , {
. tx_buf = adis - > tx + 4 ,
. bits_per_word = 8 ,
. len = 2 ,
. cs_change = 1 ,
2019-12-10 17:07:55 +03:00
. delay . value = adis - > data - > write_delay ,
. delay . unit = SPI_DELAY_UNIT_USECS ,
2019-09-26 13:51:31 +03:00
. cs_change_delay . value = adis - > data - > cs_change_delay ,
. cs_change_delay . unit = SPI_DELAY_UNIT_USECS ,
2012-11-20 17:36:00 +04:00
} , {
. tx_buf = adis - > tx + 6 ,
. bits_per_word = 8 ,
. len = 2 ,
2019-12-10 17:07:55 +03:00
. delay . value = adis - > data - > write_delay ,
. delay . unit = SPI_DELAY_UNIT_USECS ,
2012-11-20 17:36:00 +04:00
} , {
. tx_buf = adis - > tx + 8 ,
. bits_per_word = 8 ,
. len = 2 ,
2019-12-10 17:07:55 +03:00
. delay . value = adis - > data - > write_delay ,
. delay . unit = SPI_DELAY_UNIT_USECS ,
2012-11-13 17:28:00 +04:00
} ,
} ;
spi_message_init ( & msg ) ;
2012-11-20 17:36:00 +04:00
if ( adis - > current_page ! = page ) {
adis - > tx [ 0 ] = ADIS_WRITE_REG ( ADIS_REG_PAGE_ID ) ;
adis - > tx [ 1 ] = page ;
spi_message_add_tail ( & xfers [ 0 ] , & msg ) ;
}
2012-11-20 17:36:00 +04:00
switch ( size ) {
case 4 :
2012-11-20 17:36:00 +04:00
adis - > tx [ 8 ] = ADIS_WRITE_REG ( reg + 3 ) ;
adis - > tx [ 9 ] = ( value > > 24 ) & 0xff ;
adis - > tx [ 6 ] = ADIS_WRITE_REG ( reg + 2 ) ;
adis - > tx [ 7 ] = ( value > > 16 ) & 0xff ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2012-11-20 17:36:00 +04:00
case 2 :
2012-11-20 17:36:00 +04:00
adis - > tx [ 4 ] = ADIS_WRITE_REG ( reg + 1 ) ;
adis - > tx [ 5 ] = ( value > > 8 ) & 0xff ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2012-11-20 17:36:00 +04:00
case 1 :
2012-11-20 17:36:00 +04:00
adis - > tx [ 2 ] = ADIS_WRITE_REG ( reg ) ;
adis - > tx [ 3 ] = value & 0xff ;
2012-11-20 17:36:00 +04:00
break ;
default :
2019-11-22 16:24:12 +03:00
return - EINVAL ;
2012-11-20 17:36:00 +04:00
}
2012-11-20 17:36:00 +04:00
xfers [ size ] . cs_change = 0 ;
2012-11-20 17:36:00 +04:00
2012-11-20 17:36:00 +04:00
for ( i = 1 ; i < = size ; i + + )
2012-11-20 17:36:00 +04:00
spi_message_add_tail ( & xfers [ i ] , & msg ) ;
2012-11-13 17:28:00 +04:00
ret = spi_sync ( adis - > spi , & msg ) ;
2012-11-20 17:36:00 +04:00
if ( ret ) {
dev_err ( & adis - > spi - > dev , " Failed to write register 0x%02X: %d \n " ,
2022-01-22 16:09:05 +03:00
reg , ret ) ;
2012-11-20 17:36:00 +04:00
} else {
adis - > current_page = page ;
2012-11-20 17:36:00 +04:00
}
2012-11-13 17:28:00 +04:00
return ret ;
}
2022-01-30 23:56:53 +03:00
EXPORT_SYMBOL_NS_GPL ( __adis_write_reg , IIO_ADISLIB ) ;
2012-11-13 17:28:00 +04:00
/**
2019-11-22 16:24:12 +03:00
* __adis_read_reg ( ) - read N bytes from register ( unlocked version )
2012-11-13 17:28:00 +04:00
* @ adis : The adis device
* @ reg : The address of the lower of the two registers
* @ val : The value read back from the device
2019-11-22 16:24:12 +03:00
* @ size : The size of the @ val buffer
2012-11-13 17:28:00 +04:00
*/
2022-01-22 16:09:05 +03:00
int __adis_read_reg ( struct adis * adis , unsigned int reg , unsigned int * val ,
unsigned int size )
2012-11-13 17:28:00 +04:00
{
2012-11-20 17:36:00 +04:00
unsigned int page = reg / ADIS_PAGE_SIZE ;
2012-11-13 17:28:00 +04:00
struct spi_message msg ;
int ret ;
struct spi_transfer xfers [ ] = {
{
. tx_buf = adis - > tx ,
. bits_per_word = 8 ,
. len = 2 ,
. cs_change = 1 ,
2019-12-10 17:07:55 +03:00
. delay . value = adis - > data - > write_delay ,
. delay . unit = SPI_DELAY_UNIT_USECS ,
2019-09-26 13:51:31 +03:00
. cs_change_delay . value = adis - > data - > cs_change_delay ,
. cs_change_delay . unit = SPI_DELAY_UNIT_USECS ,
2012-11-13 17:28:00 +04:00
} , {
2012-11-20 17:36:00 +04:00
. tx_buf = adis - > tx + 2 ,
2012-11-20 17:36:00 +04:00
. bits_per_word = 8 ,
. len = 2 ,
. cs_change = 1 ,
2019-12-10 17:07:55 +03:00
. delay . value = adis - > data - > read_delay ,
. delay . unit = SPI_DELAY_UNIT_USECS ,
2019-09-26 13:51:31 +03:00
. cs_change_delay . value = adis - > data - > cs_change_delay ,
. cs_change_delay . unit = SPI_DELAY_UNIT_USECS ,
2012-11-20 17:36:00 +04:00
} , {
. tx_buf = adis - > tx + 4 ,
2012-11-13 17:28:00 +04:00
. rx_buf = adis - > rx ,
. bits_per_word = 8 ,
. len = 2 ,
2012-11-20 17:36:00 +04:00
. cs_change = 1 ,
2019-12-10 17:07:55 +03:00
. delay . value = adis - > data - > read_delay ,
. delay . unit = SPI_DELAY_UNIT_USECS ,
2019-09-26 13:51:31 +03:00
. cs_change_delay . value = adis - > data - > cs_change_delay ,
. cs_change_delay . unit = SPI_DELAY_UNIT_USECS ,
2012-11-20 17:36:00 +04:00
} , {
. rx_buf = adis - > rx + 2 ,
. bits_per_word = 8 ,
. len = 2 ,
2019-12-10 17:07:55 +03:00
. delay . value = adis - > data - > read_delay ,
. delay . unit = SPI_DELAY_UNIT_USECS ,
2012-11-13 17:28:00 +04:00
} ,
} ;
spi_message_init ( & msg ) ;
2012-11-20 17:36:00 +04:00
2012-11-20 17:36:00 +04:00
if ( adis - > current_page ! = page ) {
adis - > tx [ 0 ] = ADIS_WRITE_REG ( ADIS_REG_PAGE_ID ) ;
adis - > tx [ 1 ] = page ;
spi_message_add_tail ( & xfers [ 0 ] , & msg ) ;
}
2012-11-20 17:36:00 +04:00
switch ( size ) {
case 4 :
2012-11-20 17:36:00 +04:00
adis - > tx [ 2 ] = ADIS_READ_REG ( reg + 2 ) ;
2012-11-20 17:36:00 +04:00
adis - > tx [ 3 ] = 0 ;
spi_message_add_tail ( & xfers [ 1 ] , & msg ) ;
2020-08-24 01:36:59 +03:00
fallthrough ;
2012-11-20 17:36:00 +04:00
case 2 :
adis - > tx [ 4 ] = ADIS_READ_REG ( reg ) ;
adis - > tx [ 5 ] = 0 ;
2012-11-20 17:36:00 +04:00
spi_message_add_tail ( & xfers [ 2 ] , & msg ) ;
2012-11-20 17:36:00 +04:00
spi_message_add_tail ( & xfers [ 3 ] , & msg ) ;
2012-11-20 17:36:00 +04:00
break ;
default :
2019-11-22 16:24:12 +03:00
return - EINVAL ;
2012-11-20 17:36:00 +04:00
}
2012-11-13 17:28:00 +04:00
ret = spi_sync ( adis - > spi , & msg ) ;
if ( ret ) {
2012-11-20 17:36:00 +04:00
dev_err ( & adis - > spi - > dev , " Failed to read register 0x%02X: %d \n " ,
2022-01-22 16:09:05 +03:00
reg , ret ) ;
2019-11-22 16:24:12 +03:00
return ret ;
2012-11-13 17:28:00 +04:00
}
2022-01-22 16:09:05 +03:00
adis - > current_page = page ;
2012-11-20 17:36:00 +04:00
switch ( size ) {
case 4 :
* val = get_unaligned_be32 ( adis - > rx ) ;
break ;
case 2 :
* val = get_unaligned_be16 ( adis - > rx + 2 ) ;
break ;
}
2012-11-13 17:28:00 +04:00
return ret ;
}
2022-01-30 23:56:53 +03:00
EXPORT_SYMBOL_NS_GPL ( __adis_read_reg , IIO_ADISLIB ) ;
2020-04-13 11:24:42 +03:00
/**
* __adis_update_bits_base ( ) - ADIS Update bits function - Unlocked version
* @ adis : The adis device
* @ reg : The address of the lower of the two registers
* @ mask : Bitmask to change
* @ val : Value to be written
* @ size : Size of the register to update
*
* Updates the desired bits of @ reg in accordance with @ mask and @ val .
*/
int __adis_update_bits_base ( struct adis * adis , unsigned int reg , const u32 mask ,
const u32 val , u8 size )
{
int ret ;
u32 __val ;
ret = __adis_read_reg ( adis , reg , & __val , size ) ;
if ( ret )
return ret ;
__val = ( __val & ~ mask ) | ( val & mask ) ;
return __adis_write_reg ( adis , reg , __val , size ) ;
}
2022-01-30 23:56:53 +03:00
EXPORT_SYMBOL_NS_GPL ( __adis_update_bits_base , IIO_ADISLIB ) ;
2012-11-13 17:28:00 +04:00
2012-11-20 17:36:00 +04:00
# ifdef CONFIG_DEBUG_FS
2022-01-22 16:09:05 +03:00
int adis_debugfs_reg_access ( struct iio_dev * indio_dev , unsigned int reg ,
unsigned int writeval , unsigned int * readval )
2012-11-20 17:36:00 +04:00
{
struct adis * adis = iio_device_get_drvdata ( indio_dev ) ;
if ( readval ) {
2022-01-22 16:09:05 +03:00
u16 val16 ;
2012-11-20 17:36:00 +04:00
int ret ;
ret = adis_read_reg_16 ( adis , reg , & val16 ) ;
2019-11-01 12:35:04 +03:00
if ( ret = = 0 )
* readval = val16 ;
2012-11-20 17:36:00 +04:00
return ret ;
}
2022-01-22 16:09:05 +03:00
return adis_write_reg_16 ( adis , reg , writeval ) ;
2012-11-20 17:36:00 +04:00
}
2022-01-30 23:56:53 +03:00
EXPORT_SYMBOL_NS ( adis_debugfs_reg_access , IIO_ADISLIB ) ;
2012-11-20 17:36:00 +04:00
# endif
2012-11-13 17:28:00 +04:00
/**
* adis_enable_irq ( ) - Enable or disable data ready IRQ
* @ adis : The adis device
* @ enable : Whether to enable the IRQ
*
* Returns 0 on success , negative error code otherwise
*/
int adis_enable_irq ( struct adis * adis , bool enable )
{
int ret = 0 ;
2022-01-22 16:09:05 +03:00
u16 msc ;
2012-11-13 17:28:00 +04:00
2019-11-22 16:24:13 +03:00
mutex_lock ( & adis - > state_lock ) ;
2012-11-20 17:36:00 +04:00
2019-11-22 16:24:13 +03:00
if ( adis - > data - > enable_irq ) {
ret = adis - > data - > enable_irq ( adis , enable ) ;
goto out_unlock ;
2022-01-22 16:09:05 +03:00
}
if ( adis - > data - > unmasked_drdy ) {
2021-09-03 17:14:20 +03:00
if ( enable )
enable_irq ( adis - > spi - > irq ) ;
else
disable_irq ( adis - > spi - > irq ) ;
goto out_unlock ;
2019-11-22 16:24:13 +03:00
}
2012-11-20 17:36:00 +04:00
2019-11-22 16:24:13 +03:00
ret = __adis_read_reg_16 ( adis , adis - > data - > msc_ctrl_reg , & msc ) ;
2012-11-13 17:28:00 +04:00
if ( ret )
2019-11-22 16:24:13 +03:00
goto out_unlock ;
2012-11-13 17:28:00 +04:00
msc | = ADIS_MSC_CTRL_DATA_RDY_POL_HIGH ;
msc & = ~ ADIS_MSC_CTRL_DATA_RDY_DIO2 ;
if ( enable )
msc | = ADIS_MSC_CTRL_DATA_RDY_EN ;
else
msc & = ~ ADIS_MSC_CTRL_DATA_RDY_EN ;
2019-11-22 16:24:13 +03:00
ret = __adis_write_reg_16 ( adis , adis - > data - > msc_ctrl_reg , msc ) ;
2012-11-13 17:28:00 +04:00
2019-11-22 16:24:13 +03:00
out_unlock :
mutex_unlock ( & adis - > state_lock ) ;
2012-11-13 17:28:00 +04:00
return ret ;
}
2022-01-30 23:56:53 +03:00
EXPORT_SYMBOL_NS ( adis_enable_irq , IIO_ADISLIB ) ;
2012-11-13 17:28:00 +04:00
/**
2019-11-22 16:24:14 +03:00
* __adis_check_status ( ) - Check the device for error conditions ( unlocked )
2012-11-13 17:28:00 +04:00
* @ adis : The adis device
*
* Returns 0 on success , a negative error code otherwise
*/
2019-11-22 16:24:14 +03:00
int __adis_check_status ( struct adis * adis )
2012-11-13 17:28:00 +04:00
{
2022-01-22 16:09:05 +03:00
u16 status ;
2012-11-13 17:28:00 +04:00
int ret ;
int i ;
2019-11-22 16:24:14 +03:00
ret = __adis_read_reg_16 ( adis , adis - > data - > diag_stat_reg , & status ) ;
2019-11-01 12:35:00 +03:00
if ( ret )
2012-11-13 17:28:00 +04:00
return ret ;
status & = adis - > data - > status_error_mask ;
if ( status = = 0 )
return 0 ;
for ( i = 0 ; i < 16 ; + + i ) {
if ( status & BIT ( i ) ) {
dev_err ( & adis - > spi - > dev , " %s. \n " ,
adis - > data - > status_error_msgs [ i ] ) ;
}
}
return - EIO ;
}
2022-01-30 23:56:53 +03:00
EXPORT_SYMBOL_NS_GPL ( __adis_check_status , IIO_ADISLIB ) ;
2012-11-13 17:28:00 +04:00
/**
2019-11-22 16:24:15 +03:00
* __adis_reset ( ) - Reset the device ( unlocked version )
2012-11-13 17:28:00 +04:00
* @ adis : The adis device
*
* Returns 0 on success , a negative error code otherwise
*/
2019-11-22 16:24:15 +03:00
int __adis_reset ( struct adis * adis )
2012-11-13 17:28:00 +04:00
{
int ret ;
2020-01-07 14:17:04 +03:00
const struct adis_timeout * timeouts = adis - > data - > timeouts ;
2012-11-13 17:28:00 +04:00
2019-11-22 16:24:15 +03:00
ret = __adis_write_reg_8 ( adis , adis - > data - > glob_cmd_reg ,
2022-01-22 16:09:05 +03:00
ADIS_GLOB_CMD_SW_RESET ) ;
2020-01-07 14:17:04 +03:00
if ( ret ) {
2012-11-13 17:28:00 +04:00
dev_err ( & adis - > spi - > dev , " Failed to reset device: %d \n " , ret ) ;
2020-01-07 14:17:04 +03:00
return ret ;
}
2012-11-13 17:28:00 +04:00
2020-01-07 14:17:04 +03:00
msleep ( timeouts - > sw_reset_ms ) ;
return 0 ;
2012-11-13 17:28:00 +04:00
}
2022-01-30 23:56:53 +03:00
EXPORT_SYMBOL_NS_GPL ( __adis_reset , IIO_ADIS_LIB ) ;
2012-11-13 17:28:00 +04:00
static int adis_self_test ( struct adis * adis )
{
int ret ;
2020-01-07 14:17:04 +03:00
const struct adis_timeout * timeouts = adis - > data - > timeouts ;
2012-11-13 17:28:00 +04:00
2020-02-10 16:26:02 +03:00
ret = __adis_write_reg_16 ( adis , adis - > data - > self_test_reg ,
adis - > data - > self_test_mask ) ;
2012-11-13 17:28:00 +04:00
if ( ret ) {
dev_err ( & adis - > spi - > dev , " Failed to initiate self test: %d \n " ,
ret ) ;
return ret ;
}
2020-01-07 14:17:04 +03:00
msleep ( timeouts - > self_test_ms ) ;
2012-11-13 17:28:00 +04:00
2019-11-22 16:24:16 +03:00
ret = __adis_check_status ( adis ) ;
2016-04-15 17:59:38 +03:00
if ( adis - > data - > self_test_no_autoclear )
2020-02-10 16:26:02 +03:00
__adis_write_reg_16 ( adis , adis - > data - > self_test_reg , 0x00 ) ;
2016-04-15 17:59:38 +03:00
return ret ;
2012-11-13 17:28:00 +04:00
}
/**
2020-02-10 16:26:01 +03:00
* __adis_initial_startup ( ) - Device initial setup
2012-11-13 17:28:00 +04:00
* @ adis : The adis device
*
2020-02-10 16:26:03 +03:00
* The function performs a HW reset via a reset pin that should be specified
* via GPIOLIB . If no pin is configured a SW reset will be performed .
* The RST pin for the ADIS devices should be configured as ACTIVE_LOW .
*
2020-02-10 16:26:04 +03:00
* After the self - test operation is performed , the function will also check
* that the product ID is as expected . This assumes that drivers providing
* ' prod_id_reg ' will also provide the ' prod_id ' .
*
2012-11-13 17:28:00 +04:00
* Returns 0 if the device is operational , a negative error code otherwise .
*
* This function should be called early on in the device initialization sequence
* to ensure that the device is in a sane and known state and that it is usable .
*/
2020-02-10 16:26:01 +03:00
int __adis_initial_startup ( struct adis * adis )
2012-11-13 17:28:00 +04:00
{
2020-02-10 16:26:03 +03:00
const struct adis_timeout * timeouts = adis - > data - > timeouts ;
struct gpio_desc * gpio ;
2022-01-22 16:09:05 +03:00
u16 prod_id ;
2012-11-13 17:28:00 +04:00
int ret ;
2020-02-10 16:26:03 +03:00
/* check if the device has rst pin low */
2021-07-08 12:54:29 +03:00
gpio = devm_gpiod_get_optional ( & adis - > spi - > dev , " reset " , GPIOD_OUT_HIGH ) ;
2020-02-10 16:26:03 +03:00
if ( IS_ERR ( gpio ) )
return PTR_ERR ( gpio ) ;
if ( gpio ) {
2022-01-22 16:09:05 +03:00
usleep_range ( 10 , 12 ) ;
2020-02-10 16:26:03 +03:00
/* bring device out of reset */
gpiod_set_value_cansleep ( gpio , 0 ) ;
msleep ( timeouts - > reset_ms ) ;
} else {
ret = __adis_reset ( adis ) ;
2020-02-10 16:26:01 +03:00
if ( ret )
2020-02-10 16:26:03 +03:00
return ret ;
2012-11-13 17:28:00 +04:00
}
2020-02-10 16:26:04 +03:00
ret = adis_self_test ( adis ) ;
if ( ret )
return ret ;
2021-09-03 17:14:20 +03:00
/*
* don ' t bother calling this if we can ' t unmask the IRQ as in this case
* the IRQ is most likely not yet requested and we will request it
* with ' IRQF_NO_AUTOEN ' anyways .
*/
if ( ! adis - > data - > unmasked_drdy )
adis_enable_irq ( adis , false ) ;
2021-09-03 17:14:19 +03:00
2020-02-10 16:26:04 +03:00
if ( ! adis - > data - > prod_id_reg )
return 0 ;
ret = adis_read_reg_16 ( adis , adis - > data - > prod_id_reg , & prod_id ) ;
if ( ret )
return ret ;
if ( prod_id ! = adis - > data - > prod_id )
dev_warn ( & adis - > spi - > dev ,
2020-04-10 20:12:24 +03:00
" Device ID(%u) and product ID(%u) do not match. \n " ,
2020-02-10 16:26:04 +03:00
adis - > data - > prod_id , prod_id ) ;
return 0 ;
2012-11-13 17:28:00 +04:00
}
2022-01-30 23:56:53 +03:00
EXPORT_SYMBOL_NS_GPL ( __adis_initial_startup , IIO_ADISLIB ) ;
2012-11-13 17:28:00 +04:00
/**
* adis_single_conversion ( ) - Performs a single sample conversion
* @ indio_dev : The IIO device
* @ chan : The IIO channel
* @ error_mask : Mask for the error bit
* @ val : Result of the conversion
*
* Returns IIO_VAL_INT on success , a negative error code otherwise .
*
* The function performs a single conversion on a given channel and post
* processes the value accordingly to the channel spec . If a error_mask is given
* the function will check if the mask is set in the returned raw value . If it
* is set the function will perform a self - check . If the device does not report
* a error bit in the channels raw value set error_mask to 0.
*/
int adis_single_conversion ( struct iio_dev * indio_dev ,
2022-01-22 16:09:05 +03:00
const struct iio_chan_spec * chan ,
unsigned int error_mask , int * val )
2012-11-13 17:28:00 +04:00
{
struct adis * adis = iio_device_get_drvdata ( indio_dev ) ;
2012-11-20 17:36:00 +04:00
unsigned int uval ;
2012-11-13 17:28:00 +04:00
int ret ;
2019-11-22 16:24:17 +03:00
mutex_lock ( & adis - > state_lock ) ;
2012-11-13 17:28:00 +04:00
2019-11-22 16:24:17 +03:00
ret = __adis_read_reg ( adis , chan - > address , & uval ,
2022-01-22 16:09:05 +03:00
chan - > scan_type . storagebits / 8 ) ;
2012-11-13 17:28:00 +04:00
if ( ret )
goto err_unlock ;
2012-11-20 17:36:00 +04:00
if ( uval & error_mask ) {
2019-11-22 16:24:17 +03:00
ret = __adis_check_status ( adis ) ;
2012-11-13 17:28:00 +04:00
if ( ret )
goto err_unlock ;
}
if ( chan - > scan_type . sign = = ' s ' )
2012-11-20 17:36:00 +04:00
* val = sign_extend32 ( uval , chan - > scan_type . realbits - 1 ) ;
2012-11-13 17:28:00 +04:00
else
2012-11-20 17:36:00 +04:00
* val = uval & ( ( 1 < < chan - > scan_type . realbits ) - 1 ) ;
2012-11-13 17:28:00 +04:00
ret = IIO_VAL_INT ;
err_unlock :
2019-11-22 16:24:17 +03:00
mutex_unlock ( & adis - > state_lock ) ;
2012-11-13 17:28:00 +04:00
return ret ;
}
2022-01-30 23:56:53 +03:00
EXPORT_SYMBOL_NS_GPL ( adis_single_conversion , IIO_ADISLIB ) ;
2012-11-13 17:28:00 +04:00
/**
* adis_init ( ) - Initialize adis device structure
* @ adis : The adis device
* @ indio_dev : The iio device
* @ spi : The spi device
* @ data : Chip specific data
*
* Returns 0 on success , a negative error code otherwise .
*
* This function must be called , before any other adis helper function may be
* called .
*/
int adis_init ( struct adis * adis , struct iio_dev * indio_dev ,
2022-01-22 16:09:05 +03:00
struct spi_device * spi , const struct adis_data * data )
2012-11-13 17:28:00 +04:00
{
2020-01-07 14:17:04 +03:00
if ( ! data | | ! data - > timeouts ) {
dev_err ( & spi - > dev , " No config data or timeouts not defined! \n " ) ;
return - EINVAL ;
}
2019-11-22 16:24:11 +03:00
mutex_init ( & adis - > state_lock ) ;
2012-11-13 17:28:00 +04:00
adis - > spi = spi ;
adis - > data = data ;
iio_device_set_drvdata ( indio_dev , adis ) ;
2012-11-20 17:36:00 +04:00
if ( data - > has_paging ) {
/* Need to set the page before first read/write */
adis - > current_page = - 1 ;
} else {
/* Page will always be 0 */
adis - > current_page = 0 ;
}
2021-09-03 17:14:19 +03:00
return 0 ;
2012-11-13 17:28:00 +04:00
}
2022-01-30 23:56:53 +03:00
EXPORT_SYMBOL_NS_GPL ( adis_init , IIO_ADISLIB ) ;
2012-11-13 17:28:00 +04:00
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " Lars-Peter Clausen <lars@metafoo.de> " ) ;
MODULE_DESCRIPTION ( " Common library code for ADIS16XXX devices " ) ;