Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * ADIS16080/100 Yaw Rate Gyroscope with SPI driver
0004  *
0005  * Copyright 2010 Analog Devices Inc.
0006  */
0007 #include <linux/delay.h>
0008 #include <linux/mutex.h>
0009 #include <linux/device.h>
0010 #include <linux/kernel.h>
0011 #include <linux/spi/spi.h>
0012 #include <linux/slab.h>
0013 #include <linux/sysfs.h>
0014 #include <linux/module.h>
0015 
0016 #include <linux/iio/iio.h>
0017 #include <linux/iio/sysfs.h>
0018 
0019 #define ADIS16080_DIN_GYRO   (0 << 10) /* Gyroscope output */
0020 #define ADIS16080_DIN_TEMP   (1 << 10) /* Temperature output */
0021 #define ADIS16080_DIN_AIN1   (2 << 10)
0022 #define ADIS16080_DIN_AIN2   (3 << 10)
0023 
0024 /*
0025  * 1: Write contents on DIN to control register.
0026  * 0: No changes to control register.
0027  */
0028 
0029 #define ADIS16080_DIN_WRITE  (1 << 15)
0030 
0031 struct adis16080_chip_info {
0032     int scale_val;
0033     int scale_val2;
0034 };
0035 
0036 /**
0037  * struct adis16080_state - device instance specific data
0038  * @us:         actual spi_device to write data
0039  * @info:       chip specific parameters
0040  * @buf:        transmit or receive buffer
0041  * @lock:       lock to protect buffer during reads
0042  **/
0043 struct adis16080_state {
0044     struct spi_device       *us;
0045     const struct adis16080_chip_info *info;
0046     struct mutex            lock;
0047 
0048     __be16 buf __aligned(IIO_DMA_MINALIGN);
0049 };
0050 
0051 static int adis16080_read_sample(struct iio_dev *indio_dev,
0052         u16 addr, int *val)
0053 {
0054     struct adis16080_state *st = iio_priv(indio_dev);
0055     int ret;
0056     struct spi_transfer t[] = {
0057         {
0058             .tx_buf     = &st->buf,
0059             .len        = 2,
0060             .cs_change  = 1,
0061         }, {
0062             .rx_buf     = &st->buf,
0063             .len        = 2,
0064         },
0065     };
0066 
0067     st->buf = cpu_to_be16(addr | ADIS16080_DIN_WRITE);
0068 
0069     ret = spi_sync_transfer(st->us, t, ARRAY_SIZE(t));
0070     if (ret == 0)
0071         *val = sign_extend32(be16_to_cpu(st->buf), 11);
0072 
0073     return ret;
0074 }
0075 
0076 static int adis16080_read_raw(struct iio_dev *indio_dev,
0077                  struct iio_chan_spec const *chan,
0078                  int *val,
0079                  int *val2,
0080                  long mask)
0081 {
0082     struct adis16080_state *st = iio_priv(indio_dev);
0083     int ret;
0084 
0085     switch (mask) {
0086     case IIO_CHAN_INFO_RAW:
0087         mutex_lock(&st->lock);
0088         ret = adis16080_read_sample(indio_dev, chan->address, val);
0089         mutex_unlock(&st->lock);
0090         return ret ? ret : IIO_VAL_INT;
0091     case IIO_CHAN_INFO_SCALE:
0092         switch (chan->type) {
0093         case IIO_ANGL_VEL:
0094             *val = st->info->scale_val;
0095             *val2 = st->info->scale_val2;
0096             return IIO_VAL_FRACTIONAL;
0097         case IIO_VOLTAGE:
0098             /* VREF = 5V, 12 bits */
0099             *val = 5000;
0100             *val2 = 12;
0101             return IIO_VAL_FRACTIONAL_LOG2;
0102         case IIO_TEMP:
0103             /* 85 C = 585, 25 C = 0 */
0104             *val = 85000 - 25000;
0105             *val2 = 585;
0106             return IIO_VAL_FRACTIONAL;
0107         default:
0108             return -EINVAL;
0109         }
0110     case IIO_CHAN_INFO_OFFSET:
0111         switch (chan->type) {
0112         case IIO_VOLTAGE:
0113             /* 2.5 V = 0 */
0114             *val = 2048;
0115             return IIO_VAL_INT;
0116         case IIO_TEMP:
0117             /* 85 C = 585, 25 C = 0 */
0118             *val = DIV_ROUND_CLOSEST(25 * 585, 85 - 25);
0119             return IIO_VAL_INT;
0120         default:
0121             return -EINVAL;
0122         }
0123     default:
0124         break;
0125     }
0126 
0127     return -EINVAL;
0128 }
0129 
0130 static const struct iio_chan_spec adis16080_channels[] = {
0131     {
0132         .type = IIO_ANGL_VEL,
0133         .modified = 1,
0134         .channel2 = IIO_MOD_Z,
0135         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0136             BIT(IIO_CHAN_INFO_SCALE),
0137         .address = ADIS16080_DIN_GYRO,
0138     }, {
0139         .type = IIO_VOLTAGE,
0140         .indexed = 1,
0141         .channel = 0,
0142         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0143             BIT(IIO_CHAN_INFO_SCALE) |
0144             BIT(IIO_CHAN_INFO_OFFSET),
0145         .address = ADIS16080_DIN_AIN1,
0146     }, {
0147         .type = IIO_VOLTAGE,
0148         .indexed = 1,
0149         .channel = 1,
0150         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0151             BIT(IIO_CHAN_INFO_SCALE) |
0152             BIT(IIO_CHAN_INFO_OFFSET),
0153         .address = ADIS16080_DIN_AIN2,
0154     }, {
0155         .type = IIO_TEMP,
0156         .indexed = 1,
0157         .channel = 0,
0158         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
0159             BIT(IIO_CHAN_INFO_SCALE) |
0160             BIT(IIO_CHAN_INFO_OFFSET),
0161         .address = ADIS16080_DIN_TEMP,
0162     }
0163 };
0164 
0165 static const struct iio_info adis16080_info = {
0166     .read_raw = &adis16080_read_raw,
0167 };
0168 
0169 enum {
0170     ID_ADIS16080,
0171     ID_ADIS16100,
0172 };
0173 
0174 static const struct adis16080_chip_info adis16080_chip_info[] = {
0175     [ID_ADIS16080] = {
0176         /* 80 degree = 819, 819 rad = 46925 degree */
0177         .scale_val = 80,
0178         .scale_val2 = 46925,
0179     },
0180     [ID_ADIS16100] = {
0181         /* 300 degree = 1230, 1230 rad = 70474 degree */
0182         .scale_val = 300,
0183         .scale_val2 = 70474,
0184     },
0185 };
0186 
0187 static int adis16080_probe(struct spi_device *spi)
0188 {
0189     const struct spi_device_id *id = spi_get_device_id(spi);
0190     struct adis16080_state *st;
0191     struct iio_dev *indio_dev;
0192 
0193     /* setup the industrialio driver allocated elements */
0194     indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
0195     if (!indio_dev)
0196         return -ENOMEM;
0197     st = iio_priv(indio_dev);
0198 
0199     mutex_init(&st->lock);
0200 
0201     /* Allocate the comms buffers */
0202     st->us = spi;
0203     st->info = &adis16080_chip_info[id->driver_data];
0204 
0205     indio_dev->name = spi->dev.driver->name;
0206     indio_dev->channels = adis16080_channels;
0207     indio_dev->num_channels = ARRAY_SIZE(adis16080_channels);
0208     indio_dev->info = &adis16080_info;
0209     indio_dev->modes = INDIO_DIRECT_MODE;
0210 
0211     return devm_iio_device_register(&spi->dev, indio_dev);
0212 }
0213 
0214 static const struct spi_device_id adis16080_ids[] = {
0215     { "adis16080", ID_ADIS16080 },
0216     { "adis16100", ID_ADIS16100 },
0217     {},
0218 };
0219 MODULE_DEVICE_TABLE(spi, adis16080_ids);
0220 
0221 static struct spi_driver adis16080_driver = {
0222     .driver = {
0223         .name = "adis16080",
0224     },
0225     .probe = adis16080_probe,
0226     .id_table = adis16080_ids,
0227 };
0228 module_spi_driver(adis16080_driver);
0229 
0230 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
0231 MODULE_DESCRIPTION("Analog Devices ADIS16080/100 Yaw Rate Gyroscope Driver");
0232 MODULE_LICENSE("GPL v2");