1/* 2 * ADIS16060 Wide Bandwidth Yaw Rate Gyroscope with SPI driver 3 * 4 * Copyright 2010 Analog Devices Inc. 5 * 6 * Licensed under the GPL-2 or later. 7 */ 8 9#include <linux/module.h> 10#include <linux/delay.h> 11#include <linux/mutex.h> 12#include <linux/device.h> 13#include <linux/kernel.h> 14#include <linux/spi/spi.h> 15#include <linux/slab.h> 16#include <linux/sysfs.h> 17 18#include <linux/iio/iio.h> 19#include <linux/iio/sysfs.h> 20 21#define ADIS16060_GYRO 0x20 /* Measure Angular Rate (Gyro) */ 22#define ADIS16060_TEMP_OUT 0x10 /* Measure Temperature */ 23#define ADIS16060_AIN2 0x80 /* Measure AIN2 */ 24#define ADIS16060_AIN1 0x40 /* Measure AIN1 */ 25 26/** 27 * struct adis16060_state - device instance specific data 28 * @us_w: actual spi_device to write config 29 * @us_r: actual spi_device to read back data 30 * @buf: transmit or receive buffer 31 * @buf_lock: mutex to protect tx and rx 32 **/ 33struct adis16060_state { 34 struct spi_device *us_w; 35 struct spi_device *us_r; 36 struct mutex buf_lock; 37 38 u8 buf[3] ____cacheline_aligned; 39}; 40 41static struct iio_dev *adis16060_iio_dev; 42 43static int adis16060_spi_write(struct iio_dev *indio_dev, u8 val) 44{ 45 int ret; 46 struct adis16060_state *st = iio_priv(indio_dev); 47 48 mutex_lock(&st->buf_lock); 49 st->buf[2] = val; /* The last 8 bits clocked in are latched */ 50 ret = spi_write(st->us_w, st->buf, 3); 51 mutex_unlock(&st->buf_lock); 52 53 return ret; 54} 55 56static int adis16060_spi_read(struct iio_dev *indio_dev, u16 *val) 57{ 58 int ret; 59 struct adis16060_state *st = iio_priv(indio_dev); 60 61 mutex_lock(&st->buf_lock); 62 63 ret = spi_read(st->us_r, st->buf, 3); 64 65 /* The internal successive approximation ADC begins the 66 * conversion process on the falling edge of MSEL1 and 67 * starts to place data MSB first on the DOUT line at 68 * the 6th falling edge of SCLK 69 */ 70 if (ret == 0) 71 *val = ((st->buf[0] & 0x3) << 12) | 72 (st->buf[1] << 4) | 73 ((st->buf[2] >> 4) & 0xF); 74 mutex_unlock(&st->buf_lock); 75 76 return ret; 77} 78 79static int adis16060_read_raw(struct iio_dev *indio_dev, 80 struct iio_chan_spec const *chan, 81 int *val, int *val2, 82 long mask) 83{ 84 u16 tval = 0; 85 int ret; 86 87 switch (mask) { 88 case IIO_CHAN_INFO_RAW: 89 /* Take the iio_dev status lock */ 90 mutex_lock(&indio_dev->mlock); 91 ret = adis16060_spi_write(indio_dev, chan->address); 92 if (ret < 0) { 93 mutex_unlock(&indio_dev->mlock); 94 return ret; 95 } 96 ret = adis16060_spi_read(indio_dev, &tval); 97 mutex_unlock(&indio_dev->mlock); 98 *val = tval; 99 return IIO_VAL_INT; 100 case IIO_CHAN_INFO_OFFSET: 101 *val = -7; 102 *val2 = 461117; 103 return IIO_VAL_INT_PLUS_MICRO; 104 case IIO_CHAN_INFO_SCALE: 105 *val = 0; 106 *val2 = 34000; 107 return IIO_VAL_INT_PLUS_MICRO; 108 } 109 110 return -EINVAL; 111} 112 113static const struct iio_info adis16060_info = { 114 .read_raw = &adis16060_read_raw, 115 .driver_module = THIS_MODULE, 116}; 117 118static const struct iio_chan_spec adis16060_channels[] = { 119 { 120 .type = IIO_ANGL_VEL, 121 .modified = 1, 122 .channel2 = IIO_MOD_Z, 123 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 124 .address = ADIS16060_GYRO, 125 }, { 126 .type = IIO_VOLTAGE, 127 .indexed = 1, 128 .channel = 0, 129 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 130 .address = ADIS16060_AIN1, 131 }, { 132 .type = IIO_VOLTAGE, 133 .indexed = 1, 134 .channel = 1, 135 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 136 .address = ADIS16060_AIN2, 137 }, { 138 .type = IIO_TEMP, 139 .indexed = 1, 140 .channel = 0, 141 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 142 BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE), 143 .address = ADIS16060_TEMP_OUT, 144 } 145}; 146 147static int adis16060_r_probe(struct spi_device *spi) 148{ 149 int ret; 150 struct adis16060_state *st; 151 struct iio_dev *indio_dev; 152 153 /* setup the industrialio driver allocated elements */ 154 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 155 if (!indio_dev) 156 return -ENOMEM; 157 /* this is only used for removal purposes */ 158 spi_set_drvdata(spi, indio_dev); 159 st = iio_priv(indio_dev); 160 st->us_r = spi; 161 mutex_init(&st->buf_lock); 162 163 indio_dev->name = spi->dev.driver->name; 164 indio_dev->dev.parent = &spi->dev; 165 indio_dev->info = &adis16060_info; 166 indio_dev->modes = INDIO_DIRECT_MODE; 167 indio_dev->channels = adis16060_channels; 168 indio_dev->num_channels = ARRAY_SIZE(adis16060_channels); 169 170 ret = devm_iio_device_register(&spi->dev, indio_dev); 171 if (ret) 172 return ret; 173 174 adis16060_iio_dev = indio_dev; 175 return 0; 176} 177 178static int adis16060_w_probe(struct spi_device *spi) 179{ 180 int ret; 181 struct iio_dev *indio_dev = adis16060_iio_dev; 182 struct adis16060_state *st; 183 184 if (!indio_dev) { 185 ret = -ENODEV; 186 goto error_ret; 187 } 188 st = iio_priv(indio_dev); 189 spi_set_drvdata(spi, indio_dev); 190 st->us_w = spi; 191 return 0; 192 193error_ret: 194 return ret; 195} 196 197static int adis16060_w_remove(struct spi_device *spi) 198{ 199 return 0; 200} 201 202static struct spi_driver adis16060_r_driver = { 203 .driver = { 204 .name = "adis16060_r", 205 .owner = THIS_MODULE, 206 }, 207 .probe = adis16060_r_probe, 208}; 209 210static struct spi_driver adis16060_w_driver = { 211 .driver = { 212 .name = "adis16060_w", 213 .owner = THIS_MODULE, 214 }, 215 .probe = adis16060_w_probe, 216 .remove = adis16060_w_remove, 217}; 218 219static __init int adis16060_init(void) 220{ 221 int ret; 222 223 ret = spi_register_driver(&adis16060_r_driver); 224 if (ret < 0) 225 return ret; 226 227 ret = spi_register_driver(&adis16060_w_driver); 228 if (ret < 0) { 229 spi_unregister_driver(&adis16060_r_driver); 230 return ret; 231 } 232 233 return 0; 234} 235module_init(adis16060_init); 236 237static __exit void adis16060_exit(void) 238{ 239 spi_unregister_driver(&adis16060_w_driver); 240 spi_unregister_driver(&adis16060_r_driver); 241} 242module_exit(adis16060_exit); 243 244MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); 245MODULE_DESCRIPTION("Analog Devices ADIS16060 Yaw Rate Gyroscope Driver"); 246MODULE_LICENSE("GPL v2"); 247