xref: /openbmc/linux/drivers/iio/frequency/admv1014.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
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