]>
Commit | Line | Data |
---|---|---|
c499d029 LPC |
1 | /* |
2 | * AD5755, AD5755-1, AD5757, AD5735, AD5737 Digital to analog converters 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/err.h> | |
11 | #include <linux/module.h> | |
12 | #include <linux/kernel.h> | |
13 | #include <linux/spi/spi.h> | |
14 | #include <linux/slab.h> | |
15 | #include <linux/sysfs.h> | |
16 | #include <linux/delay.h> | |
c9474599 | 17 | #include <linux/of.h> |
c499d029 LPC |
18 | #include <linux/iio/iio.h> |
19 | #include <linux/iio/sysfs.h> | |
20 | #include <linux/platform_data/ad5755.h> | |
21 | ||
22 | #define AD5755_NUM_CHANNELS 4 | |
23 | ||
24 | #define AD5755_ADDR(x) ((x) << 16) | |
25 | ||
26 | #define AD5755_WRITE_REG_DATA(chan) (chan) | |
27 | #define AD5755_WRITE_REG_GAIN(chan) (0x08 | (chan)) | |
28 | #define AD5755_WRITE_REG_OFFSET(chan) (0x10 | (chan)) | |
29 | #define AD5755_WRITE_REG_CTRL(chan) (0x1c | (chan)) | |
30 | ||
31 | #define AD5755_READ_REG_DATA(chan) (chan) | |
32 | #define AD5755_READ_REG_CTRL(chan) (0x4 | (chan)) | |
33 | #define AD5755_READ_REG_GAIN(chan) (0x8 | (chan)) | |
34 | #define AD5755_READ_REG_OFFSET(chan) (0xc | (chan)) | |
35 | #define AD5755_READ_REG_CLEAR(chan) (0x10 | (chan)) | |
36 | #define AD5755_READ_REG_SLEW(chan) (0x14 | (chan)) | |
37 | #define AD5755_READ_REG_STATUS 0x18 | |
38 | #define AD5755_READ_REG_MAIN 0x19 | |
39 | #define AD5755_READ_REG_DC_DC 0x1a | |
40 | ||
41 | #define AD5755_CTRL_REG_SLEW 0x0 | |
42 | #define AD5755_CTRL_REG_MAIN 0x1 | |
43 | #define AD5755_CTRL_REG_DAC 0x2 | |
44 | #define AD5755_CTRL_REG_DC_DC 0x3 | |
45 | #define AD5755_CTRL_REG_SW 0x4 | |
46 | ||
47 | #define AD5755_READ_FLAG 0x800000 | |
48 | ||
49 | #define AD5755_NOOP 0x1CE000 | |
50 | ||
51 | #define AD5755_DAC_INT_EN BIT(8) | |
52 | #define AD5755_DAC_CLR_EN BIT(7) | |
53 | #define AD5755_DAC_OUT_EN BIT(6) | |
54 | #define AD5755_DAC_INT_CURRENT_SENSE_RESISTOR BIT(5) | |
55 | #define AD5755_DAC_DC_DC_EN BIT(4) | |
56 | #define AD5755_DAC_VOLTAGE_OVERRANGE_EN BIT(3) | |
57 | ||
58 | #define AD5755_DC_DC_MAXV 0 | |
59 | #define AD5755_DC_DC_FREQ_SHIFT 2 | |
60 | #define AD5755_DC_DC_PHASE_SHIFT 4 | |
61 | #define AD5755_EXT_DC_DC_COMP_RES BIT(6) | |
62 | ||
63 | #define AD5755_SLEW_STEP_SIZE_SHIFT 0 | |
64 | #define AD5755_SLEW_RATE_SHIFT 3 | |
65 | #define AD5755_SLEW_ENABLE BIT(12) | |
66 | ||
67 | /** | |
68 | * struct ad5755_chip_info - chip specific information | |
69 | * @channel_template: channel specification | |
70 | * @calib_shift: shift for the calibration data registers | |
71 | * @has_voltage_out: whether the chip has voltage outputs | |
72 | */ | |
73 | struct ad5755_chip_info { | |
74 | const struct iio_chan_spec channel_template; | |
75 | unsigned int calib_shift; | |
76 | bool has_voltage_out; | |
77 | }; | |
78 | ||
79 | /** | |
80 | * struct ad5755_state - driver instance specific data | |
81 | * @spi: spi device the driver is attached to | |
82 | * @chip_info: chip model specific constants, available modes etc | |
83 | * @pwr_down: bitmask which contains hether a channel is powered down or not | |
84 | * @ctrl: software shadow of the channel ctrl registers | |
85 | * @channels: iio channel spec for the device | |
86 | * @data: spi transfer buffers | |
87 | */ | |
88 | struct ad5755_state { | |
89 | struct spi_device *spi; | |
90 | const struct ad5755_chip_info *chip_info; | |
91 | unsigned int pwr_down; | |
92 | unsigned int ctrl[AD5755_NUM_CHANNELS]; | |
93 | struct iio_chan_spec channels[AD5755_NUM_CHANNELS]; | |
94 | ||
95 | /* | |
96 | * DMA (thus cache coherency maintenance) requires the | |
97 | * transfer buffers to live in their own cache lines. | |
98 | */ | |
99 | ||
100 | union { | |
edc05f26 | 101 | __be32 d32; |
c499d029 LPC |
102 | u8 d8[4]; |
103 | } data[2] ____cacheline_aligned; | |
104 | }; | |
105 | ||
106 | enum ad5755_type { | |
107 | ID_AD5755, | |
108 | ID_AD5757, | |
109 | ID_AD5735, | |
110 | ID_AD5737, | |
111 | }; | |
112 | ||
c9474599 SN |
113 | #ifdef CONFIG_OF |
114 | static const int ad5755_dcdc_freq_table[][2] = { | |
115 | { 250000, AD5755_DC_DC_FREQ_250kHZ }, | |
116 | { 410000, AD5755_DC_DC_FREQ_410kHZ }, | |
117 | { 650000, AD5755_DC_DC_FREQ_650kHZ } | |
118 | }; | |
119 | ||
120 | static const int ad5755_dcdc_maxv_table[][2] = { | |
121 | { 23000000, AD5755_DC_DC_MAXV_23V }, | |
122 | { 24500000, AD5755_DC_DC_MAXV_24V5 }, | |
123 | { 27000000, AD5755_DC_DC_MAXV_27V }, | |
124 | { 29500000, AD5755_DC_DC_MAXV_29V5 }, | |
125 | }; | |
126 | ||
127 | static const int ad5755_slew_rate_table[][2] = { | |
128 | { 64000, AD5755_SLEW_RATE_64k }, | |
129 | { 32000, AD5755_SLEW_RATE_32k }, | |
130 | { 16000, AD5755_SLEW_RATE_16k }, | |
131 | { 8000, AD5755_SLEW_RATE_8k }, | |
132 | { 4000, AD5755_SLEW_RATE_4k }, | |
133 | { 2000, AD5755_SLEW_RATE_2k }, | |
134 | { 1000, AD5755_SLEW_RATE_1k }, | |
135 | { 500, AD5755_SLEW_RATE_500 }, | |
136 | { 250, AD5755_SLEW_RATE_250 }, | |
137 | { 125, AD5755_SLEW_RATE_125 }, | |
138 | { 64, AD5755_SLEW_RATE_64 }, | |
139 | { 32, AD5755_SLEW_RATE_32 }, | |
140 | { 16, AD5755_SLEW_RATE_16 }, | |
141 | { 8, AD5755_SLEW_RATE_8 }, | |
142 | { 4, AD5755_SLEW_RATE_4 }, | |
143 | { 0, AD5755_SLEW_RATE_0_5 }, | |
144 | }; | |
145 | ||
146 | static const int ad5755_slew_step_table[][2] = { | |
147 | { 256, AD5755_SLEW_STEP_SIZE_256 }, | |
148 | { 128, AD5755_SLEW_STEP_SIZE_128 }, | |
149 | { 64, AD5755_SLEW_STEP_SIZE_64 }, | |
150 | { 32, AD5755_SLEW_STEP_SIZE_32 }, | |
151 | { 16, AD5755_SLEW_STEP_SIZE_16 }, | |
152 | { 4, AD5755_SLEW_STEP_SIZE_4 }, | |
153 | { 2, AD5755_SLEW_STEP_SIZE_2 }, | |
154 | { 1, AD5755_SLEW_STEP_SIZE_1 }, | |
155 | }; | |
156 | #endif | |
157 | ||
c499d029 LPC |
158 | static int ad5755_write_unlocked(struct iio_dev *indio_dev, |
159 | unsigned int reg, unsigned int val) | |
160 | { | |
161 | struct ad5755_state *st = iio_priv(indio_dev); | |
162 | ||
163 | st->data[0].d32 = cpu_to_be32((reg << 16) | val); | |
164 | ||
165 | return spi_write(st->spi, &st->data[0].d8[1], 3); | |
166 | } | |
167 | ||
168 | static int ad5755_write_ctrl_unlocked(struct iio_dev *indio_dev, | |
169 | unsigned int channel, unsigned int reg, unsigned int val) | |
170 | { | |
171 | return ad5755_write_unlocked(indio_dev, | |
172 | AD5755_WRITE_REG_CTRL(channel), (reg << 13) | val); | |
173 | } | |
174 | ||
175 | static int ad5755_write(struct iio_dev *indio_dev, unsigned int reg, | |
176 | unsigned int val) | |
177 | { | |
178 | int ret; | |
179 | ||
180 | mutex_lock(&indio_dev->mlock); | |
181 | ret = ad5755_write_unlocked(indio_dev, reg, val); | |
182 | mutex_unlock(&indio_dev->mlock); | |
183 | ||
184 | return ret; | |
185 | } | |
186 | ||
187 | static int ad5755_write_ctrl(struct iio_dev *indio_dev, unsigned int channel, | |
188 | unsigned int reg, unsigned int val) | |
189 | { | |
190 | int ret; | |
191 | ||
192 | mutex_lock(&indio_dev->mlock); | |
193 | ret = ad5755_write_ctrl_unlocked(indio_dev, channel, reg, val); | |
194 | mutex_unlock(&indio_dev->mlock); | |
195 | ||
196 | return ret; | |
197 | } | |
198 | ||
199 | static int ad5755_read(struct iio_dev *indio_dev, unsigned int addr) | |
200 | { | |
201 | struct ad5755_state *st = iio_priv(indio_dev); | |
c499d029 LPC |
202 | int ret; |
203 | struct spi_transfer t[] = { | |
204 | { | |
205 | .tx_buf = &st->data[0].d8[1], | |
206 | .len = 3, | |
207 | .cs_change = 1, | |
208 | }, { | |
209 | .tx_buf = &st->data[1].d8[1], | |
210 | .rx_buf = &st->data[1].d8[1], | |
211 | .len = 3, | |
212 | }, | |
213 | }; | |
214 | ||
c499d029 LPC |
215 | mutex_lock(&indio_dev->mlock); |
216 | ||
217 | st->data[0].d32 = cpu_to_be32(AD5755_READ_FLAG | (addr << 16)); | |
218 | st->data[1].d32 = cpu_to_be32(AD5755_NOOP); | |
219 | ||
14543a00 | 220 | ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t)); |
c499d029 LPC |
221 | if (ret >= 0) |
222 | ret = be32_to_cpu(st->data[1].d32) & 0xffff; | |
223 | ||
224 | mutex_unlock(&indio_dev->mlock); | |
225 | ||
226 | return ret; | |
227 | } | |
228 | ||
229 | static int ad5755_update_dac_ctrl(struct iio_dev *indio_dev, | |
230 | unsigned int channel, unsigned int set, unsigned int clr) | |
231 | { | |
232 | struct ad5755_state *st = iio_priv(indio_dev); | |
233 | int ret; | |
234 | ||
235 | st->ctrl[channel] |= set; | |
236 | st->ctrl[channel] &= ~clr; | |
237 | ||
238 | ret = ad5755_write_ctrl_unlocked(indio_dev, channel, | |
239 | AD5755_CTRL_REG_DAC, st->ctrl[channel]); | |
240 | ||
241 | return ret; | |
242 | } | |
243 | ||
244 | static int ad5755_set_channel_pwr_down(struct iio_dev *indio_dev, | |
245 | unsigned int channel, bool pwr_down) | |
246 | { | |
247 | struct ad5755_state *st = iio_priv(indio_dev); | |
248 | unsigned int mask = BIT(channel); | |
249 | ||
250 | mutex_lock(&indio_dev->mlock); | |
251 | ||
252 | if ((bool)(st->pwr_down & mask) == pwr_down) | |
253 | goto out_unlock; | |
254 | ||
255 | if (!pwr_down) { | |
256 | st->pwr_down &= ~mask; | |
257 | ad5755_update_dac_ctrl(indio_dev, channel, | |
258 | AD5755_DAC_INT_EN | AD5755_DAC_DC_DC_EN, 0); | |
259 | udelay(200); | |
260 | ad5755_update_dac_ctrl(indio_dev, channel, | |
261 | AD5755_DAC_OUT_EN, 0); | |
262 | } else { | |
263 | st->pwr_down |= mask; | |
264 | ad5755_update_dac_ctrl(indio_dev, channel, | |
265 | 0, AD5755_DAC_INT_EN | AD5755_DAC_OUT_EN | | |
266 | AD5755_DAC_DC_DC_EN); | |
267 | } | |
268 | ||
269 | out_unlock: | |
270 | mutex_unlock(&indio_dev->mlock); | |
271 | ||
272 | return 0; | |
273 | } | |
274 | ||
275 | static const int ad5755_min_max_table[][2] = { | |
276 | [AD5755_MODE_VOLTAGE_0V_5V] = { 0, 5000 }, | |
277 | [AD5755_MODE_VOLTAGE_0V_10V] = { 0, 10000 }, | |
278 | [AD5755_MODE_VOLTAGE_PLUSMINUS_5V] = { -5000, 5000 }, | |
279 | [AD5755_MODE_VOLTAGE_PLUSMINUS_10V] = { -10000, 10000 }, | |
280 | [AD5755_MODE_CURRENT_4mA_20mA] = { 4, 20 }, | |
281 | [AD5755_MODE_CURRENT_0mA_20mA] = { 0, 20 }, | |
282 | [AD5755_MODE_CURRENT_0mA_24mA] = { 0, 24 }, | |
283 | }; | |
284 | ||
285 | static void ad5755_get_min_max(struct ad5755_state *st, | |
286 | struct iio_chan_spec const *chan, int *min, int *max) | |
287 | { | |
288 | enum ad5755_mode mode = st->ctrl[chan->channel] & 7; | |
289 | *min = ad5755_min_max_table[mode][0]; | |
290 | *max = ad5755_min_max_table[mode][1]; | |
291 | } | |
292 | ||
293 | static inline int ad5755_get_offset(struct ad5755_state *st, | |
294 | struct iio_chan_spec const *chan) | |
295 | { | |
296 | int min, max; | |
297 | ||
298 | ad5755_get_min_max(st, chan, &min, &max); | |
299 | return (min * (1 << chan->scan_type.realbits)) / (max - min); | |
300 | } | |
301 | ||
c499d029 LPC |
302 | static int ad5755_chan_reg_info(struct ad5755_state *st, |
303 | struct iio_chan_spec const *chan, long info, bool write, | |
304 | unsigned int *reg, unsigned int *shift, unsigned int *offset) | |
305 | { | |
306 | switch (info) { | |
307 | case IIO_CHAN_INFO_RAW: | |
308 | if (write) | |
309 | *reg = AD5755_WRITE_REG_DATA(chan->address); | |
310 | else | |
311 | *reg = AD5755_READ_REG_DATA(chan->address); | |
312 | *shift = chan->scan_type.shift; | |
313 | *offset = 0; | |
314 | break; | |
315 | case IIO_CHAN_INFO_CALIBBIAS: | |
316 | if (write) | |
317 | *reg = AD5755_WRITE_REG_OFFSET(chan->address); | |
318 | else | |
319 | *reg = AD5755_READ_REG_OFFSET(chan->address); | |
320 | *shift = st->chip_info->calib_shift; | |
321 | *offset = 32768; | |
322 | break; | |
323 | case IIO_CHAN_INFO_CALIBSCALE: | |
324 | if (write) | |
325 | *reg = AD5755_WRITE_REG_GAIN(chan->address); | |
326 | else | |
327 | *reg = AD5755_READ_REG_GAIN(chan->address); | |
328 | *shift = st->chip_info->calib_shift; | |
329 | *offset = 0; | |
330 | break; | |
331 | default: | |
332 | return -EINVAL; | |
333 | } | |
334 | ||
335 | return 0; | |
336 | } | |
337 | ||
338 | static int ad5755_read_raw(struct iio_dev *indio_dev, | |
339 | const struct iio_chan_spec *chan, int *val, int *val2, long info) | |
340 | { | |
341 | struct ad5755_state *st = iio_priv(indio_dev); | |
342 | unsigned int reg, shift, offset; | |
ae76751f | 343 | int min, max; |
c499d029 LPC |
344 | int ret; |
345 | ||
346 | switch (info) { | |
347 | case IIO_CHAN_INFO_SCALE: | |
ae76751f LPC |
348 | ad5755_get_min_max(st, chan, &min, &max); |
349 | *val = max - min; | |
350 | *val2 = chan->scan_type.realbits; | |
351 | return IIO_VAL_FRACTIONAL_LOG2; | |
c499d029 LPC |
352 | case IIO_CHAN_INFO_OFFSET: |
353 | *val = ad5755_get_offset(st, chan); | |
354 | return IIO_VAL_INT; | |
355 | default: | |
356 | ret = ad5755_chan_reg_info(st, chan, info, false, | |
357 | ®, &shift, &offset); | |
358 | if (ret) | |
359 | return ret; | |
360 | ||
361 | ret = ad5755_read(indio_dev, reg); | |
362 | if (ret < 0) | |
363 | return ret; | |
364 | ||
365 | *val = (ret - offset) >> shift; | |
366 | ||
367 | return IIO_VAL_INT; | |
368 | } | |
369 | ||
370 | return -EINVAL; | |
371 | } | |
372 | ||
373 | static int ad5755_write_raw(struct iio_dev *indio_dev, | |
374 | const struct iio_chan_spec *chan, int val, int val2, long info) | |
375 | { | |
376 | struct ad5755_state *st = iio_priv(indio_dev); | |
377 | unsigned int shift, reg, offset; | |
378 | int ret; | |
379 | ||
380 | ret = ad5755_chan_reg_info(st, chan, info, true, | |
381 | ®, &shift, &offset); | |
382 | if (ret) | |
383 | return ret; | |
384 | ||
385 | val <<= shift; | |
386 | val += offset; | |
387 | ||
388 | if (val < 0 || val > 0xffff) | |
389 | return -EINVAL; | |
390 | ||
391 | return ad5755_write(indio_dev, reg, val); | |
392 | } | |
393 | ||
394 | static ssize_t ad5755_read_powerdown(struct iio_dev *indio_dev, uintptr_t priv, | |
395 | const struct iio_chan_spec *chan, char *buf) | |
396 | { | |
397 | struct ad5755_state *st = iio_priv(indio_dev); | |
398 | ||
399 | return sprintf(buf, "%d\n", | |
400 | (bool)(st->pwr_down & (1 << chan->channel))); | |
401 | } | |
402 | ||
403 | static ssize_t ad5755_write_powerdown(struct iio_dev *indio_dev, uintptr_t priv, | |
404 | struct iio_chan_spec const *chan, const char *buf, size_t len) | |
405 | { | |
406 | bool pwr_down; | |
407 | int ret; | |
408 | ||
409 | ret = strtobool(buf, &pwr_down); | |
410 | if (ret) | |
411 | return ret; | |
412 | ||
413 | ret = ad5755_set_channel_pwr_down(indio_dev, chan->channel, pwr_down); | |
414 | return ret ? ret : len; | |
415 | } | |
416 | ||
417 | static const struct iio_info ad5755_info = { | |
418 | .read_raw = ad5755_read_raw, | |
419 | .write_raw = ad5755_write_raw, | |
c499d029 LPC |
420 | }; |
421 | ||
422 | static const struct iio_chan_spec_ext_info ad5755_ext_info[] = { | |
423 | { | |
424 | .name = "powerdown", | |
425 | .read = ad5755_read_powerdown, | |
426 | .write = ad5755_write_powerdown, | |
3704432f | 427 | .shared = IIO_SEPARATE, |
c499d029 LPC |
428 | }, |
429 | { }, | |
430 | }; | |
431 | ||
432 | #define AD5755_CHANNEL(_bits) { \ | |
433 | .indexed = 1, \ | |
434 | .output = 1, \ | |
8ac1f3df JC |
435 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ |
436 | BIT(IIO_CHAN_INFO_SCALE) | \ | |
437 | BIT(IIO_CHAN_INFO_OFFSET) | \ | |
438 | BIT(IIO_CHAN_INFO_CALIBSCALE) | \ | |
439 | BIT(IIO_CHAN_INFO_CALIBBIAS), \ | |
64665dd3 JC |
440 | .scan_type = { \ |
441 | .sign = 'u', \ | |
442 | .realbits = (_bits), \ | |
443 | .storagebits = 16, \ | |
444 | .shift = 16 - (_bits), \ | |
445 | }, \ | |
c499d029 LPC |
446 | .ext_info = ad5755_ext_info, \ |
447 | } | |
448 | ||
449 | static const struct ad5755_chip_info ad5755_chip_info_tbl[] = { | |
450 | [ID_AD5735] = { | |
451 | .channel_template = AD5755_CHANNEL(14), | |
452 | .has_voltage_out = true, | |
453 | .calib_shift = 4, | |
454 | }, | |
455 | [ID_AD5737] = { | |
456 | .channel_template = AD5755_CHANNEL(14), | |
457 | .has_voltage_out = false, | |
458 | .calib_shift = 4, | |
459 | }, | |
460 | [ID_AD5755] = { | |
461 | .channel_template = AD5755_CHANNEL(16), | |
462 | .has_voltage_out = true, | |
463 | .calib_shift = 0, | |
464 | }, | |
465 | [ID_AD5757] = { | |
466 | .channel_template = AD5755_CHANNEL(16), | |
467 | .has_voltage_out = false, | |
468 | .calib_shift = 0, | |
469 | }, | |
470 | }; | |
471 | ||
472 | static bool ad5755_is_valid_mode(struct ad5755_state *st, enum ad5755_mode mode) | |
473 | { | |
474 | switch (mode) { | |
475 | case AD5755_MODE_VOLTAGE_0V_5V: | |
476 | case AD5755_MODE_VOLTAGE_0V_10V: | |
477 | case AD5755_MODE_VOLTAGE_PLUSMINUS_5V: | |
478 | case AD5755_MODE_VOLTAGE_PLUSMINUS_10V: | |
479 | return st->chip_info->has_voltage_out; | |
480 | case AD5755_MODE_CURRENT_4mA_20mA: | |
481 | case AD5755_MODE_CURRENT_0mA_20mA: | |
482 | case AD5755_MODE_CURRENT_0mA_24mA: | |
483 | return true; | |
484 | default: | |
485 | return false; | |
486 | } | |
487 | } | |
488 | ||
fc52692c GKH |
489 | static int ad5755_setup_pdata(struct iio_dev *indio_dev, |
490 | const struct ad5755_platform_data *pdata) | |
c499d029 LPC |
491 | { |
492 | struct ad5755_state *st = iio_priv(indio_dev); | |
c499d029 LPC |
493 | unsigned int val; |
494 | unsigned int i; | |
369d0e20 | 495 | int ret; |
c499d029 LPC |
496 | |
497 | if (pdata->dc_dc_phase > AD5755_DC_DC_PHASE_90_DEGREE || | |
498 | pdata->dc_dc_freq > AD5755_DC_DC_FREQ_650kHZ || | |
499 | pdata->dc_dc_maxv > AD5755_DC_DC_MAXV_29V5) | |
500 | return -EINVAL; | |
501 | ||
502 | val = pdata->dc_dc_maxv << AD5755_DC_DC_MAXV; | |
503 | val |= pdata->dc_dc_freq << AD5755_DC_DC_FREQ_SHIFT; | |
504 | val |= pdata->dc_dc_phase << AD5755_DC_DC_PHASE_SHIFT; | |
505 | if (pdata->ext_dc_dc_compenstation_resistor) | |
506 | val |= AD5755_EXT_DC_DC_COMP_RES; | |
507 | ||
508 | ret = ad5755_write_ctrl(indio_dev, 0, AD5755_CTRL_REG_DC_DC, val); | |
509 | if (ret < 0) | |
510 | return ret; | |
511 | ||
512 | for (i = 0; i < ARRAY_SIZE(pdata->dac); ++i) { | |
513 | val = pdata->dac[i].slew.step_size << | |
514 | AD5755_SLEW_STEP_SIZE_SHIFT; | |
515 | val |= pdata->dac[i].slew.rate << | |
516 | AD5755_SLEW_RATE_SHIFT; | |
517 | if (pdata->dac[i].slew.enable) | |
518 | val |= AD5755_SLEW_ENABLE; | |
519 | ||
520 | ret = ad5755_write_ctrl(indio_dev, i, | |
521 | AD5755_CTRL_REG_SLEW, val); | |
522 | if (ret < 0) | |
523 | return ret; | |
524 | } | |
525 | ||
526 | for (i = 0; i < ARRAY_SIZE(pdata->dac); ++i) { | |
527 | if (!ad5755_is_valid_mode(st, pdata->dac[i].mode)) | |
528 | return -EINVAL; | |
529 | ||
530 | val = 0; | |
531 | if (!pdata->dac[i].ext_current_sense_resistor) | |
532 | val |= AD5755_DAC_INT_CURRENT_SENSE_RESISTOR; | |
533 | if (pdata->dac[i].enable_voltage_overrange) | |
534 | val |= AD5755_DAC_VOLTAGE_OVERRANGE_EN; | |
535 | val |= pdata->dac[i].mode; | |
536 | ||
537 | ret = ad5755_update_dac_ctrl(indio_dev, i, val, 0); | |
538 | if (ret < 0) | |
539 | return ret; | |
540 | } | |
541 | ||
542 | return 0; | |
543 | } | |
544 | ||
fc52692c | 545 | static bool ad5755_is_voltage_mode(enum ad5755_mode mode) |
c499d029 LPC |
546 | { |
547 | switch (mode) { | |
548 | case AD5755_MODE_VOLTAGE_0V_5V: | |
549 | case AD5755_MODE_VOLTAGE_0V_10V: | |
550 | case AD5755_MODE_VOLTAGE_PLUSMINUS_5V: | |
551 | case AD5755_MODE_VOLTAGE_PLUSMINUS_10V: | |
552 | return true; | |
553 | default: | |
554 | return false; | |
555 | } | |
556 | } | |
557 | ||
fc52692c GKH |
558 | static int ad5755_init_channels(struct iio_dev *indio_dev, |
559 | const struct ad5755_platform_data *pdata) | |
c499d029 LPC |
560 | { |
561 | struct ad5755_state *st = iio_priv(indio_dev); | |
562 | struct iio_chan_spec *channels = st->channels; | |
563 | unsigned int i; | |
564 | ||
565 | for (i = 0; i < AD5755_NUM_CHANNELS; ++i) { | |
566 | channels[i] = st->chip_info->channel_template; | |
567 | channels[i].channel = i; | |
568 | channels[i].address = i; | |
569 | if (pdata && ad5755_is_voltage_mode(pdata->dac[i].mode)) | |
570 | channels[i].type = IIO_VOLTAGE; | |
571 | else | |
572 | channels[i].type = IIO_CURRENT; | |
573 | } | |
574 | ||
575 | indio_dev->channels = channels; | |
576 | ||
577 | return 0; | |
578 | } | |
579 | ||
580 | #define AD5755_DEFAULT_DAC_PDATA { \ | |
581 | .mode = AD5755_MODE_CURRENT_4mA_20mA, \ | |
582 | .ext_current_sense_resistor = true, \ | |
583 | .enable_voltage_overrange = false, \ | |
584 | .slew = { \ | |
585 | .enable = false, \ | |
586 | .rate = AD5755_SLEW_RATE_64k, \ | |
587 | .step_size = AD5755_SLEW_STEP_SIZE_1, \ | |
588 | }, \ | |
589 | } | |
590 | ||
591 | static const struct ad5755_platform_data ad5755_default_pdata = { | |
592 | .ext_dc_dc_compenstation_resistor = false, | |
593 | .dc_dc_phase = AD5755_DC_DC_PHASE_ALL_SAME_EDGE, | |
594 | .dc_dc_freq = AD5755_DC_DC_FREQ_410kHZ, | |
595 | .dc_dc_maxv = AD5755_DC_DC_MAXV_23V, | |
596 | .dac = { | |
597 | [0] = AD5755_DEFAULT_DAC_PDATA, | |
598 | [1] = AD5755_DEFAULT_DAC_PDATA, | |
599 | [2] = AD5755_DEFAULT_DAC_PDATA, | |
600 | [3] = AD5755_DEFAULT_DAC_PDATA, | |
601 | }, | |
602 | }; | |
603 | ||
c9474599 SN |
604 | #ifdef CONFIG_OF |
605 | static struct ad5755_platform_data *ad5755_parse_dt(struct device *dev) | |
606 | { | |
607 | struct device_node *np = dev->of_node; | |
608 | struct device_node *pp; | |
609 | struct ad5755_platform_data *pdata; | |
610 | unsigned int tmp; | |
611 | unsigned int tmparray[3]; | |
612 | int devnr, i; | |
613 | ||
614 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | |
615 | if (!pdata) | |
616 | return NULL; | |
617 | ||
618 | pdata->ext_dc_dc_compenstation_resistor = | |
619 | of_property_read_bool(np, "adi,ext-dc-dc-compenstation-resistor"); | |
620 | ||
621 | if (!of_property_read_u32(np, "adi,dc-dc-phase", &tmp)) | |
622 | pdata->dc_dc_phase = tmp; | |
623 | else | |
624 | pdata->dc_dc_phase = AD5755_DC_DC_PHASE_ALL_SAME_EDGE; | |
625 | ||
626 | pdata->dc_dc_freq = AD5755_DC_DC_FREQ_410kHZ; | |
627 | if (!of_property_read_u32(np, "adi,dc-dc-freq-hz", &tmp)) { | |
628 | for (i = 0; i < ARRAY_SIZE(ad5755_dcdc_freq_table); i++) { | |
629 | if (tmp == ad5755_dcdc_freq_table[i][0]) { | |
630 | pdata->dc_dc_freq = ad5755_dcdc_freq_table[i][1]; | |
631 | break; | |
632 | } | |
633 | } | |
634 | ||
635 | if (i == ARRAY_SIZE(ad5755_dcdc_freq_table)) { | |
636 | dev_err(dev, | |
637 | "adi,dc-dc-freq out of range selecting 410kHz"); | |
638 | } | |
639 | } | |
640 | ||
641 | pdata->dc_dc_maxv = AD5755_DC_DC_MAXV_23V; | |
642 | if (!of_property_read_u32(np, "adi,dc-dc-max-microvolt", &tmp)) { | |
643 | for (i = 0; i < ARRAY_SIZE(ad5755_dcdc_maxv_table); i++) { | |
644 | if (tmp == ad5755_dcdc_maxv_table[i][0]) { | |
645 | pdata->dc_dc_maxv = ad5755_dcdc_maxv_table[i][1]; | |
646 | break; | |
647 | } | |
648 | } | |
649 | if (i == ARRAY_SIZE(ad5755_dcdc_maxv_table)) { | |
650 | dev_err(dev, | |
651 | "adi,dc-dc-maxv out of range selecting 23V"); | |
652 | } | |
653 | } | |
654 | ||
655 | devnr = 0; | |
656 | for_each_child_of_node(np, pp) { | |
9d47964b | 657 | if (devnr >= AD5755_NUM_CHANNELS) { |
c9474599 SN |
658 | dev_err(dev, |
659 | "There is to many channels defined in DT\n"); | |
660 | goto error_out; | |
661 | } | |
662 | ||
663 | if (!of_property_read_u32(pp, "adi,mode", &tmp)) | |
664 | pdata->dac[devnr].mode = tmp; | |
665 | else | |
666 | pdata->dac[devnr].mode = AD5755_MODE_CURRENT_4mA_20mA; | |
667 | ||
668 | pdata->dac[devnr].ext_current_sense_resistor = | |
669 | of_property_read_bool(pp, "adi,ext-current-sense-resistor"); | |
670 | ||
671 | pdata->dac[devnr].enable_voltage_overrange = | |
672 | of_property_read_bool(pp, "adi,enable-voltage-overrange"); | |
673 | ||
674 | if (!of_property_read_u32_array(pp, "adi,slew", tmparray, 3)) { | |
675 | pdata->dac[devnr].slew.enable = tmparray[0]; | |
676 | ||
677 | pdata->dac[devnr].slew.rate = AD5755_SLEW_RATE_64k; | |
678 | for (i = 0; i < ARRAY_SIZE(ad5755_slew_rate_table); i++) { | |
679 | if (tmparray[1] == ad5755_slew_rate_table[i][0]) { | |
680 | pdata->dac[devnr].slew.rate = | |
681 | ad5755_slew_rate_table[i][1]; | |
682 | break; | |
683 | } | |
684 | } | |
685 | if (i == ARRAY_SIZE(ad5755_slew_rate_table)) { | |
686 | dev_err(dev, | |
687 | "channel %d slew rate out of range selecting 64kHz", | |
688 | devnr); | |
689 | } | |
690 | ||
691 | pdata->dac[devnr].slew.step_size = AD5755_SLEW_STEP_SIZE_1; | |
692 | for (i = 0; i < ARRAY_SIZE(ad5755_slew_step_table); i++) { | |
693 | if (tmparray[2] == ad5755_slew_step_table[i][0]) { | |
694 | pdata->dac[devnr].slew.step_size = | |
695 | ad5755_slew_step_table[i][1]; | |
696 | break; | |
697 | } | |
698 | } | |
699 | if (i == ARRAY_SIZE(ad5755_slew_step_table)) { | |
700 | dev_err(dev, | |
701 | "channel %d slew step size out of range selecting 1 LSB", | |
702 | devnr); | |
703 | } | |
704 | } else { | |
705 | pdata->dac[devnr].slew.enable = false; | |
706 | pdata->dac[devnr].slew.rate = AD5755_SLEW_RATE_64k; | |
707 | pdata->dac[devnr].slew.step_size = | |
708 | AD5755_SLEW_STEP_SIZE_1; | |
709 | } | |
710 | devnr++; | |
711 | } | |
712 | ||
713 | return pdata; | |
714 | ||
715 | error_out: | |
716 | devm_kfree(dev, pdata); | |
717 | return NULL; | |
718 | } | |
719 | #else | |
720 | static | |
721 | struct ad5755_platform_data *ad5755_parse_dt(struct device *dev) | |
722 | { | |
723 | return NULL; | |
724 | } | |
725 | #endif | |
726 | ||
fc52692c | 727 | static int ad5755_probe(struct spi_device *spi) |
c499d029 LPC |
728 | { |
729 | enum ad5755_type type = spi_get_device_id(spi)->driver_data; | |
730 | const struct ad5755_platform_data *pdata = dev_get_platdata(&spi->dev); | |
731 | struct iio_dev *indio_dev; | |
732 | struct ad5755_state *st; | |
733 | int ret; | |
734 | ||
fd047294 | 735 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); |
c499d029 LPC |
736 | if (indio_dev == NULL) { |
737 | dev_err(&spi->dev, "Failed to allocate iio device\n"); | |
738 | return -ENOMEM; | |
739 | } | |
740 | ||
741 | st = iio_priv(indio_dev); | |
742 | spi_set_drvdata(spi, indio_dev); | |
743 | ||
744 | st->chip_info = &ad5755_chip_info_tbl[type]; | |
745 | st->spi = spi; | |
746 | st->pwr_down = 0xf; | |
747 | ||
748 | indio_dev->dev.parent = &spi->dev; | |
749 | indio_dev->name = spi_get_device_id(spi)->name; | |
750 | indio_dev->info = &ad5755_info; | |
751 | indio_dev->modes = INDIO_DIRECT_MODE; | |
752 | indio_dev->num_channels = AD5755_NUM_CHANNELS; | |
753 | ||
c9474599 SN |
754 | if (spi->dev.of_node) |
755 | pdata = ad5755_parse_dt(&spi->dev); | |
756 | else | |
757 | pdata = spi->dev.platform_data; | |
758 | ||
759 | if (!pdata) { | |
760 | dev_warn(&spi->dev, "no platform data? using default\n"); | |
c499d029 | 761 | pdata = &ad5755_default_pdata; |
c9474599 | 762 | } |
c499d029 LPC |
763 | |
764 | ret = ad5755_init_channels(indio_dev, pdata); | |
765 | if (ret) | |
fd047294 | 766 | return ret; |
c499d029 LPC |
767 | |
768 | ret = ad5755_setup_pdata(indio_dev, pdata); | |
769 | if (ret) | |
fd047294 | 770 | return ret; |
c499d029 | 771 | |
1baeec9c | 772 | return devm_iio_device_register(&spi->dev, indio_dev); |
c499d029 LPC |
773 | } |
774 | ||
775 | static const struct spi_device_id ad5755_id[] = { | |
776 | { "ad5755", ID_AD5755 }, | |
777 | { "ad5755-1", ID_AD5755 }, | |
778 | { "ad5757", ID_AD5757 }, | |
779 | { "ad5735", ID_AD5735 }, | |
780 | { "ad5737", ID_AD5737 }, | |
781 | {} | |
782 | }; | |
783 | MODULE_DEVICE_TABLE(spi, ad5755_id); | |
784 | ||
c9474599 SN |
785 | static const struct of_device_id ad5755_of_match[] = { |
786 | { .compatible = "adi,ad5755" }, | |
787 | { .compatible = "adi,ad5755-1" }, | |
788 | { .compatible = "adi,ad5757" }, | |
789 | { .compatible = "adi,ad5735" }, | |
790 | { .compatible = "adi,ad5737" }, | |
791 | { } | |
792 | }; | |
793 | MODULE_DEVICE_TABLE(of, ad5755_of_match); | |
794 | ||
c499d029 LPC |
795 | static struct spi_driver ad5755_driver = { |
796 | .driver = { | |
797 | .name = "ad5755", | |
c499d029 LPC |
798 | }, |
799 | .probe = ad5755_probe, | |
c499d029 LPC |
800 | .id_table = ad5755_id, |
801 | }; | |
802 | module_spi_driver(ad5755_driver); | |
803 | ||
804 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | |
805 | MODULE_DESCRIPTION("Analog Devices AD5755/55-1/57/35/37 DAC"); | |
806 | MODULE_LICENSE("GPL v2"); |