aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2013-01-09 09:01:00 -0500
committerJonathan Cameron <jic23@kernel.org>2013-01-26 05:30:23 -0500
commita9fbbee8a2e90f88ff605ec72b388ec20b808ee4 (patch)
tree6d903ed010abfe0c6aa15f55e0946bb864f3d2e2 /drivers/iio
parent668cce24965a454f110c5835e0a2198a9aea55af (diff)
staging:iio:adis16080: Move out of staging
The driver is rather simple and in a good shape. It follows the IIO ABI and the standard codechecker tools do not report any issues, so move it out of staging. While moving it also remove one outdated 'fixme' comment. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r--drivers/iio/gyro/Kconfig7
-rw-r--r--drivers/iio/gyro/Makefile1
-rw-r--r--drivers/iio/gyro/adis16080.c259
3 files changed, 267 insertions, 0 deletions
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
index 96b68f63a902..752ac8a3448b 100644
--- a/drivers/iio/gyro/Kconfig
+++ b/drivers/iio/gyro/Kconfig
@@ -3,6 +3,13 @@
3# 3#
4menu "Digital gyroscope sensors" 4menu "Digital gyroscope sensors"
5 5
6config ADIS16080
7 tristate "Analog Devices ADIS16080/100 Yaw Rate Gyroscope with SPI driver"
8 depends on SPI
9 help
10 Say yes here to build support for Analog Devices ADIS16080, ADIS16100 Yaw
11 Rate Gyroscope with SPI.
12
6config ADIS16136 13config ADIS16136
7 tristate "Analog devices ADIS16136 and similar gyroscopes driver" 14 tristate "Analog devices ADIS16136 and similar gyroscopes driver"
8 depends on SPI_MASTER 15 depends on SPI_MASTER
diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile
index 702a058907e3..9b090ee084d3 100644
--- a/drivers/iio/gyro/Makefile
+++ b/drivers/iio/gyro/Makefile
@@ -2,5 +2,6 @@
2# Makefile for industrial I/O gyroscope sensor drivers 2# Makefile for industrial I/O gyroscope sensor drivers
3# 3#
4 4
5obj-$(CONFIG_ADIS16080) += adis16080.o
5obj-$(CONFIG_ADIS16136) += adis16136.o 6obj-$(CONFIG_ADIS16136) += adis16136.o
6obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o 7obj-$(CONFIG_HID_SENSOR_GYRO_3D) += hid-sensor-gyro-3d.o
diff --git a/drivers/iio/gyro/adis16080.c b/drivers/iio/gyro/adis16080.c
new file mode 100644
index 000000000000..1861287911f1
--- /dev/null
+++ b/drivers/iio/gyro/adis16080.c
@@ -0,0 +1,259 @@
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 <linux/iio/iio.h>
18#include <linux/iio/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
32struct adis16080_chip_info {
33 int scale_val;
34 int scale_val2;
35};
36
37/**
38 * struct adis16080_state - device instance specific data
39 * @us: actual spi_device to write data
40 * @info: chip specific parameters
41 * @buf: transmit or receive buffer
42 **/
43struct adis16080_state {
44 struct spi_device *us;
45 const struct adis16080_chip_info *info;
46
47 __be16 buf ____cacheline_aligned;
48};
49
50static int adis16080_read_sample(struct iio_dev *indio_dev,
51 u16 addr, int *val)
52{
53 struct adis16080_state *st = iio_priv(indio_dev);
54 struct spi_message m;
55 int ret;
56 struct spi_transfer t[] = {
57 {
58 .tx_buf = &st->buf,
59 .len = 2,
60 .cs_change = 1,
61 }, {
62 .rx_buf = &st->buf,
63 .len = 2,
64 },
65 };
66
67 st->buf = cpu_to_be16(addr | ADIS16080_DIN_WRITE);
68
69 spi_message_init(&m);
70 spi_message_add_tail(&t[0], &m);
71 spi_message_add_tail(&t[1], &m);
72
73 ret = spi_sync(st->us, &m);
74 if (ret == 0)
75 *val = sign_extend32(be16_to_cpu(st->buf), 11);
76
77 return ret;
78}
79
80static int adis16080_read_raw(struct iio_dev *indio_dev,
81 struct iio_chan_spec const *chan,
82 int *val,
83 int *val2,
84 long mask)
85{
86 struct adis16080_state *st = iio_priv(indio_dev);
87 int ret;
88
89 switch (mask) {
90 case IIO_CHAN_INFO_RAW:
91 mutex_lock(&indio_dev->mlock);
92 ret = adis16080_read_sample(indio_dev, chan->address, val);
93 mutex_unlock(&indio_dev->mlock);
94 return ret ? ret : IIO_VAL_INT;
95 case IIO_CHAN_INFO_SCALE:
96 switch (chan->type) {
97 case IIO_ANGL_VEL:
98 *val = st->info->scale_val;
99 *val2 = st->info->scale_val2;
100 return IIO_VAL_FRACTIONAL;
101 case IIO_VOLTAGE:
102 /* VREF = 5V, 12 bits */
103 *val = 5000;
104 *val2 = 12;
105 return IIO_VAL_FRACTIONAL_LOG2;
106 case IIO_TEMP:
107 /* 85 C = 585, 25 C = 0 */
108 *val = 85000 - 25000;
109 *val2 = 585;
110 return IIO_VAL_FRACTIONAL;
111 default:
112 return -EINVAL;
113 }
114 case IIO_CHAN_INFO_OFFSET:
115 switch (chan->type) {
116 case IIO_VOLTAGE:
117 /* 2.5 V = 0 */
118 *val = 2048;
119 return IIO_VAL_INT;
120 case IIO_TEMP:
121 /* 85 C = 585, 25 C = 0 */
122 *val = DIV_ROUND_CLOSEST(25 * 585, 85 - 25);
123 return IIO_VAL_INT;
124 default:
125 return -EINVAL;
126 }
127 default:
128 break;
129 }
130
131 return -EINVAL;
132}
133
134static const struct iio_chan_spec adis16080_channels[] = {
135 {
136 .type = IIO_ANGL_VEL,
137 .modified = 1,
138 .channel2 = IIO_MOD_Z,
139 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
140 IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
141 .address = ADIS16080_DIN_GYRO,
142 }, {
143 .type = IIO_VOLTAGE,
144 .indexed = 1,
145 .channel = 0,
146 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
147 IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
148 IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
149 .address = ADIS16080_DIN_AIN1,
150 }, {
151 .type = IIO_VOLTAGE,
152 .indexed = 1,
153 .channel = 1,
154 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
155 IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
156 IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
157 .address = ADIS16080_DIN_AIN2,
158 }, {
159 .type = IIO_TEMP,
160 .indexed = 1,
161 .channel = 0,
162 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
163 IIO_CHAN_INFO_SCALE_SEPARATE_BIT |
164 IIO_CHAN_INFO_OFFSET_SEPARATE_BIT,
165 .address = ADIS16080_DIN_TEMP,
166 }
167};
168
169static const struct iio_info adis16080_info = {
170 .read_raw = &adis16080_read_raw,
171 .driver_module = THIS_MODULE,
172};
173
174enum {
175 ID_ADIS16080,
176 ID_ADIS16100,
177};
178
179static const struct adis16080_chip_info adis16080_chip_info[] = {
180 [ID_ADIS16080] = {
181 /* 80 degree = 819, 819 rad = 46925 degree */
182 .scale_val = 80,
183 .scale_val2 = 46925,
184 },
185 [ID_ADIS16100] = {
186 /* 300 degree = 1230, 1230 rad = 70474 degree */
187 .scale_val = 300,
188 .scale_val2 = 70474,
189 },
190};
191
192static int adis16080_probe(struct spi_device *spi)
193{
194 const struct spi_device_id *id = spi_get_device_id(spi);
195 int ret;
196 struct adis16080_state *st;
197 struct iio_dev *indio_dev;
198
199 /* setup the industrialio driver allocated elements */
200 indio_dev = iio_device_alloc(sizeof(*st));
201 if (indio_dev == NULL) {
202 ret = -ENOMEM;
203 goto error_ret;
204 }
205 st = iio_priv(indio_dev);
206 /* this is only used for removal purposes */
207 spi_set_drvdata(spi, indio_dev);
208
209 /* Allocate the comms buffers */
210 st->us = spi;
211 st->info = &adis16080_chip_info[id->driver_data];
212
213 indio_dev->name = spi->dev.driver->name;
214 indio_dev->channels = adis16080_channels;
215 indio_dev->num_channels = ARRAY_SIZE(adis16080_channels);
216 indio_dev->dev.parent = &spi->dev;
217 indio_dev->info = &adis16080_info;
218 indio_dev->modes = INDIO_DIRECT_MODE;
219
220 ret = iio_device_register(indio_dev);
221 if (ret)
222 goto error_free_dev;
223 return 0;
224
225error_free_dev:
226 iio_device_free(indio_dev);
227error_ret:
228 return ret;
229}
230
231static int adis16080_remove(struct spi_device *spi)
232{
233 iio_device_unregister(spi_get_drvdata(spi));
234 iio_device_free(spi_get_drvdata(spi));
235
236 return 0;
237}
238
239static const struct spi_device_id adis16080_ids[] = {
240 { "adis16080", ID_ADIS16080 },
241 { "adis16100", ID_ADIS16100 },
242 {},
243};
244MODULE_DEVICE_TABLE(spi, adis16080_ids);
245
246static struct spi_driver adis16080_driver = {
247 .driver = {
248 .name = "adis16080",
249 .owner = THIS_MODULE,
250 },
251 .probe = adis16080_probe,
252 .remove = adis16080_remove,
253 .id_table = adis16080_ids,
254};
255module_spi_driver(adis16080_driver);
256
257MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
258MODULE_DESCRIPTION("Analog Devices ADIS16080/100 Yaw Rate Gyroscope Driver");
259MODULE_LICENSE("GPL v2");