1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * AD5770R Digital to analog converters driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright 2018 Analog Devices Inc.
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/bits.h>
9*4882a593Smuzhiyun #include <linux/delay.h>
10*4882a593Smuzhiyun #include <linux/device.h>
11*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
12*4882a593Smuzhiyun #include <linux/iio/iio.h>
13*4882a593Smuzhiyun #include <linux/iio/sysfs.h>
14*4882a593Smuzhiyun #include <linux/kernel.h>
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun #include <linux/property.h>
17*4882a593Smuzhiyun #include <linux/regmap.h>
18*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
19*4882a593Smuzhiyun #include <linux/spi/spi.h>
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #define ADI_SPI_IF_CONFIG_A 0x00
22*4882a593Smuzhiyun #define ADI_SPI_IF_CONFIG_B 0x01
23*4882a593Smuzhiyun #define ADI_SPI_IF_DEVICE_CONFIG 0x02
24*4882a593Smuzhiyun #define ADI_SPI_IF_CHIP_TYPE 0x03
25*4882a593Smuzhiyun #define ADI_SPI_IF_PRODUCT_ID_L 0x04
26*4882a593Smuzhiyun #define ADI_SPI_IF_PRODUCT_ID_H 0x05
27*4882a593Smuzhiyun #define ADI_SPI_IF_CHIP_GRADE 0x06
28*4882a593Smuzhiyun #define ADI_SPI_IF_SCRACTH_PAD 0x0A
29*4882a593Smuzhiyun #define ADI_SPI_IF_SPI_REVISION 0x0B
30*4882a593Smuzhiyun #define ADI_SPI_IF_SPI_VENDOR_L 0x0C
31*4882a593Smuzhiyun #define ADI_SPI_IF_SPI_VENDOR_H 0x0D
32*4882a593Smuzhiyun #define ADI_SPI_IF_SPI_STREAM_MODE 0x0E
33*4882a593Smuzhiyun #define ADI_SPI_IF_CONFIG_C 0x10
34*4882a593Smuzhiyun #define ADI_SPI_IF_STATUS_A 0x11
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun /* ADI_SPI_IF_CONFIG_A */
37*4882a593Smuzhiyun #define ADI_SPI_IF_SW_RESET_MSK (BIT(0) | BIT(7))
38*4882a593Smuzhiyun #define ADI_SPI_IF_SW_RESET_SEL(x) ((x) & ADI_SPI_IF_SW_RESET_MSK)
39*4882a593Smuzhiyun #define ADI_SPI_IF_ADDR_ASC_MSK (BIT(2) | BIT(5))
40*4882a593Smuzhiyun #define ADI_SPI_IF_ADDR_ASC_SEL(x) (((x) << 2) & ADI_SPI_IF_ADDR_ASC_MSK)
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /* ADI_SPI_IF_CONFIG_B */
43*4882a593Smuzhiyun #define ADI_SPI_IF_SINGLE_INS_MSK BIT(7)
44*4882a593Smuzhiyun #define ADI_SPI_IF_SINGLE_INS_SEL(x) FIELD_PREP(ADI_SPI_IF_SINGLE_INS_MSK, x)
45*4882a593Smuzhiyun #define ADI_SPI_IF_SHORT_INS_MSK BIT(7)
46*4882a593Smuzhiyun #define ADI_SPI_IF_SHORT_INS_SEL(x) FIELD_PREP(ADI_SPI_IF_SINGLE_INS_MSK, x)
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun /* ADI_SPI_IF_CONFIG_C */
49*4882a593Smuzhiyun #define ADI_SPI_IF_STRICT_REG_MSK BIT(5)
50*4882a593Smuzhiyun #define ADI_SPI_IF_STRICT_REG_GET(x) FIELD_GET(ADI_SPI_IF_STRICT_REG_MSK, x)
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun /* AD5770R configuration registers */
53*4882a593Smuzhiyun #define AD5770R_CHANNEL_CONFIG 0x14
54*4882a593Smuzhiyun #define AD5770R_OUTPUT_RANGE(ch) (0x15 + (ch))
55*4882a593Smuzhiyun #define AD5770R_FILTER_RESISTOR(ch) (0x1D + (ch))
56*4882a593Smuzhiyun #define AD5770R_REFERENCE 0x1B
57*4882a593Smuzhiyun #define AD5770R_DAC_LSB(ch) (0x26 + 2 * (ch))
58*4882a593Smuzhiyun #define AD5770R_DAC_MSB(ch) (0x27 + 2 * (ch))
59*4882a593Smuzhiyun #define AD5770R_CH_SELECT 0x34
60*4882a593Smuzhiyun #define AD5770R_CH_ENABLE 0x44
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun /* AD5770R_CHANNEL_CONFIG */
63*4882a593Smuzhiyun #define AD5770R_CFG_CH0_SINK_EN(x) (((x) & 0x1) << 7)
64*4882a593Smuzhiyun #define AD5770R_CFG_SHUTDOWN_B(x, ch) (((x) & 0x1) << (ch))
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun /* AD5770R_OUTPUT_RANGE */
67*4882a593Smuzhiyun #define AD5770R_RANGE_OUTPUT_SCALING(x) (((x) & GENMASK(5, 0)) << 2)
68*4882a593Smuzhiyun #define AD5770R_RANGE_MODE(x) ((x) & GENMASK(1, 0))
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /* AD5770R_REFERENCE */
71*4882a593Smuzhiyun #define AD5770R_REF_RESISTOR_SEL(x) (((x) & 0x1) << 2)
72*4882a593Smuzhiyun #define AD5770R_REF_SEL(x) ((x) & GENMASK(1, 0))
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun /* AD5770R_CH_ENABLE */
75*4882a593Smuzhiyun #define AD5770R_CH_SET(x, ch) (((x) & 0x1) << (ch))
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun #define AD5770R_MAX_CHANNELS 6
78*4882a593Smuzhiyun #define AD5770R_MAX_CH_MODES 14
79*4882a593Smuzhiyun #define AD5770R_LOW_VREF_mV 1250
80*4882a593Smuzhiyun #define AD5770R_HIGH_VREF_mV 2500
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun enum ad5770r_ch0_modes {
83*4882a593Smuzhiyun AD5770R_CH0_0_300 = 0,
84*4882a593Smuzhiyun AD5770R_CH0_NEG_60_0,
85*4882a593Smuzhiyun AD5770R_CH0_NEG_60_300
86*4882a593Smuzhiyun };
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun enum ad5770r_ch1_modes {
89*4882a593Smuzhiyun AD5770R_CH1_0_140_LOW_HEAD = 1,
90*4882a593Smuzhiyun AD5770R_CH1_0_140_LOW_NOISE,
91*4882a593Smuzhiyun AD5770R_CH1_0_250
92*4882a593Smuzhiyun };
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun enum ad5770r_ch2_5_modes {
95*4882a593Smuzhiyun AD5770R_CH_LOW_RANGE = 0,
96*4882a593Smuzhiyun AD5770R_CH_HIGH_RANGE
97*4882a593Smuzhiyun };
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun enum ad5770r_ref_v {
100*4882a593Smuzhiyun AD5770R_EXT_2_5_V = 0,
101*4882a593Smuzhiyun AD5770R_INT_1_25_V_OUT_ON,
102*4882a593Smuzhiyun AD5770R_EXT_1_25_V,
103*4882a593Smuzhiyun AD5770R_INT_1_25_V_OUT_OFF
104*4882a593Smuzhiyun };
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun enum ad5770r_output_filter_resistor {
107*4882a593Smuzhiyun AD5770R_FILTER_60_OHM = 0x0,
108*4882a593Smuzhiyun AD5770R_FILTER_5_6_KOHM = 0x5,
109*4882a593Smuzhiyun AD5770R_FILTER_11_2_KOHM,
110*4882a593Smuzhiyun AD5770R_FILTER_22_2_KOHM,
111*4882a593Smuzhiyun AD5770R_FILTER_44_4_KOHM,
112*4882a593Smuzhiyun AD5770R_FILTER_104_KOHM,
113*4882a593Smuzhiyun };
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun struct ad5770r_out_range {
116*4882a593Smuzhiyun u8 out_scale;
117*4882a593Smuzhiyun u8 out_range_mode;
118*4882a593Smuzhiyun };
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun /**
121*4882a593Smuzhiyun * struct ad5770R_state - driver instance specific data
122*4882a593Smuzhiyun * @spi: spi_device
123*4882a593Smuzhiyun * @regmap: regmap
124*4882a593Smuzhiyun * @vref_reg: fixed regulator for reference configuration
125*4882a593Smuzhiyun * @gpio_reset: gpio descriptor
126*4882a593Smuzhiyun * @output_mode: array contains channels output ranges
127*4882a593Smuzhiyun * @vref: reference value
128*4882a593Smuzhiyun * @ch_pwr_down: powerdown flags
129*4882a593Smuzhiyun * @internal_ref: internal reference flag
130*4882a593Smuzhiyun * @external_res: external 2.5k resistor flag
131*4882a593Smuzhiyun * @transf_buf: cache aligned buffer for spi read/write
132*4882a593Smuzhiyun */
133*4882a593Smuzhiyun struct ad5770r_state {
134*4882a593Smuzhiyun struct spi_device *spi;
135*4882a593Smuzhiyun struct regmap *regmap;
136*4882a593Smuzhiyun struct regulator *vref_reg;
137*4882a593Smuzhiyun struct gpio_desc *gpio_reset;
138*4882a593Smuzhiyun struct ad5770r_out_range output_mode[AD5770R_MAX_CHANNELS];
139*4882a593Smuzhiyun int vref;
140*4882a593Smuzhiyun bool ch_pwr_down[AD5770R_MAX_CHANNELS];
141*4882a593Smuzhiyun bool internal_ref;
142*4882a593Smuzhiyun bool external_res;
143*4882a593Smuzhiyun u8 transf_buf[2] ____cacheline_aligned;
144*4882a593Smuzhiyun };
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun static const struct regmap_config ad5770r_spi_regmap_config = {
147*4882a593Smuzhiyun .reg_bits = 8,
148*4882a593Smuzhiyun .val_bits = 8,
149*4882a593Smuzhiyun .read_flag_mask = BIT(7),
150*4882a593Smuzhiyun };
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun struct ad5770r_output_modes {
153*4882a593Smuzhiyun unsigned int ch;
154*4882a593Smuzhiyun u8 mode;
155*4882a593Smuzhiyun int min;
156*4882a593Smuzhiyun int max;
157*4882a593Smuzhiyun };
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun static struct ad5770r_output_modes ad5770r_rng_tbl[] = {
160*4882a593Smuzhiyun { 0, AD5770R_CH0_0_300, 0, 300 },
161*4882a593Smuzhiyun { 0, AD5770R_CH0_NEG_60_0, -60, 0 },
162*4882a593Smuzhiyun { 0, AD5770R_CH0_NEG_60_300, -60, 300 },
163*4882a593Smuzhiyun { 1, AD5770R_CH1_0_140_LOW_HEAD, 0, 140 },
164*4882a593Smuzhiyun { 1, AD5770R_CH1_0_140_LOW_NOISE, 0, 140 },
165*4882a593Smuzhiyun { 1, AD5770R_CH1_0_250, 0, 250 },
166*4882a593Smuzhiyun { 2, AD5770R_CH_LOW_RANGE, 0, 55 },
167*4882a593Smuzhiyun { 2, AD5770R_CH_HIGH_RANGE, 0, 150 },
168*4882a593Smuzhiyun { 3, AD5770R_CH_LOW_RANGE, 0, 45 },
169*4882a593Smuzhiyun { 3, AD5770R_CH_HIGH_RANGE, 0, 100 },
170*4882a593Smuzhiyun { 4, AD5770R_CH_LOW_RANGE, 0, 45 },
171*4882a593Smuzhiyun { 4, AD5770R_CH_HIGH_RANGE, 0, 100 },
172*4882a593Smuzhiyun { 5, AD5770R_CH_LOW_RANGE, 0, 45 },
173*4882a593Smuzhiyun { 5, AD5770R_CH_HIGH_RANGE, 0, 100 },
174*4882a593Smuzhiyun };
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun static const unsigned int ad5770r_filter_freqs[] = {
177*4882a593Smuzhiyun 153, 357, 715, 1400, 2800, 262000,
178*4882a593Smuzhiyun };
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun static const unsigned int ad5770r_filter_reg_vals[] = {
181*4882a593Smuzhiyun AD5770R_FILTER_104_KOHM,
182*4882a593Smuzhiyun AD5770R_FILTER_44_4_KOHM,
183*4882a593Smuzhiyun AD5770R_FILTER_22_2_KOHM,
184*4882a593Smuzhiyun AD5770R_FILTER_11_2_KOHM,
185*4882a593Smuzhiyun AD5770R_FILTER_5_6_KOHM,
186*4882a593Smuzhiyun AD5770R_FILTER_60_OHM
187*4882a593Smuzhiyun };
188*4882a593Smuzhiyun
ad5770r_set_output_mode(struct ad5770r_state * st,const struct ad5770r_out_range * out_mode,int channel)189*4882a593Smuzhiyun static int ad5770r_set_output_mode(struct ad5770r_state *st,
190*4882a593Smuzhiyun const struct ad5770r_out_range *out_mode,
191*4882a593Smuzhiyun int channel)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun unsigned int regval;
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun regval = AD5770R_RANGE_OUTPUT_SCALING(out_mode->out_scale) |
196*4882a593Smuzhiyun AD5770R_RANGE_MODE(out_mode->out_range_mode);
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun return regmap_write(st->regmap,
199*4882a593Smuzhiyun AD5770R_OUTPUT_RANGE(channel), regval);
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
ad5770r_set_reference(struct ad5770r_state * st)202*4882a593Smuzhiyun static int ad5770r_set_reference(struct ad5770r_state *st)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun unsigned int regval;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun regval = AD5770R_REF_RESISTOR_SEL(st->external_res);
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun if (st->internal_ref) {
209*4882a593Smuzhiyun regval |= AD5770R_REF_SEL(AD5770R_INT_1_25_V_OUT_OFF);
210*4882a593Smuzhiyun } else {
211*4882a593Smuzhiyun switch (st->vref) {
212*4882a593Smuzhiyun case AD5770R_LOW_VREF_mV:
213*4882a593Smuzhiyun regval |= AD5770R_REF_SEL(AD5770R_EXT_1_25_V);
214*4882a593Smuzhiyun break;
215*4882a593Smuzhiyun case AD5770R_HIGH_VREF_mV:
216*4882a593Smuzhiyun regval |= AD5770R_REF_SEL(AD5770R_EXT_2_5_V);
217*4882a593Smuzhiyun break;
218*4882a593Smuzhiyun default:
219*4882a593Smuzhiyun regval = AD5770R_REF_SEL(AD5770R_INT_1_25_V_OUT_OFF);
220*4882a593Smuzhiyun break;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun return regmap_write(st->regmap, AD5770R_REFERENCE, regval);
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
ad5770r_soft_reset(struct ad5770r_state * st)227*4882a593Smuzhiyun static int ad5770r_soft_reset(struct ad5770r_state *st)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun return regmap_write(st->regmap, ADI_SPI_IF_CONFIG_A,
230*4882a593Smuzhiyun ADI_SPI_IF_SW_RESET_SEL(1));
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun
ad5770r_reset(struct ad5770r_state * st)233*4882a593Smuzhiyun static int ad5770r_reset(struct ad5770r_state *st)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun /* Perform software reset if no GPIO provided */
236*4882a593Smuzhiyun if (!st->gpio_reset)
237*4882a593Smuzhiyun return ad5770r_soft_reset(st);
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun gpiod_set_value_cansleep(st->gpio_reset, 0);
240*4882a593Smuzhiyun usleep_range(10, 20);
241*4882a593Smuzhiyun gpiod_set_value_cansleep(st->gpio_reset, 1);
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun /* data must not be written during reset timeframe */
244*4882a593Smuzhiyun usleep_range(100, 200);
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun return 0;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
ad5770r_get_range(struct ad5770r_state * st,int ch,int * min,int * max)249*4882a593Smuzhiyun static int ad5770r_get_range(struct ad5770r_state *st,
250*4882a593Smuzhiyun int ch, int *min, int *max)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun int i;
253*4882a593Smuzhiyun u8 tbl_ch, tbl_mode, out_range;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun out_range = st->output_mode[ch].out_range_mode;
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun for (i = 0; i < AD5770R_MAX_CH_MODES; i++) {
258*4882a593Smuzhiyun tbl_ch = ad5770r_rng_tbl[i].ch;
259*4882a593Smuzhiyun tbl_mode = ad5770r_rng_tbl[i].mode;
260*4882a593Smuzhiyun if (tbl_ch == ch && tbl_mode == out_range) {
261*4882a593Smuzhiyun *min = ad5770r_rng_tbl[i].min;
262*4882a593Smuzhiyun *max = ad5770r_rng_tbl[i].max;
263*4882a593Smuzhiyun return 0;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun return -EINVAL;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun
ad5770r_get_filter_freq(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,int * freq)270*4882a593Smuzhiyun static int ad5770r_get_filter_freq(struct iio_dev *indio_dev,
271*4882a593Smuzhiyun const struct iio_chan_spec *chan, int *freq)
272*4882a593Smuzhiyun {
273*4882a593Smuzhiyun struct ad5770r_state *st = iio_priv(indio_dev);
274*4882a593Smuzhiyun int ret;
275*4882a593Smuzhiyun unsigned int regval, i;
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun ret = regmap_read(st->regmap,
278*4882a593Smuzhiyun AD5770R_FILTER_RESISTOR(chan->channel), ®val);
279*4882a593Smuzhiyun if (ret < 0)
280*4882a593Smuzhiyun return ret;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(ad5770r_filter_reg_vals); i++)
283*4882a593Smuzhiyun if (regval == ad5770r_filter_reg_vals[i])
284*4882a593Smuzhiyun break;
285*4882a593Smuzhiyun if (i == ARRAY_SIZE(ad5770r_filter_reg_vals))
286*4882a593Smuzhiyun return -EINVAL;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun *freq = ad5770r_filter_freqs[i];
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun return IIO_VAL_INT;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun
ad5770r_set_filter_freq(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,unsigned int freq)293*4882a593Smuzhiyun static int ad5770r_set_filter_freq(struct iio_dev *indio_dev,
294*4882a593Smuzhiyun const struct iio_chan_spec *chan,
295*4882a593Smuzhiyun unsigned int freq)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun struct ad5770r_state *st = iio_priv(indio_dev);
298*4882a593Smuzhiyun unsigned int regval, i;
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(ad5770r_filter_freqs); i++)
301*4882a593Smuzhiyun if (ad5770r_filter_freqs[i] >= freq)
302*4882a593Smuzhiyun break;
303*4882a593Smuzhiyun if (i == ARRAY_SIZE(ad5770r_filter_freqs))
304*4882a593Smuzhiyun return -EINVAL;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun regval = ad5770r_filter_reg_vals[i];
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun return regmap_write(st->regmap, AD5770R_FILTER_RESISTOR(chan->channel),
309*4882a593Smuzhiyun regval);
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
ad5770r_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long info)312*4882a593Smuzhiyun static int ad5770r_read_raw(struct iio_dev *indio_dev,
313*4882a593Smuzhiyun struct iio_chan_spec const *chan,
314*4882a593Smuzhiyun int *val, int *val2, long info)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun struct ad5770r_state *st = iio_priv(indio_dev);
317*4882a593Smuzhiyun int max, min, ret;
318*4882a593Smuzhiyun u16 buf16;
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun switch (info) {
321*4882a593Smuzhiyun case IIO_CHAN_INFO_RAW:
322*4882a593Smuzhiyun ret = regmap_bulk_read(st->regmap,
323*4882a593Smuzhiyun chan->address,
324*4882a593Smuzhiyun st->transf_buf, 2);
325*4882a593Smuzhiyun if (ret)
326*4882a593Smuzhiyun return 0;
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun buf16 = st->transf_buf[0] + (st->transf_buf[1] << 8);
329*4882a593Smuzhiyun *val = buf16 >> 2;
330*4882a593Smuzhiyun return IIO_VAL_INT;
331*4882a593Smuzhiyun case IIO_CHAN_INFO_SCALE:
332*4882a593Smuzhiyun ret = ad5770r_get_range(st, chan->channel, &min, &max);
333*4882a593Smuzhiyun if (ret < 0)
334*4882a593Smuzhiyun return ret;
335*4882a593Smuzhiyun *val = max - min;
336*4882a593Smuzhiyun /* There is no sign bit. (negative current is mapped from 0)
337*4882a593Smuzhiyun * (sourced/sinked) current = raw * scale + offset
338*4882a593Smuzhiyun * where offset in case of CH0 can be negative.
339*4882a593Smuzhiyun */
340*4882a593Smuzhiyun *val2 = 14;
341*4882a593Smuzhiyun return IIO_VAL_FRACTIONAL_LOG2;
342*4882a593Smuzhiyun case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
343*4882a593Smuzhiyun return ad5770r_get_filter_freq(indio_dev, chan, val);
344*4882a593Smuzhiyun case IIO_CHAN_INFO_OFFSET:
345*4882a593Smuzhiyun ret = ad5770r_get_range(st, chan->channel, &min, &max);
346*4882a593Smuzhiyun if (ret < 0)
347*4882a593Smuzhiyun return ret;
348*4882a593Smuzhiyun *val = min;
349*4882a593Smuzhiyun return IIO_VAL_INT;
350*4882a593Smuzhiyun default:
351*4882a593Smuzhiyun return -EINVAL;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun
ad5770r_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long info)355*4882a593Smuzhiyun static int ad5770r_write_raw(struct iio_dev *indio_dev,
356*4882a593Smuzhiyun struct iio_chan_spec const *chan,
357*4882a593Smuzhiyun int val, int val2, long info)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun struct ad5770r_state *st = iio_priv(indio_dev);
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun switch (info) {
362*4882a593Smuzhiyun case IIO_CHAN_INFO_RAW:
363*4882a593Smuzhiyun st->transf_buf[0] = ((u16)val >> 6);
364*4882a593Smuzhiyun st->transf_buf[1] = (val & GENMASK(5, 0)) << 2;
365*4882a593Smuzhiyun return regmap_bulk_write(st->regmap, chan->address,
366*4882a593Smuzhiyun st->transf_buf, 2);
367*4882a593Smuzhiyun case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
368*4882a593Smuzhiyun return ad5770r_set_filter_freq(indio_dev, chan, val);
369*4882a593Smuzhiyun default:
370*4882a593Smuzhiyun return -EINVAL;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun
ad5770r_read_freq_avail(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,const int ** vals,int * type,int * length,long mask)374*4882a593Smuzhiyun static int ad5770r_read_freq_avail(struct iio_dev *indio_dev,
375*4882a593Smuzhiyun struct iio_chan_spec const *chan,
376*4882a593Smuzhiyun const int **vals, int *type, int *length,
377*4882a593Smuzhiyun long mask)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun switch (mask) {
380*4882a593Smuzhiyun case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
381*4882a593Smuzhiyun *type = IIO_VAL_INT;
382*4882a593Smuzhiyun *vals = ad5770r_filter_freqs;
383*4882a593Smuzhiyun *length = ARRAY_SIZE(ad5770r_filter_freqs);
384*4882a593Smuzhiyun return IIO_AVAIL_LIST;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun return -EINVAL;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun
ad5770r_reg_access(struct iio_dev * indio_dev,unsigned int reg,unsigned int writeval,unsigned int * readval)390*4882a593Smuzhiyun static int ad5770r_reg_access(struct iio_dev *indio_dev,
391*4882a593Smuzhiyun unsigned int reg,
392*4882a593Smuzhiyun unsigned int writeval,
393*4882a593Smuzhiyun unsigned int *readval)
394*4882a593Smuzhiyun {
395*4882a593Smuzhiyun struct ad5770r_state *st = iio_priv(indio_dev);
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun if (readval)
398*4882a593Smuzhiyun return regmap_read(st->regmap, reg, readval);
399*4882a593Smuzhiyun else
400*4882a593Smuzhiyun return regmap_write(st->regmap, reg, writeval);
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun static const struct iio_info ad5770r_info = {
404*4882a593Smuzhiyun .read_raw = ad5770r_read_raw,
405*4882a593Smuzhiyun .write_raw = ad5770r_write_raw,
406*4882a593Smuzhiyun .read_avail = ad5770r_read_freq_avail,
407*4882a593Smuzhiyun .debugfs_reg_access = &ad5770r_reg_access,
408*4882a593Smuzhiyun };
409*4882a593Smuzhiyun
ad5770r_store_output_range(struct ad5770r_state * st,int min,int max,int index)410*4882a593Smuzhiyun static int ad5770r_store_output_range(struct ad5770r_state *st,
411*4882a593Smuzhiyun int min, int max, int index)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun int i;
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun for (i = 0; i < AD5770R_MAX_CH_MODES; i++) {
416*4882a593Smuzhiyun if (ad5770r_rng_tbl[i].ch != index)
417*4882a593Smuzhiyun continue;
418*4882a593Smuzhiyun if (ad5770r_rng_tbl[i].min != min ||
419*4882a593Smuzhiyun ad5770r_rng_tbl[i].max != max)
420*4882a593Smuzhiyun continue;
421*4882a593Smuzhiyun st->output_mode[index].out_range_mode = ad5770r_rng_tbl[i].mode;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun return 0;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun return -EINVAL;
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun
ad5770r_read_dac_powerdown(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,char * buf)429*4882a593Smuzhiyun static ssize_t ad5770r_read_dac_powerdown(struct iio_dev *indio_dev,
430*4882a593Smuzhiyun uintptr_t private,
431*4882a593Smuzhiyun const struct iio_chan_spec *chan,
432*4882a593Smuzhiyun char *buf)
433*4882a593Smuzhiyun {
434*4882a593Smuzhiyun struct ad5770r_state *st = iio_priv(indio_dev);
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun return sprintf(buf, "%d\n", st->ch_pwr_down[chan->channel]);
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun
ad5770r_write_dac_powerdown(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,const char * buf,size_t len)439*4882a593Smuzhiyun static ssize_t ad5770r_write_dac_powerdown(struct iio_dev *indio_dev,
440*4882a593Smuzhiyun uintptr_t private,
441*4882a593Smuzhiyun const struct iio_chan_spec *chan,
442*4882a593Smuzhiyun const char *buf, size_t len)
443*4882a593Smuzhiyun {
444*4882a593Smuzhiyun struct ad5770r_state *st = iio_priv(indio_dev);
445*4882a593Smuzhiyun unsigned int regval;
446*4882a593Smuzhiyun unsigned int mask;
447*4882a593Smuzhiyun bool readin;
448*4882a593Smuzhiyun int ret;
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun ret = kstrtobool(buf, &readin);
451*4882a593Smuzhiyun if (ret)
452*4882a593Smuzhiyun return ret;
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun readin = !readin;
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun regval = AD5770R_CFG_SHUTDOWN_B(readin, chan->channel);
457*4882a593Smuzhiyun if (chan->channel == 0 &&
458*4882a593Smuzhiyun st->output_mode[0].out_range_mode > AD5770R_CH0_0_300) {
459*4882a593Smuzhiyun regval |= AD5770R_CFG_CH0_SINK_EN(readin);
460*4882a593Smuzhiyun mask = BIT(chan->channel) + BIT(7);
461*4882a593Smuzhiyun } else {
462*4882a593Smuzhiyun mask = BIT(chan->channel);
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun ret = regmap_update_bits(st->regmap, AD5770R_CHANNEL_CONFIG, mask,
465*4882a593Smuzhiyun regval);
466*4882a593Smuzhiyun if (ret)
467*4882a593Smuzhiyun return ret;
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun regval = AD5770R_CH_SET(readin, chan->channel);
470*4882a593Smuzhiyun ret = regmap_update_bits(st->regmap, AD5770R_CH_ENABLE,
471*4882a593Smuzhiyun BIT(chan->channel), regval);
472*4882a593Smuzhiyun if (ret)
473*4882a593Smuzhiyun return ret;
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun st->ch_pwr_down[chan->channel] = !readin;
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun return len;
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun static const struct iio_chan_spec_ext_info ad5770r_ext_info[] = {
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun .name = "powerdown",
483*4882a593Smuzhiyun .read = ad5770r_read_dac_powerdown,
484*4882a593Smuzhiyun .write = ad5770r_write_dac_powerdown,
485*4882a593Smuzhiyun .shared = IIO_SEPARATE,
486*4882a593Smuzhiyun },
487*4882a593Smuzhiyun { }
488*4882a593Smuzhiyun };
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun #define AD5770R_IDAC_CHANNEL(index, reg) { \
491*4882a593Smuzhiyun .type = IIO_CURRENT, \
492*4882a593Smuzhiyun .address = reg, \
493*4882a593Smuzhiyun .indexed = 1, \
494*4882a593Smuzhiyun .channel = index, \
495*4882a593Smuzhiyun .output = 1, \
496*4882a593Smuzhiyun .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
497*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_SCALE) | \
498*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_OFFSET) | \
499*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
500*4882a593Smuzhiyun .info_mask_shared_by_type_available = \
501*4882a593Smuzhiyun BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
502*4882a593Smuzhiyun .ext_info = ad5770r_ext_info, \
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun static const struct iio_chan_spec ad5770r_channels[] = {
506*4882a593Smuzhiyun AD5770R_IDAC_CHANNEL(0, AD5770R_DAC_MSB(0)),
507*4882a593Smuzhiyun AD5770R_IDAC_CHANNEL(1, AD5770R_DAC_MSB(1)),
508*4882a593Smuzhiyun AD5770R_IDAC_CHANNEL(2, AD5770R_DAC_MSB(2)),
509*4882a593Smuzhiyun AD5770R_IDAC_CHANNEL(3, AD5770R_DAC_MSB(3)),
510*4882a593Smuzhiyun AD5770R_IDAC_CHANNEL(4, AD5770R_DAC_MSB(4)),
511*4882a593Smuzhiyun AD5770R_IDAC_CHANNEL(5, AD5770R_DAC_MSB(5)),
512*4882a593Smuzhiyun };
513*4882a593Smuzhiyun
ad5770r_channel_config(struct ad5770r_state * st)514*4882a593Smuzhiyun static int ad5770r_channel_config(struct ad5770r_state *st)
515*4882a593Smuzhiyun {
516*4882a593Smuzhiyun int ret, tmp[2], min, max;
517*4882a593Smuzhiyun unsigned int num;
518*4882a593Smuzhiyun struct fwnode_handle *child;
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun num = device_get_child_node_count(&st->spi->dev);
521*4882a593Smuzhiyun if (num != AD5770R_MAX_CHANNELS)
522*4882a593Smuzhiyun return -EINVAL;
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun device_for_each_child_node(&st->spi->dev, child) {
525*4882a593Smuzhiyun ret = fwnode_property_read_u32(child, "reg", &num);
526*4882a593Smuzhiyun if (ret)
527*4882a593Smuzhiyun goto err_child_out;
528*4882a593Smuzhiyun if (num >= AD5770R_MAX_CHANNELS) {
529*4882a593Smuzhiyun ret = -EINVAL;
530*4882a593Smuzhiyun goto err_child_out;
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun ret = fwnode_property_read_u32_array(child,
534*4882a593Smuzhiyun "adi,range-microamp",
535*4882a593Smuzhiyun tmp, 2);
536*4882a593Smuzhiyun if (ret)
537*4882a593Smuzhiyun goto err_child_out;
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun min = tmp[0] / 1000;
540*4882a593Smuzhiyun max = tmp[1] / 1000;
541*4882a593Smuzhiyun ret = ad5770r_store_output_range(st, min, max, num);
542*4882a593Smuzhiyun if (ret)
543*4882a593Smuzhiyun goto err_child_out;
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun return 0;
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun err_child_out:
549*4882a593Smuzhiyun fwnode_handle_put(child);
550*4882a593Smuzhiyun return ret;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun
ad5770r_init(struct ad5770r_state * st)553*4882a593Smuzhiyun static int ad5770r_init(struct ad5770r_state *st)
554*4882a593Smuzhiyun {
555*4882a593Smuzhiyun int ret, i;
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun st->gpio_reset = devm_gpiod_get_optional(&st->spi->dev, "reset",
558*4882a593Smuzhiyun GPIOD_OUT_HIGH);
559*4882a593Smuzhiyun if (IS_ERR(st->gpio_reset))
560*4882a593Smuzhiyun return PTR_ERR(st->gpio_reset);
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun /* Perform a reset */
563*4882a593Smuzhiyun ret = ad5770r_reset(st);
564*4882a593Smuzhiyun if (ret)
565*4882a593Smuzhiyun return ret;
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun /* Set output range */
568*4882a593Smuzhiyun ret = ad5770r_channel_config(st);
569*4882a593Smuzhiyun if (ret)
570*4882a593Smuzhiyun return ret;
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun for (i = 0; i < AD5770R_MAX_CHANNELS; i++) {
573*4882a593Smuzhiyun ret = ad5770r_set_output_mode(st, &st->output_mode[i], i);
574*4882a593Smuzhiyun if (ret)
575*4882a593Smuzhiyun return ret;
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun st->external_res = fwnode_property_read_bool(st->spi->dev.fwnode,
579*4882a593Smuzhiyun "adi,external-resistor");
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun ret = ad5770r_set_reference(st);
582*4882a593Smuzhiyun if (ret)
583*4882a593Smuzhiyun return ret;
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun /* Set outputs off */
586*4882a593Smuzhiyun ret = regmap_write(st->regmap, AD5770R_CHANNEL_CONFIG, 0x00);
587*4882a593Smuzhiyun if (ret)
588*4882a593Smuzhiyun return ret;
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun ret = regmap_write(st->regmap, AD5770R_CH_ENABLE, 0x00);
591*4882a593Smuzhiyun if (ret)
592*4882a593Smuzhiyun return ret;
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun for (i = 0; i < AD5770R_MAX_CHANNELS; i++)
595*4882a593Smuzhiyun st->ch_pwr_down[i] = true;
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun return ret;
598*4882a593Smuzhiyun }
599*4882a593Smuzhiyun
ad5770r_disable_regulator(void * data)600*4882a593Smuzhiyun static void ad5770r_disable_regulator(void *data)
601*4882a593Smuzhiyun {
602*4882a593Smuzhiyun struct ad5770r_state *st = data;
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun regulator_disable(st->vref_reg);
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun
ad5770r_probe(struct spi_device * spi)607*4882a593Smuzhiyun static int ad5770r_probe(struct spi_device *spi)
608*4882a593Smuzhiyun {
609*4882a593Smuzhiyun struct ad5770r_state *st;
610*4882a593Smuzhiyun struct iio_dev *indio_dev;
611*4882a593Smuzhiyun struct regmap *regmap;
612*4882a593Smuzhiyun int ret;
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
615*4882a593Smuzhiyun if (!indio_dev)
616*4882a593Smuzhiyun return -ENOMEM;
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun st = iio_priv(indio_dev);
619*4882a593Smuzhiyun spi_set_drvdata(spi, indio_dev);
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun st->spi = spi;
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun regmap = devm_regmap_init_spi(spi, &ad5770r_spi_regmap_config);
624*4882a593Smuzhiyun if (IS_ERR(regmap)) {
625*4882a593Smuzhiyun dev_err(&spi->dev, "Error initializing spi regmap: %ld\n",
626*4882a593Smuzhiyun PTR_ERR(regmap));
627*4882a593Smuzhiyun return PTR_ERR(regmap);
628*4882a593Smuzhiyun }
629*4882a593Smuzhiyun st->regmap = regmap;
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun st->vref_reg = devm_regulator_get_optional(&spi->dev, "vref");
632*4882a593Smuzhiyun if (!IS_ERR(st->vref_reg)) {
633*4882a593Smuzhiyun ret = regulator_enable(st->vref_reg);
634*4882a593Smuzhiyun if (ret) {
635*4882a593Smuzhiyun dev_err(&spi->dev,
636*4882a593Smuzhiyun "Failed to enable vref regulators: %d\n", ret);
637*4882a593Smuzhiyun return ret;
638*4882a593Smuzhiyun }
639*4882a593Smuzhiyun
640*4882a593Smuzhiyun ret = devm_add_action_or_reset(&spi->dev,
641*4882a593Smuzhiyun ad5770r_disable_regulator,
642*4882a593Smuzhiyun st);
643*4882a593Smuzhiyun if (ret < 0)
644*4882a593Smuzhiyun return ret;
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun ret = regulator_get_voltage(st->vref_reg);
647*4882a593Smuzhiyun if (ret < 0)
648*4882a593Smuzhiyun return ret;
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun st->vref = ret / 1000;
651*4882a593Smuzhiyun } else {
652*4882a593Smuzhiyun if (PTR_ERR(st->vref_reg) == -ENODEV) {
653*4882a593Smuzhiyun st->vref = AD5770R_LOW_VREF_mV;
654*4882a593Smuzhiyun st->internal_ref = true;
655*4882a593Smuzhiyun } else {
656*4882a593Smuzhiyun return PTR_ERR(st->vref_reg);
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun indio_dev->name = spi_get_device_id(spi)->name;
661*4882a593Smuzhiyun indio_dev->info = &ad5770r_info;
662*4882a593Smuzhiyun indio_dev->modes = INDIO_DIRECT_MODE;
663*4882a593Smuzhiyun indio_dev->channels = ad5770r_channels;
664*4882a593Smuzhiyun indio_dev->num_channels = ARRAY_SIZE(ad5770r_channels);
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun ret = ad5770r_init(st);
667*4882a593Smuzhiyun if (ret < 0) {
668*4882a593Smuzhiyun dev_err(&spi->dev, "AD5770R init failed\n");
669*4882a593Smuzhiyun return ret;
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun return devm_iio_device_register(&st->spi->dev, indio_dev);
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun static const struct of_device_id ad5770r_of_id[] = {
676*4882a593Smuzhiyun { .compatible = "adi,ad5770r", },
677*4882a593Smuzhiyun {},
678*4882a593Smuzhiyun };
679*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, ad5770r_of_id);
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun static const struct spi_device_id ad5770r_id[] = {
682*4882a593Smuzhiyun { "ad5770r", 0 },
683*4882a593Smuzhiyun {},
684*4882a593Smuzhiyun };
685*4882a593Smuzhiyun MODULE_DEVICE_TABLE(spi, ad5770r_id);
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun static struct spi_driver ad5770r_driver = {
688*4882a593Smuzhiyun .driver = {
689*4882a593Smuzhiyun .name = KBUILD_MODNAME,
690*4882a593Smuzhiyun .of_match_table = ad5770r_of_id,
691*4882a593Smuzhiyun },
692*4882a593Smuzhiyun .probe = ad5770r_probe,
693*4882a593Smuzhiyun .id_table = ad5770r_id,
694*4882a593Smuzhiyun };
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun module_spi_driver(ad5770r_driver);
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun MODULE_AUTHOR("Mircea Caprioru <mircea.caprioru@analog.com>");
699*4882a593Smuzhiyun MODULE_DESCRIPTION("Analog Devices AD5770R IDAC");
700*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
701