File Index
Files and directories
Sign in
FILE

ad7405.c

File preview with syntax highlighting.

linux-6.19.14/drivers/iio/adc/ad7405.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Analog Devices AD7405 driver
  4 *
  5 * Copyright 2025 Analog Devices Inc.
  6 */
  7
  8#include <linux/clk.h>
  9#include <linux/device.h>
 10#include <linux/err.h>
 11#include <linux/math64.h>
 12#include <linux/module.h>
 13#include <linux/mod_devicetable.h>
 14#include <linux/platform_device.h>
 15#include <linux/property.h>
 16#include <linux/regulator/consumer.h>
 17#include <linux/util_macros.h>
 18
 19#include <linux/iio/backend.h>
 20#include <linux/iio/iio.h>
 21
 22static const unsigned int ad7405_dec_rates_range[] = {
 23	32, 1, 4096,
 24};
 25
 26struct ad7405_chip_info {
 27	const char *name;
 28	const unsigned int full_scale_mv;
 29};
 30
 31struct ad7405_state {
 32	struct iio_backend *back;
 33	const struct ad7405_chip_info *info;
 34	unsigned int ref_frequency;
 35	unsigned int dec_rate;
 36};
 37
 38static int ad7405_set_dec_rate(struct iio_dev *indio_dev,
 39			       const struct iio_chan_spec *chan,
 40			       unsigned int dec_rate)
 41{
 42	struct ad7405_state *st = iio_priv(indio_dev);
 43	int ret;
 44
 45	if (dec_rate > 4096 || dec_rate < 32)
 46		return -EINVAL;
 47
 48	if (!iio_device_claim_direct(indio_dev))
 49		return -EBUSY;
 50
 51	ret = iio_backend_oversampling_ratio_set(st->back, chan->scan_index, dec_rate);
 52	iio_device_release_direct(indio_dev);
 53
 54	if (ret < 0)
 55		return ret;
 56
 57	st->dec_rate = dec_rate;
 58
 59	return 0;
 60}
 61
 62static int ad7405_read_raw(struct iio_dev *indio_dev,
 63			   const struct iio_chan_spec *chan, int *val,
 64			   int *val2, long info)
 65{
 66	struct ad7405_state *st = iio_priv(indio_dev);
 67
 68	switch (info) {
 69	case IIO_CHAN_INFO_SCALE:
 70		*val = st->info->full_scale_mv;
 71		*val2 = indio_dev->channels[0].scan_type.realbits - 1;
 72		return IIO_VAL_FRACTIONAL_LOG2;
 73	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
 74		*val = st->dec_rate;
 75		return IIO_VAL_INT;
 76	case IIO_CHAN_INFO_SAMP_FREQ:
 77		*val = DIV_ROUND_CLOSEST_ULL(st->ref_frequency, st->dec_rate);
 78		return IIO_VAL_INT;
 79	case IIO_CHAN_INFO_OFFSET:
 80		*val = -(1 << (indio_dev->channels[0].scan_type.realbits - 1));
 81		return IIO_VAL_INT;
 82	default:
 83		return -EINVAL;
 84	}
 85}
 86
 87static int ad7405_write_raw(struct iio_dev *indio_dev,
 88			    struct iio_chan_spec const *chan, int val,
 89			    int val2, long info)
 90{
 91	switch (info) {
 92	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
 93		if (val < 0)
 94			return -EINVAL;
 95		return ad7405_set_dec_rate(indio_dev, chan, val);
 96	default:
 97		return -EINVAL;
 98	}
 99}
100
101static int ad7405_read_avail(struct iio_dev *indio_dev,
102			     struct iio_chan_spec const *chan,
103			     const int **vals, int *type, int *length,
104			     long info)
105{
106	switch (info) {
107	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
108		*vals = ad7405_dec_rates_range;
109		*type = IIO_VAL_INT;
110		return IIO_AVAIL_RANGE;
111	default:
112		return -EINVAL;
113	}
114}
115
116static const struct iio_info ad7405_iio_info = {
117	.read_raw = &ad7405_read_raw,
118	.write_raw = &ad7405_write_raw,
119	.read_avail = &ad7405_read_avail,
120};
121
122static const struct iio_chan_spec ad7405_channel = {
123	.type = IIO_VOLTAGE,
124	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
125			BIT(IIO_CHAN_INFO_OFFSET),
126	.info_mask_shared_by_all = IIO_CHAN_INFO_SAMP_FREQ |
127			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
128	.info_mask_shared_by_all_available =
129			BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
130	.indexed = 1,
131	.channel = 0,
132	.channel2 = 1,
133	.differential = 1,
134	.scan_index = 0,
135	.scan_type = {
136		.sign = 'u',
137		.realbits = 16,
138		.storagebits = 16,
139	},
140};
141
142static const struct ad7405_chip_info ad7405_chip_info = {
143	.name = "ad7405",
144	.full_scale_mv = 320,
145};
146
147static const struct ad7405_chip_info adum7701_chip_info = {
148	.name = "adum7701",
149	.full_scale_mv = 320,
150};
151
152static const struct ad7405_chip_info adum7702_chip_info = {
153	.name = "adum7702",
154	.full_scale_mv = 64,
155};
156
157static const struct ad7405_chip_info adum7703_chip_info = {
158	.name = "adum7703",
159	.full_scale_mv = 320,
160};
161
162static const char * const ad7405_power_supplies[] = {
163	"vdd1",	"vdd2",
164};
165
166static int ad7405_probe(struct platform_device *pdev)
167{
168	struct device *dev = &pdev->dev;
169	struct iio_dev *indio_dev;
170	struct ad7405_state *st;
171	struct clk *clk;
172	int ret;
173
174	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
175	if (!indio_dev)
176		return -ENOMEM;
177
178	st = iio_priv(indio_dev);
179
180	st->info = device_get_match_data(dev);
181	if (!st->info)
182		return dev_err_probe(dev, -EINVAL, "no chip info\n");
183
184	ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(ad7405_power_supplies),
185					     ad7405_power_supplies);
186	if (ret)
187		return dev_err_probe(dev, ret, "failed to get and enable supplies");
188
189	clk = devm_clk_get_enabled(dev, NULL);
190	if (IS_ERR(clk))
191		return PTR_ERR(clk);
192
193	st->ref_frequency = clk_get_rate(clk);
194	if (!st->ref_frequency)
195		return -EINVAL;
196
197	indio_dev->name = st->info->name;
198	indio_dev->channels = &ad7405_channel;
199	indio_dev->num_channels = 1;
200	indio_dev->info = &ad7405_iio_info;
201
202	st->back = devm_iio_backend_get(dev, NULL);
203	if (IS_ERR(st->back))
204		return dev_err_probe(dev, PTR_ERR(st->back),
205				     "failed to get IIO backend");
206
207	ret = iio_backend_chan_enable(st->back, 0);
208	if (ret)
209		return ret;
210
211	ret = devm_iio_backend_request_buffer(dev, st->back, indio_dev);
212	if (ret)
213		return ret;
214
215	ret = devm_iio_backend_enable(dev, st->back);
216	if (ret)
217		return ret;
218
219	/*
220	 * Set 256 decimation rate. The default value in the AXI_ADC register
221	 * is 0, so we set the register with a decimation rate value that is
222	 * functional for all parts.
223	 */
224	ret = ad7405_set_dec_rate(indio_dev, &indio_dev->channels[0], 256);
225	if (ret)
226		return ret;
227
228	return devm_iio_device_register(dev, indio_dev);
229}
230
231static const struct of_device_id ad7405_of_match[] = {
232	{ .compatible = "adi,ad7405", .data = &ad7405_chip_info, },
233	{ .compatible = "adi,adum7701", .data = &adum7701_chip_info, },
234	{ .compatible = "adi,adum7702", .data = &adum7702_chip_info, },
235	{ .compatible = "adi,adum7703", .data = &adum7703_chip_info, },
236	{ }
237};
238MODULE_DEVICE_TABLE(of, ad7405_of_match);
239
240static struct platform_driver ad7405_driver = {
241	.driver = {
242		.name = "ad7405",
243		.of_match_table = ad7405_of_match,
244	},
245	.probe = ad7405_probe,
246};
247module_platform_driver(ad7405_driver);
248
249MODULE_AUTHOR("Dragos Bogdan <dragos.bogdan@analog.com>");
250MODULE_AUTHOR("Pop Ioan Daniel <pop.ioan-daniel@analog.com>");
251MODULE_DESCRIPTION("Analog Devices AD7405 driver");
252MODULE_LICENSE("GPL");
253MODULE_IMPORT_NS("IIO_BACKEND");
~/ Read-only file preview.