Commit | Line | Data |
---|---|---|
817e5c65 GY |
1 | /* |
2 | * ad2s1210.c support for the ADI Resolver to Digital Converters: AD2S1210 | |
3 | * | |
4 | * Copyright (c) 2010-2010 Analog Devices Inc. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 as | |
8 | * published by the Free Software Foundation. | |
9 | * | |
10 | */ | |
11 | #include <linux/types.h> | |
12 | #include <linux/mutex.h> | |
13 | #include <linux/device.h> | |
14 | #include <linux/spi/spi.h> | |
15 | #include <linux/slab.h> | |
16 | #include <linux/sysfs.h> | |
17 | #include <linux/delay.h> | |
18 | #include <linux/gpio.h> | |
19 | ||
20 | #include "../iio.h" | |
21 | #include "../sysfs.h" | |
22 | ||
23 | #define DRV_NAME "ad2s1210" | |
24 | ||
25 | #define DEF_CONTROL 0x7E | |
26 | ||
27 | #define MSB_IS_HIGH 0x80 | |
28 | #define MSB_IS_LOW 0x7F | |
29 | #define PHASE_LOCK_RANGE_44 0x20 | |
30 | #define ENABLE_HYSTERESIS 0x10 | |
31 | #define SET_ENRES1 0x08 | |
32 | #define SET_ENRES0 0x04 | |
33 | #define SET_RES1 0x02 | |
34 | #define SET_RES0 0x01 | |
35 | ||
36 | #define SET_ENRESOLUTION (SET_ENRES1 | SET_ENRES0) | |
37 | #define SET_RESOLUTION (SET_RES1 | SET_RES0) | |
38 | ||
39 | #define REG_POSITION 0x80 | |
40 | #define REG_VELOCITY 0x82 | |
41 | #define REG_LOS_THRD 0x88 | |
42 | #define REG_DOS_OVR_THRD 0x89 | |
43 | #define REG_DOS_MIS_THRD 0x8A | |
44 | #define REG_DOS_RST_MAX_THRD 0x8B | |
45 | #define REG_DOS_RST_MIN_THRD 0x8C | |
46 | #define REG_LOT_HIGH_THRD 0x8D | |
47 | #define REG_LOT_LOW_THRD 0x8E | |
48 | #define REG_EXCIT_FREQ 0x91 | |
49 | #define REG_CONTROL 0x92 | |
50 | #define REG_SOFT_RESET 0xF0 | |
51 | #define REG_FAULT 0xFF | |
52 | ||
53 | /* pin SAMPLE, A0, A1, RES0, RES1, is controlled by driver */ | |
54 | #define AD2S1210_SAA 3 | |
55 | #if defined(CONFIG_AD2S1210_GPIO_INPUT) || defined(CONFIG_AD2S1210_GPIO_OUTPUT) | |
56 | # define AD2S1210_RES 2 | |
57 | #else | |
58 | # define AD2S1210_RES 0 | |
59 | #endif | |
60 | #define AD2S1210_PN (AD2S1210_SAA + AD2S1210_RES) | |
61 | ||
62 | #define AD2S1210_MIN_CLKIN 6144000 | |
63 | #define AD2S1210_MAX_CLKIN 10240000 | |
64 | #define AD2S1210_MIN_EXCIT 2000 | |
65 | #define AD2S1210_MAX_EXCIT 20000 | |
66 | #define AD2S1210_MIN_FCW 0x4 | |
67 | #define AD2S1210_MAX_FCW 0x50 | |
68 | ||
69 | /* default input clock on serial interface */ | |
70 | #define AD2S1210_DEF_CLKIN 8192000 | |
71 | /* clock period in nano second */ | |
72 | #define AD2S1210_DEF_TCK (1000000000/AD2S1210_DEF_CLKIN) | |
73 | #define AD2S1210_DEF_EXCIT 10000 | |
74 | ||
75 | enum ad2s1210_mode { | |
76 | MOD_POS = 0, | |
77 | MOD_VEL, | |
78 | MOD_RESERVED, | |
79 | MOD_CONFIG, | |
80 | }; | |
81 | ||
82 | enum ad2s1210_res { | |
83 | RES_10 = 10, | |
84 | RES_12 = 12, | |
85 | RES_14 = 14, | |
86 | RES_16 = 16, | |
87 | }; | |
88 | ||
89 | static unsigned int resolution_value[] = { | |
90 | RES_10, RES_12, RES_14, RES_16}; | |
91 | ||
92 | struct ad2s1210_state { | |
93 | struct mutex lock; | |
94 | struct iio_dev *idev; | |
95 | struct spi_device *sdev; | |
96 | struct spi_transfer xfer; | |
97 | unsigned int hysteresis; | |
98 | unsigned int old_data; | |
99 | enum ad2s1210_mode mode; | |
100 | enum ad2s1210_res resolution; | |
101 | unsigned int fclkin; | |
102 | unsigned int fexcit; | |
103 | unsigned short sample; | |
104 | unsigned short a0; | |
105 | unsigned short a1; | |
106 | unsigned short res0; | |
107 | unsigned short res1; | |
108 | u8 rx[3]; | |
109 | u8 tx[3]; | |
110 | }; | |
111 | ||
112 | static inline void start_sample(struct ad2s1210_state *st) | |
113 | { | |
114 | gpio_set_value(st->sample, 0); | |
115 | } | |
116 | ||
117 | static inline void stop_sample(struct ad2s1210_state *st) | |
118 | { | |
119 | gpio_set_value(st->sample, 1); | |
120 | } | |
121 | ||
122 | static inline void set_mode(enum ad2s1210_mode mode, struct ad2s1210_state *st) | |
123 | { | |
124 | switch (mode) { | |
125 | case MOD_POS: | |
126 | gpio_set_value(st->a0, 0); | |
127 | gpio_set_value(st->a1, 0); | |
128 | break; | |
129 | case MOD_VEL: | |
130 | gpio_set_value(st->a0, 0); | |
131 | gpio_set_value(st->a1, 1); | |
132 | break; | |
133 | case MOD_CONFIG: | |
134 | gpio_set_value(st->a0, 1); | |
135 | gpio_set_value(st->a1, 1); | |
136 | break; | |
137 | default: | |
138 | /* set to reserved mode */ | |
139 | gpio_set_value(st->a0, 1); | |
140 | gpio_set_value(st->a1, 0); | |
141 | } | |
142 | st->mode = mode; | |
143 | } | |
144 | ||
145 | /* write 1 bytes (address or data) to the chip */ | |
146 | static int config_write(struct ad2s1210_state *st, | |
147 | unsigned char data) | |
148 | { | |
149 | struct spi_message msg; | |
150 | int ret = 0; | |
151 | ||
152 | st->xfer.len = 1; | |
153 | set_mode(MOD_CONFIG, st); | |
154 | ||
155 | spi_message_init(&msg); | |
156 | spi_message_add_tail(&st->xfer, &msg); | |
157 | st->tx[0] = data; | |
158 | ret = spi_sync(st->sdev, &msg); | |
159 | if (ret) | |
160 | return ret; | |
161 | st->old_data = 1; | |
162 | return ret; | |
163 | } | |
164 | ||
165 | /* read value from one of the registers */ | |
166 | static int config_read(struct ad2s1210_state *st, | |
167 | unsigned char address, | |
168 | unsigned char *data) | |
169 | { | |
170 | struct spi_message msg; | |
171 | int ret = 0; | |
172 | ||
173 | st->xfer.len = 2; | |
174 | set_mode(MOD_CONFIG, st); | |
175 | ||
176 | spi_message_init(&msg); | |
177 | spi_message_add_tail(&st->xfer, &msg); | |
178 | st->tx[0] = address | MSB_IS_HIGH; | |
179 | st->tx[1] = REG_FAULT; | |
180 | ret = spi_sync(st->sdev, &msg); | |
181 | if (ret) | |
182 | return ret; | |
183 | *data = st->rx[1]; | |
184 | st->old_data = 1; | |
185 | return ret; | |
186 | } | |
187 | ||
188 | static inline void update_frequency_control_word(struct ad2s1210_state *st) | |
189 | { | |
190 | unsigned char fcw; | |
191 | fcw = (unsigned char)(st->fexcit * (1 << 15) / st->fclkin); | |
192 | if (fcw >= AD2S1210_MIN_FCW && fcw <= AD2S1210_MAX_FCW) { | |
193 | config_write(st, REG_EXCIT_FREQ); | |
194 | config_write(st, fcw); | |
195 | } else | |
196 | pr_err("ad2s1210: FCW out of range\n"); | |
197 | } | |
198 | ||
199 | #if defined(CONFIG_AD2S1210_GPIO_INPUT) | |
200 | static inline unsigned char read_resolution_pin(struct ad2s1210_state *st) | |
201 | { | |
202 | unsigned int data; | |
203 | data = (gpio_get_value(st->res0) << 1) | | |
204 | gpio_get_value(st->res1); | |
205 | return resolution_value[data]; | |
206 | } | |
207 | #elif defined(CONFIG_AD2S1210_GPIO_OUTPUT) | |
208 | static inline void set_resolution_pin(struct ad2s1210_state *st) | |
209 | { | |
210 | switch (st->resolution) { | |
211 | case RES_10: | |
212 | gpio_set_value(st->res0, 0); | |
213 | gpio_set_value(st->res1, 0); | |
214 | break; | |
215 | case RES_12: | |
216 | gpio_set_value(st->res0, 0); | |
217 | gpio_set_value(st->res1, 1); | |
218 | break; | |
219 | case RES_14: | |
220 | gpio_set_value(st->res0, 1); | |
221 | gpio_set_value(st->res1, 0); | |
222 | break; | |
223 | case RES_16: | |
224 | gpio_set_value(st->res0, 1); | |
225 | gpio_set_value(st->res1, 1); | |
226 | break; | |
227 | } | |
228 | } | |
229 | #endif | |
230 | ||
231 | static inline void soft_reset(struct ad2s1210_state *st) | |
232 | { | |
233 | config_write(st, REG_SOFT_RESET); | |
234 | config_write(st, 0x0); | |
235 | } | |
236 | ||
237 | ||
238 | /* return the OLD DATA since last spi bus write */ | |
239 | static ssize_t ad2s1210_show_raw(struct device *dev, | |
240 | struct device_attribute *attr, char *buf) | |
241 | { | |
242 | struct iio_dev *idev = dev_get_drvdata(dev); | |
243 | struct ad2s1210_state *st = idev->dev_data; | |
244 | int ret; | |
245 | ||
246 | mutex_lock(&st->lock); | |
247 | if (st->old_data) { | |
248 | ret = sprintf(buf, "0x%x\n", st->rx[0]); | |
249 | st->old_data = 0; | |
250 | } else | |
251 | ret = 0; | |
252 | mutex_unlock(&st->lock); | |
253 | return ret; | |
254 | } | |
255 | ||
256 | static ssize_t ad2s1210_store_raw(struct device *dev, | |
257 | struct device_attribute *attr, | |
258 | const char *buf, size_t len) | |
259 | { | |
260 | struct iio_dev *idev = dev_get_drvdata(dev); | |
261 | struct ad2s1210_state *st = idev->dev_data; | |
262 | unsigned long udata; | |
263 | unsigned char data; | |
264 | int ret; | |
265 | ||
266 | ret = strict_strtoul(buf, 16, &udata); | |
267 | if (ret) | |
268 | return -EINVAL; | |
269 | data = udata & 0xff; | |
270 | mutex_lock(&st->lock); | |
271 | config_write(st, data); | |
272 | mutex_unlock(&st->lock); | |
273 | return 1; | |
274 | } | |
275 | ||
276 | static ssize_t ad2s1210_store_softreset(struct device *dev, | |
277 | struct device_attribute *attr, | |
278 | const char *buf, size_t len) | |
279 | { | |
280 | struct iio_dev *idev = dev_get_drvdata(dev); | |
281 | struct ad2s1210_state *st = idev->dev_data; | |
282 | mutex_lock(&st->lock); | |
283 | soft_reset(st); | |
284 | mutex_unlock(&st->lock); | |
285 | return len; | |
286 | } | |
287 | ||
288 | static ssize_t ad2s1210_show_fclkin(struct device *dev, | |
289 | struct device_attribute *attr, char *buf) | |
290 | { | |
291 | struct iio_dev *idev = dev_get_drvdata(dev); | |
292 | struct ad2s1210_state *st = idev->dev_data; | |
293 | return sprintf(buf, "%d\n", st->fclkin); | |
294 | } | |
295 | ||
296 | static ssize_t ad2s1210_store_fclkin(struct device *dev, | |
297 | struct device_attribute *attr, | |
298 | const char *buf, size_t len) | |
299 | { | |
300 | struct iio_dev *idev = dev_get_drvdata(dev); | |
301 | struct ad2s1210_state *st = idev->dev_data; | |
302 | unsigned long fclkin; | |
303 | int ret; | |
304 | ||
305 | ret = strict_strtoul(buf, 10, &fclkin); | |
306 | if (!ret && fclkin >= AD2S1210_MIN_CLKIN && | |
307 | fclkin <= AD2S1210_MAX_CLKIN) { | |
308 | mutex_lock(&st->lock); | |
309 | st->fclkin = fclkin; | |
310 | } else { | |
311 | pr_err("ad2s1210: fclkin out of range\n"); | |
312 | return -EINVAL; | |
313 | } | |
314 | update_frequency_control_word(st); | |
315 | soft_reset(st); | |
316 | mutex_unlock(&st->lock); | |
317 | return len; | |
318 | } | |
319 | ||
320 | static ssize_t ad2s1210_show_fexcit(struct device *dev, | |
321 | struct device_attribute *attr, char *buf) | |
322 | { | |
323 | struct iio_dev *idev = dev_get_drvdata(dev); | |
324 | struct ad2s1210_state *st = idev->dev_data; | |
325 | return sprintf(buf, "%d\n", st->fexcit); | |
326 | } | |
327 | ||
328 | static ssize_t ad2s1210_store_fexcit(struct device *dev, | |
329 | struct device_attribute *attr, | |
330 | const char *buf, size_t len) | |
331 | { | |
332 | struct iio_dev *idev = dev_get_drvdata(dev); | |
333 | struct ad2s1210_state *st = idev->dev_data; | |
334 | unsigned long fexcit; | |
335 | int ret; | |
336 | ||
337 | ret = strict_strtoul(buf, 10, &fexcit); | |
338 | if (!ret && fexcit >= AD2S1210_MIN_EXCIT && | |
339 | fexcit <= AD2S1210_MAX_EXCIT) { | |
340 | mutex_lock(&st->lock); | |
341 | st->fexcit = fexcit; | |
342 | } else { | |
343 | pr_err("ad2s1210: excitation frequency out of range\n"); | |
344 | return -EINVAL; | |
345 | } | |
346 | update_frequency_control_word(st); | |
347 | soft_reset(st); | |
348 | mutex_unlock(&st->lock); | |
349 | return len; | |
350 | } | |
351 | ||
352 | static ssize_t ad2s1210_show_control(struct device *dev, | |
353 | struct device_attribute *attr, char *buf) | |
354 | { | |
355 | struct iio_dev *idev = dev_get_drvdata(dev); | |
356 | struct ad2s1210_state *st = idev->dev_data; | |
357 | unsigned char data; | |
358 | mutex_lock(&st->lock); | |
359 | config_read(st, REG_CONTROL, &data); | |
360 | mutex_unlock(&st->lock); | |
361 | return sprintf(buf, "0x%x\n", data); | |
362 | } | |
363 | ||
364 | static ssize_t ad2s1210_store_control(struct device *dev, | |
365 | struct device_attribute *attr, | |
366 | const char *buf, size_t len) | |
367 | { | |
368 | struct iio_dev *idev = dev_get_drvdata(dev); | |
369 | struct ad2s1210_state *st = idev->dev_data; | |
370 | unsigned long udata; | |
371 | unsigned char data; | |
372 | int ret; | |
373 | ||
374 | ret = strict_strtoul(buf, 16, &udata); | |
375 | if (ret) { | |
376 | ret = -EINVAL; | |
377 | goto error_ret; | |
378 | } | |
379 | mutex_lock(&st->lock); | |
380 | config_write(st, REG_CONTROL); | |
381 | data = udata & MSB_IS_LOW; | |
382 | config_write(st, data); | |
383 | config_read(st, REG_CONTROL, &data); | |
384 | if (data & MSB_IS_HIGH) { | |
385 | ret = -EIO; | |
386 | pr_err("ad2s1210: write control register fail\n"); | |
387 | goto error_ret; | |
388 | } | |
389 | st->resolution = resolution_value[data & SET_RESOLUTION]; | |
390 | #if defined(CONFIG_AD2S1210_GPIO_INPUT) | |
391 | data = read_resolution_pin(st); | |
392 | if (data != st->resolution) | |
393 | pr_warning("ad2s1210: resolution settings not match\n"); | |
394 | #elif defined(CONFIG_AD2S1210_GPIO_OUTPUT) | |
395 | set_resolution_pin(st); | |
396 | #endif | |
397 | ret = len; | |
398 | if (data & ENABLE_HYSTERESIS) | |
399 | st->hysteresis = 1; | |
400 | else | |
401 | st->hysteresis = 0; | |
402 | error_ret: | |
403 | mutex_unlock(&st->lock); | |
404 | return ret; | |
405 | } | |
406 | ||
407 | static ssize_t ad2s1210_show_resolution(struct device *dev, | |
408 | struct device_attribute *attr, char *buf) | |
409 | { | |
410 | struct iio_dev *idev = dev_get_drvdata(dev); | |
411 | struct ad2s1210_state *st = idev->dev_data; | |
412 | return sprintf(buf, "%d\n", st->resolution); | |
413 | } | |
414 | ||
415 | static ssize_t ad2s1210_store_resolution(struct device *dev, | |
416 | struct device_attribute *attr, | |
417 | const char *buf, size_t len) | |
418 | { | |
419 | struct iio_dev *idev = dev_get_drvdata(dev); | |
420 | struct ad2s1210_state *st = idev->dev_data; | |
421 | unsigned char data; | |
422 | unsigned long udata; | |
423 | int ret; | |
424 | ||
425 | ret = strict_strtoul(buf, 10, &udata); | |
426 | if (ret || udata < RES_10 || udata > RES_16) { | |
427 | pr_err("ad2s1210: resolution out of range\n"); | |
428 | return -EINVAL; | |
429 | } | |
430 | mutex_lock(&st->lock); | |
431 | config_read(st, REG_CONTROL, &data); | |
432 | data &= ~SET_RESOLUTION; | |
433 | data |= (udata - RES_10) >> 1; | |
434 | config_write(st, REG_CONTROL); | |
435 | config_write(st, data & MSB_IS_LOW); | |
436 | config_read(st, REG_CONTROL, &data); | |
437 | if (data & MSB_IS_HIGH) { | |
438 | ret = -EIO; | |
439 | pr_err("ad2s1210: setting resolution fail\n"); | |
440 | goto error_ret; | |
441 | } | |
442 | st->resolution = resolution_value[data & SET_RESOLUTION]; | |
443 | #if defined(CONFIG_AD2S1210_GPIO_INPUT) | |
444 | data = read_resolution_pin(st); | |
445 | if (data != st->resolution) | |
446 | pr_warning("ad2s1210: resolution settings not match\n"); | |
447 | #elif defined(CONFIG_AD2S1210_GPIO_OUTPUT) | |
448 | set_resolution_pin(st); | |
449 | #endif | |
450 | ret = len; | |
451 | error_ret: | |
452 | mutex_unlock(&st->lock); | |
453 | return ret; | |
454 | } | |
455 | /* read the fault register since last sample */ | |
456 | static ssize_t ad2s1210_show_fault(struct device *dev, | |
457 | struct device_attribute *attr, char *buf) | |
458 | { | |
459 | int ret = 0; | |
460 | ssize_t len = 0; | |
461 | unsigned char data; | |
462 | struct iio_dev *idev = dev_get_drvdata(dev); | |
463 | struct ad2s1210_state *st = idev->dev_data; | |
464 | ||
465 | mutex_lock(&st->lock); | |
466 | ret = config_read(st, REG_FAULT, &data); | |
467 | ||
468 | if (ret) | |
469 | goto error_ret; | |
470 | len = sprintf(buf, "0x%x\n", data); | |
471 | error_ret: | |
472 | mutex_unlock(&st->lock); | |
473 | return ret ? ret : len; | |
474 | } | |
475 | ||
476 | static ssize_t ad2s1210_clear_fault(struct device *dev, | |
477 | struct device_attribute *attr, | |
478 | const char *buf, size_t len) | |
479 | { | |
480 | struct iio_dev *idev = dev_get_drvdata(dev); | |
481 | struct ad2s1210_state *st = idev->dev_data; | |
482 | unsigned char data; | |
483 | ||
484 | mutex_lock(&st->lock); | |
485 | start_sample(st); | |
486 | /* delay (2 * tck + 20) nano seconds */ | |
487 | udelay(1); | |
488 | stop_sample(st); | |
489 | config_read(st, REG_FAULT, &data); | |
490 | start_sample(st); | |
491 | stop_sample(st); | |
492 | mutex_unlock(&st->lock); | |
493 | ||
494 | return 0; | |
495 | } | |
496 | ||
497 | static ssize_t ad2s1210_show_reg(struct device *dev, | |
498 | struct device_attribute *attr, char *buf) | |
499 | { | |
500 | struct iio_dev *idev = dev_get_drvdata(dev); | |
501 | struct ad2s1210_state *st = idev->dev_data; | |
502 | unsigned char data; | |
503 | struct iio_dev_attr *iattr = to_iio_dev_attr(attr); | |
504 | ||
505 | mutex_lock(&st->lock); | |
506 | config_read(st, iattr->address, &data); | |
507 | mutex_unlock(&st->lock); | |
508 | return sprintf(buf, "%d\n", data); | |
509 | } | |
510 | ||
511 | static ssize_t ad2s1210_store_reg(struct device *dev, | |
512 | struct device_attribute *attr, const char *buf, size_t len) | |
513 | { | |
514 | struct iio_dev *idev = dev_get_drvdata(dev); | |
515 | struct ad2s1210_state *st = idev->dev_data; | |
516 | unsigned long data; | |
517 | int ret; | |
518 | struct iio_dev_attr *iattr = to_iio_dev_attr(attr); | |
519 | ||
520 | ret = strict_strtoul(buf, 10, &data); | |
521 | if (ret) | |
522 | return -EINVAL; | |
523 | mutex_lock(&st->lock); | |
524 | config_write(st, iattr->address); | |
525 | config_write(st, data & MSB_IS_LOW); | |
526 | mutex_unlock(&st->lock); | |
527 | return len; | |
528 | } | |
529 | ||
530 | static ssize_t ad2s1210_show_pos(struct device *dev, | |
531 | struct device_attribute *attr, char *buf) | |
532 | { | |
533 | struct spi_message msg; | |
534 | int ret = 0; | |
535 | ssize_t len = 0; | |
536 | u16 pos; | |
537 | struct iio_dev *idev = dev_get_drvdata(dev); | |
538 | struct ad2s1210_state *st = idev->dev_data; | |
539 | ||
540 | st->xfer.len = 2; | |
541 | mutex_lock(&st->lock); | |
542 | start_sample(st); | |
543 | /* delay (6 * tck + 20) nano seconds */ | |
544 | udelay(1); | |
545 | ||
546 | set_mode(MOD_POS, st); | |
547 | ||
548 | spi_message_init(&msg); | |
549 | spi_message_add_tail(&st->xfer, &msg); | |
550 | ret = spi_sync(st->sdev, &msg); | |
551 | if (ret) | |
552 | goto error_ret; | |
553 | pos = ((((u16)(st->rx[0])) << 8) | (st->rx[1])); | |
554 | if (st->hysteresis) | |
555 | pos >>= 16 - st->resolution; | |
556 | len = sprintf(buf, "%d\n", pos); | |
557 | error_ret: | |
558 | stop_sample(st); | |
559 | /* delay (2 * tck + 20) nano seconds */ | |
560 | udelay(1); | |
561 | mutex_unlock(&st->lock); | |
562 | ||
563 | return ret ? ret : len; | |
564 | } | |
565 | ||
566 | static ssize_t ad2s1210_show_vel(struct device *dev, | |
567 | struct device_attribute *attr, char *buf) | |
568 | { | |
569 | struct spi_message msg; | |
570 | unsigned short negative; | |
571 | int ret = 0; | |
572 | ssize_t len = 0; | |
573 | s16 vel; | |
574 | struct iio_dev *idev = dev_get_drvdata(dev); | |
575 | struct ad2s1210_state *st = idev->dev_data; | |
576 | ||
577 | st->xfer.len = 2; | |
578 | mutex_lock(&st->lock); | |
579 | start_sample(st); | |
580 | /* delay (6 * tck + 20) nano seconds */ | |
581 | udelay(1); | |
582 | ||
583 | set_mode(MOD_VEL, st); | |
584 | ||
585 | spi_message_init(&msg); | |
586 | spi_message_add_tail(&st->xfer, &msg); | |
587 | ret = spi_sync(st->sdev, &msg); | |
588 | if (ret) | |
589 | goto error_ret; | |
590 | negative = st->rx[0] & 0x80; | |
591 | vel = ((((s16)(st->rx[0])) << 8) | (st->rx[1])); | |
592 | vel >>= 16 - st->resolution; | |
593 | if (negative) { | |
594 | negative = (0xffff >> st->resolution) << st->resolution; | |
595 | vel |= negative; | |
596 | } | |
597 | len = sprintf(buf, "%d\n", vel); | |
598 | error_ret: | |
599 | stop_sample(st); | |
600 | /* delay (2 * tck + 20) nano seconds */ | |
601 | udelay(1); | |
602 | mutex_unlock(&st->lock); | |
603 | ||
604 | return ret ? ret : len; | |
605 | } | |
606 | ||
607 | static ssize_t ad2s1210_show_pos_vel(struct device *dev, | |
608 | struct device_attribute *attr, char *buf) | |
609 | { | |
610 | struct spi_message msg; | |
611 | unsigned short negative; | |
612 | int ret = 0; | |
613 | ssize_t len = 0; | |
614 | u16 pos; | |
615 | s16 vel; | |
616 | struct iio_dev *idev = dev_get_drvdata(dev); | |
617 | struct ad2s1210_state *st = idev->dev_data; | |
618 | ||
619 | st->xfer.len = 2; | |
620 | mutex_lock(&st->lock); | |
621 | start_sample(st); | |
622 | /* delay (6 * tck + 20) nano seconds */ | |
623 | udelay(1); | |
624 | ||
625 | set_mode(MOD_POS, st); | |
626 | ||
627 | spi_message_init(&msg); | |
628 | spi_message_add_tail(&st->xfer, &msg); | |
629 | ret = spi_sync(st->sdev, &msg); | |
630 | if (ret) | |
631 | goto error_ret; | |
632 | pos = ((((u16)(st->rx[0])) << 8) | (st->rx[1])); | |
633 | if (st->hysteresis) | |
634 | pos >>= 16 - st->resolution; | |
635 | len = sprintf(buf, "%d ", pos); | |
636 | ||
637 | st->xfer.len = 2; | |
638 | set_mode(MOD_VEL, st); | |
639 | spi_message_init(&msg); | |
640 | spi_message_add_tail(&st->xfer, &msg); | |
641 | ret = spi_sync(st->sdev, &msg); | |
642 | if (ret) | |
643 | goto error_ret; | |
644 | negative = st->rx[0] & 0x80; | |
645 | vel = ((((s16)(st->rx[0])) << 8) | (st->rx[1])); | |
646 | vel >>= 16 - st->resolution; | |
647 | if (negative) { | |
648 | negative = (0xffff >> st->resolution) << st->resolution; | |
649 | vel |= negative; | |
650 | } | |
651 | len += sprintf(buf + len, "%d\n", vel); | |
652 | error_ret: | |
653 | stop_sample(st); | |
654 | /* delay (2 * tck + 20) nano seconds */ | |
655 | udelay(1); | |
656 | mutex_unlock(&st->lock); | |
657 | ||
658 | return ret ? ret : len; | |
659 | } | |
660 | ||
661 | static IIO_CONST_ATTR(description, | |
662 | "Variable Resolution, 10-Bit to 16Bit R/D\n\ | |
663 | Converter with Reference Oscillator"); | |
664 | static IIO_DEVICE_ATTR(raw_io, S_IRUGO | S_IWUGO, | |
665 | ad2s1210_show_raw, ad2s1210_store_raw, 0); | |
666 | static IIO_DEVICE_ATTR(reset, S_IWUGO, | |
667 | NULL, ad2s1210_store_softreset, 0); | |
668 | static IIO_DEVICE_ATTR(fclkin, S_IRUGO | S_IWUGO, | |
669 | ad2s1210_show_fclkin, ad2s1210_store_fclkin, 0); | |
670 | static IIO_DEVICE_ATTR(fexcit, S_IRUGO | S_IWUGO, | |
671 | ad2s1210_show_fexcit, ad2s1210_store_fexcit, 0); | |
672 | static IIO_DEVICE_ATTR(control, S_IRUGO | S_IWUGO, | |
673 | ad2s1210_show_control, ad2s1210_store_control, 0); | |
674 | static IIO_DEVICE_ATTR(bits, S_IRUGO | S_IWUGO, | |
675 | ad2s1210_show_resolution, ad2s1210_store_resolution, 0); | |
676 | static IIO_DEVICE_ATTR(fault, S_IRUGO | S_IWUGO, | |
677 | ad2s1210_show_fault, ad2s1210_clear_fault, 0); | |
678 | static IIO_DEVICE_ATTR(pos, S_IRUGO, | |
679 | ad2s1210_show_pos, NULL, 0); | |
680 | static IIO_DEVICE_ATTR(vel, S_IRUGO, | |
681 | ad2s1210_show_vel, NULL, 0); | |
682 | static IIO_DEVICE_ATTR(pos_vel, S_IRUGO, | |
683 | ad2s1210_show_pos_vel, NULL, 0); | |
684 | static IIO_DEVICE_ATTR(los_thrd, S_IRUGO | S_IWUGO, | |
685 | ad2s1210_show_reg, ad2s1210_store_reg, REG_LOS_THRD); | |
686 | static IIO_DEVICE_ATTR(dos_ovr_thrd, S_IRUGO | S_IWUGO, | |
687 | ad2s1210_show_reg, ad2s1210_store_reg, REG_DOS_OVR_THRD); | |
688 | static IIO_DEVICE_ATTR(dos_mis_thrd, S_IRUGO | S_IWUGO, | |
689 | ad2s1210_show_reg, ad2s1210_store_reg, REG_DOS_MIS_THRD); | |
690 | static IIO_DEVICE_ATTR(dos_rst_max_thrd, S_IRUGO | S_IWUGO, | |
691 | ad2s1210_show_reg, ad2s1210_store_reg, REG_DOS_RST_MAX_THRD); | |
692 | static IIO_DEVICE_ATTR(dos_rst_min_thrd, S_IRUGO | S_IWUGO, | |
693 | ad2s1210_show_reg, ad2s1210_store_reg, REG_DOS_RST_MIN_THRD); | |
694 | static IIO_DEVICE_ATTR(lot_high_thrd, S_IRUGO | S_IWUGO, | |
695 | ad2s1210_show_reg, ad2s1210_store_reg, REG_LOT_HIGH_THRD); | |
696 | static IIO_DEVICE_ATTR(lot_low_thrd, S_IRUGO | S_IWUGO, | |
697 | ad2s1210_show_reg, ad2s1210_store_reg, REG_LOT_LOW_THRD); | |
698 | ||
699 | static struct attribute *ad2s1210_attributes[] = { | |
700 | &iio_const_attr_description.dev_attr.attr, | |
701 | &iio_dev_attr_raw_io.dev_attr.attr, | |
702 | &iio_dev_attr_reset.dev_attr.attr, | |
703 | &iio_dev_attr_fclkin.dev_attr.attr, | |
704 | &iio_dev_attr_fexcit.dev_attr.attr, | |
705 | &iio_dev_attr_control.dev_attr.attr, | |
706 | &iio_dev_attr_bits.dev_attr.attr, | |
707 | &iio_dev_attr_fault.dev_attr.attr, | |
708 | &iio_dev_attr_pos.dev_attr.attr, | |
709 | &iio_dev_attr_vel.dev_attr.attr, | |
710 | &iio_dev_attr_pos_vel.dev_attr.attr, | |
711 | &iio_dev_attr_los_thrd.dev_attr.attr, | |
712 | &iio_dev_attr_dos_ovr_thrd.dev_attr.attr, | |
713 | &iio_dev_attr_dos_mis_thrd.dev_attr.attr, | |
714 | &iio_dev_attr_dos_rst_max_thrd.dev_attr.attr, | |
715 | &iio_dev_attr_dos_rst_min_thrd.dev_attr.attr, | |
716 | &iio_dev_attr_lot_high_thrd.dev_attr.attr, | |
717 | &iio_dev_attr_lot_low_thrd.dev_attr.attr, | |
718 | NULL, | |
719 | }; | |
720 | ||
721 | static const struct attribute_group ad2s1210_attribute_group = { | |
722 | .name = DRV_NAME, | |
723 | .attrs = ad2s1210_attributes, | |
724 | }; | |
725 | ||
726 | static int __devinit ad2s1210_initial(struct ad2s1210_state *st) | |
727 | { | |
728 | unsigned char data; | |
729 | int ret; | |
730 | ||
731 | mutex_lock(&st->lock); | |
732 | #if defined(CONFIG_AD2S1210_GPIO_INPUT) | |
733 | st->resolution = read_resolution_pin(st); | |
734 | #elif defined(CONFIG_AD2S1210_GPIO_OUTPUT) | |
735 | set_resolution_pin(st); | |
736 | #endif | |
737 | ||
738 | config_write(st, REG_CONTROL); | |
739 | data = DEF_CONTROL & ~(SET_RESOLUTION); | |
740 | data |= (st->resolution - RES_10) >> 1; | |
741 | config_write(st, data); | |
742 | ret = config_read(st, REG_CONTROL, &data); | |
743 | if (ret) | |
744 | goto error_ret; | |
745 | ||
746 | if (data & MSB_IS_HIGH) { | |
747 | ret = -EIO; | |
748 | goto error_ret; | |
749 | } | |
750 | ||
751 | update_frequency_control_word(st); | |
752 | soft_reset(st); | |
753 | error_ret: | |
754 | mutex_unlock(&st->lock); | |
755 | return ret; | |
756 | } | |
757 | ||
758 | static int __devinit ad2s1210_probe(struct spi_device *spi) | |
759 | { | |
760 | struct ad2s1210_state *st; | |
761 | int pn, ret = 0; | |
762 | unsigned short *pins = spi->dev.platform_data; | |
763 | ||
764 | for (pn = 0; pn < AD2S1210_PN; pn++) { | |
765 | if (gpio_request(pins[pn], DRV_NAME)) { | |
766 | pr_err("%s: request gpio pin %d failed\n", | |
767 | DRV_NAME, pins[pn]); | |
768 | goto error_ret; | |
769 | } | |
770 | if (pn < AD2S1210_SAA) | |
771 | gpio_direction_output(pins[pn], 1); | |
772 | else { | |
773 | #if defined(CONFIG_AD2S1210_GPIO_INPUT) | |
774 | gpio_direction_input(pins[pn]); | |
775 | #elif defined(CONFIG_AD2S1210_GPIO_OUTPUT) | |
776 | gpio_direction_output(pins[pn], 1); | |
777 | #endif | |
778 | } | |
779 | } | |
780 | ||
781 | st = kzalloc(sizeof(*st), GFP_KERNEL); | |
782 | if (st == NULL) { | |
783 | ret = -ENOMEM; | |
784 | goto error_ret; | |
785 | } | |
786 | spi_set_drvdata(spi, st); | |
787 | ||
788 | mutex_init(&st->lock); | |
789 | st->sdev = spi; | |
790 | st->xfer.tx_buf = st->tx; | |
791 | st->xfer.rx_buf = st->rx; | |
792 | st->hysteresis = 1; | |
793 | st->mode = MOD_CONFIG; | |
794 | st->resolution = RES_12; | |
795 | st->fclkin = AD2S1210_DEF_CLKIN; | |
796 | st->fexcit = AD2S1210_DEF_EXCIT; | |
797 | st->sample = pins[0]; | |
798 | st->a0 = pins[1]; | |
799 | st->a1 = pins[2]; | |
800 | st->res0 = pins[3]; | |
801 | st->res1 = pins[4]; | |
802 | ||
803 | st->idev = iio_allocate_device(); | |
804 | if (st->idev == NULL) { | |
805 | ret = -ENOMEM; | |
806 | goto error_free_st; | |
807 | } | |
808 | st->idev->dev.parent = &spi->dev; | |
809 | st->idev->num_interrupt_lines = 0; | |
810 | st->idev->event_attrs = NULL; | |
811 | ||
812 | st->idev->attrs = &ad2s1210_attribute_group; | |
813 | st->idev->dev_data = (void *)(st); | |
814 | st->idev->driver_module = THIS_MODULE; | |
815 | st->idev->modes = INDIO_DIRECT_MODE; | |
816 | ||
817 | ret = iio_device_register(st->idev); | |
818 | if (ret) | |
819 | goto error_free_dev; | |
820 | ||
821 | if (spi->max_speed_hz != AD2S1210_DEF_CLKIN) | |
822 | st->fclkin = spi->max_speed_hz; | |
823 | spi->mode = SPI_MODE_3; | |
824 | spi_setup(spi); | |
825 | ||
826 | ad2s1210_initial(st); | |
827 | return 0; | |
828 | ||
829 | error_free_dev: | |
830 | iio_free_device(st->idev); | |
831 | error_free_st: | |
832 | kfree(st); | |
833 | error_ret: | |
834 | for (--pn; pn >= 0; pn--) | |
835 | gpio_free(pins[pn]); | |
836 | return ret; | |
837 | } | |
838 | ||
839 | static int __devexit ad2s1210_remove(struct spi_device *spi) | |
840 | { | |
841 | struct ad2s1210_state *st = spi_get_drvdata(spi); | |
842 | ||
843 | iio_device_unregister(st->idev); | |
844 | kfree(st); | |
845 | ||
846 | return 0; | |
847 | } | |
848 | ||
849 | static struct spi_driver ad2s1210_driver = { | |
850 | .driver = { | |
851 | .name = DRV_NAME, | |
852 | .owner = THIS_MODULE, | |
853 | }, | |
854 | .probe = ad2s1210_probe, | |
855 | .remove = __devexit_p(ad2s1210_remove), | |
856 | }; | |
857 | ||
858 | static __init int ad2s1210_spi_init(void) | |
859 | { | |
860 | return spi_register_driver(&ad2s1210_driver); | |
861 | } | |
862 | module_init(ad2s1210_spi_init); | |
863 | ||
864 | static __exit void ad2s1210_spi_exit(void) | |
865 | { | |
866 | spi_unregister_driver(&ad2s1210_driver); | |
867 | } | |
868 | module_exit(ad2s1210_spi_exit); | |
869 | ||
870 | MODULE_AUTHOR("Graff Yang <graff.yang@gmail.com>"); | |
871 | MODULE_DESCRIPTION("Analog Devices AD2S1210 Resolver to Digital SPI driver"); | |
872 | MODULE_LICENSE("GPL v2"); |