2 * AD7780/AD7781 SPI ADC driver
4 * Copyright 2011 Analog Devices Inc.
6 * Licensed under the GPL-2.
9 #include <linux/interrupt.h>
10 #include <linux/workqueue.h>
11 #include <linux/device.h>
12 #include <linux/kernel.h>
13 #include <linux/slab.h>
14 #include <linux/sysfs.h>
15 #include <linux/list.h>
16 #include <linux/spi/spi.h>
17 #include <linux/regulator/consumer.h>
18 #include <linux/err.h>
19 #include <linux/sched.h>
20 #include <linux/gpio.h>
24 #include "../ring_generic.h"
29 #define AD7780_RDY (1 << 7)
30 #define AD7780_FILTER (1 << 6)
31 #define AD7780_ERR (1 << 5)
32 #define AD7780_ID1 (1 << 4)
33 #define AD7780_ID0 (1 << 3)
34 #define AD7780_GAIN (1 << 2)
35 #define AD7780_PAT1 (1 << 1)
36 #define AD7780_PAT0 (1 << 0)
38 struct ad7780_chip_info
{
39 struct iio_chan_spec channel
;
43 struct spi_device
*spi
;
44 const struct ad7780_chip_info
*chip_info
;
45 struct regulator
*reg
;
46 struct ad7780_platform_data
*pdata
;
47 wait_queue_head_t wq_data_avail
;
50 struct spi_transfer xfer
;
51 struct spi_message msg
;
53 * DMA (thus cache coherency maintenance) requires the
54 * transfer buffers to live in their own cache lines.
56 unsigned int data ____cacheline_aligned
;
59 enum ad7780_supported_device_ids
{
64 static int ad7780_read(struct ad7780_state
*st
, int *val
)
68 spi_bus_lock(st
->spi
->master
);
70 enable_irq(st
->spi
->irq
);
72 gpio_set_value(st
->pdata
->gpio_pdrst
, 1);
74 ret
= wait_event_interruptible(st
->wq_data_avail
, st
->done
);
75 disable_irq_nosync(st
->spi
->irq
);
79 ret
= spi_sync_locked(st
->spi
, &st
->msg
);
80 *val
= be32_to_cpu(st
->data
);
82 gpio_set_value(st
->pdata
->gpio_pdrst
, 0);
83 spi_bus_unlock(st
->spi
->master
);
88 static int ad7780_read_raw(struct iio_dev
*indio_dev
,
89 struct iio_chan_spec
const *chan
,
94 struct ad7780_state
*st
= iio_priv(indio_dev
);
95 struct iio_chan_spec channel
= st
->chip_info
->channel
;
97 unsigned long scale_uv
;
101 mutex_lock(&indio_dev
->mlock
);
102 ret
= ad7780_read(st
, &smpl
);
103 mutex_unlock(&indio_dev
->mlock
);
108 if ((smpl
& AD7780_ERR
) ||
109 !((smpl
& AD7780_PAT0
) && !(smpl
& AD7780_PAT1
)))
112 *val
= (smpl
>> channel
.scan_type
.shift
) &
113 ((1 << (channel
.scan_type
.realbits
)) - 1);
114 *val
-= (1 << (channel
.scan_type
.realbits
- 1));
116 if (!(smpl
& AD7780_GAIN
))
120 case (1 << IIO_CHAN_INFO_SCALE_SHARED
):
121 scale_uv
= (st
->int_vref_mv
* 100000)
122 >> (channel
.scan_type
.realbits
- 1);
123 *val
= scale_uv
/ 100000;
124 *val2
= (scale_uv
% 100000) * 10;
125 return IIO_VAL_INT_PLUS_MICRO
;
130 static const struct ad7780_chip_info ad7780_chip_info_tbl
[] = {
132 .channel
= IIO_CHAN(IIO_IN
, 0, 1, 0, NULL
, 0, 0,
133 (1 << IIO_CHAN_INFO_SCALE_SHARED
),
134 0, 0, IIO_ST('s', 24, 32, 8), 0),
137 .channel
= IIO_CHAN(IIO_IN
, 0, 1, 0, NULL
, 0, 0,
138 (1 << IIO_CHAN_INFO_SCALE_SHARED
),
139 0, 0, IIO_ST('s', 20, 32, 12), 0),
146 static irqreturn_t
ad7780_interrupt(int irq
, void *dev_id
)
148 struct ad7780_state
*st
= dev_id
;
151 wake_up_interruptible(&st
->wq_data_avail
);
156 static int __devinit
ad7780_probe(struct spi_device
*spi
)
158 struct ad7780_platform_data
*pdata
= spi
->dev
.platform_data
;
159 struct ad7780_state
*st
;
160 struct iio_dev
*indio_dev
;
161 int ret
, voltage_uv
= 0;
164 dev_dbg(&spi
->dev
, "no platform data?\n");
168 indio_dev
= iio_allocate_device(sizeof(*st
));
169 if (indio_dev
== NULL
)
172 st
= iio_priv(indio_dev
);
174 st
->reg
= regulator_get(&spi
->dev
, "vcc");
175 if (!IS_ERR(st
->reg
)) {
176 ret
= regulator_enable(st
->reg
);
180 voltage_uv
= regulator_get_voltage(st
->reg
);
184 &ad7780_chip_info_tbl
[spi_get_device_id(spi
)->driver_data
];
188 if (pdata
&& pdata
->vref_mv
)
189 st
->int_vref_mv
= pdata
->vref_mv
;
191 st
->int_vref_mv
= voltage_uv
/ 1000;
193 dev_warn(&spi
->dev
, "reference voltage unspecified\n");
195 spi_set_drvdata(spi
, indio_dev
);
198 indio_dev
->dev
.parent
= &spi
->dev
;
199 indio_dev
->name
= spi_get_device_id(spi
)->name
;
200 indio_dev
->driver_module
= THIS_MODULE
;
201 indio_dev
->modes
= INDIO_DIRECT_MODE
;
202 indio_dev
->channels
= &st
->chip_info
->channel
;
203 indio_dev
->num_channels
= 1;
204 indio_dev
->read_raw
= &ad7780_read_raw
;
206 init_waitqueue_head(&st
->wq_data_avail
);
208 /* Setup default message */
210 st
->xfer
.rx_buf
= &st
->data
;
211 st
->xfer
.len
= st
->chip_info
->channel
.scan_type
.storagebits
/ 8;
213 spi_message_init(&st
->msg
);
214 spi_message_add_tail(&st
->xfer
, &st
->msg
);
216 ret
= gpio_request_one(st
->pdata
->gpio_pdrst
, GPIOF_OUT_INIT_LOW
,
219 dev_err(&spi
->dev
, "failed to request GPIO PDRST\n");
220 goto error_disable_reg
;
223 ret
= request_irq(spi
->irq
, ad7780_interrupt
,
224 IRQF_TRIGGER_FALLING
, spi_get_device_id(spi
)->name
, st
);
226 goto error_free_gpio
;
228 disable_irq(spi
->irq
);
230 ret
= iio_device_register(indio_dev
);
237 free_irq(spi
->irq
, st
);
239 gpio_free(st
->pdata
->gpio_pdrst
);
241 if (!IS_ERR(st
->reg
))
242 regulator_disable(st
->reg
);
244 if (!IS_ERR(st
->reg
))
245 regulator_put(st
->reg
);
247 iio_free_device(indio_dev
);
252 static int ad7780_remove(struct spi_device
*spi
)
254 struct iio_dev
*indio_dev
= spi_get_drvdata(spi
);
255 struct ad7780_state
*st
= iio_priv(indio_dev
);
257 free_irq(spi
->irq
, st
);
258 gpio_free(st
->pdata
->gpio_pdrst
);
259 if (!IS_ERR(st
->reg
)) {
260 regulator_disable(st
->reg
);
261 regulator_put(st
->reg
);
263 iio_device_unregister(indio_dev
);
268 static const struct spi_device_id ad7780_id
[] = {
269 {"ad7780", ID_AD7780
},
270 {"ad7781", ID_AD7781
},
274 static struct spi_driver ad7780_driver
= {
277 .bus
= &spi_bus_type
,
278 .owner
= THIS_MODULE
,
280 .probe
= ad7780_probe
,
281 .remove
= __devexit_p(ad7780_remove
),
282 .id_table
= ad7780_id
,
285 static int __init
ad7780_init(void)
287 return spi_register_driver(&ad7780_driver
);
289 module_init(ad7780_init
);
291 static void __exit
ad7780_exit(void)
293 spi_unregister_driver(&ad7780_driver
);
295 module_exit(ad7780_exit
);
297 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
298 MODULE_DESCRIPTION("Analog Devices AD7780/1 ADC");
299 MODULE_LICENSE("GPL v2");