1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * LTC2688 16 channel, 16 bit Voltage Output SoftSpan DAC driver |
4 | * |
5 | * Copyright 2022 Analog Devices Inc. |
6 | */ |
7 | #include <linux/bitfield.h> |
8 | #include <linux/bits.h> |
9 | #include <linux/clk.h> |
10 | #include <linux/device.h> |
11 | #include <linux/gpio/consumer.h> |
12 | #include <linux/iio/iio.h> |
13 | #include <linux/limits.h> |
14 | #include <linux/kernel.h> |
15 | #include <linux/module.h> |
16 | #include <linux/mod_devicetable.h> |
17 | #include <linux/mutex.h> |
18 | #include <linux/of.h> |
19 | #include <linux/property.h> |
20 | #include <linux/regmap.h> |
21 | #include <linux/regulator/consumer.h> |
22 | #include <linux/spi/spi.h> |
23 | |
24 | #define LTC2688_DAC_CHANNELS 16 |
25 | |
26 | #define LTC2688_CMD_CH_CODE(x) (0x00 + (x)) |
27 | #define LTC2688_CMD_CH_SETTING(x) (0x10 + (x)) |
28 | #define LTC2688_CMD_CH_OFFSET(x) (0X20 + (x)) |
29 | #define LTC2688_CMD_CH_GAIN(x) (0x30 + (x)) |
30 | #define LTC2688_CMD_CH_CODE_UPDATE(x) (0x40 + (x)) |
31 | |
32 | #define LTC2688_CMD_CONFIG 0x70 |
33 | #define LTC2688_CMD_POWERDOWN 0x71 |
34 | #define LTC2688_CMD_A_B_SELECT 0x72 |
35 | #define LTC2688_CMD_SW_TOGGLE 0x73 |
36 | #define LTC2688_CMD_TOGGLE_DITHER_EN 0x74 |
37 | #define LTC2688_CMD_THERMAL_STAT 0x77 |
38 | #define LTC2688_CMD_UPDATE_ALL 0x7C |
39 | #define LTC2688_CMD_NOOP 0xFF |
40 | |
41 | #define LTC2688_READ_OPERATION 0x80 |
42 | |
43 | /* Channel Settings */ |
44 | #define LTC2688_CH_SPAN_MSK GENMASK(2, 0) |
45 | #define LTC2688_CH_OVERRANGE_MSK BIT(3) |
46 | #define LTC2688_CH_TD_SEL_MSK GENMASK(5, 4) |
47 | #define LTC2688_CH_TGP_MAX 3 |
48 | #define LTC2688_CH_DIT_PER_MSK GENMASK(8, 6) |
49 | #define LTC2688_CH_DIT_PH_MSK GENMASK(10, 9) |
50 | #define LTC2688_CH_MODE_MSK BIT(11) |
51 | |
52 | #define LTC2688_DITHER_RAW_MASK GENMASK(15, 2) |
53 | #define LTC2688_CH_CALIBBIAS_MASK GENMASK(15, 2) |
54 | #define LTC2688_DITHER_RAW_MAX_VAL (BIT(14) - 1) |
55 | #define LTC2688_CH_CALIBBIAS_MAX_VAL (BIT(14) - 1) |
56 | |
57 | /* Configuration register */ |
58 | #define LTC2688_CONFIG_RST BIT(15) |
59 | #define LTC2688_CONFIG_EXT_REF BIT(1) |
60 | |
61 | #define LTC2688_DITHER_FREQ_AVAIL_N 5 |
62 | |
63 | enum { |
64 | LTC2688_SPAN_RANGE_0V_5V, |
65 | LTC2688_SPAN_RANGE_0V_10V, |
66 | LTC2688_SPAN_RANGE_M5V_5V, |
67 | LTC2688_SPAN_RANGE_M10V_10V, |
68 | LTC2688_SPAN_RANGE_M15V_15V, |
69 | LTC2688_SPAN_RANGE_MAX |
70 | }; |
71 | |
72 | enum { |
73 | LTC2688_MODE_DEFAULT, |
74 | LTC2688_MODE_DITHER_TOGGLE, |
75 | }; |
76 | |
77 | struct ltc2688_chan { |
78 | long dither_frequency[LTC2688_DITHER_FREQ_AVAIL_N]; |
79 | bool overrange; |
80 | bool toggle_chan; |
81 | u8 mode; |
82 | }; |
83 | |
84 | struct ltc2688_state { |
85 | struct spi_device *spi; |
86 | struct regmap *regmap; |
87 | struct ltc2688_chan channels[LTC2688_DAC_CHANNELS]; |
88 | struct iio_chan_spec *iio_chan; |
89 | /* lock to protect against multiple access to the device and shared data */ |
90 | struct mutex lock; |
91 | int vref; |
92 | /* |
93 | * DMA (thus cache coherency maintenance) may require the |
94 | * transfer buffers to live in their own cache lines. |
95 | */ |
96 | u8 tx_data[6] __aligned(IIO_DMA_MINALIGN); |
97 | u8 rx_data[3]; |
98 | }; |
99 | |
100 | static int ltc2688_spi_read(void *context, const void *reg, size_t reg_size, |
101 | void *val, size_t val_size) |
102 | { |
103 | struct ltc2688_state *st = context; |
104 | struct spi_transfer xfers[] = { |
105 | { |
106 | .tx_buf = st->tx_data, |
107 | .bits_per_word = 8, |
108 | .len = reg_size + val_size, |
109 | .cs_change = 1, |
110 | }, { |
111 | .tx_buf = st->tx_data + 3, |
112 | .rx_buf = st->rx_data, |
113 | .bits_per_word = 8, |
114 | .len = reg_size + val_size, |
115 | }, |
116 | }; |
117 | int ret; |
118 | |
119 | memcpy(st->tx_data, reg, reg_size); |
120 | |
121 | ret = spi_sync_transfer(spi: st->spi, xfers, ARRAY_SIZE(xfers)); |
122 | if (ret) |
123 | return ret; |
124 | |
125 | memcpy(val, &st->rx_data[1], val_size); |
126 | |
127 | return 0; |
128 | } |
129 | |
130 | static int ltc2688_spi_write(void *context, const void *data, size_t count) |
131 | { |
132 | struct ltc2688_state *st = context; |
133 | |
134 | return spi_write(spi: st->spi, buf: data, len: count); |
135 | } |
136 | |
137 | static int ltc2688_span_get(const struct ltc2688_state *st, int c) |
138 | { |
139 | int ret, reg, span; |
140 | |
141 | ret = regmap_read(map: st->regmap, LTC2688_CMD_CH_SETTING(c), val: ®); |
142 | if (ret) |
143 | return ret; |
144 | |
145 | span = FIELD_GET(LTC2688_CH_SPAN_MSK, reg); |
146 | /* sanity check to make sure we don't get any weird value from the HW */ |
147 | if (span >= LTC2688_SPAN_RANGE_MAX) |
148 | return -EIO; |
149 | |
150 | return span; |
151 | } |
152 | |
153 | static const int ltc2688_span_helper[LTC2688_SPAN_RANGE_MAX][2] = { |
154 | {0, 5000}, {0, 10000}, {-5000, 5000}, {-10000, 10000}, {-15000, 15000}, |
155 | }; |
156 | |
157 | static int ltc2688_scale_get(const struct ltc2688_state *st, int c, int *val) |
158 | { |
159 | const struct ltc2688_chan *chan = &st->channels[c]; |
160 | int span, fs; |
161 | |
162 | span = ltc2688_span_get(st, c); |
163 | if (span < 0) |
164 | return span; |
165 | |
166 | fs = ltc2688_span_helper[span][1] - ltc2688_span_helper[span][0]; |
167 | if (chan->overrange) |
168 | fs = mult_frac(fs, 105, 100); |
169 | |
170 | *val = DIV_ROUND_CLOSEST(fs * st->vref, 4096); |
171 | |
172 | return 0; |
173 | } |
174 | |
175 | static int ltc2688_offset_get(const struct ltc2688_state *st, int c, int *val) |
176 | { |
177 | int span; |
178 | |
179 | span = ltc2688_span_get(st, c); |
180 | if (span < 0) |
181 | return span; |
182 | |
183 | if (ltc2688_span_helper[span][0] < 0) |
184 | *val = -32768; |
185 | else |
186 | *val = 0; |
187 | |
188 | return 0; |
189 | } |
190 | |
191 | enum { |
192 | LTC2688_INPUT_A, |
193 | LTC2688_INPUT_B, |
194 | LTC2688_INPUT_B_AVAIL, |
195 | LTC2688_DITHER_OFF, |
196 | LTC2688_DITHER_FREQ_AVAIL, |
197 | }; |
198 | |
199 | static int ltc2688_dac_code_write(struct ltc2688_state *st, u32 chan, u32 input, |
200 | u16 code) |
201 | { |
202 | struct ltc2688_chan *c = &st->channels[chan]; |
203 | int ret, reg; |
204 | |
205 | /* 2 LSBs set to 0 if writing dither amplitude */ |
206 | if (!c->toggle_chan && input == LTC2688_INPUT_B) { |
207 | if (code > LTC2688_DITHER_RAW_MAX_VAL) |
208 | return -EINVAL; |
209 | |
210 | code = FIELD_PREP(LTC2688_DITHER_RAW_MASK, code); |
211 | } |
212 | |
213 | mutex_lock(&st->lock); |
214 | /* select the correct input register to read from */ |
215 | ret = regmap_update_bits(map: st->regmap, LTC2688_CMD_A_B_SELECT, BIT(chan), |
216 | val: input << chan); |
217 | if (ret) |
218 | goto out_unlock; |
219 | |
220 | /* |
221 | * If in dither/toggle mode the dac should be updated by an |
222 | * external signal (or sw toggle) and not here. |
223 | */ |
224 | if (c->mode == LTC2688_MODE_DEFAULT) |
225 | reg = LTC2688_CMD_CH_CODE_UPDATE(chan); |
226 | else |
227 | reg = LTC2688_CMD_CH_CODE(chan); |
228 | |
229 | ret = regmap_write(map: st->regmap, reg, val: code); |
230 | out_unlock: |
231 | mutex_unlock(lock: &st->lock); |
232 | return ret; |
233 | } |
234 | |
235 | static int ltc2688_dac_code_read(struct ltc2688_state *st, u32 chan, u32 input, |
236 | u32 *code) |
237 | { |
238 | struct ltc2688_chan *c = &st->channels[chan]; |
239 | int ret; |
240 | |
241 | mutex_lock(&st->lock); |
242 | ret = regmap_update_bits(map: st->regmap, LTC2688_CMD_A_B_SELECT, BIT(chan), |
243 | val: input << chan); |
244 | if (ret) |
245 | goto out_unlock; |
246 | |
247 | ret = regmap_read(map: st->regmap, LTC2688_CMD_CH_CODE(chan), val: code); |
248 | out_unlock: |
249 | mutex_unlock(lock: &st->lock); |
250 | |
251 | if (!c->toggle_chan && input == LTC2688_INPUT_B) |
252 | *code = FIELD_GET(LTC2688_DITHER_RAW_MASK, *code); |
253 | |
254 | return ret; |
255 | } |
256 | |
257 | static const int ltc2688_raw_range[] = {0, 1, U16_MAX}; |
258 | |
259 | static int ltc2688_read_avail(struct iio_dev *indio_dev, |
260 | struct iio_chan_spec const *chan, |
261 | const int **vals, int *type, int *length, |
262 | long info) |
263 | { |
264 | switch (info) { |
265 | case IIO_CHAN_INFO_RAW: |
266 | *vals = ltc2688_raw_range; |
267 | *type = IIO_VAL_INT; |
268 | return IIO_AVAIL_RANGE; |
269 | default: |
270 | return -EINVAL; |
271 | } |
272 | } |
273 | |
274 | static int ltc2688_read_raw(struct iio_dev *indio_dev, |
275 | struct iio_chan_spec const *chan, int *val, |
276 | int *val2, long info) |
277 | { |
278 | struct ltc2688_state *st = iio_priv(indio_dev); |
279 | int ret; |
280 | |
281 | switch (info) { |
282 | case IIO_CHAN_INFO_RAW: |
283 | ret = ltc2688_dac_code_read(st, chan: chan->channel, input: LTC2688_INPUT_A, |
284 | code: val); |
285 | if (ret) |
286 | return ret; |
287 | |
288 | return IIO_VAL_INT; |
289 | case IIO_CHAN_INFO_OFFSET: |
290 | ret = ltc2688_offset_get(st, c: chan->channel, val); |
291 | if (ret) |
292 | return ret; |
293 | |
294 | return IIO_VAL_INT; |
295 | case IIO_CHAN_INFO_SCALE: |
296 | ret = ltc2688_scale_get(st, c: chan->channel, val); |
297 | if (ret) |
298 | return ret; |
299 | |
300 | *val2 = 16; |
301 | return IIO_VAL_FRACTIONAL_LOG2; |
302 | case IIO_CHAN_INFO_CALIBBIAS: |
303 | ret = regmap_read(map: st->regmap, |
304 | LTC2688_CMD_CH_OFFSET(chan->channel), val); |
305 | if (ret) |
306 | return ret; |
307 | |
308 | *val = FIELD_GET(LTC2688_CH_CALIBBIAS_MASK, *val); |
309 | return IIO_VAL_INT; |
310 | case IIO_CHAN_INFO_CALIBSCALE: |
311 | ret = regmap_read(map: st->regmap, |
312 | LTC2688_CMD_CH_GAIN(chan->channel), val); |
313 | if (ret) |
314 | return ret; |
315 | |
316 | return IIO_VAL_INT; |
317 | default: |
318 | return -EINVAL; |
319 | } |
320 | } |
321 | |
322 | static int ltc2688_write_raw(struct iio_dev *indio_dev, |
323 | struct iio_chan_spec const *chan, int val, |
324 | int val2, long info) |
325 | { |
326 | struct ltc2688_state *st = iio_priv(indio_dev); |
327 | |
328 | switch (info) { |
329 | case IIO_CHAN_INFO_RAW: |
330 | if (val > U16_MAX || val < 0) |
331 | return -EINVAL; |
332 | |
333 | return ltc2688_dac_code_write(st, chan: chan->channel, |
334 | input: LTC2688_INPUT_A, code: val); |
335 | case IIO_CHAN_INFO_CALIBBIAS: |
336 | if (val > LTC2688_CH_CALIBBIAS_MAX_VAL) |
337 | return -EINVAL; |
338 | |
339 | return regmap_write(map: st->regmap, |
340 | LTC2688_CMD_CH_OFFSET(chan->channel), |
341 | FIELD_PREP(LTC2688_CH_CALIBBIAS_MASK, val)); |
342 | case IIO_CHAN_INFO_CALIBSCALE: |
343 | return regmap_write(map: st->regmap, |
344 | LTC2688_CMD_CH_GAIN(chan->channel), val); |
345 | default: |
346 | return -EINVAL; |
347 | } |
348 | } |
349 | |
350 | static ssize_t ltc2688_dither_toggle_set(struct iio_dev *indio_dev, |
351 | uintptr_t private, |
352 | const struct iio_chan_spec *chan, |
353 | const char *buf, size_t len) |
354 | { |
355 | struct ltc2688_state *st = iio_priv(indio_dev); |
356 | struct ltc2688_chan *c = &st->channels[chan->channel]; |
357 | int ret; |
358 | bool en; |
359 | |
360 | ret = kstrtobool(s: buf, res: &en); |
361 | if (ret) |
362 | return ret; |
363 | |
364 | mutex_lock(&st->lock); |
365 | ret = regmap_update_bits(map: st->regmap, LTC2688_CMD_TOGGLE_DITHER_EN, |
366 | BIT(chan->channel), val: en << chan->channel); |
367 | if (ret) |
368 | goto out_unlock; |
369 | |
370 | c->mode = en ? LTC2688_MODE_DITHER_TOGGLE : LTC2688_MODE_DEFAULT; |
371 | out_unlock: |
372 | mutex_unlock(lock: &st->lock); |
373 | |
374 | return ret ?: len; |
375 | } |
376 | |
377 | static ssize_t ltc2688_reg_bool_get(struct iio_dev *indio_dev, |
378 | uintptr_t private, |
379 | const struct iio_chan_spec *chan, |
380 | char *buf) |
381 | { |
382 | const struct ltc2688_state *st = iio_priv(indio_dev); |
383 | int ret; |
384 | u32 val; |
385 | |
386 | ret = regmap_read(map: st->regmap, reg: private, val: &val); |
387 | if (ret) |
388 | return ret; |
389 | |
390 | return sysfs_emit(buf, fmt: "%u\n" , !!(val & BIT(chan->channel))); |
391 | } |
392 | |
393 | static ssize_t ltc2688_reg_bool_set(struct iio_dev *indio_dev, |
394 | uintptr_t private, |
395 | const struct iio_chan_spec *chan, |
396 | const char *buf, size_t len) |
397 | { |
398 | const struct ltc2688_state *st = iio_priv(indio_dev); |
399 | int ret; |
400 | bool en; |
401 | |
402 | ret = kstrtobool(s: buf, res: &en); |
403 | if (ret) |
404 | return ret; |
405 | |
406 | ret = regmap_update_bits(map: st->regmap, reg: private, BIT(chan->channel), |
407 | val: en << chan->channel); |
408 | if (ret) |
409 | return ret; |
410 | |
411 | return len; |
412 | } |
413 | |
414 | static ssize_t ltc2688_dither_freq_avail(const struct ltc2688_state *st, |
415 | const struct ltc2688_chan *chan, |
416 | char *buf) |
417 | { |
418 | int sz = 0; |
419 | u32 f; |
420 | |
421 | for (f = 0; f < ARRAY_SIZE(chan->dither_frequency); f++) |
422 | sz += sysfs_emit_at(buf, at: sz, fmt: "%ld " , chan->dither_frequency[f]); |
423 | |
424 | buf[sz - 1] = '\n'; |
425 | |
426 | return sz; |
427 | } |
428 | |
429 | static ssize_t ltc2688_dither_freq_get(struct iio_dev *indio_dev, |
430 | uintptr_t private, |
431 | const struct iio_chan_spec *chan, |
432 | char *buf) |
433 | { |
434 | const struct ltc2688_state *st = iio_priv(indio_dev); |
435 | const struct ltc2688_chan *c = &st->channels[chan->channel]; |
436 | u32 reg, freq; |
437 | int ret; |
438 | |
439 | if (private == LTC2688_DITHER_FREQ_AVAIL) |
440 | return ltc2688_dither_freq_avail(st, chan: c, buf); |
441 | |
442 | ret = regmap_read(map: st->regmap, LTC2688_CMD_CH_SETTING(chan->channel), |
443 | val: ®); |
444 | if (ret) |
445 | return ret; |
446 | |
447 | freq = FIELD_GET(LTC2688_CH_DIT_PER_MSK, reg); |
448 | if (freq >= ARRAY_SIZE(c->dither_frequency)) |
449 | return -EIO; |
450 | |
451 | return sysfs_emit(buf, fmt: "%ld\n" , c->dither_frequency[freq]); |
452 | } |
453 | |
454 | static ssize_t ltc2688_dither_freq_set(struct iio_dev *indio_dev, |
455 | uintptr_t private, |
456 | const struct iio_chan_spec *chan, |
457 | const char *buf, size_t len) |
458 | { |
459 | const struct ltc2688_state *st = iio_priv(indio_dev); |
460 | const struct ltc2688_chan *c = &st->channels[chan->channel]; |
461 | long val; |
462 | u32 freq; |
463 | int ret; |
464 | |
465 | if (private == LTC2688_DITHER_FREQ_AVAIL) |
466 | return -EINVAL; |
467 | |
468 | ret = kstrtol(s: buf, base: 10, res: &val); |
469 | if (ret) |
470 | return ret; |
471 | |
472 | for (freq = 0; freq < ARRAY_SIZE(c->dither_frequency); freq++) { |
473 | if (val == c->dither_frequency[freq]) |
474 | break; |
475 | } |
476 | |
477 | if (freq == ARRAY_SIZE(c->dither_frequency)) |
478 | return -EINVAL; |
479 | |
480 | ret = regmap_update_bits(map: st->regmap, |
481 | LTC2688_CMD_CH_SETTING(chan->channel), |
482 | LTC2688_CH_DIT_PER_MSK, |
483 | FIELD_PREP(LTC2688_CH_DIT_PER_MSK, freq)); |
484 | if (ret) |
485 | return ret; |
486 | |
487 | return len; |
488 | } |
489 | |
490 | static ssize_t ltc2688_dac_input_read(struct iio_dev *indio_dev, |
491 | uintptr_t private, |
492 | const struct iio_chan_spec *chan, |
493 | char *buf) |
494 | { |
495 | struct ltc2688_state *st = iio_priv(indio_dev); |
496 | int ret; |
497 | u32 val; |
498 | |
499 | if (private == LTC2688_INPUT_B_AVAIL) |
500 | return sysfs_emit(buf, fmt: "[%u %u %u]\n" , ltc2688_raw_range[0], |
501 | ltc2688_raw_range[1], |
502 | ltc2688_raw_range[2] / 4); |
503 | |
504 | if (private == LTC2688_DITHER_OFF) |
505 | return sysfs_emit(buf, fmt: "0\n" ); |
506 | |
507 | ret = ltc2688_dac_code_read(st, chan: chan->channel, input: private, code: &val); |
508 | if (ret) |
509 | return ret; |
510 | |
511 | return sysfs_emit(buf, fmt: "%u\n" , val); |
512 | } |
513 | |
514 | static ssize_t ltc2688_dac_input_write(struct iio_dev *indio_dev, |
515 | uintptr_t private, |
516 | const struct iio_chan_spec *chan, |
517 | const char *buf, size_t len) |
518 | { |
519 | struct ltc2688_state *st = iio_priv(indio_dev); |
520 | int ret; |
521 | u16 val; |
522 | |
523 | if (private == LTC2688_INPUT_B_AVAIL || private == LTC2688_DITHER_OFF) |
524 | return -EINVAL; |
525 | |
526 | ret = kstrtou16(s: buf, base: 10, res: &val); |
527 | if (ret) |
528 | return ret; |
529 | |
530 | ret = ltc2688_dac_code_write(st, chan: chan->channel, input: private, code: val); |
531 | if (ret) |
532 | return ret; |
533 | |
534 | return len; |
535 | } |
536 | |
537 | static int ltc2688_get_dither_phase(struct iio_dev *dev, |
538 | const struct iio_chan_spec *chan) |
539 | { |
540 | struct ltc2688_state *st = iio_priv(indio_dev: dev); |
541 | int ret, regval; |
542 | |
543 | ret = regmap_read(map: st->regmap, LTC2688_CMD_CH_SETTING(chan->channel), |
544 | val: ®val); |
545 | if (ret) |
546 | return ret; |
547 | |
548 | return FIELD_GET(LTC2688_CH_DIT_PH_MSK, regval); |
549 | } |
550 | |
551 | static int ltc2688_set_dither_phase(struct iio_dev *dev, |
552 | const struct iio_chan_spec *chan, |
553 | unsigned int phase) |
554 | { |
555 | struct ltc2688_state *st = iio_priv(indio_dev: dev); |
556 | |
557 | return regmap_update_bits(map: st->regmap, |
558 | LTC2688_CMD_CH_SETTING(chan->channel), |
559 | LTC2688_CH_DIT_PH_MSK, |
560 | FIELD_PREP(LTC2688_CH_DIT_PH_MSK, phase)); |
561 | } |
562 | |
563 | static int ltc2688_reg_access(struct iio_dev *indio_dev, |
564 | unsigned int reg, |
565 | unsigned int writeval, |
566 | unsigned int *readval) |
567 | { |
568 | struct ltc2688_state *st = iio_priv(indio_dev); |
569 | |
570 | if (readval) |
571 | return regmap_read(map: st->regmap, reg, val: readval); |
572 | |
573 | return regmap_write(map: st->regmap, reg, val: writeval); |
574 | } |
575 | |
576 | static const char * const ltc2688_dither_phase[] = { |
577 | "0" , "1.5708" , "3.14159" , "4.71239" , |
578 | }; |
579 | |
580 | static const struct iio_enum ltc2688_dither_phase_enum = { |
581 | .items = ltc2688_dither_phase, |
582 | .num_items = ARRAY_SIZE(ltc2688_dither_phase), |
583 | .set = ltc2688_set_dither_phase, |
584 | .get = ltc2688_get_dither_phase, |
585 | }; |
586 | |
587 | #define LTC2688_CHAN_EXT_INFO(_name, _what, _shared, _read, _write) { \ |
588 | .name = _name, \ |
589 | .read = (_read), \ |
590 | .write = (_write), \ |
591 | .private = (_what), \ |
592 | .shared = (_shared), \ |
593 | } |
594 | |
595 | /* |
596 | * For toggle mode we only expose the symbol attr (sw_toggle) in case a TGPx is |
597 | * not provided in dts. |
598 | */ |
599 | static const struct iio_chan_spec_ext_info ltc2688_toggle_sym_ext_info[] = { |
600 | LTC2688_CHAN_EXT_INFO("raw0" , LTC2688_INPUT_A, IIO_SEPARATE, |
601 | ltc2688_dac_input_read, ltc2688_dac_input_write), |
602 | LTC2688_CHAN_EXT_INFO("raw1" , LTC2688_INPUT_B, IIO_SEPARATE, |
603 | ltc2688_dac_input_read, ltc2688_dac_input_write), |
604 | LTC2688_CHAN_EXT_INFO("toggle_en" , LTC2688_CMD_TOGGLE_DITHER_EN, |
605 | IIO_SEPARATE, ltc2688_reg_bool_get, |
606 | ltc2688_dither_toggle_set), |
607 | LTC2688_CHAN_EXT_INFO("powerdown" , LTC2688_CMD_POWERDOWN, IIO_SEPARATE, |
608 | ltc2688_reg_bool_get, ltc2688_reg_bool_set), |
609 | LTC2688_CHAN_EXT_INFO("symbol" , LTC2688_CMD_SW_TOGGLE, IIO_SEPARATE, |
610 | ltc2688_reg_bool_get, ltc2688_reg_bool_set), |
611 | {} |
612 | }; |
613 | |
614 | static const struct iio_chan_spec_ext_info ltc2688_toggle_ext_info[] = { |
615 | LTC2688_CHAN_EXT_INFO("raw0" , LTC2688_INPUT_A, IIO_SEPARATE, |
616 | ltc2688_dac_input_read, ltc2688_dac_input_write), |
617 | LTC2688_CHAN_EXT_INFO("raw1" , LTC2688_INPUT_B, IIO_SEPARATE, |
618 | ltc2688_dac_input_read, ltc2688_dac_input_write), |
619 | LTC2688_CHAN_EXT_INFO("toggle_en" , LTC2688_CMD_TOGGLE_DITHER_EN, |
620 | IIO_SEPARATE, ltc2688_reg_bool_get, |
621 | ltc2688_dither_toggle_set), |
622 | LTC2688_CHAN_EXT_INFO("powerdown" , LTC2688_CMD_POWERDOWN, IIO_SEPARATE, |
623 | ltc2688_reg_bool_get, ltc2688_reg_bool_set), |
624 | {} |
625 | }; |
626 | |
627 | static struct iio_chan_spec_ext_info ltc2688_dither_ext_info[] = { |
628 | LTC2688_CHAN_EXT_INFO("dither_raw" , LTC2688_INPUT_B, IIO_SEPARATE, |
629 | ltc2688_dac_input_read, ltc2688_dac_input_write), |
630 | LTC2688_CHAN_EXT_INFO("dither_raw_available" , LTC2688_INPUT_B_AVAIL, |
631 | IIO_SEPARATE, ltc2688_dac_input_read, |
632 | ltc2688_dac_input_write), |
633 | LTC2688_CHAN_EXT_INFO("dither_offset" , LTC2688_DITHER_OFF, IIO_SEPARATE, |
634 | ltc2688_dac_input_read, ltc2688_dac_input_write), |
635 | /* |
636 | * Not IIO_ENUM because the available freq needs to be computed at |
637 | * probe. We could still use it, but it didn't felt much right. |
638 | */ |
639 | LTC2688_CHAN_EXT_INFO("dither_frequency" , 0, IIO_SEPARATE, |
640 | ltc2688_dither_freq_get, ltc2688_dither_freq_set), |
641 | LTC2688_CHAN_EXT_INFO("dither_frequency_available" , |
642 | LTC2688_DITHER_FREQ_AVAIL, IIO_SEPARATE, |
643 | ltc2688_dither_freq_get, ltc2688_dither_freq_set), |
644 | IIO_ENUM("dither_phase" , IIO_SEPARATE, <c2688_dither_phase_enum), |
645 | IIO_ENUM_AVAILABLE("dither_phase" , IIO_SEPARATE, |
646 | <c2688_dither_phase_enum), |
647 | LTC2688_CHAN_EXT_INFO("dither_en" , LTC2688_CMD_TOGGLE_DITHER_EN, |
648 | IIO_SEPARATE, ltc2688_reg_bool_get, |
649 | ltc2688_dither_toggle_set), |
650 | LTC2688_CHAN_EXT_INFO("powerdown" , LTC2688_CMD_POWERDOWN, IIO_SEPARATE, |
651 | ltc2688_reg_bool_get, ltc2688_reg_bool_set), |
652 | {} |
653 | }; |
654 | |
655 | static const struct iio_chan_spec_ext_info ltc2688_ext_info[] = { |
656 | LTC2688_CHAN_EXT_INFO("powerdown" , LTC2688_CMD_POWERDOWN, IIO_SEPARATE, |
657 | ltc2688_reg_bool_get, ltc2688_reg_bool_set), |
658 | {} |
659 | }; |
660 | |
661 | #define LTC2688_CHANNEL(_chan) { \ |
662 | .type = IIO_VOLTAGE, \ |
663 | .indexed = 1, \ |
664 | .output = 1, \ |
665 | .channel = (_chan), \ |
666 | .info_mask_separate = BIT(IIO_CHAN_INFO_CALIBSCALE) | \ |
667 | BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET) | \ |
668 | BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_RAW), \ |
669 | .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW), \ |
670 | .ext_info = ltc2688_ext_info, \ |
671 | } |
672 | |
673 | static const struct iio_chan_spec ltc2688_channels[] = { |
674 | LTC2688_CHANNEL(0), |
675 | LTC2688_CHANNEL(1), |
676 | LTC2688_CHANNEL(2), |
677 | LTC2688_CHANNEL(3), |
678 | LTC2688_CHANNEL(4), |
679 | LTC2688_CHANNEL(5), |
680 | LTC2688_CHANNEL(6), |
681 | LTC2688_CHANNEL(7), |
682 | LTC2688_CHANNEL(8), |
683 | LTC2688_CHANNEL(9), |
684 | LTC2688_CHANNEL(10), |
685 | LTC2688_CHANNEL(11), |
686 | LTC2688_CHANNEL(12), |
687 | LTC2688_CHANNEL(13), |
688 | LTC2688_CHANNEL(14), |
689 | LTC2688_CHANNEL(15), |
690 | }; |
691 | |
692 | static void ltc2688_clk_disable(void *clk) |
693 | { |
694 | clk_disable_unprepare(clk); |
695 | } |
696 | |
697 | static const int ltc2688_period[LTC2688_DITHER_FREQ_AVAIL_N] = { |
698 | 4, 8, 16, 32, 64, |
699 | }; |
700 | |
701 | static int ltc2688_tgp_clk_setup(struct ltc2688_state *st, |
702 | struct ltc2688_chan *chan, |
703 | struct fwnode_handle *node, int tgp) |
704 | { |
705 | struct device *dev = &st->spi->dev; |
706 | unsigned long rate; |
707 | struct clk *clk; |
708 | int ret, f; |
709 | |
710 | clk = devm_get_clk_from_child(dev, to_of_node(node), NULL); |
711 | if (IS_ERR(ptr: clk)) |
712 | return dev_err_probe(dev, err: PTR_ERR(ptr: clk), fmt: "failed to get tgp clk.\n" ); |
713 | |
714 | ret = clk_prepare_enable(clk); |
715 | if (ret) |
716 | return dev_err_probe(dev, err: ret, fmt: "failed to enable tgp clk.\n" ); |
717 | |
718 | ret = devm_add_action_or_reset(dev, ltc2688_clk_disable, clk); |
719 | if (ret) |
720 | return ret; |
721 | |
722 | if (chan->toggle_chan) |
723 | return 0; |
724 | |
725 | /* calculate available dither frequencies */ |
726 | rate = clk_get_rate(clk); |
727 | for (f = 0; f < ARRAY_SIZE(chan->dither_frequency); f++) |
728 | chan->dither_frequency[f] = DIV_ROUND_CLOSEST(rate, ltc2688_period[f]); |
729 | |
730 | return 0; |
731 | } |
732 | |
733 | static int ltc2688_span_lookup(const struct ltc2688_state *st, int min, int max) |
734 | { |
735 | u32 span; |
736 | |
737 | for (span = 0; span < ARRAY_SIZE(ltc2688_span_helper); span++) { |
738 | if (min == ltc2688_span_helper[span][0] && |
739 | max == ltc2688_span_helper[span][1]) |
740 | return span; |
741 | } |
742 | |
743 | return -EINVAL; |
744 | } |
745 | |
746 | static int ltc2688_channel_config(struct ltc2688_state *st) |
747 | { |
748 | struct device *dev = &st->spi->dev; |
749 | struct fwnode_handle *child; |
750 | u32 reg, clk_input, val, tmp[2]; |
751 | int ret, span; |
752 | |
753 | device_for_each_child_node(dev, child) { |
754 | struct ltc2688_chan *chan; |
755 | |
756 | ret = fwnode_property_read_u32(fwnode: child, propname: "reg" , val: ®); |
757 | if (ret) { |
758 | fwnode_handle_put(fwnode: child); |
759 | return dev_err_probe(dev, err: ret, |
760 | fmt: "Failed to get reg property\n" ); |
761 | } |
762 | |
763 | if (reg >= LTC2688_DAC_CHANNELS) { |
764 | fwnode_handle_put(fwnode: child); |
765 | return dev_err_probe(dev, err: -EINVAL, |
766 | fmt: "reg bigger than: %d\n" , |
767 | LTC2688_DAC_CHANNELS); |
768 | } |
769 | |
770 | val = 0; |
771 | chan = &st->channels[reg]; |
772 | if (fwnode_property_read_bool(fwnode: child, propname: "adi,toggle-mode" )) { |
773 | chan->toggle_chan = true; |
774 | /* assume sw toggle ABI */ |
775 | st->iio_chan[reg].ext_info = ltc2688_toggle_sym_ext_info; |
776 | /* |
777 | * Clear IIO_CHAN_INFO_RAW bit as toggle channels expose |
778 | * out_voltage_raw{0|1} files. |
779 | */ |
780 | __clear_bit(IIO_CHAN_INFO_RAW, |
781 | &st->iio_chan[reg].info_mask_separate); |
782 | } |
783 | |
784 | ret = fwnode_property_read_u32_array(fwnode: child, propname: "adi,output-range-microvolt" , |
785 | val: tmp, ARRAY_SIZE(tmp)); |
786 | if (!ret) { |
787 | span = ltc2688_span_lookup(st, min: (int)tmp[0] / 1000, |
788 | max: tmp[1] / 1000); |
789 | if (span < 0) { |
790 | fwnode_handle_put(fwnode: child); |
791 | return dev_err_probe(dev, err: -EINVAL, |
792 | fmt: "output range not valid:[%d %d]\n" , |
793 | tmp[0], tmp[1]); |
794 | } |
795 | |
796 | val |= FIELD_PREP(LTC2688_CH_SPAN_MSK, span); |
797 | } |
798 | |
799 | ret = fwnode_property_read_u32(fwnode: child, propname: "adi,toggle-dither-input" , |
800 | val: &clk_input); |
801 | if (!ret) { |
802 | if (clk_input >= LTC2688_CH_TGP_MAX) { |
803 | fwnode_handle_put(fwnode: child); |
804 | return dev_err_probe(dev, err: -EINVAL, |
805 | fmt: "toggle-dither-input inv value(%d)\n" , |
806 | clk_input); |
807 | } |
808 | |
809 | ret = ltc2688_tgp_clk_setup(st, chan, node: child, tgp: clk_input); |
810 | if (ret) { |
811 | fwnode_handle_put(fwnode: child); |
812 | return ret; |
813 | } |
814 | |
815 | /* |
816 | * 0 means software toggle which is the default mode. |
817 | * Hence the +1. |
818 | */ |
819 | val |= FIELD_PREP(LTC2688_CH_TD_SEL_MSK, clk_input + 1); |
820 | |
821 | /* |
822 | * If a TGPx is given, we automatically assume a dither |
823 | * capable channel (unless toggle is already enabled). |
824 | * On top of this we just set here the dither bit in the |
825 | * channel settings. It won't have any effect until the |
826 | * global toggle/dither bit is enabled. |
827 | */ |
828 | if (!chan->toggle_chan) { |
829 | val |= FIELD_PREP(LTC2688_CH_MODE_MSK, 1); |
830 | st->iio_chan[reg].ext_info = ltc2688_dither_ext_info; |
831 | } else { |
832 | /* wait, no sw toggle after all */ |
833 | st->iio_chan[reg].ext_info = ltc2688_toggle_ext_info; |
834 | } |
835 | } |
836 | |
837 | if (fwnode_property_read_bool(fwnode: child, propname: "adi,overrange" )) { |
838 | chan->overrange = true; |
839 | val |= LTC2688_CH_OVERRANGE_MSK; |
840 | } |
841 | |
842 | if (!val) |
843 | continue; |
844 | |
845 | ret = regmap_write(map: st->regmap, LTC2688_CMD_CH_SETTING(reg), |
846 | val); |
847 | if (ret) { |
848 | fwnode_handle_put(fwnode: child); |
849 | return dev_err_probe(dev, err: -EINVAL, |
850 | fmt: "failed to set chan settings\n" ); |
851 | } |
852 | } |
853 | |
854 | return 0; |
855 | } |
856 | |
857 | static int ltc2688_setup(struct ltc2688_state *st, struct regulator *vref) |
858 | { |
859 | struct device *dev = &st->spi->dev; |
860 | struct gpio_desc *gpio; |
861 | int ret; |
862 | |
863 | /* |
864 | * If we have a reset pin, use that to reset the board, If not, use |
865 | * the reset bit. |
866 | */ |
867 | gpio = devm_gpiod_get_optional(dev, con_id: "clr" , flags: GPIOD_OUT_HIGH); |
868 | if (IS_ERR(ptr: gpio)) |
869 | return dev_err_probe(dev, err: PTR_ERR(ptr: gpio), fmt: "Failed to get reset gpio" ); |
870 | if (gpio) { |
871 | usleep_range(min: 1000, max: 1200); |
872 | /* bring device out of reset */ |
873 | gpiod_set_value_cansleep(desc: gpio, value: 0); |
874 | } else { |
875 | ret = regmap_update_bits(map: st->regmap, LTC2688_CMD_CONFIG, |
876 | LTC2688_CONFIG_RST, |
877 | LTC2688_CONFIG_RST); |
878 | if (ret) |
879 | return ret; |
880 | } |
881 | |
882 | usleep_range(min: 10000, max: 12000); |
883 | |
884 | /* |
885 | * Duplicate the default channel configuration as it can change during |
886 | * @ltc2688_channel_config() |
887 | */ |
888 | st->iio_chan = devm_kmemdup(dev, src: ltc2688_channels, |
889 | len: sizeof(ltc2688_channels), GFP_KERNEL); |
890 | if (!st->iio_chan) |
891 | return -ENOMEM; |
892 | |
893 | ret = ltc2688_channel_config(st); |
894 | if (ret) |
895 | return ret; |
896 | |
897 | if (!vref) |
898 | return 0; |
899 | |
900 | return regmap_set_bits(map: st->regmap, LTC2688_CMD_CONFIG, |
901 | LTC2688_CONFIG_EXT_REF); |
902 | } |
903 | |
904 | static void ltc2688_disable_regulator(void *regulator) |
905 | { |
906 | regulator_disable(regulator); |
907 | } |
908 | |
909 | static bool ltc2688_reg_readable(struct device *dev, unsigned int reg) |
910 | { |
911 | switch (reg) { |
912 | case LTC2688_CMD_CH_CODE(0) ... LTC2688_CMD_CH_GAIN(15): |
913 | return true; |
914 | case LTC2688_CMD_CONFIG ... LTC2688_CMD_THERMAL_STAT: |
915 | return true; |
916 | default: |
917 | return false; |
918 | } |
919 | } |
920 | |
921 | static bool ltc2688_reg_writable(struct device *dev, unsigned int reg) |
922 | { |
923 | /* |
924 | * There's a jump from 0x76 to 0x78 in the write codes and the thermal |
925 | * status code is 0x77 (which is read only) so that we need to check |
926 | * that special condition. |
927 | */ |
928 | if (reg <= LTC2688_CMD_UPDATE_ALL && reg != LTC2688_CMD_THERMAL_STAT) |
929 | return true; |
930 | |
931 | return false; |
932 | } |
933 | |
934 | static struct regmap_bus ltc2688_regmap_bus = { |
935 | .read = ltc2688_spi_read, |
936 | .write = ltc2688_spi_write, |
937 | .read_flag_mask = LTC2688_READ_OPERATION, |
938 | .reg_format_endian_default = REGMAP_ENDIAN_BIG, |
939 | .val_format_endian_default = REGMAP_ENDIAN_BIG, |
940 | }; |
941 | |
942 | static const struct regmap_config ltc2688_regmap_config = { |
943 | .reg_bits = 8, |
944 | .val_bits = 16, |
945 | .readable_reg = ltc2688_reg_readable, |
946 | .writeable_reg = ltc2688_reg_writable, |
947 | /* ignoring the no op command */ |
948 | .max_register = LTC2688_CMD_UPDATE_ALL, |
949 | }; |
950 | |
951 | static const struct iio_info ltc2688_info = { |
952 | .write_raw = ltc2688_write_raw, |
953 | .read_raw = ltc2688_read_raw, |
954 | .read_avail = ltc2688_read_avail, |
955 | .debugfs_reg_access = ltc2688_reg_access, |
956 | }; |
957 | |
958 | static int ltc2688_probe(struct spi_device *spi) |
959 | { |
960 | static const char * const regulators[] = { "vcc" , "iovcc" }; |
961 | struct ltc2688_state *st; |
962 | struct iio_dev *indio_dev; |
963 | struct regulator *vref_reg; |
964 | struct device *dev = &spi->dev; |
965 | int ret; |
966 | |
967 | indio_dev = devm_iio_device_alloc(parent: dev, sizeof_priv: sizeof(*st)); |
968 | if (!indio_dev) |
969 | return -ENOMEM; |
970 | |
971 | st = iio_priv(indio_dev); |
972 | st->spi = spi; |
973 | |
974 | /* Just write this once. No need to do it in every regmap read. */ |
975 | st->tx_data[3] = LTC2688_CMD_NOOP; |
976 | mutex_init(&st->lock); |
977 | |
978 | st->regmap = devm_regmap_init(dev, <c2688_regmap_bus, st, |
979 | <c2688_regmap_config); |
980 | if (IS_ERR(ptr: st->regmap)) |
981 | return dev_err_probe(dev, err: PTR_ERR(ptr: st->regmap), |
982 | fmt: "Failed to init regmap" ); |
983 | |
984 | ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulators), |
985 | id: regulators); |
986 | if (ret) |
987 | return dev_err_probe(dev, err: ret, fmt: "Failed to enable regulators\n" ); |
988 | |
989 | vref_reg = devm_regulator_get_optional(dev, id: "vref" ); |
990 | if (IS_ERR(ptr: vref_reg)) { |
991 | if (PTR_ERR(ptr: vref_reg) != -ENODEV) |
992 | return dev_err_probe(dev, err: PTR_ERR(ptr: vref_reg), |
993 | fmt: "Failed to get vref regulator" ); |
994 | |
995 | vref_reg = NULL; |
996 | /* internal reference */ |
997 | st->vref = 4096; |
998 | } else { |
999 | ret = regulator_enable(regulator: vref_reg); |
1000 | if (ret) |
1001 | return dev_err_probe(dev, err: ret, |
1002 | fmt: "Failed to enable vref regulators\n" ); |
1003 | |
1004 | ret = devm_add_action_or_reset(dev, ltc2688_disable_regulator, |
1005 | vref_reg); |
1006 | if (ret) |
1007 | return ret; |
1008 | |
1009 | ret = regulator_get_voltage(regulator: vref_reg); |
1010 | if (ret < 0) |
1011 | return dev_err_probe(dev, err: ret, fmt: "Failed to get vref\n" ); |
1012 | |
1013 | st->vref = ret / 1000; |
1014 | } |
1015 | |
1016 | ret = ltc2688_setup(st, vref: vref_reg); |
1017 | if (ret) |
1018 | return ret; |
1019 | |
1020 | indio_dev->name = "ltc2688" ; |
1021 | indio_dev->info = <c2688_info; |
1022 | indio_dev->modes = INDIO_DIRECT_MODE; |
1023 | indio_dev->channels = st->iio_chan; |
1024 | indio_dev->num_channels = ARRAY_SIZE(ltc2688_channels); |
1025 | |
1026 | return devm_iio_device_register(dev, indio_dev); |
1027 | } |
1028 | |
1029 | static const struct of_device_id ltc2688_of_id[] = { |
1030 | { .compatible = "adi,ltc2688" }, |
1031 | {} |
1032 | }; |
1033 | MODULE_DEVICE_TABLE(of, ltc2688_of_id); |
1034 | |
1035 | static const struct spi_device_id ltc2688_id[] = { |
1036 | { "ltc2688" }, |
1037 | {} |
1038 | }; |
1039 | MODULE_DEVICE_TABLE(spi, ltc2688_id); |
1040 | |
1041 | static struct spi_driver ltc2688_driver = { |
1042 | .driver = { |
1043 | .name = "ltc2688" , |
1044 | .of_match_table = ltc2688_of_id, |
1045 | }, |
1046 | .probe = ltc2688_probe, |
1047 | .id_table = ltc2688_id, |
1048 | }; |
1049 | module_spi_driver(ltc2688_driver); |
1050 | |
1051 | MODULE_AUTHOR("Nuno Sá <nuno.sa@analog.com>" ); |
1052 | MODULE_DESCRIPTION("Analog Devices LTC2688 DAC" ); |
1053 | MODULE_LICENSE("GPL" ); |
1054 | |