staging:iio:adis16220: Use adis library
authorLars-Peter Clausen <lars@metafoo.de>
Tue, 13 Nov 2012 13:28:00 +0000 (13:28 +0000)
committerJonathan Cameron <jic23@kernel.org>
Mon, 19 Nov 2012 22:22:07 +0000 (22:22 +0000)
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: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
drivers/staging/iio/accel/adis16220.h
drivers/staging/iio/accel/adis16220_core.c

index 024313cf5cf0cbbc03a95c97877af26be30ef145..7cc4d2f3ec28264a62839c15a333d47c6ec34741 100644 (file)
@@ -1,10 +1,9 @@
 #ifndef 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_WRITE_REG(a) ((a) | 0x80)
+#define ADIS16220_STARTUP_DELAY        220 /* ms */
 
 /* Flash memory write count */
 #define ADIS16220_FLASH_CNT     0x00
 #define ADIS16220_DIAG_STAT_FLASH_CHK  (1<<6)
 #define ADIS16220_DIAG_STAT_SELF_TEST  (1<<5)
 /* Capture period violation/interruption */
-#define ADIS16220_DIAG_STAT_VIOLATION  (1<<4)
+#define ADIS16220_DIAG_STAT_VIOLATION_BIT      4
 /* SPI communications failure */
-#define ADIS16220_DIAG_STAT_SPI_FAIL   (1<<3)
+#define ADIS16220_DIAG_STAT_SPI_FAIL_BIT       3
 /* 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 */
-#define ADIS16220_DIAG_STAT_POWER_HIGH (1<<1)
+#define ADIS16220_DIAG_STAT_POWER_HIGH_BIT     1
 /* Power supply below 3.15 V */
-#define ADIS16220_DIAG_STAT_POWER_LOW  (1<<0)
+#define ADIS16220_DIAG_STAT_POWER_LOW_BIT      0
 
 /* GLOB_CMD */
 #define ADIS16220_GLOB_CMD_SW_RESET    (1<<7)
 
 /**
  * struct adis16220_state - device instance specific data
- * @us:                        actual spi_device
+ * @adis:              adis device
  * @tx:                        transmit buffer
  * @rx:                        receive buffer
  * @buf_lock:          mutex to protect tx and rx
  **/
 struct adis16220_state {
-       struct spi_device       *us;
+       struct adis adis;
+
        struct mutex            buf_lock;
        u8                      tx[ADIS16220_MAX_TX] ____cacheline_aligned;
        u8                      rx[ADIS16220_MAX_RX];
index 22807ac8e8f88892fbe2a196e3b7af4f8aaabc3e..c39ce622eb62ba69b2c777d48cd59731411d93b8 100644 (file)
 
 #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;