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/device.h>
11 #include <linux/kernel.h>
12 #include <linux/slab.h>
13 #include <linux/sysfs.h>
14 #include <linux/spi/spi.h>
15 #include <linux/regulator/consumer.h>
16 #include <linux/err.h>
17 #include <linux/sched.h>
18 #include <linux/gpio.h>
22 #include "../ring_generic.h"
27 #define AD7780_RDY (1 << 7)
28 #define AD7780_FILTER (1 << 6)
29 #define AD7780_ERR (1 << 5)
30 #define AD7780_ID1 (1 << 4)
31 #define AD7780_ID0 (1 << 3)
32 #define AD7780_GAIN (1 << 2)
33 #define AD7780_PAT1 (1 << 1)
34 #define AD7780_PAT0 (1 << 0)
36 struct ad7780_chip_info
{
37 struct iio_chan_spec channel
;
41 struct spi_device
*spi
;
42 const struct ad7780_chip_info
*chip_info
;
43 struct regulator
*reg
;
44 struct ad7780_platform_data
*pdata
;
45 wait_queue_head_t wq_data_avail
;
48 struct spi_transfer xfer
;
49 struct spi_message msg
;
51 * DMA (thus cache coherency maintenance) requires the
52 * transfer buffers to live in their own cache lines.
54 unsigned int data ____cacheline_aligned
;
57 enum ad7780_supported_device_ids
{
62 static int ad7780_read(struct ad7780_state
*st
, int *val
)
66 spi_bus_lock(st
->spi
->master
);
68 enable_irq(st
->spi
->irq
);
70 gpio_set_value(st
->pdata
->gpio_pdrst
, 1);
72 ret
= wait_event_interruptible(st
->wq_data_avail
, st
->done
);
73 disable_irq_nosync(st
->spi
->irq
);
77 ret
= spi_sync_locked(st
->spi
, &st
->msg
);
78 *val
= be32_to_cpu(st
->data
);
80 gpio_set_value(st
->pdata
->gpio_pdrst
, 0);
81 spi_bus_unlock(st
->spi
->master
);
86 static int ad7780_read_raw(struct iio_dev
*indio_dev
,
87 struct iio_chan_spec
const *chan
,
92 struct ad7780_state
*st
= iio_priv(indio_dev
);
93 struct iio_chan_spec channel
= st
->chip_info
->channel
;
95 unsigned long scale_uv
;
99 mutex_lock(&indio_dev
->mlock
);
100 ret
= ad7780_read(st
, &smpl
);
101 mutex_unlock(&indio_dev
->mlock
);
106 if ((smpl
& AD7780_ERR
) ||
107 !((smpl
& AD7780_PAT0
) && !(smpl
& AD7780_PAT1
)))
110 *val
= (smpl
>> channel
.scan_type
.shift
) &
111 ((1 << (channel
.scan_type
.realbits
)) - 1);
112 *val
-= (1 << (channel
.scan_type
.realbits
- 1));
114 if (!(smpl
& AD7780_GAIN
))
118 case (1 << IIO_CHAN_INFO_SCALE_SHARED
):
119 scale_uv
= (st
->int_vref_mv
* 100000)
120 >> (channel
.scan_type
.realbits
- 1);
121 *val
= scale_uv
/ 100000;
122 *val2
= (scale_uv
% 100000) * 10;
123 return IIO_VAL_INT_PLUS_MICRO
;
128 static const struct ad7780_chip_info ad7780_chip_info_tbl
[] = {
130 .channel
= IIO_CHAN(IIO_IN
, 0, 1, 0, NULL
, 0, 0,
131 (1 << IIO_CHAN_INFO_SCALE_SHARED
),
132 0, 0, IIO_ST('s', 24, 32, 8), 0),
135 .channel
= IIO_CHAN(IIO_IN
, 0, 1, 0, NULL
, 0, 0,
136 (1 << IIO_CHAN_INFO_SCALE_SHARED
),
137 0, 0, IIO_ST('s', 20, 32, 12), 0),
144 static irqreturn_t
ad7780_interrupt(int irq
, void *dev_id
)
146 struct ad7780_state
*st
= dev_id
;
149 wake_up_interruptible(&st
->wq_data_avail
);
154 static const struct iio_info ad7780_info
= {
155 .read_raw
= &ad7780_read_raw
,
156 .driver_module
= THIS_MODULE
,
159 static int __devinit
ad7780_probe(struct spi_device
*spi
)
161 struct ad7780_platform_data
*pdata
= spi
->dev
.platform_data
;
162 struct ad7780_state
*st
;
163 struct iio_dev
*indio_dev
;
164 int ret
, voltage_uv
= 0;
167 dev_dbg(&spi
->dev
, "no platform data?\n");
171 indio_dev
= iio_allocate_device(sizeof(*st
));
172 if (indio_dev
== NULL
)
175 st
= iio_priv(indio_dev
);
177 st
->reg
= regulator_get(&spi
->dev
, "vcc");
178 if (!IS_ERR(st
->reg
)) {
179 ret
= regulator_enable(st
->reg
);
183 voltage_uv
= regulator_get_voltage(st
->reg
);
187 &ad7780_chip_info_tbl
[spi_get_device_id(spi
)->driver_data
];
191 if (pdata
&& pdata
->vref_mv
)
192 st
->int_vref_mv
= pdata
->vref_mv
;
194 st
->int_vref_mv
= voltage_uv
/ 1000;
196 dev_warn(&spi
->dev
, "reference voltage unspecified\n");
198 spi_set_drvdata(spi
, indio_dev
);
201 indio_dev
->dev
.parent
= &spi
->dev
;
202 indio_dev
->name
= spi_get_device_id(spi
)->name
;
203 indio_dev
->modes
= INDIO_DIRECT_MODE
;
204 indio_dev
->channels
= &st
->chip_info
->channel
;
205 indio_dev
->num_channels
= 1;
206 indio_dev
->info
= &ad7780_info
;
208 init_waitqueue_head(&st
->wq_data_avail
);
210 /* Setup default message */
212 st
->xfer
.rx_buf
= &st
->data
;
213 st
->xfer
.len
= st
->chip_info
->channel
.scan_type
.storagebits
/ 8;
215 spi_message_init(&st
->msg
);
216 spi_message_add_tail(&st
->xfer
, &st
->msg
);
218 ret
= gpio_request_one(st
->pdata
->gpio_pdrst
, GPIOF_OUT_INIT_LOW
,
221 dev_err(&spi
->dev
, "failed to request GPIO PDRST\n");
222 goto error_disable_reg
;
225 ret
= request_irq(spi
->irq
, ad7780_interrupt
,
226 IRQF_TRIGGER_FALLING
, spi_get_device_id(spi
)->name
, st
);
228 goto error_free_gpio
;
230 disable_irq(spi
->irq
);
232 ret
= iio_device_register(indio_dev
);
239 free_irq(spi
->irq
, st
);
241 gpio_free(st
->pdata
->gpio_pdrst
);
243 if (!IS_ERR(st
->reg
))
244 regulator_disable(st
->reg
);
246 if (!IS_ERR(st
->reg
))
247 regulator_put(st
->reg
);
249 iio_free_device(indio_dev
);
254 static int ad7780_remove(struct spi_device
*spi
)
256 struct iio_dev
*indio_dev
= spi_get_drvdata(spi
);
257 struct ad7780_state
*st
= iio_priv(indio_dev
);
259 free_irq(spi
->irq
, st
);
260 gpio_free(st
->pdata
->gpio_pdrst
);
261 if (!IS_ERR(st
->reg
)) {
262 regulator_disable(st
->reg
);
263 regulator_put(st
->reg
);
265 iio_device_unregister(indio_dev
);
270 static const struct spi_device_id ad7780_id
[] = {
271 {"ad7780", ID_AD7780
},
272 {"ad7781", ID_AD7781
},
276 static struct spi_driver ad7780_driver
= {
279 .bus
= &spi_bus_type
,
280 .owner
= THIS_MODULE
,
282 .probe
= ad7780_probe
,
283 .remove
= __devexit_p(ad7780_remove
),
284 .id_table
= ad7780_id
,
287 static int __init
ad7780_init(void)
289 return spi_register_driver(&ad7780_driver
);
291 module_init(ad7780_init
);
293 static void __exit
ad7780_exit(void)
295 spi_unregister_driver(&ad7780_driver
);
297 module_exit(ad7780_exit
);
299 MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
300 MODULE_DESCRIPTION("Analog Devices AD7780/1 ADC");
301 MODULE_LICENSE("GPL v2");