File Index
Files and directories
Sign in
FILE

ti-adc128s052.c

File preview with syntax highlighting.

linux-6.19.14/drivers/iio/adc/ti-adc128s052.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (C) 2014 Angelo Compagnucci <angelo.compagnucci@gmail.com>
  4 *
  5 * Driver for Texas Instruments' ADC128S052, ADC122S021 and ADC124S021 ADC chip.
  6 * Datasheets can be found here:
  7 * https://www.ti.com/lit/ds/symlink/adc128s052.pdf
  8 * https://www.ti.com/lit/ds/symlink/adc122s021.pdf
  9 * https://www.ti.com/lit/ds/symlink/adc124s021.pdf
 10 */
 11
 12#include <linux/cleanup.h>
 13#include <linux/err.h>
 14#include <linux/iio/iio.h>
 15#include <linux/mod_devicetable.h>
 16#include <linux/module.h>
 17#include <linux/property.h>
 18#include <linux/regulator/consumer.h>
 19#include <linux/spi/spi.h>
 20
 21struct adc128_configuration {
 22	const struct iio_chan_spec	*channels;
 23	u8				num_channels;
 24	const char			*refname;
 25	int				num_other_regulators;
 26	const char * const		(*other_regulators)[];
 27};
 28
 29struct adc128 {
 30	struct spi_device *spi;
 31
 32	/*
 33	 * Serialize the SPI 'write-channel + read data' accesses and protect
 34	 * the shared buffer.
 35	 */
 36	struct mutex lock;
 37	int vref_mv;
 38	union {
 39		__be16 buffer16;
 40		u8 buffer[2];
 41	} __aligned(IIO_DMA_MINALIGN);
 42};
 43
 44static int adc128_adc_conversion(struct adc128 *adc, u8 channel)
 45{
 46	int ret;
 47
 48	guard(mutex)(&adc->lock);
 49
 50	adc->buffer[0] = channel << 3;
 51	adc->buffer[1] = 0;
 52
 53	ret = spi_write(adc->spi, &adc->buffer, sizeof(adc->buffer));
 54	if (ret < 0)
 55		return ret;
 56
 57	ret = spi_read(adc->spi, &adc->buffer16, sizeof(adc->buffer16));
 58	if (ret < 0)
 59		return ret;
 60
 61	return be16_to_cpu(adc->buffer16) & 0xFFF;
 62}
 63
 64static int adc128_read_raw(struct iio_dev *indio_dev,
 65			   struct iio_chan_spec const *channel, int *val,
 66			   int *val2, long mask)
 67{
 68	struct adc128 *adc = iio_priv(indio_dev);
 69	int ret;
 70
 71	switch (mask) {
 72	case IIO_CHAN_INFO_RAW:
 73
 74		ret = adc128_adc_conversion(adc, channel->channel);
 75		if (ret < 0)
 76			return ret;
 77
 78		*val = ret;
 79		return IIO_VAL_INT;
 80
 81	case IIO_CHAN_INFO_SCALE:
 82
 83		*val = adc->vref_mv;
 84		*val2 = 12;
 85		return IIO_VAL_FRACTIONAL_LOG2;
 86
 87	default:
 88		return -EINVAL;
 89	}
 90
 91}
 92
 93#define ADC128_VOLTAGE_CHANNEL(num)	\
 94	{ \
 95		.type = IIO_VOLTAGE, \
 96		.indexed = 1, \
 97		.channel = (num), \
 98		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
 99		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
100	}
101
102static const struct iio_chan_spec simple_1chan_adc_channels[] = {
103	ADC128_VOLTAGE_CHANNEL(0),
104};
105
106static const struct iio_chan_spec simple_2chan_adc_channels[] = {
107	ADC128_VOLTAGE_CHANNEL(0),
108	ADC128_VOLTAGE_CHANNEL(1),
109};
110
111static const struct iio_chan_spec simple_4chan_adc_channels[] = {
112	ADC128_VOLTAGE_CHANNEL(0),
113	ADC128_VOLTAGE_CHANNEL(1),
114	ADC128_VOLTAGE_CHANNEL(2),
115	ADC128_VOLTAGE_CHANNEL(3),
116};
117
118static const struct iio_chan_spec simple_8chan_adc_channels[] = {
119	ADC128_VOLTAGE_CHANNEL(0),
120	ADC128_VOLTAGE_CHANNEL(1),
121	ADC128_VOLTAGE_CHANNEL(2),
122	ADC128_VOLTAGE_CHANNEL(3),
123	ADC128_VOLTAGE_CHANNEL(4),
124	ADC128_VOLTAGE_CHANNEL(5),
125	ADC128_VOLTAGE_CHANNEL(6),
126	ADC128_VOLTAGE_CHANNEL(7),
127};
128
129static const char * const bd79104_regulators[] = { "iovdd" };
130
131static const struct adc128_configuration adc122s_config = {
132	.channels = simple_2chan_adc_channels,
133	.num_channels = ARRAY_SIZE(simple_2chan_adc_channels),
134	.refname = "vref",
135};
136
137static const struct adc128_configuration adc124s_config = {
138	.channels = simple_4chan_adc_channels,
139	.num_channels = ARRAY_SIZE(simple_4chan_adc_channels),
140	.refname = "vref",
141};
142
143static const struct adc128_configuration adc128s_config = {
144	.channels = simple_8chan_adc_channels,
145	.num_channels = ARRAY_SIZE(simple_8chan_adc_channels),
146	.refname = "vref",
147};
148
149static const struct adc128_configuration bd79100_config = {
150	.channels = simple_1chan_adc_channels,
151	.num_channels = ARRAY_SIZE(simple_1chan_adc_channels),
152	.refname = "vdd",
153	.other_regulators = &bd79104_regulators,
154	.num_other_regulators = 1,
155};
156
157static const struct adc128_configuration bd79101_config = {
158	.channels = simple_2chan_adc_channels,
159	.num_channels = ARRAY_SIZE(simple_2chan_adc_channels),
160	.refname = "vdd",
161	.other_regulators = &bd79104_regulators,
162	.num_other_regulators = 1,
163};
164
165static const struct adc128_configuration bd79102_config = {
166	.channels = simple_4chan_adc_channels,
167	.num_channels = ARRAY_SIZE(simple_4chan_adc_channels),
168	.refname = "vdd",
169	.other_regulators = &bd79104_regulators,
170	.num_other_regulators = 1,
171};
172
173static const struct adc128_configuration bd79104_config = {
174	.channels = simple_8chan_adc_channels,
175	.num_channels = ARRAY_SIZE(simple_8chan_adc_channels),
176	.refname = "vdd",
177	.other_regulators = &bd79104_regulators,
178	.num_other_regulators = 1,
179};
180
181static const struct iio_info adc128_info = {
182	.read_raw = adc128_read_raw,
183};
184
185static int adc128_probe(struct spi_device *spi)
186{
187	const struct adc128_configuration *config;
188	struct iio_dev *indio_dev;
189	struct adc128 *adc;
190	int ret;
191
192	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
193	if (!indio_dev)
194		return -ENOMEM;
195
196	adc = iio_priv(indio_dev);
197	adc->spi = spi;
198
199	indio_dev->name = spi_get_device_id(spi)->name;
200	indio_dev->modes = INDIO_DIRECT_MODE;
201	indio_dev->info = &adc128_info;
202
203	config = spi_get_device_match_data(spi);
204
205	indio_dev->channels = config->channels;
206	indio_dev->num_channels = config->num_channels;
207
208	ret = devm_regulator_get_enable_read_voltage(&spi->dev,
209						     config->refname);
210	if (ret < 0)
211		return dev_err_probe(&spi->dev, ret,
212				     "failed to read '%s' voltage",
213				     config->refname);
214
215	adc->vref_mv = ret / 1000;
216
217	if (config->num_other_regulators) {
218		ret = devm_regulator_bulk_get_enable(&spi->dev,
219						config->num_other_regulators,
220						*config->other_regulators);
221		if (ret)
222			return dev_err_probe(&spi->dev, ret,
223					     "Failed to enable regulators\n");
224	}
225
226	ret = devm_mutex_init(&spi->dev, &adc->lock);
227	if (ret)
228		return ret;
229
230	return devm_iio_device_register(&spi->dev, indio_dev);
231}
232
233static const struct of_device_id adc128_of_match[] = {
234	{ .compatible = "ti,adc128s052", .data = &adc128s_config },
235	{ .compatible = "ti,adc122s021", .data = &adc122s_config },
236	{ .compatible = "ti,adc122s051", .data = &adc122s_config },
237	{ .compatible = "ti,adc122s101", .data = &adc122s_config },
238	{ .compatible = "ti,adc124s021", .data = &adc124s_config },
239	{ .compatible = "ti,adc124s051", .data = &adc124s_config },
240	{ .compatible = "ti,adc124s101", .data = &adc124s_config },
241	{ .compatible = "rohm,bd79100", .data = &bd79100_config },
242	{ .compatible = "rohm,bd79101", .data = &bd79101_config },
243	{ .compatible = "rohm,bd79102", .data = &bd79102_config },
244	{ .compatible = "rohm,bd79103", .data = &bd79104_config },
245	{ .compatible = "rohm,bd79104", .data = &bd79104_config },
246	{ }
247};
248MODULE_DEVICE_TABLE(of, adc128_of_match);
249
250static const struct spi_device_id adc128_id[] = {
251	{ "adc128s052", (kernel_ulong_t)&adc128s_config },
252	{ "adc122s021",	(kernel_ulong_t)&adc122s_config },
253	{ "adc122s051",	(kernel_ulong_t)&adc122s_config },
254	{ "adc122s101",	(kernel_ulong_t)&adc122s_config },
255	{ "adc124s021", (kernel_ulong_t)&adc124s_config },
256	{ "adc124s051", (kernel_ulong_t)&adc124s_config },
257	{ "adc124s101", (kernel_ulong_t)&adc124s_config },
258	{ "bd79100", (kernel_ulong_t)&bd79100_config },
259	{ "bd79101", (kernel_ulong_t)&bd79101_config },
260	{ "bd79102", (kernel_ulong_t)&bd79102_config },
261	{ "bd79103", (kernel_ulong_t)&bd79104_config },
262	{ "bd79104", (kernel_ulong_t)&bd79104_config },
263	{ }
264};
265MODULE_DEVICE_TABLE(spi, adc128_id);
266
267static const struct acpi_device_id adc128_acpi_match[] = {
268	{ "AANT1280", (kernel_ulong_t)&adc124s_config },
269	{ }
270};
271MODULE_DEVICE_TABLE(acpi, adc128_acpi_match);
272
273static struct spi_driver adc128_driver = {
274	.driver = {
275		.name = "adc128s052",
276		.of_match_table = adc128_of_match,
277		.acpi_match_table = adc128_acpi_match,
278	},
279	.probe = adc128_probe,
280	.id_table = adc128_id,
281};
282module_spi_driver(adc128_driver);
283
284MODULE_AUTHOR("Angelo Compagnucci <angelo.compagnucci@gmail.com>");
285MODULE_DESCRIPTION("Texas Instruments ADC128S052");
286MODULE_LICENSE("GPL v2");
~/ Read-only file preview.