diff options
Diffstat (limited to 'drivers/iio/imu/adis.c')
| -rw-r--r-- | drivers/iio/imu/adis.c | 440 | 
1 files changed, 0 insertions, 440 deletions
diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c deleted file mode 100644 index 911255d41c1..00000000000 --- a/drivers/iio/imu/adis.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Common library for ADIS16XXX devices - * - * Copyright 2012 Analog Devices Inc. - *   Author: Lars-Peter Clausen <lars@metafoo.de> - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/delay.h> -#include <linux/mutex.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/spi/spi.h> -#include <linux/slab.h> -#include <linux/sysfs.h> -#include <linux/module.h> -#include <asm/unaligned.h> - -#include <linux/iio/iio.h> -#include <linux/iio/sysfs.h> -#include <linux/iio/buffer.h> -#include <linux/iio/imu/adis.h> - -#define ADIS_MSC_CTRL_DATA_RDY_EN	BIT(2) -#define ADIS_MSC_CTRL_DATA_RDY_POL_HIGH	BIT(1) -#define ADIS_MSC_CTRL_DATA_RDY_DIO2	BIT(0) -#define ADIS_GLOB_CMD_SW_RESET		BIT(7) - -int adis_write_reg(struct adis *adis, unsigned int reg, -	unsigned int value, unsigned int size) -{ -	unsigned int page = reg / ADIS_PAGE_SIZE; -	int ret, i; -	struct spi_message msg; -	struct spi_transfer xfers[] = { -		{ -			.tx_buf = adis->tx, -			.bits_per_word = 8, -			.len = 2, -			.cs_change = 1, -			.delay_usecs = adis->data->write_delay, -		}, { -			.tx_buf = adis->tx + 2, -			.bits_per_word = 8, -			.len = 2, -			.cs_change = 1, -			.delay_usecs = adis->data->write_delay, -		}, { -			.tx_buf = adis->tx + 4, -			.bits_per_word = 8, -			.len = 2, -			.cs_change = 1, -			.delay_usecs = adis->data->write_delay, -		}, { -			.tx_buf = adis->tx + 6, -			.bits_per_word = 8, -			.len = 2, -			.delay_usecs = adis->data->write_delay, -		}, { -			.tx_buf = adis->tx + 8, -			.bits_per_word = 8, -			.len = 2, -			.delay_usecs = adis->data->write_delay, -		}, -	}; - -	mutex_lock(&adis->txrx_lock); - -	spi_message_init(&msg); - -	if (adis->current_page != page) { -		adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); -		adis->tx[1] = page; -		spi_message_add_tail(&xfers[0], &msg); -	} - -	switch (size) { -	case 4: -		adis->tx[8] = ADIS_WRITE_REG(reg + 3); -		adis->tx[9] = (value >> 24) & 0xff; -		adis->tx[6] = ADIS_WRITE_REG(reg + 2); -		adis->tx[7] = (value >> 16) & 0xff; -	case 2: -		adis->tx[4] = ADIS_WRITE_REG(reg + 1); -		adis->tx[5] = (value >> 8) & 0xff; -	case 1: -		adis->tx[2] = ADIS_WRITE_REG(reg); -		adis->tx[3] = value & 0xff; -		break; -	default: -		ret = -EINVAL; -		goto out_unlock; -	} - -	xfers[size].cs_change = 0; - -	for (i = 1; i <= size; i++) -		spi_message_add_tail(&xfers[i], &msg); - -	ret = spi_sync(adis->spi, &msg); -	if (ret) { -		dev_err(&adis->spi->dev, "Failed to write register 0x%02X: %d\n", -				reg, ret); -	} else { -		adis->current_page = page; -	} - -out_unlock: -	mutex_unlock(&adis->txrx_lock); - -	return ret; -} -EXPORT_SYMBOL_GPL(adis_write_reg); - -/** - * adis_read_reg() - read 2 bytes from a 16-bit register - * @adis: The adis device - * @reg: The address of the lower of the two registers - * @val: The value read back from the device - */ -int adis_read_reg(struct adis *adis, unsigned int reg, -	unsigned int *val, unsigned int size) -{ -	unsigned int page = reg / ADIS_PAGE_SIZE; -	struct spi_message msg; -	int ret; -	struct spi_transfer xfers[] = { -		{ -			.tx_buf = adis->tx, -			.bits_per_word = 8, -			.len = 2, -			.cs_change = 1, -			.delay_usecs = adis->data->write_delay, -		}, { -			.tx_buf = adis->tx + 2, -			.bits_per_word = 8, -			.len = 2, -			.cs_change = 1, -			.delay_usecs = adis->data->read_delay, -		}, { -			.tx_buf = adis->tx + 4, -			.rx_buf = adis->rx, -			.bits_per_word = 8, -			.len = 2, -			.cs_change = 1, -			.delay_usecs = adis->data->read_delay, -		}, { -			.rx_buf = adis->rx + 2, -			.bits_per_word = 8, -			.len = 2, -			.delay_usecs = adis->data->read_delay, -		}, -	}; - -	mutex_lock(&adis->txrx_lock); -	spi_message_init(&msg); - -	if (adis->current_page != page) { -		adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID); -		adis->tx[1] = page; -		spi_message_add_tail(&xfers[0], &msg); -	} - -	switch (size) { -	case 4: -		adis->tx[2] = ADIS_READ_REG(reg + 2); -		adis->tx[3] = 0; -		spi_message_add_tail(&xfers[1], &msg); -	case 2: -		adis->tx[4] = ADIS_READ_REG(reg); -		adis->tx[5] = 0; -		spi_message_add_tail(&xfers[2], &msg); -		spi_message_add_tail(&xfers[3], &msg); -		break; -	default: -		ret = -EINVAL; -		goto out_unlock; -	} - -	ret = spi_sync(adis->spi, &msg); -	if (ret) { -		dev_err(&adis->spi->dev, "Failed to read register 0x%02X: %d\n", -				reg, ret); -		goto out_unlock; -	} else { -		adis->current_page = page; -	} - -	switch (size) { -	case 4: -		*val = get_unaligned_be32(adis->rx); -		break; -	case 2: -		*val = get_unaligned_be16(adis->rx + 2); -		break; -	} - -out_unlock: -	mutex_unlock(&adis->txrx_lock); - -	return ret; -} -EXPORT_SYMBOL_GPL(adis_read_reg); - -#ifdef CONFIG_DEBUG_FS - -int adis_debugfs_reg_access(struct iio_dev *indio_dev, -	unsigned int reg, unsigned int writeval, unsigned int *readval) -{ -	struct adis *adis = iio_device_get_drvdata(indio_dev); - -	if (readval) { -		uint16_t val16; -		int ret; - -		ret = adis_read_reg_16(adis, reg, &val16); -		*readval = val16; - -		return ret; -	} else { -		return adis_write_reg_16(adis, reg, writeval); -	} -} -EXPORT_SYMBOL(adis_debugfs_reg_access); - -#endif - -/** - * adis_enable_irq() - Enable or disable data ready IRQ - * @adis: The adis device - * @enable: Whether to enable the IRQ - * - * Returns 0 on success, negative error code otherwise - */ -int adis_enable_irq(struct adis *adis, bool enable) -{ -	int ret = 0; -	uint16_t msc; - -	if (adis->data->enable_irq) -		return adis->data->enable_irq(adis, enable); - -	ret = adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc); -	if (ret) -		goto error_ret; - -	msc |= ADIS_MSC_CTRL_DATA_RDY_POL_HIGH; -	msc &= ~ADIS_MSC_CTRL_DATA_RDY_DIO2; -	if (enable) -		msc |= ADIS_MSC_CTRL_DATA_RDY_EN; -	else -		msc &= ~ADIS_MSC_CTRL_DATA_RDY_EN; - -	ret = adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc); - -error_ret: -	return ret; -} -EXPORT_SYMBOL(adis_enable_irq); - -/** - * adis_check_status() - Check the device for error conditions - * @adis: The adis device - * - * Returns 0 on success, a negative error code otherwise - */ -int adis_check_status(struct adis *adis) -{ -	uint16_t status; -	int ret; -	int i; - -	ret = adis_read_reg_16(adis, adis->data->diag_stat_reg, &status); -	if (ret < 0) -		return ret; - -	status &= adis->data->status_error_mask; - -	if (status == 0) -		return 0; - -	for (i = 0; i < 16; ++i) { -		if (status & BIT(i)) { -			dev_err(&adis->spi->dev, "%s.\n", -				adis->data->status_error_msgs[i]); -		} -	} - -	return -EIO; -} -EXPORT_SYMBOL_GPL(adis_check_status); - -/** - * adis_reset() - Reset the device - * @adis: The adis device - * - * Returns 0 on success, a negative error code otherwise - */ -int adis_reset(struct adis *adis) -{ -	int ret; - -	ret = adis_write_reg_8(adis, adis->data->glob_cmd_reg, -			ADIS_GLOB_CMD_SW_RESET); -	if (ret) -		dev_err(&adis->spi->dev, "Failed to reset device: %d\n", ret); - -	return ret; -} -EXPORT_SYMBOL_GPL(adis_reset); - -static int adis_self_test(struct adis *adis) -{ -	int ret; - -	ret = adis_write_reg_16(adis, adis->data->msc_ctrl_reg, -			adis->data->self_test_mask); -	if (ret) { -		dev_err(&adis->spi->dev, "Failed to initiate self test: %d\n", -			ret); -		return ret; -	} - -	msleep(adis->data->startup_delay); - -	return adis_check_status(adis); -} - -/** - * adis_inital_startup() - Performs device self-test - * @adis: The adis device - * - * Returns 0 if the device is operational, a negative error code otherwise. - * - * This function should be called early on in the device initialization sequence - * to ensure that the device is in a sane and known state and that it is usable. - */ -int adis_initial_startup(struct adis *adis) -{ -	int ret; - -	ret = adis_self_test(adis); -	if (ret) { -		dev_err(&adis->spi->dev, "Self-test failed, trying reset.\n"); -		adis_reset(adis); -		msleep(adis->data->startup_delay); -		ret = adis_self_test(adis); -		if (ret) { -			dev_err(&adis->spi->dev, "Second self-test failed, giving up.\n"); -			return ret; -		} -	} - -	return 0; -} -EXPORT_SYMBOL_GPL(adis_initial_startup); - -/** - * adis_single_conversion() - Performs a single sample conversion - * @indio_dev: The IIO device - * @chan: The IIO channel - * @error_mask: Mask for the error bit - * @val: Result of the conversion - * - * Returns IIO_VAL_INT on success, a negative error code otherwise. - * - * The function performs a single conversion on a given channel and post - * processes the value accordingly to the channel spec. If a error_mask is given - * the function will check if the mask is set in the returned raw value. If it - * is set the function will perform a self-check. If the device does not report - * a error bit in the channels raw value set error_mask to 0. - */ -int adis_single_conversion(struct iio_dev *indio_dev, -	const struct iio_chan_spec *chan, unsigned int error_mask, int *val) -{ -	struct adis *adis = iio_device_get_drvdata(indio_dev); -	unsigned int uval; -	int ret; - -	mutex_lock(&indio_dev->mlock); - -	ret = adis_read_reg(adis, chan->address, &uval, -			chan->scan_type.storagebits / 8); -	if (ret) -		goto err_unlock; - -	if (uval & error_mask) { -		ret = adis_check_status(adis); -		if (ret) -			goto err_unlock; -	} - -	if (chan->scan_type.sign == 's') -		*val = sign_extend32(uval, chan->scan_type.realbits - 1); -	else -		*val = uval & ((1 << chan->scan_type.realbits) - 1); - -	ret = IIO_VAL_INT; -err_unlock: -	mutex_unlock(&indio_dev->mlock); -	return ret; -} -EXPORT_SYMBOL_GPL(adis_single_conversion); - -/** - * adis_init() - Initialize adis device structure - * @adis:	The adis device - * @indio_dev:	The iio device - * @spi:	The spi device - * @data:	Chip specific data - * - * Returns 0 on success, a negative error code otherwise. - * - * This function must be called, before any other adis helper function may be - * called. - */ -int adis_init(struct adis *adis, struct iio_dev *indio_dev, -	struct spi_device *spi, const struct adis_data *data) -{ -	mutex_init(&adis->txrx_lock); -	adis->spi = spi; -	adis->data = data; -	iio_device_set_drvdata(indio_dev, adis); - -	if (data->has_paging) { -		/* Need to set the page before first read/write */ -		adis->current_page = -1; -	} else { -		/* Page will always be 0 */ -		adis->current_page = 0; -	} - -	return adis_enable_irq(adis, false); -} -EXPORT_SYMBOL_GPL(adis_init); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); -MODULE_DESCRIPTION("Common library code for ADIS16XXX devices");  |