aboutsummaryrefslogtreecommitdiffstats
path: root/include
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:12 -0400
commitaf3008485ea0372fb9ce1f69f3768617d39eb4e6 (patch)
treed6c6ca6ed6f6ec0a84e43827503870fd05bb7fac /include
parent2d66f389ccf2c3ffea93c0270ef34186e4995333 (diff)
iio:adc: Add common code for ADI Sigma Delta devices
Most devices from the Analog Devices Sigma Delta family use a similar scheme for communication with the device. This includes register access, as well as trigger handling. But each device sub-family has different features and different register layouts (some even have no registers at all) and thus it is impractical to try to support all of the devices by the same driver. This patch adds a common base library for Sigma Delta converter devices. It will be used by individual drivers. This code is mostly based on the three existing Sigma Delta drivers the AD7192, AD7780 and AD7793, but has been improved for more robustness and flexibility. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/iio/adc/ad_sigma_delta.h173
1 files changed, 173 insertions, 0 deletions
diff --git a/include/linux/iio/adc/ad_sigma_delta.h b/include/linux/iio/adc/ad_sigma_delta.h
new file mode 100644
index 000000000000..2e4eab9868a3
--- /dev/null
+++ b/include/linux/iio/adc/ad_sigma_delta.h
@@ -0,0 +1,173 @@
1/*
2 * Support code for Analog Devices Sigma-Delta ADCs
3 *
4 * Copyright 2012 Analog Devices Inc.
5 * Author: Lars-Peter Clausen <lars@metafoo.de>
6 *
7 * Licensed under the GPL-2.
8 */
9#ifndef __AD_SIGMA_DELTA_H__
10#define __AD_SIGMA_DELTA_H__
11
12enum ad_sigma_delta_mode {
13 AD_SD_MODE_CONTINUOUS = 0,
14 AD_SD_MODE_SINGLE = 1,
15 AD_SD_MODE_IDLE = 2,
16 AD_SD_MODE_POWERDOWN = 3,
17};
18
19/**
20 * struct ad_sigma_delta_calib_data - Calibration data for Sigma Delta devices
21 * @mode: Calibration mode.
22 * @channel: Calibration channel.
23 */
24struct ad_sd_calib_data {
25 unsigned int mode;
26 unsigned int channel;
27};
28
29struct ad_sigma_delta;
30struct iio_dev;
31
32/**
33 * struct ad_sigma_delta_info - Sigma Delta driver specific callbacks and options
34 * @set_channel: Will be called to select the current channel, may be NULL.
35 * @set_mode: Will be called to select the current mode, may be NULL.
36 * @postprocess_sample: Is called for each sampled data word, can be used to
37 * modify or drop the sample data, it, may be NULL.
38 * @has_registers: true if the device has writable and readable registers, false
39 * if there is just one read-only sample data shift register.
40 * @addr_shift: Shift of the register address in the communications register.
41 * @read_mask: Mask for the communications register having the read bit set.
42 */
43struct ad_sigma_delta_info {
44 int (*set_channel)(struct ad_sigma_delta *, unsigned int channel);
45 int (*set_mode)(struct ad_sigma_delta *, enum ad_sigma_delta_mode mode);
46 int (*postprocess_sample)(struct ad_sigma_delta *, unsigned int raw_sample);
47 bool has_registers;
48 unsigned int addr_shift;
49 unsigned int read_mask;
50};
51
52/**
53 * struct ad_sigma_delta - Sigma Delta device struct
54 * @spi: The spi device associated with the Sigma Delta device.
55 * @trig: The IIO trigger associated with the Sigma Delta device.
56 *
57 * Most of the fields are private to the sigma delta library code and should not
58 * be accessed by individual drivers.
59 */
60struct ad_sigma_delta {
61 struct spi_device *spi;
62 struct iio_trigger *trig;
63
64/* private: */
65 struct completion completion;
66 bool irq_dis;
67
68 bool bus_locked;
69
70 uint8_t comm;
71
72 const struct ad_sigma_delta_info *info;
73
74 /*
75 * DMA (thus cache coherency maintenance) requires the
76 * transfer buffers to live in their own cache lines.
77 */
78 uint8_t data[4] ____cacheline_aligned;
79};
80
81static inline int ad_sigma_delta_set_channel(struct ad_sigma_delta *sd,
82 unsigned int channel)
83{
84 if (sd->info->set_channel)
85 return sd->info->set_channel(sd, channel);
86
87 return 0;
88}
89
90static inline int ad_sigma_delta_set_mode(struct ad_sigma_delta *sd,
91 unsigned int mode)
92{
93 if (sd->info->set_mode)
94 return sd->info->set_mode(sd, mode);
95
96 return 0;
97}
98
99static inline int ad_sigma_delta_postprocess_sample(struct ad_sigma_delta *sd,
100 unsigned int raw_sample)
101{
102 if (sd->info->postprocess_sample)
103 return sd->info->postprocess_sample(sd, raw_sample);
104
105 return 0;
106}
107
108void ad_sd_set_comm(struct ad_sigma_delta *sigma_delta, uint8_t comm);
109int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
110 unsigned int size, unsigned int val);
111int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
112 unsigned int size, unsigned int *val);
113
114int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
115 const struct iio_chan_spec *chan, int *val);
116int ad_sd_calibrate_all(struct ad_sigma_delta *sigma_delta,
117 const struct ad_sd_calib_data *cd, unsigned int n);
118int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
119 struct spi_device *spi, const struct ad_sigma_delta_info *info);
120
121int ad_sd_setup_buffer_and_trigger(struct iio_dev *indio_dev);
122void ad_sd_cleanup_buffer_and_trigger(struct iio_dev *indio_dev);
123
124int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig);
125
126#define __AD_SD_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
127 _storagebits, _shift, _extend_name, _type) \
128 { \
129 .type = (_type), \
130 .differential = (_channel2 == -1 ? 0 : 1), \
131 .indexed = 1, \
132 .channel = (_channel1), \
133 .channel2 = (_channel2), \
134 .address = (_address), \
135 .extend_name = (_extend_name), \
136 .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
137 IIO_CHAN_INFO_SCALE_SHARED_BIT | \
138 IIO_CHAN_INFO_OFFSET_SEPARATE_BIT, \
139 .scan_index = (_si), \
140 .scan_type = { \
141 .sign = 'u', \
142 .realbits = (_bits), \
143 .storagebits = (_storagebits), \
144 .shift = (_shift), \
145 .endianness = IIO_BE, \
146 }, \
147 }
148
149#define AD_SD_DIFF_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
150 _storagebits, _shift) \
151 __AD_SD_CHANNEL(_si, _channel1, _channel2, _address, _bits, \
152 _storagebits, _shift, NULL, IIO_VOLTAGE)
153
154#define AD_SD_SHORTED_CHANNEL(_si, _channel, _address, _bits, \
155 _storagebits, _shift) \
156 __AD_SD_CHANNEL(_si, _channel, _channel, _address, _bits, \
157 _storagebits, _shift, "shorted", IIO_VOLTAGE)
158
159#define AD_SD_CHANNEL(_si, _channel, _address, _bits, \
160 _storagebits, _shift) \
161 __AD_SD_CHANNEL(_si, _channel, -1, _address, _bits, \
162 _storagebits, _shift, NULL, IIO_VOLTAGE)
163
164#define AD_SD_TEMP_CHANNEL(_si, _address, _bits, _storagebits, _shift) \
165 __AD_SD_CHANNEL(_si, 0, -1, _address, _bits, \
166 _storagebits, _shift, NULL, IIO_TEMP)
167
168#define AD_SD_SUPPLY_CHANNEL(_si, _channel, _address, _bits, _storagebits, \
169 _shift) \
170 __AD_SD_CHANNEL(_si, _channel, -1, _address, _bits, \
171 _storagebits, _shift, "supply", IIO_VOLTAGE)
172
173#endif