1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * ADMV1014 driver |
4 | * |
5 | * Copyright 2022 Analog Devices Inc. |
6 | */ |
7 | |
8 | #include <linux/bitfield.h> |
9 | #include <linux/bits.h> |
10 | #include <linux/clk.h> |
11 | #include <linux/clkdev.h> |
12 | #include <linux/device.h> |
13 | #include <linux/iio/iio.h> |
14 | #include <linux/module.h> |
15 | #include <linux/mod_devicetable.h> |
16 | #include <linux/notifier.h> |
17 | #include <linux/property.h> |
18 | #include <linux/regulator/consumer.h> |
19 | #include <linux/spi/spi.h> |
20 | #include <linux/units.h> |
21 | |
22 | #include <asm/unaligned.h> |
23 | |
24 | /* ADMV1014 Register Map */ |
25 | #define ADMV1014_REG_SPI_CONTROL 0x00 |
26 | #define ADMV1014_REG_ALARM 0x01 |
27 | #define ADMV1014_REG_ALARM_MASKS 0x02 |
28 | #define ADMV1014_REG_ENABLE 0x03 |
29 | #define ADMV1014_REG_QUAD 0x04 |
30 | #define ADMV1014_REG_LO_AMP_PHASE_ADJUST1 0x05 |
31 | #define ADMV1014_REG_MIXER 0x07 |
32 | #define ADMV1014_REG_IF_AMP 0x08 |
33 | #define ADMV1014_REG_IF_AMP_BB_AMP 0x09 |
34 | #define ADMV1014_REG_BB_AMP_AGC 0x0A |
35 | #define ADMV1014_REG_VVA_TEMP_COMP 0x0B |
36 | |
37 | /* ADMV1014_REG_SPI_CONTROL Map */ |
38 | #define ADMV1014_PARITY_EN_MSK BIT(15) |
39 | #define ADMV1014_SPI_SOFT_RESET_MSK BIT(14) |
40 | #define ADMV1014_CHIP_ID_MSK GENMASK(11, 4) |
41 | #define ADMV1014_CHIP_ID 0x9 |
42 | #define ADMV1014_REVISION_ID_MSK GENMASK(3, 0) |
43 | |
44 | /* ADMV1014_REG_ALARM Map */ |
45 | #define ADMV1014_PARITY_ERROR_MSK BIT(15) |
46 | #define ADMV1014_TOO_FEW_ERRORS_MSK BIT(14) |
47 | #define ADMV1014_TOO_MANY_ERRORS_MSK BIT(13) |
48 | #define ADMV1014_ADDRESS_RANGE_ERROR_MSK BIT(12) |
49 | |
50 | /* ADMV1014_REG_ENABLE Map */ |
51 | #define ADMV1014_IBIAS_PD_MSK BIT(14) |
52 | #define ADMV1014_P1DB_COMPENSATION_MSK GENMASK(13, 12) |
53 | #define ADMV1014_IF_AMP_PD_MSK BIT(11) |
54 | #define ADMV1014_QUAD_BG_PD_MSK BIT(9) |
55 | #define ADMV1014_BB_AMP_PD_MSK BIT(8) |
56 | #define ADMV1014_QUAD_IBIAS_PD_MSK BIT(7) |
57 | #define ADMV1014_DET_EN_MSK BIT(6) |
58 | #define ADMV1014_BG_PD_MSK BIT(5) |
59 | |
60 | /* ADMV1014_REG_QUAD Map */ |
61 | #define ADMV1014_QUAD_SE_MODE_MSK GENMASK(9, 6) |
62 | #define ADMV1014_QUAD_FILTERS_MSK GENMASK(3, 0) |
63 | |
64 | /* ADMV1014_REG_LO_AMP_PHASE_ADJUST1 Map */ |
65 | #define ADMV1014_LOAMP_PH_ADJ_I_FINE_MSK GENMASK(15, 9) |
66 | #define ADMV1014_LOAMP_PH_ADJ_Q_FINE_MSK GENMASK(8, 2) |
67 | |
68 | /* ADMV1014_REG_MIXER Map */ |
69 | #define ADMV1014_MIXER_VGATE_MSK GENMASK(15, 9) |
70 | #define ADMV1014_DET_PROG_MSK GENMASK(6, 0) |
71 | |
72 | /* ADMV1014_REG_IF_AMP Map */ |
73 | #define ADMV1014_IF_AMP_COARSE_GAIN_I_MSK GENMASK(11, 8) |
74 | #define ADMV1014_IF_AMP_FINE_GAIN_Q_MSK GENMASK(7, 4) |
75 | #define ADMV1014_IF_AMP_FINE_GAIN_I_MSK GENMASK(3, 0) |
76 | |
77 | /* ADMV1014_REG_IF_AMP_BB_AMP Map */ |
78 | #define ADMV1014_IF_AMP_COARSE_GAIN_Q_MSK GENMASK(15, 12) |
79 | #define ADMV1014_BB_AMP_OFFSET_Q_MSK GENMASK(9, 5) |
80 | #define ADMV1014_BB_AMP_OFFSET_I_MSK GENMASK(4, 0) |
81 | |
82 | /* ADMV1014_REG_BB_AMP_AGC Map */ |
83 | #define ADMV1014_BB_AMP_REF_GEN_MSK GENMASK(6, 3) |
84 | #define ADMV1014_BB_AMP_GAIN_CTRL_MSK GENMASK(2, 1) |
85 | #define ADMV1014_BB_SWITCH_HIGH_LOW_CM_MSK BIT(0) |
86 | |
87 | /* ADMV1014_REG_VVA_TEMP_COMP Map */ |
88 | #define ADMV1014_VVA_TEMP_COMP_MSK GENMASK(15, 0) |
89 | |
90 | /* ADMV1014 Miscellaneous Defines */ |
91 | #define ADMV1014_READ BIT(7) |
92 | #define ADMV1014_REG_ADDR_READ_MSK GENMASK(6, 1) |
93 | #define ADMV1014_REG_ADDR_WRITE_MSK GENMASK(22, 17) |
94 | #define ADMV1014_REG_DATA_MSK GENMASK(16, 1) |
95 | #define ADMV1014_NUM_REGULATORS 9 |
96 | |
97 | enum { |
98 | ADMV1014_IQ_MODE, |
99 | ADMV1014_IF_MODE, |
100 | }; |
101 | |
102 | enum { |
103 | ADMV1014_SE_MODE_POS = 6, |
104 | ADMV1014_SE_MODE_NEG = 9, |
105 | ADMV1014_SE_MODE_DIFF = 12, |
106 | }; |
107 | |
108 | enum { |
109 | ADMV1014_CALIBSCALE_COARSE, |
110 | ADMV1014_CALIBSCALE_FINE, |
111 | }; |
112 | |
113 | static const int detector_table[] = {0, 1, 2, 4, 8, 16, 32, 64}; |
114 | |
115 | static const char * const input_mode_names[] = { "iq" , "if" }; |
116 | |
117 | static const char * const quad_se_mode_names[] = { "se-pos" , "se-neg" , "diff" }; |
118 | |
119 | struct admv1014_state { |
120 | struct spi_device *spi; |
121 | struct clk *clkin; |
122 | struct notifier_block nb; |
123 | /* Protect against concurrent accesses to the device and to data*/ |
124 | struct mutex lock; |
125 | struct regulator_bulk_data regulators[ADMV1014_NUM_REGULATORS]; |
126 | unsigned int input_mode; |
127 | unsigned int quad_se_mode; |
128 | unsigned int p1db_comp; |
129 | bool det_en; |
130 | u8 data[3] __aligned(IIO_DMA_MINALIGN); |
131 | }; |
132 | |
133 | static const int mixer_vgate_table[] = {106, 107, 108, 110, 111, 112, 113, 114, |
134 | 117, 118, 119, 120, 122, 123, 44, 45}; |
135 | |
136 | static int __admv1014_spi_read(struct admv1014_state *st, unsigned int reg, |
137 | unsigned int *val) |
138 | { |
139 | struct spi_transfer t = {}; |
140 | int ret; |
141 | |
142 | st->data[0] = ADMV1014_READ | FIELD_PREP(ADMV1014_REG_ADDR_READ_MSK, reg); |
143 | st->data[1] = 0; |
144 | st->data[2] = 0; |
145 | |
146 | t.rx_buf = &st->data[0]; |
147 | t.tx_buf = &st->data[0]; |
148 | t.len = sizeof(st->data); |
149 | |
150 | ret = spi_sync_transfer(spi: st->spi, xfers: &t, num_xfers: 1); |
151 | if (ret) |
152 | return ret; |
153 | |
154 | *val = FIELD_GET(ADMV1014_REG_DATA_MSK, get_unaligned_be24(&st->data[0])); |
155 | |
156 | return ret; |
157 | } |
158 | |
159 | static int admv1014_spi_read(struct admv1014_state *st, unsigned int reg, |
160 | unsigned int *val) |
161 | { |
162 | int ret; |
163 | |
164 | mutex_lock(&st->lock); |
165 | ret = __admv1014_spi_read(st, reg, val); |
166 | mutex_unlock(lock: &st->lock); |
167 | |
168 | return ret; |
169 | } |
170 | |
171 | static int __admv1014_spi_write(struct admv1014_state *st, |
172 | unsigned int reg, |
173 | unsigned int val) |
174 | { |
175 | put_unaligned_be24(FIELD_PREP(ADMV1014_REG_DATA_MSK, val) | |
176 | FIELD_PREP(ADMV1014_REG_ADDR_WRITE_MSK, reg), p: &st->data[0]); |
177 | |
178 | return spi_write(spi: st->spi, buf: &st->data[0], len: 3); |
179 | } |
180 | |
181 | static int admv1014_spi_write(struct admv1014_state *st, unsigned int reg, |
182 | unsigned int val) |
183 | { |
184 | int ret; |
185 | |
186 | mutex_lock(&st->lock); |
187 | ret = __admv1014_spi_write(st, reg, val); |
188 | mutex_unlock(lock: &st->lock); |
189 | |
190 | return ret; |
191 | } |
192 | |
193 | static int __admv1014_spi_update_bits(struct admv1014_state *st, unsigned int reg, |
194 | unsigned int mask, unsigned int val) |
195 | { |
196 | unsigned int data, temp; |
197 | int ret; |
198 | |
199 | ret = __admv1014_spi_read(st, reg, val: &data); |
200 | if (ret) |
201 | return ret; |
202 | |
203 | temp = (data & ~mask) | (val & mask); |
204 | |
205 | return __admv1014_spi_write(st, reg, val: temp); |
206 | } |
207 | |
208 | static int admv1014_spi_update_bits(struct admv1014_state *st, unsigned int reg, |
209 | unsigned int mask, unsigned int val) |
210 | { |
211 | int ret; |
212 | |
213 | mutex_lock(&st->lock); |
214 | ret = __admv1014_spi_update_bits(st, reg, mask, val); |
215 | mutex_unlock(lock: &st->lock); |
216 | |
217 | return ret; |
218 | } |
219 | |
220 | static int admv1014_update_quad_filters(struct admv1014_state *st) |
221 | { |
222 | unsigned int filt_raw; |
223 | u64 rate = clk_get_rate(clk: st->clkin); |
224 | |
225 | if (rate >= (5400 * HZ_PER_MHZ) && rate <= (7000 * HZ_PER_MHZ)) |
226 | filt_raw = 15; |
227 | else if (rate > (7000 * HZ_PER_MHZ) && rate <= (8000 * HZ_PER_MHZ)) |
228 | filt_raw = 10; |
229 | else if (rate > (8000 * HZ_PER_MHZ) && rate <= (9200 * HZ_PER_MHZ)) |
230 | filt_raw = 5; |
231 | else |
232 | filt_raw = 0; |
233 | |
234 | return __admv1014_spi_update_bits(st, ADMV1014_REG_QUAD, |
235 | ADMV1014_QUAD_FILTERS_MSK, |
236 | FIELD_PREP(ADMV1014_QUAD_FILTERS_MSK, filt_raw)); |
237 | } |
238 | |
239 | static int admv1014_update_vcm_settings(struct admv1014_state *st) |
240 | { |
241 | unsigned int i, vcm_mv, vcm_comp, bb_sw_hl_cm; |
242 | int ret; |
243 | |
244 | vcm_mv = regulator_get_voltage(regulator: st->regulators[0].consumer) / 1000; |
245 | for (i = 0; i < ARRAY_SIZE(mixer_vgate_table); i++) { |
246 | vcm_comp = 1050 + mult_frac(i, 450, 8); |
247 | if (vcm_mv != vcm_comp) |
248 | continue; |
249 | |
250 | ret = __admv1014_spi_update_bits(st, ADMV1014_REG_MIXER, |
251 | ADMV1014_MIXER_VGATE_MSK, |
252 | FIELD_PREP(ADMV1014_MIXER_VGATE_MSK, |
253 | mixer_vgate_table[i])); |
254 | if (ret) |
255 | return ret; |
256 | |
257 | bb_sw_hl_cm = ~(i / 8); |
258 | bb_sw_hl_cm = FIELD_PREP(ADMV1014_BB_SWITCH_HIGH_LOW_CM_MSK, bb_sw_hl_cm); |
259 | |
260 | return __admv1014_spi_update_bits(st, ADMV1014_REG_BB_AMP_AGC, |
261 | ADMV1014_BB_AMP_REF_GEN_MSK | |
262 | ADMV1014_BB_SWITCH_HIGH_LOW_CM_MSK, |
263 | FIELD_PREP(ADMV1014_BB_AMP_REF_GEN_MSK, i) | |
264 | bb_sw_hl_cm); |
265 | } |
266 | |
267 | return -EINVAL; |
268 | } |
269 | |
270 | static int admv1014_read_raw(struct iio_dev *indio_dev, |
271 | struct iio_chan_spec const *chan, |
272 | int *val, int *val2, long info) |
273 | { |
274 | struct admv1014_state *st = iio_priv(indio_dev); |
275 | unsigned int data; |
276 | int ret; |
277 | |
278 | switch (info) { |
279 | case IIO_CHAN_INFO_OFFSET: |
280 | ret = admv1014_spi_read(st, ADMV1014_REG_IF_AMP_BB_AMP, val: &data); |
281 | if (ret) |
282 | return ret; |
283 | |
284 | if (chan->channel2 == IIO_MOD_I) |
285 | *val = FIELD_GET(ADMV1014_BB_AMP_OFFSET_I_MSK, data); |
286 | else |
287 | *val = FIELD_GET(ADMV1014_BB_AMP_OFFSET_Q_MSK, data); |
288 | |
289 | return IIO_VAL_INT; |
290 | case IIO_CHAN_INFO_PHASE: |
291 | ret = admv1014_spi_read(st, ADMV1014_REG_LO_AMP_PHASE_ADJUST1, val: &data); |
292 | if (ret) |
293 | return ret; |
294 | |
295 | if (chan->channel2 == IIO_MOD_I) |
296 | *val = FIELD_GET(ADMV1014_LOAMP_PH_ADJ_I_FINE_MSK, data); |
297 | else |
298 | *val = FIELD_GET(ADMV1014_LOAMP_PH_ADJ_Q_FINE_MSK, data); |
299 | |
300 | return IIO_VAL_INT; |
301 | case IIO_CHAN_INFO_SCALE: |
302 | ret = admv1014_spi_read(st, ADMV1014_REG_MIXER, val: &data); |
303 | if (ret) |
304 | return ret; |
305 | |
306 | *val = FIELD_GET(ADMV1014_DET_PROG_MSK, data); |
307 | return IIO_VAL_INT; |
308 | case IIO_CHAN_INFO_CALIBSCALE: |
309 | ret = admv1014_spi_read(st, ADMV1014_REG_BB_AMP_AGC, val: &data); |
310 | if (ret) |
311 | return ret; |
312 | |
313 | *val = FIELD_GET(ADMV1014_BB_AMP_GAIN_CTRL_MSK, data); |
314 | return IIO_VAL_INT; |
315 | default: |
316 | return -EINVAL; |
317 | } |
318 | } |
319 | |
320 | static int admv1014_write_raw(struct iio_dev *indio_dev, |
321 | struct iio_chan_spec const *chan, |
322 | int val, int val2, long info) |
323 | { |
324 | int data; |
325 | unsigned int msk; |
326 | struct admv1014_state *st = iio_priv(indio_dev); |
327 | |
328 | switch (info) { |
329 | case IIO_CHAN_INFO_OFFSET: |
330 | if (chan->channel2 == IIO_MOD_I) { |
331 | msk = ADMV1014_BB_AMP_OFFSET_I_MSK; |
332 | data = FIELD_PREP(ADMV1014_BB_AMP_OFFSET_I_MSK, val); |
333 | } else { |
334 | msk = ADMV1014_BB_AMP_OFFSET_Q_MSK; |
335 | data = FIELD_PREP(ADMV1014_BB_AMP_OFFSET_Q_MSK, val); |
336 | } |
337 | |
338 | return admv1014_spi_update_bits(st, ADMV1014_REG_IF_AMP_BB_AMP, mask: msk, val: data); |
339 | case IIO_CHAN_INFO_PHASE: |
340 | if (chan->channel2 == IIO_MOD_I) { |
341 | msk = ADMV1014_LOAMP_PH_ADJ_I_FINE_MSK; |
342 | data = FIELD_PREP(ADMV1014_LOAMP_PH_ADJ_I_FINE_MSK, val); |
343 | } else { |
344 | msk = ADMV1014_LOAMP_PH_ADJ_Q_FINE_MSK; |
345 | data = FIELD_PREP(ADMV1014_LOAMP_PH_ADJ_Q_FINE_MSK, val); |
346 | } |
347 | |
348 | return admv1014_spi_update_bits(st, ADMV1014_REG_LO_AMP_PHASE_ADJUST1, mask: msk, val: data); |
349 | case IIO_CHAN_INFO_SCALE: |
350 | return admv1014_spi_update_bits(st, ADMV1014_REG_MIXER, |
351 | ADMV1014_DET_PROG_MSK, |
352 | FIELD_PREP(ADMV1014_DET_PROG_MSK, val)); |
353 | case IIO_CHAN_INFO_CALIBSCALE: |
354 | return admv1014_spi_update_bits(st, ADMV1014_REG_BB_AMP_AGC, |
355 | ADMV1014_BB_AMP_GAIN_CTRL_MSK, |
356 | FIELD_PREP(ADMV1014_BB_AMP_GAIN_CTRL_MSK, val)); |
357 | default: |
358 | return -EINVAL; |
359 | } |
360 | } |
361 | |
362 | static ssize_t admv1014_read(struct iio_dev *indio_dev, |
363 | uintptr_t private, |
364 | const struct iio_chan_spec *chan, |
365 | char *buf) |
366 | { |
367 | struct admv1014_state *st = iio_priv(indio_dev); |
368 | unsigned int data; |
369 | int ret; |
370 | |
371 | switch (private) { |
372 | case ADMV1014_CALIBSCALE_COARSE: |
373 | if (chan->channel2 == IIO_MOD_I) { |
374 | ret = admv1014_spi_read(st, ADMV1014_REG_IF_AMP, val: &data); |
375 | if (ret) |
376 | return ret; |
377 | |
378 | data = FIELD_GET(ADMV1014_IF_AMP_COARSE_GAIN_I_MSK, data); |
379 | } else { |
380 | ret = admv1014_spi_read(st, ADMV1014_REG_IF_AMP_BB_AMP, val: &data); |
381 | if (ret) |
382 | return ret; |
383 | |
384 | data = FIELD_GET(ADMV1014_IF_AMP_COARSE_GAIN_Q_MSK, data); |
385 | } |
386 | break; |
387 | case ADMV1014_CALIBSCALE_FINE: |
388 | ret = admv1014_spi_read(st, ADMV1014_REG_IF_AMP, val: &data); |
389 | if (ret) |
390 | return ret; |
391 | |
392 | if (chan->channel2 == IIO_MOD_I) |
393 | data = FIELD_GET(ADMV1014_IF_AMP_FINE_GAIN_I_MSK, data); |
394 | else |
395 | data = FIELD_GET(ADMV1014_IF_AMP_FINE_GAIN_Q_MSK, data); |
396 | break; |
397 | default: |
398 | return -EINVAL; |
399 | } |
400 | |
401 | return sysfs_emit(buf, fmt: "%u\n" , data); |
402 | } |
403 | |
404 | static ssize_t admv1014_write(struct iio_dev *indio_dev, |
405 | uintptr_t private, |
406 | const struct iio_chan_spec *chan, |
407 | const char *buf, size_t len) |
408 | { |
409 | struct admv1014_state *st = iio_priv(indio_dev); |
410 | unsigned int data, addr, msk; |
411 | int ret; |
412 | |
413 | ret = kstrtouint(s: buf, base: 10, res: &data); |
414 | if (ret) |
415 | return ret; |
416 | |
417 | switch (private) { |
418 | case ADMV1014_CALIBSCALE_COARSE: |
419 | if (chan->channel2 == IIO_MOD_I) { |
420 | addr = ADMV1014_REG_IF_AMP; |
421 | msk = ADMV1014_IF_AMP_COARSE_GAIN_I_MSK; |
422 | data = FIELD_PREP(ADMV1014_IF_AMP_COARSE_GAIN_I_MSK, data); |
423 | } else { |
424 | addr = ADMV1014_REG_IF_AMP_BB_AMP; |
425 | msk = ADMV1014_IF_AMP_COARSE_GAIN_Q_MSK; |
426 | data = FIELD_PREP(ADMV1014_IF_AMP_COARSE_GAIN_Q_MSK, data); |
427 | } |
428 | break; |
429 | case ADMV1014_CALIBSCALE_FINE: |
430 | addr = ADMV1014_REG_IF_AMP; |
431 | |
432 | if (chan->channel2 == IIO_MOD_I) { |
433 | msk = ADMV1014_IF_AMP_FINE_GAIN_I_MSK; |
434 | data = FIELD_PREP(ADMV1014_IF_AMP_FINE_GAIN_I_MSK, data); |
435 | } else { |
436 | msk = ADMV1014_IF_AMP_FINE_GAIN_Q_MSK; |
437 | data = FIELD_PREP(ADMV1014_IF_AMP_FINE_GAIN_Q_MSK, data); |
438 | } |
439 | break; |
440 | default: |
441 | return -EINVAL; |
442 | } |
443 | |
444 | ret = admv1014_spi_update_bits(st, reg: addr, mask: msk, val: data); |
445 | |
446 | return ret ? ret : len; |
447 | } |
448 | |
449 | static int admv1014_read_avail(struct iio_dev *indio_dev, |
450 | struct iio_chan_spec const *chan, |
451 | const int **vals, int *type, int *length, |
452 | long info) |
453 | { |
454 | switch (info) { |
455 | case IIO_CHAN_INFO_SCALE: |
456 | *vals = detector_table; |
457 | *type = IIO_VAL_INT; |
458 | *length = ARRAY_SIZE(detector_table); |
459 | |
460 | return IIO_AVAIL_LIST; |
461 | default: |
462 | return -EINVAL; |
463 | } |
464 | } |
465 | |
466 | static int admv1014_reg_access(struct iio_dev *indio_dev, |
467 | unsigned int reg, |
468 | unsigned int write_val, |
469 | unsigned int *read_val) |
470 | { |
471 | struct admv1014_state *st = iio_priv(indio_dev); |
472 | |
473 | if (read_val) |
474 | return admv1014_spi_read(st, reg, val: read_val); |
475 | else |
476 | return admv1014_spi_write(st, reg, val: write_val); |
477 | } |
478 | |
479 | static const struct iio_info admv1014_info = { |
480 | .read_raw = admv1014_read_raw, |
481 | .write_raw = admv1014_write_raw, |
482 | .read_avail = &admv1014_read_avail, |
483 | .debugfs_reg_access = &admv1014_reg_access, |
484 | }; |
485 | |
486 | static const char * const admv1014_reg_name[] = { |
487 | "vcm" , "vcc-if-bb" , "vcc-vga" , "vcc-vva" , "vcc-lna-3p3" , |
488 | "vcc-lna-1p5" , "vcc-bg" , "vcc-quad" , "vcc-mixer" |
489 | }; |
490 | |
491 | static int admv1014_freq_change(struct notifier_block *nb, unsigned long action, void *data) |
492 | { |
493 | struct admv1014_state *st = container_of(nb, struct admv1014_state, nb); |
494 | int ret; |
495 | |
496 | if (action == POST_RATE_CHANGE) { |
497 | mutex_lock(&st->lock); |
498 | ret = notifier_from_errno(err: admv1014_update_quad_filters(st)); |
499 | mutex_unlock(lock: &st->lock); |
500 | return ret; |
501 | } |
502 | |
503 | return NOTIFY_OK; |
504 | } |
505 | |
506 | #define _ADMV1014_EXT_INFO(_name, _shared, _ident) { \ |
507 | .name = _name, \ |
508 | .read = admv1014_read, \ |
509 | .write = admv1014_write, \ |
510 | .private = _ident, \ |
511 | .shared = _shared, \ |
512 | } |
513 | |
514 | static const struct iio_chan_spec_ext_info admv1014_ext_info[] = { |
515 | _ADMV1014_EXT_INFO("calibscale_coarse" , IIO_SEPARATE, ADMV1014_CALIBSCALE_COARSE), |
516 | _ADMV1014_EXT_INFO("calibscale_fine" , IIO_SEPARATE, ADMV1014_CALIBSCALE_FINE), |
517 | { } |
518 | }; |
519 | |
520 | #define ADMV1014_CHAN_IQ(_channel, rf_comp) { \ |
521 | .type = IIO_ALTVOLTAGE, \ |
522 | .modified = 1, \ |
523 | .output = 0, \ |
524 | .indexed = 1, \ |
525 | .channel2 = IIO_MOD_##rf_comp, \ |
526 | .channel = _channel, \ |
527 | .info_mask_separate = BIT(IIO_CHAN_INFO_PHASE) | \ |
528 | BIT(IIO_CHAN_INFO_OFFSET), \ |
529 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBSCALE), \ |
530 | } |
531 | |
532 | #define ADMV1014_CHAN_IF(_channel, rf_comp) { \ |
533 | .type = IIO_ALTVOLTAGE, \ |
534 | .modified = 1, \ |
535 | .output = 0, \ |
536 | .indexed = 1, \ |
537 | .channel2 = IIO_MOD_##rf_comp, \ |
538 | .channel = _channel, \ |
539 | .info_mask_separate = BIT(IIO_CHAN_INFO_PHASE) | \ |
540 | BIT(IIO_CHAN_INFO_OFFSET), \ |
541 | } |
542 | |
543 | #define ADMV1014_CHAN_POWER(_channel) { \ |
544 | .type = IIO_POWER, \ |
545 | .output = 0, \ |
546 | .indexed = 1, \ |
547 | .channel = _channel, \ |
548 | .info_mask_separate = BIT(IIO_CHAN_INFO_SCALE), \ |
549 | .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE), \ |
550 | } |
551 | |
552 | #define ADMV1014_CHAN_CALIBSCALE(_channel, rf_comp, _admv1014_ext_info) { \ |
553 | .type = IIO_ALTVOLTAGE, \ |
554 | .modified = 1, \ |
555 | .output = 0, \ |
556 | .indexed = 1, \ |
557 | .channel2 = IIO_MOD_##rf_comp, \ |
558 | .channel = _channel, \ |
559 | .ext_info = _admv1014_ext_info, \ |
560 | } |
561 | |
562 | static const struct iio_chan_spec admv1014_channels_iq[] = { |
563 | ADMV1014_CHAN_IQ(0, I), |
564 | ADMV1014_CHAN_IQ(0, Q), |
565 | ADMV1014_CHAN_POWER(0), |
566 | }; |
567 | |
568 | static const struct iio_chan_spec admv1014_channels_if[] = { |
569 | ADMV1014_CHAN_IF(0, I), |
570 | ADMV1014_CHAN_IF(0, Q), |
571 | ADMV1014_CHAN_CALIBSCALE(0, I, admv1014_ext_info), |
572 | ADMV1014_CHAN_CALIBSCALE(0, Q, admv1014_ext_info), |
573 | ADMV1014_CHAN_POWER(0), |
574 | }; |
575 | |
576 | static void admv1014_clk_disable(void *data) |
577 | { |
578 | clk_disable_unprepare(clk: data); |
579 | } |
580 | |
581 | static void admv1014_reg_disable(void *data) |
582 | { |
583 | regulator_bulk_disable(ADMV1014_NUM_REGULATORS, consumers: data); |
584 | } |
585 | |
586 | static void admv1014_powerdown(void *data) |
587 | { |
588 | unsigned int enable_reg, enable_reg_msk; |
589 | |
590 | /* Disable all components in the Enable Register */ |
591 | enable_reg_msk = ADMV1014_IBIAS_PD_MSK | |
592 | ADMV1014_IF_AMP_PD_MSK | |
593 | ADMV1014_QUAD_BG_PD_MSK | |
594 | ADMV1014_BB_AMP_PD_MSK | |
595 | ADMV1014_QUAD_IBIAS_PD_MSK | |
596 | ADMV1014_BG_PD_MSK; |
597 | |
598 | enable_reg = FIELD_PREP(ADMV1014_IBIAS_PD_MSK, 1) | |
599 | FIELD_PREP(ADMV1014_IF_AMP_PD_MSK, 1) | |
600 | FIELD_PREP(ADMV1014_QUAD_BG_PD_MSK, 1) | |
601 | FIELD_PREP(ADMV1014_BB_AMP_PD_MSK, 1) | |
602 | FIELD_PREP(ADMV1014_QUAD_IBIAS_PD_MSK, 1) | |
603 | FIELD_PREP(ADMV1014_BG_PD_MSK, 1); |
604 | |
605 | admv1014_spi_update_bits(st: data, ADMV1014_REG_ENABLE, |
606 | mask: enable_reg_msk, val: enable_reg); |
607 | } |
608 | |
609 | static int admv1014_init(struct admv1014_state *st) |
610 | { |
611 | unsigned int chip_id, enable_reg, enable_reg_msk; |
612 | struct spi_device *spi = st->spi; |
613 | int ret; |
614 | |
615 | ret = regulator_bulk_enable(ADMV1014_NUM_REGULATORS, consumers: st->regulators); |
616 | if (ret) { |
617 | dev_err(&spi->dev, "Failed to enable regulators" ); |
618 | return ret; |
619 | } |
620 | |
621 | ret = devm_add_action_or_reset(&spi->dev, admv1014_reg_disable, st->regulators); |
622 | if (ret) |
623 | return ret; |
624 | |
625 | ret = clk_prepare_enable(clk: st->clkin); |
626 | if (ret) |
627 | return ret; |
628 | |
629 | ret = devm_add_action_or_reset(&spi->dev, admv1014_clk_disable, st->clkin); |
630 | if (ret) |
631 | return ret; |
632 | |
633 | st->nb.notifier_call = admv1014_freq_change; |
634 | ret = devm_clk_notifier_register(dev: &spi->dev, clk: st->clkin, nb: &st->nb); |
635 | if (ret) |
636 | return ret; |
637 | |
638 | ret = devm_add_action_or_reset(&spi->dev, admv1014_powerdown, st); |
639 | if (ret) |
640 | return ret; |
641 | |
642 | /* Perform a software reset */ |
643 | ret = __admv1014_spi_update_bits(st, ADMV1014_REG_SPI_CONTROL, |
644 | ADMV1014_SPI_SOFT_RESET_MSK, |
645 | FIELD_PREP(ADMV1014_SPI_SOFT_RESET_MSK, 1)); |
646 | if (ret) { |
647 | dev_err(&spi->dev, "ADMV1014 SPI software reset failed.\n" ); |
648 | return ret; |
649 | } |
650 | |
651 | ret = __admv1014_spi_update_bits(st, ADMV1014_REG_SPI_CONTROL, |
652 | ADMV1014_SPI_SOFT_RESET_MSK, |
653 | FIELD_PREP(ADMV1014_SPI_SOFT_RESET_MSK, 0)); |
654 | if (ret) { |
655 | dev_err(&spi->dev, "ADMV1014 SPI software reset disable failed.\n" ); |
656 | return ret; |
657 | } |
658 | |
659 | ret = __admv1014_spi_write(st, ADMV1014_REG_VVA_TEMP_COMP, val: 0x727C); |
660 | if (ret) { |
661 | dev_err(&spi->dev, "Writing default Temperature Compensation value failed.\n" ); |
662 | return ret; |
663 | } |
664 | |
665 | ret = __admv1014_spi_read(st, ADMV1014_REG_SPI_CONTROL, val: &chip_id); |
666 | if (ret) |
667 | return ret; |
668 | |
669 | chip_id = FIELD_GET(ADMV1014_CHIP_ID_MSK, chip_id); |
670 | if (chip_id != ADMV1014_CHIP_ID) { |
671 | dev_err(&spi->dev, "Invalid Chip ID.\n" ); |
672 | return -EINVAL; |
673 | } |
674 | |
675 | ret = __admv1014_spi_update_bits(st, ADMV1014_REG_QUAD, |
676 | ADMV1014_QUAD_SE_MODE_MSK, |
677 | FIELD_PREP(ADMV1014_QUAD_SE_MODE_MSK, |
678 | st->quad_se_mode)); |
679 | if (ret) { |
680 | dev_err(&spi->dev, "Writing Quad SE Mode failed.\n" ); |
681 | return ret; |
682 | } |
683 | |
684 | ret = admv1014_update_quad_filters(st); |
685 | if (ret) { |
686 | dev_err(&spi->dev, "Update Quad Filters failed.\n" ); |
687 | return ret; |
688 | } |
689 | |
690 | ret = admv1014_update_vcm_settings(st); |
691 | if (ret) { |
692 | dev_err(&spi->dev, "Update VCM Settings failed.\n" ); |
693 | return ret; |
694 | } |
695 | |
696 | enable_reg_msk = ADMV1014_P1DB_COMPENSATION_MSK | |
697 | ADMV1014_IF_AMP_PD_MSK | |
698 | ADMV1014_BB_AMP_PD_MSK | |
699 | ADMV1014_DET_EN_MSK; |
700 | |
701 | enable_reg = FIELD_PREP(ADMV1014_P1DB_COMPENSATION_MSK, st->p1db_comp ? 3 : 0) | |
702 | FIELD_PREP(ADMV1014_IF_AMP_PD_MSK, |
703 | (st->input_mode == ADMV1014_IF_MODE) ? 0 : 1) | |
704 | FIELD_PREP(ADMV1014_BB_AMP_PD_MSK, |
705 | (st->input_mode == ADMV1014_IF_MODE) ? 1 : 0) | |
706 | FIELD_PREP(ADMV1014_DET_EN_MSK, st->det_en); |
707 | |
708 | return __admv1014_spi_update_bits(st, ADMV1014_REG_ENABLE, mask: enable_reg_msk, val: enable_reg); |
709 | } |
710 | |
711 | static int admv1014_properties_parse(struct admv1014_state *st) |
712 | { |
713 | unsigned int i; |
714 | struct spi_device *spi = st->spi; |
715 | int ret; |
716 | |
717 | st->det_en = device_property_read_bool(dev: &spi->dev, propname: "adi,detector-enable" ); |
718 | |
719 | st->p1db_comp = device_property_read_bool(dev: &spi->dev, propname: "adi,p1db-compensation-enable" ); |
720 | |
721 | ret = device_property_match_property_string(dev: &spi->dev, propname: "adi,input-mode" , |
722 | array: input_mode_names, |
723 | ARRAY_SIZE(input_mode_names)); |
724 | if (ret >= 0) |
725 | st->input_mode = ret; |
726 | else |
727 | st->input_mode = ADMV1014_IQ_MODE; |
728 | |
729 | ret = device_property_match_property_string(dev: &spi->dev, propname: "adi,quad-se-mode" , |
730 | array: quad_se_mode_names, |
731 | ARRAY_SIZE(quad_se_mode_names)); |
732 | if (ret >= 0) |
733 | st->quad_se_mode = ADMV1014_SE_MODE_POS + (ret * 3); |
734 | else |
735 | st->quad_se_mode = ADMV1014_SE_MODE_POS; |
736 | |
737 | for (i = 0; i < ADMV1014_NUM_REGULATORS; ++i) |
738 | st->regulators[i].supply = admv1014_reg_name[i]; |
739 | |
740 | ret = devm_regulator_bulk_get(dev: &st->spi->dev, ADMV1014_NUM_REGULATORS, |
741 | consumers: st->regulators); |
742 | if (ret) { |
743 | dev_err(&spi->dev, "Failed to request regulators" ); |
744 | return ret; |
745 | } |
746 | |
747 | st->clkin = devm_clk_get(dev: &spi->dev, id: "lo_in" ); |
748 | if (IS_ERR(ptr: st->clkin)) |
749 | return dev_err_probe(dev: &spi->dev, err: PTR_ERR(ptr: st->clkin), |
750 | fmt: "failed to get the LO input clock\n" ); |
751 | |
752 | return 0; |
753 | } |
754 | |
755 | static int admv1014_probe(struct spi_device *spi) |
756 | { |
757 | struct iio_dev *indio_dev; |
758 | struct admv1014_state *st; |
759 | int ret; |
760 | |
761 | indio_dev = devm_iio_device_alloc(parent: &spi->dev, sizeof_priv: sizeof(*st)); |
762 | if (!indio_dev) |
763 | return -ENOMEM; |
764 | |
765 | st = iio_priv(indio_dev); |
766 | |
767 | ret = admv1014_properties_parse(st); |
768 | if (ret) |
769 | return ret; |
770 | |
771 | indio_dev->info = &admv1014_info; |
772 | indio_dev->name = "admv1014" ; |
773 | |
774 | if (st->input_mode == ADMV1014_IQ_MODE) { |
775 | indio_dev->channels = admv1014_channels_iq; |
776 | indio_dev->num_channels = ARRAY_SIZE(admv1014_channels_iq); |
777 | } else { |
778 | indio_dev->channels = admv1014_channels_if; |
779 | indio_dev->num_channels = ARRAY_SIZE(admv1014_channels_if); |
780 | } |
781 | |
782 | st->spi = spi; |
783 | |
784 | mutex_init(&st->lock); |
785 | |
786 | ret = admv1014_init(st); |
787 | if (ret) |
788 | return ret; |
789 | |
790 | return devm_iio_device_register(&spi->dev, indio_dev); |
791 | } |
792 | |
793 | static const struct spi_device_id admv1014_id[] = { |
794 | { "admv1014" , 0 }, |
795 | {} |
796 | }; |
797 | MODULE_DEVICE_TABLE(spi, admv1014_id); |
798 | |
799 | static const struct of_device_id admv1014_of_match[] = { |
800 | { .compatible = "adi,admv1014" }, |
801 | {} |
802 | }; |
803 | MODULE_DEVICE_TABLE(of, admv1014_of_match); |
804 | |
805 | static struct spi_driver admv1014_driver = { |
806 | .driver = { |
807 | .name = "admv1014" , |
808 | .of_match_table = admv1014_of_match, |
809 | }, |
810 | .probe = admv1014_probe, |
811 | .id_table = admv1014_id, |
812 | }; |
813 | module_spi_driver(admv1014_driver); |
814 | |
815 | MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com" ); |
816 | MODULE_DESCRIPTION("Analog Devices ADMV1014" ); |
817 | MODULE_LICENSE("GPL v2" ); |
818 | |