Commit | Line | Data |
---|---|---|
ad679712 MH |
1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* | |
3 | * Analog Devices AD9467 SPI ADC driver | |
4 | * | |
5 | * Copyright 2012-2020 Analog Devices Inc. | |
6 | */ | |
7 | ||
8 | #include <linux/module.h> | |
9 | #include <linux/device.h> | |
10 | #include <linux/kernel.h> | |
11 | #include <linux/slab.h> | |
12 | #include <linux/spi/spi.h> | |
13 | #include <linux/err.h> | |
14 | #include <linux/delay.h> | |
15 | #include <linux/gpio/consumer.h> | |
16 | #include <linux/of_device.h> | |
17 | ||
18 | ||
19 | #include <linux/iio/iio.h> | |
20 | #include <linux/iio/sysfs.h> | |
21 | ||
22 | #include <linux/clk.h> | |
23 | ||
24 | #include <linux/iio/adc/adi-axi-adc.h> | |
25 | ||
26 | /* | |
27 | * ADI High-Speed ADC common spi interface registers | |
28 | * See Application-Note AN-877: | |
29 | * https://www.analog.com/media/en/technical-documentation/application-notes/AN-877.pdf | |
30 | */ | |
31 | ||
32 | #define AN877_ADC_REG_CHIP_PORT_CONF 0x00 | |
33 | #define AN877_ADC_REG_CHIP_ID 0x01 | |
34 | #define AN877_ADC_REG_CHIP_GRADE 0x02 | |
35 | #define AN877_ADC_REG_CHAN_INDEX 0x05 | |
36 | #define AN877_ADC_REG_TRANSFER 0xFF | |
37 | #define AN877_ADC_REG_MODES 0x08 | |
38 | #define AN877_ADC_REG_TEST_IO 0x0D | |
39 | #define AN877_ADC_REG_ADC_INPUT 0x0F | |
40 | #define AN877_ADC_REG_OFFSET 0x10 | |
41 | #define AN877_ADC_REG_OUTPUT_MODE 0x14 | |
42 | #define AN877_ADC_REG_OUTPUT_ADJUST 0x15 | |
43 | #define AN877_ADC_REG_OUTPUT_PHASE 0x16 | |
44 | #define AN877_ADC_REG_OUTPUT_DELAY 0x17 | |
45 | #define AN877_ADC_REG_VREF 0x18 | |
46 | #define AN877_ADC_REG_ANALOG_INPUT 0x2C | |
47 | ||
48 | /* AN877_ADC_REG_TEST_IO */ | |
49 | #define AN877_ADC_TESTMODE_OFF 0x0 | |
50 | #define AN877_ADC_TESTMODE_MIDSCALE_SHORT 0x1 | |
51 | #define AN877_ADC_TESTMODE_POS_FULLSCALE 0x2 | |
52 | #define AN877_ADC_TESTMODE_NEG_FULLSCALE 0x3 | |
53 | #define AN877_ADC_TESTMODE_ALT_CHECKERBOARD 0x4 | |
54 | #define AN877_ADC_TESTMODE_PN23_SEQ 0x5 | |
55 | #define AN877_ADC_TESTMODE_PN9_SEQ 0x6 | |
56 | #define AN877_ADC_TESTMODE_ONE_ZERO_TOGGLE 0x7 | |
57 | #define AN877_ADC_TESTMODE_USER 0x8 | |
58 | #define AN877_ADC_TESTMODE_BIT_TOGGLE 0x9 | |
59 | #define AN877_ADC_TESTMODE_SYNC 0xA | |
60 | #define AN877_ADC_TESTMODE_ONE_BIT_HIGH 0xB | |
61 | #define AN877_ADC_TESTMODE_MIXED_BIT_FREQUENCY 0xC | |
62 | #define AN877_ADC_TESTMODE_RAMP 0xF | |
63 | ||
64 | /* AN877_ADC_REG_TRANSFER */ | |
65 | #define AN877_ADC_TRANSFER_SYNC 0x1 | |
66 | ||
67 | /* AN877_ADC_REG_OUTPUT_MODE */ | |
68 | #define AN877_ADC_OUTPUT_MODE_OFFSET_BINARY 0x0 | |
69 | #define AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT 0x1 | |
70 | #define AN877_ADC_OUTPUT_MODE_GRAY_CODE 0x2 | |
71 | ||
72 | /* AN877_ADC_REG_OUTPUT_PHASE */ | |
73 | #define AN877_ADC_OUTPUT_EVEN_ODD_MODE_EN 0x20 | |
74 | #define AN877_ADC_INVERT_DCO_CLK 0x80 | |
75 | ||
76 | /* AN877_ADC_REG_OUTPUT_DELAY */ | |
77 | #define AN877_ADC_DCO_DELAY_ENABLE 0x80 | |
78 | ||
eb61343d MH |
79 | /* |
80 | * Analog Devices AD9265 16-Bit, 125/105/80 MSPS ADC | |
81 | */ | |
82 | ||
83 | #define CHIPID_AD9265 0x64 | |
84 | #define AD9265_DEF_OUTPUT_MODE 0x40 | |
85 | #define AD9265_REG_VREF_MASK 0xC0 | |
86 | ||
4606d0f4 MH |
87 | /* |
88 | * Analog Devices AD9434 12-Bit, 370/500 MSPS ADC | |
89 | */ | |
90 | ||
91 | #define CHIPID_AD9434 0x6A | |
92 | #define AD9434_DEF_OUTPUT_MODE 0x00 | |
93 | #define AD9434_REG_VREF_MASK 0xC0 | |
94 | ||
ad679712 MH |
95 | /* |
96 | * Analog Devices AD9467 16-Bit, 200/250 MSPS ADC | |
97 | */ | |
98 | ||
99 | #define CHIPID_AD9467 0x50 | |
100 | #define AD9467_DEF_OUTPUT_MODE 0x08 | |
101 | #define AD9467_REG_VREF_MASK 0x0F | |
102 | ||
103 | enum { | |
eb61343d | 104 | ID_AD9265, |
4606d0f4 | 105 | ID_AD9434, |
ad679712 MH |
106 | ID_AD9467, |
107 | }; | |
108 | ||
337dbb6e AA |
109 | struct ad9467_chip_info { |
110 | struct adi_axi_adc_chip_info axi_adc_info; | |
111 | unsigned int default_output_mode; | |
112 | unsigned int vref_mask; | |
113 | }; | |
114 | ||
115 | #define to_ad9467_chip_info(_info) \ | |
116 | container_of(_info, struct ad9467_chip_info, axi_adc_info) | |
117 | ||
ad679712 MH |
118 | struct ad9467_state { |
119 | struct spi_device *spi; | |
120 | struct clk *clk; | |
121 | unsigned int output_mode; | |
122 | ||
123 | struct gpio_desc *pwrdown_gpio; | |
124 | struct gpio_desc *reset_gpio; | |
125 | }; | |
126 | ||
127 | static int ad9467_spi_read(struct spi_device *spi, unsigned int reg) | |
128 | { | |
129 | unsigned char tbuf[2], rbuf[1]; | |
130 | int ret; | |
131 | ||
132 | tbuf[0] = 0x80 | (reg >> 8); | |
133 | tbuf[1] = reg & 0xFF; | |
134 | ||
135 | ret = spi_write_then_read(spi, | |
136 | tbuf, ARRAY_SIZE(tbuf), | |
137 | rbuf, ARRAY_SIZE(rbuf)); | |
138 | ||
139 | if (ret < 0) | |
140 | return ret; | |
141 | ||
142 | return rbuf[0]; | |
143 | } | |
144 | ||
145 | static int ad9467_spi_write(struct spi_device *spi, unsigned int reg, | |
146 | unsigned int val) | |
147 | { | |
148 | unsigned char buf[3]; | |
149 | ||
150 | buf[0] = reg >> 8; | |
151 | buf[1] = reg & 0xFF; | |
152 | buf[2] = val; | |
153 | ||
154 | return spi_write(spi, buf, ARRAY_SIZE(buf)); | |
155 | } | |
156 | ||
157 | static int ad9467_reg_access(struct adi_axi_adc_conv *conv, unsigned int reg, | |
158 | unsigned int writeval, unsigned int *readval) | |
159 | { | |
160 | struct ad9467_state *st = adi_axi_adc_conv_priv(conv); | |
161 | struct spi_device *spi = st->spi; | |
162 | int ret; | |
163 | ||
164 | if (readval == NULL) { | |
165 | ret = ad9467_spi_write(spi, reg, writeval); | |
166 | ad9467_spi_write(spi, AN877_ADC_REG_TRANSFER, | |
167 | AN877_ADC_TRANSFER_SYNC); | |
168 | return ret; | |
169 | } | |
170 | ||
171 | ret = ad9467_spi_read(spi, reg); | |
172 | if (ret < 0) | |
173 | return ret; | |
174 | *readval = ret; | |
175 | ||
176 | return 0; | |
177 | } | |
178 | ||
eb61343d MH |
179 | static const unsigned int ad9265_scale_table[][2] = { |
180 | {1250, 0x00}, {1500, 0x40}, {1750, 0x80}, {2000, 0xC0}, | |
181 | }; | |
182 | ||
4606d0f4 MH |
183 | static const unsigned int ad9434_scale_table[][2] = { |
184 | {1600, 0x1C}, {1580, 0x1D}, {1550, 0x1E}, {1520, 0x1F}, {1500, 0x00}, | |
185 | {1470, 0x01}, {1440, 0x02}, {1420, 0x03}, {1390, 0x04}, {1360, 0x05}, | |
186 | {1340, 0x06}, {1310, 0x07}, {1280, 0x08}, {1260, 0x09}, {1230, 0x0A}, | |
187 | {1200, 0x0B}, {1180, 0x0C}, | |
188 | }; | |
189 | ||
ad679712 MH |
190 | static const unsigned int ad9467_scale_table[][2] = { |
191 | {2000, 0}, {2100, 6}, {2200, 7}, | |
192 | {2300, 8}, {2400, 9}, {2500, 10}, | |
193 | }; | |
194 | ||
195 | static void __ad9467_get_scale(struct adi_axi_adc_conv *conv, int index, | |
196 | unsigned int *val, unsigned int *val2) | |
197 | { | |
198 | const struct adi_axi_adc_chip_info *info = conv->chip_info; | |
199 | const struct iio_chan_spec *chan = &info->channels[0]; | |
200 | unsigned int tmp; | |
201 | ||
202 | tmp = (info->scale_table[index][0] * 1000000ULL) >> | |
203 | chan->scan_type.realbits; | |
204 | *val = tmp / 1000000; | |
205 | *val2 = tmp % 1000000; | |
206 | } | |
207 | ||
208 | #define AD9467_CHAN(_chan, _si, _bits, _sign) \ | |
209 | { \ | |
210 | .type = IIO_VOLTAGE, \ | |
211 | .indexed = 1, \ | |
212 | .channel = _chan, \ | |
213 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ | |
214 | BIT(IIO_CHAN_INFO_SAMP_FREQ), \ | |
215 | .scan_index = _si, \ | |
216 | .scan_type = { \ | |
217 | .sign = _sign, \ | |
218 | .realbits = _bits, \ | |
219 | .storagebits = 16, \ | |
220 | }, \ | |
221 | } | |
222 | ||
4606d0f4 MH |
223 | static const struct iio_chan_spec ad9434_channels[] = { |
224 | AD9467_CHAN(0, 0, 12, 'S'), | |
225 | }; | |
226 | ||
ad679712 MH |
227 | static const struct iio_chan_spec ad9467_channels[] = { |
228 | AD9467_CHAN(0, 0, 16, 'S'), | |
229 | }; | |
230 | ||
337dbb6e | 231 | static const struct ad9467_chip_info ad9467_chip_tbl[] = { |
eb61343d MH |
232 | [ID_AD9265] = { |
233 | .axi_adc_info = { | |
234 | .id = CHIPID_AD9265, | |
235 | .max_rate = 125000000UL, | |
236 | .scale_table = ad9265_scale_table, | |
237 | .num_scales = ARRAY_SIZE(ad9265_scale_table), | |
238 | .channels = ad9467_channels, | |
239 | .num_channels = ARRAY_SIZE(ad9467_channels), | |
240 | }, | |
241 | .default_output_mode = AD9265_DEF_OUTPUT_MODE, | |
242 | .vref_mask = AD9265_REG_VREF_MASK, | |
243 | }, | |
4606d0f4 MH |
244 | [ID_AD9434] = { |
245 | .axi_adc_info = { | |
246 | .id = CHIPID_AD9434, | |
247 | .max_rate = 500000000UL, | |
248 | .scale_table = ad9434_scale_table, | |
249 | .num_scales = ARRAY_SIZE(ad9434_scale_table), | |
250 | .channels = ad9434_channels, | |
251 | .num_channels = ARRAY_SIZE(ad9434_channels), | |
252 | }, | |
253 | .default_output_mode = AD9434_DEF_OUTPUT_MODE, | |
254 | .vref_mask = AD9434_REG_VREF_MASK, | |
255 | }, | |
ad679712 | 256 | [ID_AD9467] = { |
337dbb6e AA |
257 | .axi_adc_info = { |
258 | .id = CHIPID_AD9467, | |
259 | .max_rate = 250000000UL, | |
260 | .scale_table = ad9467_scale_table, | |
261 | .num_scales = ARRAY_SIZE(ad9467_scale_table), | |
262 | .channels = ad9467_channels, | |
263 | .num_channels = ARRAY_SIZE(ad9467_channels), | |
264 | }, | |
265 | .default_output_mode = AD9467_DEF_OUTPUT_MODE, | |
266 | .vref_mask = AD9467_REG_VREF_MASK, | |
ad679712 MH |
267 | }, |
268 | }; | |
269 | ||
270 | static int ad9467_get_scale(struct adi_axi_adc_conv *conv, int *val, int *val2) | |
271 | { | |
272 | const struct adi_axi_adc_chip_info *info = conv->chip_info; | |
337dbb6e | 273 | const struct ad9467_chip_info *info1 = to_ad9467_chip_info(info); |
ad679712 | 274 | struct ad9467_state *st = adi_axi_adc_conv_priv(conv); |
337dbb6e | 275 | unsigned int i, vref_val; |
ad679712 MH |
276 | |
277 | vref_val = ad9467_spi_read(st->spi, AN877_ADC_REG_VREF); | |
278 | ||
337dbb6e | 279 | vref_val &= info1->vref_mask; |
ad679712 MH |
280 | |
281 | for (i = 0; i < info->num_scales; i++) { | |
282 | if (vref_val == info->scale_table[i][1]) | |
283 | break; | |
284 | } | |
285 | ||
286 | if (i == info->num_scales) | |
287 | return -ERANGE; | |
288 | ||
289 | __ad9467_get_scale(conv, i, val, val2); | |
290 | ||
291 | return IIO_VAL_INT_PLUS_MICRO; | |
292 | } | |
293 | ||
294 | static int ad9467_set_scale(struct adi_axi_adc_conv *conv, int val, int val2) | |
295 | { | |
296 | const struct adi_axi_adc_chip_info *info = conv->chip_info; | |
297 | struct ad9467_state *st = adi_axi_adc_conv_priv(conv); | |
298 | unsigned int scale_val[2]; | |
299 | unsigned int i; | |
300 | ||
301 | if (val != 0) | |
302 | return -EINVAL; | |
303 | ||
304 | for (i = 0; i < info->num_scales; i++) { | |
305 | __ad9467_get_scale(conv, i, &scale_val[0], &scale_val[1]); | |
306 | if (scale_val[0] != val || scale_val[1] != val2) | |
307 | continue; | |
308 | ||
309 | ad9467_spi_write(st->spi, AN877_ADC_REG_VREF, | |
310 | info->scale_table[i][1]); | |
311 | ad9467_spi_write(st->spi, AN877_ADC_REG_TRANSFER, | |
312 | AN877_ADC_TRANSFER_SYNC); | |
313 | return 0; | |
314 | } | |
315 | ||
316 | return -EINVAL; | |
317 | } | |
318 | ||
319 | static int ad9467_read_raw(struct adi_axi_adc_conv *conv, | |
320 | struct iio_chan_spec const *chan, | |
321 | int *val, int *val2, long m) | |
322 | { | |
323 | struct ad9467_state *st = adi_axi_adc_conv_priv(conv); | |
324 | ||
325 | switch (m) { | |
326 | case IIO_CHAN_INFO_SCALE: | |
327 | return ad9467_get_scale(conv, val, val2); | |
328 | case IIO_CHAN_INFO_SAMP_FREQ: | |
329 | *val = clk_get_rate(st->clk); | |
330 | ||
331 | return IIO_VAL_INT; | |
332 | default: | |
333 | return -EINVAL; | |
334 | } | |
335 | } | |
336 | ||
337 | static int ad9467_write_raw(struct adi_axi_adc_conv *conv, | |
338 | struct iio_chan_spec const *chan, | |
339 | int val, int val2, long mask) | |
340 | { | |
341 | const struct adi_axi_adc_chip_info *info = conv->chip_info; | |
342 | struct ad9467_state *st = adi_axi_adc_conv_priv(conv); | |
343 | long r_clk; | |
344 | ||
345 | switch (mask) { | |
346 | case IIO_CHAN_INFO_SCALE: | |
347 | return ad9467_set_scale(conv, val, val2); | |
348 | case IIO_CHAN_INFO_SAMP_FREQ: | |
349 | r_clk = clk_round_rate(st->clk, val); | |
350 | if (r_clk < 0 || r_clk > info->max_rate) { | |
351 | dev_warn(&st->spi->dev, | |
352 | "Error setting ADC sample rate %ld", r_clk); | |
353 | return -EINVAL; | |
354 | } | |
355 | ||
356 | return clk_set_rate(st->clk, r_clk); | |
357 | default: | |
358 | return -EINVAL; | |
359 | } | |
360 | } | |
361 | ||
362 | static int ad9467_outputmode_set(struct spi_device *spi, unsigned int mode) | |
363 | { | |
364 | int ret; | |
365 | ||
366 | ret = ad9467_spi_write(spi, AN877_ADC_REG_OUTPUT_MODE, mode); | |
367 | if (ret < 0) | |
368 | return ret; | |
369 | ||
370 | return ad9467_spi_write(spi, AN877_ADC_REG_TRANSFER, | |
371 | AN877_ADC_TRANSFER_SYNC); | |
372 | } | |
373 | ||
374 | static int ad9467_preenable_setup(struct adi_axi_adc_conv *conv) | |
375 | { | |
376 | struct ad9467_state *st = adi_axi_adc_conv_priv(conv); | |
377 | ||
378 | return ad9467_outputmode_set(st->spi, st->output_mode); | |
379 | } | |
380 | ||
ad679712 MH |
381 | static int ad9467_probe(struct spi_device *spi) |
382 | { | |
337dbb6e | 383 | const struct ad9467_chip_info *info; |
ad679712 MH |
384 | struct adi_axi_adc_conv *conv; |
385 | struct ad9467_state *st; | |
386 | unsigned int id; | |
387 | int ret; | |
388 | ||
389 | info = of_device_get_match_data(&spi->dev); | |
28302652 WY |
390 | if (!info) |
391 | info = (void *)spi_get_device_id(spi)->driver_data; | |
ad679712 MH |
392 | if (!info) |
393 | return -ENODEV; | |
394 | ||
395 | conv = devm_adi_axi_adc_conv_register(&spi->dev, sizeof(*st)); | |
396 | if (IS_ERR(conv)) | |
397 | return PTR_ERR(conv); | |
398 | ||
399 | st = adi_axi_adc_conv_priv(conv); | |
400 | st->spi = spi; | |
401 | ||
cdd07b3a | 402 | st->clk = devm_clk_get_enabled(&spi->dev, "adc-clk"); |
ad679712 MH |
403 | if (IS_ERR(st->clk)) |
404 | return PTR_ERR(st->clk); | |
405 | ||
ad679712 MH |
406 | st->pwrdown_gpio = devm_gpiod_get_optional(&spi->dev, "powerdown", |
407 | GPIOD_OUT_LOW); | |
408 | if (IS_ERR(st->pwrdown_gpio)) | |
409 | return PTR_ERR(st->pwrdown_gpio); | |
410 | ||
411 | st->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", | |
412 | GPIOD_OUT_LOW); | |
413 | if (IS_ERR(st->reset_gpio)) | |
414 | return PTR_ERR(st->reset_gpio); | |
415 | ||
416 | if (st->reset_gpio) { | |
417 | udelay(1); | |
418 | ret = gpiod_direction_output(st->reset_gpio, 1); | |
419 | if (ret) | |
420 | return ret; | |
421 | mdelay(10); | |
422 | } | |
423 | ||
337dbb6e | 424 | conv->chip_info = &info->axi_adc_info; |
ad679712 MH |
425 | |
426 | id = ad9467_spi_read(spi, AN877_ADC_REG_CHIP_ID); | |
427 | if (id != conv->chip_info->id) { | |
6026af6a AA |
428 | dev_err(&spi->dev, "Mismatch CHIP_ID, got 0x%X, expected 0x%X\n", |
429 | id, conv->chip_info->id); | |
ad679712 MH |
430 | return -ENODEV; |
431 | } | |
432 | ||
433 | conv->reg_access = ad9467_reg_access; | |
434 | conv->write_raw = ad9467_write_raw; | |
435 | conv->read_raw = ad9467_read_raw; | |
436 | conv->preenable_setup = ad9467_preenable_setup; | |
437 | ||
337dbb6e AA |
438 | st->output_mode = info->default_output_mode | |
439 | AN877_ADC_OUTPUT_MODE_TWOS_COMPLEMENT; | |
440 | ||
441 | return 0; | |
ad679712 MH |
442 | } |
443 | ||
444 | static const struct of_device_id ad9467_of_match[] = { | |
eb61343d | 445 | { .compatible = "adi,ad9265", .data = &ad9467_chip_tbl[ID_AD9265], }, |
4606d0f4 | 446 | { .compatible = "adi,ad9434", .data = &ad9467_chip_tbl[ID_AD9434], }, |
ad679712 MH |
447 | { .compatible = "adi,ad9467", .data = &ad9467_chip_tbl[ID_AD9467], }, |
448 | {} | |
449 | }; | |
450 | MODULE_DEVICE_TABLE(of, ad9467_of_match); | |
451 | ||
28302652 WY |
452 | static const struct spi_device_id ad9467_ids[] = { |
453 | { "ad9265", (kernel_ulong_t)&ad9467_chip_tbl[ID_AD9265] }, | |
454 | { "ad9434", (kernel_ulong_t)&ad9467_chip_tbl[ID_AD9434] }, | |
455 | { "ad9467", (kernel_ulong_t)&ad9467_chip_tbl[ID_AD9467] }, | |
456 | {} | |
457 | }; | |
458 | MODULE_DEVICE_TABLE(spi, ad9467_ids); | |
459 | ||
ad679712 MH |
460 | static struct spi_driver ad9467_driver = { |
461 | .driver = { | |
462 | .name = "ad9467", | |
463 | .of_match_table = ad9467_of_match, | |
464 | }, | |
465 | .probe = ad9467_probe, | |
28302652 | 466 | .id_table = ad9467_ids, |
ad679712 MH |
467 | }; |
468 | module_spi_driver(ad9467_driver); | |
469 | ||
470 | MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); | |
471 | MODULE_DESCRIPTION("Analog Devices AD9467 ADC driver"); | |
472 | MODULE_LICENSE("GPL v2"); | |
129d7c49 | 473 | MODULE_IMPORT_NS(IIO_ADI_AXI); |