diff options
Diffstat (limited to 'drivers/staging/iio/accel/adis16220_core.c')
-rw-r--r-- | drivers/staging/iio/accel/adis16220_core.c | 288 |
1 files changed, 53 insertions, 235 deletions
diff --git a/drivers/staging/iio/accel/adis16220_core.c b/drivers/staging/iio/accel/adis16220_core.c index eaadd9df3f78..370b01aa767a 100644 --- a/drivers/staging/iio/accel/adis16220_core.c +++ b/drivers/staging/iio/accel/adis16220_core.c @@ -20,138 +20,19 @@ #include "adis16220.h" -#define DRIVER_NAME "adis16220" - -/** - * 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) @@ -166,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; @@ -180,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"); @@ -192,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) @@ -224,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, @@ -335,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) @@ -344,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; @@ -353,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); @@ -474,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; @@ -518,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; @@ -603,7 +395,33 @@ static const struct iio_info adis16220_info = { .read_raw = &adis16220_read_raw, }; -static int __devinit adis16220_probe(struct spi_device *spi) +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 adis16220_probe(struct spi_device *spi) { int ret; struct adis16220_state *st; @@ -620,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; @@ -646,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; @@ -666,7 +484,7 @@ error_ret: return ret; } -static int __devexit adis16220_remove(struct spi_device *spi) +static int adis16220_remove(struct spi_device *spi) { struct iio_dev *indio_dev = spi_get_drvdata(spi); @@ -685,7 +503,7 @@ static struct spi_driver adis16220_driver = { .owner = THIS_MODULE, }, .probe = adis16220_probe, - .remove = __devexit_p(adis16220_remove), + .remove = adis16220_remove, }; module_spi_driver(adis16220_driver); |