Commit | Line | Data |
---|---|---|
f94aa354 MH |
1 | /* |
2 | * AD5933 AD5934 Impedance Converter, Network Analyzer | |
3 | * | |
4 | * Copyright 2011 Analog Devices Inc. | |
5 | * | |
6 | * Licensed under the GPL-2. | |
7 | */ | |
8 | ||
9 | #include <linux/interrupt.h> | |
10 | #include <linux/device.h> | |
11 | #include <linux/kernel.h> | |
12 | #include <linux/sysfs.h> | |
13 | #include <linux/i2c.h> | |
14 | #include <linux/regulator/consumer.h> | |
f94aa354 MH |
15 | #include <linux/types.h> |
16 | #include <linux/err.h> | |
17 | #include <linux/delay.h> | |
748b636c | 18 | #include <linux/module.h> |
f94aa354 | 19 | |
06458e27 JC |
20 | #include <linux/iio/iio.h> |
21 | #include <linux/iio/sysfs.h> | |
22 | #include <linux/iio/buffer.h> | |
032658a4 | 23 | #include <linux/iio/kfifo_buf.h> |
f94aa354 | 24 | |
f94aa354 MH |
25 | /* AD5933/AD5934 Registers */ |
26 | #define AD5933_REG_CONTROL_HB 0x80 /* R/W, 2 bytes */ | |
27 | #define AD5933_REG_CONTROL_LB 0x81 /* R/W, 2 bytes */ | |
28 | #define AD5933_REG_FREQ_START 0x82 /* R/W, 3 bytes */ | |
29 | #define AD5933_REG_FREQ_INC 0x85 /* R/W, 3 bytes */ | |
30 | #define AD5933_REG_INC_NUM 0x88 /* R/W, 2 bytes, 9 bit */ | |
31 | #define AD5933_REG_SETTLING_CYCLES 0x8A /* R/W, 2 bytes */ | |
32 | #define AD5933_REG_STATUS 0x8F /* R, 1 byte */ | |
33 | #define AD5933_REG_TEMP_DATA 0x92 /* R, 2 bytes*/ | |
34 | #define AD5933_REG_REAL_DATA 0x94 /* R, 2 bytes*/ | |
35 | #define AD5933_REG_IMAG_DATA 0x96 /* R, 2 bytes*/ | |
36 | ||
37 | /* AD5933_REG_CONTROL_HB Bits */ | |
38 | #define AD5933_CTRL_INIT_START_FREQ (0x1 << 4) | |
39 | #define AD5933_CTRL_START_SWEEP (0x2 << 4) | |
40 | #define AD5933_CTRL_INC_FREQ (0x3 << 4) | |
41 | #define AD5933_CTRL_REPEAT_FREQ (0x4 << 4) | |
42 | #define AD5933_CTRL_MEASURE_TEMP (0x9 << 4) | |
43 | #define AD5933_CTRL_POWER_DOWN (0xA << 4) | |
44 | #define AD5933_CTRL_STANDBY (0xB << 4) | |
45 | ||
46 | #define AD5933_CTRL_RANGE_2000mVpp (0x0 << 1) | |
47 | #define AD5933_CTRL_RANGE_200mVpp (0x1 << 1) | |
48 | #define AD5933_CTRL_RANGE_400mVpp (0x2 << 1) | |
49 | #define AD5933_CTRL_RANGE_1000mVpp (0x3 << 1) | |
50 | #define AD5933_CTRL_RANGE(x) ((x) << 1) | |
51 | ||
52 | #define AD5933_CTRL_PGA_GAIN_1 (0x1 << 0) | |
53 | #define AD5933_CTRL_PGA_GAIN_5 (0x0 << 0) | |
54 | ||
55 | /* AD5933_REG_CONTROL_LB Bits */ | |
56 | #define AD5933_CTRL_RESET (0x1 << 4) | |
57 | #define AD5933_CTRL_INT_SYSCLK (0x0 << 3) | |
58 | #define AD5933_CTRL_EXT_SYSCLK (0x1 << 3) | |
59 | ||
60 | /* AD5933_REG_STATUS Bits */ | |
61 | #define AD5933_STAT_TEMP_VALID (0x1 << 0) | |
62 | #define AD5933_STAT_DATA_VALID (0x1 << 1) | |
63 | #define AD5933_STAT_SWEEP_DONE (0x1 << 2) | |
64 | ||
65 | /* I2C Block Commands */ | |
66 | #define AD5933_I2C_BLOCK_WRITE 0xA0 | |
67 | #define AD5933_I2C_BLOCK_READ 0xA1 | |
68 | #define AD5933_I2C_ADDR_POINTER 0xB0 | |
69 | ||
70 | /* Device Specs */ | |
71 | #define AD5933_INT_OSC_FREQ_Hz 16776000 | |
72 | #define AD5933_MAX_OUTPUT_FREQ_Hz 100000 | |
73 | #define AD5933_MAX_RETRIES 100 | |
74 | ||
75 | #define AD5933_OUT_RANGE 1 | |
76 | #define AD5933_OUT_RANGE_AVAIL 2 | |
77 | #define AD5933_OUT_SETTLING_CYCLES 3 | |
78 | #define AD5933_IN_PGA_GAIN 4 | |
79 | #define AD5933_IN_PGA_GAIN_AVAIL 5 | |
80 | #define AD5933_FREQ_POINTS 6 | |
81 | ||
82 | #define AD5933_POLL_TIME_ms 10 | |
83 | #define AD5933_INIT_EXCITATION_TIME_ms 100 | |
84 | ||
f5d82ad9 AS |
85 | /** |
86 | * struct ad5933_platform_data - platform specific data | |
87 | * @ext_clk_Hz: the external clock frequency in Hz, if not set | |
88 | * the driver uses the internal clock (16.776 MHz) | |
89 | * @vref_mv: the external reference voltage in millivolt | |
90 | */ | |
91 | ||
92 | struct ad5933_platform_data { | |
93 | unsigned long ext_clk_Hz; | |
94 | unsigned short vref_mv; | |
95 | }; | |
96 | ||
f94aa354 MH |
97 | struct ad5933_state { |
98 | struct i2c_client *client; | |
99 | struct regulator *reg; | |
f94aa354 MH |
100 | struct delayed_work work; |
101 | unsigned long mclk_hz; | |
102 | unsigned char ctrl_hb; | |
103 | unsigned char ctrl_lb; | |
51fadb98 | 104 | unsigned int range_avail[4]; |
f94aa354 MH |
105 | unsigned short vref_mv; |
106 | unsigned short settling_cycles; | |
107 | unsigned short freq_points; | |
51fadb98 AS |
108 | unsigned int freq_start; |
109 | unsigned int freq_inc; | |
110 | unsigned int state; | |
111 | unsigned int poll_time_jiffies; | |
f94aa354 MH |
112 | }; |
113 | ||
114 | static struct ad5933_platform_data ad5933_default_pdata = { | |
115 | .vref_mv = 3300, | |
116 | }; | |
117 | ||
f4e4b955 | 118 | static const struct iio_chan_spec ad5933_channels[] = { |
cdacc05b JC |
119 | { |
120 | .type = IIO_TEMP, | |
121 | .indexed = 1, | |
cdacc05b | 122 | .channel = 0, |
9251d14a LPC |
123 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | |
124 | BIT(IIO_CHAN_INFO_SCALE), | |
cdacc05b | 125 | .address = AD5933_REG_TEMP_DATA, |
824269c5 | 126 | .scan_index = -1, |
cdacc05b JC |
127 | .scan_type = { |
128 | .sign = 's', | |
129 | .realbits = 14, | |
130 | .storagebits = 16, | |
131 | }, | |
132 | }, { /* Ring Channels */ | |
133 | .type = IIO_VOLTAGE, | |
134 | .indexed = 1, | |
135 | .channel = 0, | |
6822ee34 | 136 | .extend_name = "real", |
cdacc05b JC |
137 | .address = AD5933_REG_REAL_DATA, |
138 | .scan_index = 0, | |
139 | .scan_type = { | |
140 | .sign = 's', | |
141 | .realbits = 16, | |
142 | .storagebits = 16, | |
143 | }, | |
144 | }, { | |
145 | .type = IIO_VOLTAGE, | |
146 | .indexed = 1, | |
147 | .channel = 0, | |
6822ee34 | 148 | .extend_name = "imag", |
cdacc05b JC |
149 | .address = AD5933_REG_IMAG_DATA, |
150 | .scan_index = 1, | |
151 | .scan_type = { | |
152 | .sign = 's', | |
153 | .realbits = 16, | |
154 | .storagebits = 16, | |
155 | }, | |
156 | }, | |
f94aa354 MH |
157 | }; |
158 | ||
159 | static int ad5933_i2c_write(struct i2c_client *client, | |
160 | u8 reg, u8 len, u8 *data) | |
161 | { | |
162 | int ret; | |
163 | ||
164 | while (len--) { | |
165 | ret = i2c_smbus_write_byte_data(client, reg++, *data++); | |
166 | if (ret < 0) { | |
167 | dev_err(&client->dev, "I2C write error\n"); | |
168 | return ret; | |
169 | } | |
170 | } | |
171 | return 0; | |
172 | } | |
173 | ||
174 | static int ad5933_i2c_read(struct i2c_client *client, | |
175 | u8 reg, u8 len, u8 *data) | |
176 | { | |
177 | int ret; | |
178 | ||
179 | while (len--) { | |
180 | ret = i2c_smbus_read_byte_data(client, reg++); | |
181 | if (ret < 0) { | |
182 | dev_err(&client->dev, "I2C read error\n"); | |
183 | return ret; | |
184 | } | |
185 | *data++ = ret; | |
186 | } | |
187 | return 0; | |
188 | } | |
189 | ||
190 | static int ad5933_cmd(struct ad5933_state *st, unsigned char cmd) | |
191 | { | |
192 | unsigned char dat = st->ctrl_hb | cmd; | |
193 | ||
194 | return ad5933_i2c_write(st->client, | |
195 | AD5933_REG_CONTROL_HB, 1, &dat); | |
196 | } | |
197 | ||
198 | static int ad5933_reset(struct ad5933_state *st) | |
199 | { | |
200 | unsigned char dat = st->ctrl_lb | AD5933_CTRL_RESET; | |
69869c01 | 201 | |
f94aa354 MH |
202 | return ad5933_i2c_write(st->client, |
203 | AD5933_REG_CONTROL_LB, 1, &dat); | |
204 | } | |
205 | ||
206 | static int ad5933_wait_busy(struct ad5933_state *st, unsigned char event) | |
207 | { | |
208 | unsigned char val, timeout = AD5933_MAX_RETRIES; | |
209 | int ret; | |
210 | ||
211 | while (timeout--) { | |
212 | ret = ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &val); | |
213 | if (ret < 0) | |
214 | return ret; | |
215 | if (val & event) | |
216 | return val; | |
217 | cpu_relax(); | |
218 | mdelay(1); | |
219 | } | |
220 | ||
221 | return -EAGAIN; | |
222 | } | |
223 | ||
224 | static int ad5933_set_freq(struct ad5933_state *st, | |
51fadb98 | 225 | unsigned int reg, unsigned long freq) |
f94aa354 MH |
226 | { |
227 | unsigned long long freqreg; | |
228 | union { | |
7ddebf54 | 229 | __be32 d32; |
f94aa354 MH |
230 | u8 d8[4]; |
231 | } dat; | |
232 | ||
233 | freqreg = (u64) freq * (u64) (1 << 27); | |
234 | do_div(freqreg, st->mclk_hz / 4); | |
235 | ||
236 | switch (reg) { | |
237 | case AD5933_REG_FREQ_START: | |
238 | st->freq_start = freq; | |
239 | break; | |
240 | case AD5933_REG_FREQ_INC: | |
241 | st->freq_inc = freq; | |
242 | break; | |
243 | default: | |
244 | return -EINVAL; | |
245 | } | |
246 | ||
247 | dat.d32 = cpu_to_be32(freqreg); | |
248 | return ad5933_i2c_write(st->client, reg, 3, &dat.d8[1]); | |
249 | } | |
250 | ||
251 | static int ad5933_setup(struct ad5933_state *st) | |
252 | { | |
7ddebf54 | 253 | __be16 dat; |
f94aa354 MH |
254 | int ret; |
255 | ||
256 | ret = ad5933_reset(st); | |
257 | if (ret < 0) | |
258 | return ret; | |
259 | ||
260 | ret = ad5933_set_freq(st, AD5933_REG_FREQ_START, 10000); | |
261 | if (ret < 0) | |
262 | return ret; | |
263 | ||
264 | ret = ad5933_set_freq(st, AD5933_REG_FREQ_INC, 200); | |
265 | if (ret < 0) | |
266 | return ret; | |
267 | ||
268 | st->settling_cycles = 10; | |
269 | dat = cpu_to_be16(st->settling_cycles); | |
270 | ||
271 | ret = ad5933_i2c_write(st->client, | |
272 | AD5933_REG_SETTLING_CYCLES, 2, (u8 *)&dat); | |
273 | if (ret < 0) | |
274 | return ret; | |
275 | ||
276 | st->freq_points = 100; | |
277 | dat = cpu_to_be16(st->freq_points); | |
278 | ||
279 | return ad5933_i2c_write(st->client, AD5933_REG_INC_NUM, 2, (u8 *)&dat); | |
280 | } | |
281 | ||
282 | static void ad5933_calc_out_ranges(struct ad5933_state *st) | |
283 | { | |
284 | int i; | |
51fadb98 | 285 | unsigned int normalized_3v3[4] = {1980, 198, 383, 970}; |
f94aa354 MH |
286 | |
287 | for (i = 0; i < 4; i++) | |
288 | st->range_avail[i] = normalized_3v3[i] * st->vref_mv / 3300; | |
289 | ||
290 | } | |
291 | ||
292 | /* | |
293 | * handles: AD5933_REG_FREQ_START and AD5933_REG_FREQ_INC | |
294 | */ | |
295 | ||
296 | static ssize_t ad5933_show_frequency(struct device *dev, | |
297 | struct device_attribute *attr, | |
298 | char *buf) | |
299 | { | |
ba86dc46 | 300 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
638e59fc | 301 | struct ad5933_state *st = iio_priv(indio_dev); |
f94aa354 MH |
302 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
303 | int ret; | |
304 | unsigned long long freqreg; | |
305 | union { | |
7ddebf54 | 306 | __be32 d32; |
f94aa354 MH |
307 | u8 d8[4]; |
308 | } dat; | |
309 | ||
638e59fc | 310 | mutex_lock(&indio_dev->mlock); |
f94aa354 | 311 | ret = ad5933_i2c_read(st->client, this_attr->address, 3, &dat.d8[1]); |
638e59fc | 312 | mutex_unlock(&indio_dev->mlock); |
f94aa354 MH |
313 | if (ret < 0) |
314 | return ret; | |
315 | ||
316 | freqreg = be32_to_cpu(dat.d32) & 0xFFFFFF; | |
317 | ||
7df7ee9b | 318 | freqreg = (u64)freqreg * (u64)(st->mclk_hz / 4); |
f94aa354 MH |
319 | do_div(freqreg, 1 << 27); |
320 | ||
7df7ee9b | 321 | return sprintf(buf, "%d\n", (int)freqreg); |
f94aa354 MH |
322 | } |
323 | ||
324 | static ssize_t ad5933_store_frequency(struct device *dev, | |
325 | struct device_attribute *attr, | |
326 | const char *buf, | |
327 | size_t len) | |
328 | { | |
ba86dc46 | 329 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
638e59fc | 330 | struct ad5933_state *st = iio_priv(indio_dev); |
f94aa354 | 331 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
e5e26dd5 | 332 | unsigned long val; |
f94aa354 MH |
333 | int ret; |
334 | ||
e5e26dd5 | 335 | ret = kstrtoul(buf, 10, &val); |
f94aa354 MH |
336 | if (ret) |
337 | return ret; | |
338 | ||
339 | if (val > AD5933_MAX_OUTPUT_FREQ_Hz) | |
340 | return -EINVAL; | |
341 | ||
638e59fc | 342 | mutex_lock(&indio_dev->mlock); |
f94aa354 | 343 | ret = ad5933_set_freq(st, this_attr->address, val); |
638e59fc | 344 | mutex_unlock(&indio_dev->mlock); |
f94aa354 MH |
345 | |
346 | return ret ? ret : len; | |
347 | } | |
348 | ||
322c9563 | 349 | static IIO_DEVICE_ATTR(out_voltage0_freq_start, S_IRUGO | S_IWUSR, |
f94aa354 MH |
350 | ad5933_show_frequency, |
351 | ad5933_store_frequency, | |
352 | AD5933_REG_FREQ_START); | |
353 | ||
322c9563 | 354 | static IIO_DEVICE_ATTR(out_voltage0_freq_increment, S_IRUGO | S_IWUSR, |
f94aa354 MH |
355 | ad5933_show_frequency, |
356 | ad5933_store_frequency, | |
357 | AD5933_REG_FREQ_INC); | |
358 | ||
359 | static ssize_t ad5933_show(struct device *dev, | |
360 | struct device_attribute *attr, | |
361 | char *buf) | |
362 | { | |
ba86dc46 | 363 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
638e59fc | 364 | struct ad5933_state *st = iio_priv(indio_dev); |
f94aa354 MH |
365 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
366 | int ret = 0, len = 0; | |
367 | ||
638e59fc | 368 | mutex_lock(&indio_dev->mlock); |
7df7ee9b | 369 | switch ((u32)this_attr->address) { |
f94aa354 | 370 | case AD5933_OUT_RANGE: |
f0002b3b | 371 | len = sprintf(buf, "%u\n", |
f94aa354 MH |
372 | st->range_avail[(st->ctrl_hb >> 1) & 0x3]); |
373 | break; | |
374 | case AD5933_OUT_RANGE_AVAIL: | |
f0002b3b | 375 | len = sprintf(buf, "%u %u %u %u\n", st->range_avail[0], |
f94aa354 MH |
376 | st->range_avail[3], st->range_avail[2], |
377 | st->range_avail[1]); | |
378 | break; | |
379 | case AD5933_OUT_SETTLING_CYCLES: | |
380 | len = sprintf(buf, "%d\n", st->settling_cycles); | |
381 | break; | |
382 | case AD5933_IN_PGA_GAIN: | |
383 | len = sprintf(buf, "%s\n", | |
384 | (st->ctrl_hb & AD5933_CTRL_PGA_GAIN_1) ? | |
385 | "1" : "0.2"); | |
386 | break; | |
387 | case AD5933_IN_PGA_GAIN_AVAIL: | |
388 | len = sprintf(buf, "1 0.2\n"); | |
389 | break; | |
390 | case AD5933_FREQ_POINTS: | |
391 | len = sprintf(buf, "%d\n", st->freq_points); | |
392 | break; | |
393 | default: | |
394 | ret = -EINVAL; | |
395 | } | |
396 | ||
638e59fc | 397 | mutex_unlock(&indio_dev->mlock); |
f94aa354 MH |
398 | return ret ? ret : len; |
399 | } | |
400 | ||
401 | static ssize_t ad5933_store(struct device *dev, | |
402 | struct device_attribute *attr, | |
403 | const char *buf, | |
404 | size_t len) | |
405 | { | |
ba86dc46 | 406 | struct iio_dev *indio_dev = dev_to_iio_dev(dev); |
638e59fc | 407 | struct ad5933_state *st = iio_priv(indio_dev); |
f94aa354 | 408 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); |
e5e26dd5 | 409 | u16 val; |
f94aa354 | 410 | int i, ret = 0; |
7ddebf54 | 411 | __be16 dat; |
f94aa354 MH |
412 | |
413 | if (this_attr->address != AD5933_IN_PGA_GAIN) { | |
e5e26dd5 | 414 | ret = kstrtou16(buf, 10, &val); |
f94aa354 MH |
415 | if (ret) |
416 | return ret; | |
417 | } | |
418 | ||
638e59fc | 419 | mutex_lock(&indio_dev->mlock); |
7df7ee9b | 420 | switch ((u32)this_attr->address) { |
f94aa354 MH |
421 | case AD5933_OUT_RANGE: |
422 | for (i = 0; i < 4; i++) | |
423 | if (val == st->range_avail[i]) { | |
424 | st->ctrl_hb &= ~AD5933_CTRL_RANGE(0x3); | |
425 | st->ctrl_hb |= AD5933_CTRL_RANGE(i); | |
426 | ret = ad5933_cmd(st, 0); | |
427 | break; | |
428 | } | |
429 | ret = -EINVAL; | |
430 | break; | |
431 | case AD5933_IN_PGA_GAIN: | |
432 | if (sysfs_streq(buf, "1")) { | |
433 | st->ctrl_hb |= AD5933_CTRL_PGA_GAIN_1; | |
434 | } else if (sysfs_streq(buf, "0.2")) { | |
435 | st->ctrl_hb &= ~AD5933_CTRL_PGA_GAIN_1; | |
436 | } else { | |
437 | ret = -EINVAL; | |
438 | break; | |
439 | } | |
440 | ret = ad5933_cmd(st, 0); | |
441 | break; | |
442 | case AD5933_OUT_SETTLING_CYCLES: | |
e5e26dd5 | 443 | val = clamp(val, (u16)0, (u16)0x7FF); |
f94aa354 MH |
444 | st->settling_cycles = val; |
445 | ||
446 | /* 2x, 4x handling, see datasheet */ | |
f4070a19 | 447 | if (val > 1022) |
f94aa354 | 448 | val = (val >> 2) | (3 << 9); |
f4070a19 LB |
449 | else if (val > 511) |
450 | val = (val >> 1) | (1 << 9); | |
f94aa354 MH |
451 | |
452 | dat = cpu_to_be16(val); | |
453 | ret = ad5933_i2c_write(st->client, | |
454 | AD5933_REG_SETTLING_CYCLES, 2, (u8 *)&dat); | |
455 | break; | |
456 | case AD5933_FREQ_POINTS: | |
e5e26dd5 | 457 | val = clamp(val, (u16)0, (u16)511); |
f94aa354 MH |
458 | st->freq_points = val; |
459 | ||
460 | dat = cpu_to_be16(val); | |
461 | ret = ad5933_i2c_write(st->client, AD5933_REG_INC_NUM, 2, | |
462 | (u8 *)&dat); | |
463 | break; | |
464 | default: | |
465 | ret = -EINVAL; | |
466 | } | |
467 | ||
638e59fc | 468 | mutex_unlock(&indio_dev->mlock); |
f94aa354 MH |
469 | return ret ? ret : len; |
470 | } | |
471 | ||
322c9563 | 472 | static IIO_DEVICE_ATTR(out_voltage0_scale, S_IRUGO | S_IWUSR, |
f94aa354 MH |
473 | ad5933_show, |
474 | ad5933_store, | |
475 | AD5933_OUT_RANGE); | |
476 | ||
322c9563 | 477 | static IIO_DEVICE_ATTR(out_voltage0_scale_available, S_IRUGO, |
f94aa354 MH |
478 | ad5933_show, |
479 | NULL, | |
480 | AD5933_OUT_RANGE_AVAIL); | |
481 | ||
322c9563 | 482 | static IIO_DEVICE_ATTR(in_voltage0_scale, S_IRUGO | S_IWUSR, |
f94aa354 MH |
483 | ad5933_show, |
484 | ad5933_store, | |
485 | AD5933_IN_PGA_GAIN); | |
486 | ||
322c9563 | 487 | static IIO_DEVICE_ATTR(in_voltage0_scale_available, S_IRUGO, |
f94aa354 MH |
488 | ad5933_show, |
489 | NULL, | |
490 | AD5933_IN_PGA_GAIN_AVAIL); | |
491 | ||
322c9563 | 492 | static IIO_DEVICE_ATTR(out_voltage0_freq_points, S_IRUGO | S_IWUSR, |
f94aa354 MH |
493 | ad5933_show, |
494 | ad5933_store, | |
495 | AD5933_FREQ_POINTS); | |
496 | ||
322c9563 | 497 | static IIO_DEVICE_ATTR(out_voltage0_settling_cycles, S_IRUGO | S_IWUSR, |
f94aa354 MH |
498 | ad5933_show, |
499 | ad5933_store, | |
500 | AD5933_OUT_SETTLING_CYCLES); | |
501 | ||
502 | /* note: | |
503 | * ideally we would handle the scale attributes via the iio_info | |
504 | * (read|write)_raw methods, however this part is a untypical since we | |
505 | * don't create dedicated sysfs channel attributes for out0 and in0. | |
506 | */ | |
507 | static struct attribute *ad5933_attributes[] = { | |
322c9563 JC |
508 | &iio_dev_attr_out_voltage0_scale.dev_attr.attr, |
509 | &iio_dev_attr_out_voltage0_scale_available.dev_attr.attr, | |
510 | &iio_dev_attr_out_voltage0_freq_start.dev_attr.attr, | |
511 | &iio_dev_attr_out_voltage0_freq_increment.dev_attr.attr, | |
512 | &iio_dev_attr_out_voltage0_freq_points.dev_attr.attr, | |
513 | &iio_dev_attr_out_voltage0_settling_cycles.dev_attr.attr, | |
514 | &iio_dev_attr_in_voltage0_scale.dev_attr.attr, | |
515 | &iio_dev_attr_in_voltage0_scale_available.dev_attr.attr, | |
f94aa354 MH |
516 | NULL |
517 | }; | |
518 | ||
519 | static const struct attribute_group ad5933_attribute_group = { | |
520 | .attrs = ad5933_attributes, | |
521 | }; | |
522 | ||
638e59fc | 523 | static int ad5933_read_raw(struct iio_dev *indio_dev, |
f94aa354 MH |
524 | struct iio_chan_spec const *chan, |
525 | int *val, | |
526 | int *val2, | |
527 | long m) | |
528 | { | |
638e59fc | 529 | struct ad5933_state *st = iio_priv(indio_dev); |
7ddebf54 | 530 | __be16 dat; |
9251d14a | 531 | int ret; |
f94aa354 | 532 | |
f94aa354 | 533 | switch (m) { |
967d3fe0 | 534 | case IIO_CHAN_INFO_RAW: |
9251d14a | 535 | mutex_lock(&indio_dev->mlock); |
638e59fc | 536 | if (iio_buffer_enabled(indio_dev)) { |
f94aa354 MH |
537 | ret = -EBUSY; |
538 | goto out; | |
539 | } | |
540 | ret = ad5933_cmd(st, AD5933_CTRL_MEASURE_TEMP); | |
541 | if (ret < 0) | |
542 | goto out; | |
543 | ret = ad5933_wait_busy(st, AD5933_STAT_TEMP_VALID); | |
544 | if (ret < 0) | |
545 | goto out; | |
546 | ||
547 | ret = ad5933_i2c_read(st->client, | |
548 | AD5933_REG_TEMP_DATA, 2, | |
549 | (u8 *)&dat); | |
550 | if (ret < 0) | |
551 | goto out; | |
638e59fc | 552 | mutex_unlock(&indio_dev->mlock); |
9251d14a | 553 | *val = sign_extend32(be16_to_cpu(dat), 13); |
f94aa354 MH |
554 | |
555 | return IIO_VAL_INT; | |
9251d14a LPC |
556 | case IIO_CHAN_INFO_SCALE: |
557 | *val = 1000; | |
558 | *val2 = 5; | |
559 | return IIO_VAL_FRACTIONAL_LOG2; | |
f94aa354 MH |
560 | } |
561 | ||
9251d14a | 562 | return -EINVAL; |
f94aa354 | 563 | out: |
638e59fc | 564 | mutex_unlock(&indio_dev->mlock); |
f94aa354 MH |
565 | return ret; |
566 | } | |
567 | ||
568 | static const struct iio_info ad5933_info = { | |
478375ce | 569 | .read_raw = ad5933_read_raw, |
f94aa354 MH |
570 | .attrs = &ad5933_attribute_group, |
571 | .driver_module = THIS_MODULE, | |
572 | }; | |
573 | ||
574 | static int ad5933_ring_preenable(struct iio_dev *indio_dev) | |
575 | { | |
576 | struct ad5933_state *st = iio_priv(indio_dev); | |
f94aa354 MH |
577 | int ret; |
578 | ||
550268ca | 579 | if (bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) |
f94aa354 MH |
580 | return -EINVAL; |
581 | ||
f94aa354 MH |
582 | ret = ad5933_reset(st); |
583 | if (ret < 0) | |
584 | return ret; | |
585 | ||
586 | ret = ad5933_cmd(st, AD5933_CTRL_STANDBY); | |
587 | if (ret < 0) | |
588 | return ret; | |
589 | ||
590 | ret = ad5933_cmd(st, AD5933_CTRL_INIT_START_FREQ); | |
591 | if (ret < 0) | |
592 | return ret; | |
593 | ||
594 | st->state = AD5933_CTRL_INIT_START_FREQ; | |
595 | ||
596 | return 0; | |
597 | } | |
598 | ||
599 | static int ad5933_ring_postenable(struct iio_dev *indio_dev) | |
600 | { | |
601 | struct ad5933_state *st = iio_priv(indio_dev); | |
602 | ||
603 | /* AD5933_CTRL_INIT_START_FREQ: | |
604 | * High Q complex circuits require a long time to reach steady state. | |
605 | * To facilitate the measurement of such impedances, this mode allows | |
606 | * the user full control of the settling time requirement before | |
607 | * entering start frequency sweep mode where the impedance measurement | |
608 | * takes place. In this mode the impedance is excited with the | |
609 | * programmed start frequency (ad5933_ring_preenable), | |
610 | * but no measurement takes place. | |
611 | */ | |
612 | ||
613 | schedule_delayed_work(&st->work, | |
614 | msecs_to_jiffies(AD5933_INIT_EXCITATION_TIME_ms)); | |
615 | return 0; | |
616 | } | |
617 | ||
618 | static int ad5933_ring_postdisable(struct iio_dev *indio_dev) | |
619 | { | |
620 | struct ad5933_state *st = iio_priv(indio_dev); | |
621 | ||
622 | cancel_delayed_work_sync(&st->work); | |
623 | return ad5933_cmd(st, AD5933_CTRL_POWER_DOWN); | |
624 | } | |
625 | ||
14555b14 | 626 | static const struct iio_buffer_setup_ops ad5933_ring_setup_ops = { |
478375ce BG |
627 | .preenable = ad5933_ring_preenable, |
628 | .postenable = ad5933_ring_postenable, | |
629 | .postdisable = ad5933_ring_postdisable, | |
f94aa354 MH |
630 | }; |
631 | ||
632 | static int ad5933_register_ring_funcs_and_init(struct iio_dev *indio_dev) | |
633 | { | |
9e69c935 LPC |
634 | struct iio_buffer *buffer; |
635 | ||
7ab374a0 | 636 | buffer = iio_kfifo_allocate(); |
e9ed104d | 637 | if (!buffer) |
f94aa354 MH |
638 | return -ENOMEM; |
639 | ||
9e69c935 LPC |
640 | iio_device_attach_buffer(indio_dev, buffer); |
641 | ||
f94aa354 | 642 | /* Ring buffer functions - here trigger setup related */ |
1612244f | 643 | indio_dev->setup_ops = &ad5933_ring_setup_ops; |
f94aa354 | 644 | |
ec3afa40 | 645 | indio_dev->modes |= INDIO_BUFFER_HARDWARE; |
f94aa354 MH |
646 | |
647 | return 0; | |
648 | } | |
649 | ||
650 | static void ad5933_work(struct work_struct *work) | |
651 | { | |
652 | struct ad5933_state *st = container_of(work, | |
653 | struct ad5933_state, work.work); | |
654 | struct iio_dev *indio_dev = i2c_get_clientdata(st->client); | |
4c3577db KS |
655 | __be16 buf[2]; |
656 | int val[2]; | |
f94aa354 MH |
657 | unsigned char status; |
658 | ||
659 | mutex_lock(&indio_dev->mlock); | |
660 | if (st->state == AD5933_CTRL_INIT_START_FREQ) { | |
661 | /* start sweep */ | |
662 | ad5933_cmd(st, AD5933_CTRL_START_SWEEP); | |
663 | st->state = AD5933_CTRL_START_SWEEP; | |
664 | schedule_delayed_work(&st->work, st->poll_time_jiffies); | |
665 | mutex_unlock(&indio_dev->mlock); | |
666 | return; | |
667 | } | |
668 | ||
669 | ad5933_i2c_read(st->client, AD5933_REG_STATUS, 1, &status); | |
670 | ||
671 | if (status & AD5933_STAT_DATA_VALID) { | |
550268ca JC |
672 | int scan_count = bitmap_weight(indio_dev->active_scan_mask, |
673 | indio_dev->masklength); | |
f94aa354 | 674 | ad5933_i2c_read(st->client, |
550268ca | 675 | test_bit(1, indio_dev->active_scan_mask) ? |
f94aa354 | 676 | AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA, |
550268ca | 677 | scan_count * 2, (u8 *)buf); |
f94aa354 | 678 | |
550268ca | 679 | if (scan_count == 2) { |
4c3577db KS |
680 | val[0] = be16_to_cpu(buf[0]); |
681 | val[1] = be16_to_cpu(buf[1]); | |
f94aa354 | 682 | } else { |
4c3577db | 683 | val[0] = be16_to_cpu(buf[0]); |
f94aa354 | 684 | } |
4c3577db | 685 | iio_push_to_buffers(indio_dev, val); |
f94aa354 MH |
686 | } else { |
687 | /* no data available - try again later */ | |
688 | schedule_delayed_work(&st->work, st->poll_time_jiffies); | |
689 | mutex_unlock(&indio_dev->mlock); | |
690 | return; | |
691 | } | |
692 | ||
693 | if (status & AD5933_STAT_SWEEP_DONE) { | |
a6634f83 AS |
694 | /* last sample received - power down do |
695 | * nothing until the ring enable is toggled | |
696 | */ | |
f94aa354 MH |
697 | ad5933_cmd(st, AD5933_CTRL_POWER_DOWN); |
698 | } else { | |
699 | /* we just received a valid datum, move on to the next */ | |
700 | ad5933_cmd(st, AD5933_CTRL_INC_FREQ); | |
701 | schedule_delayed_work(&st->work, st->poll_time_jiffies); | |
702 | } | |
703 | ||
704 | mutex_unlock(&indio_dev->mlock); | |
705 | } | |
706 | ||
4ae1c61f | 707 | static int ad5933_probe(struct i2c_client *client, |
f94aa354 MH |
708 | const struct i2c_device_id *id) |
709 | { | |
26d25ae3 | 710 | int ret, voltage_uv = 0; |
7b58e240 | 711 | struct ad5933_platform_data *pdata = dev_get_platdata(&client->dev); |
f94aa354 | 712 | struct ad5933_state *st; |
53703a49 SK |
713 | struct iio_dev *indio_dev; |
714 | ||
715 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); | |
16d55be4 | 716 | if (!indio_dev) |
f94aa354 MH |
717 | return -ENOMEM; |
718 | ||
719 | st = iio_priv(indio_dev); | |
720 | i2c_set_clientdata(client, indio_dev); | |
721 | st->client = client; | |
722 | ||
723 | if (!pdata) | |
0a01db9d | 724 | pdata = &ad5933_default_pdata; |
f94aa354 | 725 | |
53703a49 | 726 | st->reg = devm_regulator_get(&client->dev, "vcc"); |
f94aa354 MH |
727 | if (!IS_ERR(st->reg)) { |
728 | ret = regulator_enable(st->reg); | |
729 | if (ret) | |
53703a49 | 730 | return ret; |
f94aa354 MH |
731 | voltage_uv = regulator_get_voltage(st->reg); |
732 | } | |
733 | ||
734 | if (voltage_uv) | |
735 | st->vref_mv = voltage_uv / 1000; | |
736 | else | |
0a01db9d | 737 | st->vref_mv = pdata->vref_mv; |
f94aa354 | 738 | |
0a01db9d LPC |
739 | if (pdata->ext_clk_Hz) { |
740 | st->mclk_hz = pdata->ext_clk_Hz; | |
f94aa354 MH |
741 | st->ctrl_lb = AD5933_CTRL_EXT_SYSCLK; |
742 | } else { | |
743 | st->mclk_hz = AD5933_INT_OSC_FREQ_Hz; | |
744 | st->ctrl_lb = AD5933_CTRL_INT_SYSCLK; | |
745 | } | |
746 | ||
747 | ad5933_calc_out_ranges(st); | |
748 | INIT_DELAYED_WORK(&st->work, ad5933_work); | |
749 | st->poll_time_jiffies = msecs_to_jiffies(AD5933_POLL_TIME_ms); | |
750 | ||
751 | indio_dev->dev.parent = &client->dev; | |
752 | indio_dev->info = &ad5933_info; | |
753 | indio_dev->name = id->name; | |
754 | indio_dev->modes = INDIO_DIRECT_MODE; | |
755 | indio_dev->channels = ad5933_channels; | |
824269c5 | 756 | indio_dev->num_channels = ARRAY_SIZE(ad5933_channels); |
f94aa354 MH |
757 | |
758 | ret = ad5933_register_ring_funcs_and_init(indio_dev); | |
759 | if (ret) | |
760 | goto error_disable_reg; | |
761 | ||
f94aa354 MH |
762 | ret = ad5933_setup(st); |
763 | if (ret) | |
3e1b6c95 | 764 | goto error_unreg_ring; |
f94aa354 | 765 | |
26d25ae3 JC |
766 | ret = iio_device_register(indio_dev); |
767 | if (ret) | |
3e1b6c95 | 768 | goto error_unreg_ring; |
26d25ae3 | 769 | |
f94aa354 MH |
770 | return 0; |
771 | ||
f94aa354 | 772 | error_unreg_ring: |
032658a4 | 773 | iio_kfifo_free(indio_dev->buffer); |
f94aa354 MH |
774 | error_disable_reg: |
775 | if (!IS_ERR(st->reg)) | |
776 | regulator_disable(st->reg); | |
f94aa354 MH |
777 | |
778 | return ret; | |
779 | } | |
780 | ||
447d4f29 | 781 | static int ad5933_remove(struct i2c_client *client) |
f94aa354 MH |
782 | { |
783 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | |
784 | struct ad5933_state *st = iio_priv(indio_dev); | |
785 | ||
d2fffd6c | 786 | iio_device_unregister(indio_dev); |
032658a4 | 787 | iio_kfifo_free(indio_dev->buffer); |
53703a49 | 788 | if (!IS_ERR(st->reg)) |
f94aa354 | 789 | regulator_disable(st->reg); |
f94aa354 MH |
790 | |
791 | return 0; | |
792 | } | |
793 | ||
794 | static const struct i2c_device_id ad5933_id[] = { | |
795 | { "ad5933", 0 }, | |
796 | { "ad5934", 0 }, | |
797 | {} | |
798 | }; | |
799 | ||
800 | MODULE_DEVICE_TABLE(i2c, ad5933_id); | |
801 | ||
802 | static struct i2c_driver ad5933_driver = { | |
803 | .driver = { | |
804 | .name = "ad5933", | |
805 | }, | |
806 | .probe = ad5933_probe, | |
e543acf0 | 807 | .remove = ad5933_remove, |
f94aa354 MH |
808 | .id_table = ad5933_id, |
809 | }; | |
6e5af184 | 810 | module_i2c_driver(ad5933_driver); |
f94aa354 MH |
811 | |
812 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | |
813 | MODULE_DESCRIPTION("Analog Devices AD5933 Impedance Conv. Network Analyzer"); | |
814 | MODULE_LICENSE("GPL v2"); |