summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2012-08-10 12:36:00 -0400
committerJonathan Cameron <jic23@kernel.org>2012-08-27 12:53:24 -0400
commit32e0e7e08c32fbd61ddfb7e80ba96c13085f3d39 (patch)
tree969ee97cfbf6d3f30e69ea801ea66de29033b4a4 /drivers
parentaf3008485ea0372fb9ce1f69f3768617d39eb4e6 (diff)
staging:iio:ad7780: Use common Sigma Delta library
Convert the ad7780 driver to make use of the new common code for devices from the Analog Devices Sigma Delta family. As a bonus the ad7780 driver gains support for buffered mode. Although this is a bit tricky. The ad7780 reports in the lower 4 unused bits of the data word the internal gain used. The driver will update the scale attribute value depending on the gain accordingly, but obviously this will only work if the gain does not change while sampling. This is not perfect, but since we store the raw value in the buffer an application which is aware of this can extract the gain factor from the buffer as well an apply it accordingly. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/iio/adc/Kconfig1
-rw-r--r--drivers/staging/iio/adc/ad7780.c186
2 files changed, 71 insertions, 116 deletions
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index 845fb6c70ca3..d0eb27be381c 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -99,6 +99,7 @@ config AD7780
99 tristate "Analog Devices AD7780 AD7781 ADC driver" 99 tristate "Analog Devices AD7780 AD7781 ADC driver"
100 depends on SPI 100 depends on SPI
101 depends on GPIOLIB 101 depends on GPIOLIB
102 select AD_SIGMA_DELTA
102 help 103 help
103 Say yes here to build support for Analog Devices 104 Say yes here to build support for Analog Devices
104 AD7780 and AD7781 SPI analog to digital converters (ADC). 105 AD7780 and AD7781 SPI analog to digital converters (ADC).
diff --git a/drivers/staging/iio/adc/ad7780.c b/drivers/staging/iio/adc/ad7780.c
index 19ee49c95de4..853f8b16b4ef 100644
--- a/drivers/staging/iio/adc/ad7780.c
+++ b/drivers/staging/iio/adc/ad7780.c
@@ -20,6 +20,7 @@
20 20
21#include <linux/iio/iio.h> 21#include <linux/iio/iio.h>
22#include <linux/iio/sysfs.h> 22#include <linux/iio/sysfs.h>
23#include <linux/iio/adc/ad_sigma_delta.h>
23 24
24#include "ad7780.h" 25#include "ad7780.h"
25 26
@@ -37,20 +38,13 @@ struct ad7780_chip_info {
37}; 38};
38 39
39struct ad7780_state { 40struct ad7780_state {
40 struct spi_device *spi;
41 const struct ad7780_chip_info *chip_info; 41 const struct ad7780_chip_info *chip_info;
42 struct regulator *reg; 42 struct regulator *reg;
43 struct ad7780_platform_data *pdata; 43 int powerdown_gpio;
44 wait_queue_head_t wq_data_avail; 44 unsigned int gain;
45 bool done;
46 u16 int_vref_mv; 45 u16 int_vref_mv;
47 struct spi_transfer xfer; 46
48 struct spi_message msg; 47 struct ad_sigma_delta sd;
49 /*
50 * DMA (thus cache coherency maintenance) requires the
51 * transfer buffers to live in their own cache lines.
52 */
53 unsigned int data ____cacheline_aligned;
54}; 48};
55 49
56enum ad7780_supported_device_ids { 50enum ad7780_supported_device_ids {
@@ -58,28 +52,30 @@ enum ad7780_supported_device_ids {
58 ID_AD7781, 52 ID_AD7781,
59}; 53};
60 54
61static int ad7780_read(struct ad7780_state *st, int *val) 55static struct ad7780_state *ad_sigma_delta_to_ad7780(struct ad_sigma_delta *sd)
62{ 56{
63 int ret; 57 return container_of(sd, struct ad7780_state, sd);
64 58}
65 spi_bus_lock(st->spi->master);
66
67 enable_irq(st->spi->irq);
68 st->done = false;
69 gpio_set_value(st->pdata->gpio_pdrst, 1);
70 59
71 ret = wait_event_interruptible(st->wq_data_avail, st->done); 60static int ad7780_set_mode(struct ad_sigma_delta *sigma_delta,
72 disable_irq_nosync(st->spi->irq); 61 enum ad_sigma_delta_mode mode)
73 if (ret) 62{
74 goto out; 63 struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta);
64 unsigned val;
65
66 switch (mode) {
67 case AD_SD_MODE_SINGLE:
68 case AD_SD_MODE_CONTINUOUS:
69 val = 1;
70 break;
71 default:
72 val = 0;
73 break;
74 }
75 75
76 ret = spi_sync_locked(st->spi, &st->msg); 76 gpio_set_value(st->powerdown_gpio, val);
77 *val = be32_to_cpu(st->data);
78out:
79 gpio_set_value(st->pdata->gpio_pdrst, 0);
80 spi_bus_unlock(st->spi->master);
81 77
82 return ret; 78 return 0;
83} 79}
84 80
85static int ad7780_read_raw(struct iio_dev *indio_dev, 81static int ad7780_read_raw(struct iio_dev *indio_dev,
@@ -89,89 +85,57 @@ static int ad7780_read_raw(struct iio_dev *indio_dev,
89 long m) 85 long m)
90{ 86{
91 struct ad7780_state *st = iio_priv(indio_dev); 87 struct ad7780_state *st = iio_priv(indio_dev);
92 struct iio_chan_spec channel = st->chip_info->channel;
93 int ret, smpl = 0;
94 unsigned long scale_uv; 88 unsigned long scale_uv;
95 89
96 switch (m) { 90 switch (m) {
97 case IIO_CHAN_INFO_RAW: 91 case IIO_CHAN_INFO_RAW:
98 mutex_lock(&indio_dev->mlock); 92 return ad_sigma_delta_single_conversion(indio_dev, chan, val);
99 ret = ad7780_read(st, &smpl);
100 mutex_unlock(&indio_dev->mlock);
101
102 if (ret < 0)
103 return ret;
104
105 if ((smpl & AD7780_ERR) ||
106 !((smpl & AD7780_PAT0) && !(smpl & AD7780_PAT1)))
107 return -EIO;
108
109 *val = (smpl >> channel.scan_type.shift) &
110 ((1 << (channel.scan_type.realbits)) - 1);
111 *val -= (1 << (channel.scan_type.realbits - 1));
112
113 if (!(smpl & AD7780_GAIN))
114 *val *= 128;
115
116 return IIO_VAL_INT;
117 case IIO_CHAN_INFO_SCALE: 93 case IIO_CHAN_INFO_SCALE:
118 scale_uv = (st->int_vref_mv * 100000) 94 scale_uv = (st->int_vref_mv * 100000 * st->gain)
119 >> (channel.scan_type.realbits - 1); 95 >> (chan->scan_type.realbits - 1);
120 *val = scale_uv / 100000; 96 *val = scale_uv / 100000;
121 *val2 = (scale_uv % 100000) * 10; 97 *val2 = (scale_uv % 100000) * 10;
122 return IIO_VAL_INT_PLUS_MICRO; 98 return IIO_VAL_INT_PLUS_MICRO;
99 case IIO_CHAN_INFO_OFFSET:
100 *val -= (1 << (chan->scan_type.realbits - 1));
101 return IIO_VAL_INT;
123 } 102 }
103
124 return -EINVAL; 104 return -EINVAL;
125} 105}
126 106
107static int ad7780_postprocess_sample(struct ad_sigma_delta *sigma_delta,
108 unsigned int raw_sample)
109{
110 struct ad7780_state *st = ad_sigma_delta_to_ad7780(sigma_delta);
111
112 if ((raw_sample & AD7780_ERR) ||
113 !((raw_sample & AD7780_PAT0) && !(raw_sample & AD7780_PAT1)))
114 return -EIO;
115
116 if (raw_sample & AD7780_GAIN)
117 st->gain = 1;
118 else
119 st->gain = 128;
120
121 return 0;
122}
123
124static const struct ad_sigma_delta_info ad7780_sigma_delta_info = {
125 .set_mode = ad7780_set_mode,
126 .postprocess_sample = ad7780_postprocess_sample,
127 .has_registers = false,
128};
129
127static const struct ad7780_chip_info ad7780_chip_info_tbl[] = { 130static const struct ad7780_chip_info ad7780_chip_info_tbl[] = {
128 [ID_AD7780] = { 131 [ID_AD7780] = {
129 .channel = { 132 .channel = AD_SD_CHANNEL(1, 0, 0, 24, 32, 8),
130 .type = IIO_VOLTAGE,
131 .indexed = 1,
132 .channel = 0,
133 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
134 IIO_CHAN_INFO_SCALE_SHARED_BIT |
135 IIO_CHAN_INFO_OFFSET_SHARED_BIT,
136 .scan_type = {
137 .sign = 'u',
138 .realbits = 24,
139 .storagebits = 32,
140 .shift = 8,
141 },
142 },
143 }, 133 },
144 [ID_AD7781] = { 134 [ID_AD7781] = {
145 .channel = { 135 .channel = AD_SD_CHANNEL(1, 0, 0, 20, 32, 12),
146 .type = IIO_VOLTAGE,
147 .indexed = 1,
148 .channel = 0,
149 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
150 IIO_CHAN_INFO_SCALE_SHARED_BIT |
151 IIO_CHAN_INFO_OFFSET_SHARED_BIT,
152 .scan_type = {
153 .sign = 'u',
154 .realbits = 20,
155 .storagebits = 32,
156 .shift = 12,
157 },
158 },
159 }, 136 },
160}; 137};
161 138
162/**
163 * Interrupt handler
164 */
165static irqreturn_t ad7780_interrupt(int irq, void *dev_id)
166{
167 struct ad7780_state *st = dev_id;
168
169 st->done = true;
170 wake_up_interruptible(&st->wq_data_avail);
171
172 return IRQ_HANDLED;
173};
174
175static const struct iio_info ad7780_info = { 139static const struct iio_info ad7780_info = {
176 .read_raw = &ad7780_read_raw, 140 .read_raw = &ad7780_read_raw,
177 .driver_module = THIS_MODULE, 141 .driver_module = THIS_MODULE,
@@ -194,6 +158,9 @@ static int __devinit ad7780_probe(struct spi_device *spi)
194 return -ENOMEM; 158 return -ENOMEM;
195 159
196 st = iio_priv(indio_dev); 160 st = iio_priv(indio_dev);
161 st->gain = 1;
162
163 ad_sd_init(&st->sd, indio_dev, spi, &ad7780_sigma_delta_info);
197 164
198 st->reg = regulator_get(&spi->dev, "vcc"); 165 st->reg = regulator_get(&spi->dev, "vcc");
199 if (!IS_ERR(st->reg)) { 166 if (!IS_ERR(st->reg)) {
@@ -207,7 +174,7 @@ static int __devinit ad7780_probe(struct spi_device *spi)
207 st->chip_info = 174 st->chip_info =
208 &ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data]; 175 &ad7780_chip_info_tbl[spi_get_device_id(spi)->driver_data];
209 176
210 st->pdata = pdata; 177 st->powerdown_gpio = pdata->gpio_pdrst;
211 178
212 if (pdata && pdata->vref_mv) 179 if (pdata && pdata->vref_mv)
213 st->int_vref_mv = pdata->vref_mv; 180 st->int_vref_mv = pdata->vref_mv;
@@ -217,7 +184,6 @@ static int __devinit ad7780_probe(struct spi_device *spi)
217 dev_warn(&spi->dev, "reference voltage unspecified\n"); 184 dev_warn(&spi->dev, "reference voltage unspecified\n");
218 185
219 spi_set_drvdata(spi, indio_dev); 186 spi_set_drvdata(spi, indio_dev);
220 st->spi = spi;
221 187
222 indio_dev->dev.parent = &spi->dev; 188 indio_dev->dev.parent = &spi->dev;
223 indio_dev->name = spi_get_device_id(spi)->name; 189 indio_dev->name = spi_get_device_id(spi)->name;
@@ -226,40 +192,27 @@ static int __devinit ad7780_probe(struct spi_device *spi)
226 indio_dev->num_channels = 1; 192 indio_dev->num_channels = 1;
227 indio_dev->info = &ad7780_info; 193 indio_dev->info = &ad7780_info;
228 194
229 init_waitqueue_head(&st->wq_data_avail); 195 ret = gpio_request_one(pdata->gpio_pdrst, GPIOF_OUT_INIT_LOW,
230
231 /* Setup default message */
232
233 st->xfer.rx_buf = &st->data;
234 st->xfer.len = st->chip_info->channel.scan_type.storagebits / 8;
235
236 spi_message_init(&st->msg);
237 spi_message_add_tail(&st->xfer, &st->msg);
238
239 ret = gpio_request_one(st->pdata->gpio_pdrst, GPIOF_OUT_INIT_LOW,
240 "AD7780 /PDRST"); 196 "AD7780 /PDRST");
241 if (ret) { 197 if (ret) {
242 dev_err(&spi->dev, "failed to request GPIO PDRST\n"); 198 dev_err(&spi->dev, "failed to request GPIO PDRST\n");
243 goto error_disable_reg; 199 goto error_disable_reg;
244 } 200 }
245 201
246 ret = request_irq(spi->irq, ad7780_interrupt, 202 ret = ad_sd_setup_buffer_and_trigger(indio_dev);
247 IRQF_TRIGGER_FALLING, spi_get_device_id(spi)->name, st);
248 if (ret) 203 if (ret)
249 goto error_free_gpio; 204 goto error_free_gpio;
250 205
251 disable_irq(spi->irq);
252
253 ret = iio_device_register(indio_dev); 206 ret = iio_device_register(indio_dev);
254 if (ret) 207 if (ret)
255 goto error_free_irq; 208 goto error_cleanup_buffer_and_trigger;
256 209
257 return 0; 210 return 0;
258 211
259error_free_irq: 212error_cleanup_buffer_and_trigger:
260 free_irq(spi->irq, st); 213 ad_sd_cleanup_buffer_and_trigger(indio_dev);
261error_free_gpio: 214error_free_gpio:
262 gpio_free(st->pdata->gpio_pdrst); 215 gpio_free(pdata->gpio_pdrst);
263error_disable_reg: 216error_disable_reg:
264 if (!IS_ERR(st->reg)) 217 if (!IS_ERR(st->reg))
265 regulator_disable(st->reg); 218 regulator_disable(st->reg);
@@ -278,8 +231,9 @@ static int ad7780_remove(struct spi_device *spi)
278 struct ad7780_state *st = iio_priv(indio_dev); 231 struct ad7780_state *st = iio_priv(indio_dev);
279 232
280 iio_device_unregister(indio_dev); 233 iio_device_unregister(indio_dev);
281 free_irq(spi->irq, st); 234 ad_sd_cleanup_buffer_and_trigger(indio_dev);
282 gpio_free(st->pdata->gpio_pdrst); 235
236 gpio_free(st->powerdown_gpio);
283 if (!IS_ERR(st->reg)) { 237 if (!IS_ERR(st->reg)) {
284 regulator_disable(st->reg); 238 regulator_disable(st->reg);
285 regulator_put(st->reg); 239 regulator_put(st->reg);