Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+10 −10
Original line number Diff line number Diff line
#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
@@ -102,15 +101,15 @@
#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)
@@ -125,13 +124,14 @@

/**
 * 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];
+50 −230
Original line number Diff line number Diff line
@@ -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 @@ static ssize_t adis16220_write_16bit(struct device *dev,

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;