aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2013-06-10 10:00:00 -0400
committerJonathan Cameron <jic23@kernel.org>2013-06-11 15:34:36 -0400
commit32341859f04e0f0d418d0d0eec903a959cb09ebb (patch)
treea7aafb3ea7b602aed94bfa7a4e62497cd54de6d6 /drivers/iio
parent597e1a86df7965f638045fea04bd3fde57f8bd04 (diff)
staging:iio:adis16130: Move out of staging
The adis16130 driver is fairly simple and it a good shape now, so move it out of staging. Remove an outdated FIXME along the way. 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/adis16130.c207
3 files changed, 215 insertions, 0 deletions
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
index b8daf1b2ea06..8498e9dcda68 100644
--- a/drivers/iio/gyro/Kconfig
+++ b/drivers/iio/gyro/Kconfig
@@ -10,6 +10,13 @@ config ADIS16080
10 Say yes here to build support for Analog Devices ADIS16080, ADIS16100 Yaw 10 Say yes here to build support for Analog Devices ADIS16080, ADIS16100 Yaw
11 Rate Gyroscope with SPI. 11 Rate Gyroscope with SPI.
12 12
13config ADIS16130
14 tristate "Analog Devices ADIS16130 High Precision Angular Rate Sensor driver"
15 depends on SPI
16 help
17 Say yes here to build support for Analog Devices ADIS16130 High Precision
18 Angular Rate Sensor driver.
19
13config ADIS16136 20config ADIS16136
14 tristate "Analog devices ADIS16136 and similar gyroscopes driver" 21 tristate "Analog devices ADIS16136 and similar gyroscopes driver"
15 depends on SPI_MASTER 22 depends on SPI_MASTER
diff --git a/drivers/iio/gyro/Makefile b/drivers/iio/gyro/Makefile
index 225d289082e6..e9dc034aa18b 100644
--- a/drivers/iio/gyro/Makefile
+++ b/drivers/iio/gyro/Makefile
@@ -3,6 +3,7 @@
3# 3#
4 4
5obj-$(CONFIG_ADIS16080) += adis16080.o 5obj-$(CONFIG_ADIS16080) += adis16080.o
6obj-$(CONFIG_ADIS16130) += adis16130.o
6obj-$(CONFIG_ADIS16136) += adis16136.o 7obj-$(CONFIG_ADIS16136) += adis16136.o
7obj-$(CONFIG_ADXRS450) += adxrs450.o 8obj-$(CONFIG_ADXRS450) += adxrs450.o
8 9
diff --git a/drivers/iio/gyro/adis16130.c b/drivers/iio/gyro/adis16130.c
new file mode 100644
index 000000000000..129acdf801a4
--- /dev/null
+++ b/drivers/iio/gyro/adis16130.c
@@ -0,0 +1,207 @@
1/*
2 * ADIS16130 Digital Output, High Precision Angular Rate Sensor driver
3 *
4 * Copyright 2010 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/mutex.h>
10#include <linux/kernel.h>
11#include <linux/spi/spi.h>
12#include <linux/module.h>
13
14#include <linux/iio/iio.h>
15
16#define ADIS16130_CON 0x0
17#define ADIS16130_CON_RD (1 << 6)
18#define ADIS16130_IOP 0x1
19
20/* 1 = data-ready signal low when unread data on all channels; */
21#define ADIS16130_IOP_ALL_RDY (1 << 3)
22#define ADIS16130_IOP_SYNC (1 << 0) /* 1 = synchronization enabled */
23#define ADIS16130_RATEDATA 0x8 /* Gyroscope output, rate of rotation */
24#define ADIS16130_TEMPDATA 0xA /* Temperature output */
25#define ADIS16130_RATECS 0x28 /* Gyroscope channel setup */
26#define ADIS16130_RATECS_EN (1 << 3) /* 1 = channel enable; */
27#define ADIS16130_TEMPCS 0x2A /* Temperature channel setup */
28#define ADIS16130_TEMPCS_EN (1 << 3)
29#define ADIS16130_RATECONV 0x30
30#define ADIS16130_TEMPCONV 0x32
31#define ADIS16130_MODE 0x38
32#define ADIS16130_MODE_24BIT (1 << 1) /* 1 = 24-bit resolution; */
33
34/**
35 * struct adis16130_state - device instance specific data
36 * @us: actual spi_device to write data
37 * @buf_lock: mutex to protect tx and rx
38 * @buf: unified tx/rx buffer
39 **/
40struct adis16130_state {
41 struct spi_device *us;
42 struct mutex buf_lock;
43 u8 buf[4] ____cacheline_aligned;
44};
45
46static int adis16130_spi_read(struct iio_dev *indio_dev, u8 reg_addr, u32 *val)
47{
48 int ret;
49 struct adis16130_state *st = iio_priv(indio_dev);
50 struct spi_message msg;
51 struct spi_transfer xfer = {
52 .tx_buf = st->buf,
53 .rx_buf = st->buf,
54 .len = 4,
55 };
56
57 mutex_lock(&st->buf_lock);
58
59 st->buf[0] = ADIS16130_CON_RD | reg_addr;
60 st->buf[1] = st->buf[2] = st->buf[3] = 0;
61
62 spi_message_init(&msg);
63 spi_message_add_tail(&xfer, &msg);
64 ret = spi_sync(st->us, &msg);
65
66 if (ret == 0)
67 *val = (st->buf[1] << 16) | (st->buf[2] << 8) | st->buf[3];
68 mutex_unlock(&st->buf_lock);
69
70 return ret;
71}
72
73static int adis16130_read_raw(struct iio_dev *indio_dev,
74 struct iio_chan_spec const *chan,
75 int *val, int *val2,
76 long mask)
77{
78 int ret;
79 u32 temp;
80
81 switch (mask) {
82 case IIO_CHAN_INFO_RAW:
83 /* Take the iio_dev status lock */
84 mutex_lock(&indio_dev->mlock);
85 ret = adis16130_spi_read(indio_dev, chan->address, &temp);
86 mutex_unlock(&indio_dev->mlock);
87 if (ret)
88 return ret;
89 *val = temp;
90 return IIO_VAL_INT;
91 case IIO_CHAN_INFO_SCALE:
92 switch (chan->type) {
93 case IIO_ANGL_VEL:
94 /* 0 degree = 838860, 250 degree = 14260608 */
95 *val = 250;
96 *val2 = 336440817; /* RAD_TO_DEGREE(14260608 - 8388608) */
97 return IIO_VAL_FRACTIONAL;
98 case IIO_TEMP:
99 /* 0C = 8036283, 105C = 9516048 */
100 *val = 105000;
101 *val2 = 9516048 - 8036283;
102 return IIO_VAL_FRACTIONAL;
103 default:
104 return -EINVAL;
105 }
106 break;
107 case IIO_CHAN_INFO_OFFSET:
108 switch (chan->type) {
109 case IIO_ANGL_VEL:
110 *val = -8388608;
111 return IIO_VAL_INT;
112 case IIO_TEMP:
113 *val = -8036283;
114 return IIO_VAL_INT;
115 default:
116 return -EINVAL;
117 }
118 break;
119 }
120
121 return -EINVAL;
122}
123
124static const struct iio_chan_spec adis16130_channels[] = {
125 {
126 .type = IIO_ANGL_VEL,
127 .modified = 1,
128 .channel2 = IIO_MOD_Z,
129 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
130 BIT(IIO_CHAN_INFO_SCALE) |
131 BIT(IIO_CHAN_INFO_OFFSET),
132 .address = ADIS16130_RATEDATA,
133 }, {
134 .type = IIO_TEMP,
135 .indexed = 1,
136 .channel = 0,
137 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
138 BIT(IIO_CHAN_INFO_SCALE) |
139 BIT(IIO_CHAN_INFO_OFFSET),
140 .address = ADIS16130_TEMPDATA,
141 }
142};
143
144static const struct iio_info adis16130_info = {
145 .read_raw = &adis16130_read_raw,
146 .driver_module = THIS_MODULE,
147};
148
149static int adis16130_probe(struct spi_device *spi)
150{
151 int ret;
152 struct adis16130_state *st;
153 struct iio_dev *indio_dev;
154
155 /* setup the industrialio driver allocated elements */
156 indio_dev = iio_device_alloc(sizeof(*st));
157 if (indio_dev == NULL) {
158 ret = -ENOMEM;
159 goto error_ret;
160 }
161 st = iio_priv(indio_dev);
162 /* this is only used for removal purposes */
163 spi_set_drvdata(spi, indio_dev);
164 st->us = spi;
165 mutex_init(&st->buf_lock);
166 indio_dev->name = spi->dev.driver->name;
167 indio_dev->channels = adis16130_channels;
168 indio_dev->num_channels = ARRAY_SIZE(adis16130_channels);
169 indio_dev->dev.parent = &spi->dev;
170 indio_dev->info = &adis16130_info;
171 indio_dev->modes = INDIO_DIRECT_MODE;
172
173 ret = iio_device_register(indio_dev);
174 if (ret)
175 goto error_free_dev;
176
177 return 0;
178
179error_free_dev:
180 iio_device_free(indio_dev);
181
182error_ret:
183 return ret;
184}
185
186static int adis16130_remove(struct spi_device *spi)
187{
188 iio_device_unregister(spi_get_drvdata(spi));
189 iio_device_free(spi_get_drvdata(spi));
190
191 return 0;
192}
193
194static struct spi_driver adis16130_driver = {
195 .driver = {
196 .name = "adis16130",
197 .owner = THIS_MODULE,
198 },
199 .probe = adis16130_probe,
200 .remove = adis16130_remove,
201};
202module_spi_driver(adis16130_driver);
203
204MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
205MODULE_DESCRIPTION("Analog Devices ADIS16130 High Precision Angular Rate");
206MODULE_LICENSE("GPL v2");
207MODULE_ALIAS("spi:adis16130");