1832cb9eeSNuno Sá // SPDX-License-Identifier: GPL-2.0
2832cb9eeSNuno Sá /*
3832cb9eeSNuno Sá * LTC2688 16 channel, 16 bit Voltage Output SoftSpan DAC driver
4832cb9eeSNuno Sá *
5832cb9eeSNuno Sá * Copyright 2022 Analog Devices Inc.
6832cb9eeSNuno Sá */
7832cb9eeSNuno Sá #include <linux/bitfield.h>
8832cb9eeSNuno Sá #include <linux/bits.h>
9832cb9eeSNuno Sá #include <linux/clk.h>
10832cb9eeSNuno Sá #include <linux/device.h>
11832cb9eeSNuno Sá #include <linux/gpio/consumer.h>
12832cb9eeSNuno Sá #include <linux/iio/iio.h>
13832cb9eeSNuno Sá #include <linux/limits.h>
14832cb9eeSNuno Sá #include <linux/kernel.h>
15832cb9eeSNuno Sá #include <linux/module.h>
16832cb9eeSNuno Sá #include <linux/mod_devicetable.h>
17832cb9eeSNuno Sá #include <linux/mutex.h>
18832cb9eeSNuno Sá #include <linux/of.h>
19832cb9eeSNuno Sá #include <linux/property.h>
20832cb9eeSNuno Sá #include <linux/regmap.h>
21832cb9eeSNuno Sá #include <linux/regulator/consumer.h>
22832cb9eeSNuno Sá #include <linux/spi/spi.h>
23832cb9eeSNuno Sá
24832cb9eeSNuno Sá #define LTC2688_DAC_CHANNELS 16
25832cb9eeSNuno Sá
26832cb9eeSNuno Sá #define LTC2688_CMD_CH_CODE(x) (0x00 + (x))
27832cb9eeSNuno Sá #define LTC2688_CMD_CH_SETTING(x) (0x10 + (x))
28832cb9eeSNuno Sá #define LTC2688_CMD_CH_OFFSET(x) (0X20 + (x))
29832cb9eeSNuno Sá #define LTC2688_CMD_CH_GAIN(x) (0x30 + (x))
30832cb9eeSNuno Sá #define LTC2688_CMD_CH_CODE_UPDATE(x) (0x40 + (x))
31832cb9eeSNuno Sá
32832cb9eeSNuno Sá #define LTC2688_CMD_CONFIG 0x70
33832cb9eeSNuno Sá #define LTC2688_CMD_POWERDOWN 0x71
34832cb9eeSNuno Sá #define LTC2688_CMD_A_B_SELECT 0x72
35832cb9eeSNuno Sá #define LTC2688_CMD_SW_TOGGLE 0x73
36832cb9eeSNuno Sá #define LTC2688_CMD_TOGGLE_DITHER_EN 0x74
37832cb9eeSNuno Sá #define LTC2688_CMD_THERMAL_STAT 0x77
38832cb9eeSNuno Sá #define LTC2688_CMD_UPDATE_ALL 0x7C
39832cb9eeSNuno Sá #define LTC2688_CMD_NOOP 0xFF
40832cb9eeSNuno Sá
41832cb9eeSNuno Sá #define LTC2688_READ_OPERATION 0x80
42832cb9eeSNuno Sá
43832cb9eeSNuno Sá /* Channel Settings */
44832cb9eeSNuno Sá #define LTC2688_CH_SPAN_MSK GENMASK(2, 0)
45832cb9eeSNuno Sá #define LTC2688_CH_OVERRANGE_MSK BIT(3)
46832cb9eeSNuno Sá #define LTC2688_CH_TD_SEL_MSK GENMASK(5, 4)
47832cb9eeSNuno Sá #define LTC2688_CH_TGP_MAX 3
48832cb9eeSNuno Sá #define LTC2688_CH_DIT_PER_MSK GENMASK(8, 6)
49832cb9eeSNuno Sá #define LTC2688_CH_DIT_PH_MSK GENMASK(10, 9)
50832cb9eeSNuno Sá #define LTC2688_CH_MODE_MSK BIT(11)
51832cb9eeSNuno Sá
52832cb9eeSNuno Sá #define LTC2688_DITHER_RAW_MASK GENMASK(15, 2)
53832cb9eeSNuno Sá #define LTC2688_CH_CALIBBIAS_MASK GENMASK(15, 2)
54832cb9eeSNuno Sá #define LTC2688_DITHER_RAW_MAX_VAL (BIT(14) - 1)
55832cb9eeSNuno Sá #define LTC2688_CH_CALIBBIAS_MAX_VAL (BIT(14) - 1)
56832cb9eeSNuno Sá
57832cb9eeSNuno Sá /* Configuration register */
58832cb9eeSNuno Sá #define LTC2688_CONFIG_RST BIT(15)
59832cb9eeSNuno Sá #define LTC2688_CONFIG_EXT_REF BIT(1)
60832cb9eeSNuno Sá
61832cb9eeSNuno Sá #define LTC2688_DITHER_FREQ_AVAIL_N 5
62832cb9eeSNuno Sá
63832cb9eeSNuno Sá enum {
64832cb9eeSNuno Sá LTC2688_SPAN_RANGE_0V_5V,
65832cb9eeSNuno Sá LTC2688_SPAN_RANGE_0V_10V,
66832cb9eeSNuno Sá LTC2688_SPAN_RANGE_M5V_5V,
67832cb9eeSNuno Sá LTC2688_SPAN_RANGE_M10V_10V,
68832cb9eeSNuno Sá LTC2688_SPAN_RANGE_M15V_15V,
69832cb9eeSNuno Sá LTC2688_SPAN_RANGE_MAX
70832cb9eeSNuno Sá };
71832cb9eeSNuno Sá
72832cb9eeSNuno Sá enum {
73832cb9eeSNuno Sá LTC2688_MODE_DEFAULT,
74832cb9eeSNuno Sá LTC2688_MODE_DITHER_TOGGLE,
75832cb9eeSNuno Sá };
76832cb9eeSNuno Sá
77832cb9eeSNuno Sá struct ltc2688_chan {
78832cb9eeSNuno Sá long dither_frequency[LTC2688_DITHER_FREQ_AVAIL_N];
79832cb9eeSNuno Sá bool overrange;
80832cb9eeSNuno Sá bool toggle_chan;
81832cb9eeSNuno Sá u8 mode;
82832cb9eeSNuno Sá };
83832cb9eeSNuno Sá
84832cb9eeSNuno Sá struct ltc2688_state {
85832cb9eeSNuno Sá struct spi_device *spi;
86832cb9eeSNuno Sá struct regmap *regmap;
87832cb9eeSNuno Sá struct ltc2688_chan channels[LTC2688_DAC_CHANNELS];
88832cb9eeSNuno Sá struct iio_chan_spec *iio_chan;
89832cb9eeSNuno Sá /* lock to protect against multiple access to the device and shared data */
90832cb9eeSNuno Sá struct mutex lock;
91832cb9eeSNuno Sá int vref;
92832cb9eeSNuno Sá /*
9320307083SJonathan Cameron * DMA (thus cache coherency maintenance) may require the
94832cb9eeSNuno Sá * transfer buffers to live in their own cache lines.
95832cb9eeSNuno Sá */
9620307083SJonathan Cameron u8 tx_data[6] __aligned(IIO_DMA_MINALIGN);
97832cb9eeSNuno Sá u8 rx_data[3];
98832cb9eeSNuno Sá };
99832cb9eeSNuno Sá
ltc2688_spi_read(void * context,const void * reg,size_t reg_size,void * val,size_t val_size)100832cb9eeSNuno Sá static int ltc2688_spi_read(void *context, const void *reg, size_t reg_size,
101832cb9eeSNuno Sá void *val, size_t val_size)
102832cb9eeSNuno Sá {
103832cb9eeSNuno Sá struct ltc2688_state *st = context;
104832cb9eeSNuno Sá struct spi_transfer xfers[] = {
105832cb9eeSNuno Sá {
106832cb9eeSNuno Sá .tx_buf = st->tx_data,
107832cb9eeSNuno Sá .bits_per_word = 8,
108832cb9eeSNuno Sá .len = reg_size + val_size,
109832cb9eeSNuno Sá .cs_change = 1,
110832cb9eeSNuno Sá }, {
111832cb9eeSNuno Sá .tx_buf = st->tx_data + 3,
112832cb9eeSNuno Sá .rx_buf = st->rx_data,
113832cb9eeSNuno Sá .bits_per_word = 8,
114832cb9eeSNuno Sá .len = reg_size + val_size,
115832cb9eeSNuno Sá },
116832cb9eeSNuno Sá };
117832cb9eeSNuno Sá int ret;
118832cb9eeSNuno Sá
119832cb9eeSNuno Sá memcpy(st->tx_data, reg, reg_size);
120832cb9eeSNuno Sá
121832cb9eeSNuno Sá ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
122832cb9eeSNuno Sá if (ret)
123832cb9eeSNuno Sá return ret;
124832cb9eeSNuno Sá
125832cb9eeSNuno Sá memcpy(val, &st->rx_data[1], val_size);
126832cb9eeSNuno Sá
127832cb9eeSNuno Sá return 0;
128832cb9eeSNuno Sá }
129832cb9eeSNuno Sá
ltc2688_spi_write(void * context,const void * data,size_t count)130832cb9eeSNuno Sá static int ltc2688_spi_write(void *context, const void *data, size_t count)
131832cb9eeSNuno Sá {
132832cb9eeSNuno Sá struct ltc2688_state *st = context;
133832cb9eeSNuno Sá
134832cb9eeSNuno Sá return spi_write(st->spi, data, count);
135832cb9eeSNuno Sá }
136832cb9eeSNuno Sá
ltc2688_span_get(const struct ltc2688_state * st,int c)137832cb9eeSNuno Sá static int ltc2688_span_get(const struct ltc2688_state *st, int c)
138832cb9eeSNuno Sá {
139832cb9eeSNuno Sá int ret, reg, span;
140832cb9eeSNuno Sá
141832cb9eeSNuno Sá ret = regmap_read(st->regmap, LTC2688_CMD_CH_SETTING(c), ®);
142832cb9eeSNuno Sá if (ret)
143832cb9eeSNuno Sá return ret;
144832cb9eeSNuno Sá
145832cb9eeSNuno Sá span = FIELD_GET(LTC2688_CH_SPAN_MSK, reg);
146832cb9eeSNuno Sá /* sanity check to make sure we don't get any weird value from the HW */
147832cb9eeSNuno Sá if (span >= LTC2688_SPAN_RANGE_MAX)
148832cb9eeSNuno Sá return -EIO;
149832cb9eeSNuno Sá
150832cb9eeSNuno Sá return span;
151832cb9eeSNuno Sá }
152832cb9eeSNuno Sá
153832cb9eeSNuno Sá static const int ltc2688_span_helper[LTC2688_SPAN_RANGE_MAX][2] = {
154832cb9eeSNuno Sá {0, 5000}, {0, 10000}, {-5000, 5000}, {-10000, 10000}, {-15000, 15000},
155832cb9eeSNuno Sá };
156832cb9eeSNuno Sá
ltc2688_scale_get(const struct ltc2688_state * st,int c,int * val)157832cb9eeSNuno Sá static int ltc2688_scale_get(const struct ltc2688_state *st, int c, int *val)
158832cb9eeSNuno Sá {
159832cb9eeSNuno Sá const struct ltc2688_chan *chan = &st->channels[c];
160832cb9eeSNuno Sá int span, fs;
161832cb9eeSNuno Sá
162832cb9eeSNuno Sá span = ltc2688_span_get(st, c);
163832cb9eeSNuno Sá if (span < 0)
164832cb9eeSNuno Sá return span;
165832cb9eeSNuno Sá
166832cb9eeSNuno Sá fs = ltc2688_span_helper[span][1] - ltc2688_span_helper[span][0];
167832cb9eeSNuno Sá if (chan->overrange)
168832cb9eeSNuno Sá fs = mult_frac(fs, 105, 100);
169832cb9eeSNuno Sá
170832cb9eeSNuno Sá *val = DIV_ROUND_CLOSEST(fs * st->vref, 4096);
171832cb9eeSNuno Sá
172832cb9eeSNuno Sá return 0;
173832cb9eeSNuno Sá }
174832cb9eeSNuno Sá
ltc2688_offset_get(const struct ltc2688_state * st,int c,int * val)175832cb9eeSNuno Sá static int ltc2688_offset_get(const struct ltc2688_state *st, int c, int *val)
176832cb9eeSNuno Sá {
177832cb9eeSNuno Sá int span;
178832cb9eeSNuno Sá
179832cb9eeSNuno Sá span = ltc2688_span_get(st, c);
180832cb9eeSNuno Sá if (span < 0)
181832cb9eeSNuno Sá return span;
182832cb9eeSNuno Sá
183832cb9eeSNuno Sá if (ltc2688_span_helper[span][0] < 0)
184832cb9eeSNuno Sá *val = -32768;
185832cb9eeSNuno Sá else
186832cb9eeSNuno Sá *val = 0;
187832cb9eeSNuno Sá
188832cb9eeSNuno Sá return 0;
189832cb9eeSNuno Sá }
190832cb9eeSNuno Sá
191832cb9eeSNuno Sá enum {
192832cb9eeSNuno Sá LTC2688_INPUT_A,
193832cb9eeSNuno Sá LTC2688_INPUT_B,
194832cb9eeSNuno Sá LTC2688_INPUT_B_AVAIL,
195832cb9eeSNuno Sá LTC2688_DITHER_OFF,
196832cb9eeSNuno Sá LTC2688_DITHER_FREQ_AVAIL,
197832cb9eeSNuno Sá };
198832cb9eeSNuno Sá
ltc2688_dac_code_write(struct ltc2688_state * st,u32 chan,u32 input,u16 code)199832cb9eeSNuno Sá static int ltc2688_dac_code_write(struct ltc2688_state *st, u32 chan, u32 input,
200832cb9eeSNuno Sá u16 code)
201832cb9eeSNuno Sá {
202832cb9eeSNuno Sá struct ltc2688_chan *c = &st->channels[chan];
203832cb9eeSNuno Sá int ret, reg;
204832cb9eeSNuno Sá
205832cb9eeSNuno Sá /* 2 LSBs set to 0 if writing dither amplitude */
206832cb9eeSNuno Sá if (!c->toggle_chan && input == LTC2688_INPUT_B) {
207832cb9eeSNuno Sá if (code > LTC2688_DITHER_RAW_MAX_VAL)
208832cb9eeSNuno Sá return -EINVAL;
209832cb9eeSNuno Sá
210832cb9eeSNuno Sá code = FIELD_PREP(LTC2688_DITHER_RAW_MASK, code);
211832cb9eeSNuno Sá }
212832cb9eeSNuno Sá
213832cb9eeSNuno Sá mutex_lock(&st->lock);
214832cb9eeSNuno Sá /* select the correct input register to read from */
215832cb9eeSNuno Sá ret = regmap_update_bits(st->regmap, LTC2688_CMD_A_B_SELECT, BIT(chan),
216832cb9eeSNuno Sá input << chan);
217832cb9eeSNuno Sá if (ret)
218832cb9eeSNuno Sá goto out_unlock;
219832cb9eeSNuno Sá
220832cb9eeSNuno Sá /*
221832cb9eeSNuno Sá * If in dither/toggle mode the dac should be updated by an
222832cb9eeSNuno Sá * external signal (or sw toggle) and not here.
223832cb9eeSNuno Sá */
224832cb9eeSNuno Sá if (c->mode == LTC2688_MODE_DEFAULT)
225832cb9eeSNuno Sá reg = LTC2688_CMD_CH_CODE_UPDATE(chan);
226832cb9eeSNuno Sá else
227832cb9eeSNuno Sá reg = LTC2688_CMD_CH_CODE(chan);
228832cb9eeSNuno Sá
229832cb9eeSNuno Sá ret = regmap_write(st->regmap, reg, code);
230832cb9eeSNuno Sá out_unlock:
231832cb9eeSNuno Sá mutex_unlock(&st->lock);
232832cb9eeSNuno Sá return ret;
233832cb9eeSNuno Sá }
234832cb9eeSNuno Sá
ltc2688_dac_code_read(struct ltc2688_state * st,u32 chan,u32 input,u32 * code)235832cb9eeSNuno Sá static int ltc2688_dac_code_read(struct ltc2688_state *st, u32 chan, u32 input,
236832cb9eeSNuno Sá u32 *code)
237832cb9eeSNuno Sá {
238832cb9eeSNuno Sá struct ltc2688_chan *c = &st->channels[chan];
239832cb9eeSNuno Sá int ret;
240832cb9eeSNuno Sá
241832cb9eeSNuno Sá mutex_lock(&st->lock);
242832cb9eeSNuno Sá ret = regmap_update_bits(st->regmap, LTC2688_CMD_A_B_SELECT, BIT(chan),
243832cb9eeSNuno Sá input << chan);
244832cb9eeSNuno Sá if (ret)
245832cb9eeSNuno Sá goto out_unlock;
246832cb9eeSNuno Sá
247832cb9eeSNuno Sá ret = regmap_read(st->regmap, LTC2688_CMD_CH_CODE(chan), code);
248832cb9eeSNuno Sá out_unlock:
249832cb9eeSNuno Sá mutex_unlock(&st->lock);
250832cb9eeSNuno Sá
251832cb9eeSNuno Sá if (!c->toggle_chan && input == LTC2688_INPUT_B)
252832cb9eeSNuno Sá *code = FIELD_GET(LTC2688_DITHER_RAW_MASK, *code);
253832cb9eeSNuno Sá
254832cb9eeSNuno Sá return ret;
255832cb9eeSNuno Sá }
256832cb9eeSNuno Sá
257832cb9eeSNuno Sá static const int ltc2688_raw_range[] = {0, 1, U16_MAX};
258832cb9eeSNuno Sá
ltc2688_read_avail(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,const int ** vals,int * type,int * length,long info)259832cb9eeSNuno Sá static int ltc2688_read_avail(struct iio_dev *indio_dev,
260832cb9eeSNuno Sá struct iio_chan_spec const *chan,
261832cb9eeSNuno Sá const int **vals, int *type, int *length,
262832cb9eeSNuno Sá long info)
263832cb9eeSNuno Sá {
264832cb9eeSNuno Sá switch (info) {
265832cb9eeSNuno Sá case IIO_CHAN_INFO_RAW:
266832cb9eeSNuno Sá *vals = ltc2688_raw_range;
267832cb9eeSNuno Sá *type = IIO_VAL_INT;
268832cb9eeSNuno Sá return IIO_AVAIL_RANGE;
269832cb9eeSNuno Sá default:
270832cb9eeSNuno Sá return -EINVAL;
271832cb9eeSNuno Sá }
272832cb9eeSNuno Sá }
273832cb9eeSNuno Sá
ltc2688_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long info)274832cb9eeSNuno Sá static int ltc2688_read_raw(struct iio_dev *indio_dev,
275832cb9eeSNuno Sá struct iio_chan_spec const *chan, int *val,
276832cb9eeSNuno Sá int *val2, long info)
277832cb9eeSNuno Sá {
278832cb9eeSNuno Sá struct ltc2688_state *st = iio_priv(indio_dev);
279832cb9eeSNuno Sá int ret;
280832cb9eeSNuno Sá
281832cb9eeSNuno Sá switch (info) {
282832cb9eeSNuno Sá case IIO_CHAN_INFO_RAW:
283832cb9eeSNuno Sá ret = ltc2688_dac_code_read(st, chan->channel, LTC2688_INPUT_A,
284832cb9eeSNuno Sá val);
285832cb9eeSNuno Sá if (ret)
286832cb9eeSNuno Sá return ret;
287832cb9eeSNuno Sá
288832cb9eeSNuno Sá return IIO_VAL_INT;
289832cb9eeSNuno Sá case IIO_CHAN_INFO_OFFSET:
290832cb9eeSNuno Sá ret = ltc2688_offset_get(st, chan->channel, val);
291832cb9eeSNuno Sá if (ret)
292832cb9eeSNuno Sá return ret;
293832cb9eeSNuno Sá
294832cb9eeSNuno Sá return IIO_VAL_INT;
295832cb9eeSNuno Sá case IIO_CHAN_INFO_SCALE:
296832cb9eeSNuno Sá ret = ltc2688_scale_get(st, chan->channel, val);
297832cb9eeSNuno Sá if (ret)
298832cb9eeSNuno Sá return ret;
299832cb9eeSNuno Sá
300e7e51eb0SNuno Sá *val2 = 16;
301832cb9eeSNuno Sá return IIO_VAL_FRACTIONAL_LOG2;
302832cb9eeSNuno Sá case IIO_CHAN_INFO_CALIBBIAS:
303832cb9eeSNuno Sá ret = regmap_read(st->regmap,
304832cb9eeSNuno Sá LTC2688_CMD_CH_OFFSET(chan->channel), val);
305832cb9eeSNuno Sá if (ret)
306832cb9eeSNuno Sá return ret;
307832cb9eeSNuno Sá
308832cb9eeSNuno Sá *val = FIELD_GET(LTC2688_CH_CALIBBIAS_MASK, *val);
309832cb9eeSNuno Sá return IIO_VAL_INT;
310832cb9eeSNuno Sá case IIO_CHAN_INFO_CALIBSCALE:
311832cb9eeSNuno Sá ret = regmap_read(st->regmap,
312832cb9eeSNuno Sá LTC2688_CMD_CH_GAIN(chan->channel), val);
313832cb9eeSNuno Sá if (ret)
314832cb9eeSNuno Sá return ret;
315832cb9eeSNuno Sá
316832cb9eeSNuno Sá return IIO_VAL_INT;
317832cb9eeSNuno Sá default:
318832cb9eeSNuno Sá return -EINVAL;
319832cb9eeSNuno Sá }
320832cb9eeSNuno Sá }
321832cb9eeSNuno Sá
ltc2688_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long info)322832cb9eeSNuno Sá static int ltc2688_write_raw(struct iio_dev *indio_dev,
323832cb9eeSNuno Sá struct iio_chan_spec const *chan, int val,
324832cb9eeSNuno Sá int val2, long info)
325832cb9eeSNuno Sá {
326832cb9eeSNuno Sá struct ltc2688_state *st = iio_priv(indio_dev);
327832cb9eeSNuno Sá
328832cb9eeSNuno Sá switch (info) {
329832cb9eeSNuno Sá case IIO_CHAN_INFO_RAW:
330832cb9eeSNuno Sá if (val > U16_MAX || val < 0)
331832cb9eeSNuno Sá return -EINVAL;
332832cb9eeSNuno Sá
333832cb9eeSNuno Sá return ltc2688_dac_code_write(st, chan->channel,
334832cb9eeSNuno Sá LTC2688_INPUT_A, val);
335832cb9eeSNuno Sá case IIO_CHAN_INFO_CALIBBIAS:
336832cb9eeSNuno Sá if (val > LTC2688_CH_CALIBBIAS_MAX_VAL)
337832cb9eeSNuno Sá return -EINVAL;
338832cb9eeSNuno Sá
339832cb9eeSNuno Sá return regmap_write(st->regmap,
340832cb9eeSNuno Sá LTC2688_CMD_CH_OFFSET(chan->channel),
341832cb9eeSNuno Sá FIELD_PREP(LTC2688_CH_CALIBBIAS_MASK, val));
342832cb9eeSNuno Sá case IIO_CHAN_INFO_CALIBSCALE:
343832cb9eeSNuno Sá return regmap_write(st->regmap,
344832cb9eeSNuno Sá LTC2688_CMD_CH_GAIN(chan->channel), val);
345832cb9eeSNuno Sá default:
346832cb9eeSNuno Sá return -EINVAL;
347832cb9eeSNuno Sá }
348832cb9eeSNuno Sá }
349832cb9eeSNuno Sá
ltc2688_dither_toggle_set(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,const char * buf,size_t len)350832cb9eeSNuno Sá static ssize_t ltc2688_dither_toggle_set(struct iio_dev *indio_dev,
351832cb9eeSNuno Sá uintptr_t private,
352832cb9eeSNuno Sá const struct iio_chan_spec *chan,
353832cb9eeSNuno Sá const char *buf, size_t len)
354832cb9eeSNuno Sá {
355832cb9eeSNuno Sá struct ltc2688_state *st = iio_priv(indio_dev);
356832cb9eeSNuno Sá struct ltc2688_chan *c = &st->channels[chan->channel];
357832cb9eeSNuno Sá int ret;
358832cb9eeSNuno Sá bool en;
359832cb9eeSNuno Sá
360832cb9eeSNuno Sá ret = kstrtobool(buf, &en);
361832cb9eeSNuno Sá if (ret)
362832cb9eeSNuno Sá return ret;
363832cb9eeSNuno Sá
364832cb9eeSNuno Sá mutex_lock(&st->lock);
365832cb9eeSNuno Sá ret = regmap_update_bits(st->regmap, LTC2688_CMD_TOGGLE_DITHER_EN,
366832cb9eeSNuno Sá BIT(chan->channel), en << chan->channel);
367832cb9eeSNuno Sá if (ret)
368832cb9eeSNuno Sá goto out_unlock;
369832cb9eeSNuno Sá
370832cb9eeSNuno Sá c->mode = en ? LTC2688_MODE_DITHER_TOGGLE : LTC2688_MODE_DEFAULT;
371832cb9eeSNuno Sá out_unlock:
372832cb9eeSNuno Sá mutex_unlock(&st->lock);
373832cb9eeSNuno Sá
374832cb9eeSNuno Sá return ret ?: len;
375832cb9eeSNuno Sá }
376832cb9eeSNuno Sá
ltc2688_reg_bool_get(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,char * buf)377832cb9eeSNuno Sá static ssize_t ltc2688_reg_bool_get(struct iio_dev *indio_dev,
378832cb9eeSNuno Sá uintptr_t private,
379832cb9eeSNuno Sá const struct iio_chan_spec *chan,
380832cb9eeSNuno Sá char *buf)
381832cb9eeSNuno Sá {
382832cb9eeSNuno Sá const struct ltc2688_state *st = iio_priv(indio_dev);
383832cb9eeSNuno Sá int ret;
384832cb9eeSNuno Sá u32 val;
385832cb9eeSNuno Sá
386832cb9eeSNuno Sá ret = regmap_read(st->regmap, private, &val);
387832cb9eeSNuno Sá if (ret)
388832cb9eeSNuno Sá return ret;
389832cb9eeSNuno Sá
390832cb9eeSNuno Sá return sysfs_emit(buf, "%u\n", !!(val & BIT(chan->channel)));
391832cb9eeSNuno Sá }
392832cb9eeSNuno Sá
ltc2688_reg_bool_set(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,const char * buf,size_t len)393832cb9eeSNuno Sá static ssize_t ltc2688_reg_bool_set(struct iio_dev *indio_dev,
394832cb9eeSNuno Sá uintptr_t private,
395832cb9eeSNuno Sá const struct iio_chan_spec *chan,
396832cb9eeSNuno Sá const char *buf, size_t len)
397832cb9eeSNuno Sá {
398832cb9eeSNuno Sá const struct ltc2688_state *st = iio_priv(indio_dev);
399832cb9eeSNuno Sá int ret;
400832cb9eeSNuno Sá bool en;
401832cb9eeSNuno Sá
402832cb9eeSNuno Sá ret = kstrtobool(buf, &en);
403832cb9eeSNuno Sá if (ret)
404832cb9eeSNuno Sá return ret;
405832cb9eeSNuno Sá
406832cb9eeSNuno Sá ret = regmap_update_bits(st->regmap, private, BIT(chan->channel),
407832cb9eeSNuno Sá en << chan->channel);
408832cb9eeSNuno Sá if (ret)
409832cb9eeSNuno Sá return ret;
410832cb9eeSNuno Sá
411832cb9eeSNuno Sá return len;
412832cb9eeSNuno Sá }
413832cb9eeSNuno Sá
ltc2688_dither_freq_avail(const struct ltc2688_state * st,const struct ltc2688_chan * chan,char * buf)414832cb9eeSNuno Sá static ssize_t ltc2688_dither_freq_avail(const struct ltc2688_state *st,
415832cb9eeSNuno Sá const struct ltc2688_chan *chan,
416832cb9eeSNuno Sá char *buf)
417832cb9eeSNuno Sá {
418832cb9eeSNuno Sá int sz = 0;
419832cb9eeSNuno Sá u32 f;
420832cb9eeSNuno Sá
421832cb9eeSNuno Sá for (f = 0; f < ARRAY_SIZE(chan->dither_frequency); f++)
422832cb9eeSNuno Sá sz += sysfs_emit_at(buf, sz, "%ld ", chan->dither_frequency[f]);
423832cb9eeSNuno Sá
424832cb9eeSNuno Sá buf[sz - 1] = '\n';
425832cb9eeSNuno Sá
426832cb9eeSNuno Sá return sz;
427832cb9eeSNuno Sá }
428832cb9eeSNuno Sá
ltc2688_dither_freq_get(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,char * buf)429832cb9eeSNuno Sá static ssize_t ltc2688_dither_freq_get(struct iio_dev *indio_dev,
430832cb9eeSNuno Sá uintptr_t private,
431832cb9eeSNuno Sá const struct iio_chan_spec *chan,
432832cb9eeSNuno Sá char *buf)
433832cb9eeSNuno Sá {
434832cb9eeSNuno Sá const struct ltc2688_state *st = iio_priv(indio_dev);
435832cb9eeSNuno Sá const struct ltc2688_chan *c = &st->channels[chan->channel];
436832cb9eeSNuno Sá u32 reg, freq;
437832cb9eeSNuno Sá int ret;
438832cb9eeSNuno Sá
439832cb9eeSNuno Sá if (private == LTC2688_DITHER_FREQ_AVAIL)
440832cb9eeSNuno Sá return ltc2688_dither_freq_avail(st, c, buf);
441832cb9eeSNuno Sá
442832cb9eeSNuno Sá ret = regmap_read(st->regmap, LTC2688_CMD_CH_SETTING(chan->channel),
443832cb9eeSNuno Sá ®);
444832cb9eeSNuno Sá if (ret)
445832cb9eeSNuno Sá return ret;
446832cb9eeSNuno Sá
447832cb9eeSNuno Sá freq = FIELD_GET(LTC2688_CH_DIT_PER_MSK, reg);
448832cb9eeSNuno Sá if (freq >= ARRAY_SIZE(c->dither_frequency))
449832cb9eeSNuno Sá return -EIO;
450832cb9eeSNuno Sá
451832cb9eeSNuno Sá return sysfs_emit(buf, "%ld\n", c->dither_frequency[freq]);
452832cb9eeSNuno Sá }
453832cb9eeSNuno Sá
ltc2688_dither_freq_set(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,const char * buf,size_t len)454832cb9eeSNuno Sá static ssize_t ltc2688_dither_freq_set(struct iio_dev *indio_dev,
455832cb9eeSNuno Sá uintptr_t private,
456832cb9eeSNuno Sá const struct iio_chan_spec *chan,
457832cb9eeSNuno Sá const char *buf, size_t len)
458832cb9eeSNuno Sá {
459832cb9eeSNuno Sá const struct ltc2688_state *st = iio_priv(indio_dev);
460832cb9eeSNuno Sá const struct ltc2688_chan *c = &st->channels[chan->channel];
461832cb9eeSNuno Sá long val;
462832cb9eeSNuno Sá u32 freq;
463832cb9eeSNuno Sá int ret;
464832cb9eeSNuno Sá
465832cb9eeSNuno Sá if (private == LTC2688_DITHER_FREQ_AVAIL)
466832cb9eeSNuno Sá return -EINVAL;
467832cb9eeSNuno Sá
468832cb9eeSNuno Sá ret = kstrtol(buf, 10, &val);
469832cb9eeSNuno Sá if (ret)
470832cb9eeSNuno Sá return ret;
471832cb9eeSNuno Sá
472832cb9eeSNuno Sá for (freq = 0; freq < ARRAY_SIZE(c->dither_frequency); freq++) {
473832cb9eeSNuno Sá if (val == c->dither_frequency[freq])
474832cb9eeSNuno Sá break;
475832cb9eeSNuno Sá }
476832cb9eeSNuno Sá
477832cb9eeSNuno Sá if (freq == ARRAY_SIZE(c->dither_frequency))
478832cb9eeSNuno Sá return -EINVAL;
479832cb9eeSNuno Sá
480832cb9eeSNuno Sá ret = regmap_update_bits(st->regmap,
481832cb9eeSNuno Sá LTC2688_CMD_CH_SETTING(chan->channel),
482832cb9eeSNuno Sá LTC2688_CH_DIT_PER_MSK,
483832cb9eeSNuno Sá FIELD_PREP(LTC2688_CH_DIT_PER_MSK, freq));
484832cb9eeSNuno Sá if (ret)
485832cb9eeSNuno Sá return ret;
486832cb9eeSNuno Sá
487832cb9eeSNuno Sá return len;
488832cb9eeSNuno Sá }
489832cb9eeSNuno Sá
ltc2688_dac_input_read(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,char * buf)490832cb9eeSNuno Sá static ssize_t ltc2688_dac_input_read(struct iio_dev *indio_dev,
491832cb9eeSNuno Sá uintptr_t private,
492832cb9eeSNuno Sá const struct iio_chan_spec *chan,
493832cb9eeSNuno Sá char *buf)
494832cb9eeSNuno Sá {
495832cb9eeSNuno Sá struct ltc2688_state *st = iio_priv(indio_dev);
496832cb9eeSNuno Sá int ret;
497832cb9eeSNuno Sá u32 val;
498832cb9eeSNuno Sá
499832cb9eeSNuno Sá if (private == LTC2688_INPUT_B_AVAIL)
500832cb9eeSNuno Sá return sysfs_emit(buf, "[%u %u %u]\n", ltc2688_raw_range[0],
501832cb9eeSNuno Sá ltc2688_raw_range[1],
502832cb9eeSNuno Sá ltc2688_raw_range[2] / 4);
503832cb9eeSNuno Sá
504832cb9eeSNuno Sá if (private == LTC2688_DITHER_OFF)
505832cb9eeSNuno Sá return sysfs_emit(buf, "0\n");
506832cb9eeSNuno Sá
507832cb9eeSNuno Sá ret = ltc2688_dac_code_read(st, chan->channel, private, &val);
508832cb9eeSNuno Sá if (ret)
509832cb9eeSNuno Sá return ret;
510832cb9eeSNuno Sá
511832cb9eeSNuno Sá return sysfs_emit(buf, "%u\n", val);
512832cb9eeSNuno Sá }
513832cb9eeSNuno Sá
ltc2688_dac_input_write(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,const char * buf,size_t len)514832cb9eeSNuno Sá static ssize_t ltc2688_dac_input_write(struct iio_dev *indio_dev,
515832cb9eeSNuno Sá uintptr_t private,
516832cb9eeSNuno Sá const struct iio_chan_spec *chan,
517832cb9eeSNuno Sá const char *buf, size_t len)
518832cb9eeSNuno Sá {
519832cb9eeSNuno Sá struct ltc2688_state *st = iio_priv(indio_dev);
520832cb9eeSNuno Sá int ret;
521832cb9eeSNuno Sá u16 val;
522832cb9eeSNuno Sá
523832cb9eeSNuno Sá if (private == LTC2688_INPUT_B_AVAIL || private == LTC2688_DITHER_OFF)
524832cb9eeSNuno Sá return -EINVAL;
525832cb9eeSNuno Sá
526832cb9eeSNuno Sá ret = kstrtou16(buf, 10, &val);
527832cb9eeSNuno Sá if (ret)
528832cb9eeSNuno Sá return ret;
529832cb9eeSNuno Sá
530832cb9eeSNuno Sá ret = ltc2688_dac_code_write(st, chan->channel, private, val);
531832cb9eeSNuno Sá if (ret)
532832cb9eeSNuno Sá return ret;
533832cb9eeSNuno Sá
534832cb9eeSNuno Sá return len;
535832cb9eeSNuno Sá }
536832cb9eeSNuno Sá
ltc2688_get_dither_phase(struct iio_dev * dev,const struct iio_chan_spec * chan)537832cb9eeSNuno Sá static int ltc2688_get_dither_phase(struct iio_dev *dev,
538832cb9eeSNuno Sá const struct iio_chan_spec *chan)
539832cb9eeSNuno Sá {
540832cb9eeSNuno Sá struct ltc2688_state *st = iio_priv(dev);
541832cb9eeSNuno Sá int ret, regval;
542832cb9eeSNuno Sá
543832cb9eeSNuno Sá ret = regmap_read(st->regmap, LTC2688_CMD_CH_SETTING(chan->channel),
544832cb9eeSNuno Sá ®val);
545832cb9eeSNuno Sá if (ret)
546832cb9eeSNuno Sá return ret;
547832cb9eeSNuno Sá
548832cb9eeSNuno Sá return FIELD_GET(LTC2688_CH_DIT_PH_MSK, regval);
549832cb9eeSNuno Sá }
550832cb9eeSNuno Sá
ltc2688_set_dither_phase(struct iio_dev * dev,const struct iio_chan_spec * chan,unsigned int phase)551832cb9eeSNuno Sá static int ltc2688_set_dither_phase(struct iio_dev *dev,
552832cb9eeSNuno Sá const struct iio_chan_spec *chan,
553832cb9eeSNuno Sá unsigned int phase)
554832cb9eeSNuno Sá {
555832cb9eeSNuno Sá struct ltc2688_state *st = iio_priv(dev);
556832cb9eeSNuno Sá
557832cb9eeSNuno Sá return regmap_update_bits(st->regmap,
558832cb9eeSNuno Sá LTC2688_CMD_CH_SETTING(chan->channel),
559832cb9eeSNuno Sá LTC2688_CH_DIT_PH_MSK,
560832cb9eeSNuno Sá FIELD_PREP(LTC2688_CH_DIT_PH_MSK, phase));
561832cb9eeSNuno Sá }
562832cb9eeSNuno Sá
ltc2688_reg_access(struct iio_dev * indio_dev,unsigned int reg,unsigned int writeval,unsigned int * readval)563832cb9eeSNuno Sá static int ltc2688_reg_access(struct iio_dev *indio_dev,
564832cb9eeSNuno Sá unsigned int reg,
565832cb9eeSNuno Sá unsigned int writeval,
566832cb9eeSNuno Sá unsigned int *readval)
567832cb9eeSNuno Sá {
568832cb9eeSNuno Sá struct ltc2688_state *st = iio_priv(indio_dev);
569832cb9eeSNuno Sá
570832cb9eeSNuno Sá if (readval)
571832cb9eeSNuno Sá return regmap_read(st->regmap, reg, readval);
572832cb9eeSNuno Sá
573832cb9eeSNuno Sá return regmap_write(st->regmap, reg, writeval);
574832cb9eeSNuno Sá }
575832cb9eeSNuno Sá
576832cb9eeSNuno Sá static const char * const ltc2688_dither_phase[] = {
577832cb9eeSNuno Sá "0", "1.5708", "3.14159", "4.71239",
578832cb9eeSNuno Sá };
579832cb9eeSNuno Sá
580832cb9eeSNuno Sá static const struct iio_enum ltc2688_dither_phase_enum = {
581832cb9eeSNuno Sá .items = ltc2688_dither_phase,
582832cb9eeSNuno Sá .num_items = ARRAY_SIZE(ltc2688_dither_phase),
583832cb9eeSNuno Sá .set = ltc2688_set_dither_phase,
584832cb9eeSNuno Sá .get = ltc2688_get_dither_phase,
585832cb9eeSNuno Sá };
586832cb9eeSNuno Sá
587832cb9eeSNuno Sá #define LTC2688_CHAN_EXT_INFO(_name, _what, _shared, _read, _write) { \
588832cb9eeSNuno Sá .name = _name, \
589832cb9eeSNuno Sá .read = (_read), \
590832cb9eeSNuno Sá .write = (_write), \
591832cb9eeSNuno Sá .private = (_what), \
592832cb9eeSNuno Sá .shared = (_shared), \
593832cb9eeSNuno Sá }
594832cb9eeSNuno Sá
595832cb9eeSNuno Sá /*
596832cb9eeSNuno Sá * For toggle mode we only expose the symbol attr (sw_toggle) in case a TGPx is
597832cb9eeSNuno Sá * not provided in dts.
598832cb9eeSNuno Sá */
599832cb9eeSNuno Sá static const struct iio_chan_spec_ext_info ltc2688_toggle_sym_ext_info[] = {
600832cb9eeSNuno Sá LTC2688_CHAN_EXT_INFO("raw0", LTC2688_INPUT_A, IIO_SEPARATE,
601832cb9eeSNuno Sá ltc2688_dac_input_read, ltc2688_dac_input_write),
602832cb9eeSNuno Sá LTC2688_CHAN_EXT_INFO("raw1", LTC2688_INPUT_B, IIO_SEPARATE,
603832cb9eeSNuno Sá ltc2688_dac_input_read, ltc2688_dac_input_write),
604832cb9eeSNuno Sá LTC2688_CHAN_EXT_INFO("toggle_en", LTC2688_CMD_TOGGLE_DITHER_EN,
605832cb9eeSNuno Sá IIO_SEPARATE, ltc2688_reg_bool_get,
606832cb9eeSNuno Sá ltc2688_dither_toggle_set),
607832cb9eeSNuno Sá LTC2688_CHAN_EXT_INFO("powerdown", LTC2688_CMD_POWERDOWN, IIO_SEPARATE,
608832cb9eeSNuno Sá ltc2688_reg_bool_get, ltc2688_reg_bool_set),
609832cb9eeSNuno Sá LTC2688_CHAN_EXT_INFO("symbol", LTC2688_CMD_SW_TOGGLE, IIO_SEPARATE,
610832cb9eeSNuno Sá ltc2688_reg_bool_get, ltc2688_reg_bool_set),
611832cb9eeSNuno Sá {}
612832cb9eeSNuno Sá };
613832cb9eeSNuno Sá
614832cb9eeSNuno Sá static const struct iio_chan_spec_ext_info ltc2688_toggle_ext_info[] = {
615832cb9eeSNuno Sá LTC2688_CHAN_EXT_INFO("raw0", LTC2688_INPUT_A, IIO_SEPARATE,
616832cb9eeSNuno Sá ltc2688_dac_input_read, ltc2688_dac_input_write),
617832cb9eeSNuno Sá LTC2688_CHAN_EXT_INFO("raw1", LTC2688_INPUT_B, IIO_SEPARATE,
618832cb9eeSNuno Sá ltc2688_dac_input_read, ltc2688_dac_input_write),
619832cb9eeSNuno Sá LTC2688_CHAN_EXT_INFO("toggle_en", LTC2688_CMD_TOGGLE_DITHER_EN,
620832cb9eeSNuno Sá IIO_SEPARATE, ltc2688_reg_bool_get,
621832cb9eeSNuno Sá ltc2688_dither_toggle_set),
622832cb9eeSNuno Sá LTC2688_CHAN_EXT_INFO("powerdown", LTC2688_CMD_POWERDOWN, IIO_SEPARATE,
623832cb9eeSNuno Sá ltc2688_reg_bool_get, ltc2688_reg_bool_set),
624832cb9eeSNuno Sá {}
625832cb9eeSNuno Sá };
626832cb9eeSNuno Sá
627832cb9eeSNuno Sá static struct iio_chan_spec_ext_info ltc2688_dither_ext_info[] = {
628832cb9eeSNuno Sá LTC2688_CHAN_EXT_INFO("dither_raw", LTC2688_INPUT_B, IIO_SEPARATE,
629832cb9eeSNuno Sá ltc2688_dac_input_read, ltc2688_dac_input_write),
630832cb9eeSNuno Sá LTC2688_CHAN_EXT_INFO("dither_raw_available", LTC2688_INPUT_B_AVAIL,
631832cb9eeSNuno Sá IIO_SEPARATE, ltc2688_dac_input_read,
632832cb9eeSNuno Sá ltc2688_dac_input_write),
633832cb9eeSNuno Sá LTC2688_CHAN_EXT_INFO("dither_offset", LTC2688_DITHER_OFF, IIO_SEPARATE,
634832cb9eeSNuno Sá ltc2688_dac_input_read, ltc2688_dac_input_write),
635832cb9eeSNuno Sá /*
636832cb9eeSNuno Sá * Not IIO_ENUM because the available freq needs to be computed at
637832cb9eeSNuno Sá * probe. We could still use it, but it didn't felt much right.
638832cb9eeSNuno Sá */
639832cb9eeSNuno Sá LTC2688_CHAN_EXT_INFO("dither_frequency", 0, IIO_SEPARATE,
640832cb9eeSNuno Sá ltc2688_dither_freq_get, ltc2688_dither_freq_set),
641832cb9eeSNuno Sá LTC2688_CHAN_EXT_INFO("dither_frequency_available",
642832cb9eeSNuno Sá LTC2688_DITHER_FREQ_AVAIL, IIO_SEPARATE,
643832cb9eeSNuno Sá ltc2688_dither_freq_get, ltc2688_dither_freq_set),
644832cb9eeSNuno Sá IIO_ENUM("dither_phase", IIO_SEPARATE, <c2688_dither_phase_enum),
645832cb9eeSNuno Sá IIO_ENUM_AVAILABLE("dither_phase", IIO_SEPARATE,
646832cb9eeSNuno Sá <c2688_dither_phase_enum),
647832cb9eeSNuno Sá LTC2688_CHAN_EXT_INFO("dither_en", LTC2688_CMD_TOGGLE_DITHER_EN,
648832cb9eeSNuno Sá IIO_SEPARATE, ltc2688_reg_bool_get,
649832cb9eeSNuno Sá ltc2688_dither_toggle_set),
650832cb9eeSNuno Sá LTC2688_CHAN_EXT_INFO("powerdown", LTC2688_CMD_POWERDOWN, IIO_SEPARATE,
651832cb9eeSNuno Sá ltc2688_reg_bool_get, ltc2688_reg_bool_set),
652832cb9eeSNuno Sá {}
653832cb9eeSNuno Sá };
654832cb9eeSNuno Sá
655832cb9eeSNuno Sá static const struct iio_chan_spec_ext_info ltc2688_ext_info[] = {
656832cb9eeSNuno Sá LTC2688_CHAN_EXT_INFO("powerdown", LTC2688_CMD_POWERDOWN, IIO_SEPARATE,
657832cb9eeSNuno Sá ltc2688_reg_bool_get, ltc2688_reg_bool_set),
658832cb9eeSNuno Sá {}
659832cb9eeSNuno Sá };
660832cb9eeSNuno Sá
661832cb9eeSNuno Sá #define LTC2688_CHANNEL(_chan) { \
662832cb9eeSNuno Sá .type = IIO_VOLTAGE, \
663832cb9eeSNuno Sá .indexed = 1, \
664832cb9eeSNuno Sá .output = 1, \
665832cb9eeSNuno Sá .channel = (_chan), \
666832cb9eeSNuno Sá .info_mask_separate = BIT(IIO_CHAN_INFO_CALIBSCALE) | \
667832cb9eeSNuno Sá BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET) | \
668832cb9eeSNuno Sá BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_RAW), \
669832cb9eeSNuno Sá .info_mask_separate_available = BIT(IIO_CHAN_INFO_RAW), \
670832cb9eeSNuno Sá .ext_info = ltc2688_ext_info, \
671832cb9eeSNuno Sá }
672832cb9eeSNuno Sá
673832cb9eeSNuno Sá static const struct iio_chan_spec ltc2688_channels[] = {
674832cb9eeSNuno Sá LTC2688_CHANNEL(0),
675832cb9eeSNuno Sá LTC2688_CHANNEL(1),
676832cb9eeSNuno Sá LTC2688_CHANNEL(2),
677832cb9eeSNuno Sá LTC2688_CHANNEL(3),
678832cb9eeSNuno Sá LTC2688_CHANNEL(4),
679832cb9eeSNuno Sá LTC2688_CHANNEL(5),
680832cb9eeSNuno Sá LTC2688_CHANNEL(6),
681832cb9eeSNuno Sá LTC2688_CHANNEL(7),
682832cb9eeSNuno Sá LTC2688_CHANNEL(8),
683832cb9eeSNuno Sá LTC2688_CHANNEL(9),
684832cb9eeSNuno Sá LTC2688_CHANNEL(10),
685832cb9eeSNuno Sá LTC2688_CHANNEL(11),
686832cb9eeSNuno Sá LTC2688_CHANNEL(12),
687832cb9eeSNuno Sá LTC2688_CHANNEL(13),
688832cb9eeSNuno Sá LTC2688_CHANNEL(14),
689832cb9eeSNuno Sá LTC2688_CHANNEL(15),
690832cb9eeSNuno Sá };
691832cb9eeSNuno Sá
ltc2688_clk_disable(void * clk)692832cb9eeSNuno Sá static void ltc2688_clk_disable(void *clk)
693832cb9eeSNuno Sá {
694832cb9eeSNuno Sá clk_disable_unprepare(clk);
695832cb9eeSNuno Sá }
696832cb9eeSNuno Sá
697832cb9eeSNuno Sá static const int ltc2688_period[LTC2688_DITHER_FREQ_AVAIL_N] = {
698832cb9eeSNuno Sá 4, 8, 16, 32, 64,
699832cb9eeSNuno Sá };
700832cb9eeSNuno Sá
ltc2688_tgp_clk_setup(struct ltc2688_state * st,struct ltc2688_chan * chan,struct fwnode_handle * node,int tgp)701832cb9eeSNuno Sá static int ltc2688_tgp_clk_setup(struct ltc2688_state *st,
702832cb9eeSNuno Sá struct ltc2688_chan *chan,
703832cb9eeSNuno Sá struct fwnode_handle *node, int tgp)
704832cb9eeSNuno Sá {
705fee4ac32SAndy Shevchenko struct device *dev = &st->spi->dev;
706832cb9eeSNuno Sá unsigned long rate;
707832cb9eeSNuno Sá struct clk *clk;
708832cb9eeSNuno Sá int ret, f;
709832cb9eeSNuno Sá
710fee4ac32SAndy Shevchenko clk = devm_get_clk_from_child(dev, to_of_node(node), NULL);
711832cb9eeSNuno Sá if (IS_ERR(clk))
712fee4ac32SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(clk), "failed to get tgp clk.\n");
713832cb9eeSNuno Sá
714832cb9eeSNuno Sá ret = clk_prepare_enable(clk);
715832cb9eeSNuno Sá if (ret)
716fee4ac32SAndy Shevchenko return dev_err_probe(dev, ret, "failed to enable tgp clk.\n");
717832cb9eeSNuno Sá
718fee4ac32SAndy Shevchenko ret = devm_add_action_or_reset(dev, ltc2688_clk_disable, clk);
719832cb9eeSNuno Sá if (ret)
720832cb9eeSNuno Sá return ret;
721832cb9eeSNuno Sá
722832cb9eeSNuno Sá if (chan->toggle_chan)
723832cb9eeSNuno Sá return 0;
724832cb9eeSNuno Sá
725832cb9eeSNuno Sá /* calculate available dither frequencies */
726832cb9eeSNuno Sá rate = clk_get_rate(clk);
727832cb9eeSNuno Sá for (f = 0; f < ARRAY_SIZE(chan->dither_frequency); f++)
728832cb9eeSNuno Sá chan->dither_frequency[f] = DIV_ROUND_CLOSEST(rate, ltc2688_period[f]);
729832cb9eeSNuno Sá
730832cb9eeSNuno Sá return 0;
731832cb9eeSNuno Sá }
732832cb9eeSNuno Sá
ltc2688_span_lookup(const struct ltc2688_state * st,int min,int max)733832cb9eeSNuno Sá static int ltc2688_span_lookup(const struct ltc2688_state *st, int min, int max)
734832cb9eeSNuno Sá {
735832cb9eeSNuno Sá u32 span;
736832cb9eeSNuno Sá
737832cb9eeSNuno Sá for (span = 0; span < ARRAY_SIZE(ltc2688_span_helper); span++) {
738832cb9eeSNuno Sá if (min == ltc2688_span_helper[span][0] &&
739832cb9eeSNuno Sá max == ltc2688_span_helper[span][1])
740832cb9eeSNuno Sá return span;
741832cb9eeSNuno Sá }
742832cb9eeSNuno Sá
743832cb9eeSNuno Sá return -EINVAL;
744832cb9eeSNuno Sá }
745832cb9eeSNuno Sá
ltc2688_channel_config(struct ltc2688_state * st)746832cb9eeSNuno Sá static int ltc2688_channel_config(struct ltc2688_state *st)
747832cb9eeSNuno Sá {
748832cb9eeSNuno Sá struct device *dev = &st->spi->dev;
749832cb9eeSNuno Sá struct fwnode_handle *child;
750832cb9eeSNuno Sá u32 reg, clk_input, val, tmp[2];
751832cb9eeSNuno Sá int ret, span;
752832cb9eeSNuno Sá
753832cb9eeSNuno Sá device_for_each_child_node(dev, child) {
754832cb9eeSNuno Sá struct ltc2688_chan *chan;
755832cb9eeSNuno Sá
756832cb9eeSNuno Sá ret = fwnode_property_read_u32(child, "reg", ®);
757832cb9eeSNuno Sá if (ret) {
758832cb9eeSNuno Sá fwnode_handle_put(child);
759832cb9eeSNuno Sá return dev_err_probe(dev, ret,
760832cb9eeSNuno Sá "Failed to get reg property\n");
761832cb9eeSNuno Sá }
762832cb9eeSNuno Sá
763832cb9eeSNuno Sá if (reg >= LTC2688_DAC_CHANNELS) {
764832cb9eeSNuno Sá fwnode_handle_put(child);
765832cb9eeSNuno Sá return dev_err_probe(dev, -EINVAL,
766832cb9eeSNuno Sá "reg bigger than: %d\n",
767832cb9eeSNuno Sá LTC2688_DAC_CHANNELS);
768832cb9eeSNuno Sá }
769832cb9eeSNuno Sá
770832cb9eeSNuno Sá val = 0;
771832cb9eeSNuno Sá chan = &st->channels[reg];
772832cb9eeSNuno Sá if (fwnode_property_read_bool(child, "adi,toggle-mode")) {
773832cb9eeSNuno Sá chan->toggle_chan = true;
774832cb9eeSNuno Sá /* assume sw toggle ABI */
775832cb9eeSNuno Sá st->iio_chan[reg].ext_info = ltc2688_toggle_sym_ext_info;
776832cb9eeSNuno Sá /*
777832cb9eeSNuno Sá * Clear IIO_CHAN_INFO_RAW bit as toggle channels expose
778832cb9eeSNuno Sá * out_voltage_raw{0|1} files.
779832cb9eeSNuno Sá */
780832cb9eeSNuno Sá __clear_bit(IIO_CHAN_INFO_RAW,
781832cb9eeSNuno Sá &st->iio_chan[reg].info_mask_separate);
782832cb9eeSNuno Sá }
783832cb9eeSNuno Sá
784832cb9eeSNuno Sá ret = fwnode_property_read_u32_array(child, "adi,output-range-microvolt",
785832cb9eeSNuno Sá tmp, ARRAY_SIZE(tmp));
786832cb9eeSNuno Sá if (!ret) {
787832cb9eeSNuno Sá span = ltc2688_span_lookup(st, (int)tmp[0] / 1000,
788832cb9eeSNuno Sá tmp[1] / 1000);
789832cb9eeSNuno Sá if (span < 0) {
790832cb9eeSNuno Sá fwnode_handle_put(child);
791832cb9eeSNuno Sá return dev_err_probe(dev, -EINVAL,
792832cb9eeSNuno Sá "output range not valid:[%d %d]\n",
793832cb9eeSNuno Sá tmp[0], tmp[1]);
794832cb9eeSNuno Sá }
795832cb9eeSNuno Sá
796832cb9eeSNuno Sá val |= FIELD_PREP(LTC2688_CH_SPAN_MSK, span);
797832cb9eeSNuno Sá }
798832cb9eeSNuno Sá
799832cb9eeSNuno Sá ret = fwnode_property_read_u32(child, "adi,toggle-dither-input",
800832cb9eeSNuno Sá &clk_input);
801832cb9eeSNuno Sá if (!ret) {
802832cb9eeSNuno Sá if (clk_input >= LTC2688_CH_TGP_MAX) {
803832cb9eeSNuno Sá fwnode_handle_put(child);
804832cb9eeSNuno Sá return dev_err_probe(dev, -EINVAL,
805832cb9eeSNuno Sá "toggle-dither-input inv value(%d)\n",
806832cb9eeSNuno Sá clk_input);
807832cb9eeSNuno Sá }
808832cb9eeSNuno Sá
809832cb9eeSNuno Sá ret = ltc2688_tgp_clk_setup(st, chan, child, clk_input);
810832cb9eeSNuno Sá if (ret) {
811832cb9eeSNuno Sá fwnode_handle_put(child);
812832cb9eeSNuno Sá return ret;
813832cb9eeSNuno Sá }
814832cb9eeSNuno Sá
815832cb9eeSNuno Sá /*
816832cb9eeSNuno Sá * 0 means software toggle which is the default mode.
817832cb9eeSNuno Sá * Hence the +1.
818832cb9eeSNuno Sá */
819832cb9eeSNuno Sá val |= FIELD_PREP(LTC2688_CH_TD_SEL_MSK, clk_input + 1);
820832cb9eeSNuno Sá
821832cb9eeSNuno Sá /*
822832cb9eeSNuno Sá * If a TGPx is given, we automatically assume a dither
823832cb9eeSNuno Sá * capable channel (unless toggle is already enabled).
824832cb9eeSNuno Sá * On top of this we just set here the dither bit in the
825832cb9eeSNuno Sá * channel settings. It won't have any effect until the
826832cb9eeSNuno Sá * global toggle/dither bit is enabled.
827832cb9eeSNuno Sá */
828832cb9eeSNuno Sá if (!chan->toggle_chan) {
829832cb9eeSNuno Sá val |= FIELD_PREP(LTC2688_CH_MODE_MSK, 1);
830832cb9eeSNuno Sá st->iio_chan[reg].ext_info = ltc2688_dither_ext_info;
831832cb9eeSNuno Sá } else {
832832cb9eeSNuno Sá /* wait, no sw toggle after all */
833832cb9eeSNuno Sá st->iio_chan[reg].ext_info = ltc2688_toggle_ext_info;
834832cb9eeSNuno Sá }
835832cb9eeSNuno Sá }
836832cb9eeSNuno Sá
837832cb9eeSNuno Sá if (fwnode_property_read_bool(child, "adi,overrange")) {
838832cb9eeSNuno Sá chan->overrange = true;
839832cb9eeSNuno Sá val |= LTC2688_CH_OVERRANGE_MSK;
840832cb9eeSNuno Sá }
841832cb9eeSNuno Sá
842832cb9eeSNuno Sá if (!val)
843832cb9eeSNuno Sá continue;
844832cb9eeSNuno Sá
845832cb9eeSNuno Sá ret = regmap_write(st->regmap, LTC2688_CMD_CH_SETTING(reg),
846832cb9eeSNuno Sá val);
847832cb9eeSNuno Sá if (ret) {
848832cb9eeSNuno Sá fwnode_handle_put(child);
849832cb9eeSNuno Sá return dev_err_probe(dev, -EINVAL,
850832cb9eeSNuno Sá "failed to set chan settings\n");
851832cb9eeSNuno Sá }
852832cb9eeSNuno Sá }
853832cb9eeSNuno Sá
854832cb9eeSNuno Sá return 0;
855832cb9eeSNuno Sá }
856832cb9eeSNuno Sá
ltc2688_setup(struct ltc2688_state * st,struct regulator * vref)857832cb9eeSNuno Sá static int ltc2688_setup(struct ltc2688_state *st, struct regulator *vref)
858832cb9eeSNuno Sá {
859fee4ac32SAndy Shevchenko struct device *dev = &st->spi->dev;
860832cb9eeSNuno Sá struct gpio_desc *gpio;
861832cb9eeSNuno Sá int ret;
862832cb9eeSNuno Sá
863832cb9eeSNuno Sá /*
864832cb9eeSNuno Sá * If we have a reset pin, use that to reset the board, If not, use
865832cb9eeSNuno Sá * the reset bit.
866832cb9eeSNuno Sá */
867fee4ac32SAndy Shevchenko gpio = devm_gpiod_get_optional(dev, "clr", GPIOD_OUT_HIGH);
868832cb9eeSNuno Sá if (IS_ERR(gpio))
869fee4ac32SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(gpio), "Failed to get reset gpio");
870832cb9eeSNuno Sá if (gpio) {
871832cb9eeSNuno Sá usleep_range(1000, 1200);
872832cb9eeSNuno Sá /* bring device out of reset */
873832cb9eeSNuno Sá gpiod_set_value_cansleep(gpio, 0);
874832cb9eeSNuno Sá } else {
875832cb9eeSNuno Sá ret = regmap_update_bits(st->regmap, LTC2688_CMD_CONFIG,
876832cb9eeSNuno Sá LTC2688_CONFIG_RST,
877832cb9eeSNuno Sá LTC2688_CONFIG_RST);
878832cb9eeSNuno Sá if (ret)
879832cb9eeSNuno Sá return ret;
880832cb9eeSNuno Sá }
881832cb9eeSNuno Sá
882832cb9eeSNuno Sá usleep_range(10000, 12000);
883832cb9eeSNuno Sá
884832cb9eeSNuno Sá /*
885832cb9eeSNuno Sá * Duplicate the default channel configuration as it can change during
886832cb9eeSNuno Sá * @ltc2688_channel_config()
887832cb9eeSNuno Sá */
888fee4ac32SAndy Shevchenko st->iio_chan = devm_kmemdup(dev, ltc2688_channels,
889832cb9eeSNuno Sá sizeof(ltc2688_channels), GFP_KERNEL);
890832cb9eeSNuno Sá if (!st->iio_chan)
891832cb9eeSNuno Sá return -ENOMEM;
892832cb9eeSNuno Sá
893832cb9eeSNuno Sá ret = ltc2688_channel_config(st);
894832cb9eeSNuno Sá if (ret)
895832cb9eeSNuno Sá return ret;
896832cb9eeSNuno Sá
897832cb9eeSNuno Sá if (!vref)
898832cb9eeSNuno Sá return 0;
899832cb9eeSNuno Sá
900832cb9eeSNuno Sá return regmap_set_bits(st->regmap, LTC2688_CMD_CONFIG,
901832cb9eeSNuno Sá LTC2688_CONFIG_EXT_REF);
902832cb9eeSNuno Sá }
903832cb9eeSNuno Sá
ltc2688_disable_regulator(void * regulator)904832cb9eeSNuno Sá static void ltc2688_disable_regulator(void *regulator)
905832cb9eeSNuno Sá {
906832cb9eeSNuno Sá regulator_disable(regulator);
907832cb9eeSNuno Sá }
908832cb9eeSNuno Sá
ltc2688_reg_readable(struct device * dev,unsigned int reg)909832cb9eeSNuno Sá static bool ltc2688_reg_readable(struct device *dev, unsigned int reg)
910832cb9eeSNuno Sá {
911832cb9eeSNuno Sá switch (reg) {
912832cb9eeSNuno Sá case LTC2688_CMD_CH_CODE(0) ... LTC2688_CMD_CH_GAIN(15):
913832cb9eeSNuno Sá return true;
914832cb9eeSNuno Sá case LTC2688_CMD_CONFIG ... LTC2688_CMD_THERMAL_STAT:
915832cb9eeSNuno Sá return true;
916832cb9eeSNuno Sá default:
917832cb9eeSNuno Sá return false;
918832cb9eeSNuno Sá }
919832cb9eeSNuno Sá }
920832cb9eeSNuno Sá
ltc2688_reg_writable(struct device * dev,unsigned int reg)921832cb9eeSNuno Sá static bool ltc2688_reg_writable(struct device *dev, unsigned int reg)
922832cb9eeSNuno Sá {
923832cb9eeSNuno Sá /*
924832cb9eeSNuno Sá * There's a jump from 0x76 to 0x78 in the write codes and the thermal
925832cb9eeSNuno Sá * status code is 0x77 (which is read only) so that we need to check
926832cb9eeSNuno Sá * that special condition.
927832cb9eeSNuno Sá */
928832cb9eeSNuno Sá if (reg <= LTC2688_CMD_UPDATE_ALL && reg != LTC2688_CMD_THERMAL_STAT)
929832cb9eeSNuno Sá return true;
930832cb9eeSNuno Sá
931832cb9eeSNuno Sá return false;
932832cb9eeSNuno Sá }
933832cb9eeSNuno Sá
934832cb9eeSNuno Sá static struct regmap_bus ltc2688_regmap_bus = {
935832cb9eeSNuno Sá .read = ltc2688_spi_read,
936832cb9eeSNuno Sá .write = ltc2688_spi_write,
937832cb9eeSNuno Sá .read_flag_mask = LTC2688_READ_OPERATION,
938832cb9eeSNuno Sá .reg_format_endian_default = REGMAP_ENDIAN_BIG,
939832cb9eeSNuno Sá .val_format_endian_default = REGMAP_ENDIAN_BIG,
940832cb9eeSNuno Sá };
941832cb9eeSNuno Sá
942832cb9eeSNuno Sá static const struct regmap_config ltc2688_regmap_config = {
943832cb9eeSNuno Sá .reg_bits = 8,
944832cb9eeSNuno Sá .val_bits = 16,
945832cb9eeSNuno Sá .readable_reg = ltc2688_reg_readable,
946832cb9eeSNuno Sá .writeable_reg = ltc2688_reg_writable,
947832cb9eeSNuno Sá /* ignoring the no op command */
948832cb9eeSNuno Sá .max_register = LTC2688_CMD_UPDATE_ALL,
949832cb9eeSNuno Sá };
950832cb9eeSNuno Sá
951832cb9eeSNuno Sá static const struct iio_info ltc2688_info = {
952832cb9eeSNuno Sá .write_raw = ltc2688_write_raw,
953832cb9eeSNuno Sá .read_raw = ltc2688_read_raw,
954832cb9eeSNuno Sá .read_avail = ltc2688_read_avail,
955832cb9eeSNuno Sá .debugfs_reg_access = ltc2688_reg_access,
956832cb9eeSNuno Sá };
957832cb9eeSNuno Sá
ltc2688_probe(struct spi_device * spi)958832cb9eeSNuno Sá static int ltc2688_probe(struct spi_device *spi)
959832cb9eeSNuno Sá {
960*08f75f18SMatti Vaittinen static const char * const regulators[] = { "vcc", "iovcc" };
961832cb9eeSNuno Sá struct ltc2688_state *st;
962832cb9eeSNuno Sá struct iio_dev *indio_dev;
963832cb9eeSNuno Sá struct regulator *vref_reg;
964832cb9eeSNuno Sá struct device *dev = &spi->dev;
965832cb9eeSNuno Sá int ret;
966832cb9eeSNuno Sá
967832cb9eeSNuno Sá indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
968832cb9eeSNuno Sá if (!indio_dev)
969832cb9eeSNuno Sá return -ENOMEM;
970832cb9eeSNuno Sá
971832cb9eeSNuno Sá st = iio_priv(indio_dev);
972832cb9eeSNuno Sá st->spi = spi;
973832cb9eeSNuno Sá
974832cb9eeSNuno Sá /* Just write this once. No need to do it in every regmap read. */
975832cb9eeSNuno Sá st->tx_data[3] = LTC2688_CMD_NOOP;
976832cb9eeSNuno Sá mutex_init(&st->lock);
977832cb9eeSNuno Sá
978832cb9eeSNuno Sá st->regmap = devm_regmap_init(dev, <c2688_regmap_bus, st,
979832cb9eeSNuno Sá <c2688_regmap_config);
980832cb9eeSNuno Sá if (IS_ERR(st->regmap))
981832cb9eeSNuno Sá return dev_err_probe(dev, PTR_ERR(st->regmap),
982832cb9eeSNuno Sá "Failed to init regmap");
983832cb9eeSNuno Sá
984*08f75f18SMatti Vaittinen ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulators),
985*08f75f18SMatti Vaittinen regulators);
986832cb9eeSNuno Sá if (ret)
987832cb9eeSNuno Sá return dev_err_probe(dev, ret, "Failed to enable regulators\n");
988832cb9eeSNuno Sá
989832cb9eeSNuno Sá vref_reg = devm_regulator_get_optional(dev, "vref");
990832cb9eeSNuno Sá if (IS_ERR(vref_reg)) {
991832cb9eeSNuno Sá if (PTR_ERR(vref_reg) != -ENODEV)
992832cb9eeSNuno Sá return dev_err_probe(dev, PTR_ERR(vref_reg),
993832cb9eeSNuno Sá "Failed to get vref regulator");
994832cb9eeSNuno Sá
995832cb9eeSNuno Sá vref_reg = NULL;
996832cb9eeSNuno Sá /* internal reference */
997832cb9eeSNuno Sá st->vref = 4096;
998832cb9eeSNuno Sá } else {
999832cb9eeSNuno Sá ret = regulator_enable(vref_reg);
1000832cb9eeSNuno Sá if (ret)
1001832cb9eeSNuno Sá return dev_err_probe(dev, ret,
1002832cb9eeSNuno Sá "Failed to enable vref regulators\n");
1003832cb9eeSNuno Sá
1004832cb9eeSNuno Sá ret = devm_add_action_or_reset(dev, ltc2688_disable_regulator,
1005832cb9eeSNuno Sá vref_reg);
1006832cb9eeSNuno Sá if (ret)
1007832cb9eeSNuno Sá return ret;
1008832cb9eeSNuno Sá
1009832cb9eeSNuno Sá ret = regulator_get_voltage(vref_reg);
1010832cb9eeSNuno Sá if (ret < 0)
1011832cb9eeSNuno Sá return dev_err_probe(dev, ret, "Failed to get vref\n");
1012832cb9eeSNuno Sá
1013832cb9eeSNuno Sá st->vref = ret / 1000;
1014832cb9eeSNuno Sá }
1015832cb9eeSNuno Sá
1016832cb9eeSNuno Sá ret = ltc2688_setup(st, vref_reg);
1017832cb9eeSNuno Sá if (ret)
1018832cb9eeSNuno Sá return ret;
1019832cb9eeSNuno Sá
1020832cb9eeSNuno Sá indio_dev->name = "ltc2688";
1021832cb9eeSNuno Sá indio_dev->info = <c2688_info;
1022832cb9eeSNuno Sá indio_dev->modes = INDIO_DIRECT_MODE;
1023832cb9eeSNuno Sá indio_dev->channels = st->iio_chan;
1024832cb9eeSNuno Sá indio_dev->num_channels = ARRAY_SIZE(ltc2688_channels);
1025832cb9eeSNuno Sá
1026832cb9eeSNuno Sá return devm_iio_device_register(dev, indio_dev);
1027832cb9eeSNuno Sá }
1028832cb9eeSNuno Sá
1029832cb9eeSNuno Sá static const struct of_device_id ltc2688_of_id[] = {
1030832cb9eeSNuno Sá { .compatible = "adi,ltc2688" },
1031832cb9eeSNuno Sá {}
1032832cb9eeSNuno Sá };
1033832cb9eeSNuno Sá MODULE_DEVICE_TABLE(of, ltc2688_of_id);
1034832cb9eeSNuno Sá
1035832cb9eeSNuno Sá static const struct spi_device_id ltc2688_id[] = {
1036832cb9eeSNuno Sá { "ltc2688" },
1037832cb9eeSNuno Sá {}
1038832cb9eeSNuno Sá };
1039832cb9eeSNuno Sá MODULE_DEVICE_TABLE(spi, ltc2688_id);
1040832cb9eeSNuno Sá
1041832cb9eeSNuno Sá static struct spi_driver ltc2688_driver = {
1042832cb9eeSNuno Sá .driver = {
1043832cb9eeSNuno Sá .name = "ltc2688",
1044832cb9eeSNuno Sá .of_match_table = ltc2688_of_id,
1045832cb9eeSNuno Sá },
1046832cb9eeSNuno Sá .probe = ltc2688_probe,
1047832cb9eeSNuno Sá .id_table = ltc2688_id,
1048832cb9eeSNuno Sá };
1049832cb9eeSNuno Sá module_spi_driver(ltc2688_driver);
1050832cb9eeSNuno Sá
1051832cb9eeSNuno Sá MODULE_AUTHOR("Nuno Sá <nuno.sa@analog.com>");
1052832cb9eeSNuno Sá MODULE_DESCRIPTION("Analog Devices LTC2688 DAC");
1053832cb9eeSNuno Sá MODULE_LICENSE("GPL");
1054