1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * AD5760, AD5780, AD5781, AD5790, AD5791 Voltage Output Digital to Analog |
4 | * Converter |
5 | * |
6 | * Copyright 2011 Analog Devices Inc. |
7 | */ |
8 | |
9 | #include <linux/interrupt.h> |
10 | #include <linux/fs.h> |
11 | #include <linux/device.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 | #include <linux/module.h> |
18 | #include <linux/bitops.h> |
19 | |
20 | #include <linux/iio/iio.h> |
21 | #include <linux/iio/sysfs.h> |
22 | #include <linux/iio/dac/ad5791.h> |
23 | |
24 | #define AD5791_DAC_MASK GENMASK(19, 0) |
25 | |
26 | #define AD5791_CMD_READ BIT(23) |
27 | #define AD5791_CMD_WRITE 0 |
28 | #define AD5791_ADDR(addr) ((addr) << 20) |
29 | |
30 | /* Registers */ |
31 | #define AD5791_ADDR_NOOP 0 |
32 | #define AD5791_ADDR_DAC0 1 |
33 | #define AD5791_ADDR_CTRL 2 |
34 | #define AD5791_ADDR_CLRCODE 3 |
35 | #define AD5791_ADDR_SW_CTRL 4 |
36 | |
37 | /* Control Register */ |
38 | #define AD5791_CTRL_RBUF BIT(1) |
39 | #define AD5791_CTRL_OPGND BIT(2) |
40 | #define AD5791_CTRL_DACTRI BIT(3) |
41 | #define AD5791_CTRL_BIN2SC BIT(4) |
42 | #define AD5791_CTRL_SDODIS BIT(5) |
43 | #define AD5761_CTRL_LINCOMP(x) ((x) << 6) |
44 | |
45 | #define AD5791_LINCOMP_0_10 0 |
46 | #define AD5791_LINCOMP_10_12 1 |
47 | #define AD5791_LINCOMP_12_16 2 |
48 | #define AD5791_LINCOMP_16_19 3 |
49 | #define AD5791_LINCOMP_19_20 12 |
50 | |
51 | #define AD5780_LINCOMP_0_10 0 |
52 | #define AD5780_LINCOMP_10_20 12 |
53 | |
54 | /* Software Control Register */ |
55 | #define AD5791_SWCTRL_LDAC BIT(0) |
56 | #define AD5791_SWCTRL_CLR BIT(1) |
57 | #define AD5791_SWCTRL_RESET BIT(2) |
58 | |
59 | #define AD5791_DAC_PWRDN_6K 0 |
60 | #define AD5791_DAC_PWRDN_3STATE 1 |
61 | |
62 | /** |
63 | * struct ad5791_chip_info - chip specific information |
64 | * @get_lin_comp: function pointer to the device specific function |
65 | */ |
66 | |
67 | struct ad5791_chip_info { |
68 | int (*get_lin_comp) (unsigned int span); |
69 | }; |
70 | |
71 | /** |
72 | * struct ad5791_state - driver instance specific data |
73 | * @spi: spi_device |
74 | * @reg_vdd: positive supply regulator |
75 | * @reg_vss: negative supply regulator |
76 | * @chip_info: chip model specific constants |
77 | * @vref_mv: actual reference voltage used |
78 | * @vref_neg_mv: voltage of the negative supply |
79 | * @ctrl: control register cache |
80 | * @pwr_down_mode: current power down mode |
81 | * @pwr_down: true if device is powered down |
82 | * @data: spi transfer buffers |
83 | */ |
84 | struct ad5791_state { |
85 | struct spi_device *spi; |
86 | struct regulator *reg_vdd; |
87 | struct regulator *reg_vss; |
88 | const struct ad5791_chip_info *chip_info; |
89 | unsigned short vref_mv; |
90 | unsigned int vref_neg_mv; |
91 | unsigned ctrl; |
92 | unsigned pwr_down_mode; |
93 | bool pwr_down; |
94 | |
95 | union { |
96 | __be32 d32; |
97 | u8 d8[4]; |
98 | } data[3] __aligned(IIO_DMA_MINALIGN); |
99 | }; |
100 | |
101 | enum ad5791_supported_device_ids { |
102 | ID_AD5760, |
103 | ID_AD5780, |
104 | ID_AD5781, |
105 | ID_AD5791, |
106 | }; |
107 | |
108 | static int ad5791_spi_write(struct ad5791_state *st, u8 addr, u32 val) |
109 | { |
110 | st->data[0].d32 = cpu_to_be32(AD5791_CMD_WRITE | |
111 | AD5791_ADDR(addr) | |
112 | (val & AD5791_DAC_MASK)); |
113 | |
114 | return spi_write(spi: st->spi, buf: &st->data[0].d8[1], len: 3); |
115 | } |
116 | |
117 | static int ad5791_spi_read(struct ad5791_state *st, u8 addr, u32 *val) |
118 | { |
119 | int ret; |
120 | struct spi_transfer xfers[] = { |
121 | { |
122 | .tx_buf = &st->data[0].d8[1], |
123 | .bits_per_word = 8, |
124 | .len = 3, |
125 | .cs_change = 1, |
126 | }, { |
127 | .tx_buf = &st->data[1].d8[1], |
128 | .rx_buf = &st->data[2].d8[1], |
129 | .bits_per_word = 8, |
130 | .len = 3, |
131 | }, |
132 | }; |
133 | |
134 | st->data[0].d32 = cpu_to_be32(AD5791_CMD_READ | |
135 | AD5791_ADDR(addr)); |
136 | st->data[1].d32 = cpu_to_be32(AD5791_ADDR(AD5791_ADDR_NOOP)); |
137 | |
138 | ret = spi_sync_transfer(spi: st->spi, xfers, ARRAY_SIZE(xfers)); |
139 | |
140 | *val = be32_to_cpu(st->data[2].d32); |
141 | |
142 | return ret; |
143 | } |
144 | |
145 | static const char * const ad5791_powerdown_modes[] = { |
146 | "6kohm_to_gnd" , |
147 | "three_state" , |
148 | }; |
149 | |
150 | static int ad5791_get_powerdown_mode(struct iio_dev *indio_dev, |
151 | const struct iio_chan_spec *chan) |
152 | { |
153 | struct ad5791_state *st = iio_priv(indio_dev); |
154 | |
155 | return st->pwr_down_mode; |
156 | } |
157 | |
158 | static int ad5791_set_powerdown_mode(struct iio_dev *indio_dev, |
159 | const struct iio_chan_spec *chan, unsigned int mode) |
160 | { |
161 | struct ad5791_state *st = iio_priv(indio_dev); |
162 | |
163 | st->pwr_down_mode = mode; |
164 | |
165 | return 0; |
166 | } |
167 | |
168 | static const struct iio_enum ad5791_powerdown_mode_enum = { |
169 | .items = ad5791_powerdown_modes, |
170 | .num_items = ARRAY_SIZE(ad5791_powerdown_modes), |
171 | .get = ad5791_get_powerdown_mode, |
172 | .set = ad5791_set_powerdown_mode, |
173 | }; |
174 | |
175 | static ssize_t ad5791_read_dac_powerdown(struct iio_dev *indio_dev, |
176 | uintptr_t private, const struct iio_chan_spec *chan, char *buf) |
177 | { |
178 | struct ad5791_state *st = iio_priv(indio_dev); |
179 | |
180 | return sysfs_emit(buf, fmt: "%d\n" , st->pwr_down); |
181 | } |
182 | |
183 | static ssize_t ad5791_write_dac_powerdown(struct iio_dev *indio_dev, |
184 | uintptr_t private, const struct iio_chan_spec *chan, const char *buf, |
185 | size_t len) |
186 | { |
187 | bool pwr_down; |
188 | int ret; |
189 | struct ad5791_state *st = iio_priv(indio_dev); |
190 | |
191 | ret = kstrtobool(s: buf, res: &pwr_down); |
192 | if (ret) |
193 | return ret; |
194 | |
195 | if (!pwr_down) { |
196 | st->ctrl &= ~(AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI); |
197 | } else { |
198 | if (st->pwr_down_mode == AD5791_DAC_PWRDN_6K) |
199 | st->ctrl |= AD5791_CTRL_OPGND; |
200 | else if (st->pwr_down_mode == AD5791_DAC_PWRDN_3STATE) |
201 | st->ctrl |= AD5791_CTRL_DACTRI; |
202 | } |
203 | st->pwr_down = pwr_down; |
204 | |
205 | ret = ad5791_spi_write(st, AD5791_ADDR_CTRL, val: st->ctrl); |
206 | |
207 | return ret ? ret : len; |
208 | } |
209 | |
210 | static int ad5791_get_lin_comp(unsigned int span) |
211 | { |
212 | if (span <= 10000) |
213 | return AD5791_LINCOMP_0_10; |
214 | else if (span <= 12000) |
215 | return AD5791_LINCOMP_10_12; |
216 | else if (span <= 16000) |
217 | return AD5791_LINCOMP_12_16; |
218 | else if (span <= 19000) |
219 | return AD5791_LINCOMP_16_19; |
220 | else |
221 | return AD5791_LINCOMP_19_20; |
222 | } |
223 | |
224 | static int ad5780_get_lin_comp(unsigned int span) |
225 | { |
226 | if (span <= 10000) |
227 | return AD5780_LINCOMP_0_10; |
228 | else |
229 | return AD5780_LINCOMP_10_20; |
230 | } |
231 | static const struct ad5791_chip_info ad5791_chip_info_tbl[] = { |
232 | [ID_AD5760] = { |
233 | .get_lin_comp = ad5780_get_lin_comp, |
234 | }, |
235 | [ID_AD5780] = { |
236 | .get_lin_comp = ad5780_get_lin_comp, |
237 | }, |
238 | [ID_AD5781] = { |
239 | .get_lin_comp = ad5791_get_lin_comp, |
240 | }, |
241 | [ID_AD5791] = { |
242 | .get_lin_comp = ad5791_get_lin_comp, |
243 | }, |
244 | }; |
245 | |
246 | static int ad5791_read_raw(struct iio_dev *indio_dev, |
247 | struct iio_chan_spec const *chan, |
248 | int *val, |
249 | int *val2, |
250 | long m) |
251 | { |
252 | struct ad5791_state *st = iio_priv(indio_dev); |
253 | u64 val64; |
254 | int ret; |
255 | |
256 | switch (m) { |
257 | case IIO_CHAN_INFO_RAW: |
258 | ret = ad5791_spi_read(st, addr: chan->address, val); |
259 | if (ret) |
260 | return ret; |
261 | *val &= AD5791_DAC_MASK; |
262 | *val >>= chan->scan_type.shift; |
263 | return IIO_VAL_INT; |
264 | case IIO_CHAN_INFO_SCALE: |
265 | *val = st->vref_mv; |
266 | *val2 = (1 << chan->scan_type.realbits) - 1; |
267 | return IIO_VAL_FRACTIONAL; |
268 | case IIO_CHAN_INFO_OFFSET: |
269 | val64 = (((u64)st->vref_neg_mv) << chan->scan_type.realbits); |
270 | do_div(val64, st->vref_mv); |
271 | *val = -val64; |
272 | return IIO_VAL_INT; |
273 | default: |
274 | return -EINVAL; |
275 | } |
276 | |
277 | }; |
278 | |
279 | static const struct iio_chan_spec_ext_info ad5791_ext_info[] = { |
280 | { |
281 | .name = "powerdown" , |
282 | .shared = IIO_SHARED_BY_TYPE, |
283 | .read = ad5791_read_dac_powerdown, |
284 | .write = ad5791_write_dac_powerdown, |
285 | }, |
286 | IIO_ENUM("powerdown_mode" , IIO_SHARED_BY_TYPE, |
287 | &ad5791_powerdown_mode_enum), |
288 | IIO_ENUM_AVAILABLE("powerdown_mode" , IIO_SHARED_BY_TYPE, &ad5791_powerdown_mode_enum), |
289 | { }, |
290 | }; |
291 | |
292 | #define AD5791_CHAN(bits, _shift) { \ |
293 | .type = IIO_VOLTAGE, \ |
294 | .output = 1, \ |
295 | .indexed = 1, \ |
296 | .address = AD5791_ADDR_DAC0, \ |
297 | .channel = 0, \ |
298 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
299 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ |
300 | BIT(IIO_CHAN_INFO_OFFSET), \ |
301 | .scan_type = { \ |
302 | .sign = 'u', \ |
303 | .realbits = (bits), \ |
304 | .storagebits = 24, \ |
305 | .shift = (_shift), \ |
306 | }, \ |
307 | .ext_info = ad5791_ext_info, \ |
308 | } |
309 | |
310 | static const struct iio_chan_spec ad5791_channels[] = { |
311 | [ID_AD5760] = AD5791_CHAN(16, 4), |
312 | [ID_AD5780] = AD5791_CHAN(18, 2), |
313 | [ID_AD5781] = AD5791_CHAN(18, 2), |
314 | [ID_AD5791] = AD5791_CHAN(20, 0) |
315 | }; |
316 | |
317 | static int ad5791_write_raw(struct iio_dev *indio_dev, |
318 | struct iio_chan_spec const *chan, |
319 | int val, |
320 | int val2, |
321 | long mask) |
322 | { |
323 | struct ad5791_state *st = iio_priv(indio_dev); |
324 | |
325 | switch (mask) { |
326 | case IIO_CHAN_INFO_RAW: |
327 | val &= GENMASK(chan->scan_type.realbits - 1, 0); |
328 | val <<= chan->scan_type.shift; |
329 | |
330 | return ad5791_spi_write(st, addr: chan->address, val); |
331 | |
332 | default: |
333 | return -EINVAL; |
334 | } |
335 | } |
336 | |
337 | static const struct iio_info ad5791_info = { |
338 | .read_raw = &ad5791_read_raw, |
339 | .write_raw = &ad5791_write_raw, |
340 | }; |
341 | |
342 | static int ad5791_probe(struct spi_device *spi) |
343 | { |
344 | struct ad5791_platform_data *pdata = spi->dev.platform_data; |
345 | struct iio_dev *indio_dev; |
346 | struct ad5791_state *st; |
347 | int ret, pos_voltage_uv = 0, neg_voltage_uv = 0; |
348 | bool use_rbuf_gain2; |
349 | |
350 | indio_dev = devm_iio_device_alloc(parent: &spi->dev, sizeof_priv: sizeof(*st)); |
351 | if (!indio_dev) |
352 | return -ENOMEM; |
353 | st = iio_priv(indio_dev); |
354 | st->reg_vdd = devm_regulator_get(dev: &spi->dev, id: "vdd" ); |
355 | if (!IS_ERR(ptr: st->reg_vdd)) { |
356 | ret = regulator_enable(regulator: st->reg_vdd); |
357 | if (ret) |
358 | return ret; |
359 | |
360 | ret = regulator_get_voltage(regulator: st->reg_vdd); |
361 | if (ret < 0) |
362 | goto error_disable_reg_pos; |
363 | |
364 | pos_voltage_uv = ret; |
365 | } |
366 | |
367 | st->reg_vss = devm_regulator_get(dev: &spi->dev, id: "vss" ); |
368 | if (!IS_ERR(ptr: st->reg_vss)) { |
369 | ret = regulator_enable(regulator: st->reg_vss); |
370 | if (ret) |
371 | goto error_disable_reg_pos; |
372 | |
373 | ret = regulator_get_voltage(regulator: st->reg_vss); |
374 | if (ret < 0) |
375 | goto error_disable_reg_neg; |
376 | |
377 | neg_voltage_uv = ret; |
378 | } |
379 | |
380 | st->pwr_down = true; |
381 | st->spi = spi; |
382 | |
383 | if (pdata) |
384 | use_rbuf_gain2 = pdata->use_rbuf_gain2; |
385 | else |
386 | use_rbuf_gain2 = device_property_read_bool(dev: &spi->dev, |
387 | propname: "adi,rbuf-gain2-en" ); |
388 | |
389 | if (!IS_ERR(ptr: st->reg_vss) && !IS_ERR(ptr: st->reg_vdd)) { |
390 | st->vref_mv = (pos_voltage_uv + neg_voltage_uv) / 1000; |
391 | st->vref_neg_mv = neg_voltage_uv / 1000; |
392 | } else if (pdata) { |
393 | st->vref_mv = pdata->vref_pos_mv + pdata->vref_neg_mv; |
394 | st->vref_neg_mv = pdata->vref_neg_mv; |
395 | } else { |
396 | dev_warn(&spi->dev, "reference voltage unspecified\n" ); |
397 | } |
398 | |
399 | ret = ad5791_spi_write(st, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET); |
400 | if (ret) |
401 | goto error_disable_reg_neg; |
402 | |
403 | st->chip_info = &ad5791_chip_info_tbl[spi_get_device_id(sdev: spi) |
404 | ->driver_data]; |
405 | |
406 | |
407 | st->ctrl = AD5761_CTRL_LINCOMP(st->chip_info->get_lin_comp(st->vref_mv)) |
408 | | (use_rbuf_gain2 ? 0 : AD5791_CTRL_RBUF) | |
409 | AD5791_CTRL_BIN2SC; |
410 | |
411 | ret = ad5791_spi_write(st, AD5791_ADDR_CTRL, val: st->ctrl | |
412 | AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI); |
413 | if (ret) |
414 | goto error_disable_reg_neg; |
415 | |
416 | spi_set_drvdata(spi, data: indio_dev); |
417 | indio_dev->info = &ad5791_info; |
418 | indio_dev->modes = INDIO_DIRECT_MODE; |
419 | indio_dev->channels |
420 | = &ad5791_channels[spi_get_device_id(sdev: spi)->driver_data]; |
421 | indio_dev->num_channels = 1; |
422 | indio_dev->name = spi_get_device_id(sdev: st->spi)->name; |
423 | ret = iio_device_register(indio_dev); |
424 | if (ret) |
425 | goto error_disable_reg_neg; |
426 | |
427 | return 0; |
428 | |
429 | error_disable_reg_neg: |
430 | if (!IS_ERR(ptr: st->reg_vss)) |
431 | regulator_disable(regulator: st->reg_vss); |
432 | error_disable_reg_pos: |
433 | if (!IS_ERR(ptr: st->reg_vdd)) |
434 | regulator_disable(regulator: st->reg_vdd); |
435 | return ret; |
436 | } |
437 | |
438 | static void ad5791_remove(struct spi_device *spi) |
439 | { |
440 | struct iio_dev *indio_dev = spi_get_drvdata(spi); |
441 | struct ad5791_state *st = iio_priv(indio_dev); |
442 | |
443 | iio_device_unregister(indio_dev); |
444 | if (!IS_ERR(ptr: st->reg_vdd)) |
445 | regulator_disable(regulator: st->reg_vdd); |
446 | |
447 | if (!IS_ERR(ptr: st->reg_vss)) |
448 | regulator_disable(regulator: st->reg_vss); |
449 | } |
450 | |
451 | static const struct spi_device_id ad5791_id[] = { |
452 | {"ad5760" , ID_AD5760}, |
453 | {"ad5780" , ID_AD5780}, |
454 | {"ad5781" , ID_AD5781}, |
455 | {"ad5790" , ID_AD5791}, |
456 | {"ad5791" , ID_AD5791}, |
457 | {} |
458 | }; |
459 | MODULE_DEVICE_TABLE(spi, ad5791_id); |
460 | |
461 | static struct spi_driver ad5791_driver = { |
462 | .driver = { |
463 | .name = "ad5791" , |
464 | }, |
465 | .probe = ad5791_probe, |
466 | .remove = ad5791_remove, |
467 | .id_table = ad5791_id, |
468 | }; |
469 | module_spi_driver(ad5791_driver); |
470 | |
471 | MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>" ); |
472 | MODULE_DESCRIPTION("Analog Devices AD5760/AD5780/AD5781/AD5790/AD5791 DAC" ); |
473 | MODULE_LICENSE("GPL v2" ); |
474 | |