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