diff options
author | Lars-Peter Clausen <lars@metafoo.de> | 2012-09-17 05:24:00 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2012-09-17 15:55:54 -0400 |
commit | c499d029d80534a01e858ce9fd1687f2042f7a86 (patch) | |
tree | 3073c67c56c3e400ed6760851442705dd568ba8a /drivers/iio | |
parent | b2b79ffa40d7ae40115631660ff8b6da3cf989b6 (diff) |
iio:dac: Add ad5755 driver
This patch adds support for the AD5755, AD5755-1, AD5757, AD5735, AD5737 16 and
14 bit quad-channel DACs. The AD5757/AD5737 only have current outputs, but
for the AD5755/AD5757 each of the outputs can be configured to either be a
voltage or a current output. We only allow to configure this at device probe
time since usually this needs to match the external circuitry and should not be
changed on the fly.
A few trivial formatting changes on merge.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r-- | drivers/iio/dac/Kconfig | 11 | ||||
-rw-r--r-- | drivers/iio/dac/Makefile | 1 | ||||
-rw-r--r-- | drivers/iio/dac/ad5755.c | 650 |
3 files changed, 662 insertions, 0 deletions
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index 78452630f85d..b1c0ee5294ca 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig | |||
@@ -77,6 +77,17 @@ config AD5504 | |||
77 | To compile this driver as a module, choose M here: the | 77 | To compile this driver as a module, choose M here: the |
78 | module will be called ad5504. | 78 | module will be called ad5504. |
79 | 79 | ||
80 | config AD5755 | ||
81 | tristate "Analog Devices AD5755/AD5755-1/AD5757/AD5735/AD5737 DAC driver" | ||
82 | depends on SPI_MASTER | ||
83 | help | ||
84 | Say yes here to build support for Analog Devices AD5755, AD5755-1, | ||
85 | AD5757, AD5735, AD5737 quad channel Digital to | ||
86 | Analog Converter. | ||
87 | |||
88 | To compile this driver as a module, choose M here: the | ||
89 | module will be called ad5755. | ||
90 | |||
80 | config AD5764 | 91 | config AD5764 |
81 | tristate "Analog Devices AD5764/64R/44/44R DAC driver" | 92 | tristate "Analog Devices AD5764/64R/44/44R DAC driver" |
82 | depends on SPI_MASTER | 93 | depends on SPI_MASTER |
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index 9ea3ceeefc07..c0d333b23ba3 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile | |||
@@ -9,6 +9,7 @@ obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o | |||
9 | obj-$(CONFIG_AD5064) += ad5064.o | 9 | obj-$(CONFIG_AD5064) += ad5064.o |
10 | obj-$(CONFIG_AD5504) += ad5504.o | 10 | obj-$(CONFIG_AD5504) += ad5504.o |
11 | obj-$(CONFIG_AD5446) += ad5446.o | 11 | obj-$(CONFIG_AD5446) += ad5446.o |
12 | obj-$(CONFIG_AD5755) += ad5755.o | ||
12 | obj-$(CONFIG_AD5764) += ad5764.o | 13 | obj-$(CONFIG_AD5764) += ad5764.o |
13 | obj-$(CONFIG_AD5791) += ad5791.o | 14 | obj-$(CONFIG_AD5791) += ad5791.o |
14 | obj-$(CONFIG_AD5686) += ad5686.o | 15 | obj-$(CONFIG_AD5686) += ad5686.o |
diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c new file mode 100644 index 000000000000..e6dbe5ff7e5a --- /dev/null +++ b/drivers/iio/dac/ad5755.c | |||
@@ -0,0 +1,650 @@ | |||
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> | ||
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 { | ||
100 | u32 d32; | ||
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 | |||
112 | static int ad5755_write_unlocked(struct iio_dev *indio_dev, | ||
113 | unsigned int reg, unsigned int val) | ||
114 | { | ||
115 | struct ad5755_state *st = iio_priv(indio_dev); | ||
116 | |||
117 | st->data[0].d32 = cpu_to_be32((reg << 16) | val); | ||
118 | |||
119 | return spi_write(st->spi, &st->data[0].d8[1], 3); | ||
120 | } | ||
121 | |||
122 | static int ad5755_write_ctrl_unlocked(struct iio_dev *indio_dev, | ||
123 | unsigned int channel, unsigned int reg, unsigned int val) | ||
124 | { | ||
125 | return ad5755_write_unlocked(indio_dev, | ||
126 | AD5755_WRITE_REG_CTRL(channel), (reg << 13) | val); | ||
127 | } | ||
128 | |||
129 | static int ad5755_write(struct iio_dev *indio_dev, unsigned int reg, | ||
130 | unsigned int val) | ||
131 | { | ||
132 | int ret; | ||
133 | |||
134 | mutex_lock(&indio_dev->mlock); | ||
135 | ret = ad5755_write_unlocked(indio_dev, reg, val); | ||
136 | mutex_unlock(&indio_dev->mlock); | ||
137 | |||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | static int ad5755_write_ctrl(struct iio_dev *indio_dev, unsigned int channel, | ||
142 | unsigned int reg, unsigned int val) | ||
143 | { | ||
144 | int ret; | ||
145 | |||
146 | mutex_lock(&indio_dev->mlock); | ||
147 | ret = ad5755_write_ctrl_unlocked(indio_dev, channel, reg, val); | ||
148 | mutex_unlock(&indio_dev->mlock); | ||
149 | |||
150 | return ret; | ||
151 | } | ||
152 | |||
153 | static int ad5755_read(struct iio_dev *indio_dev, unsigned int addr) | ||
154 | { | ||
155 | struct ad5755_state *st = iio_priv(indio_dev); | ||
156 | struct spi_message m; | ||
157 | int ret; | ||
158 | struct spi_transfer t[] = { | ||
159 | { | ||
160 | .tx_buf = &st->data[0].d8[1], | ||
161 | .len = 3, | ||
162 | .cs_change = 1, | ||
163 | }, { | ||
164 | .tx_buf = &st->data[1].d8[1], | ||
165 | .rx_buf = &st->data[1].d8[1], | ||
166 | .len = 3, | ||
167 | }, | ||
168 | }; | ||
169 | |||
170 | spi_message_init(&m); | ||
171 | spi_message_add_tail(&t[0], &m); | ||
172 | spi_message_add_tail(&t[1], &m); | ||
173 | |||
174 | mutex_lock(&indio_dev->mlock); | ||
175 | |||
176 | st->data[0].d32 = cpu_to_be32(AD5755_READ_FLAG | (addr << 16)); | ||
177 | st->data[1].d32 = cpu_to_be32(AD5755_NOOP); | ||
178 | |||
179 | ret = spi_sync(st->spi, &m); | ||
180 | if (ret >= 0) | ||
181 | ret = be32_to_cpu(st->data[1].d32) & 0xffff; | ||
182 | |||
183 | mutex_unlock(&indio_dev->mlock); | ||
184 | |||
185 | return ret; | ||
186 | } | ||
187 | |||
188 | static int ad5755_update_dac_ctrl(struct iio_dev *indio_dev, | ||
189 | unsigned int channel, unsigned int set, unsigned int clr) | ||
190 | { | ||
191 | struct ad5755_state *st = iio_priv(indio_dev); | ||
192 | int ret; | ||
193 | |||
194 | st->ctrl[channel] |= set; | ||
195 | st->ctrl[channel] &= ~clr; | ||
196 | |||
197 | ret = ad5755_write_ctrl_unlocked(indio_dev, channel, | ||
198 | AD5755_CTRL_REG_DAC, st->ctrl[channel]); | ||
199 | |||
200 | return ret; | ||
201 | } | ||
202 | |||
203 | static int ad5755_set_channel_pwr_down(struct iio_dev *indio_dev, | ||
204 | unsigned int channel, bool pwr_down) | ||
205 | { | ||
206 | struct ad5755_state *st = iio_priv(indio_dev); | ||
207 | unsigned int mask = BIT(channel); | ||
208 | |||
209 | mutex_lock(&indio_dev->mlock); | ||
210 | |||
211 | if ((bool)(st->pwr_down & mask) == pwr_down) | ||
212 | goto out_unlock; | ||
213 | |||
214 | if (!pwr_down) { | ||
215 | st->pwr_down &= ~mask; | ||
216 | ad5755_update_dac_ctrl(indio_dev, channel, | ||
217 | AD5755_DAC_INT_EN | AD5755_DAC_DC_DC_EN, 0); | ||
218 | udelay(200); | ||
219 | ad5755_update_dac_ctrl(indio_dev, channel, | ||
220 | AD5755_DAC_OUT_EN, 0); | ||
221 | } else { | ||
222 | st->pwr_down |= mask; | ||
223 | ad5755_update_dac_ctrl(indio_dev, channel, | ||
224 | 0, AD5755_DAC_INT_EN | AD5755_DAC_OUT_EN | | ||
225 | AD5755_DAC_DC_DC_EN); | ||
226 | } | ||
227 | |||
228 | out_unlock: | ||
229 | mutex_unlock(&indio_dev->mlock); | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static const int ad5755_min_max_table[][2] = { | ||
235 | [AD5755_MODE_VOLTAGE_0V_5V] = { 0, 5000 }, | ||
236 | [AD5755_MODE_VOLTAGE_0V_10V] = { 0, 10000 }, | ||
237 | [AD5755_MODE_VOLTAGE_PLUSMINUS_5V] = { -5000, 5000 }, | ||
238 | [AD5755_MODE_VOLTAGE_PLUSMINUS_10V] = { -10000, 10000 }, | ||
239 | [AD5755_MODE_CURRENT_4mA_20mA] = { 4, 20 }, | ||
240 | [AD5755_MODE_CURRENT_0mA_20mA] = { 0, 20 }, | ||
241 | [AD5755_MODE_CURRENT_0mA_24mA] = { 0, 24 }, | ||
242 | }; | ||
243 | |||
244 | static void ad5755_get_min_max(struct ad5755_state *st, | ||
245 | struct iio_chan_spec const *chan, int *min, int *max) | ||
246 | { | ||
247 | enum ad5755_mode mode = st->ctrl[chan->channel] & 7; | ||
248 | *min = ad5755_min_max_table[mode][0]; | ||
249 | *max = ad5755_min_max_table[mode][1]; | ||
250 | } | ||
251 | |||
252 | static inline int ad5755_get_offset(struct ad5755_state *st, | ||
253 | struct iio_chan_spec const *chan) | ||
254 | { | ||
255 | int min, max; | ||
256 | |||
257 | ad5755_get_min_max(st, chan, &min, &max); | ||
258 | return (min * (1 << chan->scan_type.realbits)) / (max - min); | ||
259 | } | ||
260 | |||
261 | static inline int ad5755_get_scale(struct ad5755_state *st, | ||
262 | struct iio_chan_spec const *chan) | ||
263 | { | ||
264 | int min, max; | ||
265 | |||
266 | ad5755_get_min_max(st, chan, &min, &max); | ||
267 | return ((max - min) * 1000000000ULL) >> chan->scan_type.realbits; | ||
268 | } | ||
269 | |||
270 | static int ad5755_chan_reg_info(struct ad5755_state *st, | ||
271 | struct iio_chan_spec const *chan, long info, bool write, | ||
272 | unsigned int *reg, unsigned int *shift, unsigned int *offset) | ||
273 | { | ||
274 | switch (info) { | ||
275 | case IIO_CHAN_INFO_RAW: | ||
276 | if (write) | ||
277 | *reg = AD5755_WRITE_REG_DATA(chan->address); | ||
278 | else | ||
279 | *reg = AD5755_READ_REG_DATA(chan->address); | ||
280 | *shift = chan->scan_type.shift; | ||
281 | *offset = 0; | ||
282 | break; | ||
283 | case IIO_CHAN_INFO_CALIBBIAS: | ||
284 | if (write) | ||
285 | *reg = AD5755_WRITE_REG_OFFSET(chan->address); | ||
286 | else | ||
287 | *reg = AD5755_READ_REG_OFFSET(chan->address); | ||
288 | *shift = st->chip_info->calib_shift; | ||
289 | *offset = 32768; | ||
290 | break; | ||
291 | case IIO_CHAN_INFO_CALIBSCALE: | ||
292 | if (write) | ||
293 | *reg = AD5755_WRITE_REG_GAIN(chan->address); | ||
294 | else | ||
295 | *reg = AD5755_READ_REG_GAIN(chan->address); | ||
296 | *shift = st->chip_info->calib_shift; | ||
297 | *offset = 0; | ||
298 | break; | ||
299 | default: | ||
300 | return -EINVAL; | ||
301 | } | ||
302 | |||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | static int ad5755_read_raw(struct iio_dev *indio_dev, | ||
307 | const struct iio_chan_spec *chan, int *val, int *val2, long info) | ||
308 | { | ||
309 | struct ad5755_state *st = iio_priv(indio_dev); | ||
310 | unsigned int reg, shift, offset; | ||
311 | int ret; | ||
312 | |||
313 | switch (info) { | ||
314 | case IIO_CHAN_INFO_SCALE: | ||
315 | *val = 0; | ||
316 | *val2 = ad5755_get_scale(st, chan); | ||
317 | return IIO_VAL_INT_PLUS_NANO; | ||
318 | case IIO_CHAN_INFO_OFFSET: | ||
319 | *val = ad5755_get_offset(st, chan); | ||
320 | return IIO_VAL_INT; | ||
321 | default: | ||
322 | ret = ad5755_chan_reg_info(st, chan, info, false, | ||
323 | ®, &shift, &offset); | ||
324 | if (ret) | ||
325 | return ret; | ||
326 | |||
327 | ret = ad5755_read(indio_dev, reg); | ||
328 | if (ret < 0) | ||
329 | return ret; | ||
330 | |||
331 | *val = (ret - offset) >> shift; | ||
332 | |||
333 | return IIO_VAL_INT; | ||
334 | } | ||
335 | |||
336 | return -EINVAL; | ||
337 | } | ||
338 | |||
339 | static int ad5755_write_raw(struct iio_dev *indio_dev, | ||
340 | const struct iio_chan_spec *chan, int val, int val2, long info) | ||
341 | { | ||
342 | struct ad5755_state *st = iio_priv(indio_dev); | ||
343 | unsigned int shift, reg, offset; | ||
344 | int ret; | ||
345 | |||
346 | ret = ad5755_chan_reg_info(st, chan, info, true, | ||
347 | ®, &shift, &offset); | ||
348 | if (ret) | ||
349 | return ret; | ||
350 | |||
351 | val <<= shift; | ||
352 | val += offset; | ||
353 | |||
354 | if (val < 0 || val > 0xffff) | ||
355 | return -EINVAL; | ||
356 | |||
357 | return ad5755_write(indio_dev, reg, val); | ||
358 | } | ||
359 | |||
360 | static ssize_t ad5755_read_powerdown(struct iio_dev *indio_dev, uintptr_t priv, | ||
361 | const struct iio_chan_spec *chan, char *buf) | ||
362 | { | ||
363 | struct ad5755_state *st = iio_priv(indio_dev); | ||
364 | |||
365 | return sprintf(buf, "%d\n", | ||
366 | (bool)(st->pwr_down & (1 << chan->channel))); | ||
367 | } | ||
368 | |||
369 | static ssize_t ad5755_write_powerdown(struct iio_dev *indio_dev, uintptr_t priv, | ||
370 | struct iio_chan_spec const *chan, const char *buf, size_t len) | ||
371 | { | ||
372 | bool pwr_down; | ||
373 | int ret; | ||
374 | |||
375 | ret = strtobool(buf, &pwr_down); | ||
376 | if (ret) | ||
377 | return ret; | ||
378 | |||
379 | ret = ad5755_set_channel_pwr_down(indio_dev, chan->channel, pwr_down); | ||
380 | return ret ? ret : len; | ||
381 | } | ||
382 | |||
383 | static const struct iio_info ad5755_info = { | ||
384 | .read_raw = ad5755_read_raw, | ||
385 | .write_raw = ad5755_write_raw, | ||
386 | .driver_module = THIS_MODULE, | ||
387 | }; | ||
388 | |||
389 | static const struct iio_chan_spec_ext_info ad5755_ext_info[] = { | ||
390 | { | ||
391 | .name = "powerdown", | ||
392 | .read = ad5755_read_powerdown, | ||
393 | .write = ad5755_write_powerdown, | ||
394 | }, | ||
395 | { }, | ||
396 | }; | ||
397 | |||
398 | #define AD5755_CHANNEL(_bits) { \ | ||
399 | .indexed = 1, \ | ||
400 | .output = 1, \ | ||
401 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ | ||
402 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT | \ | ||
403 | IIO_CHAN_INFO_OFFSET_SEPARATE_BIT | \ | ||
404 | IIO_CHAN_INFO_CALIBSCALE_SEPARATE_BIT | \ | ||
405 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT, \ | ||
406 | .scan_type = IIO_ST('u', (_bits), 16, 16 - (_bits)), \ | ||
407 | .ext_info = ad5755_ext_info, \ | ||
408 | } | ||
409 | |||
410 | static const struct ad5755_chip_info ad5755_chip_info_tbl[] = { | ||
411 | [ID_AD5735] = { | ||
412 | .channel_template = AD5755_CHANNEL(14), | ||
413 | .has_voltage_out = true, | ||
414 | .calib_shift = 4, | ||
415 | }, | ||
416 | [ID_AD5737] = { | ||
417 | .channel_template = AD5755_CHANNEL(14), | ||
418 | .has_voltage_out = false, | ||
419 | .calib_shift = 4, | ||
420 | }, | ||
421 | [ID_AD5755] = { | ||
422 | .channel_template = AD5755_CHANNEL(16), | ||
423 | .has_voltage_out = true, | ||
424 | .calib_shift = 0, | ||
425 | }, | ||
426 | [ID_AD5757] = { | ||
427 | .channel_template = AD5755_CHANNEL(16), | ||
428 | .has_voltage_out = false, | ||
429 | .calib_shift = 0, | ||
430 | }, | ||
431 | }; | ||
432 | |||
433 | static bool ad5755_is_valid_mode(struct ad5755_state *st, enum ad5755_mode mode) | ||
434 | { | ||
435 | switch (mode) { | ||
436 | case AD5755_MODE_VOLTAGE_0V_5V: | ||
437 | case AD5755_MODE_VOLTAGE_0V_10V: | ||
438 | case AD5755_MODE_VOLTAGE_PLUSMINUS_5V: | ||
439 | case AD5755_MODE_VOLTAGE_PLUSMINUS_10V: | ||
440 | return st->chip_info->has_voltage_out; | ||
441 | case AD5755_MODE_CURRENT_4mA_20mA: | ||
442 | case AD5755_MODE_CURRENT_0mA_20mA: | ||
443 | case AD5755_MODE_CURRENT_0mA_24mA: | ||
444 | return true; | ||
445 | default: | ||
446 | return false; | ||
447 | } | ||
448 | } | ||
449 | |||
450 | static int __devinit ad5755_setup_pdata(struct iio_dev *indio_dev, | ||
451 | const struct ad5755_platform_data *pdata) | ||
452 | { | ||
453 | struct ad5755_state *st = iio_priv(indio_dev); | ||
454 | unsigned int ret; | ||
455 | unsigned int val; | ||
456 | unsigned int i; | ||
457 | |||
458 | if (pdata->dc_dc_phase > AD5755_DC_DC_PHASE_90_DEGREE || | ||
459 | pdata->dc_dc_freq > AD5755_DC_DC_FREQ_650kHZ || | ||
460 | pdata->dc_dc_maxv > AD5755_DC_DC_MAXV_29V5) | ||
461 | return -EINVAL; | ||
462 | |||
463 | val = pdata->dc_dc_maxv << AD5755_DC_DC_MAXV; | ||
464 | val |= pdata->dc_dc_freq << AD5755_DC_DC_FREQ_SHIFT; | ||
465 | val |= pdata->dc_dc_phase << AD5755_DC_DC_PHASE_SHIFT; | ||
466 | if (pdata->ext_dc_dc_compenstation_resistor) | ||
467 | val |= AD5755_EXT_DC_DC_COMP_RES; | ||
468 | |||
469 | ret = ad5755_write_ctrl(indio_dev, 0, AD5755_CTRL_REG_DC_DC, val); | ||
470 | if (ret < 0) | ||
471 | return ret; | ||
472 | |||
473 | for (i = 0; i < ARRAY_SIZE(pdata->dac); ++i) { | ||
474 | val = pdata->dac[i].slew.step_size << | ||
475 | AD5755_SLEW_STEP_SIZE_SHIFT; | ||
476 | val |= pdata->dac[i].slew.rate << | ||
477 | AD5755_SLEW_RATE_SHIFT; | ||
478 | if (pdata->dac[i].slew.enable) | ||
479 | val |= AD5755_SLEW_ENABLE; | ||
480 | |||
481 | ret = ad5755_write_ctrl(indio_dev, i, | ||
482 | AD5755_CTRL_REG_SLEW, val); | ||
483 | if (ret < 0) | ||
484 | return ret; | ||
485 | } | ||
486 | |||
487 | for (i = 0; i < ARRAY_SIZE(pdata->dac); ++i) { | ||
488 | if (!ad5755_is_valid_mode(st, pdata->dac[i].mode)) | ||
489 | return -EINVAL; | ||
490 | |||
491 | val = 0; | ||
492 | if (!pdata->dac[i].ext_current_sense_resistor) | ||
493 | val |= AD5755_DAC_INT_CURRENT_SENSE_RESISTOR; | ||
494 | if (pdata->dac[i].enable_voltage_overrange) | ||
495 | val |= AD5755_DAC_VOLTAGE_OVERRANGE_EN; | ||
496 | val |= pdata->dac[i].mode; | ||
497 | |||
498 | ret = ad5755_update_dac_ctrl(indio_dev, i, val, 0); | ||
499 | if (ret < 0) | ||
500 | return ret; | ||
501 | } | ||
502 | |||
503 | return 0; | ||
504 | } | ||
505 | |||
506 | static bool __devinit ad5755_is_voltage_mode(enum ad5755_mode mode) | ||
507 | { | ||
508 | switch (mode) { | ||
509 | case AD5755_MODE_VOLTAGE_0V_5V: | ||
510 | case AD5755_MODE_VOLTAGE_0V_10V: | ||
511 | case AD5755_MODE_VOLTAGE_PLUSMINUS_5V: | ||
512 | case AD5755_MODE_VOLTAGE_PLUSMINUS_10V: | ||
513 | return true; | ||
514 | default: | ||
515 | return false; | ||
516 | } | ||
517 | } | ||
518 | |||
519 | static int __devinit ad5755_init_channels(struct iio_dev *indio_dev, | ||
520 | const struct ad5755_platform_data *pdata) | ||
521 | { | ||
522 | struct ad5755_state *st = iio_priv(indio_dev); | ||
523 | struct iio_chan_spec *channels = st->channels; | ||
524 | unsigned int i; | ||
525 | |||
526 | for (i = 0; i < AD5755_NUM_CHANNELS; ++i) { | ||
527 | channels[i] = st->chip_info->channel_template; | ||
528 | channels[i].channel = i; | ||
529 | channels[i].address = i; | ||
530 | if (pdata && ad5755_is_voltage_mode(pdata->dac[i].mode)) | ||
531 | channels[i].type = IIO_VOLTAGE; | ||
532 | else | ||
533 | channels[i].type = IIO_CURRENT; | ||
534 | } | ||
535 | |||
536 | indio_dev->channels = channels; | ||
537 | |||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | #define AD5755_DEFAULT_DAC_PDATA { \ | ||
542 | .mode = AD5755_MODE_CURRENT_4mA_20mA, \ | ||
543 | .ext_current_sense_resistor = true, \ | ||
544 | .enable_voltage_overrange = false, \ | ||
545 | .slew = { \ | ||
546 | .enable = false, \ | ||
547 | .rate = AD5755_SLEW_RATE_64k, \ | ||
548 | .step_size = AD5755_SLEW_STEP_SIZE_1, \ | ||
549 | }, \ | ||
550 | } | ||
551 | |||
552 | static const struct ad5755_platform_data ad5755_default_pdata = { | ||
553 | .ext_dc_dc_compenstation_resistor = false, | ||
554 | .dc_dc_phase = AD5755_DC_DC_PHASE_ALL_SAME_EDGE, | ||
555 | .dc_dc_freq = AD5755_DC_DC_FREQ_410kHZ, | ||
556 | .dc_dc_maxv = AD5755_DC_DC_MAXV_23V, | ||
557 | .dac = { | ||
558 | [0] = AD5755_DEFAULT_DAC_PDATA, | ||
559 | [1] = AD5755_DEFAULT_DAC_PDATA, | ||
560 | [2] = AD5755_DEFAULT_DAC_PDATA, | ||
561 | [3] = AD5755_DEFAULT_DAC_PDATA, | ||
562 | }, | ||
563 | }; | ||
564 | |||
565 | static int __devinit ad5755_probe(struct spi_device *spi) | ||
566 | { | ||
567 | enum ad5755_type type = spi_get_device_id(spi)->driver_data; | ||
568 | const struct ad5755_platform_data *pdata = dev_get_platdata(&spi->dev); | ||
569 | struct iio_dev *indio_dev; | ||
570 | struct ad5755_state *st; | ||
571 | int ret; | ||
572 | |||
573 | indio_dev = iio_device_alloc(sizeof(*st)); | ||
574 | if (indio_dev == NULL) { | ||
575 | dev_err(&spi->dev, "Failed to allocate iio device\n"); | ||
576 | return -ENOMEM; | ||
577 | } | ||
578 | |||
579 | st = iio_priv(indio_dev); | ||
580 | spi_set_drvdata(spi, indio_dev); | ||
581 | |||
582 | st->chip_info = &ad5755_chip_info_tbl[type]; | ||
583 | st->spi = spi; | ||
584 | st->pwr_down = 0xf; | ||
585 | |||
586 | indio_dev->dev.parent = &spi->dev; | ||
587 | indio_dev->name = spi_get_device_id(spi)->name; | ||
588 | indio_dev->info = &ad5755_info; | ||
589 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
590 | indio_dev->num_channels = AD5755_NUM_CHANNELS; | ||
591 | |||
592 | if (!pdata) | ||
593 | pdata = &ad5755_default_pdata; | ||
594 | |||
595 | ret = ad5755_init_channels(indio_dev, pdata); | ||
596 | if (ret) | ||
597 | goto error_free; | ||
598 | |||
599 | ret = ad5755_setup_pdata(indio_dev, pdata); | ||
600 | if (ret) | ||
601 | goto error_free; | ||
602 | |||
603 | ret = iio_device_register(indio_dev); | ||
604 | if (ret) { | ||
605 | dev_err(&spi->dev, "Failed to register iio device: %d\n", ret); | ||
606 | goto error_free; | ||
607 | } | ||
608 | |||
609 | return 0; | ||
610 | |||
611 | error_free: | ||
612 | iio_device_free(indio_dev); | ||
613 | |||
614 | return ret; | ||
615 | } | ||
616 | |||
617 | static int __devexit ad5755_remove(struct spi_device *spi) | ||
618 | { | ||
619 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
620 | |||
621 | iio_device_unregister(indio_dev); | ||
622 | iio_device_free(indio_dev); | ||
623 | |||
624 | return 0; | ||
625 | } | ||
626 | |||
627 | static const struct spi_device_id ad5755_id[] = { | ||
628 | { "ad5755", ID_AD5755 }, | ||
629 | { "ad5755-1", ID_AD5755 }, | ||
630 | { "ad5757", ID_AD5757 }, | ||
631 | { "ad5735", ID_AD5735 }, | ||
632 | { "ad5737", ID_AD5737 }, | ||
633 | {} | ||
634 | }; | ||
635 | MODULE_DEVICE_TABLE(spi, ad5755_id); | ||
636 | |||
637 | static struct spi_driver ad5755_driver = { | ||
638 | .driver = { | ||
639 | .name = "ad5755", | ||
640 | .owner = THIS_MODULE, | ||
641 | }, | ||
642 | .probe = ad5755_probe, | ||
643 | .remove = __devexit_p(ad5755_remove), | ||
644 | .id_table = ad5755_id, | ||
645 | }; | ||
646 | module_spi_driver(ad5755_driver); | ||
647 | |||
648 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
649 | MODULE_DESCRIPTION("Analog Devices AD5755/55-1/57/35/37 DAC"); | ||
650 | MODULE_LICENSE("GPL v2"); | ||