1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Support code for Analog Devices Sigma-Delta ADCs
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright 2012 Analog Devices Inc.
6*4882a593Smuzhiyun * Author: Lars-Peter Clausen <lars@metafoo.de>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/interrupt.h>
10*4882a593Smuzhiyun #include <linux/device.h>
11*4882a593Smuzhiyun #include <linux/kernel.h>
12*4882a593Smuzhiyun #include <linux/slab.h>
13*4882a593Smuzhiyun #include <linux/spi/spi.h>
14*4882a593Smuzhiyun #include <linux/err.h>
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <linux/iio/iio.h>
18*4882a593Smuzhiyun #include <linux/iio/sysfs.h>
19*4882a593Smuzhiyun #include <linux/iio/buffer.h>
20*4882a593Smuzhiyun #include <linux/iio/trigger.h>
21*4882a593Smuzhiyun #include <linux/iio/trigger_consumer.h>
22*4882a593Smuzhiyun #include <linux/iio/triggered_buffer.h>
23*4882a593Smuzhiyun #include <linux/iio/adc/ad_sigma_delta.h>
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun #include <asm/unaligned.h>
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #define AD_SD_COMM_CHAN_MASK 0x3
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #define AD_SD_REG_COMM 0x00
31*4882a593Smuzhiyun #define AD_SD_REG_DATA 0x03
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun /**
34*4882a593Smuzhiyun * ad_sd_set_comm() - Set communications register
35*4882a593Smuzhiyun *
36*4882a593Smuzhiyun * @sigma_delta: The sigma delta device
37*4882a593Smuzhiyun * @comm: New value for the communications register
38*4882a593Smuzhiyun */
ad_sd_set_comm(struct ad_sigma_delta * sigma_delta,uint8_t comm)39*4882a593Smuzhiyun void ad_sd_set_comm(struct ad_sigma_delta *sigma_delta, uint8_t comm)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun /* Some variants use the lower two bits of the communications register
42*4882a593Smuzhiyun * to select the channel */
43*4882a593Smuzhiyun sigma_delta->comm = comm & AD_SD_COMM_CHAN_MASK;
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(ad_sd_set_comm);
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun /**
48*4882a593Smuzhiyun * ad_sd_write_reg() - Write a register
49*4882a593Smuzhiyun *
50*4882a593Smuzhiyun * @sigma_delta: The sigma delta device
51*4882a593Smuzhiyun * @reg: Address of the register
52*4882a593Smuzhiyun * @size: Size of the register (0-3)
53*4882a593Smuzhiyun * @val: Value to write to the register
54*4882a593Smuzhiyun *
55*4882a593Smuzhiyun * Returns 0 on success, an error code otherwise.
56*4882a593Smuzhiyun **/
ad_sd_write_reg(struct ad_sigma_delta * sigma_delta,unsigned int reg,unsigned int size,unsigned int val)57*4882a593Smuzhiyun int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
58*4882a593Smuzhiyun unsigned int size, unsigned int val)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun uint8_t *data = sigma_delta->tx_buf;
61*4882a593Smuzhiyun struct spi_transfer t = {
62*4882a593Smuzhiyun .tx_buf = data,
63*4882a593Smuzhiyun .len = size + 1,
64*4882a593Smuzhiyun .cs_change = sigma_delta->keep_cs_asserted,
65*4882a593Smuzhiyun };
66*4882a593Smuzhiyun struct spi_message m;
67*4882a593Smuzhiyun int ret;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun data[0] = (reg << sigma_delta->info->addr_shift) | sigma_delta->comm;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun switch (size) {
72*4882a593Smuzhiyun case 3:
73*4882a593Smuzhiyun put_unaligned_be24(val, &data[1]);
74*4882a593Smuzhiyun break;
75*4882a593Smuzhiyun case 2:
76*4882a593Smuzhiyun put_unaligned_be16(val, &data[1]);
77*4882a593Smuzhiyun break;
78*4882a593Smuzhiyun case 1:
79*4882a593Smuzhiyun data[1] = val;
80*4882a593Smuzhiyun break;
81*4882a593Smuzhiyun case 0:
82*4882a593Smuzhiyun break;
83*4882a593Smuzhiyun default:
84*4882a593Smuzhiyun return -EINVAL;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun spi_message_init(&m);
88*4882a593Smuzhiyun spi_message_add_tail(&t, &m);
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun if (sigma_delta->bus_locked)
91*4882a593Smuzhiyun ret = spi_sync_locked(sigma_delta->spi, &m);
92*4882a593Smuzhiyun else
93*4882a593Smuzhiyun ret = spi_sync(sigma_delta->spi, &m);
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun return ret;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(ad_sd_write_reg);
98*4882a593Smuzhiyun
ad_sd_read_reg_raw(struct ad_sigma_delta * sigma_delta,unsigned int reg,unsigned int size,uint8_t * val)99*4882a593Smuzhiyun static int ad_sd_read_reg_raw(struct ad_sigma_delta *sigma_delta,
100*4882a593Smuzhiyun unsigned int reg, unsigned int size, uint8_t *val)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun uint8_t *data = sigma_delta->tx_buf;
103*4882a593Smuzhiyun int ret;
104*4882a593Smuzhiyun struct spi_transfer t[] = {
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun .tx_buf = data,
107*4882a593Smuzhiyun .len = 1,
108*4882a593Smuzhiyun }, {
109*4882a593Smuzhiyun .rx_buf = val,
110*4882a593Smuzhiyun .len = size,
111*4882a593Smuzhiyun .cs_change = sigma_delta->bus_locked,
112*4882a593Smuzhiyun },
113*4882a593Smuzhiyun };
114*4882a593Smuzhiyun struct spi_message m;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun spi_message_init(&m);
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun if (sigma_delta->info->has_registers) {
119*4882a593Smuzhiyun data[0] = reg << sigma_delta->info->addr_shift;
120*4882a593Smuzhiyun data[0] |= sigma_delta->info->read_mask;
121*4882a593Smuzhiyun data[0] |= sigma_delta->comm;
122*4882a593Smuzhiyun spi_message_add_tail(&t[0], &m);
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun spi_message_add_tail(&t[1], &m);
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun if (sigma_delta->bus_locked)
127*4882a593Smuzhiyun ret = spi_sync_locked(sigma_delta->spi, &m);
128*4882a593Smuzhiyun else
129*4882a593Smuzhiyun ret = spi_sync(sigma_delta->spi, &m);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun return ret;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun /**
135*4882a593Smuzhiyun * ad_sd_read_reg() - Read a register
136*4882a593Smuzhiyun *
137*4882a593Smuzhiyun * @sigma_delta: The sigma delta device
138*4882a593Smuzhiyun * @reg: Address of the register
139*4882a593Smuzhiyun * @size: Size of the register (1-4)
140*4882a593Smuzhiyun * @val: Read value
141*4882a593Smuzhiyun *
142*4882a593Smuzhiyun * Returns 0 on success, an error code otherwise.
143*4882a593Smuzhiyun **/
ad_sd_read_reg(struct ad_sigma_delta * sigma_delta,unsigned int reg,unsigned int size,unsigned int * val)144*4882a593Smuzhiyun int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta,
145*4882a593Smuzhiyun unsigned int reg, unsigned int size, unsigned int *val)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun int ret;
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun ret = ad_sd_read_reg_raw(sigma_delta, reg, size, sigma_delta->rx_buf);
150*4882a593Smuzhiyun if (ret < 0)
151*4882a593Smuzhiyun goto out;
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun switch (size) {
154*4882a593Smuzhiyun case 4:
155*4882a593Smuzhiyun *val = get_unaligned_be32(sigma_delta->rx_buf);
156*4882a593Smuzhiyun break;
157*4882a593Smuzhiyun case 3:
158*4882a593Smuzhiyun *val = get_unaligned_be24(sigma_delta->rx_buf);
159*4882a593Smuzhiyun break;
160*4882a593Smuzhiyun case 2:
161*4882a593Smuzhiyun *val = get_unaligned_be16(sigma_delta->rx_buf);
162*4882a593Smuzhiyun break;
163*4882a593Smuzhiyun case 1:
164*4882a593Smuzhiyun *val = sigma_delta->rx_buf[0];
165*4882a593Smuzhiyun break;
166*4882a593Smuzhiyun default:
167*4882a593Smuzhiyun ret = -EINVAL;
168*4882a593Smuzhiyun break;
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun out:
172*4882a593Smuzhiyun return ret;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(ad_sd_read_reg);
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun /**
177*4882a593Smuzhiyun * ad_sd_reset() - Reset the serial interface
178*4882a593Smuzhiyun *
179*4882a593Smuzhiyun * @sigma_delta: The sigma delta device
180*4882a593Smuzhiyun * @reset_length: Number of SCLKs with DIN = 1
181*4882a593Smuzhiyun *
182*4882a593Smuzhiyun * Returns 0 on success, an error code otherwise.
183*4882a593Smuzhiyun **/
ad_sd_reset(struct ad_sigma_delta * sigma_delta,unsigned int reset_length)184*4882a593Smuzhiyun int ad_sd_reset(struct ad_sigma_delta *sigma_delta,
185*4882a593Smuzhiyun unsigned int reset_length)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun uint8_t *buf;
188*4882a593Smuzhiyun unsigned int size;
189*4882a593Smuzhiyun int ret;
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun size = DIV_ROUND_UP(reset_length, 8);
192*4882a593Smuzhiyun buf = kcalloc(size, sizeof(*buf), GFP_KERNEL);
193*4882a593Smuzhiyun if (!buf)
194*4882a593Smuzhiyun return -ENOMEM;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun memset(buf, 0xff, size);
197*4882a593Smuzhiyun ret = spi_write(sigma_delta->spi, buf, size);
198*4882a593Smuzhiyun kfree(buf);
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun return ret;
201*4882a593Smuzhiyun }
202*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(ad_sd_reset);
203*4882a593Smuzhiyun
ad_sd_calibrate(struct ad_sigma_delta * sigma_delta,unsigned int mode,unsigned int channel)204*4882a593Smuzhiyun int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
205*4882a593Smuzhiyun unsigned int mode, unsigned int channel)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun int ret;
208*4882a593Smuzhiyun unsigned long timeout;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun ret = ad_sigma_delta_set_channel(sigma_delta, channel);
211*4882a593Smuzhiyun if (ret)
212*4882a593Smuzhiyun return ret;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun spi_bus_lock(sigma_delta->spi->master);
215*4882a593Smuzhiyun sigma_delta->bus_locked = true;
216*4882a593Smuzhiyun sigma_delta->keep_cs_asserted = true;
217*4882a593Smuzhiyun reinit_completion(&sigma_delta->completion);
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun ret = ad_sigma_delta_set_mode(sigma_delta, mode);
220*4882a593Smuzhiyun if (ret < 0)
221*4882a593Smuzhiyun goto out;
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun sigma_delta->irq_dis = false;
224*4882a593Smuzhiyun enable_irq(sigma_delta->spi->irq);
225*4882a593Smuzhiyun timeout = wait_for_completion_timeout(&sigma_delta->completion, 2 * HZ);
226*4882a593Smuzhiyun if (timeout == 0) {
227*4882a593Smuzhiyun sigma_delta->irq_dis = true;
228*4882a593Smuzhiyun disable_irq_nosync(sigma_delta->spi->irq);
229*4882a593Smuzhiyun ret = -EIO;
230*4882a593Smuzhiyun } else {
231*4882a593Smuzhiyun ret = 0;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun out:
234*4882a593Smuzhiyun sigma_delta->keep_cs_asserted = false;
235*4882a593Smuzhiyun ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
236*4882a593Smuzhiyun sigma_delta->bus_locked = false;
237*4882a593Smuzhiyun spi_bus_unlock(sigma_delta->spi->master);
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun return ret;
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(ad_sd_calibrate);
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun /**
244*4882a593Smuzhiyun * ad_sd_calibrate_all() - Performs channel calibration
245*4882a593Smuzhiyun * @sigma_delta: The sigma delta device
246*4882a593Smuzhiyun * @cb: Array of channels and calibration type to perform
247*4882a593Smuzhiyun * @n: Number of items in cb
248*4882a593Smuzhiyun *
249*4882a593Smuzhiyun * Returns 0 on success, an error code otherwise.
250*4882a593Smuzhiyun **/
ad_sd_calibrate_all(struct ad_sigma_delta * sigma_delta,const struct ad_sd_calib_data * cb,unsigned int n)251*4882a593Smuzhiyun int ad_sd_calibrate_all(struct ad_sigma_delta *sigma_delta,
252*4882a593Smuzhiyun const struct ad_sd_calib_data *cb, unsigned int n)
253*4882a593Smuzhiyun {
254*4882a593Smuzhiyun unsigned int i;
255*4882a593Smuzhiyun int ret;
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun for (i = 0; i < n; i++) {
258*4882a593Smuzhiyun ret = ad_sd_calibrate(sigma_delta, cb[i].mode, cb[i].channel);
259*4882a593Smuzhiyun if (ret)
260*4882a593Smuzhiyun return ret;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun return 0;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(ad_sd_calibrate_all);
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun /**
268*4882a593Smuzhiyun * ad_sigma_delta_single_conversion() - Performs a single data conversion
269*4882a593Smuzhiyun * @indio_dev: The IIO device
270*4882a593Smuzhiyun * @chan: The conversion is done for this channel
271*4882a593Smuzhiyun * @val: Pointer to the location where to store the read value
272*4882a593Smuzhiyun *
273*4882a593Smuzhiyun * Returns: 0 on success, an error value otherwise.
274*4882a593Smuzhiyun */
ad_sigma_delta_single_conversion(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,int * val)275*4882a593Smuzhiyun int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
276*4882a593Smuzhiyun const struct iio_chan_spec *chan, int *val)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
279*4882a593Smuzhiyun unsigned int sample, raw_sample;
280*4882a593Smuzhiyun unsigned int data_reg;
281*4882a593Smuzhiyun int ret = 0;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun if (iio_buffer_enabled(indio_dev))
284*4882a593Smuzhiyun return -EBUSY;
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun mutex_lock(&indio_dev->mlock);
287*4882a593Smuzhiyun ad_sigma_delta_set_channel(sigma_delta, chan->address);
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun spi_bus_lock(sigma_delta->spi->master);
290*4882a593Smuzhiyun sigma_delta->bus_locked = true;
291*4882a593Smuzhiyun sigma_delta->keep_cs_asserted = true;
292*4882a593Smuzhiyun reinit_completion(&sigma_delta->completion);
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_SINGLE);
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun sigma_delta->irq_dis = false;
297*4882a593Smuzhiyun enable_irq(sigma_delta->spi->irq);
298*4882a593Smuzhiyun ret = wait_for_completion_interruptible_timeout(
299*4882a593Smuzhiyun &sigma_delta->completion, HZ);
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun if (ret == 0)
302*4882a593Smuzhiyun ret = -EIO;
303*4882a593Smuzhiyun if (ret < 0)
304*4882a593Smuzhiyun goto out;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun if (sigma_delta->info->data_reg != 0)
307*4882a593Smuzhiyun data_reg = sigma_delta->info->data_reg;
308*4882a593Smuzhiyun else
309*4882a593Smuzhiyun data_reg = AD_SD_REG_DATA;
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun ret = ad_sd_read_reg(sigma_delta, data_reg,
312*4882a593Smuzhiyun DIV_ROUND_UP(chan->scan_type.realbits + chan->scan_type.shift, 8),
313*4882a593Smuzhiyun &raw_sample);
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun out:
316*4882a593Smuzhiyun if (!sigma_delta->irq_dis) {
317*4882a593Smuzhiyun disable_irq_nosync(sigma_delta->spi->irq);
318*4882a593Smuzhiyun sigma_delta->irq_dis = true;
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun sigma_delta->keep_cs_asserted = false;
322*4882a593Smuzhiyun ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
323*4882a593Smuzhiyun sigma_delta->bus_locked = false;
324*4882a593Smuzhiyun spi_bus_unlock(sigma_delta->spi->master);
325*4882a593Smuzhiyun mutex_unlock(&indio_dev->mlock);
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun if (ret)
328*4882a593Smuzhiyun return ret;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun sample = raw_sample >> chan->scan_type.shift;
331*4882a593Smuzhiyun sample &= (1 << chan->scan_type.realbits) - 1;
332*4882a593Smuzhiyun *val = sample;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun ret = ad_sigma_delta_postprocess_sample(sigma_delta, raw_sample);
335*4882a593Smuzhiyun if (ret)
336*4882a593Smuzhiyun return ret;
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun return IIO_VAL_INT;
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(ad_sigma_delta_single_conversion);
341*4882a593Smuzhiyun
ad_sd_buffer_postenable(struct iio_dev * indio_dev)342*4882a593Smuzhiyun static int ad_sd_buffer_postenable(struct iio_dev *indio_dev)
343*4882a593Smuzhiyun {
344*4882a593Smuzhiyun struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
345*4882a593Smuzhiyun unsigned int channel;
346*4882a593Smuzhiyun int ret;
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun channel = find_first_bit(indio_dev->active_scan_mask,
349*4882a593Smuzhiyun indio_dev->masklength);
350*4882a593Smuzhiyun ret = ad_sigma_delta_set_channel(sigma_delta,
351*4882a593Smuzhiyun indio_dev->channels[channel].address);
352*4882a593Smuzhiyun if (ret)
353*4882a593Smuzhiyun return ret;
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun spi_bus_lock(sigma_delta->spi->master);
356*4882a593Smuzhiyun sigma_delta->bus_locked = true;
357*4882a593Smuzhiyun sigma_delta->keep_cs_asserted = true;
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun ret = ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_CONTINUOUS);
360*4882a593Smuzhiyun if (ret)
361*4882a593Smuzhiyun goto err_unlock;
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun sigma_delta->irq_dis = false;
364*4882a593Smuzhiyun enable_irq(sigma_delta->spi->irq);
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun return 0;
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun err_unlock:
369*4882a593Smuzhiyun spi_bus_unlock(sigma_delta->spi->master);
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun return ret;
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun
ad_sd_buffer_postdisable(struct iio_dev * indio_dev)374*4882a593Smuzhiyun static int ad_sd_buffer_postdisable(struct iio_dev *indio_dev)
375*4882a593Smuzhiyun {
376*4882a593Smuzhiyun struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun reinit_completion(&sigma_delta->completion);
379*4882a593Smuzhiyun wait_for_completion_timeout(&sigma_delta->completion, HZ);
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun if (!sigma_delta->irq_dis) {
382*4882a593Smuzhiyun disable_irq_nosync(sigma_delta->spi->irq);
383*4882a593Smuzhiyun sigma_delta->irq_dis = true;
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun sigma_delta->keep_cs_asserted = false;
387*4882a593Smuzhiyun ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun sigma_delta->bus_locked = false;
390*4882a593Smuzhiyun return spi_bus_unlock(sigma_delta->spi->master);
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun
ad_sd_trigger_handler(int irq,void * p)393*4882a593Smuzhiyun static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
394*4882a593Smuzhiyun {
395*4882a593Smuzhiyun struct iio_poll_func *pf = p;
396*4882a593Smuzhiyun struct iio_dev *indio_dev = pf->indio_dev;
397*4882a593Smuzhiyun struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
398*4882a593Smuzhiyun uint8_t *data = sigma_delta->rx_buf;
399*4882a593Smuzhiyun unsigned int reg_size;
400*4882a593Smuzhiyun unsigned int data_reg;
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun reg_size = indio_dev->channels[0].scan_type.realbits +
403*4882a593Smuzhiyun indio_dev->channels[0].scan_type.shift;
404*4882a593Smuzhiyun reg_size = DIV_ROUND_UP(reg_size, 8);
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun if (sigma_delta->info->data_reg != 0)
407*4882a593Smuzhiyun data_reg = sigma_delta->info->data_reg;
408*4882a593Smuzhiyun else
409*4882a593Smuzhiyun data_reg = AD_SD_REG_DATA;
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun switch (reg_size) {
412*4882a593Smuzhiyun case 4:
413*4882a593Smuzhiyun case 2:
414*4882a593Smuzhiyun case 1:
415*4882a593Smuzhiyun ad_sd_read_reg_raw(sigma_delta, data_reg, reg_size, &data[0]);
416*4882a593Smuzhiyun break;
417*4882a593Smuzhiyun case 3:
418*4882a593Smuzhiyun /* We store 24 bit samples in a 32 bit word. Keep the upper
419*4882a593Smuzhiyun * byte set to zero. */
420*4882a593Smuzhiyun ad_sd_read_reg_raw(sigma_delta, data_reg, reg_size, &data[1]);
421*4882a593Smuzhiyun break;
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun iio_push_to_buffers_with_timestamp(indio_dev, data, pf->timestamp);
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun iio_trigger_notify_done(indio_dev->trig);
427*4882a593Smuzhiyun sigma_delta->irq_dis = false;
428*4882a593Smuzhiyun enable_irq(sigma_delta->spi->irq);
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun return IRQ_HANDLED;
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun static const struct iio_buffer_setup_ops ad_sd_buffer_setup_ops = {
434*4882a593Smuzhiyun .postenable = &ad_sd_buffer_postenable,
435*4882a593Smuzhiyun .postdisable = &ad_sd_buffer_postdisable,
436*4882a593Smuzhiyun .validate_scan_mask = &iio_validate_scan_mask_onehot,
437*4882a593Smuzhiyun };
438*4882a593Smuzhiyun
ad_sd_data_rdy_trig_poll(int irq,void * private)439*4882a593Smuzhiyun static irqreturn_t ad_sd_data_rdy_trig_poll(int irq, void *private)
440*4882a593Smuzhiyun {
441*4882a593Smuzhiyun struct ad_sigma_delta *sigma_delta = private;
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun complete(&sigma_delta->completion);
444*4882a593Smuzhiyun disable_irq_nosync(irq);
445*4882a593Smuzhiyun sigma_delta->irq_dis = true;
446*4882a593Smuzhiyun iio_trigger_poll(sigma_delta->trig);
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun return IRQ_HANDLED;
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun /**
452*4882a593Smuzhiyun * ad_sd_validate_trigger() - validate_trigger callback for ad_sigma_delta devices
453*4882a593Smuzhiyun * @indio_dev: The IIO device
454*4882a593Smuzhiyun * @trig: The new trigger
455*4882a593Smuzhiyun *
456*4882a593Smuzhiyun * Returns: 0 if the 'trig' matches the trigger registered by the ad_sigma_delta
457*4882a593Smuzhiyun * device, -EINVAL otherwise.
458*4882a593Smuzhiyun */
ad_sd_validate_trigger(struct iio_dev * indio_dev,struct iio_trigger * trig)459*4882a593Smuzhiyun int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig)
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun if (sigma_delta->trig != trig)
464*4882a593Smuzhiyun return -EINVAL;
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun return 0;
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(ad_sd_validate_trigger);
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun static const struct iio_trigger_ops ad_sd_trigger_ops = {
471*4882a593Smuzhiyun };
472*4882a593Smuzhiyun
ad_sd_probe_trigger(struct iio_dev * indio_dev)473*4882a593Smuzhiyun static int ad_sd_probe_trigger(struct iio_dev *indio_dev)
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
476*4882a593Smuzhiyun int ret;
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun sigma_delta->trig = iio_trigger_alloc("%s-dev%d", indio_dev->name,
479*4882a593Smuzhiyun indio_dev->id);
480*4882a593Smuzhiyun if (sigma_delta->trig == NULL) {
481*4882a593Smuzhiyun ret = -ENOMEM;
482*4882a593Smuzhiyun goto error_ret;
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun sigma_delta->trig->ops = &ad_sd_trigger_ops;
485*4882a593Smuzhiyun init_completion(&sigma_delta->completion);
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun ret = request_irq(sigma_delta->spi->irq,
488*4882a593Smuzhiyun ad_sd_data_rdy_trig_poll,
489*4882a593Smuzhiyun sigma_delta->info->irq_flags,
490*4882a593Smuzhiyun indio_dev->name,
491*4882a593Smuzhiyun sigma_delta);
492*4882a593Smuzhiyun if (ret)
493*4882a593Smuzhiyun goto error_free_trig;
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun if (!sigma_delta->irq_dis) {
496*4882a593Smuzhiyun sigma_delta->irq_dis = true;
497*4882a593Smuzhiyun disable_irq_nosync(sigma_delta->spi->irq);
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun sigma_delta->trig->dev.parent = &sigma_delta->spi->dev;
500*4882a593Smuzhiyun iio_trigger_set_drvdata(sigma_delta->trig, sigma_delta);
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun ret = iio_trigger_register(sigma_delta->trig);
503*4882a593Smuzhiyun if (ret)
504*4882a593Smuzhiyun goto error_free_irq;
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun /* select default trigger */
507*4882a593Smuzhiyun indio_dev->trig = iio_trigger_get(sigma_delta->trig);
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun return 0;
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun error_free_irq:
512*4882a593Smuzhiyun free_irq(sigma_delta->spi->irq, sigma_delta);
513*4882a593Smuzhiyun error_free_trig:
514*4882a593Smuzhiyun iio_trigger_free(sigma_delta->trig);
515*4882a593Smuzhiyun error_ret:
516*4882a593Smuzhiyun return ret;
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun
ad_sd_remove_trigger(struct iio_dev * indio_dev)519*4882a593Smuzhiyun static void ad_sd_remove_trigger(struct iio_dev *indio_dev)
520*4882a593Smuzhiyun {
521*4882a593Smuzhiyun struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun iio_trigger_unregister(sigma_delta->trig);
524*4882a593Smuzhiyun free_irq(sigma_delta->spi->irq, sigma_delta);
525*4882a593Smuzhiyun iio_trigger_free(sigma_delta->trig);
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun /**
529*4882a593Smuzhiyun * ad_sd_setup_buffer_and_trigger() -
530*4882a593Smuzhiyun * @indio_dev: The IIO device
531*4882a593Smuzhiyun */
ad_sd_setup_buffer_and_trigger(struct iio_dev * indio_dev)532*4882a593Smuzhiyun int ad_sd_setup_buffer_and_trigger(struct iio_dev *indio_dev)
533*4882a593Smuzhiyun {
534*4882a593Smuzhiyun int ret;
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
537*4882a593Smuzhiyun &ad_sd_trigger_handler, &ad_sd_buffer_setup_ops);
538*4882a593Smuzhiyun if (ret)
539*4882a593Smuzhiyun return ret;
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun ret = ad_sd_probe_trigger(indio_dev);
542*4882a593Smuzhiyun if (ret) {
543*4882a593Smuzhiyun iio_triggered_buffer_cleanup(indio_dev);
544*4882a593Smuzhiyun return ret;
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun return 0;
548*4882a593Smuzhiyun }
549*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(ad_sd_setup_buffer_and_trigger);
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun /**
552*4882a593Smuzhiyun * ad_sd_cleanup_buffer_and_trigger() -
553*4882a593Smuzhiyun * @indio_dev: The IIO device
554*4882a593Smuzhiyun */
ad_sd_cleanup_buffer_and_trigger(struct iio_dev * indio_dev)555*4882a593Smuzhiyun void ad_sd_cleanup_buffer_and_trigger(struct iio_dev *indio_dev)
556*4882a593Smuzhiyun {
557*4882a593Smuzhiyun ad_sd_remove_trigger(indio_dev);
558*4882a593Smuzhiyun iio_triggered_buffer_cleanup(indio_dev);
559*4882a593Smuzhiyun }
560*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(ad_sd_cleanup_buffer_and_trigger);
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun /**
563*4882a593Smuzhiyun * ad_sd_init() - Initializes a ad_sigma_delta struct
564*4882a593Smuzhiyun * @sigma_delta: The ad_sigma_delta device
565*4882a593Smuzhiyun * @indio_dev: The IIO device which the Sigma Delta device is used for
566*4882a593Smuzhiyun * @spi: The SPI device for the ad_sigma_delta device
567*4882a593Smuzhiyun * @info: Device specific callbacks and options
568*4882a593Smuzhiyun *
569*4882a593Smuzhiyun * This function needs to be called before any other operations are performed on
570*4882a593Smuzhiyun * the ad_sigma_delta struct.
571*4882a593Smuzhiyun */
ad_sd_init(struct ad_sigma_delta * sigma_delta,struct iio_dev * indio_dev,struct spi_device * spi,const struct ad_sigma_delta_info * info)572*4882a593Smuzhiyun int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
573*4882a593Smuzhiyun struct spi_device *spi, const struct ad_sigma_delta_info *info)
574*4882a593Smuzhiyun {
575*4882a593Smuzhiyun sigma_delta->spi = spi;
576*4882a593Smuzhiyun sigma_delta->info = info;
577*4882a593Smuzhiyun iio_device_set_drvdata(indio_dev, sigma_delta);
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun return 0;
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(ad_sd_init);
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
584*4882a593Smuzhiyun MODULE_DESCRIPTION("Analog Devices Sigma-Delta ADCs");
585*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
586