1/* 2 * ADIS16080/100 Yaw Rate Gyroscope with SPI driver 3 * 4 * Copyright 2010 Analog Devices Inc. 5 * 6 * Licensed under the GPL-2 or later. 7 */ 8#include <linux/delay.h> 9#include <linux/mutex.h> 10#include <linux/device.h> 11#include <linux/kernel.h> 12#include <linux/spi/spi.h> 13#include <linux/slab.h> 14#include <linux/sysfs.h> 15#include <linux/module.h> 16 17#include "../iio.h" 18#include "../sysfs.h" 19 20#define ADIS16080_DIN_GYRO (0 << 10) /* Gyroscope output */ 21#define ADIS16080_DIN_TEMP (1 << 10) /* Temperature output */ 22#define ADIS16080_DIN_AIN1 (2 << 10) 23#define ADIS16080_DIN_AIN2 (3 << 10) 24 25/* 26 * 1: Write contents on DIN to control register. 27 * 0: No changes to control register. 28 */ 29 30#define ADIS16080_DIN_WRITE (1 << 15) 31 32/** 33 * struct adis16080_state - device instance specific data 34 * @us: actual spi_device to write data 35 * @buf: transmit or receive buffer 36 * @buf_lock: mutex to protect tx and rx 37 **/ 38struct adis16080_state { 39 struct spi_device *us; 40 struct mutex buf_lock; 41 42 u8 buf[2] ____cacheline_aligned; 43}; 44 45static int adis16080_spi_write(struct iio_dev *indio_dev, 46 u16 val) 47{ 48 int ret; 49 struct adis16080_state *st = iio_priv(indio_dev); 50 51 mutex_lock(&st->buf_lock); 52 st->buf[0] = val >> 8; 53 st->buf[1] = val; 54 55 ret = spi_write(st->us, st->buf, 2); 56 mutex_unlock(&st->buf_lock); 57 58 return ret; 59} 60 61static int adis16080_spi_read(struct iio_dev *indio_dev, 62 u16 *val) 63{ 64 int ret; 65 struct adis16080_state *st = iio_priv(indio_dev); 66 67 mutex_lock(&st->buf_lock); 68 69 ret = spi_read(st->us, st->buf, 2); 70 71 if (ret == 0) 72 *val = ((st->buf[0] & 0xF) << 8) | st->buf[1]; 73 mutex_unlock(&st->buf_lock); 74 75 return ret; 76} 77 78static int adis16080_read_raw(struct iio_dev *indio_dev, 79 struct iio_chan_spec const *chan, 80 int *val, 81 int *val2, 82 long mask) 83{ 84 int ret = -EINVAL; 85 u16 ut; 86 /* Take the iio_dev status lock */ 87 88 mutex_lock(&indio_dev->mlock); 89 switch (mask) { 90 case 0: 91 ret = adis16080_spi_write(indio_dev, 92 chan->address | 93 ADIS16080_DIN_WRITE); 94 if (ret < 0) 95 break; 96 ret = adis16080_spi_read(indio_dev, &ut); 97 if (ret < 0) 98 break; 99 *val = ut; 100 ret = IIO_VAL_INT; 101 break; 102 } 103 mutex_unlock(&indio_dev->mlock); 104 105 return ret; 106} 107 108static const struct iio_chan_spec adis16080_channels[] = { 109 { 110 .type = IIO_ANGL_VEL, 111 .modified = 1, 112 .channel2 = IIO_MOD_Z, 113 .address = ADIS16080_DIN_GYRO, 114 }, { 115 .type = IIO_VOLTAGE, 116 .indexed = 1, 117 .channel = 0, 118 .address = ADIS16080_DIN_AIN1, 119 }, { 120 .type = IIO_VOLTAGE, 121 .indexed = 1, 122 .channel = 1, 123 .address = ADIS16080_DIN_AIN2, 124 }, { 125 .type = IIO_TEMP, 126 .indexed = 1, 127 .channel = 0, 128 .address = ADIS16080_DIN_TEMP, 129 } 130}; 131 132static const struct iio_info adis16080_info = { 133 .read_raw = &adis16080_read_raw, 134 .driver_module = THIS_MODULE, 135}; 136 137static int __devinit adis16080_probe(struct spi_device *spi) 138{ 139 int ret; 140 struct adis16080_state *st; 141 struct iio_dev *indio_dev; 142 143 /* setup the industrialio driver allocated elements */ 144 indio_dev = iio_allocate_device(sizeof(*st)); 145 if (indio_dev == NULL) { 146 ret = -ENOMEM; 147 goto error_ret; 148 } 149 st = iio_priv(indio_dev); 150 /* this is only used for removal purposes */ 151 spi_set_drvdata(spi, indio_dev); 152 153 /* Allocate the comms buffers */ 154 st->us = spi; 155 mutex_init(&st->buf_lock); 156 157 indio_dev->name = spi->dev.driver->name; 158 indio_dev->channels = adis16080_channels; 159 indio_dev->num_channels = ARRAY_SIZE(adis16080_channels); 160 indio_dev->dev.parent = &spi->dev; 161 indio_dev->info = &adis16080_info; 162 indio_dev->modes = INDIO_DIRECT_MODE; 163 164 ret = iio_device_register(indio_dev); 165 if (ret) 166 goto error_free_dev; 167 return 0; 168 169error_free_dev: 170 iio_free_device(indio_dev); 171error_ret: 172 return ret; 173} 174 175/* fixme, confirm ordering in this function */ 176static int adis16080_remove(struct spi_device *spi) 177{ 178 iio_device_unregister(spi_get_drvdata(spi)); 179 iio_free_device(spi_get_drvdata(spi)); 180 181 return 0; 182} 183 184static struct spi_driver adis16080_driver = { 185 .driver = { 186 .name = "adis16080", 187 .owner = THIS_MODULE, 188 }, 189 .probe = adis16080_probe, 190 .remove = __devexit_p(adis16080_remove), 191}; 192module_spi_driver(adis16080_driver); 193 194MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); 195MODULE_DESCRIPTION("Analog Devices ADIS16080/100 Yaw Rate Gyroscope Driver"); 196MODULE_LICENSE("GPL v2"); 197MODULE_ALIAS("spi:adis16080"); 198