diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2013-06-10 10:00:00 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2013-06-11 15:34:36 -0400 |
commit | 32341859f04e0f0d418d0d0eec903a959cb09ebb (patch) | |
tree | a7aafb3ea7b602aed94bfa7a4e62497cd54de6d6 /drivers/iio | |
parent | 597e1a86df7965f638045fea04bd3fde57f8bd04 (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/Kconfig | 7 | ||||
-rw-r--r-- | drivers/iio/gyro/Makefile | 1 | ||||
-rw-r--r-- | drivers/iio/gyro/adis16130.c | 207 |
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 | ||
13 | config 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 | |||
13 | config ADIS16136 | 20 | config 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 | ||
5 | obj-$(CONFIG_ADIS16080) += adis16080.o | 5 | obj-$(CONFIG_ADIS16080) += adis16080.o |
6 | obj-$(CONFIG_ADIS16130) += adis16130.o | ||
6 | obj-$(CONFIG_ADIS16136) += adis16136.o | 7 | obj-$(CONFIG_ADIS16136) += adis16136.o |
7 | obj-$(CONFIG_ADXRS450) += adxrs450.o | 8 | obj-$(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 | **/ | ||
40 | struct adis16130_state { | ||
41 | struct spi_device *us; | ||
42 | struct mutex buf_lock; | ||
43 | u8 buf[4] ____cacheline_aligned; | ||
44 | }; | ||
45 | |||
46 | static 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 | |||
73 | static 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 | |||
124 | static 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 | |||
144 | static const struct iio_info adis16130_info = { | ||
145 | .read_raw = &adis16130_read_raw, | ||
146 | .driver_module = THIS_MODULE, | ||
147 | }; | ||
148 | |||
149 | static 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 | |||
179 | error_free_dev: | ||
180 | iio_device_free(indio_dev); | ||
181 | |||
182 | error_ret: | ||
183 | return ret; | ||
184 | } | ||
185 | |||
186 | static 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 | |||
194 | static struct spi_driver adis16130_driver = { | ||
195 | .driver = { | ||
196 | .name = "adis16130", | ||
197 | .owner = THIS_MODULE, | ||
198 | }, | ||
199 | .probe = adis16130_probe, | ||
200 | .remove = adis16130_remove, | ||
201 | }; | ||
202 | module_spi_driver(adis16130_driver); | ||
203 | |||
204 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | ||
205 | MODULE_DESCRIPTION("Analog Devices ADIS16130 High Precision Angular Rate"); | ||
206 | MODULE_LICENSE("GPL v2"); | ||
207 | MODULE_ALIAS("spi:adis16130"); | ||