Commit | Line | Data |
---|---|---|
fcf265d6 LPC |
1 | /* |
2 | * AD5064, AD5064-1, AD5044, AD5024 Digital to analog converters driver | |
3 | * | |
4 | * Copyright 2011 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/regulator/consumer.h> | |
17 | ||
18 | #include "../iio.h" | |
19 | #include "../sysfs.h" | |
20 | #include "dac.h" | |
21 | ||
22 | #define AD5064_DAC_CHANNELS 4 | |
23 | ||
24 | #define AD5064_ADDR(x) ((x) << 20) | |
25 | #define AD5064_CMD(x) ((x) << 24) | |
26 | ||
27 | #define AD5064_ADDR_DAC(chan) (chan) | |
28 | #define AD5064_ADDR_ALL_DAC 0xF | |
29 | ||
30 | #define AD5064_CMD_WRITE_INPUT_N 0x0 | |
31 | #define AD5064_CMD_UPDATE_DAC_N 0x1 | |
32 | #define AD5064_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2 | |
33 | #define AD5064_CMD_WRITE_INPUT_N_UPDATE_N 0x3 | |
34 | #define AD5064_CMD_POWERDOWN_DAC 0x4 | |
35 | #define AD5064_CMD_CLEAR 0x5 | |
36 | #define AD5064_CMD_LDAC_MASK 0x6 | |
37 | #define AD5064_CMD_RESET 0x7 | |
38 | #define AD5064_CMD_DAISY_CHAIN_ENABLE 0x8 | |
39 | ||
40 | #define AD5064_LDAC_PWRDN_NONE 0x0 | |
41 | #define AD5064_LDAC_PWRDN_1K 0x1 | |
42 | #define AD5064_LDAC_PWRDN_100K 0x2 | |
43 | #define AD5064_LDAC_PWRDN_3STATE 0x3 | |
44 | ||
45 | /** | |
46 | * struct ad5064_chip_info - chip specific information | |
47 | * @shared_vref: whether the vref supply is shared between channels | |
48 | * @channel: channel specification | |
49 | */ | |
50 | ||
51 | struct ad5064_chip_info { | |
52 | bool shared_vref; | |
53 | struct iio_chan_spec channel[AD5064_DAC_CHANNELS]; | |
54 | }; | |
55 | ||
56 | /** | |
57 | * struct ad5064_state - driver instance specific data | |
58 | * @spi: spi_device | |
59 | * @chip_info: chip model specific constants, available modes etc | |
60 | * @vref_reg: vref supply regulators | |
61 | * @pwr_down: whether channel is powered down | |
62 | * @pwr_down_mode: channel's current power down mode | |
63 | * @dac_cache: current DAC raw value (chip does not support readback) | |
64 | * @data: spi transfer buffers | |
65 | */ | |
66 | ||
67 | struct ad5064_state { | |
68 | struct spi_device *spi; | |
69 | const struct ad5064_chip_info *chip_info; | |
70 | struct regulator_bulk_data vref_reg[AD5064_DAC_CHANNELS]; | |
71 | bool pwr_down[AD5064_DAC_CHANNELS]; | |
72 | u8 pwr_down_mode[AD5064_DAC_CHANNELS]; | |
73 | unsigned int dac_cache[AD5064_DAC_CHANNELS]; | |
74 | ||
75 | /* | |
76 | * DMA (thus cache coherency maintenance) requires the | |
77 | * transfer buffers to live in their own cache lines. | |
78 | */ | |
79 | __be32 data ____cacheline_aligned; | |
80 | }; | |
81 | ||
82 | enum ad5064_type { | |
83 | ID_AD5024, | |
84 | ID_AD5044, | |
85 | ID_AD5064, | |
86 | ID_AD5064_1, | |
87 | }; | |
88 | ||
89 | #define AD5064_CHANNEL(chan, bits) { \ | |
90 | .type = IIO_VOLTAGE, \ | |
91 | .indexed = 1, \ | |
92 | .output = 1, \ | |
93 | .channel = (chan), \ | |
94 | .info_mask = (1 << IIO_CHAN_INFO_SCALE_SEPARATE), \ | |
95 | .address = AD5064_ADDR_DAC(chan), \ | |
96 | .scan_type = IIO_ST('u', (bits), 16, 20 - (bits)) \ | |
97 | } | |
98 | ||
99 | static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { | |
100 | [ID_AD5024] = { | |
101 | .shared_vref = false, | |
102 | .channel[0] = AD5064_CHANNEL(0, 12), | |
103 | .channel[1] = AD5064_CHANNEL(1, 12), | |
104 | .channel[2] = AD5064_CHANNEL(2, 12), | |
105 | .channel[3] = AD5064_CHANNEL(3, 12), | |
106 | }, | |
107 | [ID_AD5044] = { | |
108 | .shared_vref = false, | |
109 | .channel[0] = AD5064_CHANNEL(0, 14), | |
110 | .channel[1] = AD5064_CHANNEL(1, 14), | |
111 | .channel[2] = AD5064_CHANNEL(2, 14), | |
112 | .channel[3] = AD5064_CHANNEL(3, 14), | |
113 | }, | |
114 | [ID_AD5064] = { | |
115 | .shared_vref = false, | |
116 | .channel[0] = AD5064_CHANNEL(0, 16), | |
117 | .channel[1] = AD5064_CHANNEL(1, 16), | |
118 | .channel[2] = AD5064_CHANNEL(2, 16), | |
119 | .channel[3] = AD5064_CHANNEL(3, 16), | |
120 | }, | |
121 | [ID_AD5064_1] = { | |
122 | .shared_vref = true, | |
123 | .channel[0] = AD5064_CHANNEL(0, 16), | |
124 | .channel[1] = AD5064_CHANNEL(1, 16), | |
125 | .channel[2] = AD5064_CHANNEL(2, 16), | |
126 | .channel[3] = AD5064_CHANNEL(3, 16), | |
127 | }, | |
128 | }; | |
129 | ||
130 | static int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd, | |
131 | unsigned int addr, unsigned int val, unsigned int shift) | |
132 | { | |
133 | val <<= shift; | |
134 | ||
135 | st->data = cpu_to_be32(AD5064_CMD(cmd) | AD5064_ADDR(addr) | val); | |
136 | ||
137 | return spi_write(st->spi, &st->data, sizeof(st->data)); | |
138 | } | |
139 | ||
140 | static int ad5064_sync_powerdown_mode(struct ad5064_state *st, | |
141 | unsigned int channel) | |
142 | { | |
143 | unsigned int val; | |
144 | int ret; | |
145 | ||
146 | val = (0x1 << channel); | |
147 | ||
148 | if (st->pwr_down[channel]) | |
149 | val |= st->pwr_down_mode[channel] << 8; | |
150 | ||
151 | ret = ad5064_spi_write(st, AD5064_CMD_POWERDOWN_DAC, 0, val, 0); | |
152 | ||
153 | return ret; | |
154 | } | |
155 | ||
156 | static const char ad5064_powerdown_modes[][15] = { | |
157 | [AD5064_LDAC_PWRDN_NONE] = "", | |
158 | [AD5064_LDAC_PWRDN_1K] = "1kohm_to_gnd", | |
159 | [AD5064_LDAC_PWRDN_100K] = "100kohm_to_gnd", | |
160 | [AD5064_LDAC_PWRDN_3STATE] = "three_state", | |
161 | }; | |
162 | ||
163 | static ssize_t ad5064_read_powerdown_mode(struct device *dev, | |
164 | struct device_attribute *attr, char *buf) | |
165 | { | |
166 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | |
167 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
168 | struct ad5064_state *st = iio_priv(indio_dev); | |
169 | ||
170 | return sprintf(buf, "%s\n", | |
171 | ad5064_powerdown_modes[st->pwr_down_mode[this_attr->address]]); | |
172 | } | |
173 | ||
174 | static ssize_t ad5064_write_powerdown_mode(struct device *dev, | |
175 | struct device_attribute *attr, const char *buf, size_t len) | |
176 | { | |
177 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | |
178 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
179 | struct ad5064_state *st = iio_priv(indio_dev); | |
180 | unsigned int mode, i; | |
181 | int ret; | |
182 | ||
183 | mode = 0; | |
184 | ||
185 | for (i = 1; i < ARRAY_SIZE(ad5064_powerdown_modes); ++i) { | |
186 | if (sysfs_streq(buf, ad5064_powerdown_modes[i])) { | |
187 | mode = i; | |
188 | break; | |
189 | } | |
190 | } | |
191 | if (mode == 0) | |
192 | return -EINVAL; | |
193 | ||
194 | mutex_lock(&indio_dev->mlock); | |
195 | st->pwr_down_mode[this_attr->address] = mode; | |
196 | ||
197 | ret = ad5064_sync_powerdown_mode(st, this_attr->address); | |
198 | mutex_unlock(&indio_dev->mlock); | |
199 | ||
200 | return ret ? ret : len; | |
201 | } | |
202 | ||
203 | static ssize_t ad5064_read_dac_powerdown(struct device *dev, | |
204 | struct device_attribute *attr, | |
205 | char *buf) | |
206 | { | |
207 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
208 | struct ad5064_state *st = iio_priv(indio_dev); | |
209 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | |
210 | ||
211 | return sprintf(buf, "%d\n", st->pwr_down[this_attr->address]); | |
212 | } | |
213 | ||
214 | static ssize_t ad5064_write_dac_powerdown(struct device *dev, | |
215 | struct device_attribute *attr, const char *buf, size_t len) | |
216 | { | |
217 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | |
218 | struct ad5064_state *st = iio_priv(indio_dev); | |
219 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | |
220 | bool pwr_down; | |
221 | int ret; | |
222 | ||
223 | ret = strtobool(buf, &pwr_down); | |
224 | if (ret) | |
225 | return ret; | |
226 | ||
227 | mutex_lock(&indio_dev->mlock); | |
228 | st->pwr_down[this_attr->address] = pwr_down; | |
229 | ||
230 | ret = ad5064_sync_powerdown_mode(st, this_attr->address); | |
231 | mutex_unlock(&indio_dev->mlock); | |
232 | return ret ? ret : len; | |
233 | } | |
234 | ||
235 | static IIO_CONST_ATTR(out_voltage_powerdown_mode_available, | |
236 | "1kohm_to_gnd 100kohm_to_gnd three_state"); | |
237 | ||
238 | #define IIO_DEV_ATTR_DAC_POWERDOWN_MODE(_chan) \ | |
239 | IIO_DEVICE_ATTR(out_voltage##_chan##_powerdown_mode, \ | |
240 | S_IRUGO | S_IWUSR, \ | |
241 | ad5064_read_powerdown_mode, \ | |
242 | ad5064_write_powerdown_mode, _chan); | |
243 | ||
244 | #define IIO_DEV_ATTR_DAC_POWERDOWN(_chan) \ | |
245 | IIO_DEVICE_ATTR(out_voltage##_chan##_powerdown, \ | |
246 | S_IRUGO | S_IWUSR, \ | |
247 | ad5064_read_dac_powerdown, \ | |
248 | ad5064_write_dac_powerdown, _chan) | |
249 | ||
250 | static IIO_DEV_ATTR_DAC_POWERDOWN(0); | |
251 | static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(0); | |
252 | static IIO_DEV_ATTR_DAC_POWERDOWN(1); | |
253 | static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(1); | |
254 | static IIO_DEV_ATTR_DAC_POWERDOWN(2); | |
255 | static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(2); | |
256 | static IIO_DEV_ATTR_DAC_POWERDOWN(3); | |
257 | static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(3); | |
258 | ||
259 | static struct attribute *ad5064_attributes[] = { | |
260 | &iio_dev_attr_out_voltage0_powerdown.dev_attr.attr, | |
261 | &iio_dev_attr_out_voltage1_powerdown.dev_attr.attr, | |
262 | &iio_dev_attr_out_voltage2_powerdown.dev_attr.attr, | |
263 | &iio_dev_attr_out_voltage3_powerdown.dev_attr.attr, | |
264 | &iio_dev_attr_out_voltage0_powerdown_mode.dev_attr.attr, | |
265 | &iio_dev_attr_out_voltage1_powerdown_mode.dev_attr.attr, | |
266 | &iio_dev_attr_out_voltage2_powerdown_mode.dev_attr.attr, | |
267 | &iio_dev_attr_out_voltage3_powerdown_mode.dev_attr.attr, | |
268 | &iio_const_attr_out_voltage_powerdown_mode_available.dev_attr.attr, | |
269 | NULL, | |
270 | }; | |
271 | ||
272 | static const struct attribute_group ad5064_attribute_group = { | |
273 | .attrs = ad5064_attributes, | |
274 | }; | |
275 | ||
276 | static int ad5064_read_raw(struct iio_dev *indio_dev, | |
277 | struct iio_chan_spec const *chan, | |
278 | int *val, | |
279 | int *val2, | |
280 | long m) | |
281 | { | |
282 | struct ad5064_state *st = iio_priv(indio_dev); | |
283 | unsigned long scale_uv; | |
284 | unsigned int vref; | |
285 | ||
286 | switch (m) { | |
287 | case 0: | |
288 | *val = st->dac_cache[chan->channel]; | |
289 | return IIO_VAL_INT; | |
290 | case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): | |
291 | vref = st->chip_info->shared_vref ? 0 : chan->channel; | |
292 | scale_uv = regulator_get_voltage(st->vref_reg[vref].consumer); | |
293 | if (scale_uv < 0) | |
294 | return scale_uv; | |
295 | ||
296 | scale_uv = (scale_uv * 100) >> chan->scan_type.realbits; | |
297 | *val = scale_uv / 100000; | |
298 | *val2 = (scale_uv % 100000) * 10; | |
299 | return IIO_VAL_INT_PLUS_MICRO; | |
300 | default: | |
301 | break; | |
302 | } | |
303 | return -EINVAL; | |
304 | } | |
305 | ||
306 | static int ad5064_write_raw(struct iio_dev *indio_dev, | |
307 | struct iio_chan_spec const *chan, int val, int val2, long mask) | |
308 | { | |
309 | struct ad5064_state *st = iio_priv(indio_dev); | |
310 | int ret; | |
311 | ||
312 | switch (mask) { | |
313 | case 0: | |
314 | if (val > (1 << chan->scan_type.realbits) || val < 0) | |
315 | return -EINVAL; | |
316 | ||
317 | mutex_lock(&indio_dev->mlock); | |
318 | ret = ad5064_spi_write(st, AD5064_CMD_WRITE_INPUT_N_UPDATE_N, | |
319 | chan->address, val, chan->scan_type.shift); | |
320 | if (ret == 0) | |
321 | st->dac_cache[chan->channel] = val; | |
322 | mutex_unlock(&indio_dev->mlock); | |
323 | break; | |
324 | default: | |
325 | ret = -EINVAL; | |
326 | } | |
327 | ||
328 | return ret; | |
329 | } | |
330 | ||
331 | static const struct iio_info ad5064_info = { | |
332 | .read_raw = ad5064_read_raw, | |
333 | .write_raw = ad5064_write_raw, | |
334 | .attrs = &ad5064_attribute_group, | |
335 | .driver_module = THIS_MODULE, | |
336 | }; | |
337 | ||
338 | static inline unsigned int ad5064_num_vref(struct ad5064_state *st) | |
339 | { | |
340 | return st->chip_info->shared_vref ? 1 : AD5064_DAC_CHANNELS; | |
341 | } | |
342 | ||
343 | static const char * const ad5064_vref_names[] = { | |
344 | "vrefA", | |
345 | "vrefB", | |
346 | "vrefC", | |
347 | "vrefD", | |
348 | }; | |
349 | ||
350 | static const char * const ad5064_vref_name(struct ad5064_state *st, | |
351 | unsigned int vref) | |
352 | { | |
353 | return st->chip_info->shared_vref ? "vref" : ad5064_vref_names[vref]; | |
354 | } | |
355 | ||
356 | static int __devinit ad5064_probe(struct spi_device *spi) | |
357 | { | |
358 | enum ad5064_type type = spi_get_device_id(spi)->driver_data; | |
359 | struct iio_dev *indio_dev; | |
360 | struct ad5064_state *st; | |
361 | unsigned int i; | |
362 | int ret; | |
363 | ||
364 | indio_dev = iio_allocate_device(sizeof(*st)); | |
365 | if (indio_dev == NULL) | |
366 | return -ENOMEM; | |
367 | ||
368 | st = iio_priv(indio_dev); | |
369 | spi_set_drvdata(spi, indio_dev); | |
370 | ||
371 | st->chip_info = &ad5064_chip_info_tbl[type]; | |
372 | st->spi = spi; | |
373 | ||
374 | for (i = 0; i < ad5064_num_vref(st); ++i) | |
375 | st->vref_reg[i].supply = ad5064_vref_name(st, i); | |
376 | ||
377 | ret = regulator_bulk_get(&st->spi->dev, ad5064_num_vref(st), | |
378 | st->vref_reg); | |
379 | if (ret) | |
380 | goto error_free; | |
381 | ||
382 | ret = regulator_bulk_enable(ad5064_num_vref(st), st->vref_reg); | |
383 | if (ret) | |
384 | goto error_free_reg; | |
385 | ||
386 | for (i = 0; i < AD5064_DAC_CHANNELS; ++i) { | |
387 | st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K; | |
388 | st->dac_cache[i] = 0x8000; | |
389 | } | |
390 | ||
391 | indio_dev->dev.parent = &spi->dev; | |
392 | indio_dev->name = spi_get_device_id(spi)->name; | |
393 | indio_dev->info = &ad5064_info; | |
394 | indio_dev->modes = INDIO_DIRECT_MODE; | |
395 | indio_dev->channels = st->chip_info->channel; | |
396 | indio_dev->num_channels = AD5064_DAC_CHANNELS; | |
397 | ||
398 | ret = iio_device_register(indio_dev); | |
399 | if (ret) | |
400 | goto error_disable_reg; | |
401 | ||
402 | return 0; | |
403 | ||
404 | error_disable_reg: | |
405 | regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); | |
406 | error_free_reg: | |
407 | regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); | |
408 | error_free: | |
409 | iio_free_device(indio_dev); | |
410 | ||
411 | return ret; | |
412 | } | |
413 | ||
414 | ||
415 | static int __devexit ad5064_remove(struct spi_device *spi) | |
416 | { | |
417 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | |
418 | struct ad5064_state *st = iio_priv(indio_dev); | |
419 | ||
420 | iio_device_unregister(indio_dev); | |
421 | ||
422 | regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg); | |
423 | regulator_bulk_free(ad5064_num_vref(st), st->vref_reg); | |
424 | ||
425 | iio_free_device(indio_dev); | |
426 | ||
427 | return 0; | |
428 | } | |
429 | ||
430 | static const struct spi_device_id ad5064_id[] = { | |
431 | {"ad5024", ID_AD5024}, | |
432 | {"ad5044", ID_AD5044}, | |
433 | {"ad5064", ID_AD5064}, | |
434 | {"ad5064-1", ID_AD5064_1}, | |
435 | {} | |
436 | }; | |
437 | MODULE_DEVICE_TABLE(spi, ad5064_id); | |
438 | ||
439 | static struct spi_driver ad5064_driver = { | |
440 | .driver = { | |
441 | .name = "ad5064", | |
442 | .owner = THIS_MODULE, | |
443 | }, | |
444 | .probe = ad5064_probe, | |
445 | .remove = __devexit_p(ad5064_remove), | |
446 | .id_table = ad5064_id, | |
447 | }; | |
ae6ae6fe | 448 | module_spi_driver(ad5064_driver); |
fcf265d6 LPC |
449 | |
450 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | |
451 | MODULE_DESCRIPTION("Analog Devices AD5064/64-1/44/24 DAC"); | |
452 | MODULE_LICENSE("GPL v2"); |