summaryrefslogtreecommitdiff
path: root/drivers/iio/imu/adis.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/imu/adis.c')
-rw-r--r--drivers/iio/imu/adis.c77
1 files changed, 44 insertions, 33 deletions
diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c
index 495caf4ce87a..d160147cce0b 100644
--- a/drivers/iio/imu/adis.c
+++ b/drivers/iio/imu/adis.c
@@ -13,7 +13,7 @@
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/module.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include <linux/iio/iio.h>
#include <linux/iio/imu/adis.h>
@@ -39,34 +39,29 @@ int __adis_write_reg(struct adis *adis, unsigned int reg, unsigned int value,
struct spi_transfer xfers[] = {
{
.tx_buf = adis->tx,
- .bits_per_word = 8,
.len = 2,
.cs_change = 1,
.delay.value = adis->data->write_delay,
.delay.unit = SPI_DELAY_UNIT_USECS,
}, {
.tx_buf = adis->tx + 2,
- .bits_per_word = 8,
.len = 2,
.cs_change = 1,
.delay.value = adis->data->write_delay,
.delay.unit = SPI_DELAY_UNIT_USECS,
}, {
.tx_buf = adis->tx + 4,
- .bits_per_word = 8,
.len = 2,
.cs_change = 1,
.delay.value = adis->data->write_delay,
.delay.unit = SPI_DELAY_UNIT_USECS,
}, {
.tx_buf = adis->tx + 6,
- .bits_per_word = 8,
.len = 2,
.delay.value = adis->data->write_delay,
.delay.unit = SPI_DELAY_UNIT_USECS,
}, {
.tx_buf = adis->tx + 8,
- .bits_per_word = 8,
.len = 2,
.delay.value = adis->data->write_delay,
.delay.unit = SPI_DELAY_UNIT_USECS,
@@ -115,7 +110,7 @@ int __adis_write_reg(struct adis *adis, unsigned int reg, unsigned int value,
return ret;
}
-EXPORT_SYMBOL_NS_GPL(__adis_write_reg, IIO_ADISLIB);
+EXPORT_SYMBOL_NS_GPL(__adis_write_reg, "IIO_ADISLIB");
/**
* __adis_read_reg() - read N bytes from register (unlocked version)
@@ -133,14 +128,12 @@ int __adis_read_reg(struct adis *adis, unsigned int reg, unsigned int *val,
struct spi_transfer xfers[] = {
{
.tx_buf = adis->tx,
- .bits_per_word = 8,
.len = 2,
.cs_change = 1,
.delay.value = adis->data->write_delay,
.delay.unit = SPI_DELAY_UNIT_USECS,
}, {
.tx_buf = adis->tx + 2,
- .bits_per_word = 8,
.len = 2,
.cs_change = 1,
.delay.value = adis->data->read_delay,
@@ -148,14 +141,12 @@ int __adis_read_reg(struct adis *adis, unsigned int reg, unsigned int *val,
}, {
.tx_buf = adis->tx + 4,
.rx_buf = adis->rx,
- .bits_per_word = 8,
.len = 2,
.cs_change = 1,
.delay.value = adis->data->read_delay,
.delay.unit = SPI_DELAY_UNIT_USECS,
}, {
.rx_buf = adis->rx + 2,
- .bits_per_word = 8,
.len = 2,
.delay.value = adis->data->read_delay,
.delay.unit = SPI_DELAY_UNIT_USECS,
@@ -206,7 +197,7 @@ int __adis_read_reg(struct adis *adis, unsigned int reg, unsigned int *val,
return ret;
}
-EXPORT_SYMBOL_NS_GPL(__adis_read_reg, IIO_ADISLIB);
+EXPORT_SYMBOL_NS_GPL(__adis_read_reg, "IIO_ADISLIB");
/**
* __adis_update_bits_base() - ADIS Update bits function - Unlocked version
* @adis: The adis device
@@ -223,15 +214,15 @@ int __adis_update_bits_base(struct adis *adis, unsigned int reg, const u32 mask,
int ret;
u32 __val;
- ret = __adis_read_reg(adis, reg, &__val, size);
+ ret = adis->ops->read(adis, reg, &__val, size);
if (ret)
return ret;
__val = (__val & ~mask) | (val & mask);
- return __adis_write_reg(adis, reg, __val, size);
+ return adis->ops->write(adis, reg, __val, size);
}
-EXPORT_SYMBOL_NS_GPL(__adis_update_bits_base, IIO_ADISLIB);
+EXPORT_SYMBOL_NS_GPL(__adis_update_bits_base, "IIO_ADISLIB");
#ifdef CONFIG_DEBUG_FS
@@ -253,7 +244,7 @@ int adis_debugfs_reg_access(struct iio_dev *indio_dev, unsigned int reg,
return adis_write_reg_16(adis, reg, writeval);
}
-EXPORT_SYMBOL_NS(adis_debugfs_reg_access, IIO_ADISLIB);
+EXPORT_SYMBOL_NS(adis_debugfs_reg_access, "IIO_ADISLIB");
#endif
@@ -294,7 +285,7 @@ int __adis_enable_irq(struct adis *adis, bool enable)
return __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc);
}
-EXPORT_SYMBOL_NS(__adis_enable_irq, IIO_ADISLIB);
+EXPORT_SYMBOL_NS(__adis_enable_irq, "IIO_ADISLIB");
/**
* __adis_check_status() - Check the device for error conditions (unlocked)
@@ -304,11 +295,20 @@ EXPORT_SYMBOL_NS(__adis_enable_irq, IIO_ADISLIB);
*/
int __adis_check_status(struct adis *adis)
{
- u16 status;
+ unsigned int status;
+ int diag_stat_bits;
+ u16 status_16 = 0;
int ret;
int i;
- ret = __adis_read_reg_16(adis, adis->data->diag_stat_reg, &status);
+ if (adis->data->diag_stat_size) {
+ ret = adis->ops->read(adis, adis->data->diag_stat_reg, &status,
+ adis->data->diag_stat_size);
+ } else {
+ ret = __adis_read_reg_16(adis, adis->data->diag_stat_reg,
+ &status_16);
+ status = status_16;
+ }
if (ret)
return ret;
@@ -317,7 +317,10 @@ int __adis_check_status(struct adis *adis)
if (status == 0)
return 0;
- for (i = 0; i < 16; ++i) {
+ diag_stat_bits = BITS_PER_BYTE * (adis->data->diag_stat_size ?
+ adis->data->diag_stat_size : 2);
+
+ for (i = 0; i < diag_stat_bits; ++i) {
if (status & BIT(i)) {
dev_err(&adis->spi->dev, "%s.\n",
adis->data->status_error_msgs[i]);
@@ -326,7 +329,7 @@ int __adis_check_status(struct adis *adis)
return -EIO;
}
-EXPORT_SYMBOL_NS_GPL(__adis_check_status, IIO_ADISLIB);
+EXPORT_SYMBOL_NS_GPL(__adis_check_status, "IIO_ADISLIB");
/**
* __adis_reset() - Reset the device (unlocked version)
@@ -350,7 +353,7 @@ int __adis_reset(struct adis *adis)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(__adis_reset, IIO_ADIS_LIB);
+EXPORT_SYMBOL_NS_GPL(__adis_reset, "IIO_ADIS_LIB");
static int adis_self_test(struct adis *adis)
{
@@ -441,7 +444,7 @@ int __adis_initial_startup(struct adis *adis)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(__adis_initial_startup, IIO_ADISLIB);
+EXPORT_SYMBOL_NS_GPL(__adis_initial_startup, "IIO_ADISLIB");
/**
* adis_single_conversion() - Performs a single sample conversion
@@ -466,17 +469,17 @@ int adis_single_conversion(struct iio_dev *indio_dev,
unsigned int uval;
int ret;
- mutex_lock(&adis->state_lock);
+ guard(mutex)(&adis->state_lock);
- ret = __adis_read_reg(adis, chan->address, &uval,
+ ret = adis->ops->read(adis, chan->address, &uval,
chan->scan_type.storagebits / 8);
if (ret)
- goto err_unlock;
+ return ret;
if (uval & error_mask) {
ret = __adis_check_status(adis);
if (ret)
- goto err_unlock;
+ return ret;
}
if (chan->scan_type.sign == 's')
@@ -484,12 +487,15 @@ int adis_single_conversion(struct iio_dev *indio_dev,
else
*val = uval & ((1 << chan->scan_type.realbits) - 1);
- ret = IIO_VAL_INT;
-err_unlock:
- mutex_unlock(&adis->state_lock);
- return ret;
+ return IIO_VAL_INT;
}
-EXPORT_SYMBOL_NS_GPL(adis_single_conversion, IIO_ADISLIB);
+EXPORT_SYMBOL_NS_GPL(adis_single_conversion, "IIO_ADISLIB");
+
+static const struct adis_ops adis_default_ops = {
+ .read = __adis_read_reg,
+ .write = __adis_write_reg,
+ .reset = __adis_reset,
+};
/**
* adis_init() - Initialize adis device structure
@@ -520,6 +526,11 @@ int adis_init(struct adis *adis, struct iio_dev *indio_dev,
adis->spi = spi;
adis->data = data;
+ if (!adis->ops->write && !adis->ops->read && !adis->ops->reset)
+ adis->ops = &adis_default_ops;
+ else if (!adis->ops->write || !adis->ops->read || !adis->ops->reset)
+ return -EINVAL;
+
iio_device_set_drvdata(indio_dev, adis);
if (data->has_paging) {
@@ -532,7 +543,7 @@ int adis_init(struct adis *adis, struct iio_dev *indio_dev,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(adis_init, IIO_ADISLIB);
+EXPORT_SYMBOL_NS_GPL(adis_init, "IIO_ADISLIB");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");