summaryrefslogtreecommitdiffstats
path: root/include/adc.h
blob: 4b1401784983b5da17603657b1ad67c6b4c35353 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
/*
 * Copyright (C) 2015 Samsung Electronics
 * Przemyslaw Marczak <p.marczak@samsung.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#ifndef _ADC_H_
#define _ADC_H_

/* ADC_CHANNEL() - ADC channel bit mask, to select only required channels */
#define ADC_CHANNEL(x)		(1 << x)

/* The last possible selected channel with 32-bit mask */
#define ADC_MAX_CHANNEL		31

/**
 * adc_data_format: define the ADC output data format, can be useful when
 * the device's input Voltage range is bipolar.
 * - ADC_DATA_FORMAT_BIN - binary offset
 * - ADC_DATA_FORMAT_2S  - two's complement
 *
 * Note: Device's driver should fill the 'data_format' field of its uclass's
 * platform data using one of the above data format types.
 */
enum adc_data_format {
	ADC_DATA_FORMAT_BIN,
	ADC_DATA_FORMAT_2S,
};

/**
 * struct adc_channel - structure to hold channel conversion data.
 * Useful to keep the result of a multi-channel conversion output.
 *
 * @id   - channel id
 * @data - channel conversion data
 */
struct adc_channel {
	int id;
	unsigned int data;
};

/**
 * struct adc_uclass_platdata - basic ADC info
 *
 * Note: The positive/negative reference Voltage is only a name and it doesn't
 * provide an information about the value polarity. It is possible, for both
 * values to be a negative or positive. For this purpose the uclass's platform
 * data provides a bool fields: 'vdd/vss_supply_is_negative'. This is useful,
 * since the regulator API returns only a positive Voltage values.
 *
 * To get the reference Voltage values with polarity, use functions:
 * - adc_vdd_value()
 * - adc_vss_value()
 * Those are useful for some cases of ADC's references, e.g.:
 * * Vdd: +3.3V; Vss: -3.3V -> 6.6 Vdiff
 * * Vdd: +3.3V; Vss: +0.3V -> 3.0 Vdiff
 * * Vdd: +3.3V; Vss:  0.0V -> 3.3 Vdiff
 * The last one is usually standard and doesn't require the fdt polarity info.
 *
 * For more informations read binding info:
 * - doc/device-tree-bindings/adc/adc.txt
 *
 * @data_mask              - conversion output data mask
 * @data_timeout_us        - single channel conversion timeout
 * @multidata_timeout_us   - multi channel conversion timeout
 * @channel_mask           - bit mask of available channels [0:31]
 * @vdd_supply             - positive reference Voltage supply (regulator)
 * @vss_supply             - negative reference Voltage supply (regulator)
 * @vdd_polarity_negative  - positive reference Voltage has negative polarity
 * @vss_polarity_negative  - negative reference Voltage has negative polarity
 * @vdd_microvolts         - positive reference Voltage value
 * @vss_microvolts         - negative reference Voltage value
 */
struct adc_uclass_platdata {
	int data_format;
	unsigned int data_mask;
	unsigned int data_timeout_us;
	unsigned int multidata_timeout_us;
	unsigned int channel_mask;
	struct udevice *vdd_supply;
	struct udevice *vss_supply;
	bool vdd_polarity_negative;
	bool vss_polarity_negative;
	int vdd_microvolts;
	int vss_microvolts;
};

/**
 * struct adc_ops - ADC device operations for single/multi-channel operation.
 */
struct adc_ops {
	/**
	 * start_channel() - start conversion with its default parameters
	 *                   for the given channel number.
	 *
	 * @dev:          ADC device to init
	 * @channel:      analog channel number
	 * @return:       0 if OK, -ve on error
	 */
	int (*start_channel)(struct udevice *dev, int channel);

	/**
	 * start_channels() - start conversion with its default parameters
	 *                    for the channel numbers selected by the bit mask.
	 *
	 * This is optional, useful when the hardware supports multichannel
	 * conversion by the single software trigger.
	 *
	 * @dev:          ADC device to init
	 * @channel_mask: bit mask of selected analog channels
	 * @return:       0 if OK, -ve on error
	 */
	int (*start_channels)(struct udevice *dev, unsigned int channel_mask);

	/**
	 * channel_data() - get conversion output data for the given channel.
	 *
	 * Note: The implementation of this function should only check, that
	 * the conversion data is available at the call time. If the hardware
	 * requires some delay to get the data, then this function should
	 * return with -EBUSY value. The ADC API will call it in a loop,
	 * until the data is available or the timeout expires. The maximum
	 * timeout for this operation is defined by the field 'data_timeout_us'
	 * in ADC uclasses platform data structure.
	 *
	 * @dev:          ADC device to trigger
	 * @channel:      selected analog channel number
	 * @data:         returned pointer to selected channel's output data
	 * @return:       0 if OK, -EBUSY if busy, and other negative on error
	 */
	int (*channel_data)(struct udevice *dev, int channel,
			    unsigned int *data);

	/**
	 * channels_data() - get conversion data for the selected channels.
	 *
	 * This is optional, useful when multichannel conversion is supported
	 * by the hardware, by the single software trigger.
	 *
	 * For the proper implementation, please look at the 'Note' for the
	 * above method. The only difference is in used timeout value, which
	 * is defined by field 'multidata_timeout_us'.
	 *
	 * @dev:          ADC device to trigger
	 * @channel_mask: bit mask of selected analog channels
	 * @channels:     returned pointer to array of output data for channels
	 *                selected by the given mask
	 * @return:       0 if OK, -ve on error
	 */
	int (*channels_data)(struct udevice *dev, unsigned int channel_mask,
			     struct adc_channel *channels);

	/**
	 * stop() - stop conversion of the given ADC device
	 *
	 * @dev:          ADC device to stop
	 * @return:       0 if OK, -ve on error
	 */
	int (*stop)(struct udevice *dev);
};

/**
 * adc_start_channel() - start conversion for given device/channel and exit.
 *
 * @dev:     ADC device
 * @channel: analog channel number
 * @return:  0 if OK, -ve on error
 */
int adc_start_channel(struct udevice *dev, int channel);

/**
 * adc_start_channels() - start conversion for given device/channels and exit.
 *
 * Note:
 * To use this function, device must implement method: start_channels().
 *
 * @dev:          ADC device to start
 * @channel_mask: channel selection - a bit mask
 * @channel_mask: bit mask of analog channels
 * @return:       0 if OK, -ve on error
 */
int adc_start_channels(struct udevice *dev, unsigned int channel_mask);

/**
 * adc_channel_data() - get conversion data for the given device channel number.
 *
 * @dev:     ADC device to read
 * @channel: analog channel number
 * @data:    pointer to returned channel's data
 * @return:  0 if OK, -ve on error
 */
int adc_channel_data(struct udevice *dev, int channel, unsigned int *data);

/**
 * adc_channels_data() - get conversion data for the channels selected by mask
 *
 * Note:
 * To use this function, device must implement methods:
 * - start_channels()
 * - channels_data()
 *
 * @dev:          ADC device to read
 * @channel_mask: channel selection - a bit mask
 * @channels:     pointer to structure array of returned data for each channel
 * @return:       0 if OK, -ve on error
 */
int adc_channels_data(struct udevice *dev, unsigned int channel_mask,
		      struct adc_channel *channels);

/**
 * adc_data_mask() - get data mask (ADC resolution bitmask) for given ADC device
 *
 * This can be used if adc uclass platform data is filled.
 *
 * @dev:       ADC device to check
 * @data_mask: pointer to the returned data bitmask
 * @return: 0 if OK, -ve on error
 */
int adc_data_mask(struct udevice *dev, unsigned int *data_mask);

/**
 * adc_channel_single_shot() - get output data of conversion for the ADC
 * device's channel. This function searches for the device with the given name,
 * starts the given channel conversion and returns the output data.
 *
 * Note: To use this function, device must implement metods:
 * - start_channel()
 * - channel_data()
 *
 * @name:    device's name to search
 * @channel: device's input channel to init
 * @data:    pointer to conversion output data
 * @return:  0 if OK, -ve on error
 */
int adc_channel_single_shot(const char *name, int channel, unsigned int *data);

/**
 * adc_channels_single_shot() - get ADC conversion output data for the selected
 * device's channels. This function searches for the device by the given name,
 * starts the selected channels conversion and returns the output data as array
 * of type 'struct adc_channel'.
 *
 * Note: This function can be used if device implements one of ADC's single
 * or multi-channel operation API. If multi-channel operation is not supported,
 * then each selected channel is triggered by the sequence start/data in a loop.
 *
 * @name:         device's name to search
 * @channel_mask: channel selection - a bit mask
 * @channels:     pointer to conversion output data for the selected channels
 * @return:       0 if OK, -ve on error
 */
int adc_channels_single_shot(const char *name, unsigned int channel_mask,
			     struct adc_channel *channels);

/**
 * adc_vdd_value() - get the ADC device's positive reference Voltage value
 *
 * Note: Depending on bool value 'vdd_supply_is_negative' of platform data,
 * the returned uV value can be negative, and it's not an error.
 *
 * @dev:     ADC device to check
 * @uV:      Voltage value with polarization sign (uV)
 * @return:  0 on success or -ve on error
*/
int adc_vdd_value(struct udevice *dev, int *uV);

/**
 * adc_vss_value() - get the ADC device's negative reference Voltage value
 *
 * Note: Depending on bool value 'vdd_supply_is_negative' of platform data,
 * the returned uV value can be negative, and it's not an error.
 *
 * @dev:     ADC device to check
 * @uV:      Voltage value with polarization sign (uV)
 * @return:  0 on success or -ve on error
*/
int adc_vss_value(struct udevice *dev, int *uV);

/**
 * adc_stop() - stop operation for given ADC device.
 *
 * @dev:     ADC device to stop
 * @return:  0 if OK, -ve on error
 */
int adc_stop(struct udevice *dev);

#endif