Linux 6.12-rc1
[linux-block.git] / drivers / iio / amplifiers / ad8366.c
CommitLineData
38ffa3a3 1// SPDX-License-Identifier: GPL-2.0
e71d42e0 2/*
cee211f4
PC
3 * AD8366 and similar Gain Amplifiers
4 * This driver supports the following gain amplifiers:
5 * AD8366 Dual-Digital Variable Gain Amplifier (VGA)
6 * ADA4961 BiCMOS RF Digital Gain Amplifier (DGA)
075da9cd 7 * ADL5240 Digitally controlled variable gain amplifier (VGA)
247d3b63 8 * HMC792A 0.25 dB LSB GaAs MMIC 6-Bit Digital Attenuator
cc74a38d 9 * HMC1119 0.25 dB LSB, 7-Bit, Silicon Digital Attenuator
e71d42e0 10 *
38ffa3a3 11 * Copyright 2012-2019 Analog Devices Inc.
e71d42e0
MH
12 */
13
14#include <linux/device.h>
15#include <linux/kernel.h>
16#include <linux/slab.h>
17#include <linux/sysfs.h>
18#include <linux/spi/spi.h>
19#include <linux/regulator/consumer.h>
cee211f4 20#include <linux/gpio/consumer.h>
e71d42e0
MH
21#include <linux/err.h>
22#include <linux/module.h>
23#include <linux/bitrev.h>
24
25#include <linux/iio/iio.h>
26#include <linux/iio/sysfs.h>
27
11ab555a
AA
28enum ad8366_type {
29 ID_AD8366,
cee211f4 30 ID_ADA4961,
075da9cd 31 ID_ADL5240,
247d3b63 32 ID_HMC792,
cc74a38d 33 ID_HMC1119,
11ab555a
AA
34};
35
36struct ad8366_info {
37 int gain_min;
38 int gain_max;
39};
40
e71d42e0
MH
41struct ad8366_state {
42 struct spi_device *spi;
43 struct regulator *reg;
dbcf6b5d 44 struct mutex lock; /* protect sensor state */
cee211f4 45 struct gpio_desc *reset_gpio;
e71d42e0 46 unsigned char ch[2];
11ab555a
AA
47 enum ad8366_type type;
48 struct ad8366_info *info;
e71d42e0 49 /*
026bffa4 50 * DMA (thus cache coherency maintenance) may require the
e71d42e0
MH
51 * transfer buffers to live in their own cache lines.
52 */
026bffa4 53 unsigned char data[2] __aligned(IIO_DMA_MINALIGN);
e71d42e0
MH
54};
55
11ab555a
AA
56static struct ad8366_info ad8366_infos[] = {
57 [ID_AD8366] = {
58 .gain_min = 4500,
59 .gain_max = 20500,
60 },
cee211f4
PC
61 [ID_ADA4961] = {
62 .gain_min = -6000,
63 .gain_max = 15000,
64 },
075da9cd
AA
65 [ID_ADL5240] = {
66 .gain_min = -11500,
67 .gain_max = 20000,
68 },
247d3b63
KSP
69 [ID_HMC792] = {
70 .gain_min = -15750,
71 .gain_max = 0,
72 },
cc74a38d
SC
73 [ID_HMC1119] = {
74 .gain_min = -31750,
75 .gain_max = 0,
76 },
11ab555a
AA
77};
78
e71d42e0 79static int ad8366_write(struct iio_dev *indio_dev,
ff6f4629 80 unsigned char ch_a, unsigned char ch_b)
e71d42e0
MH
81{
82 struct ad8366_state *st = iio_priv(indio_dev);
83 int ret;
84
11ab555a
AA
85 switch (st->type) {
86 case ID_AD8366:
87 ch_a = bitrev8(ch_a & 0x3F);
88 ch_b = bitrev8(ch_b & 0x3F);
e71d42e0 89
11ab555a
AA
90 st->data[0] = ch_b >> 4;
91 st->data[1] = (ch_b << 4) | (ch_a >> 2);
92 break;
cee211f4
PC
93 case ID_ADA4961:
94 st->data[0] = ch_a & 0x1F;
95 break;
075da9cd
AA
96 case ID_ADL5240:
97 st->data[0] = (ch_a & 0x3F);
98 break;
247d3b63 99 case ID_HMC792:
cc74a38d
SC
100 case ID_HMC1119:
101 st->data[0] = ch_a;
102 break;
11ab555a 103 }
e71d42e0 104
11ab555a 105 ret = spi_write(st->spi, st->data, indio_dev->num_channels);
e71d42e0
MH
106 if (ret < 0)
107 dev_err(&indio_dev->dev, "write failed (%d)", ret);
108
109 return ret;
110}
111
112static int ad8366_read_raw(struct iio_dev *indio_dev,
113 struct iio_chan_spec const *chan,
114 int *val,
115 int *val2,
116 long m)
117{
118 struct ad8366_state *st = iio_priv(indio_dev);
119 int ret;
11ab555a 120 int code, gain = 0;
e71d42e0 121
dbcf6b5d 122 mutex_lock(&st->lock);
e71d42e0
MH
123 switch (m) {
124 case IIO_CHAN_INFO_HARDWAREGAIN:
125 code = st->ch[chan->channel];
126
11ab555a
AA
127 switch (st->type) {
128 case ID_AD8366:
129 gain = code * 253 + 4500;
130 break;
cee211f4
PC
131 case ID_ADA4961:
132 gain = 15000 - code * 1000;
133 break;
075da9cd
AA
134 case ID_ADL5240:
135 gain = 20000 - 31500 + code * 500;
136 break;
247d3b63
KSP
137 case ID_HMC792:
138 gain = -1 * code * 500;
139 break;
cc74a38d
SC
140 case ID_HMC1119:
141 gain = -1 * code * 250;
142 break;
11ab555a
AA
143 }
144
e71d42e0 145 /* Values in dB */
11ab555a
AA
146 *val = gain / 1000;
147 *val2 = (gain % 1000) * 1000;
e71d42e0
MH
148
149 ret = IIO_VAL_INT_PLUS_MICRO_DB;
150 break;
151 default:
152 ret = -EINVAL;
153 }
dbcf6b5d 154 mutex_unlock(&st->lock);
e71d42e0
MH
155
156 return ret;
157};
158
159static int ad8366_write_raw(struct iio_dev *indio_dev,
160 struct iio_chan_spec const *chan,
161 int val,
162 int val2,
163 long mask)
164{
165 struct ad8366_state *st = iio_priv(indio_dev);
11ab555a
AA
166 struct ad8366_info *inf = st->info;
167 int code = 0, gain;
e71d42e0
MH
168 int ret;
169
e71d42e0 170 /* Values in dB */
11ab555a
AA
171 if (val < 0)
172 gain = (val * 1000) - (val2 / 1000);
173 else
174 gain = (val * 1000) + (val2 / 1000);
e71d42e0 175
11ab555a 176 if (gain > inf->gain_max || gain < inf->gain_min)
e71d42e0
MH
177 return -EINVAL;
178
11ab555a
AA
179 switch (st->type) {
180 case ID_AD8366:
181 code = (gain - 4500) / 253;
182 break;
cee211f4
PC
183 case ID_ADA4961:
184 code = (15000 - gain) / 1000;
185 break;
075da9cd
AA
186 case ID_ADL5240:
187 code = ((gain - 500 - 20000) / 500) & 0x3F;
188 break;
247d3b63
KSP
189 case ID_HMC792:
190 code = (abs(gain) / 500) & 0x3F;
191 break;
cc74a38d
SC
192 case ID_HMC1119:
193 code = (abs(gain) / 250) & 0x7F;
194 break;
11ab555a 195 }
e71d42e0 196
dbcf6b5d 197 mutex_lock(&st->lock);
e71d42e0
MH
198 switch (mask) {
199 case IIO_CHAN_INFO_HARDWAREGAIN:
200 st->ch[chan->channel] = code;
201 ret = ad8366_write(indio_dev, st->ch[0], st->ch[1]);
202 break;
203 default:
204 ret = -EINVAL;
205 }
dbcf6b5d 206 mutex_unlock(&st->lock);
e71d42e0
MH
207
208 return ret;
209}
210
0cc97f2e
BB
211static int ad8366_write_raw_get_fmt(struct iio_dev *indio_dev,
212 struct iio_chan_spec const *chan,
213 long mask)
214{
215 switch (mask) {
216 case IIO_CHAN_INFO_HARDWAREGAIN:
217 return IIO_VAL_INT_PLUS_MICRO_DB;
218 default:
219 return -EINVAL;
220 }
221}
222
e71d42e0
MH
223static const struct iio_info ad8366_info = {
224 .read_raw = &ad8366_read_raw,
225 .write_raw = &ad8366_write_raw,
0cc97f2e 226 .write_raw_get_fmt = &ad8366_write_raw_get_fmt,
e71d42e0
MH
227};
228
229#define AD8366_CHAN(_channel) { \
230 .type = IIO_VOLTAGE, \
231 .output = 1, \
232 .indexed = 1, \
233 .channel = _channel, \
b34ec6f3 234 .info_mask_separate = BIT(IIO_CHAN_INFO_HARDWAREGAIN),\
e71d42e0
MH
235}
236
237static const struct iio_chan_spec ad8366_channels[] = {
238 AD8366_CHAN(0),
239 AD8366_CHAN(1),
240};
241
cee211f4
PC
242static const struct iio_chan_spec ada4961_channels[] = {
243 AD8366_CHAN(0),
244};
245
fc52692c 246static int ad8366_probe(struct spi_device *spi)
e71d42e0
MH
247{
248 struct iio_dev *indio_dev;
249 struct ad8366_state *st;
250 int ret;
251
36db8c72 252 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
e71d42e0
MH
253 if (indio_dev == NULL)
254 return -ENOMEM;
255
256 st = iio_priv(indio_dev);
257
36db8c72 258 st->reg = devm_regulator_get(&spi->dev, "vcc");
e71d42e0
MH
259 if (!IS_ERR(st->reg)) {
260 ret = regulator_enable(st->reg);
261 if (ret)
36db8c72 262 return ret;
e71d42e0
MH
263 }
264
265 spi_set_drvdata(spi, indio_dev);
dbcf6b5d 266 mutex_init(&st->lock);
e71d42e0 267 st->spi = spi;
11ab555a
AA
268 st->type = spi_get_device_id(spi)->driver_data;
269
270 switch (st->type) {
271 case ID_AD8366:
272 indio_dev->channels = ad8366_channels;
273 indio_dev->num_channels = ARRAY_SIZE(ad8366_channels);
274 break;
cee211f4 275 case ID_ADA4961:
075da9cd 276 case ID_ADL5240:
247d3b63 277 case ID_HMC792:
cc74a38d 278 case ID_HMC1119:
9ca39411
CY
279 st->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", GPIOD_OUT_HIGH);
280 if (IS_ERR(st->reset_gpio)) {
281 ret = PTR_ERR(st->reset_gpio);
282 goto error_disable_reg;
283 }
cee211f4
PC
284 indio_dev->channels = ada4961_channels;
285 indio_dev->num_channels = ARRAY_SIZE(ada4961_channels);
286 break;
11ab555a
AA
287 default:
288 dev_err(&spi->dev, "Invalid device ID\n");
289 ret = -EINVAL;
290 goto error_disable_reg;
291 }
e71d42e0 292
11ab555a 293 st->info = &ad8366_infos[st->type];
e71d42e0
MH
294 indio_dev->name = spi_get_device_id(spi)->name;
295 indio_dev->info = &ad8366_info;
296 indio_dev->modes = INDIO_DIRECT_MODE;
e71d42e0 297
8b5e7c33 298 ret = ad8366_write(indio_dev, 0, 0);
2636d005
AA
299 if (ret < 0)
300 goto error_disable_reg;
301
e71d42e0
MH
302 ret = iio_device_register(indio_dev);
303 if (ret)
304 goto error_disable_reg;
305
e71d42e0
MH
306 return 0;
307
308error_disable_reg:
309 if (!IS_ERR(st->reg))
310 regulator_disable(st->reg);
e71d42e0
MH
311
312 return ret;
313}
314
a0386bba 315static void ad8366_remove(struct spi_device *spi)
e71d42e0
MH
316{
317 struct iio_dev *indio_dev = spi_get_drvdata(spi);
318 struct ad8366_state *st = iio_priv(indio_dev);
319 struct regulator *reg = st->reg;
320
321 iio_device_unregister(indio_dev);
322
d3789c3e 323 if (!IS_ERR(reg))
e71d42e0 324 regulator_disable(reg);
e71d42e0
MH
325}
326
327static const struct spi_device_id ad8366_id[] = {
11ab555a 328 {"ad8366", ID_AD8366},
cee211f4 329 {"ada4961", ID_ADA4961},
075da9cd 330 {"adl5240", ID_ADL5240},
247d3b63 331 {"hmc792a", ID_HMC792},
cc74a38d 332 {"hmc1119", ID_HMC1119},
e71d42e0
MH
333 {}
334};
ed199a11 335MODULE_DEVICE_TABLE(spi, ad8366_id);
e71d42e0
MH
336
337static struct spi_driver ad8366_driver = {
338 .driver = {
339 .name = KBUILD_MODNAME,
e71d42e0
MH
340 },
341 .probe = ad8366_probe,
fc52692c 342 .remove = ad8366_remove,
e71d42e0
MH
343 .id_table = ad8366_id,
344};
345
346module_spi_driver(ad8366_driver);
347
9920ed25 348MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
cee211f4 349MODULE_DESCRIPTION("Analog Devices AD8366 and similar Gain Amplifiers");
e71d42e0 350MODULE_LICENSE("GPL v2");