|
@@ -20,136 +20,19 @@
|
|
|
|
|
|
#include "adis16220.h"
|
|
|
|
|
|
-/**
|
|
|
- * adis16220_spi_write_reg_8() - write single byte to a register
|
|
|
- * @indio_dev: iio device associated with child of actual device
|
|
|
- * @reg_address: the address of the register to be written
|
|
|
- * @val: the value to write
|
|
|
- **/
|
|
|
-static int adis16220_spi_write_reg_8(struct iio_dev *indio_dev,
|
|
|
- u8 reg_address,
|
|
|
- u8 val)
|
|
|
-{
|
|
|
- int ret;
|
|
|
- struct adis16220_state *st = iio_priv(indio_dev);
|
|
|
-
|
|
|
- mutex_lock(&st->buf_lock);
|
|
|
- st->tx[0] = ADIS16220_WRITE_REG(reg_address);
|
|
|
- st->tx[1] = val;
|
|
|
-
|
|
|
- ret = spi_write(st->us, st->tx, 2);
|
|
|
- mutex_unlock(&st->buf_lock);
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * adis16220_spi_write_reg_16() - write 2 bytes to a pair of registers
|
|
|
- * @indio_dev: iio device associated with child of actual device
|
|
|
- * @reg_address: the address of the lower of the two registers. Second register
|
|
|
- * is assumed to have address one greater.
|
|
|
- * @val: value to be written
|
|
|
- **/
|
|
|
-static int adis16220_spi_write_reg_16(struct iio_dev *indio_dev,
|
|
|
- u8 lower_reg_address,
|
|
|
- u16 value)
|
|
|
-{
|
|
|
- int ret;
|
|
|
- struct spi_message msg;
|
|
|
- struct adis16220_state *st = iio_priv(indio_dev);
|
|
|
- struct spi_transfer xfers[] = {
|
|
|
- {
|
|
|
- .tx_buf = st->tx,
|
|
|
- .bits_per_word = 8,
|
|
|
- .len = 2,
|
|
|
- .cs_change = 1,
|
|
|
- .delay_usecs = 35,
|
|
|
- }, {
|
|
|
- .tx_buf = st->tx + 2,
|
|
|
- .bits_per_word = 8,
|
|
|
- .len = 2,
|
|
|
- .delay_usecs = 35,
|
|
|
- },
|
|
|
- };
|
|
|
-
|
|
|
- mutex_lock(&st->buf_lock);
|
|
|
- st->tx[0] = ADIS16220_WRITE_REG(lower_reg_address);
|
|
|
- st->tx[1] = value & 0xFF;
|
|
|
- st->tx[2] = ADIS16220_WRITE_REG(lower_reg_address + 1);
|
|
|
- st->tx[3] = (value >> 8) & 0xFF;
|
|
|
-
|
|
|
- spi_message_init(&msg);
|
|
|
- spi_message_add_tail(&xfers[0], &msg);
|
|
|
- spi_message_add_tail(&xfers[1], &msg);
|
|
|
- ret = spi_sync(st->us, &msg);
|
|
|
- mutex_unlock(&st->buf_lock);
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * adis16220_spi_read_reg_16() - read 2 bytes from a 16-bit register
|
|
|
- * @indio_dev: iio device associated with child of actual device
|
|
|
- * @reg_address: the address of the lower of the two registers. Second register
|
|
|
- * is assumed to have address one greater.
|
|
|
- * @val: somewhere to pass back the value read
|
|
|
- **/
|
|
|
-static int adis16220_spi_read_reg_16(struct iio_dev *indio_dev,
|
|
|
- u8 lower_reg_address,
|
|
|
- u16 *val)
|
|
|
-{
|
|
|
- struct spi_message msg;
|
|
|
- struct adis16220_state *st = iio_priv(indio_dev);
|
|
|
- int ret;
|
|
|
- struct spi_transfer xfers[] = {
|
|
|
- {
|
|
|
- .tx_buf = st->tx,
|
|
|
- .bits_per_word = 8,
|
|
|
- .len = 2,
|
|
|
- .cs_change = 1,
|
|
|
- .delay_usecs = 35,
|
|
|
- }, {
|
|
|
- .rx_buf = st->rx,
|
|
|
- .bits_per_word = 8,
|
|
|
- .len = 2,
|
|
|
- .cs_change = 1,
|
|
|
- .delay_usecs = 35,
|
|
|
- },
|
|
|
- };
|
|
|
-
|
|
|
- mutex_lock(&st->buf_lock);
|
|
|
- st->tx[0] = ADIS16220_READ_REG(lower_reg_address);
|
|
|
- st->tx[1] = 0;
|
|
|
-
|
|
|
- spi_message_init(&msg);
|
|
|
- spi_message_add_tail(&xfers[0], &msg);
|
|
|
- spi_message_add_tail(&xfers[1], &msg);
|
|
|
- ret = spi_sync(st->us, &msg);
|
|
|
- if (ret) {
|
|
|
- dev_err(&st->us->dev,
|
|
|
- "problem when reading 16 bit register 0x%02X",
|
|
|
- lower_reg_address);
|
|
|
- goto error_ret;
|
|
|
- }
|
|
|
- *val = (st->rx[0] << 8) | st->rx[1];
|
|
|
-
|
|
|
-error_ret:
|
|
|
- mutex_unlock(&st->buf_lock);
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
static ssize_t adis16220_read_16bit(struct device *dev,
|
|
|
struct device_attribute *attr,
|
|
|
char *buf)
|
|
|
{
|
|
|
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
|
|
|
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
|
|
+ struct adis16220_state *st = iio_priv(indio_dev);
|
|
|
ssize_t ret;
|
|
|
s16 val = 0;
|
|
|
|
|
|
/* Take the iio_dev status lock */
|
|
|
mutex_lock(&indio_dev->mlock);
|
|
|
- ret = adis16220_spi_read_reg_16(indio_dev, this_attr->address,
|
|
|
+ ret = adis_read_reg_16(&st->adis, this_attr->address,
|
|
|
(u16 *)&val);
|
|
|
mutex_unlock(&indio_dev->mlock);
|
|
|
if (ret)
|
|
@@ -164,13 +47,14 @@ static ssize_t adis16220_write_16bit(struct device *dev,
|
|
|
{
|
|
|
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
|
|
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
|
|
|
+ struct adis16220_state *st = iio_priv(indio_dev);
|
|
|
int ret;
|
|
|
u16 val;
|
|
|
|
|
|
ret = kstrtou16(buf, 10, &val);
|
|
|
if (ret)
|
|
|
goto error_ret;
|
|
|
- ret = adis16220_spi_write_reg_16(indio_dev, this_attr->address, val);
|
|
|
+ ret = adis_write_reg_16(&st->adis, this_attr->address, val);
|
|
|
|
|
|
error_ret:
|
|
|
return ret ? ret : len;
|
|
@@ -178,10 +62,11 @@ error_ret:
|
|
|
|
|
|
static int adis16220_capture(struct iio_dev *indio_dev)
|
|
|
{
|
|
|
+ struct adis16220_state *st = iio_priv(indio_dev);
|
|
|
int ret;
|
|
|
- ret = adis16220_spi_write_reg_16(indio_dev,
|
|
|
- ADIS16220_GLOB_CMD,
|
|
|
- 0xBF08); /* initiates a manual data capture */
|
|
|
+
|
|
|
+ /* initiates a manual data capture */
|
|
|
+ ret = adis_write_reg_16(&st->adis, ADIS16220_GLOB_CMD, 0xBF08);
|
|
|
if (ret)
|
|
|
dev_err(&indio_dev->dev, "problem beginning capture");
|
|
|
|
|
@@ -190,18 +75,6 @@ static int adis16220_capture(struct iio_dev *indio_dev)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static int adis16220_reset(struct iio_dev *indio_dev)
|
|
|
-{
|
|
|
- int ret;
|
|
|
- ret = adis16220_spi_write_reg_8(indio_dev,
|
|
|
- ADIS16220_GLOB_CMD,
|
|
|
- ADIS16220_GLOB_CMD_SW_RESET);
|
|
|
- if (ret)
|
|
|
- dev_err(&indio_dev->dev, "problem resetting device");
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
static ssize_t adis16220_write_capture(struct device *dev,
|
|
|
struct device_attribute *attr,
|
|
|
const char *buf, size_t len)
|
|
@@ -222,81 +95,6 @@ static ssize_t adis16220_write_capture(struct device *dev,
|
|
|
return len;
|
|
|
}
|
|
|
|
|
|
-static int adis16220_check_status(struct iio_dev *indio_dev)
|
|
|
-{
|
|
|
- u16 status;
|
|
|
- int ret;
|
|
|
-
|
|
|
- ret = adis16220_spi_read_reg_16(indio_dev, ADIS16220_DIAG_STAT,
|
|
|
- &status);
|
|
|
-
|
|
|
- if (ret < 0) {
|
|
|
- dev_err(&indio_dev->dev, "Reading status failed\n");
|
|
|
- goto error_ret;
|
|
|
- }
|
|
|
- ret = status & 0x7F;
|
|
|
-
|
|
|
- if (status & ADIS16220_DIAG_STAT_VIOLATION)
|
|
|
- dev_err(&indio_dev->dev,
|
|
|
- "Capture period violation/interruption\n");
|
|
|
- if (status & ADIS16220_DIAG_STAT_SPI_FAIL)
|
|
|
- dev_err(&indio_dev->dev, "SPI failure\n");
|
|
|
- if (status & ADIS16220_DIAG_STAT_FLASH_UPT)
|
|
|
- dev_err(&indio_dev->dev, "Flash update failed\n");
|
|
|
- if (status & ADIS16220_DIAG_STAT_POWER_HIGH)
|
|
|
- dev_err(&indio_dev->dev, "Power supply above 3.625V\n");
|
|
|
- if (status & ADIS16220_DIAG_STAT_POWER_LOW)
|
|
|
- dev_err(&indio_dev->dev, "Power supply below 3.15V\n");
|
|
|
-
|
|
|
-error_ret:
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-static int adis16220_self_test(struct iio_dev *indio_dev)
|
|
|
-{
|
|
|
- int ret;
|
|
|
- ret = adis16220_spi_write_reg_16(indio_dev,
|
|
|
- ADIS16220_MSC_CTRL,
|
|
|
- ADIS16220_MSC_CTRL_SELF_TEST_EN);
|
|
|
- if (ret) {
|
|
|
- dev_err(&indio_dev->dev, "problem starting self test");
|
|
|
- goto err_ret;
|
|
|
- }
|
|
|
-
|
|
|
- adis16220_check_status(indio_dev);
|
|
|
-
|
|
|
-err_ret:
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-static int adis16220_initial_setup(struct iio_dev *indio_dev)
|
|
|
-{
|
|
|
- int ret;
|
|
|
-
|
|
|
- /* Do self test */
|
|
|
- ret = adis16220_self_test(indio_dev);
|
|
|
- if (ret) {
|
|
|
- dev_err(&indio_dev->dev, "self test failure");
|
|
|
- goto err_ret;
|
|
|
- }
|
|
|
-
|
|
|
- /* Read status register to check the result */
|
|
|
- ret = adis16220_check_status(indio_dev);
|
|
|
- if (ret) {
|
|
|
- adis16220_reset(indio_dev);
|
|
|
- dev_err(&indio_dev->dev, "device not playing ball -> reset");
|
|
|
- msleep(ADIS16220_STARTUP_DELAY);
|
|
|
- ret = adis16220_check_status(indio_dev);
|
|
|
- if (ret) {
|
|
|
- dev_err(&indio_dev->dev, "giving up");
|
|
|
- goto err_ret;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-err_ret:
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
|
|
|
char *buf,
|
|
|
loff_t off,
|
|
@@ -333,7 +131,7 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
|
|
|
count = ADIS16220_CAPTURE_SIZE - off;
|
|
|
|
|
|
/* write the begin position of capture buffer */
|
|
|
- ret = adis16220_spi_write_reg_16(indio_dev,
|
|
|
+ ret = adis_write_reg_16(&st->adis,
|
|
|
ADIS16220_CAPT_PNTR,
|
|
|
off > 1);
|
|
|
if (ret)
|
|
@@ -342,8 +140,9 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
|
|
|
/* read count/2 values from capture buffer */
|
|
|
mutex_lock(&st->buf_lock);
|
|
|
|
|
|
+
|
|
|
for (i = 0; i < count; i += 2) {
|
|
|
- st->tx[i] = ADIS16220_READ_REG(addr);
|
|
|
+ st->tx[i] = ADIS_READ_REG(addr);
|
|
|
st->tx[i + 1] = 0;
|
|
|
}
|
|
|
xfers[1].len = count;
|
|
@@ -351,7 +150,7 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
|
|
|
spi_message_init(&msg);
|
|
|
spi_message_add_tail(&xfers[0], &msg);
|
|
|
spi_message_add_tail(&xfers[1], &msg);
|
|
|
- ret = spi_sync(st->us, &msg);
|
|
|
+ ret = spi_sync(st->adis.spi, &msg);
|
|
|
if (ret) {
|
|
|
|
|
|
mutex_unlock(&st->buf_lock);
|
|
@@ -472,6 +271,8 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,
|
|
|
int *val, int *val2,
|
|
|
long mask)
|
|
|
{
|
|
|
+ struct adis16220_state *st = iio_priv(indio_dev);
|
|
|
+ const struct adis16220_address_spec *addr;
|
|
|
int ret = -EINVAL;
|
|
|
int addrind = 0;
|
|
|
u16 uval;
|
|
@@ -516,28 +317,21 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,
|
|
|
default:
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
- if (adis16220_addresses[chan->address][addrind].sign) {
|
|
|
- ret = adis16220_spi_read_reg_16(indio_dev,
|
|
|
- adis16220_addresses[chan
|
|
|
- ->address]
|
|
|
- [addrind].addr,
|
|
|
- &sval);
|
|
|
+ addr = &adis16220_addresses[chan->address][addrind];
|
|
|
+ if (addr->sign) {
|
|
|
+ ret = adis_read_reg_16(&st->adis, addr->addr, &sval);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
- bits = adis16220_addresses[chan->address][addrind].bits;
|
|
|
+ bits = addr->bits;
|
|
|
sval &= (1 << bits) - 1;
|
|
|
sval = (s16)(sval << (16 - bits)) >> (16 - bits);
|
|
|
*val = sval;
|
|
|
return IIO_VAL_INT;
|
|
|
} else {
|
|
|
- ret = adis16220_spi_read_reg_16(indio_dev,
|
|
|
- adis16220_addresses[chan
|
|
|
- ->address]
|
|
|
- [addrind].addr,
|
|
|
- &uval);
|
|
|
+ ret = adis_read_reg_16(&st->adis, addr->addr, &uval);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
- bits = adis16220_addresses[chan->address][addrind].bits;
|
|
|
+ bits = addr->bits;
|
|
|
uval &= (1 << bits) - 1;
|
|
|
*val = uval;
|
|
|
return IIO_VAL_INT;
|
|
@@ -601,6 +395,32 @@ static const struct iio_info adis16220_info = {
|
|
|
.read_raw = &adis16220_read_raw,
|
|
|
};
|
|
|
|
|
|
+static const char * const adis16220_status_error_msgs[] = {
|
|
|
+ [ADIS16220_DIAG_STAT_VIOLATION_BIT] = "Capture period violation/interruption",
|
|
|
+ [ADIS16220_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
|
|
|
+ [ADIS16220_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
|
|
|
+ [ADIS16220_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V",
|
|
|
+ [ADIS16220_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 3.15V",
|
|
|
+};
|
|
|
+
|
|
|
+static const struct adis_data adis16220_data = {
|
|
|
+ .read_delay = 35,
|
|
|
+ .write_delay = 35,
|
|
|
+ .msc_ctrl_reg = ADIS16220_MSC_CTRL,
|
|
|
+ .glob_cmd_reg = ADIS16220_GLOB_CMD,
|
|
|
+ .diag_stat_reg = ADIS16220_DIAG_STAT,
|
|
|
+
|
|
|
+ .self_test_mask = ADIS16220_MSC_CTRL_SELF_TEST_EN,
|
|
|
+ .startup_delay = ADIS16220_STARTUP_DELAY,
|
|
|
+
|
|
|
+ .status_error_msgs = adis16220_status_error_msgs,
|
|
|
+ .status_error_mask = BIT(ADIS16220_DIAG_STAT_VIOLATION_BIT) |
|
|
|
+ BIT(ADIS16220_DIAG_STAT_SPI_FAIL_BIT) |
|
|
|
+ BIT(ADIS16220_DIAG_STAT_FLASH_UPT_BIT) |
|
|
|
+ BIT(ADIS16220_DIAG_STAT_POWER_HIGH_BIT) |
|
|
|
+ BIT(ADIS16220_DIAG_STAT_POWER_LOW_BIT),
|
|
|
+};
|
|
|
+
|
|
|
static int __devinit adis16220_probe(struct spi_device *spi)
|
|
|
{
|
|
|
int ret;
|
|
@@ -618,9 +438,6 @@ static int __devinit adis16220_probe(struct spi_device *spi)
|
|
|
/* this is only used for removal purposes */
|
|
|
spi_set_drvdata(spi, indio_dev);
|
|
|
|
|
|
- st->us = spi;
|
|
|
- mutex_init(&st->buf_lock);
|
|
|
-
|
|
|
indio_dev->name = spi->dev.driver->name;
|
|
|
indio_dev->dev.parent = &spi->dev;
|
|
|
indio_dev->info = &adis16220_info;
|
|
@@ -644,8 +461,11 @@ static int __devinit adis16220_probe(struct spi_device *spi)
|
|
|
if (ret)
|
|
|
goto error_rm_adc1_bin;
|
|
|
|
|
|
+ ret = adis_init(&st->adis, indio_dev, spi, &adis16220_data);
|
|
|
+ if (ret)
|
|
|
+ goto error_rm_adc2_bin;
|
|
|
/* Get the device into a sane initial state */
|
|
|
- ret = adis16220_initial_setup(indio_dev);
|
|
|
+ ret = adis_initial_startup(&st->adis);
|
|
|
if (ret)
|
|
|
goto error_rm_adc2_bin;
|
|
|
return 0;
|