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