staging:iio: Move adxrs450 driver out of staging
authorLars-Peter Clausen <lars@metafoo.de>
Thu, 31 Jan 2013 14:27:00 +0000 (14:27 +0000)
committerJonathan Cameron <jic23@kernel.org>
Sat, 2 Feb 2013 09:27:56 +0000 (09:27 +0000)
The adxrs450 is in a reasonable shape now. It follows the IIO ABI and non of the
standard code checker tools report any issue, so move it out of staging.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
drivers/iio/gyro/Kconfig
drivers/iio/gyro/Makefile
drivers/iio/gyro/adxrs450.c [new file with mode: 0644]
drivers/staging/iio/gyro/Kconfig
drivers/staging/iio/gyro/Makefile
drivers/staging/iio/gyro/adxrs450.c [deleted file]

index c9f177dd4cc74464807e779254d8e45a51e9625c..51ac6bc791c683cb0e5e234e94a19862cd5f030e 100644 (file)
@@ -19,6 +19,16 @@ config ADIS16136
          Say yes here to build support for the Analog Devices ADIS16133, ADIS16135,
          ADIS16136 gyroscope devices.
 
+config ADXRS450
+       tristate "Analog Devices ADXRS450/3 Digital Output Gyroscope SPI driver"
+       depends on SPI
+       help
+         Say yes here to build support for Analog Devices ADXRS450 and ADXRS453
+         programmable digital output gyroscope.
+
+         This driver can also be built as a module.  If so, the module
+         will be called adxrs450.
+
 config HID_SENSOR_GYRO_3D
        depends on HID_SENSOR_HUB
        select IIO_BUFFER
index 66b517d9468a4519acc910329990b918e8d3a329..eff9bb0119a29fab2ec023ae9aec1fa8b3cb6679 100644 (file)
@@ -4,6 +4,8 @@
 
 obj-$(CONFIG_ADIS16080) += adis16080.o
 obj-$(CONFIG_ADIS16136) += adis16136.o
+obj-$(CONFIG_ADXRS450) += adxrs450.o
+
 obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o
 
 obj-$(CONFIG_IIO_ST_GYRO_3AXIS) += st_gyro.o
diff --git a/drivers/iio/gyro/adxrs450.c b/drivers/iio/gyro/adxrs450.c
new file mode 100644 (file)
index 0000000..d9d4383
--- /dev/null
@@ -0,0 +1,497 @@
+/*
+ * ADXRS450/ADXRS453 Digital Output Gyroscope Driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#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/list.h>
+#include <linux/module.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define ADXRS450_STARTUP_DELAY 50 /* ms */
+
+/* The MSB for the spi commands */
+#define ADXRS450_SENSOR_DATA    (0x20 << 24)
+#define ADXRS450_WRITE_DATA    (0x40 << 24)
+#define ADXRS450_READ_DATA     (0x80 << 24)
+
+#define ADXRS450_RATE1 0x00    /* Rate Registers */
+#define ADXRS450_TEMP1 0x02    /* Temperature Registers */
+#define ADXRS450_LOCST1        0x04    /* Low CST Memory Registers */
+#define ADXRS450_HICST1        0x06    /* High CST Memory Registers */
+#define ADXRS450_QUAD1 0x08    /* Quad Memory Registers */
+#define ADXRS450_FAULT1        0x0A    /* Fault Registers */
+#define ADXRS450_PID1  0x0C    /* Part ID Register 1 */
+#define ADXRS450_SNH   0x0E    /* Serial Number Registers, 4 bytes */
+#define ADXRS450_SNL   0x10
+#define ADXRS450_DNC1  0x12    /* Dynamic Null Correction Registers */
+/* Check bits */
+#define ADXRS450_P     0x01
+#define ADXRS450_CHK   0x02
+#define ADXRS450_CST   0x04
+#define ADXRS450_PWR   0x08
+#define ADXRS450_POR   0x10
+#define ADXRS450_NVM   0x20
+#define ADXRS450_Q     0x40
+#define ADXRS450_PLL   0x80
+#define ADXRS450_UV    0x100
+#define ADXRS450_OV    0x200
+#define ADXRS450_AMP   0x400
+#define ADXRS450_FAIL  0x800
+
+#define ADXRS450_WRERR_MASK    (0x7 << 29)
+
+#define ADXRS450_MAX_RX 4
+#define ADXRS450_MAX_TX 4
+
+#define ADXRS450_GET_ST(a)     ((a >> 26) & 0x3)
+
+enum {
+       ID_ADXRS450,
+       ID_ADXRS453,
+};
+
+/**
+ * struct adxrs450_state - device instance specific data
+ * @us:                        actual spi_device
+ * @buf_lock:          mutex to protect tx and rx
+ * @tx:                        transmit buffer
+ * @rx:                        receive buffer
+ **/
+struct adxrs450_state {
+       struct spi_device       *us;
+       struct mutex            buf_lock;
+       __be32                  tx ____cacheline_aligned;
+       __be32                  rx;
+
+};
+
+/**
+ * adxrs450_spi_read_reg_16() - read 2 bytes from a register pair
+ * @indio_dev: device associated with child of actual iio_dev
+ * @reg_address: the address of the lower of the two registers, which should be
+ *     an even address, the second register's address is reg_address + 1.
+ * @val: somewhere to pass back the value read
+ **/
+static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev,
+                                   u8 reg_address,
+                                   u16 *val)
+{
+       struct spi_message msg;
+       struct adxrs450_state *st = iio_priv(indio_dev);
+       u32 tx;
+       int ret;
+       struct spi_transfer xfers[] = {
+               {
+                       .tx_buf = &st->tx,
+                       .bits_per_word = 8,
+                       .len = sizeof(st->tx),
+                       .cs_change = 1,
+               }, {
+                       .rx_buf = &st->rx,
+                       .bits_per_word = 8,
+                       .len = sizeof(st->rx),
+               },
+       };
+
+       mutex_lock(&st->buf_lock);
+       tx = ADXRS450_READ_DATA | (reg_address << 17);
+
+       if (!(hweight32(tx) & 1))
+               tx |= ADXRS450_P;
+
+       st->tx = cpu_to_be32(tx);
+       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 while reading 16 bit register 0x%02x\n",
+                               reg_address);
+               goto error_ret;
+       }
+
+       *val = (be32_to_cpu(st->rx) >> 5) & 0xFFFF;
+
+error_ret:
+       mutex_unlock(&st->buf_lock);
+       return ret;
+}
+
+/**
+ * adxrs450_spi_write_reg_16() - write 2 bytes data to a register pair
+ * @indio_dev: device associated with child of actual actual iio_dev
+ * @reg_address: the address of the lower of the two registers,which should be
+ *     an even address, the second register's address is reg_address + 1.
+ * @val: value to be written.
+ **/
+static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev,
+                                    u8 reg_address,
+                                    u16 val)
+{
+       struct adxrs450_state *st = iio_priv(indio_dev);
+       u32 tx;
+       int ret;
+
+       mutex_lock(&st->buf_lock);
+       tx = ADXRS450_WRITE_DATA | (reg_address << 17) | (val << 1);
+
+       if (!(hweight32(tx) & 1))
+               tx |= ADXRS450_P;
+
+       st->tx = cpu_to_be32(tx);
+       ret = spi_write(st->us, &st->tx, sizeof(st->tx));
+       if (ret)
+               dev_err(&st->us->dev, "problem while writing 16 bit register 0x%02x\n",
+                       reg_address);
+       usleep_range(100, 1000); /* enforce sequential transfer delay 0.1ms */
+       mutex_unlock(&st->buf_lock);
+       return ret;
+}
+
+/**
+ * adxrs450_spi_sensor_data() - read 2 bytes sensor data
+ * @indio_dev: device associated with child of actual iio_dev
+ * @val: somewhere to pass back the value read
+ **/
+static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val)
+{
+       struct spi_message msg;
+       struct adxrs450_state *st = iio_priv(indio_dev);
+       int ret;
+       struct spi_transfer xfers[] = {
+               {
+                       .tx_buf = &st->tx,
+                       .bits_per_word = 8,
+                       .len = sizeof(st->tx),
+                       .cs_change = 1,
+               }, {
+                       .rx_buf = &st->rx,
+                       .bits_per_word = 8,
+                       .len = sizeof(st->rx),
+               },
+       };
+
+       mutex_lock(&st->buf_lock);
+       st->tx = cpu_to_be32(ADXRS450_SENSOR_DATA);
+
+       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 while reading sensor data\n");
+               goto error_ret;
+       }
+
+       *val = (be32_to_cpu(st->rx) >> 10) & 0xFFFF;
+
+error_ret:
+       mutex_unlock(&st->buf_lock);
+       return ret;
+}
+
+/**
+ * adxrs450_spi_initial() - use for initializing procedure.
+ * @st: device instance specific data
+ * @val: somewhere to pass back the value read
+ * @chk: Whether to perform fault check
+ **/
+static int adxrs450_spi_initial(struct adxrs450_state *st,
+               u32 *val, char chk)
+{
+       struct spi_message msg;
+       int ret;
+       u32 tx;
+       struct spi_transfer xfers = {
+               .tx_buf = &st->tx,
+               .rx_buf = &st->rx,
+               .bits_per_word = 8,
+               .len = sizeof(st->tx),
+       };
+
+       mutex_lock(&st->buf_lock);
+       tx = ADXRS450_SENSOR_DATA;
+       if (chk)
+               tx |= (ADXRS450_CHK | ADXRS450_P);
+       st->tx = cpu_to_be32(tx);
+       spi_message_init(&msg);
+       spi_message_add_tail(&xfers, &msg);
+       ret = spi_sync(st->us, &msg);
+       if (ret) {
+               dev_err(&st->us->dev, "Problem while reading initializing data\n");
+               goto error_ret;
+       }
+
+       *val = be32_to_cpu(st->rx);
+
+error_ret:
+       mutex_unlock(&st->buf_lock);
+       return ret;
+}
+
+/* Recommended Startup Sequence by spec */
+static int adxrs450_initial_setup(struct iio_dev *indio_dev)
+{
+       u32 t;
+       u16 data;
+       int ret;
+       struct adxrs450_state *st = iio_priv(indio_dev);
+
+       msleep(ADXRS450_STARTUP_DELAY*2);
+       ret = adxrs450_spi_initial(st, &t, 1);
+       if (ret)
+               return ret;
+       if (t != 0x01)
+               dev_warn(&st->us->dev, "The initial power on response is not correct! Restart without reset?\n");
+
+       msleep(ADXRS450_STARTUP_DELAY);
+       ret = adxrs450_spi_initial(st, &t, 0);
+       if (ret)
+               return ret;
+
+       msleep(ADXRS450_STARTUP_DELAY);
+       ret = adxrs450_spi_initial(st, &t, 0);
+       if (ret)
+               return ret;
+       if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) {
+               dev_err(&st->us->dev, "The second response is not correct!\n");
+               return -EIO;
+
+       }
+       ret = adxrs450_spi_initial(st, &t, 0);
+       if (ret)
+               return ret;
+       if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) {
+               dev_err(&st->us->dev, "The third response is not correct!\n");
+               return -EIO;
+
+       }
+       ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_FAULT1, &data);
+       if (ret)
+               return ret;
+       if (data & 0x0fff) {
+               dev_err(&st->us->dev, "The device is not in normal status!\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int adxrs450_write_raw(struct iio_dev *indio_dev,
+                             struct iio_chan_spec const *chan,
+                             int val,
+                             int val2,
+                             long mask)
+{
+       int ret;
+       switch (mask) {
+       case IIO_CHAN_INFO_CALIBBIAS:
+               if (val < -0x400 || val >= 0x400)
+                       return -EINVAL;
+               ret = adxrs450_spi_write_reg_16(indio_dev,
+                                               ADXRS450_DNC1, val);
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+       return ret;
+}
+
+static int adxrs450_read_raw(struct iio_dev *indio_dev,
+                            struct iio_chan_spec const *chan,
+                            int *val,
+                            int *val2,
+                            long mask)
+{
+       int ret;
+       s16 t;
+
+       switch (mask) {
+       case IIO_CHAN_INFO_RAW:
+               switch (chan->type) {
+               case IIO_ANGL_VEL:
+                       ret = adxrs450_spi_sensor_data(indio_dev, &t);
+                       if (ret)
+                               break;
+                       *val = t;
+                       ret = IIO_VAL_INT;
+                       break;
+               case IIO_TEMP:
+                       ret = adxrs450_spi_read_reg_16(indio_dev,
+                                                      ADXRS450_TEMP1, &t);
+                       if (ret)
+                               break;
+                       *val = (t >> 6) + 225;
+                       ret = IIO_VAL_INT;
+                       break;
+               default:
+                       ret = -EINVAL;
+                       break;
+               }
+               break;
+       case IIO_CHAN_INFO_SCALE:
+               switch (chan->type) {
+               case IIO_ANGL_VEL:
+                       *val = 0;
+                       *val2 = 218166;
+                       return IIO_VAL_INT_PLUS_NANO;
+               case IIO_TEMP:
+                       *val = 200;
+                       *val2 = 0;
+                       return IIO_VAL_INT;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       case IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW:
+               ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_QUAD1, &t);
+               if (ret)
+                       break;
+               *val = t;
+               ret = IIO_VAL_INT;
+               break;
+       case IIO_CHAN_INFO_CALIBBIAS:
+               ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_DNC1, &t);
+               if (ret)
+                       break;
+               *val = sign_extend32(t, 9);
+               ret = IIO_VAL_INT;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
+       }
+
+       return ret;
+}
+
+static const struct iio_chan_spec adxrs450_channels[2][2] = {
+       [ID_ADXRS450] = {
+               {
+                       .type = IIO_ANGL_VEL,
+                       .modified = 1,
+                       .channel2 = IIO_MOD_Z,
+                       .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+                       IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+                       IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT |
+                       IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+               }, {
+                       .type = IIO_TEMP,
+                       .indexed = 1,
+                       .channel = 0,
+                       .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+                       IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+               }
+       },
+       [ID_ADXRS453] = {
+               {
+                       .type = IIO_ANGL_VEL,
+                       .modified = 1,
+                       .channel2 = IIO_MOD_Z,
+                       .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+                       IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
+                       IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT,
+               }, {
+                       .type = IIO_TEMP,
+                       .indexed = 1,
+                       .channel = 0,
+                       .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
+                       IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
+               }
+       },
+};
+
+static const struct iio_info adxrs450_info = {
+       .driver_module = THIS_MODULE,
+       .read_raw = &adxrs450_read_raw,
+       .write_raw = &adxrs450_write_raw,
+};
+
+static int adxrs450_probe(struct spi_device *spi)
+{
+       int ret;
+       struct adxrs450_state *st;
+       struct iio_dev *indio_dev;
+
+       /* setup the industrialio driver allocated elements */
+       indio_dev = iio_device_alloc(sizeof(*st));
+       if (indio_dev == NULL) {
+               ret = -ENOMEM;
+               goto error_ret;
+       }
+       st = iio_priv(indio_dev);
+       st->us = spi;
+       mutex_init(&st->buf_lock);
+       /* This is only used for removal purposes */
+       spi_set_drvdata(spi, indio_dev);
+
+       indio_dev->dev.parent = &spi->dev;
+       indio_dev->info = &adxrs450_info;
+       indio_dev->modes = INDIO_DIRECT_MODE;
+       indio_dev->channels =
+               adxrs450_channels[spi_get_device_id(spi)->driver_data];
+       indio_dev->num_channels = ARRAY_SIZE(adxrs450_channels);
+       indio_dev->name = spi->dev.driver->name;
+
+       ret = iio_device_register(indio_dev);
+       if (ret)
+               goto error_free_dev;
+
+       /* Get the device into a sane initial state */
+       ret = adxrs450_initial_setup(indio_dev);
+       if (ret)
+               goto error_initial;
+       return 0;
+error_initial:
+       iio_device_unregister(indio_dev);
+error_free_dev:
+       iio_device_free(indio_dev);
+
+error_ret:
+       return ret;
+}
+
+static int adxrs450_remove(struct spi_device *spi)
+{
+       iio_device_unregister(spi_get_drvdata(spi));
+       iio_device_free(spi_get_drvdata(spi));
+
+       return 0;
+}
+
+static const struct spi_device_id adxrs450_id[] = {
+       {"adxrs450", ID_ADXRS450},
+       {"adxrs453", ID_ADXRS453},
+       {}
+};
+MODULE_DEVICE_TABLE(spi, adxrs450_id);
+
+static struct spi_driver adxrs450_driver = {
+       .driver = {
+               .name = "adxrs450",
+               .owner = THIS_MODULE,
+       },
+       .probe = adxrs450_probe,
+       .remove = adxrs450_remove,
+       .id_table       = adxrs450_id,
+};
+module_spi_driver(adxrs450_driver);
+
+MODULE_AUTHOR("Cliff Cai <cliff.cai@xxxxxxxxxx>");
+MODULE_DESCRIPTION("Analog Devices ADXRS450/ADXRS453 Gyroscope SPI driver");
+MODULE_LICENSE("GPL v2");
index 658b3673d056b879138f7dd4e74205177e70f66d..836066287192d3ef5e8ead829928032be74e0971 100644 (file)
@@ -29,14 +29,4 @@ config ADIS16260
          This driver can also be built as a module.  If so, the module
          will be called adis16260.
 
-config ADXRS450
-       tristate "Analog Devices ADXRS450/3 Digital Output Gyroscope SPI driver"
-       depends on SPI
-       help
-         Say yes here to build support for Analog Devices ADXRS450 and ADXRS453
-         programmable digital output gyroscope.
-
-         This driver can also be built as a module.  If so, the module
-         will be called adxrs450.
-
 endmenu
index 6b4e60ab743f6826805b8fcc071043c283de2665..98e650061a3a8cb5e4f7bab9029fc9a1a024c5ef 100644 (file)
@@ -10,5 +10,3 @@ obj-$(CONFIG_ADIS16130) += adis16130.o
 
 adis16260-y             := adis16260_core.o
 obj-$(CONFIG_ADIS16260) += adis16260.o
-
-obj-$(CONFIG_ADXRS450) += adxrs450.o
diff --git a/drivers/staging/iio/gyro/adxrs450.c b/drivers/staging/iio/gyro/adxrs450.c
deleted file mode 100644 (file)
index d9d4383..0000000
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * ADXRS450/ADXRS453 Digital Output Gyroscope Driver
- *
- * Copyright 2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2.
- */
-
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#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/list.h>
-#include <linux/module.h>
-
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-
-#define ADXRS450_STARTUP_DELAY 50 /* ms */
-
-/* The MSB for the spi commands */
-#define ADXRS450_SENSOR_DATA    (0x20 << 24)
-#define ADXRS450_WRITE_DATA    (0x40 << 24)
-#define ADXRS450_READ_DATA     (0x80 << 24)
-
-#define ADXRS450_RATE1 0x00    /* Rate Registers */
-#define ADXRS450_TEMP1 0x02    /* Temperature Registers */
-#define ADXRS450_LOCST1        0x04    /* Low CST Memory Registers */
-#define ADXRS450_HICST1        0x06    /* High CST Memory Registers */
-#define ADXRS450_QUAD1 0x08    /* Quad Memory Registers */
-#define ADXRS450_FAULT1        0x0A    /* Fault Registers */
-#define ADXRS450_PID1  0x0C    /* Part ID Register 1 */
-#define ADXRS450_SNH   0x0E    /* Serial Number Registers, 4 bytes */
-#define ADXRS450_SNL   0x10
-#define ADXRS450_DNC1  0x12    /* Dynamic Null Correction Registers */
-/* Check bits */
-#define ADXRS450_P     0x01
-#define ADXRS450_CHK   0x02
-#define ADXRS450_CST   0x04
-#define ADXRS450_PWR   0x08
-#define ADXRS450_POR   0x10
-#define ADXRS450_NVM   0x20
-#define ADXRS450_Q     0x40
-#define ADXRS450_PLL   0x80
-#define ADXRS450_UV    0x100
-#define ADXRS450_OV    0x200
-#define ADXRS450_AMP   0x400
-#define ADXRS450_FAIL  0x800
-
-#define ADXRS450_WRERR_MASK    (0x7 << 29)
-
-#define ADXRS450_MAX_RX 4
-#define ADXRS450_MAX_TX 4
-
-#define ADXRS450_GET_ST(a)     ((a >> 26) & 0x3)
-
-enum {
-       ID_ADXRS450,
-       ID_ADXRS453,
-};
-
-/**
- * struct adxrs450_state - device instance specific data
- * @us:                        actual spi_device
- * @buf_lock:          mutex to protect tx and rx
- * @tx:                        transmit buffer
- * @rx:                        receive buffer
- **/
-struct adxrs450_state {
-       struct spi_device       *us;
-       struct mutex            buf_lock;
-       __be32                  tx ____cacheline_aligned;
-       __be32                  rx;
-
-};
-
-/**
- * adxrs450_spi_read_reg_16() - read 2 bytes from a register pair
- * @indio_dev: device associated with child of actual iio_dev
- * @reg_address: the address of the lower of the two registers, which should be
- *     an even address, the second register's address is reg_address + 1.
- * @val: somewhere to pass back the value read
- **/
-static int adxrs450_spi_read_reg_16(struct iio_dev *indio_dev,
-                                   u8 reg_address,
-                                   u16 *val)
-{
-       struct spi_message msg;
-       struct adxrs450_state *st = iio_priv(indio_dev);
-       u32 tx;
-       int ret;
-       struct spi_transfer xfers[] = {
-               {
-                       .tx_buf = &st->tx,
-                       .bits_per_word = 8,
-                       .len = sizeof(st->tx),
-                       .cs_change = 1,
-               }, {
-                       .rx_buf = &st->rx,
-                       .bits_per_word = 8,
-                       .len = sizeof(st->rx),
-               },
-       };
-
-       mutex_lock(&st->buf_lock);
-       tx = ADXRS450_READ_DATA | (reg_address << 17);
-
-       if (!(hweight32(tx) & 1))
-               tx |= ADXRS450_P;
-
-       st->tx = cpu_to_be32(tx);
-       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 while reading 16 bit register 0x%02x\n",
-                               reg_address);
-               goto error_ret;
-       }
-
-       *val = (be32_to_cpu(st->rx) >> 5) & 0xFFFF;
-
-error_ret:
-       mutex_unlock(&st->buf_lock);
-       return ret;
-}
-
-/**
- * adxrs450_spi_write_reg_16() - write 2 bytes data to a register pair
- * @indio_dev: device associated with child of actual actual iio_dev
- * @reg_address: the address of the lower of the two registers,which should be
- *     an even address, the second register's address is reg_address + 1.
- * @val: value to be written.
- **/
-static int adxrs450_spi_write_reg_16(struct iio_dev *indio_dev,
-                                    u8 reg_address,
-                                    u16 val)
-{
-       struct adxrs450_state *st = iio_priv(indio_dev);
-       u32 tx;
-       int ret;
-
-       mutex_lock(&st->buf_lock);
-       tx = ADXRS450_WRITE_DATA | (reg_address << 17) | (val << 1);
-
-       if (!(hweight32(tx) & 1))
-               tx |= ADXRS450_P;
-
-       st->tx = cpu_to_be32(tx);
-       ret = spi_write(st->us, &st->tx, sizeof(st->tx));
-       if (ret)
-               dev_err(&st->us->dev, "problem while writing 16 bit register 0x%02x\n",
-                       reg_address);
-       usleep_range(100, 1000); /* enforce sequential transfer delay 0.1ms */
-       mutex_unlock(&st->buf_lock);
-       return ret;
-}
-
-/**
- * adxrs450_spi_sensor_data() - read 2 bytes sensor data
- * @indio_dev: device associated with child of actual iio_dev
- * @val: somewhere to pass back the value read
- **/
-static int adxrs450_spi_sensor_data(struct iio_dev *indio_dev, s16 *val)
-{
-       struct spi_message msg;
-       struct adxrs450_state *st = iio_priv(indio_dev);
-       int ret;
-       struct spi_transfer xfers[] = {
-               {
-                       .tx_buf = &st->tx,
-                       .bits_per_word = 8,
-                       .len = sizeof(st->tx),
-                       .cs_change = 1,
-               }, {
-                       .rx_buf = &st->rx,
-                       .bits_per_word = 8,
-                       .len = sizeof(st->rx),
-               },
-       };
-
-       mutex_lock(&st->buf_lock);
-       st->tx = cpu_to_be32(ADXRS450_SENSOR_DATA);
-
-       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 while reading sensor data\n");
-               goto error_ret;
-       }
-
-       *val = (be32_to_cpu(st->rx) >> 10) & 0xFFFF;
-
-error_ret:
-       mutex_unlock(&st->buf_lock);
-       return ret;
-}
-
-/**
- * adxrs450_spi_initial() - use for initializing procedure.
- * @st: device instance specific data
- * @val: somewhere to pass back the value read
- * @chk: Whether to perform fault check
- **/
-static int adxrs450_spi_initial(struct adxrs450_state *st,
-               u32 *val, char chk)
-{
-       struct spi_message msg;
-       int ret;
-       u32 tx;
-       struct spi_transfer xfers = {
-               .tx_buf = &st->tx,
-               .rx_buf = &st->rx,
-               .bits_per_word = 8,
-               .len = sizeof(st->tx),
-       };
-
-       mutex_lock(&st->buf_lock);
-       tx = ADXRS450_SENSOR_DATA;
-       if (chk)
-               tx |= (ADXRS450_CHK | ADXRS450_P);
-       st->tx = cpu_to_be32(tx);
-       spi_message_init(&msg);
-       spi_message_add_tail(&xfers, &msg);
-       ret = spi_sync(st->us, &msg);
-       if (ret) {
-               dev_err(&st->us->dev, "Problem while reading initializing data\n");
-               goto error_ret;
-       }
-
-       *val = be32_to_cpu(st->rx);
-
-error_ret:
-       mutex_unlock(&st->buf_lock);
-       return ret;
-}
-
-/* Recommended Startup Sequence by spec */
-static int adxrs450_initial_setup(struct iio_dev *indio_dev)
-{
-       u32 t;
-       u16 data;
-       int ret;
-       struct adxrs450_state *st = iio_priv(indio_dev);
-
-       msleep(ADXRS450_STARTUP_DELAY*2);
-       ret = adxrs450_spi_initial(st, &t, 1);
-       if (ret)
-               return ret;
-       if (t != 0x01)
-               dev_warn(&st->us->dev, "The initial power on response is not correct! Restart without reset?\n");
-
-       msleep(ADXRS450_STARTUP_DELAY);
-       ret = adxrs450_spi_initial(st, &t, 0);
-       if (ret)
-               return ret;
-
-       msleep(ADXRS450_STARTUP_DELAY);
-       ret = adxrs450_spi_initial(st, &t, 0);
-       if (ret)
-               return ret;
-       if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) {
-               dev_err(&st->us->dev, "The second response is not correct!\n");
-               return -EIO;
-
-       }
-       ret = adxrs450_spi_initial(st, &t, 0);
-       if (ret)
-               return ret;
-       if (((t & 0xff) | 0x01) != 0xff || ADXRS450_GET_ST(t) != 2) {
-               dev_err(&st->us->dev, "The third response is not correct!\n");
-               return -EIO;
-
-       }
-       ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_FAULT1, &data);
-       if (ret)
-               return ret;
-       if (data & 0x0fff) {
-               dev_err(&st->us->dev, "The device is not in normal status!\n");
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int adxrs450_write_raw(struct iio_dev *indio_dev,
-                             struct iio_chan_spec const *chan,
-                             int val,
-                             int val2,
-                             long mask)
-{
-       int ret;
-       switch (mask) {
-       case IIO_CHAN_INFO_CALIBBIAS:
-               if (val < -0x400 || val >= 0x400)
-                       return -EINVAL;
-               ret = adxrs450_spi_write_reg_16(indio_dev,
-                                               ADXRS450_DNC1, val);
-               break;
-       default:
-               ret = -EINVAL;
-               break;
-       }
-       return ret;
-}
-
-static int adxrs450_read_raw(struct iio_dev *indio_dev,
-                            struct iio_chan_spec const *chan,
-                            int *val,
-                            int *val2,
-                            long mask)
-{
-       int ret;
-       s16 t;
-
-       switch (mask) {
-       case IIO_CHAN_INFO_RAW:
-               switch (chan->type) {
-               case IIO_ANGL_VEL:
-                       ret = adxrs450_spi_sensor_data(indio_dev, &t);
-                       if (ret)
-                               break;
-                       *val = t;
-                       ret = IIO_VAL_INT;
-                       break;
-               case IIO_TEMP:
-                       ret = adxrs450_spi_read_reg_16(indio_dev,
-                                                      ADXRS450_TEMP1, &t);
-                       if (ret)
-                               break;
-                       *val = (t >> 6) + 225;
-                       ret = IIO_VAL_INT;
-                       break;
-               default:
-                       ret = -EINVAL;
-                       break;
-               }
-               break;
-       case IIO_CHAN_INFO_SCALE:
-               switch (chan->type) {
-               case IIO_ANGL_VEL:
-                       *val = 0;
-                       *val2 = 218166;
-                       return IIO_VAL_INT_PLUS_NANO;
-               case IIO_TEMP:
-                       *val = 200;
-                       *val2 = 0;
-                       return IIO_VAL_INT;
-               default:
-                       return -EINVAL;
-               }
-               break;
-       case IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW:
-               ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_QUAD1, &t);
-               if (ret)
-                       break;
-               *val = t;
-               ret = IIO_VAL_INT;
-               break;
-       case IIO_CHAN_INFO_CALIBBIAS:
-               ret = adxrs450_spi_read_reg_16(indio_dev, ADXRS450_DNC1, &t);
-               if (ret)
-                       break;
-               *val = sign_extend32(t, 9);
-               ret = IIO_VAL_INT;
-               break;
-       default:
-               ret = -EINVAL;
-               break;
-       }
-
-       return ret;
-}
-
-static const struct iio_chan_spec adxrs450_channels[2][2] = {
-       [ID_ADXRS450] = {
-               {
-                       .type = IIO_ANGL_VEL,
-                       .modified = 1,
-                       .channel2 = IIO_MOD_Z,
-                       .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-                       IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
-                       IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT |
-                       IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-               }, {
-                       .type = IIO_TEMP,
-                       .indexed = 1,
-                       .channel = 0,
-                       .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-                       IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-               }
-       },
-       [ID_ADXRS453] = {
-               {
-                       .type = IIO_ANGL_VEL,
-                       .modified = 1,
-                       .channel2 = IIO_MOD_Z,
-                       .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-                       IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
-                       IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SEPARATE_BIT,
-               }, {
-                       .type = IIO_TEMP,
-                       .indexed = 1,
-                       .channel = 0,
-                       .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-                       IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
-               }
-       },
-};
-
-static const struct iio_info adxrs450_info = {
-       .driver_module = THIS_MODULE,
-       .read_raw = &adxrs450_read_raw,
-       .write_raw = &adxrs450_write_raw,
-};
-
-static int adxrs450_probe(struct spi_device *spi)
-{
-       int ret;
-       struct adxrs450_state *st;
-       struct iio_dev *indio_dev;
-
-       /* setup the industrialio driver allocated elements */
-       indio_dev = iio_device_alloc(sizeof(*st));
-       if (indio_dev == NULL) {
-               ret = -ENOMEM;
-               goto error_ret;
-       }
-       st = iio_priv(indio_dev);
-       st->us = spi;
-       mutex_init(&st->buf_lock);
-       /* This is only used for removal purposes */
-       spi_set_drvdata(spi, indio_dev);
-
-       indio_dev->dev.parent = &spi->dev;
-       indio_dev->info = &adxrs450_info;
-       indio_dev->modes = INDIO_DIRECT_MODE;
-       indio_dev->channels =
-               adxrs450_channels[spi_get_device_id(spi)->driver_data];
-       indio_dev->num_channels = ARRAY_SIZE(adxrs450_channels);
-       indio_dev->name = spi->dev.driver->name;
-
-       ret = iio_device_register(indio_dev);
-       if (ret)
-               goto error_free_dev;
-
-       /* Get the device into a sane initial state */
-       ret = adxrs450_initial_setup(indio_dev);
-       if (ret)
-               goto error_initial;
-       return 0;
-error_initial:
-       iio_device_unregister(indio_dev);
-error_free_dev:
-       iio_device_free(indio_dev);
-
-error_ret:
-       return ret;
-}
-
-static int adxrs450_remove(struct spi_device *spi)
-{
-       iio_device_unregister(spi_get_drvdata(spi));
-       iio_device_free(spi_get_drvdata(spi));
-
-       return 0;
-}
-
-static const struct spi_device_id adxrs450_id[] = {
-       {"adxrs450", ID_ADXRS450},
-       {"adxrs453", ID_ADXRS453},
-       {}
-};
-MODULE_DEVICE_TABLE(spi, adxrs450_id);
-
-static struct spi_driver adxrs450_driver = {
-       .driver = {
-               .name = "adxrs450",
-               .owner = THIS_MODULE,
-       },
-       .probe = adxrs450_probe,
-       .remove = adxrs450_remove,
-       .id_table       = adxrs450_id,
-};
-module_spi_driver(adxrs450_driver);
-
-MODULE_AUTHOR("Cliff Cai <cliff.cai@xxxxxxxxxx>");
-MODULE_DESCRIPTION("Analog Devices ADXRS450/ADXRS453 Gyroscope SPI driver");
-MODULE_LICENSE("GPL v2");