aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/iio/adc/ad7923.c60
1 files changed, 53 insertions, 7 deletions
diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c
index 36eee248a9f6..11ccc42b25a6 100644
--- a/drivers/iio/adc/ad7923.c
+++ b/drivers/iio/adc/ad7923.c
@@ -12,6 +12,7 @@
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <linux/sysfs.h> 13#include <linux/sysfs.h>
14#include <linux/spi/spi.h> 14#include <linux/spi/spi.h>
15#include <linux/regulator/consumer.h>
15#include <linux/err.h> 16#include <linux/err.h>
16#include <linux/delay.h> 17#include <linux/delay.h>
17#include <linux/module.h> 18#include <linux/module.h>
@@ -56,6 +57,11 @@ struct ad7923_state {
56 struct spi_transfer scan_single_xfer[2]; 57 struct spi_transfer scan_single_xfer[2];
57 struct spi_message ring_msg; 58 struct spi_message ring_msg;
58 struct spi_message scan_single_msg; 59 struct spi_message scan_single_msg;
60
61 struct regulator *reg;
62
63 unsigned int settings;
64
59 /* 65 /*
60 * DMA (thus cache coherency maintenance) requires the 66 * DMA (thus cache coherency maintenance) requires the
61 * transfer buffers to live in their own cache lines. 67 * transfer buffers to live in their own cache lines.
@@ -100,10 +106,9 @@ static int ad7923_update_scan_mode(struct iio_dev *indio_dev,
100 106
101 len = 0; 107 len = 0;
102 for_each_set_bit(i, active_scan_mask, AD7923_MAX_CHAN) { 108 for_each_set_bit(i, active_scan_mask, AD7923_MAX_CHAN) {
103 cmd = AD7923_WRITE_CR | AD7923_CODING | AD7923_RANGE | 109 cmd = AD7923_WRITE_CR | AD7923_CHANNEL_WRITE(i) |
104 AD7923_PM_MODE_WRITE(AD7923_PM_MODE_OPS) |
105 AD7923_SEQUENCE_WRITE(AD7923_SEQUENCE_OFF) | 110 AD7923_SEQUENCE_WRITE(AD7923_SEQUENCE_OFF) |
106 AD7923_CHANNEL_WRITE(i); 111 st->settings;
107 cmd <<= AD7923_SHIFT_REGISTER; 112 cmd <<= AD7923_SHIFT_REGISTER;
108 st->tx_buf[len++] = cpu_to_be16(cmd); 113 st->tx_buf[len++] = cpu_to_be16(cmd);
109 } 114 }
@@ -163,9 +168,9 @@ static int ad7923_scan_direct(struct ad7923_state *st, unsigned ch)
163{ 168{
164 int ret, cmd; 169 int ret, cmd;
165 170
166 cmd = AD7923_WRITE_CR | AD7923_PM_MODE_WRITE(AD7923_PM_MODE_OPS) | 171 cmd = AD7923_WRITE_CR | AD7923_CHANNEL_WRITE(ch) |
167 AD7923_SEQUENCE_WRITE(AD7923_SEQUENCE_OFF) | AD7923_CODING | 172 AD7923_SEQUENCE_WRITE(AD7923_SEQUENCE_OFF) |
168 AD7923_CHANNEL_WRITE(ch) | AD7923_RANGE; 173 st->settings;
169 cmd <<= AD7923_SHIFT_REGISTER; 174 cmd <<= AD7923_SHIFT_REGISTER;
170 st->tx_buf[0] = cpu_to_be16(cmd); 175 st->tx_buf[0] = cpu_to_be16(cmd);
171 176
@@ -176,6 +181,22 @@ static int ad7923_scan_direct(struct ad7923_state *st, unsigned ch)
176 return be16_to_cpu(st->rx_buf[0]); 181 return be16_to_cpu(st->rx_buf[0]);
177} 182}
178 183
184static int ad7923_get_range(struct ad7923_state *st)
185{
186 int vref;
187
188 vref = regulator_get_voltage(st->reg);
189 if (vref < 0)
190 return vref;
191
192 vref /= 1000;
193
194 if (!(st->settings & AD7923_RANGE))
195 vref *= 2;
196
197 return vref;
198}
199
179static int ad7923_read_raw(struct iio_dev *indio_dev, 200static int ad7923_read_raw(struct iio_dev *indio_dev,
180 struct iio_chan_spec const *chan, 201 struct iio_chan_spec const *chan,
181 int *val, 202 int *val,
@@ -203,6 +224,13 @@ static int ad7923_read_raw(struct iio_dev *indio_dev,
203 return -EIO; 224 return -EIO;
204 225
205 return IIO_VAL_INT; 226 return IIO_VAL_INT;
227 case IIO_CHAN_INFO_SCALE:
228 ret = ad7923_get_range(st);
229 if (ret < 0)
230 return ret;
231 *val = ret;
232 *val2 = chan->scan_type.realbits;
233 return IIO_VAL_FRACTIONAL_LOG2;
206 } 234 }
207 return -EINVAL; 235 return -EINVAL;
208} 236}
@@ -227,6 +255,8 @@ static int ad7923_probe(struct spi_device *spi)
227 spi_set_drvdata(spi, indio_dev); 255 spi_set_drvdata(spi, indio_dev);
228 256
229 st->spi = spi; 257 st->spi = spi;
258 st->settings = AD7923_CODING | AD7923_RANGE |
259 AD7923_PM_MODE_WRITE(AD7923_PM_MODE_OPS);
230 260
231 indio_dev->name = spi_get_device_id(spi)->name; 261 indio_dev->name = spi_get_device_id(spi)->name;
232 indio_dev->dev.parent = &spi->dev; 262 indio_dev->dev.parent = &spi->dev;
@@ -247,10 +277,19 @@ static int ad7923_probe(struct spi_device *spi)
247 spi_message_add_tail(&st->scan_single_xfer[0], &st->scan_single_msg); 277 spi_message_add_tail(&st->scan_single_xfer[0], &st->scan_single_msg);
248 spi_message_add_tail(&st->scan_single_xfer[1], &st->scan_single_msg); 278 spi_message_add_tail(&st->scan_single_xfer[1], &st->scan_single_msg);
249 279
280 st->reg = regulator_get(&spi->dev, "refin");
281 if (IS_ERR(st->reg)) {
282 ret = PTR_ERR(st->reg);
283 goto error_free;
284 }
285 ret = regulator_enable(st->reg);
286 if (ret)
287 goto error_put_reg;
288
250 ret = iio_triggered_buffer_setup(indio_dev, NULL, 289 ret = iio_triggered_buffer_setup(indio_dev, NULL,
251 &ad7923_trigger_handler, NULL); 290 &ad7923_trigger_handler, NULL);
252 if (ret) 291 if (ret)
253 goto error_free; 292 goto error_disable_reg;
254 293
255 ret = iio_device_register(indio_dev); 294 ret = iio_device_register(indio_dev);
256 if (ret) 295 if (ret)
@@ -260,6 +299,10 @@ static int ad7923_probe(struct spi_device *spi)
260 299
261error_cleanup_ring: 300error_cleanup_ring:
262 iio_triggered_buffer_cleanup(indio_dev); 301 iio_triggered_buffer_cleanup(indio_dev);
302error_disable_reg:
303 regulator_disable(st->reg);
304error_put_reg:
305 regulator_put(st->reg);
263error_free: 306error_free:
264 iio_device_free(indio_dev); 307 iio_device_free(indio_dev);
265 308
@@ -269,9 +312,12 @@ error_free:
269static int ad7923_remove(struct spi_device *spi) 312static int ad7923_remove(struct spi_device *spi)
270{ 313{
271 struct iio_dev *indio_dev = spi_get_drvdata(spi); 314 struct iio_dev *indio_dev = spi_get_drvdata(spi);
315 struct ad7923_state *st = iio_priv(indio_dev);
272 316
273 iio_device_unregister(indio_dev); 317 iio_device_unregister(indio_dev);
274 iio_triggered_buffer_cleanup(indio_dev); 318 iio_triggered_buffer_cleanup(indio_dev);
319 regulator_disable(st->reg);
320 regulator_put(st->reg);
275 iio_device_free(indio_dev); 321 iio_device_free(indio_dev);
276 322
277 return 0; 323 return 0;