Commit edcf6009 authored by Lars-Peter Clausen's avatar Lars-Peter Clausen Committed by Jonathan Cameron

staging:iio:adis16220: Use adis library

Use the new adis library for the adis16220 driver. The adis16220 driver is a bit
special and so we can only make use of the generic register access and control
functions for now.
Signed-off-by: default avatarLars-Peter Clausen <lars@metafoo.de>
Signed-off-by: default avatarJonathan Cameron <jic23@kernel.org>
parent 511fb29e
#ifndef SPI_ADIS16220_H_ #ifndef SPI_ADIS16220_H_
#define SPI_ADIS16220_H_ #define SPI_ADIS16220_H_
#define ADIS16220_STARTUP_DELAY 220 /* ms */ #include "../imu/adis.h"
#define ADIS16220_READ_REG(a) a #define ADIS16220_STARTUP_DELAY 220 /* ms */
#define ADIS16220_WRITE_REG(a) ((a) | 0x80)
/* Flash memory write count */ /* Flash memory write count */
#define ADIS16220_FLASH_CNT 0x00 #define ADIS16220_FLASH_CNT 0x00
...@@ -102,15 +101,15 @@ ...@@ -102,15 +101,15 @@
#define ADIS16220_DIAG_STAT_FLASH_CHK (1<<6) #define ADIS16220_DIAG_STAT_FLASH_CHK (1<<6)
#define ADIS16220_DIAG_STAT_SELF_TEST (1<<5) #define ADIS16220_DIAG_STAT_SELF_TEST (1<<5)
/* Capture period violation/interruption */ /* Capture period violation/interruption */
#define ADIS16220_DIAG_STAT_VIOLATION (1<<4) #define ADIS16220_DIAG_STAT_VIOLATION_BIT 4
/* SPI communications failure */ /* SPI communications failure */
#define ADIS16220_DIAG_STAT_SPI_FAIL (1<<3) #define ADIS16220_DIAG_STAT_SPI_FAIL_BIT 3
/* Flash update failure */ /* Flash update failure */
#define ADIS16220_DIAG_STAT_FLASH_UPT (1<<2) #define ADIS16220_DIAG_STAT_FLASH_UPT_BIT 2
/* Power supply above 3.625 V */ /* Power supply above 3.625 V */
#define ADIS16220_DIAG_STAT_POWER_HIGH (1<<1) #define ADIS16220_DIAG_STAT_POWER_HIGH_BIT 1
/* Power supply below 3.15 V */ /* Power supply below 3.15 V */
#define ADIS16220_DIAG_STAT_POWER_LOW (1<<0) #define ADIS16220_DIAG_STAT_POWER_LOW_BIT 0
/* GLOB_CMD */ /* GLOB_CMD */
#define ADIS16220_GLOB_CMD_SW_RESET (1<<7) #define ADIS16220_GLOB_CMD_SW_RESET (1<<7)
...@@ -125,13 +124,14 @@ ...@@ -125,13 +124,14 @@
/** /**
* struct adis16220_state - device instance specific data * struct adis16220_state - device instance specific data
* @us: actual spi_device * @adis: adis device
* @tx: transmit buffer * @tx: transmit buffer
* @rx: receive buffer * @rx: receive buffer
* @buf_lock: mutex to protect tx and rx * @buf_lock: mutex to protect tx and rx
**/ **/
struct adis16220_state { struct adis16220_state {
struct spi_device *us; struct adis adis;
struct mutex buf_lock; struct mutex buf_lock;
u8 tx[ADIS16220_MAX_TX] ____cacheline_aligned; u8 tx[ADIS16220_MAX_TX] ____cacheline_aligned;
u8 rx[ADIS16220_MAX_RX]; u8 rx[ADIS16220_MAX_RX];
......
...@@ -20,136 +20,19 @@ ...@@ -20,136 +20,19 @@
#include "adis16220.h" #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, static ssize_t adis16220_read_16bit(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct iio_dev *indio_dev = dev_to_iio_dev(dev); struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct adis16220_state *st = iio_priv(indio_dev);
ssize_t ret; ssize_t ret;
s16 val = 0; s16 val = 0;
/* Take the iio_dev status lock */ /* Take the iio_dev status lock */
mutex_lock(&indio_dev->mlock); 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); (u16 *)&val);
mutex_unlock(&indio_dev->mlock); mutex_unlock(&indio_dev->mlock);
if (ret) if (ret)
...@@ -164,13 +47,14 @@ static ssize_t adis16220_write_16bit(struct device *dev, ...@@ -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 *indio_dev = dev_to_iio_dev(dev);
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
struct adis16220_state *st = iio_priv(indio_dev);
int ret; int ret;
u16 val; u16 val;
ret = kstrtou16(buf, 10, &val); ret = kstrtou16(buf, 10, &val);
if (ret) if (ret)
goto error_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: error_ret:
return ret ? ret : len; return ret ? ret : len;
...@@ -178,10 +62,11 @@ static ssize_t adis16220_write_16bit(struct device *dev, ...@@ -178,10 +62,11 @@ static ssize_t adis16220_write_16bit(struct device *dev,
static int adis16220_capture(struct iio_dev *indio_dev) static int adis16220_capture(struct iio_dev *indio_dev)
{ {
struct adis16220_state *st = iio_priv(indio_dev);
int ret; int ret;
ret = adis16220_spi_write_reg_16(indio_dev,
ADIS16220_GLOB_CMD, /* initiates a manual data capture */
0xBF08); /* initiates a manual data capture */ ret = adis_write_reg_16(&st->adis, ADIS16220_GLOB_CMD, 0xBF08);
if (ret) if (ret)
dev_err(&indio_dev->dev, "problem beginning capture"); dev_err(&indio_dev->dev, "problem beginning capture");
...@@ -190,18 +75,6 @@ static int adis16220_capture(struct iio_dev *indio_dev) ...@@ -190,18 +75,6 @@ static int adis16220_capture(struct iio_dev *indio_dev)
return ret; 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, static ssize_t adis16220_write_capture(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t len) const char *buf, size_t len)
...@@ -222,81 +95,6 @@ static ssize_t adis16220_write_capture(struct device *dev, ...@@ -222,81 +95,6 @@ static ssize_t adis16220_write_capture(struct device *dev,
return len; 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, static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
char *buf, char *buf,
loff_t off, loff_t off,
...@@ -333,7 +131,7 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev, ...@@ -333,7 +131,7 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
count = ADIS16220_CAPTURE_SIZE - off; count = ADIS16220_CAPTURE_SIZE - off;
/* write the begin position of capture buffer */ /* 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, ADIS16220_CAPT_PNTR,
off > 1); off > 1);
if (ret) if (ret)
...@@ -342,8 +140,9 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev, ...@@ -342,8 +140,9 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
/* read count/2 values from capture buffer */ /* read count/2 values from capture buffer */
mutex_lock(&st->buf_lock); mutex_lock(&st->buf_lock);
for (i = 0; i < count; i += 2) { 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; st->tx[i + 1] = 0;
} }
xfers[1].len = count; xfers[1].len = count;
...@@ -351,7 +150,7 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev, ...@@ -351,7 +150,7 @@ static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev,
spi_message_init(&msg); spi_message_init(&msg);
spi_message_add_tail(&xfers[0], &msg); spi_message_add_tail(&xfers[0], &msg);
spi_message_add_tail(&xfers[1], &msg); spi_message_add_tail(&xfers[1], &msg);
ret = spi_sync(st->us, &msg); ret = spi_sync(st->adis.spi, &msg);
if (ret) { if (ret) {
mutex_unlock(&st->buf_lock); mutex_unlock(&st->buf_lock);
...@@ -472,6 +271,8 @@ static int adis16220_read_raw(struct iio_dev *indio_dev, ...@@ -472,6 +271,8 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, int *val, int *val2,
long mask) long mask)
{ {
struct adis16220_state *st = iio_priv(indio_dev);
const struct adis16220_address_spec *addr;
int ret = -EINVAL; int ret = -EINVAL;
int addrind = 0; int addrind = 0;
u16 uval; u16 uval;
...@@ -516,28 +317,21 @@ static int adis16220_read_raw(struct iio_dev *indio_dev, ...@@ -516,28 +317,21 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,
default: default:
return -EINVAL; return -EINVAL;
} }
if (adis16220_addresses[chan->address][addrind].sign) { addr = &adis16220_addresses[chan->address][addrind];
ret = adis16220_spi_read_reg_16(indio_dev, if (addr->sign) {
adis16220_addresses[chan ret = adis_read_reg_16(&st->adis, addr->addr, &sval);
->address]
[addrind].addr,
&sval);
if (ret) if (ret)
return ret; return ret;
bits = adis16220_addresses[chan->address][addrind].bits; bits = addr->bits;
sval &= (1 << bits) - 1; sval &= (1 << bits) - 1;
sval = (s16)(sval << (16 - bits)) >> (16 - bits); sval = (s16)(sval << (16 - bits)) >> (16 - bits);
*val = sval; *val = sval;
return IIO_VAL_INT; return IIO_VAL_INT;
} else { } else {
ret = adis16220_spi_read_reg_16(indio_dev, ret = adis_read_reg_16(&st->adis, addr->addr, &uval);
adis16220_addresses[chan
->address]
[addrind].addr,
&uval);
if (ret) if (ret)
return ret; return ret;
bits = adis16220_addresses[chan->address][addrind].bits; bits = addr->bits;
uval &= (1 << bits) - 1; uval &= (1 << bits) - 1;
*val = uval; *val = uval;
return IIO_VAL_INT; return IIO_VAL_INT;
...@@ -601,6 +395,32 @@ static const struct iio_info adis16220_info = { ...@@ -601,6 +395,32 @@ static const struct iio_info adis16220_info = {
.read_raw = &adis16220_read_raw, .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) static int __devinit adis16220_probe(struct spi_device *spi)
{ {
int ret; int ret;
...@@ -618,9 +438,6 @@ static int __devinit adis16220_probe(struct spi_device *spi) ...@@ -618,9 +438,6 @@ static int __devinit adis16220_probe(struct spi_device *spi)
/* this is only used for removal purposes */ /* this is only used for removal purposes */
spi_set_drvdata(spi, indio_dev); spi_set_drvdata(spi, indio_dev);
st->us = spi;
mutex_init(&st->buf_lock);
indio_dev->name = spi->dev.driver->name; indio_dev->name = spi->dev.driver->name;
indio_dev->dev.parent = &spi->dev; indio_dev->dev.parent = &spi->dev;
indio_dev->info = &adis16220_info; indio_dev->info = &adis16220_info;
...@@ -644,8 +461,11 @@ static int __devinit adis16220_probe(struct spi_device *spi) ...@@ -644,8 +461,11 @@ static int __devinit adis16220_probe(struct spi_device *spi)
if (ret) if (ret)
goto error_rm_adc1_bin; 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 */ /* Get the device into a sane initial state */
ret = adis16220_initial_setup(indio_dev); ret = adis_initial_startup(&st->adis);
if (ret) if (ret)
goto error_rm_adc2_bin; goto error_rm_adc2_bin;
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment