Commit c01ef023ec1d2af185e55f7600405dcce1813d5d
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
Merge branch 'togreg' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-next
Showing 19 changed files Inline Diff
- drivers/iio/adc/Kconfig
- drivers/iio/adc/Makefile
- drivers/iio/adc/ad7266.c
- drivers/iio/dac/Kconfig
- drivers/iio/dac/ad5064.c
- drivers/iio/industrialio-core.c
- drivers/iio/inkern.c
- drivers/staging/iio/accel/adis16201_core.c
- drivers/staging/iio/accel/adis16203_core.c
- drivers/staging/iio/accel/adis16204_core.c
- drivers/staging/iio/accel/adis16209_core.c
- drivers/staging/iio/accel/adis16220_core.c
- drivers/staging/iio/accel/adis16240_core.c
- drivers/staging/iio/gyro/adis16260_core.c
- drivers/staging/iio/iio_hwmon.c
- drivers/staging/iio/imu/adis16400_core.c
- include/linux/iio/consumer.h
- include/linux/iio/types.h
- include/linux/platform_data/ad7266.h
drivers/iio/adc/Kconfig
1 | # | 1 | # |
2 | # ADC drivers | 2 | # ADC drivers |
3 | # | 3 | # |
4 | menu "Analog to digital converters" | 4 | menu "Analog to digital converters" |
5 | 5 | ||
6 | config AD7266 | ||
7 | tristate "Analog Devices AD7265/AD7266 ADC driver" | ||
8 | depends on SPI_MASTER | ||
9 | select IIO_BUFFER | ||
10 | select IIO_TRIGGER | ||
11 | select IIO_TRIGGERED_BUFFER | ||
12 | help | ||
13 | Say yes here to build support for Analog Devices AD7265 and AD7266 | ||
14 | ADCs. | ||
15 | |||
6 | config AT91_ADC | 16 | config AT91_ADC |
7 | tristate "Atmel AT91 ADC" | 17 | tristate "Atmel AT91 ADC" |
8 | depends on ARCH_AT91 | 18 | depends on ARCH_AT91 |
9 | select IIO_BUFFER | 19 | select IIO_BUFFER |
10 | select IIO_TRIGGERED_BUFFER | 20 | select IIO_TRIGGERED_BUFFER |
11 | select SYSFS | 21 | select SYSFS |
12 | help | 22 | help |
13 | Say yes here to build support for Atmel AT91 ADC. | 23 | Say yes here to build support for Atmel AT91 ADC. |
14 | 24 | ||
15 | endmenu | 25 | endmenu |
16 | 26 |
drivers/iio/adc/Makefile
1 | # | 1 | # |
2 | # Makefile for IIO ADC drivers | 2 | # Makefile for IIO ADC drivers |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_AD7266) += ad7266.o | ||
5 | obj-$(CONFIG_AT91_ADC) += at91_adc.o | 6 | obj-$(CONFIG_AT91_ADC) += at91_adc.o |
6 | 7 |
drivers/iio/adc/ad7266.c
File was created | 1 | /* | |
2 | * AD7266/65 SPI ADC driver | ||
3 | * | ||
4 | * Copyright 2012 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/device.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/spi/spi.h> | ||
13 | #include <linux/regulator/consumer.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/gpio.h> | ||
16 | #include <linux/module.h> | ||
17 | |||
18 | #include <linux/interrupt.h> | ||
19 | |||
20 | #include <linux/iio/iio.h> | ||
21 | #include <linux/iio/buffer.h> | ||
22 | #include <linux/iio/trigger_consumer.h> | ||
23 | #include <linux/iio/triggered_buffer.h> | ||
24 | |||
25 | #include <linux/platform_data/ad7266.h> | ||
26 | |||
27 | struct ad7266_state { | ||
28 | struct spi_device *spi; | ||
29 | struct regulator *reg; | ||
30 | unsigned long vref_uv; | ||
31 | |||
32 | struct spi_transfer single_xfer[3]; | ||
33 | struct spi_message single_msg; | ||
34 | |||
35 | enum ad7266_range range; | ||
36 | enum ad7266_mode mode; | ||
37 | bool fixed_addr; | ||
38 | struct gpio gpios[3]; | ||
39 | |||
40 | /* | ||
41 | * DMA (thus cache coherency maintenance) requires the | ||
42 | * transfer buffers to live in their own cache lines. | ||
43 | * The buffer needs to be large enough to hold two samples (4 bytes) and | ||
44 | * the naturally aligned timestamp (8 bytes). | ||
45 | */ | ||
46 | uint8_t data[ALIGN(4, sizeof(s64)) + sizeof(s64)] ____cacheline_aligned; | ||
47 | }; | ||
48 | |||
49 | static int ad7266_wakeup(struct ad7266_state *st) | ||
50 | { | ||
51 | /* Any read with >= 2 bytes will wake the device */ | ||
52 | return spi_read(st->spi, st->data, 2); | ||
53 | } | ||
54 | |||
55 | static int ad7266_powerdown(struct ad7266_state *st) | ||
56 | { | ||
57 | /* Any read with < 2 bytes will powerdown the device */ | ||
58 | return spi_read(st->spi, st->data, 1); | ||
59 | } | ||
60 | |||
61 | static int ad7266_preenable(struct iio_dev *indio_dev) | ||
62 | { | ||
63 | struct ad7266_state *st = iio_priv(indio_dev); | ||
64 | int ret; | ||
65 | |||
66 | ret = ad7266_wakeup(st); | ||
67 | if (ret) | ||
68 | return ret; | ||
69 | |||
70 | ret = iio_sw_buffer_preenable(indio_dev); | ||
71 | if (ret) | ||
72 | ad7266_powerdown(st); | ||
73 | |||
74 | return ret; | ||
75 | } | ||
76 | |||
77 | static int ad7266_postdisable(struct iio_dev *indio_dev) | ||
78 | { | ||
79 | struct ad7266_state *st = iio_priv(indio_dev); | ||
80 | return ad7266_powerdown(st); | ||
81 | } | ||
82 | |||
83 | static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = { | ||
84 | .preenable = &ad7266_preenable, | ||
85 | .postenable = &iio_triggered_buffer_postenable, | ||
86 | .predisable = &iio_triggered_buffer_predisable, | ||
87 | .postdisable = &ad7266_postdisable, | ||
88 | }; | ||
89 | |||
90 | static irqreturn_t ad7266_trigger_handler(int irq, void *p) | ||
91 | { | ||
92 | struct iio_poll_func *pf = p; | ||
93 | struct iio_dev *indio_dev = pf->indio_dev; | ||
94 | struct iio_buffer *buffer = indio_dev->buffer; | ||
95 | struct ad7266_state *st = iio_priv(indio_dev); | ||
96 | int ret; | ||
97 | |||
98 | ret = spi_read(st->spi, st->data, 4); | ||
99 | if (ret == 0) { | ||
100 | if (indio_dev->scan_timestamp) | ||
101 | ((s64 *)st->data)[1] = pf->timestamp; | ||
102 | iio_push_to_buffer(buffer, (u8 *)st->data, pf->timestamp); | ||
103 | } | ||
104 | |||
105 | iio_trigger_notify_done(indio_dev->trig); | ||
106 | |||
107 | return IRQ_HANDLED; | ||
108 | } | ||
109 | |||
110 | static void ad7266_select_input(struct ad7266_state *st, unsigned int nr) | ||
111 | { | ||
112 | unsigned int i; | ||
113 | |||
114 | if (st->fixed_addr) | ||
115 | return; | ||
116 | |||
117 | switch (st->mode) { | ||
118 | case AD7266_MODE_SINGLE_ENDED: | ||
119 | nr >>= 1; | ||
120 | break; | ||
121 | case AD7266_MODE_PSEUDO_DIFF: | ||
122 | nr |= 1; | ||
123 | break; | ||
124 | case AD7266_MODE_DIFF: | ||
125 | nr &= ~1; | ||
126 | break; | ||
127 | } | ||
128 | |||
129 | for (i = 0; i < 3; ++i) | ||
130 | gpio_set_value(st->gpios[i].gpio, (bool)(nr & BIT(i))); | ||
131 | } | ||
132 | |||
133 | static int ad7266_update_scan_mode(struct iio_dev *indio_dev, | ||
134 | const unsigned long *scan_mask) | ||
135 | { | ||
136 | struct ad7266_state *st = iio_priv(indio_dev); | ||
137 | unsigned int nr = find_first_bit(scan_mask, indio_dev->masklength); | ||
138 | |||
139 | ad7266_select_input(st, nr); | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int ad7266_read_single(struct ad7266_state *st, int *val, | ||
145 | unsigned int address) | ||
146 | { | ||
147 | int ret; | ||
148 | |||
149 | ad7266_select_input(st, address); | ||
150 | |||
151 | ret = spi_sync(st->spi, &st->single_msg); | ||
152 | *val = be16_to_cpu(st->data[address % 2]); | ||
153 | |||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | static int ad7266_read_raw(struct iio_dev *indio_dev, | ||
158 | struct iio_chan_spec const *chan, int *val, int *val2, long m) | ||
159 | { | ||
160 | struct ad7266_state *st = iio_priv(indio_dev); | ||
161 | unsigned long scale_uv; | ||
162 | int ret; | ||
163 | |||
164 | switch (m) { | ||
165 | case IIO_CHAN_INFO_RAW: | ||
166 | if (iio_buffer_enabled(indio_dev)) | ||
167 | return -EBUSY; | ||
168 | |||
169 | ret = ad7266_read_single(st, val, chan->address); | ||
170 | if (ret) | ||
171 | return ret; | ||
172 | |||
173 | *val = (*val >> 2) & 0xfff; | ||
174 | if (chan->scan_type.sign == 's') | ||
175 | *val = sign_extend32(*val, 11); | ||
176 | |||
177 | return IIO_VAL_INT; | ||
178 | case IIO_CHAN_INFO_SCALE: | ||
179 | scale_uv = (st->vref_uv * 100); | ||
180 | if (st->mode == AD7266_MODE_DIFF) | ||
181 | scale_uv *= 2; | ||
182 | if (st->range == AD7266_RANGE_2VREF) | ||
183 | scale_uv *= 2; | ||
184 | |||
185 | scale_uv >>= chan->scan_type.realbits; | ||
186 | *val = scale_uv / 100000; | ||
187 | *val2 = (scale_uv % 100000) * 10; | ||
188 | return IIO_VAL_INT_PLUS_MICRO; | ||
189 | case IIO_CHAN_INFO_OFFSET: | ||
190 | if (st->range == AD7266_RANGE_2VREF && | ||
191 | st->mode != AD7266_MODE_DIFF) | ||
192 | *val = 2048; | ||
193 | else | ||
194 | *val = 0; | ||
195 | return IIO_VAL_INT; | ||
196 | } | ||
197 | return -EINVAL; | ||
198 | } | ||
199 | |||
200 | #define AD7266_CHAN(_chan, _sign) { \ | ||
201 | .type = IIO_VOLTAGE, \ | ||
202 | .indexed = 1, \ | ||
203 | .channel = (_chan), \ | ||
204 | .address = (_chan), \ | ||
205 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT \ | ||
206 | | IIO_CHAN_INFO_SCALE_SHARED_BIT \ | ||
207 | | IIO_CHAN_INFO_OFFSET_SHARED_BIT, \ | ||
208 | .scan_index = (_chan), \ | ||
209 | .scan_type = { \ | ||
210 | .sign = (_sign), \ | ||
211 | .realbits = 12, \ | ||
212 | .storagebits = 16, \ | ||
213 | .shift = 2, \ | ||
214 | .endianness = IIO_BE, \ | ||
215 | }, \ | ||
216 | } | ||
217 | |||
218 | #define AD7266_DECLARE_SINGLE_ENDED_CHANNELS(_name, _sign) \ | ||
219 | const struct iio_chan_spec ad7266_channels_##_name[] = { \ | ||
220 | AD7266_CHAN(0, (_sign)), \ | ||
221 | AD7266_CHAN(1, (_sign)), \ | ||
222 | AD7266_CHAN(2, (_sign)), \ | ||
223 | AD7266_CHAN(3, (_sign)), \ | ||
224 | AD7266_CHAN(4, (_sign)), \ | ||
225 | AD7266_CHAN(5, (_sign)), \ | ||
226 | AD7266_CHAN(6, (_sign)), \ | ||
227 | AD7266_CHAN(7, (_sign)), \ | ||
228 | AD7266_CHAN(8, (_sign)), \ | ||
229 | AD7266_CHAN(9, (_sign)), \ | ||
230 | AD7266_CHAN(10, (_sign)), \ | ||
231 | AD7266_CHAN(11, (_sign)), \ | ||
232 | IIO_CHAN_SOFT_TIMESTAMP(13), \ | ||
233 | } | ||
234 | |||
235 | #define AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(_name, _sign) \ | ||
236 | const struct iio_chan_spec ad7266_channels_##_name##_fixed[] = { \ | ||
237 | AD7266_CHAN(0, (_sign)), \ | ||
238 | AD7266_CHAN(1, (_sign)), \ | ||
239 | IIO_CHAN_SOFT_TIMESTAMP(2), \ | ||
240 | } | ||
241 | |||
242 | static AD7266_DECLARE_SINGLE_ENDED_CHANNELS(u, 'u'); | ||
243 | static AD7266_DECLARE_SINGLE_ENDED_CHANNELS(s, 's'); | ||
244 | static AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(u, 'u'); | ||
245 | static AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(s, 's'); | ||
246 | |||
247 | #define AD7266_CHAN_DIFF(_chan, _sign) { \ | ||
248 | .type = IIO_VOLTAGE, \ | ||
249 | .indexed = 1, \ | ||
250 | .channel = (_chan) * 2, \ | ||
251 | .channel2 = (_chan) * 2 + 1, \ | ||
252 | .address = (_chan), \ | ||
253 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT \ | ||
254 | | IIO_CHAN_INFO_SCALE_SHARED_BIT \ | ||
255 | | IIO_CHAN_INFO_OFFSET_SHARED_BIT, \ | ||
256 | .scan_index = (_chan), \ | ||
257 | .scan_type = { \ | ||
258 | .sign = _sign, \ | ||
259 | .realbits = 12, \ | ||
260 | .storagebits = 16, \ | ||
261 | .shift = 2, \ | ||
262 | .endianness = IIO_BE, \ | ||
263 | }, \ | ||
264 | .differential = 1, \ | ||
265 | } | ||
266 | |||
267 | #define AD7266_DECLARE_DIFF_CHANNELS(_name, _sign) \ | ||
268 | const struct iio_chan_spec ad7266_channels_diff_##_name[] = { \ | ||
269 | AD7266_CHAN_DIFF(0, (_sign)), \ | ||
270 | AD7266_CHAN_DIFF(1, (_sign)), \ | ||
271 | AD7266_CHAN_DIFF(2, (_sign)), \ | ||
272 | AD7266_CHAN_DIFF(3, (_sign)), \ | ||
273 | AD7266_CHAN_DIFF(4, (_sign)), \ | ||
274 | AD7266_CHAN_DIFF(5, (_sign)), \ | ||
275 | IIO_CHAN_SOFT_TIMESTAMP(6), \ | ||
276 | } | ||
277 | |||
278 | static AD7266_DECLARE_DIFF_CHANNELS(s, 's'); | ||
279 | static AD7266_DECLARE_DIFF_CHANNELS(u, 'u'); | ||
280 | |||
281 | #define AD7266_DECLARE_DIFF_CHANNELS_FIXED(_name, _sign) \ | ||
282 | const struct iio_chan_spec ad7266_channels_diff_fixed_##_name[] = { \ | ||
283 | AD7266_CHAN_DIFF(0, (_sign)), \ | ||
284 | AD7266_CHAN_DIFF(1, (_sign)), \ | ||
285 | IIO_CHAN_SOFT_TIMESTAMP(2), \ | ||
286 | } | ||
287 | |||
288 | static AD7266_DECLARE_DIFF_CHANNELS_FIXED(s, 's'); | ||
289 | static AD7266_DECLARE_DIFF_CHANNELS_FIXED(u, 'u'); | ||
290 | |||
291 | static const struct iio_info ad7266_info = { | ||
292 | .read_raw = &ad7266_read_raw, | ||
293 | .update_scan_mode = &ad7266_update_scan_mode, | ||
294 | .driver_module = THIS_MODULE, | ||
295 | }; | ||
296 | |||
297 | static unsigned long ad7266_available_scan_masks[] = { | ||
298 | 0x003, | ||
299 | 0x00c, | ||
300 | 0x030, | ||
301 | 0x0c0, | ||
302 | 0x300, | ||
303 | 0xc00, | ||
304 | 0x000, | ||
305 | }; | ||
306 | |||
307 | static unsigned long ad7266_available_scan_masks_diff[] = { | ||
308 | 0x003, | ||
309 | 0x00c, | ||
310 | 0x030, | ||
311 | 0x000, | ||
312 | }; | ||
313 | |||
314 | static unsigned long ad7266_available_scan_masks_fixed[] = { | ||
315 | 0x003, | ||
316 | 0x000, | ||
317 | }; | ||
318 | |||
319 | struct ad7266_chan_info { | ||
320 | const struct iio_chan_spec *channels; | ||
321 | unsigned int num_channels; | ||
322 | unsigned long *scan_masks; | ||
323 | }; | ||
324 | |||
325 | #define AD7266_CHAN_INFO_INDEX(_differential, _signed, _fixed) \ | ||
326 | (((_differential) << 2) | ((_signed) << 1) | ((_fixed) << 0)) | ||
327 | |||
328 | static const struct ad7266_chan_info ad7266_chan_infos[] = { | ||
329 | [AD7266_CHAN_INFO_INDEX(0, 0, 0)] = { | ||
330 | .channels = ad7266_channels_u, | ||
331 | .num_channels = ARRAY_SIZE(ad7266_channels_u), | ||
332 | .scan_masks = ad7266_available_scan_masks, | ||
333 | }, | ||
334 | [AD7266_CHAN_INFO_INDEX(0, 0, 1)] = { | ||
335 | .channels = ad7266_channels_u_fixed, | ||
336 | .num_channels = ARRAY_SIZE(ad7266_channels_u_fixed), | ||
337 | .scan_masks = ad7266_available_scan_masks_fixed, | ||
338 | }, | ||
339 | [AD7266_CHAN_INFO_INDEX(0, 1, 0)] = { | ||
340 | .channels = ad7266_channels_s, | ||
341 | .num_channels = ARRAY_SIZE(ad7266_channels_s), | ||
342 | .scan_masks = ad7266_available_scan_masks, | ||
343 | }, | ||
344 | [AD7266_CHAN_INFO_INDEX(0, 1, 1)] = { | ||
345 | .channels = ad7266_channels_s_fixed, | ||
346 | .num_channels = ARRAY_SIZE(ad7266_channels_s_fixed), | ||
347 | .scan_masks = ad7266_available_scan_masks_fixed, | ||
348 | }, | ||
349 | [AD7266_CHAN_INFO_INDEX(1, 0, 0)] = { | ||
350 | .channels = ad7266_channels_diff_u, | ||
351 | .num_channels = ARRAY_SIZE(ad7266_channels_diff_u), | ||
352 | .scan_masks = ad7266_available_scan_masks_diff, | ||
353 | }, | ||
354 | [AD7266_CHAN_INFO_INDEX(1, 0, 1)] = { | ||
355 | .channels = ad7266_channels_diff_fixed_u, | ||
356 | .num_channels = ARRAY_SIZE(ad7266_channels_diff_fixed_u), | ||
357 | .scan_masks = ad7266_available_scan_masks_fixed, | ||
358 | }, | ||
359 | [AD7266_CHAN_INFO_INDEX(1, 1, 0)] = { | ||
360 | .channels = ad7266_channels_diff_s, | ||
361 | .num_channels = ARRAY_SIZE(ad7266_channels_diff_s), | ||
362 | .scan_masks = ad7266_available_scan_masks_diff, | ||
363 | }, | ||
364 | [AD7266_CHAN_INFO_INDEX(1, 1, 1)] = { | ||
365 | .channels = ad7266_channels_diff_fixed_s, | ||
366 | .num_channels = ARRAY_SIZE(ad7266_channels_diff_fixed_s), | ||
367 | .scan_masks = ad7266_available_scan_masks_fixed, | ||
368 | }, | ||
369 | }; | ||
370 | |||
371 | static void __devinit ad7266_init_channels(struct iio_dev *indio_dev) | ||
372 | { | ||
373 | struct ad7266_state *st = iio_priv(indio_dev); | ||
374 | bool is_differential, is_signed; | ||
375 | const struct ad7266_chan_info *chan_info; | ||
376 | int i; | ||
377 | |||
378 | is_differential = st->mode != AD7266_MODE_SINGLE_ENDED; | ||
379 | is_signed = (st->range == AD7266_RANGE_2VREF) | | ||
380 | (st->mode == AD7266_MODE_DIFF); | ||
381 | |||
382 | i = AD7266_CHAN_INFO_INDEX(is_differential, is_signed, st->fixed_addr); | ||
383 | chan_info = &ad7266_chan_infos[i]; | ||
384 | |||
385 | indio_dev->channels = chan_info->channels; | ||
386 | indio_dev->num_channels = chan_info->num_channels; | ||
387 | indio_dev->available_scan_masks = chan_info->scan_masks; | ||
388 | indio_dev->masklength = chan_info->num_channels - 1; | ||
389 | } | ||
390 | |||
391 | static const char * const ad7266_gpio_labels[] = { | ||
392 | "AD0", "AD1", "AD2", | ||
393 | }; | ||
394 | |||
395 | static int __devinit ad7266_probe(struct spi_device *spi) | ||
396 | { | ||
397 | struct ad7266_platform_data *pdata = spi->dev.platform_data; | ||
398 | struct iio_dev *indio_dev; | ||
399 | struct ad7266_state *st; | ||
400 | unsigned int i; | ||
401 | int ret; | ||
402 | |||
403 | indio_dev = iio_device_alloc(sizeof(*st)); | ||
404 | if (indio_dev == NULL) | ||
405 | return -ENOMEM; | ||
406 | |||
407 | st = iio_priv(indio_dev); | ||
408 | |||
409 | st->reg = regulator_get(&spi->dev, "vref"); | ||
410 | if (!IS_ERR_OR_NULL(st->reg)) { | ||
411 | ret = regulator_enable(st->reg); | ||
412 | if (ret) | ||
413 | goto error_put_reg; | ||
414 | |||
415 | st->vref_uv = regulator_get_voltage(st->reg); | ||
416 | } else { | ||
417 | /* Use internal reference */ | ||
418 | st->vref_uv = 2500000; | ||
419 | } | ||
420 | |||
421 | if (pdata) { | ||
422 | st->fixed_addr = pdata->fixed_addr; | ||
423 | st->mode = pdata->mode; | ||
424 | st->range = pdata->range; | ||
425 | |||
426 | if (!st->fixed_addr) { | ||
427 | for (i = 0; i < ARRAY_SIZE(st->gpios); ++i) { | ||
428 | st->gpios[i].gpio = pdata->addr_gpios[i]; | ||
429 | st->gpios[i].flags = GPIOF_OUT_INIT_LOW; | ||
430 | st->gpios[i].label = ad7266_gpio_labels[i]; | ||
431 | } | ||
432 | ret = gpio_request_array(st->gpios, | ||
433 | ARRAY_SIZE(st->gpios)); | ||
434 | if (ret) | ||
435 | goto error_disable_reg; | ||
436 | } | ||
437 | } else { | ||
438 | st->fixed_addr = true; | ||
439 | st->range = AD7266_RANGE_VREF; | ||
440 | st->mode = AD7266_MODE_DIFF; | ||
441 | } | ||
442 | |||
443 | spi_set_drvdata(spi, indio_dev); | ||
444 | st->spi = spi; | ||
445 | |||
446 | indio_dev->dev.parent = &spi->dev; | ||
447 | indio_dev->name = spi_get_device_id(spi)->name; | ||
448 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
449 | indio_dev->info = &ad7266_info; | ||
450 | |||
451 | ad7266_init_channels(indio_dev); | ||
452 | |||
453 | /* wakeup */ | ||
454 | st->single_xfer[0].rx_buf = &st->data; | ||
455 | st->single_xfer[0].len = 2; | ||
456 | st->single_xfer[0].cs_change = 1; | ||
457 | /* conversion */ | ||
458 | st->single_xfer[1].rx_buf = &st->data; | ||
459 | st->single_xfer[1].len = 4; | ||
460 | st->single_xfer[1].cs_change = 1; | ||
461 | /* powerdown */ | ||
462 | st->single_xfer[2].tx_buf = &st->data; | ||
463 | st->single_xfer[2].len = 1; | ||
464 | |||
465 | spi_message_init(&st->single_msg); | ||
466 | spi_message_add_tail(&st->single_xfer[0], &st->single_msg); | ||
467 | spi_message_add_tail(&st->single_xfer[1], &st->single_msg); | ||
468 | spi_message_add_tail(&st->single_xfer[2], &st->single_msg); | ||
469 | |||
470 | ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time, | ||
471 | &ad7266_trigger_handler, &iio_triggered_buffer_setup_ops); | ||
472 | if (ret) | ||
473 | goto error_free_gpios; | ||
474 | |||
475 | ret = iio_device_register(indio_dev); | ||
476 | if (ret) | ||
477 | goto error_buffer_cleanup; | ||
478 | |||
479 | return 0; | ||
480 | |||
481 | error_buffer_cleanup: | ||
482 | iio_triggered_buffer_cleanup(indio_dev); | ||
483 | error_free_gpios: | ||
484 | if (!st->fixed_addr) | ||
485 | gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios)); | ||
486 | error_disable_reg: | ||
487 | if (!IS_ERR_OR_NULL(st->reg)) | ||
488 | regulator_disable(st->reg); | ||
489 | error_put_reg: | ||
490 | if (!IS_ERR_OR_NULL(st->reg)) | ||
491 | regulator_put(st->reg); | ||
492 | |||
493 | iio_device_free(indio_dev); | ||
494 | |||
495 | return ret; | ||
496 | } | ||
497 | |||
498 | static int __devexit ad7266_remove(struct spi_device *spi) | ||
499 | { | ||
500 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
501 | struct ad7266_state *st = iio_priv(indio_dev); | ||
502 | |||
503 | iio_device_unregister(indio_dev); | ||
504 | iio_triggered_buffer_cleanup(indio_dev); | ||
505 | if (!st->fixed_addr) | ||
506 | gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios)); | ||
507 | if (!IS_ERR_OR_NULL(st->reg)) { | ||
508 | regulator_disable(st->reg); | ||
509 | regulator_put(st->reg); | ||
510 | } | ||
511 | iio_device_free(indio_dev); | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | static const struct spi_device_id ad7266_id[] = { | ||
517 | {"ad7265", 0}, | ||
518 | {"ad7266", 0}, | ||
519 | { } | ||
520 | }; | ||
521 | MODULE_DEVICE_TABLE(spi, ad7266_id); | ||
522 | |||
523 | static struct spi_driver ad7266_driver = { | ||
524 | .driver = { | ||
525 | .name = "ad7266", | ||
526 | .owner = THIS_MODULE, | ||
527 | }, | ||
528 | .probe = ad7266_probe, | ||
529 | .remove = __devexit_p(ad7266_remove), | ||
530 | .id_table = ad7266_id, | ||
531 | }; | ||
532 | module_spi_driver(ad7266_driver); | ||
533 | |||
534 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
535 | MODULE_DESCRIPTION("Analog Devices AD7266/65 ADC"); | ||
536 | MODULE_LICENSE("GPL v2"); | ||
537 |
drivers/iio/dac/Kconfig
1 | # | 1 | # |
2 | # DAC drivers | 2 | # DAC drivers |
3 | # | 3 | # |
4 | menu "Digital to analog converters" | 4 | menu "Digital to analog converters" |
5 | 5 | ||
6 | config AD5064 | 6 | config AD5064 |
7 | tristate "Analog Devices AD5064/64-1/65/44/45/24/25, AD5628/48/66/68 DAC driver" | 7 | tristate "Analog Devices AD5064 and similar multi-channel DAC driver" |
8 | depends on SPI | 8 | depends on (SPI_MASTER || I2C) |
9 | help | 9 | help |
10 | Say yes here to build support for Analog Devices AD5024, AD5025, AD5044, | 10 | Say yes here to build support for Analog Devices AD5024, AD5025, AD5044, |
11 | AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5648, AD5666, AD5668 Digital | 11 | AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5629R, AD5648, AD5666, AD5668, |
12 | to Analog Converter. | 12 | AD5669R Digital to Analog Converter. |
13 | 13 | ||
14 | To compile this driver as a module, choose M here: the | 14 | To compile this driver as a module, choose M here: the |
15 | module will be called ad5064. | 15 | module will be called ad5064. |
16 | 16 | ||
17 | config AD5360 | 17 | config AD5360 |
18 | tristate "Analog Devices Analog Devices AD5360/61/62/63/70/71/73 DAC driver" | 18 | tristate "Analog Devices Analog Devices AD5360/61/62/63/70/71/73 DAC driver" |
19 | depends on SPI | 19 | depends on SPI |
20 | help | 20 | help |
21 | Say yes here to build support for Analog Devices AD5360, AD5361, | 21 | Say yes here to build support for Analog Devices AD5360, AD5361, |
22 | AD5362, AD5363, AD5370, AD5371, AD5373 multi-channel | 22 | AD5362, AD5363, AD5370, AD5371, AD5373 multi-channel |
23 | Digital to Analog Converters (DAC). | 23 | Digital to Analog Converters (DAC). |
24 | 24 | ||
25 | To compile this driver as module choose M here: the module will be called | 25 | To compile this driver as module choose M here: the module will be called |
26 | ad5360. | 26 | ad5360. |
27 | 27 | ||
28 | config AD5380 | 28 | config AD5380 |
29 | tristate "Analog Devices AD5380/81/82/83/84/90/91/92 DAC driver" | 29 | tristate "Analog Devices AD5380/81/82/83/84/90/91/92 DAC driver" |
30 | depends on (SPI_MASTER || I2C) | 30 | depends on (SPI_MASTER || I2C) |
31 | select REGMAP_I2C if I2C | 31 | select REGMAP_I2C if I2C |
32 | select REGMAP_SPI if SPI_MASTER | 32 | select REGMAP_SPI if SPI_MASTER |
33 | help | 33 | help |
34 | Say yes here to build support for Analog Devices AD5380, AD5381, | 34 | Say yes here to build support for Analog Devices AD5380, AD5381, |
35 | AD5382, AD5383, AD5384, AD5390, AD5391, AD5392 multi-channel | 35 | AD5382, AD5383, AD5384, AD5390, AD5391, AD5392 multi-channel |
36 | Digital to Analog Converters (DAC). | 36 | Digital to Analog Converters (DAC). |
37 | 37 | ||
38 | To compile this driver as module choose M here: the module will be called | 38 | To compile this driver as module choose M here: the module will be called |
39 | ad5380. | 39 | ad5380. |
40 | 40 | ||
41 | config AD5421 | 41 | config AD5421 |
42 | tristate "Analog Devices AD5421 DAC driver" | 42 | tristate "Analog Devices AD5421 DAC driver" |
43 | depends on SPI | 43 | depends on SPI |
44 | help | 44 | help |
45 | Say yes here to build support for Analog Devices AD5421 loop-powered | 45 | Say yes here to build support for Analog Devices AD5421 loop-powered |
46 | digital-to-analog convertors (DAC). | 46 | digital-to-analog convertors (DAC). |
47 | 47 | ||
48 | To compile this driver as module choose M here: the module will be called | 48 | To compile this driver as module choose M here: the module will be called |
49 | ad5421. | 49 | ad5421. |
50 | 50 | ||
51 | config AD5624R_SPI | 51 | config AD5624R_SPI |
52 | tristate "Analog Devices AD5624/44/64R DAC spi driver" | 52 | tristate "Analog Devices AD5624/44/64R DAC spi driver" |
53 | depends on SPI | 53 | depends on SPI |
54 | help | 54 | help |
55 | Say yes here to build support for Analog Devices AD5624R, AD5644R and | 55 | Say yes here to build support for Analog Devices AD5624R, AD5644R and |
56 | AD5664R converters (DAC). This driver uses the common SPI interface. | 56 | AD5664R converters (DAC). This driver uses the common SPI interface. |
57 | 57 | ||
58 | config AD5446 | 58 | config AD5446 |
59 | tristate "Analog Devices AD5446 and similar single channel DACs driver" | 59 | tristate "Analog Devices AD5446 and similar single channel DACs driver" |
60 | depends on SPI | 60 | depends on SPI |
61 | help | 61 | help |
62 | Say yes here to build support for Analog Devices AD5444, AD5446, AD5450, | 62 | Say yes here to build support for Analog Devices AD5444, AD5446, AD5450, |
63 | AD5451, AD5452, AD5453, AD5512A, AD5541A, AD5542A, AD5543, AD5553, AD5601, | 63 | AD5451, AD5452, AD5453, AD5512A, AD5541A, AD5542A, AD5543, AD5553, AD5601, |
64 | AD5611, AD5620, AD5621, AD5640, AD5660, AD5662 DACs. | 64 | AD5611, AD5620, AD5621, AD5640, AD5660, AD5662 DACs. |
65 | 65 | ||
66 | To compile this driver as a module, choose M here: the | 66 | To compile this driver as a module, choose M here: the |
67 | module will be called ad5446. | 67 | module will be called ad5446. |
68 | 68 | ||
69 | config AD5504 | 69 | config AD5504 |
70 | tristate "Analog Devices AD5504/AD5501 DAC SPI driver" | 70 | tristate "Analog Devices AD5504/AD5501 DAC SPI driver" |
71 | depends on SPI | 71 | depends on SPI |
72 | help | 72 | help |
73 | Say yes here to build support for Analog Devices AD5504, AD5501, | 73 | Say yes here to build support for Analog Devices AD5504, AD5501, |
74 | High Voltage Digital to Analog Converter. | 74 | High Voltage Digital to Analog Converter. |
75 | 75 | ||
76 | To compile this driver as a module, choose M here: the | 76 | To compile this driver as a module, choose M here: the |
77 | module will be called ad5504. | 77 | module will be called ad5504. |
78 | 78 | ||
79 | config AD5764 | 79 | config AD5764 |
80 | tristate "Analog Devices AD5764/64R/44/44R DAC driver" | 80 | tristate "Analog Devices AD5764/64R/44/44R DAC driver" |
81 | depends on SPI_MASTER | 81 | depends on SPI_MASTER |
82 | help | 82 | help |
83 | Say yes here to build support for Analog Devices AD5764, AD5764R, AD5744, | 83 | Say yes here to build support for Analog Devices AD5764, AD5764R, AD5744, |
84 | AD5744R Digital to Analog Converter. | 84 | AD5744R Digital to Analog Converter. |
85 | 85 | ||
86 | To compile this driver as a module, choose M here: the | 86 | To compile this driver as a module, choose M here: the |
87 | module will be called ad5764. | 87 | module will be called ad5764. |
88 | 88 | ||
89 | config AD5791 | 89 | config AD5791 |
90 | tristate "Analog Devices AD5760/AD5780/AD5781/AD5790/AD5791 DAC SPI driver" | 90 | tristate "Analog Devices AD5760/AD5780/AD5781/AD5790/AD5791 DAC SPI driver" |
91 | depends on SPI | 91 | depends on SPI |
92 | help | 92 | help |
93 | Say yes here to build support for Analog Devices AD5760, AD5780, | 93 | Say yes here to build support for Analog Devices AD5760, AD5780, |
94 | AD5781, AD5790, AD5791 High Resolution Voltage Output Digital to | 94 | AD5781, AD5790, AD5791 High Resolution Voltage Output Digital to |
95 | Analog Converter. | 95 | Analog Converter. |
96 | 96 | ||
97 | To compile this driver as a module, choose M here: the | 97 | To compile this driver as a module, choose M here: the |
98 | module will be called ad5791. | 98 | module will be called ad5791. |
99 | 99 | ||
100 | config AD5686 | 100 | config AD5686 |
101 | tristate "Analog Devices AD5686R/AD5685R/AD5684R DAC SPI driver" | 101 | tristate "Analog Devices AD5686R/AD5685R/AD5684R DAC SPI driver" |
102 | depends on SPI | 102 | depends on SPI |
103 | help | 103 | help |
104 | Say yes here to build support for Analog Devices AD5686R, AD5685R, | 104 | Say yes here to build support for Analog Devices AD5686R, AD5685R, |
105 | AD5684R, AD5791 Voltage Output Digital to | 105 | AD5684R, AD5791 Voltage Output Digital to |
106 | Analog Converter. | 106 | Analog Converter. |
107 | 107 | ||
108 | To compile this driver as a module, choose M here: the | 108 | To compile this driver as a module, choose M here: the |
109 | module will be called ad5686. | 109 | module will be called ad5686. |
110 | 110 | ||
111 | config MAX517 | 111 | config MAX517 |
112 | tristate "Maxim MAX517/518/519 DAC driver" | 112 | tristate "Maxim MAX517/518/519 DAC driver" |
113 | depends on I2C && EXPERIMENTAL | 113 | depends on I2C && EXPERIMENTAL |
114 | help | 114 | help |
115 | If you say yes here you get support for the Maxim chips MAX517, | 115 | If you say yes here you get support for the Maxim chips MAX517, |
116 | MAX518 and MAX519 (I2C 8-Bit DACs with rail-to-rail outputs). | 116 | MAX518 and MAX519 (I2C 8-Bit DACs with rail-to-rail outputs). |
117 | 117 | ||
118 | This driver can also be built as a module. If so, the module | 118 | This driver can also be built as a module. If so, the module |
119 | will be called max517. | 119 | will be called max517. |
120 | 120 | ||
121 | config MCP4725 | 121 | config MCP4725 |
122 | tristate "MCP4725 DAC driver" | 122 | tristate "MCP4725 DAC driver" |
123 | depends on I2C | 123 | depends on I2C |
124 | ---help--- | 124 | ---help--- |
125 | Say Y here if you want to build a driver for the Microchip | 125 | Say Y here if you want to build a driver for the Microchip |
126 | MCP 4725 12-bit digital-to-analog converter (DAC) with I2C | 126 | MCP 4725 12-bit digital-to-analog converter (DAC) with I2C |
127 | interface. | 127 | interface. |
128 | 128 | ||
129 | To compile this driver as a module, choose M here: the module | 129 | To compile this driver as a module, choose M here: the module |
130 | will be called mcp4725. | 130 | will be called mcp4725. |
131 | 131 | ||
132 | endmenu | 132 | endmenu |
133 | 133 |
drivers/iio/dac/ad5064.c
1 | /* | 1 | /* |
2 | * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5648, | 2 | * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5629R, |
3 | * AD5666, AD5668 Digital to analog converters driver | 3 | * AD5648, AD5666, AD5668, AD5669R Digital to analog converters driver |
4 | * | 4 | * |
5 | * Copyright 2011 Analog Devices Inc. | 5 | * Copyright 2011 Analog Devices Inc. |
6 | * | 6 | * |
7 | * Licensed under the GPL-2. | 7 | * Licensed under the GPL-2. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/device.h> | 10 | #include <linux/device.h> |
11 | #include <linux/err.h> | 11 | #include <linux/err.h> |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/spi/spi.h> | 14 | #include <linux/spi/spi.h> |
15 | #include <linux/i2c.h> | ||
15 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
16 | #include <linux/sysfs.h> | 17 | #include <linux/sysfs.h> |
17 | #include <linux/regulator/consumer.h> | 18 | #include <linux/regulator/consumer.h> |
19 | #include <asm/unaligned.h> | ||
18 | 20 | ||
19 | #include <linux/iio/iio.h> | 21 | #include <linux/iio/iio.h> |
20 | #include <linux/iio/sysfs.h> | 22 | #include <linux/iio/sysfs.h> |
21 | 23 | ||
22 | #define AD5064_MAX_DAC_CHANNELS 8 | 24 | #define AD5064_MAX_DAC_CHANNELS 8 |
23 | #define AD5064_MAX_VREFS 4 | 25 | #define AD5064_MAX_VREFS 4 |
24 | 26 | ||
25 | #define AD5064_ADDR(x) ((x) << 20) | 27 | #define AD5064_ADDR(x) ((x) << 20) |
26 | #define AD5064_CMD(x) ((x) << 24) | 28 | #define AD5064_CMD(x) ((x) << 24) |
27 | 29 | ||
28 | #define AD5064_ADDR_DAC(chan) (chan) | 30 | #define AD5064_ADDR_DAC(chan) (chan) |
29 | #define AD5064_ADDR_ALL_DAC 0xF | 31 | #define AD5064_ADDR_ALL_DAC 0xF |
30 | 32 | ||
31 | #define AD5064_CMD_WRITE_INPUT_N 0x0 | 33 | #define AD5064_CMD_WRITE_INPUT_N 0x0 |
32 | #define AD5064_CMD_UPDATE_DAC_N 0x1 | 34 | #define AD5064_CMD_UPDATE_DAC_N 0x1 |
33 | #define AD5064_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2 | 35 | #define AD5064_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2 |
34 | #define AD5064_CMD_WRITE_INPUT_N_UPDATE_N 0x3 | 36 | #define AD5064_CMD_WRITE_INPUT_N_UPDATE_N 0x3 |
35 | #define AD5064_CMD_POWERDOWN_DAC 0x4 | 37 | #define AD5064_CMD_POWERDOWN_DAC 0x4 |
36 | #define AD5064_CMD_CLEAR 0x5 | 38 | #define AD5064_CMD_CLEAR 0x5 |
37 | #define AD5064_CMD_LDAC_MASK 0x6 | 39 | #define AD5064_CMD_LDAC_MASK 0x6 |
38 | #define AD5064_CMD_RESET 0x7 | 40 | #define AD5064_CMD_RESET 0x7 |
39 | #define AD5064_CMD_CONFIG 0x8 | 41 | #define AD5064_CMD_CONFIG 0x8 |
40 | 42 | ||
41 | #define AD5064_CONFIG_DAISY_CHAIN_ENABLE BIT(1) | 43 | #define AD5064_CONFIG_DAISY_CHAIN_ENABLE BIT(1) |
42 | #define AD5064_CONFIG_INT_VREF_ENABLE BIT(0) | 44 | #define AD5064_CONFIG_INT_VREF_ENABLE BIT(0) |
43 | 45 | ||
44 | #define AD5064_LDAC_PWRDN_NONE 0x0 | 46 | #define AD5064_LDAC_PWRDN_NONE 0x0 |
45 | #define AD5064_LDAC_PWRDN_1K 0x1 | 47 | #define AD5064_LDAC_PWRDN_1K 0x1 |
46 | #define AD5064_LDAC_PWRDN_100K 0x2 | 48 | #define AD5064_LDAC_PWRDN_100K 0x2 |
47 | #define AD5064_LDAC_PWRDN_3STATE 0x3 | 49 | #define AD5064_LDAC_PWRDN_3STATE 0x3 |
48 | 50 | ||
49 | /** | 51 | /** |
50 | * struct ad5064_chip_info - chip specific information | 52 | * struct ad5064_chip_info - chip specific information |
51 | * @shared_vref: whether the vref supply is shared between channels | 53 | * @shared_vref: whether the vref supply is shared between channels |
52 | * @internal_vref: internal reference voltage. 0 if the chip has no internal | 54 | * @internal_vref: internal reference voltage. 0 if the chip has no internal |
53 | * vref. | 55 | * vref. |
54 | * @channel: channel specification | 56 | * @channel: channel specification |
55 | * @num_channels: number of channels | 57 | * @num_channels: number of channels |
56 | */ | 58 | */ |
57 | 59 | ||
58 | struct ad5064_chip_info { | 60 | struct ad5064_chip_info { |
59 | bool shared_vref; | 61 | bool shared_vref; |
60 | unsigned long internal_vref; | 62 | unsigned long internal_vref; |
61 | const struct iio_chan_spec *channels; | 63 | const struct iio_chan_spec *channels; |
62 | unsigned int num_channels; | 64 | unsigned int num_channels; |
63 | }; | 65 | }; |
64 | 66 | ||
67 | struct ad5064_state; | ||
68 | |||
69 | typedef int (*ad5064_write_func)(struct ad5064_state *st, unsigned int cmd, | ||
70 | unsigned int addr, unsigned int val); | ||
71 | |||
65 | /** | 72 | /** |
66 | * struct ad5064_state - driver instance specific data | 73 | * struct ad5064_state - driver instance specific data |
67 | * @spi: spi_device | 74 | * @dev: the device for this driver instance |
68 | * @chip_info: chip model specific constants, available modes etc | 75 | * @chip_info: chip model specific constants, available modes etc |
69 | * @vref_reg: vref supply regulators | 76 | * @vref_reg: vref supply regulators |
70 | * @pwr_down: whether channel is powered down | 77 | * @pwr_down: whether channel is powered down |
71 | * @pwr_down_mode: channel's current power down mode | 78 | * @pwr_down_mode: channel's current power down mode |
72 | * @dac_cache: current DAC raw value (chip does not support readback) | 79 | * @dac_cache: current DAC raw value (chip does not support readback) |
73 | * @use_internal_vref: set to true if the internal reference voltage should be | 80 | * @use_internal_vref: set to true if the internal reference voltage should be |
74 | * used. | 81 | * used. |
75 | * @data: spi transfer buffers | 82 | * @write: register write callback |
83 | * @data: i2c/spi transfer buffers | ||
76 | */ | 84 | */ |
77 | 85 | ||
78 | struct ad5064_state { | 86 | struct ad5064_state { |
79 | struct spi_device *spi; | 87 | struct device *dev; |
80 | const struct ad5064_chip_info *chip_info; | 88 | const struct ad5064_chip_info *chip_info; |
81 | struct regulator_bulk_data vref_reg[AD5064_MAX_VREFS]; | 89 | struct regulator_bulk_data vref_reg[AD5064_MAX_VREFS]; |
82 | bool pwr_down[AD5064_MAX_DAC_CHANNELS]; | 90 | bool pwr_down[AD5064_MAX_DAC_CHANNELS]; |
83 | u8 pwr_down_mode[AD5064_MAX_DAC_CHANNELS]; | 91 | u8 pwr_down_mode[AD5064_MAX_DAC_CHANNELS]; |
84 | unsigned int dac_cache[AD5064_MAX_DAC_CHANNELS]; | 92 | unsigned int dac_cache[AD5064_MAX_DAC_CHANNELS]; |
85 | bool use_internal_vref; | 93 | bool use_internal_vref; |
86 | 94 | ||
95 | ad5064_write_func write; | ||
96 | |||
87 | /* | 97 | /* |
88 | * DMA (thus cache coherency maintenance) requires the | 98 | * DMA (thus cache coherency maintenance) requires the |
89 | * transfer buffers to live in their own cache lines. | 99 | * transfer buffers to live in their own cache lines. |
90 | */ | 100 | */ |
91 | __be32 data ____cacheline_aligned; | 101 | union { |
102 | u8 i2c[3]; | ||
103 | __be32 spi; | ||
104 | } data ____cacheline_aligned; | ||
92 | }; | 105 | }; |
93 | 106 | ||
94 | enum ad5064_type { | 107 | enum ad5064_type { |
95 | ID_AD5024, | 108 | ID_AD5024, |
96 | ID_AD5025, | 109 | ID_AD5025, |
97 | ID_AD5044, | 110 | ID_AD5044, |
98 | ID_AD5045, | 111 | ID_AD5045, |
99 | ID_AD5064, | 112 | ID_AD5064, |
100 | ID_AD5064_1, | 113 | ID_AD5064_1, |
101 | ID_AD5065, | 114 | ID_AD5065, |
102 | ID_AD5628_1, | 115 | ID_AD5628_1, |
103 | ID_AD5628_2, | 116 | ID_AD5628_2, |
104 | ID_AD5648_1, | 117 | ID_AD5648_1, |
105 | ID_AD5648_2, | 118 | ID_AD5648_2, |
106 | ID_AD5666_1, | 119 | ID_AD5666_1, |
107 | ID_AD5666_2, | 120 | ID_AD5666_2, |
108 | ID_AD5668_1, | 121 | ID_AD5668_1, |
109 | ID_AD5668_2, | 122 | ID_AD5668_2, |
110 | }; | 123 | }; |
111 | 124 | ||
125 | static int ad5064_i2c_write(struct ad5064_state *st, unsigned int cmd, | ||
126 | unsigned int addr, unsigned int val) | ||
127 | { | ||
128 | struct i2c_client *i2c = to_i2c_client(st->dev); | ||
129 | |||
130 | st->data.i2c[0] = (cmd << 4) | addr; | ||
131 | put_unaligned_be16(val, &st->data.i2c[1]); | ||
132 | return i2c_master_send(i2c, st->data.i2c, 3); | ||
133 | } | ||
134 | |||
112 | static int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd, | 135 | static int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd, |
136 | unsigned int addr, unsigned int val) | ||
137 | { | ||
138 | struct spi_device *spi = to_spi_device(st->dev); | ||
139 | |||
140 | st->data.spi = cpu_to_be32(AD5064_CMD(cmd) | AD5064_ADDR(addr) | val); | ||
141 | return spi_write(spi, &st->data.spi, sizeof(st->data.spi)); | ||
142 | } | ||
143 | |||
144 | static int ad5064_write(struct ad5064_state *st, unsigned int cmd, | ||
113 | unsigned int addr, unsigned int val, unsigned int shift) | 145 | unsigned int addr, unsigned int val, unsigned int shift) |
114 | { | 146 | { |
115 | val <<= shift; | 147 | val <<= shift; |
116 | 148 | ||
117 | st->data = cpu_to_be32(AD5064_CMD(cmd) | AD5064_ADDR(addr) | val); | 149 | return st->write(st, cmd, addr, val); |
118 | |||
119 | return spi_write(st->spi, &st->data, sizeof(st->data)); | ||
120 | } | 150 | } |
121 | 151 | ||
122 | static int ad5064_sync_powerdown_mode(struct ad5064_state *st, | 152 | static int ad5064_sync_powerdown_mode(struct ad5064_state *st, |
123 | unsigned int channel) | 153 | unsigned int channel) |
124 | { | 154 | { |
125 | unsigned int val; | 155 | unsigned int val; |
126 | int ret; | 156 | int ret; |
127 | 157 | ||
128 | val = (0x1 << channel); | 158 | val = (0x1 << channel); |
129 | 159 | ||
130 | if (st->pwr_down[channel]) | 160 | if (st->pwr_down[channel]) |
131 | val |= st->pwr_down_mode[channel] << 8; | 161 | val |= st->pwr_down_mode[channel] << 8; |
132 | 162 | ||
133 | ret = ad5064_spi_write(st, AD5064_CMD_POWERDOWN_DAC, 0, val, 0); | 163 | ret = ad5064_write(st, AD5064_CMD_POWERDOWN_DAC, 0, val, 0); |
134 | 164 | ||
135 | return ret; | 165 | return ret; |
136 | } | 166 | } |
137 | 167 | ||
138 | static const char * const ad5064_powerdown_modes[] = { | 168 | static const char * const ad5064_powerdown_modes[] = { |
139 | "1kohm_to_gnd", | 169 | "1kohm_to_gnd", |
140 | "100kohm_to_gnd", | 170 | "100kohm_to_gnd", |
141 | "three_state", | 171 | "three_state", |
142 | }; | 172 | }; |
143 | 173 | ||
144 | static int ad5064_get_powerdown_mode(struct iio_dev *indio_dev, | 174 | static int ad5064_get_powerdown_mode(struct iio_dev *indio_dev, |
145 | const struct iio_chan_spec *chan) | 175 | const struct iio_chan_spec *chan) |
146 | { | 176 | { |
147 | struct ad5064_state *st = iio_priv(indio_dev); | 177 | struct ad5064_state *st = iio_priv(indio_dev); |
148 | 178 | ||
149 | return st->pwr_down_mode[chan->channel] - 1; | 179 | return st->pwr_down_mode[chan->channel] - 1; |
150 | } | 180 | } |
151 | 181 | ||
152 | static int ad5064_set_powerdown_mode(struct iio_dev *indio_dev, | 182 | static int ad5064_set_powerdown_mode(struct iio_dev *indio_dev, |
153 | const struct iio_chan_spec *chan, unsigned int mode) | 183 | const struct iio_chan_spec *chan, unsigned int mode) |
154 | { | 184 | { |
155 | struct ad5064_state *st = iio_priv(indio_dev); | 185 | struct ad5064_state *st = iio_priv(indio_dev); |
156 | int ret; | 186 | int ret; |
157 | 187 | ||
158 | mutex_lock(&indio_dev->mlock); | 188 | mutex_lock(&indio_dev->mlock); |
159 | st->pwr_down_mode[chan->channel] = mode + 1; | 189 | st->pwr_down_mode[chan->channel] = mode + 1; |
160 | 190 | ||
161 | ret = ad5064_sync_powerdown_mode(st, chan->channel); | 191 | ret = ad5064_sync_powerdown_mode(st, chan->channel); |
162 | mutex_unlock(&indio_dev->mlock); | 192 | mutex_unlock(&indio_dev->mlock); |
163 | 193 | ||
164 | return ret; | 194 | return ret; |
165 | } | 195 | } |
166 | 196 | ||
167 | static const struct iio_enum ad5064_powerdown_mode_enum = { | 197 | static const struct iio_enum ad5064_powerdown_mode_enum = { |
168 | .items = ad5064_powerdown_modes, | 198 | .items = ad5064_powerdown_modes, |
169 | .num_items = ARRAY_SIZE(ad5064_powerdown_modes), | 199 | .num_items = ARRAY_SIZE(ad5064_powerdown_modes), |
170 | .get = ad5064_get_powerdown_mode, | 200 | .get = ad5064_get_powerdown_mode, |
171 | .set = ad5064_set_powerdown_mode, | 201 | .set = ad5064_set_powerdown_mode, |
172 | }; | 202 | }; |
173 | 203 | ||
174 | static ssize_t ad5064_read_dac_powerdown(struct iio_dev *indio_dev, | 204 | static ssize_t ad5064_read_dac_powerdown(struct iio_dev *indio_dev, |
175 | uintptr_t private, const struct iio_chan_spec *chan, char *buf) | 205 | uintptr_t private, const struct iio_chan_spec *chan, char *buf) |
176 | { | 206 | { |
177 | struct ad5064_state *st = iio_priv(indio_dev); | 207 | struct ad5064_state *st = iio_priv(indio_dev); |
178 | 208 | ||
179 | return sprintf(buf, "%d\n", st->pwr_down[chan->channel]); | 209 | return sprintf(buf, "%d\n", st->pwr_down[chan->channel]); |
180 | } | 210 | } |
181 | 211 | ||
182 | static ssize_t ad5064_write_dac_powerdown(struct iio_dev *indio_dev, | 212 | static ssize_t ad5064_write_dac_powerdown(struct iio_dev *indio_dev, |
183 | uintptr_t private, const struct iio_chan_spec *chan, const char *buf, | 213 | uintptr_t private, const struct iio_chan_spec *chan, const char *buf, |
184 | size_t len) | 214 | size_t len) |
185 | { | 215 | { |
186 | struct ad5064_state *st = iio_priv(indio_dev); | 216 | struct ad5064_state *st = iio_priv(indio_dev); |
187 | bool pwr_down; | 217 | bool pwr_down; |
188 | int ret; | 218 | int ret; |
189 | 219 | ||
190 | ret = strtobool(buf, &pwr_down); | 220 | ret = strtobool(buf, &pwr_down); |
191 | if (ret) | 221 | if (ret) |
192 | return ret; | 222 | return ret; |
193 | 223 | ||
194 | mutex_lock(&indio_dev->mlock); | 224 | mutex_lock(&indio_dev->mlock); |
195 | st->pwr_down[chan->channel] = pwr_down; | 225 | st->pwr_down[chan->channel] = pwr_down; |
196 | 226 | ||
197 | ret = ad5064_sync_powerdown_mode(st, chan->channel); | 227 | ret = ad5064_sync_powerdown_mode(st, chan->channel); |
198 | mutex_unlock(&indio_dev->mlock); | 228 | mutex_unlock(&indio_dev->mlock); |
199 | return ret ? ret : len; | 229 | return ret ? ret : len; |
200 | } | 230 | } |
201 | 231 | ||
202 | static int ad5064_get_vref(struct ad5064_state *st, | 232 | static int ad5064_get_vref(struct ad5064_state *st, |
203 | struct iio_chan_spec const *chan) | 233 | struct iio_chan_spec const *chan) |
204 | { | 234 | { |
205 | unsigned int i; | 235 | unsigned int i; |
206 | 236 | ||
207 | if (st->use_internal_vref) | 237 | if (st->use_internal_vref) |
208 | return st->chip_info->internal_vref; | 238 | return st->chip_info->internal_vref; |
209 | 239 | ||
210 | i = st->chip_info->shared_vref ? 0 : chan->channel; | 240 | i = st->chip_info->shared_vref ? 0 : chan->channel; |
211 | return regulator_get_voltage(st->vref_reg[i].consumer); | 241 | return regulator_get_voltage(st->vref_reg[i].consumer); |
212 | } | 242 | } |
213 | 243 | ||
214 | static int ad5064_read_raw(struct iio_dev *indio_dev, | 244 | static int ad5064_read_raw(struct iio_dev *indio_dev, |
215 | struct iio_chan_spec const *chan, | 245 | struct iio_chan_spec const *chan, |
216 | int *val, | 246 | int *val, |
217 | int *val2, | 247 | int *val2, |
218 | long m) | 248 | long m) |
219 | { | 249 | { |
220 | struct ad5064_state *st = iio_priv(indio_dev); | 250 | struct ad5064_state *st = iio_priv(indio_dev); |
221 | int scale_uv; | 251 | int scale_uv; |
222 | 252 | ||
223 | switch (m) { | 253 | switch (m) { |
224 | case IIO_CHAN_INFO_RAW: | 254 | case IIO_CHAN_INFO_RAW: |
225 | *val = st->dac_cache[chan->channel]; | 255 | *val = st->dac_cache[chan->channel]; |
226 | return IIO_VAL_INT; | 256 | return IIO_VAL_INT; |
227 | case IIO_CHAN_INFO_SCALE: | 257 | case IIO_CHAN_INFO_SCALE: |
228 | scale_uv = ad5064_get_vref(st, chan); | 258 | scale_uv = ad5064_get_vref(st, chan); |
229 | if (scale_uv < 0) | 259 | if (scale_uv < 0) |
230 | return scale_uv; | 260 | return scale_uv; |
231 | 261 | ||
232 | scale_uv = (scale_uv * 100) >> chan->scan_type.realbits; | 262 | scale_uv = (scale_uv * 100) >> chan->scan_type.realbits; |
233 | *val = scale_uv / 100000; | 263 | *val = scale_uv / 100000; |
234 | *val2 = (scale_uv % 100000) * 10; | 264 | *val2 = (scale_uv % 100000) * 10; |
235 | return IIO_VAL_INT_PLUS_MICRO; | 265 | return IIO_VAL_INT_PLUS_MICRO; |
236 | default: | 266 | default: |
237 | break; | 267 | break; |
238 | } | 268 | } |
239 | return -EINVAL; | 269 | return -EINVAL; |
240 | } | 270 | } |
241 | 271 | ||
242 | static int ad5064_write_raw(struct iio_dev *indio_dev, | 272 | static int ad5064_write_raw(struct iio_dev *indio_dev, |
243 | struct iio_chan_spec const *chan, int val, int val2, long mask) | 273 | struct iio_chan_spec const *chan, int val, int val2, long mask) |
244 | { | 274 | { |
245 | struct ad5064_state *st = iio_priv(indio_dev); | 275 | struct ad5064_state *st = iio_priv(indio_dev); |
246 | int ret; | 276 | int ret; |
247 | 277 | ||
248 | switch (mask) { | 278 | switch (mask) { |
249 | case IIO_CHAN_INFO_RAW: | 279 | case IIO_CHAN_INFO_RAW: |
250 | if (val > (1 << chan->scan_type.realbits) || val < 0) | 280 | if (val > (1 << chan->scan_type.realbits) || val < 0) |
251 | return -EINVAL; | 281 | return -EINVAL; |
252 | 282 | ||
253 | mutex_lock(&indio_dev->mlock); | 283 | mutex_lock(&indio_dev->mlock); |
254 | ret = ad5064_spi_write(st, AD5064_CMD_WRITE_INPUT_N_UPDATE_N, | 284 | ret = ad5064_write(st, AD5064_CMD_WRITE_INPUT_N_UPDATE_N, |
255 | chan->address, val, chan->scan_type.shift); | 285 | chan->address, val, chan->scan_type.shift); |
256 | if (ret == 0) | 286 | if (ret == 0) |
257 | st->dac_cache[chan->channel] = val; | 287 | st->dac_cache[chan->channel] = val; |
258 | mutex_unlock(&indio_dev->mlock); | 288 | mutex_unlock(&indio_dev->mlock); |
259 | break; | 289 | break; |
260 | default: | 290 | default: |
261 | ret = -EINVAL; | 291 | ret = -EINVAL; |
262 | } | 292 | } |
263 | 293 | ||
264 | return ret; | 294 | return ret; |
265 | } | 295 | } |
266 | 296 | ||
267 | static const struct iio_info ad5064_info = { | 297 | static const struct iio_info ad5064_info = { |
268 | .read_raw = ad5064_read_raw, | 298 | .read_raw = ad5064_read_raw, |
269 | .write_raw = ad5064_write_raw, | 299 | .write_raw = ad5064_write_raw, |
270 | .driver_module = THIS_MODULE, | 300 | .driver_module = THIS_MODULE, |
271 | }; | 301 | }; |
272 | 302 | ||
273 | static const struct iio_chan_spec_ext_info ad5064_ext_info[] = { | 303 | static const struct iio_chan_spec_ext_info ad5064_ext_info[] = { |
274 | { | 304 | { |
275 | .name = "powerdown", | 305 | .name = "powerdown", |
276 | .read = ad5064_read_dac_powerdown, | 306 | .read = ad5064_read_dac_powerdown, |
277 | .write = ad5064_write_dac_powerdown, | 307 | .write = ad5064_write_dac_powerdown, |
278 | }, | 308 | }, |
279 | IIO_ENUM("powerdown_mode", false, &ad5064_powerdown_mode_enum), | 309 | IIO_ENUM("powerdown_mode", false, &ad5064_powerdown_mode_enum), |
280 | IIO_ENUM_AVAILABLE("powerdown_mode", &ad5064_powerdown_mode_enum), | 310 | IIO_ENUM_AVAILABLE("powerdown_mode", &ad5064_powerdown_mode_enum), |
281 | { }, | 311 | { }, |
282 | }; | 312 | }; |
283 | 313 | ||
284 | #define AD5064_CHANNEL(chan, bits) { \ | 314 | #define AD5064_CHANNEL(chan, bits) { \ |
285 | .type = IIO_VOLTAGE, \ | 315 | .type = IIO_VOLTAGE, \ |
286 | .indexed = 1, \ | 316 | .indexed = 1, \ |
287 | .output = 1, \ | 317 | .output = 1, \ |
288 | .channel = (chan), \ | 318 | .channel = (chan), \ |
289 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ | 319 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ |
290 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ | 320 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ |
291 | .address = AD5064_ADDR_DAC(chan), \ | 321 | .address = AD5064_ADDR_DAC(chan), \ |
292 | .scan_type = IIO_ST('u', (bits), 16, 20 - (bits)), \ | 322 | .scan_type = IIO_ST('u', (bits), 16, 20 - (bits)), \ |
293 | .ext_info = ad5064_ext_info, \ | 323 | .ext_info = ad5064_ext_info, \ |
294 | } | 324 | } |
295 | 325 | ||
296 | #define DECLARE_AD5064_CHANNELS(name, bits) \ | 326 | #define DECLARE_AD5064_CHANNELS(name, bits) \ |
297 | const struct iio_chan_spec name[] = { \ | 327 | const struct iio_chan_spec name[] = { \ |
298 | AD5064_CHANNEL(0, bits), \ | 328 | AD5064_CHANNEL(0, bits), \ |
299 | AD5064_CHANNEL(1, bits), \ | 329 | AD5064_CHANNEL(1, bits), \ |
300 | AD5064_CHANNEL(2, bits), \ | 330 | AD5064_CHANNEL(2, bits), \ |
301 | AD5064_CHANNEL(3, bits), \ | 331 | AD5064_CHANNEL(3, bits), \ |
302 | AD5064_CHANNEL(4, bits), \ | 332 | AD5064_CHANNEL(4, bits), \ |
303 | AD5064_CHANNEL(5, bits), \ | 333 | AD5064_CHANNEL(5, bits), \ |
304 | AD5064_CHANNEL(6, bits), \ | 334 | AD5064_CHANNEL(6, bits), \ |
305 | AD5064_CHANNEL(7, bits), \ | 335 | AD5064_CHANNEL(7, bits), \ |
306 | } | 336 | } |
307 | 337 | ||
308 | static DECLARE_AD5064_CHANNELS(ad5024_channels, 12); | 338 | static DECLARE_AD5064_CHANNELS(ad5024_channels, 12); |
309 | static DECLARE_AD5064_CHANNELS(ad5044_channels, 14); | 339 | static DECLARE_AD5064_CHANNELS(ad5044_channels, 14); |
310 | static DECLARE_AD5064_CHANNELS(ad5064_channels, 16); | 340 | static DECLARE_AD5064_CHANNELS(ad5064_channels, 16); |
311 | 341 | ||
312 | static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { | 342 | static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { |
313 | [ID_AD5024] = { | 343 | [ID_AD5024] = { |
314 | .shared_vref = false, | 344 | .shared_vref = false, |
315 | .channels = ad5024_channels, | 345 | .channels = ad5024_channels, |
316 | .num_channels = 4, | 346 | .num_channels = 4, |
317 | }, | 347 | }, |
318 | [ID_AD5025] = { | 348 | [ID_AD5025] = { |
319 | .shared_vref = false, | 349 | .shared_vref = false, |
320 | .channels = ad5024_channels, | 350 | .channels = ad5024_channels, |
321 | .num_channels = 2, | 351 | .num_channels = 2, |
322 | }, | 352 | }, |
323 | [ID_AD5044] = { | 353 | [ID_AD5044] = { |
324 | .shared_vref = false, | 354 | .shared_vref = false, |
325 | .channels = ad5044_channels, | 355 | .channels = ad5044_channels, |
326 | .num_channels = 4, | 356 | .num_channels = 4, |
327 | }, | 357 | }, |
328 | [ID_AD5045] = { | 358 | [ID_AD5045] = { |
329 | .shared_vref = false, | 359 | .shared_vref = false, |
330 | .channels = ad5044_channels, | 360 | .channels = ad5044_channels, |
331 | .num_channels = 2, | 361 | .num_channels = 2, |
332 | }, | 362 | }, |
333 | [ID_AD5064] = { | 363 | [ID_AD5064] = { |
334 | .shared_vref = false, | 364 | .shared_vref = false, |
335 | .channels = ad5064_channels, | 365 | .channels = ad5064_channels, |
336 | .num_channels = 4, | 366 | .num_channels = 4, |
337 | }, | 367 | }, |
338 | [ID_AD5064_1] = { | 368 | [ID_AD5064_1] = { |
339 | .shared_vref = true, | 369 | .shared_vref = true, |
340 | .channels = ad5064_channels, | 370 | .channels = ad5064_channels, |
341 | .num_channels = 4, | 371 | .num_channels = 4, |
342 | }, | 372 | }, |
343 | [ID_AD5065] = { | 373 | [ID_AD5065] = { |
344 | .shared_vref = false, | 374 | .shared_vref = false, |
345 | .channels = ad5064_channels, | 375 | .channels = ad5064_channels, |
346 | .num_channels = 2, | 376 | .num_channels = 2, |
347 | }, | 377 | }, |
348 | [ID_AD5628_1] = { | 378 | [ID_AD5628_1] = { |
349 | .shared_vref = true, | 379 | .shared_vref = true, |
350 | .internal_vref = 2500000, | 380 | .internal_vref = 2500000, |
351 | .channels = ad5024_channels, | 381 | .channels = ad5024_channels, |
352 | .num_channels = 8, | 382 | .num_channels = 8, |
353 | }, | 383 | }, |
354 | [ID_AD5628_2] = { | 384 | [ID_AD5628_2] = { |
355 | .shared_vref = true, | 385 | .shared_vref = true, |
356 | .internal_vref = 5000000, | 386 | .internal_vref = 5000000, |
357 | .channels = ad5024_channels, | 387 | .channels = ad5024_channels, |
358 | .num_channels = 8, | 388 | .num_channels = 8, |
359 | }, | 389 | }, |
360 | [ID_AD5648_1] = { | 390 | [ID_AD5648_1] = { |
361 | .shared_vref = true, | 391 | .shared_vref = true, |
362 | .internal_vref = 2500000, | 392 | .internal_vref = 2500000, |
363 | .channels = ad5044_channels, | 393 | .channels = ad5044_channels, |
364 | .num_channels = 8, | 394 | .num_channels = 8, |
365 | }, | 395 | }, |
366 | [ID_AD5648_2] = { | 396 | [ID_AD5648_2] = { |
367 | .shared_vref = true, | 397 | .shared_vref = true, |
368 | .internal_vref = 5000000, | 398 | .internal_vref = 5000000, |
369 | .channels = ad5044_channels, | 399 | .channels = ad5044_channels, |
370 | .num_channels = 8, | 400 | .num_channels = 8, |
371 | }, | 401 | }, |
372 | [ID_AD5666_1] = { | 402 | [ID_AD5666_1] = { |
373 | .shared_vref = true, | 403 | .shared_vref = true, |
374 | .internal_vref = 2500000, | 404 | .internal_vref = 2500000, |
375 | .channels = ad5064_channels, | 405 | .channels = ad5064_channels, |
376 | .num_channels = 4, | 406 | .num_channels = 4, |
377 | }, | 407 | }, |
378 | [ID_AD5666_2] = { | 408 | [ID_AD5666_2] = { |
379 | .shared_vref = true, | 409 | .shared_vref = true, |
380 | .internal_vref = 5000000, | 410 | .internal_vref = 5000000, |
381 | .channels = ad5064_channels, | 411 | .channels = ad5064_channels, |
382 | .num_channels = 4, | 412 | .num_channels = 4, |
383 | }, | 413 | }, |
384 | [ID_AD5668_1] = { | 414 | [ID_AD5668_1] = { |
385 | .shared_vref = true, | 415 | .shared_vref = true, |
386 | .internal_vref = 2500000, | 416 | .internal_vref = 2500000, |
387 | .channels = ad5064_channels, | 417 | .channels = ad5064_channels, |
388 | .num_channels = 8, | 418 | .num_channels = 8, |
389 | }, | 419 | }, |
390 | [ID_AD5668_2] = { | 420 | [ID_AD5668_2] = { |
391 | .shared_vref = true, | 421 | .shared_vref = true, |
392 | .internal_vref = 5000000, | 422 | .internal_vref = 5000000, |
393 | .channels = ad5064_channels, | 423 | .channels = ad5064_channels, |
394 | .num_channels = 8, | 424 | .num_channels = 8, |
395 | }, | 425 | }, |
396 | }; | 426 | }; |
397 | 427 | ||
398 | static inline unsigned int ad5064_num_vref(struct ad5064_state *st) | 428 | static inline unsigned int ad5064_num_vref(struct ad5064_state *st) |
399 | { | 429 | { |
400 | return st->chip_info->shared_vref ? 1 : st->chip_info->num_channels; | 430 | return st->chip_info->shared_vref ? 1 : st->chip_info->num_channels; |
401 | } | 431 | } |
402 | 432 | ||
403 | static const char * const ad5064_vref_names[] = { | 433 | static const char * const ad5064_vref_names[] = { |
404 | "vrefA", | 434 | "vrefA", |
405 | "vrefB", | 435 | "vrefB", |
406 | "vrefC", | 436 | "vrefC", |
407 | "vrefD", | 437 | "vrefD", |
408 | }; | 438 | }; |
409 | 439 | ||
410 | static const char * const ad5064_vref_name(struct ad5064_state *st, | 440 | static const char * const ad5064_vref_name(struct ad5064_state *st, |
411 | unsigned int vref) | 441 | unsigned int vref) |
412 | { | 442 | { |
413 | return st->chip_info->shared_vref ? "vref" : ad5064_vref_names[vref]; | 443 | return st->chip_info->shared_vref ? "vref" : ad5064_vref_names[vref]; |
414 | } | 444 | } |
415 | 445 | ||
416 | static int __devinit ad5064_probe(struct spi_device *spi) | 446 | static int __devinit ad5064_probe(struct device *dev, enum ad5064_type type, |
447 | const char *name, ad5064_write_func write) | ||
417 | { | 448 | { |
418 | enum ad5064_type type = spi_get_device_id(spi)->driver_data; | ||
419 | struct iio_dev *indio_dev; | 449 | struct iio_dev *indio_dev; |
420 | struct ad5064_state *st; | 450 | struct ad5064_state *st; |
421 | unsigned int i; | 451 | unsigned int i; |
422 | int ret; | 452 | int ret; |
423 | 453 | ||
424 | indio_dev = iio_device_alloc(sizeof(*st)); | 454 | indio_dev = iio_device_alloc(sizeof(*st)); |
425 | if (indio_dev == NULL) | 455 | if (indio_dev == NULL) |
426 | return -ENOMEM; | 456 | return -ENOMEM; |
427 | 457 | ||
428 | st = iio_priv(indio_dev); | 458 | st = iio_priv(indio_dev); |
429 | spi_set_drvdata(spi, indio_dev); | 459 | dev_set_drvdata(dev, indio_dev); |
430 | 460 | ||
431 | st->chip_info = &ad5064_chip_info_tbl[type]; | 461 | st->chip_info = &ad5064_chip_info_tbl[type]; |
432 | st->spi = spi; | 462 | st->dev = dev; |
463 | st->write = write; | ||
433 | 464 | ||
434 | for (i = 0; i < ad5064_num_vref(st); ++i) | 465 | for (i = 0; i < ad5064_num_vref(st); ++i) |
435 | st->vref_reg[i].supply = ad5064_vref_name(st, i); | 466 | st->vref_reg[i].supply = ad5064_vref_name(st, i); |
436 | 467 | ||
437 | ret = regulator_bulk_get(&st->spi->dev, ad5064_num_vref(st), | 468 | ret = regulator_bulk_get(dev, ad5064_num_vref(st), |
438 | st->vref_reg); | 469 | st->vref_reg); |
439 | if (ret) { | 470 | if (ret) { |
440 | if (!st->chip_info->internal_vref) | 471 | if (!st->chip_info->internal_vref) |
441 | goto error_free; | 472 | goto error_free; |
442 | st->use_internal_vref = true; | 473 | st->use_internal_vref = true; |
443 | ret = ad5064_spi_write(st, AD5064_CMD_CONFIG, 0, | 474 | ret = ad5064_write(st, AD5064_CMD_CONFIG, 0, |
444 | AD5064_CONFIG_INT_VREF_ENABLE, 0); | 475 | AD5064_CONFIG_INT_VREF_ENABLE, 0); |
445 | if (ret) { | 476 | if (ret) { |
446 | dev_err(&spi->dev, "Failed to enable internal vref: %d\n", | 477 | dev_err(dev, "Failed to enable internal vref: %d\n", |
447 | ret); | 478 | ret); |
448 | goto error_free; | 479 | goto error_free; |
449 | } | 480 | } |
450 | } else { | 481 | } else { |
451 | ret = regulator_bulk_enable(ad5064_num_vref(st), st->vref_reg); | 482 | ret = regulator_bulk_enable(ad5064_num_vref(st), st->vref_reg); |
452 | if (ret) | 483 | if (ret) |
453 | goto error_free_reg; | 484 | goto error_free_reg; |
454 | } | 485 | } |
455 | 486 | ||
456 | for (i = 0; i < st->chip_info->num_channels; ++i) { | 487 | for (i = 0; i < st->chip_info->num_channels; ++i) { |
457 | st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K; | 488 | st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K; |
458 | st->dac_cache[i] = 0x8000; | 489 | st->dac_cache[i] = 0x8000; |
459 | } | 490 | } |
460 | 491 | ||
461 | indio_dev->dev.parent = &spi->dev; | 492 | indio_dev->dev.parent = dev; |
462 | indio_dev->name = spi_get_device_id(spi)->name; | 493 | indio_dev->name = name; |
463 | indio_dev->info = &ad5064_info; | 494 | indio_dev->info = &ad5064_info; |
464 | indio_dev->modes = INDIO_DIRECT_MODE; | 495 | indio_dev->modes = INDIO_DIRECT_MODE; |
465 | indio_dev->channels = st->chip_info->channels; | 496 | indio_dev->channels = st->chip_info->channels; |
466 | indio_dev->num_channels = st->chip_info->num_channels; | 497 | indio_dev->num_channels = st->chip_info->num_channels; |
467 | 498 | ||
468 | ret = iio_device_register(indio_dev); | 499 | ret = iio_device_register(indio_dev); |
469 | if (ret) | 500 | if (ret) |
470 | goto error_disable_reg; | 501 | goto error_disable_reg; |
471 | 502 | ||
472 | return 0; | 503 | return 0; |
473 | 504 | ||
474 | error_disable_reg: | 505 | error_disable_reg: |
475 | if (!st->use_internal_vref) | 506 | if (!st->use_internal_vref) |
476 | regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); | 507 | regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); |
477 | error_free_reg: | 508 | error_free_reg: |
478 | if (!st->use_internal_vref) | 509 | if (!st->use_internal_vref) |
479 | regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); | 510 | regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); |
480 | error_free: | 511 | error_free: |
481 | iio_device_free(indio_dev); | 512 | iio_device_free(indio_dev); |
482 | 513 | ||
483 | return ret; | 514 | return ret; |
484 | } | 515 | } |
485 | 516 | ||
486 | 517 | static int __devexit ad5064_remove(struct device *dev) | |
487 | static int __devexit ad5064_remove(struct spi_device *spi) | ||
488 | { | 518 | { |
489 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | 519 | struct iio_dev *indio_dev = dev_get_drvdata(dev); |
490 | struct ad5064_state *st = iio_priv(indio_dev); | 520 | struct ad5064_state *st = iio_priv(indio_dev); |
491 | 521 | ||
492 | iio_device_unregister(indio_dev); | 522 | iio_device_unregister(indio_dev); |
493 | 523 | ||
494 | if (!st->use_internal_vref) { | 524 | if (!st->use_internal_vref) { |
495 | regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); | 525 | regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); |
496 | regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); | 526 | regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); |
497 | } | 527 | } |
498 | 528 | ||
499 | iio_device_free(indio_dev); | 529 | iio_device_free(indio_dev); |
500 | 530 | ||
501 | return 0; | 531 | return 0; |
502 | } | 532 | } |
503 | 533 | ||
504 | static const struct spi_device_id ad5064_id[] = { | 534 | #if IS_ENABLED(CONFIG_SPI_MASTER) |
535 | |||
536 | static int __devinit ad5064_spi_probe(struct spi_device *spi) | ||
537 | { | ||
538 | const struct spi_device_id *id = spi_get_device_id(spi); | ||
539 | |||
540 | return ad5064_probe(&spi->dev, id->driver_data, id->name, | ||
541 | ad5064_spi_write); | ||
542 | } | ||
543 | |||
544 | static int __devexit ad5064_spi_remove(struct spi_device *spi) | ||
545 | { | ||
546 | return ad5064_remove(&spi->dev); | ||
547 | } | ||
548 | |||
549 | static const struct spi_device_id ad5064_spi_ids[] = { | ||
505 | {"ad5024", ID_AD5024}, | 550 | {"ad5024", ID_AD5024}, |
506 | {"ad5025", ID_AD5025}, | 551 | {"ad5025", ID_AD5025}, |
507 | {"ad5044", ID_AD5044}, | 552 | {"ad5044", ID_AD5044}, |
508 | {"ad5045", ID_AD5045}, | 553 | {"ad5045", ID_AD5045}, |
509 | {"ad5064", ID_AD5064}, | 554 | {"ad5064", ID_AD5064}, |
510 | {"ad5064-1", ID_AD5064_1}, | 555 | {"ad5064-1", ID_AD5064_1}, |
511 | {"ad5065", ID_AD5065}, | 556 | {"ad5065", ID_AD5065}, |
512 | {"ad5628-1", ID_AD5628_1}, | 557 | {"ad5628-1", ID_AD5628_1}, |
513 | {"ad5628-2", ID_AD5628_2}, | 558 | {"ad5628-2", ID_AD5628_2}, |
514 | {"ad5648-1", ID_AD5648_1}, | 559 | {"ad5648-1", ID_AD5648_1}, |
515 | {"ad5648-2", ID_AD5648_2}, | 560 | {"ad5648-2", ID_AD5648_2}, |
516 | {"ad5666-1", ID_AD5666_1}, | 561 | {"ad5666-1", ID_AD5666_1}, |
517 | {"ad5666-2", ID_AD5666_2}, | 562 | {"ad5666-2", ID_AD5666_2}, |
518 | {"ad5668-1", ID_AD5668_1}, | 563 | {"ad5668-1", ID_AD5668_1}, |
519 | {"ad5668-2", ID_AD5668_2}, | 564 | {"ad5668-2", ID_AD5668_2}, |
520 | {"ad5668-3", ID_AD5668_2}, /* similar enough to ad5668-2 */ | 565 | {"ad5668-3", ID_AD5668_2}, /* similar enough to ad5668-2 */ |
521 | {} | 566 | {} |
522 | }; | 567 | }; |
523 | MODULE_DEVICE_TABLE(spi, ad5064_id); | 568 | MODULE_DEVICE_TABLE(spi, ad5064_spi_ids); |
524 | 569 | ||
525 | static struct spi_driver ad5064_driver = { | 570 | static struct spi_driver ad5064_spi_driver = { |
526 | .driver = { | 571 | .driver = { |
527 | .name = "ad5064", | 572 | .name = "ad5064", |
528 | .owner = THIS_MODULE, | 573 | .owner = THIS_MODULE, |
529 | }, | 574 | }, |
530 | .probe = ad5064_probe, | 575 | .probe = ad5064_spi_probe, |
531 | .remove = __devexit_p(ad5064_remove), | 576 | .remove = __devexit_p(ad5064_spi_remove), |
532 | .id_table = ad5064_id, | 577 | .id_table = ad5064_spi_ids, |
533 | }; | 578 | }; |
534 | module_spi_driver(ad5064_driver); | ||
535 | 579 | ||
580 | static int __init ad5064_spi_register_driver(void) | ||
581 | { | ||
582 | return spi_register_driver(&ad5064_spi_driver); | ||
583 | } | ||
584 | |||
585 | static void __exit ad5064_spi_unregister_driver(void) | ||
586 | { | ||
587 | spi_unregister_driver(&ad5064_spi_driver); | ||
588 | } | ||
589 | |||
590 | #else | ||
591 | |||
592 | static inline int ad5064_spi_register_driver(void) { return 0; } | ||
593 | static inline void ad5064_spi_unregister_driver(void) { } | ||
594 | |||
595 | #endif | ||
596 | |||
597 | #if IS_ENABLED(CONFIG_I2C) | ||
598 | |||
599 | static int __devinit ad5064_i2c_probe(struct i2c_client *i2c, | ||
600 | const struct i2c_device_id *id) | ||
601 | { | ||
602 | return ad5064_probe(&i2c->dev, id->driver_data, id->name, | ||
603 | ad5064_i2c_write); | ||
604 | } | ||
605 | |||
606 | static int __devexit ad5064_i2c_remove(struct i2c_client *i2c) | ||
607 | { | ||
608 | return ad5064_remove(&i2c->dev); | ||
609 | } | ||
610 | |||
611 | static const struct i2c_device_id ad5064_i2c_ids[] = { | ||
612 | {"ad5629-1", ID_AD5628_1}, | ||
613 | {"ad5629-2", ID_AD5628_2}, | ||
614 | {"ad5629-3", ID_AD5628_2}, /* similar enough to ad5629-2 */ | ||
615 | {"ad5669-1", ID_AD5668_1}, | ||
616 | {"ad5669-2", ID_AD5668_2}, | ||
617 | {"ad5669-3", ID_AD5668_2}, /* similar enough to ad5669-2 */ | ||
618 | {} | ||
619 | }; | ||
620 | MODULE_DEVICE_TABLE(i2c, ad5064_i2c_ids); | ||
621 | |||
622 | static struct i2c_driver ad5064_i2c_driver = { | ||
623 | .driver = { | ||
624 | .name = "ad5064", | ||
625 | .owner = THIS_MODULE, | ||
626 | }, | ||
627 | .probe = ad5064_i2c_probe, | ||
628 | .remove = __devexit_p(ad5064_i2c_remove), | ||
629 | .id_table = ad5064_i2c_ids, | ||
630 | }; | ||
631 | |||
632 | static int __init ad5064_i2c_register_driver(void) | ||
633 | { | ||
634 | return i2c_add_driver(&ad5064_i2c_driver); | ||
635 | } | ||
636 | |||
637 | static void __exit ad5064_i2c_unregister_driver(void) | ||
638 | { | ||
639 | i2c_del_driver(&ad5064_i2c_driver); | ||
640 | } | ||
641 | |||
642 | #else | ||
643 | |||
644 | static inline int ad5064_i2c_register_driver(void) { return 0; } | ||
645 | static inline void ad5064_i2c_unregister_driver(void) { } | ||
646 | |||
647 | #endif | ||
648 | |||
649 | static int __init ad5064_init(void) | ||
650 | { | ||
651 | int ret; | ||
652 | |||
653 | ret = ad5064_spi_register_driver(); | ||
654 | if (ret) | ||
655 | return ret; | ||
656 | |||
657 | ret = ad5064_i2c_register_driver(); | ||
658 | if (ret) { | ||
659 | ad5064_spi_unregister_driver(); | ||
660 | return ret; | ||
661 | } | ||
662 | |||
663 | return 0; | ||
664 | } | ||
665 | module_init(ad5064_init); | ||
666 | |||
667 | static void __exit ad5064_exit(void) | ||
668 | { | ||
669 | ad5064_i2c_unregister_driver(); | ||
670 | ad5064_spi_unregister_driver(); | ||
671 | } | ||
672 | module_exit(ad5064_exit); |
drivers/iio/industrialio-core.c
1 | /* The industrial I/O core | 1 | /* The industrial I/O core |
2 | * | 2 | * |
3 | * Copyright (c) 2008 Jonathan Cameron | 3 | * Copyright (c) 2008 Jonathan Cameron |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 as published by | 6 | * under the terms of the GNU General Public License version 2 as published by |
7 | * the Free Software Foundation. | 7 | * the Free Software Foundation. |
8 | * | 8 | * |
9 | * Based on elements of hwmon and input subsystems. | 9 | * Based on elements of hwmon and input subsystems. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/idr.h> | 14 | #include <linux/idr.h> |
15 | #include <linux/kdev_t.h> | 15 | #include <linux/kdev_t.h> |
16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
17 | #include <linux/device.h> | 17 | #include <linux/device.h> |
18 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
19 | #include <linux/poll.h> | 19 | #include <linux/poll.h> |
20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
21 | #include <linux/wait.h> | 21 | #include <linux/wait.h> |
22 | #include <linux/cdev.h> | 22 | #include <linux/cdev.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/anon_inodes.h> | 24 | #include <linux/anon_inodes.h> |
25 | #include <linux/debugfs.h> | 25 | #include <linux/debugfs.h> |
26 | #include <linux/iio/iio.h> | 26 | #include <linux/iio/iio.h> |
27 | #include "iio_core.h" | 27 | #include "iio_core.h" |
28 | #include "iio_core_trigger.h" | 28 | #include "iio_core_trigger.h" |
29 | #include <linux/iio/sysfs.h> | 29 | #include <linux/iio/sysfs.h> |
30 | #include <linux/iio/events.h> | 30 | #include <linux/iio/events.h> |
31 | 31 | ||
32 | /* IDA to assign each registered device a unique id*/ | 32 | /* IDA to assign each registered device a unique id*/ |
33 | static DEFINE_IDA(iio_ida); | 33 | static DEFINE_IDA(iio_ida); |
34 | 34 | ||
35 | static dev_t iio_devt; | 35 | static dev_t iio_devt; |
36 | 36 | ||
37 | #define IIO_DEV_MAX 256 | 37 | #define IIO_DEV_MAX 256 |
38 | struct bus_type iio_bus_type = { | 38 | struct bus_type iio_bus_type = { |
39 | .name = "iio", | 39 | .name = "iio", |
40 | }; | 40 | }; |
41 | EXPORT_SYMBOL(iio_bus_type); | 41 | EXPORT_SYMBOL(iio_bus_type); |
42 | 42 | ||
43 | static struct dentry *iio_debugfs_dentry; | 43 | static struct dentry *iio_debugfs_dentry; |
44 | 44 | ||
45 | static const char * const iio_direction[] = { | 45 | static const char * const iio_direction[] = { |
46 | [0] = "in", | 46 | [0] = "in", |
47 | [1] = "out", | 47 | [1] = "out", |
48 | }; | 48 | }; |
49 | 49 | ||
50 | static const char * const iio_chan_type_name_spec[] = { | 50 | static const char * const iio_chan_type_name_spec[] = { |
51 | [IIO_VOLTAGE] = "voltage", | 51 | [IIO_VOLTAGE] = "voltage", |
52 | [IIO_CURRENT] = "current", | 52 | [IIO_CURRENT] = "current", |
53 | [IIO_POWER] = "power", | 53 | [IIO_POWER] = "power", |
54 | [IIO_ACCEL] = "accel", | 54 | [IIO_ACCEL] = "accel", |
55 | [IIO_ANGL_VEL] = "anglvel", | 55 | [IIO_ANGL_VEL] = "anglvel", |
56 | [IIO_MAGN] = "magn", | 56 | [IIO_MAGN] = "magn", |
57 | [IIO_LIGHT] = "illuminance", | 57 | [IIO_LIGHT] = "illuminance", |
58 | [IIO_INTENSITY] = "intensity", | 58 | [IIO_INTENSITY] = "intensity", |
59 | [IIO_PROXIMITY] = "proximity", | 59 | [IIO_PROXIMITY] = "proximity", |
60 | [IIO_TEMP] = "temp", | 60 | [IIO_TEMP] = "temp", |
61 | [IIO_INCLI] = "incli", | 61 | [IIO_INCLI] = "incli", |
62 | [IIO_ROT] = "rot", | 62 | [IIO_ROT] = "rot", |
63 | [IIO_ANGL] = "angl", | 63 | [IIO_ANGL] = "angl", |
64 | [IIO_TIMESTAMP] = "timestamp", | 64 | [IIO_TIMESTAMP] = "timestamp", |
65 | [IIO_CAPACITANCE] = "capacitance", | 65 | [IIO_CAPACITANCE] = "capacitance", |
66 | [IIO_ALTVOLTAGE] = "altvoltage", | 66 | [IIO_ALTVOLTAGE] = "altvoltage", |
67 | }; | 67 | }; |
68 | 68 | ||
69 | static const char * const iio_modifier_names[] = { | 69 | static const char * const iio_modifier_names[] = { |
70 | [IIO_MOD_X] = "x", | 70 | [IIO_MOD_X] = "x", |
71 | [IIO_MOD_Y] = "y", | 71 | [IIO_MOD_Y] = "y", |
72 | [IIO_MOD_Z] = "z", | 72 | [IIO_MOD_Z] = "z", |
73 | [IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)", | ||
74 | [IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2", | ||
73 | [IIO_MOD_LIGHT_BOTH] = "both", | 75 | [IIO_MOD_LIGHT_BOTH] = "both", |
74 | [IIO_MOD_LIGHT_IR] = "ir", | 76 | [IIO_MOD_LIGHT_IR] = "ir", |
75 | }; | 77 | }; |
76 | 78 | ||
77 | /* relies on pairs of these shared then separate */ | 79 | /* relies on pairs of these shared then separate */ |
78 | static const char * const iio_chan_info_postfix[] = { | 80 | static const char * const iio_chan_info_postfix[] = { |
79 | [IIO_CHAN_INFO_RAW] = "raw", | 81 | [IIO_CHAN_INFO_RAW] = "raw", |
80 | [IIO_CHAN_INFO_PROCESSED] = "input", | 82 | [IIO_CHAN_INFO_PROCESSED] = "input", |
81 | [IIO_CHAN_INFO_SCALE] = "scale", | 83 | [IIO_CHAN_INFO_SCALE] = "scale", |
82 | [IIO_CHAN_INFO_OFFSET] = "offset", | 84 | [IIO_CHAN_INFO_OFFSET] = "offset", |
83 | [IIO_CHAN_INFO_CALIBSCALE] = "calibscale", | 85 | [IIO_CHAN_INFO_CALIBSCALE] = "calibscale", |
84 | [IIO_CHAN_INFO_CALIBBIAS] = "calibbias", | 86 | [IIO_CHAN_INFO_CALIBBIAS] = "calibbias", |
85 | [IIO_CHAN_INFO_PEAK] = "peak_raw", | 87 | [IIO_CHAN_INFO_PEAK] = "peak_raw", |
86 | [IIO_CHAN_INFO_PEAK_SCALE] = "peak_scale", | 88 | [IIO_CHAN_INFO_PEAK_SCALE] = "peak_scale", |
87 | [IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW] = "quadrature_correction_raw", | 89 | [IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW] = "quadrature_correction_raw", |
88 | [IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw", | 90 | [IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw", |
89 | [IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY] | 91 | [IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY] |
90 | = "filter_low_pass_3db_frequency", | 92 | = "filter_low_pass_3db_frequency", |
91 | [IIO_CHAN_INFO_SAMP_FREQ] = "sampling_frequency", | 93 | [IIO_CHAN_INFO_SAMP_FREQ] = "sampling_frequency", |
92 | [IIO_CHAN_INFO_FREQUENCY] = "frequency", | 94 | [IIO_CHAN_INFO_FREQUENCY] = "frequency", |
93 | [IIO_CHAN_INFO_PHASE] = "phase", | 95 | [IIO_CHAN_INFO_PHASE] = "phase", |
94 | [IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain", | 96 | [IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain", |
95 | }; | 97 | }; |
96 | 98 | ||
97 | const struct iio_chan_spec | 99 | const struct iio_chan_spec |
98 | *iio_find_channel_from_si(struct iio_dev *indio_dev, int si) | 100 | *iio_find_channel_from_si(struct iio_dev *indio_dev, int si) |
99 | { | 101 | { |
100 | int i; | 102 | int i; |
101 | 103 | ||
102 | for (i = 0; i < indio_dev->num_channels; i++) | 104 | for (i = 0; i < indio_dev->num_channels; i++) |
103 | if (indio_dev->channels[i].scan_index == si) | 105 | if (indio_dev->channels[i].scan_index == si) |
104 | return &indio_dev->channels[i]; | 106 | return &indio_dev->channels[i]; |
105 | return NULL; | 107 | return NULL; |
106 | } | 108 | } |
107 | 109 | ||
108 | /* This turns up an awful lot */ | 110 | /* This turns up an awful lot */ |
109 | ssize_t iio_read_const_attr(struct device *dev, | 111 | ssize_t iio_read_const_attr(struct device *dev, |
110 | struct device_attribute *attr, | 112 | struct device_attribute *attr, |
111 | char *buf) | 113 | char *buf) |
112 | { | 114 | { |
113 | return sprintf(buf, "%s\n", to_iio_const_attr(attr)->string); | 115 | return sprintf(buf, "%s\n", to_iio_const_attr(attr)->string); |
114 | } | 116 | } |
115 | EXPORT_SYMBOL(iio_read_const_attr); | 117 | EXPORT_SYMBOL(iio_read_const_attr); |
116 | 118 | ||
117 | static int __init iio_init(void) | 119 | static int __init iio_init(void) |
118 | { | 120 | { |
119 | int ret; | 121 | int ret; |
120 | 122 | ||
121 | /* Register sysfs bus */ | 123 | /* Register sysfs bus */ |
122 | ret = bus_register(&iio_bus_type); | 124 | ret = bus_register(&iio_bus_type); |
123 | if (ret < 0) { | 125 | if (ret < 0) { |
124 | printk(KERN_ERR | 126 | printk(KERN_ERR |
125 | "%s could not register bus type\n", | 127 | "%s could not register bus type\n", |
126 | __FILE__); | 128 | __FILE__); |
127 | goto error_nothing; | 129 | goto error_nothing; |
128 | } | 130 | } |
129 | 131 | ||
130 | ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio"); | 132 | ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio"); |
131 | if (ret < 0) { | 133 | if (ret < 0) { |
132 | printk(KERN_ERR "%s: failed to allocate char dev region\n", | 134 | printk(KERN_ERR "%s: failed to allocate char dev region\n", |
133 | __FILE__); | 135 | __FILE__); |
134 | goto error_unregister_bus_type; | 136 | goto error_unregister_bus_type; |
135 | } | 137 | } |
136 | 138 | ||
137 | iio_debugfs_dentry = debugfs_create_dir("iio", NULL); | 139 | iio_debugfs_dentry = debugfs_create_dir("iio", NULL); |
138 | 140 | ||
139 | return 0; | 141 | return 0; |
140 | 142 | ||
141 | error_unregister_bus_type: | 143 | error_unregister_bus_type: |
142 | bus_unregister(&iio_bus_type); | 144 | bus_unregister(&iio_bus_type); |
143 | error_nothing: | 145 | error_nothing: |
144 | return ret; | 146 | return ret; |
145 | } | 147 | } |
146 | 148 | ||
147 | static void __exit iio_exit(void) | 149 | static void __exit iio_exit(void) |
148 | { | 150 | { |
149 | if (iio_devt) | 151 | if (iio_devt) |
150 | unregister_chrdev_region(iio_devt, IIO_DEV_MAX); | 152 | unregister_chrdev_region(iio_devt, IIO_DEV_MAX); |
151 | bus_unregister(&iio_bus_type); | 153 | bus_unregister(&iio_bus_type); |
152 | debugfs_remove(iio_debugfs_dentry); | 154 | debugfs_remove(iio_debugfs_dentry); |
153 | } | 155 | } |
154 | 156 | ||
155 | #if defined(CONFIG_DEBUG_FS) | 157 | #if defined(CONFIG_DEBUG_FS) |
156 | static ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf, | 158 | static ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf, |
157 | size_t count, loff_t *ppos) | 159 | size_t count, loff_t *ppos) |
158 | { | 160 | { |
159 | struct iio_dev *indio_dev = file->private_data; | 161 | struct iio_dev *indio_dev = file->private_data; |
160 | char buf[20]; | 162 | char buf[20]; |
161 | unsigned val = 0; | 163 | unsigned val = 0; |
162 | ssize_t len; | 164 | ssize_t len; |
163 | int ret; | 165 | int ret; |
164 | 166 | ||
165 | ret = indio_dev->info->debugfs_reg_access(indio_dev, | 167 | ret = indio_dev->info->debugfs_reg_access(indio_dev, |
166 | indio_dev->cached_reg_addr, | 168 | indio_dev->cached_reg_addr, |
167 | 0, &val); | 169 | 0, &val); |
168 | if (ret) | 170 | if (ret) |
169 | dev_err(indio_dev->dev.parent, "%s: read failed\n", __func__); | 171 | dev_err(indio_dev->dev.parent, "%s: read failed\n", __func__); |
170 | 172 | ||
171 | len = snprintf(buf, sizeof(buf), "0x%X\n", val); | 173 | len = snprintf(buf, sizeof(buf), "0x%X\n", val); |
172 | 174 | ||
173 | return simple_read_from_buffer(userbuf, count, ppos, buf, len); | 175 | return simple_read_from_buffer(userbuf, count, ppos, buf, len); |
174 | } | 176 | } |
175 | 177 | ||
176 | static ssize_t iio_debugfs_write_reg(struct file *file, | 178 | static ssize_t iio_debugfs_write_reg(struct file *file, |
177 | const char __user *userbuf, size_t count, loff_t *ppos) | 179 | const char __user *userbuf, size_t count, loff_t *ppos) |
178 | { | 180 | { |
179 | struct iio_dev *indio_dev = file->private_data; | 181 | struct iio_dev *indio_dev = file->private_data; |
180 | unsigned reg, val; | 182 | unsigned reg, val; |
181 | char buf[80]; | 183 | char buf[80]; |
182 | int ret; | 184 | int ret; |
183 | 185 | ||
184 | count = min_t(size_t, count, (sizeof(buf)-1)); | 186 | count = min_t(size_t, count, (sizeof(buf)-1)); |
185 | if (copy_from_user(buf, userbuf, count)) | 187 | if (copy_from_user(buf, userbuf, count)) |
186 | return -EFAULT; | 188 | return -EFAULT; |
187 | 189 | ||
188 | buf[count] = 0; | 190 | buf[count] = 0; |
189 | 191 | ||
190 | ret = sscanf(buf, "%i %i", ®, &val); | 192 | ret = sscanf(buf, "%i %i", ®, &val); |
191 | 193 | ||
192 | switch (ret) { | 194 | switch (ret) { |
193 | case 1: | 195 | case 1: |
194 | indio_dev->cached_reg_addr = reg; | 196 | indio_dev->cached_reg_addr = reg; |
195 | break; | 197 | break; |
196 | case 2: | 198 | case 2: |
197 | indio_dev->cached_reg_addr = reg; | 199 | indio_dev->cached_reg_addr = reg; |
198 | ret = indio_dev->info->debugfs_reg_access(indio_dev, reg, | 200 | ret = indio_dev->info->debugfs_reg_access(indio_dev, reg, |
199 | val, NULL); | 201 | val, NULL); |
200 | if (ret) { | 202 | if (ret) { |
201 | dev_err(indio_dev->dev.parent, "%s: write failed\n", | 203 | dev_err(indio_dev->dev.parent, "%s: write failed\n", |
202 | __func__); | 204 | __func__); |
203 | return ret; | 205 | return ret; |
204 | } | 206 | } |
205 | break; | 207 | break; |
206 | default: | 208 | default: |
207 | return -EINVAL; | 209 | return -EINVAL; |
208 | } | 210 | } |
209 | 211 | ||
210 | return count; | 212 | return count; |
211 | } | 213 | } |
212 | 214 | ||
213 | static const struct file_operations iio_debugfs_reg_fops = { | 215 | static const struct file_operations iio_debugfs_reg_fops = { |
214 | .open = simple_open, | 216 | .open = simple_open, |
215 | .read = iio_debugfs_read_reg, | 217 | .read = iio_debugfs_read_reg, |
216 | .write = iio_debugfs_write_reg, | 218 | .write = iio_debugfs_write_reg, |
217 | }; | 219 | }; |
218 | 220 | ||
219 | static void iio_device_unregister_debugfs(struct iio_dev *indio_dev) | 221 | static void iio_device_unregister_debugfs(struct iio_dev *indio_dev) |
220 | { | 222 | { |
221 | debugfs_remove_recursive(indio_dev->debugfs_dentry); | 223 | debugfs_remove_recursive(indio_dev->debugfs_dentry); |
222 | } | 224 | } |
223 | 225 | ||
224 | static int iio_device_register_debugfs(struct iio_dev *indio_dev) | 226 | static int iio_device_register_debugfs(struct iio_dev *indio_dev) |
225 | { | 227 | { |
226 | struct dentry *d; | 228 | struct dentry *d; |
227 | 229 | ||
228 | if (indio_dev->info->debugfs_reg_access == NULL) | 230 | if (indio_dev->info->debugfs_reg_access == NULL) |
229 | return 0; | 231 | return 0; |
230 | 232 | ||
231 | if (!iio_debugfs_dentry) | 233 | if (!iio_debugfs_dentry) |
232 | return 0; | 234 | return 0; |
233 | 235 | ||
234 | indio_dev->debugfs_dentry = | 236 | indio_dev->debugfs_dentry = |
235 | debugfs_create_dir(dev_name(&indio_dev->dev), | 237 | debugfs_create_dir(dev_name(&indio_dev->dev), |
236 | iio_debugfs_dentry); | 238 | iio_debugfs_dentry); |
237 | if (indio_dev->debugfs_dentry == NULL) { | 239 | if (indio_dev->debugfs_dentry == NULL) { |
238 | dev_warn(indio_dev->dev.parent, | 240 | dev_warn(indio_dev->dev.parent, |
239 | "Failed to create debugfs directory\n"); | 241 | "Failed to create debugfs directory\n"); |
240 | return -EFAULT; | 242 | return -EFAULT; |
241 | } | 243 | } |
242 | 244 | ||
243 | d = debugfs_create_file("direct_reg_access", 0644, | 245 | d = debugfs_create_file("direct_reg_access", 0644, |
244 | indio_dev->debugfs_dentry, | 246 | indio_dev->debugfs_dentry, |
245 | indio_dev, &iio_debugfs_reg_fops); | 247 | indio_dev, &iio_debugfs_reg_fops); |
246 | if (!d) { | 248 | if (!d) { |
247 | iio_device_unregister_debugfs(indio_dev); | 249 | iio_device_unregister_debugfs(indio_dev); |
248 | return -ENOMEM; | 250 | return -ENOMEM; |
249 | } | 251 | } |
250 | 252 | ||
251 | return 0; | 253 | return 0; |
252 | } | 254 | } |
253 | #else | 255 | #else |
254 | static int iio_device_register_debugfs(struct iio_dev *indio_dev) | 256 | static int iio_device_register_debugfs(struct iio_dev *indio_dev) |
255 | { | 257 | { |
256 | return 0; | 258 | return 0; |
257 | } | 259 | } |
258 | 260 | ||
259 | static void iio_device_unregister_debugfs(struct iio_dev *indio_dev) | 261 | static void iio_device_unregister_debugfs(struct iio_dev *indio_dev) |
260 | { | 262 | { |
261 | } | 263 | } |
262 | #endif /* CONFIG_DEBUG_FS */ | 264 | #endif /* CONFIG_DEBUG_FS */ |
263 | 265 | ||
264 | static ssize_t iio_read_channel_ext_info(struct device *dev, | 266 | static ssize_t iio_read_channel_ext_info(struct device *dev, |
265 | struct device_attribute *attr, | 267 | struct device_attribute *attr, |
266 | char *buf) | 268 | char *buf) |
267 | { | 269 | { |
268 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 270 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
269 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | 271 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
270 | const struct iio_chan_spec_ext_info *ext_info; | 272 | const struct iio_chan_spec_ext_info *ext_info; |
271 | 273 | ||
272 | ext_info = &this_attr->c->ext_info[this_attr->address]; | 274 | ext_info = &this_attr->c->ext_info[this_attr->address]; |
273 | 275 | ||
274 | return ext_info->read(indio_dev, ext_info->private, this_attr->c, buf); | 276 | return ext_info->read(indio_dev, ext_info->private, this_attr->c, buf); |
275 | } | 277 | } |
276 | 278 | ||
277 | static ssize_t iio_write_channel_ext_info(struct device *dev, | 279 | static ssize_t iio_write_channel_ext_info(struct device *dev, |
278 | struct device_attribute *attr, | 280 | struct device_attribute *attr, |
279 | const char *buf, | 281 | const char *buf, |
280 | size_t len) | 282 | size_t len) |
281 | { | 283 | { |
282 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 284 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
283 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | 285 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
284 | const struct iio_chan_spec_ext_info *ext_info; | 286 | const struct iio_chan_spec_ext_info *ext_info; |
285 | 287 | ||
286 | ext_info = &this_attr->c->ext_info[this_attr->address]; | 288 | ext_info = &this_attr->c->ext_info[this_attr->address]; |
287 | 289 | ||
288 | return ext_info->write(indio_dev, ext_info->private, | 290 | return ext_info->write(indio_dev, ext_info->private, |
289 | this_attr->c, buf, len); | 291 | this_attr->c, buf, len); |
290 | } | 292 | } |
291 | 293 | ||
292 | ssize_t iio_enum_available_read(struct iio_dev *indio_dev, | 294 | ssize_t iio_enum_available_read(struct iio_dev *indio_dev, |
293 | uintptr_t priv, const struct iio_chan_spec *chan, char *buf) | 295 | uintptr_t priv, const struct iio_chan_spec *chan, char *buf) |
294 | { | 296 | { |
295 | const struct iio_enum *e = (const struct iio_enum *)priv; | 297 | const struct iio_enum *e = (const struct iio_enum *)priv; |
296 | unsigned int i; | 298 | unsigned int i; |
297 | size_t len = 0; | 299 | size_t len = 0; |
298 | 300 | ||
299 | if (!e->num_items) | 301 | if (!e->num_items) |
300 | return 0; | 302 | return 0; |
301 | 303 | ||
302 | for (i = 0; i < e->num_items; ++i) | 304 | for (i = 0; i < e->num_items; ++i) |
303 | len += scnprintf(buf + len, PAGE_SIZE - len, "%s ", e->items[i]); | 305 | len += scnprintf(buf + len, PAGE_SIZE - len, "%s ", e->items[i]); |
304 | 306 | ||
305 | /* replace last space with a newline */ | 307 | /* replace last space with a newline */ |
306 | buf[len - 1] = '\n'; | 308 | buf[len - 1] = '\n'; |
307 | 309 | ||
308 | return len; | 310 | return len; |
309 | } | 311 | } |
310 | EXPORT_SYMBOL_GPL(iio_enum_available_read); | 312 | EXPORT_SYMBOL_GPL(iio_enum_available_read); |
311 | 313 | ||
312 | ssize_t iio_enum_read(struct iio_dev *indio_dev, | 314 | ssize_t iio_enum_read(struct iio_dev *indio_dev, |
313 | uintptr_t priv, const struct iio_chan_spec *chan, char *buf) | 315 | uintptr_t priv, const struct iio_chan_spec *chan, char *buf) |
314 | { | 316 | { |
315 | const struct iio_enum *e = (const struct iio_enum *)priv; | 317 | const struct iio_enum *e = (const struct iio_enum *)priv; |
316 | int i; | 318 | int i; |
317 | 319 | ||
318 | if (!e->get) | 320 | if (!e->get) |
319 | return -EINVAL; | 321 | return -EINVAL; |
320 | 322 | ||
321 | i = e->get(indio_dev, chan); | 323 | i = e->get(indio_dev, chan); |
322 | if (i < 0) | 324 | if (i < 0) |
323 | return i; | 325 | return i; |
324 | else if (i >= e->num_items) | 326 | else if (i >= e->num_items) |
325 | return -EINVAL; | 327 | return -EINVAL; |
326 | 328 | ||
327 | return sprintf(buf, "%s\n", e->items[i]); | 329 | return sprintf(buf, "%s\n", e->items[i]); |
328 | } | 330 | } |
329 | EXPORT_SYMBOL_GPL(iio_enum_read); | 331 | EXPORT_SYMBOL_GPL(iio_enum_read); |
330 | 332 | ||
331 | ssize_t iio_enum_write(struct iio_dev *indio_dev, | 333 | ssize_t iio_enum_write(struct iio_dev *indio_dev, |
332 | uintptr_t priv, const struct iio_chan_spec *chan, const char *buf, | 334 | uintptr_t priv, const struct iio_chan_spec *chan, const char *buf, |
333 | size_t len) | 335 | size_t len) |
334 | { | 336 | { |
335 | const struct iio_enum *e = (const struct iio_enum *)priv; | 337 | const struct iio_enum *e = (const struct iio_enum *)priv; |
336 | unsigned int i; | 338 | unsigned int i; |
337 | int ret; | 339 | int ret; |
338 | 340 | ||
339 | if (!e->set) | 341 | if (!e->set) |
340 | return -EINVAL; | 342 | return -EINVAL; |
341 | 343 | ||
342 | for (i = 0; i < e->num_items; i++) { | 344 | for (i = 0; i < e->num_items; i++) { |
343 | if (sysfs_streq(buf, e->items[i])) | 345 | if (sysfs_streq(buf, e->items[i])) |
344 | break; | 346 | break; |
345 | } | 347 | } |
346 | 348 | ||
347 | if (i == e->num_items) | 349 | if (i == e->num_items) |
348 | return -EINVAL; | 350 | return -EINVAL; |
349 | 351 | ||
350 | ret = e->set(indio_dev, chan, i); | 352 | ret = e->set(indio_dev, chan, i); |
351 | return ret ? ret : len; | 353 | return ret ? ret : len; |
352 | } | 354 | } |
353 | EXPORT_SYMBOL_GPL(iio_enum_write); | 355 | EXPORT_SYMBOL_GPL(iio_enum_write); |
354 | 356 | ||
355 | static ssize_t iio_read_channel_info(struct device *dev, | 357 | static ssize_t iio_read_channel_info(struct device *dev, |
356 | struct device_attribute *attr, | 358 | struct device_attribute *attr, |
357 | char *buf) | 359 | char *buf) |
358 | { | 360 | { |
359 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 361 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
360 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | 362 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
361 | int val, val2; | 363 | int val, val2; |
362 | bool scale_db = false; | 364 | bool scale_db = false; |
363 | int ret = indio_dev->info->read_raw(indio_dev, this_attr->c, | 365 | int ret = indio_dev->info->read_raw(indio_dev, this_attr->c, |
364 | &val, &val2, this_attr->address); | 366 | &val, &val2, this_attr->address); |
365 | 367 | ||
366 | if (ret < 0) | 368 | if (ret < 0) |
367 | return ret; | 369 | return ret; |
368 | 370 | ||
369 | switch (ret) { | 371 | switch (ret) { |
370 | case IIO_VAL_INT: | 372 | case IIO_VAL_INT: |
371 | return sprintf(buf, "%d\n", val); | 373 | return sprintf(buf, "%d\n", val); |
372 | case IIO_VAL_INT_PLUS_MICRO_DB: | 374 | case IIO_VAL_INT_PLUS_MICRO_DB: |
373 | scale_db = true; | 375 | scale_db = true; |
374 | case IIO_VAL_INT_PLUS_MICRO: | 376 | case IIO_VAL_INT_PLUS_MICRO: |
375 | if (val2 < 0) | 377 | if (val2 < 0) |
376 | return sprintf(buf, "-%d.%06u%s\n", val, -val2, | 378 | return sprintf(buf, "-%d.%06u%s\n", val, -val2, |
377 | scale_db ? " dB" : ""); | 379 | scale_db ? " dB" : ""); |
378 | else | 380 | else |
379 | return sprintf(buf, "%d.%06u%s\n", val, val2, | 381 | return sprintf(buf, "%d.%06u%s\n", val, val2, |
380 | scale_db ? " dB" : ""); | 382 | scale_db ? " dB" : ""); |
381 | case IIO_VAL_INT_PLUS_NANO: | 383 | case IIO_VAL_INT_PLUS_NANO: |
382 | if (val2 < 0) | 384 | if (val2 < 0) |
383 | return sprintf(buf, "-%d.%09u\n", val, -val2); | 385 | return sprintf(buf, "-%d.%09u\n", val, -val2); |
384 | else | 386 | else |
385 | return sprintf(buf, "%d.%09u\n", val, val2); | 387 | return sprintf(buf, "%d.%09u\n", val, val2); |
386 | default: | 388 | default: |
387 | return 0; | 389 | return 0; |
388 | } | 390 | } |
389 | } | 391 | } |
390 | 392 | ||
391 | static ssize_t iio_write_channel_info(struct device *dev, | 393 | static ssize_t iio_write_channel_info(struct device *dev, |
392 | struct device_attribute *attr, | 394 | struct device_attribute *attr, |
393 | const char *buf, | 395 | const char *buf, |
394 | size_t len) | 396 | size_t len) |
395 | { | 397 | { |
396 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 398 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
397 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | 399 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
398 | int ret, integer = 0, fract = 0, fract_mult = 100000; | 400 | int ret, integer = 0, fract = 0, fract_mult = 100000; |
399 | bool integer_part = true, negative = false; | 401 | bool integer_part = true, negative = false; |
400 | 402 | ||
401 | /* Assumes decimal - precision based on number of digits */ | 403 | /* Assumes decimal - precision based on number of digits */ |
402 | if (!indio_dev->info->write_raw) | 404 | if (!indio_dev->info->write_raw) |
403 | return -EINVAL; | 405 | return -EINVAL; |
404 | 406 | ||
405 | if (indio_dev->info->write_raw_get_fmt) | 407 | if (indio_dev->info->write_raw_get_fmt) |
406 | switch (indio_dev->info->write_raw_get_fmt(indio_dev, | 408 | switch (indio_dev->info->write_raw_get_fmt(indio_dev, |
407 | this_attr->c, this_attr->address)) { | 409 | this_attr->c, this_attr->address)) { |
408 | case IIO_VAL_INT_PLUS_MICRO: | 410 | case IIO_VAL_INT_PLUS_MICRO: |
409 | fract_mult = 100000; | 411 | fract_mult = 100000; |
410 | break; | 412 | break; |
411 | case IIO_VAL_INT_PLUS_NANO: | 413 | case IIO_VAL_INT_PLUS_NANO: |
412 | fract_mult = 100000000; | 414 | fract_mult = 100000000; |
413 | break; | 415 | break; |
414 | default: | 416 | default: |
415 | return -EINVAL; | 417 | return -EINVAL; |
416 | } | 418 | } |
417 | 419 | ||
418 | if (buf[0] == '-') { | 420 | if (buf[0] == '-') { |
419 | negative = true; | 421 | negative = true; |
420 | buf++; | 422 | buf++; |
421 | } | 423 | } |
422 | 424 | ||
423 | while (*buf) { | 425 | while (*buf) { |
424 | if ('0' <= *buf && *buf <= '9') { | 426 | if ('0' <= *buf && *buf <= '9') { |
425 | if (integer_part) | 427 | if (integer_part) |
426 | integer = integer*10 + *buf - '0'; | 428 | integer = integer*10 + *buf - '0'; |
427 | else { | 429 | else { |
428 | fract += fract_mult*(*buf - '0'); | 430 | fract += fract_mult*(*buf - '0'); |
429 | if (fract_mult == 1) | 431 | if (fract_mult == 1) |
430 | break; | 432 | break; |
431 | fract_mult /= 10; | 433 | fract_mult /= 10; |
432 | } | 434 | } |
433 | } else if (*buf == '\n') { | 435 | } else if (*buf == '\n') { |
434 | if (*(buf + 1) == '\0') | 436 | if (*(buf + 1) == '\0') |
435 | break; | 437 | break; |
436 | else | 438 | else |
437 | return -EINVAL; | 439 | return -EINVAL; |
438 | } else if (*buf == '.') { | 440 | } else if (*buf == '.') { |
439 | integer_part = false; | 441 | integer_part = false; |
440 | } else { | 442 | } else { |
441 | return -EINVAL; | 443 | return -EINVAL; |
442 | } | 444 | } |
443 | buf++; | 445 | buf++; |
444 | } | 446 | } |
445 | if (negative) { | 447 | if (negative) { |
446 | if (integer) | 448 | if (integer) |
447 | integer = -integer; | 449 | integer = -integer; |
448 | else | 450 | else |
449 | fract = -fract; | 451 | fract = -fract; |
450 | } | 452 | } |
451 | 453 | ||
452 | ret = indio_dev->info->write_raw(indio_dev, this_attr->c, | 454 | ret = indio_dev->info->write_raw(indio_dev, this_attr->c, |
453 | integer, fract, this_attr->address); | 455 | integer, fract, this_attr->address); |
454 | if (ret) | 456 | if (ret) |
455 | return ret; | 457 | return ret; |
456 | 458 | ||
457 | return len; | 459 | return len; |
458 | } | 460 | } |
459 | 461 | ||
460 | static | 462 | static |
461 | int __iio_device_attr_init(struct device_attribute *dev_attr, | 463 | int __iio_device_attr_init(struct device_attribute *dev_attr, |
462 | const char *postfix, | 464 | const char *postfix, |
463 | struct iio_chan_spec const *chan, | 465 | struct iio_chan_spec const *chan, |
464 | ssize_t (*readfunc)(struct device *dev, | 466 | ssize_t (*readfunc)(struct device *dev, |
465 | struct device_attribute *attr, | 467 | struct device_attribute *attr, |
466 | char *buf), | 468 | char *buf), |
467 | ssize_t (*writefunc)(struct device *dev, | 469 | ssize_t (*writefunc)(struct device *dev, |
468 | struct device_attribute *attr, | 470 | struct device_attribute *attr, |
469 | const char *buf, | 471 | const char *buf, |
470 | size_t len), | 472 | size_t len), |
471 | bool generic) | 473 | bool generic) |
472 | { | 474 | { |
473 | int ret; | 475 | int ret; |
474 | char *name_format, *full_postfix; | 476 | char *name_format, *full_postfix; |
475 | sysfs_attr_init(&dev_attr->attr); | 477 | sysfs_attr_init(&dev_attr->attr); |
476 | 478 | ||
477 | /* Build up postfix of <extend_name>_<modifier>_postfix */ | 479 | /* Build up postfix of <extend_name>_<modifier>_postfix */ |
478 | if (chan->modified && !generic) { | 480 | if (chan->modified && !generic) { |
479 | if (chan->extend_name) | 481 | if (chan->extend_name) |
480 | full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", | 482 | full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", |
481 | iio_modifier_names[chan | 483 | iio_modifier_names[chan |
482 | ->channel2], | 484 | ->channel2], |
483 | chan->extend_name, | 485 | chan->extend_name, |
484 | postfix); | 486 | postfix); |
485 | else | 487 | else |
486 | full_postfix = kasprintf(GFP_KERNEL, "%s_%s", | 488 | full_postfix = kasprintf(GFP_KERNEL, "%s_%s", |
487 | iio_modifier_names[chan | 489 | iio_modifier_names[chan |
488 | ->channel2], | 490 | ->channel2], |
489 | postfix); | 491 | postfix); |
490 | } else { | 492 | } else { |
491 | if (chan->extend_name == NULL) | 493 | if (chan->extend_name == NULL) |
492 | full_postfix = kstrdup(postfix, GFP_KERNEL); | 494 | full_postfix = kstrdup(postfix, GFP_KERNEL); |
493 | else | 495 | else |
494 | full_postfix = kasprintf(GFP_KERNEL, | 496 | full_postfix = kasprintf(GFP_KERNEL, |
495 | "%s_%s", | 497 | "%s_%s", |
496 | chan->extend_name, | 498 | chan->extend_name, |
497 | postfix); | 499 | postfix); |
498 | } | 500 | } |
499 | if (full_postfix == NULL) { | 501 | if (full_postfix == NULL) { |
500 | ret = -ENOMEM; | 502 | ret = -ENOMEM; |
501 | goto error_ret; | 503 | goto error_ret; |
502 | } | 504 | } |
503 | 505 | ||
504 | if (chan->differential) { /* Differential can not have modifier */ | 506 | if (chan->differential) { /* Differential can not have modifier */ |
505 | if (generic) | 507 | if (generic) |
506 | name_format | 508 | name_format |
507 | = kasprintf(GFP_KERNEL, "%s_%s-%s_%s", | 509 | = kasprintf(GFP_KERNEL, "%s_%s-%s_%s", |
508 | iio_direction[chan->output], | 510 | iio_direction[chan->output], |
509 | iio_chan_type_name_spec[chan->type], | 511 | iio_chan_type_name_spec[chan->type], |
510 | iio_chan_type_name_spec[chan->type], | 512 | iio_chan_type_name_spec[chan->type], |
511 | full_postfix); | 513 | full_postfix); |
512 | else if (chan->indexed) | 514 | else if (chan->indexed) |
513 | name_format | 515 | name_format |
514 | = kasprintf(GFP_KERNEL, "%s_%s%d-%s%d_%s", | 516 | = kasprintf(GFP_KERNEL, "%s_%s%d-%s%d_%s", |
515 | iio_direction[chan->output], | 517 | iio_direction[chan->output], |
516 | iio_chan_type_name_spec[chan->type], | 518 | iio_chan_type_name_spec[chan->type], |
517 | chan->channel, | 519 | chan->channel, |
518 | iio_chan_type_name_spec[chan->type], | 520 | iio_chan_type_name_spec[chan->type], |
519 | chan->channel2, | 521 | chan->channel2, |
520 | full_postfix); | 522 | full_postfix); |
521 | else { | 523 | else { |
522 | WARN_ON("Differential channels must be indexed\n"); | 524 | WARN_ON("Differential channels must be indexed\n"); |
523 | ret = -EINVAL; | 525 | ret = -EINVAL; |
524 | goto error_free_full_postfix; | 526 | goto error_free_full_postfix; |
525 | } | 527 | } |
526 | } else { /* Single ended */ | 528 | } else { /* Single ended */ |
527 | if (generic) | 529 | if (generic) |
528 | name_format | 530 | name_format |
529 | = kasprintf(GFP_KERNEL, "%s_%s_%s", | 531 | = kasprintf(GFP_KERNEL, "%s_%s_%s", |
530 | iio_direction[chan->output], | 532 | iio_direction[chan->output], |
531 | iio_chan_type_name_spec[chan->type], | 533 | iio_chan_type_name_spec[chan->type], |
532 | full_postfix); | 534 | full_postfix); |
533 | else if (chan->indexed) | 535 | else if (chan->indexed) |
534 | name_format | 536 | name_format |
535 | = kasprintf(GFP_KERNEL, "%s_%s%d_%s", | 537 | = kasprintf(GFP_KERNEL, "%s_%s%d_%s", |
536 | iio_direction[chan->output], | 538 | iio_direction[chan->output], |
537 | iio_chan_type_name_spec[chan->type], | 539 | iio_chan_type_name_spec[chan->type], |
538 | chan->channel, | 540 | chan->channel, |
539 | full_postfix); | 541 | full_postfix); |
540 | else | 542 | else |
541 | name_format | 543 | name_format |
542 | = kasprintf(GFP_KERNEL, "%s_%s_%s", | 544 | = kasprintf(GFP_KERNEL, "%s_%s_%s", |
543 | iio_direction[chan->output], | 545 | iio_direction[chan->output], |
544 | iio_chan_type_name_spec[chan->type], | 546 | iio_chan_type_name_spec[chan->type], |
545 | full_postfix); | 547 | full_postfix); |
546 | } | 548 | } |
547 | if (name_format == NULL) { | 549 | if (name_format == NULL) { |
548 | ret = -ENOMEM; | 550 | ret = -ENOMEM; |
549 | goto error_free_full_postfix; | 551 | goto error_free_full_postfix; |
550 | } | 552 | } |
551 | dev_attr->attr.name = kasprintf(GFP_KERNEL, | 553 | dev_attr->attr.name = kasprintf(GFP_KERNEL, |
552 | name_format, | 554 | name_format, |
553 | chan->channel, | 555 | chan->channel, |
554 | chan->channel2); | 556 | chan->channel2); |
555 | if (dev_attr->attr.name == NULL) { | 557 | if (dev_attr->attr.name == NULL) { |
556 | ret = -ENOMEM; | 558 | ret = -ENOMEM; |
557 | goto error_free_name_format; | 559 | goto error_free_name_format; |
558 | } | 560 | } |
559 | 561 | ||
560 | if (readfunc) { | 562 | if (readfunc) { |
561 | dev_attr->attr.mode |= S_IRUGO; | 563 | dev_attr->attr.mode |= S_IRUGO; |
562 | dev_attr->show = readfunc; | 564 | dev_attr->show = readfunc; |
563 | } | 565 | } |
564 | 566 | ||
565 | if (writefunc) { | 567 | if (writefunc) { |
566 | dev_attr->attr.mode |= S_IWUSR; | 568 | dev_attr->attr.mode |= S_IWUSR; |
567 | dev_attr->store = writefunc; | 569 | dev_attr->store = writefunc; |
568 | } | 570 | } |
569 | kfree(name_format); | 571 | kfree(name_format); |
570 | kfree(full_postfix); | 572 | kfree(full_postfix); |
571 | 573 | ||
572 | return 0; | 574 | return 0; |
573 | 575 | ||
574 | error_free_name_format: | 576 | error_free_name_format: |
575 | kfree(name_format); | 577 | kfree(name_format); |
576 | error_free_full_postfix: | 578 | error_free_full_postfix: |
577 | kfree(full_postfix); | 579 | kfree(full_postfix); |
578 | error_ret: | 580 | error_ret: |
579 | return ret; | 581 | return ret; |
580 | } | 582 | } |
581 | 583 | ||
582 | static void __iio_device_attr_deinit(struct device_attribute *dev_attr) | 584 | static void __iio_device_attr_deinit(struct device_attribute *dev_attr) |
583 | { | 585 | { |
584 | kfree(dev_attr->attr.name); | 586 | kfree(dev_attr->attr.name); |
585 | } | 587 | } |
586 | 588 | ||
587 | int __iio_add_chan_devattr(const char *postfix, | 589 | int __iio_add_chan_devattr(const char *postfix, |
588 | struct iio_chan_spec const *chan, | 590 | struct iio_chan_spec const *chan, |
589 | ssize_t (*readfunc)(struct device *dev, | 591 | ssize_t (*readfunc)(struct device *dev, |
590 | struct device_attribute *attr, | 592 | struct device_attribute *attr, |
591 | char *buf), | 593 | char *buf), |
592 | ssize_t (*writefunc)(struct device *dev, | 594 | ssize_t (*writefunc)(struct device *dev, |
593 | struct device_attribute *attr, | 595 | struct device_attribute *attr, |
594 | const char *buf, | 596 | const char *buf, |
595 | size_t len), | 597 | size_t len), |
596 | u64 mask, | 598 | u64 mask, |
597 | bool generic, | 599 | bool generic, |
598 | struct device *dev, | 600 | struct device *dev, |
599 | struct list_head *attr_list) | 601 | struct list_head *attr_list) |
600 | { | 602 | { |
601 | int ret; | 603 | int ret; |
602 | struct iio_dev_attr *iio_attr, *t; | 604 | struct iio_dev_attr *iio_attr, *t; |
603 | 605 | ||
604 | iio_attr = kzalloc(sizeof *iio_attr, GFP_KERNEL); | 606 | iio_attr = kzalloc(sizeof *iio_attr, GFP_KERNEL); |
605 | if (iio_attr == NULL) { | 607 | if (iio_attr == NULL) { |
606 | ret = -ENOMEM; | 608 | ret = -ENOMEM; |
607 | goto error_ret; | 609 | goto error_ret; |
608 | } | 610 | } |
609 | ret = __iio_device_attr_init(&iio_attr->dev_attr, | 611 | ret = __iio_device_attr_init(&iio_attr->dev_attr, |
610 | postfix, chan, | 612 | postfix, chan, |
611 | readfunc, writefunc, generic); | 613 | readfunc, writefunc, generic); |
612 | if (ret) | 614 | if (ret) |
613 | goto error_iio_dev_attr_free; | 615 | goto error_iio_dev_attr_free; |
614 | iio_attr->c = chan; | 616 | iio_attr->c = chan; |
615 | iio_attr->address = mask; | 617 | iio_attr->address = mask; |
616 | list_for_each_entry(t, attr_list, l) | 618 | list_for_each_entry(t, attr_list, l) |
617 | if (strcmp(t->dev_attr.attr.name, | 619 | if (strcmp(t->dev_attr.attr.name, |
618 | iio_attr->dev_attr.attr.name) == 0) { | 620 | iio_attr->dev_attr.attr.name) == 0) { |
619 | if (!generic) | 621 | if (!generic) |
620 | dev_err(dev, "tried to double register : %s\n", | 622 | dev_err(dev, "tried to double register : %s\n", |
621 | t->dev_attr.attr.name); | 623 | t->dev_attr.attr.name); |
622 | ret = -EBUSY; | 624 | ret = -EBUSY; |
623 | goto error_device_attr_deinit; | 625 | goto error_device_attr_deinit; |
624 | } | 626 | } |
625 | list_add(&iio_attr->l, attr_list); | 627 | list_add(&iio_attr->l, attr_list); |
626 | 628 | ||
627 | return 0; | 629 | return 0; |
628 | 630 | ||
629 | error_device_attr_deinit: | 631 | error_device_attr_deinit: |
630 | __iio_device_attr_deinit(&iio_attr->dev_attr); | 632 | __iio_device_attr_deinit(&iio_attr->dev_attr); |
631 | error_iio_dev_attr_free: | 633 | error_iio_dev_attr_free: |
632 | kfree(iio_attr); | 634 | kfree(iio_attr); |
633 | error_ret: | 635 | error_ret: |
634 | return ret; | 636 | return ret; |
635 | } | 637 | } |
636 | 638 | ||
637 | static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, | 639 | static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, |
638 | struct iio_chan_spec const *chan) | 640 | struct iio_chan_spec const *chan) |
639 | { | 641 | { |
640 | int ret, attrcount = 0; | 642 | int ret, attrcount = 0; |
641 | int i; | 643 | int i; |
642 | const struct iio_chan_spec_ext_info *ext_info; | 644 | const struct iio_chan_spec_ext_info *ext_info; |
643 | 645 | ||
644 | if (chan->channel < 0) | 646 | if (chan->channel < 0) |
645 | return 0; | 647 | return 0; |
646 | for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) { | 648 | for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) { |
647 | ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2], | 649 | ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2], |
648 | chan, | 650 | chan, |
649 | &iio_read_channel_info, | 651 | &iio_read_channel_info, |
650 | &iio_write_channel_info, | 652 | &iio_write_channel_info, |
651 | i/2, | 653 | i/2, |
652 | !(i%2), | 654 | !(i%2), |
653 | &indio_dev->dev, | 655 | &indio_dev->dev, |
654 | &indio_dev->channel_attr_list); | 656 | &indio_dev->channel_attr_list); |
655 | if (ret == -EBUSY && (i%2 == 0)) { | 657 | if (ret == -EBUSY && (i%2 == 0)) { |
656 | ret = 0; | 658 | ret = 0; |
657 | continue; | 659 | continue; |
658 | } | 660 | } |
659 | if (ret < 0) | 661 | if (ret < 0) |
660 | goto error_ret; | 662 | goto error_ret; |
661 | attrcount++; | 663 | attrcount++; |
662 | } | 664 | } |
663 | 665 | ||
664 | if (chan->ext_info) { | 666 | if (chan->ext_info) { |
665 | unsigned int i = 0; | 667 | unsigned int i = 0; |
666 | for (ext_info = chan->ext_info; ext_info->name; ext_info++) { | 668 | for (ext_info = chan->ext_info; ext_info->name; ext_info++) { |
667 | ret = __iio_add_chan_devattr(ext_info->name, | 669 | ret = __iio_add_chan_devattr(ext_info->name, |
668 | chan, | 670 | chan, |
669 | ext_info->read ? | 671 | ext_info->read ? |
670 | &iio_read_channel_ext_info : NULL, | 672 | &iio_read_channel_ext_info : NULL, |
671 | ext_info->write ? | 673 | ext_info->write ? |
672 | &iio_write_channel_ext_info : NULL, | 674 | &iio_write_channel_ext_info : NULL, |
673 | i, | 675 | i, |
674 | ext_info->shared, | 676 | ext_info->shared, |
675 | &indio_dev->dev, | 677 | &indio_dev->dev, |
676 | &indio_dev->channel_attr_list); | 678 | &indio_dev->channel_attr_list); |
677 | i++; | 679 | i++; |
678 | if (ret == -EBUSY && ext_info->shared) | 680 | if (ret == -EBUSY && ext_info->shared) |
679 | continue; | 681 | continue; |
680 | 682 | ||
681 | if (ret) | 683 | if (ret) |
682 | goto error_ret; | 684 | goto error_ret; |
683 | 685 | ||
684 | attrcount++; | 686 | attrcount++; |
685 | } | 687 | } |
686 | } | 688 | } |
687 | 689 | ||
688 | ret = attrcount; | 690 | ret = attrcount; |
689 | error_ret: | 691 | error_ret: |
690 | return ret; | 692 | return ret; |
691 | } | 693 | } |
692 | 694 | ||
693 | static void iio_device_remove_and_free_read_attr(struct iio_dev *indio_dev, | 695 | static void iio_device_remove_and_free_read_attr(struct iio_dev *indio_dev, |
694 | struct iio_dev_attr *p) | 696 | struct iio_dev_attr *p) |
695 | { | 697 | { |
696 | kfree(p->dev_attr.attr.name); | 698 | kfree(p->dev_attr.attr.name); |
697 | kfree(p); | 699 | kfree(p); |
698 | } | 700 | } |
699 | 701 | ||
700 | static ssize_t iio_show_dev_name(struct device *dev, | 702 | static ssize_t iio_show_dev_name(struct device *dev, |
701 | struct device_attribute *attr, | 703 | struct device_attribute *attr, |
702 | char *buf) | 704 | char *buf) |
703 | { | 705 | { |
704 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 706 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
705 | return sprintf(buf, "%s\n", indio_dev->name); | 707 | return sprintf(buf, "%s\n", indio_dev->name); |
706 | } | 708 | } |
707 | 709 | ||
708 | static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL); | 710 | static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL); |
709 | 711 | ||
710 | static int iio_device_register_sysfs(struct iio_dev *indio_dev) | 712 | static int iio_device_register_sysfs(struct iio_dev *indio_dev) |
711 | { | 713 | { |
712 | int i, ret = 0, attrcount, attrn, attrcount_orig = 0; | 714 | int i, ret = 0, attrcount, attrn, attrcount_orig = 0; |
713 | struct iio_dev_attr *p, *n; | 715 | struct iio_dev_attr *p, *n; |
714 | struct attribute **attr; | 716 | struct attribute **attr; |
715 | 717 | ||
716 | /* First count elements in any existing group */ | 718 | /* First count elements in any existing group */ |
717 | if (indio_dev->info->attrs) { | 719 | if (indio_dev->info->attrs) { |
718 | attr = indio_dev->info->attrs->attrs; | 720 | attr = indio_dev->info->attrs->attrs; |
719 | while (*attr++ != NULL) | 721 | while (*attr++ != NULL) |
720 | attrcount_orig++; | 722 | attrcount_orig++; |
721 | } | 723 | } |
722 | attrcount = attrcount_orig; | 724 | attrcount = attrcount_orig; |
723 | /* | 725 | /* |
724 | * New channel registration method - relies on the fact a group does | 726 | * New channel registration method - relies on the fact a group does |
725 | * not need to be initialized if it is name is NULL. | 727 | * not need to be initialized if it is name is NULL. |
726 | */ | 728 | */ |
727 | if (indio_dev->channels) | 729 | if (indio_dev->channels) |
728 | for (i = 0; i < indio_dev->num_channels; i++) { | 730 | for (i = 0; i < indio_dev->num_channels; i++) { |
729 | ret = iio_device_add_channel_sysfs(indio_dev, | 731 | ret = iio_device_add_channel_sysfs(indio_dev, |
730 | &indio_dev | 732 | &indio_dev |
731 | ->channels[i]); | 733 | ->channels[i]); |
732 | if (ret < 0) | 734 | if (ret < 0) |
733 | goto error_clear_attrs; | 735 | goto error_clear_attrs; |
734 | attrcount += ret; | 736 | attrcount += ret; |
735 | } | 737 | } |
736 | 738 | ||
737 | if (indio_dev->name) | 739 | if (indio_dev->name) |
738 | attrcount++; | 740 | attrcount++; |
739 | 741 | ||
740 | indio_dev->chan_attr_group.attrs = kcalloc(attrcount + 1, | 742 | indio_dev->chan_attr_group.attrs = kcalloc(attrcount + 1, |
741 | sizeof(indio_dev->chan_attr_group.attrs[0]), | 743 | sizeof(indio_dev->chan_attr_group.attrs[0]), |
742 | GFP_KERNEL); | 744 | GFP_KERNEL); |
743 | if (indio_dev->chan_attr_group.attrs == NULL) { | 745 | if (indio_dev->chan_attr_group.attrs == NULL) { |
744 | ret = -ENOMEM; | 746 | ret = -ENOMEM; |
745 | goto error_clear_attrs; | 747 | goto error_clear_attrs; |
746 | } | 748 | } |
747 | /* Copy across original attributes */ | 749 | /* Copy across original attributes */ |
748 | if (indio_dev->info->attrs) | 750 | if (indio_dev->info->attrs) |
749 | memcpy(indio_dev->chan_attr_group.attrs, | 751 | memcpy(indio_dev->chan_attr_group.attrs, |
750 | indio_dev->info->attrs->attrs, | 752 | indio_dev->info->attrs->attrs, |
751 | sizeof(indio_dev->chan_attr_group.attrs[0]) | 753 | sizeof(indio_dev->chan_attr_group.attrs[0]) |
752 | *attrcount_orig); | 754 | *attrcount_orig); |
753 | attrn = attrcount_orig; | 755 | attrn = attrcount_orig; |
754 | /* Add all elements from the list. */ | 756 | /* Add all elements from the list. */ |
755 | list_for_each_entry(p, &indio_dev->channel_attr_list, l) | 757 | list_for_each_entry(p, &indio_dev->channel_attr_list, l) |
756 | indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr; | 758 | indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr; |
757 | if (indio_dev->name) | 759 | if (indio_dev->name) |
758 | indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr; | 760 | indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr; |
759 | 761 | ||
760 | indio_dev->groups[indio_dev->groupcounter++] = | 762 | indio_dev->groups[indio_dev->groupcounter++] = |
761 | &indio_dev->chan_attr_group; | 763 | &indio_dev->chan_attr_group; |
762 | 764 | ||
763 | return 0; | 765 | return 0; |
764 | 766 | ||
765 | error_clear_attrs: | 767 | error_clear_attrs: |
766 | list_for_each_entry_safe(p, n, | 768 | list_for_each_entry_safe(p, n, |
767 | &indio_dev->channel_attr_list, l) { | 769 | &indio_dev->channel_attr_list, l) { |
768 | list_del(&p->l); | 770 | list_del(&p->l); |
769 | iio_device_remove_and_free_read_attr(indio_dev, p); | 771 | iio_device_remove_and_free_read_attr(indio_dev, p); |
770 | } | 772 | } |
771 | 773 | ||
772 | return ret; | 774 | return ret; |
773 | } | 775 | } |
774 | 776 | ||
775 | static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) | 777 | static void iio_device_unregister_sysfs(struct iio_dev *indio_dev) |
776 | { | 778 | { |
777 | 779 | ||
778 | struct iio_dev_attr *p, *n; | 780 | struct iio_dev_attr *p, *n; |
779 | 781 | ||
780 | list_for_each_entry_safe(p, n, &indio_dev->channel_attr_list, l) { | 782 | list_for_each_entry_safe(p, n, &indio_dev->channel_attr_list, l) { |
781 | list_del(&p->l); | 783 | list_del(&p->l); |
782 | iio_device_remove_and_free_read_attr(indio_dev, p); | 784 | iio_device_remove_and_free_read_attr(indio_dev, p); |
783 | } | 785 | } |
784 | kfree(indio_dev->chan_attr_group.attrs); | 786 | kfree(indio_dev->chan_attr_group.attrs); |
785 | } | 787 | } |
786 | 788 | ||
787 | static void iio_dev_release(struct device *device) | 789 | static void iio_dev_release(struct device *device) |
788 | { | 790 | { |
789 | struct iio_dev *indio_dev = dev_to_iio_dev(device); | 791 | struct iio_dev *indio_dev = dev_to_iio_dev(device); |
790 | if (indio_dev->chrdev.dev) | 792 | if (indio_dev->chrdev.dev) |
791 | cdev_del(&indio_dev->chrdev); | 793 | cdev_del(&indio_dev->chrdev); |
792 | if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) | 794 | if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) |
793 | iio_device_unregister_trigger_consumer(indio_dev); | 795 | iio_device_unregister_trigger_consumer(indio_dev); |
794 | iio_device_unregister_eventset(indio_dev); | 796 | iio_device_unregister_eventset(indio_dev); |
795 | iio_device_unregister_sysfs(indio_dev); | 797 | iio_device_unregister_sysfs(indio_dev); |
796 | iio_device_unregister_debugfs(indio_dev); | 798 | iio_device_unregister_debugfs(indio_dev); |
797 | 799 | ||
798 | ida_simple_remove(&iio_ida, indio_dev->id); | 800 | ida_simple_remove(&iio_ida, indio_dev->id); |
799 | kfree(indio_dev); | 801 | kfree(indio_dev); |
800 | } | 802 | } |
801 | 803 | ||
802 | static struct device_type iio_dev_type = { | 804 | static struct device_type iio_dev_type = { |
803 | .name = "iio_device", | 805 | .name = "iio_device", |
804 | .release = iio_dev_release, | 806 | .release = iio_dev_release, |
805 | }; | 807 | }; |
806 | 808 | ||
807 | struct iio_dev *iio_device_alloc(int sizeof_priv) | 809 | struct iio_dev *iio_device_alloc(int sizeof_priv) |
808 | { | 810 | { |
809 | struct iio_dev *dev; | 811 | struct iio_dev *dev; |
810 | size_t alloc_size; | 812 | size_t alloc_size; |
811 | 813 | ||
812 | alloc_size = sizeof(struct iio_dev); | 814 | alloc_size = sizeof(struct iio_dev); |
813 | if (sizeof_priv) { | 815 | if (sizeof_priv) { |
814 | alloc_size = ALIGN(alloc_size, IIO_ALIGN); | 816 | alloc_size = ALIGN(alloc_size, IIO_ALIGN); |
815 | alloc_size += sizeof_priv; | 817 | alloc_size += sizeof_priv; |
816 | } | 818 | } |
817 | /* ensure 32-byte alignment of whole construct ? */ | 819 | /* ensure 32-byte alignment of whole construct ? */ |
818 | alloc_size += IIO_ALIGN - 1; | 820 | alloc_size += IIO_ALIGN - 1; |
819 | 821 | ||
820 | dev = kzalloc(alloc_size, GFP_KERNEL); | 822 | dev = kzalloc(alloc_size, GFP_KERNEL); |
821 | 823 | ||
822 | if (dev) { | 824 | if (dev) { |
823 | dev->dev.groups = dev->groups; | 825 | dev->dev.groups = dev->groups; |
824 | dev->dev.type = &iio_dev_type; | 826 | dev->dev.type = &iio_dev_type; |
825 | dev->dev.bus = &iio_bus_type; | 827 | dev->dev.bus = &iio_bus_type; |
826 | device_initialize(&dev->dev); | 828 | device_initialize(&dev->dev); |
827 | dev_set_drvdata(&dev->dev, (void *)dev); | 829 | dev_set_drvdata(&dev->dev, (void *)dev); |
828 | mutex_init(&dev->mlock); | 830 | mutex_init(&dev->mlock); |
829 | mutex_init(&dev->info_exist_lock); | 831 | mutex_init(&dev->info_exist_lock); |
830 | INIT_LIST_HEAD(&dev->channel_attr_list); | 832 | INIT_LIST_HEAD(&dev->channel_attr_list); |
831 | 833 | ||
832 | dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); | 834 | dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); |
833 | if (dev->id < 0) { | 835 | if (dev->id < 0) { |
834 | /* cannot use a dev_err as the name isn't available */ | 836 | /* cannot use a dev_err as the name isn't available */ |
835 | printk(KERN_ERR "Failed to get id\n"); | 837 | printk(KERN_ERR "Failed to get id\n"); |
836 | kfree(dev); | 838 | kfree(dev); |
837 | return NULL; | 839 | return NULL; |
838 | } | 840 | } |
839 | dev_set_name(&dev->dev, "iio:device%d", dev->id); | 841 | dev_set_name(&dev->dev, "iio:device%d", dev->id); |
840 | } | 842 | } |
841 | 843 | ||
842 | return dev; | 844 | return dev; |
843 | } | 845 | } |
844 | EXPORT_SYMBOL(iio_device_alloc); | 846 | EXPORT_SYMBOL(iio_device_alloc); |
845 | 847 | ||
846 | void iio_device_free(struct iio_dev *dev) | 848 | void iio_device_free(struct iio_dev *dev) |
847 | { | 849 | { |
848 | if (dev) | 850 | if (dev) |
849 | put_device(&dev->dev); | 851 | put_device(&dev->dev); |
850 | } | 852 | } |
851 | EXPORT_SYMBOL(iio_device_free); | 853 | EXPORT_SYMBOL(iio_device_free); |
852 | 854 | ||
853 | /** | 855 | /** |
854 | * iio_chrdev_open() - chrdev file open for buffer access and ioctls | 856 | * iio_chrdev_open() - chrdev file open for buffer access and ioctls |
855 | **/ | 857 | **/ |
856 | static int iio_chrdev_open(struct inode *inode, struct file *filp) | 858 | static int iio_chrdev_open(struct inode *inode, struct file *filp) |
857 | { | 859 | { |
858 | struct iio_dev *indio_dev = container_of(inode->i_cdev, | 860 | struct iio_dev *indio_dev = container_of(inode->i_cdev, |
859 | struct iio_dev, chrdev); | 861 | struct iio_dev, chrdev); |
860 | 862 | ||
861 | if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags)) | 863 | if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags)) |
862 | return -EBUSY; | 864 | return -EBUSY; |
863 | 865 | ||
864 | filp->private_data = indio_dev; | 866 | filp->private_data = indio_dev; |
865 | 867 | ||
866 | return 0; | 868 | return 0; |
867 | } | 869 | } |
868 | 870 | ||
869 | /** | 871 | /** |
870 | * iio_chrdev_release() - chrdev file close buffer access and ioctls | 872 | * iio_chrdev_release() - chrdev file close buffer access and ioctls |
871 | **/ | 873 | **/ |
872 | static int iio_chrdev_release(struct inode *inode, struct file *filp) | 874 | static int iio_chrdev_release(struct inode *inode, struct file *filp) |
873 | { | 875 | { |
874 | struct iio_dev *indio_dev = container_of(inode->i_cdev, | 876 | struct iio_dev *indio_dev = container_of(inode->i_cdev, |
875 | struct iio_dev, chrdev); | 877 | struct iio_dev, chrdev); |
876 | clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags); | 878 | clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags); |
877 | return 0; | 879 | return 0; |
878 | } | 880 | } |
879 | 881 | ||
880 | /* Somewhat of a cross file organization violation - ioctls here are actually | 882 | /* Somewhat of a cross file organization violation - ioctls here are actually |
881 | * event related */ | 883 | * event related */ |
882 | static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 884 | static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
883 | { | 885 | { |
884 | struct iio_dev *indio_dev = filp->private_data; | 886 | struct iio_dev *indio_dev = filp->private_data; |
885 | int __user *ip = (int __user *)arg; | 887 | int __user *ip = (int __user *)arg; |
886 | int fd; | 888 | int fd; |
887 | 889 | ||
888 | if (cmd == IIO_GET_EVENT_FD_IOCTL) { | 890 | if (cmd == IIO_GET_EVENT_FD_IOCTL) { |
889 | fd = iio_event_getfd(indio_dev); | 891 | fd = iio_event_getfd(indio_dev); |
890 | if (copy_to_user(ip, &fd, sizeof(fd))) | 892 | if (copy_to_user(ip, &fd, sizeof(fd))) |
891 | return -EFAULT; | 893 | return -EFAULT; |
892 | return 0; | 894 | return 0; |
893 | } | 895 | } |
894 | return -EINVAL; | 896 | return -EINVAL; |
895 | } | 897 | } |
896 | 898 | ||
897 | static const struct file_operations iio_buffer_fileops = { | 899 | static const struct file_operations iio_buffer_fileops = { |
898 | .read = iio_buffer_read_first_n_outer_addr, | 900 | .read = iio_buffer_read_first_n_outer_addr, |
899 | .release = iio_chrdev_release, | 901 | .release = iio_chrdev_release, |
900 | .open = iio_chrdev_open, | 902 | .open = iio_chrdev_open, |
901 | .poll = iio_buffer_poll_addr, | 903 | .poll = iio_buffer_poll_addr, |
902 | .owner = THIS_MODULE, | 904 | .owner = THIS_MODULE, |
903 | .llseek = noop_llseek, | 905 | .llseek = noop_llseek, |
904 | .unlocked_ioctl = iio_ioctl, | 906 | .unlocked_ioctl = iio_ioctl, |
905 | .compat_ioctl = iio_ioctl, | 907 | .compat_ioctl = iio_ioctl, |
906 | }; | 908 | }; |
907 | 909 | ||
908 | static const struct iio_buffer_setup_ops noop_ring_setup_ops; | 910 | static const struct iio_buffer_setup_ops noop_ring_setup_ops; |
909 | 911 | ||
910 | int iio_device_register(struct iio_dev *indio_dev) | 912 | int iio_device_register(struct iio_dev *indio_dev) |
911 | { | 913 | { |
912 | int ret; | 914 | int ret; |
913 | 915 | ||
914 | /* configure elements for the chrdev */ | 916 | /* configure elements for the chrdev */ |
915 | indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id); | 917 | indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id); |
916 | 918 | ||
917 | ret = iio_device_register_debugfs(indio_dev); | 919 | ret = iio_device_register_debugfs(indio_dev); |
918 | if (ret) { | 920 | if (ret) { |
919 | dev_err(indio_dev->dev.parent, | 921 | dev_err(indio_dev->dev.parent, |
920 | "Failed to register debugfs interfaces\n"); | 922 | "Failed to register debugfs interfaces\n"); |
921 | goto error_ret; | 923 | goto error_ret; |
922 | } | 924 | } |
923 | ret = iio_device_register_sysfs(indio_dev); | 925 | ret = iio_device_register_sysfs(indio_dev); |
924 | if (ret) { | 926 | if (ret) { |
925 | dev_err(indio_dev->dev.parent, | 927 | dev_err(indio_dev->dev.parent, |
926 | "Failed to register sysfs interfaces\n"); | 928 | "Failed to register sysfs interfaces\n"); |
927 | goto error_unreg_debugfs; | 929 | goto error_unreg_debugfs; |
928 | } | 930 | } |
929 | ret = iio_device_register_eventset(indio_dev); | 931 | ret = iio_device_register_eventset(indio_dev); |
930 | if (ret) { | 932 | if (ret) { |
931 | dev_err(indio_dev->dev.parent, | 933 | dev_err(indio_dev->dev.parent, |
932 | "Failed to register event set\n"); | 934 | "Failed to register event set\n"); |
933 | goto error_free_sysfs; | 935 | goto error_free_sysfs; |
934 | } | 936 | } |
935 | if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) | 937 | if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) |
936 | iio_device_register_trigger_consumer(indio_dev); | 938 | iio_device_register_trigger_consumer(indio_dev); |
937 | 939 | ||
938 | if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) && | 940 | if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) && |
939 | indio_dev->setup_ops == NULL) | 941 | indio_dev->setup_ops == NULL) |
940 | indio_dev->setup_ops = &noop_ring_setup_ops; | 942 | indio_dev->setup_ops = &noop_ring_setup_ops; |
941 | 943 | ||
942 | ret = device_add(&indio_dev->dev); | 944 | ret = device_add(&indio_dev->dev); |
943 | if (ret < 0) | 945 | if (ret < 0) |
944 | goto error_unreg_eventset; | 946 | goto error_unreg_eventset; |
945 | cdev_init(&indio_dev->chrdev, &iio_buffer_fileops); | 947 | cdev_init(&indio_dev->chrdev, &iio_buffer_fileops); |
946 | indio_dev->chrdev.owner = indio_dev->info->driver_module; | 948 | indio_dev->chrdev.owner = indio_dev->info->driver_module; |
947 | ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1); | 949 | ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1); |
948 | if (ret < 0) | 950 | if (ret < 0) |
949 | goto error_del_device; | 951 | goto error_del_device; |
950 | return 0; | 952 | return 0; |
951 | 953 | ||
952 | error_del_device: | 954 | error_del_device: |
953 | device_del(&indio_dev->dev); | 955 | device_del(&indio_dev->dev); |
954 | error_unreg_eventset: | 956 | error_unreg_eventset: |
955 | iio_device_unregister_eventset(indio_dev); | 957 | iio_device_unregister_eventset(indio_dev); |
956 | error_free_sysfs: | 958 | error_free_sysfs: |
957 | iio_device_unregister_sysfs(indio_dev); | 959 | iio_device_unregister_sysfs(indio_dev); |
958 | error_unreg_debugfs: | 960 | error_unreg_debugfs: |
959 | iio_device_unregister_debugfs(indio_dev); | 961 | iio_device_unregister_debugfs(indio_dev); |
960 | error_ret: | 962 | error_ret: |
961 | return ret; | 963 | return ret; |
962 | } | 964 | } |
963 | EXPORT_SYMBOL(iio_device_register); | 965 | EXPORT_SYMBOL(iio_device_register); |
964 | 966 | ||
965 | void iio_device_unregister(struct iio_dev *indio_dev) | 967 | void iio_device_unregister(struct iio_dev *indio_dev) |
966 | { | 968 | { |
967 | mutex_lock(&indio_dev->info_exist_lock); | 969 | mutex_lock(&indio_dev->info_exist_lock); |
968 | indio_dev->info = NULL; | 970 | indio_dev->info = NULL; |
969 | mutex_unlock(&indio_dev->info_exist_lock); | 971 | mutex_unlock(&indio_dev->info_exist_lock); |
970 | device_del(&indio_dev->dev); | 972 | device_del(&indio_dev->dev); |
971 | } | 973 | } |
972 | EXPORT_SYMBOL(iio_device_unregister); | 974 | EXPORT_SYMBOL(iio_device_unregister); |
973 | subsys_initcall(iio_init); | 975 | subsys_initcall(iio_init); |
974 | module_exit(iio_exit); | 976 | module_exit(iio_exit); |
975 | 977 | ||
976 | MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); | 978 | MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); |
977 | MODULE_DESCRIPTION("Industrial I/O core"); | 979 | MODULE_DESCRIPTION("Industrial I/O core"); |
978 | MODULE_LICENSE("GPL"); | 980 | MODULE_LICENSE("GPL"); |
979 | 981 |
drivers/iio/inkern.c
1 | /* The industrial I/O core in kernel channel mapping | 1 | /* The industrial I/O core in kernel channel mapping |
2 | * | 2 | * |
3 | * Copyright (c) 2011 Jonathan Cameron | 3 | * Copyright (c) 2011 Jonathan Cameron |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 as published by | 6 | * under the terms of the GNU General Public License version 2 as published by |
7 | * the Free Software Foundation. | 7 | * the Free Software Foundation. |
8 | */ | 8 | */ |
9 | #include <linux/err.h> | 9 | #include <linux/err.h> |
10 | #include <linux/export.h> | 10 | #include <linux/export.h> |
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/mutex.h> | 12 | #include <linux/mutex.h> |
13 | 13 | ||
14 | #include <linux/iio/iio.h> | 14 | #include <linux/iio/iio.h> |
15 | #include "iio_core.h" | 15 | #include "iio_core.h" |
16 | #include <linux/iio/machine.h> | 16 | #include <linux/iio/machine.h> |
17 | #include <linux/iio/driver.h> | 17 | #include <linux/iio/driver.h> |
18 | #include <linux/iio/consumer.h> | 18 | #include <linux/iio/consumer.h> |
19 | 19 | ||
20 | struct iio_map_internal { | 20 | struct iio_map_internal { |
21 | struct iio_dev *indio_dev; | 21 | struct iio_dev *indio_dev; |
22 | struct iio_map *map; | 22 | struct iio_map *map; |
23 | struct list_head l; | 23 | struct list_head l; |
24 | }; | 24 | }; |
25 | 25 | ||
26 | static LIST_HEAD(iio_map_list); | 26 | static LIST_HEAD(iio_map_list); |
27 | static DEFINE_MUTEX(iio_map_list_lock); | 27 | static DEFINE_MUTEX(iio_map_list_lock); |
28 | 28 | ||
29 | int iio_map_array_register(struct iio_dev *indio_dev, struct iio_map *maps) | 29 | int iio_map_array_register(struct iio_dev *indio_dev, struct iio_map *maps) |
30 | { | 30 | { |
31 | int i = 0, ret = 0; | 31 | int i = 0, ret = 0; |
32 | struct iio_map_internal *mapi; | 32 | struct iio_map_internal *mapi; |
33 | 33 | ||
34 | if (maps == NULL) | 34 | if (maps == NULL) |
35 | return 0; | 35 | return 0; |
36 | 36 | ||
37 | mutex_lock(&iio_map_list_lock); | 37 | mutex_lock(&iio_map_list_lock); |
38 | while (maps[i].consumer_dev_name != NULL) { | 38 | while (maps[i].consumer_dev_name != NULL) { |
39 | mapi = kzalloc(sizeof(*mapi), GFP_KERNEL); | 39 | mapi = kzalloc(sizeof(*mapi), GFP_KERNEL); |
40 | if (mapi == NULL) { | 40 | if (mapi == NULL) { |
41 | ret = -ENOMEM; | 41 | ret = -ENOMEM; |
42 | goto error_ret; | 42 | goto error_ret; |
43 | } | 43 | } |
44 | mapi->map = &maps[i]; | 44 | mapi->map = &maps[i]; |
45 | mapi->indio_dev = indio_dev; | 45 | mapi->indio_dev = indio_dev; |
46 | list_add(&mapi->l, &iio_map_list); | 46 | list_add(&mapi->l, &iio_map_list); |
47 | i++; | 47 | i++; |
48 | } | 48 | } |
49 | error_ret: | 49 | error_ret: |
50 | mutex_unlock(&iio_map_list_lock); | 50 | mutex_unlock(&iio_map_list_lock); |
51 | 51 | ||
52 | return ret; | 52 | return ret; |
53 | } | 53 | } |
54 | EXPORT_SYMBOL_GPL(iio_map_array_register); | 54 | EXPORT_SYMBOL_GPL(iio_map_array_register); |
55 | 55 | ||
56 | 56 | ||
57 | /* Assumes the exact same array (e.g. memory locations) | 57 | /* Assumes the exact same array (e.g. memory locations) |
58 | * used at unregistration as used at registration rather than | 58 | * used at unregistration as used at registration rather than |
59 | * more complex checking of contents. | 59 | * more complex checking of contents. |
60 | */ | 60 | */ |
61 | int iio_map_array_unregister(struct iio_dev *indio_dev, | 61 | int iio_map_array_unregister(struct iio_dev *indio_dev, |
62 | struct iio_map *maps) | 62 | struct iio_map *maps) |
63 | { | 63 | { |
64 | int i = 0, ret = 0; | 64 | int i = 0, ret = 0; |
65 | bool found_it; | 65 | bool found_it; |
66 | struct iio_map_internal *mapi; | 66 | struct iio_map_internal *mapi; |
67 | 67 | ||
68 | if (maps == NULL) | 68 | if (maps == NULL) |
69 | return 0; | 69 | return 0; |
70 | 70 | ||
71 | mutex_lock(&iio_map_list_lock); | 71 | mutex_lock(&iio_map_list_lock); |
72 | while (maps[i].consumer_dev_name != NULL) { | 72 | while (maps[i].consumer_dev_name != NULL) { |
73 | found_it = false; | 73 | found_it = false; |
74 | list_for_each_entry(mapi, &iio_map_list, l) | 74 | list_for_each_entry(mapi, &iio_map_list, l) |
75 | if (&maps[i] == mapi->map) { | 75 | if (&maps[i] == mapi->map) { |
76 | list_del(&mapi->l); | 76 | list_del(&mapi->l); |
77 | kfree(mapi); | 77 | kfree(mapi); |
78 | found_it = true; | 78 | found_it = true; |
79 | break; | 79 | break; |
80 | } | 80 | } |
81 | if (found_it == false) { | 81 | if (found_it == false) { |
82 | ret = -ENODEV; | 82 | ret = -ENODEV; |
83 | goto error_ret; | 83 | goto error_ret; |
84 | } | 84 | } |
85 | i++; | 85 | i++; |
86 | } | 86 | } |
87 | error_ret: | 87 | error_ret: |
88 | mutex_unlock(&iio_map_list_lock); | 88 | mutex_unlock(&iio_map_list_lock); |
89 | 89 | ||
90 | return ret; | 90 | return ret; |
91 | } | 91 | } |
92 | EXPORT_SYMBOL_GPL(iio_map_array_unregister); | 92 | EXPORT_SYMBOL_GPL(iio_map_array_unregister); |
93 | 93 | ||
94 | static const struct iio_chan_spec | 94 | static const struct iio_chan_spec |
95 | *iio_chan_spec_from_name(const struct iio_dev *indio_dev, | 95 | *iio_chan_spec_from_name(const struct iio_dev *indio_dev, const char *name) |
96 | const char *name) | ||
97 | { | 96 | { |
98 | int i; | 97 | int i; |
99 | const struct iio_chan_spec *chan = NULL; | 98 | const struct iio_chan_spec *chan = NULL; |
100 | 99 | ||
101 | for (i = 0; i < indio_dev->num_channels; i++) | 100 | for (i = 0; i < indio_dev->num_channels; i++) |
102 | if (indio_dev->channels[i].datasheet_name && | 101 | if (indio_dev->channels[i].datasheet_name && |
103 | strcmp(name, indio_dev->channels[i].datasheet_name) == 0) { | 102 | strcmp(name, indio_dev->channels[i].datasheet_name) == 0) { |
104 | chan = &indio_dev->channels[i]; | 103 | chan = &indio_dev->channels[i]; |
105 | break; | 104 | break; |
106 | } | 105 | } |
107 | return chan; | 106 | return chan; |
108 | } | 107 | } |
109 | 108 | ||
110 | 109 | ||
111 | struct iio_channel *iio_st_channel_get(const char *name, | 110 | struct iio_channel *iio_channel_get(const char *name, const char *channel_name) |
112 | const char *channel_name) | ||
113 | { | 111 | { |
114 | struct iio_map_internal *c_i = NULL, *c = NULL; | 112 | struct iio_map_internal *c_i = NULL, *c = NULL; |
115 | struct iio_channel *channel; | 113 | struct iio_channel *channel; |
116 | 114 | ||
117 | if (name == NULL && channel_name == NULL) | 115 | if (name == NULL && channel_name == NULL) |
118 | return ERR_PTR(-ENODEV); | 116 | return ERR_PTR(-ENODEV); |
119 | 117 | ||
120 | /* first find matching entry the channel map */ | 118 | /* first find matching entry the channel map */ |
121 | mutex_lock(&iio_map_list_lock); | 119 | mutex_lock(&iio_map_list_lock); |
122 | list_for_each_entry(c_i, &iio_map_list, l) { | 120 | list_for_each_entry(c_i, &iio_map_list, l) { |
123 | if ((name && strcmp(name, c_i->map->consumer_dev_name) != 0) || | 121 | if ((name && strcmp(name, c_i->map->consumer_dev_name) != 0) || |
124 | (channel_name && | 122 | (channel_name && |
125 | strcmp(channel_name, c_i->map->consumer_channel) != 0)) | 123 | strcmp(channel_name, c_i->map->consumer_channel) != 0)) |
126 | continue; | 124 | continue; |
127 | c = c_i; | 125 | c = c_i; |
128 | iio_device_get(c->indio_dev); | 126 | iio_device_get(c->indio_dev); |
129 | break; | 127 | break; |
130 | } | 128 | } |
131 | mutex_unlock(&iio_map_list_lock); | 129 | mutex_unlock(&iio_map_list_lock); |
132 | if (c == NULL) | 130 | if (c == NULL) |
133 | return ERR_PTR(-ENODEV); | 131 | return ERR_PTR(-ENODEV); |
134 | 132 | ||
135 | channel = kmalloc(sizeof(*channel), GFP_KERNEL); | 133 | channel = kmalloc(sizeof(*channel), GFP_KERNEL); |
136 | if (channel == NULL) | 134 | if (channel == NULL) |
137 | return ERR_PTR(-ENOMEM); | 135 | return ERR_PTR(-ENOMEM); |
138 | 136 | ||
139 | channel->indio_dev = c->indio_dev; | 137 | channel->indio_dev = c->indio_dev; |
140 | 138 | ||
141 | if (c->map->adc_channel_label) | 139 | if (c->map->adc_channel_label) |
142 | channel->channel = | 140 | channel->channel = |
143 | iio_chan_spec_from_name(channel->indio_dev, | 141 | iio_chan_spec_from_name(channel->indio_dev, |
144 | c->map->adc_channel_label); | 142 | c->map->adc_channel_label); |
145 | 143 | ||
146 | return channel; | 144 | return channel; |
147 | } | 145 | } |
148 | EXPORT_SYMBOL_GPL(iio_st_channel_get); | 146 | EXPORT_SYMBOL_GPL(iio_channel_get); |
149 | 147 | ||
150 | void iio_st_channel_release(struct iio_channel *channel) | 148 | void iio_channel_release(struct iio_channel *channel) |
151 | { | 149 | { |
152 | iio_device_put(channel->indio_dev); | 150 | iio_device_put(channel->indio_dev); |
153 | kfree(channel); | 151 | kfree(channel); |
154 | } | 152 | } |
155 | EXPORT_SYMBOL_GPL(iio_st_channel_release); | 153 | EXPORT_SYMBOL_GPL(iio_channel_release); |
156 | 154 | ||
157 | struct iio_channel *iio_st_channel_get_all(const char *name) | 155 | struct iio_channel *iio_channel_get_all(const char *name) |
158 | { | 156 | { |
159 | struct iio_channel *chans; | 157 | struct iio_channel *chans; |
160 | struct iio_map_internal *c = NULL; | 158 | struct iio_map_internal *c = NULL; |
161 | int nummaps = 0; | 159 | int nummaps = 0; |
162 | int mapind = 0; | 160 | int mapind = 0; |
163 | int i, ret; | 161 | int i, ret; |
164 | 162 | ||
165 | if (name == NULL) | 163 | if (name == NULL) |
166 | return ERR_PTR(-EINVAL); | 164 | return ERR_PTR(-EINVAL); |
167 | 165 | ||
168 | mutex_lock(&iio_map_list_lock); | 166 | mutex_lock(&iio_map_list_lock); |
169 | /* first count the matching maps */ | 167 | /* first count the matching maps */ |
170 | list_for_each_entry(c, &iio_map_list, l) | 168 | list_for_each_entry(c, &iio_map_list, l) |
171 | if (name && strcmp(name, c->map->consumer_dev_name) != 0) | 169 | if (name && strcmp(name, c->map->consumer_dev_name) != 0) |
172 | continue; | 170 | continue; |
173 | else | 171 | else |
174 | nummaps++; | 172 | nummaps++; |
175 | 173 | ||
176 | if (nummaps == 0) { | 174 | if (nummaps == 0) { |
177 | ret = -ENODEV; | 175 | ret = -ENODEV; |
178 | goto error_ret; | 176 | goto error_ret; |
179 | } | 177 | } |
180 | 178 | ||
181 | /* NULL terminated array to save passing size */ | 179 | /* NULL terminated array to save passing size */ |
182 | chans = kzalloc(sizeof(*chans)*(nummaps + 1), GFP_KERNEL); | 180 | chans = kzalloc(sizeof(*chans)*(nummaps + 1), GFP_KERNEL); |
183 | if (chans == NULL) { | 181 | if (chans == NULL) { |
184 | ret = -ENOMEM; | 182 | ret = -ENOMEM; |
185 | goto error_ret; | 183 | goto error_ret; |
186 | } | 184 | } |
187 | 185 | ||
188 | /* for each map fill in the chans element */ | 186 | /* for each map fill in the chans element */ |
189 | list_for_each_entry(c, &iio_map_list, l) { | 187 | list_for_each_entry(c, &iio_map_list, l) { |
190 | if (name && strcmp(name, c->map->consumer_dev_name) != 0) | 188 | if (name && strcmp(name, c->map->consumer_dev_name) != 0) |
191 | continue; | 189 | continue; |
192 | chans[mapind].indio_dev = c->indio_dev; | 190 | chans[mapind].indio_dev = c->indio_dev; |
193 | chans[mapind].channel = | 191 | chans[mapind].channel = |
194 | iio_chan_spec_from_name(chans[mapind].indio_dev, | 192 | iio_chan_spec_from_name(chans[mapind].indio_dev, |
195 | c->map->adc_channel_label); | 193 | c->map->adc_channel_label); |
196 | if (chans[mapind].channel == NULL) { | 194 | if (chans[mapind].channel == NULL) { |
197 | ret = -EINVAL; | 195 | ret = -EINVAL; |
198 | iio_device_put(chans[mapind].indio_dev); | 196 | iio_device_put(chans[mapind].indio_dev); |
199 | goto error_free_chans; | 197 | goto error_free_chans; |
200 | } | 198 | } |
201 | iio_device_get(chans[mapind].indio_dev); | 199 | iio_device_get(chans[mapind].indio_dev); |
202 | mapind++; | 200 | mapind++; |
203 | } | 201 | } |
204 | mutex_unlock(&iio_map_list_lock); | 202 | mutex_unlock(&iio_map_list_lock); |
205 | if (mapind == 0) { | 203 | if (mapind == 0) { |
206 | ret = -ENODEV; | 204 | ret = -ENODEV; |
207 | goto error_free_chans; | 205 | goto error_free_chans; |
208 | } | 206 | } |
209 | return chans; | 207 | return chans; |
210 | 208 | ||
211 | error_free_chans: | 209 | error_free_chans: |
212 | for (i = 0; i < nummaps; i++) | 210 | for (i = 0; i < nummaps; i++) |
213 | iio_device_put(chans[i].indio_dev); | 211 | iio_device_put(chans[i].indio_dev); |
214 | kfree(chans); | 212 | kfree(chans); |
215 | error_ret: | 213 | error_ret: |
216 | mutex_unlock(&iio_map_list_lock); | 214 | mutex_unlock(&iio_map_list_lock); |
217 | 215 | ||
218 | return ERR_PTR(ret); | 216 | return ERR_PTR(ret); |
219 | } | 217 | } |
220 | EXPORT_SYMBOL_GPL(iio_st_channel_get_all); | 218 | EXPORT_SYMBOL_GPL(iio_channel_get_all); |
221 | 219 | ||
222 | void iio_st_channel_release_all(struct iio_channel *channels) | 220 | void iio_channel_release_all(struct iio_channel *channels) |
223 | { | 221 | { |
224 | struct iio_channel *chan = &channels[0]; | 222 | struct iio_channel *chan = &channels[0]; |
225 | 223 | ||
226 | while (chan->indio_dev) { | 224 | while (chan->indio_dev) { |
227 | iio_device_put(chan->indio_dev); | 225 | iio_device_put(chan->indio_dev); |
228 | chan++; | 226 | chan++; |
229 | } | 227 | } |
230 | kfree(channels); | 228 | kfree(channels); |
231 | } | 229 | } |
232 | EXPORT_SYMBOL_GPL(iio_st_channel_release_all); | 230 | EXPORT_SYMBOL_GPL(iio_channel_release_all); |
233 | 231 | ||
234 | int iio_st_read_channel_raw(struct iio_channel *chan, int *val) | 232 | int iio_read_channel_raw(struct iio_channel *chan, int *val) |
235 | { | 233 | { |
236 | int val2, ret; | 234 | int val2, ret; |
237 | 235 | ||
238 | mutex_lock(&chan->indio_dev->info_exist_lock); | 236 | mutex_lock(&chan->indio_dev->info_exist_lock); |
239 | if (chan->indio_dev->info == NULL) { | 237 | if (chan->indio_dev->info == NULL) { |
240 | ret = -ENODEV; | 238 | ret = -ENODEV; |
241 | goto err_unlock; | 239 | goto err_unlock; |
242 | } | 240 | } |
243 | 241 | ||
244 | ret = chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel, | 242 | ret = chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel, |
245 | val, &val2, 0); | 243 | val, &val2, 0); |
246 | err_unlock: | 244 | err_unlock: |
247 | mutex_unlock(&chan->indio_dev->info_exist_lock); | 245 | mutex_unlock(&chan->indio_dev->info_exist_lock); |
248 | 246 | ||
249 | return ret; | 247 | return ret; |
250 | } | 248 | } |
251 | EXPORT_SYMBOL_GPL(iio_st_read_channel_raw); | 249 | EXPORT_SYMBOL_GPL(iio_read_channel_raw); |
252 | 250 | ||
253 | int iio_st_read_channel_scale(struct iio_channel *chan, int *val, int *val2) | 251 | int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2) |
254 | { | 252 | { |
255 | int ret; | 253 | int ret; |
256 | 254 | ||
257 | mutex_lock(&chan->indio_dev->info_exist_lock); | 255 | mutex_lock(&chan->indio_dev->info_exist_lock); |
258 | if (chan->indio_dev->info == NULL) { | 256 | if (chan->indio_dev->info == NULL) { |
259 | ret = -ENODEV; | 257 | ret = -ENODEV; |
260 | goto err_unlock; | 258 | goto err_unlock; |
261 | } | 259 | } |
262 | 260 | ||
263 | ret = chan->indio_dev->info->read_raw(chan->indio_dev, | 261 | ret = chan->indio_dev->info->read_raw(chan->indio_dev, |
264 | chan->channel, | 262 | chan->channel, |
265 | val, val2, | 263 | val, val2, |
266 | IIO_CHAN_INFO_SCALE); | 264 | IIO_CHAN_INFO_SCALE); |
267 | err_unlock: | 265 | err_unlock: |
268 | mutex_unlock(&chan->indio_dev->info_exist_lock); | 266 | mutex_unlock(&chan->indio_dev->info_exist_lock); |
269 | 267 | ||
270 | return ret; | 268 | return ret; |
271 | } | 269 | } |
272 | EXPORT_SYMBOL_GPL(iio_st_read_channel_scale); | 270 | EXPORT_SYMBOL_GPL(iio_read_channel_scale); |
273 | 271 | ||
274 | int iio_st_get_channel_type(struct iio_channel *chan, | 272 | int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type) |
275 | enum iio_chan_type *type) | ||
276 | { | 273 | { |
277 | int ret = 0; | 274 | int ret = 0; |
278 | /* Need to verify underlying driver has not gone away */ | 275 | /* Need to verify underlying driver has not gone away */ |
279 | 276 | ||
280 | mutex_lock(&chan->indio_dev->info_exist_lock); | 277 | mutex_lock(&chan->indio_dev->info_exist_lock); |
281 | if (chan->indio_dev->info == NULL) { | 278 | if (chan->indio_dev->info == NULL) { |
282 | ret = -ENODEV; | 279 | ret = -ENODEV; |
283 | goto err_unlock; | 280 | goto err_unlock; |
284 | } | 281 | } |
285 | 282 | ||
286 | *type = chan->channel->type; | 283 | *type = chan->channel->type; |
287 | err_unlock: | 284 | err_unlock: |
288 | mutex_unlock(&chan->indio_dev->info_exist_lock); | 285 | mutex_unlock(&chan->indio_dev->info_exist_lock); |
289 | 286 | ||
290 | return ret; | 287 | return ret; |
291 | } | 288 | } |
292 | EXPORT_SYMBOL_GPL(iio_st_get_channel_type); | 289 | EXPORT_SYMBOL_GPL(iio_get_channel_type); |
293 | 290 |
drivers/staging/iio/accel/adis16201_core.c
1 | /* | 1 | /* |
2 | * ADIS16201 Programmable Digital Vibration Sensor driver | 2 | * ADIS16201 Programmable Digital Vibration Sensor driver |
3 | * | 3 | * |
4 | * Copyright 2010 Analog Devices Inc. | 4 | * Copyright 2010 Analog Devices Inc. |
5 | * | 5 | * |
6 | * Licensed under the GPL-2 or later. | 6 | * Licensed under the GPL-2 or later. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
10 | #include <linux/mutex.h> | 10 | #include <linux/mutex.h> |
11 | #include <linux/device.h> | 11 | #include <linux/device.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/spi/spi.h> | 13 | #include <linux/spi/spi.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/sysfs.h> | 15 | #include <linux/sysfs.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | 17 | ||
18 | #include <linux/iio/iio.h> | 18 | #include <linux/iio/iio.h> |
19 | #include <linux/iio/sysfs.h> | 19 | #include <linux/iio/sysfs.h> |
20 | #include <linux/iio/buffer.h> | 20 | #include <linux/iio/buffer.h> |
21 | 21 | ||
22 | #include "adis16201.h" | 22 | #include "adis16201.h" |
23 | 23 | ||
24 | enum adis16201_chan { | 24 | enum adis16201_chan { |
25 | in_supply, | 25 | in_supply, |
26 | temp, | 26 | temp, |
27 | accel_x, | 27 | accel_x, |
28 | accel_y, | 28 | accel_y, |
29 | incli_x, | 29 | incli_x, |
30 | incli_y, | 30 | incli_y, |
31 | in_aux, | 31 | in_aux, |
32 | }; | 32 | }; |
33 | 33 | ||
34 | /** | 34 | /** |
35 | * adis16201_spi_write_reg_8() - write single byte to a register | 35 | * adis16201_spi_write_reg_8() - write single byte to a register |
36 | * @dev: device associated with child of actual device (iio_dev or iio_trig) | 36 | * @dev: device associated with child of actual device (iio_dev or iio_trig) |
37 | * @reg_address: the address of the register to be written | 37 | * @reg_address: the address of the register to be written |
38 | * @val: the value to write | 38 | * @val: the value to write |
39 | **/ | 39 | **/ |
40 | static int adis16201_spi_write_reg_8(struct iio_dev *indio_dev, | 40 | static int adis16201_spi_write_reg_8(struct iio_dev *indio_dev, |
41 | u8 reg_address, | 41 | u8 reg_address, |
42 | u8 val) | 42 | u8 val) |
43 | { | 43 | { |
44 | int ret; | 44 | int ret; |
45 | struct adis16201_state *st = iio_priv(indio_dev); | 45 | struct adis16201_state *st = iio_priv(indio_dev); |
46 | 46 | ||
47 | mutex_lock(&st->buf_lock); | 47 | mutex_lock(&st->buf_lock); |
48 | st->tx[0] = ADIS16201_WRITE_REG(reg_address); | 48 | st->tx[0] = ADIS16201_WRITE_REG(reg_address); |
49 | st->tx[1] = val; | 49 | st->tx[1] = val; |
50 | 50 | ||
51 | ret = spi_write(st->us, st->tx, 2); | 51 | ret = spi_write(st->us, st->tx, 2); |
52 | mutex_unlock(&st->buf_lock); | 52 | mutex_unlock(&st->buf_lock); |
53 | 53 | ||
54 | return ret; | 54 | return ret; |
55 | } | 55 | } |
56 | 56 | ||
57 | /** | 57 | /** |
58 | * adis16201_spi_write_reg_16() - write 2 bytes to a pair of registers | 58 | * adis16201_spi_write_reg_16() - write 2 bytes to a pair of registers |
59 | * @indio_dev: iio device associated with child of actual device | 59 | * @indio_dev: iio device associated with child of actual device |
60 | * @reg_address: the address of the lower of the two registers. Second register | 60 | * @reg_address: the address of the lower of the two registers. Second register |
61 | * is assumed to have address one greater. | 61 | * is assumed to have address one greater. |
62 | * @val: value to be written | 62 | * @val: value to be written |
63 | **/ | 63 | **/ |
64 | static int adis16201_spi_write_reg_16(struct iio_dev *indio_dev, | 64 | static int adis16201_spi_write_reg_16(struct iio_dev *indio_dev, |
65 | u8 lower_reg_address, | 65 | u8 lower_reg_address, |
66 | u16 value) | 66 | u16 value) |
67 | { | 67 | { |
68 | int ret; | 68 | int ret; |
69 | struct spi_message msg; | 69 | struct spi_message msg; |
70 | struct adis16201_state *st = iio_priv(indio_dev); | 70 | struct adis16201_state *st = iio_priv(indio_dev); |
71 | struct spi_transfer xfers[] = { | 71 | struct spi_transfer xfers[] = { |
72 | { | 72 | { |
73 | .tx_buf = st->tx, | 73 | .tx_buf = st->tx, |
74 | .bits_per_word = 8, | 74 | .bits_per_word = 8, |
75 | .len = 2, | 75 | .len = 2, |
76 | .cs_change = 1, | 76 | .cs_change = 1, |
77 | }, { | 77 | }, { |
78 | .tx_buf = st->tx + 2, | 78 | .tx_buf = st->tx + 2, |
79 | .bits_per_word = 8, | 79 | .bits_per_word = 8, |
80 | .len = 2, | 80 | .len = 2, |
81 | }, | 81 | }, |
82 | }; | 82 | }; |
83 | 83 | ||
84 | mutex_lock(&st->buf_lock); | 84 | mutex_lock(&st->buf_lock); |
85 | st->tx[0] = ADIS16201_WRITE_REG(lower_reg_address); | 85 | st->tx[0] = ADIS16201_WRITE_REG(lower_reg_address); |
86 | st->tx[1] = value & 0xFF; | 86 | st->tx[1] = value & 0xFF; |
87 | st->tx[2] = ADIS16201_WRITE_REG(lower_reg_address + 1); | 87 | st->tx[2] = ADIS16201_WRITE_REG(lower_reg_address + 1); |
88 | st->tx[3] = (value >> 8) & 0xFF; | 88 | st->tx[3] = (value >> 8) & 0xFF; |
89 | 89 | ||
90 | spi_message_init(&msg); | 90 | spi_message_init(&msg); |
91 | spi_message_add_tail(&xfers[0], &msg); | 91 | spi_message_add_tail(&xfers[0], &msg); |
92 | spi_message_add_tail(&xfers[1], &msg); | 92 | spi_message_add_tail(&xfers[1], &msg); |
93 | ret = spi_sync(st->us, &msg); | 93 | ret = spi_sync(st->us, &msg); |
94 | mutex_unlock(&st->buf_lock); | 94 | mutex_unlock(&st->buf_lock); |
95 | 95 | ||
96 | return ret; | 96 | return ret; |
97 | } | 97 | } |
98 | 98 | ||
99 | /** | 99 | /** |
100 | * adis16201_spi_read_reg_16() - read 2 bytes from a 16-bit register | 100 | * adis16201_spi_read_reg_16() - read 2 bytes from a 16-bit register |
101 | * @indio_dev: iio device associated with child of actual device | 101 | * @indio_dev: iio device associated with child of actual device |
102 | * @reg_address: the address of the lower of the two registers. Second register | 102 | * @reg_address: the address of the lower of the two registers. Second register |
103 | * is assumed to have address one greater. | 103 | * is assumed to have address one greater. |
104 | * @val: somewhere to pass back the value read | 104 | * @val: somewhere to pass back the value read |
105 | **/ | 105 | **/ |
106 | static int adis16201_spi_read_reg_16(struct iio_dev *indio_dev, | 106 | static int adis16201_spi_read_reg_16(struct iio_dev *indio_dev, |
107 | u8 lower_reg_address, | 107 | u8 lower_reg_address, |
108 | u16 *val) | 108 | u16 *val) |
109 | { | 109 | { |
110 | struct spi_message msg; | 110 | struct spi_message msg; |
111 | struct adis16201_state *st = iio_priv(indio_dev); | 111 | struct adis16201_state *st = iio_priv(indio_dev); |
112 | int ret; | 112 | int ret; |
113 | struct spi_transfer xfers[] = { | 113 | struct spi_transfer xfers[] = { |
114 | { | 114 | { |
115 | .tx_buf = st->tx, | 115 | .tx_buf = st->tx, |
116 | .bits_per_word = 8, | 116 | .bits_per_word = 8, |
117 | .len = 2, | 117 | .len = 2, |
118 | .cs_change = 1, | 118 | .cs_change = 1, |
119 | .delay_usecs = 20, | 119 | .delay_usecs = 20, |
120 | }, { | 120 | }, { |
121 | .rx_buf = st->rx, | 121 | .rx_buf = st->rx, |
122 | .bits_per_word = 8, | 122 | .bits_per_word = 8, |
123 | .len = 2, | 123 | .len = 2, |
124 | .delay_usecs = 20, | 124 | .delay_usecs = 20, |
125 | }, | 125 | }, |
126 | }; | 126 | }; |
127 | 127 | ||
128 | mutex_lock(&st->buf_lock); | 128 | mutex_lock(&st->buf_lock); |
129 | st->tx[0] = ADIS16201_READ_REG(lower_reg_address); | 129 | st->tx[0] = ADIS16201_READ_REG(lower_reg_address); |
130 | st->tx[1] = 0; | 130 | st->tx[1] = 0; |
131 | 131 | ||
132 | spi_message_init(&msg); | 132 | spi_message_init(&msg); |
133 | spi_message_add_tail(&xfers[0], &msg); | 133 | spi_message_add_tail(&xfers[0], &msg); |
134 | spi_message_add_tail(&xfers[1], &msg); | 134 | spi_message_add_tail(&xfers[1], &msg); |
135 | ret = spi_sync(st->us, &msg); | 135 | ret = spi_sync(st->us, &msg); |
136 | if (ret) { | 136 | if (ret) { |
137 | dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", | 137 | dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", |
138 | lower_reg_address); | 138 | lower_reg_address); |
139 | goto error_ret; | 139 | goto error_ret; |
140 | } | 140 | } |
141 | *val = (st->rx[0] << 8) | st->rx[1]; | 141 | *val = (st->rx[0] << 8) | st->rx[1]; |
142 | 142 | ||
143 | error_ret: | 143 | error_ret: |
144 | mutex_unlock(&st->buf_lock); | 144 | mutex_unlock(&st->buf_lock); |
145 | return ret; | 145 | return ret; |
146 | } | 146 | } |
147 | 147 | ||
148 | static int adis16201_reset(struct iio_dev *indio_dev) | 148 | static int adis16201_reset(struct iio_dev *indio_dev) |
149 | { | 149 | { |
150 | int ret; | 150 | int ret; |
151 | struct adis16201_state *st = iio_priv(indio_dev); | 151 | struct adis16201_state *st = iio_priv(indio_dev); |
152 | 152 | ||
153 | ret = adis16201_spi_write_reg_8(indio_dev, | 153 | ret = adis16201_spi_write_reg_8(indio_dev, |
154 | ADIS16201_GLOB_CMD, | 154 | ADIS16201_GLOB_CMD, |
155 | ADIS16201_GLOB_CMD_SW_RESET); | 155 | ADIS16201_GLOB_CMD_SW_RESET); |
156 | if (ret) | 156 | if (ret) |
157 | dev_err(&st->us->dev, "problem resetting device"); | 157 | dev_err(&st->us->dev, "problem resetting device"); |
158 | 158 | ||
159 | return ret; | 159 | return ret; |
160 | } | 160 | } |
161 | 161 | ||
162 | static ssize_t adis16201_write_reset(struct device *dev, | ||
163 | struct device_attribute *attr, | ||
164 | const char *buf, size_t len) | ||
165 | { | ||
166 | int ret; | ||
167 | bool res; | ||
168 | |||
169 | if (len < 1) | ||
170 | return -EINVAL; | ||
171 | ret = strtobool(buf, &res); | ||
172 | if (ret || !res) | ||
173 | return ret; | ||
174 | return adis16201_reset(dev_to_iio_dev(dev)); | ||
175 | } | ||
176 | |||
177 | int adis16201_set_irq(struct iio_dev *indio_dev, bool enable) | 162 | int adis16201_set_irq(struct iio_dev *indio_dev, bool enable) |
178 | { | 163 | { |
179 | int ret = 0; | 164 | int ret = 0; |
180 | u16 msc; | 165 | u16 msc; |
181 | 166 | ||
182 | ret = adis16201_spi_read_reg_16(indio_dev, ADIS16201_MSC_CTRL, &msc); | 167 | ret = adis16201_spi_read_reg_16(indio_dev, ADIS16201_MSC_CTRL, &msc); |
183 | if (ret) | 168 | if (ret) |
184 | goto error_ret; | 169 | goto error_ret; |
185 | 170 | ||
186 | msc |= ADIS16201_MSC_CTRL_ACTIVE_HIGH; | 171 | msc |= ADIS16201_MSC_CTRL_ACTIVE_HIGH; |
187 | msc &= ~ADIS16201_MSC_CTRL_DATA_RDY_DIO1; | 172 | msc &= ~ADIS16201_MSC_CTRL_DATA_RDY_DIO1; |
188 | if (enable) | 173 | if (enable) |
189 | msc |= ADIS16201_MSC_CTRL_DATA_RDY_EN; | 174 | msc |= ADIS16201_MSC_CTRL_DATA_RDY_EN; |
190 | else | 175 | else |
191 | msc &= ~ADIS16201_MSC_CTRL_DATA_RDY_EN; | 176 | msc &= ~ADIS16201_MSC_CTRL_DATA_RDY_EN; |
192 | 177 | ||
193 | ret = adis16201_spi_write_reg_16(indio_dev, ADIS16201_MSC_CTRL, msc); | 178 | ret = adis16201_spi_write_reg_16(indio_dev, ADIS16201_MSC_CTRL, msc); |
194 | 179 | ||
195 | error_ret: | 180 | error_ret: |
196 | return ret; | 181 | return ret; |
197 | } | 182 | } |
198 | 183 | ||
199 | static int adis16201_check_status(struct iio_dev *indio_dev) | 184 | static int adis16201_check_status(struct iio_dev *indio_dev) |
200 | { | 185 | { |
201 | u16 status; | 186 | u16 status; |
202 | int ret; | 187 | int ret; |
203 | 188 | ||
204 | ret = adis16201_spi_read_reg_16(indio_dev, | 189 | ret = adis16201_spi_read_reg_16(indio_dev, |
205 | ADIS16201_DIAG_STAT, &status); | 190 | ADIS16201_DIAG_STAT, &status); |
206 | if (ret < 0) { | 191 | if (ret < 0) { |
207 | dev_err(&indio_dev->dev, "Reading status failed\n"); | 192 | dev_err(&indio_dev->dev, "Reading status failed\n"); |
208 | goto error_ret; | 193 | goto error_ret; |
209 | } | 194 | } |
210 | ret = status & 0xF; | 195 | ret = status & 0xF; |
211 | if (ret) | 196 | if (ret) |
212 | ret = -EFAULT; | 197 | ret = -EFAULT; |
213 | 198 | ||
214 | if (status & ADIS16201_DIAG_STAT_SPI_FAIL) | 199 | if (status & ADIS16201_DIAG_STAT_SPI_FAIL) |
215 | dev_err(&indio_dev->dev, "SPI failure\n"); | 200 | dev_err(&indio_dev->dev, "SPI failure\n"); |
216 | if (status & ADIS16201_DIAG_STAT_FLASH_UPT) | 201 | if (status & ADIS16201_DIAG_STAT_FLASH_UPT) |
217 | dev_err(&indio_dev->dev, "Flash update failed\n"); | 202 | dev_err(&indio_dev->dev, "Flash update failed\n"); |
218 | if (status & ADIS16201_DIAG_STAT_POWER_HIGH) | 203 | if (status & ADIS16201_DIAG_STAT_POWER_HIGH) |
219 | dev_err(&indio_dev->dev, "Power supply above 3.625V\n"); | 204 | dev_err(&indio_dev->dev, "Power supply above 3.625V\n"); |
220 | if (status & ADIS16201_DIAG_STAT_POWER_LOW) | 205 | if (status & ADIS16201_DIAG_STAT_POWER_LOW) |
221 | dev_err(&indio_dev->dev, "Power supply below 3.15V\n"); | 206 | dev_err(&indio_dev->dev, "Power supply below 3.15V\n"); |
222 | 207 | ||
223 | error_ret: | 208 | error_ret: |
224 | return ret; | 209 | return ret; |
225 | } | 210 | } |
226 | 211 | ||
227 | static int adis16201_self_test(struct iio_dev *indio_dev) | 212 | static int adis16201_self_test(struct iio_dev *indio_dev) |
228 | { | 213 | { |
229 | int ret; | 214 | int ret; |
230 | ret = adis16201_spi_write_reg_16(indio_dev, | 215 | ret = adis16201_spi_write_reg_16(indio_dev, |
231 | ADIS16201_MSC_CTRL, | 216 | ADIS16201_MSC_CTRL, |
232 | ADIS16201_MSC_CTRL_SELF_TEST_EN); | 217 | ADIS16201_MSC_CTRL_SELF_TEST_EN); |
233 | if (ret) { | 218 | if (ret) { |
234 | dev_err(&indio_dev->dev, "problem starting self test"); | 219 | dev_err(&indio_dev->dev, "problem starting self test"); |
235 | goto err_ret; | 220 | goto err_ret; |
236 | } | 221 | } |
237 | 222 | ||
238 | ret = adis16201_check_status(indio_dev); | 223 | ret = adis16201_check_status(indio_dev); |
239 | 224 | ||
240 | err_ret: | 225 | err_ret: |
241 | return ret; | 226 | return ret; |
242 | } | 227 | } |
243 | 228 | ||
244 | static int adis16201_initial_setup(struct iio_dev *indio_dev) | 229 | static int adis16201_initial_setup(struct iio_dev *indio_dev) |
245 | { | 230 | { |
246 | int ret; | 231 | int ret; |
247 | struct device *dev = &indio_dev->dev; | 232 | struct device *dev = &indio_dev->dev; |
248 | 233 | ||
249 | /* Disable IRQ */ | 234 | /* Disable IRQ */ |
250 | ret = adis16201_set_irq(indio_dev, false); | 235 | ret = adis16201_set_irq(indio_dev, false); |
251 | if (ret) { | 236 | if (ret) { |
252 | dev_err(dev, "disable irq failed"); | 237 | dev_err(dev, "disable irq failed"); |
253 | goto err_ret; | 238 | goto err_ret; |
254 | } | 239 | } |
255 | 240 | ||
256 | /* Do self test */ | 241 | /* Do self test */ |
257 | ret = adis16201_self_test(indio_dev); | 242 | ret = adis16201_self_test(indio_dev); |
258 | if (ret) { | 243 | if (ret) { |
259 | dev_err(dev, "self test failure"); | 244 | dev_err(dev, "self test failure"); |
260 | goto err_ret; | 245 | goto err_ret; |
261 | } | 246 | } |
262 | 247 | ||
263 | /* Read status register to check the result */ | 248 | /* Read status register to check the result */ |
264 | ret = adis16201_check_status(indio_dev); | 249 | ret = adis16201_check_status(indio_dev); |
265 | if (ret) { | 250 | if (ret) { |
266 | adis16201_reset(indio_dev); | 251 | adis16201_reset(indio_dev); |
267 | dev_err(dev, "device not playing ball -> reset"); | 252 | dev_err(dev, "device not playing ball -> reset"); |
268 | msleep(ADIS16201_STARTUP_DELAY); | 253 | msleep(ADIS16201_STARTUP_DELAY); |
269 | ret = adis16201_check_status(indio_dev); | 254 | ret = adis16201_check_status(indio_dev); |
270 | if (ret) { | 255 | if (ret) { |
271 | dev_err(dev, "giving up"); | 256 | dev_err(dev, "giving up"); |
272 | goto err_ret; | 257 | goto err_ret; |
273 | } | 258 | } |
274 | } | 259 | } |
275 | 260 | ||
276 | err_ret: | 261 | err_ret: |
277 | return ret; | 262 | return ret; |
278 | } | 263 | } |
279 | 264 | ||
280 | static u8 adis16201_addresses[7][2] = { | 265 | static u8 adis16201_addresses[7][2] = { |
281 | [in_supply] = { ADIS16201_SUPPLY_OUT, }, | 266 | [in_supply] = { ADIS16201_SUPPLY_OUT, }, |
282 | [temp] = { ADIS16201_TEMP_OUT }, | 267 | [temp] = { ADIS16201_TEMP_OUT }, |
283 | [accel_x] = { ADIS16201_XACCL_OUT, ADIS16201_XACCL_OFFS }, | 268 | [accel_x] = { ADIS16201_XACCL_OUT, ADIS16201_XACCL_OFFS }, |
284 | [accel_y] = { ADIS16201_YACCL_OUT, ADIS16201_YACCL_OFFS }, | 269 | [accel_y] = { ADIS16201_YACCL_OUT, ADIS16201_YACCL_OFFS }, |
285 | [in_aux] = { ADIS16201_AUX_ADC }, | 270 | [in_aux] = { ADIS16201_AUX_ADC }, |
286 | [incli_x] = { ADIS16201_XINCL_OUT }, | 271 | [incli_x] = { ADIS16201_XINCL_OUT }, |
287 | [incli_y] = { ADIS16201_YINCL_OUT }, | 272 | [incli_y] = { ADIS16201_YINCL_OUT }, |
288 | }; | 273 | }; |
289 | 274 | ||
290 | static int adis16201_read_raw(struct iio_dev *indio_dev, | 275 | static int adis16201_read_raw(struct iio_dev *indio_dev, |
291 | struct iio_chan_spec const *chan, | 276 | struct iio_chan_spec const *chan, |
292 | int *val, int *val2, | 277 | int *val, int *val2, |
293 | long mask) | 278 | long mask) |
294 | { | 279 | { |
295 | int ret; | 280 | int ret; |
296 | int bits; | 281 | int bits; |
297 | u8 addr; | 282 | u8 addr; |
298 | s16 val16; | 283 | s16 val16; |
299 | 284 | ||
300 | switch (mask) { | 285 | switch (mask) { |
301 | case IIO_CHAN_INFO_RAW: | 286 | case IIO_CHAN_INFO_RAW: |
302 | mutex_lock(&indio_dev->mlock); | 287 | mutex_lock(&indio_dev->mlock); |
303 | addr = adis16201_addresses[chan->address][0]; | 288 | addr = adis16201_addresses[chan->address][0]; |
304 | ret = adis16201_spi_read_reg_16(indio_dev, addr, &val16); | 289 | ret = adis16201_spi_read_reg_16(indio_dev, addr, &val16); |
305 | if (ret) { | 290 | if (ret) { |
306 | mutex_unlock(&indio_dev->mlock); | 291 | mutex_unlock(&indio_dev->mlock); |
307 | return ret; | 292 | return ret; |
308 | } | 293 | } |
309 | 294 | ||
310 | if (val16 & ADIS16201_ERROR_ACTIVE) { | 295 | if (val16 & ADIS16201_ERROR_ACTIVE) { |
311 | ret = adis16201_check_status(indio_dev); | 296 | ret = adis16201_check_status(indio_dev); |
312 | if (ret) { | 297 | if (ret) { |
313 | mutex_unlock(&indio_dev->mlock); | 298 | mutex_unlock(&indio_dev->mlock); |
314 | return ret; | 299 | return ret; |
315 | } | 300 | } |
316 | } | 301 | } |
317 | val16 = val16 & ((1 << chan->scan_type.realbits) - 1); | 302 | val16 = val16 & ((1 << chan->scan_type.realbits) - 1); |
318 | if (chan->scan_type.sign == 's') | 303 | if (chan->scan_type.sign == 's') |
319 | val16 = (s16)(val16 << | 304 | val16 = (s16)(val16 << |
320 | (16 - chan->scan_type.realbits)) >> | 305 | (16 - chan->scan_type.realbits)) >> |
321 | (16 - chan->scan_type.realbits); | 306 | (16 - chan->scan_type.realbits); |
322 | *val = val16; | 307 | *val = val16; |
323 | mutex_unlock(&indio_dev->mlock); | 308 | mutex_unlock(&indio_dev->mlock); |
324 | return IIO_VAL_INT; | 309 | return IIO_VAL_INT; |
325 | case IIO_CHAN_INFO_SCALE: | 310 | case IIO_CHAN_INFO_SCALE: |
326 | switch (chan->type) { | 311 | switch (chan->type) { |
327 | case IIO_VOLTAGE: | 312 | case IIO_VOLTAGE: |
328 | *val = 0; | 313 | *val = 0; |
329 | if (chan->channel == 0) | 314 | if (chan->channel == 0) |
330 | *val2 = 1220; | 315 | *val2 = 1220; |
331 | else | 316 | else |
332 | *val2 = 610; | 317 | *val2 = 610; |
333 | return IIO_VAL_INT_PLUS_MICRO; | 318 | return IIO_VAL_INT_PLUS_MICRO; |
334 | case IIO_TEMP: | 319 | case IIO_TEMP: |
335 | *val = 0; | 320 | *val = 0; |
336 | *val2 = -470000; | 321 | *val2 = -470000; |
337 | return IIO_VAL_INT_PLUS_MICRO; | 322 | return IIO_VAL_INT_PLUS_MICRO; |
338 | case IIO_ACCEL: | 323 | case IIO_ACCEL: |
339 | *val = 0; | 324 | *val = 0; |
340 | *val2 = 462500; | 325 | *val2 = 462500; |
341 | return IIO_VAL_INT_PLUS_MICRO; | 326 | return IIO_VAL_INT_PLUS_MICRO; |
342 | case IIO_INCLI: | 327 | case IIO_INCLI: |
343 | *val = 0; | 328 | *val = 0; |
344 | *val2 = 100000; | 329 | *val2 = 100000; |
345 | return IIO_VAL_INT_PLUS_MICRO; | 330 | return IIO_VAL_INT_PLUS_MICRO; |
346 | default: | 331 | default: |
347 | return -EINVAL; | 332 | return -EINVAL; |
348 | } | 333 | } |
349 | break; | 334 | break; |
350 | case IIO_CHAN_INFO_OFFSET: | 335 | case IIO_CHAN_INFO_OFFSET: |
351 | *val = 25; | 336 | *val = 25; |
352 | return IIO_VAL_INT; | 337 | return IIO_VAL_INT; |
353 | case IIO_CHAN_INFO_CALIBBIAS: | 338 | case IIO_CHAN_INFO_CALIBBIAS: |
354 | switch (chan->type) { | 339 | switch (chan->type) { |
355 | case IIO_ACCEL: | 340 | case IIO_ACCEL: |
356 | bits = 12; | 341 | bits = 12; |
357 | break; | 342 | break; |
358 | case IIO_INCLI: | 343 | case IIO_INCLI: |
359 | bits = 9; | 344 | bits = 9; |
360 | break; | 345 | break; |
361 | default: | 346 | default: |
362 | return -EINVAL; | 347 | return -EINVAL; |
363 | }; | 348 | }; |
364 | mutex_lock(&indio_dev->mlock); | 349 | mutex_lock(&indio_dev->mlock); |
365 | addr = adis16201_addresses[chan->address][1]; | 350 | addr = adis16201_addresses[chan->address][1]; |
366 | ret = adis16201_spi_read_reg_16(indio_dev, addr, &val16); | 351 | ret = adis16201_spi_read_reg_16(indio_dev, addr, &val16); |
367 | if (ret) { | 352 | if (ret) { |
368 | mutex_unlock(&indio_dev->mlock); | 353 | mutex_unlock(&indio_dev->mlock); |
369 | return ret; | 354 | return ret; |
370 | } | 355 | } |
371 | val16 &= (1 << bits) - 1; | 356 | val16 &= (1 << bits) - 1; |
372 | val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); | 357 | val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); |
373 | *val = val16; | 358 | *val = val16; |
374 | mutex_unlock(&indio_dev->mlock); | 359 | mutex_unlock(&indio_dev->mlock); |
375 | return IIO_VAL_INT; | 360 | return IIO_VAL_INT; |
376 | } | 361 | } |
377 | return -EINVAL; | 362 | return -EINVAL; |
378 | } | 363 | } |
379 | 364 | ||
380 | static int adis16201_write_raw(struct iio_dev *indio_dev, | 365 | static int adis16201_write_raw(struct iio_dev *indio_dev, |
381 | struct iio_chan_spec const *chan, | 366 | struct iio_chan_spec const *chan, |
382 | int val, | 367 | int val, |
383 | int val2, | 368 | int val2, |
384 | long mask) | 369 | long mask) |
385 | { | 370 | { |
386 | int bits; | 371 | int bits; |
387 | s16 val16; | 372 | s16 val16; |
388 | u8 addr; | 373 | u8 addr; |
389 | switch (mask) { | 374 | switch (mask) { |
390 | case IIO_CHAN_INFO_CALIBBIAS: | 375 | case IIO_CHAN_INFO_CALIBBIAS: |
391 | switch (chan->type) { | 376 | switch (chan->type) { |
392 | case IIO_ACCEL: | 377 | case IIO_ACCEL: |
393 | bits = 12; | 378 | bits = 12; |
394 | break; | 379 | break; |
395 | case IIO_INCLI: | 380 | case IIO_INCLI: |
396 | bits = 9; | 381 | bits = 9; |
397 | break; | 382 | break; |
398 | default: | 383 | default: |
399 | return -EINVAL; | 384 | return -EINVAL; |
400 | }; | 385 | }; |
401 | val16 = val & ((1 << bits) - 1); | 386 | val16 = val & ((1 << bits) - 1); |
402 | addr = adis16201_addresses[chan->address][1]; | 387 | addr = adis16201_addresses[chan->address][1]; |
403 | return adis16201_spi_write_reg_16(indio_dev, addr, val16); | 388 | return adis16201_spi_write_reg_16(indio_dev, addr, val16); |
404 | } | 389 | } |
405 | return -EINVAL; | 390 | return -EINVAL; |
406 | } | 391 | } |
407 | 392 | ||
408 | static struct iio_chan_spec adis16201_channels[] = { | 393 | static struct iio_chan_spec adis16201_channels[] = { |
409 | { | 394 | { |
410 | .type = IIO_VOLTAGE, | 395 | .type = IIO_VOLTAGE, |
411 | .indexed = 1, | 396 | .indexed = 1, |
412 | .channel = 0, | 397 | .channel = 0, |
413 | .extend_name = "supply", | 398 | .extend_name = "supply", |
414 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 399 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
415 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 400 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
416 | .address = in_supply, | 401 | .address = in_supply, |
417 | .scan_index = ADIS16201_SCAN_SUPPLY, | 402 | .scan_index = ADIS16201_SCAN_SUPPLY, |
418 | .scan_type = { | 403 | .scan_type = { |
419 | .sign = 'u', | 404 | .sign = 'u', |
420 | .realbits = 12, | 405 | .realbits = 12, |
421 | .storagebits = 16, | 406 | .storagebits = 16, |
422 | }, | 407 | }, |
423 | }, { | 408 | }, { |
424 | .type = IIO_TEMP, | 409 | .type = IIO_TEMP, |
425 | .indexed = 1, | 410 | .indexed = 1, |
426 | .channel = 0, | 411 | .channel = 0, |
427 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 412 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
428 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | | 413 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | |
429 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, | 414 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, |
430 | .address = temp, | 415 | .address = temp, |
431 | .scan_index = ADIS16201_SCAN_TEMP, | 416 | .scan_index = ADIS16201_SCAN_TEMP, |
432 | .scan_type = { | 417 | .scan_type = { |
433 | .sign = 'u', | 418 | .sign = 'u', |
434 | .realbits = 12, | 419 | .realbits = 12, |
435 | .storagebits = 16, | 420 | .storagebits = 16, |
436 | }, | 421 | }, |
437 | }, { | 422 | }, { |
438 | .type = IIO_ACCEL, | 423 | .type = IIO_ACCEL, |
439 | .modified = 1, | 424 | .modified = 1, |
440 | .channel2 = IIO_MOD_X, | 425 | .channel2 = IIO_MOD_X, |
441 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 426 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
442 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 427 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
443 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, | 428 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, |
444 | .address = accel_x, | 429 | .address = accel_x, |
445 | .scan_index = ADIS16201_SCAN_ACC_X, | 430 | .scan_index = ADIS16201_SCAN_ACC_X, |
446 | .scan_type = { | 431 | .scan_type = { |
447 | .sign = 's', | 432 | .sign = 's', |
448 | .realbits = 14, | 433 | .realbits = 14, |
449 | .storagebits = 16, | 434 | .storagebits = 16, |
450 | }, | 435 | }, |
451 | }, { | 436 | }, { |
452 | .type = IIO_ACCEL, | 437 | .type = IIO_ACCEL, |
453 | .modified = 1, | 438 | .modified = 1, |
454 | .channel2 = IIO_MOD_Y, | 439 | .channel2 = IIO_MOD_Y, |
455 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 440 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
456 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 441 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
457 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, | 442 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, |
458 | .address = accel_y, | 443 | .address = accel_y, |
459 | .scan_index = ADIS16201_SCAN_ACC_Y, | 444 | .scan_index = ADIS16201_SCAN_ACC_Y, |
460 | .scan_type = { | 445 | .scan_type = { |
461 | .sign = 's', | 446 | .sign = 's', |
462 | .realbits = 14, | 447 | .realbits = 14, |
463 | .storagebits = 16, | 448 | .storagebits = 16, |
464 | }, | 449 | }, |
465 | }, { | 450 | }, { |
466 | .type = IIO_VOLTAGE, | 451 | .type = IIO_VOLTAGE, |
467 | .indexed = 1, | 452 | .indexed = 1, |
468 | .channel = 1, | 453 | .channel = 1, |
469 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 454 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
470 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 455 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
471 | .address = in_aux, | 456 | .address = in_aux, |
472 | .scan_index = ADIS16201_SCAN_AUX_ADC, | 457 | .scan_index = ADIS16201_SCAN_AUX_ADC, |
473 | .scan_type = { | 458 | .scan_type = { |
474 | .sign = 'u', | 459 | .sign = 'u', |
475 | .realbits = 12, | 460 | .realbits = 12, |
476 | .storagebits = 16, | 461 | .storagebits = 16, |
477 | }, | 462 | }, |
478 | }, { | 463 | }, { |
479 | .type = IIO_INCLI, | 464 | .type = IIO_INCLI, |
480 | .modified = 1, | 465 | .modified = 1, |
481 | .channel2 = IIO_MOD_X, | 466 | .channel2 = IIO_MOD_X, |
482 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 467 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
483 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 468 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
484 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, | 469 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, |
485 | .address = incli_x, | 470 | .address = incli_x, |
486 | .scan_index = ADIS16201_SCAN_INCLI_X, | 471 | .scan_index = ADIS16201_SCAN_INCLI_X, |
487 | .scan_type = { | 472 | .scan_type = { |
488 | .sign = 's', | 473 | .sign = 's', |
489 | .realbits = 14, | 474 | .realbits = 14, |
490 | .storagebits = 16, | 475 | .storagebits = 16, |
491 | }, | 476 | }, |
492 | }, { | 477 | }, { |
493 | .type = IIO_INCLI, | 478 | .type = IIO_INCLI, |
494 | .modified = 1, | 479 | .modified = 1, |
495 | .channel2 = IIO_MOD_Y, | 480 | .channel2 = IIO_MOD_Y, |
496 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 481 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
497 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 482 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
498 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, | 483 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, |
499 | .address = incli_y, | 484 | .address = incli_y, |
500 | .scan_index = ADIS16201_SCAN_INCLI_Y, | 485 | .scan_index = ADIS16201_SCAN_INCLI_Y, |
501 | .scan_type = { | 486 | .scan_type = { |
502 | .sign = 's', | 487 | .sign = 's', |
503 | .realbits = 14, | 488 | .realbits = 14, |
504 | .storagebits = 16, | 489 | .storagebits = 16, |
505 | }, | 490 | }, |
506 | }, | 491 | }, |
507 | IIO_CHAN_SOFT_TIMESTAMP(7) | 492 | IIO_CHAN_SOFT_TIMESTAMP(7) |
508 | }; | 493 | }; |
509 | 494 | ||
510 | static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16201_write_reset, 0); | ||
511 | |||
512 | static struct attribute *adis16201_attributes[] = { | ||
513 | &iio_dev_attr_reset.dev_attr.attr, | ||
514 | NULL | ||
515 | }; | ||
516 | |||
517 | static const struct attribute_group adis16201_attribute_group = { | ||
518 | .attrs = adis16201_attributes, | ||
519 | }; | ||
520 | |||
521 | static const struct iio_info adis16201_info = { | 495 | static const struct iio_info adis16201_info = { |
522 | .attrs = &adis16201_attribute_group, | ||
523 | .read_raw = &adis16201_read_raw, | 496 | .read_raw = &adis16201_read_raw, |
524 | .write_raw = &adis16201_write_raw, | 497 | .write_raw = &adis16201_write_raw, |
525 | .driver_module = THIS_MODULE, | 498 | .driver_module = THIS_MODULE, |
526 | }; | 499 | }; |
527 | 500 | ||
528 | static int __devinit adis16201_probe(struct spi_device *spi) | 501 | static int __devinit adis16201_probe(struct spi_device *spi) |
529 | { | 502 | { |
530 | int ret; | 503 | int ret; |
531 | struct adis16201_state *st; | 504 | struct adis16201_state *st; |
532 | struct iio_dev *indio_dev; | 505 | struct iio_dev *indio_dev; |
533 | 506 | ||
534 | /* setup the industrialio driver allocated elements */ | 507 | /* setup the industrialio driver allocated elements */ |
535 | indio_dev = iio_device_alloc(sizeof(*st)); | 508 | indio_dev = iio_device_alloc(sizeof(*st)); |
536 | if (indio_dev == NULL) { | 509 | if (indio_dev == NULL) { |
537 | ret = -ENOMEM; | 510 | ret = -ENOMEM; |
538 | goto error_ret; | 511 | goto error_ret; |
539 | } | 512 | } |
540 | st = iio_priv(indio_dev); | 513 | st = iio_priv(indio_dev); |
541 | /* this is only used for removal purposes */ | 514 | /* this is only used for removal purposes */ |
542 | spi_set_drvdata(spi, indio_dev); | 515 | spi_set_drvdata(spi, indio_dev); |
543 | 516 | ||
544 | st->us = spi; | 517 | st->us = spi; |
545 | mutex_init(&st->buf_lock); | 518 | mutex_init(&st->buf_lock); |
546 | 519 | ||
547 | indio_dev->name = spi->dev.driver->name; | 520 | indio_dev->name = spi->dev.driver->name; |
548 | indio_dev->dev.parent = &spi->dev; | 521 | indio_dev->dev.parent = &spi->dev; |
549 | indio_dev->info = &adis16201_info; | 522 | indio_dev->info = &adis16201_info; |
550 | 523 | ||
551 | indio_dev->channels = adis16201_channels; | 524 | indio_dev->channels = adis16201_channels; |
552 | indio_dev->num_channels = ARRAY_SIZE(adis16201_channels); | 525 | indio_dev->num_channels = ARRAY_SIZE(adis16201_channels); |
553 | indio_dev->modes = INDIO_DIRECT_MODE; | 526 | indio_dev->modes = INDIO_DIRECT_MODE; |
554 | 527 | ||
555 | ret = adis16201_configure_ring(indio_dev); | 528 | ret = adis16201_configure_ring(indio_dev); |
556 | if (ret) | 529 | if (ret) |
557 | goto error_free_dev; | 530 | goto error_free_dev; |
558 | 531 | ||
559 | ret = iio_buffer_register(indio_dev, | 532 | ret = iio_buffer_register(indio_dev, |
560 | adis16201_channels, | 533 | adis16201_channels, |
561 | ARRAY_SIZE(adis16201_channels)); | 534 | ARRAY_SIZE(adis16201_channels)); |
562 | if (ret) { | 535 | if (ret) { |
563 | printk(KERN_ERR "failed to initialize the ring\n"); | 536 | printk(KERN_ERR "failed to initialize the ring\n"); |
564 | goto error_unreg_ring_funcs; | 537 | goto error_unreg_ring_funcs; |
565 | } | 538 | } |
566 | 539 | ||
567 | if (spi->irq) { | 540 | if (spi->irq) { |
568 | ret = adis16201_probe_trigger(indio_dev); | 541 | ret = adis16201_probe_trigger(indio_dev); |
569 | if (ret) | 542 | if (ret) |
570 | goto error_uninitialize_ring; | 543 | goto error_uninitialize_ring; |
571 | } | 544 | } |
572 | 545 | ||
573 | /* Get the device into a sane initial state */ | 546 | /* Get the device into a sane initial state */ |
574 | ret = adis16201_initial_setup(indio_dev); | 547 | ret = adis16201_initial_setup(indio_dev); |
575 | if (ret) | 548 | if (ret) |
576 | goto error_remove_trigger; | 549 | goto error_remove_trigger; |
577 | 550 | ||
578 | ret = iio_device_register(indio_dev); | 551 | ret = iio_device_register(indio_dev); |
579 | if (ret < 0) | 552 | if (ret < 0) |
580 | goto error_remove_trigger; | 553 | goto error_remove_trigger; |
581 | return 0; | 554 | return 0; |
582 | 555 | ||
583 | error_remove_trigger: | 556 | error_remove_trigger: |
584 | adis16201_remove_trigger(indio_dev); | 557 | adis16201_remove_trigger(indio_dev); |
585 | error_uninitialize_ring: | 558 | error_uninitialize_ring: |
586 | iio_buffer_unregister(indio_dev); | 559 | iio_buffer_unregister(indio_dev); |
587 | error_unreg_ring_funcs: | 560 | error_unreg_ring_funcs: |
588 | adis16201_unconfigure_ring(indio_dev); | 561 | adis16201_unconfigure_ring(indio_dev); |
589 | error_free_dev: | 562 | error_free_dev: |
590 | iio_device_free(indio_dev); | 563 | iio_device_free(indio_dev); |
591 | error_ret: | 564 | error_ret: |
592 | return ret; | 565 | return ret; |
593 | } | 566 | } |
594 | 567 | ||
595 | static int adis16201_remove(struct spi_device *spi) | 568 | static int adis16201_remove(struct spi_device *spi) |
596 | { | 569 | { |
597 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | 570 | struct iio_dev *indio_dev = spi_get_drvdata(spi); |
598 | 571 | ||
599 | iio_device_unregister(indio_dev); | 572 | iio_device_unregister(indio_dev); |
600 | adis16201_remove_trigger(indio_dev); | 573 | adis16201_remove_trigger(indio_dev); |
601 | iio_buffer_unregister(indio_dev); | 574 | iio_buffer_unregister(indio_dev); |
602 | adis16201_unconfigure_ring(indio_dev); | 575 | adis16201_unconfigure_ring(indio_dev); |
603 | iio_device_free(indio_dev); | 576 | iio_device_free(indio_dev); |
604 | 577 | ||
605 | return 0; | 578 | return 0; |
606 | } | 579 | } |
607 | 580 | ||
608 | static struct spi_driver adis16201_driver = { | 581 | static struct spi_driver adis16201_driver = { |
609 | .driver = { | 582 | .driver = { |
610 | .name = "adis16201", | 583 | .name = "adis16201", |
611 | .owner = THIS_MODULE, | 584 | .owner = THIS_MODULE, |
612 | }, | 585 | }, |
613 | .probe = adis16201_probe, | 586 | .probe = adis16201_probe, |
614 | .remove = __devexit_p(adis16201_remove), | 587 | .remove = __devexit_p(adis16201_remove), |
615 | }; | 588 | }; |
616 | module_spi_driver(adis16201_driver); | 589 | module_spi_driver(adis16201_driver); |
617 | 590 | ||
618 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | 591 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); |
619 | MODULE_DESCRIPTION("Analog Devices ADIS16201 Programmable Digital Vibration Sensor driver"); | 592 | MODULE_DESCRIPTION("Analog Devices ADIS16201 Programmable Digital Vibration Sensor driver"); |
620 | MODULE_LICENSE("GPL v2"); | 593 | MODULE_LICENSE("GPL v2"); |
621 | MODULE_ALIAS("spi:adis16201"); | 594 | MODULE_ALIAS("spi:adis16201"); |
622 | 595 |
drivers/staging/iio/accel/adis16203_core.c
1 | /* | 1 | /* |
2 | * ADIS16203 Programmable Digital Vibration Sensor driver | 2 | * ADIS16203 Programmable Digital Vibration Sensor driver |
3 | * | 3 | * |
4 | * Copyright 2010 Analog Devices Inc. | 4 | * Copyright 2010 Analog Devices Inc. |
5 | * | 5 | * |
6 | * Licensed under the GPL-2 or later. | 6 | * Licensed under the GPL-2 or later. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
10 | #include <linux/mutex.h> | 10 | #include <linux/mutex.h> |
11 | #include <linux/device.h> | 11 | #include <linux/device.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/spi/spi.h> | 13 | #include <linux/spi/spi.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/sysfs.h> | 15 | #include <linux/sysfs.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | 17 | ||
18 | #include <linux/iio/iio.h> | 18 | #include <linux/iio/iio.h> |
19 | #include <linux/iio/sysfs.h> | 19 | #include <linux/iio/sysfs.h> |
20 | #include <linux/iio/buffer.h> | 20 | #include <linux/iio/buffer.h> |
21 | 21 | ||
22 | #include "adis16203.h" | 22 | #include "adis16203.h" |
23 | 23 | ||
24 | #define DRIVER_NAME "adis16203" | 24 | #define DRIVER_NAME "adis16203" |
25 | 25 | ||
26 | /** | 26 | /** |
27 | * adis16203_spi_write_reg_8() - write single byte to a register | 27 | * adis16203_spi_write_reg_8() - write single byte to a register |
28 | * @indio_dev: iio device associated with child of actual device | 28 | * @indio_dev: iio device associated with child of actual device |
29 | * @reg_address: the address of the register to be written | 29 | * @reg_address: the address of the register to be written |
30 | * @val: the value to write | 30 | * @val: the value to write |
31 | **/ | 31 | **/ |
32 | static int adis16203_spi_write_reg_8(struct iio_dev *indio_dev, | 32 | static int adis16203_spi_write_reg_8(struct iio_dev *indio_dev, |
33 | u8 reg_address, | 33 | u8 reg_address, |
34 | u8 val) | 34 | u8 val) |
35 | { | 35 | { |
36 | int ret; | 36 | int ret; |
37 | struct adis16203_state *st = iio_priv(indio_dev); | 37 | struct adis16203_state *st = iio_priv(indio_dev); |
38 | 38 | ||
39 | mutex_lock(&st->buf_lock); | 39 | mutex_lock(&st->buf_lock); |
40 | st->tx[0] = ADIS16203_WRITE_REG(reg_address); | 40 | st->tx[0] = ADIS16203_WRITE_REG(reg_address); |
41 | st->tx[1] = val; | 41 | st->tx[1] = val; |
42 | 42 | ||
43 | ret = spi_write(st->us, st->tx, 2); | 43 | ret = spi_write(st->us, st->tx, 2); |
44 | mutex_unlock(&st->buf_lock); | 44 | mutex_unlock(&st->buf_lock); |
45 | 45 | ||
46 | return ret; | 46 | return ret; |
47 | } | 47 | } |
48 | 48 | ||
49 | /** | 49 | /** |
50 | * adis16203_spi_write_reg_16() - write 2 bytes to a pair of registers | 50 | * adis16203_spi_write_reg_16() - write 2 bytes to a pair of registers |
51 | * @indio_dev: iio device associated with child of actual device | 51 | * @indio_dev: iio device associated with child of actual device |
52 | * @reg_address: the address of the lower of the two registers. Second register | 52 | * @reg_address: the address of the lower of the two registers. Second register |
53 | * is assumed to have address one greater. | 53 | * is assumed to have address one greater. |
54 | * @val: value to be written | 54 | * @val: value to be written |
55 | **/ | 55 | **/ |
56 | static int adis16203_spi_write_reg_16(struct iio_dev *indio_dev, | 56 | static int adis16203_spi_write_reg_16(struct iio_dev *indio_dev, |
57 | u8 lower_reg_address, | 57 | u8 lower_reg_address, |
58 | u16 value) | 58 | u16 value) |
59 | { | 59 | { |
60 | int ret; | 60 | int ret; |
61 | struct spi_message msg; | 61 | struct spi_message msg; |
62 | struct adis16203_state *st = iio_priv(indio_dev); | 62 | struct adis16203_state *st = iio_priv(indio_dev); |
63 | struct spi_transfer xfers[] = { | 63 | struct spi_transfer xfers[] = { |
64 | { | 64 | { |
65 | .tx_buf = st->tx, | 65 | .tx_buf = st->tx, |
66 | .bits_per_word = 8, | 66 | .bits_per_word = 8, |
67 | .len = 2, | 67 | .len = 2, |
68 | .cs_change = 1, | 68 | .cs_change = 1, |
69 | }, { | 69 | }, { |
70 | .tx_buf = st->tx + 2, | 70 | .tx_buf = st->tx + 2, |
71 | .bits_per_word = 8, | 71 | .bits_per_word = 8, |
72 | .len = 2, | 72 | .len = 2, |
73 | }, | 73 | }, |
74 | }; | 74 | }; |
75 | 75 | ||
76 | mutex_lock(&st->buf_lock); | 76 | mutex_lock(&st->buf_lock); |
77 | st->tx[0] = ADIS16203_WRITE_REG(lower_reg_address); | 77 | st->tx[0] = ADIS16203_WRITE_REG(lower_reg_address); |
78 | st->tx[1] = value & 0xFF; | 78 | st->tx[1] = value & 0xFF; |
79 | st->tx[2] = ADIS16203_WRITE_REG(lower_reg_address + 1); | 79 | st->tx[2] = ADIS16203_WRITE_REG(lower_reg_address + 1); |
80 | st->tx[3] = (value >> 8) & 0xFF; | 80 | st->tx[3] = (value >> 8) & 0xFF; |
81 | 81 | ||
82 | spi_message_init(&msg); | 82 | spi_message_init(&msg); |
83 | spi_message_add_tail(&xfers[0], &msg); | 83 | spi_message_add_tail(&xfers[0], &msg); |
84 | spi_message_add_tail(&xfers[1], &msg); | 84 | spi_message_add_tail(&xfers[1], &msg); |
85 | ret = spi_sync(st->us, &msg); | 85 | ret = spi_sync(st->us, &msg); |
86 | mutex_unlock(&st->buf_lock); | 86 | mutex_unlock(&st->buf_lock); |
87 | 87 | ||
88 | return ret; | 88 | return ret; |
89 | } | 89 | } |
90 | 90 | ||
91 | /** | 91 | /** |
92 | * adis16203_spi_read_reg_16() - read 2 bytes from a 16-bit register | 92 | * adis16203_spi_read_reg_16() - read 2 bytes from a 16-bit register |
93 | * @indio_dev: iio device associated with child of actual device | 93 | * @indio_dev: iio device associated with child of actual device |
94 | * @reg_address: the address of the lower of the two registers. Second register | 94 | * @reg_address: the address of the lower of the two registers. Second register |
95 | * is assumed to have address one greater. | 95 | * is assumed to have address one greater. |
96 | * @val: somewhere to pass back the value read | 96 | * @val: somewhere to pass back the value read |
97 | **/ | 97 | **/ |
98 | static int adis16203_spi_read_reg_16(struct iio_dev *indio_dev, | 98 | static int adis16203_spi_read_reg_16(struct iio_dev *indio_dev, |
99 | u8 lower_reg_address, | 99 | u8 lower_reg_address, |
100 | u16 *val) | 100 | u16 *val) |
101 | { | 101 | { |
102 | struct spi_message msg; | 102 | struct spi_message msg; |
103 | struct adis16203_state *st = iio_priv(indio_dev); | 103 | struct adis16203_state *st = iio_priv(indio_dev); |
104 | int ret; | 104 | int ret; |
105 | struct spi_transfer xfers[] = { | 105 | struct spi_transfer xfers[] = { |
106 | { | 106 | { |
107 | .tx_buf = st->tx, | 107 | .tx_buf = st->tx, |
108 | .bits_per_word = 8, | 108 | .bits_per_word = 8, |
109 | .len = 2, | 109 | .len = 2, |
110 | .cs_change = 1, | 110 | .cs_change = 1, |
111 | .delay_usecs = 20, | 111 | .delay_usecs = 20, |
112 | }, { | 112 | }, { |
113 | .rx_buf = st->rx, | 113 | .rx_buf = st->rx, |
114 | .bits_per_word = 8, | 114 | .bits_per_word = 8, |
115 | .len = 2, | 115 | .len = 2, |
116 | .delay_usecs = 20, | 116 | .delay_usecs = 20, |
117 | }, | 117 | }, |
118 | }; | 118 | }; |
119 | 119 | ||
120 | mutex_lock(&st->buf_lock); | 120 | mutex_lock(&st->buf_lock); |
121 | st->tx[0] = ADIS16203_READ_REG(lower_reg_address); | 121 | st->tx[0] = ADIS16203_READ_REG(lower_reg_address); |
122 | st->tx[1] = 0; | 122 | st->tx[1] = 0; |
123 | 123 | ||
124 | spi_message_init(&msg); | 124 | spi_message_init(&msg); |
125 | spi_message_add_tail(&xfers[0], &msg); | 125 | spi_message_add_tail(&xfers[0], &msg); |
126 | spi_message_add_tail(&xfers[1], &msg); | 126 | spi_message_add_tail(&xfers[1], &msg); |
127 | ret = spi_sync(st->us, &msg); | 127 | ret = spi_sync(st->us, &msg); |
128 | if (ret) { | 128 | if (ret) { |
129 | dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", | 129 | dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", |
130 | lower_reg_address); | 130 | lower_reg_address); |
131 | goto error_ret; | 131 | goto error_ret; |
132 | } | 132 | } |
133 | *val = (st->rx[0] << 8) | st->rx[1]; | 133 | *val = (st->rx[0] << 8) | st->rx[1]; |
134 | 134 | ||
135 | error_ret: | 135 | error_ret: |
136 | mutex_unlock(&st->buf_lock); | 136 | mutex_unlock(&st->buf_lock); |
137 | return ret; | 137 | return ret; |
138 | } | 138 | } |
139 | 139 | ||
140 | static int adis16203_check_status(struct iio_dev *indio_dev) | 140 | static int adis16203_check_status(struct iio_dev *indio_dev) |
141 | { | 141 | { |
142 | u16 status; | 142 | u16 status; |
143 | int ret; | 143 | int ret; |
144 | 144 | ||
145 | ret = adis16203_spi_read_reg_16(indio_dev, | 145 | ret = adis16203_spi_read_reg_16(indio_dev, |
146 | ADIS16203_DIAG_STAT, | 146 | ADIS16203_DIAG_STAT, |
147 | &status); | 147 | &status); |
148 | if (ret < 0) { | 148 | if (ret < 0) { |
149 | dev_err(&indio_dev->dev, "Reading status failed\n"); | 149 | dev_err(&indio_dev->dev, "Reading status failed\n"); |
150 | goto error_ret; | 150 | goto error_ret; |
151 | } | 151 | } |
152 | ret = status & 0x1F; | 152 | ret = status & 0x1F; |
153 | 153 | ||
154 | if (status & ADIS16203_DIAG_STAT_SELFTEST_FAIL) | 154 | if (status & ADIS16203_DIAG_STAT_SELFTEST_FAIL) |
155 | dev_err(&indio_dev->dev, "Self test failure\n"); | 155 | dev_err(&indio_dev->dev, "Self test failure\n"); |
156 | if (status & ADIS16203_DIAG_STAT_SPI_FAIL) | 156 | if (status & ADIS16203_DIAG_STAT_SPI_FAIL) |
157 | dev_err(&indio_dev->dev, "SPI failure\n"); | 157 | dev_err(&indio_dev->dev, "SPI failure\n"); |
158 | if (status & ADIS16203_DIAG_STAT_FLASH_UPT) | 158 | if (status & ADIS16203_DIAG_STAT_FLASH_UPT) |
159 | dev_err(&indio_dev->dev, "Flash update failed\n"); | 159 | dev_err(&indio_dev->dev, "Flash update failed\n"); |
160 | if (status & ADIS16203_DIAG_STAT_POWER_HIGH) | 160 | if (status & ADIS16203_DIAG_STAT_POWER_HIGH) |
161 | dev_err(&indio_dev->dev, "Power supply above 3.625V\n"); | 161 | dev_err(&indio_dev->dev, "Power supply above 3.625V\n"); |
162 | if (status & ADIS16203_DIAG_STAT_POWER_LOW) | 162 | if (status & ADIS16203_DIAG_STAT_POWER_LOW) |
163 | dev_err(&indio_dev->dev, "Power supply below 3.15V\n"); | 163 | dev_err(&indio_dev->dev, "Power supply below 3.15V\n"); |
164 | 164 | ||
165 | error_ret: | 165 | error_ret: |
166 | return ret; | 166 | return ret; |
167 | } | 167 | } |
168 | 168 | ||
169 | static int adis16203_reset(struct iio_dev *indio_dev) | 169 | static int adis16203_reset(struct iio_dev *indio_dev) |
170 | { | 170 | { |
171 | int ret; | 171 | int ret; |
172 | ret = adis16203_spi_write_reg_8(indio_dev, | 172 | ret = adis16203_spi_write_reg_8(indio_dev, |
173 | ADIS16203_GLOB_CMD, | 173 | ADIS16203_GLOB_CMD, |
174 | ADIS16203_GLOB_CMD_SW_RESET); | 174 | ADIS16203_GLOB_CMD_SW_RESET); |
175 | if (ret) | 175 | if (ret) |
176 | dev_err(&indio_dev->dev, "problem resetting device"); | 176 | dev_err(&indio_dev->dev, "problem resetting device"); |
177 | 177 | ||
178 | return ret; | 178 | return ret; |
179 | } | 179 | } |
180 | 180 | ||
181 | static ssize_t adis16203_write_reset(struct device *dev, | ||
182 | struct device_attribute *attr, | ||
183 | const char *buf, size_t len) | ||
184 | { | ||
185 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
186 | if (len < 1) | ||
187 | return -EINVAL; | ||
188 | switch (buf[0]) { | ||
189 | case '1': | ||
190 | case 'y': | ||
191 | case 'Y': | ||
192 | return adis16203_reset(indio_dev); | ||
193 | } | ||
194 | return -EINVAL; | ||
195 | } | ||
196 | |||
197 | int adis16203_set_irq(struct iio_dev *indio_dev, bool enable) | 181 | int adis16203_set_irq(struct iio_dev *indio_dev, bool enable) |
198 | { | 182 | { |
199 | int ret = 0; | 183 | int ret = 0; |
200 | u16 msc; | 184 | u16 msc; |
201 | 185 | ||
202 | ret = adis16203_spi_read_reg_16(indio_dev, ADIS16203_MSC_CTRL, &msc); | 186 | ret = adis16203_spi_read_reg_16(indio_dev, ADIS16203_MSC_CTRL, &msc); |
203 | if (ret) | 187 | if (ret) |
204 | goto error_ret; | 188 | goto error_ret; |
205 | 189 | ||
206 | msc |= ADIS16203_MSC_CTRL_ACTIVE_HIGH; | 190 | msc |= ADIS16203_MSC_CTRL_ACTIVE_HIGH; |
207 | msc &= ~ADIS16203_MSC_CTRL_DATA_RDY_DIO1; | 191 | msc &= ~ADIS16203_MSC_CTRL_DATA_RDY_DIO1; |
208 | if (enable) | 192 | if (enable) |
209 | msc |= ADIS16203_MSC_CTRL_DATA_RDY_EN; | 193 | msc |= ADIS16203_MSC_CTRL_DATA_RDY_EN; |
210 | else | 194 | else |
211 | msc &= ~ADIS16203_MSC_CTRL_DATA_RDY_EN; | 195 | msc &= ~ADIS16203_MSC_CTRL_DATA_RDY_EN; |
212 | 196 | ||
213 | ret = adis16203_spi_write_reg_16(indio_dev, ADIS16203_MSC_CTRL, msc); | 197 | ret = adis16203_spi_write_reg_16(indio_dev, ADIS16203_MSC_CTRL, msc); |
214 | 198 | ||
215 | error_ret: | 199 | error_ret: |
216 | return ret; | 200 | return ret; |
217 | } | 201 | } |
218 | 202 | ||
219 | static int adis16203_self_test(struct iio_dev *indio_dev) | 203 | static int adis16203_self_test(struct iio_dev *indio_dev) |
220 | { | 204 | { |
221 | int ret; | 205 | int ret; |
222 | ret = adis16203_spi_write_reg_16(indio_dev, | 206 | ret = adis16203_spi_write_reg_16(indio_dev, |
223 | ADIS16203_MSC_CTRL, | 207 | ADIS16203_MSC_CTRL, |
224 | ADIS16203_MSC_CTRL_SELF_TEST_EN); | 208 | ADIS16203_MSC_CTRL_SELF_TEST_EN); |
225 | if (ret) { | 209 | if (ret) { |
226 | dev_err(&indio_dev->dev, "problem starting self test"); | 210 | dev_err(&indio_dev->dev, "problem starting self test"); |
227 | goto err_ret; | 211 | goto err_ret; |
228 | } | 212 | } |
229 | 213 | ||
230 | adis16203_check_status(indio_dev); | 214 | adis16203_check_status(indio_dev); |
231 | 215 | ||
232 | err_ret: | 216 | err_ret: |
233 | return ret; | 217 | return ret; |
234 | } | 218 | } |
235 | 219 | ||
236 | static int adis16203_initial_setup(struct iio_dev *indio_dev) | 220 | static int adis16203_initial_setup(struct iio_dev *indio_dev) |
237 | { | 221 | { |
238 | int ret; | 222 | int ret; |
239 | 223 | ||
240 | /* Disable IRQ */ | 224 | /* Disable IRQ */ |
241 | ret = adis16203_set_irq(indio_dev, false); | 225 | ret = adis16203_set_irq(indio_dev, false); |
242 | if (ret) { | 226 | if (ret) { |
243 | dev_err(&indio_dev->dev, "disable irq failed"); | 227 | dev_err(&indio_dev->dev, "disable irq failed"); |
244 | goto err_ret; | 228 | goto err_ret; |
245 | } | 229 | } |
246 | 230 | ||
247 | /* Do self test */ | 231 | /* Do self test */ |
248 | ret = adis16203_self_test(indio_dev); | 232 | ret = adis16203_self_test(indio_dev); |
249 | if (ret) { | 233 | if (ret) { |
250 | dev_err(&indio_dev->dev, "self test failure"); | 234 | dev_err(&indio_dev->dev, "self test failure"); |
251 | goto err_ret; | 235 | goto err_ret; |
252 | } | 236 | } |
253 | 237 | ||
254 | /* Read status register to check the result */ | 238 | /* Read status register to check the result */ |
255 | ret = adis16203_check_status(indio_dev); | 239 | ret = adis16203_check_status(indio_dev); |
256 | if (ret) { | 240 | if (ret) { |
257 | adis16203_reset(indio_dev); | 241 | adis16203_reset(indio_dev); |
258 | dev_err(&indio_dev->dev, "device not playing ball -> reset"); | 242 | dev_err(&indio_dev->dev, "device not playing ball -> reset"); |
259 | msleep(ADIS16203_STARTUP_DELAY); | 243 | msleep(ADIS16203_STARTUP_DELAY); |
260 | ret = adis16203_check_status(indio_dev); | 244 | ret = adis16203_check_status(indio_dev); |
261 | if (ret) { | 245 | if (ret) { |
262 | dev_err(&indio_dev->dev, "giving up"); | 246 | dev_err(&indio_dev->dev, "giving up"); |
263 | goto err_ret; | 247 | goto err_ret; |
264 | } | 248 | } |
265 | } | 249 | } |
266 | 250 | ||
267 | err_ret: | 251 | err_ret: |
268 | return ret; | 252 | return ret; |
269 | } | 253 | } |
270 | 254 | ||
271 | enum adis16203_chan { | 255 | enum adis16203_chan { |
272 | in_supply, | 256 | in_supply, |
273 | in_aux, | 257 | in_aux, |
274 | incli_x, | 258 | incli_x, |
275 | incli_y, | 259 | incli_y, |
276 | temp, | 260 | temp, |
277 | }; | 261 | }; |
278 | 262 | ||
279 | static u8 adis16203_addresses[5][2] = { | 263 | static u8 adis16203_addresses[5][2] = { |
280 | [in_supply] = { ADIS16203_SUPPLY_OUT }, | 264 | [in_supply] = { ADIS16203_SUPPLY_OUT }, |
281 | [in_aux] = { ADIS16203_AUX_ADC }, | 265 | [in_aux] = { ADIS16203_AUX_ADC }, |
282 | [incli_x] = { ADIS16203_XINCL_OUT, ADIS16203_INCL_NULL}, | 266 | [incli_x] = { ADIS16203_XINCL_OUT, ADIS16203_INCL_NULL}, |
283 | [incli_y] = { ADIS16203_YINCL_OUT }, | 267 | [incli_y] = { ADIS16203_YINCL_OUT }, |
284 | [temp] = { ADIS16203_TEMP_OUT } | 268 | [temp] = { ADIS16203_TEMP_OUT } |
285 | }; | 269 | }; |
286 | 270 | ||
287 | static int adis16203_write_raw(struct iio_dev *indio_dev, | 271 | static int adis16203_write_raw(struct iio_dev *indio_dev, |
288 | struct iio_chan_spec const *chan, | 272 | struct iio_chan_spec const *chan, |
289 | int val, | 273 | int val, |
290 | int val2, | 274 | int val2, |
291 | long mask) | 275 | long mask) |
292 | { | 276 | { |
293 | /* currently only one writable parameter which keeps this simple */ | 277 | /* currently only one writable parameter which keeps this simple */ |
294 | u8 addr = adis16203_addresses[chan->address][1]; | 278 | u8 addr = adis16203_addresses[chan->address][1]; |
295 | return adis16203_spi_write_reg_16(indio_dev, addr, val & 0x3FFF); | 279 | return adis16203_spi_write_reg_16(indio_dev, addr, val & 0x3FFF); |
296 | } | 280 | } |
297 | 281 | ||
298 | static int adis16203_read_raw(struct iio_dev *indio_dev, | 282 | static int adis16203_read_raw(struct iio_dev *indio_dev, |
299 | struct iio_chan_spec const *chan, | 283 | struct iio_chan_spec const *chan, |
300 | int *val, int *val2, | 284 | int *val, int *val2, |
301 | long mask) | 285 | long mask) |
302 | { | 286 | { |
303 | int ret; | 287 | int ret; |
304 | int bits; | 288 | int bits; |
305 | u8 addr; | 289 | u8 addr; |
306 | s16 val16; | 290 | s16 val16; |
307 | switch (mask) { | 291 | switch (mask) { |
308 | case IIO_CHAN_INFO_RAW: | 292 | case IIO_CHAN_INFO_RAW: |
309 | mutex_lock(&indio_dev->mlock); | 293 | mutex_lock(&indio_dev->mlock); |
310 | addr = adis16203_addresses[chan->address][0]; | 294 | addr = adis16203_addresses[chan->address][0]; |
311 | ret = adis16203_spi_read_reg_16(indio_dev, addr, &val16); | 295 | ret = adis16203_spi_read_reg_16(indio_dev, addr, &val16); |
312 | if (ret) { | 296 | if (ret) { |
313 | mutex_unlock(&indio_dev->mlock); | 297 | mutex_unlock(&indio_dev->mlock); |
314 | return ret; | 298 | return ret; |
315 | } | 299 | } |
316 | 300 | ||
317 | if (val16 & ADIS16203_ERROR_ACTIVE) { | 301 | if (val16 & ADIS16203_ERROR_ACTIVE) { |
318 | ret = adis16203_check_status(indio_dev); | 302 | ret = adis16203_check_status(indio_dev); |
319 | if (ret) { | 303 | if (ret) { |
320 | mutex_unlock(&indio_dev->mlock); | 304 | mutex_unlock(&indio_dev->mlock); |
321 | return ret; | 305 | return ret; |
322 | } | 306 | } |
323 | } | 307 | } |
324 | val16 = val16 & ((1 << chan->scan_type.realbits) - 1); | 308 | val16 = val16 & ((1 << chan->scan_type.realbits) - 1); |
325 | if (chan->scan_type.sign == 's') | 309 | if (chan->scan_type.sign == 's') |
326 | val16 = (s16)(val16 << | 310 | val16 = (s16)(val16 << |
327 | (16 - chan->scan_type.realbits)) >> | 311 | (16 - chan->scan_type.realbits)) >> |
328 | (16 - chan->scan_type.realbits); | 312 | (16 - chan->scan_type.realbits); |
329 | *val = val16; | 313 | *val = val16; |
330 | mutex_unlock(&indio_dev->mlock); | 314 | mutex_unlock(&indio_dev->mlock); |
331 | return IIO_VAL_INT; | 315 | return IIO_VAL_INT; |
332 | case IIO_CHAN_INFO_SCALE: | 316 | case IIO_CHAN_INFO_SCALE: |
333 | switch (chan->type) { | 317 | switch (chan->type) { |
334 | case IIO_VOLTAGE: | 318 | case IIO_VOLTAGE: |
335 | *val = 0; | 319 | *val = 0; |
336 | if (chan->channel == 0) | 320 | if (chan->channel == 0) |
337 | *val2 = 1220; | 321 | *val2 = 1220; |
338 | else | 322 | else |
339 | *val2 = 610; | 323 | *val2 = 610; |
340 | return IIO_VAL_INT_PLUS_MICRO; | 324 | return IIO_VAL_INT_PLUS_MICRO; |
341 | case IIO_TEMP: | 325 | case IIO_TEMP: |
342 | *val = 0; | 326 | *val = 0; |
343 | *val2 = -470000; | 327 | *val2 = -470000; |
344 | return IIO_VAL_INT_PLUS_MICRO; | 328 | return IIO_VAL_INT_PLUS_MICRO; |
345 | case IIO_INCLI: | 329 | case IIO_INCLI: |
346 | *val = 0; | 330 | *val = 0; |
347 | *val2 = 25000; | 331 | *val2 = 25000; |
348 | return IIO_VAL_INT_PLUS_MICRO; | 332 | return IIO_VAL_INT_PLUS_MICRO; |
349 | default: | 333 | default: |
350 | return -EINVAL; | 334 | return -EINVAL; |
351 | } | 335 | } |
352 | case IIO_CHAN_INFO_OFFSET: | 336 | case IIO_CHAN_INFO_OFFSET: |
353 | *val = 25; | 337 | *val = 25; |
354 | return IIO_VAL_INT; | 338 | return IIO_VAL_INT; |
355 | case IIO_CHAN_INFO_CALIBBIAS: | 339 | case IIO_CHAN_INFO_CALIBBIAS: |
356 | bits = 14; | 340 | bits = 14; |
357 | mutex_lock(&indio_dev->mlock); | 341 | mutex_lock(&indio_dev->mlock); |
358 | addr = adis16203_addresses[chan->address][1]; | 342 | addr = adis16203_addresses[chan->address][1]; |
359 | ret = adis16203_spi_read_reg_16(indio_dev, addr, &val16); | 343 | ret = adis16203_spi_read_reg_16(indio_dev, addr, &val16); |
360 | if (ret) { | 344 | if (ret) { |
361 | mutex_unlock(&indio_dev->mlock); | 345 | mutex_unlock(&indio_dev->mlock); |
362 | return ret; | 346 | return ret; |
363 | } | 347 | } |
364 | val16 &= (1 << bits) - 1; | 348 | val16 &= (1 << bits) - 1; |
365 | val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); | 349 | val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); |
366 | *val = val16; | 350 | *val = val16; |
367 | mutex_unlock(&indio_dev->mlock); | 351 | mutex_unlock(&indio_dev->mlock); |
368 | return IIO_VAL_INT; | 352 | return IIO_VAL_INT; |
369 | default: | 353 | default: |
370 | return -EINVAL; | 354 | return -EINVAL; |
371 | } | 355 | } |
372 | } | 356 | } |
373 | 357 | ||
374 | static struct iio_chan_spec adis16203_channels[] = { | 358 | static struct iio_chan_spec adis16203_channels[] = { |
375 | { | 359 | { |
376 | .type = IIO_VOLTAGE, | 360 | .type = IIO_VOLTAGE, |
377 | .indexed = 1, | 361 | .indexed = 1, |
378 | .channel = 0, | 362 | .channel = 0, |
379 | .extend_name = "supply", | 363 | .extend_name = "supply", |
380 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 364 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
381 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 365 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
382 | .address = in_supply, | 366 | .address = in_supply, |
383 | .scan_index = ADIS16203_SCAN_SUPPLY, | 367 | .scan_index = ADIS16203_SCAN_SUPPLY, |
384 | .scan_type = { | 368 | .scan_type = { |
385 | .sign = 'u', | 369 | .sign = 'u', |
386 | .realbits = 12, | 370 | .realbits = 12, |
387 | .storagebits = 16, | 371 | .storagebits = 16, |
388 | }, | 372 | }, |
389 | }, { | 373 | }, { |
390 | .type = IIO_VOLTAGE, | 374 | .type = IIO_VOLTAGE, |
391 | .indexed = 1, | 375 | .indexed = 1, |
392 | .channel = 1, | 376 | .channel = 1, |
393 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 377 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
394 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 378 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
395 | .address = in_aux, | 379 | .address = in_aux, |
396 | .scan_index = ADIS16203_SCAN_AUX_ADC, | 380 | .scan_index = ADIS16203_SCAN_AUX_ADC, |
397 | .scan_type = { | 381 | .scan_type = { |
398 | .sign = 'u', | 382 | .sign = 'u', |
399 | .realbits = 12, | 383 | .realbits = 12, |
400 | .storagebits = 16, | 384 | .storagebits = 16, |
401 | }, | 385 | }, |
402 | }, { | 386 | }, { |
403 | .type = IIO_INCLI, | 387 | .type = IIO_INCLI, |
404 | .modified = 1, | 388 | .modified = 1, |
405 | .channel2 = IIO_MOD_X, | 389 | .channel2 = IIO_MOD_X, |
406 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 390 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
407 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 391 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
408 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, | 392 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, |
409 | .address = incli_x, | 393 | .address = incli_x, |
410 | .scan_index = ADIS16203_SCAN_INCLI_X, | 394 | .scan_index = ADIS16203_SCAN_INCLI_X, |
411 | .scan_type = { | 395 | .scan_type = { |
412 | .sign = 's', | 396 | .sign = 's', |
413 | .realbits = 14, | 397 | .realbits = 14, |
414 | .storagebits = 16, | 398 | .storagebits = 16, |
415 | }, | 399 | }, |
416 | }, { /* Fixme: Not what it appears to be - see data sheet */ | 400 | }, { /* Fixme: Not what it appears to be - see data sheet */ |
417 | .type = IIO_INCLI, | 401 | .type = IIO_INCLI, |
418 | .modified = 1, | 402 | .modified = 1, |
419 | .channel2 = IIO_MOD_Y, | 403 | .channel2 = IIO_MOD_Y, |
420 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 404 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
421 | IIO_CHAN_INFO_SCALE_SHARED_BIT, | 405 | IIO_CHAN_INFO_SCALE_SHARED_BIT, |
422 | .address = incli_y, | 406 | .address = incli_y, |
423 | .scan_index = ADIS16203_SCAN_INCLI_Y, | 407 | .scan_index = ADIS16203_SCAN_INCLI_Y, |
424 | .scan_type = { | 408 | .scan_type = { |
425 | .sign = 's', | 409 | .sign = 's', |
426 | .realbits = 14, | 410 | .realbits = 14, |
427 | .storagebits = 16, | 411 | .storagebits = 16, |
428 | }, | 412 | }, |
429 | }, { | 413 | }, { |
430 | .type = IIO_TEMP, | 414 | .type = IIO_TEMP, |
431 | .indexed = 1, | 415 | .indexed = 1, |
432 | .channel = 0, | 416 | .channel = 0, |
433 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 417 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
434 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | | 418 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | |
435 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, | 419 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, |
436 | .address = temp, | 420 | .address = temp, |
437 | .scan_index = ADIS16203_SCAN_TEMP, | 421 | .scan_index = ADIS16203_SCAN_TEMP, |
438 | .scan_type = { | 422 | .scan_type = { |
439 | .sign = 'u', | 423 | .sign = 'u', |
440 | .realbits = 12, | 424 | .realbits = 12, |
441 | .storagebits = 16, | 425 | .storagebits = 16, |
442 | }, | 426 | }, |
443 | }, | 427 | }, |
444 | IIO_CHAN_SOFT_TIMESTAMP(5), | 428 | IIO_CHAN_SOFT_TIMESTAMP(5), |
445 | }; | 429 | }; |
446 | 430 | ||
447 | static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16203_write_reset, 0); | ||
448 | |||
449 | static struct attribute *adis16203_attributes[] = { | ||
450 | &iio_dev_attr_reset.dev_attr.attr, | ||
451 | NULL | ||
452 | }; | ||
453 | |||
454 | static const struct attribute_group adis16203_attribute_group = { | ||
455 | .attrs = adis16203_attributes, | ||
456 | }; | ||
457 | |||
458 | static const struct iio_info adis16203_info = { | 431 | static const struct iio_info adis16203_info = { |
459 | .attrs = &adis16203_attribute_group, | ||
460 | .read_raw = &adis16203_read_raw, | 432 | .read_raw = &adis16203_read_raw, |
461 | .write_raw = &adis16203_write_raw, | 433 | .write_raw = &adis16203_write_raw, |
462 | .driver_module = THIS_MODULE, | 434 | .driver_module = THIS_MODULE, |
463 | }; | 435 | }; |
464 | 436 | ||
465 | static int __devinit adis16203_probe(struct spi_device *spi) | 437 | static int __devinit adis16203_probe(struct spi_device *spi) |
466 | { | 438 | { |
467 | int ret; | 439 | int ret; |
468 | struct iio_dev *indio_dev; | 440 | struct iio_dev *indio_dev; |
469 | struct adis16203_state *st; | 441 | struct adis16203_state *st; |
470 | 442 | ||
471 | /* setup the industrialio driver allocated elements */ | 443 | /* setup the industrialio driver allocated elements */ |
472 | indio_dev = iio_device_alloc(sizeof(*st)); | 444 | indio_dev = iio_device_alloc(sizeof(*st)); |
473 | if (indio_dev == NULL) { | 445 | if (indio_dev == NULL) { |
474 | ret = -ENOMEM; | 446 | ret = -ENOMEM; |
475 | goto error_ret; | 447 | goto error_ret; |
476 | } | 448 | } |
477 | st = iio_priv(indio_dev); | 449 | st = iio_priv(indio_dev); |
478 | /* this is only used for removal purposes */ | 450 | /* this is only used for removal purposes */ |
479 | spi_set_drvdata(spi, indio_dev); | 451 | spi_set_drvdata(spi, indio_dev); |
480 | st->us = spi; | 452 | st->us = spi; |
481 | mutex_init(&st->buf_lock); | 453 | mutex_init(&st->buf_lock); |
482 | 454 | ||
483 | indio_dev->name = spi->dev.driver->name; | 455 | indio_dev->name = spi->dev.driver->name; |
484 | indio_dev->dev.parent = &spi->dev; | 456 | indio_dev->dev.parent = &spi->dev; |
485 | indio_dev->channels = adis16203_channels; | 457 | indio_dev->channels = adis16203_channels; |
486 | indio_dev->num_channels = ARRAY_SIZE(adis16203_channels); | 458 | indio_dev->num_channels = ARRAY_SIZE(adis16203_channels); |
487 | indio_dev->info = &adis16203_info; | 459 | indio_dev->info = &adis16203_info; |
488 | indio_dev->modes = INDIO_DIRECT_MODE; | 460 | indio_dev->modes = INDIO_DIRECT_MODE; |
489 | 461 | ||
490 | ret = adis16203_configure_ring(indio_dev); | 462 | ret = adis16203_configure_ring(indio_dev); |
491 | if (ret) | 463 | if (ret) |
492 | goto error_free_dev; | 464 | goto error_free_dev; |
493 | 465 | ||
494 | ret = iio_buffer_register(indio_dev, | 466 | ret = iio_buffer_register(indio_dev, |
495 | adis16203_channels, | 467 | adis16203_channels, |
496 | ARRAY_SIZE(adis16203_channels)); | 468 | ARRAY_SIZE(adis16203_channels)); |
497 | if (ret) { | 469 | if (ret) { |
498 | printk(KERN_ERR "failed to initialize the ring\n"); | 470 | printk(KERN_ERR "failed to initialize the ring\n"); |
499 | goto error_unreg_ring_funcs; | 471 | goto error_unreg_ring_funcs; |
500 | } | 472 | } |
501 | 473 | ||
502 | if (spi->irq) { | 474 | if (spi->irq) { |
503 | ret = adis16203_probe_trigger(indio_dev); | 475 | ret = adis16203_probe_trigger(indio_dev); |
504 | if (ret) | 476 | if (ret) |
505 | goto error_uninitialize_ring; | 477 | goto error_uninitialize_ring; |
506 | } | 478 | } |
507 | 479 | ||
508 | /* Get the device into a sane initial state */ | 480 | /* Get the device into a sane initial state */ |
509 | ret = adis16203_initial_setup(indio_dev); | 481 | ret = adis16203_initial_setup(indio_dev); |
510 | if (ret) | 482 | if (ret) |
511 | goto error_remove_trigger; | 483 | goto error_remove_trigger; |
512 | 484 | ||
513 | ret = iio_device_register(indio_dev); | 485 | ret = iio_device_register(indio_dev); |
514 | if (ret) | 486 | if (ret) |
515 | goto error_remove_trigger; | 487 | goto error_remove_trigger; |
516 | 488 | ||
517 | return 0; | 489 | return 0; |
518 | 490 | ||
519 | error_remove_trigger: | 491 | error_remove_trigger: |
520 | adis16203_remove_trigger(indio_dev); | 492 | adis16203_remove_trigger(indio_dev); |
521 | error_uninitialize_ring: | 493 | error_uninitialize_ring: |
522 | iio_buffer_unregister(indio_dev); | 494 | iio_buffer_unregister(indio_dev); |
523 | error_unreg_ring_funcs: | 495 | error_unreg_ring_funcs: |
524 | adis16203_unconfigure_ring(indio_dev); | 496 | adis16203_unconfigure_ring(indio_dev); |
525 | error_free_dev: | 497 | error_free_dev: |
526 | iio_device_free(indio_dev); | 498 | iio_device_free(indio_dev); |
527 | error_ret: | 499 | error_ret: |
528 | return ret; | 500 | return ret; |
529 | } | 501 | } |
530 | 502 | ||
531 | static int adis16203_remove(struct spi_device *spi) | 503 | static int adis16203_remove(struct spi_device *spi) |
532 | { | 504 | { |
533 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | 505 | struct iio_dev *indio_dev = spi_get_drvdata(spi); |
534 | 506 | ||
535 | iio_device_unregister(indio_dev); | 507 | iio_device_unregister(indio_dev); |
536 | adis16203_remove_trigger(indio_dev); | 508 | adis16203_remove_trigger(indio_dev); |
537 | iio_buffer_unregister(indio_dev); | 509 | iio_buffer_unregister(indio_dev); |
538 | adis16203_unconfigure_ring(indio_dev); | 510 | adis16203_unconfigure_ring(indio_dev); |
539 | iio_device_free(indio_dev); | 511 | iio_device_free(indio_dev); |
540 | 512 | ||
541 | return 0; | 513 | return 0; |
542 | } | 514 | } |
543 | 515 | ||
544 | static struct spi_driver adis16203_driver = { | 516 | static struct spi_driver adis16203_driver = { |
545 | .driver = { | 517 | .driver = { |
546 | .name = "adis16203", | 518 | .name = "adis16203", |
547 | .owner = THIS_MODULE, | 519 | .owner = THIS_MODULE, |
548 | }, | 520 | }, |
549 | .probe = adis16203_probe, | 521 | .probe = adis16203_probe, |
550 | .remove = __devexit_p(adis16203_remove), | 522 | .remove = __devexit_p(adis16203_remove), |
551 | }; | 523 | }; |
552 | module_spi_driver(adis16203_driver); | 524 | module_spi_driver(adis16203_driver); |
553 | 525 | ||
554 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | 526 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); |
555 | MODULE_DESCRIPTION("Analog Devices ADIS16203 Programmable Digital Vibration Sensor driver"); | 527 | MODULE_DESCRIPTION("Analog Devices ADIS16203 Programmable Digital Vibration Sensor driver"); |
556 | MODULE_LICENSE("GPL v2"); | 528 | MODULE_LICENSE("GPL v2"); |
557 | MODULE_ALIAS("spi:adis16203"); | 529 | MODULE_ALIAS("spi:adis16203"); |
558 | 530 |
drivers/staging/iio/accel/adis16204_core.c
1 | /* | 1 | /* |
2 | * ADIS16204 Programmable High-g Digital Impact Sensor and Recorder | 2 | * ADIS16204 Programmable High-g Digital Impact Sensor and Recorder |
3 | * | 3 | * |
4 | * Copyright 2010 Analog Devices Inc. | 4 | * Copyright 2010 Analog Devices Inc. |
5 | * | 5 | * |
6 | * Licensed under the GPL-2 or later. | 6 | * Licensed under the GPL-2 or later. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/interrupt.h> | 9 | #include <linux/interrupt.h> |
10 | #include <linux/irq.h> | 10 | #include <linux/irq.h> |
11 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
12 | #include <linux/mutex.h> | 12 | #include <linux/mutex.h> |
13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/spi/spi.h> | 15 | #include <linux/spi/spi.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/sysfs.h> | 17 | #include <linux/sysfs.h> |
18 | #include <linux/list.h> | 18 | #include <linux/list.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | 20 | ||
21 | #include <linux/iio/iio.h> | 21 | #include <linux/iio/iio.h> |
22 | #include <linux/iio/sysfs.h> | 22 | #include <linux/iio/sysfs.h> |
23 | #include <linux/iio/buffer.h> | 23 | #include <linux/iio/buffer.h> |
24 | 24 | ||
25 | #include "adis16204.h" | 25 | #include "adis16204.h" |
26 | 26 | ||
27 | #define DRIVER_NAME "adis16204" | 27 | #define DRIVER_NAME "adis16204" |
28 | 28 | ||
29 | /** | 29 | /** |
30 | * adis16204_spi_write_reg_8() - write single byte to a register | 30 | * adis16204_spi_write_reg_8() - write single byte to a register |
31 | * @dev: device associated with child of actual device (iio_dev or iio_trig) | 31 | * @dev: device associated with child of actual device (iio_dev or iio_trig) |
32 | * @reg_address: the address of the register to be written | 32 | * @reg_address: the address of the register to be written |
33 | * @val: the value to write | 33 | * @val: the value to write |
34 | **/ | 34 | **/ |
35 | static int adis16204_spi_write_reg_8(struct iio_dev *indio_dev, | 35 | static int adis16204_spi_write_reg_8(struct iio_dev *indio_dev, |
36 | u8 reg_address, | 36 | u8 reg_address, |
37 | u8 val) | 37 | u8 val) |
38 | { | 38 | { |
39 | int ret; | 39 | int ret; |
40 | struct adis16204_state *st = iio_priv(indio_dev); | 40 | struct adis16204_state *st = iio_priv(indio_dev); |
41 | 41 | ||
42 | mutex_lock(&st->buf_lock); | 42 | mutex_lock(&st->buf_lock); |
43 | st->tx[0] = ADIS16204_WRITE_REG(reg_address); | 43 | st->tx[0] = ADIS16204_WRITE_REG(reg_address); |
44 | st->tx[1] = val; | 44 | st->tx[1] = val; |
45 | 45 | ||
46 | ret = spi_write(st->us, st->tx, 2); | 46 | ret = spi_write(st->us, st->tx, 2); |
47 | mutex_unlock(&st->buf_lock); | 47 | mutex_unlock(&st->buf_lock); |
48 | 48 | ||
49 | return ret; | 49 | return ret; |
50 | } | 50 | } |
51 | 51 | ||
52 | /** | 52 | /** |
53 | * adis16204_spi_write_reg_16() - write 2 bytes to a pair of registers | 53 | * adis16204_spi_write_reg_16() - write 2 bytes to a pair of registers |
54 | * @indio_dev: iio device associated with child of actual device | 54 | * @indio_dev: iio device associated with child of actual device |
55 | * @reg_address: the address of the lower of the two registers. Second register | 55 | * @reg_address: the address of the lower of the two registers. Second register |
56 | * is assumed to have address one greater. | 56 | * is assumed to have address one greater. |
57 | * @val: value to be written | 57 | * @val: value to be written |
58 | **/ | 58 | **/ |
59 | static int adis16204_spi_write_reg_16(struct iio_dev *indio_dev, | 59 | static int adis16204_spi_write_reg_16(struct iio_dev *indio_dev, |
60 | u8 lower_reg_address, | 60 | u8 lower_reg_address, |
61 | u16 value) | 61 | u16 value) |
62 | { | 62 | { |
63 | int ret; | 63 | int ret; |
64 | struct spi_message msg; | 64 | struct spi_message msg; |
65 | struct adis16204_state *st = iio_priv(indio_dev); | 65 | struct adis16204_state *st = iio_priv(indio_dev); |
66 | struct spi_transfer xfers[] = { | 66 | struct spi_transfer xfers[] = { |
67 | { | 67 | { |
68 | .tx_buf = st->tx, | 68 | .tx_buf = st->tx, |
69 | .bits_per_word = 8, | 69 | .bits_per_word = 8, |
70 | .len = 2, | 70 | .len = 2, |
71 | .cs_change = 1, | 71 | .cs_change = 1, |
72 | }, { | 72 | }, { |
73 | .tx_buf = st->tx + 2, | 73 | .tx_buf = st->tx + 2, |
74 | .bits_per_word = 8, | 74 | .bits_per_word = 8, |
75 | .len = 2, | 75 | .len = 2, |
76 | .cs_change = 1, | 76 | .cs_change = 1, |
77 | }, | 77 | }, |
78 | }; | 78 | }; |
79 | 79 | ||
80 | mutex_lock(&st->buf_lock); | 80 | mutex_lock(&st->buf_lock); |
81 | st->tx[0] = ADIS16204_WRITE_REG(lower_reg_address); | 81 | st->tx[0] = ADIS16204_WRITE_REG(lower_reg_address); |
82 | st->tx[1] = value & 0xFF; | 82 | st->tx[1] = value & 0xFF; |
83 | st->tx[2] = ADIS16204_WRITE_REG(lower_reg_address + 1); | 83 | st->tx[2] = ADIS16204_WRITE_REG(lower_reg_address + 1); |
84 | st->tx[3] = (value >> 8) & 0xFF; | 84 | st->tx[3] = (value >> 8) & 0xFF; |
85 | 85 | ||
86 | spi_message_init(&msg); | 86 | spi_message_init(&msg); |
87 | spi_message_add_tail(&xfers[0], &msg); | 87 | spi_message_add_tail(&xfers[0], &msg); |
88 | spi_message_add_tail(&xfers[1], &msg); | 88 | spi_message_add_tail(&xfers[1], &msg); |
89 | ret = spi_sync(st->us, &msg); | 89 | ret = spi_sync(st->us, &msg); |
90 | mutex_unlock(&st->buf_lock); | 90 | mutex_unlock(&st->buf_lock); |
91 | 91 | ||
92 | return ret; | 92 | return ret; |
93 | } | 93 | } |
94 | 94 | ||
95 | /** | 95 | /** |
96 | * adis16204_spi_read_reg_16() - read 2 bytes from a 16-bit register | 96 | * adis16204_spi_read_reg_16() - read 2 bytes from a 16-bit register |
97 | * @indio_dev: iio device associated with child of actual device | 97 | * @indio_dev: iio device associated with child of actual device |
98 | * @reg_address: the address of the lower of the two registers. Second register | 98 | * @reg_address: the address of the lower of the two registers. Second register |
99 | * is assumed to have address one greater. | 99 | * is assumed to have address one greater. |
100 | * @val: somewhere to pass back the value read | 100 | * @val: somewhere to pass back the value read |
101 | **/ | 101 | **/ |
102 | static int adis16204_spi_read_reg_16(struct iio_dev *indio_dev, | 102 | static int adis16204_spi_read_reg_16(struct iio_dev *indio_dev, |
103 | u8 lower_reg_address, | 103 | u8 lower_reg_address, |
104 | u16 *val) | 104 | u16 *val) |
105 | { | 105 | { |
106 | struct spi_message msg; | 106 | struct spi_message msg; |
107 | struct adis16204_state *st = iio_priv(indio_dev); | 107 | struct adis16204_state *st = iio_priv(indio_dev); |
108 | int ret; | 108 | int ret; |
109 | struct spi_transfer xfers[] = { | 109 | struct spi_transfer xfers[] = { |
110 | { | 110 | { |
111 | .tx_buf = st->tx, | 111 | .tx_buf = st->tx, |
112 | .bits_per_word = 8, | 112 | .bits_per_word = 8, |
113 | .len = 2, | 113 | .len = 2, |
114 | .cs_change = 1, | 114 | .cs_change = 1, |
115 | .delay_usecs = 20, | 115 | .delay_usecs = 20, |
116 | }, { | 116 | }, { |
117 | .rx_buf = st->rx, | 117 | .rx_buf = st->rx, |
118 | .bits_per_word = 8, | 118 | .bits_per_word = 8, |
119 | .len = 2, | 119 | .len = 2, |
120 | .delay_usecs = 20, | 120 | .delay_usecs = 20, |
121 | }, | 121 | }, |
122 | }; | 122 | }; |
123 | 123 | ||
124 | mutex_lock(&st->buf_lock); | 124 | mutex_lock(&st->buf_lock); |
125 | st->tx[0] = ADIS16204_READ_REG(lower_reg_address); | 125 | st->tx[0] = ADIS16204_READ_REG(lower_reg_address); |
126 | st->tx[1] = 0; | 126 | st->tx[1] = 0; |
127 | 127 | ||
128 | spi_message_init(&msg); | 128 | spi_message_init(&msg); |
129 | spi_message_add_tail(&xfers[0], &msg); | 129 | spi_message_add_tail(&xfers[0], &msg); |
130 | spi_message_add_tail(&xfers[1], &msg); | 130 | spi_message_add_tail(&xfers[1], &msg); |
131 | ret = spi_sync(st->us, &msg); | 131 | ret = spi_sync(st->us, &msg); |
132 | if (ret) { | 132 | if (ret) { |
133 | dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", | 133 | dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X", |
134 | lower_reg_address); | 134 | lower_reg_address); |
135 | goto error_ret; | 135 | goto error_ret; |
136 | } | 136 | } |
137 | *val = (st->rx[0] << 8) | st->rx[1]; | 137 | *val = (st->rx[0] << 8) | st->rx[1]; |
138 | 138 | ||
139 | error_ret: | 139 | error_ret: |
140 | mutex_unlock(&st->buf_lock); | 140 | mutex_unlock(&st->buf_lock); |
141 | return ret; | 141 | return ret; |
142 | } | 142 | } |
143 | 143 | ||
144 | static int adis16204_check_status(struct iio_dev *indio_dev) | 144 | static int adis16204_check_status(struct iio_dev *indio_dev) |
145 | { | 145 | { |
146 | u16 status; | 146 | u16 status; |
147 | int ret; | 147 | int ret; |
148 | 148 | ||
149 | ret = adis16204_spi_read_reg_16(indio_dev, | 149 | ret = adis16204_spi_read_reg_16(indio_dev, |
150 | ADIS16204_DIAG_STAT, &status); | 150 | ADIS16204_DIAG_STAT, &status); |
151 | if (ret < 0) { | 151 | if (ret < 0) { |
152 | dev_err(&indio_dev->dev, "Reading status failed\n"); | 152 | dev_err(&indio_dev->dev, "Reading status failed\n"); |
153 | goto error_ret; | 153 | goto error_ret; |
154 | } | 154 | } |
155 | ret = status & 0x1F; | 155 | ret = status & 0x1F; |
156 | 156 | ||
157 | if (status & ADIS16204_DIAG_STAT_SELFTEST_FAIL) | 157 | if (status & ADIS16204_DIAG_STAT_SELFTEST_FAIL) |
158 | dev_err(&indio_dev->dev, "Self test failure\n"); | 158 | dev_err(&indio_dev->dev, "Self test failure\n"); |
159 | if (status & ADIS16204_DIAG_STAT_SPI_FAIL) | 159 | if (status & ADIS16204_DIAG_STAT_SPI_FAIL) |
160 | dev_err(&indio_dev->dev, "SPI failure\n"); | 160 | dev_err(&indio_dev->dev, "SPI failure\n"); |
161 | if (status & ADIS16204_DIAG_STAT_FLASH_UPT) | 161 | if (status & ADIS16204_DIAG_STAT_FLASH_UPT) |
162 | dev_err(&indio_dev->dev, "Flash update failed\n"); | 162 | dev_err(&indio_dev->dev, "Flash update failed\n"); |
163 | if (status & ADIS16204_DIAG_STAT_POWER_HIGH) | 163 | if (status & ADIS16204_DIAG_STAT_POWER_HIGH) |
164 | dev_err(&indio_dev->dev, "Power supply above 3.625V\n"); | 164 | dev_err(&indio_dev->dev, "Power supply above 3.625V\n"); |
165 | if (status & ADIS16204_DIAG_STAT_POWER_LOW) | 165 | if (status & ADIS16204_DIAG_STAT_POWER_LOW) |
166 | dev_err(&indio_dev->dev, "Power supply below 2.975V\n"); | 166 | dev_err(&indio_dev->dev, "Power supply below 2.975V\n"); |
167 | 167 | ||
168 | error_ret: | 168 | error_ret: |
169 | return ret; | 169 | return ret; |
170 | } | 170 | } |
171 | 171 | ||
172 | static ssize_t adis16204_read_14bit_signed(struct device *dev, | ||
173 | struct device_attribute *attr, | ||
174 | char *buf) | ||
175 | { | ||
176 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
177 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
178 | s16 val = 0; | ||
179 | ssize_t ret; | ||
180 | |||
181 | mutex_lock(&indio_dev->mlock); | ||
182 | |||
183 | ret = adis16204_spi_read_reg_16(indio_dev, | ||
184 | this_attr->address, (u16 *)&val); | ||
185 | if (!ret) { | ||
186 | if (val & ADIS16204_ERROR_ACTIVE) | ||
187 | adis16204_check_status(indio_dev); | ||
188 | |||
189 | val = ((s16)(val << 2) >> 2); | ||
190 | ret = sprintf(buf, "%d\n", val); | ||
191 | } | ||
192 | |||
193 | mutex_unlock(&indio_dev->mlock); | ||
194 | |||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | static int adis16204_reset(struct iio_dev *indio_dev) | 172 | static int adis16204_reset(struct iio_dev *indio_dev) |
199 | { | 173 | { |
200 | int ret; | 174 | int ret; |
201 | ret = adis16204_spi_write_reg_8(indio_dev, | 175 | ret = adis16204_spi_write_reg_8(indio_dev, |
202 | ADIS16204_GLOB_CMD, | 176 | ADIS16204_GLOB_CMD, |
203 | ADIS16204_GLOB_CMD_SW_RESET); | 177 | ADIS16204_GLOB_CMD_SW_RESET); |
204 | if (ret) | 178 | if (ret) |
205 | dev_err(&indio_dev->dev, "problem resetting device"); | 179 | dev_err(&indio_dev->dev, "problem resetting device"); |
206 | 180 | ||
207 | return ret; | 181 | return ret; |
208 | } | 182 | } |
209 | 183 | ||
210 | static ssize_t adis16204_write_reset(struct device *dev, | ||
211 | struct device_attribute *attr, | ||
212 | const char *buf, size_t len) | ||
213 | { | ||
214 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
215 | |||
216 | if (len < 1) | ||
217 | return -EINVAL; | ||
218 | switch (buf[0]) { | ||
219 | case '1': | ||
220 | case 'y': | ||
221 | case 'Y': | ||
222 | return adis16204_reset(indio_dev); | ||
223 | } | ||
224 | return -EINVAL; | ||
225 | } | ||
226 | |||
227 | int adis16204_set_irq(struct iio_dev *indio_dev, bool enable) | 184 | int adis16204_set_irq(struct iio_dev *indio_dev, bool enable) |
228 | { | 185 | { |
229 | int ret = 0; | 186 | int ret = 0; |
230 | u16 msc; | 187 | u16 msc; |
231 | 188 | ||
232 | ret = adis16204_spi_read_reg_16(indio_dev, ADIS16204_MSC_CTRL, &msc); | 189 | ret = adis16204_spi_read_reg_16(indio_dev, ADIS16204_MSC_CTRL, &msc); |
233 | if (ret) | 190 | if (ret) |
234 | goto error_ret; | 191 | goto error_ret; |
235 | 192 | ||
236 | msc |= ADIS16204_MSC_CTRL_ACTIVE_HIGH; | 193 | msc |= ADIS16204_MSC_CTRL_ACTIVE_HIGH; |
237 | msc &= ~ADIS16204_MSC_CTRL_DATA_RDY_DIO2; | 194 | msc &= ~ADIS16204_MSC_CTRL_DATA_RDY_DIO2; |
238 | if (enable) | 195 | if (enable) |
239 | msc |= ADIS16204_MSC_CTRL_DATA_RDY_EN; | 196 | msc |= ADIS16204_MSC_CTRL_DATA_RDY_EN; |
240 | else | 197 | else |
241 | msc &= ~ADIS16204_MSC_CTRL_DATA_RDY_EN; | 198 | msc &= ~ADIS16204_MSC_CTRL_DATA_RDY_EN; |
242 | 199 | ||
243 | ret = adis16204_spi_write_reg_16(indio_dev, ADIS16204_MSC_CTRL, msc); | 200 | ret = adis16204_spi_write_reg_16(indio_dev, ADIS16204_MSC_CTRL, msc); |
244 | 201 | ||
245 | error_ret: | 202 | error_ret: |
246 | return ret; | 203 | return ret; |
247 | } | 204 | } |
248 | 205 | ||
249 | static int adis16204_self_test(struct iio_dev *indio_dev) | 206 | static int adis16204_self_test(struct iio_dev *indio_dev) |
250 | { | 207 | { |
251 | int ret; | 208 | int ret; |
252 | ret = adis16204_spi_write_reg_16(indio_dev, | 209 | ret = adis16204_spi_write_reg_16(indio_dev, |
253 | ADIS16204_MSC_CTRL, | 210 | ADIS16204_MSC_CTRL, |
254 | ADIS16204_MSC_CTRL_SELF_TEST_EN); | 211 | ADIS16204_MSC_CTRL_SELF_TEST_EN); |
255 | if (ret) { | 212 | if (ret) { |
256 | dev_err(&indio_dev->dev, "problem starting self test"); | 213 | dev_err(&indio_dev->dev, "problem starting self test"); |
257 | goto err_ret; | 214 | goto err_ret; |
258 | } | 215 | } |
259 | 216 | ||
260 | adis16204_check_status(indio_dev); | 217 | adis16204_check_status(indio_dev); |
261 | 218 | ||
262 | err_ret: | 219 | err_ret: |
263 | return ret; | 220 | return ret; |
264 | } | 221 | } |
265 | 222 | ||
266 | static int adis16204_initial_setup(struct iio_dev *indio_dev) | 223 | static int adis16204_initial_setup(struct iio_dev *indio_dev) |
267 | { | 224 | { |
268 | int ret; | 225 | int ret; |
269 | 226 | ||
270 | /* Disable IRQ */ | 227 | /* Disable IRQ */ |
271 | ret = adis16204_set_irq(indio_dev, false); | 228 | ret = adis16204_set_irq(indio_dev, false); |
272 | if (ret) { | 229 | if (ret) { |
273 | dev_err(&indio_dev->dev, "disable irq failed"); | 230 | dev_err(&indio_dev->dev, "disable irq failed"); |
274 | goto err_ret; | 231 | goto err_ret; |
275 | } | 232 | } |
276 | 233 | ||
277 | /* Do self test */ | 234 | /* Do self test */ |
278 | ret = adis16204_self_test(indio_dev); | 235 | ret = adis16204_self_test(indio_dev); |
279 | if (ret) { | 236 | if (ret) { |
280 | dev_err(&indio_dev->dev, "self test failure"); | 237 | dev_err(&indio_dev->dev, "self test failure"); |
281 | goto err_ret; | 238 | goto err_ret; |
282 | } | 239 | } |
283 | 240 | ||
284 | /* Read status register to check the result */ | 241 | /* Read status register to check the result */ |
285 | ret = adis16204_check_status(indio_dev); | 242 | ret = adis16204_check_status(indio_dev); |
286 | if (ret) { | 243 | if (ret) { |
287 | adis16204_reset(indio_dev); | 244 | adis16204_reset(indio_dev); |
288 | dev_err(&indio_dev->dev, "device not playing ball -> reset"); | 245 | dev_err(&indio_dev->dev, "device not playing ball -> reset"); |
289 | msleep(ADIS16204_STARTUP_DELAY); | 246 | msleep(ADIS16204_STARTUP_DELAY); |
290 | ret = adis16204_check_status(indio_dev); | 247 | ret = adis16204_check_status(indio_dev); |
291 | if (ret) { | 248 | if (ret) { |
292 | dev_err(&indio_dev->dev, "giving up"); | 249 | dev_err(&indio_dev->dev, "giving up"); |
293 | goto err_ret; | 250 | goto err_ret; |
294 | } | 251 | } |
295 | } | 252 | } |
296 | 253 | ||
297 | err_ret: | 254 | err_ret: |
298 | return ret; | 255 | return ret; |
299 | } | 256 | } |
300 | 257 | ||
301 | /* Unique to this driver currently */ | 258 | /* Unique to this driver currently */ |
302 | #define IIO_DEV_ATTR_ACCEL_XY(_show, _addr) \ | ||
303 | IIO_DEVICE_ATTR(in_accel_xy, S_IRUGO, _show, NULL, _addr) | ||
304 | #define IIO_DEV_ATTR_ACCEL_XYPEAK(_show, _addr) \ | ||
305 | IIO_DEVICE_ATTR(in_accel_xypeak, S_IRUGO, _show, NULL, _addr) | ||
306 | 259 | ||
307 | static IIO_DEV_ATTR_ACCEL_XY(adis16204_read_14bit_signed, | ||
308 | ADIS16204_XY_RSS_OUT); | ||
309 | static IIO_DEV_ATTR_ACCEL_XYPEAK(adis16204_read_14bit_signed, | ||
310 | ADIS16204_XY_PEAK_OUT); | ||
311 | static IIO_CONST_ATTR(in_accel_xy_scale, "0.017125"); | ||
312 | |||
313 | static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16204_write_reset, 0); | ||
314 | |||
315 | enum adis16204_channel { | 260 | enum adis16204_channel { |
316 | in_supply, | 261 | in_supply, |
317 | in_aux, | 262 | in_aux, |
318 | temp, | 263 | temp, |
319 | accel_x, | 264 | accel_x, |
320 | accel_y, | 265 | accel_y, |
266 | accel_xy, | ||
321 | }; | 267 | }; |
322 | 268 | ||
323 | static u8 adis16204_addresses[5][3] = { | 269 | static u8 adis16204_addresses[6][3] = { |
324 | [in_supply] = { ADIS16204_SUPPLY_OUT }, | 270 | [in_supply] = { ADIS16204_SUPPLY_OUT }, |
325 | [in_aux] = { ADIS16204_AUX_ADC }, | 271 | [in_aux] = { ADIS16204_AUX_ADC }, |
326 | [temp] = { ADIS16204_TEMP_OUT }, | 272 | [temp] = { ADIS16204_TEMP_OUT }, |
327 | [accel_x] = { ADIS16204_XACCL_OUT, ADIS16204_XACCL_NULL, | 273 | [accel_x] = { ADIS16204_XACCL_OUT, ADIS16204_XACCL_NULL, |
328 | ADIS16204_X_PEAK_OUT }, | 274 | ADIS16204_X_PEAK_OUT }, |
329 | [accel_y] = { ADIS16204_XACCL_OUT, ADIS16204_YACCL_NULL, | 275 | [accel_y] = { ADIS16204_XACCL_OUT, ADIS16204_YACCL_NULL, |
330 | ADIS16204_Y_PEAK_OUT }, | 276 | ADIS16204_Y_PEAK_OUT }, |
277 | [accel_xy] = { ADIS16204_XY_RSS_OUT, 0, | ||
278 | ADIS16204_XY_PEAK_OUT }, | ||
331 | }; | 279 | }; |
332 | 280 | ||
333 | static int adis16204_read_raw(struct iio_dev *indio_dev, | 281 | static int adis16204_read_raw(struct iio_dev *indio_dev, |
334 | struct iio_chan_spec const *chan, | 282 | struct iio_chan_spec const *chan, |
335 | int *val, int *val2, | 283 | int *val, int *val2, |
336 | long mask) | 284 | long mask) |
337 | { | 285 | { |
338 | int ret; | 286 | int ret; |
339 | int bits; | 287 | int bits; |
340 | u8 addr; | 288 | u8 addr; |
341 | s16 val16; | 289 | s16 val16; |
342 | int addrind; | 290 | int addrind; |
343 | 291 | ||
344 | switch (mask) { | 292 | switch (mask) { |
345 | case IIO_CHAN_INFO_RAW: | 293 | case IIO_CHAN_INFO_RAW: |
346 | mutex_lock(&indio_dev->mlock); | 294 | mutex_lock(&indio_dev->mlock); |
347 | addr = adis16204_addresses[chan->address][0]; | 295 | addr = adis16204_addresses[chan->address][0]; |
348 | ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16); | 296 | ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16); |
349 | if (ret) { | 297 | if (ret) { |
350 | mutex_unlock(&indio_dev->mlock); | 298 | mutex_unlock(&indio_dev->mlock); |
351 | return ret; | 299 | return ret; |
352 | } | 300 | } |
353 | 301 | ||
354 | if (val16 & ADIS16204_ERROR_ACTIVE) { | 302 | if (val16 & ADIS16204_ERROR_ACTIVE) { |
355 | ret = adis16204_check_status(indio_dev); | 303 | ret = adis16204_check_status(indio_dev); |
356 | if (ret) { | 304 | if (ret) { |
357 | mutex_unlock(&indio_dev->mlock); | 305 | mutex_unlock(&indio_dev->mlock); |
358 | return ret; | 306 | return ret; |
359 | } | 307 | } |
360 | } | 308 | } |
361 | val16 = val16 & ((1 << chan->scan_type.realbits) - 1); | 309 | val16 = val16 & ((1 << chan->scan_type.realbits) - 1); |
362 | if (chan->scan_type.sign == 's') | 310 | if (chan->scan_type.sign == 's') |
363 | val16 = (s16)(val16 << | 311 | val16 = (s16)(val16 << |
364 | (16 - chan->scan_type.realbits)) >> | 312 | (16 - chan->scan_type.realbits)) >> |
365 | (16 - chan->scan_type.realbits); | 313 | (16 - chan->scan_type.realbits); |
366 | *val = val16; | 314 | *val = val16; |
367 | mutex_unlock(&indio_dev->mlock); | 315 | mutex_unlock(&indio_dev->mlock); |
368 | return IIO_VAL_INT; | 316 | return IIO_VAL_INT; |
369 | case IIO_CHAN_INFO_SCALE: | 317 | case IIO_CHAN_INFO_SCALE: |
370 | switch (chan->type) { | 318 | switch (chan->type) { |
371 | case IIO_VOLTAGE: | 319 | case IIO_VOLTAGE: |
372 | *val = 0; | 320 | *val = 0; |
373 | if (chan->channel == 0) | 321 | if (chan->channel == 0) |
374 | *val2 = 1220; | 322 | *val2 = 1220; |
375 | else | 323 | else |
376 | *val2 = 610; | 324 | *val2 = 610; |
377 | return IIO_VAL_INT_PLUS_MICRO; | 325 | return IIO_VAL_INT_PLUS_MICRO; |
378 | case IIO_TEMP: | 326 | case IIO_TEMP: |
379 | *val = 0; | 327 | *val = 0; |
380 | *val2 = -470000; | 328 | *val2 = -470000; |
381 | return IIO_VAL_INT_PLUS_MICRO; | 329 | return IIO_VAL_INT_PLUS_MICRO; |
382 | case IIO_ACCEL: | 330 | case IIO_ACCEL: |
383 | *val = 0; | 331 | *val = 0; |
384 | if (chan->channel2 == IIO_MOD_X) | 332 | switch (chan->channel2) { |
333 | case IIO_MOD_X: | ||
334 | case IIO_MOD_ROOT_SUM_SQUARED_X_Y: | ||
385 | *val2 = 17125; | 335 | *val2 = 17125; |
386 | else | 336 | break; |
337 | case IIO_MOD_Y: | ||
338 | case IIO_MOD_Z: | ||
387 | *val2 = 8407; | 339 | *val2 = 8407; |
340 | break; | ||
341 | } | ||
388 | return IIO_VAL_INT_PLUS_MICRO; | 342 | return IIO_VAL_INT_PLUS_MICRO; |
389 | default: | 343 | default: |
390 | return -EINVAL; | 344 | return -EINVAL; |
391 | } | 345 | } |
392 | break; | 346 | break; |
393 | case IIO_CHAN_INFO_OFFSET: | 347 | case IIO_CHAN_INFO_OFFSET: |
394 | *val = 25; | 348 | *val = 25; |
395 | return IIO_VAL_INT; | 349 | return IIO_VAL_INT; |
396 | case IIO_CHAN_INFO_CALIBBIAS: | 350 | case IIO_CHAN_INFO_CALIBBIAS: |
397 | case IIO_CHAN_INFO_PEAK: | 351 | case IIO_CHAN_INFO_PEAK: |
398 | if (mask == IIO_CHAN_INFO_CALIBBIAS) { | 352 | if (mask == IIO_CHAN_INFO_CALIBBIAS) { |
399 | bits = 12; | 353 | bits = 12; |
400 | addrind = 1; | 354 | addrind = 1; |
401 | } else { /* PEAK_SEPARATE */ | 355 | } else { /* PEAK_SEPARATE */ |
402 | bits = 14; | 356 | bits = 14; |
403 | addrind = 2; | 357 | addrind = 2; |
404 | } | 358 | } |
405 | mutex_lock(&indio_dev->mlock); | 359 | mutex_lock(&indio_dev->mlock); |
406 | addr = adis16204_addresses[chan->address][addrind]; | 360 | addr = adis16204_addresses[chan->address][addrind]; |
407 | ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16); | 361 | ret = adis16204_spi_read_reg_16(indio_dev, addr, &val16); |
408 | if (ret) { | 362 | if (ret) { |
409 | mutex_unlock(&indio_dev->mlock); | 363 | mutex_unlock(&indio_dev->mlock); |
410 | return ret; | 364 | return ret; |
411 | } | 365 | } |
412 | val16 &= (1 << bits) - 1; | 366 | val16 &= (1 << bits) - 1; |
413 | val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); | 367 | val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); |
414 | *val = val16; | 368 | *val = val16; |
415 | mutex_unlock(&indio_dev->mlock); | 369 | mutex_unlock(&indio_dev->mlock); |
416 | return IIO_VAL_INT; | 370 | return IIO_VAL_INT; |
417 | } | 371 | } |
418 | return -EINVAL; | 372 | return -EINVAL; |
419 | } | 373 | } |
420 | 374 | ||
421 | static int adis16204_write_raw(struct iio_dev *indio_dev, | 375 | static int adis16204_write_raw(struct iio_dev *indio_dev, |
422 | struct iio_chan_spec const *chan, | 376 | struct iio_chan_spec const *chan, |
423 | int val, | 377 | int val, |
424 | int val2, | 378 | int val2, |
425 | long mask) | 379 | long mask) |
426 | { | 380 | { |
427 | int bits; | 381 | int bits; |
428 | s16 val16; | 382 | s16 val16; |
429 | u8 addr; | 383 | u8 addr; |
430 | switch (mask) { | 384 | switch (mask) { |
431 | case IIO_CHAN_INFO_CALIBBIAS: | 385 | case IIO_CHAN_INFO_CALIBBIAS: |
432 | switch (chan->type) { | 386 | switch (chan->type) { |
433 | case IIO_ACCEL: | 387 | case IIO_ACCEL: |
434 | bits = 12; | 388 | bits = 12; |
435 | break; | 389 | break; |
436 | default: | 390 | default: |
437 | return -EINVAL; | 391 | return -EINVAL; |
438 | }; | 392 | }; |
439 | val16 = val & ((1 << bits) - 1); | 393 | val16 = val & ((1 << bits) - 1); |
440 | addr = adis16204_addresses[chan->address][1]; | 394 | addr = adis16204_addresses[chan->address][1]; |
441 | return adis16204_spi_write_reg_16(indio_dev, addr, val16); | 395 | return adis16204_spi_write_reg_16(indio_dev, addr, val16); |
442 | } | 396 | } |
443 | return -EINVAL; | 397 | return -EINVAL; |
444 | } | 398 | } |
445 | 399 | ||
446 | static struct iio_chan_spec adis16204_channels[] = { | 400 | static struct iio_chan_spec adis16204_channels[] = { |
447 | { | 401 | { |
448 | .type = IIO_VOLTAGE, | 402 | .type = IIO_VOLTAGE, |
449 | .indexed = 1, /* Note was not previously indexed */ | 403 | .indexed = 1, /* Note was not previously indexed */ |
450 | .channel = 0, | 404 | .channel = 0, |
451 | .extend_name = "supply", | 405 | .extend_name = "supply", |
452 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 406 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
453 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 407 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
454 | .address = in_supply, | 408 | .address = in_supply, |
455 | .scan_index = ADIS16204_SCAN_SUPPLY, | 409 | .scan_index = ADIS16204_SCAN_SUPPLY, |
456 | .scan_type = { | 410 | .scan_type = { |
457 | .sign = 'u', | 411 | .sign = 'u', |
458 | .realbits = 12, | 412 | .realbits = 12, |
459 | .storagebits = 16, | 413 | .storagebits = 16, |
460 | }, | 414 | }, |
461 | }, { | 415 | }, { |
462 | .type = IIO_VOLTAGE, | 416 | .type = IIO_VOLTAGE, |
463 | .indexed = 1, | 417 | .indexed = 1, |
464 | .channel = 1, | 418 | .channel = 1, |
465 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 419 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
466 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 420 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
467 | .address = in_aux, | 421 | .address = in_aux, |
468 | .scan_index = ADIS16204_SCAN_AUX_ADC, | 422 | .scan_index = ADIS16204_SCAN_AUX_ADC, |
469 | .scan_type = { | 423 | .scan_type = { |
470 | .sign = 'u', | 424 | .sign = 'u', |
471 | .realbits = 12, | 425 | .realbits = 12, |
472 | .storagebits = 16, | 426 | .storagebits = 16, |
473 | }, | 427 | }, |
474 | }, { | 428 | }, { |
475 | .type = IIO_TEMP, | 429 | .type = IIO_TEMP, |
476 | .indexed = 1, | 430 | .indexed = 1, |
477 | .channel = 0, | 431 | .channel = 0, |
478 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 432 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
479 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | | 433 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | |
480 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, | 434 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, |
481 | .address = temp, | 435 | .address = temp, |
482 | .scan_index = ADIS16204_SCAN_TEMP, | 436 | .scan_index = ADIS16204_SCAN_TEMP, |
483 | .scan_type = { | 437 | .scan_type = { |
484 | .sign = 'u', | 438 | .sign = 'u', |
485 | .realbits = 12, | 439 | .realbits = 12, |
486 | .storagebits = 16, | 440 | .storagebits = 16, |
487 | }, | 441 | }, |
488 | }, { | 442 | }, { |
489 | .type = IIO_ACCEL, | 443 | .type = IIO_ACCEL, |
490 | .modified = 1, | 444 | .modified = 1, |
491 | .channel2 = IIO_MOD_X, | 445 | .channel2 = IIO_MOD_X, |
492 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 446 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
493 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | | 447 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | |
494 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 448 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
495 | IIO_CHAN_INFO_PEAK_SEPARATE_BIT, | 449 | IIO_CHAN_INFO_PEAK_SEPARATE_BIT, |
496 | .address = accel_x, | 450 | .address = accel_x, |
497 | .scan_index = ADIS16204_SCAN_ACC_X, | 451 | .scan_index = ADIS16204_SCAN_ACC_X, |
498 | .scan_type = { | 452 | .scan_type = { |
499 | .sign = 's', | 453 | .sign = 's', |
500 | .realbits = 14, | 454 | .realbits = 14, |
501 | .storagebits = 16, | 455 | .storagebits = 16, |
502 | }, | 456 | }, |
503 | }, { | 457 | }, { |
504 | .type = IIO_ACCEL, | 458 | .type = IIO_ACCEL, |
505 | .modified = 1, | 459 | .modified = 1, |
506 | .channel2 = IIO_MOD_Y, | 460 | .channel2 = IIO_MOD_Y, |
507 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 461 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
508 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | | 462 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | |
509 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 463 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
510 | IIO_CHAN_INFO_PEAK_SEPARATE_BIT, | 464 | IIO_CHAN_INFO_PEAK_SEPARATE_BIT, |
511 | .address = accel_y, | 465 | .address = accel_y, |
512 | .scan_index = ADIS16204_SCAN_ACC_Y, | 466 | .scan_index = ADIS16204_SCAN_ACC_Y, |
513 | .scan_type = { | 467 | .scan_type = { |
514 | .sign = 's', | 468 | .sign = 's', |
515 | .realbits = 14, | 469 | .realbits = 14, |
516 | .storagebits = 16, | 470 | .storagebits = 16, |
517 | }, | 471 | }, |
518 | }, | 472 | }, |
519 | IIO_CHAN_SOFT_TIMESTAMP(5), | 473 | IIO_CHAN_SOFT_TIMESTAMP(5), |
474 | { | ||
475 | .type = IIO_ACCEL, | ||
476 | .modified = 1, | ||
477 | .channel2 = IIO_MOD_ROOT_SUM_SQUARED_X_Y, | ||
478 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | ||
479 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | | ||
480 | IIO_CHAN_INFO_PEAK_SEPARATE_BIT, | ||
481 | .address = accel_xy, | ||
482 | .scan_type = { | ||
483 | .sign = 'u', | ||
484 | .realbits = 14, | ||
485 | .storagebits = 16, | ||
486 | }, | ||
487 | } | ||
520 | }; | 488 | }; |
521 | 489 | ||
522 | static struct attribute *adis16204_attributes[] = { | ||
523 | &iio_dev_attr_reset.dev_attr.attr, | ||
524 | &iio_dev_attr_in_accel_xy.dev_attr.attr, | ||
525 | &iio_dev_attr_in_accel_xypeak.dev_attr.attr, | ||
526 | &iio_const_attr_in_accel_xy_scale.dev_attr.attr, | ||
527 | NULL | ||
528 | }; | ||
529 | |||
530 | static const struct attribute_group adis16204_attribute_group = { | ||
531 | .attrs = adis16204_attributes, | ||
532 | }; | ||
533 | |||
534 | static const struct iio_info adis16204_info = { | 490 | static const struct iio_info adis16204_info = { |
535 | .attrs = &adis16204_attribute_group, | ||
536 | .read_raw = &adis16204_read_raw, | 491 | .read_raw = &adis16204_read_raw, |
537 | .write_raw = &adis16204_write_raw, | 492 | .write_raw = &adis16204_write_raw, |
538 | .driver_module = THIS_MODULE, | 493 | .driver_module = THIS_MODULE, |
539 | }; | 494 | }; |
540 | 495 | ||
541 | static int __devinit adis16204_probe(struct spi_device *spi) | 496 | static int __devinit adis16204_probe(struct spi_device *spi) |
542 | { | 497 | { |
543 | int ret; | 498 | int ret; |
544 | struct adis16204_state *st; | 499 | struct adis16204_state *st; |
545 | struct iio_dev *indio_dev; | 500 | struct iio_dev *indio_dev; |
546 | 501 | ||
547 | /* setup the industrialio driver allocated elements */ | 502 | /* setup the industrialio driver allocated elements */ |
548 | indio_dev = iio_device_alloc(sizeof(*st)); | 503 | indio_dev = iio_device_alloc(sizeof(*st)); |
549 | if (indio_dev == NULL) { | 504 | if (indio_dev == NULL) { |
550 | ret = -ENOMEM; | 505 | ret = -ENOMEM; |
551 | goto error_ret; | 506 | goto error_ret; |
552 | } | 507 | } |
553 | st = iio_priv(indio_dev); | 508 | st = iio_priv(indio_dev); |
554 | /* this is only used for removal purposes */ | 509 | /* this is only used for removal purposes */ |
555 | spi_set_drvdata(spi, indio_dev); | 510 | spi_set_drvdata(spi, indio_dev); |
556 | st->us = spi; | 511 | st->us = spi; |
557 | mutex_init(&st->buf_lock); | 512 | mutex_init(&st->buf_lock); |
558 | 513 | ||
559 | indio_dev->name = spi->dev.driver->name; | 514 | indio_dev->name = spi->dev.driver->name; |
560 | indio_dev->dev.parent = &spi->dev; | 515 | indio_dev->dev.parent = &spi->dev; |
561 | indio_dev->info = &adis16204_info; | 516 | indio_dev->info = &adis16204_info; |
562 | indio_dev->channels = adis16204_channels; | 517 | indio_dev->channels = adis16204_channels; |
563 | indio_dev->num_channels = ARRAY_SIZE(adis16204_channels); | 518 | indio_dev->num_channels = ARRAY_SIZE(adis16204_channels); |
564 | indio_dev->modes = INDIO_DIRECT_MODE; | 519 | indio_dev->modes = INDIO_DIRECT_MODE; |
565 | 520 | ||
566 | ret = adis16204_configure_ring(indio_dev); | 521 | ret = adis16204_configure_ring(indio_dev); |
567 | if (ret) | 522 | if (ret) |
568 | goto error_free_dev; | 523 | goto error_free_dev; |
569 | 524 | ||
570 | ret = iio_buffer_register(indio_dev, | 525 | ret = iio_buffer_register(indio_dev, |
571 | adis16204_channels, | 526 | adis16204_channels, |
572 | ARRAY_SIZE(adis16204_channels)); | 527 | 6); |
573 | if (ret) { | 528 | if (ret) { |
574 | printk(KERN_ERR "failed to initialize the ring\n"); | 529 | printk(KERN_ERR "failed to initialize the ring\n"); |
575 | goto error_unreg_ring_funcs; | 530 | goto error_unreg_ring_funcs; |
576 | } | 531 | } |
577 | 532 | ||
578 | if (spi->irq) { | 533 | if (spi->irq) { |
579 | ret = adis16204_probe_trigger(indio_dev); | 534 | ret = adis16204_probe_trigger(indio_dev); |
580 | if (ret) | 535 | if (ret) |
581 | goto error_uninitialize_ring; | 536 | goto error_uninitialize_ring; |
582 | } | 537 | } |
583 | 538 | ||
584 | /* Get the device into a sane initial state */ | 539 | /* Get the device into a sane initial state */ |
585 | ret = adis16204_initial_setup(indio_dev); | 540 | ret = adis16204_initial_setup(indio_dev); |
586 | if (ret) | 541 | if (ret) |
587 | goto error_remove_trigger; | 542 | goto error_remove_trigger; |
588 | ret = iio_device_register(indio_dev); | 543 | ret = iio_device_register(indio_dev); |
589 | if (ret) | 544 | if (ret) |
590 | goto error_remove_trigger; | 545 | goto error_remove_trigger; |
591 | 546 | ||
592 | return 0; | 547 | return 0; |
593 | 548 | ||
594 | error_remove_trigger: | 549 | error_remove_trigger: |
595 | adis16204_remove_trigger(indio_dev); | 550 | adis16204_remove_trigger(indio_dev); |
596 | error_uninitialize_ring: | 551 | error_uninitialize_ring: |
597 | iio_buffer_unregister(indio_dev); | 552 | iio_buffer_unregister(indio_dev); |
598 | error_unreg_ring_funcs: | 553 | error_unreg_ring_funcs: |
599 | adis16204_unconfigure_ring(indio_dev); | 554 | adis16204_unconfigure_ring(indio_dev); |
600 | error_free_dev: | 555 | error_free_dev: |
601 | iio_device_free(indio_dev); | 556 | iio_device_free(indio_dev); |
602 | error_ret: | 557 | error_ret: |
603 | return ret; | 558 | return ret; |
604 | } | 559 | } |
605 | 560 | ||
606 | static int adis16204_remove(struct spi_device *spi) | 561 | static int adis16204_remove(struct spi_device *spi) |
607 | { | 562 | { |
608 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | 563 | struct iio_dev *indio_dev = spi_get_drvdata(spi); |
609 | 564 | ||
610 | iio_device_unregister(indio_dev); | 565 | iio_device_unregister(indio_dev); |
drivers/staging/iio/accel/adis16209_core.c
1 | /* | 1 | /* |
2 | * ADIS16209 Programmable Digital Vibration Sensor driver | 2 | * ADIS16209 Programmable Digital Vibration Sensor driver |
3 | * | 3 | * |
4 | * Copyright 2010 Analog Devices Inc. | 4 | * Copyright 2010 Analog Devices Inc. |
5 | * | 5 | * |
6 | * Licensed under the GPL-2 or later. | 6 | * Licensed under the GPL-2 or later. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
10 | #include <linux/mutex.h> | 10 | #include <linux/mutex.h> |
11 | #include <linux/device.h> | 11 | #include <linux/device.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/spi/spi.h> | 13 | #include <linux/spi/spi.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/sysfs.h> | 15 | #include <linux/sysfs.h> |
16 | #include <linux/list.h> | 16 | #include <linux/list.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | 18 | ||
19 | #include <linux/iio/iio.h> | 19 | #include <linux/iio/iio.h> |
20 | #include <linux/iio/sysfs.h> | 20 | #include <linux/iio/sysfs.h> |
21 | #include <linux/iio/buffer.h> | 21 | #include <linux/iio/buffer.h> |
22 | 22 | ||
23 | #include "adis16209.h" | 23 | #include "adis16209.h" |
24 | 24 | ||
25 | #define DRIVER_NAME "adis16209" | 25 | #define DRIVER_NAME "adis16209" |
26 | 26 | ||
27 | /** | 27 | /** |
28 | * adis16209_spi_write_reg_8() - write single byte to a register | 28 | * adis16209_spi_write_reg_8() - write single byte to a register |
29 | * @indio_dev: iio device associated with actual device | 29 | * @indio_dev: iio device associated with actual device |
30 | * @reg_address: the address of the register to be written | 30 | * @reg_address: the address of the register to be written |
31 | * @val: the value to write | 31 | * @val: the value to write |
32 | **/ | 32 | **/ |
33 | static int adis16209_spi_write_reg_8(struct iio_dev *indio_dev, | 33 | static int adis16209_spi_write_reg_8(struct iio_dev *indio_dev, |
34 | u8 reg_address, | 34 | u8 reg_address, |
35 | u8 val) | 35 | u8 val) |
36 | { | 36 | { |
37 | int ret; | 37 | int ret; |
38 | struct adis16209_state *st = iio_priv(indio_dev); | 38 | struct adis16209_state *st = iio_priv(indio_dev); |
39 | 39 | ||
40 | mutex_lock(&st->buf_lock); | 40 | mutex_lock(&st->buf_lock); |
41 | st->tx[0] = ADIS16209_WRITE_REG(reg_address); | 41 | st->tx[0] = ADIS16209_WRITE_REG(reg_address); |
42 | st->tx[1] = val; | 42 | st->tx[1] = val; |
43 | 43 | ||
44 | ret = spi_write(st->us, st->tx, 2); | 44 | ret = spi_write(st->us, st->tx, 2); |
45 | mutex_unlock(&st->buf_lock); | 45 | mutex_unlock(&st->buf_lock); |
46 | 46 | ||
47 | return ret; | 47 | return ret; |
48 | } | 48 | } |
49 | 49 | ||
50 | /** | 50 | /** |
51 | * adis16209_spi_write_reg_16() - write 2 bytes to a pair of registers | 51 | * adis16209_spi_write_reg_16() - write 2 bytes to a pair of registers |
52 | * @indio_dev: iio device associated actual device | 52 | * @indio_dev: iio device associated actual device |
53 | * @reg_address: the address of the lower of the two registers. Second register | 53 | * @reg_address: the address of the lower of the two registers. Second register |
54 | * is assumed to have address one greater. | 54 | * is assumed to have address one greater. |
55 | * @val: value to be written | 55 | * @val: value to be written |
56 | **/ | 56 | **/ |
57 | static int adis16209_spi_write_reg_16(struct iio_dev *indio_dev, | 57 | static int adis16209_spi_write_reg_16(struct iio_dev *indio_dev, |
58 | u8 lower_reg_address, | 58 | u8 lower_reg_address, |
59 | u16 value) | 59 | u16 value) |
60 | { | 60 | { |
61 | int ret; | 61 | int ret; |
62 | struct spi_message msg; | 62 | struct spi_message msg; |
63 | struct adis16209_state *st = iio_priv(indio_dev); | 63 | struct adis16209_state *st = iio_priv(indio_dev); |
64 | struct spi_transfer xfers[] = { | 64 | struct spi_transfer xfers[] = { |
65 | { | 65 | { |
66 | .tx_buf = st->tx, | 66 | .tx_buf = st->tx, |
67 | .bits_per_word = 8, | 67 | .bits_per_word = 8, |
68 | .len = 2, | 68 | .len = 2, |
69 | .cs_change = 1, | 69 | .cs_change = 1, |
70 | .delay_usecs = 30, | 70 | .delay_usecs = 30, |
71 | }, { | 71 | }, { |
72 | .tx_buf = st->tx + 2, | 72 | .tx_buf = st->tx + 2, |
73 | .bits_per_word = 8, | 73 | .bits_per_word = 8, |
74 | .len = 2, | 74 | .len = 2, |
75 | .delay_usecs = 30, | 75 | .delay_usecs = 30, |
76 | }, | 76 | }, |
77 | }; | 77 | }; |
78 | 78 | ||
79 | mutex_lock(&st->buf_lock); | 79 | mutex_lock(&st->buf_lock); |
80 | st->tx[0] = ADIS16209_WRITE_REG(lower_reg_address); | 80 | st->tx[0] = ADIS16209_WRITE_REG(lower_reg_address); |
81 | st->tx[1] = value & 0xFF; | 81 | st->tx[1] = value & 0xFF; |
82 | st->tx[2] = ADIS16209_WRITE_REG(lower_reg_address + 1); | 82 | st->tx[2] = ADIS16209_WRITE_REG(lower_reg_address + 1); |
83 | st->tx[3] = (value >> 8) & 0xFF; | 83 | st->tx[3] = (value >> 8) & 0xFF; |
84 | 84 | ||
85 | spi_message_init(&msg); | 85 | spi_message_init(&msg); |
86 | spi_message_add_tail(&xfers[0], &msg); | 86 | spi_message_add_tail(&xfers[0], &msg); |
87 | spi_message_add_tail(&xfers[1], &msg); | 87 | spi_message_add_tail(&xfers[1], &msg); |
88 | ret = spi_sync(st->us, &msg); | 88 | ret = spi_sync(st->us, &msg); |
89 | mutex_unlock(&st->buf_lock); | 89 | mutex_unlock(&st->buf_lock); |
90 | 90 | ||
91 | return ret; | 91 | return ret; |
92 | } | 92 | } |
93 | 93 | ||
94 | /** | 94 | /** |
95 | * adis16209_spi_read_reg_16() - read 2 bytes from a 16-bit register | 95 | * adis16209_spi_read_reg_16() - read 2 bytes from a 16-bit register |
96 | * @indio_dev: iio device associated with device | 96 | * @indio_dev: iio device associated with device |
97 | * @reg_address: the address of the lower of the two registers. Second register | 97 | * @reg_address: the address of the lower of the two registers. Second register |
98 | * is assumed to have address one greater. | 98 | * is assumed to have address one greater. |
99 | * @val: somewhere to pass back the value read | 99 | * @val: somewhere to pass back the value read |
100 | **/ | 100 | **/ |
101 | static int adis16209_spi_read_reg_16(struct iio_dev *indio_dev, | 101 | static int adis16209_spi_read_reg_16(struct iio_dev *indio_dev, |
102 | u8 lower_reg_address, | 102 | u8 lower_reg_address, |
103 | u16 *val) | 103 | u16 *val) |
104 | { | 104 | { |
105 | struct spi_message msg; | 105 | struct spi_message msg; |
106 | struct adis16209_state *st = iio_priv(indio_dev); | 106 | struct adis16209_state *st = iio_priv(indio_dev); |
107 | int ret; | 107 | int ret; |
108 | struct spi_transfer xfers[] = { | 108 | struct spi_transfer xfers[] = { |
109 | { | 109 | { |
110 | .tx_buf = st->tx, | 110 | .tx_buf = st->tx, |
111 | .bits_per_word = 8, | 111 | .bits_per_word = 8, |
112 | .len = 2, | 112 | .len = 2, |
113 | .cs_change = 1, | 113 | .cs_change = 1, |
114 | .delay_usecs = 30, | 114 | .delay_usecs = 30, |
115 | }, { | 115 | }, { |
116 | .rx_buf = st->rx, | 116 | .rx_buf = st->rx, |
117 | .bits_per_word = 8, | 117 | .bits_per_word = 8, |
118 | .len = 2, | 118 | .len = 2, |
119 | .delay_usecs = 30, | 119 | .delay_usecs = 30, |
120 | }, | 120 | }, |
121 | }; | 121 | }; |
122 | 122 | ||
123 | mutex_lock(&st->buf_lock); | 123 | mutex_lock(&st->buf_lock); |
124 | st->tx[0] = ADIS16209_READ_REG(lower_reg_address); | 124 | st->tx[0] = ADIS16209_READ_REG(lower_reg_address); |
125 | st->tx[1] = 0; | 125 | st->tx[1] = 0; |
126 | 126 | ||
127 | spi_message_init(&msg); | 127 | spi_message_init(&msg); |
128 | spi_message_add_tail(&xfers[0], &msg); | 128 | spi_message_add_tail(&xfers[0], &msg); |
129 | spi_message_add_tail(&xfers[1], &msg); | 129 | spi_message_add_tail(&xfers[1], &msg); |
130 | ret = spi_sync(st->us, &msg); | 130 | ret = spi_sync(st->us, &msg); |
131 | if (ret) { | 131 | if (ret) { |
132 | dev_err(&st->us->dev, | 132 | dev_err(&st->us->dev, |
133 | "problem when reading 16 bit register 0x%02X", | 133 | "problem when reading 16 bit register 0x%02X", |
134 | lower_reg_address); | 134 | lower_reg_address); |
135 | goto error_ret; | 135 | goto error_ret; |
136 | } | 136 | } |
137 | *val = (st->rx[0] << 8) | st->rx[1]; | 137 | *val = (st->rx[0] << 8) | st->rx[1]; |
138 | 138 | ||
139 | error_ret: | 139 | error_ret: |
140 | mutex_unlock(&st->buf_lock); | 140 | mutex_unlock(&st->buf_lock); |
141 | return ret; | 141 | return ret; |
142 | } | 142 | } |
143 | 143 | ||
144 | static int adis16209_reset(struct iio_dev *indio_dev) | 144 | static int adis16209_reset(struct iio_dev *indio_dev) |
145 | { | 145 | { |
146 | int ret; | 146 | int ret; |
147 | ret = adis16209_spi_write_reg_8(indio_dev, | 147 | ret = adis16209_spi_write_reg_8(indio_dev, |
148 | ADIS16209_GLOB_CMD, | 148 | ADIS16209_GLOB_CMD, |
149 | ADIS16209_GLOB_CMD_SW_RESET); | 149 | ADIS16209_GLOB_CMD_SW_RESET); |
150 | if (ret) | 150 | if (ret) |
151 | dev_err(&indio_dev->dev, "problem resetting device"); | 151 | dev_err(&indio_dev->dev, "problem resetting device"); |
152 | 152 | ||
153 | return ret; | 153 | return ret; |
154 | } | 154 | } |
155 | 155 | ||
156 | static ssize_t adis16209_write_reset(struct device *dev, | ||
157 | struct device_attribute *attr, | ||
158 | const char *buf, size_t len) | ||
159 | { | ||
160 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
161 | |||
162 | if (len < 1) | ||
163 | return -EINVAL; | ||
164 | switch (buf[0]) { | ||
165 | case '1': | ||
166 | case 'y': | ||
167 | case 'Y': | ||
168 | return adis16209_reset(indio_dev); | ||
169 | } | ||
170 | return -EINVAL; | ||
171 | } | ||
172 | |||
173 | int adis16209_set_irq(struct iio_dev *indio_dev, bool enable) | 156 | int adis16209_set_irq(struct iio_dev *indio_dev, bool enable) |
174 | { | 157 | { |
175 | int ret = 0; | 158 | int ret = 0; |
176 | u16 msc; | 159 | u16 msc; |
177 | 160 | ||
178 | ret = adis16209_spi_read_reg_16(indio_dev, ADIS16209_MSC_CTRL, &msc); | 161 | ret = adis16209_spi_read_reg_16(indio_dev, ADIS16209_MSC_CTRL, &msc); |
179 | if (ret) | 162 | if (ret) |
180 | goto error_ret; | 163 | goto error_ret; |
181 | 164 | ||
182 | msc |= ADIS16209_MSC_CTRL_ACTIVE_HIGH; | 165 | msc |= ADIS16209_MSC_CTRL_ACTIVE_HIGH; |
183 | msc &= ~ADIS16209_MSC_CTRL_DATA_RDY_DIO2; | 166 | msc &= ~ADIS16209_MSC_CTRL_DATA_RDY_DIO2; |
184 | if (enable) | 167 | if (enable) |
185 | msc |= ADIS16209_MSC_CTRL_DATA_RDY_EN; | 168 | msc |= ADIS16209_MSC_CTRL_DATA_RDY_EN; |
186 | else | 169 | else |
187 | msc &= ~ADIS16209_MSC_CTRL_DATA_RDY_EN; | 170 | msc &= ~ADIS16209_MSC_CTRL_DATA_RDY_EN; |
188 | 171 | ||
189 | ret = adis16209_spi_write_reg_16(indio_dev, ADIS16209_MSC_CTRL, msc); | 172 | ret = adis16209_spi_write_reg_16(indio_dev, ADIS16209_MSC_CTRL, msc); |
190 | 173 | ||
191 | error_ret: | 174 | error_ret: |
192 | return ret; | 175 | return ret; |
193 | } | 176 | } |
194 | 177 | ||
195 | static int adis16209_check_status(struct iio_dev *indio_dev) | 178 | static int adis16209_check_status(struct iio_dev *indio_dev) |
196 | { | 179 | { |
197 | u16 status; | 180 | u16 status; |
198 | int ret; | 181 | int ret; |
199 | 182 | ||
200 | ret = adis16209_spi_read_reg_16(indio_dev, | 183 | ret = adis16209_spi_read_reg_16(indio_dev, |
201 | ADIS16209_DIAG_STAT, &status); | 184 | ADIS16209_DIAG_STAT, &status); |
202 | if (ret < 0) { | 185 | if (ret < 0) { |
203 | dev_err(&indio_dev->dev, "Reading status failed\n"); | 186 | dev_err(&indio_dev->dev, "Reading status failed\n"); |
204 | goto error_ret; | 187 | goto error_ret; |
205 | } | 188 | } |
206 | ret = status & 0x1F; | 189 | ret = status & 0x1F; |
207 | 190 | ||
208 | if (status & ADIS16209_DIAG_STAT_SELFTEST_FAIL) | 191 | if (status & ADIS16209_DIAG_STAT_SELFTEST_FAIL) |
209 | dev_err(&indio_dev->dev, "Self test failure\n"); | 192 | dev_err(&indio_dev->dev, "Self test failure\n"); |
210 | if (status & ADIS16209_DIAG_STAT_SPI_FAIL) | 193 | if (status & ADIS16209_DIAG_STAT_SPI_FAIL) |
211 | dev_err(&indio_dev->dev, "SPI failure\n"); | 194 | dev_err(&indio_dev->dev, "SPI failure\n"); |
212 | if (status & ADIS16209_DIAG_STAT_FLASH_UPT) | 195 | if (status & ADIS16209_DIAG_STAT_FLASH_UPT) |
213 | dev_err(&indio_dev->dev, "Flash update failed\n"); | 196 | dev_err(&indio_dev->dev, "Flash update failed\n"); |
214 | if (status & ADIS16209_DIAG_STAT_POWER_HIGH) | 197 | if (status & ADIS16209_DIAG_STAT_POWER_HIGH) |
215 | dev_err(&indio_dev->dev, "Power supply above 3.625V\n"); | 198 | dev_err(&indio_dev->dev, "Power supply above 3.625V\n"); |
216 | if (status & ADIS16209_DIAG_STAT_POWER_LOW) | 199 | if (status & ADIS16209_DIAG_STAT_POWER_LOW) |
217 | dev_err(&indio_dev->dev, "Power supply below 3.15V\n"); | 200 | dev_err(&indio_dev->dev, "Power supply below 3.15V\n"); |
218 | 201 | ||
219 | error_ret: | 202 | error_ret: |
220 | return ret; | 203 | return ret; |
221 | } | 204 | } |
222 | 205 | ||
223 | static int adis16209_self_test(struct iio_dev *indio_dev) | 206 | static int adis16209_self_test(struct iio_dev *indio_dev) |
224 | { | 207 | { |
225 | int ret; | 208 | int ret; |
226 | ret = adis16209_spi_write_reg_16(indio_dev, | 209 | ret = adis16209_spi_write_reg_16(indio_dev, |
227 | ADIS16209_MSC_CTRL, | 210 | ADIS16209_MSC_CTRL, |
228 | ADIS16209_MSC_CTRL_SELF_TEST_EN); | 211 | ADIS16209_MSC_CTRL_SELF_TEST_EN); |
229 | if (ret) { | 212 | if (ret) { |
230 | dev_err(&indio_dev->dev, "problem starting self test"); | 213 | dev_err(&indio_dev->dev, "problem starting self test"); |
231 | goto err_ret; | 214 | goto err_ret; |
232 | } | 215 | } |
233 | 216 | ||
234 | adis16209_check_status(indio_dev); | 217 | adis16209_check_status(indio_dev); |
235 | 218 | ||
236 | err_ret: | 219 | err_ret: |
237 | return ret; | 220 | return ret; |
238 | } | 221 | } |
239 | 222 | ||
240 | static int adis16209_initial_setup(struct iio_dev *indio_dev) | 223 | static int adis16209_initial_setup(struct iio_dev *indio_dev) |
241 | { | 224 | { |
242 | int ret; | 225 | int ret; |
243 | 226 | ||
244 | /* Disable IRQ */ | 227 | /* Disable IRQ */ |
245 | ret = adis16209_set_irq(indio_dev, false); | 228 | ret = adis16209_set_irq(indio_dev, false); |
246 | if (ret) { | 229 | if (ret) { |
247 | dev_err(&indio_dev->dev, "disable irq failed"); | 230 | dev_err(&indio_dev->dev, "disable irq failed"); |
248 | goto err_ret; | 231 | goto err_ret; |
249 | } | 232 | } |
250 | 233 | ||
251 | /* Do self test */ | 234 | /* Do self test */ |
252 | ret = adis16209_self_test(indio_dev); | 235 | ret = adis16209_self_test(indio_dev); |
253 | if (ret) { | 236 | if (ret) { |
254 | dev_err(&indio_dev->dev, "self test failure"); | 237 | dev_err(&indio_dev->dev, "self test failure"); |
255 | goto err_ret; | 238 | goto err_ret; |
256 | } | 239 | } |
257 | 240 | ||
258 | /* Read status register to check the result */ | 241 | /* Read status register to check the result */ |
259 | ret = adis16209_check_status(indio_dev); | 242 | ret = adis16209_check_status(indio_dev); |
260 | if (ret) { | 243 | if (ret) { |
261 | adis16209_reset(indio_dev); | 244 | adis16209_reset(indio_dev); |
262 | dev_err(&indio_dev->dev, "device not playing ball -> reset"); | 245 | dev_err(&indio_dev->dev, "device not playing ball -> reset"); |
263 | msleep(ADIS16209_STARTUP_DELAY); | 246 | msleep(ADIS16209_STARTUP_DELAY); |
264 | ret = adis16209_check_status(indio_dev); | 247 | ret = adis16209_check_status(indio_dev); |
265 | if (ret) { | 248 | if (ret) { |
266 | dev_err(&indio_dev->dev, "giving up"); | 249 | dev_err(&indio_dev->dev, "giving up"); |
267 | goto err_ret; | 250 | goto err_ret; |
268 | } | 251 | } |
269 | } | 252 | } |
270 | 253 | ||
271 | err_ret: | 254 | err_ret: |
272 | return ret; | 255 | return ret; |
273 | } | 256 | } |
274 | 257 | ||
275 | enum adis16209_chan { | 258 | enum adis16209_chan { |
276 | in_supply, | 259 | in_supply, |
277 | temp, | 260 | temp, |
278 | accel_x, | 261 | accel_x, |
279 | accel_y, | 262 | accel_y, |
280 | incli_x, | 263 | incli_x, |
281 | incli_y, | 264 | incli_y, |
282 | in_aux, | 265 | in_aux, |
283 | rot, | 266 | rot, |
284 | }; | 267 | }; |
285 | 268 | ||
286 | static const u8 adis16209_addresses[8][2] = { | 269 | static const u8 adis16209_addresses[8][2] = { |
287 | [in_supply] = { ADIS16209_SUPPLY_OUT }, | 270 | [in_supply] = { ADIS16209_SUPPLY_OUT }, |
288 | [in_aux] = { ADIS16209_AUX_ADC }, | 271 | [in_aux] = { ADIS16209_AUX_ADC }, |
289 | [accel_x] = { ADIS16209_XACCL_OUT, ADIS16209_XACCL_NULL }, | 272 | [accel_x] = { ADIS16209_XACCL_OUT, ADIS16209_XACCL_NULL }, |
290 | [accel_y] = { ADIS16209_YACCL_OUT, ADIS16209_YACCL_NULL }, | 273 | [accel_y] = { ADIS16209_YACCL_OUT, ADIS16209_YACCL_NULL }, |
291 | [incli_x] = { ADIS16209_XINCL_OUT, ADIS16209_XINCL_NULL }, | 274 | [incli_x] = { ADIS16209_XINCL_OUT, ADIS16209_XINCL_NULL }, |
292 | [incli_y] = { ADIS16209_YINCL_OUT, ADIS16209_YINCL_NULL }, | 275 | [incli_y] = { ADIS16209_YINCL_OUT, ADIS16209_YINCL_NULL }, |
293 | [rot] = { ADIS16209_ROT_OUT }, | 276 | [rot] = { ADIS16209_ROT_OUT }, |
294 | [temp] = { ADIS16209_TEMP_OUT }, | 277 | [temp] = { ADIS16209_TEMP_OUT }, |
295 | }; | 278 | }; |
296 | 279 | ||
297 | static int adis16209_write_raw(struct iio_dev *indio_dev, | 280 | static int adis16209_write_raw(struct iio_dev *indio_dev, |
298 | struct iio_chan_spec const *chan, | 281 | struct iio_chan_spec const *chan, |
299 | int val, | 282 | int val, |
300 | int val2, | 283 | int val2, |
301 | long mask) | 284 | long mask) |
302 | { | 285 | { |
303 | int bits; | 286 | int bits; |
304 | s16 val16; | 287 | s16 val16; |
305 | u8 addr; | 288 | u8 addr; |
306 | switch (mask) { | 289 | switch (mask) { |
307 | case IIO_CHAN_INFO_CALIBBIAS: | 290 | case IIO_CHAN_INFO_CALIBBIAS: |
308 | switch (chan->type) { | 291 | switch (chan->type) { |
309 | case IIO_ACCEL: | 292 | case IIO_ACCEL: |
310 | case IIO_INCLI: | 293 | case IIO_INCLI: |
311 | bits = 14; | 294 | bits = 14; |
312 | break; | 295 | break; |
313 | default: | 296 | default: |
314 | return -EINVAL; | 297 | return -EINVAL; |
315 | }; | 298 | }; |
316 | val16 = val & ((1 << bits) - 1); | 299 | val16 = val & ((1 << bits) - 1); |
317 | addr = adis16209_addresses[chan->address][1]; | 300 | addr = adis16209_addresses[chan->address][1]; |
318 | return adis16209_spi_write_reg_16(indio_dev, addr, val16); | 301 | return adis16209_spi_write_reg_16(indio_dev, addr, val16); |
319 | } | 302 | } |
320 | return -EINVAL; | 303 | return -EINVAL; |
321 | } | 304 | } |
322 | 305 | ||
323 | static int adis16209_read_raw(struct iio_dev *indio_dev, | 306 | static int adis16209_read_raw(struct iio_dev *indio_dev, |
324 | struct iio_chan_spec const *chan, | 307 | struct iio_chan_spec const *chan, |
325 | int *val, int *val2, | 308 | int *val, int *val2, |
326 | long mask) | 309 | long mask) |
327 | { | 310 | { |
328 | int ret; | 311 | int ret; |
329 | int bits; | 312 | int bits; |
330 | u8 addr; | 313 | u8 addr; |
331 | s16 val16; | 314 | s16 val16; |
332 | 315 | ||
333 | switch (mask) { | 316 | switch (mask) { |
334 | case IIO_CHAN_INFO_RAW: | 317 | case IIO_CHAN_INFO_RAW: |
335 | mutex_lock(&indio_dev->mlock); | 318 | mutex_lock(&indio_dev->mlock); |
336 | addr = adis16209_addresses[chan->address][0]; | 319 | addr = adis16209_addresses[chan->address][0]; |
337 | ret = adis16209_spi_read_reg_16(indio_dev, addr, &val16); | 320 | ret = adis16209_spi_read_reg_16(indio_dev, addr, &val16); |
338 | if (ret) { | 321 | if (ret) { |
339 | mutex_unlock(&indio_dev->mlock); | 322 | mutex_unlock(&indio_dev->mlock); |
340 | return ret; | 323 | return ret; |
341 | } | 324 | } |
342 | 325 | ||
343 | if (val16 & ADIS16209_ERROR_ACTIVE) { | 326 | if (val16 & ADIS16209_ERROR_ACTIVE) { |
344 | ret = adis16209_check_status(indio_dev); | 327 | ret = adis16209_check_status(indio_dev); |
345 | if (ret) { | 328 | if (ret) { |
346 | mutex_unlock(&indio_dev->mlock); | 329 | mutex_unlock(&indio_dev->mlock); |
347 | return ret; | 330 | return ret; |
348 | } | 331 | } |
349 | } | 332 | } |
350 | val16 = val16 & ((1 << chan->scan_type.realbits) - 1); | 333 | val16 = val16 & ((1 << chan->scan_type.realbits) - 1); |
351 | if (chan->scan_type.sign == 's') | 334 | if (chan->scan_type.sign == 's') |
352 | val16 = (s16)(val16 << | 335 | val16 = (s16)(val16 << |
353 | (16 - chan->scan_type.realbits)) >> | 336 | (16 - chan->scan_type.realbits)) >> |
354 | (16 - chan->scan_type.realbits); | 337 | (16 - chan->scan_type.realbits); |
355 | *val = val16; | 338 | *val = val16; |
356 | mutex_unlock(&indio_dev->mlock); | 339 | mutex_unlock(&indio_dev->mlock); |
357 | return IIO_VAL_INT; | 340 | return IIO_VAL_INT; |
358 | case IIO_CHAN_INFO_SCALE: | 341 | case IIO_CHAN_INFO_SCALE: |
359 | switch (chan->type) { | 342 | switch (chan->type) { |
360 | case IIO_VOLTAGE: | 343 | case IIO_VOLTAGE: |
361 | *val = 0; | 344 | *val = 0; |
362 | if (chan->channel == 0) | 345 | if (chan->channel == 0) |
363 | *val2 = 305180; | 346 | *val2 = 305180; |
364 | else | 347 | else |
365 | *val2 = 610500; | 348 | *val2 = 610500; |
366 | return IIO_VAL_INT_PLUS_MICRO; | 349 | return IIO_VAL_INT_PLUS_MICRO; |
367 | case IIO_TEMP: | 350 | case IIO_TEMP: |
368 | *val = 0; | 351 | *val = 0; |
369 | *val2 = -470000; | 352 | *val2 = -470000; |
370 | return IIO_VAL_INT_PLUS_MICRO; | 353 | return IIO_VAL_INT_PLUS_MICRO; |
371 | case IIO_ACCEL: | 354 | case IIO_ACCEL: |
372 | *val = 0; | 355 | *val = 0; |
373 | *val2 = 2394; | 356 | *val2 = 2394; |
374 | return IIO_VAL_INT_PLUS_MICRO; | 357 | return IIO_VAL_INT_PLUS_MICRO; |
375 | case IIO_INCLI: | 358 | case IIO_INCLI: |
376 | *val = 0; | 359 | *val = 0; |
377 | *val2 = 436; | 360 | *val2 = 436; |
378 | return IIO_VAL_INT_PLUS_MICRO; | 361 | return IIO_VAL_INT_PLUS_MICRO; |
379 | default: | 362 | default: |
380 | return -EINVAL; | 363 | return -EINVAL; |
381 | } | 364 | } |
382 | break; | 365 | break; |
383 | case IIO_CHAN_INFO_OFFSET: | 366 | case IIO_CHAN_INFO_OFFSET: |
384 | *val = 25; | 367 | *val = 25; |
385 | return IIO_VAL_INT; | 368 | return IIO_VAL_INT; |
386 | case IIO_CHAN_INFO_CALIBBIAS: | 369 | case IIO_CHAN_INFO_CALIBBIAS: |
387 | switch (chan->type) { | 370 | switch (chan->type) { |
388 | case IIO_ACCEL: | 371 | case IIO_ACCEL: |
389 | bits = 14; | 372 | bits = 14; |
390 | break; | 373 | break; |
391 | default: | 374 | default: |
392 | return -EINVAL; | 375 | return -EINVAL; |
393 | }; | 376 | }; |
394 | mutex_lock(&indio_dev->mlock); | 377 | mutex_lock(&indio_dev->mlock); |
395 | addr = adis16209_addresses[chan->address][1]; | 378 | addr = adis16209_addresses[chan->address][1]; |
396 | ret = adis16209_spi_read_reg_16(indio_dev, addr, &val16); | 379 | ret = adis16209_spi_read_reg_16(indio_dev, addr, &val16); |
397 | if (ret) { | 380 | if (ret) { |
398 | mutex_unlock(&indio_dev->mlock); | 381 | mutex_unlock(&indio_dev->mlock); |
399 | return ret; | 382 | return ret; |
400 | } | 383 | } |
401 | val16 &= (1 << bits) - 1; | 384 | val16 &= (1 << bits) - 1; |
402 | val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); | 385 | val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); |
403 | *val = val16; | 386 | *val = val16; |
404 | mutex_unlock(&indio_dev->mlock); | 387 | mutex_unlock(&indio_dev->mlock); |
405 | return IIO_VAL_INT; | 388 | return IIO_VAL_INT; |
406 | } | 389 | } |
407 | return -EINVAL; | 390 | return -EINVAL; |
408 | } | 391 | } |
409 | 392 | ||
410 | static struct iio_chan_spec adis16209_channels[] = { | 393 | static struct iio_chan_spec adis16209_channels[] = { |
411 | { | 394 | { |
412 | .type = IIO_VOLTAGE, | 395 | .type = IIO_VOLTAGE, |
413 | .indexed = 1, | 396 | .indexed = 1, |
414 | .channel = 0, | 397 | .channel = 0, |
415 | .extend_name = "supply", | 398 | .extend_name = "supply", |
416 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 399 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
417 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 400 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
418 | .address = in_supply, | 401 | .address = in_supply, |
419 | .scan_index = ADIS16209_SCAN_SUPPLY, | 402 | .scan_index = ADIS16209_SCAN_SUPPLY, |
420 | .scan_type = { | 403 | .scan_type = { |
421 | .sign = 'u', | 404 | .sign = 'u', |
422 | .realbits = 14, | 405 | .realbits = 14, |
423 | .storagebits = 16, | 406 | .storagebits = 16, |
424 | }, | 407 | }, |
425 | }, { | 408 | }, { |
426 | .type = IIO_TEMP, | 409 | .type = IIO_TEMP, |
427 | .indexed = 0, | 410 | .indexed = 0, |
428 | .channel = 0, | 411 | .channel = 0, |
429 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 412 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
430 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | | 413 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | |
431 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, | 414 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, |
432 | .address = temp, | 415 | .address = temp, |
433 | .scan_index = ADIS16209_SCAN_TEMP, | 416 | .scan_index = ADIS16209_SCAN_TEMP, |
434 | .scan_type = { | 417 | .scan_type = { |
435 | .sign = 'u', | 418 | .sign = 'u', |
436 | .realbits = 12, | 419 | .realbits = 12, |
437 | .storagebits = 16, | 420 | .storagebits = 16, |
438 | }, | 421 | }, |
439 | }, { | 422 | }, { |
440 | .type = IIO_ACCEL, | 423 | .type = IIO_ACCEL, |
441 | .modified = 1, | 424 | .modified = 1, |
442 | .channel2 = IIO_MOD_X, | 425 | .channel2 = IIO_MOD_X, |
443 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 426 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
444 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 427 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
445 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, | 428 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, |
446 | .address = accel_x, | 429 | .address = accel_x, |
447 | .scan_index = ADIS16209_SCAN_ACC_X, | 430 | .scan_index = ADIS16209_SCAN_ACC_X, |
448 | .scan_type = { | 431 | .scan_type = { |
449 | .sign = 's', | 432 | .sign = 's', |
450 | .realbits = 14, | 433 | .realbits = 14, |
451 | .storagebits = 16, | 434 | .storagebits = 16, |
452 | }, | 435 | }, |
453 | }, { | 436 | }, { |
454 | .type = IIO_ACCEL, | 437 | .type = IIO_ACCEL, |
455 | .modified = 1, | 438 | .modified = 1, |
456 | .channel2 = IIO_MOD_Y, | 439 | .channel2 = IIO_MOD_Y, |
457 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 440 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
458 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 441 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
459 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, | 442 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, |
460 | .address = accel_y, | 443 | .address = accel_y, |
461 | .scan_index = ADIS16209_SCAN_ACC_Y, | 444 | .scan_index = ADIS16209_SCAN_ACC_Y, |
462 | .scan_type = { | 445 | .scan_type = { |
463 | .sign = 's', | 446 | .sign = 's', |
464 | .realbits = 14, | 447 | .realbits = 14, |
465 | .storagebits = 16, | 448 | .storagebits = 16, |
466 | }, | 449 | }, |
467 | }, { | 450 | }, { |
468 | .type = IIO_VOLTAGE, | 451 | .type = IIO_VOLTAGE, |
469 | .indexed = 1, | 452 | .indexed = 1, |
470 | .channel = 1, | 453 | .channel = 1, |
471 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 454 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
472 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 455 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
473 | .address = in_aux, | 456 | .address = in_aux, |
474 | .scan_index = ADIS16209_SCAN_AUX_ADC, | 457 | .scan_index = ADIS16209_SCAN_AUX_ADC, |
475 | .scan_type = { | 458 | .scan_type = { |
476 | .sign = 'u', | 459 | .sign = 'u', |
477 | .realbits = 12, | 460 | .realbits = 12, |
478 | .storagebits = 16, | 461 | .storagebits = 16, |
479 | }, | 462 | }, |
480 | }, { | 463 | }, { |
481 | .type = IIO_INCLI, | 464 | .type = IIO_INCLI, |
482 | .modified = 1, | 465 | .modified = 1, |
483 | .channel2 = IIO_MOD_X, | 466 | .channel2 = IIO_MOD_X, |
484 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 467 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
485 | IIO_CHAN_INFO_SCALE_SHARED_BIT, | 468 | IIO_CHAN_INFO_SCALE_SHARED_BIT, |
486 | .address = incli_x, | 469 | .address = incli_x, |
487 | .scan_index = ADIS16209_SCAN_INCLI_X, | 470 | .scan_index = ADIS16209_SCAN_INCLI_X, |
488 | .scan_type = { | 471 | .scan_type = { |
489 | .sign = 's', | 472 | .sign = 's', |
490 | .realbits = 14, | 473 | .realbits = 14, |
491 | .storagebits = 16, | 474 | .storagebits = 16, |
492 | }, | 475 | }, |
493 | }, { | 476 | }, { |
494 | .type = IIO_INCLI, | 477 | .type = IIO_INCLI, |
495 | .modified = 1, | 478 | .modified = 1, |
496 | .channel2 = IIO_MOD_Y, | 479 | .channel2 = IIO_MOD_Y, |
497 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 480 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
498 | IIO_CHAN_INFO_SCALE_SHARED_BIT, | 481 | IIO_CHAN_INFO_SCALE_SHARED_BIT, |
499 | .address = incli_y, | 482 | .address = incli_y, |
500 | .scan_index = ADIS16209_SCAN_INCLI_Y, | 483 | .scan_index = ADIS16209_SCAN_INCLI_Y, |
501 | .scan_type = { | 484 | .scan_type = { |
502 | .sign = 's', | 485 | .sign = 's', |
503 | .realbits = 14, | 486 | .realbits = 14, |
504 | .storagebits = 16, | 487 | .storagebits = 16, |
505 | }, | 488 | }, |
506 | }, { | 489 | }, { |
507 | .type = IIO_ROT, | 490 | .type = IIO_ROT, |
508 | .modified = 1, | 491 | .modified = 1, |
509 | .channel2 = IIO_MOD_X, | 492 | .channel2 = IIO_MOD_X, |
510 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, | 493 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, |
511 | .address = rot, | 494 | .address = rot, |
512 | .scan_index = ADIS16209_SCAN_ROT, | 495 | .scan_index = ADIS16209_SCAN_ROT, |
513 | .scan_type = { | 496 | .scan_type = { |
514 | .sign = 's', | 497 | .sign = 's', |
515 | .realbits = 14, | 498 | .realbits = 14, |
516 | .storagebits = 16, | 499 | .storagebits = 16, |
517 | }, | 500 | }, |
518 | }, | 501 | }, |
519 | IIO_CHAN_SOFT_TIMESTAMP(8) | 502 | IIO_CHAN_SOFT_TIMESTAMP(8) |
520 | }; | 503 | }; |
521 | 504 | ||
522 | static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16209_write_reset, 0); | ||
523 | |||
524 | static struct attribute *adis16209_attributes[] = { | ||
525 | &iio_dev_attr_reset.dev_attr.attr, | ||
526 | NULL | ||
527 | }; | ||
528 | |||
529 | static const struct attribute_group adis16209_attribute_group = { | ||
530 | .attrs = adis16209_attributes, | ||
531 | }; | ||
532 | |||
533 | static const struct iio_info adis16209_info = { | 505 | static const struct iio_info adis16209_info = { |
534 | .attrs = &adis16209_attribute_group, | ||
535 | .read_raw = &adis16209_read_raw, | 506 | .read_raw = &adis16209_read_raw, |
536 | .write_raw = &adis16209_write_raw, | 507 | .write_raw = &adis16209_write_raw, |
537 | .driver_module = THIS_MODULE, | 508 | .driver_module = THIS_MODULE, |
538 | }; | 509 | }; |
539 | 510 | ||
540 | static int __devinit adis16209_probe(struct spi_device *spi) | 511 | static int __devinit adis16209_probe(struct spi_device *spi) |
541 | { | 512 | { |
542 | int ret; | 513 | int ret; |
543 | struct adis16209_state *st; | 514 | struct adis16209_state *st; |
544 | struct iio_dev *indio_dev; | 515 | struct iio_dev *indio_dev; |
545 | 516 | ||
546 | /* setup the industrialio driver allocated elements */ | 517 | /* setup the industrialio driver allocated elements */ |
547 | indio_dev = iio_device_alloc(sizeof(*st)); | 518 | indio_dev = iio_device_alloc(sizeof(*st)); |
548 | if (indio_dev == NULL) { | 519 | if (indio_dev == NULL) { |
549 | ret = -ENOMEM; | 520 | ret = -ENOMEM; |
550 | goto error_ret; | 521 | goto error_ret; |
551 | } | 522 | } |
552 | st = iio_priv(indio_dev); | 523 | st = iio_priv(indio_dev); |
553 | /* this is only used for removal purposes */ | 524 | /* this is only used for removal purposes */ |
554 | spi_set_drvdata(spi, indio_dev); | 525 | spi_set_drvdata(spi, indio_dev); |
555 | st->us = spi; | 526 | st->us = spi; |
556 | mutex_init(&st->buf_lock); | 527 | mutex_init(&st->buf_lock); |
557 | 528 | ||
558 | indio_dev->name = spi->dev.driver->name; | 529 | indio_dev->name = spi->dev.driver->name; |
559 | indio_dev->dev.parent = &spi->dev; | 530 | indio_dev->dev.parent = &spi->dev; |
560 | indio_dev->info = &adis16209_info; | 531 | indio_dev->info = &adis16209_info; |
561 | indio_dev->channels = adis16209_channels; | 532 | indio_dev->channels = adis16209_channels; |
562 | indio_dev->num_channels = ARRAY_SIZE(adis16209_channels); | 533 | indio_dev->num_channels = ARRAY_SIZE(adis16209_channels); |
563 | indio_dev->modes = INDIO_DIRECT_MODE; | 534 | indio_dev->modes = INDIO_DIRECT_MODE; |
564 | 535 | ||
565 | ret = adis16209_configure_ring(indio_dev); | 536 | ret = adis16209_configure_ring(indio_dev); |
566 | if (ret) | 537 | if (ret) |
567 | goto error_free_dev; | 538 | goto error_free_dev; |
568 | 539 | ||
569 | ret = iio_buffer_register(indio_dev, | 540 | ret = iio_buffer_register(indio_dev, |
570 | adis16209_channels, | 541 | adis16209_channels, |
571 | ARRAY_SIZE(adis16209_channels)); | 542 | ARRAY_SIZE(adis16209_channels)); |
572 | if (ret) { | 543 | if (ret) { |
573 | printk(KERN_ERR "failed to initialize the ring\n"); | 544 | printk(KERN_ERR "failed to initialize the ring\n"); |
574 | goto error_unreg_ring_funcs; | 545 | goto error_unreg_ring_funcs; |
575 | } | 546 | } |
576 | 547 | ||
577 | if (spi->irq) { | 548 | if (spi->irq) { |
578 | ret = adis16209_probe_trigger(indio_dev); | 549 | ret = adis16209_probe_trigger(indio_dev); |
579 | if (ret) | 550 | if (ret) |
580 | goto error_uninitialize_ring; | 551 | goto error_uninitialize_ring; |
581 | } | 552 | } |
582 | 553 | ||
583 | /* Get the device into a sane initial state */ | 554 | /* Get the device into a sane initial state */ |
584 | ret = adis16209_initial_setup(indio_dev); | 555 | ret = adis16209_initial_setup(indio_dev); |
585 | if (ret) | 556 | if (ret) |
586 | goto error_remove_trigger; | 557 | goto error_remove_trigger; |
587 | ret = iio_device_register(indio_dev); | 558 | ret = iio_device_register(indio_dev); |
588 | if (ret) | 559 | if (ret) |
589 | goto error_remove_trigger; | 560 | goto error_remove_trigger; |
590 | 561 | ||
591 | return 0; | 562 | return 0; |
592 | 563 | ||
593 | error_remove_trigger: | 564 | error_remove_trigger: |
594 | adis16209_remove_trigger(indio_dev); | 565 | adis16209_remove_trigger(indio_dev); |
595 | error_uninitialize_ring: | 566 | error_uninitialize_ring: |
596 | iio_buffer_unregister(indio_dev); | 567 | iio_buffer_unregister(indio_dev); |
597 | error_unreg_ring_funcs: | 568 | error_unreg_ring_funcs: |
598 | adis16209_unconfigure_ring(indio_dev); | 569 | adis16209_unconfigure_ring(indio_dev); |
599 | error_free_dev: | 570 | error_free_dev: |
600 | iio_device_free(indio_dev); | 571 | iio_device_free(indio_dev); |
601 | error_ret: | 572 | error_ret: |
602 | return ret; | 573 | return ret; |
603 | } | 574 | } |
604 | 575 | ||
605 | static int adis16209_remove(struct spi_device *spi) | 576 | static int adis16209_remove(struct spi_device *spi) |
606 | { | 577 | { |
607 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | 578 | struct iio_dev *indio_dev = spi_get_drvdata(spi); |
608 | 579 | ||
609 | iio_device_unregister(indio_dev); | 580 | iio_device_unregister(indio_dev); |
610 | adis16209_remove_trigger(indio_dev); | 581 | adis16209_remove_trigger(indio_dev); |
611 | iio_buffer_unregister(indio_dev); | 582 | iio_buffer_unregister(indio_dev); |
612 | adis16209_unconfigure_ring(indio_dev); | 583 | adis16209_unconfigure_ring(indio_dev); |
613 | iio_device_free(indio_dev); | 584 | iio_device_free(indio_dev); |
614 | 585 | ||
615 | return 0; | 586 | return 0; |
616 | } | 587 | } |
617 | 588 | ||
618 | static struct spi_driver adis16209_driver = { | 589 | static struct spi_driver adis16209_driver = { |
619 | .driver = { | 590 | .driver = { |
620 | .name = "adis16209", | 591 | .name = "adis16209", |
621 | .owner = THIS_MODULE, | 592 | .owner = THIS_MODULE, |
622 | }, | 593 | }, |
623 | .probe = adis16209_probe, | 594 | .probe = adis16209_probe, |
624 | .remove = __devexit_p(adis16209_remove), | 595 | .remove = __devexit_p(adis16209_remove), |
625 | }; | 596 | }; |
626 | module_spi_driver(adis16209_driver); | 597 | module_spi_driver(adis16209_driver); |
627 | 598 | ||
628 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | 599 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); |
629 | MODULE_DESCRIPTION("Analog Devices ADIS16209 Digital Vibration Sensor driver"); | 600 | MODULE_DESCRIPTION("Analog Devices ADIS16209 Digital Vibration Sensor driver"); |
630 | MODULE_LICENSE("GPL v2"); | 601 | MODULE_LICENSE("GPL v2"); |
631 | MODULE_ALIAS("spi:adis16209"); | 602 | MODULE_ALIAS("spi:adis16209"); |
632 | 603 |
drivers/staging/iio/accel/adis16220_core.c
1 | /* | 1 | /* |
2 | * ADIS16220 Programmable Digital Vibration Sensor driver | 2 | * ADIS16220 Programmable Digital Vibration Sensor driver |
3 | * | 3 | * |
4 | * Copyright 2010 Analog Devices Inc. | 4 | * Copyright 2010 Analog Devices Inc. |
5 | * | 5 | * |
6 | * Licensed under the GPL-2 or later. | 6 | * Licensed under the GPL-2 or later. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
10 | #include <linux/mutex.h> | 10 | #include <linux/mutex.h> |
11 | #include <linux/device.h> | 11 | #include <linux/device.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/spi/spi.h> | 13 | #include <linux/spi/spi.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/sysfs.h> | 15 | #include <linux/sysfs.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | 17 | ||
18 | #include <linux/iio/iio.h> | 18 | #include <linux/iio/iio.h> |
19 | #include <linux/iio/sysfs.h> | 19 | #include <linux/iio/sysfs.h> |
20 | 20 | ||
21 | #include "adis16220.h" | 21 | #include "adis16220.h" |
22 | 22 | ||
23 | #define DRIVER_NAME "adis16220" | 23 | #define DRIVER_NAME "adis16220" |
24 | 24 | ||
25 | /** | 25 | /** |
26 | * adis16220_spi_write_reg_8() - write single byte to a register | 26 | * adis16220_spi_write_reg_8() - write single byte to a register |
27 | * @indio_dev: iio device associated with child of actual device | 27 | * @indio_dev: iio device associated with child of actual device |
28 | * @reg_address: the address of the register to be written | 28 | * @reg_address: the address of the register to be written |
29 | * @val: the value to write | 29 | * @val: the value to write |
30 | **/ | 30 | **/ |
31 | static int adis16220_spi_write_reg_8(struct iio_dev *indio_dev, | 31 | static int adis16220_spi_write_reg_8(struct iio_dev *indio_dev, |
32 | u8 reg_address, | 32 | u8 reg_address, |
33 | u8 val) | 33 | u8 val) |
34 | { | 34 | { |
35 | int ret; | 35 | int ret; |
36 | struct adis16220_state *st = iio_priv(indio_dev); | 36 | struct adis16220_state *st = iio_priv(indio_dev); |
37 | 37 | ||
38 | mutex_lock(&st->buf_lock); | 38 | mutex_lock(&st->buf_lock); |
39 | st->tx[0] = ADIS16220_WRITE_REG(reg_address); | 39 | st->tx[0] = ADIS16220_WRITE_REG(reg_address); |
40 | st->tx[1] = val; | 40 | st->tx[1] = val; |
41 | 41 | ||
42 | ret = spi_write(st->us, st->tx, 2); | 42 | ret = spi_write(st->us, st->tx, 2); |
43 | mutex_unlock(&st->buf_lock); | 43 | mutex_unlock(&st->buf_lock); |
44 | 44 | ||
45 | return ret; | 45 | return ret; |
46 | } | 46 | } |
47 | 47 | ||
48 | /** | 48 | /** |
49 | * adis16220_spi_write_reg_16() - write 2 bytes to a pair of registers | 49 | * adis16220_spi_write_reg_16() - write 2 bytes to a pair of registers |
50 | * @indio_dev: iio device associated with child of actual device | 50 | * @indio_dev: iio device associated with child of actual device |
51 | * @reg_address: the address of the lower of the two registers. Second register | 51 | * @reg_address: the address of the lower of the two registers. Second register |
52 | * is assumed to have address one greater. | 52 | * is assumed to have address one greater. |
53 | * @val: value to be written | 53 | * @val: value to be written |
54 | **/ | 54 | **/ |
55 | static int adis16220_spi_write_reg_16(struct iio_dev *indio_dev, | 55 | static int adis16220_spi_write_reg_16(struct iio_dev *indio_dev, |
56 | u8 lower_reg_address, | 56 | u8 lower_reg_address, |
57 | u16 value) | 57 | u16 value) |
58 | { | 58 | { |
59 | int ret; | 59 | int ret; |
60 | struct spi_message msg; | 60 | struct spi_message msg; |
61 | struct adis16220_state *st = iio_priv(indio_dev); | 61 | struct adis16220_state *st = iio_priv(indio_dev); |
62 | struct spi_transfer xfers[] = { | 62 | struct spi_transfer xfers[] = { |
63 | { | 63 | { |
64 | .tx_buf = st->tx, | 64 | .tx_buf = st->tx, |
65 | .bits_per_word = 8, | 65 | .bits_per_word = 8, |
66 | .len = 2, | 66 | .len = 2, |
67 | .cs_change = 1, | 67 | .cs_change = 1, |
68 | .delay_usecs = 35, | 68 | .delay_usecs = 35, |
69 | }, { | 69 | }, { |
70 | .tx_buf = st->tx + 2, | 70 | .tx_buf = st->tx + 2, |
71 | .bits_per_word = 8, | 71 | .bits_per_word = 8, |
72 | .len = 2, | 72 | .len = 2, |
73 | .delay_usecs = 35, | 73 | .delay_usecs = 35, |
74 | }, | 74 | }, |
75 | }; | 75 | }; |
76 | 76 | ||
77 | mutex_lock(&st->buf_lock); | 77 | mutex_lock(&st->buf_lock); |
78 | st->tx[0] = ADIS16220_WRITE_REG(lower_reg_address); | 78 | st->tx[0] = ADIS16220_WRITE_REG(lower_reg_address); |
79 | st->tx[1] = value & 0xFF; | 79 | st->tx[1] = value & 0xFF; |
80 | st->tx[2] = ADIS16220_WRITE_REG(lower_reg_address + 1); | 80 | st->tx[2] = ADIS16220_WRITE_REG(lower_reg_address + 1); |
81 | st->tx[3] = (value >> 8) & 0xFF; | 81 | st->tx[3] = (value >> 8) & 0xFF; |
82 | 82 | ||
83 | spi_message_init(&msg); | 83 | spi_message_init(&msg); |
84 | spi_message_add_tail(&xfers[0], &msg); | 84 | spi_message_add_tail(&xfers[0], &msg); |
85 | spi_message_add_tail(&xfers[1], &msg); | 85 | spi_message_add_tail(&xfers[1], &msg); |
86 | ret = spi_sync(st->us, &msg); | 86 | ret = spi_sync(st->us, &msg); |
87 | mutex_unlock(&st->buf_lock); | 87 | mutex_unlock(&st->buf_lock); |
88 | 88 | ||
89 | return ret; | 89 | return ret; |
90 | } | 90 | } |
91 | 91 | ||
92 | /** | 92 | /** |
93 | * adis16220_spi_read_reg_16() - read 2 bytes from a 16-bit register | 93 | * adis16220_spi_read_reg_16() - read 2 bytes from a 16-bit register |
94 | * @indio_dev: iio device associated with child of actual device | 94 | * @indio_dev: iio device associated with child of actual device |
95 | * @reg_address: the address of the lower of the two registers. Second register | 95 | * @reg_address: the address of the lower of the two registers. Second register |
96 | * is assumed to have address one greater. | 96 | * is assumed to have address one greater. |
97 | * @val: somewhere to pass back the value read | 97 | * @val: somewhere to pass back the value read |
98 | **/ | 98 | **/ |
99 | static int adis16220_spi_read_reg_16(struct iio_dev *indio_dev, | 99 | static int adis16220_spi_read_reg_16(struct iio_dev *indio_dev, |
100 | u8 lower_reg_address, | 100 | u8 lower_reg_address, |
101 | u16 *val) | 101 | u16 *val) |
102 | { | 102 | { |
103 | struct spi_message msg; | 103 | struct spi_message msg; |
104 | struct adis16220_state *st = iio_priv(indio_dev); | 104 | struct adis16220_state *st = iio_priv(indio_dev); |
105 | int ret; | 105 | int ret; |
106 | struct spi_transfer xfers[] = { | 106 | struct spi_transfer xfers[] = { |
107 | { | 107 | { |
108 | .tx_buf = st->tx, | 108 | .tx_buf = st->tx, |
109 | .bits_per_word = 8, | 109 | .bits_per_word = 8, |
110 | .len = 2, | 110 | .len = 2, |
111 | .cs_change = 1, | 111 | .cs_change = 1, |
112 | .delay_usecs = 35, | 112 | .delay_usecs = 35, |
113 | }, { | 113 | }, { |
114 | .rx_buf = st->rx, | 114 | .rx_buf = st->rx, |
115 | .bits_per_word = 8, | 115 | .bits_per_word = 8, |
116 | .len = 2, | 116 | .len = 2, |
117 | .cs_change = 1, | 117 | .cs_change = 1, |
118 | .delay_usecs = 35, | 118 | .delay_usecs = 35, |
119 | }, | 119 | }, |
120 | }; | 120 | }; |
121 | 121 | ||
122 | mutex_lock(&st->buf_lock); | 122 | mutex_lock(&st->buf_lock); |
123 | st->tx[0] = ADIS16220_READ_REG(lower_reg_address); | 123 | st->tx[0] = ADIS16220_READ_REG(lower_reg_address); |
124 | st->tx[1] = 0; | 124 | st->tx[1] = 0; |
125 | 125 | ||
126 | spi_message_init(&msg); | 126 | spi_message_init(&msg); |
127 | spi_message_add_tail(&xfers[0], &msg); | 127 | spi_message_add_tail(&xfers[0], &msg); |
128 | spi_message_add_tail(&xfers[1], &msg); | 128 | spi_message_add_tail(&xfers[1], &msg); |
129 | ret = spi_sync(st->us, &msg); | 129 | ret = spi_sync(st->us, &msg); |
130 | if (ret) { | 130 | if (ret) { |
131 | dev_err(&st->us->dev, | 131 | dev_err(&st->us->dev, |
132 | "problem when reading 16 bit register 0x%02X", | 132 | "problem when reading 16 bit register 0x%02X", |
133 | lower_reg_address); | 133 | lower_reg_address); |
134 | goto error_ret; | 134 | goto error_ret; |
135 | } | 135 | } |
136 | *val = (st->rx[0] << 8) | st->rx[1]; | 136 | *val = (st->rx[0] << 8) | st->rx[1]; |
137 | 137 | ||
138 | error_ret: | 138 | error_ret: |
139 | mutex_unlock(&st->buf_lock); | 139 | mutex_unlock(&st->buf_lock); |
140 | return ret; | 140 | return ret; |
141 | } | 141 | } |
142 | 142 | ||
143 | static ssize_t adis16220_read_16bit(struct device *dev, | 143 | static ssize_t adis16220_read_16bit(struct device *dev, |
144 | struct device_attribute *attr, | 144 | struct device_attribute *attr, |
145 | char *buf) | 145 | char *buf) |
146 | { | 146 | { |
147 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | 147 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
148 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 148 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
149 | ssize_t ret; | 149 | ssize_t ret; |
150 | s16 val = 0; | 150 | s16 val = 0; |
151 | 151 | ||
152 | /* Take the iio_dev status lock */ | 152 | /* Take the iio_dev status lock */ |
153 | mutex_lock(&indio_dev->mlock); | 153 | mutex_lock(&indio_dev->mlock); |
154 | ret = adis16220_spi_read_reg_16(indio_dev, this_attr->address, | 154 | ret = adis16220_spi_read_reg_16(indio_dev, this_attr->address, |
155 | (u16 *)&val); | 155 | (u16 *)&val); |
156 | mutex_unlock(&indio_dev->mlock); | 156 | mutex_unlock(&indio_dev->mlock); |
157 | if (ret) | 157 | if (ret) |
158 | return ret; | 158 | return ret; |
159 | return sprintf(buf, "%d\n", val); | 159 | return sprintf(buf, "%d\n", val); |
160 | } | 160 | } |
161 | 161 | ||
162 | static ssize_t adis16220_write_16bit(struct device *dev, | 162 | static ssize_t adis16220_write_16bit(struct device *dev, |
163 | struct device_attribute *attr, | 163 | struct device_attribute *attr, |
164 | const char *buf, | 164 | const char *buf, |
165 | size_t len) | 165 | size_t len) |
166 | { | 166 | { |
167 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 167 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
168 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | 168 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
169 | int ret; | 169 | int ret; |
170 | u16 val; | 170 | u16 val; |
171 | 171 | ||
172 | ret = kstrtou16(buf, 10, &val); | 172 | ret = kstrtou16(buf, 10, &val); |
173 | if (ret) | 173 | if (ret) |
174 | goto error_ret; | 174 | goto error_ret; |
175 | ret = adis16220_spi_write_reg_16(indio_dev, this_attr->address, val); | 175 | ret = adis16220_spi_write_reg_16(indio_dev, this_attr->address, val); |
176 | 176 | ||
177 | error_ret: | 177 | error_ret: |
178 | return ret ? ret : len; | 178 | return ret ? ret : len; |
179 | } | 179 | } |
180 | 180 | ||
181 | static int adis16220_capture(struct iio_dev *indio_dev) | 181 | static int adis16220_capture(struct iio_dev *indio_dev) |
182 | { | 182 | { |
183 | int ret; | 183 | int ret; |
184 | ret = adis16220_spi_write_reg_16(indio_dev, | 184 | ret = adis16220_spi_write_reg_16(indio_dev, |
185 | ADIS16220_GLOB_CMD, | 185 | ADIS16220_GLOB_CMD, |
186 | 0xBF08); /* initiates a manual data capture */ | 186 | 0xBF08); /* initiates a manual data capture */ |
187 | if (ret) | 187 | if (ret) |
188 | dev_err(&indio_dev->dev, "problem beginning capture"); | 188 | dev_err(&indio_dev->dev, "problem beginning capture"); |
189 | 189 | ||
190 | msleep(10); /* delay for capture to finish */ | 190 | msleep(10); /* delay for capture to finish */ |
191 | 191 | ||
192 | return ret; | 192 | return ret; |
193 | } | 193 | } |
194 | 194 | ||
195 | static int adis16220_reset(struct iio_dev *indio_dev) | 195 | static int adis16220_reset(struct iio_dev *indio_dev) |
196 | { | 196 | { |
197 | int ret; | 197 | int ret; |
198 | ret = adis16220_spi_write_reg_8(indio_dev, | 198 | ret = adis16220_spi_write_reg_8(indio_dev, |
199 | ADIS16220_GLOB_CMD, | 199 | ADIS16220_GLOB_CMD, |
200 | ADIS16220_GLOB_CMD_SW_RESET); | 200 | ADIS16220_GLOB_CMD_SW_RESET); |
201 | if (ret) | 201 | if (ret) |
202 | dev_err(&indio_dev->dev, "problem resetting device"); | 202 | dev_err(&indio_dev->dev, "problem resetting device"); |
203 | 203 | ||
204 | return ret; | 204 | return ret; |
205 | } | 205 | } |
206 | 206 | ||
207 | static ssize_t adis16220_write_reset(struct device *dev, | ||
208 | struct device_attribute *attr, | ||
209 | const char *buf, size_t len) | ||
210 | { | ||
211 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
212 | bool val; | ||
213 | int ret; | ||
214 | |||
215 | ret = strtobool(buf, &val); | ||
216 | if (ret) | ||
217 | return ret; | ||
218 | if (!val) | ||
219 | return -EINVAL; | ||
220 | |||
221 | ret = adis16220_reset(indio_dev); | ||
222 | if (ret) | ||
223 | return ret; | ||
224 | return len; | ||
225 | } | ||
226 | |||
227 | static ssize_t adis16220_write_capture(struct device *dev, | 207 | static ssize_t adis16220_write_capture(struct device *dev, |
228 | struct device_attribute *attr, | 208 | struct device_attribute *attr, |
229 | const char *buf, size_t len) | 209 | const char *buf, size_t len) |
230 | { | 210 | { |
231 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 211 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
232 | bool val; | 212 | bool val; |
233 | int ret; | 213 | int ret; |
234 | 214 | ||
235 | ret = strtobool(buf, &val); | 215 | ret = strtobool(buf, &val); |
236 | if (ret) | 216 | if (ret) |
237 | return ret; | 217 | return ret; |
238 | if (!val) | 218 | if (!val) |
239 | return -EINVAL; | 219 | return -EINVAL; |
240 | ret = adis16220_capture(indio_dev); | 220 | ret = adis16220_capture(indio_dev); |
241 | if (ret) | 221 | if (ret) |
242 | return ret; | 222 | return ret; |
243 | 223 | ||
244 | return len; | 224 | return len; |
245 | } | 225 | } |
246 | 226 | ||
247 | static int adis16220_check_status(struct iio_dev *indio_dev) | 227 | static int adis16220_check_status(struct iio_dev *indio_dev) |
248 | { | 228 | { |
249 | u16 status; | 229 | u16 status; |
250 | int ret; | 230 | int ret; |
251 | 231 | ||
252 | ret = adis16220_spi_read_reg_16(indio_dev, ADIS16220_DIAG_STAT, | 232 | ret = adis16220_spi_read_reg_16(indio_dev, ADIS16220_DIAG_STAT, |
253 | &status); | 233 | &status); |
254 | 234 | ||
255 | if (ret < 0) { | 235 | if (ret < 0) { |
256 | dev_err(&indio_dev->dev, "Reading status failed\n"); | 236 | dev_err(&indio_dev->dev, "Reading status failed\n"); |
257 | goto error_ret; | 237 | goto error_ret; |
258 | } | 238 | } |
259 | ret = status & 0x7F; | 239 | ret = status & 0x7F; |
260 | 240 | ||
261 | if (status & ADIS16220_DIAG_STAT_VIOLATION) | 241 | if (status & ADIS16220_DIAG_STAT_VIOLATION) |
262 | dev_err(&indio_dev->dev, | 242 | dev_err(&indio_dev->dev, |
263 | "Capture period violation/interruption\n"); | 243 | "Capture period violation/interruption\n"); |
264 | if (status & ADIS16220_DIAG_STAT_SPI_FAIL) | 244 | if (status & ADIS16220_DIAG_STAT_SPI_FAIL) |
265 | dev_err(&indio_dev->dev, "SPI failure\n"); | 245 | dev_err(&indio_dev->dev, "SPI failure\n"); |
266 | if (status & ADIS16220_DIAG_STAT_FLASH_UPT) | 246 | if (status & ADIS16220_DIAG_STAT_FLASH_UPT) |
267 | dev_err(&indio_dev->dev, "Flash update failed\n"); | 247 | dev_err(&indio_dev->dev, "Flash update failed\n"); |
268 | if (status & ADIS16220_DIAG_STAT_POWER_HIGH) | 248 | if (status & ADIS16220_DIAG_STAT_POWER_HIGH) |
269 | dev_err(&indio_dev->dev, "Power supply above 3.625V\n"); | 249 | dev_err(&indio_dev->dev, "Power supply above 3.625V\n"); |
270 | if (status & ADIS16220_DIAG_STAT_POWER_LOW) | 250 | if (status & ADIS16220_DIAG_STAT_POWER_LOW) |
271 | dev_err(&indio_dev->dev, "Power supply below 3.15V\n"); | 251 | dev_err(&indio_dev->dev, "Power supply below 3.15V\n"); |
272 | 252 | ||
273 | error_ret: | 253 | error_ret: |
274 | return ret; | 254 | return ret; |
275 | } | 255 | } |
276 | 256 | ||
277 | static int adis16220_self_test(struct iio_dev *indio_dev) | 257 | static int adis16220_self_test(struct iio_dev *indio_dev) |
278 | { | 258 | { |
279 | int ret; | 259 | int ret; |
280 | ret = adis16220_spi_write_reg_16(indio_dev, | 260 | ret = adis16220_spi_write_reg_16(indio_dev, |
281 | ADIS16220_MSC_CTRL, | 261 | ADIS16220_MSC_CTRL, |
282 | ADIS16220_MSC_CTRL_SELF_TEST_EN); | 262 | ADIS16220_MSC_CTRL_SELF_TEST_EN); |
283 | if (ret) { | 263 | if (ret) { |
284 | dev_err(&indio_dev->dev, "problem starting self test"); | 264 | dev_err(&indio_dev->dev, "problem starting self test"); |
285 | goto err_ret; | 265 | goto err_ret; |
286 | } | 266 | } |
287 | 267 | ||
288 | adis16220_check_status(indio_dev); | 268 | adis16220_check_status(indio_dev); |
289 | 269 | ||
290 | err_ret: | 270 | err_ret: |
291 | return ret; | 271 | return ret; |
292 | } | 272 | } |
293 | 273 | ||
294 | static int adis16220_initial_setup(struct iio_dev *indio_dev) | 274 | static int adis16220_initial_setup(struct iio_dev *indio_dev) |
295 | { | 275 | { |
296 | int ret; | 276 | int ret; |
297 | 277 | ||
298 | /* Do self test */ | 278 | /* Do self test */ |
299 | ret = adis16220_self_test(indio_dev); | 279 | ret = adis16220_self_test(indio_dev); |
300 | if (ret) { | 280 | if (ret) { |
301 | dev_err(&indio_dev->dev, "self test failure"); | 281 | dev_err(&indio_dev->dev, "self test failure"); |
302 | goto err_ret; | 282 | goto err_ret; |
303 | } | 283 | } |
304 | 284 | ||
305 | /* Read status register to check the result */ | 285 | /* Read status register to check the result */ |
306 | ret = adis16220_check_status(indio_dev); | 286 | ret = adis16220_check_status(indio_dev); |
307 | if (ret) { | 287 | if (ret) { |
308 | adis16220_reset(indio_dev); | 288 | adis16220_reset(indio_dev); |
309 | dev_err(&indio_dev->dev, "device not playing ball -> reset"); | 289 | dev_err(&indio_dev->dev, "device not playing ball -> reset"); |
310 | msleep(ADIS16220_STARTUP_DELAY); | 290 | msleep(ADIS16220_STARTUP_DELAY); |
311 | ret = adis16220_check_status(indio_dev); | 291 | ret = adis16220_check_status(indio_dev); |
312 | if (ret) { | 292 | if (ret) { |
313 | dev_err(&indio_dev->dev, "giving up"); | 293 | dev_err(&indio_dev->dev, "giving up"); |
314 | goto err_ret; | 294 | goto err_ret; |
315 | } | 295 | } |
316 | } | 296 | } |
317 | 297 | ||
318 | err_ret: | 298 | err_ret: |
319 | return ret; | 299 | return ret; |
320 | } | 300 | } |
321 | 301 | ||
322 | static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev, | 302 | static ssize_t adis16220_capture_buffer_read(struct iio_dev *indio_dev, |
323 | char *buf, | 303 | char *buf, |
324 | loff_t off, | 304 | loff_t off, |
325 | size_t count, | 305 | size_t count, |
326 | int addr) | 306 | int addr) |
327 | { | 307 | { |
328 | struct adis16220_state *st = iio_priv(indio_dev); | 308 | struct adis16220_state *st = iio_priv(indio_dev); |
329 | struct spi_message msg; | 309 | struct spi_message msg; |
330 | struct spi_transfer xfers[] = { | 310 | struct spi_transfer xfers[] = { |
331 | { | 311 | { |
332 | .tx_buf = st->tx, | 312 | .tx_buf = st->tx, |
333 | .bits_per_word = 8, | 313 | .bits_per_word = 8, |
334 | .len = 2, | 314 | .len = 2, |
335 | .cs_change = 1, | 315 | .cs_change = 1, |
336 | .delay_usecs = 25, | 316 | .delay_usecs = 25, |
337 | }, { | 317 | }, { |
338 | .tx_buf = st->tx, | 318 | .tx_buf = st->tx, |
339 | .rx_buf = st->rx, | 319 | .rx_buf = st->rx, |
340 | .bits_per_word = 8, | 320 | .bits_per_word = 8, |
341 | .cs_change = 1, | 321 | .cs_change = 1, |
342 | .delay_usecs = 25, | 322 | .delay_usecs = 25, |
343 | }, | 323 | }, |
344 | }; | 324 | }; |
345 | int ret; | 325 | int ret; |
346 | int i; | 326 | int i; |
347 | 327 | ||
348 | if (unlikely(!count)) | 328 | if (unlikely(!count)) |
349 | return count; | 329 | return count; |
350 | 330 | ||
351 | if ((off >= ADIS16220_CAPTURE_SIZE) || (count & 1) || (off & 1)) | 331 | if ((off >= ADIS16220_CAPTURE_SIZE) || (count & 1) || (off & 1)) |
352 | return -EINVAL; | 332 | return -EINVAL; |
353 | 333 | ||
354 | if (off + count > ADIS16220_CAPTURE_SIZE) | 334 | if (off + count > ADIS16220_CAPTURE_SIZE) |
355 | count = ADIS16220_CAPTURE_SIZE - off; | 335 | count = ADIS16220_CAPTURE_SIZE - off; |
356 | 336 | ||
357 | /* write the begin position of capture buffer */ | 337 | /* write the begin position of capture buffer */ |
358 | ret = adis16220_spi_write_reg_16(indio_dev, | 338 | ret = adis16220_spi_write_reg_16(indio_dev, |
359 | ADIS16220_CAPT_PNTR, | 339 | ADIS16220_CAPT_PNTR, |
360 | off > 1); | 340 | off > 1); |
361 | if (ret) | 341 | if (ret) |
362 | return -EIO; | 342 | return -EIO; |
363 | 343 | ||
364 | /* read count/2 values from capture buffer */ | 344 | /* read count/2 values from capture buffer */ |
365 | mutex_lock(&st->buf_lock); | 345 | mutex_lock(&st->buf_lock); |
366 | 346 | ||
367 | for (i = 0; i < count; i += 2) { | 347 | for (i = 0; i < count; i += 2) { |
368 | st->tx[i] = ADIS16220_READ_REG(addr); | 348 | st->tx[i] = ADIS16220_READ_REG(addr); |
369 | st->tx[i + 1] = 0; | 349 | st->tx[i + 1] = 0; |
370 | } | 350 | } |
371 | xfers[1].len = count; | 351 | xfers[1].len = count; |
372 | 352 | ||
373 | spi_message_init(&msg); | 353 | spi_message_init(&msg); |
374 | spi_message_add_tail(&xfers[0], &msg); | 354 | spi_message_add_tail(&xfers[0], &msg); |
375 | spi_message_add_tail(&xfers[1], &msg); | 355 | spi_message_add_tail(&xfers[1], &msg); |
376 | ret = spi_sync(st->us, &msg); | 356 | ret = spi_sync(st->us, &msg); |
377 | if (ret) { | 357 | if (ret) { |
378 | 358 | ||
379 | mutex_unlock(&st->buf_lock); | 359 | mutex_unlock(&st->buf_lock); |
380 | return -EIO; | 360 | return -EIO; |
381 | } | 361 | } |
382 | 362 | ||
383 | memcpy(buf, st->rx, count); | 363 | memcpy(buf, st->rx, count); |
384 | 364 | ||
385 | mutex_unlock(&st->buf_lock); | 365 | mutex_unlock(&st->buf_lock); |
386 | return count; | 366 | return count; |
387 | } | 367 | } |
388 | 368 | ||
389 | static ssize_t adis16220_accel_bin_read(struct file *filp, struct kobject *kobj, | 369 | static ssize_t adis16220_accel_bin_read(struct file *filp, struct kobject *kobj, |
390 | struct bin_attribute *attr, | 370 | struct bin_attribute *attr, |
391 | char *buf, | 371 | char *buf, |
392 | loff_t off, | 372 | loff_t off, |
393 | size_t count) | 373 | size_t count) |
394 | { | 374 | { |
395 | struct device *dev = container_of(kobj, struct device, kobj); | 375 | struct device *dev = container_of(kobj, struct device, kobj); |
396 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 376 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
397 | 377 | ||
398 | return adis16220_capture_buffer_read(indio_dev, buf, | 378 | return adis16220_capture_buffer_read(indio_dev, buf, |
399 | off, count, | 379 | off, count, |
400 | ADIS16220_CAPT_BUFA); | 380 | ADIS16220_CAPT_BUFA); |
401 | } | 381 | } |
402 | 382 | ||
403 | static struct bin_attribute accel_bin = { | 383 | static struct bin_attribute accel_bin = { |
404 | .attr = { | 384 | .attr = { |
405 | .name = "accel_bin", | 385 | .name = "accel_bin", |
406 | .mode = S_IRUGO, | 386 | .mode = S_IRUGO, |
407 | }, | 387 | }, |
408 | .read = adis16220_accel_bin_read, | 388 | .read = adis16220_accel_bin_read, |
409 | .size = ADIS16220_CAPTURE_SIZE, | 389 | .size = ADIS16220_CAPTURE_SIZE, |
410 | }; | 390 | }; |
411 | 391 | ||
412 | static ssize_t adis16220_adc1_bin_read(struct file *filp, struct kobject *kobj, | 392 | static ssize_t adis16220_adc1_bin_read(struct file *filp, struct kobject *kobj, |
413 | struct bin_attribute *attr, | 393 | struct bin_attribute *attr, |
414 | char *buf, loff_t off, | 394 | char *buf, loff_t off, |
415 | size_t count) | 395 | size_t count) |
416 | { | 396 | { |
417 | struct device *dev = container_of(kobj, struct device, kobj); | 397 | struct device *dev = container_of(kobj, struct device, kobj); |
418 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 398 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
419 | 399 | ||
420 | return adis16220_capture_buffer_read(indio_dev, buf, | 400 | return adis16220_capture_buffer_read(indio_dev, buf, |
421 | off, count, | 401 | off, count, |
422 | ADIS16220_CAPT_BUF1); | 402 | ADIS16220_CAPT_BUF1); |
423 | } | 403 | } |
424 | 404 | ||
425 | static struct bin_attribute adc1_bin = { | 405 | static struct bin_attribute adc1_bin = { |
426 | .attr = { | 406 | .attr = { |
427 | .name = "in0_bin", | 407 | .name = "in0_bin", |
428 | .mode = S_IRUGO, | 408 | .mode = S_IRUGO, |
429 | }, | 409 | }, |
430 | .read = adis16220_adc1_bin_read, | 410 | .read = adis16220_adc1_bin_read, |
431 | .size = ADIS16220_CAPTURE_SIZE, | 411 | .size = ADIS16220_CAPTURE_SIZE, |
432 | }; | 412 | }; |
433 | 413 | ||
434 | static ssize_t adis16220_adc2_bin_read(struct file *filp, struct kobject *kobj, | 414 | static ssize_t adis16220_adc2_bin_read(struct file *filp, struct kobject *kobj, |
435 | struct bin_attribute *attr, | 415 | struct bin_attribute *attr, |
436 | char *buf, loff_t off, | 416 | char *buf, loff_t off, |
437 | size_t count) | 417 | size_t count) |
438 | { | 418 | { |
439 | struct device *dev = container_of(kobj, struct device, kobj); | 419 | struct device *dev = container_of(kobj, struct device, kobj); |
440 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 420 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
441 | 421 | ||
442 | return adis16220_capture_buffer_read(indio_dev, buf, | 422 | return adis16220_capture_buffer_read(indio_dev, buf, |
443 | off, count, | 423 | off, count, |
444 | ADIS16220_CAPT_BUF2); | 424 | ADIS16220_CAPT_BUF2); |
445 | } | 425 | } |
446 | 426 | ||
447 | 427 | ||
448 | static struct bin_attribute adc2_bin = { | 428 | static struct bin_attribute adc2_bin = { |
449 | .attr = { | 429 | .attr = { |
450 | .name = "in1_bin", | 430 | .name = "in1_bin", |
451 | .mode = S_IRUGO, | 431 | .mode = S_IRUGO, |
452 | }, | 432 | }, |
453 | .read = adis16220_adc2_bin_read, | 433 | .read = adis16220_adc2_bin_read, |
454 | .size = ADIS16220_CAPTURE_SIZE, | 434 | .size = ADIS16220_CAPTURE_SIZE, |
455 | }; | 435 | }; |
456 | 436 | ||
457 | static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, | ||
458 | adis16220_write_reset, 0); | ||
459 | |||
460 | #define IIO_DEV_ATTR_CAPTURE(_store) \ | 437 | #define IIO_DEV_ATTR_CAPTURE(_store) \ |
461 | IIO_DEVICE_ATTR(capture, S_IWUSR, NULL, _store, 0) | 438 | IIO_DEVICE_ATTR(capture, S_IWUSR, NULL, _store, 0) |
462 | 439 | ||
463 | static IIO_DEV_ATTR_CAPTURE(adis16220_write_capture); | 440 | static IIO_DEV_ATTR_CAPTURE(adis16220_write_capture); |
464 | 441 | ||
465 | #define IIO_DEV_ATTR_CAPTURE_COUNT(_mode, _show, _store, _addr) \ | 442 | #define IIO_DEV_ATTR_CAPTURE_COUNT(_mode, _show, _store, _addr) \ |
466 | IIO_DEVICE_ATTR(capture_count, _mode, _show, _store, _addr) | 443 | IIO_DEVICE_ATTR(capture_count, _mode, _show, _store, _addr) |
467 | 444 | ||
468 | static IIO_DEV_ATTR_CAPTURE_COUNT(S_IWUSR | S_IRUGO, | 445 | static IIO_DEV_ATTR_CAPTURE_COUNT(S_IWUSR | S_IRUGO, |
469 | adis16220_read_16bit, | 446 | adis16220_read_16bit, |
470 | adis16220_write_16bit, | 447 | adis16220_write_16bit, |
471 | ADIS16220_CAPT_PNTR); | 448 | ADIS16220_CAPT_PNTR); |
472 | 449 | ||
473 | enum adis16220_channel { | 450 | enum adis16220_channel { |
474 | in_supply, in_1, in_2, accel, temp | 451 | in_supply, in_1, in_2, accel, temp |
475 | }; | 452 | }; |
476 | 453 | ||
477 | struct adis16220_address_spec { | 454 | struct adis16220_address_spec { |
478 | u8 addr; | 455 | u8 addr; |
479 | u8 bits; | 456 | u8 bits; |
480 | bool sign; | 457 | bool sign; |
481 | }; | 458 | }; |
482 | 459 | ||
483 | /* Address / bits / signed */ | 460 | /* Address / bits / signed */ |
484 | static const struct adis16220_address_spec adis16220_addresses[][3] = { | 461 | static const struct adis16220_address_spec adis16220_addresses[][3] = { |
485 | [in_supply] = { { ADIS16220_CAPT_SUPPLY, 12, 0 }, }, | 462 | [in_supply] = { { ADIS16220_CAPT_SUPPLY, 12, 0 }, }, |
486 | [in_1] = { { ADIS16220_CAPT_BUF1, 16, 1 }, | 463 | [in_1] = { { ADIS16220_CAPT_BUF1, 16, 1 }, |
487 | { ADIS16220_AIN1_NULL, 16, 1 }, | 464 | { ADIS16220_AIN1_NULL, 16, 1 }, |
488 | { ADIS16220_CAPT_PEAK1, 16, 1 }, }, | 465 | { ADIS16220_CAPT_PEAK1, 16, 1 }, }, |
489 | [in_2] = { { ADIS16220_CAPT_BUF2, 16, 1 }, | 466 | [in_2] = { { ADIS16220_CAPT_BUF2, 16, 1 }, |
490 | { ADIS16220_AIN2_NULL, 16, 1 }, | 467 | { ADIS16220_AIN2_NULL, 16, 1 }, |
491 | { ADIS16220_CAPT_PEAK2, 16, 1 }, }, | 468 | { ADIS16220_CAPT_PEAK2, 16, 1 }, }, |
492 | [accel] = { { ADIS16220_CAPT_BUFA, 16, 1 }, | 469 | [accel] = { { ADIS16220_CAPT_BUFA, 16, 1 }, |
493 | { ADIS16220_ACCL_NULL, 16, 1 }, | 470 | { ADIS16220_ACCL_NULL, 16, 1 }, |
494 | { ADIS16220_CAPT_PEAKA, 16, 1 }, }, | 471 | { ADIS16220_CAPT_PEAKA, 16, 1 }, }, |
495 | [temp] = { { ADIS16220_CAPT_TEMP, 12, 0 }, } | 472 | [temp] = { { ADIS16220_CAPT_TEMP, 12, 0 }, } |
496 | }; | 473 | }; |
497 | 474 | ||
498 | static int adis16220_read_raw(struct iio_dev *indio_dev, | 475 | static int adis16220_read_raw(struct iio_dev *indio_dev, |
499 | struct iio_chan_spec const *chan, | 476 | struct iio_chan_spec const *chan, |
500 | int *val, int *val2, | 477 | int *val, int *val2, |
501 | long mask) | 478 | long mask) |
502 | { | 479 | { |
503 | int ret = -EINVAL; | 480 | int ret = -EINVAL; |
504 | int addrind = 0; | 481 | int addrind = 0; |
505 | u16 uval; | 482 | u16 uval; |
506 | s16 sval; | 483 | s16 sval; |
507 | u8 bits; | 484 | u8 bits; |
508 | 485 | ||
509 | switch (mask) { | 486 | switch (mask) { |
510 | case IIO_CHAN_INFO_RAW: | 487 | case IIO_CHAN_INFO_RAW: |
511 | addrind = 0; | 488 | addrind = 0; |
512 | break; | 489 | break; |
513 | case IIO_CHAN_INFO_OFFSET: | 490 | case IIO_CHAN_INFO_OFFSET: |
514 | if (chan->type == IIO_TEMP) { | 491 | if (chan->type == IIO_TEMP) { |
515 | *val = 25; | 492 | *val = 25; |
516 | return IIO_VAL_INT; | 493 | return IIO_VAL_INT; |
517 | } | 494 | } |
518 | addrind = 1; | 495 | addrind = 1; |
519 | break; | 496 | break; |
520 | case IIO_CHAN_INFO_PEAK: | 497 | case IIO_CHAN_INFO_PEAK: |
521 | addrind = 2; | 498 | addrind = 2; |
522 | break; | 499 | break; |
523 | case IIO_CHAN_INFO_SCALE: | 500 | case IIO_CHAN_INFO_SCALE: |
524 | *val = 0; | 501 | *val = 0; |
525 | switch (chan->type) { | 502 | switch (chan->type) { |
526 | case IIO_TEMP: | 503 | case IIO_TEMP: |
527 | *val2 = -470000; | 504 | *val2 = -470000; |
528 | return IIO_VAL_INT_PLUS_MICRO; | 505 | return IIO_VAL_INT_PLUS_MICRO; |
529 | case IIO_ACCEL: | 506 | case IIO_ACCEL: |
530 | *val2 = 1887042; | 507 | *val2 = 1887042; |
531 | return IIO_VAL_INT_PLUS_MICRO; | 508 | return IIO_VAL_INT_PLUS_MICRO; |
532 | case IIO_VOLTAGE: | 509 | case IIO_VOLTAGE: |
533 | if (chan->channel == 0) | 510 | if (chan->channel == 0) |
534 | *val2 = 0012221; | 511 | *val2 = 0012221; |
535 | else /* Should really be dependent on VDD */ | 512 | else /* Should really be dependent on VDD */ |
536 | *val2 = 305; | 513 | *val2 = 305; |
537 | return IIO_VAL_INT_PLUS_MICRO; | 514 | return IIO_VAL_INT_PLUS_MICRO; |
538 | default: | 515 | default: |
539 | return -EINVAL; | 516 | return -EINVAL; |
540 | } | 517 | } |
541 | default: | 518 | default: |
542 | return -EINVAL; | 519 | return -EINVAL; |
543 | } | 520 | } |
544 | if (adis16220_addresses[chan->address][addrind].sign) { | 521 | if (adis16220_addresses[chan->address][addrind].sign) { |
545 | ret = adis16220_spi_read_reg_16(indio_dev, | 522 | ret = adis16220_spi_read_reg_16(indio_dev, |
546 | adis16220_addresses[chan | 523 | adis16220_addresses[chan |
547 | ->address] | 524 | ->address] |
548 | [addrind].addr, | 525 | [addrind].addr, |
549 | &sval); | 526 | &sval); |
550 | if (ret) | 527 | if (ret) |
551 | return ret; | 528 | return ret; |
552 | bits = adis16220_addresses[chan->address][addrind].bits; | 529 | bits = adis16220_addresses[chan->address][addrind].bits; |
553 | sval &= (1 << bits) - 1; | 530 | sval &= (1 << bits) - 1; |
554 | sval = (s16)(sval << (16 - bits)) >> (16 - bits); | 531 | sval = (s16)(sval << (16 - bits)) >> (16 - bits); |
555 | *val = sval; | 532 | *val = sval; |
556 | return IIO_VAL_INT; | 533 | return IIO_VAL_INT; |
557 | } else { | 534 | } else { |
558 | ret = adis16220_spi_read_reg_16(indio_dev, | 535 | ret = adis16220_spi_read_reg_16(indio_dev, |
559 | adis16220_addresses[chan | 536 | adis16220_addresses[chan |
560 | ->address] | 537 | ->address] |
561 | [addrind].addr, | 538 | [addrind].addr, |
562 | &uval); | 539 | &uval); |
563 | if (ret) | 540 | if (ret) |
564 | return ret; | 541 | return ret; |
565 | bits = adis16220_addresses[chan->address][addrind].bits; | 542 | bits = adis16220_addresses[chan->address][addrind].bits; |
566 | uval &= (1 << bits) - 1; | 543 | uval &= (1 << bits) - 1; |
567 | *val = uval; | 544 | *val = uval; |
568 | return IIO_VAL_INT; | 545 | return IIO_VAL_INT; |
569 | } | 546 | } |
570 | } | 547 | } |
571 | 548 | ||
572 | static const struct iio_chan_spec adis16220_channels[] = { | 549 | static const struct iio_chan_spec adis16220_channels[] = { |
573 | { | 550 | { |
574 | .type = IIO_VOLTAGE, | 551 | .type = IIO_VOLTAGE, |
575 | .indexed = 1, | 552 | .indexed = 1, |
576 | .channel = 0, | 553 | .channel = 0, |
577 | .extend_name = "supply", | 554 | .extend_name = "supply", |
578 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 555 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
579 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 556 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
580 | .address = in_supply, | 557 | .address = in_supply, |
581 | }, { | 558 | }, { |
582 | .type = IIO_ACCEL, | 559 | .type = IIO_ACCEL, |
583 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 560 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
584 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | | 561 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | |
585 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | | 562 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | |
586 | IIO_CHAN_INFO_PEAK_SEPARATE_BIT, | 563 | IIO_CHAN_INFO_PEAK_SEPARATE_BIT, |
587 | .address = accel, | 564 | .address = accel, |
588 | }, { | 565 | }, { |
589 | .type = IIO_TEMP, | 566 | .type = IIO_TEMP, |
590 | .indexed = 1, | 567 | .indexed = 1, |
591 | .channel = 0, | 568 | .channel = 0, |
592 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 569 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
593 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | | 570 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | |
594 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 571 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
595 | .address = temp, | 572 | .address = temp, |
596 | }, { | 573 | }, { |
597 | .type = IIO_VOLTAGE, | 574 | .type = IIO_VOLTAGE, |
598 | .indexed = 1, | 575 | .indexed = 1, |
599 | .channel = 1, | 576 | .channel = 1, |
600 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 577 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
601 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | | 578 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | |
602 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 579 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
603 | .address = in_1, | 580 | .address = in_1, |
604 | }, { | 581 | }, { |
605 | .type = IIO_VOLTAGE, | 582 | .type = IIO_VOLTAGE, |
606 | .indexed = 1, | 583 | .indexed = 1, |
607 | .channel = 2, | 584 | .channel = 2, |
608 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, | 585 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, |
609 | .address = in_2, | 586 | .address = in_2, |
610 | } | 587 | } |
611 | }; | 588 | }; |
612 | 589 | ||
613 | static struct attribute *adis16220_attributes[] = { | 590 | static struct attribute *adis16220_attributes[] = { |
614 | &iio_dev_attr_reset.dev_attr.attr, | ||
615 | &iio_dev_attr_capture.dev_attr.attr, | 591 | &iio_dev_attr_capture.dev_attr.attr, |
616 | &iio_dev_attr_capture_count.dev_attr.attr, | 592 | &iio_dev_attr_capture_count.dev_attr.attr, |
617 | NULL | 593 | NULL |
618 | }; | 594 | }; |
619 | 595 | ||
620 | static const struct attribute_group adis16220_attribute_group = { | 596 | static const struct attribute_group adis16220_attribute_group = { |
621 | .attrs = adis16220_attributes, | 597 | .attrs = adis16220_attributes, |
622 | }; | 598 | }; |
623 | 599 | ||
624 | static const struct iio_info adis16220_info = { | 600 | static const struct iio_info adis16220_info = { |
625 | .attrs = &adis16220_attribute_group, | 601 | .attrs = &adis16220_attribute_group, |
626 | .driver_module = THIS_MODULE, | 602 | .driver_module = THIS_MODULE, |
627 | .read_raw = &adis16220_read_raw, | 603 | .read_raw = &adis16220_read_raw, |
628 | }; | 604 | }; |
629 | 605 | ||
630 | static int __devinit adis16220_probe(struct spi_device *spi) | 606 | static int __devinit adis16220_probe(struct spi_device *spi) |
631 | { | 607 | { |
632 | int ret; | 608 | int ret; |
633 | struct adis16220_state *st; | 609 | struct adis16220_state *st; |
634 | struct iio_dev *indio_dev; | 610 | struct iio_dev *indio_dev; |
635 | 611 | ||
636 | /* setup the industrialio driver allocated elements */ | 612 | /* setup the industrialio driver allocated elements */ |
637 | indio_dev = iio_device_alloc(sizeof(*st)); | 613 | indio_dev = iio_device_alloc(sizeof(*st)); |
638 | if (indio_dev == NULL) { | 614 | if (indio_dev == NULL) { |
639 | ret = -ENOMEM; | 615 | ret = -ENOMEM; |
640 | goto error_ret; | 616 | goto error_ret; |
641 | } | 617 | } |
642 | 618 | ||
643 | st = iio_priv(indio_dev); | 619 | st = iio_priv(indio_dev); |
644 | /* this is only used for removal purposes */ | 620 | /* this is only used for removal purposes */ |
645 | spi_set_drvdata(spi, indio_dev); | 621 | spi_set_drvdata(spi, indio_dev); |
646 | 622 | ||
647 | st->us = spi; | 623 | st->us = spi; |
648 | mutex_init(&st->buf_lock); | 624 | mutex_init(&st->buf_lock); |
649 | 625 | ||
650 | indio_dev->name = spi->dev.driver->name; | 626 | indio_dev->name = spi->dev.driver->name; |
651 | indio_dev->dev.parent = &spi->dev; | 627 | indio_dev->dev.parent = &spi->dev; |
652 | indio_dev->info = &adis16220_info; | 628 | indio_dev->info = &adis16220_info; |
653 | indio_dev->modes = INDIO_DIRECT_MODE; | 629 | indio_dev->modes = INDIO_DIRECT_MODE; |
654 | indio_dev->channels = adis16220_channels; | 630 | indio_dev->channels = adis16220_channels; |
655 | indio_dev->num_channels = ARRAY_SIZE(adis16220_channels); | 631 | indio_dev->num_channels = ARRAY_SIZE(adis16220_channels); |
656 | 632 | ||
657 | ret = iio_device_register(indio_dev); | 633 | ret = iio_device_register(indio_dev); |
658 | if (ret) | 634 | if (ret) |
659 | goto error_free_dev; | 635 | goto error_free_dev; |
660 | 636 | ||
661 | ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &accel_bin); | 637 | ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &accel_bin); |
662 | if (ret) | 638 | if (ret) |
663 | goto error_unregister_dev; | 639 | goto error_unregister_dev; |
664 | 640 | ||
665 | ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &adc1_bin); | 641 | ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &adc1_bin); |
666 | if (ret) | 642 | if (ret) |
667 | goto error_rm_accel_bin; | 643 | goto error_rm_accel_bin; |
668 | 644 | ||
669 | ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &adc2_bin); | 645 | ret = sysfs_create_bin_file(&indio_dev->dev.kobj, &adc2_bin); |
670 | if (ret) | 646 | if (ret) |
671 | goto error_rm_adc1_bin; | 647 | goto error_rm_adc1_bin; |
672 | 648 | ||
673 | /* Get the device into a sane initial state */ | 649 | /* Get the device into a sane initial state */ |
674 | ret = adis16220_initial_setup(indio_dev); | 650 | ret = adis16220_initial_setup(indio_dev); |
675 | if (ret) | 651 | if (ret) |
676 | goto error_rm_adc2_bin; | 652 | goto error_rm_adc2_bin; |
677 | return 0; | 653 | return 0; |
678 | 654 | ||
679 | error_rm_adc2_bin: | 655 | error_rm_adc2_bin: |
680 | sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc2_bin); | 656 | sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc2_bin); |
681 | error_rm_adc1_bin: | 657 | error_rm_adc1_bin: |
682 | sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin); | 658 | sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin); |
683 | error_rm_accel_bin: | 659 | error_rm_accel_bin: |
684 | sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin); | 660 | sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin); |
685 | error_unregister_dev: | 661 | error_unregister_dev: |
686 | iio_device_unregister(indio_dev); | 662 | iio_device_unregister(indio_dev); |
687 | error_free_dev: | 663 | error_free_dev: |
688 | iio_device_free(indio_dev); | 664 | iio_device_free(indio_dev); |
689 | error_ret: | 665 | error_ret: |
690 | return ret; | 666 | return ret; |
691 | } | 667 | } |
692 | 668 | ||
693 | static int adis16220_remove(struct spi_device *spi) | 669 | static int adis16220_remove(struct spi_device *spi) |
694 | { | 670 | { |
695 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | 671 | struct iio_dev *indio_dev = spi_get_drvdata(spi); |
696 | 672 | ||
697 | sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc2_bin); | 673 | sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc2_bin); |
698 | sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin); | 674 | sysfs_remove_bin_file(&indio_dev->dev.kobj, &adc1_bin); |
699 | sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin); | 675 | sysfs_remove_bin_file(&indio_dev->dev.kobj, &accel_bin); |
700 | iio_device_unregister(indio_dev); | 676 | iio_device_unregister(indio_dev); |
701 | iio_device_free(indio_dev); | 677 | iio_device_free(indio_dev); |
702 | 678 | ||
703 | return 0; | 679 | return 0; |
704 | } | 680 | } |
705 | 681 | ||
706 | static struct spi_driver adis16220_driver = { | 682 | static struct spi_driver adis16220_driver = { |
707 | .driver = { | 683 | .driver = { |
708 | .name = "adis16220", | 684 | .name = "adis16220", |
709 | .owner = THIS_MODULE, | 685 | .owner = THIS_MODULE, |
710 | }, | 686 | }, |
711 | .probe = adis16220_probe, | 687 | .probe = adis16220_probe, |
712 | .remove = __devexit_p(adis16220_remove), | 688 | .remove = __devexit_p(adis16220_remove), |
713 | }; | 689 | }; |
714 | module_spi_driver(adis16220_driver); | 690 | module_spi_driver(adis16220_driver); |
715 | 691 | ||
716 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | 692 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); |
717 | MODULE_DESCRIPTION("Analog Devices ADIS16220 Digital Vibration Sensor"); | 693 | MODULE_DESCRIPTION("Analog Devices ADIS16220 Digital Vibration Sensor"); |
718 | MODULE_LICENSE("GPL v2"); | 694 | MODULE_LICENSE("GPL v2"); |
719 | MODULE_ALIAS("spi:adis16220"); | 695 | MODULE_ALIAS("spi:adis16220"); |
720 | 696 |
drivers/staging/iio/accel/adis16240_core.c
1 | /* | 1 | /* |
2 | * ADIS16240 Programmable Impact Sensor and Recorder driver | 2 | * ADIS16240 Programmable Impact Sensor and Recorder driver |
3 | * | 3 | * |
4 | * Copyright 2010 Analog Devices Inc. | 4 | * Copyright 2010 Analog Devices Inc. |
5 | * | 5 | * |
6 | * Licensed under the GPL-2 or later. | 6 | * Licensed under the GPL-2 or later. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/interrupt.h> | 9 | #include <linux/interrupt.h> |
10 | #include <linux/irq.h> | 10 | #include <linux/irq.h> |
11 | #include <linux/gpio.h> | 11 | #include <linux/gpio.h> |
12 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
13 | #include <linux/mutex.h> | 13 | #include <linux/mutex.h> |
14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/spi/spi.h> | 16 | #include <linux/spi/spi.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/sysfs.h> | 18 | #include <linux/sysfs.h> |
19 | #include <linux/list.h> | 19 | #include <linux/list.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | 21 | ||
22 | #include <linux/iio/iio.h> | 22 | #include <linux/iio/iio.h> |
23 | #include <linux/iio/sysfs.h> | 23 | #include <linux/iio/sysfs.h> |
24 | #include <linux/iio/buffer.h> | 24 | #include <linux/iio/buffer.h> |
25 | 25 | ||
26 | #include "adis16240.h" | 26 | #include "adis16240.h" |
27 | 27 | ||
28 | #define DRIVER_NAME "adis16240" | 28 | #define DRIVER_NAME "adis16240" |
29 | 29 | ||
30 | static int adis16240_check_status(struct iio_dev *indio_dev); | 30 | static int adis16240_check_status(struct iio_dev *indio_dev); |
31 | 31 | ||
32 | /** | 32 | /** |
33 | * adis16240_spi_write_reg_8() - write single byte to a register | 33 | * adis16240_spi_write_reg_8() - write single byte to a register |
34 | * @indio_dev: iio_dev associated with device | 34 | * @indio_dev: iio_dev associated with device |
35 | * @reg_address: the address of the register to be written | 35 | * @reg_address: the address of the register to be written |
36 | * @val: the value to write | 36 | * @val: the value to write |
37 | **/ | 37 | **/ |
38 | static int adis16240_spi_write_reg_8(struct iio_dev *indio_dev, | 38 | static int adis16240_spi_write_reg_8(struct iio_dev *indio_dev, |
39 | u8 reg_address, | 39 | u8 reg_address, |
40 | u8 val) | 40 | u8 val) |
41 | { | 41 | { |
42 | int ret; | 42 | int ret; |
43 | struct adis16240_state *st = iio_priv(indio_dev); | 43 | struct adis16240_state *st = iio_priv(indio_dev); |
44 | 44 | ||
45 | mutex_lock(&st->buf_lock); | 45 | mutex_lock(&st->buf_lock); |
46 | st->tx[0] = ADIS16240_WRITE_REG(reg_address); | 46 | st->tx[0] = ADIS16240_WRITE_REG(reg_address); |
47 | st->tx[1] = val; | 47 | st->tx[1] = val; |
48 | 48 | ||
49 | ret = spi_write(st->us, st->tx, 2); | 49 | ret = spi_write(st->us, st->tx, 2); |
50 | mutex_unlock(&st->buf_lock); | 50 | mutex_unlock(&st->buf_lock); |
51 | 51 | ||
52 | return ret; | 52 | return ret; |
53 | } | 53 | } |
54 | 54 | ||
55 | /** | 55 | /** |
56 | * adis16240_spi_write_reg_16() - write 2 bytes to a pair of registers | 56 | * adis16240_spi_write_reg_16() - write 2 bytes to a pair of registers |
57 | * @indio_dev: iio_dev for this device | 57 | * @indio_dev: iio_dev for this device |
58 | * @reg_address: the address of the lower of the two registers. Second register | 58 | * @reg_address: the address of the lower of the two registers. Second register |
59 | * is assumed to have address one greater. | 59 | * is assumed to have address one greater. |
60 | * @val: value to be written | 60 | * @val: value to be written |
61 | **/ | 61 | **/ |
62 | static int adis16240_spi_write_reg_16(struct iio_dev *indio_dev, | 62 | static int adis16240_spi_write_reg_16(struct iio_dev *indio_dev, |
63 | u8 lower_reg_address, | 63 | u8 lower_reg_address, |
64 | u16 value) | 64 | u16 value) |
65 | { | 65 | { |
66 | int ret; | 66 | int ret; |
67 | struct spi_message msg; | 67 | struct spi_message msg; |
68 | struct adis16240_state *st = iio_priv(indio_dev); | 68 | struct adis16240_state *st = iio_priv(indio_dev); |
69 | struct spi_transfer xfers[] = { | 69 | struct spi_transfer xfers[] = { |
70 | { | 70 | { |
71 | .tx_buf = st->tx, | 71 | .tx_buf = st->tx, |
72 | .bits_per_word = 8, | 72 | .bits_per_word = 8, |
73 | .len = 2, | 73 | .len = 2, |
74 | .cs_change = 1, | 74 | .cs_change = 1, |
75 | .delay_usecs = 35, | 75 | .delay_usecs = 35, |
76 | }, { | 76 | }, { |
77 | .tx_buf = st->tx + 2, | 77 | .tx_buf = st->tx + 2, |
78 | .bits_per_word = 8, | 78 | .bits_per_word = 8, |
79 | .len = 2, | 79 | .len = 2, |
80 | .delay_usecs = 35, | 80 | .delay_usecs = 35, |
81 | }, | 81 | }, |
82 | }; | 82 | }; |
83 | 83 | ||
84 | mutex_lock(&st->buf_lock); | 84 | mutex_lock(&st->buf_lock); |
85 | st->tx[0] = ADIS16240_WRITE_REG(lower_reg_address); | 85 | st->tx[0] = ADIS16240_WRITE_REG(lower_reg_address); |
86 | st->tx[1] = value & 0xFF; | 86 | st->tx[1] = value & 0xFF; |
87 | st->tx[2] = ADIS16240_WRITE_REG(lower_reg_address + 1); | 87 | st->tx[2] = ADIS16240_WRITE_REG(lower_reg_address + 1); |
88 | st->tx[3] = (value >> 8) & 0xFF; | 88 | st->tx[3] = (value >> 8) & 0xFF; |
89 | 89 | ||
90 | spi_message_init(&msg); | 90 | spi_message_init(&msg); |
91 | spi_message_add_tail(&xfers[0], &msg); | 91 | spi_message_add_tail(&xfers[0], &msg); |
92 | spi_message_add_tail(&xfers[1], &msg); | 92 | spi_message_add_tail(&xfers[1], &msg); |
93 | ret = spi_sync(st->us, &msg); | 93 | ret = spi_sync(st->us, &msg); |
94 | mutex_unlock(&st->buf_lock); | 94 | mutex_unlock(&st->buf_lock); |
95 | 95 | ||
96 | return ret; | 96 | return ret; |
97 | } | 97 | } |
98 | 98 | ||
99 | /** | 99 | /** |
100 | * adis16240_spi_read_reg_16() - read 2 bytes from a 16-bit register | 100 | * adis16240_spi_read_reg_16() - read 2 bytes from a 16-bit register |
101 | * @indio_dev: iio_dev for this device | 101 | * @indio_dev: iio_dev for this device |
102 | * @reg_address: the address of the lower of the two registers. Second register | 102 | * @reg_address: the address of the lower of the two registers. Second register |
103 | * is assumed to have address one greater. | 103 | * is assumed to have address one greater. |
104 | * @val: somewhere to pass back the value read | 104 | * @val: somewhere to pass back the value read |
105 | **/ | 105 | **/ |
106 | static int adis16240_spi_read_reg_16(struct iio_dev *indio_dev, | 106 | static int adis16240_spi_read_reg_16(struct iio_dev *indio_dev, |
107 | u8 lower_reg_address, | 107 | u8 lower_reg_address, |
108 | u16 *val) | 108 | u16 *val) |
109 | { | 109 | { |
110 | struct spi_message msg; | 110 | struct spi_message msg; |
111 | struct adis16240_state *st = iio_priv(indio_dev); | 111 | struct adis16240_state *st = iio_priv(indio_dev); |
112 | int ret; | 112 | int ret; |
113 | struct spi_transfer xfers[] = { | 113 | struct spi_transfer xfers[] = { |
114 | { | 114 | { |
115 | .tx_buf = st->tx, | 115 | .tx_buf = st->tx, |
116 | .bits_per_word = 8, | 116 | .bits_per_word = 8, |
117 | .len = 2, | 117 | .len = 2, |
118 | .cs_change = 1, | 118 | .cs_change = 1, |
119 | .delay_usecs = 35, | 119 | .delay_usecs = 35, |
120 | }, { | 120 | }, { |
121 | .rx_buf = st->rx, | 121 | .rx_buf = st->rx, |
122 | .bits_per_word = 8, | 122 | .bits_per_word = 8, |
123 | .len = 2, | 123 | .len = 2, |
124 | .cs_change = 1, | 124 | .cs_change = 1, |
125 | .delay_usecs = 35, | 125 | .delay_usecs = 35, |
126 | }, | 126 | }, |
127 | }; | 127 | }; |
128 | 128 | ||
129 | mutex_lock(&st->buf_lock); | 129 | mutex_lock(&st->buf_lock); |
130 | st->tx[0] = ADIS16240_READ_REG(lower_reg_address); | 130 | st->tx[0] = ADIS16240_READ_REG(lower_reg_address); |
131 | st->tx[1] = 0; | 131 | st->tx[1] = 0; |
132 | st->tx[2] = 0; | 132 | st->tx[2] = 0; |
133 | st->tx[3] = 0; | 133 | st->tx[3] = 0; |
134 | 134 | ||
135 | spi_message_init(&msg); | 135 | spi_message_init(&msg); |
136 | spi_message_add_tail(&xfers[0], &msg); | 136 | spi_message_add_tail(&xfers[0], &msg); |
137 | spi_message_add_tail(&xfers[1], &msg); | 137 | spi_message_add_tail(&xfers[1], &msg); |
138 | ret = spi_sync(st->us, &msg); | 138 | ret = spi_sync(st->us, &msg); |
139 | if (ret) { | 139 | if (ret) { |
140 | dev_err(&st->us->dev, | 140 | dev_err(&st->us->dev, |
141 | "problem when reading 16 bit register 0x%02X", | 141 | "problem when reading 16 bit register 0x%02X", |
142 | lower_reg_address); | 142 | lower_reg_address); |
143 | goto error_ret; | 143 | goto error_ret; |
144 | } | 144 | } |
145 | *val = (st->rx[0] << 8) | st->rx[1]; | 145 | *val = (st->rx[0] << 8) | st->rx[1]; |
146 | 146 | ||
147 | error_ret: | 147 | error_ret: |
148 | mutex_unlock(&st->buf_lock); | 148 | mutex_unlock(&st->buf_lock); |
149 | return ret; | 149 | return ret; |
150 | } | 150 | } |
151 | 151 | ||
152 | static ssize_t adis16240_spi_read_signed(struct device *dev, | 152 | static ssize_t adis16240_spi_read_signed(struct device *dev, |
153 | struct device_attribute *attr, | 153 | struct device_attribute *attr, |
154 | char *buf, | 154 | char *buf, |
155 | unsigned bits) | 155 | unsigned bits) |
156 | { | 156 | { |
157 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 157 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
158 | int ret; | 158 | int ret; |
159 | s16 val = 0; | 159 | s16 val = 0; |
160 | unsigned shift = 16 - bits; | 160 | unsigned shift = 16 - bits; |
161 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | 161 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
162 | 162 | ||
163 | ret = adis16240_spi_read_reg_16(indio_dev, | 163 | ret = adis16240_spi_read_reg_16(indio_dev, |
164 | this_attr->address, (u16 *)&val); | 164 | this_attr->address, (u16 *)&val); |
165 | if (ret) | 165 | if (ret) |
166 | return ret; | 166 | return ret; |
167 | 167 | ||
168 | if (val & ADIS16240_ERROR_ACTIVE) | 168 | if (val & ADIS16240_ERROR_ACTIVE) |
169 | adis16240_check_status(indio_dev); | 169 | adis16240_check_status(indio_dev); |
170 | 170 | ||
171 | val = ((s16)(val << shift) >> shift); | 171 | val = ((s16)(val << shift) >> shift); |
172 | return sprintf(buf, "%d\n", val); | 172 | return sprintf(buf, "%d\n", val); |
173 | } | 173 | } |
174 | 174 | ||
175 | static ssize_t adis16240_read_12bit_signed(struct device *dev, | 175 | static ssize_t adis16240_read_12bit_signed(struct device *dev, |
176 | struct device_attribute *attr, | 176 | struct device_attribute *attr, |
177 | char *buf) | 177 | char *buf) |
178 | { | 178 | { |
179 | ssize_t ret; | 179 | ssize_t ret; |
180 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 180 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
181 | 181 | ||
182 | /* Take the iio_dev status lock */ | 182 | /* Take the iio_dev status lock */ |
183 | mutex_lock(&indio_dev->mlock); | 183 | mutex_lock(&indio_dev->mlock); |
184 | ret = adis16240_spi_read_signed(dev, attr, buf, 12); | 184 | ret = adis16240_spi_read_signed(dev, attr, buf, 12); |
185 | mutex_unlock(&indio_dev->mlock); | 185 | mutex_unlock(&indio_dev->mlock); |
186 | 186 | ||
187 | return ret; | 187 | return ret; |
188 | } | 188 | } |
189 | 189 | ||
190 | static int adis16240_reset(struct iio_dev *indio_dev) | 190 | static int adis16240_reset(struct iio_dev *indio_dev) |
191 | { | 191 | { |
192 | int ret; | 192 | int ret; |
193 | ret = adis16240_spi_write_reg_8(indio_dev, | 193 | ret = adis16240_spi_write_reg_8(indio_dev, |
194 | ADIS16240_GLOB_CMD, | 194 | ADIS16240_GLOB_CMD, |
195 | ADIS16240_GLOB_CMD_SW_RESET); | 195 | ADIS16240_GLOB_CMD_SW_RESET); |
196 | if (ret) | 196 | if (ret) |
197 | dev_err(&indio_dev->dev, "problem resetting device"); | 197 | dev_err(&indio_dev->dev, "problem resetting device"); |
198 | 198 | ||
199 | return ret; | 199 | return ret; |
200 | } | 200 | } |
201 | 201 | ||
202 | static ssize_t adis16240_write_reset(struct device *dev, | ||
203 | struct device_attribute *attr, | ||
204 | const char *buf, size_t len) | ||
205 | { | ||
206 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
207 | |||
208 | if (len < 1) | ||
209 | return -EINVAL; | ||
210 | switch (buf[0]) { | ||
211 | case '1': | ||
212 | case 'y': | ||
213 | case 'Y': | ||
214 | return adis16240_reset(indio_dev); | ||
215 | } | ||
216 | return -EINVAL; | ||
217 | } | ||
218 | |||
219 | int adis16240_set_irq(struct iio_dev *indio_dev, bool enable) | 202 | int adis16240_set_irq(struct iio_dev *indio_dev, bool enable) |
220 | { | 203 | { |
221 | int ret = 0; | 204 | int ret = 0; |
222 | u16 msc; | 205 | u16 msc; |
223 | 206 | ||
224 | ret = adis16240_spi_read_reg_16(indio_dev, | 207 | ret = adis16240_spi_read_reg_16(indio_dev, |
225 | ADIS16240_MSC_CTRL, &msc); | 208 | ADIS16240_MSC_CTRL, &msc); |
226 | if (ret) | 209 | if (ret) |
227 | goto error_ret; | 210 | goto error_ret; |
228 | 211 | ||
229 | msc |= ADIS16240_MSC_CTRL_ACTIVE_HIGH; | 212 | msc |= ADIS16240_MSC_CTRL_ACTIVE_HIGH; |
230 | msc &= ~ADIS16240_MSC_CTRL_DATA_RDY_DIO2; | 213 | msc &= ~ADIS16240_MSC_CTRL_DATA_RDY_DIO2; |
231 | if (enable) | 214 | if (enable) |
232 | msc |= ADIS16240_MSC_CTRL_DATA_RDY_EN; | 215 | msc |= ADIS16240_MSC_CTRL_DATA_RDY_EN; |
233 | else | 216 | else |
234 | msc &= ~ADIS16240_MSC_CTRL_DATA_RDY_EN; | 217 | msc &= ~ADIS16240_MSC_CTRL_DATA_RDY_EN; |
235 | 218 | ||
236 | ret = adis16240_spi_write_reg_16(indio_dev, | 219 | ret = adis16240_spi_write_reg_16(indio_dev, |
237 | ADIS16240_MSC_CTRL, msc); | 220 | ADIS16240_MSC_CTRL, msc); |
238 | 221 | ||
239 | error_ret: | 222 | error_ret: |
240 | return ret; | 223 | return ret; |
241 | } | 224 | } |
242 | 225 | ||
243 | static int adis16240_self_test(struct iio_dev *indio_dev) | 226 | static int adis16240_self_test(struct iio_dev *indio_dev) |
244 | { | 227 | { |
245 | int ret; | 228 | int ret; |
246 | ret = adis16240_spi_write_reg_16(indio_dev, | 229 | ret = adis16240_spi_write_reg_16(indio_dev, |
247 | ADIS16240_MSC_CTRL, | 230 | ADIS16240_MSC_CTRL, |
248 | ADIS16240_MSC_CTRL_SELF_TEST_EN); | 231 | ADIS16240_MSC_CTRL_SELF_TEST_EN); |
249 | if (ret) { | 232 | if (ret) { |
250 | dev_err(&indio_dev->dev, "problem starting self test"); | 233 | dev_err(&indio_dev->dev, "problem starting self test"); |
251 | goto err_ret; | 234 | goto err_ret; |
252 | } | 235 | } |
253 | 236 | ||
254 | msleep(ADIS16240_STARTUP_DELAY); | 237 | msleep(ADIS16240_STARTUP_DELAY); |
255 | 238 | ||
256 | adis16240_check_status(indio_dev); | 239 | adis16240_check_status(indio_dev); |
257 | 240 | ||
258 | err_ret: | 241 | err_ret: |
259 | return ret; | 242 | return ret; |
260 | } | 243 | } |
261 | 244 | ||
262 | static int adis16240_check_status(struct iio_dev *indio_dev) | 245 | static int adis16240_check_status(struct iio_dev *indio_dev) |
263 | { | 246 | { |
264 | u16 status; | 247 | u16 status; |
265 | int ret; | 248 | int ret; |
266 | struct device *dev = &indio_dev->dev; | 249 | struct device *dev = &indio_dev->dev; |
267 | 250 | ||
268 | ret = adis16240_spi_read_reg_16(indio_dev, | 251 | ret = adis16240_spi_read_reg_16(indio_dev, |
269 | ADIS16240_DIAG_STAT, &status); | 252 | ADIS16240_DIAG_STAT, &status); |
270 | 253 | ||
271 | if (ret < 0) { | 254 | if (ret < 0) { |
272 | dev_err(dev, "Reading status failed\n"); | 255 | dev_err(dev, "Reading status failed\n"); |
273 | goto error_ret; | 256 | goto error_ret; |
274 | } | 257 | } |
275 | 258 | ||
276 | ret = status & 0x2F; | 259 | ret = status & 0x2F; |
277 | if (status & ADIS16240_DIAG_STAT_PWRON_FAIL) | 260 | if (status & ADIS16240_DIAG_STAT_PWRON_FAIL) |
278 | dev_err(dev, "Power-on, self-test fail\n"); | 261 | dev_err(dev, "Power-on, self-test fail\n"); |
279 | if (status & ADIS16240_DIAG_STAT_SPI_FAIL) | 262 | if (status & ADIS16240_DIAG_STAT_SPI_FAIL) |
280 | dev_err(dev, "SPI failure\n"); | 263 | dev_err(dev, "SPI failure\n"); |
281 | if (status & ADIS16240_DIAG_STAT_FLASH_UPT) | 264 | if (status & ADIS16240_DIAG_STAT_FLASH_UPT) |
282 | dev_err(dev, "Flash update failed\n"); | 265 | dev_err(dev, "Flash update failed\n"); |
283 | if (status & ADIS16240_DIAG_STAT_POWER_HIGH) | 266 | if (status & ADIS16240_DIAG_STAT_POWER_HIGH) |
284 | dev_err(dev, "Power supply above 3.625V\n"); | 267 | dev_err(dev, "Power supply above 3.625V\n"); |
285 | if (status & ADIS16240_DIAG_STAT_POWER_LOW) | 268 | if (status & ADIS16240_DIAG_STAT_POWER_LOW) |
286 | dev_err(dev, "Power supply below 2.225V\n"); | 269 | dev_err(dev, "Power supply below 2.225V\n"); |
287 | 270 | ||
288 | error_ret: | 271 | error_ret: |
289 | return ret; | 272 | return ret; |
290 | } | 273 | } |
291 | 274 | ||
292 | static int adis16240_initial_setup(struct iio_dev *indio_dev) | 275 | static int adis16240_initial_setup(struct iio_dev *indio_dev) |
293 | { | 276 | { |
294 | int ret; | 277 | int ret; |
295 | struct device *dev = &indio_dev->dev; | 278 | struct device *dev = &indio_dev->dev; |
296 | 279 | ||
297 | /* Disable IRQ */ | 280 | /* Disable IRQ */ |
298 | ret = adis16240_set_irq(indio_dev, false); | 281 | ret = adis16240_set_irq(indio_dev, false); |
299 | if (ret) { | 282 | if (ret) { |
300 | dev_err(dev, "disable irq failed"); | 283 | dev_err(dev, "disable irq failed"); |
301 | goto err_ret; | 284 | goto err_ret; |
302 | } | 285 | } |
303 | 286 | ||
304 | /* Do self test */ | 287 | /* Do self test */ |
305 | ret = adis16240_self_test(indio_dev); | 288 | ret = adis16240_self_test(indio_dev); |
306 | if (ret) { | 289 | if (ret) { |
307 | dev_err(dev, "self test failure"); | 290 | dev_err(dev, "self test failure"); |
308 | goto err_ret; | 291 | goto err_ret; |
309 | } | 292 | } |
310 | 293 | ||
311 | /* Read status register to check the result */ | 294 | /* Read status register to check the result */ |
312 | ret = adis16240_check_status(indio_dev); | 295 | ret = adis16240_check_status(indio_dev); |
313 | if (ret) { | 296 | if (ret) { |
314 | adis16240_reset(indio_dev); | 297 | adis16240_reset(indio_dev); |
315 | dev_err(dev, "device not playing ball -> reset"); | 298 | dev_err(dev, "device not playing ball -> reset"); |
316 | msleep(ADIS16240_STARTUP_DELAY); | 299 | msleep(ADIS16240_STARTUP_DELAY); |
317 | ret = adis16240_check_status(indio_dev); | 300 | ret = adis16240_check_status(indio_dev); |
318 | if (ret) { | 301 | if (ret) { |
319 | dev_err(dev, "giving up"); | 302 | dev_err(dev, "giving up"); |
320 | goto err_ret; | 303 | goto err_ret; |
321 | } | 304 | } |
322 | } | 305 | } |
323 | 306 | ||
324 | err_ret: | 307 | err_ret: |
325 | return ret; | 308 | return ret; |
326 | } | 309 | } |
327 | 310 | ||
328 | static IIO_DEVICE_ATTR(in_accel_xyz_squared_peak_raw, S_IRUGO, | 311 | static IIO_DEVICE_ATTR(in_accel_xyz_squared_peak_raw, S_IRUGO, |
329 | adis16240_read_12bit_signed, NULL, | 312 | adis16240_read_12bit_signed, NULL, |
330 | ADIS16240_XYZPEAK_OUT); | 313 | ADIS16240_XYZPEAK_OUT); |
331 | 314 | ||
332 | static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16240_write_reset, 0); | ||
333 | |||
334 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("4096"); | 315 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("4096"); |
335 | 316 | ||
336 | enum adis16240_chan { | 317 | enum adis16240_chan { |
337 | in_supply, | 318 | in_supply, |
338 | in_aux, | 319 | in_aux, |
339 | accel_x, | 320 | accel_x, |
340 | accel_y, | 321 | accel_y, |
341 | accel_z, | 322 | accel_z, |
342 | temp, | 323 | temp, |
343 | }; | 324 | }; |
344 | 325 | ||
345 | static const u8 adis16240_addresses[6][3] = { | 326 | static const u8 adis16240_addresses[6][3] = { |
346 | [in_supply] = { ADIS16240_SUPPLY_OUT }, | 327 | [in_supply] = { ADIS16240_SUPPLY_OUT }, |
347 | [in_aux] = { ADIS16240_AUX_ADC }, | 328 | [in_aux] = { ADIS16240_AUX_ADC }, |
348 | [accel_x] = { ADIS16240_XACCL_OUT, ADIS16240_XACCL_OFF, | 329 | [accel_x] = { ADIS16240_XACCL_OUT, ADIS16240_XACCL_OFF, |
349 | ADIS16240_XPEAK_OUT }, | 330 | ADIS16240_XPEAK_OUT }, |
350 | [accel_y] = { ADIS16240_YACCL_OUT, ADIS16240_YACCL_OFF, | 331 | [accel_y] = { ADIS16240_YACCL_OUT, ADIS16240_YACCL_OFF, |
351 | ADIS16240_YPEAK_OUT }, | 332 | ADIS16240_YPEAK_OUT }, |
352 | [accel_z] = { ADIS16240_ZACCL_OUT, ADIS16240_ZACCL_OFF, | 333 | [accel_z] = { ADIS16240_ZACCL_OUT, ADIS16240_ZACCL_OFF, |
353 | ADIS16240_ZPEAK_OUT }, | 334 | ADIS16240_ZPEAK_OUT }, |
354 | [temp] = { ADIS16240_TEMP_OUT }, | 335 | [temp] = { ADIS16240_TEMP_OUT }, |
355 | }; | 336 | }; |
356 | 337 | ||
357 | static int adis16240_read_raw(struct iio_dev *indio_dev, | 338 | static int adis16240_read_raw(struct iio_dev *indio_dev, |
358 | struct iio_chan_spec const *chan, | 339 | struct iio_chan_spec const *chan, |
359 | int *val, int *val2, | 340 | int *val, int *val2, |
360 | long mask) | 341 | long mask) |
361 | { | 342 | { |
362 | int ret; | 343 | int ret; |
363 | int bits; | 344 | int bits; |
364 | u8 addr; | 345 | u8 addr; |
365 | s16 val16; | 346 | s16 val16; |
366 | 347 | ||
367 | switch (mask) { | 348 | switch (mask) { |
368 | case IIO_CHAN_INFO_RAW: | 349 | case IIO_CHAN_INFO_RAW: |
369 | mutex_lock(&indio_dev->mlock); | 350 | mutex_lock(&indio_dev->mlock); |
370 | addr = adis16240_addresses[chan->address][0]; | 351 | addr = adis16240_addresses[chan->address][0]; |
371 | ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16); | 352 | ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16); |
372 | if (ret) { | 353 | if (ret) { |
373 | mutex_unlock(&indio_dev->mlock); | 354 | mutex_unlock(&indio_dev->mlock); |
374 | return ret; | 355 | return ret; |
375 | } | 356 | } |
376 | 357 | ||
377 | if (val16 & ADIS16240_ERROR_ACTIVE) { | 358 | if (val16 & ADIS16240_ERROR_ACTIVE) { |
378 | ret = adis16240_check_status(indio_dev); | 359 | ret = adis16240_check_status(indio_dev); |
379 | if (ret) { | 360 | if (ret) { |
380 | mutex_unlock(&indio_dev->mlock); | 361 | mutex_unlock(&indio_dev->mlock); |
381 | return ret; | 362 | return ret; |
382 | } | 363 | } |
383 | } | 364 | } |
384 | val16 = val16 & ((1 << chan->scan_type.realbits) - 1); | 365 | val16 = val16 & ((1 << chan->scan_type.realbits) - 1); |
385 | if (chan->scan_type.sign == 's') | 366 | if (chan->scan_type.sign == 's') |
386 | val16 = (s16)(val16 << | 367 | val16 = (s16)(val16 << |
387 | (16 - chan->scan_type.realbits)) >> | 368 | (16 - chan->scan_type.realbits)) >> |
388 | (16 - chan->scan_type.realbits); | 369 | (16 - chan->scan_type.realbits); |
389 | *val = val16; | 370 | *val = val16; |
390 | mutex_unlock(&indio_dev->mlock); | 371 | mutex_unlock(&indio_dev->mlock); |
391 | return IIO_VAL_INT; | 372 | return IIO_VAL_INT; |
392 | case IIO_CHAN_INFO_SCALE: | 373 | case IIO_CHAN_INFO_SCALE: |
393 | switch (chan->type) { | 374 | switch (chan->type) { |
394 | case IIO_VOLTAGE: | 375 | case IIO_VOLTAGE: |
395 | *val = 0; | 376 | *val = 0; |
396 | if (chan->channel == 0) | 377 | if (chan->channel == 0) |
397 | *val2 = 4880; | 378 | *val2 = 4880; |
398 | else | 379 | else |
399 | return -EINVAL; | 380 | return -EINVAL; |
400 | return IIO_VAL_INT_PLUS_MICRO; | 381 | return IIO_VAL_INT_PLUS_MICRO; |
401 | case IIO_TEMP: | 382 | case IIO_TEMP: |
402 | *val = 0; | 383 | *val = 0; |
403 | *val2 = 244000; | 384 | *val2 = 244000; |
404 | return IIO_VAL_INT_PLUS_MICRO; | 385 | return IIO_VAL_INT_PLUS_MICRO; |
405 | case IIO_ACCEL: | 386 | case IIO_ACCEL: |
406 | *val = 0; | 387 | *val = 0; |
407 | *val2 = 504062; | 388 | *val2 = 504062; |
408 | return IIO_VAL_INT_PLUS_MICRO; | 389 | return IIO_VAL_INT_PLUS_MICRO; |
409 | default: | 390 | default: |
410 | return -EINVAL; | 391 | return -EINVAL; |
411 | } | 392 | } |
412 | break; | 393 | break; |
413 | case IIO_CHAN_INFO_PEAK_SCALE: | 394 | case IIO_CHAN_INFO_PEAK_SCALE: |
414 | *val = 6; | 395 | *val = 6; |
415 | *val2 = 629295; | 396 | *val2 = 629295; |
416 | return IIO_VAL_INT_PLUS_MICRO; | 397 | return IIO_VAL_INT_PLUS_MICRO; |
417 | case IIO_CHAN_INFO_OFFSET: | 398 | case IIO_CHAN_INFO_OFFSET: |
418 | *val = 25; | 399 | *val = 25; |
419 | return IIO_VAL_INT; | 400 | return IIO_VAL_INT; |
420 | case IIO_CHAN_INFO_CALIBBIAS: | 401 | case IIO_CHAN_INFO_CALIBBIAS: |
421 | bits = 10; | 402 | bits = 10; |
422 | mutex_lock(&indio_dev->mlock); | 403 | mutex_lock(&indio_dev->mlock); |
423 | addr = adis16240_addresses[chan->address][1]; | 404 | addr = adis16240_addresses[chan->address][1]; |
424 | ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16); | 405 | ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16); |
425 | if (ret) { | 406 | if (ret) { |
426 | mutex_unlock(&indio_dev->mlock); | 407 | mutex_unlock(&indio_dev->mlock); |
427 | return ret; | 408 | return ret; |
428 | } | 409 | } |
429 | val16 &= (1 << bits) - 1; | 410 | val16 &= (1 << bits) - 1; |
430 | val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); | 411 | val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); |
431 | *val = val16; | 412 | *val = val16; |
432 | mutex_unlock(&indio_dev->mlock); | 413 | mutex_unlock(&indio_dev->mlock); |
433 | return IIO_VAL_INT; | 414 | return IIO_VAL_INT; |
434 | case IIO_CHAN_INFO_PEAK: | 415 | case IIO_CHAN_INFO_PEAK: |
435 | bits = 10; | 416 | bits = 10; |
436 | mutex_lock(&indio_dev->mlock); | 417 | mutex_lock(&indio_dev->mlock); |
437 | addr = adis16240_addresses[chan->address][2]; | 418 | addr = adis16240_addresses[chan->address][2]; |
438 | ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16); | 419 | ret = adis16240_spi_read_reg_16(indio_dev, addr, &val16); |
439 | if (ret) { | 420 | if (ret) { |
440 | mutex_unlock(&indio_dev->mlock); | 421 | mutex_unlock(&indio_dev->mlock); |
441 | return ret; | 422 | return ret; |
442 | } | 423 | } |
443 | val16 &= (1 << bits) - 1; | 424 | val16 &= (1 << bits) - 1; |
444 | val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); | 425 | val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); |
445 | *val = val16; | 426 | *val = val16; |
446 | mutex_unlock(&indio_dev->mlock); | 427 | mutex_unlock(&indio_dev->mlock); |
447 | return IIO_VAL_INT; | 428 | return IIO_VAL_INT; |
448 | } | 429 | } |
449 | return -EINVAL; | 430 | return -EINVAL; |
450 | } | 431 | } |
451 | 432 | ||
452 | static int adis16240_write_raw(struct iio_dev *indio_dev, | 433 | static int adis16240_write_raw(struct iio_dev *indio_dev, |
453 | struct iio_chan_spec const *chan, | 434 | struct iio_chan_spec const *chan, |
454 | int val, | 435 | int val, |
455 | int val2, | 436 | int val2, |
456 | long mask) | 437 | long mask) |
457 | { | 438 | { |
458 | int bits = 10; | 439 | int bits = 10; |
459 | s16 val16; | 440 | s16 val16; |
460 | u8 addr; | 441 | u8 addr; |
461 | switch (mask) { | 442 | switch (mask) { |
462 | case IIO_CHAN_INFO_CALIBBIAS: | 443 | case IIO_CHAN_INFO_CALIBBIAS: |
463 | val16 = val & ((1 << bits) - 1); | 444 | val16 = val & ((1 << bits) - 1); |
464 | addr = adis16240_addresses[chan->address][1]; | 445 | addr = adis16240_addresses[chan->address][1]; |
465 | return adis16240_spi_write_reg_16(indio_dev, addr, val16); | 446 | return adis16240_spi_write_reg_16(indio_dev, addr, val16); |
466 | } | 447 | } |
467 | return -EINVAL; | 448 | return -EINVAL; |
468 | } | 449 | } |
469 | 450 | ||
470 | static struct iio_chan_spec adis16240_channels[] = { | 451 | static struct iio_chan_spec adis16240_channels[] = { |
471 | { | 452 | { |
472 | .type = IIO_VOLTAGE, | 453 | .type = IIO_VOLTAGE, |
473 | .indexed = 1, | 454 | .indexed = 1, |
474 | .channel = 0, | 455 | .channel = 0, |
475 | .extend_name = "supply", | 456 | .extend_name = "supply", |
476 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 457 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
477 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 458 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
478 | .address = in_supply, | 459 | .address = in_supply, |
479 | .scan_index = ADIS16240_SCAN_SUPPLY, | 460 | .scan_index = ADIS16240_SCAN_SUPPLY, |
480 | .scan_type = { | 461 | .scan_type = { |
481 | .sign = 'u', | 462 | .sign = 'u', |
482 | .realbits = 10, | 463 | .realbits = 10, |
483 | .storagebits = 16, | 464 | .storagebits = 16, |
484 | }, | 465 | }, |
485 | }, { | 466 | }, { |
486 | .type = IIO_VOLTAGE, | 467 | .type = IIO_VOLTAGE, |
487 | .indexed = 1, | 468 | .indexed = 1, |
488 | .channel = 1, | 469 | .channel = 1, |
489 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, | 470 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, |
490 | .address = in_aux, | 471 | .address = in_aux, |
491 | .scan_index = ADIS16240_SCAN_AUX_ADC, | 472 | .scan_index = ADIS16240_SCAN_AUX_ADC, |
492 | .scan_type = { | 473 | .scan_type = { |
493 | .sign = 'u', | 474 | .sign = 'u', |
494 | .realbits = 10, | 475 | .realbits = 10, |
495 | .storagebits = 16, | 476 | .storagebits = 16, |
496 | }, | 477 | }, |
497 | }, { | 478 | }, { |
498 | .type = IIO_ACCEL, | 479 | .type = IIO_ACCEL, |
499 | .modified = 1, | 480 | .modified = 1, |
500 | .channel2 = IIO_MOD_X, | 481 | .channel2 = IIO_MOD_X, |
501 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 482 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
502 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 483 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
503 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 484 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
504 | IIO_CHAN_INFO_PEAK_SEPARATE_BIT, | 485 | IIO_CHAN_INFO_PEAK_SEPARATE_BIT, |
505 | .address = accel_x, | 486 | .address = accel_x, |
506 | .scan_index = ADIS16240_SCAN_ACC_X, | 487 | .scan_index = ADIS16240_SCAN_ACC_X, |
507 | .scan_type = { | 488 | .scan_type = { |
508 | .sign = 's', | 489 | .sign = 's', |
509 | .realbits = 10, | 490 | .realbits = 10, |
510 | .storagebits = 16, | 491 | .storagebits = 16, |
511 | }, | 492 | }, |
512 | }, { | 493 | }, { |
513 | .type = IIO_ACCEL, | 494 | .type = IIO_ACCEL, |
514 | .modified = 1, | 495 | .modified = 1, |
515 | .channel2 = IIO_MOD_Y, | 496 | .channel2 = IIO_MOD_Y, |
516 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 497 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
517 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 498 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
518 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 499 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
519 | IIO_CHAN_INFO_PEAK_SEPARATE_BIT, | 500 | IIO_CHAN_INFO_PEAK_SEPARATE_BIT, |
520 | .address = accel_y, | 501 | .address = accel_y, |
521 | .scan_index = ADIS16240_SCAN_ACC_Y, | 502 | .scan_index = ADIS16240_SCAN_ACC_Y, |
522 | .scan_type = { | 503 | .scan_type = { |
523 | .sign = 's', | 504 | .sign = 's', |
524 | .realbits = 10, | 505 | .realbits = 10, |
525 | .storagebits = 16, | 506 | .storagebits = 16, |
526 | }, | 507 | }, |
527 | }, { | 508 | }, { |
528 | .type = IIO_ACCEL, | 509 | .type = IIO_ACCEL, |
529 | .modified = 1, | 510 | .modified = 1, |
530 | .channel2 = IIO_MOD_Z, | 511 | .channel2 = IIO_MOD_Z, |
531 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 512 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
532 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 513 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
533 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 514 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
534 | IIO_CHAN_INFO_PEAK_SEPARATE_BIT, | 515 | IIO_CHAN_INFO_PEAK_SEPARATE_BIT, |
535 | .address = accel_z, | 516 | .address = accel_z, |
536 | .scan_index = ADIS16240_SCAN_ACC_Z, | 517 | .scan_index = ADIS16240_SCAN_ACC_Z, |
537 | .scan_type = { | 518 | .scan_type = { |
538 | .sign = 's', | 519 | .sign = 's', |
539 | .realbits = 10, | 520 | .realbits = 10, |
540 | .storagebits = 16, | 521 | .storagebits = 16, |
541 | }, | 522 | }, |
542 | }, { | 523 | }, { |
543 | .type = IIO_TEMP, | 524 | .type = IIO_TEMP, |
544 | .indexed = 1, | 525 | .indexed = 1, |
545 | .channel = 0, | 526 | .channel = 0, |
546 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 527 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
547 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 528 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
548 | .address = temp, | 529 | .address = temp, |
549 | .scan_index = ADIS16240_SCAN_TEMP, | 530 | .scan_index = ADIS16240_SCAN_TEMP, |
550 | .scan_type = { | 531 | .scan_type = { |
551 | .sign = 'u', | 532 | .sign = 'u', |
552 | .realbits = 10, | 533 | .realbits = 10, |
553 | .storagebits = 16, | 534 | .storagebits = 16, |
554 | }, | 535 | }, |
555 | }, | 536 | }, |
556 | IIO_CHAN_SOFT_TIMESTAMP(6) | 537 | IIO_CHAN_SOFT_TIMESTAMP(6) |
557 | }; | 538 | }; |
558 | 539 | ||
559 | static struct attribute *adis16240_attributes[] = { | 540 | static struct attribute *adis16240_attributes[] = { |
560 | &iio_dev_attr_in_accel_xyz_squared_peak_raw.dev_attr.attr, | 541 | &iio_dev_attr_in_accel_xyz_squared_peak_raw.dev_attr.attr, |
561 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, | 542 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, |
562 | &iio_dev_attr_reset.dev_attr.attr, | ||
563 | NULL | 543 | NULL |
564 | }; | 544 | }; |
565 | 545 | ||
566 | static const struct attribute_group adis16240_attribute_group = { | 546 | static const struct attribute_group adis16240_attribute_group = { |
567 | .attrs = adis16240_attributes, | 547 | .attrs = adis16240_attributes, |
568 | }; | 548 | }; |
569 | 549 | ||
570 | static const struct iio_info adis16240_info = { | 550 | static const struct iio_info adis16240_info = { |
571 | .attrs = &adis16240_attribute_group, | 551 | .attrs = &adis16240_attribute_group, |
572 | .read_raw = &adis16240_read_raw, | 552 | .read_raw = &adis16240_read_raw, |
573 | .write_raw = &adis16240_write_raw, | 553 | .write_raw = &adis16240_write_raw, |
574 | .driver_module = THIS_MODULE, | 554 | .driver_module = THIS_MODULE, |
575 | }; | 555 | }; |
576 | 556 | ||
577 | static int __devinit adis16240_probe(struct spi_device *spi) | 557 | static int __devinit adis16240_probe(struct spi_device *spi) |
578 | { | 558 | { |
579 | int ret; | 559 | int ret; |
580 | struct adis16240_state *st; | 560 | struct adis16240_state *st; |
581 | struct iio_dev *indio_dev; | 561 | struct iio_dev *indio_dev; |
582 | 562 | ||
583 | /* setup the industrialio driver allocated elements */ | 563 | /* setup the industrialio driver allocated elements */ |
584 | indio_dev = iio_device_alloc(sizeof(*st)); | 564 | indio_dev = iio_device_alloc(sizeof(*st)); |
585 | if (indio_dev == NULL) { | 565 | if (indio_dev == NULL) { |
586 | ret = -ENOMEM; | 566 | ret = -ENOMEM; |
587 | goto error_ret; | 567 | goto error_ret; |
588 | } | 568 | } |
589 | st = iio_priv(indio_dev); | 569 | st = iio_priv(indio_dev); |
590 | /* this is only used for removal purposes */ | 570 | /* this is only used for removal purposes */ |
591 | spi_set_drvdata(spi, indio_dev); | 571 | spi_set_drvdata(spi, indio_dev); |
592 | 572 | ||
593 | st->us = spi; | 573 | st->us = spi; |
594 | mutex_init(&st->buf_lock); | 574 | mutex_init(&st->buf_lock); |
595 | 575 | ||
596 | indio_dev->name = spi->dev.driver->name; | 576 | indio_dev->name = spi->dev.driver->name; |
597 | indio_dev->dev.parent = &spi->dev; | 577 | indio_dev->dev.parent = &spi->dev; |
598 | indio_dev->info = &adis16240_info; | 578 | indio_dev->info = &adis16240_info; |
599 | indio_dev->channels = adis16240_channels; | 579 | indio_dev->channels = adis16240_channels; |
600 | indio_dev->num_channels = ARRAY_SIZE(adis16240_channels); | 580 | indio_dev->num_channels = ARRAY_SIZE(adis16240_channels); |
601 | indio_dev->modes = INDIO_DIRECT_MODE; | 581 | indio_dev->modes = INDIO_DIRECT_MODE; |
602 | 582 | ||
603 | ret = adis16240_configure_ring(indio_dev); | 583 | ret = adis16240_configure_ring(indio_dev); |
604 | if (ret) | 584 | if (ret) |
605 | goto error_free_dev; | 585 | goto error_free_dev; |
606 | 586 | ||
607 | ret = iio_buffer_register(indio_dev, | 587 | ret = iio_buffer_register(indio_dev, |
608 | adis16240_channels, | 588 | adis16240_channels, |
609 | ARRAY_SIZE(adis16240_channels)); | 589 | ARRAY_SIZE(adis16240_channels)); |
610 | if (ret) { | 590 | if (ret) { |
611 | printk(KERN_ERR "failed to initialize the ring\n"); | 591 | printk(KERN_ERR "failed to initialize the ring\n"); |
612 | goto error_unreg_ring_funcs; | 592 | goto error_unreg_ring_funcs; |
613 | } | 593 | } |
614 | 594 | ||
615 | if (spi->irq) { | 595 | if (spi->irq) { |
616 | ret = adis16240_probe_trigger(indio_dev); | 596 | ret = adis16240_probe_trigger(indio_dev); |
617 | if (ret) | 597 | if (ret) |
618 | goto error_uninitialize_ring; | 598 | goto error_uninitialize_ring; |
619 | } | 599 | } |
620 | 600 | ||
621 | /* Get the device into a sane initial state */ | 601 | /* Get the device into a sane initial state */ |
622 | ret = adis16240_initial_setup(indio_dev); | 602 | ret = adis16240_initial_setup(indio_dev); |
623 | if (ret) | 603 | if (ret) |
624 | goto error_remove_trigger; | 604 | goto error_remove_trigger; |
625 | ret = iio_device_register(indio_dev); | 605 | ret = iio_device_register(indio_dev); |
626 | if (ret) | 606 | if (ret) |
627 | goto error_remove_trigger; | 607 | goto error_remove_trigger; |
628 | return 0; | 608 | return 0; |
629 | 609 | ||
630 | error_remove_trigger: | 610 | error_remove_trigger: |
631 | adis16240_remove_trigger(indio_dev); | 611 | adis16240_remove_trigger(indio_dev); |
632 | error_uninitialize_ring: | 612 | error_uninitialize_ring: |
633 | iio_buffer_unregister(indio_dev); | 613 | iio_buffer_unregister(indio_dev); |
634 | error_unreg_ring_funcs: | 614 | error_unreg_ring_funcs: |
635 | adis16240_unconfigure_ring(indio_dev); | 615 | adis16240_unconfigure_ring(indio_dev); |
636 | error_free_dev: | 616 | error_free_dev: |
637 | iio_device_free(indio_dev); | 617 | iio_device_free(indio_dev); |
638 | error_ret: | 618 | error_ret: |
639 | return ret; | 619 | return ret; |
640 | } | 620 | } |
641 | 621 | ||
642 | static int adis16240_remove(struct spi_device *spi) | 622 | static int adis16240_remove(struct spi_device *spi) |
643 | { | 623 | { |
644 | 624 | ||
645 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | 625 | struct iio_dev *indio_dev = spi_get_drvdata(spi); |
646 | 626 | ||
647 | iio_device_unregister(indio_dev); | 627 | iio_device_unregister(indio_dev); |
648 | adis16240_remove_trigger(indio_dev); | 628 | adis16240_remove_trigger(indio_dev); |
649 | iio_buffer_unregister(indio_dev); | 629 | iio_buffer_unregister(indio_dev); |
650 | adis16240_unconfigure_ring(indio_dev); | 630 | adis16240_unconfigure_ring(indio_dev); |
651 | iio_device_free(indio_dev); | 631 | iio_device_free(indio_dev); |
652 | 632 | ||
653 | return 0; | 633 | return 0; |
654 | } | 634 | } |
655 | 635 | ||
656 | static struct spi_driver adis16240_driver = { | 636 | static struct spi_driver adis16240_driver = { |
657 | .driver = { | 637 | .driver = { |
658 | .name = "adis16240", | 638 | .name = "adis16240", |
659 | .owner = THIS_MODULE, | 639 | .owner = THIS_MODULE, |
660 | }, | 640 | }, |
661 | .probe = adis16240_probe, | 641 | .probe = adis16240_probe, |
662 | .remove = __devexit_p(adis16240_remove), | 642 | .remove = __devexit_p(adis16240_remove), |
663 | }; | 643 | }; |
664 | module_spi_driver(adis16240_driver); | 644 | module_spi_driver(adis16240_driver); |
665 | 645 | ||
666 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | 646 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); |
667 | MODULE_DESCRIPTION("Analog Devices Programmable Impact Sensor and Recorder"); | 647 | MODULE_DESCRIPTION("Analog Devices Programmable Impact Sensor and Recorder"); |
668 | MODULE_LICENSE("GPL v2"); | 648 | MODULE_LICENSE("GPL v2"); |
669 | MODULE_ALIAS("spi:adis16240"); | 649 | MODULE_ALIAS("spi:adis16240"); |
670 | 650 |
drivers/staging/iio/gyro/adis16260_core.c
1 | /* | 1 | /* |
2 | * ADIS16260/ADIS16265 Programmable Digital Gyroscope Sensor Driver | 2 | * ADIS16260/ADIS16265 Programmable Digital Gyroscope Sensor Driver |
3 | * | 3 | * |
4 | * Copyright 2010 Analog Devices Inc. | 4 | * Copyright 2010 Analog Devices Inc. |
5 | * | 5 | * |
6 | * Licensed under the GPL-2 or later. | 6 | * Licensed under the GPL-2 or later. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/interrupt.h> | 9 | #include <linux/interrupt.h> |
10 | #include <linux/irq.h> | 10 | #include <linux/irq.h> |
11 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
12 | #include <linux/mutex.h> | 12 | #include <linux/mutex.h> |
13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/spi/spi.h> | 15 | #include <linux/spi/spi.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/sysfs.h> | 17 | #include <linux/sysfs.h> |
18 | #include <linux/list.h> | 18 | #include <linux/list.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | 20 | ||
21 | #include <linux/iio/iio.h> | 21 | #include <linux/iio/iio.h> |
22 | #include <linux/iio/sysfs.h> | 22 | #include <linux/iio/sysfs.h> |
23 | #include <linux/iio/buffer.h> | 23 | #include <linux/iio/buffer.h> |
24 | 24 | ||
25 | #include "adis16260.h" | 25 | #include "adis16260.h" |
26 | 26 | ||
27 | #define DRIVER_NAME "adis16260" | 27 | #define DRIVER_NAME "adis16260" |
28 | 28 | ||
29 | static int adis16260_check_status(struct iio_dev *indio_dev); | 29 | static int adis16260_check_status(struct iio_dev *indio_dev); |
30 | 30 | ||
31 | /** | 31 | /** |
32 | * adis16260_spi_write_reg_8() - write single byte to a register | 32 | * adis16260_spi_write_reg_8() - write single byte to a register |
33 | * @indio_dev: iio_dev for the device | 33 | * @indio_dev: iio_dev for the device |
34 | * @reg_address: the address of the register to be written | 34 | * @reg_address: the address of the register to be written |
35 | * @val: the value to write | 35 | * @val: the value to write |
36 | **/ | 36 | **/ |
37 | static int adis16260_spi_write_reg_8(struct iio_dev *indio_dev, | 37 | static int adis16260_spi_write_reg_8(struct iio_dev *indio_dev, |
38 | u8 reg_address, | 38 | u8 reg_address, |
39 | u8 val) | 39 | u8 val) |
40 | { | 40 | { |
41 | int ret; | 41 | int ret; |
42 | struct adis16260_state *st = iio_priv(indio_dev); | 42 | struct adis16260_state *st = iio_priv(indio_dev); |
43 | 43 | ||
44 | mutex_lock(&st->buf_lock); | 44 | mutex_lock(&st->buf_lock); |
45 | st->tx[0] = ADIS16260_WRITE_REG(reg_address); | 45 | st->tx[0] = ADIS16260_WRITE_REG(reg_address); |
46 | st->tx[1] = val; | 46 | st->tx[1] = val; |
47 | 47 | ||
48 | ret = spi_write(st->us, st->tx, 2); | 48 | ret = spi_write(st->us, st->tx, 2); |
49 | mutex_unlock(&st->buf_lock); | 49 | mutex_unlock(&st->buf_lock); |
50 | 50 | ||
51 | return ret; | 51 | return ret; |
52 | } | 52 | } |
53 | 53 | ||
54 | /** | 54 | /** |
55 | * adis16260_spi_write_reg_16() - write 2 bytes to a pair of registers | 55 | * adis16260_spi_write_reg_16() - write 2 bytes to a pair of registers |
56 | * @indio_dev: iio_dev for the device | 56 | * @indio_dev: iio_dev for the device |
57 | * @reg_address: the address of the lower of the two registers. Second register | 57 | * @reg_address: the address of the lower of the two registers. Second register |
58 | * is assumed to have address one greater. | 58 | * is assumed to have address one greater. |
59 | * @val: value to be written | 59 | * @val: value to be written |
60 | **/ | 60 | **/ |
61 | static int adis16260_spi_write_reg_16(struct iio_dev *indio_dev, | 61 | static int adis16260_spi_write_reg_16(struct iio_dev *indio_dev, |
62 | u8 lower_reg_address, | 62 | u8 lower_reg_address, |
63 | u16 value) | 63 | u16 value) |
64 | { | 64 | { |
65 | int ret; | 65 | int ret; |
66 | struct spi_message msg; | 66 | struct spi_message msg; |
67 | struct adis16260_state *st = iio_priv(indio_dev); | 67 | struct adis16260_state *st = iio_priv(indio_dev); |
68 | struct spi_transfer xfers[] = { | 68 | struct spi_transfer xfers[] = { |
69 | { | 69 | { |
70 | .tx_buf = st->tx, | 70 | .tx_buf = st->tx, |
71 | .bits_per_word = 8, | 71 | .bits_per_word = 8, |
72 | .len = 2, | 72 | .len = 2, |
73 | .cs_change = 1, | 73 | .cs_change = 1, |
74 | .delay_usecs = 20, | 74 | .delay_usecs = 20, |
75 | }, { | 75 | }, { |
76 | .tx_buf = st->tx + 2, | 76 | .tx_buf = st->tx + 2, |
77 | .bits_per_word = 8, | 77 | .bits_per_word = 8, |
78 | .len = 2, | 78 | .len = 2, |
79 | .delay_usecs = 20, | 79 | .delay_usecs = 20, |
80 | }, | 80 | }, |
81 | }; | 81 | }; |
82 | 82 | ||
83 | mutex_lock(&st->buf_lock); | 83 | mutex_lock(&st->buf_lock); |
84 | st->tx[0] = ADIS16260_WRITE_REG(lower_reg_address); | 84 | st->tx[0] = ADIS16260_WRITE_REG(lower_reg_address); |
85 | st->tx[1] = value & 0xFF; | 85 | st->tx[1] = value & 0xFF; |
86 | st->tx[2] = ADIS16260_WRITE_REG(lower_reg_address + 1); | 86 | st->tx[2] = ADIS16260_WRITE_REG(lower_reg_address + 1); |
87 | st->tx[3] = (value >> 8) & 0xFF; | 87 | st->tx[3] = (value >> 8) & 0xFF; |
88 | 88 | ||
89 | spi_message_init(&msg); | 89 | spi_message_init(&msg); |
90 | spi_message_add_tail(&xfers[0], &msg); | 90 | spi_message_add_tail(&xfers[0], &msg); |
91 | spi_message_add_tail(&xfers[1], &msg); | 91 | spi_message_add_tail(&xfers[1], &msg); |
92 | ret = spi_sync(st->us, &msg); | 92 | ret = spi_sync(st->us, &msg); |
93 | mutex_unlock(&st->buf_lock); | 93 | mutex_unlock(&st->buf_lock); |
94 | 94 | ||
95 | return ret; | 95 | return ret; |
96 | } | 96 | } |
97 | 97 | ||
98 | /** | 98 | /** |
99 | * adis16260_spi_read_reg_16() - read 2 bytes from a 16-bit register | 99 | * adis16260_spi_read_reg_16() - read 2 bytes from a 16-bit register |
100 | * @indio_dev: iio_dev for the device | 100 | * @indio_dev: iio_dev for the device |
101 | * @reg_address: the address of the lower of the two registers. Second register | 101 | * @reg_address: the address of the lower of the two registers. Second register |
102 | * is assumed to have address one greater. | 102 | * is assumed to have address one greater. |
103 | * @val: somewhere to pass back the value read | 103 | * @val: somewhere to pass back the value read |
104 | **/ | 104 | **/ |
105 | static int adis16260_spi_read_reg_16(struct iio_dev *indio_dev, | 105 | static int adis16260_spi_read_reg_16(struct iio_dev *indio_dev, |
106 | u8 lower_reg_address, | 106 | u8 lower_reg_address, |
107 | u16 *val) | 107 | u16 *val) |
108 | { | 108 | { |
109 | struct spi_message msg; | 109 | struct spi_message msg; |
110 | struct adis16260_state *st = iio_priv(indio_dev); | 110 | struct adis16260_state *st = iio_priv(indio_dev); |
111 | int ret; | 111 | int ret; |
112 | struct spi_transfer xfers[] = { | 112 | struct spi_transfer xfers[] = { |
113 | { | 113 | { |
114 | .tx_buf = st->tx, | 114 | .tx_buf = st->tx, |
115 | .bits_per_word = 8, | 115 | .bits_per_word = 8, |
116 | .len = 2, | 116 | .len = 2, |
117 | .cs_change = 1, | 117 | .cs_change = 1, |
118 | .delay_usecs = 30, | 118 | .delay_usecs = 30, |
119 | }, { | 119 | }, { |
120 | .rx_buf = st->rx, | 120 | .rx_buf = st->rx, |
121 | .bits_per_word = 8, | 121 | .bits_per_word = 8, |
122 | .len = 2, | 122 | .len = 2, |
123 | .delay_usecs = 30, | 123 | .delay_usecs = 30, |
124 | }, | 124 | }, |
125 | }; | 125 | }; |
126 | 126 | ||
127 | mutex_lock(&st->buf_lock); | 127 | mutex_lock(&st->buf_lock); |
128 | st->tx[0] = ADIS16260_READ_REG(lower_reg_address); | 128 | st->tx[0] = ADIS16260_READ_REG(lower_reg_address); |
129 | st->tx[1] = 0; | 129 | st->tx[1] = 0; |
130 | 130 | ||
131 | spi_message_init(&msg); | 131 | spi_message_init(&msg); |
132 | spi_message_add_tail(&xfers[0], &msg); | 132 | spi_message_add_tail(&xfers[0], &msg); |
133 | spi_message_add_tail(&xfers[1], &msg); | 133 | spi_message_add_tail(&xfers[1], &msg); |
134 | ret = spi_sync(st->us, &msg); | 134 | ret = spi_sync(st->us, &msg); |
135 | if (ret) { | 135 | if (ret) { |
136 | dev_err(&st->us->dev, | 136 | dev_err(&st->us->dev, |
137 | "problem when reading 16 bit register 0x%02X", | 137 | "problem when reading 16 bit register 0x%02X", |
138 | lower_reg_address); | 138 | lower_reg_address); |
139 | goto error_ret; | 139 | goto error_ret; |
140 | } | 140 | } |
141 | *val = (st->rx[0] << 8) | st->rx[1]; | 141 | *val = (st->rx[0] << 8) | st->rx[1]; |
142 | 142 | ||
143 | error_ret: | 143 | error_ret: |
144 | mutex_unlock(&st->buf_lock); | 144 | mutex_unlock(&st->buf_lock); |
145 | return ret; | 145 | return ret; |
146 | } | 146 | } |
147 | 147 | ||
148 | static ssize_t adis16260_read_frequency_available(struct device *dev, | 148 | static ssize_t adis16260_read_frequency_available(struct device *dev, |
149 | struct device_attribute *attr, | 149 | struct device_attribute *attr, |
150 | char *buf) | 150 | char *buf) |
151 | { | 151 | { |
152 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 152 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
153 | struct adis16260_state *st = iio_priv(indio_dev); | 153 | struct adis16260_state *st = iio_priv(indio_dev); |
154 | if (spi_get_device_id(st->us)->driver_data) | 154 | if (spi_get_device_id(st->us)->driver_data) |
155 | return sprintf(buf, "%s\n", "0.129 ~ 256"); | 155 | return sprintf(buf, "%s\n", "0.129 ~ 256"); |
156 | else | 156 | else |
157 | return sprintf(buf, "%s\n", "256 2048"); | 157 | return sprintf(buf, "%s\n", "256 2048"); |
158 | } | 158 | } |
159 | 159 | ||
160 | static ssize_t adis16260_read_frequency(struct device *dev, | 160 | static ssize_t adis16260_read_frequency(struct device *dev, |
161 | struct device_attribute *attr, | 161 | struct device_attribute *attr, |
162 | char *buf) | 162 | char *buf) |
163 | { | 163 | { |
164 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 164 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
165 | struct adis16260_state *st = iio_priv(indio_dev); | 165 | struct adis16260_state *st = iio_priv(indio_dev); |
166 | int ret, len = 0; | 166 | int ret, len = 0; |
167 | u16 t; | 167 | u16 t; |
168 | int sps; | 168 | int sps; |
169 | ret = adis16260_spi_read_reg_16(indio_dev, | 169 | ret = adis16260_spi_read_reg_16(indio_dev, |
170 | ADIS16260_SMPL_PRD, | 170 | ADIS16260_SMPL_PRD, |
171 | &t); | 171 | &t); |
172 | if (ret) | 172 | if (ret) |
173 | return ret; | 173 | return ret; |
174 | 174 | ||
175 | if (spi_get_device_id(st->us)->driver_data) /* If an adis16251 */ | 175 | if (spi_get_device_id(st->us)->driver_data) /* If an adis16251 */ |
176 | sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 8 : 256; | 176 | sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 8 : 256; |
177 | else | 177 | else |
178 | sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 66 : 2048; | 178 | sps = (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 66 : 2048; |
179 | sps /= (t & ADIS16260_SMPL_PRD_DIV_MASK) + 1; | 179 | sps /= (t & ADIS16260_SMPL_PRD_DIV_MASK) + 1; |
180 | len = sprintf(buf, "%d SPS\n", sps); | 180 | len = sprintf(buf, "%d SPS\n", sps); |
181 | return len; | 181 | return len; |
182 | } | 182 | } |
183 | 183 | ||
184 | static ssize_t adis16260_write_frequency(struct device *dev, | 184 | static ssize_t adis16260_write_frequency(struct device *dev, |
185 | struct device_attribute *attr, | 185 | struct device_attribute *attr, |
186 | const char *buf, | 186 | const char *buf, |
187 | size_t len) | 187 | size_t len) |
188 | { | 188 | { |
189 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 189 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
190 | struct adis16260_state *st = iio_priv(indio_dev); | 190 | struct adis16260_state *st = iio_priv(indio_dev); |
191 | long val; | 191 | long val; |
192 | int ret; | 192 | int ret; |
193 | u8 t; | 193 | u8 t; |
194 | 194 | ||
195 | ret = strict_strtol(buf, 10, &val); | 195 | ret = strict_strtol(buf, 10, &val); |
196 | if (ret) | 196 | if (ret) |
197 | return ret; | 197 | return ret; |
198 | 198 | ||
199 | mutex_lock(&indio_dev->mlock); | 199 | mutex_lock(&indio_dev->mlock); |
200 | if (spi_get_device_id(st->us)) { | 200 | if (spi_get_device_id(st->us)) { |
201 | t = (256 / val); | 201 | t = (256 / val); |
202 | if (t > 0) | 202 | if (t > 0) |
203 | t--; | 203 | t--; |
204 | t &= ADIS16260_SMPL_PRD_DIV_MASK; | 204 | t &= ADIS16260_SMPL_PRD_DIV_MASK; |
205 | } else { | 205 | } else { |
206 | t = (2048 / val); | 206 | t = (2048 / val); |
207 | if (t > 0) | 207 | if (t > 0) |
208 | t--; | 208 | t--; |
209 | t &= ADIS16260_SMPL_PRD_DIV_MASK; | 209 | t &= ADIS16260_SMPL_PRD_DIV_MASK; |
210 | } | 210 | } |
211 | if ((t & ADIS16260_SMPL_PRD_DIV_MASK) >= 0x0A) | 211 | if ((t & ADIS16260_SMPL_PRD_DIV_MASK) >= 0x0A) |
212 | st->us->max_speed_hz = ADIS16260_SPI_SLOW; | 212 | st->us->max_speed_hz = ADIS16260_SPI_SLOW; |
213 | else | 213 | else |
214 | st->us->max_speed_hz = ADIS16260_SPI_FAST; | 214 | st->us->max_speed_hz = ADIS16260_SPI_FAST; |
215 | ret = adis16260_spi_write_reg_8(indio_dev, | 215 | ret = adis16260_spi_write_reg_8(indio_dev, |
216 | ADIS16260_SMPL_PRD, | 216 | ADIS16260_SMPL_PRD, |
217 | t); | 217 | t); |
218 | 218 | ||
219 | mutex_unlock(&indio_dev->mlock); | 219 | mutex_unlock(&indio_dev->mlock); |
220 | 220 | ||
221 | return ret ? ret : len; | 221 | return ret ? ret : len; |
222 | } | 222 | } |
223 | 223 | ||
224 | static int adis16260_reset(struct iio_dev *indio_dev) | 224 | static int adis16260_reset(struct iio_dev *indio_dev) |
225 | { | 225 | { |
226 | int ret; | 226 | int ret; |
227 | ret = adis16260_spi_write_reg_8(indio_dev, | 227 | ret = adis16260_spi_write_reg_8(indio_dev, |
228 | ADIS16260_GLOB_CMD, | 228 | ADIS16260_GLOB_CMD, |
229 | ADIS16260_GLOB_CMD_SW_RESET); | 229 | ADIS16260_GLOB_CMD_SW_RESET); |
230 | if (ret) | 230 | if (ret) |
231 | dev_err(&indio_dev->dev, "problem resetting device"); | 231 | dev_err(&indio_dev->dev, "problem resetting device"); |
232 | 232 | ||
233 | return ret; | 233 | return ret; |
234 | } | 234 | } |
235 | 235 | ||
236 | static ssize_t adis16260_write_reset(struct device *dev, | ||
237 | struct device_attribute *attr, | ||
238 | const char *buf, size_t len) | ||
239 | { | ||
240 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | ||
241 | if (len < 1) | ||
242 | return -EINVAL; | ||
243 | switch (buf[0]) { | ||
244 | case '1': | ||
245 | case 'y': | ||
246 | case 'Y': | ||
247 | return adis16260_reset(indio_dev); | ||
248 | } | ||
249 | return -EINVAL; | ||
250 | } | ||
251 | |||
252 | int adis16260_set_irq(struct iio_dev *indio_dev, bool enable) | 236 | int adis16260_set_irq(struct iio_dev *indio_dev, bool enable) |
253 | { | 237 | { |
254 | int ret; | 238 | int ret; |
255 | u16 msc; | 239 | u16 msc; |
256 | ret = adis16260_spi_read_reg_16(indio_dev, ADIS16260_MSC_CTRL, &msc); | 240 | ret = adis16260_spi_read_reg_16(indio_dev, ADIS16260_MSC_CTRL, &msc); |
257 | if (ret) | 241 | if (ret) |
258 | goto error_ret; | 242 | goto error_ret; |
259 | 243 | ||
260 | msc |= ADIS16260_MSC_CTRL_DATA_RDY_POL_HIGH; | 244 | msc |= ADIS16260_MSC_CTRL_DATA_RDY_POL_HIGH; |
261 | if (enable) | 245 | if (enable) |
262 | msc |= ADIS16260_MSC_CTRL_DATA_RDY_EN; | 246 | msc |= ADIS16260_MSC_CTRL_DATA_RDY_EN; |
263 | else | 247 | else |
264 | msc &= ~ADIS16260_MSC_CTRL_DATA_RDY_EN; | 248 | msc &= ~ADIS16260_MSC_CTRL_DATA_RDY_EN; |
265 | 249 | ||
266 | ret = adis16260_spi_write_reg_16(indio_dev, ADIS16260_MSC_CTRL, msc); | 250 | ret = adis16260_spi_write_reg_16(indio_dev, ADIS16260_MSC_CTRL, msc); |
267 | if (ret) | 251 | if (ret) |
268 | goto error_ret; | 252 | goto error_ret; |
269 | 253 | ||
270 | error_ret: | 254 | error_ret: |
271 | return ret; | 255 | return ret; |
272 | } | 256 | } |
273 | 257 | ||
274 | /* Power down the device */ | 258 | /* Power down the device */ |
275 | static int adis16260_stop_device(struct iio_dev *indio_dev) | 259 | static int adis16260_stop_device(struct iio_dev *indio_dev) |
276 | { | 260 | { |
277 | int ret; | 261 | int ret; |
278 | u16 val = ADIS16260_SLP_CNT_POWER_OFF; | 262 | u16 val = ADIS16260_SLP_CNT_POWER_OFF; |
279 | 263 | ||
280 | ret = adis16260_spi_write_reg_16(indio_dev, ADIS16260_SLP_CNT, val); | 264 | ret = adis16260_spi_write_reg_16(indio_dev, ADIS16260_SLP_CNT, val); |
281 | if (ret) | 265 | if (ret) |
282 | dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT"); | 266 | dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT"); |
283 | 267 | ||
284 | return ret; | 268 | return ret; |
285 | } | 269 | } |
286 | 270 | ||
287 | static int adis16260_self_test(struct iio_dev *indio_dev) | 271 | static int adis16260_self_test(struct iio_dev *indio_dev) |
288 | { | 272 | { |
289 | int ret; | 273 | int ret; |
290 | ret = adis16260_spi_write_reg_16(indio_dev, | 274 | ret = adis16260_spi_write_reg_16(indio_dev, |
291 | ADIS16260_MSC_CTRL, | 275 | ADIS16260_MSC_CTRL, |
292 | ADIS16260_MSC_CTRL_MEM_TEST); | 276 | ADIS16260_MSC_CTRL_MEM_TEST); |
293 | if (ret) { | 277 | if (ret) { |
294 | dev_err(&indio_dev->dev, "problem starting self test"); | 278 | dev_err(&indio_dev->dev, "problem starting self test"); |
295 | goto err_ret; | 279 | goto err_ret; |
296 | } | 280 | } |
297 | 281 | ||
298 | adis16260_check_status(indio_dev); | 282 | adis16260_check_status(indio_dev); |
299 | 283 | ||
300 | err_ret: | 284 | err_ret: |
301 | return ret; | 285 | return ret; |
302 | } | 286 | } |
303 | 287 | ||
304 | static int adis16260_check_status(struct iio_dev *indio_dev) | 288 | static int adis16260_check_status(struct iio_dev *indio_dev) |
305 | { | 289 | { |
306 | u16 status; | 290 | u16 status; |
307 | int ret; | 291 | int ret; |
308 | struct device *dev = &indio_dev->dev; | 292 | struct device *dev = &indio_dev->dev; |
309 | 293 | ||
310 | ret = adis16260_spi_read_reg_16(indio_dev, | 294 | ret = adis16260_spi_read_reg_16(indio_dev, |
311 | ADIS16260_DIAG_STAT, | 295 | ADIS16260_DIAG_STAT, |
312 | &status); | 296 | &status); |
313 | 297 | ||
314 | if (ret < 0) { | 298 | if (ret < 0) { |
315 | dev_err(dev, "Reading status failed\n"); | 299 | dev_err(dev, "Reading status failed\n"); |
316 | goto error_ret; | 300 | goto error_ret; |
317 | } | 301 | } |
318 | ret = status & 0x7F; | 302 | ret = status & 0x7F; |
319 | if (status & ADIS16260_DIAG_STAT_FLASH_CHK) | 303 | if (status & ADIS16260_DIAG_STAT_FLASH_CHK) |
320 | dev_err(dev, "Flash checksum error\n"); | 304 | dev_err(dev, "Flash checksum error\n"); |
321 | if (status & ADIS16260_DIAG_STAT_SELF_TEST) | 305 | if (status & ADIS16260_DIAG_STAT_SELF_TEST) |
322 | dev_err(dev, "Self test error\n"); | 306 | dev_err(dev, "Self test error\n"); |
323 | if (status & ADIS16260_DIAG_STAT_OVERFLOW) | 307 | if (status & ADIS16260_DIAG_STAT_OVERFLOW) |
324 | dev_err(dev, "Sensor overrange\n"); | 308 | dev_err(dev, "Sensor overrange\n"); |
325 | if (status & ADIS16260_DIAG_STAT_SPI_FAIL) | 309 | if (status & ADIS16260_DIAG_STAT_SPI_FAIL) |
326 | dev_err(dev, "SPI failure\n"); | 310 | dev_err(dev, "SPI failure\n"); |
327 | if (status & ADIS16260_DIAG_STAT_FLASH_UPT) | 311 | if (status & ADIS16260_DIAG_STAT_FLASH_UPT) |
328 | dev_err(dev, "Flash update failed\n"); | 312 | dev_err(dev, "Flash update failed\n"); |
329 | if (status & ADIS16260_DIAG_STAT_POWER_HIGH) | 313 | if (status & ADIS16260_DIAG_STAT_POWER_HIGH) |
330 | dev_err(dev, "Power supply above 5.25V\n"); | 314 | dev_err(dev, "Power supply above 5.25V\n"); |
331 | if (status & ADIS16260_DIAG_STAT_POWER_LOW) | 315 | if (status & ADIS16260_DIAG_STAT_POWER_LOW) |
332 | dev_err(dev, "Power supply below 4.75V\n"); | 316 | dev_err(dev, "Power supply below 4.75V\n"); |
333 | 317 | ||
334 | error_ret: | 318 | error_ret: |
335 | return ret; | 319 | return ret; |
336 | } | 320 | } |
337 | 321 | ||
338 | static int adis16260_initial_setup(struct iio_dev *indio_dev) | 322 | static int adis16260_initial_setup(struct iio_dev *indio_dev) |
339 | { | 323 | { |
340 | int ret; | 324 | int ret; |
341 | struct device *dev = &indio_dev->dev; | 325 | struct device *dev = &indio_dev->dev; |
342 | 326 | ||
343 | /* Disable IRQ */ | 327 | /* Disable IRQ */ |
344 | ret = adis16260_set_irq(indio_dev, false); | 328 | ret = adis16260_set_irq(indio_dev, false); |
345 | if (ret) { | 329 | if (ret) { |
346 | dev_err(dev, "disable irq failed"); | 330 | dev_err(dev, "disable irq failed"); |
347 | goto err_ret; | 331 | goto err_ret; |
348 | } | 332 | } |
349 | 333 | ||
350 | /* Do self test */ | 334 | /* Do self test */ |
351 | ret = adis16260_self_test(indio_dev); | 335 | ret = adis16260_self_test(indio_dev); |
352 | if (ret) { | 336 | if (ret) { |
353 | dev_err(dev, "self test failure"); | 337 | dev_err(dev, "self test failure"); |
354 | goto err_ret; | 338 | goto err_ret; |
355 | } | 339 | } |
356 | 340 | ||
357 | /* Read status register to check the result */ | 341 | /* Read status register to check the result */ |
358 | ret = adis16260_check_status(indio_dev); | 342 | ret = adis16260_check_status(indio_dev); |
359 | if (ret) { | 343 | if (ret) { |
360 | adis16260_reset(indio_dev); | 344 | adis16260_reset(indio_dev); |
361 | dev_err(dev, "device not playing ball -> reset"); | 345 | dev_err(dev, "device not playing ball -> reset"); |
362 | msleep(ADIS16260_STARTUP_DELAY); | 346 | msleep(ADIS16260_STARTUP_DELAY); |
363 | ret = adis16260_check_status(indio_dev); | 347 | ret = adis16260_check_status(indio_dev); |
364 | if (ret) { | 348 | if (ret) { |
365 | dev_err(dev, "giving up"); | 349 | dev_err(dev, "giving up"); |
366 | goto err_ret; | 350 | goto err_ret; |
367 | } | 351 | } |
368 | } | 352 | } |
369 | 353 | ||
370 | err_ret: | 354 | err_ret: |
371 | return ret; | 355 | return ret; |
372 | } | 356 | } |
373 | 357 | ||
374 | static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, | 358 | static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, |
375 | adis16260_read_frequency, | 359 | adis16260_read_frequency, |
376 | adis16260_write_frequency); | 360 | adis16260_write_frequency); |
377 | 361 | ||
378 | static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16260_write_reset, 0); | ||
379 | |||
380 | static IIO_DEVICE_ATTR(sampling_frequency_available, | 362 | static IIO_DEVICE_ATTR(sampling_frequency_available, |
381 | S_IRUGO, adis16260_read_frequency_available, NULL, 0); | 363 | S_IRUGO, adis16260_read_frequency_available, NULL, 0); |
382 | 364 | ||
383 | enum adis16260_channel { | 365 | enum adis16260_channel { |
384 | gyro, | 366 | gyro, |
385 | temp, | 367 | temp, |
386 | in_supply, | 368 | in_supply, |
387 | in_aux, | 369 | in_aux, |
388 | angle, | 370 | angle, |
389 | }; | 371 | }; |
390 | #define ADIS16260_GYRO_CHANNEL_SET(axis, mod) \ | 372 | #define ADIS16260_GYRO_CHANNEL_SET(axis, mod) \ |
391 | struct iio_chan_spec adis16260_channels_##axis[] = { \ | 373 | struct iio_chan_spec adis16260_channels_##axis[] = { \ |
392 | { \ | 374 | { \ |
393 | .type = IIO_ANGL_VEL, \ | 375 | .type = IIO_ANGL_VEL, \ |
394 | .modified = 1, \ | 376 | .modified = 1, \ |
395 | .channel2 = mod, \ | 377 | .channel2 = mod, \ |
396 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ | 378 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ |
397 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \ | 379 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | \ |
398 | IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ | 380 | IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ |
399 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ | 381 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ |
400 | .address = gyro, \ | 382 | .address = gyro, \ |
401 | .scan_index = ADIS16260_SCAN_GYRO, \ | 383 | .scan_index = ADIS16260_SCAN_GYRO, \ |
402 | .scan_type = { \ | 384 | .scan_type = { \ |
403 | .sign = 's', \ | 385 | .sign = 's', \ |
404 | .realbits = 14, \ | 386 | .realbits = 14, \ |
405 | .storagebits = 16, \ | 387 | .storagebits = 16, \ |
406 | }, \ | 388 | }, \ |
407 | }, { \ | 389 | }, { \ |
408 | .type = IIO_ANGL, \ | 390 | .type = IIO_ANGL, \ |
409 | .modified = 1, \ | 391 | .modified = 1, \ |
410 | .channel2 = mod, \ | 392 | .channel2 = mod, \ |
411 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, \ | 393 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, \ |
412 | .address = angle, \ | 394 | .address = angle, \ |
413 | .scan_index = ADIS16260_SCAN_ANGL, \ | 395 | .scan_index = ADIS16260_SCAN_ANGL, \ |
414 | .scan_type = { \ | 396 | .scan_type = { \ |
415 | .sign = 'u', \ | 397 | .sign = 'u', \ |
416 | .realbits = 14, \ | 398 | .realbits = 14, \ |
417 | .storagebits = 16, \ | 399 | .storagebits = 16, \ |
418 | }, \ | 400 | }, \ |
419 | }, { \ | 401 | }, { \ |
420 | .type = IIO_TEMP, \ | 402 | .type = IIO_TEMP, \ |
421 | .indexed = 1, \ | 403 | .indexed = 1, \ |
422 | .channel = 0, \ | 404 | .channel = 0, \ |
423 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ | 405 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ |
424 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \ | 406 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \ |
425 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ | 407 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ |
426 | .address = temp, \ | 408 | .address = temp, \ |
427 | .scan_index = ADIS16260_SCAN_TEMP, \ | 409 | .scan_index = ADIS16260_SCAN_TEMP, \ |
428 | .scan_type = { \ | 410 | .scan_type = { \ |
429 | .sign = 'u', \ | 411 | .sign = 'u', \ |
430 | .realbits = 12, \ | 412 | .realbits = 12, \ |
431 | .storagebits = 16, \ | 413 | .storagebits = 16, \ |
432 | }, \ | 414 | }, \ |
433 | }, { \ | 415 | }, { \ |
434 | .type = IIO_VOLTAGE, \ | 416 | .type = IIO_VOLTAGE, \ |
435 | .indexed = 1, \ | 417 | .indexed = 1, \ |
436 | .channel = 0, \ | 418 | .channel = 0, \ |
437 | .extend_name = "supply", \ | 419 | .extend_name = "supply", \ |
438 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ | 420 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ |
439 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ | 421 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ |
440 | .address = in_supply, \ | 422 | .address = in_supply, \ |
441 | .scan_index = ADIS16260_SCAN_SUPPLY, \ | 423 | .scan_index = ADIS16260_SCAN_SUPPLY, \ |
442 | .scan_type = { \ | 424 | .scan_type = { \ |
443 | .sign = 'u', \ | 425 | .sign = 'u', \ |
444 | .realbits = 12, \ | 426 | .realbits = 12, \ |
445 | .storagebits = 16, \ | 427 | .storagebits = 16, \ |
446 | }, \ | 428 | }, \ |
447 | }, { \ | 429 | }, { \ |
448 | .type = IIO_VOLTAGE, \ | 430 | .type = IIO_VOLTAGE, \ |
449 | .indexed = 1, \ | 431 | .indexed = 1, \ |
450 | .channel = 1, \ | 432 | .channel = 1, \ |
451 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ | 433 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ |
452 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ | 434 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ |
453 | .address = in_aux, \ | 435 | .address = in_aux, \ |
454 | .scan_index = ADIS16260_SCAN_AUX_ADC, \ | 436 | .scan_index = ADIS16260_SCAN_AUX_ADC, \ |
455 | .scan_type = { \ | 437 | .scan_type = { \ |
456 | .sign = 'u', \ | 438 | .sign = 'u', \ |
457 | .realbits = 12, \ | 439 | .realbits = 12, \ |
458 | .storagebits = 16, \ | 440 | .storagebits = 16, \ |
459 | }, \ | 441 | }, \ |
460 | }, \ | 442 | }, \ |
461 | IIO_CHAN_SOFT_TIMESTAMP(5), \ | 443 | IIO_CHAN_SOFT_TIMESTAMP(5), \ |
462 | } | 444 | } |
463 | 445 | ||
464 | static const ADIS16260_GYRO_CHANNEL_SET(x, IIO_MOD_X); | 446 | static const ADIS16260_GYRO_CHANNEL_SET(x, IIO_MOD_X); |
465 | static const ADIS16260_GYRO_CHANNEL_SET(y, IIO_MOD_Y); | 447 | static const ADIS16260_GYRO_CHANNEL_SET(y, IIO_MOD_Y); |
466 | static const ADIS16260_GYRO_CHANNEL_SET(z, IIO_MOD_Z); | 448 | static const ADIS16260_GYRO_CHANNEL_SET(z, IIO_MOD_Z); |
467 | 449 | ||
468 | static const u8 adis16260_addresses[5][3] = { | 450 | static const u8 adis16260_addresses[5][3] = { |
469 | [gyro] = { ADIS16260_GYRO_OUT, | 451 | [gyro] = { ADIS16260_GYRO_OUT, |
470 | ADIS16260_GYRO_OFF, | 452 | ADIS16260_GYRO_OFF, |
471 | ADIS16260_GYRO_SCALE }, | 453 | ADIS16260_GYRO_SCALE }, |
472 | [angle] = { ADIS16260_ANGL_OUT }, | 454 | [angle] = { ADIS16260_ANGL_OUT }, |
473 | [in_supply] = { ADIS16260_SUPPLY_OUT }, | 455 | [in_supply] = { ADIS16260_SUPPLY_OUT }, |
474 | [in_aux] = { ADIS16260_AUX_ADC }, | 456 | [in_aux] = { ADIS16260_AUX_ADC }, |
475 | [temp] = { ADIS16260_TEMP_OUT }, | 457 | [temp] = { ADIS16260_TEMP_OUT }, |
476 | }; | 458 | }; |
477 | static int adis16260_read_raw(struct iio_dev *indio_dev, | 459 | static int adis16260_read_raw(struct iio_dev *indio_dev, |
478 | struct iio_chan_spec const *chan, | 460 | struct iio_chan_spec const *chan, |
479 | int *val, int *val2, | 461 | int *val, int *val2, |
480 | long mask) | 462 | long mask) |
481 | { | 463 | { |
482 | struct adis16260_state *st = iio_priv(indio_dev); | 464 | struct adis16260_state *st = iio_priv(indio_dev); |
483 | int ret; | 465 | int ret; |
484 | int bits; | 466 | int bits; |
485 | u8 addr; | 467 | u8 addr; |
486 | s16 val16; | 468 | s16 val16; |
487 | 469 | ||
488 | switch (mask) { | 470 | switch (mask) { |
489 | case IIO_CHAN_INFO_RAW: | 471 | case IIO_CHAN_INFO_RAW: |
490 | mutex_lock(&indio_dev->mlock); | 472 | mutex_lock(&indio_dev->mlock); |
491 | addr = adis16260_addresses[chan->address][0]; | 473 | addr = adis16260_addresses[chan->address][0]; |
492 | ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16); | 474 | ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16); |
493 | if (ret) { | 475 | if (ret) { |
494 | mutex_unlock(&indio_dev->mlock); | 476 | mutex_unlock(&indio_dev->mlock); |
495 | return ret; | 477 | return ret; |
496 | } | 478 | } |
497 | 479 | ||
498 | if (val16 & ADIS16260_ERROR_ACTIVE) { | 480 | if (val16 & ADIS16260_ERROR_ACTIVE) { |
499 | ret = adis16260_check_status(indio_dev); | 481 | ret = adis16260_check_status(indio_dev); |
500 | if (ret) { | 482 | if (ret) { |
501 | mutex_unlock(&indio_dev->mlock); | 483 | mutex_unlock(&indio_dev->mlock); |
502 | return ret; | 484 | return ret; |
503 | } | 485 | } |
504 | } | 486 | } |
505 | val16 = val16 & ((1 << chan->scan_type.realbits) - 1); | 487 | val16 = val16 & ((1 << chan->scan_type.realbits) - 1); |
506 | if (chan->scan_type.sign == 's') | 488 | if (chan->scan_type.sign == 's') |
507 | val16 = (s16)(val16 << | 489 | val16 = (s16)(val16 << |
508 | (16 - chan->scan_type.realbits)) >> | 490 | (16 - chan->scan_type.realbits)) >> |
509 | (16 - chan->scan_type.realbits); | 491 | (16 - chan->scan_type.realbits); |
510 | *val = val16; | 492 | *val = val16; |
511 | mutex_unlock(&indio_dev->mlock); | 493 | mutex_unlock(&indio_dev->mlock); |
512 | return IIO_VAL_INT; | 494 | return IIO_VAL_INT; |
513 | case IIO_CHAN_INFO_SCALE: | 495 | case IIO_CHAN_INFO_SCALE: |
514 | switch (chan->type) { | 496 | switch (chan->type) { |
515 | case IIO_ANGL_VEL: | 497 | case IIO_ANGL_VEL: |
516 | *val = 0; | 498 | *val = 0; |
517 | if (spi_get_device_id(st->us)->driver_data) | 499 | if (spi_get_device_id(st->us)->driver_data) |
518 | *val2 = 320; | 500 | *val2 = 320; |
519 | else | 501 | else |
520 | *val2 = 1278; | 502 | *val2 = 1278; |
521 | return IIO_VAL_INT_PLUS_MICRO; | 503 | return IIO_VAL_INT_PLUS_MICRO; |
522 | case IIO_VOLTAGE: | 504 | case IIO_VOLTAGE: |
523 | *val = 0; | 505 | *val = 0; |
524 | if (chan->channel == 0) | 506 | if (chan->channel == 0) |
525 | *val2 = 18315; | 507 | *val2 = 18315; |
526 | else | 508 | else |
527 | *val2 = 610500; | 509 | *val2 = 610500; |
528 | return IIO_VAL_INT_PLUS_MICRO; | 510 | return IIO_VAL_INT_PLUS_MICRO; |
529 | case IIO_TEMP: | 511 | case IIO_TEMP: |
530 | *val = 0; | 512 | *val = 0; |
531 | *val2 = 145300; | 513 | *val2 = 145300; |
532 | return IIO_VAL_INT_PLUS_MICRO; | 514 | return IIO_VAL_INT_PLUS_MICRO; |
533 | default: | 515 | default: |
534 | return -EINVAL; | 516 | return -EINVAL; |
535 | } | 517 | } |
536 | break; | 518 | break; |
537 | case IIO_CHAN_INFO_OFFSET: | 519 | case IIO_CHAN_INFO_OFFSET: |
538 | *val = 25; | 520 | *val = 25; |
539 | return IIO_VAL_INT; | 521 | return IIO_VAL_INT; |
540 | case IIO_CHAN_INFO_CALIBBIAS: | 522 | case IIO_CHAN_INFO_CALIBBIAS: |
541 | switch (chan->type) { | 523 | switch (chan->type) { |
542 | case IIO_ANGL_VEL: | 524 | case IIO_ANGL_VEL: |
543 | bits = 12; | 525 | bits = 12; |
544 | break; | 526 | break; |
545 | default: | 527 | default: |
546 | return -EINVAL; | 528 | return -EINVAL; |
547 | }; | 529 | }; |
548 | mutex_lock(&indio_dev->mlock); | 530 | mutex_lock(&indio_dev->mlock); |
549 | addr = adis16260_addresses[chan->address][1]; | 531 | addr = adis16260_addresses[chan->address][1]; |
550 | ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16); | 532 | ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16); |
551 | if (ret) { | 533 | if (ret) { |
552 | mutex_unlock(&indio_dev->mlock); | 534 | mutex_unlock(&indio_dev->mlock); |
553 | return ret; | 535 | return ret; |
554 | } | 536 | } |
555 | val16 &= (1 << bits) - 1; | 537 | val16 &= (1 << bits) - 1; |
556 | val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); | 538 | val16 = (s16)(val16 << (16 - bits)) >> (16 - bits); |
557 | *val = val16; | 539 | *val = val16; |
558 | mutex_unlock(&indio_dev->mlock); | 540 | mutex_unlock(&indio_dev->mlock); |
559 | return IIO_VAL_INT; | 541 | return IIO_VAL_INT; |
560 | case IIO_CHAN_INFO_CALIBSCALE: | 542 | case IIO_CHAN_INFO_CALIBSCALE: |
561 | switch (chan->type) { | 543 | switch (chan->type) { |
562 | case IIO_ANGL_VEL: | 544 | case IIO_ANGL_VEL: |
563 | bits = 12; | 545 | bits = 12; |
564 | break; | 546 | break; |
565 | default: | 547 | default: |
566 | return -EINVAL; | 548 | return -EINVAL; |
567 | }; | 549 | }; |
568 | mutex_lock(&indio_dev->mlock); | 550 | mutex_lock(&indio_dev->mlock); |
569 | addr = adis16260_addresses[chan->address][2]; | 551 | addr = adis16260_addresses[chan->address][2]; |
570 | ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16); | 552 | ret = adis16260_spi_read_reg_16(indio_dev, addr, &val16); |
571 | if (ret) { | 553 | if (ret) { |
572 | mutex_unlock(&indio_dev->mlock); | 554 | mutex_unlock(&indio_dev->mlock); |
573 | return ret; | 555 | return ret; |
574 | } | 556 | } |
575 | *val = (1 << bits) - 1; | 557 | *val = (1 << bits) - 1; |
576 | mutex_unlock(&indio_dev->mlock); | 558 | mutex_unlock(&indio_dev->mlock); |
577 | return IIO_VAL_INT; | 559 | return IIO_VAL_INT; |
578 | } | 560 | } |
579 | return -EINVAL; | 561 | return -EINVAL; |
580 | } | 562 | } |
581 | 563 | ||
582 | static int adis16260_write_raw(struct iio_dev *indio_dev, | 564 | static int adis16260_write_raw(struct iio_dev *indio_dev, |
583 | struct iio_chan_spec const *chan, | 565 | struct iio_chan_spec const *chan, |
584 | int val, | 566 | int val, |
585 | int val2, | 567 | int val2, |
586 | long mask) | 568 | long mask) |
587 | { | 569 | { |
588 | int bits = 12; | 570 | int bits = 12; |
589 | s16 val16; | 571 | s16 val16; |
590 | u8 addr; | 572 | u8 addr; |
591 | switch (mask) { | 573 | switch (mask) { |
592 | case IIO_CHAN_INFO_CALIBBIAS: | 574 | case IIO_CHAN_INFO_CALIBBIAS: |
593 | val16 = val & ((1 << bits) - 1); | 575 | val16 = val & ((1 << bits) - 1); |
594 | addr = adis16260_addresses[chan->address][1]; | 576 | addr = adis16260_addresses[chan->address][1]; |
595 | return adis16260_spi_write_reg_16(indio_dev, addr, val16); | 577 | return adis16260_spi_write_reg_16(indio_dev, addr, val16); |
596 | case IIO_CHAN_INFO_CALIBSCALE: | 578 | case IIO_CHAN_INFO_CALIBSCALE: |
597 | val16 = val & ((1 << bits) - 1); | 579 | val16 = val & ((1 << bits) - 1); |
598 | addr = adis16260_addresses[chan->address][2]; | 580 | addr = adis16260_addresses[chan->address][2]; |
599 | return adis16260_spi_write_reg_16(indio_dev, addr, val16); | 581 | return adis16260_spi_write_reg_16(indio_dev, addr, val16); |
600 | } | 582 | } |
601 | return -EINVAL; | 583 | return -EINVAL; |
602 | } | 584 | } |
603 | 585 | ||
604 | static struct attribute *adis16260_attributes[] = { | 586 | static struct attribute *adis16260_attributes[] = { |
605 | &iio_dev_attr_sampling_frequency.dev_attr.attr, | 587 | &iio_dev_attr_sampling_frequency.dev_attr.attr, |
606 | &iio_dev_attr_sampling_frequency_available.dev_attr.attr, | 588 | &iio_dev_attr_sampling_frequency_available.dev_attr.attr, |
607 | &iio_dev_attr_reset.dev_attr.attr, | ||
608 | NULL | 589 | NULL |
609 | }; | 590 | }; |
610 | 591 | ||
611 | static const struct attribute_group adis16260_attribute_group = { | 592 | static const struct attribute_group adis16260_attribute_group = { |
612 | .attrs = adis16260_attributes, | 593 | .attrs = adis16260_attributes, |
613 | }; | 594 | }; |
614 | 595 | ||
615 | static const struct iio_info adis16260_info = { | 596 | static const struct iio_info adis16260_info = { |
616 | .attrs = &adis16260_attribute_group, | 597 | .attrs = &adis16260_attribute_group, |
617 | .read_raw = &adis16260_read_raw, | 598 | .read_raw = &adis16260_read_raw, |
618 | .write_raw = &adis16260_write_raw, | 599 | .write_raw = &adis16260_write_raw, |
619 | .driver_module = THIS_MODULE, | 600 | .driver_module = THIS_MODULE, |
620 | }; | 601 | }; |
621 | 602 | ||
622 | static int __devinit adis16260_probe(struct spi_device *spi) | 603 | static int __devinit adis16260_probe(struct spi_device *spi) |
623 | { | 604 | { |
624 | int ret; | 605 | int ret; |
625 | struct adis16260_platform_data *pd = spi->dev.platform_data; | 606 | struct adis16260_platform_data *pd = spi->dev.platform_data; |
626 | struct adis16260_state *st; | 607 | struct adis16260_state *st; |
627 | struct iio_dev *indio_dev; | 608 | struct iio_dev *indio_dev; |
628 | 609 | ||
629 | /* setup the industrialio driver allocated elements */ | 610 | /* setup the industrialio driver allocated elements */ |
630 | indio_dev = iio_device_alloc(sizeof(*st)); | 611 | indio_dev = iio_device_alloc(sizeof(*st)); |
631 | if (indio_dev == NULL) { | 612 | if (indio_dev == NULL) { |
632 | ret = -ENOMEM; | 613 | ret = -ENOMEM; |
633 | goto error_ret; | 614 | goto error_ret; |
634 | } | 615 | } |
635 | st = iio_priv(indio_dev); | 616 | st = iio_priv(indio_dev); |
636 | if (pd) | 617 | if (pd) |
637 | st->negate = pd->negate; | 618 | st->negate = pd->negate; |
638 | /* this is only used for removal purposes */ | 619 | /* this is only used for removal purposes */ |
639 | spi_set_drvdata(spi, st); | 620 | spi_set_drvdata(spi, st); |
640 | 621 | ||
641 | st->us = spi; | 622 | st->us = spi; |
642 | mutex_init(&st->buf_lock); | 623 | mutex_init(&st->buf_lock); |
643 | 624 | ||
644 | indio_dev->name = spi_get_device_id(st->us)->name; | 625 | indio_dev->name = spi_get_device_id(st->us)->name; |
645 | indio_dev->dev.parent = &spi->dev; | 626 | indio_dev->dev.parent = &spi->dev; |
646 | indio_dev->info = &adis16260_info; | 627 | indio_dev->info = &adis16260_info; |
647 | indio_dev->num_channels | 628 | indio_dev->num_channels |
648 | = ARRAY_SIZE(adis16260_channels_x); | 629 | = ARRAY_SIZE(adis16260_channels_x); |
649 | if (pd && pd->direction) | 630 | if (pd && pd->direction) |
650 | switch (pd->direction) { | 631 | switch (pd->direction) { |
651 | case 'x': | 632 | case 'x': |
652 | indio_dev->channels = adis16260_channels_x; | 633 | indio_dev->channels = adis16260_channels_x; |
653 | break; | 634 | break; |
654 | case 'y': | 635 | case 'y': |
655 | indio_dev->channels = adis16260_channels_y; | 636 | indio_dev->channels = adis16260_channels_y; |
656 | break; | 637 | break; |
657 | case 'z': | 638 | case 'z': |
658 | indio_dev->channels = adis16260_channels_z; | 639 | indio_dev->channels = adis16260_channels_z; |
659 | break; | 640 | break; |
660 | default: | 641 | default: |
661 | return -EINVAL; | 642 | return -EINVAL; |
662 | } | 643 | } |
663 | else | 644 | else |
664 | indio_dev->channels = adis16260_channels_x; | 645 | indio_dev->channels = adis16260_channels_x; |
665 | indio_dev->num_channels = ARRAY_SIZE(adis16260_channels_x); | 646 | indio_dev->num_channels = ARRAY_SIZE(adis16260_channels_x); |
666 | indio_dev->modes = INDIO_DIRECT_MODE; | 647 | indio_dev->modes = INDIO_DIRECT_MODE; |
667 | 648 | ||
668 | ret = adis16260_configure_ring(indio_dev); | 649 | ret = adis16260_configure_ring(indio_dev); |
669 | if (ret) | 650 | if (ret) |
670 | goto error_free_dev; | 651 | goto error_free_dev; |
671 | 652 | ||
672 | ret = iio_buffer_register(indio_dev, | 653 | ret = iio_buffer_register(indio_dev, |
673 | indio_dev->channels, | 654 | indio_dev->channels, |
674 | ARRAY_SIZE(adis16260_channels_x)); | 655 | ARRAY_SIZE(adis16260_channels_x)); |
675 | if (ret) { | 656 | if (ret) { |
676 | printk(KERN_ERR "failed to initialize the ring\n"); | 657 | printk(KERN_ERR "failed to initialize the ring\n"); |
677 | goto error_unreg_ring_funcs; | 658 | goto error_unreg_ring_funcs; |
678 | } | 659 | } |
679 | if (indio_dev->buffer) { | 660 | if (indio_dev->buffer) { |
680 | /* Set default scan mode */ | 661 | /* Set default scan mode */ |
681 | iio_scan_mask_set(indio_dev, indio_dev->buffer, | 662 | iio_scan_mask_set(indio_dev, indio_dev->buffer, |
682 | ADIS16260_SCAN_SUPPLY); | 663 | ADIS16260_SCAN_SUPPLY); |
683 | iio_scan_mask_set(indio_dev, indio_dev->buffer, | 664 | iio_scan_mask_set(indio_dev, indio_dev->buffer, |
684 | ADIS16260_SCAN_GYRO); | 665 | ADIS16260_SCAN_GYRO); |
685 | iio_scan_mask_set(indio_dev, indio_dev->buffer, | 666 | iio_scan_mask_set(indio_dev, indio_dev->buffer, |
686 | ADIS16260_SCAN_AUX_ADC); | 667 | ADIS16260_SCAN_AUX_ADC); |
687 | iio_scan_mask_set(indio_dev, indio_dev->buffer, | 668 | iio_scan_mask_set(indio_dev, indio_dev->buffer, |
688 | ADIS16260_SCAN_TEMP); | 669 | ADIS16260_SCAN_TEMP); |
689 | iio_scan_mask_set(indio_dev, indio_dev->buffer, | 670 | iio_scan_mask_set(indio_dev, indio_dev->buffer, |
690 | ADIS16260_SCAN_ANGL); | 671 | ADIS16260_SCAN_ANGL); |
691 | } | 672 | } |
692 | if (spi->irq) { | 673 | if (spi->irq) { |
693 | ret = adis16260_probe_trigger(indio_dev); | 674 | ret = adis16260_probe_trigger(indio_dev); |
694 | if (ret) | 675 | if (ret) |
695 | goto error_uninitialize_ring; | 676 | goto error_uninitialize_ring; |
696 | } | 677 | } |
697 | 678 | ||
698 | /* Get the device into a sane initial state */ | 679 | /* Get the device into a sane initial state */ |
699 | ret = adis16260_initial_setup(indio_dev); | 680 | ret = adis16260_initial_setup(indio_dev); |
700 | if (ret) | 681 | if (ret) |
701 | goto error_remove_trigger; | 682 | goto error_remove_trigger; |
702 | ret = iio_device_register(indio_dev); | 683 | ret = iio_device_register(indio_dev); |
703 | if (ret) | 684 | if (ret) |
704 | goto error_remove_trigger; | 685 | goto error_remove_trigger; |
705 | 686 | ||
706 | return 0; | 687 | return 0; |
707 | 688 | ||
708 | error_remove_trigger: | 689 | error_remove_trigger: |
709 | adis16260_remove_trigger(indio_dev); | 690 | adis16260_remove_trigger(indio_dev); |
710 | error_uninitialize_ring: | 691 | error_uninitialize_ring: |
711 | iio_buffer_unregister(indio_dev); | 692 | iio_buffer_unregister(indio_dev); |
712 | error_unreg_ring_funcs: | 693 | error_unreg_ring_funcs: |
713 | adis16260_unconfigure_ring(indio_dev); | 694 | adis16260_unconfigure_ring(indio_dev); |
714 | error_free_dev: | 695 | error_free_dev: |
715 | iio_device_free(indio_dev); | 696 | iio_device_free(indio_dev); |
716 | error_ret: | 697 | error_ret: |
717 | return ret; | 698 | return ret; |
718 | } | 699 | } |
719 | 700 | ||
720 | static int adis16260_remove(struct spi_device *spi) | 701 | static int adis16260_remove(struct spi_device *spi) |
721 | { | 702 | { |
722 | int ret; | 703 | int ret; |
723 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | 704 | struct iio_dev *indio_dev = spi_get_drvdata(spi); |
724 | 705 | ||
725 | iio_device_unregister(indio_dev); | 706 | iio_device_unregister(indio_dev); |
726 | 707 | ||
727 | ret = adis16260_stop_device(indio_dev); | 708 | ret = adis16260_stop_device(indio_dev); |
728 | if (ret) | 709 | if (ret) |
729 | goto err_ret; | 710 | goto err_ret; |
730 | 711 | ||
731 | adis16260_remove_trigger(indio_dev); | 712 | adis16260_remove_trigger(indio_dev); |
732 | iio_buffer_unregister(indio_dev); | 713 | iio_buffer_unregister(indio_dev); |
733 | adis16260_unconfigure_ring(indio_dev); | 714 | adis16260_unconfigure_ring(indio_dev); |
734 | iio_device_free(indio_dev); | 715 | iio_device_free(indio_dev); |
735 | 716 | ||
736 | err_ret: | 717 | err_ret: |
737 | return ret; | 718 | return ret; |
738 | } | 719 | } |
739 | 720 | ||
740 | /* | 721 | /* |
741 | * These parts do not need to be differentiated until someone adds | 722 | * These parts do not need to be differentiated until someone adds |
742 | * support for the on chip filtering. | 723 | * support for the on chip filtering. |
743 | */ | 724 | */ |
744 | static const struct spi_device_id adis16260_id[] = { | 725 | static const struct spi_device_id adis16260_id[] = { |
745 | {"adis16260", 0}, | 726 | {"adis16260", 0}, |
746 | {"adis16265", 0}, | 727 | {"adis16265", 0}, |
747 | {"adis16250", 0}, | 728 | {"adis16250", 0}, |
748 | {"adis16255", 0}, | 729 | {"adis16255", 0}, |
749 | {"adis16251", 1}, | 730 | {"adis16251", 1}, |
750 | {} | 731 | {} |
751 | }; | 732 | }; |
752 | MODULE_DEVICE_TABLE(spi, adis16260_id); | 733 | MODULE_DEVICE_TABLE(spi, adis16260_id); |
753 | 734 | ||
754 | static struct spi_driver adis16260_driver = { | 735 | static struct spi_driver adis16260_driver = { |
755 | .driver = { | 736 | .driver = { |
756 | .name = "adis16260", | 737 | .name = "adis16260", |
757 | .owner = THIS_MODULE, | 738 | .owner = THIS_MODULE, |
758 | }, | 739 | }, |
759 | .probe = adis16260_probe, | 740 | .probe = adis16260_probe, |
760 | .remove = __devexit_p(adis16260_remove), | 741 | .remove = __devexit_p(adis16260_remove), |
761 | .id_table = adis16260_id, | 742 | .id_table = adis16260_id, |
762 | }; | 743 | }; |
763 | module_spi_driver(adis16260_driver); | 744 | module_spi_driver(adis16260_driver); |
764 | 745 | ||
765 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | 746 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); |
766 | MODULE_DESCRIPTION("Analog Devices ADIS16260/5 Digital Gyroscope Sensor"); | 747 | MODULE_DESCRIPTION("Analog Devices ADIS16260/5 Digital Gyroscope Sensor"); |
767 | MODULE_LICENSE("GPL v2"); | 748 | MODULE_LICENSE("GPL v2"); |
768 | 749 |
drivers/staging/iio/iio_hwmon.c
1 | /* Hwmon client for industrial I/O devices | 1 | /* Hwmon client for industrial I/O devices |
2 | * | 2 | * |
3 | * Copyright (c) 2011 Jonathan Cameron | 3 | * Copyright (c) 2011 Jonathan Cameron |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 as published by | 6 | * under the terms of the GNU General Public License version 2 as published by |
7 | * the Free Software Foundation. | 7 | * the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/hwmon.h> | 15 | #include <linux/hwmon.h> |
16 | #include <linux/hwmon-sysfs.h> | 16 | #include <linux/hwmon-sysfs.h> |
17 | #include <linux/iio/consumer.h> | 17 | #include <linux/iio/consumer.h> |
18 | #include <linux/iio/types.h> | 18 | #include <linux/iio/types.h> |
19 | 19 | ||
20 | /** | 20 | /** |
21 | * struct iio_hwmon_state - device instance state | 21 | * struct iio_hwmon_state - device instance state |
22 | * @channels: filled with array of channels from iio | 22 | * @channels: filled with array of channels from iio |
23 | * @num_channels: number of channels in channels (saves counting twice) | 23 | * @num_channels: number of channels in channels (saves counting twice) |
24 | * @hwmon_dev: associated hwmon device | 24 | * @hwmon_dev: associated hwmon device |
25 | * @attr_group: the group of attributes | 25 | * @attr_group: the group of attributes |
26 | * @attrs: null terminated array of attribute pointers. | 26 | * @attrs: null terminated array of attribute pointers. |
27 | */ | 27 | */ |
28 | struct iio_hwmon_state { | 28 | struct iio_hwmon_state { |
29 | struct iio_channel *channels; | 29 | struct iio_channel *channels; |
30 | int num_channels; | 30 | int num_channels; |
31 | struct device *hwmon_dev; | 31 | struct device *hwmon_dev; |
32 | struct attribute_group attr_group; | 32 | struct attribute_group attr_group; |
33 | struct attribute **attrs; | 33 | struct attribute **attrs; |
34 | }; | 34 | }; |
35 | 35 | ||
36 | /* | 36 | /* |
37 | * Assumes that IIO and hwmon operate in the same base units. | 37 | * Assumes that IIO and hwmon operate in the same base units. |
38 | * This is supposed to be true, but needs verification for | 38 | * This is supposed to be true, but needs verification for |
39 | * new channel types. | 39 | * new channel types. |
40 | */ | 40 | */ |
41 | static ssize_t iio_hwmon_read_val(struct device *dev, | 41 | static ssize_t iio_hwmon_read_val(struct device *dev, |
42 | struct device_attribute *attr, | 42 | struct device_attribute *attr, |
43 | char *buf) | 43 | char *buf) |
44 | { | 44 | { |
45 | long result; | 45 | long result; |
46 | int val, ret, scaleint, scalepart; | 46 | int val, ret, scaleint, scalepart; |
47 | struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); | 47 | struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); |
48 | struct iio_hwmon_state *state = dev_get_drvdata(dev); | 48 | struct iio_hwmon_state *state = dev_get_drvdata(dev); |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * No locking between this pair, so theoretically possible | 51 | * No locking between this pair, so theoretically possible |
52 | * the scale has changed. | 52 | * the scale has changed. |
53 | */ | 53 | */ |
54 | ret = iio_st_read_channel_raw(&state->channels[sattr->index], | 54 | ret = iio_read_channel_raw(&state->channels[sattr->index], |
55 | &val); | 55 | &val); |
56 | if (ret < 0) | 56 | if (ret < 0) |
57 | return ret; | 57 | return ret; |
58 | 58 | ||
59 | ret = iio_st_read_channel_scale(&state->channels[sattr->index], | 59 | ret = iio_read_channel_scale(&state->channels[sattr->index], |
60 | &scaleint, &scalepart); | 60 | &scaleint, &scalepart); |
61 | if (ret < 0) | 61 | if (ret < 0) |
62 | return ret; | 62 | return ret; |
63 | switch (ret) { | 63 | switch (ret) { |
64 | case IIO_VAL_INT: | 64 | case IIO_VAL_INT: |
65 | result = val * scaleint; | 65 | result = val * scaleint; |
66 | break; | 66 | break; |
67 | case IIO_VAL_INT_PLUS_MICRO: | 67 | case IIO_VAL_INT_PLUS_MICRO: |
68 | result = (s64)val * (s64)scaleint + | 68 | result = (s64)val * (s64)scaleint + |
69 | div_s64((s64)val * (s64)scalepart, 1000000LL); | 69 | div_s64((s64)val * (s64)scalepart, 1000000LL); |
70 | break; | 70 | break; |
71 | case IIO_VAL_INT_PLUS_NANO: | 71 | case IIO_VAL_INT_PLUS_NANO: |
72 | result = (s64)val * (s64)scaleint + | 72 | result = (s64)val * (s64)scaleint + |
73 | div_s64((s64)val * (s64)scalepart, 1000000000LL); | 73 | div_s64((s64)val * (s64)scalepart, 1000000000LL); |
74 | break; | 74 | break; |
75 | default: | 75 | default: |
76 | return -EINVAL; | 76 | return -EINVAL; |
77 | } | 77 | } |
78 | return sprintf(buf, "%ld\n", result); | 78 | return sprintf(buf, "%ld\n", result); |
79 | } | 79 | } |
80 | 80 | ||
81 | static void iio_hwmon_free_attrs(struct iio_hwmon_state *st) | 81 | static void iio_hwmon_free_attrs(struct iio_hwmon_state *st) |
82 | { | 82 | { |
83 | int i; | 83 | int i; |
84 | struct sensor_device_attribute *a; | 84 | struct sensor_device_attribute *a; |
85 | for (i = 0; i < st->num_channels; i++) | 85 | for (i = 0; i < st->num_channels; i++) |
86 | if (st->attrs[i]) { | 86 | if (st->attrs[i]) { |
87 | a = to_sensor_dev_attr( | 87 | a = to_sensor_dev_attr( |
88 | container_of(st->attrs[i], | 88 | container_of(st->attrs[i], |
89 | struct device_attribute, | 89 | struct device_attribute, |
90 | attr)); | 90 | attr)); |
91 | kfree(a); | 91 | kfree(a); |
92 | } | 92 | } |
93 | } | 93 | } |
94 | 94 | ||
95 | static int __devinit iio_hwmon_probe(struct platform_device *pdev) | 95 | static int __devinit iio_hwmon_probe(struct platform_device *pdev) |
96 | { | 96 | { |
97 | struct iio_hwmon_state *st; | 97 | struct iio_hwmon_state *st; |
98 | struct sensor_device_attribute *a; | 98 | struct sensor_device_attribute *a; |
99 | int ret, i; | 99 | int ret, i; |
100 | int in_i = 1, temp_i = 1, curr_i = 1; | 100 | int in_i = 1, temp_i = 1, curr_i = 1; |
101 | enum iio_chan_type type; | 101 | enum iio_chan_type type; |
102 | 102 | ||
103 | st = kzalloc(sizeof(*st), GFP_KERNEL); | 103 | st = kzalloc(sizeof(*st), GFP_KERNEL); |
104 | if (st == NULL) { | 104 | if (st == NULL) { |
105 | ret = -ENOMEM; | 105 | ret = -ENOMEM; |
106 | goto error_ret; | 106 | goto error_ret; |
107 | } | 107 | } |
108 | 108 | ||
109 | st->channels = iio_st_channel_get_all(dev_name(&pdev->dev)); | 109 | st->channels = iio_channel_get_all(dev_name(&pdev->dev)); |
110 | if (IS_ERR(st->channels)) { | 110 | if (IS_ERR(st->channels)) { |
111 | ret = PTR_ERR(st->channels); | 111 | ret = PTR_ERR(st->channels); |
112 | goto error_free_state; | 112 | goto error_free_state; |
113 | } | 113 | } |
114 | 114 | ||
115 | /* count how many attributes we have */ | 115 | /* count how many attributes we have */ |
116 | while (st->channels[st->num_channels].indio_dev) | 116 | while (st->channels[st->num_channels].indio_dev) |
117 | st->num_channels++; | 117 | st->num_channels++; |
118 | 118 | ||
119 | st->attrs = kzalloc(sizeof(st->attrs) * (st->num_channels + 1), | 119 | st->attrs = kzalloc(sizeof(st->attrs) * (st->num_channels + 1), |
120 | GFP_KERNEL); | 120 | GFP_KERNEL); |
121 | if (st->attrs == NULL) { | 121 | if (st->attrs == NULL) { |
122 | ret = -ENOMEM; | 122 | ret = -ENOMEM; |
123 | goto error_release_channels; | 123 | goto error_release_channels; |
124 | } | 124 | } |
125 | for (i = 0; i < st->num_channels; i++) { | 125 | for (i = 0; i < st->num_channels; i++) { |
126 | a = kzalloc(sizeof(*a), GFP_KERNEL); | 126 | a = kzalloc(sizeof(*a), GFP_KERNEL); |
127 | if (a == NULL) { | 127 | if (a == NULL) { |
128 | ret = -ENOMEM; | 128 | ret = -ENOMEM; |
129 | goto error_free_attrs; | 129 | goto error_free_attrs; |
130 | } | 130 | } |
131 | 131 | ||
132 | sysfs_attr_init(&a->dev_attr.attr); | 132 | sysfs_attr_init(&a->dev_attr.attr); |
133 | ret = iio_st_get_channel_type(&st->channels[i], &type); | 133 | ret = iio_get_channel_type(&st->channels[i], &type); |
134 | if (ret < 0) { | 134 | if (ret < 0) { |
135 | kfree(a); | 135 | kfree(a); |
136 | goto error_free_attrs; | 136 | goto error_free_attrs; |
137 | } | 137 | } |
138 | switch (type) { | 138 | switch (type) { |
139 | case IIO_VOLTAGE: | 139 | case IIO_VOLTAGE: |
140 | a->dev_attr.attr.name = kasprintf(GFP_KERNEL, | 140 | a->dev_attr.attr.name = kasprintf(GFP_KERNEL, |
141 | "in%d_input", | 141 | "in%d_input", |
142 | in_i++); | 142 | in_i++); |
143 | break; | 143 | break; |
144 | case IIO_TEMP: | 144 | case IIO_TEMP: |
145 | a->dev_attr.attr.name = kasprintf(GFP_KERNEL, | 145 | a->dev_attr.attr.name = kasprintf(GFP_KERNEL, |
146 | "temp%d_input", | 146 | "temp%d_input", |
147 | temp_i++); | 147 | temp_i++); |
148 | break; | 148 | break; |
149 | case IIO_CURRENT: | 149 | case IIO_CURRENT: |
150 | a->dev_attr.attr.name = kasprintf(GFP_KERNEL, | 150 | a->dev_attr.attr.name = kasprintf(GFP_KERNEL, |
151 | "curr%d_input", | 151 | "curr%d_input", |
152 | curr_i++); | 152 | curr_i++); |
153 | break; | 153 | break; |
154 | default: | 154 | default: |
155 | ret = -EINVAL; | 155 | ret = -EINVAL; |
156 | kfree(a); | 156 | kfree(a); |
157 | goto error_free_attrs; | 157 | goto error_free_attrs; |
158 | } | 158 | } |
159 | if (a->dev_attr.attr.name == NULL) { | 159 | if (a->dev_attr.attr.name == NULL) { |
160 | kfree(a); | 160 | kfree(a); |
161 | ret = -ENOMEM; | 161 | ret = -ENOMEM; |
162 | goto error_free_attrs; | 162 | goto error_free_attrs; |
163 | } | 163 | } |
164 | a->dev_attr.show = iio_hwmon_read_val; | 164 | a->dev_attr.show = iio_hwmon_read_val; |
165 | a->dev_attr.attr.mode = S_IRUGO; | 165 | a->dev_attr.attr.mode = S_IRUGO; |
166 | a->index = i; | 166 | a->index = i; |
167 | st->attrs[i] = &a->dev_attr.attr; | 167 | st->attrs[i] = &a->dev_attr.attr; |
168 | } | 168 | } |
169 | 169 | ||
170 | st->attr_group.attrs = st->attrs; | 170 | st->attr_group.attrs = st->attrs; |
171 | platform_set_drvdata(pdev, st); | 171 | platform_set_drvdata(pdev, st); |
172 | ret = sysfs_create_group(&pdev->dev.kobj, &st->attr_group); | 172 | ret = sysfs_create_group(&pdev->dev.kobj, &st->attr_group); |
173 | if (ret < 0) | 173 | if (ret < 0) |
174 | goto error_free_attrs; | 174 | goto error_free_attrs; |
175 | 175 | ||
176 | st->hwmon_dev = hwmon_device_register(&pdev->dev); | 176 | st->hwmon_dev = hwmon_device_register(&pdev->dev); |
177 | if (IS_ERR(st->hwmon_dev)) { | 177 | if (IS_ERR(st->hwmon_dev)) { |
178 | ret = PTR_ERR(st->hwmon_dev); | 178 | ret = PTR_ERR(st->hwmon_dev); |
179 | goto error_remove_group; | 179 | goto error_remove_group; |
180 | } | 180 | } |
181 | return 0; | 181 | return 0; |
182 | 182 | ||
183 | error_remove_group: | 183 | error_remove_group: |
184 | sysfs_remove_group(&pdev->dev.kobj, &st->attr_group); | 184 | sysfs_remove_group(&pdev->dev.kobj, &st->attr_group); |
185 | error_free_attrs: | 185 | error_free_attrs: |
186 | iio_hwmon_free_attrs(st); | 186 | iio_hwmon_free_attrs(st); |
187 | kfree(st->attrs); | 187 | kfree(st->attrs); |
188 | error_release_channels: | 188 | error_release_channels: |
189 | iio_st_channel_release_all(st->channels); | 189 | iio_channel_release_all(st->channels); |
190 | error_free_state: | 190 | error_free_state: |
191 | kfree(st); | 191 | kfree(st); |
192 | error_ret: | 192 | error_ret: |
193 | return ret; | 193 | return ret; |
194 | } | 194 | } |
195 | 195 | ||
196 | static int __devexit iio_hwmon_remove(struct platform_device *pdev) | 196 | static int __devexit iio_hwmon_remove(struct platform_device *pdev) |
197 | { | 197 | { |
198 | struct iio_hwmon_state *st = platform_get_drvdata(pdev); | 198 | struct iio_hwmon_state *st = platform_get_drvdata(pdev); |
199 | 199 | ||
200 | hwmon_device_unregister(st->hwmon_dev); | 200 | hwmon_device_unregister(st->hwmon_dev); |
201 | sysfs_remove_group(&pdev->dev.kobj, &st->attr_group); | 201 | sysfs_remove_group(&pdev->dev.kobj, &st->attr_group); |
202 | iio_hwmon_free_attrs(st); | 202 | iio_hwmon_free_attrs(st); |
203 | kfree(st->attrs); | 203 | kfree(st->attrs); |
204 | iio_st_channel_release_all(st->channels); | 204 | iio_channel_release_all(st->channels); |
205 | 205 | ||
206 | return 0; | 206 | return 0; |
207 | } | 207 | } |
208 | 208 | ||
209 | static struct platform_driver __refdata iio_hwmon_driver = { | 209 | static struct platform_driver __refdata iio_hwmon_driver = { |
210 | .driver = { | 210 | .driver = { |
211 | .name = "iio_hwmon", | 211 | .name = "iio_hwmon", |
212 | .owner = THIS_MODULE, | 212 | .owner = THIS_MODULE, |
213 | }, | 213 | }, |
214 | .probe = iio_hwmon_probe, | 214 | .probe = iio_hwmon_probe, |
215 | .remove = __devexit_p(iio_hwmon_remove), | 215 | .remove = __devexit_p(iio_hwmon_remove), |
216 | }; | 216 | }; |
217 | 217 | ||
218 | static int iio_inkern_init(void) | 218 | static int iio_inkern_init(void) |
219 | { | 219 | { |
220 | return platform_driver_register(&iio_hwmon_driver); | 220 | return platform_driver_register(&iio_hwmon_driver); |
221 | } | 221 | } |
222 | module_init(iio_inkern_init); | 222 | module_init(iio_inkern_init); |
223 | 223 | ||
224 | static void iio_inkern_exit(void) | 224 | static void iio_inkern_exit(void) |
225 | { | 225 | { |
226 | platform_driver_unregister(&iio_hwmon_driver); | 226 | platform_driver_unregister(&iio_hwmon_driver); |
227 | } | 227 | } |
228 | module_exit(iio_inkern_exit); | 228 | module_exit(iio_inkern_exit); |
229 | 229 | ||
230 | MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); | 230 | MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); |
231 | MODULE_DESCRIPTION("IIO to hwmon driver"); | 231 | MODULE_DESCRIPTION("IIO to hwmon driver"); |
232 | MODULE_LICENSE("GPL v2"); | 232 | MODULE_LICENSE("GPL v2"); |
233 | 233 |
drivers/staging/iio/imu/adis16400_core.c
1 | /* | 1 | /* |
2 | * adis16400.c support Analog Devices ADIS16400/5 | 2 | * adis16400.c support Analog Devices ADIS16400/5 |
3 | * 3d 2g Linear Accelerometers, | 3 | * 3d 2g Linear Accelerometers, |
4 | * 3d Gyroscopes, | 4 | * 3d Gyroscopes, |
5 | * 3d Magnetometers via SPI | 5 | * 3d Magnetometers via SPI |
6 | * | 6 | * |
7 | * Copyright (c) 2009 Manuel Stahl <manuel.stahl@iis.fraunhofer.de> | 7 | * Copyright (c) 2009 Manuel Stahl <manuel.stahl@iis.fraunhofer.de> |
8 | * Copyright (c) 2007 Jonathan Cameron <jic23@cam.ac.uk> | 8 | * Copyright (c) 2007 Jonathan Cameron <jic23@cam.ac.uk> |
9 | * Copyright (c) 2011 Analog Devices Inc. | 9 | * Copyright (c) 2011 Analog Devices Inc. |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License version 2 as | 12 | * it under the terms of the GNU General Public License version 2 as |
13 | * published by the Free Software Foundation. | 13 | * published by the Free Software Foundation. |
14 | * | 14 | * |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
21 | #include <linux/device.h> | 21 | #include <linux/device.h> |
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/spi/spi.h> | 23 | #include <linux/spi/spi.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/sysfs.h> | 25 | #include <linux/sysfs.h> |
26 | #include <linux/list.h> | 26 | #include <linux/list.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | 28 | ||
29 | #include <linux/iio/iio.h> | 29 | #include <linux/iio/iio.h> |
30 | #include <linux/iio/sysfs.h> | 30 | #include <linux/iio/sysfs.h> |
31 | #include <linux/iio/buffer.h> | 31 | #include <linux/iio/buffer.h> |
32 | #include "adis16400.h" | 32 | #include "adis16400.h" |
33 | 33 | ||
34 | enum adis16400_chip_variant { | 34 | enum adis16400_chip_variant { |
35 | ADIS16300, | 35 | ADIS16300, |
36 | ADIS16334, | 36 | ADIS16334, |
37 | ADIS16350, | 37 | ADIS16350, |
38 | ADIS16360, | 38 | ADIS16360, |
39 | ADIS16362, | 39 | ADIS16362, |
40 | ADIS16364, | 40 | ADIS16364, |
41 | ADIS16365, | 41 | ADIS16365, |
42 | ADIS16400, | 42 | ADIS16400, |
43 | }; | 43 | }; |
44 | 44 | ||
45 | /** | 45 | /** |
46 | * adis16400_spi_write_reg_8() - write single byte to a register | 46 | * adis16400_spi_write_reg_8() - write single byte to a register |
47 | * @dev: device associated with child of actual device (iio_dev or iio_trig) | 47 | * @dev: device associated with child of actual device (iio_dev or iio_trig) |
48 | * @reg_address: the address of the register to be written | 48 | * @reg_address: the address of the register to be written |
49 | * @val: the value to write | 49 | * @val: the value to write |
50 | */ | 50 | */ |
51 | static int adis16400_spi_write_reg_8(struct iio_dev *indio_dev, | 51 | static int adis16400_spi_write_reg_8(struct iio_dev *indio_dev, |
52 | u8 reg_address, | 52 | u8 reg_address, |
53 | u8 val) | 53 | u8 val) |
54 | { | 54 | { |
55 | int ret; | 55 | int ret; |
56 | struct adis16400_state *st = iio_priv(indio_dev); | 56 | struct adis16400_state *st = iio_priv(indio_dev); |
57 | 57 | ||
58 | mutex_lock(&st->buf_lock); | 58 | mutex_lock(&st->buf_lock); |
59 | st->tx[0] = ADIS16400_WRITE_REG(reg_address); | 59 | st->tx[0] = ADIS16400_WRITE_REG(reg_address); |
60 | st->tx[1] = val; | 60 | st->tx[1] = val; |
61 | 61 | ||
62 | ret = spi_write(st->us, st->tx, 2); | 62 | ret = spi_write(st->us, st->tx, 2); |
63 | mutex_unlock(&st->buf_lock); | 63 | mutex_unlock(&st->buf_lock); |
64 | 64 | ||
65 | return ret; | 65 | return ret; |
66 | } | 66 | } |
67 | 67 | ||
68 | /** | 68 | /** |
69 | * adis16400_spi_write_reg_16() - write 2 bytes to a pair of registers | 69 | * adis16400_spi_write_reg_16() - write 2 bytes to a pair of registers |
70 | * @dev: device associated with child of actual device (iio_dev or iio_trig) | 70 | * @dev: device associated with child of actual device (iio_dev or iio_trig) |
71 | * @reg_address: the address of the lower of the two registers. Second register | 71 | * @reg_address: the address of the lower of the two registers. Second register |
72 | * is assumed to have address one greater. | 72 | * is assumed to have address one greater. |
73 | * @val: value to be written | 73 | * @val: value to be written |
74 | * | 74 | * |
75 | * At the moment the spi framework doesn't allow global setting of cs_change. | 75 | * At the moment the spi framework doesn't allow global setting of cs_change. |
76 | * This means that use cannot be made of spi_write. | 76 | * This means that use cannot be made of spi_write. |
77 | */ | 77 | */ |
78 | static int adis16400_spi_write_reg_16(struct iio_dev *indio_dev, | 78 | static int adis16400_spi_write_reg_16(struct iio_dev *indio_dev, |
79 | u8 lower_reg_address, | 79 | u8 lower_reg_address, |
80 | u16 value) | 80 | u16 value) |
81 | { | 81 | { |
82 | int ret; | 82 | int ret; |
83 | struct spi_message msg; | 83 | struct spi_message msg; |
84 | struct adis16400_state *st = iio_priv(indio_dev); | 84 | struct adis16400_state *st = iio_priv(indio_dev); |
85 | struct spi_transfer xfers[] = { | 85 | struct spi_transfer xfers[] = { |
86 | { | 86 | { |
87 | .tx_buf = st->tx, | 87 | .tx_buf = st->tx, |
88 | .bits_per_word = 8, | 88 | .bits_per_word = 8, |
89 | .len = 2, | 89 | .len = 2, |
90 | .cs_change = 1, | 90 | .cs_change = 1, |
91 | }, { | 91 | }, { |
92 | .tx_buf = st->tx + 2, | 92 | .tx_buf = st->tx + 2, |
93 | .bits_per_word = 8, | 93 | .bits_per_word = 8, |
94 | .len = 2, | 94 | .len = 2, |
95 | }, | 95 | }, |
96 | }; | 96 | }; |
97 | 97 | ||
98 | mutex_lock(&st->buf_lock); | 98 | mutex_lock(&st->buf_lock); |
99 | st->tx[0] = ADIS16400_WRITE_REG(lower_reg_address); | 99 | st->tx[0] = ADIS16400_WRITE_REG(lower_reg_address); |
100 | st->tx[1] = value & 0xFF; | 100 | st->tx[1] = value & 0xFF; |
101 | st->tx[2] = ADIS16400_WRITE_REG(lower_reg_address + 1); | 101 | st->tx[2] = ADIS16400_WRITE_REG(lower_reg_address + 1); |
102 | st->tx[3] = (value >> 8) & 0xFF; | 102 | st->tx[3] = (value >> 8) & 0xFF; |
103 | 103 | ||
104 | spi_message_init(&msg); | 104 | spi_message_init(&msg); |
105 | spi_message_add_tail(&xfers[0], &msg); | 105 | spi_message_add_tail(&xfers[0], &msg); |
106 | spi_message_add_tail(&xfers[1], &msg); | 106 | spi_message_add_tail(&xfers[1], &msg); |
107 | ret = spi_sync(st->us, &msg); | 107 | ret = spi_sync(st->us, &msg); |
108 | mutex_unlock(&st->buf_lock); | 108 | mutex_unlock(&st->buf_lock); |
109 | 109 | ||
110 | return ret; | 110 | return ret; |
111 | } | 111 | } |
112 | 112 | ||
113 | /** | 113 | /** |
114 | * adis16400_spi_read_reg_16() - read 2 bytes from a 16-bit register | 114 | * adis16400_spi_read_reg_16() - read 2 bytes from a 16-bit register |
115 | * @indio_dev: iio device | 115 | * @indio_dev: iio device |
116 | * @reg_address: the address of the lower of the two registers. Second register | 116 | * @reg_address: the address of the lower of the two registers. Second register |
117 | * is assumed to have address one greater. | 117 | * is assumed to have address one greater. |
118 | * @val: somewhere to pass back the value read | 118 | * @val: somewhere to pass back the value read |
119 | * | 119 | * |
120 | * At the moment the spi framework doesn't allow global setting of cs_change. | 120 | * At the moment the spi framework doesn't allow global setting of cs_change. |
121 | * This means that use cannot be made of spi_read. | 121 | * This means that use cannot be made of spi_read. |
122 | **/ | 122 | **/ |
123 | static int adis16400_spi_read_reg_16(struct iio_dev *indio_dev, | 123 | static int adis16400_spi_read_reg_16(struct iio_dev *indio_dev, |
124 | u8 lower_reg_address, | 124 | u8 lower_reg_address, |
125 | u16 *val) | 125 | u16 *val) |
126 | { | 126 | { |
127 | struct spi_message msg; | 127 | struct spi_message msg; |
128 | struct adis16400_state *st = iio_priv(indio_dev); | 128 | struct adis16400_state *st = iio_priv(indio_dev); |
129 | int ret; | 129 | int ret; |
130 | struct spi_transfer xfers[] = { | 130 | struct spi_transfer xfers[] = { |
131 | { | 131 | { |
132 | .tx_buf = st->tx, | 132 | .tx_buf = st->tx, |
133 | .bits_per_word = 8, | 133 | .bits_per_word = 8, |
134 | .len = 2, | 134 | .len = 2, |
135 | .cs_change = 1, | 135 | .cs_change = 1, |
136 | }, { | 136 | }, { |
137 | .rx_buf = st->rx, | 137 | .rx_buf = st->rx, |
138 | .bits_per_word = 8, | 138 | .bits_per_word = 8, |
139 | .len = 2, | 139 | .len = 2, |
140 | }, | 140 | }, |
141 | }; | 141 | }; |
142 | 142 | ||
143 | mutex_lock(&st->buf_lock); | 143 | mutex_lock(&st->buf_lock); |
144 | st->tx[0] = ADIS16400_READ_REG(lower_reg_address); | 144 | st->tx[0] = ADIS16400_READ_REG(lower_reg_address); |
145 | st->tx[1] = 0; | 145 | st->tx[1] = 0; |
146 | 146 | ||
147 | spi_message_init(&msg); | 147 | spi_message_init(&msg); |
148 | spi_message_add_tail(&xfers[0], &msg); | 148 | spi_message_add_tail(&xfers[0], &msg); |
149 | spi_message_add_tail(&xfers[1], &msg); | 149 | spi_message_add_tail(&xfers[1], &msg); |
150 | ret = spi_sync(st->us, &msg); | 150 | ret = spi_sync(st->us, &msg); |
151 | if (ret) { | 151 | if (ret) { |
152 | dev_err(&st->us->dev, | 152 | dev_err(&st->us->dev, |
153 | "problem when reading 16 bit register 0x%02X", | 153 | "problem when reading 16 bit register 0x%02X", |
154 | lower_reg_address); | 154 | lower_reg_address); |
155 | goto error_ret; | 155 | goto error_ret; |
156 | } | 156 | } |
157 | *val = (st->rx[0] << 8) | st->rx[1]; | 157 | *val = (st->rx[0] << 8) | st->rx[1]; |
158 | 158 | ||
159 | error_ret: | 159 | error_ret: |
160 | mutex_unlock(&st->buf_lock); | 160 | mutex_unlock(&st->buf_lock); |
161 | return ret; | 161 | return ret; |
162 | } | 162 | } |
163 | 163 | ||
164 | static int adis16400_get_freq(struct iio_dev *indio_dev) | 164 | static int adis16400_get_freq(struct iio_dev *indio_dev) |
165 | { | 165 | { |
166 | u16 t; | 166 | u16 t; |
167 | int sps, ret; | 167 | int sps, ret; |
168 | 168 | ||
169 | ret = adis16400_spi_read_reg_16(indio_dev, ADIS16400_SMPL_PRD, &t); | 169 | ret = adis16400_spi_read_reg_16(indio_dev, ADIS16400_SMPL_PRD, &t); |
170 | if (ret < 0) | 170 | if (ret < 0) |
171 | return ret; | 171 | return ret; |
172 | sps = (t & ADIS16400_SMPL_PRD_TIME_BASE) ? 53 : 1638; | 172 | sps = (t & ADIS16400_SMPL_PRD_TIME_BASE) ? 53 : 1638; |
173 | sps /= (t & ADIS16400_SMPL_PRD_DIV_MASK) + 1; | 173 | sps /= (t & ADIS16400_SMPL_PRD_DIV_MASK) + 1; |
174 | 174 | ||
175 | return sps; | 175 | return sps; |
176 | } | 176 | } |
177 | 177 | ||
178 | static ssize_t adis16400_read_frequency(struct device *dev, | 178 | static ssize_t adis16400_read_frequency(struct device *dev, |
179 | struct device_attribute *attr, | 179 | struct device_attribute *attr, |
180 | char *buf) | 180 | char *buf) |
181 | { | 181 | { |
182 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 182 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
183 | int ret, len = 0; | 183 | int ret, len = 0; |
184 | ret = adis16400_get_freq(indio_dev); | 184 | ret = adis16400_get_freq(indio_dev); |
185 | if (ret < 0) | 185 | if (ret < 0) |
186 | return ret; | 186 | return ret; |
187 | len = sprintf(buf, "%d SPS\n", ret); | 187 | len = sprintf(buf, "%d SPS\n", ret); |
188 | return len; | 188 | return len; |
189 | } | 189 | } |
190 | 190 | ||
191 | static const unsigned adis16400_3db_divisors[] = { | 191 | static const unsigned adis16400_3db_divisors[] = { |
192 | [0] = 2, /* Special case */ | 192 | [0] = 2, /* Special case */ |
193 | [1] = 5, | 193 | [1] = 5, |
194 | [2] = 10, | 194 | [2] = 10, |
195 | [3] = 50, | 195 | [3] = 50, |
196 | [4] = 200, | 196 | [4] = 200, |
197 | }; | 197 | }; |
198 | 198 | ||
199 | static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val) | 199 | static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val) |
200 | { | 200 | { |
201 | int i, ret; | 201 | int i, ret; |
202 | u16 val16; | 202 | u16 val16; |
203 | for (i = ARRAY_SIZE(adis16400_3db_divisors) - 1; i >= 0; i--) | 203 | for (i = ARRAY_SIZE(adis16400_3db_divisors) - 1; i >= 0; i--) |
204 | if (sps/adis16400_3db_divisors[i] > val) | 204 | if (sps/adis16400_3db_divisors[i] > val) |
205 | break; | 205 | break; |
206 | if (i == -1) | 206 | if (i == -1) |
207 | ret = -EINVAL; | 207 | ret = -EINVAL; |
208 | else { | 208 | else { |
209 | ret = adis16400_spi_read_reg_16(indio_dev, | 209 | ret = adis16400_spi_read_reg_16(indio_dev, |
210 | ADIS16400_SENS_AVG, | 210 | ADIS16400_SENS_AVG, |
211 | &val16); | 211 | &val16); |
212 | if (ret < 0) | 212 | if (ret < 0) |
213 | goto error_ret; | 213 | goto error_ret; |
214 | 214 | ||
215 | ret = adis16400_spi_write_reg_16(indio_dev, | 215 | ret = adis16400_spi_write_reg_16(indio_dev, |
216 | ADIS16400_SENS_AVG, | 216 | ADIS16400_SENS_AVG, |
217 | (val16 & ~0x03) | i); | 217 | (val16 & ~0x03) | i); |
218 | } | 218 | } |
219 | error_ret: | 219 | error_ret: |
220 | return ret; | 220 | return ret; |
221 | } | 221 | } |
222 | 222 | ||
223 | static ssize_t adis16400_write_frequency(struct device *dev, | 223 | static ssize_t adis16400_write_frequency(struct device *dev, |
224 | struct device_attribute *attr, | 224 | struct device_attribute *attr, |
225 | const char *buf, | 225 | const char *buf, |
226 | size_t len) | 226 | size_t len) |
227 | { | 227 | { |
228 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); | 228 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
229 | struct adis16400_state *st = iio_priv(indio_dev); | 229 | struct adis16400_state *st = iio_priv(indio_dev); |
230 | long val; | 230 | long val; |
231 | int ret; | 231 | int ret; |
232 | u8 t; | 232 | u8 t; |
233 | 233 | ||
234 | ret = strict_strtol(buf, 10, &val); | 234 | ret = strict_strtol(buf, 10, &val); |
235 | if (ret) | 235 | if (ret) |
236 | return ret; | 236 | return ret; |
237 | 237 | ||
238 | mutex_lock(&indio_dev->mlock); | 238 | mutex_lock(&indio_dev->mlock); |
239 | 239 | ||
240 | t = (1638 / val); | 240 | t = (1638 / val); |
241 | if (t > 0) | 241 | if (t > 0) |
242 | t--; | 242 | t--; |
243 | t &= ADIS16400_SMPL_PRD_DIV_MASK; | 243 | t &= ADIS16400_SMPL_PRD_DIV_MASK; |
244 | if ((t & ADIS16400_SMPL_PRD_DIV_MASK) >= 0x0A) | 244 | if ((t & ADIS16400_SMPL_PRD_DIV_MASK) >= 0x0A) |
245 | st->us->max_speed_hz = ADIS16400_SPI_SLOW; | 245 | st->us->max_speed_hz = ADIS16400_SPI_SLOW; |
246 | else | 246 | else |
247 | st->us->max_speed_hz = ADIS16400_SPI_FAST; | 247 | st->us->max_speed_hz = ADIS16400_SPI_FAST; |
248 | 248 | ||
249 | ret = adis16400_spi_write_reg_8(indio_dev, | 249 | ret = adis16400_spi_write_reg_8(indio_dev, |
250 | ADIS16400_SMPL_PRD, | 250 | ADIS16400_SMPL_PRD, |
251 | t); | 251 | t); |
252 | 252 | ||
253 | /* Also update the filter */ | 253 | /* Also update the filter */ |
254 | mutex_unlock(&indio_dev->mlock); | 254 | mutex_unlock(&indio_dev->mlock); |
255 | 255 | ||
256 | return ret ? ret : len; | 256 | return ret ? ret : len; |
257 | } | 257 | } |
258 | 258 | ||
259 | static int adis16400_reset(struct iio_dev *indio_dev) | 259 | static int adis16400_reset(struct iio_dev *indio_dev) |
260 | { | 260 | { |
261 | int ret; | 261 | int ret; |
262 | ret = adis16400_spi_write_reg_8(indio_dev, | 262 | ret = adis16400_spi_write_reg_8(indio_dev, |
263 | ADIS16400_GLOB_CMD, | 263 | ADIS16400_GLOB_CMD, |
264 | ADIS16400_GLOB_CMD_SW_RESET); | 264 | ADIS16400_GLOB_CMD_SW_RESET); |
265 | if (ret) | 265 | if (ret) |
266 | dev_err(&indio_dev->dev, "problem resetting device"); | 266 | dev_err(&indio_dev->dev, "problem resetting device"); |
267 | 267 | ||
268 | return ret; | 268 | return ret; |
269 | } | 269 | } |
270 | 270 | ||
271 | static ssize_t adis16400_write_reset(struct device *dev, | ||
272 | struct device_attribute *attr, | ||
273 | const char *buf, size_t len) | ||
274 | { | ||
275 | bool val; | ||
276 | int ret; | ||
277 | |||
278 | ret = strtobool(buf, &val); | ||
279 | if (ret < 0) | ||
280 | return ret; | ||
281 | if (val) { | ||
282 | ret = adis16400_reset(dev_to_iio_dev(dev)); | ||
283 | if (ret < 0) | ||
284 | return ret; | ||
285 | } | ||
286 | |||
287 | return len; | ||
288 | } | ||
289 | |||
290 | int adis16400_set_irq(struct iio_dev *indio_dev, bool enable) | 271 | int adis16400_set_irq(struct iio_dev *indio_dev, bool enable) |
291 | { | 272 | { |
292 | int ret; | 273 | int ret; |
293 | u16 msc; | 274 | u16 msc; |
294 | 275 | ||
295 | ret = adis16400_spi_read_reg_16(indio_dev, ADIS16400_MSC_CTRL, &msc); | 276 | ret = adis16400_spi_read_reg_16(indio_dev, ADIS16400_MSC_CTRL, &msc); |
296 | if (ret) | 277 | if (ret) |
297 | goto error_ret; | 278 | goto error_ret; |
298 | 279 | ||
299 | msc |= ADIS16400_MSC_CTRL_DATA_RDY_POL_HIGH; | 280 | msc |= ADIS16400_MSC_CTRL_DATA_RDY_POL_HIGH; |
300 | if (enable) | 281 | if (enable) |
301 | msc |= ADIS16400_MSC_CTRL_DATA_RDY_EN; | 282 | msc |= ADIS16400_MSC_CTRL_DATA_RDY_EN; |
302 | else | 283 | else |
303 | msc &= ~ADIS16400_MSC_CTRL_DATA_RDY_EN; | 284 | msc &= ~ADIS16400_MSC_CTRL_DATA_RDY_EN; |
304 | 285 | ||
305 | ret = adis16400_spi_write_reg_16(indio_dev, ADIS16400_MSC_CTRL, msc); | 286 | ret = adis16400_spi_write_reg_16(indio_dev, ADIS16400_MSC_CTRL, msc); |
306 | if (ret) | 287 | if (ret) |
307 | goto error_ret; | 288 | goto error_ret; |
308 | 289 | ||
309 | error_ret: | 290 | error_ret: |
310 | return ret; | 291 | return ret; |
311 | } | 292 | } |
312 | 293 | ||
313 | /* Power down the device */ | 294 | /* Power down the device */ |
314 | static int adis16400_stop_device(struct iio_dev *indio_dev) | 295 | static int adis16400_stop_device(struct iio_dev *indio_dev) |
315 | { | 296 | { |
316 | int ret; | 297 | int ret; |
317 | u16 val = ADIS16400_SLP_CNT_POWER_OFF; | 298 | u16 val = ADIS16400_SLP_CNT_POWER_OFF; |
318 | 299 | ||
319 | ret = adis16400_spi_write_reg_16(indio_dev, ADIS16400_SLP_CNT, val); | 300 | ret = adis16400_spi_write_reg_16(indio_dev, ADIS16400_SLP_CNT, val); |
320 | if (ret) | 301 | if (ret) |
321 | dev_err(&indio_dev->dev, | 302 | dev_err(&indio_dev->dev, |
322 | "problem with turning device off: SLP_CNT"); | 303 | "problem with turning device off: SLP_CNT"); |
323 | 304 | ||
324 | return ret; | 305 | return ret; |
325 | } | 306 | } |
326 | 307 | ||
327 | static int adis16400_check_status(struct iio_dev *indio_dev) | 308 | static int adis16400_check_status(struct iio_dev *indio_dev) |
328 | { | 309 | { |
329 | u16 status; | 310 | u16 status; |
330 | int ret; | 311 | int ret; |
331 | struct device *dev = &indio_dev->dev; | 312 | struct device *dev = &indio_dev->dev; |
332 | 313 | ||
333 | ret = adis16400_spi_read_reg_16(indio_dev, | 314 | ret = adis16400_spi_read_reg_16(indio_dev, |
334 | ADIS16400_DIAG_STAT, &status); | 315 | ADIS16400_DIAG_STAT, &status); |
335 | 316 | ||
336 | if (ret < 0) { | 317 | if (ret < 0) { |
337 | dev_err(dev, "Reading status failed\n"); | 318 | dev_err(dev, "Reading status failed\n"); |
338 | goto error_ret; | 319 | goto error_ret; |
339 | } | 320 | } |
340 | ret = status; | 321 | ret = status; |
341 | if (status & ADIS16400_DIAG_STAT_ZACCL_FAIL) | 322 | if (status & ADIS16400_DIAG_STAT_ZACCL_FAIL) |
342 | dev_err(dev, "Z-axis accelerometer self-test failure\n"); | 323 | dev_err(dev, "Z-axis accelerometer self-test failure\n"); |
343 | if (status & ADIS16400_DIAG_STAT_YACCL_FAIL) | 324 | if (status & ADIS16400_DIAG_STAT_YACCL_FAIL) |
344 | dev_err(dev, "Y-axis accelerometer self-test failure\n"); | 325 | dev_err(dev, "Y-axis accelerometer self-test failure\n"); |
345 | if (status & ADIS16400_DIAG_STAT_XACCL_FAIL) | 326 | if (status & ADIS16400_DIAG_STAT_XACCL_FAIL) |
346 | dev_err(dev, "X-axis accelerometer self-test failure\n"); | 327 | dev_err(dev, "X-axis accelerometer self-test failure\n"); |
347 | if (status & ADIS16400_DIAG_STAT_XGYRO_FAIL) | 328 | if (status & ADIS16400_DIAG_STAT_XGYRO_FAIL) |
348 | dev_err(dev, "X-axis gyroscope self-test failure\n"); | 329 | dev_err(dev, "X-axis gyroscope self-test failure\n"); |
349 | if (status & ADIS16400_DIAG_STAT_YGYRO_FAIL) | 330 | if (status & ADIS16400_DIAG_STAT_YGYRO_FAIL) |
350 | dev_err(dev, "Y-axis gyroscope self-test failure\n"); | 331 | dev_err(dev, "Y-axis gyroscope self-test failure\n"); |
351 | if (status & ADIS16400_DIAG_STAT_ZGYRO_FAIL) | 332 | if (status & ADIS16400_DIAG_STAT_ZGYRO_FAIL) |
352 | dev_err(dev, "Z-axis gyroscope self-test failure\n"); | 333 | dev_err(dev, "Z-axis gyroscope self-test failure\n"); |
353 | if (status & ADIS16400_DIAG_STAT_ALARM2) | 334 | if (status & ADIS16400_DIAG_STAT_ALARM2) |
354 | dev_err(dev, "Alarm 2 active\n"); | 335 | dev_err(dev, "Alarm 2 active\n"); |
355 | if (status & ADIS16400_DIAG_STAT_ALARM1) | 336 | if (status & ADIS16400_DIAG_STAT_ALARM1) |
356 | dev_err(dev, "Alarm 1 active\n"); | 337 | dev_err(dev, "Alarm 1 active\n"); |
357 | if (status & ADIS16400_DIAG_STAT_FLASH_CHK) | 338 | if (status & ADIS16400_DIAG_STAT_FLASH_CHK) |
358 | dev_err(dev, "Flash checksum error\n"); | 339 | dev_err(dev, "Flash checksum error\n"); |
359 | if (status & ADIS16400_DIAG_STAT_SELF_TEST) | 340 | if (status & ADIS16400_DIAG_STAT_SELF_TEST) |
360 | dev_err(dev, "Self test error\n"); | 341 | dev_err(dev, "Self test error\n"); |
361 | if (status & ADIS16400_DIAG_STAT_OVERFLOW) | 342 | if (status & ADIS16400_DIAG_STAT_OVERFLOW) |
362 | dev_err(dev, "Sensor overrange\n"); | 343 | dev_err(dev, "Sensor overrange\n"); |
363 | if (status & ADIS16400_DIAG_STAT_SPI_FAIL) | 344 | if (status & ADIS16400_DIAG_STAT_SPI_FAIL) |
364 | dev_err(dev, "SPI failure\n"); | 345 | dev_err(dev, "SPI failure\n"); |
365 | if (status & ADIS16400_DIAG_STAT_FLASH_UPT) | 346 | if (status & ADIS16400_DIAG_STAT_FLASH_UPT) |
366 | dev_err(dev, "Flash update failed\n"); | 347 | dev_err(dev, "Flash update failed\n"); |
367 | if (status & ADIS16400_DIAG_STAT_POWER_HIGH) | 348 | if (status & ADIS16400_DIAG_STAT_POWER_HIGH) |
368 | dev_err(dev, "Power supply above 5.25V\n"); | 349 | dev_err(dev, "Power supply above 5.25V\n"); |
369 | if (status & ADIS16400_DIAG_STAT_POWER_LOW) | 350 | if (status & ADIS16400_DIAG_STAT_POWER_LOW) |
370 | dev_err(dev, "Power supply below 4.75V\n"); | 351 | dev_err(dev, "Power supply below 4.75V\n"); |
371 | 352 | ||
372 | error_ret: | 353 | error_ret: |
373 | return ret; | 354 | return ret; |
374 | } | 355 | } |
375 | 356 | ||
376 | static int adis16400_self_test(struct iio_dev *indio_dev) | 357 | static int adis16400_self_test(struct iio_dev *indio_dev) |
377 | { | 358 | { |
378 | int ret; | 359 | int ret; |
379 | ret = adis16400_spi_write_reg_16(indio_dev, | 360 | ret = adis16400_spi_write_reg_16(indio_dev, |
380 | ADIS16400_MSC_CTRL, | 361 | ADIS16400_MSC_CTRL, |
381 | ADIS16400_MSC_CTRL_MEM_TEST); | 362 | ADIS16400_MSC_CTRL_MEM_TEST); |
382 | if (ret) { | 363 | if (ret) { |
383 | dev_err(&indio_dev->dev, "problem starting self test"); | 364 | dev_err(&indio_dev->dev, "problem starting self test"); |
384 | goto err_ret; | 365 | goto err_ret; |
385 | } | 366 | } |
386 | 367 | ||
387 | msleep(ADIS16400_MTEST_DELAY); | 368 | msleep(ADIS16400_MTEST_DELAY); |
388 | adis16400_check_status(indio_dev); | 369 | adis16400_check_status(indio_dev); |
389 | 370 | ||
390 | err_ret: | 371 | err_ret: |
391 | return ret; | 372 | return ret; |
392 | } | 373 | } |
393 | 374 | ||
394 | static int adis16400_initial_setup(struct iio_dev *indio_dev) | 375 | static int adis16400_initial_setup(struct iio_dev *indio_dev) |
395 | { | 376 | { |
396 | int ret; | 377 | int ret; |
397 | u16 prod_id, smp_prd; | 378 | u16 prod_id, smp_prd; |
398 | struct adis16400_state *st = iio_priv(indio_dev); | 379 | struct adis16400_state *st = iio_priv(indio_dev); |
399 | 380 | ||
400 | /* use low spi speed for init */ | 381 | /* use low spi speed for init */ |
401 | st->us->max_speed_hz = ADIS16400_SPI_SLOW; | 382 | st->us->max_speed_hz = ADIS16400_SPI_SLOW; |
402 | st->us->mode = SPI_MODE_3; | 383 | st->us->mode = SPI_MODE_3; |
403 | spi_setup(st->us); | 384 | spi_setup(st->us); |
404 | 385 | ||
405 | ret = adis16400_set_irq(indio_dev, false); | 386 | ret = adis16400_set_irq(indio_dev, false); |
406 | if (ret) { | 387 | if (ret) { |
407 | dev_err(&indio_dev->dev, "disable irq failed"); | 388 | dev_err(&indio_dev->dev, "disable irq failed"); |
408 | goto err_ret; | 389 | goto err_ret; |
409 | } | 390 | } |
410 | 391 | ||
411 | ret = adis16400_self_test(indio_dev); | 392 | ret = adis16400_self_test(indio_dev); |
412 | if (ret) { | 393 | if (ret) { |
413 | dev_err(&indio_dev->dev, "self test failure"); | 394 | dev_err(&indio_dev->dev, "self test failure"); |
414 | goto err_ret; | 395 | goto err_ret; |
415 | } | 396 | } |
416 | 397 | ||
417 | ret = adis16400_check_status(indio_dev); | 398 | ret = adis16400_check_status(indio_dev); |
418 | if (ret) { | 399 | if (ret) { |
419 | adis16400_reset(indio_dev); | 400 | adis16400_reset(indio_dev); |
420 | dev_err(&indio_dev->dev, "device not playing ball -> reset"); | 401 | dev_err(&indio_dev->dev, "device not playing ball -> reset"); |
421 | msleep(ADIS16400_STARTUP_DELAY); | 402 | msleep(ADIS16400_STARTUP_DELAY); |
422 | ret = adis16400_check_status(indio_dev); | 403 | ret = adis16400_check_status(indio_dev); |
423 | if (ret) { | 404 | if (ret) { |
424 | dev_err(&indio_dev->dev, "giving up"); | 405 | dev_err(&indio_dev->dev, "giving up"); |
425 | goto err_ret; | 406 | goto err_ret; |
426 | } | 407 | } |
427 | } | 408 | } |
428 | if (st->variant->flags & ADIS16400_HAS_PROD_ID) { | 409 | if (st->variant->flags & ADIS16400_HAS_PROD_ID) { |
429 | ret = adis16400_spi_read_reg_16(indio_dev, | 410 | ret = adis16400_spi_read_reg_16(indio_dev, |
430 | ADIS16400_PRODUCT_ID, &prod_id); | 411 | ADIS16400_PRODUCT_ID, &prod_id); |
431 | if (ret) | 412 | if (ret) |
432 | goto err_ret; | 413 | goto err_ret; |
433 | 414 | ||
434 | if ((prod_id & 0xF000) != st->variant->product_id) | 415 | if ((prod_id & 0xF000) != st->variant->product_id) |
435 | dev_warn(&indio_dev->dev, "incorrect id"); | 416 | dev_warn(&indio_dev->dev, "incorrect id"); |
436 | 417 | ||
437 | dev_info(&indio_dev->dev, "%s: prod_id 0x%04x at CS%d (irq %d)\n", | 418 | dev_info(&indio_dev->dev, "%s: prod_id 0x%04x at CS%d (irq %d)\n", |
438 | indio_dev->name, prod_id, | 419 | indio_dev->name, prod_id, |
439 | st->us->chip_select, st->us->irq); | 420 | st->us->chip_select, st->us->irq); |
440 | } | 421 | } |
441 | /* use high spi speed if possible */ | 422 | /* use high spi speed if possible */ |
442 | ret = adis16400_spi_read_reg_16(indio_dev, | 423 | ret = adis16400_spi_read_reg_16(indio_dev, |
443 | ADIS16400_SMPL_PRD, &smp_prd); | 424 | ADIS16400_SMPL_PRD, &smp_prd); |
444 | if (!ret && (smp_prd & ADIS16400_SMPL_PRD_DIV_MASK) < 0x0A) { | 425 | if (!ret && (smp_prd & ADIS16400_SMPL_PRD_DIV_MASK) < 0x0A) { |
445 | st->us->max_speed_hz = ADIS16400_SPI_SLOW; | 426 | st->us->max_speed_hz = ADIS16400_SPI_SLOW; |
446 | spi_setup(st->us); | 427 | spi_setup(st->us); |
447 | } | 428 | } |
448 | 429 | ||
449 | err_ret: | 430 | err_ret: |
450 | return ret; | 431 | return ret; |
451 | } | 432 | } |
452 | 433 | ||
453 | static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, | 434 | static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, |
454 | adis16400_read_frequency, | 435 | adis16400_read_frequency, |
455 | adis16400_write_frequency); | 436 | adis16400_write_frequency); |
456 | 437 | ||
457 | static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16400_write_reset, 0); | ||
458 | |||
459 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("409 546 819 1638"); | 438 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("409 546 819 1638"); |
460 | 439 | ||
461 | enum adis16400_chan { | 440 | enum adis16400_chan { |
462 | in_supply, | 441 | in_supply, |
463 | gyro_x, | 442 | gyro_x, |
464 | gyro_y, | 443 | gyro_y, |
465 | gyro_z, | 444 | gyro_z, |
466 | accel_x, | 445 | accel_x, |
467 | accel_y, | 446 | accel_y, |
468 | accel_z, | 447 | accel_z, |
469 | magn_x, | 448 | magn_x, |
470 | magn_y, | 449 | magn_y, |
471 | magn_z, | 450 | magn_z, |
472 | temp, | 451 | temp, |
473 | temp0, temp1, temp2, | 452 | temp0, temp1, temp2, |
474 | in1, | 453 | in1, |
475 | in2, | 454 | in2, |
476 | incli_x, | 455 | incli_x, |
477 | incli_y, | 456 | incli_y, |
478 | }; | 457 | }; |
479 | 458 | ||
480 | static u8 adis16400_addresses[18][2] = { | 459 | static u8 adis16400_addresses[18][2] = { |
481 | [in_supply] = { ADIS16400_SUPPLY_OUT }, | 460 | [in_supply] = { ADIS16400_SUPPLY_OUT }, |
482 | [gyro_x] = { ADIS16400_XGYRO_OUT, ADIS16400_XGYRO_OFF }, | 461 | [gyro_x] = { ADIS16400_XGYRO_OUT, ADIS16400_XGYRO_OFF }, |
483 | [gyro_y] = { ADIS16400_YGYRO_OUT, ADIS16400_YGYRO_OFF }, | 462 | [gyro_y] = { ADIS16400_YGYRO_OUT, ADIS16400_YGYRO_OFF }, |
484 | [gyro_z] = { ADIS16400_ZGYRO_OUT, ADIS16400_ZGYRO_OFF }, | 463 | [gyro_z] = { ADIS16400_ZGYRO_OUT, ADIS16400_ZGYRO_OFF }, |
485 | [accel_x] = { ADIS16400_XACCL_OUT, ADIS16400_XACCL_OFF }, | 464 | [accel_x] = { ADIS16400_XACCL_OUT, ADIS16400_XACCL_OFF }, |
486 | [accel_y] = { ADIS16400_YACCL_OUT, ADIS16400_YACCL_OFF }, | 465 | [accel_y] = { ADIS16400_YACCL_OUT, ADIS16400_YACCL_OFF }, |
487 | [accel_z] = { ADIS16400_ZACCL_OUT, ADIS16400_ZACCL_OFF }, | 466 | [accel_z] = { ADIS16400_ZACCL_OUT, ADIS16400_ZACCL_OFF }, |
488 | [magn_x] = { ADIS16400_XMAGN_OUT }, | 467 | [magn_x] = { ADIS16400_XMAGN_OUT }, |
489 | [magn_y] = { ADIS16400_YMAGN_OUT }, | 468 | [magn_y] = { ADIS16400_YMAGN_OUT }, |
490 | [magn_z] = { ADIS16400_ZMAGN_OUT }, | 469 | [magn_z] = { ADIS16400_ZMAGN_OUT }, |
491 | [temp] = { ADIS16400_TEMP_OUT }, | 470 | [temp] = { ADIS16400_TEMP_OUT }, |
492 | [temp0] = { ADIS16350_XTEMP_OUT }, | 471 | [temp0] = { ADIS16350_XTEMP_OUT }, |
493 | [temp1] = { ADIS16350_YTEMP_OUT }, | 472 | [temp1] = { ADIS16350_YTEMP_OUT }, |
494 | [temp2] = { ADIS16350_ZTEMP_OUT }, | 473 | [temp2] = { ADIS16350_ZTEMP_OUT }, |
495 | [in1] = { ADIS16300_AUX_ADC }, | 474 | [in1] = { ADIS16300_AUX_ADC }, |
496 | [in2] = { ADIS16400_AUX_ADC }, | 475 | [in2] = { ADIS16400_AUX_ADC }, |
497 | [incli_x] = { ADIS16300_PITCH_OUT }, | 476 | [incli_x] = { ADIS16300_PITCH_OUT }, |
498 | [incli_y] = { ADIS16300_ROLL_OUT } | 477 | [incli_y] = { ADIS16300_ROLL_OUT } |
499 | }; | 478 | }; |
500 | 479 | ||
501 | 480 | ||
502 | static int adis16400_write_raw(struct iio_dev *indio_dev, | 481 | static int adis16400_write_raw(struct iio_dev *indio_dev, |
503 | struct iio_chan_spec const *chan, | 482 | struct iio_chan_spec const *chan, |
504 | int val, | 483 | int val, |
505 | int val2, | 484 | int val2, |
506 | long mask) | 485 | long mask) |
507 | { | 486 | { |
508 | struct adis16400_state *st = iio_priv(indio_dev); | 487 | struct adis16400_state *st = iio_priv(indio_dev); |
509 | int ret, sps; | 488 | int ret, sps; |
510 | 489 | ||
511 | switch (mask) { | 490 | switch (mask) { |
512 | case IIO_CHAN_INFO_CALIBBIAS: | 491 | case IIO_CHAN_INFO_CALIBBIAS: |
513 | mutex_lock(&indio_dev->mlock); | 492 | mutex_lock(&indio_dev->mlock); |
514 | ret = adis16400_spi_write_reg_16(indio_dev, | 493 | ret = adis16400_spi_write_reg_16(indio_dev, |
515 | adis16400_addresses[chan->address][1], | 494 | adis16400_addresses[chan->address][1], |
516 | val); | 495 | val); |
517 | mutex_unlock(&indio_dev->mlock); | 496 | mutex_unlock(&indio_dev->mlock); |
518 | return ret; | 497 | return ret; |
519 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: | 498 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: |
520 | /* Need to cache values so we can update if the frequency | 499 | /* Need to cache values so we can update if the frequency |
521 | changes */ | 500 | changes */ |
522 | mutex_lock(&indio_dev->mlock); | 501 | mutex_lock(&indio_dev->mlock); |
523 | st->filt_int = val; | 502 | st->filt_int = val; |
524 | /* Work out update to current value */ | 503 | /* Work out update to current value */ |
525 | sps = adis16400_get_freq(indio_dev); | 504 | sps = adis16400_get_freq(indio_dev); |
526 | if (sps < 0) { | 505 | if (sps < 0) { |
527 | mutex_unlock(&indio_dev->mlock); | 506 | mutex_unlock(&indio_dev->mlock); |
528 | return sps; | 507 | return sps; |
529 | } | 508 | } |
530 | 509 | ||
531 | ret = adis16400_set_filter(indio_dev, sps, val); | 510 | ret = adis16400_set_filter(indio_dev, sps, val); |
532 | mutex_unlock(&indio_dev->mlock); | 511 | mutex_unlock(&indio_dev->mlock); |
533 | return ret; | 512 | return ret; |
534 | default: | 513 | default: |
535 | return -EINVAL; | 514 | return -EINVAL; |
536 | } | 515 | } |
537 | } | 516 | } |
538 | 517 | ||
539 | static int adis16400_read_raw(struct iio_dev *indio_dev, | 518 | static int adis16400_read_raw(struct iio_dev *indio_dev, |
540 | struct iio_chan_spec const *chan, | 519 | struct iio_chan_spec const *chan, |
541 | int *val, | 520 | int *val, |
542 | int *val2, | 521 | int *val2, |
543 | long mask) | 522 | long mask) |
544 | { | 523 | { |
545 | struct adis16400_state *st = iio_priv(indio_dev); | 524 | struct adis16400_state *st = iio_priv(indio_dev); |
546 | int ret, shift; | 525 | int ret, shift; |
547 | s16 val16; | 526 | s16 val16; |
548 | 527 | ||
549 | switch (mask) { | 528 | switch (mask) { |
550 | case IIO_CHAN_INFO_RAW: | 529 | case IIO_CHAN_INFO_RAW: |
551 | mutex_lock(&indio_dev->mlock); | 530 | mutex_lock(&indio_dev->mlock); |
552 | ret = adis16400_spi_read_reg_16(indio_dev, | 531 | ret = adis16400_spi_read_reg_16(indio_dev, |
553 | adis16400_addresses[chan->address][0], | 532 | adis16400_addresses[chan->address][0], |
554 | &val16); | 533 | &val16); |
555 | if (ret) { | 534 | if (ret) { |
556 | mutex_unlock(&indio_dev->mlock); | 535 | mutex_unlock(&indio_dev->mlock); |
557 | return ret; | 536 | return ret; |
558 | } | 537 | } |
559 | val16 &= (1 << chan->scan_type.realbits) - 1; | 538 | val16 &= (1 << chan->scan_type.realbits) - 1; |
560 | if (chan->scan_type.sign == 's') { | 539 | if (chan->scan_type.sign == 's') { |
561 | shift = 16 - chan->scan_type.realbits; | 540 | shift = 16 - chan->scan_type.realbits; |
562 | val16 = (s16)(val16 << shift) >> shift; | 541 | val16 = (s16)(val16 << shift) >> shift; |
563 | } | 542 | } |
564 | *val = val16; | 543 | *val = val16; |
565 | mutex_unlock(&indio_dev->mlock); | 544 | mutex_unlock(&indio_dev->mlock); |
566 | return IIO_VAL_INT; | 545 | return IIO_VAL_INT; |
567 | case IIO_CHAN_INFO_SCALE: | 546 | case IIO_CHAN_INFO_SCALE: |
568 | switch (chan->type) { | 547 | switch (chan->type) { |
569 | case IIO_ANGL_VEL: | 548 | case IIO_ANGL_VEL: |
570 | *val = 0; | 549 | *val = 0; |
571 | *val2 = st->variant->gyro_scale_micro; | 550 | *val2 = st->variant->gyro_scale_micro; |
572 | return IIO_VAL_INT_PLUS_MICRO; | 551 | return IIO_VAL_INT_PLUS_MICRO; |
573 | case IIO_VOLTAGE: | 552 | case IIO_VOLTAGE: |
574 | *val = 0; | 553 | *val = 0; |
575 | if (chan->channel == 0) | 554 | if (chan->channel == 0) |
576 | *val2 = 2418; | 555 | *val2 = 2418; |
577 | else | 556 | else |
578 | *val2 = 806; | 557 | *val2 = 806; |
579 | return IIO_VAL_INT_PLUS_MICRO; | 558 | return IIO_VAL_INT_PLUS_MICRO; |
580 | case IIO_ACCEL: | 559 | case IIO_ACCEL: |
581 | *val = 0; | 560 | *val = 0; |
582 | *val2 = st->variant->accel_scale_micro; | 561 | *val2 = st->variant->accel_scale_micro; |
583 | return IIO_VAL_INT_PLUS_MICRO; | 562 | return IIO_VAL_INT_PLUS_MICRO; |
584 | case IIO_MAGN: | 563 | case IIO_MAGN: |
585 | *val = 0; | 564 | *val = 0; |
586 | *val2 = 500; | 565 | *val2 = 500; |
587 | return IIO_VAL_INT_PLUS_MICRO; | 566 | return IIO_VAL_INT_PLUS_MICRO; |
588 | case IIO_TEMP: | 567 | case IIO_TEMP: |
589 | *val = 0; | 568 | *val = 0; |
590 | *val2 = 140000; | 569 | *val2 = 140000; |
591 | return IIO_VAL_INT_PLUS_MICRO; | 570 | return IIO_VAL_INT_PLUS_MICRO; |
592 | default: | 571 | default: |
593 | return -EINVAL; | 572 | return -EINVAL; |
594 | } | 573 | } |
595 | case IIO_CHAN_INFO_CALIBBIAS: | 574 | case IIO_CHAN_INFO_CALIBBIAS: |
596 | mutex_lock(&indio_dev->mlock); | 575 | mutex_lock(&indio_dev->mlock); |
597 | ret = adis16400_spi_read_reg_16(indio_dev, | 576 | ret = adis16400_spi_read_reg_16(indio_dev, |
598 | adis16400_addresses[chan->address][1], | 577 | adis16400_addresses[chan->address][1], |
599 | &val16); | 578 | &val16); |
600 | mutex_unlock(&indio_dev->mlock); | 579 | mutex_unlock(&indio_dev->mlock); |
601 | if (ret) | 580 | if (ret) |
602 | return ret; | 581 | return ret; |
603 | val16 = ((val16 & 0xFFF) << 4) >> 4; | 582 | val16 = ((val16 & 0xFFF) << 4) >> 4; |
604 | *val = val16; | 583 | *val = val16; |
605 | return IIO_VAL_INT; | 584 | return IIO_VAL_INT; |
606 | case IIO_CHAN_INFO_OFFSET: | 585 | case IIO_CHAN_INFO_OFFSET: |
607 | /* currently only temperature */ | 586 | /* currently only temperature */ |
608 | *val = 198; | 587 | *val = 198; |
609 | *val2 = 160000; | 588 | *val2 = 160000; |
610 | return IIO_VAL_INT_PLUS_MICRO; | 589 | return IIO_VAL_INT_PLUS_MICRO; |
611 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: | 590 | case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: |
612 | mutex_lock(&indio_dev->mlock); | 591 | mutex_lock(&indio_dev->mlock); |
613 | /* Need both the number of taps and the sampling frequency */ | 592 | /* Need both the number of taps and the sampling frequency */ |
614 | ret = adis16400_spi_read_reg_16(indio_dev, | 593 | ret = adis16400_spi_read_reg_16(indio_dev, |
615 | ADIS16400_SENS_AVG, | 594 | ADIS16400_SENS_AVG, |
616 | &val16); | 595 | &val16); |
617 | if (ret < 0) { | 596 | if (ret < 0) { |
618 | mutex_unlock(&indio_dev->mlock); | 597 | mutex_unlock(&indio_dev->mlock); |
619 | return ret; | 598 | return ret; |
620 | } | 599 | } |
621 | ret = adis16400_get_freq(indio_dev); | 600 | ret = adis16400_get_freq(indio_dev); |
622 | if (ret > 0) | 601 | if (ret > 0) |
623 | *val = ret/adis16400_3db_divisors[val16 & 0x03]; | 602 | *val = ret/adis16400_3db_divisors[val16 & 0x03]; |
624 | *val2 = 0; | 603 | *val2 = 0; |
625 | mutex_unlock(&indio_dev->mlock); | 604 | mutex_unlock(&indio_dev->mlock); |
626 | if (ret < 0) | 605 | if (ret < 0) |
627 | return ret; | 606 | return ret; |
628 | return IIO_VAL_INT_PLUS_MICRO; | 607 | return IIO_VAL_INT_PLUS_MICRO; |
629 | default: | 608 | default: |
630 | return -EINVAL; | 609 | return -EINVAL; |
631 | } | 610 | } |
632 | } | 611 | } |
633 | 612 | ||
634 | static struct iio_chan_spec adis16400_channels[] = { | 613 | static struct iio_chan_spec adis16400_channels[] = { |
635 | { | 614 | { |
636 | .type = IIO_VOLTAGE, | 615 | .type = IIO_VOLTAGE, |
637 | .indexed = 1, | 616 | .indexed = 1, |
638 | .channel = 0, | 617 | .channel = 0, |
639 | .extend_name = "supply", | 618 | .extend_name = "supply", |
640 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 619 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
641 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 620 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
642 | .address = in_supply, | 621 | .address = in_supply, |
643 | .scan_index = ADIS16400_SCAN_SUPPLY, | 622 | .scan_index = ADIS16400_SCAN_SUPPLY, |
644 | .scan_type = IIO_ST('u', 14, 16, 0) | 623 | .scan_type = IIO_ST('u', 14, 16, 0) |
645 | }, { | 624 | }, { |
646 | .type = IIO_ANGL_VEL, | 625 | .type = IIO_ANGL_VEL, |
647 | .modified = 1, | 626 | .modified = 1, |
648 | .channel2 = IIO_MOD_X, | 627 | .channel2 = IIO_MOD_X, |
649 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 628 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
650 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 629 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
651 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 630 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
652 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 631 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
653 | .address = gyro_x, | 632 | .address = gyro_x, |
654 | .scan_index = ADIS16400_SCAN_GYRO_X, | 633 | .scan_index = ADIS16400_SCAN_GYRO_X, |
655 | .scan_type = IIO_ST('s', 14, 16, 0) | 634 | .scan_type = IIO_ST('s', 14, 16, 0) |
656 | }, { | 635 | }, { |
657 | .type = IIO_ANGL_VEL, | 636 | .type = IIO_ANGL_VEL, |
658 | .modified = 1, | 637 | .modified = 1, |
659 | .channel2 = IIO_MOD_Y, | 638 | .channel2 = IIO_MOD_Y, |
660 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 639 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
661 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 640 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
662 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 641 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
663 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 642 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
664 | .address = gyro_y, | 643 | .address = gyro_y, |
665 | .scan_index = ADIS16400_SCAN_GYRO_Y, | 644 | .scan_index = ADIS16400_SCAN_GYRO_Y, |
666 | .scan_type = IIO_ST('s', 14, 16, 0), | 645 | .scan_type = IIO_ST('s', 14, 16, 0), |
667 | }, { | 646 | }, { |
668 | .type = IIO_ANGL_VEL, | 647 | .type = IIO_ANGL_VEL, |
669 | .modified = 1, | 648 | .modified = 1, |
670 | .channel2 = IIO_MOD_Z, | 649 | .channel2 = IIO_MOD_Z, |
671 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 650 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
672 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 651 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
673 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 652 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
674 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 653 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
675 | .address = gyro_z, | 654 | .address = gyro_z, |
676 | .scan_index = ADIS16400_SCAN_GYRO_Z, | 655 | .scan_index = ADIS16400_SCAN_GYRO_Z, |
677 | .scan_type = IIO_ST('s', 14, 16, 0), | 656 | .scan_type = IIO_ST('s', 14, 16, 0), |
678 | }, { | 657 | }, { |
679 | .type = IIO_ACCEL, | 658 | .type = IIO_ACCEL, |
680 | .modified = 1, | 659 | .modified = 1, |
681 | .channel2 = IIO_MOD_X, | 660 | .channel2 = IIO_MOD_X, |
682 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 661 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
683 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 662 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
684 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 663 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
685 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 664 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
686 | .address = accel_x, | 665 | .address = accel_x, |
687 | .scan_index = ADIS16400_SCAN_ACC_X, | 666 | .scan_index = ADIS16400_SCAN_ACC_X, |
688 | .scan_type = IIO_ST('s', 14, 16, 0), | 667 | .scan_type = IIO_ST('s', 14, 16, 0), |
689 | }, { | 668 | }, { |
690 | .type = IIO_ACCEL, | 669 | .type = IIO_ACCEL, |
691 | .modified = 1, | 670 | .modified = 1, |
692 | .channel2 = IIO_MOD_Y, | 671 | .channel2 = IIO_MOD_Y, |
693 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 672 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
694 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 673 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
695 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 674 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
696 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 675 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
697 | .address = accel_y, | 676 | .address = accel_y, |
698 | .scan_index = ADIS16400_SCAN_ACC_Y, | 677 | .scan_index = ADIS16400_SCAN_ACC_Y, |
699 | .scan_type = IIO_ST('s', 14, 16, 0), | 678 | .scan_type = IIO_ST('s', 14, 16, 0), |
700 | }, { | 679 | }, { |
701 | .type = IIO_ACCEL, | 680 | .type = IIO_ACCEL, |
702 | .modified = 1, | 681 | .modified = 1, |
703 | .channel2 = IIO_MOD_Z, | 682 | .channel2 = IIO_MOD_Z, |
704 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 683 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
705 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 684 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
706 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 685 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
707 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 686 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
708 | .address = accel_z, | 687 | .address = accel_z, |
709 | .scan_index = ADIS16400_SCAN_ACC_Z, | 688 | .scan_index = ADIS16400_SCAN_ACC_Z, |
710 | .scan_type = IIO_ST('s', 14, 16, 0), | 689 | .scan_type = IIO_ST('s', 14, 16, 0), |
711 | }, { | 690 | }, { |
712 | .type = IIO_MAGN, | 691 | .type = IIO_MAGN, |
713 | .modified = 1, | 692 | .modified = 1, |
714 | .channel2 = IIO_MOD_X, | 693 | .channel2 = IIO_MOD_X, |
715 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 694 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
716 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 695 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
717 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 696 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
718 | .address = magn_x, | 697 | .address = magn_x, |
719 | .scan_index = ADIS16400_SCAN_MAGN_X, | 698 | .scan_index = ADIS16400_SCAN_MAGN_X, |
720 | .scan_type = IIO_ST('s', 14, 16, 0), | 699 | .scan_type = IIO_ST('s', 14, 16, 0), |
721 | }, { | 700 | }, { |
722 | .type = IIO_MAGN, | 701 | .type = IIO_MAGN, |
723 | .modified = 1, | 702 | .modified = 1, |
724 | .channel2 = IIO_MOD_Y, | 703 | .channel2 = IIO_MOD_Y, |
725 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 704 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
726 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 705 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
727 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 706 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
728 | .address = magn_y, | 707 | .address = magn_y, |
729 | .scan_index = ADIS16400_SCAN_MAGN_Y, | 708 | .scan_index = ADIS16400_SCAN_MAGN_Y, |
730 | .scan_type = IIO_ST('s', 14, 16, 0), | 709 | .scan_type = IIO_ST('s', 14, 16, 0), |
731 | }, { | 710 | }, { |
732 | .type = IIO_MAGN, | 711 | .type = IIO_MAGN, |
733 | .modified = 1, | 712 | .modified = 1, |
734 | .channel2 = IIO_MOD_Z, | 713 | .channel2 = IIO_MOD_Z, |
735 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 714 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
736 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 715 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
737 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 716 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
738 | .address = magn_z, | 717 | .address = magn_z, |
739 | .scan_index = ADIS16400_SCAN_MAGN_Z, | 718 | .scan_index = ADIS16400_SCAN_MAGN_Z, |
740 | .scan_type = IIO_ST('s', 14, 16, 0), | 719 | .scan_type = IIO_ST('s', 14, 16, 0), |
741 | }, { | 720 | }, { |
742 | .type = IIO_TEMP, | 721 | .type = IIO_TEMP, |
743 | .indexed = 1, | 722 | .indexed = 1, |
744 | .channel = 0, | 723 | .channel = 0, |
745 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 724 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
746 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | | 725 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | |
747 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 726 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
748 | .address = temp, | 727 | .address = temp, |
749 | .scan_index = ADIS16400_SCAN_TEMP, | 728 | .scan_index = ADIS16400_SCAN_TEMP, |
750 | .scan_type = IIO_ST('s', 12, 16, 0), | 729 | .scan_type = IIO_ST('s', 12, 16, 0), |
751 | }, { | 730 | }, { |
752 | .type = IIO_VOLTAGE, | 731 | .type = IIO_VOLTAGE, |
753 | .indexed = 1, | 732 | .indexed = 1, |
754 | .channel = 1, | 733 | .channel = 1, |
755 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 734 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
756 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 735 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
757 | .address = in2, | 736 | .address = in2, |
758 | .scan_index = ADIS16400_SCAN_ADC_0, | 737 | .scan_index = ADIS16400_SCAN_ADC_0, |
759 | .scan_type = IIO_ST('s', 12, 16, 0), | 738 | .scan_type = IIO_ST('s', 12, 16, 0), |
760 | }, | 739 | }, |
761 | IIO_CHAN_SOFT_TIMESTAMP(12) | 740 | IIO_CHAN_SOFT_TIMESTAMP(12) |
762 | }; | 741 | }; |
763 | 742 | ||
764 | static struct iio_chan_spec adis16350_channels[] = { | 743 | static struct iio_chan_spec adis16350_channels[] = { |
765 | { | 744 | { |
766 | .type = IIO_VOLTAGE, | 745 | .type = IIO_VOLTAGE, |
767 | .indexed = 1, | 746 | .indexed = 1, |
768 | .channel = 0, | 747 | .channel = 0, |
769 | .extend_name = "supply", | 748 | .extend_name = "supply", |
770 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 749 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
771 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 750 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
772 | .address = in_supply, | 751 | .address = in_supply, |
773 | .scan_index = ADIS16400_SCAN_SUPPLY, | 752 | .scan_index = ADIS16400_SCAN_SUPPLY, |
774 | .scan_type = IIO_ST('u', 12, 16, 0) | 753 | .scan_type = IIO_ST('u', 12, 16, 0) |
775 | }, { | 754 | }, { |
776 | .type = IIO_ANGL_VEL, | 755 | .type = IIO_ANGL_VEL, |
777 | .modified = 1, | 756 | .modified = 1, |
778 | .channel2 = IIO_MOD_X, | 757 | .channel2 = IIO_MOD_X, |
779 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 758 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
780 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 759 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
781 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 760 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
782 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 761 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
783 | .address = gyro_x, | 762 | .address = gyro_x, |
784 | .scan_index = ADIS16400_SCAN_GYRO_X, | 763 | .scan_index = ADIS16400_SCAN_GYRO_X, |
785 | .scan_type = IIO_ST('s', 14, 16, 0) | 764 | .scan_type = IIO_ST('s', 14, 16, 0) |
786 | }, { | 765 | }, { |
787 | .type = IIO_ANGL_VEL, | 766 | .type = IIO_ANGL_VEL, |
788 | .modified = 1, | 767 | .modified = 1, |
789 | .channel2 = IIO_MOD_Y, | 768 | .channel2 = IIO_MOD_Y, |
790 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 769 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
791 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 770 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
792 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 771 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
793 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 772 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
794 | .address = gyro_y, | 773 | .address = gyro_y, |
795 | .scan_index = ADIS16400_SCAN_GYRO_Y, | 774 | .scan_index = ADIS16400_SCAN_GYRO_Y, |
796 | .scan_type = IIO_ST('s', 14, 16, 0), | 775 | .scan_type = IIO_ST('s', 14, 16, 0), |
797 | }, { | 776 | }, { |
798 | .type = IIO_ANGL_VEL, | 777 | .type = IIO_ANGL_VEL, |
799 | .modified = 1, | 778 | .modified = 1, |
800 | .channel2 = IIO_MOD_Z, | 779 | .channel2 = IIO_MOD_Z, |
801 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 780 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
802 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 781 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
803 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 782 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
804 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 783 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
805 | .address = gyro_z, | 784 | .address = gyro_z, |
806 | .scan_index = ADIS16400_SCAN_GYRO_Z, | 785 | .scan_index = ADIS16400_SCAN_GYRO_Z, |
807 | .scan_type = IIO_ST('s', 14, 16, 0), | 786 | .scan_type = IIO_ST('s', 14, 16, 0), |
808 | }, { | 787 | }, { |
809 | .type = IIO_ACCEL, | 788 | .type = IIO_ACCEL, |
810 | .modified = 1, | 789 | .modified = 1, |
811 | .channel2 = IIO_MOD_X, | 790 | .channel2 = IIO_MOD_X, |
812 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 791 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
813 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 792 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
814 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 793 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
815 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 794 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
816 | .address = accel_x, | 795 | .address = accel_x, |
817 | .scan_index = ADIS16400_SCAN_ACC_X, | 796 | .scan_index = ADIS16400_SCAN_ACC_X, |
818 | .scan_type = IIO_ST('s', 14, 16, 0), | 797 | .scan_type = IIO_ST('s', 14, 16, 0), |
819 | }, { | 798 | }, { |
820 | .type = IIO_ACCEL, | 799 | .type = IIO_ACCEL, |
821 | .modified = 1, | 800 | .modified = 1, |
822 | .channel2 = IIO_MOD_Y, | 801 | .channel2 = IIO_MOD_Y, |
823 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 802 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
824 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 803 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
825 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 804 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
826 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 805 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
827 | .address = accel_y, | 806 | .address = accel_y, |
828 | .scan_index = ADIS16400_SCAN_ACC_Y, | 807 | .scan_index = ADIS16400_SCAN_ACC_Y, |
829 | .scan_type = IIO_ST('s', 14, 16, 0), | 808 | .scan_type = IIO_ST('s', 14, 16, 0), |
830 | }, { | 809 | }, { |
831 | .type = IIO_ACCEL, | 810 | .type = IIO_ACCEL, |
832 | .modified = 1, | 811 | .modified = 1, |
833 | .channel2 = IIO_MOD_Z, | 812 | .channel2 = IIO_MOD_Z, |
834 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 813 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
835 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 814 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
836 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 815 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
837 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 816 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
838 | .address = accel_z, | 817 | .address = accel_z, |
839 | .scan_index = ADIS16400_SCAN_ACC_Z, | 818 | .scan_index = ADIS16400_SCAN_ACC_Z, |
840 | .scan_type = IIO_ST('s', 14, 16, 0), | 819 | .scan_type = IIO_ST('s', 14, 16, 0), |
841 | }, { | 820 | }, { |
842 | .type = IIO_TEMP, | 821 | .type = IIO_TEMP, |
843 | .indexed = 1, | 822 | .indexed = 1, |
844 | .channel = 0, | 823 | .channel = 0, |
845 | .extend_name = "x", | 824 | .extend_name = "x", |
846 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 825 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
847 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | | 826 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | |
848 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | | 827 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | |
849 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 828 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
850 | .address = temp0, | 829 | .address = temp0, |
851 | .scan_index = ADIS16350_SCAN_TEMP_X, | 830 | .scan_index = ADIS16350_SCAN_TEMP_X, |
852 | .scan_type = IIO_ST('s', 12, 16, 0), | 831 | .scan_type = IIO_ST('s', 12, 16, 0), |
853 | }, { | 832 | }, { |
854 | .type = IIO_TEMP, | 833 | .type = IIO_TEMP, |
855 | .indexed = 1, | 834 | .indexed = 1, |
856 | .channel = 1, | 835 | .channel = 1, |
857 | .extend_name = "y", | 836 | .extend_name = "y", |
858 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 837 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
859 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | | 838 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | |
860 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | | 839 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | |
861 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 840 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
862 | .address = temp1, | 841 | .address = temp1, |
863 | .scan_index = ADIS16350_SCAN_TEMP_Y, | 842 | .scan_index = ADIS16350_SCAN_TEMP_Y, |
864 | .scan_type = IIO_ST('s', 12, 16, 0), | 843 | .scan_type = IIO_ST('s', 12, 16, 0), |
865 | }, { | 844 | }, { |
866 | .type = IIO_TEMP, | 845 | .type = IIO_TEMP, |
867 | .indexed = 1, | 846 | .indexed = 1, |
868 | .channel = 2, | 847 | .channel = 2, |
869 | .extend_name = "z", | 848 | .extend_name = "z", |
870 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 849 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
871 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | | 850 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | |
872 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 851 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
873 | .address = temp2, | 852 | .address = temp2, |
874 | .scan_index = ADIS16350_SCAN_TEMP_Z, | 853 | .scan_index = ADIS16350_SCAN_TEMP_Z, |
875 | .scan_type = IIO_ST('s', 12, 16, 0), | 854 | .scan_type = IIO_ST('s', 12, 16, 0), |
876 | }, { | 855 | }, { |
877 | .type = IIO_VOLTAGE, | 856 | .type = IIO_VOLTAGE, |
878 | .indexed = 1, | 857 | .indexed = 1, |
879 | .channel = 1, | 858 | .channel = 1, |
880 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 859 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
881 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 860 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
882 | .address = in1, | 861 | .address = in1, |
883 | .scan_index = ADIS16350_SCAN_ADC_0, | 862 | .scan_index = ADIS16350_SCAN_ADC_0, |
884 | .scan_type = IIO_ST('s', 12, 16, 0), | 863 | .scan_type = IIO_ST('s', 12, 16, 0), |
885 | }, | 864 | }, |
886 | IIO_CHAN_SOFT_TIMESTAMP(11) | 865 | IIO_CHAN_SOFT_TIMESTAMP(11) |
887 | }; | 866 | }; |
888 | 867 | ||
889 | static struct iio_chan_spec adis16300_channels[] = { | 868 | static struct iio_chan_spec adis16300_channels[] = { |
890 | { | 869 | { |
891 | .type = IIO_VOLTAGE, | 870 | .type = IIO_VOLTAGE, |
892 | .indexed = 1, | 871 | .indexed = 1, |
893 | .channel = 0, | 872 | .channel = 0, |
894 | .extend_name = "supply", | 873 | .extend_name = "supply", |
895 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 874 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
896 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 875 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
897 | .address = in_supply, | 876 | .address = in_supply, |
898 | .scan_index = ADIS16400_SCAN_SUPPLY, | 877 | .scan_index = ADIS16400_SCAN_SUPPLY, |
899 | .scan_type = IIO_ST('u', 12, 16, 0) | 878 | .scan_type = IIO_ST('u', 12, 16, 0) |
900 | }, { | 879 | }, { |
901 | .type = IIO_ANGL_VEL, | 880 | .type = IIO_ANGL_VEL, |
902 | .modified = 1, | 881 | .modified = 1, |
903 | .channel2 = IIO_MOD_X, | 882 | .channel2 = IIO_MOD_X, |
904 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 883 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
905 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 884 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
906 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 885 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
907 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 886 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
908 | .address = gyro_x, | 887 | .address = gyro_x, |
909 | .scan_index = ADIS16400_SCAN_GYRO_X, | 888 | .scan_index = ADIS16400_SCAN_GYRO_X, |
910 | .scan_type = IIO_ST('s', 14, 16, 0), | 889 | .scan_type = IIO_ST('s', 14, 16, 0), |
911 | }, { | 890 | }, { |
912 | .type = IIO_ACCEL, | 891 | .type = IIO_ACCEL, |
913 | .modified = 1, | 892 | .modified = 1, |
914 | .channel2 = IIO_MOD_X, | 893 | .channel2 = IIO_MOD_X, |
915 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 894 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
916 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 895 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
917 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 896 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
918 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 897 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
919 | .address = accel_x, | 898 | .address = accel_x, |
920 | .scan_index = ADIS16400_SCAN_ACC_X, | 899 | .scan_index = ADIS16400_SCAN_ACC_X, |
921 | .scan_type = IIO_ST('s', 14, 16, 0), | 900 | .scan_type = IIO_ST('s', 14, 16, 0), |
922 | }, { | 901 | }, { |
923 | .type = IIO_ACCEL, | 902 | .type = IIO_ACCEL, |
924 | .modified = 1, | 903 | .modified = 1, |
925 | .channel2 = IIO_MOD_Y, | 904 | .channel2 = IIO_MOD_Y, |
926 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 905 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
927 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 906 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
928 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 907 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
929 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 908 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
930 | .address = accel_y, | 909 | .address = accel_y, |
931 | .scan_index = ADIS16400_SCAN_ACC_Y, | 910 | .scan_index = ADIS16400_SCAN_ACC_Y, |
932 | .scan_type = IIO_ST('s', 14, 16, 0), | 911 | .scan_type = IIO_ST('s', 14, 16, 0), |
933 | }, { | 912 | }, { |
934 | .type = IIO_ACCEL, | 913 | .type = IIO_ACCEL, |
935 | .modified = 1, | 914 | .modified = 1, |
936 | .channel2 = IIO_MOD_Z, | 915 | .channel2 = IIO_MOD_Z, |
937 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 916 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
938 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 917 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
939 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 918 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
940 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 919 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
941 | .address = accel_z, | 920 | .address = accel_z, |
942 | .scan_index = ADIS16400_SCAN_ACC_Z, | 921 | .scan_index = ADIS16400_SCAN_ACC_Z, |
943 | .scan_type = IIO_ST('s', 14, 16, 0), | 922 | .scan_type = IIO_ST('s', 14, 16, 0), |
944 | }, { | 923 | }, { |
945 | .type = IIO_TEMP, | 924 | .type = IIO_TEMP, |
946 | .indexed = 1, | 925 | .indexed = 1, |
947 | .channel = 0, | 926 | .channel = 0, |
948 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 927 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
949 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | | 928 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | |
950 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 929 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
951 | .address = temp0, | 930 | .address = temp0, |
952 | .scan_index = ADIS16400_SCAN_TEMP, | 931 | .scan_index = ADIS16400_SCAN_TEMP, |
953 | .scan_type = IIO_ST('s', 12, 16, 0), | 932 | .scan_type = IIO_ST('s', 12, 16, 0), |
954 | }, { | 933 | }, { |
955 | .type = IIO_VOLTAGE, | 934 | .type = IIO_VOLTAGE, |
956 | .indexed = 1, | 935 | .indexed = 1, |
957 | .channel = 1, | 936 | .channel = 1, |
958 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 937 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
959 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, | 938 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, |
960 | .address = in1, | 939 | .address = in1, |
961 | .scan_index = ADIS16350_SCAN_ADC_0, | 940 | .scan_index = ADIS16350_SCAN_ADC_0, |
962 | .scan_type = IIO_ST('s', 12, 16, 0), | 941 | .scan_type = IIO_ST('s', 12, 16, 0), |
963 | }, { | 942 | }, { |
964 | .type = IIO_INCLI, | 943 | .type = IIO_INCLI, |
965 | .modified = 1, | 944 | .modified = 1, |
966 | .channel2 = IIO_MOD_X, | 945 | .channel2 = IIO_MOD_X, |
967 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 946 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
968 | IIO_CHAN_INFO_SCALE_SHARED_BIT, | 947 | IIO_CHAN_INFO_SCALE_SHARED_BIT, |
969 | .address = incli_x, | 948 | .address = incli_x, |
970 | .scan_index = ADIS16300_SCAN_INCLI_X, | 949 | .scan_index = ADIS16300_SCAN_INCLI_X, |
971 | .scan_type = IIO_ST('s', 13, 16, 0), | 950 | .scan_type = IIO_ST('s', 13, 16, 0), |
972 | }, { | 951 | }, { |
973 | .type = IIO_INCLI, | 952 | .type = IIO_INCLI, |
974 | .modified = 1, | 953 | .modified = 1, |
975 | .channel2 = IIO_MOD_Y, | 954 | .channel2 = IIO_MOD_Y, |
976 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 955 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
977 | IIO_CHAN_INFO_SCALE_SHARED_BIT, | 956 | IIO_CHAN_INFO_SCALE_SHARED_BIT, |
978 | .address = incli_y, | 957 | .address = incli_y, |
979 | .scan_index = ADIS16300_SCAN_INCLI_Y, | 958 | .scan_index = ADIS16300_SCAN_INCLI_Y, |
980 | .scan_type = IIO_ST('s', 13, 16, 0), | 959 | .scan_type = IIO_ST('s', 13, 16, 0), |
981 | }, | 960 | }, |
982 | IIO_CHAN_SOFT_TIMESTAMP(14) | 961 | IIO_CHAN_SOFT_TIMESTAMP(14) |
983 | }; | 962 | }; |
984 | 963 | ||
985 | static const struct iio_chan_spec adis16334_channels[] = { | 964 | static const struct iio_chan_spec adis16334_channels[] = { |
986 | { | 965 | { |
987 | .type = IIO_ANGL_VEL, | 966 | .type = IIO_ANGL_VEL, |
988 | .modified = 1, | 967 | .modified = 1, |
989 | .channel2 = IIO_MOD_X, | 968 | .channel2 = IIO_MOD_X, |
990 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 969 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
991 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 970 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
992 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 971 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
993 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 972 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
994 | .address = gyro_x, | 973 | .address = gyro_x, |
995 | .scan_index = ADIS16400_SCAN_GYRO_X, | 974 | .scan_index = ADIS16400_SCAN_GYRO_X, |
996 | .scan_type = IIO_ST('s', 14, 16, 0), | 975 | .scan_type = IIO_ST('s', 14, 16, 0), |
997 | }, { | 976 | }, { |
998 | .type = IIO_ANGL_VEL, | 977 | .type = IIO_ANGL_VEL, |
999 | .modified = 1, | 978 | .modified = 1, |
1000 | .channel2 = IIO_MOD_Y, | 979 | .channel2 = IIO_MOD_Y, |
1001 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 980 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
1002 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 981 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
1003 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 982 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
1004 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 983 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
1005 | .address = gyro_y, | 984 | .address = gyro_y, |
1006 | .scan_index = ADIS16400_SCAN_GYRO_Y, | 985 | .scan_index = ADIS16400_SCAN_GYRO_Y, |
1007 | .scan_type = IIO_ST('s', 14, 16, 0), | 986 | .scan_type = IIO_ST('s', 14, 16, 0), |
1008 | }, { | 987 | }, { |
1009 | .type = IIO_ANGL_VEL, | 988 | .type = IIO_ANGL_VEL, |
1010 | .modified = 1, | 989 | .modified = 1, |
1011 | .channel2 = IIO_MOD_Z, | 990 | .channel2 = IIO_MOD_Z, |
1012 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 991 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
1013 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 992 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
1014 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 993 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
1015 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 994 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
1016 | .address = gyro_z, | 995 | .address = gyro_z, |
1017 | .scan_index = ADIS16400_SCAN_GYRO_Z, | 996 | .scan_index = ADIS16400_SCAN_GYRO_Z, |
1018 | .scan_type = IIO_ST('s', 14, 16, 0), | 997 | .scan_type = IIO_ST('s', 14, 16, 0), |
1019 | }, { | 998 | }, { |
1020 | .type = IIO_ACCEL, | 999 | .type = IIO_ACCEL, |
1021 | .modified = 1, | 1000 | .modified = 1, |
1022 | .channel2 = IIO_MOD_X, | 1001 | .channel2 = IIO_MOD_X, |
1023 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 1002 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
1024 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 1003 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
1025 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 1004 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
1026 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 1005 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
1027 | .address = accel_x, | 1006 | .address = accel_x, |
1028 | .scan_index = ADIS16400_SCAN_ACC_X, | 1007 | .scan_index = ADIS16400_SCAN_ACC_X, |
1029 | .scan_type = IIO_ST('s', 14, 16, 0), | 1008 | .scan_type = IIO_ST('s', 14, 16, 0), |
1030 | }, { | 1009 | }, { |
1031 | .type = IIO_ACCEL, | 1010 | .type = IIO_ACCEL, |
1032 | .modified = 1, | 1011 | .modified = 1, |
1033 | .channel2 = IIO_MOD_Y, | 1012 | .channel2 = IIO_MOD_Y, |
1034 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 1013 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
1035 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 1014 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
1036 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 1015 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
1037 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 1016 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
1038 | .address = accel_y, | 1017 | .address = accel_y, |
1039 | .scan_index = ADIS16400_SCAN_ACC_Y, | 1018 | .scan_index = ADIS16400_SCAN_ACC_Y, |
1040 | .scan_type = IIO_ST('s', 14, 16, 0), | 1019 | .scan_type = IIO_ST('s', 14, 16, 0), |
1041 | }, { | 1020 | }, { |
1042 | .type = IIO_ACCEL, | 1021 | .type = IIO_ACCEL, |
1043 | .modified = 1, | 1022 | .modified = 1, |
1044 | .channel2 = IIO_MOD_Z, | 1023 | .channel2 = IIO_MOD_Z, |
1045 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 1024 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
1046 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 1025 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
1047 | IIO_CHAN_INFO_SCALE_SHARED_BIT | | 1026 | IIO_CHAN_INFO_SCALE_SHARED_BIT | |
1048 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, | 1027 | IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT, |
1049 | .address = accel_z, | 1028 | .address = accel_z, |
1050 | .scan_index = ADIS16400_SCAN_ACC_Z, | 1029 | .scan_index = ADIS16400_SCAN_ACC_Z, |
1051 | .scan_type = IIO_ST('s', 14, 16, 0), | 1030 | .scan_type = IIO_ST('s', 14, 16, 0), |
1052 | }, { | 1031 | }, { |
1053 | .type = IIO_TEMP, | 1032 | .type = IIO_TEMP, |
1054 | .indexed = 1, | 1033 | .indexed = 1, |
1055 | .channel = 0, | 1034 | .channel = 0, |
1056 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | | 1035 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | |
1057 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | | 1036 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT | |
1058 | IIO_CHAN_INFO_SCALE_SHARED_BIT, | 1037 | IIO_CHAN_INFO_SCALE_SHARED_BIT, |
1059 | .address = temp0, | 1038 | .address = temp0, |
1060 | .scan_index = ADIS16400_SCAN_TEMP, | 1039 | .scan_index = ADIS16400_SCAN_TEMP, |
1061 | .scan_type = IIO_ST('s', 14, 16, 0), | 1040 | .scan_type = IIO_ST('s', 14, 16, 0), |
1062 | }, | 1041 | }, |
1063 | IIO_CHAN_SOFT_TIMESTAMP(12) | 1042 | IIO_CHAN_SOFT_TIMESTAMP(12) |
1064 | }; | 1043 | }; |
1065 | 1044 | ||
1066 | static struct attribute *adis16400_attributes[] = { | 1045 | static struct attribute *adis16400_attributes[] = { |
1067 | &iio_dev_attr_sampling_frequency.dev_attr.attr, | 1046 | &iio_dev_attr_sampling_frequency.dev_attr.attr, |
1068 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, | 1047 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, |
1069 | &iio_dev_attr_reset.dev_attr.attr, | ||
1070 | NULL | 1048 | NULL |
1071 | }; | 1049 | }; |
1072 | 1050 | ||
1073 | static const struct attribute_group adis16400_attribute_group = { | 1051 | static const struct attribute_group adis16400_attribute_group = { |
1074 | .attrs = adis16400_attributes, | 1052 | .attrs = adis16400_attributes, |
1075 | }; | 1053 | }; |
1076 | 1054 | ||
1077 | static struct adis16400_chip_info adis16400_chips[] = { | 1055 | static struct adis16400_chip_info adis16400_chips[] = { |
1078 | [ADIS16300] = { | 1056 | [ADIS16300] = { |
1079 | .channels = adis16300_channels, | 1057 | .channels = adis16300_channels, |
1080 | .num_channels = ARRAY_SIZE(adis16300_channels), | 1058 | .num_channels = ARRAY_SIZE(adis16300_channels), |
1081 | .gyro_scale_micro = 873, | 1059 | .gyro_scale_micro = 873, |
1082 | .accel_scale_micro = 5884, | 1060 | .accel_scale_micro = 5884, |
1083 | .default_scan_mask = (1 << ADIS16400_SCAN_SUPPLY) | | 1061 | .default_scan_mask = (1 << ADIS16400_SCAN_SUPPLY) | |
1084 | (1 << ADIS16400_SCAN_GYRO_X) | (1 << ADIS16400_SCAN_ACC_X) | | 1062 | (1 << ADIS16400_SCAN_GYRO_X) | (1 << ADIS16400_SCAN_ACC_X) | |
1085 | (1 << ADIS16400_SCAN_ACC_Y) | (1 << ADIS16400_SCAN_ACC_Z) | | 1063 | (1 << ADIS16400_SCAN_ACC_Y) | (1 << ADIS16400_SCAN_ACC_Z) | |
1086 | (1 << ADIS16400_SCAN_TEMP) | (1 << ADIS16400_SCAN_ADC_0) | | 1064 | (1 << ADIS16400_SCAN_TEMP) | (1 << ADIS16400_SCAN_ADC_0) | |
1087 | (1 << ADIS16300_SCAN_INCLI_X) | (1 << ADIS16300_SCAN_INCLI_Y) | | 1065 | (1 << ADIS16300_SCAN_INCLI_X) | (1 << ADIS16300_SCAN_INCLI_Y) | |
1088 | (1 << 14), | 1066 | (1 << 14), |
1089 | }, | 1067 | }, |
1090 | [ADIS16334] = { | 1068 | [ADIS16334] = { |
1091 | .channels = adis16334_channels, | 1069 | .channels = adis16334_channels, |
1092 | .num_channels = ARRAY_SIZE(adis16334_channels), | 1070 | .num_channels = ARRAY_SIZE(adis16334_channels), |
1093 | .gyro_scale_micro = 873, | 1071 | .gyro_scale_micro = 873, |
1094 | .accel_scale_micro = 981, | 1072 | .accel_scale_micro = 981, |
1095 | .default_scan_mask = (1 << ADIS16400_SCAN_GYRO_X) | | 1073 | .default_scan_mask = (1 << ADIS16400_SCAN_GYRO_X) | |
1096 | (1 << ADIS16400_SCAN_GYRO_Y) | (1 << ADIS16400_SCAN_GYRO_Z) | | 1074 | (1 << ADIS16400_SCAN_GYRO_Y) | (1 << ADIS16400_SCAN_GYRO_Z) | |
1097 | (1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) | | 1075 | (1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) | |
1098 | (1 << ADIS16400_SCAN_ACC_Z), | 1076 | (1 << ADIS16400_SCAN_ACC_Z), |
1099 | }, | 1077 | }, |
1100 | [ADIS16350] = { | 1078 | [ADIS16350] = { |
1101 | .channels = adis16350_channels, | 1079 | .channels = adis16350_channels, |
1102 | .num_channels = ARRAY_SIZE(adis16350_channels), | 1080 | .num_channels = ARRAY_SIZE(adis16350_channels), |
1103 | .gyro_scale_micro = 872664, | 1081 | .gyro_scale_micro = 872664, |
1104 | .accel_scale_micro = 24732, | 1082 | .accel_scale_micro = 24732, |
1105 | .default_scan_mask = 0x7FF, | 1083 | .default_scan_mask = 0x7FF, |
1106 | .flags = ADIS16400_NO_BURST, | 1084 | .flags = ADIS16400_NO_BURST, |
1107 | }, | 1085 | }, |
1108 | [ADIS16360] = { | 1086 | [ADIS16360] = { |
1109 | .channels = adis16350_channels, | 1087 | .channels = adis16350_channels, |
1110 | .num_channels = ARRAY_SIZE(adis16350_channels), | 1088 | .num_channels = ARRAY_SIZE(adis16350_channels), |
1111 | .flags = ADIS16400_HAS_PROD_ID, | 1089 | .flags = ADIS16400_HAS_PROD_ID, |
1112 | .product_id = 0x3FE8, | 1090 | .product_id = 0x3FE8, |
1113 | .gyro_scale_micro = 1279, | 1091 | .gyro_scale_micro = 1279, |
1114 | .accel_scale_micro = 24732, | 1092 | .accel_scale_micro = 24732, |
1115 | .default_scan_mask = 0x7FF, | 1093 | .default_scan_mask = 0x7FF, |
1116 | }, | 1094 | }, |
1117 | [ADIS16362] = { | 1095 | [ADIS16362] = { |
1118 | .channels = adis16350_channels, | 1096 | .channels = adis16350_channels, |
1119 | .num_channels = ARRAY_SIZE(adis16350_channels), | 1097 | .num_channels = ARRAY_SIZE(adis16350_channels), |
1120 | .flags = ADIS16400_HAS_PROD_ID, | 1098 | .flags = ADIS16400_HAS_PROD_ID, |
1121 | .product_id = 0x3FEA, | 1099 | .product_id = 0x3FEA, |
1122 | .gyro_scale_micro = 1279, | 1100 | .gyro_scale_micro = 1279, |
1123 | .accel_scale_micro = 24732, | 1101 | .accel_scale_micro = 24732, |
1124 | .default_scan_mask = 0x7FF, | 1102 | .default_scan_mask = 0x7FF, |
1125 | }, | 1103 | }, |
1126 | [ADIS16364] = { | 1104 | [ADIS16364] = { |
1127 | .channels = adis16350_channels, | 1105 | .channels = adis16350_channels, |
1128 | .num_channels = ARRAY_SIZE(adis16350_channels), | 1106 | .num_channels = ARRAY_SIZE(adis16350_channels), |
1129 | .flags = ADIS16400_HAS_PROD_ID, | 1107 | .flags = ADIS16400_HAS_PROD_ID, |
1130 | .product_id = 0x3FEC, | 1108 | .product_id = 0x3FEC, |
1131 | .gyro_scale_micro = 1279, | 1109 | .gyro_scale_micro = 1279, |
1132 | .accel_scale_micro = 24732, | 1110 | .accel_scale_micro = 24732, |
1133 | .default_scan_mask = 0x7FF, | 1111 | .default_scan_mask = 0x7FF, |
1134 | }, | 1112 | }, |
1135 | [ADIS16365] = { | 1113 | [ADIS16365] = { |
1136 | .channels = adis16350_channels, | 1114 | .channels = adis16350_channels, |
1137 | .num_channels = ARRAY_SIZE(adis16350_channels), | 1115 | .num_channels = ARRAY_SIZE(adis16350_channels), |
1138 | .flags = ADIS16400_HAS_PROD_ID, | 1116 | .flags = ADIS16400_HAS_PROD_ID, |
1139 | .product_id = 0x3FED, | 1117 | .product_id = 0x3FED, |
1140 | .gyro_scale_micro = 1279, | 1118 | .gyro_scale_micro = 1279, |
1141 | .accel_scale_micro = 24732, | 1119 | .accel_scale_micro = 24732, |
1142 | .default_scan_mask = 0x7FF, | 1120 | .default_scan_mask = 0x7FF, |
1143 | }, | 1121 | }, |
1144 | [ADIS16400] = { | 1122 | [ADIS16400] = { |
1145 | .channels = adis16400_channels, | 1123 | .channels = adis16400_channels, |
1146 | .num_channels = ARRAY_SIZE(adis16400_channels), | 1124 | .num_channels = ARRAY_SIZE(adis16400_channels), |
1147 | .flags = ADIS16400_HAS_PROD_ID, | 1125 | .flags = ADIS16400_HAS_PROD_ID, |
1148 | .product_id = 0x4015, | 1126 | .product_id = 0x4015, |
1149 | .gyro_scale_micro = 873, | 1127 | .gyro_scale_micro = 873, |
1150 | .accel_scale_micro = 32656, | 1128 | .accel_scale_micro = 32656, |
1151 | .default_scan_mask = 0xFFF, | 1129 | .default_scan_mask = 0xFFF, |
1152 | } | 1130 | } |
1153 | }; | 1131 | }; |
1154 | 1132 | ||
1155 | static const struct iio_info adis16400_info = { | 1133 | static const struct iio_info adis16400_info = { |
1156 | .driver_module = THIS_MODULE, | 1134 | .driver_module = THIS_MODULE, |
1157 | .read_raw = &adis16400_read_raw, | 1135 | .read_raw = &adis16400_read_raw, |
1158 | .write_raw = &adis16400_write_raw, | 1136 | .write_raw = &adis16400_write_raw, |
1159 | .attrs = &adis16400_attribute_group, | 1137 | .attrs = &adis16400_attribute_group, |
1160 | }; | 1138 | }; |
1161 | 1139 | ||
1162 | static int __devinit adis16400_probe(struct spi_device *spi) | 1140 | static int __devinit adis16400_probe(struct spi_device *spi) |
1163 | { | 1141 | { |
1164 | int ret; | 1142 | int ret; |
1165 | struct adis16400_state *st; | 1143 | struct adis16400_state *st; |
1166 | struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st)); | 1144 | struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st)); |
1167 | if (indio_dev == NULL) { | 1145 | if (indio_dev == NULL) { |
1168 | ret = -ENOMEM; | 1146 | ret = -ENOMEM; |
1169 | goto error_ret; | 1147 | goto error_ret; |
1170 | } | 1148 | } |
1171 | st = iio_priv(indio_dev); | 1149 | st = iio_priv(indio_dev); |
1172 | /* this is only used for removal purposes */ | 1150 | /* this is only used for removal purposes */ |
1173 | spi_set_drvdata(spi, indio_dev); | 1151 | spi_set_drvdata(spi, indio_dev); |
1174 | 1152 | ||
1175 | st->us = spi; | 1153 | st->us = spi; |
1176 | mutex_init(&st->buf_lock); | 1154 | mutex_init(&st->buf_lock); |
1177 | 1155 | ||
1178 | /* setup the industrialio driver allocated elements */ | 1156 | /* setup the industrialio driver allocated elements */ |
1179 | st->variant = &adis16400_chips[spi_get_device_id(spi)->driver_data]; | 1157 | st->variant = &adis16400_chips[spi_get_device_id(spi)->driver_data]; |
1180 | indio_dev->dev.parent = &spi->dev; | 1158 | indio_dev->dev.parent = &spi->dev; |
1181 | indio_dev->name = spi_get_device_id(spi)->name; | 1159 | indio_dev->name = spi_get_device_id(spi)->name; |
1182 | indio_dev->channels = st->variant->channels; | 1160 | indio_dev->channels = st->variant->channels; |
1183 | indio_dev->num_channels = st->variant->num_channels; | 1161 | indio_dev->num_channels = st->variant->num_channels; |
1184 | indio_dev->info = &adis16400_info; | 1162 | indio_dev->info = &adis16400_info; |
1185 | indio_dev->modes = INDIO_DIRECT_MODE; | 1163 | indio_dev->modes = INDIO_DIRECT_MODE; |
1186 | 1164 | ||
1187 | ret = adis16400_configure_ring(indio_dev); | 1165 | ret = adis16400_configure_ring(indio_dev); |
1188 | if (ret) | 1166 | if (ret) |
1189 | goto error_free_dev; | 1167 | goto error_free_dev; |
1190 | 1168 | ||
1191 | ret = iio_buffer_register(indio_dev, | 1169 | ret = iio_buffer_register(indio_dev, |
1192 | st->variant->channels, | 1170 | st->variant->channels, |
1193 | st->variant->num_channels); | 1171 | st->variant->num_channels); |
1194 | if (ret) { | 1172 | if (ret) { |
1195 | dev_err(&spi->dev, "failed to initialize the ring\n"); | 1173 | dev_err(&spi->dev, "failed to initialize the ring\n"); |
1196 | goto error_unreg_ring_funcs; | 1174 | goto error_unreg_ring_funcs; |
1197 | } | 1175 | } |
1198 | 1176 | ||
1199 | if (spi->irq) { | 1177 | if (spi->irq) { |
1200 | ret = adis16400_probe_trigger(indio_dev); | 1178 | ret = adis16400_probe_trigger(indio_dev); |
1201 | if (ret) | 1179 | if (ret) |
1202 | goto error_uninitialize_ring; | 1180 | goto error_uninitialize_ring; |
1203 | } | 1181 | } |
1204 | 1182 | ||
1205 | /* Get the device into a sane initial state */ | 1183 | /* Get the device into a sane initial state */ |
1206 | ret = adis16400_initial_setup(indio_dev); | 1184 | ret = adis16400_initial_setup(indio_dev); |
1207 | if (ret) | 1185 | if (ret) |
1208 | goto error_remove_trigger; | 1186 | goto error_remove_trigger; |
1209 | ret = iio_device_register(indio_dev); | 1187 | ret = iio_device_register(indio_dev); |
1210 | if (ret) | 1188 | if (ret) |
1211 | goto error_remove_trigger; | 1189 | goto error_remove_trigger; |
1212 | 1190 | ||
1213 | return 0; | 1191 | return 0; |
1214 | 1192 | ||
1215 | error_remove_trigger: | 1193 | error_remove_trigger: |
1216 | if (spi->irq) | 1194 | if (spi->irq) |
1217 | adis16400_remove_trigger(indio_dev); | 1195 | adis16400_remove_trigger(indio_dev); |
1218 | error_uninitialize_ring: | 1196 | error_uninitialize_ring: |
1219 | iio_buffer_unregister(indio_dev); | 1197 | iio_buffer_unregister(indio_dev); |
1220 | error_unreg_ring_funcs: | 1198 | error_unreg_ring_funcs: |
1221 | adis16400_unconfigure_ring(indio_dev); | 1199 | adis16400_unconfigure_ring(indio_dev); |
1222 | error_free_dev: | 1200 | error_free_dev: |
1223 | iio_device_free(indio_dev); | 1201 | iio_device_free(indio_dev); |
1224 | error_ret: | 1202 | error_ret: |
1225 | return ret; | 1203 | return ret; |
1226 | } | 1204 | } |
1227 | 1205 | ||
1228 | /* fixme, confirm ordering in this function */ | 1206 | /* fixme, confirm ordering in this function */ |
1229 | static int adis16400_remove(struct spi_device *spi) | 1207 | static int adis16400_remove(struct spi_device *spi) |
1230 | { | 1208 | { |
1231 | int ret; | 1209 | int ret; |
1232 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | 1210 | struct iio_dev *indio_dev = spi_get_drvdata(spi); |
1233 | 1211 | ||
1234 | iio_device_unregister(indio_dev); | 1212 | iio_device_unregister(indio_dev); |
1235 | ret = adis16400_stop_device(indio_dev); | 1213 | ret = adis16400_stop_device(indio_dev); |
1236 | if (ret) | 1214 | if (ret) |
1237 | goto err_ret; | 1215 | goto err_ret; |
1238 | 1216 | ||
1239 | adis16400_remove_trigger(indio_dev); | 1217 | adis16400_remove_trigger(indio_dev); |
1240 | iio_buffer_unregister(indio_dev); | 1218 | iio_buffer_unregister(indio_dev); |
1241 | adis16400_unconfigure_ring(indio_dev); | 1219 | adis16400_unconfigure_ring(indio_dev); |
1242 | iio_device_free(indio_dev); | 1220 | iio_device_free(indio_dev); |
1243 | 1221 | ||
1244 | return 0; | 1222 | return 0; |
1245 | 1223 | ||
1246 | err_ret: | 1224 | err_ret: |
1247 | return ret; | 1225 | return ret; |
1248 | } | 1226 | } |
1249 | 1227 | ||
1250 | static const struct spi_device_id adis16400_id[] = { | 1228 | static const struct spi_device_id adis16400_id[] = { |
1251 | {"adis16300", ADIS16300}, | 1229 | {"adis16300", ADIS16300}, |
1252 | {"adis16334", ADIS16334}, | 1230 | {"adis16334", ADIS16334}, |
1253 | {"adis16350", ADIS16350}, | 1231 | {"adis16350", ADIS16350}, |
1254 | {"adis16354", ADIS16350}, | 1232 | {"adis16354", ADIS16350}, |
1255 | {"adis16355", ADIS16350}, | 1233 | {"adis16355", ADIS16350}, |
1256 | {"adis16360", ADIS16360}, | 1234 | {"adis16360", ADIS16360}, |
1257 | {"adis16362", ADIS16362}, | 1235 | {"adis16362", ADIS16362}, |
1258 | {"adis16364", ADIS16364}, | 1236 | {"adis16364", ADIS16364}, |
1259 | {"adis16365", ADIS16365}, | 1237 | {"adis16365", ADIS16365}, |
1260 | {"adis16400", ADIS16400}, | 1238 | {"adis16400", ADIS16400}, |
1261 | {"adis16405", ADIS16400}, | 1239 | {"adis16405", ADIS16400}, |
1262 | {} | 1240 | {} |
1263 | }; | 1241 | }; |
1264 | MODULE_DEVICE_TABLE(spi, adis16400_id); | 1242 | MODULE_DEVICE_TABLE(spi, adis16400_id); |
1265 | 1243 | ||
1266 | static struct spi_driver adis16400_driver = { | 1244 | static struct spi_driver adis16400_driver = { |
1267 | .driver = { | 1245 | .driver = { |
1268 | .name = "adis16400", | 1246 | .name = "adis16400", |
1269 | .owner = THIS_MODULE, | 1247 | .owner = THIS_MODULE, |
1270 | }, | 1248 | }, |
1271 | .id_table = adis16400_id, | 1249 | .id_table = adis16400_id, |
1272 | .probe = adis16400_probe, | 1250 | .probe = adis16400_probe, |
1273 | .remove = __devexit_p(adis16400_remove), | 1251 | .remove = __devexit_p(adis16400_remove), |
1274 | }; | 1252 | }; |
1275 | module_spi_driver(adis16400_driver); | 1253 | module_spi_driver(adis16400_driver); |
1276 | 1254 | ||
1277 | MODULE_AUTHOR("Manuel Stahl <manuel.stahl@iis.fraunhofer.de>"); | 1255 | MODULE_AUTHOR("Manuel Stahl <manuel.stahl@iis.fraunhofer.de>"); |
1278 | MODULE_DESCRIPTION("Analog Devices ADIS16400/5 IMU SPI driver"); | 1256 | MODULE_DESCRIPTION("Analog Devices ADIS16400/5 IMU SPI driver"); |
1279 | MODULE_LICENSE("GPL v2"); | 1257 | MODULE_LICENSE("GPL v2"); |
1280 | 1258 |
include/linux/iio/consumer.h
1 | /* | 1 | /* |
2 | * Industrial I/O in kernel consumer interface | 2 | * Industrial I/O in kernel consumer interface |
3 | * | 3 | * |
4 | * Copyright (c) 2011 Jonathan Cameron | 4 | * Copyright (c) 2011 Jonathan Cameron |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License version 2 as published by | 7 | * under the terms of the GNU General Public License version 2 as published by |
8 | * the Free Software Foundation. | 8 | * the Free Software Foundation. |
9 | */ | 9 | */ |
10 | #ifndef _IIO_INKERN_CONSUMER_H_ | 10 | #ifndef _IIO_INKERN_CONSUMER_H_ |
11 | #define _IIO_INKERN_CONSUMER_H | 11 | #define _IIO_INKERN_CONSUMER_H |
12 | #include <linux/iio/types.h> | 12 | #include <linux/iio/types.h> |
13 | 13 | ||
14 | struct iio_dev; | 14 | struct iio_dev; |
15 | struct iio_chan_spec; | 15 | struct iio_chan_spec; |
16 | 16 | ||
17 | /** | 17 | /** |
18 | * struct iio_channel - everything needed for a consumer to use a channel | 18 | * struct iio_channel - everything needed for a consumer to use a channel |
19 | * @indio_dev: Device on which the channel exists. | 19 | * @indio_dev: Device on which the channel exists. |
20 | * @channel: Full description of the channel. | 20 | * @channel: Full description of the channel. |
21 | */ | 21 | */ |
22 | struct iio_channel { | 22 | struct iio_channel { |
23 | struct iio_dev *indio_dev; | 23 | struct iio_dev *indio_dev; |
24 | const struct iio_chan_spec *channel; | 24 | const struct iio_chan_spec *channel; |
25 | }; | 25 | }; |
26 | 26 | ||
27 | /** | 27 | /** |
28 | * iio_channel_get() - get description of all that is needed to access channel. | 28 | * iio_channel_get() - get description of all that is needed to access channel. |
29 | * @name: Unique name of the device as provided in the iio_map | 29 | * @name: Unique name of the device as provided in the iio_map |
30 | * with which the desired provider to consumer mapping | 30 | * with which the desired provider to consumer mapping |
31 | * was registered. | 31 | * was registered. |
32 | * @consumer_channel: Unique name to identify the channel on the consumer | 32 | * @consumer_channel: Unique name to identify the channel on the consumer |
33 | * side. This typically describes the channels use within | 33 | * side. This typically describes the channels use within |
34 | * the consumer. E.g. 'battery_voltage' | 34 | * the consumer. E.g. 'battery_voltage' |
35 | */ | 35 | */ |
36 | struct iio_channel *iio_st_channel_get(const char *name, | 36 | struct iio_channel *iio_channel_get(const char *name, |
37 | const char *consumer_channel); | 37 | const char *consumer_channel); |
38 | 38 | ||
39 | /** | 39 | /** |
40 | * iio_st_channel_release() - release channels obtained via iio_st_channel_get | 40 | * iio_channel_release() - release channels obtained via iio_channel_get |
41 | * @chan: The channel to be released. | 41 | * @chan: The channel to be released. |
42 | */ | 42 | */ |
43 | void iio_st_channel_release(struct iio_channel *chan); | 43 | void iio_channel_release(struct iio_channel *chan); |
44 | 44 | ||
45 | /** | 45 | /** |
46 | * iio_st_channel_get_all() - get all channels associated with a client | 46 | * iio_channel_get_all() - get all channels associated with a client |
47 | * @name: name of consumer device. | 47 | * @name: name of consumer device. |
48 | * | 48 | * |
49 | * Returns an array of iio_channel structures terminated with one with | 49 | * Returns an array of iio_channel structures terminated with one with |
50 | * null iio_dev pointer. | 50 | * null iio_dev pointer. |
51 | * This function is used by fairly generic consumers to get all the | 51 | * This function is used by fairly generic consumers to get all the |
52 | * channels registered as having this consumer. | 52 | * channels registered as having this consumer. |
53 | */ | 53 | */ |
54 | struct iio_channel *iio_st_channel_get_all(const char *name); | 54 | struct iio_channel *iio_channel_get_all(const char *name); |
55 | 55 | ||
56 | /** | 56 | /** |
57 | * iio_st_channel_release_all() - reverse iio_st_get_all | 57 | * iio_channel_release_all() - reverse iio_channel_get_all |
58 | * @chan: Array of channels to be released. | 58 | * @chan: Array of channels to be released. |
59 | */ | 59 | */ |
60 | void iio_st_channel_release_all(struct iio_channel *chan); | 60 | void iio_channel_release_all(struct iio_channel *chan); |
61 | 61 | ||
62 | /** | 62 | /** |
63 | * iio_st_read_channel_raw() - read from a given channel | 63 | * iio_read_channel_raw() - read from a given channel |
64 | * @channel: The channel being queried. | 64 | * @channel: The channel being queried. |
65 | * @val: Value read back. | 65 | * @val: Value read back. |
66 | * | 66 | * |
67 | * Note raw reads from iio channels are in adc counts and hence | 67 | * Note raw reads from iio channels are in adc counts and hence |
68 | * scale will need to be applied if standard units required. | 68 | * scale will need to be applied if standard units required. |
69 | */ | 69 | */ |
70 | int iio_st_read_channel_raw(struct iio_channel *chan, | 70 | int iio_read_channel_raw(struct iio_channel *chan, |
71 | int *val); | 71 | int *val); |
72 | 72 | ||
73 | /** | 73 | /** |
74 | * iio_st_get_channel_type() - get the type of a channel | 74 | * iio_get_channel_type() - get the type of a channel |
75 | * @channel: The channel being queried. | 75 | * @channel: The channel being queried. |
76 | * @type: The type of the channel. | 76 | * @type: The type of the channel. |
77 | * | 77 | * |
78 | * returns the enum iio_chan_type of the channel | 78 | * returns the enum iio_chan_type of the channel |
79 | */ | 79 | */ |
80 | int iio_st_get_channel_type(struct iio_channel *channel, | 80 | int iio_get_channel_type(struct iio_channel *channel, |
81 | enum iio_chan_type *type); | 81 | enum iio_chan_type *type); |
82 | 82 | ||
83 | /** | 83 | /** |
84 | * iio_st_read_channel_scale() - read the scale value for a channel | 84 | * iio_read_channel_scale() - read the scale value for a channel |
85 | * @channel: The channel being queried. | 85 | * @channel: The channel being queried. |
86 | * @val: First part of value read back. | 86 | * @val: First part of value read back. |
87 | * @val2: Second part of value read back. | 87 | * @val2: Second part of value read back. |
88 | * | 88 | * |
89 | * Note returns a description of what is in val and val2, such | 89 | * Note returns a description of what is in val and val2, such |
90 | * as IIO_VAL_INT_PLUS_MICRO telling us we have a value of val | 90 | * as IIO_VAL_INT_PLUS_MICRO telling us we have a value of val |
91 | * + val2/1e6 | 91 | * + val2/1e6 |
92 | */ | 92 | */ |
93 | int iio_st_read_channel_scale(struct iio_channel *chan, int *val, | 93 | int iio_read_channel_scale(struct iio_channel *chan, int *val, |
94 | int *val2); | 94 | int *val2); |
95 | 95 | ||
96 | #endif | 96 | #endif |
97 | 97 |
include/linux/iio/types.h
1 | /* industrial I/O data types needed both in and out of kernel | 1 | /* industrial I/O data types needed both in and out of kernel |
2 | * | 2 | * |
3 | * Copyright (c) 2008 Jonathan Cameron | 3 | * Copyright (c) 2008 Jonathan Cameron |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 as published by | 6 | * under the terms of the GNU General Public License version 2 as published by |
7 | * the Free Software Foundation. | 7 | * the Free Software Foundation. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #ifndef _IIO_TYPES_H_ | 10 | #ifndef _IIO_TYPES_H_ |
11 | #define _IIO_TYPES_H_ | 11 | #define _IIO_TYPES_H_ |
12 | 12 | ||
13 | enum iio_chan_type { | 13 | enum iio_chan_type { |
14 | IIO_VOLTAGE, | 14 | IIO_VOLTAGE, |
15 | IIO_CURRENT, | 15 | IIO_CURRENT, |
16 | IIO_POWER, | 16 | IIO_POWER, |
17 | IIO_ACCEL, | 17 | IIO_ACCEL, |
18 | IIO_ANGL_VEL, | 18 | IIO_ANGL_VEL, |
19 | IIO_MAGN, | 19 | IIO_MAGN, |
20 | IIO_LIGHT, | 20 | IIO_LIGHT, |
21 | IIO_INTENSITY, | 21 | IIO_INTENSITY, |
22 | IIO_PROXIMITY, | 22 | IIO_PROXIMITY, |
23 | IIO_TEMP, | 23 | IIO_TEMP, |
24 | IIO_INCLI, | 24 | IIO_INCLI, |
25 | IIO_ROT, | 25 | IIO_ROT, |
26 | IIO_ANGL, | 26 | IIO_ANGL, |
27 | IIO_TIMESTAMP, | 27 | IIO_TIMESTAMP, |
28 | IIO_CAPACITANCE, | 28 | IIO_CAPACITANCE, |
29 | IIO_ALTVOLTAGE, | 29 | IIO_ALTVOLTAGE, |
30 | }; | 30 | }; |
31 | 31 | ||
32 | enum iio_modifier { | 32 | enum iio_modifier { |
33 | IIO_NO_MOD, | 33 | IIO_NO_MOD, |
34 | IIO_MOD_X, | 34 | IIO_MOD_X, |
35 | IIO_MOD_Y, | 35 | IIO_MOD_Y, |
36 | IIO_MOD_Z, | 36 | IIO_MOD_Z, |
37 | IIO_MOD_X_AND_Y, | 37 | IIO_MOD_X_AND_Y, |
38 | IIO_MOD_X_AND_Z, | 38 | IIO_MOD_X_AND_Z, |
39 | IIO_MOD_Y_AND_Z, | 39 | IIO_MOD_Y_AND_Z, |
40 | IIO_MOD_X_AND_Y_AND_Z, | 40 | IIO_MOD_X_AND_Y_AND_Z, |
41 | IIO_MOD_X_OR_Y, | 41 | IIO_MOD_X_OR_Y, |
42 | IIO_MOD_X_OR_Z, | 42 | IIO_MOD_X_OR_Z, |
43 | IIO_MOD_Y_OR_Z, | 43 | IIO_MOD_Y_OR_Z, |
44 | IIO_MOD_X_OR_Y_OR_Z, | 44 | IIO_MOD_X_OR_Y_OR_Z, |
45 | IIO_MOD_LIGHT_BOTH, | 45 | IIO_MOD_LIGHT_BOTH, |
46 | IIO_MOD_LIGHT_IR, | 46 | IIO_MOD_LIGHT_IR, |
47 | IIO_MOD_ROOT_SUM_SQUARED_X_Y, | ||
48 | IIO_MOD_SUM_SQUARED_X_Y_Z, | ||
47 | }; | 49 | }; |
48 | 50 | ||
49 | #define IIO_VAL_INT 1 | 51 | #define IIO_VAL_INT 1 |
50 | #define IIO_VAL_INT_PLUS_MICRO 2 | 52 | #define IIO_VAL_INT_PLUS_MICRO 2 |
51 | #define IIO_VAL_INT_PLUS_NANO 3 | 53 | #define IIO_VAL_INT_PLUS_NANO 3 |
52 | #define IIO_VAL_INT_PLUS_MICRO_DB 4 | 54 | #define IIO_VAL_INT_PLUS_MICRO_DB 4 |
53 | 55 | ||
54 | #endif /* _IIO_TYPES_H_ */ | 56 | #endif /* _IIO_TYPES_H_ */ |
55 | 57 |
include/linux/platform_data/ad7266.h
File was created | 1 | /* | |
2 | * AD7266/65 SPI ADC driver | ||
3 | * | ||
4 | * Copyright 2012 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #ifndef __IIO_ADC_AD7266_H__ | ||
10 | #define __IIO_ADC_AD7266_H__ | ||
11 | |||
12 | /** | ||
13 | * enum ad7266_range - AD7266 reference voltage range | ||
14 | * @AD7266_RANGE_VREF: Device is configured for input range 0V - VREF | ||
15 | * (RANGE pin set to low) | ||
16 | * @AD7266_RANGE_2VREF: Device is configured for input range 0V - 2VREF | ||
17 | * (RANGE pin set to high) | ||
18 | */ | ||
19 | enum ad7266_range { | ||
20 | AD7266_RANGE_VREF, | ||
21 | AD7266_RANGE_2VREF, | ||
22 | }; | ||
23 | |||
24 | /** | ||
25 | * enum ad7266_mode - AD7266 sample mode | ||
26 | * @AD7266_MODE_DIFF: Device is configured for full differential mode | ||
27 | * (SGL/DIFF pin set to low, AD0 pin set to low) | ||
28 | * @AD7266_MODE_PSEUDO_DIFF: Device is configured for pseudo differential mode | ||
29 | * (SGL/DIFF pin set to low, AD0 pin set to high) | ||
30 | * @AD7266_MODE_SINGLE_ENDED: Device is configured for single-ended mode | ||
31 | * (SGL/DIFF pin set to high) | ||
32 | */ | ||
33 | enum ad7266_mode { | ||
34 | AD7266_MODE_DIFF, | ||
35 | AD7266_MODE_PSEUDO_DIFF, | ||
36 | AD7266_MODE_SINGLE_ENDED, | ||
37 | }; | ||
38 | |||
39 | /** | ||
40 | * struct ad7266_platform_data - Platform data for the AD7266 driver | ||
41 | * @range: Reference voltage range the device is configured for | ||
42 | * @mode: Sample mode the device is configured for | ||
43 | * @fixed_addr: Whether the address pins are hard-wired | ||
44 | * @addr_gpios: GPIOs used for controlling the address pins, only used if | ||
45 | * fixed_addr is set to false. | ||
46 | */ | ||
47 | struct ad7266_platform_data { | ||
48 | enum ad7266_range range; | ||
49 | enum ad7266_mode mode; | ||
50 | bool fixed_addr; | ||
51 | unsigned int addr_gpios[3]; | ||
52 | }; | ||
53 | |||
54 | #endif | ||
55 |