1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2017 Axis Communications AB |
4 | * |
5 | * Driver for Texas Instruments' ADC084S021 ADC chip. |
6 | * Datasheets can be found here: |
7 | * https://www.ti.com/lit/ds/symlink/adc084s021.pdf |
8 | */ |
9 | |
10 | #include <linux/err.h> |
11 | #include <linux/spi/spi.h> |
12 | #include <linux/module.h> |
13 | #include <linux/mod_devicetable.h> |
14 | #include <linux/interrupt.h> |
15 | #include <linux/iio/iio.h> |
16 | #include <linux/iio/buffer.h> |
17 | #include <linux/iio/triggered_buffer.h> |
18 | #include <linux/iio/trigger_consumer.h> |
19 | #include <linux/regulator/consumer.h> |
20 | |
21 | #define ADC084S021_DRIVER_NAME "adc084s021" |
22 | |
23 | struct adc084s021 { |
24 | struct spi_device *spi; |
25 | struct spi_message message; |
26 | struct spi_transfer spi_trans; |
27 | struct regulator *reg; |
28 | struct mutex lock; |
29 | /* Buffer used to align data */ |
30 | struct { |
31 | __be16 channels[4]; |
32 | s64 ts __aligned(8); |
33 | } scan; |
34 | /* |
35 | * DMA (thus cache coherency maintenance) may require the |
36 | * transfer buffers to live in their own cache line. |
37 | */ |
38 | u16 tx_buf[4] __aligned(IIO_DMA_MINALIGN); |
39 | __be16 rx_buf[5]; /* First 16-bits are trash */ |
40 | }; |
41 | |
42 | #define ADC084S021_VOLTAGE_CHANNEL(num) \ |
43 | { \ |
44 | .type = IIO_VOLTAGE, \ |
45 | .channel = (num), \ |
46 | .indexed = 1, \ |
47 | .scan_index = (num), \ |
48 | .scan_type = { \ |
49 | .sign = 'u', \ |
50 | .realbits = 8, \ |
51 | .storagebits = 16, \ |
52 | .shift = 4, \ |
53 | .endianness = IIO_BE, \ |
54 | }, \ |
55 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
56 | .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ |
57 | } |
58 | |
59 | static const struct iio_chan_spec adc084s021_channels[] = { |
60 | ADC084S021_VOLTAGE_CHANNEL(0), |
61 | ADC084S021_VOLTAGE_CHANNEL(1), |
62 | ADC084S021_VOLTAGE_CHANNEL(2), |
63 | ADC084S021_VOLTAGE_CHANNEL(3), |
64 | IIO_CHAN_SOFT_TIMESTAMP(4), |
65 | }; |
66 | |
67 | /** |
68 | * adc084s021_adc_conversion() - Read an ADC channel and return its value. |
69 | * |
70 | * @adc: The ADC SPI data. |
71 | * @data: Buffer for converted data. |
72 | */ |
73 | static int adc084s021_adc_conversion(struct adc084s021 *adc, __be16 *data) |
74 | { |
75 | int n_words = (adc->spi_trans.len >> 1) - 1; /* Discard first word */ |
76 | int ret, i = 0; |
77 | |
78 | /* Do the transfer */ |
79 | ret = spi_sync(spi: adc->spi, message: &adc->message); |
80 | if (ret < 0) |
81 | return ret; |
82 | |
83 | for (; i < n_words; i++) |
84 | *(data + i) = adc->rx_buf[i + 1]; |
85 | |
86 | return ret; |
87 | } |
88 | |
89 | static int adc084s021_read_raw(struct iio_dev *indio_dev, |
90 | struct iio_chan_spec const *channel, int *val, |
91 | int *val2, long mask) |
92 | { |
93 | struct adc084s021 *adc = iio_priv(indio_dev); |
94 | int ret; |
95 | __be16 be_val; |
96 | |
97 | switch (mask) { |
98 | case IIO_CHAN_INFO_RAW: |
99 | ret = iio_device_claim_direct_mode(indio_dev); |
100 | if (ret < 0) |
101 | return ret; |
102 | |
103 | ret = regulator_enable(regulator: adc->reg); |
104 | if (ret) { |
105 | iio_device_release_direct_mode(indio_dev); |
106 | return ret; |
107 | } |
108 | |
109 | adc->tx_buf[0] = channel->channel << 3; |
110 | ret = adc084s021_adc_conversion(adc, data: &be_val); |
111 | iio_device_release_direct_mode(indio_dev); |
112 | regulator_disable(regulator: adc->reg); |
113 | if (ret < 0) |
114 | return ret; |
115 | |
116 | *val = be16_to_cpu(be_val); |
117 | *val = (*val >> channel->scan_type.shift) & 0xff; |
118 | |
119 | return IIO_VAL_INT; |
120 | case IIO_CHAN_INFO_SCALE: |
121 | ret = regulator_enable(regulator: adc->reg); |
122 | if (ret) |
123 | return ret; |
124 | |
125 | ret = regulator_get_voltage(regulator: adc->reg); |
126 | regulator_disable(regulator: adc->reg); |
127 | if (ret < 0) |
128 | return ret; |
129 | |
130 | *val = ret / 1000; |
131 | |
132 | return IIO_VAL_INT; |
133 | default: |
134 | return -EINVAL; |
135 | } |
136 | } |
137 | |
138 | /** |
139 | * adc084s021_buffer_trigger_handler() - Read ADC channels and push to buffer. |
140 | * |
141 | * @irq: The interrupt number (not used). |
142 | * @pollfunc: Pointer to the poll func. |
143 | */ |
144 | static irqreturn_t adc084s021_buffer_trigger_handler(int irq, void *pollfunc) |
145 | { |
146 | struct iio_poll_func *pf = pollfunc; |
147 | struct iio_dev *indio_dev = pf->indio_dev; |
148 | struct adc084s021 *adc = iio_priv(indio_dev); |
149 | |
150 | mutex_lock(&adc->lock); |
151 | |
152 | if (adc084s021_adc_conversion(adc, data: adc->scan.channels) < 0) |
153 | dev_err(&adc->spi->dev, "Failed to read data\n" ); |
154 | |
155 | iio_push_to_buffers_with_timestamp(indio_dev, data: &adc->scan, |
156 | timestamp: iio_get_time_ns(indio_dev)); |
157 | mutex_unlock(lock: &adc->lock); |
158 | iio_trigger_notify_done(trig: indio_dev->trig); |
159 | |
160 | return IRQ_HANDLED; |
161 | } |
162 | |
163 | static int adc084s021_buffer_preenable(struct iio_dev *indio_dev) |
164 | { |
165 | struct adc084s021 *adc = iio_priv(indio_dev); |
166 | int scan_index; |
167 | int i = 0; |
168 | |
169 | for_each_set_bit(scan_index, indio_dev->active_scan_mask, |
170 | indio_dev->masklength) { |
171 | const struct iio_chan_spec *channel = |
172 | &indio_dev->channels[scan_index]; |
173 | adc->tx_buf[i++] = channel->channel << 3; |
174 | } |
175 | adc->spi_trans.len = 2 + (i * sizeof(__be16)); /* Trash + channels */ |
176 | |
177 | return regulator_enable(regulator: adc->reg); |
178 | } |
179 | |
180 | static int adc084s021_buffer_postdisable(struct iio_dev *indio_dev) |
181 | { |
182 | struct adc084s021 *adc = iio_priv(indio_dev); |
183 | |
184 | adc->spi_trans.len = 4; /* Trash + single channel */ |
185 | |
186 | return regulator_disable(regulator: adc->reg); |
187 | } |
188 | |
189 | static const struct iio_info adc084s021_info = { |
190 | .read_raw = adc084s021_read_raw, |
191 | }; |
192 | |
193 | static const struct iio_buffer_setup_ops adc084s021_buffer_setup_ops = { |
194 | .preenable = adc084s021_buffer_preenable, |
195 | .postdisable = adc084s021_buffer_postdisable, |
196 | }; |
197 | |
198 | static int adc084s021_probe(struct spi_device *spi) |
199 | { |
200 | struct iio_dev *indio_dev; |
201 | struct adc084s021 *adc; |
202 | int ret; |
203 | |
204 | indio_dev = devm_iio_device_alloc(parent: &spi->dev, sizeof_priv: sizeof(*adc)); |
205 | if (!indio_dev) { |
206 | dev_err(&spi->dev, "Failed to allocate IIO device\n" ); |
207 | return -ENOMEM; |
208 | } |
209 | |
210 | adc = iio_priv(indio_dev); |
211 | adc->spi = spi; |
212 | |
213 | /* Initiate the Industrial I/O device */ |
214 | indio_dev->name = spi_get_device_id(sdev: spi)->name; |
215 | indio_dev->modes = INDIO_DIRECT_MODE; |
216 | indio_dev->info = &adc084s021_info; |
217 | indio_dev->channels = adc084s021_channels; |
218 | indio_dev->num_channels = ARRAY_SIZE(adc084s021_channels); |
219 | |
220 | /* Create SPI transfer for channel reads */ |
221 | adc->spi_trans.tx_buf = adc->tx_buf; |
222 | adc->spi_trans.rx_buf = adc->rx_buf; |
223 | adc->spi_trans.len = 4; /* Trash + single channel */ |
224 | spi_message_init_with_transfers(m: &adc->message, xfers: &adc->spi_trans, num_xfers: 1); |
225 | |
226 | adc->reg = devm_regulator_get(dev: &spi->dev, id: "vref" ); |
227 | if (IS_ERR(ptr: adc->reg)) |
228 | return PTR_ERR(ptr: adc->reg); |
229 | |
230 | mutex_init(&adc->lock); |
231 | |
232 | /* Setup triggered buffer with pollfunction */ |
233 | ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev, NULL, |
234 | adc084s021_buffer_trigger_handler, |
235 | &adc084s021_buffer_setup_ops); |
236 | if (ret) { |
237 | dev_err(&spi->dev, "Failed to setup triggered buffer\n" ); |
238 | return ret; |
239 | } |
240 | |
241 | return devm_iio_device_register(&spi->dev, indio_dev); |
242 | } |
243 | |
244 | static const struct of_device_id adc084s021_of_match[] = { |
245 | { .compatible = "ti,adc084s021" , }, |
246 | {}, |
247 | }; |
248 | MODULE_DEVICE_TABLE(of, adc084s021_of_match); |
249 | |
250 | static const struct spi_device_id adc084s021_id[] = { |
251 | { ADC084S021_DRIVER_NAME, 0 }, |
252 | {} |
253 | }; |
254 | MODULE_DEVICE_TABLE(spi, adc084s021_id); |
255 | |
256 | static struct spi_driver adc084s021_driver = { |
257 | .driver = { |
258 | .name = ADC084S021_DRIVER_NAME, |
259 | .of_match_table = adc084s021_of_match, |
260 | }, |
261 | .probe = adc084s021_probe, |
262 | .id_table = adc084s021_id, |
263 | }; |
264 | module_spi_driver(adc084s021_driver); |
265 | |
266 | MODULE_AUTHOR("Mårten Lindahl <martenli@axis.com>" ); |
267 | MODULE_DESCRIPTION("Texas Instruments ADC084S021" ); |
268 | MODULE_LICENSE("GPL v2" ); |
269 | MODULE_VERSION("1.0" ); |
270 | |