From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Jonathan Cameron To: linux-iio@vger.kernel.org Cc: Michael.Hennerich@analog.com, Robin.Getz@analog.com, manuel.stahl@iis.fraunhofer.de, Jonathan Cameron Subject: [PATCH 5/6] staging:iio:adis16300 merge into adis16350 driver Date: Sat, 11 Sep 2010 15:58:19 +0100 Message-Id: <1284217100-2469-6-git-send-email-jic23@cam.ac.uk> In-Reply-To: <1284217100-2469-1-git-send-email-jic23@cam.ac.uk> References: <1284217100-2469-1-git-send-email-jic23@cam.ac.uk> List-ID: Also fix incorrect axis for adis16300 gyro. It is about the z axis not x. Signed-off-by: Jonathan Cameron --- drivers/staging/iio/imu/Kconfig | 14 +- drivers/staging/iio/imu/Makefile | 4 - drivers/staging/iio/imu/adis16300.h | 184 ------- drivers/staging/iio/imu/adis16300_core.c | 756 --------------------------- drivers/staging/iio/imu/adis16300_ring.c | 220 -------- drivers/staging/iio/imu/adis16300_trigger.c | 125 ----- drivers/staging/iio/imu/adis16350.h | 40 ++ drivers/staging/iio/imu/adis16350_core.c | 190 ++++++- drivers/staging/iio/imu/adis16350_ring.c | 67 ++- 9 files changed, 261 insertions(+), 1339 deletions(-) diff --git a/drivers/staging/iio/imu/Kconfig b/drivers/staging/iio/imu/Kconfig index 11a4984..ca433d8 100644 --- a/drivers/staging/iio/imu/Kconfig +++ b/drivers/staging/iio/imu/Kconfig @@ -3,22 +3,14 @@ # comment "Inertial measurement units" -config ADIS16300 - tristate "Analog Devices ADIS16300 IMU SPI driver" - depends on SPI - select IIO_SW_RING if IIO_RING_BUFFER - select IIO_TRIGGER if IIO_RING_BUFFER - help - Say yes here to build support for Analog Devices adis16300 four degrees - of freedom inertial sensor. - config ADIS16350 - tristate "Analog Devices ADIS16350/54/55/60/62/64/65 IMU SPI driver" + tristate "Analog Devices ADIS16350/00/54/55/60/62/64/65 IMU SPI driver" depends on SPI select IIO_TRIGGER if IIO_RING_BUFFER select IIO_SW_RING if IIO_RING_BUFFER help - Say yes here to build support for Analog Devices adis16350/54/55/60/62/64/65 + Say yes here to build support for Analog Devices adis16300, adis16350, + adis16354, adis16355, adis16360, adis16362 and adis16364, high precision tri-axis inertial sensor. if ADIS16350 diff --git a/drivers/staging/iio/imu/Makefile b/drivers/staging/iio/imu/Makefile index 551a20f..f27f896 100644 --- a/drivers/staging/iio/imu/Makefile +++ b/drivers/staging/iio/imu/Makefile @@ -2,10 +2,6 @@ # Makefile for Inertial Measurement Units # -adis16300-y := adis16300_core.o -adis16300-$(CONFIG_IIO_RING_BUFFER) += adis16300_ring.o adis16300_trigger.o -obj-$(CONFIG_ADIS16300) += adis16300.o - adis16350-y := adis16350_core.o adis16350-$(CONFIG_ADIS16350_EVENT) += adis16350_event.o adis16350-$(CONFIG_IIO_RING_BUFFER) += adis16350_ring.o adis16350_trigger.o diff --git a/drivers/staging/iio/imu/adis16300.h b/drivers/staging/iio/imu/adis16300.h deleted file mode 100644 index 1f25d68..0000000 --- a/drivers/staging/iio/imu/adis16300.h +++ /dev/null @@ -1,184 +0,0 @@ -#ifndef SPI_ADIS16300_H_ -#define SPI_ADIS16300_H_ - -#define ADIS16300_STARTUP_DELAY 220 /* ms */ - -#define ADIS16300_READ_REG(a) a -#define ADIS16300_WRITE_REG(a) ((a) | 0x80) - -#define ADIS16300_FLASH_CNT 0x00 /* Flash memory write count */ -#define ADIS16300_SUPPLY_OUT 0x02 /* Power supply measurement */ -#define ADIS16300_XGYRO_OUT 0x04 /* X-axis gyroscope output */ -#define ADIS16300_XACCL_OUT 0x0A /* X-axis accelerometer output */ -#define ADIS16300_YACCL_OUT 0x0C /* Y-axis accelerometer output */ -#define ADIS16300_ZACCL_OUT 0x0E /* Z-axis accelerometer output */ -#define ADIS16300_TEMP_OUT 0x10 /* Temperature output */ -#define ADIS16300_XINCLI_OUT 0x12 /* X-axis inclinometer output measurement */ -#define ADIS16300_YINCLI_OUT 0x14 /* Y-axis inclinometer output measurement */ -#define ADIS16300_AUX_ADC 0x16 /* Auxiliary ADC measurement */ - -/* Calibration parameters */ -#define ADIS16300_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */ -#define ADIS16300_XACCL_OFF 0x20 /* X-axis acceleration bias offset factor */ -#define ADIS16300_YACCL_OFF 0x22 /* Y-axis acceleration bias offset factor */ -#define ADIS16300_ZACCL_OFF 0x24 /* Z-axis acceleration bias offset factor */ - -#define ADIS16300_GPIO_CTRL 0x32 /* Auxiliary digital input/output control */ -#define ADIS16300_MSC_CTRL 0x34 /* Miscellaneous control */ -#define ADIS16300_SMPL_PRD 0x36 /* Internal sample period (rate) control */ -#define ADIS16300_SENS_AVG 0x38 /* Dynamic range and digital filter control */ -#define ADIS16300_SLP_CNT 0x3A /* Sleep mode control */ -#define ADIS16300_DIAG_STAT 0x3C /* System status */ - -/* Alarm functions */ -#define ADIS16300_GLOB_CMD 0x3E /* System command */ -#define ADIS16300_ALM_MAG1 0x26 /* Alarm 1 amplitude threshold */ -#define ADIS16300_ALM_MAG2 0x28 /* Alarm 2 amplitude threshold */ -#define ADIS16300_ALM_SMPL1 0x2A /* Alarm 1 sample size */ -#define ADIS16300_ALM_SMPL2 0x2C /* Alarm 2 sample size */ -#define ADIS16300_ALM_CTRL 0x2E /* Alarm control */ -#define ADIS16300_AUX_DAC 0x30 /* Auxiliary DAC data */ - -#define ADIS16300_ERROR_ACTIVE (1<<14) -#define ADIS16300_NEW_DATA (1<<15) - -/* MSC_CTRL */ -#define ADIS16300_MSC_CTRL_MEM_TEST (1<<11) -#define ADIS16300_MSC_CTRL_INT_SELF_TEST (1<<10) -#define ADIS16300_MSC_CTRL_NEG_SELF_TEST (1<<9) -#define ADIS16300_MSC_CTRL_POS_SELF_TEST (1<<8) -#define ADIS16300_MSC_CTRL_GYRO_BIAS (1<<7) -#define ADIS16300_MSC_CTRL_ACCL_ALIGN (1<<6) -#define ADIS16300_MSC_CTRL_DATA_RDY_EN (1<<2) -#define ADIS16300_MSC_CTRL_DATA_RDY_POL_HIGH (1<<1) -#define ADIS16300_MSC_CTRL_DATA_RDY_DIO2 (1<<0) - -/* SMPL_PRD */ -#define ADIS16300_SMPL_PRD_TIME_BASE (1<<7) -#define ADIS16300_SMPL_PRD_DIV_MASK 0x7F - -/* DIAG_STAT */ -#define ADIS16300_DIAG_STAT_ZACCL_FAIL (1<<15) -#define ADIS16300_DIAG_STAT_YACCL_FAIL (1<<14) -#define ADIS16300_DIAG_STAT_XACCL_FAIL (1<<13) -#define ADIS16300_DIAG_STAT_XGYRO_FAIL (1<<10) -#define ADIS16300_DIAG_STAT_ALARM2 (1<<9) -#define ADIS16300_DIAG_STAT_ALARM1 (1<<8) -#define ADIS16300_DIAG_STAT_FLASH_CHK (1<<6) -#define ADIS16300_DIAG_STAT_SELF_TEST (1<<5) -#define ADIS16300_DIAG_STAT_OVERFLOW (1<<4) -#define ADIS16300_DIAG_STAT_SPI_FAIL (1<<3) -#define ADIS16300_DIAG_STAT_FLASH_UPT (1<<2) -#define ADIS16300_DIAG_STAT_POWER_HIGH (1<<1) -#define ADIS16300_DIAG_STAT_POWER_LOW (1<<0) - -/* GLOB_CMD */ -#define ADIS16300_GLOB_CMD_SW_RESET (1<<7) -#define ADIS16300_GLOB_CMD_P_AUTO_NULL (1<<4) -#define ADIS16300_GLOB_CMD_FLASH_UPD (1<<3) -#define ADIS16300_GLOB_CMD_DAC_LATCH (1<<2) -#define ADIS16300_GLOB_CMD_FAC_CALIB (1<<1) -#define ADIS16300_GLOB_CMD_AUTO_NULL (1<<0) - -/* SLP_CNT */ -#define ADIS16300_SLP_CNT_POWER_OFF (1<<8) - -#define ADIS16300_MAX_TX 18 -#define ADIS16300_MAX_RX 18 - -#define ADIS16300_SPI_SLOW (u32)(300 * 1000) -#define ADIS16300_SPI_BURST (u32)(1000 * 1000) -#define ADIS16300_SPI_FAST (u32)(2000 * 1000) - -/** - * struct adis16300_state - device instance specific data - * @us: actual spi_device - * @work_trigger_to_ring: bh for triggered event handling - * @inter: used to check if new interrupt has been triggered - * @last_timestamp: passing timestamp from th to bh of interrupt handler - * @indio_dev: industrial I/O device structure - * @trig: data ready trigger registered with iio - * @tx: transmit buffer - * @rx: recieve buffer - * @buf_lock: mutex to protect tx and rx - **/ -struct adis16300_state { - struct spi_device *us; - struct work_struct work_trigger_to_ring; - s64 last_timestamp; - struct iio_dev *indio_dev; - struct iio_trigger *trig; - u8 *tx; - u8 *rx; - struct mutex buf_lock; -}; - -int adis16300_set_irq(struct device *dev, bool enable); - -#ifdef CONFIG_IIO_RING_BUFFER -/* At the moment triggers are only used for ring buffer - * filling. This may change! - */ - -#define ADIS16300_SCAN_SUPPLY 0 -#define ADIS16300_SCAN_GYRO_X 1 -#define ADIS16300_SCAN_ACC_X 2 -#define ADIS16300_SCAN_ACC_Y 3 -#define ADIS16300_SCAN_ACC_Z 4 -#define ADIS16300_SCAN_TEMP 5 -#define ADIS16300_SCAN_ADC_0 6 -#define ADIS16300_SCAN_INCLI_X 7 -#define ADIS16300_SCAN_INCLI_Y 8 - -void adis16300_remove_trigger(struct iio_dev *indio_dev); -int adis16300_probe_trigger(struct iio_dev *indio_dev); - -ssize_t adis16300_read_data_from_ring(struct device *dev, - struct device_attribute *attr, - char *buf); - - -int adis16300_configure_ring(struct iio_dev *indio_dev); -void adis16300_unconfigure_ring(struct iio_dev *indio_dev); - -int adis16300_initialize_ring(struct iio_ring_buffer *ring); -void adis16300_uninitialize_ring(struct iio_ring_buffer *ring); -#else /* CONFIG_IIO_RING_BUFFER */ - -static inline void adis16300_remove_trigger(struct iio_dev *indio_dev) -{ -} - -static inline int adis16300_probe_trigger(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline ssize_t -adis16300_read_data_from_ring(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return 0; -} - -static int adis16300_configure_ring(struct iio_dev *indio_dev) -{ - return 0; -} - -static inline void adis16300_unconfigure_ring(struct iio_dev *indio_dev) -{ -} - -static inline int adis16300_initialize_ring(struct iio_ring_buffer *ring) -{ - return 0; -} - -static inline void adis16300_uninitialize_ring(struct iio_ring_buffer *ring) -{ -} - -#endif /* CONFIG_IIO_RING_BUFFER */ -#endif /* SPI_ADIS16300_H_ */ diff --git a/drivers/staging/iio/imu/adis16300_core.c b/drivers/staging/iio/imu/adis16300_core.c deleted file mode 100644 index 3ed86cc..0000000 --- a/drivers/staging/iio/imu/adis16300_core.c +++ /dev/null @@ -1,756 +0,0 @@ -/* - * ADIS16300 Four Degrees of Freedom Inertial Sensor Driver - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../iio.h" -#include "../sysfs.h" -#include "../ring_generic.h" -#include "../accel/accel.h" -#include "../accel/inclinometer.h" -#include "../gyro/gyro.h" -#include "../adc/adc.h" - -#include "adis16300.h" - -#define DRIVER_NAME "adis16300" - -static int adis16300_check_status(struct device *dev); - -/** - * adis16300_spi_write_reg_8() - write single byte to a register - * @dev: device associated with child of actual device (iio_dev or iio_trig) - * @reg_address: the address of the register to be written - * @val: the value to write - **/ -static int adis16300_spi_write_reg_8(struct device *dev, - u8 reg_address, - u8 val) -{ - int ret; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16300_state *st = iio_dev_get_devdata(indio_dev); - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16300_WRITE_REG(reg_address); - st->tx[1] = val; - - ret = spi_write(st->us, st->tx, 2); - mutex_unlock(&st->buf_lock); - - return ret; -} - -/** - * adis16300_spi_write_reg_16() - write 2 bytes to a pair of registers - * @dev: device associated with child of actual device (iio_dev or iio_trig) - * @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 adis16300_spi_write_reg_16(struct device *dev, - u8 lower_reg_address, - u16 value) -{ - int ret; - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16300_state *st = iio_dev_get_devdata(indio_dev); - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .delay_usecs = 75, - }, { - .tx_buf = st->tx + 2, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .delay_usecs = 75, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16300_WRITE_REG(lower_reg_address); - st->tx[1] = value & 0xFF; - st->tx[2] = ADIS16300_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; -} - -/** - * adis16300_spi_read_reg_16() - read 2 bytes from a 16-bit register - * @dev: device associated with child of actual device (iio_dev or iio_trig) - * @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 adis16300_spi_read_reg_16(struct device *dev, - u8 lower_reg_address, - u16 *val) -{ - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16300_state *st = iio_dev_get_devdata(indio_dev); - int ret; - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .delay_usecs = 75, - }, { - .rx_buf = st->rx, - .bits_per_word = 8, - .len = 2, - .cs_change = 1, - .delay_usecs = 75, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16300_READ_REG(lower_reg_address); - st->tx[1] = 0; - st->tx[2] = 0; - st->tx[3] = 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 adis16300_spi_read_signed(struct device *dev, - struct device_attribute *attr, - char *buf, - unsigned bits) -{ - int ret; - s16 val = 0; - unsigned shift = 16 - bits; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = adis16300_spi_read_reg_16(dev, this_attr->address, (u16 *)&val); - if (ret) - return ret; - - if (val & ADIS16300_ERROR_ACTIVE) - adis16300_check_status(dev); - val = ((s16)(val << shift) >> shift); - return sprintf(buf, "%d\n", val); -} - -static ssize_t adis16300_read_12bit_unsigned(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u16 val = 0; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = adis16300_spi_read_reg_16(dev, this_attr->address, &val); - if (ret) - return ret; - - if (val & ADIS16300_ERROR_ACTIVE) - adis16300_check_status(dev); - - return sprintf(buf, "%u\n", val & 0x0FFF); -} - -static ssize_t adis16300_read_14bit_unsigned(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - u16 val = 0; - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - - ret = adis16300_spi_read_reg_16(dev, this_attr->address, &val); - if (ret) - return ret; - - if (val & ADIS16300_ERROR_ACTIVE) - adis16300_check_status(dev); - - return sprintf(buf, "%u\n", val & 0x3FFF); -} - -static ssize_t adis16300_read_14bit_signed(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - ssize_t ret; - - /* Take the iio_dev status lock */ - mutex_lock(&indio_dev->mlock); - ret = adis16300_spi_read_signed(dev, attr, buf, 14); - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static ssize_t adis16300_read_12bit_signed(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - ssize_t ret; - - /* Take the iio_dev status lock */ - mutex_lock(&indio_dev->mlock); - ret = adis16300_spi_read_signed(dev, attr, buf, 12); - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static ssize_t adis16300_read_13bit_signed(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - ssize_t ret; - - /* Take the iio_dev status lock */ - mutex_lock(&indio_dev->mlock); - ret = adis16300_spi_read_signed(dev, attr, buf, 13); - mutex_unlock(&indio_dev->mlock); - - return ret; -} - -static ssize_t adis16300_write_16bit(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); - int ret; - long val; - - ret = strict_strtol(buf, 10, &val); - if (ret) - goto error_ret; - ret = adis16300_spi_write_reg_16(dev, this_attr->address, val); - -error_ret: - return ret ? ret : len; -} - -static ssize_t adis16300_read_frequency(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret, len = 0; - u16 t; - int sps; - ret = adis16300_spi_read_reg_16(dev, - ADIS16300_SMPL_PRD, - &t); - if (ret) - return ret; - sps = (t & ADIS16300_SMPL_PRD_TIME_BASE) ? 53 : 1638; - sps /= (t & ADIS16300_SMPL_PRD_DIV_MASK) + 1; - len = sprintf(buf, "%d SPS\n", sps); - return len; -} - -static ssize_t adis16300_write_frequency(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t len) -{ - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16300_state *st = iio_dev_get_devdata(indio_dev); - long val; - int ret; - u8 t; - - ret = strict_strtol(buf, 10, &val); - if (ret) - return ret; - - mutex_lock(&indio_dev->mlock); - - t = (1638 / val); - if (t > 0) - t--; - t &= ADIS16300_SMPL_PRD_DIV_MASK; - if ((t & ADIS16300_SMPL_PRD_DIV_MASK) >= 0x0A) - st->us->max_speed_hz = ADIS16300_SPI_SLOW; - else - st->us->max_speed_hz = ADIS16300_SPI_FAST; - - ret = adis16300_spi_write_reg_8(dev, - ADIS16300_SMPL_PRD, - t); - - mutex_unlock(&indio_dev->mlock); - - return ret ? ret : len; -} - -static int adis16300_reset(struct device *dev) -{ - int ret; - ret = adis16300_spi_write_reg_8(dev, - ADIS16300_GLOB_CMD, - ADIS16300_GLOB_CMD_SW_RESET); - if (ret) - dev_err(dev, "problem resetting device"); - - return ret; -} - -static ssize_t adis16300_write_reset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len) -{ - if (len < 1) - return -1; - switch (buf[0]) { - case '1': - case 'y': - case 'Y': - return adis16300_reset(dev); - } - return -1; -} - -int adis16300_set_irq(struct device *dev, bool enable) -{ - int ret; - u16 msc; - ret = adis16300_spi_read_reg_16(dev, ADIS16300_MSC_CTRL, &msc); - if (ret) - goto error_ret; - - msc |= ADIS16300_MSC_CTRL_DATA_RDY_POL_HIGH; - msc &= ~ADIS16300_MSC_CTRL_DATA_RDY_DIO2; - if (enable) - msc |= ADIS16300_MSC_CTRL_DATA_RDY_EN; - else - msc &= ~ADIS16300_MSC_CTRL_DATA_RDY_EN; - - ret = adis16300_spi_write_reg_16(dev, ADIS16300_MSC_CTRL, msc); - if (ret) - goto error_ret; - -error_ret: - return ret; -} - -/* Power down the device */ -static int adis16300_stop_device(struct device *dev) -{ - int ret; - u16 val = ADIS16300_SLP_CNT_POWER_OFF; - - ret = adis16300_spi_write_reg_16(dev, ADIS16300_SLP_CNT, val); - if (ret) - dev_err(dev, "problem with turning device off: SLP_CNT"); - - return ret; -} - -static int adis16300_self_test(struct device *dev) -{ - int ret; - ret = adis16300_spi_write_reg_16(dev, - ADIS16300_MSC_CTRL, - ADIS16300_MSC_CTRL_MEM_TEST); - if (ret) { - dev_err(dev, "problem starting self test"); - goto err_ret; - } - - adis16300_check_status(dev); - -err_ret: - return ret; -} - -static int adis16300_check_status(struct device *dev) -{ - u16 status; - int ret; - - ret = adis16300_spi_read_reg_16(dev, ADIS16300_DIAG_STAT, &status); - - if (ret < 0) { - dev_err(dev, "Reading status failed\n"); - goto error_ret; - } - ret = status; - if (status & ADIS16300_DIAG_STAT_ZACCL_FAIL) - dev_err(dev, "Z-axis accelerometer self-test failure\n"); - if (status & ADIS16300_DIAG_STAT_YACCL_FAIL) - dev_err(dev, "Y-axis accelerometer self-test failure\n"); - if (status & ADIS16300_DIAG_STAT_XACCL_FAIL) - dev_err(dev, "X-axis accelerometer self-test failure\n"); - if (status & ADIS16300_DIAG_STAT_XGYRO_FAIL) - dev_err(dev, "X-axis gyroscope self-test failure\n"); - if (status & ADIS16300_DIAG_STAT_ALARM2) - dev_err(dev, "Alarm 2 active\n"); - if (status & ADIS16300_DIAG_STAT_ALARM1) - dev_err(dev, "Alarm 1 active\n"); - if (status & ADIS16300_DIAG_STAT_FLASH_CHK) - dev_err(dev, "Flash checksum error\n"); - if (status & ADIS16300_DIAG_STAT_SELF_TEST) - dev_err(dev, "Self test error\n"); - if (status & ADIS16300_DIAG_STAT_OVERFLOW) - dev_err(dev, "Sensor overrange\n"); - if (status & ADIS16300_DIAG_STAT_SPI_FAIL) - dev_err(dev, "SPI failure\n"); - if (status & ADIS16300_DIAG_STAT_FLASH_UPT) - dev_err(dev, "Flash update failed\n"); - if (status & ADIS16300_DIAG_STAT_POWER_HIGH) - dev_err(dev, "Power supply above 5.25V\n"); - if (status & ADIS16300_DIAG_STAT_POWER_LOW) - dev_err(dev, "Power supply below 4.75V\n"); - -error_ret: - return ret; -} - -static int adis16300_initial_setup(struct adis16300_state *st) -{ - int ret; - u16 smp_prd; - struct device *dev = &st->indio_dev->dev; - - /* use low spi speed for init */ - st->us->max_speed_hz = ADIS16300_SPI_SLOW; - st->us->mode = SPI_MODE_3; - spi_setup(st->us); - - /* Disable IRQ */ - ret = adis16300_set_irq(dev, false); - if (ret) { - dev_err(dev, "disable irq failed"); - goto err_ret; - } - - /* Do self test */ - ret = adis16300_self_test(dev); - if (ret) { - dev_err(dev, "self test failure"); - goto err_ret; - } - - /* Read status register to check the result */ - ret = adis16300_check_status(dev); - if (ret) { - adis16300_reset(dev); - dev_err(dev, "device not playing ball -> reset"); - msleep(ADIS16300_STARTUP_DELAY); - ret = adis16300_check_status(dev); - if (ret) { - dev_err(dev, "giving up"); - goto err_ret; - } - } - - printk(KERN_INFO DRIVER_NAME ": at CS%d (irq %d)\n", - st->us->chip_select, st->us->irq); - - /* use high spi speed if possible */ - ret = adis16300_spi_read_reg_16(dev, ADIS16300_SMPL_PRD, &smp_prd); - if (!ret && (smp_prd & ADIS16300_SMPL_PRD_DIV_MASK) < 0x0A) { - st->us->max_speed_hz = ADIS16300_SPI_SLOW; - spi_setup(st->us); - } - -err_ret: - return ret; -} - -static IIO_DEV_ATTR_GYRO_X_CALIBBIAS(S_IWUSR | S_IRUGO, - adis16300_read_12bit_signed, - adis16300_write_16bit, - ADIS16300_XGYRO_OFF); - -static IIO_DEV_ATTR_ACCEL_X_CALIBBIAS(S_IWUSR | S_IRUGO, - adis16300_read_12bit_signed, - adis16300_write_16bit, - ADIS16300_XACCL_OFF); - -static IIO_DEV_ATTR_ACCEL_Y_CALIBBIAS(S_IWUSR | S_IRUGO, - adis16300_read_12bit_signed, - adis16300_write_16bit, - ADIS16300_YACCL_OFF); - -static IIO_DEV_ATTR_ACCEL_Z_CALIBBIAS(S_IWUSR | S_IRUGO, - adis16300_read_12bit_signed, - adis16300_write_16bit, - ADIS16300_ZACCL_OFF); - -static IIO_DEV_ATTR_IN_NAMED_RAW(supply, adis16300_read_14bit_unsigned, - ADIS16300_SUPPLY_OUT); -static IIO_CONST_ATTR_IN_NAMED_SCALE(supply, "0.00242"); - -static IIO_DEV_ATTR_GYRO_X(adis16300_read_14bit_signed, - ADIS16300_XGYRO_OUT); -static IIO_CONST_ATTR_GYRO_SCALE("0.000872664"); - -static IIO_DEV_ATTR_ACCEL_X(adis16300_read_14bit_signed, - ADIS16300_XACCL_OUT); -static IIO_DEV_ATTR_ACCEL_Y(adis16300_read_14bit_signed, - ADIS16300_YACCL_OUT); -static IIO_DEV_ATTR_ACCEL_Z(adis16300_read_14bit_signed, - ADIS16300_ZACCL_OUT); -static IIO_CONST_ATTR_ACCEL_SCALE("0.00588399"); - -static IIO_DEV_ATTR_INCLI_X(adis16300_read_13bit_signed, - ADIS16300_XINCLI_OUT); -static IIO_DEV_ATTR_INCLI_Y(adis16300_read_13bit_signed, - ADIS16300_YINCLI_OUT); -static IIO_CONST_ATTR_INCLI_SCALE("0.00076794487"); - -static IIO_DEV_ATTR_TEMP_RAW(adis16300_read_12bit_unsigned); -static IIO_CONST_ATTR_TEMP_OFFSET("198.16"); -static IIO_CONST_ATTR_TEMP_SCALE("0.14"); - -static IIO_DEV_ATTR_IN_RAW(0, adis16300_read_12bit_unsigned, - ADIS16300_AUX_ADC); -static IIO_CONST_ATTR(in0_scale, "0.000806"); - -static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, - adis16300_read_frequency, - adis16300_write_frequency); - -static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16300_write_reset, 0); - -static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("409 546 819 1638"); - -static IIO_CONST_ATTR_NAME("adis16300"); - -static struct attribute *adis16300_event_attributes[] = { - NULL -}; - -static struct attribute_group adis16300_event_attribute_group = { - .attrs = adis16300_event_attributes, -}; - -static struct attribute *adis16300_attributes[] = { - &iio_dev_attr_gyro_x_calibbias.dev_attr.attr, - &iio_dev_attr_accel_x_calibbias.dev_attr.attr, - &iio_dev_attr_accel_y_calibbias.dev_attr.attr, - &iio_dev_attr_accel_z_calibbias.dev_attr.attr, - &iio_dev_attr_in_supply_raw.dev_attr.attr, - &iio_const_attr_in_supply_scale.dev_attr.attr, - &iio_dev_attr_gyro_x_raw.dev_attr.attr, - &iio_const_attr_gyro_scale.dev_attr.attr, - &iio_dev_attr_accel_x_raw.dev_attr.attr, - &iio_dev_attr_accel_y_raw.dev_attr.attr, - &iio_dev_attr_accel_z_raw.dev_attr.attr, - &iio_const_attr_accel_scale.dev_attr.attr, - &iio_dev_attr_incli_x_raw.dev_attr.attr, - &iio_dev_attr_incli_y_raw.dev_attr.attr, - &iio_const_attr_incli_scale.dev_attr.attr, - &iio_dev_attr_temp_raw.dev_attr.attr, - &iio_const_attr_temp_offset.dev_attr.attr, - &iio_const_attr_temp_scale.dev_attr.attr, - &iio_dev_attr_in0_raw.dev_attr.attr, - &iio_const_attr_in0_scale.dev_attr.attr, - &iio_dev_attr_sampling_frequency.dev_attr.attr, - &iio_const_attr_sampling_frequency_available.dev_attr.attr, - &iio_dev_attr_reset.dev_attr.attr, - &iio_const_attr_name.dev_attr.attr, - NULL -}; - -static const struct attribute_group adis16300_attribute_group = { - .attrs = adis16300_attributes, -}; - -static int __devinit adis16300_probe(struct spi_device *spi) -{ - int ret, regdone = 0; - struct adis16300_state *st = kzalloc(sizeof *st, GFP_KERNEL); - if (!st) { - ret = -ENOMEM; - goto error_ret; - } - /* this is only used for removal purposes */ - spi_set_drvdata(spi, st); - - /* Allocate the comms buffers */ - st->rx = kzalloc(sizeof(*st->rx)*ADIS16300_MAX_RX, GFP_KERNEL); - if (st->rx == NULL) { - ret = -ENOMEM; - goto error_free_st; - } - st->tx = kzalloc(sizeof(*st->tx)*ADIS16300_MAX_TX, GFP_KERNEL); - if (st->tx == NULL) { - ret = -ENOMEM; - goto error_free_rx; - } - st->us = spi; - mutex_init(&st->buf_lock); - /* setup the industrialio driver allocated elements */ - st->indio_dev = iio_allocate_device(); - if (st->indio_dev == NULL) { - ret = -ENOMEM; - goto error_free_tx; - } - - st->indio_dev->dev.parent = &spi->dev; - st->indio_dev->num_interrupt_lines = 1; - st->indio_dev->event_attrs = &adis16300_event_attribute_group; - st->indio_dev->attrs = &adis16300_attribute_group; - st->indio_dev->dev_data = (void *)(st); - st->indio_dev->driver_module = THIS_MODULE; - st->indio_dev->modes = INDIO_DIRECT_MODE; - - ret = adis16300_configure_ring(st->indio_dev); - if (ret) - goto error_free_dev; - - ret = iio_device_register(st->indio_dev); - if (ret) - goto error_unreg_ring_funcs; - regdone = 1; - - ret = iio_ring_buffer_register(st->indio_dev->ring, 0); - if (ret) { - printk(KERN_ERR "failed to initialize the ring\n"); - goto error_unreg_ring_funcs; - } - - if (spi->irq) { - ret = iio_register_interrupt_line(spi->irq, - st->indio_dev, - 0, - IRQF_TRIGGER_RISING, - "adis16300"); - if (ret) - goto error_uninitialize_ring; - - ret = adis16300_probe_trigger(st->indio_dev); - if (ret) - goto error_unregister_line; - } - - /* Get the device into a sane initial state */ - ret = adis16300_initial_setup(st); - if (ret) - goto error_remove_trigger; - return 0; - -error_remove_trigger: - adis16300_remove_trigger(st->indio_dev); -error_unregister_line: - if (spi->irq) - iio_unregister_interrupt_line(st->indio_dev, 0); -error_uninitialize_ring: - iio_ring_buffer_unregister(st->indio_dev->ring); -error_unreg_ring_funcs: - adis16300_unconfigure_ring(st->indio_dev); -error_free_dev: - if (regdone) - iio_device_unregister(st->indio_dev); - else - iio_free_device(st->indio_dev); -error_free_tx: - kfree(st->tx); -error_free_rx: - kfree(st->rx); -error_free_st: - kfree(st); -error_ret: - return ret; -} - -static int adis16300_remove(struct spi_device *spi) -{ - int ret; - struct adis16300_state *st = spi_get_drvdata(spi); - struct iio_dev *indio_dev = st->indio_dev; - - ret = adis16300_stop_device(&(indio_dev->dev)); - if (ret) - goto err_ret; - - flush_scheduled_work(); - - adis16300_remove_trigger(indio_dev); - if (spi->irq) - iio_unregister_interrupt_line(indio_dev, 0); - - iio_ring_buffer_unregister(indio_dev->ring); - iio_device_unregister(indio_dev); - adis16300_unconfigure_ring(indio_dev); - kfree(st->tx); - kfree(st->rx); - kfree(st); - - return 0; - -err_ret: - return ret; -} - -static struct spi_driver adis16300_driver = { - .driver = { - .name = "adis16300", - .owner = THIS_MODULE, - }, - .probe = adis16300_probe, - .remove = __devexit_p(adis16300_remove), -}; - -static __init int adis16300_init(void) -{ - return spi_register_driver(&adis16300_driver); -} -module_init(adis16300_init); - -static __exit void adis16300_exit(void) -{ - spi_unregister_driver(&adis16300_driver); -} -module_exit(adis16300_exit); - -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_DESCRIPTION("Analog Devices ADIS16300 IMU SPI driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/staging/iio/imu/adis16300_ring.c b/drivers/staging/iio/imu/adis16300_ring.c deleted file mode 100644 index 0e09051..0000000 --- a/drivers/staging/iio/imu/adis16300_ring.c +++ /dev/null @@ -1,220 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../iio.h" -#include "../sysfs.h" -#include "../ring_sw.h" -#include "../accel/accel.h" -#include "../trigger.h" -#include "adis16300.h" - -static IIO_SCAN_EL_C(in_supply, ADIS16300_SCAN_SUPPLY, IIO_UNSIGNED(14), - ADIS16300_SUPPLY_OUT, NULL); - -static IIO_SCAN_EL_C(gyro_x, ADIS16300_SCAN_GYRO_X, IIO_SIGNED(14), - ADIS16300_XGYRO_OUT, NULL); - -static IIO_SCAN_EL_C(accel_x, ADIS16300_SCAN_ACC_X, IIO_SIGNED(14), - ADIS16300_XACCL_OUT, NULL); -static IIO_SCAN_EL_C(accel_y, ADIS16300_SCAN_ACC_Y, IIO_SIGNED(14), - ADIS16300_YACCL_OUT, NULL); -static IIO_SCAN_EL_C(accel_z, ADIS16300_SCAN_ACC_Z, IIO_SIGNED(14), - ADIS16300_ZACCL_OUT, NULL); - -static IIO_SCAN_EL_C(temp, ADIS16300_SCAN_TEMP, IIO_UNSIGNED(12), - ADIS16300_TEMP_OUT, NULL); -static IIO_SCAN_EL_C(in0, ADIS16300_SCAN_ADC_0, IIO_UNSIGNED(12), - ADIS16300_AUX_ADC, NULL); - -static IIO_SCAN_EL_C(incli_x, ADIS16300_SCAN_INCLI_X, IIO_SIGNED(12), - ADIS16300_XINCLI_OUT, NULL); -static IIO_SCAN_EL_C(incli_y, ADIS16300_SCAN_INCLI_Y, IIO_SIGNED(12), - ADIS16300_YINCLI_OUT, NULL); - -static IIO_SCAN_EL_TIMESTAMP(9); - -static struct attribute *adis16300_scan_el_attrs[] = { - &iio_scan_el_in_supply.dev_attr.attr, - &iio_scan_el_gyro_x.dev_attr.attr, - &iio_scan_el_temp.dev_attr.attr, - &iio_scan_el_accel_x.dev_attr.attr, - &iio_scan_el_accel_y.dev_attr.attr, - &iio_scan_el_accel_z.dev_attr.attr, - &iio_scan_el_incli_x.dev_attr.attr, - &iio_scan_el_incli_y.dev_attr.attr, - &iio_scan_el_in0.dev_attr.attr, - &iio_scan_el_timestamp.dev_attr.attr, - NULL, -}; - -static struct attribute_group adis16300_scan_el_group = { - .attrs = adis16300_scan_el_attrs, - .name = "scan_elements", -}; - -/** - * adis16300_poll_func_th() top half interrupt handler called by trigger - * @private_data: iio_dev - **/ -static void adis16300_poll_func_th(struct iio_dev *indio_dev, s64 time) -{ - struct adis16300_state *st = iio_dev_get_devdata(indio_dev); - st->last_timestamp = time; - schedule_work(&st->work_trigger_to_ring); - /* Indicate that this interrupt is being handled */ - - /* Technically this is trigger related, but without this - * handler running there is currently no way for the interrupt - * to clear. - */ -} - -/** - * adis16300_spi_read_burst() - read all data registers - * @dev: device associated with child of actual device (iio_dev or iio_trig) - * @rx: somewhere to pass back the value read (min size is 24 bytes) - **/ -static int adis16300_spi_read_burst(struct device *dev, u8 *rx) -{ - struct spi_message msg; - struct iio_dev *indio_dev = dev_get_drvdata(dev); - struct adis16300_state *st = iio_dev_get_devdata(indio_dev); - u32 old_speed_hz = st->us->max_speed_hz; - int ret; - - struct spi_transfer xfers[] = { - { - .tx_buf = st->tx, - .bits_per_word = 8, - .len = 2, - .cs_change = 0, - }, { - .rx_buf = rx, - .bits_per_word = 8, - .len = 18, - .cs_change = 0, - }, - }; - - mutex_lock(&st->buf_lock); - st->tx[0] = ADIS16300_READ_REG(ADIS16300_GLOB_CMD); - st->tx[1] = 0; - - spi_message_init(&msg); - spi_message_add_tail(&xfers[0], &msg); - spi_message_add_tail(&xfers[1], &msg); - - st->us->max_speed_hz = ADIS16300_SPI_BURST; - spi_setup(st->us); - - ret = spi_sync(st->us, &msg); - if (ret) - dev_err(&st->us->dev, "problem when burst reading"); - - st->us->max_speed_hz = old_speed_hz; - spi_setup(st->us); - mutex_unlock(&st->buf_lock); - return ret; -} - -/* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device - * specific to be rolled into the core. - */ -static void adis16300_trigger_bh_to_ring(struct work_struct *work_s) -{ - struct adis16300_state *st - = container_of(work_s, struct adis16300_state, - work_trigger_to_ring); - struct iio_ring_buffer *ring = st->indio_dev->ring; - - int i = 0; - s16 *data; - size_t datasize = ring->access.get_bytes_per_datum(ring); - - data = kmalloc(datasize , GFP_KERNEL); - if (data == NULL) { - dev_err(&st->us->dev, "memory alloc failed in ring bh"); - return; - } - - if (ring->scan_count) - if (adis16300_spi_read_burst(&st->indio_dev->dev, st->rx) >= 0) - for (; i < ring->scan_count; i++) - data[i] = be16_to_cpup( - (__be16 *)&(st->rx[i*2])); - - /* Guaranteed to be aligned with 8 byte boundary */ - if (ring->scan_timestamp) - *((s64 *)(data + ((i + 3)/4)*4)) = st->last_timestamp; - - ring->access.store_to(ring, - (u8 *)data, - st->last_timestamp); - - iio_trigger_notify_done(st->indio_dev->trig); - kfree(data); - - return; -} - -void adis16300_unconfigure_ring(struct iio_dev *indio_dev) -{ - kfree(indio_dev->pollfunc); - iio_sw_rb_free(indio_dev->ring); -} - -int adis16300_configure_ring(struct iio_dev *indio_dev) -{ - int ret = 0; - struct adis16300_state *st = indio_dev->dev_data; - struct iio_ring_buffer *ring; - INIT_WORK(&st->work_trigger_to_ring, adis16300_trigger_bh_to_ring); - - ring = iio_sw_rb_allocate(indio_dev); - if (!ring) { - ret = -ENOMEM; - return ret; - } - indio_dev->ring = ring; - /* Effectively select the ring buffer implementation */ - iio_ring_sw_register_funcs(&ring->access); - ring->bpe = 2; - ring->scan_el_attrs = &adis16300_scan_el_group; - ring->scan_timestamp = true; - ring->preenable = &iio_sw_ring_preenable; - ring->postenable = &iio_triggered_ring_postenable; - ring->predisable = &iio_triggered_ring_predisable; - ring->owner = THIS_MODULE; - - /* Set default scan mode */ - iio_scan_mask_set(ring, iio_scan_el_in_supply.number); - iio_scan_mask_set(ring, iio_scan_el_gyro_x.number); - iio_scan_mask_set(ring, iio_scan_el_accel_x.number); - iio_scan_mask_set(ring, iio_scan_el_accel_y.number); - iio_scan_mask_set(ring, iio_scan_el_accel_z.number); - iio_scan_mask_set(ring, iio_scan_el_temp.number); - iio_scan_mask_set(ring, iio_scan_el_in0.number); - iio_scan_mask_set(ring, iio_scan_el_incli_x.number); - iio_scan_mask_set(ring, iio_scan_el_incli_y.number); - - ret = iio_alloc_pollfunc(indio_dev, NULL, &adis16300_poll_func_th); - if (ret) - goto error_iio_sw_rb_free; - - indio_dev->modes |= INDIO_RING_TRIGGERED; - return 0; - -error_iio_sw_rb_free: - iio_sw_rb_free(indio_dev->ring); - return ret; -} - diff --git a/drivers/staging/iio/imu/adis16300_trigger.c b/drivers/staging/iio/imu/adis16300_trigger.c deleted file mode 100644 index d6677b6..0000000 --- a/drivers/staging/iio/imu/adis16300_trigger.c +++ /dev/null @@ -1,125 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../iio.h" -#include "../sysfs.h" -#include "../trigger.h" -#include "adis16300.h" - -/** - * adis16300_data_rdy_trig_poll() the event handler for the data rdy trig - **/ -static int adis16300_data_rdy_trig_poll(struct iio_dev *dev_info, - int index, - s64 timestamp, - int no_test) -{ - struct adis16300_state *st = iio_dev_get_devdata(dev_info); - struct iio_trigger *trig = st->trig; - - iio_trigger_poll(trig, timestamp); - - return IRQ_HANDLED; -} - -IIO_EVENT_SH(data_rdy_trig, &adis16300_data_rdy_trig_poll); - -static IIO_TRIGGER_NAME_ATTR; - -static struct attribute *adis16300_trigger_attrs[] = { - &dev_attr_name.attr, - NULL, -}; - -static const struct attribute_group adis16300_trigger_attr_group = { - .attrs = adis16300_trigger_attrs, -}; - -/** - * adis16300_data_rdy_trigger_set_state() set datardy interrupt state - **/ -static int adis16300_data_rdy_trigger_set_state(struct iio_trigger *trig, - bool state) -{ - struct adis16300_state *st = trig->private_data; - struct iio_dev *indio_dev = st->indio_dev; - int ret = 0; - - dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); - ret = adis16300_set_irq(&st->indio_dev->dev, state); - if (state == false) { - iio_remove_event_from_list(&iio_event_data_rdy_trig, - &indio_dev->interrupts[0] - ->ev_list); - /* possible quirk with handler currently worked around - by ensuring the work queue is empty */ - flush_scheduled_work(); - } else { - iio_add_event_to_list(&iio_event_data_rdy_trig, - &indio_dev->interrupts[0]->ev_list); - } - return ret; -} - -/** - * adis16300_trig_try_reen() try renabling irq for data rdy trigger - * @trig: the datardy trigger - **/ -static int adis16300_trig_try_reen(struct iio_trigger *trig) -{ - struct adis16300_state *st = trig->private_data; - enable_irq(st->us->irq); - /* irq reenabled so success! */ - return 0; -} - -int adis16300_probe_trigger(struct iio_dev *indio_dev) -{ - int ret; - struct adis16300_state *st = indio_dev->dev_data; - - st->trig = iio_allocate_trigger(); - st->trig->name = kasprintf(GFP_KERNEL, - "adis16300-dev%d", - indio_dev->id); - if (!st->trig->name) { - ret = -ENOMEM; - goto error_free_trig; - } - st->trig->dev.parent = &st->us->dev; - st->trig->owner = THIS_MODULE; - st->trig->private_data = st; - st->trig->set_trigger_state = &adis16300_data_rdy_trigger_set_state; - st->trig->try_reenable = &adis16300_trig_try_reen; - st->trig->control_attrs = &adis16300_trigger_attr_group; - ret = iio_trigger_register(st->trig); - - /* select default trigger */ - indio_dev->trig = st->trig; - if (ret) - goto error_free_trig_name; - - return 0; - -error_free_trig_name: - kfree(st->trig->name); -error_free_trig: - iio_free_trigger(st->trig); - - return ret; -} - -void adis16300_remove_trigger(struct iio_dev *indio_dev) -{ - struct adis16300_state *state = indio_dev->dev_data; - - iio_trigger_unregister(state->trig); - kfree(state->trig->name); - iio_free_trigger(state->trig); -} diff --git a/drivers/staging/iio/imu/adis16350.h b/drivers/staging/iio/imu/adis16350.h index 2d8080e..b7c9052 100644 --- a/drivers/staging/iio/imu/adis16350.h +++ b/drivers/staging/iio/imu/adis16350.h @@ -19,6 +19,10 @@ #define ADIS16350_ZTEMP_OUT 0x14 /* Z-axis gyroscope temperature measurement */ #define ADIS16350_AUX_ADC 0x16 /* Auxiliary ADC measurement */ +#define ADIS16300_TEMP_OUT 0x10 /* Temperature output */ +#define ADIS16300_XINCLI_OUT 0x12 /* X-axis inclinometer output measurement */ +#define ADIS16300_YINCLI_OUT 0x14 /* Y-axis inclinometer output measurement */ + /* Calibration parameters */ #define ADIS16350_XGYRO_OFF 0x1A /* X-axis gyroscope bias offset factor */ #define ADIS16350_YGYRO_OFF 0x1C /* Y-axis gyroscope bias offset factor */ @@ -96,6 +100,34 @@ #define ADIS16350_SPI_BURST (u32)(1000 * 1000) #define ADIS16350_SPI_FAST (u32)(2000 * 1000) +enum adis16350_chip_variants { + adis16300, + adis16350, + adis16360, +}; + +extern struct attribute_group adis16300_scan_el_group; +extern struct attribute_group adis16350_scan_el_group; + +/** + * struct adis16350_chip_info - chip type specific parameters + * @attribute_group: sysfs attributes for this variant + * @burst_available: does the device support burst reading + * @gyro_scale: the scale factor to convert to radians / sec + * @accel_scale: the scale factor to convert to m/s^2 + * @burst_length: the number of bytes needed for a burst read + * @all_mask: a bit mask specifying which scan elements exist + **/ +struct adis16350_chip_info { + const struct attribute_group *attribute_group; + struct attribute_group *scan_el_group; + unsigned burst_available:1; + const char *gyro_scale; + const char *accel_scale; + u8 burst_length; + ulong all_mask; +}; + /** * struct adis16350_state - device instance specific data * @us: actual spi_device @@ -103,6 +135,7 @@ * @inter: used to check if new interrupt has been triggered * @last_timestamp: passing timestamp from th to bh of interrupt handler * @indio_dev: industrial I/O device structure + * @variant: structure providing chip variant specific data * @trig: data ready trigger registered with iio * @tx: transmit buffer * @rx: recieve buffer @@ -121,6 +154,7 @@ struct adis16350_state { struct work_struct work_trigger_to_ring; s64 last_timestamp; struct iio_dev *indio_dev; + struct adis16350_chip_info *variant; struct iio_trigger *trig; u8 *tx; u8 *rx; @@ -164,6 +198,9 @@ static inline void adis16350_unconfigure_event_line(struct adis16350_state *st) } #endif +/** + * All we guarantee with these is that they are monotonic + **/ #define ADIS16350_SCAN_IN_SUPPLY 0 #define ADIS16350_SCAN_GYRO_X 1 #define ADIS16350_SCAN_GYRO_Y 2 @@ -171,9 +208,12 @@ static inline void adis16350_unconfigure_event_line(struct adis16350_state *st) #define ADIS16350_SCAN_ACCEL_X 4 #define ADIS16350_SCAN_ACCEL_Y 5 #define ADIS16350_SCAN_ACCEL_Z 6 +#define ADIS16300_SCAN_TEMP 7 #define ADIS16350_SCAN_TEMP_X 7 #define ADIS16350_SCAN_TEMP_Y 8 +#define ADIS16300_SCAN_INCLI_X 8 #define ADIS16350_SCAN_TEMP_Z 9 +#define ADIS16300_SCAN_INCLI_Y 9 #define ADIS16350_SCAN_IN0 10 #ifdef CONFIG_IIO_RING_BUFFER diff --git a/drivers/staging/iio/imu/adis16350_core.c b/drivers/staging/iio/imu/adis16350_core.c index dc83489..f154886 100644 --- a/drivers/staging/iio/imu/adis16350_core.c +++ b/drivers/staging/iio/imu/adis16350_core.c @@ -22,6 +22,7 @@ #include "../sysfs.h" #include "../ring_generic.h" #include "../accel/accel.h" +#include "../accel/inclinometer.h" #include "../adc/adc.h" #include "../gyro/gyro.h" @@ -224,6 +225,21 @@ static ssize_t adis16350_read_12bit_signed(struct device *dev, return ret; } +static ssize_t adis16350_read_13bit_signed(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *indio_dev = dev_get_drvdata(dev); + ssize_t ret; + + /* Take the iio_dev status lock */ + mutex_lock(&indio_dev->mlock); + ret = adis16350_spi_read_signed(dev, attr, buf, 13); + mutex_unlock(&indio_dev->mlock); + + return ret; +} + static ssize_t adis16350_write_16bit(struct device *dev, struct device_attribute *attr, const char *buf, @@ -515,7 +531,16 @@ static IIO_DEV_ATTR_GYRO_Y(adis16350_read_14bit_signed, ADIS16350_YGYRO_OUT); static IIO_DEV_ATTR_GYRO_Z(adis16350_read_14bit_signed, ADIS16350_ZGYRO_OUT); -static IIO_CONST_ATTR_GYRO_SCALE("0.00127862821"); + +static ssize_t adis16350_show_gyro_scale(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adis16350_state *st = iio_dev_get_devdata(dev_info); + return sprintf(buf, "%s\n", st->variant->gyro_scale); +} +static IIO_DEV_ATTR_GYRO_SCALE(S_IRUGO, adis16350_show_gyro_scale, NULL, 0); static IIO_DEV_ATTR_ACCEL_X(adis16350_read_14bit_signed, ADIS16350_XACCL_OUT); @@ -523,7 +548,16 @@ static IIO_DEV_ATTR_ACCEL_Y(adis16350_read_14bit_signed, ADIS16350_YACCL_OUT); static IIO_DEV_ATTR_ACCEL_Z(adis16350_read_14bit_signed, ADIS16350_ZACCL_OUT); -static IIO_CONST_ATTR_ACCEL_SCALE("0.0247323713"); + +static ssize_t adis16350_show_accel_scale(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adis16350_state *st = iio_dev_get_devdata(dev_info); + return sprintf(buf, "%s\n", st->variant->accel_scale); +} +static IIO_DEV_ATTR_ACCEL_SCALE(S_IRUGO, adis16350_show_accel_scale, NULL, 0); static IIO_DEVICE_ATTR(temp_x_raw, S_IRUGO, adis16350_read_12bit_signed, NULL, ADIS16350_XTEMP_OUT); @@ -547,7 +581,16 @@ static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("409 546 819 1638"); -static IIO_CONST_ATTR_NAME("adis16350"); + +static ssize_t adis16350_show_name(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct iio_dev *dev_info = dev_get_drvdata(dev); + struct adis16350_state *st = iio_dev_get_devdata(dev_info); + return sprintf(buf, "%s\n", spi_get_device_id(st->us)->name); +} +static IIO_DEVICE_ATTR(name, S_IRUGO, adis16350_show_name, NULL, 0); static struct attribute *adis16350_attributes[] = { &iio_dev_attr_gyro_x_calibbias.dev_attr.attr, @@ -561,11 +604,11 @@ static struct attribute *adis16350_attributes[] = { &iio_dev_attr_gyro_x_raw.dev_attr.attr, &iio_dev_attr_gyro_y_raw.dev_attr.attr, &iio_dev_attr_gyro_z_raw.dev_attr.attr, - &iio_const_attr_gyro_scale.dev_attr.attr, + &iio_dev_attr_gyro_scale.dev_attr.attr, &iio_dev_attr_accel_x_raw.dev_attr.attr, &iio_dev_attr_accel_y_raw.dev_attr.attr, &iio_dev_attr_accel_z_raw.dev_attr.attr, - &iio_const_attr_accel_scale.dev_attr.attr, + &iio_dev_attr_accel_scale.dev_attr.attr, &iio_dev_attr_temp_x_raw.dev_attr.attr, &iio_dev_attr_temp_y_raw.dev_attr.attr, &iio_dev_attr_temp_z_raw.dev_attr.attr, @@ -576,7 +619,7 @@ static struct attribute *adis16350_attributes[] = { &iio_dev_attr_sampling_frequency.dev_attr.attr, &iio_const_attr_sampling_frequency_available.dev_attr.attr, &iio_dev_attr_reset.dev_attr.attr, - &iio_const_attr_name.dev_attr.attr, + &iio_dev_attr_name.dev_attr.attr, NULL }; @@ -584,6 +627,111 @@ static const struct attribute_group adis16350_attribute_group = { .attrs = adis16350_attributes, }; +#define ADIS16300_TEMP_OUT 0x10 /* Temperature output */ +#define ADIS16300_XINCLI_OUT 0x12 /* X-axis inclinometer output measurement */ +#define ADIS16300_YINCLI_OUT 0x14 /* Y-axis inclinometer output measurement */ + +static IIO_DEVICE_ATTR(temp_raw, S_IRUGO, adis16350_read_12bit_unsigned, + NULL, ADIS16300_TEMP_OUT); + +static IIO_DEV_ATTR_INCLI_X(adis16350_read_13bit_signed, + ADIS16300_XINCLI_OUT); +static IIO_DEV_ATTR_INCLI_Y(adis16350_read_13bit_signed, + ADIS16300_YINCLI_OUT); +static IIO_CONST_ATTR_INCLI_SCALE("0.00076794487"); + +static struct attribute *adis16300_attributes[] = { + &iio_dev_attr_gyro_x_calibbias.dev_attr.attr, + &iio_dev_attr_accel_x_calibbias.dev_attr.attr, + &iio_dev_attr_accel_y_calibbias.dev_attr.attr, + &iio_dev_attr_accel_z_calibbias.dev_attr.attr, + &iio_dev_attr_in_supply_raw.dev_attr.attr, + &iio_const_attr_in_supply_scale.dev_attr.attr, + &iio_dev_attr_gyro_z_raw.dev_attr.attr, + &iio_dev_attr_gyro_scale.dev_attr.attr, + &iio_dev_attr_accel_x_raw.dev_attr.attr, + &iio_dev_attr_accel_y_raw.dev_attr.attr, + &iio_dev_attr_accel_z_raw.dev_attr.attr, + &iio_dev_attr_accel_scale.dev_attr.attr, + &iio_dev_attr_incli_x_raw.dev_attr.attr, + &iio_dev_attr_incli_y_raw.dev_attr.attr, + &iio_const_attr_incli_scale.dev_attr.attr, + &iio_dev_attr_temp_raw.dev_attr.attr, + &iio_const_attr_temp_offset.dev_attr.attr, + &iio_const_attr_temp_scale.dev_attr.attr, + &iio_dev_attr_in0_raw.dev_attr.attr, + &iio_const_attr_in0_scale.dev_attr.attr, + &iio_dev_attr_sampling_frequency.dev_attr.attr, + &iio_const_attr_sampling_frequency_available.dev_attr.attr, + &iio_dev_attr_reset.dev_attr.attr, + &iio_dev_attr_name.dev_attr.attr, + NULL +}; + +static const struct attribute_group adis16300_attribute_group = { + .attrs = adis16300_attributes, +}; + +static struct adis16350_chip_info adis16350_variants[] = { + [adis16300] = { + .attribute_group = &adis16300_attribute_group, + .scan_el_group = &adis16300_scan_el_group, + .burst_available = 1, + .gyro_scale = "0.000872664", + .accel_scale = "0.00588399", + .burst_length = 18, + .all_mask = + BIT(ADIS16350_SCAN_IN_SUPPLY) | + BIT(ADIS16350_SCAN_GYRO_Z) | + BIT(ADIS16350_SCAN_ACCEL_X) | + BIT(ADIS16350_SCAN_ACCEL_Y) | + BIT(ADIS16350_SCAN_ACCEL_Z) | + BIT(ADIS16300_SCAN_TEMP) | + BIT(ADIS16300_SCAN_INCLI_X) | + BIT(ADIS16300_SCAN_INCLI_Y) | + BIT(ADIS16350_SCAN_IN0), + }, + [adis16350] = { + .attribute_group = &adis16350_attribute_group, + .scan_el_group = &adis16350_scan_el_group, + .burst_available = 0, + .gyro_scale = "0.00127862821", + .accel_scale = "0.0247323713", + .all_mask = + BIT(ADIS16350_SCAN_IN_SUPPLY) | + BIT(ADIS16350_SCAN_GYRO_X) | + BIT(ADIS16350_SCAN_GYRO_Y) | + BIT(ADIS16350_SCAN_GYRO_Z) | + BIT(ADIS16350_SCAN_ACCEL_X) | + BIT(ADIS16350_SCAN_ACCEL_Y) | + BIT(ADIS16350_SCAN_ACCEL_Z) | + BIT(ADIS16350_SCAN_TEMP_X) | + BIT(ADIS16350_SCAN_TEMP_Y) | + BIT(ADIS16350_SCAN_TEMP_Z) | + BIT(ADIS16350_SCAN_IN0), + }, + [adis16360] = { + .attribute_group = &adis16350_attribute_group, + .scan_el_group = &adis16350_scan_el_group, + .burst_available = 1, + .gyro_scale = "0.00127862821", + .accel_scale = "0.0247323713", + .burst_length = 22, + .all_mask = + BIT(ADIS16350_SCAN_IN_SUPPLY) | + BIT(ADIS16350_SCAN_GYRO_X) | + BIT(ADIS16350_SCAN_GYRO_Y) | + BIT(ADIS16350_SCAN_GYRO_Z) | + BIT(ADIS16350_SCAN_ACCEL_X) | + BIT(ADIS16350_SCAN_ACCEL_Y) | + BIT(ADIS16350_SCAN_ACCEL_Z) | + BIT(ADIS16350_SCAN_TEMP_X) | + BIT(ADIS16350_SCAN_TEMP_Y) | + BIT(ADIS16350_SCAN_TEMP_Z) | + BIT(ADIS16350_SCAN_IN0), + }, +}; + static int __devinit adis16350_probe(struct spi_device *spi) { int ret, regdone = 0; @@ -608,7 +756,8 @@ static int __devinit adis16350_probe(struct spi_device *spi) } st->us = spi; mutex_init(&st->buf_lock); - st->burst_available = spi_get_device_id(spi)->driver_data; + st->variant = &adis16350_variants[spi_get_device_id(spi)->driver_data]; + /* setup the industrialio driver allocated elements */ st->indio_dev = iio_allocate_device(); if (st->indio_dev == NULL) { @@ -642,10 +791,16 @@ static int __devinit adis16350_probe(struct spi_device *spi) if (ret) goto error_uninitialize_ring; } - /* The event irq */ - if (spi->dev.platform_data) { + /* + * The event irq - currently only supported in the adis16350 + * and adis16360 famillies. + */ + if (spi->dev.platform_data && + (spi_get_device_id(spi)->driver_data == adis16350 || + spi_get_device_id(spi)->driver_data == adis16360)) { ret = adis16350_configure_event_line(st, - *(int *)spi->dev.platform_data); + *(int *)spi + ->dev.platform_data); if (ret) goto error_remove_trigger; } @@ -709,13 +864,14 @@ err_ret: } static const struct spi_device_id adis16350_id[] = { - {"adis16350", 0}, - {"adis16354", 0}, - {"adis16355", 0}, - {"adis16360", 1}, - {"adis16362", 1}, - {"adis16364", 1}, - {"adis16365", 1}, + {"adis16300", adis16300}, + {"adis16350", adis16350}, + {"adis16354", adis16350}, + {"adis16355", adis16350}, + {"adis16360", adis16360}, + {"adis16362", adis16360}, + {"adis16364", adis16360}, + {"adis16365", adis16360}, {} }; diff --git a/drivers/staging/iio/imu/adis16350_ring.c b/drivers/staging/iio/imu/adis16350_ring.c index 9af0345..37ec884 100644 --- a/drivers/staging/iio/imu/adis16350_ring.c +++ b/drivers/staging/iio/imu/adis16350_ring.c @@ -62,10 +62,35 @@ static struct attribute *adis16350_scan_el_attrs[] = { NULL, }; -static struct attribute_group adis16350_scan_el_group = { +struct attribute_group adis16350_scan_el_group = { .attrs = adis16350_scan_el_attrs, .name = "scan_elements", }; +static IIO_SCAN_EL_C(incli_x, ADIS16300_SCAN_INCLI_X, IIO_SIGNED(12), + ADIS16300_XINCLI_OUT, NULL); +static IIO_SCAN_EL_C(incli_y, ADIS16300_SCAN_INCLI_Y, IIO_SIGNED(12), + ADIS16300_YINCLI_OUT, NULL); +static IIO_SCAN_EL_C(temp, ADIS16300_SCAN_TEMP, IIO_UNSIGNED(12), + ADIS16300_TEMP_OUT, NULL); + +static struct attribute *adis16300_scan_el_attrs[] = { + &iio_scan_el_in_supply.dev_attr.attr, + &iio_scan_el_gyro_x.dev_attr.attr, + &iio_scan_el_temp.dev_attr.attr, + &iio_scan_el_accel_x.dev_attr.attr, + &iio_scan_el_accel_y.dev_attr.attr, + &iio_scan_el_accel_z.dev_attr.attr, + &iio_scan_el_incli_x.dev_attr.attr, + &iio_scan_el_incli_y.dev_attr.attr, + &iio_scan_el_in0.dev_attr.attr, + &iio_scan_el_timestamp.dev_attr.attr, + NULL, +}; + +struct attribute_group adis16300_scan_el_group = { + .attrs = adis16300_scan_el_attrs, + .name = "scan_elements", +}; /** * adis16350_poll_func_th() top half interrupt handler called by trigger @@ -100,7 +125,7 @@ static int adis16350_spi_read_burst(struct device *dev, u8 *rx) }, { .rx_buf = rx, .bits_per_word = 8, - .len = 22, + .len = st->variant->burst_length, .cs_change = 0, }, }; @@ -126,7 +151,8 @@ static int adis16350_spi_read_burst(struct device *dev, u8 *rx) return ret; } -static const u16 read_all_tx_array[] = { +/* So far only the adis16350 familly requires this */ +static const u16 adis16350_read_all_tx_array[] = { be16_to_cpu(ADIS16350_READ_REG(ADIS16350_SUPPLY_OUT)), be16_to_cpu(ADIS16350_READ_REG(ADIS16350_XGYRO_OUT)), be16_to_cpu(ADIS16350_READ_REG(ADIS16350_YGYRO_OUT)), @@ -155,9 +181,9 @@ static int adis16350_spi_read_all(struct device *dev, u16 *rx_array) if (xfers == NULL) return -ENOMEM; - for (i = 0; i < ARRAY_SIZE(read_all_tx_array); i++) + for (i = 0; i < ARRAY_SIZE(adis16350_read_all_tx_array); i++) if (st->indio_dev->ring->scan_mask & (1 << i)) { - xfers[j].tx_buf = &read_all_tx_array[i]; + xfers[j].tx_buf = &adis16350_read_all_tx_array[i]; xfers[j].bits_per_word = 16; xfers[j].len = 2; xfers[j + 1].rx_buf = rx_array + j; @@ -197,15 +223,22 @@ static void adis16350_trigger_bh_to_ring(struct work_struct *work_s) } if (ring->scan_count) { - if (st->burst_available) { + if (st->variant->burst_available) { if (adis16350_spi_read_burst(&st->indio_dev->dev, - st->rx) < 0) + st->rx) < 0) return; - for (; i < ring->scan_count; i++) - if (st->indio_dev->ring->scan_mask & (1 << i)) - data[j++] = le16_to_cpup( + /* This compexity is to allow for devices supported by + * the same driver to include non contiguous sets of + * channels + */ + for_each_set_bit(i, &st->variant->all_mask, + sizeof(st->variant->all_mask)* + BITS_PER_BYTE) + if (st->indio_dev->ring->scan_mask & BIT(i)) + data[j++] = le16_to_cpup( (__le16 *)&(st->rx[i*2])); } else { + /* adis16350 only so far */ if (adis16350_spi_read_all(&st->indio_dev->dev, (u16 *)st->rx) < 0) return; @@ -249,7 +282,7 @@ int adis16350_configure_ring(struct iio_dev *indio_dev) /* Effectively select the ring buffer implementation */ iio_ring_sw_register_funcs(&ring->access); ring->bpe = 2; - ring->scan_el_attrs = &adis16350_scan_el_group; + ring->scan_el_attrs = st->variant->scan_el_group; ring->scan_timestamp = true; ring->preenable = &iio_sw_ring_preenable; ring->postenable = &iio_triggered_ring_postenable; @@ -257,17 +290,7 @@ int adis16350_configure_ring(struct iio_dev *indio_dev) ring->owner = THIS_MODULE; /* Set default scan mode */ - iio_scan_mask_set(ring, iio_scan_el_in_supply.number); - iio_scan_mask_set(ring, iio_scan_el_gyro_x.number); - iio_scan_mask_set(ring, iio_scan_el_gyro_y.number); - iio_scan_mask_set(ring, iio_scan_el_gyro_z.number); - iio_scan_mask_set(ring, iio_scan_el_accel_x.number); - iio_scan_mask_set(ring, iio_scan_el_accel_y.number); - iio_scan_mask_set(ring, iio_scan_el_accel_z.number); - iio_scan_mask_set(ring, iio_scan_el_temp_x.number); - iio_scan_mask_set(ring, iio_scan_el_temp_y.number); - iio_scan_mask_set(ring, iio_scan_el_temp_z.number); - iio_scan_mask_set(ring, iio_scan_el_in0.number); + ring->scan_mask = st->variant->all_mask; ret = iio_alloc_pollfunc(indio_dev, NULL, &adis16350_poll_func_th); if (ret) -- 1.7.2.2