diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-22 10:38:37 -0500 |
commit | fcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch) | |
tree | a57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/staging/iio | |
parent | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff) |
Diffstat (limited to 'drivers/staging/iio')
78 files changed, 21277 insertions, 0 deletions
diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio b/drivers/staging/iio/Documentation/sysfs-bus-iio new file mode 100644 index 00000000000..467c49a4725 --- /dev/null +++ b/drivers/staging/iio/Documentation/sysfs-bus-iio | |||
@@ -0,0 +1,713 @@ | |||
1 | What: /sys/bus/iio/devices/deviceX | ||
2 | KernelVersion: 2.6.35 | ||
3 | Contact: linux-iio@vger.kernel.org | ||
4 | Description: | ||
5 | Hardware chip or device accessed by on communication port. | ||
6 | Corresponds to a grouping of sensor channels. X is the IIO | ||
7 | index of the device. | ||
8 | |||
9 | What: /sys/bus/iio/devices/device[n]/power_state | ||
10 | KernelVersion: 2.6.37 | ||
11 | Contact: linux-iio@vger.kernel.org | ||
12 | Description: | ||
13 | This property gets/sets the device power state. | ||
14 | |||
15 | What: /sys/bus/iio/devices/triggerX | ||
16 | KernelVersion: 2.6.35 | ||
17 | Contact: linux-iio@vger.kernel.org | ||
18 | Description: | ||
19 | An event driven driver of data capture to an in kernel buffer. | ||
20 | May be provided by a device driver that also has an IIO device | ||
21 | based on hardware generated events (e.g. data ready) or | ||
22 | provided by a separate driver for other hardware (e.g. | ||
23 | periodic timer, GPIO or high resolution timer). | ||
24 | Contains trigger type specific elements. These do not | ||
25 | generalize well and hence are not documented in this file. | ||
26 | X is the IIO index of the trigger. | ||
27 | |||
28 | What: /sys/bus/iio/devices/deviceX:buffer | ||
29 | KernelVersion: 2.6.35 | ||
30 | Contact: linux-iio@vger.kernel.org | ||
31 | Description: | ||
32 | Link to /sys/class/iio/deviceX/deviceX:buffer. X indicates | ||
33 | the device with which this buffer buffer is associated. | ||
34 | |||
35 | What: /sys/bus/iio/devices/deviceX/name | ||
36 | KernelVersion: 2.6.35 | ||
37 | Contact: linux-iio@vger.kernel.org | ||
38 | Description: | ||
39 | Description of the physical chip / device for device X. | ||
40 | Typically a part number. | ||
41 | |||
42 | What: /sys/bus/iio/devices/deviceX/sampling_frequency | ||
43 | KernelVersion: 2.6.35 | ||
44 | Contact: linux-iio@vger.kernel.org | ||
45 | Description: | ||
46 | Some devices have internal clocks. This parameter sets the | ||
47 | resulting sampling frequency. In many devices this | ||
48 | parameter has an effect on input filters etc rather than | ||
49 | simply controlling when the input is sampled. As this | ||
50 | effects datardy triggers, hardware buffers and the sysfs | ||
51 | direct access interfaces, it may be found in any of the | ||
52 | relevant directories. If it effects all of the above | ||
53 | then it is to be found in the base device directory as here. | ||
54 | |||
55 | What: /sys/bus/iio/devices/deviceX/sampling_frequency_available | ||
56 | KernelVersion: 2.6.35 | ||
57 | Contact: linux-iio@vger.kernel.org | ||
58 | Description: | ||
59 | When the internal sampling clock can only take a small | ||
60 | discrete set of values, this file lists those available. | ||
61 | |||
62 | What: /sys/bus/iio/devices/deviceX/range | ||
63 | KernelVersion: 2.6.38 | ||
64 | Contact: linux-iio@vger.kernel.org | ||
65 | Description: | ||
66 | Hardware dependent ADC Full Scale Range in mVolt. | ||
67 | |||
68 | What: /sys/bus/iio/devices/deviceX/range_available | ||
69 | KernelVersion: 2.6.38 | ||
70 | Contact: linux-iio@vger.kernel.org | ||
71 | Description: | ||
72 | Hardware dependent supported vales for ADC Full Scale Range. | ||
73 | |||
74 | What: /sys/bus/iio/devices/deviceX/oversampling_ratio | ||
75 | KernelVersion: 2.6.38 | ||
76 | Contact: linux-iio@vger.kernel.org | ||
77 | Description: | ||
78 | Hardware dependent ADC oversampling. Controls the sampling ratio | ||
79 | of the digital filter if available. | ||
80 | |||
81 | What: /sys/bus/iio/devices/deviceX/oversampling_ratio_available | ||
82 | KernelVersion: 2.6.38 | ||
83 | Contact: linux-iio@vger.kernel.org | ||
84 | Description: | ||
85 | Hardware dependent values supported by the oversampling filter. | ||
86 | |||
87 | What: /sys/bus/iio/devices/deviceX/inY_raw | ||
88 | What: /sys/bus/iio/devices/deviceX/inY_supply_raw | ||
89 | KernelVersion: 2.6.35 | ||
90 | Contact: linux-iio@vger.kernel.org | ||
91 | Description: | ||
92 | Raw (unscaled no bias removal etc) voltage measurement from | ||
93 | channel Y. In special cases where the channel does not | ||
94 | correspond to externally available input one of the named | ||
95 | versions may be used. The number must always be specified and | ||
96 | unique to allow association with event codes. | ||
97 | |||
98 | What: /sys/bus/iio/devices/deviceX/inY-inZ_raw | ||
99 | KernelVersion: 2.6.35 | ||
100 | Contact: linux-iio@vger.kernel.org | ||
101 | Description: | ||
102 | Raw (unscaled) differential voltage measurement equivalent to | ||
103 | channel Y - channel Z where these channel numbers apply to the | ||
104 | physically equivalent inputs when non differential readings are | ||
105 | separately available. In differential only parts, then all that | ||
106 | is required is a consistent labeling. | ||
107 | |||
108 | What: /sys/bus/iio/devices/deviceX/temp_raw | ||
109 | What: /sys/bus/iio/devices/deviceX/temp_x_raw | ||
110 | What: /sys/bus/iio/devices/deviceX/temp_y_raw | ||
111 | What: /sys/bus/iio/devices/deviceX/temp_z_raw | ||
112 | KernelVersion: 2.6.35 | ||
113 | Contact: linux-iio@vger.kernel.org | ||
114 | Description: | ||
115 | Raw (unscaled no bias removal etc) temperature measurement. | ||
116 | It an axis is specified it generally means that the temperature | ||
117 | sensor is associated with one part of a compound device (e.g. | ||
118 | a gyroscope axis). | ||
119 | |||
120 | What: /sys/bus/iio/devices/deviceX/tempX_input | ||
121 | KernelVersion: 2.6.38 | ||
122 | Contact: linux-iio@vger.kernel.org | ||
123 | Description: | ||
124 | Scaled temperature measurement in milli degrees Celsius. | ||
125 | |||
126 | What: /sys/bus/iio/devices/deviceX/accel_x_raw | ||
127 | What: /sys/bus/iio/devices/deviceX/accel_y_raw | ||
128 | What: /sys/bus/iio/devices/deviceX/accel_z_raw | ||
129 | KernelVersion: 2.6.35 | ||
130 | Contact: linux-iio@vger.kernel.org | ||
131 | Description: | ||
132 | Acceleration in direction x, y or z (may be arbitrarily assigned | ||
133 | but should match other such assignments on device) | ||
134 | channel m (not present if only one accelerometer channel at | ||
135 | this orientation). Has all of the equivalent parameters as per | ||
136 | inY. Units after application of scale and offset are m/s^2. | ||
137 | |||
138 | What: /sys/bus/iio/devices/deviceX/gyro_x_raw | ||
139 | What: /sys/bus/iio/devices/deviceX/gyro_y_raw | ||
140 | What: /sys/bus/iio/devices/deviceX/gyro_z_raw | ||
141 | KernelVersion: 2.6.35 | ||
142 | Contact: linux-iio@vger.kernel.org | ||
143 | Description: | ||
144 | Angular velocity about axis x, y or z (may be arbitrarily | ||
145 | assigned) Data converted by application of offset then scale to | ||
146 | radians per second. Has all the equivalent parameters as | ||
147 | per inY. | ||
148 | |||
149 | What: /sys/bus/iio/devices/deviceX/incli_x_raw | ||
150 | What: /sys/bus/iio/devices/deviceX/incli_y_raw | ||
151 | What: /sys/bus/iio/devices/deviceX/incli_z_raw | ||
152 | KernelVersion: 2.6.35 | ||
153 | Contact: linux-iio@vger.kernel.org | ||
154 | Description: | ||
155 | Inclination raw reading about axis x, y or z (may be | ||
156 | arbitrarily assigned). Data converted by application of offset | ||
157 | and scale to Degrees. | ||
158 | |||
159 | What: /sys/bus/iio/devices/deviceX/magn_x_raw | ||
160 | What: /sys/bus/iio/devices/deviceX/magn_y_raw | ||
161 | What: /sys/bus/iio/devices/deviceX/magn_z_raw | ||
162 | KernelVersion: 2.6.35 | ||
163 | Contact: linux-iio@vger.kernel.org | ||
164 | Description: | ||
165 | Magnetic field along axis x, y or z (may be arbitrarily | ||
166 | assigned) channel m (not present if only one magnetometer | ||
167 | at this orientation). Data converted by application of | ||
168 | offset then scale to Gauss. Has all the equivalent modifiers | ||
169 | as per inY. | ||
170 | |||
171 | What: /sys/bus/iio/devices/deviceX/accel_x_peak_raw | ||
172 | What: /sys/bus/iio/devices/deviceX/accel_y_peak_raw | ||
173 | What: /sys/bus/iio/devices/deviceX/accel_z_peak_raw | ||
174 | KernelVersion: 2.6.36 | ||
175 | Contact: linux-iio@vger.kernel.org | ||
176 | Description: | ||
177 | Some devices provide a store of the highest value seen since | ||
178 | some reset condition. These attributes allow access to this | ||
179 | and are otherwise the direct equivalent of the | ||
180 | <type>Y[_name]_raw attributes. | ||
181 | |||
182 | What: /sys/bus/iio/devices/deviceX/accel_xyz_squared_peak_raw | ||
183 | KernelVersion: 2.6.36 | ||
184 | Contact: linux-iio@vger.kernel.org | ||
185 | Description: | ||
186 | A computed peak value based on the sum squared magnitude of | ||
187 | the underlying value in the specified directions. | ||
188 | |||
189 | What: /sys/bus/iio/devices/deviceX/accel_offset | ||
190 | What: /sys/bus/iio/devices/deviceX/temp_offset | ||
191 | KernelVersion: 2.6.35 | ||
192 | Contact: linux-iio@vger.kernel.org | ||
193 | Description: | ||
194 | If known for a device, offset to be added to <type>[Y]_raw prior | ||
195 | to scaling by <type>[Y]_scale in order to obtain value in the | ||
196 | <type> units as specified in <type>[y]_raw documentation. | ||
197 | Not present if the offset is always 0 or unknown. If Y is not | ||
198 | present, then the offset applies to all in channels of <type>. | ||
199 | May be writable if a variable offset can be applied on the | ||
200 | device. Note that this is different to calibbias which | ||
201 | is for devices (or drivers) that apply offsets to compensate | ||
202 | for variation between different instances of the part, typically | ||
203 | adjusted by using some hardware supported calibration procedure. | ||
204 | |||
205 | What: /sys/bus/iio/devices/deviceX/inY_scale | ||
206 | What: /sys/bus/iio/devices/deviceX/inY_supply_scale | ||
207 | What: /sys/bus/iio/devices/deviceX/in_scale | ||
208 | What: /sys/bus/iio/devices/deviceX/outY_scale | ||
209 | What: /sys/bus/iio/devices/deviceX/accel_scale | ||
210 | What: /sys/bus/iio/devices/deviceX/accel_peak_scale | ||
211 | What: /sys/bus/iio/devices/deviceX/gyro_scale | ||
212 | What: /sys/bus/iio/devices/deviceX/magn_scale | ||
213 | What: /sys/bus/iio/devices/deviceX/magn_x_scale | ||
214 | What: /sys/bus/iio/devices/deviceX/magn_y_scale | ||
215 | What: /sys/bus/iio/devices/deviceX/magn_z_scale | ||
216 | KernelVersion: 2.6.35 | ||
217 | Contact: linux-iio@vger.kernel.org | ||
218 | Description: | ||
219 | If known for a device, scale to be applied to <type>Y[_name]_raw | ||
220 | post addition of <type>[Y][_name]_offset in order to obtain the | ||
221 | measured value in <type> units as specified in | ||
222 | <type>[Y][_name]_raw documentation.. If shared across all in | ||
223 | channels then Y is not present and the value is called | ||
224 | <type>[Y][_name]_scale. The peak modifier means this value | ||
225 | is applied to <type>Y[_name]_peak_raw values. | ||
226 | |||
227 | What: /sys/bus/iio/devices/deviceX/accel_x_calibbias | ||
228 | What: /sys/bus/iio/devices/deviceX/accel_y_calibbias | ||
229 | What: /sys/bus/iio/devices/deviceX/accel_z_calibbias | ||
230 | What: /sys/bus/iio/devices/deviceX/gyro_x_calibbias | ||
231 | What: /sys/bus/iio/devices/deviceX/gyro_y_calibbias | ||
232 | What: /sys/bus/iio/devices/deviceX/gyro_z_calibbias | ||
233 | KernelVersion: 2.6.35 | ||
234 | Contact: linux-iio@vger.kernel.org | ||
235 | Description: | ||
236 | Hardware applied calibration offset. (assumed to fix production | ||
237 | inaccuracies). If shared across all channels, <type>_calibbias | ||
238 | is used. | ||
239 | |||
240 | What /sys/bus/iio/devices/deviceX/inY_calibscale | ||
241 | What /sys/bus/iio/devices/deviceX/inY_supply_calibscale | ||
242 | What /sys/bus/iio/devices/deviceX/in_calibscale | ||
243 | What /sys/bus/iio/devices/deviceX/accel_x_calibscale | ||
244 | What /sys/bus/iio/devices/deviceX/accel_y_calibscale | ||
245 | What /sys/bus/iio/devices/deviceX/accel_z_calibscale | ||
246 | What /sys/bus/iio/devices/deviceX/gyro_x_calibscale | ||
247 | What /sys/bus/iio/devices/deviceX/gyro_y_calibscale | ||
248 | What /sys/bus/iio/devices/deviceX/gyro_z_calibscale | ||
249 | KernelVersion: 2.6.35 | ||
250 | Contact: linux-iio@vger.kernel.org | ||
251 | Description: | ||
252 | Hardware applied calibration scale factor. (assumed to fix | ||
253 | production inaccuracies). If shared across all channels, | ||
254 | <type>_calibscale is used. | ||
255 | |||
256 | What: /sys/bus/iio/devices/deviceX/accel_scale_available | ||
257 | KernelVersion: 2.635 | ||
258 | Contact: linux-iio@vger.kernel.org | ||
259 | Description: | ||
260 | If a discrete set of scale values are available, they | ||
261 | are listed in this attribute. | ||
262 | |||
263 | What: /sys/bus/iio/devices/deviceX/outY_raw | ||
264 | KernelVersion: 2.6.37 | ||
265 | Contact: linux-iio@vger.kernel.org | ||
266 | Description: | ||
267 | Raw (unscaled, no bias etc.) output voltage for | ||
268 | channel Y. The number must always be specified and | ||
269 | unique if the output corresponds to a single channel. | ||
270 | |||
271 | What: /sys/bus/iio/devices/deviceX/outY&Z_raw | ||
272 | KernelVersion: 2.6.37 | ||
273 | Contact: linux-iio@vger.kernel.org | ||
274 | Description: | ||
275 | Raw (unscaled, no bias etc.) output voltage for an aggregate of | ||
276 | channel Y, channel Z, etc. This interface is available in cases | ||
277 | where a single output sets the value for multiple channels | ||
278 | simultaneously. | ||
279 | |||
280 | What: /sys/bus/iio/devices/deviceX/outY_powerdown_mode | ||
281 | What: /sys/bus/iio/devices/deviceX/out_powerdown_mode | ||
282 | KernelVersion: 2.6.38 | ||
283 | Contact: linux-iio@vger.kernel.org | ||
284 | Description: | ||
285 | Specifies the output powerdown mode. | ||
286 | DAC output stage is disconnected from the amplifier and | ||
287 | 1kohm_to_gnd: connected to ground via an 1kOhm resistor | ||
288 | 100kohm_to_gnd: connected to ground via an 100kOhm resistor | ||
289 | three_state: left floating | ||
290 | For a list of available output power down options read | ||
291 | outX_powerdown_mode_available. If Y is not present the | ||
292 | mode is shared across all outputs. | ||
293 | |||
294 | What: /sys/bus/iio/devices/deviceX/outY_powerdown_mode_available | ||
295 | What: /sys/bus/iio/devices/deviceX/out_powerdown_mode_available | ||
296 | KernelVersion: 2.6.38 | ||
297 | Contact: linux-iio@vger.kernel.org | ||
298 | Description: | ||
299 | Lists all available output power down modes. | ||
300 | If Y is not present the mode is shared across all outputs. | ||
301 | |||
302 | What: /sys/bus/iio/devices/deviceX/outY_powerdown | ||
303 | What: /sys/bus/iio/devices/deviceX/out_powerdown | ||
304 | KernelVersion: 2.6.38 | ||
305 | Contact: linux-iio@vger.kernel.org | ||
306 | Description: | ||
307 | Writing 1 causes output Y to enter the power down mode specified | ||
308 | by the corresponding outY_powerdown_mode. Clearing returns to | ||
309 | normal operation. Y may be suppressed if all outputs are | ||
310 | controlled together. | ||
311 | |||
312 | What: /sys/bus/iio/devices/deviceX/deviceX:eventY | ||
313 | KernelVersion: 2.6.35 | ||
314 | Contact: linux-iio@vger.kernel.org | ||
315 | Description: | ||
316 | Configuration of which hardware generated events are passed up | ||
317 | to user-space. | ||
318 | |||
319 | What: /sys/bus/iio/devices/deviceX:event/dev | ||
320 | What: /sys/bus/iio/devices/deviceX:eventY/dev | ||
321 | KernelVersion: 2.6.35 | ||
322 | Contact: linux-iio@vger.kernel.org | ||
323 | Description: | ||
324 | major:minor character device numbers for the event line Y of | ||
325 | device X. | ||
326 | |||
327 | What: /sys/.../deviceX:eventY/accel_x_thresh_rising_en | ||
328 | What: /sys/.../deviceX:eventY/accel_x_thresh_falling_en | ||
329 | What: /sys/.../deviceX:eventY/accel_y_thresh_rising_en | ||
330 | What: /sys/.../deviceX:eventY/accel_y_thresh_falling_en | ||
331 | What: /sys/.../deviceX:eventY/accel_z_thresh_rising_en | ||
332 | What: /sys/.../deviceX:eventY/accel_z_thresh_falling_en | ||
333 | What: /sys/.../deviceX:eventY/gyro_x_thresh_rising_en | ||
334 | What: /sys/.../deviceX:eventY/gyro_x_thresh_falling_en | ||
335 | What: /sys/.../deviceX:eventY/gyro_y_thresh_rising_en | ||
336 | What: /sys/.../deviceX:eventY/gyro_y_thresh_falling_en | ||
337 | What: /sys/.../deviceX:eventY/gyro_z_thresh_rising_en | ||
338 | What: /sys/.../deviceX:eventY/gyro_z_thresh_falling_en | ||
339 | What: /sys/.../deviceX:eventY/magn_x_thresh_rising_en | ||
340 | What: /sys/.../deviceX:eventY/magn_x_thresh_falling_en | ||
341 | What: /sys/.../deviceX:eventY/magn_y_thresh_rising_en | ||
342 | What: /sys/.../deviceX:eventY/magn_y_thresh_falling_en | ||
343 | What: /sys/.../deviceX:eventY/magn_z_thresh_rising_en | ||
344 | What: /sys/.../deviceX:eventY/magn_z_thresh_falling_en | ||
345 | What: /sys/.../deviceX:eventY/inZ_supply_thresh_rising_en | ||
346 | What: /sys/.../deviceX:eventY/inZ_supply_thresh_falling_en | ||
347 | What: /sys/.../deviceX:eventY/inZ_thresh_rising_en | ||
348 | What: /sys/.../deviceX:eventY/inZ_thresh_falling_en | ||
349 | What: /sys/.../deviceX:eventY/temp_thresh_rising_en | ||
350 | What: /sys/.../deviceX:eventY/temp_thresh_falling_en | ||
351 | KernelVersion: 2.6.37 | ||
352 | Contact: linux-iio@vger.kernel.org | ||
353 | Description: | ||
354 | Event generated when channel passes a threshold in the specified | ||
355 | (_rising|_falling) direction. If the direction is not specified, | ||
356 | then either the device will report an event which ever direction | ||
357 | a single threshold value is called in (e.g. | ||
358 | <type>[Z][_name]_<raw|input>_thresh_value) or | ||
359 | <type>[Z][_name]_<raw|input>_thresh_rising_value and | ||
360 | <type>[Z][_name]_<raw|input>_thresh_falling_value may take | ||
361 | different values, but the device can only enable both thresholds | ||
362 | or neither. | ||
363 | Note the driver will assume the last p events requested are | ||
364 | to be enabled where p is however many it supports (which may | ||
365 | vary depending on the exact set requested. So if you want to be | ||
366 | sure you have set what you think you have, check the contents of | ||
367 | these attributes after everything is configured. Drivers may | ||
368 | have to buffer any parameters so that they are consistent when | ||
369 | a given event type is enabled a future point (and not those for | ||
370 | whatever event was previously enabled). | ||
371 | |||
372 | What: /sys/.../deviceX:eventY/accel_x_roc_rising_en | ||
373 | What: /sys/.../deviceX:eventY/accel_x_roc_falling_en | ||
374 | What: /sys/.../deviceX:eventY/accel_y_roc_rising_en | ||
375 | What: /sys/.../deviceX:eventY/accel_y_roc_falling_en | ||
376 | What: /sys/.../deviceX:eventY/accel_z_roc_rising_en | ||
377 | What: /sys/.../deviceX:eventY/accel_z_roc_falling_en | ||
378 | What: /sys/.../deviceX:eventY/gyro_x_roc_rising_en | ||
379 | What: /sys/.../deviceX:eventY/gyro_x_roc_falling_en | ||
380 | What: /sys/.../deviceX:eventY/gyro_y_roc_rising_en | ||
381 | What: /sys/.../deviceX:eventY/gyro_y_roc_falling_en | ||
382 | What: /sys/.../deviceX:eventY/gyro_z_roc_rising_en | ||
383 | What: /sys/.../deviceX:eventY/gyro_z_roc_falling_en | ||
384 | What: /sys/.../deviceX:eventY/magn_x_roc_rising_en | ||
385 | What: /sys/.../deviceX:eventY/magn_x_roc_falling_en | ||
386 | What: /sys/.../deviceX:eventY/magn_y_roc_rising_en | ||
387 | What: /sys/.../deviceX:eventY/magn_y_roc_falling_en | ||
388 | What: /sys/.../deviceX:eventY/magn_z_roc_rising_en | ||
389 | What: /sys/.../deviceX:eventY/magn_z_roc_falling_en | ||
390 | What: /sys/.../deviceX:eventY/inZ_supply_roc_rising_en | ||
391 | What: /sys/.../deviceX:eventY/inZ_supply_roc_falling_en | ||
392 | What: /sys/.../deviceX:eventY/inZ_roc_rising_en | ||
393 | What: /sys/.../deviceX:eventY/inZ_roc_falling_en | ||
394 | What: /sys/.../deviceX:eventY/temp_roc_rising_en | ||
395 | What: /sys/.../deviceX:eventY/temp_roc_falling_en | ||
396 | KernelVersion: 2.6.37 | ||
397 | Contact: linux-iio@vger.kernel.org | ||
398 | Description: | ||
399 | Event generated when channel passes a threshold on the rate of | ||
400 | change (1st differential) in the specified (_rising|_falling) | ||
401 | direction. If the direction is not specified, then either the | ||
402 | device will report an event which ever direction a single | ||
403 | threshold value is called in (e.g. | ||
404 | <type>[Z][_name]_<raw|input>_roc_value) or | ||
405 | <type>[Z][_name]_<raw|input>_roc_rising_value and | ||
406 | <type>[Z][_name]_<raw|input>_roc_falling_value may take | ||
407 | different values, but the device can only enable both rate of | ||
408 | change thresholds or neither. | ||
409 | Note the driver will assume the last p events requested are | ||
410 | to be enabled where p is however many it supports (which may | ||
411 | vary depending on the exact set requested. So if you want to be | ||
412 | sure you have set what you think you have, check the contents of | ||
413 | these attributes after everything is configured. Drivers may | ||
414 | have to buffer any parameters so that they are consistent when | ||
415 | a given event type is enabled a future point (and not those for | ||
416 | whatever event was previously enabled). | ||
417 | |||
418 | What: /sys/.../deviceX:eventY/accel_x_raw_thresh_rising_value | ||
419 | What: /sys/.../deviceX:eventY/accel_x_raw_thresh_falling_value | ||
420 | What: /sys/.../deviceX:eventY/accel_y_raw_thresh_rising_value | ||
421 | What: /sys/.../deviceX:eventY/accel_y_raw_thresh_falling_value | ||
422 | What: /sys/.../deviceX:eventY/accel_z_raw_thresh_rising_value | ||
423 | What: /sys/.../deviceX:eventY/accel_z_raw_thresh_falling_value | ||
424 | What: /sys/.../deviceX:eventY/gyro_x_raw_thresh_rising_value | ||
425 | What: /sys/.../deviceX:eventY/gyro_x_raw_thresh_falling_value | ||
426 | What: /sys/.../deviceX:eventY/gyro_y_raw_thresh_rising_value | ||
427 | What: /sys/.../deviceX:eventY/gyro_y_raw_thresh_falling_value | ||
428 | What: /sys/.../deviceX:eventY/gyro_z_raw_thresh_rising_value | ||
429 | What: /sys/.../deviceX:eventY/gyro_z_raw_thresh_falling_value | ||
430 | What: /sys/.../deviceX:eventY/magn_x_raw_thresh_rising_value | ||
431 | What: /sys/.../deviceX:eventY/magn_x_raw_thresh_falling_value | ||
432 | What: /sys/.../deviceX:eventY/magn_y_raw_thresh_rising_value | ||
433 | What: /sys/.../deviceX:eventY/magn_y_raw_thresh_falling_value | ||
434 | What: /sys/.../deviceX:eventY/magn_z_raw_thresh_rising_value | ||
435 | What: /sys/.../deviceX:eventY/magn_z_raw_thresh_falling_value | ||
436 | What: /sys/.../deviceX:eventY/inZ_supply_raw_thresh_rising_value | ||
437 | What: /sys/.../deviceX:eventY/inZ_supply_raw_thresh_falling_value | ||
438 | What: /sys/.../deviceX:eventY/inZ_raw_thresh_falling_value | ||
439 | What: /sys/.../deviceX:eventY/inZ_raw_thresh_falling_value | ||
440 | What: /sys/.../deviceX:eventY/temp_raw_thresh_falling_value | ||
441 | What: /sys/.../deviceX:eventY/temp_raw_thresh_falling_value | ||
442 | KernelVersion: 2.6.37 | ||
443 | Contact: linux-iio@vger.kernel.org | ||
444 | Description: | ||
445 | Specifies the value of threshold that the device is comparing | ||
446 | against for the events enabled by | ||
447 | <type>Z[_name]_thresh[_rising|falling]_en. | ||
448 | If separate attributes exist for the two directions, but | ||
449 | direction is not specified for this attribute, then a single | ||
450 | threshold value applies to both directions. | ||
451 | The raw or input element of the name indicates whether the | ||
452 | value is in raw device units or in processed units (as _raw | ||
453 | and _input do on sysfs direct channel read attributes). | ||
454 | |||
455 | What: /sys/.../deviceX:eventY/accel_x_raw_roc_rising_value | ||
456 | What: /sys/.../deviceX:eventY/accel_x_raw_roc_falling_value | ||
457 | What: /sys/.../deviceX:eventY/accel_y_raw_roc_rising_value | ||
458 | What: /sys/.../deviceX:eventY/accel_y_raw_roc_falling_value | ||
459 | What: /sys/.../deviceX:eventY/accel_z_raw_roc_rising_value | ||
460 | What: /sys/.../deviceX:eventY/accel_z_raw_roc_falling_value | ||
461 | What: /sys/.../deviceX:eventY/gyro_x_raw_roc_rising_value | ||
462 | What: /sys/.../deviceX:eventY/gyro_x_raw_roc_falling_value | ||
463 | What: /sys/.../deviceX:eventY/gyro_y_raw_roc_rising_value | ||
464 | What: /sys/.../deviceX:eventY/gyro_y_raw_roc_falling_value | ||
465 | What: /sys/.../deviceX:eventY/gyro_z_raw_roc_rising_value | ||
466 | What: /sys/.../deviceX:eventY/gyro_z_raw_roc_falling_value | ||
467 | What: /sys/.../deviceX:eventY/magn_x_raw_roc_rising_value | ||
468 | What: /sys/.../deviceX:eventY/magn_x_raw_roc_falling_value | ||
469 | What: /sys/.../deviceX:eventY/magn_y_raw_roc_rising_value | ||
470 | What: /sys/.../deviceX:eventY/magn_y_raw_roc_falling_value | ||
471 | What: /sys/.../deviceX:eventY/magn_z_raw_roc_rising_value | ||
472 | What: /sys/.../deviceX:eventY/magn_z_raw_roc_falling_value | ||
473 | What: /sys/.../deviceX:eventY/inZ_supply_raw_roc_rising_value | ||
474 | What: /sys/.../deviceX:eventY/inZ_supply_raw_roc_falling_value | ||
475 | What: /sys/.../deviceX:eventY/inZ_raw_roc_falling_value | ||
476 | What: /sys/.../deviceX:eventY/inZ_raw_roc_falling_value | ||
477 | What: /sys/.../deviceX:eventY/temp_raw_roc_falling_value | ||
478 | What: /sys/.../deviceX:eventY/temp_raw_roc_falling_value | ||
479 | KernelVersion: 2.6.37 | ||
480 | Contact: linux-iio@vger.kernel.org | ||
481 | Description: | ||
482 | Specifies the value of rate of change threshold that the | ||
483 | device is comparing against for the events enabled by | ||
484 | <type>[Z][_name]_roc[_rising|falling]_en. | ||
485 | If separate attributes exist for the two directions, | ||
486 | but direction is not specified for this attribute, | ||
487 | then a single threshold value applies to both directions. | ||
488 | The raw or input element of the name indicates whether the | ||
489 | value is in raw device units or in processed units (as _raw | ||
490 | and _input do on sysfs direct channel read attributes). | ||
491 | |||
492 | What: /sys/.../deviceX:eventY/accel_x_thresh_rising_period | ||
493 | What: /sys/.../deviceX:eventY/accel_x_thresh_falling_period | ||
494 | hat: /sys/.../deviceX:eventY/accel_x_roc_rising_period | ||
495 | What: /sys/.../deviceX:eventY/accel_x_roc_falling_period | ||
496 | What: /sys/.../deviceX:eventY/accel_y_thresh_rising_period | ||
497 | What: /sys/.../deviceX:eventY/accel_y_thresh_falling_period | ||
498 | What: /sys/.../deviceX:eventY/accel_y_roc_rising_period | ||
499 | What: /sys/.../deviceX:eventY/accel_y_roc_falling_period | ||
500 | What: /sys/.../deviceX:eventY/accel_z_thresh_rising_period | ||
501 | What: /sys/.../deviceX:eventY/accel_z_thresh_falling_period | ||
502 | What: /sys/.../deviceX:eventY/accel_z_roc_rising_period | ||
503 | What: /sys/.../deviceX:eventY/accel_z_roc_falling_period | ||
504 | What: /sys/.../deviceX:eventY/gyro_x_thresh_rising_period | ||
505 | What: /sys/.../deviceX:eventY/gyro_x_thresh_falling_period | ||
506 | What: /sys/.../deviceX:eventY/gyro_x_roc_rising_period | ||
507 | What: /sys/.../deviceX:eventY/gyro_x_roc_falling_period | ||
508 | What: /sys/.../deviceX:eventY/gyro_y_thresh_rising_period | ||
509 | What: /sys/.../deviceX:eventY/gyro_y_thresh_falling_period | ||
510 | What: /sys/.../deviceX:eventY/gyro_y_roc_rising_period | ||
511 | What: /sys/.../deviceX:eventY/gyro_y_roc_falling_period | ||
512 | What: /sys/.../deviceX:eventY/gyro_z_thresh_rising_period | ||
513 | What: /sys/.../deviceX:eventY/gyro_z_thresh_falling_period | ||
514 | What: /sys/.../deviceX:eventY/gyro_z_roc_rising_period | ||
515 | What: /sys/.../deviceX:eventY/gyro_z_roc_falling_period | ||
516 | What: /sys/.../deviceX:eventY/magn_x_thresh_rising_period | ||
517 | What: /sys/.../deviceX:eventY/magn_x_thresh_falling_period | ||
518 | What: /sys/.../deviceX:eventY/magn_x_roc_rising_period | ||
519 | What: /sys/.../deviceX:eventY/magn_x_roc_falling_period | ||
520 | What: /sys/.../deviceX:eventY/magn_y_thresh_rising_period | ||
521 | What: /sys/.../deviceX:eventY/magn_y_thresh_falling_period | ||
522 | What: /sys/.../deviceX:eventY/magn_y_roc_rising_period | ||
523 | What: /sys/.../deviceX:eventY/magn_y_roc_falling_period | ||
524 | What: /sys/.../deviceX:eventY/magn_z_thresh_rising_period | ||
525 | What: /sys/.../deviceX:eventY/magn_z_thresh_falling_period | ||
526 | What: /sys/.../deviceX:eventY/magn_z_roc_rising_period | ||
527 | What: /sys/.../deviceX:eventY/magn_z_roc_falling_period | ||
528 | What: /sys/.../deviceX:eventY/inZ_supply_thresh_rising_period | ||
529 | What: /sys/.../deviceX:eventY/inZ_supply_thresh_falling_period | ||
530 | What: /sys/.../deviceX:eventY/inz_supply_roc_rising_period | ||
531 | What: /sys/.../deviceX:eventY/inZ_supply_roc_falling_period | ||
532 | What: /sys/.../deviceX:eventY/inZ_thresh_rising_period | ||
533 | What: /sys/.../deviceX:eventY/inZ_thresh_falling_period | ||
534 | What: /sys/.../deviceX:eventY/inZ_roc_rising_period | ||
535 | What: /sys/.../deviceX:eventY/inZ_roc_falling_period | ||
536 | What: /sys/.../deviceX:eventY/temp_thresh_rising_period | ||
537 | What: /sys/.../deviceX:eventY/temp_thresh_falling_period | ||
538 | What: /sys/.../deviceX:eventY/temp_roc_rising_period | ||
539 | What: /sys/.../deviceX:eventY/temp_roc_falling_period | ||
540 | What: /sys/.../deviceX:eventY/accel_x&y&z_mag_falling_period | ||
541 | KernelVersion: 2.6.37 | ||
542 | Contact: linux-iio@vger.kernel.org | ||
543 | Description: | ||
544 | Period of time (in seconds) for which the condition must be | ||
545 | met before an event is generated. If direction is not | ||
546 | specified then this period applies to both directions. | ||
547 | |||
548 | What: /sys/.../deviceX:eventY/accel_mag_en | ||
549 | What: /sys/.../deviceX:eventY/accel_mag_rising_en | ||
550 | What: /sys/.../deviceX:eventY/accel_mag_falling_en | ||
551 | What: /sys/.../deviceX:eventY/accel_x_mag_en | ||
552 | What: /sys/.../deviceX:eventY/accel_x_mag_rising_en | ||
553 | What: /sys/.../deviceX:eventY/accel_x_mag_falling_en | ||
554 | What: /sys/.../deviceX:eventY/accel_y_mag_en | ||
555 | What: /sys/.../deviceX:eventY/accel_y_mag_rising_en | ||
556 | What: /sys/.../deviceX:eventY/accel_y_mag_falling_en | ||
557 | What: /sys/.../deviceX:eventY/accel_z_mag_en | ||
558 | What: /sys/.../deviceX:eventY/accel_z_mag_rising_en | ||
559 | What: /sys/.../deviceX:eventY/accel_z_mag_falling_en | ||
560 | What: /sys/.../deviceX:eventY/accel_x&y&z_mag_rising_en | ||
561 | What: /sys/.../deviceX:eventY/accel_x&y&z_mag_falling_en | ||
562 | KernelVersion: 2.6.37 | ||
563 | Contact: linux-iio@vger.kernel.org | ||
564 | Description: | ||
565 | Similar to accel_x_thresh[_rising|_falling]_en, but here the | ||
566 | magnitude of the channel is compared to the threshold, not its | ||
567 | signed value. | ||
568 | |||
569 | What: /sys/.../accel_raw_mag_value | ||
570 | What: /sys/.../accel_x_raw_mag_rising_value | ||
571 | What: /sys/.../accel_y_raw_mag_rising_value | ||
572 | What: /sys/.../accel_z_raw_mag_rising_value | ||
573 | KernelVersion: 2.6.37 | ||
574 | Contact: linux-iio@vger.kernel.org | ||
575 | Description: | ||
576 | The value to which the magnitude of the channel is compared. If | ||
577 | number or direction is not specified, applies to all channels of | ||
578 | this type. | ||
579 | |||
580 | What: /sys/bus/iio/devices/deviceX:buffer:event/dev | ||
581 | KernelVersion: 2.6.35 | ||
582 | Contact: linux-iio@vger.kernel.org | ||
583 | Description: | ||
584 | Buffer for device X event character device major:minor numbers. | ||
585 | |||
586 | What: /sys/bus/iio/devices/deviceX:buffer:access/dev | ||
587 | KernelVersion: 2.6.35 | ||
588 | Contact: linux-iio@vger.kernel.org | ||
589 | Description: | ||
590 | Buffer for device X access character device major:minor numbers. | ||
591 | |||
592 | What: /sys/bus/iio/devices/deviceX:buffer/trigger | ||
593 | KernelVersion: 2.6.35 | ||
594 | Contact: linux-iio@vger.kernel.org | ||
595 | Description: | ||
596 | The name of the trigger source being used, as per string given | ||
597 | in /sys/class/iio/triggerY/name. | ||
598 | |||
599 | What: /sys/bus/iio/devices/deviceX:buffer/length | ||
600 | KernelVersion: 2.6.35 | ||
601 | Contact: linux-iio@vger.kernel.org | ||
602 | Description: | ||
603 | Number of scans contained by the buffer. | ||
604 | |||
605 | What: /sys/bus/iio/devices/deviceX:buffer/bytes_per_datum | ||
606 | KernelVersion: 2.6.37 | ||
607 | Contact: linux-iio@vger.kernel.org | ||
608 | Description: | ||
609 | Bytes per scan. Due to alignment fun, the scan may be larger | ||
610 | than implied directly by the scan_element parameters. | ||
611 | |||
612 | What: /sys/bus/iio/devices/deviceX:buffer/enable | ||
613 | KernelVersion: 2.6.35 | ||
614 | Contact: linux-iio@vger.kernel.org | ||
615 | Description: | ||
616 | Actually start the buffer capture up. Will start trigger | ||
617 | if first device and appropriate. | ||
618 | |||
619 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements | ||
620 | KernelVersion: 2.6.37 | ||
621 | Contact: linux-iio@vger.kernel.org | ||
622 | Description: | ||
623 | Directory containing interfaces for elements that will be | ||
624 | captured for a single triggered sample set in the buffer. | ||
625 | |||
626 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/accel_x_en | ||
627 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/accel_y_en | ||
628 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/accel_z_en | ||
629 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/gyro_x_en | ||
630 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/gyro_y_en | ||
631 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/gyro_z_en | ||
632 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/magn_x_en | ||
633 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/magn_y_en | ||
634 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/magn_z_en | ||
635 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/timestamp_en | ||
636 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/inY_supply_en | ||
637 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/inY_en | ||
638 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/inY-inZ_en | ||
639 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/incli_x_en | ||
640 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/incli_y_en | ||
641 | KernelVersion: 2.6.37 | ||
642 | Contact: linux-iio@vger.kernel.org | ||
643 | Description: | ||
644 | Scan element control for triggered data capture. | ||
645 | |||
646 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/accel_type | ||
647 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/gyro_type | ||
648 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/magn_type | ||
649 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/incli_type | ||
650 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/inY_type | ||
651 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/in-in_type | ||
652 | What: /sys/.../deviceX:buffer/scan_elements/inY_supply_type | ||
653 | What: /sys/.../deviceX:buffer/scan_elements/timestamp_type | ||
654 | KernelVersion: 2.6.37 | ||
655 | Contact: linux-iio@vger.kernel.org | ||
656 | Description: | ||
657 | Description of the scan element data storage within the buffer | ||
658 | and hence the form in which it is read from user-space. | ||
659 | Form is [s|u]bits/storagebits[>>shift]. s or u specifies if | ||
660 | signed (2's complement) or unsigned. bits is the number of bits | ||
661 | of data and storagebits is the space (after padding) that it | ||
662 | occupies in the buffer. shift if specified, is the shift that | ||
663 | needs to be applied prior to masking out unused bits. Some | ||
664 | devices put their data in the middle of the transferred elements | ||
665 | with additional information on both sides. Note that some | ||
666 | devices will have additional information in the unused bits | ||
667 | so to get a clean value, the bits value must be used to mask | ||
668 | the buffer output value appropriately. The storagebits value | ||
669 | also specifies the data alignment. So s48/64>>2 will be a | ||
670 | signed 48 bit integer stored in a 64 bit location aligned to | ||
671 | a a64 bit boundary. To obtain the clean value, shift right 2 | ||
672 | and apply a mask to zero the top 16 bits of the result. | ||
673 | For other storage combinations this attribute will be extended | ||
674 | appropriately. | ||
675 | |||
676 | What: /sys/.../deviceX:buffer/scan_elements/accel_type_available | ||
677 | KernelVersion: 2.6.37 | ||
678 | Contact: linux-iio@vger.kernel.org | ||
679 | Description: | ||
680 | If the type parameter can take one of a small set of values, | ||
681 | this attribute lists them. | ||
682 | |||
683 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/inY_index | ||
684 | What: /sys/.../deviceX:buffer/scan_elements/inY_supply_index | ||
685 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/accel_x_index | ||
686 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/accel_y_index | ||
687 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/accel_z_index | ||
688 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/gyro_x_index | ||
689 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/gyro_y_index | ||
690 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/gyro_z_index | ||
691 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/magn_x_index | ||
692 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/magn_y_index | ||
693 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/magn_z_index | ||
694 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/incli_x_index | ||
695 | What: /sys/bus/iio/devices/deviceX:buffer/scan_elements/incli_y_index | ||
696 | What: /sys/.../deviceX:buffer/scan_elements/timestamp_index | ||
697 | KernelVersion: 2.6.37 | ||
698 | Contact: linux-iio@vger.kernel.org | ||
699 | Description: | ||
700 | A single positive integer specifying the position of this | ||
701 | scan element in the buffer. Note these are not dependent on | ||
702 | what is enabled and may not be contiguous. Thus for user-space | ||
703 | to establish the full layout these must be used in conjunction | ||
704 | with all _en attributes to establish which channels are present, | ||
705 | and the relevant _type attributes to establish the data storage | ||
706 | format. | ||
707 | |||
708 | What: /sys/bus/iio/devices/deviceX/gyro_z_quadrature_correction_raw | ||
709 | KernelVersion: 2.6.38 | ||
710 | Contact: linux-iio@xxxxxxxxxxxxxxx | ||
711 | Description: | ||
712 | This attribute is used to read the amount of quadrature error | ||
713 | present in the device at a given time. | ||
diff --git a/drivers/staging/iio/accel/accel.h b/drivers/staging/iio/accel/accel.h new file mode 100644 index 00000000000..50651f835ce --- /dev/null +++ b/drivers/staging/iio/accel/accel.h | |||
@@ -0,0 +1,87 @@ | |||
1 | |||
2 | #include "../sysfs.h" | ||
3 | |||
4 | /* Accelerometer types of attribute */ | ||
5 | #define IIO_DEV_ATTR_ACCEL_OFFSET(_mode, _show, _store, _addr) \ | ||
6 | IIO_DEVICE_ATTR(accel_offset, _mode, _show, _store, _addr) | ||
7 | |||
8 | #define IIO_DEV_ATTR_ACCEL_X_OFFSET(_mode, _show, _store, _addr) \ | ||
9 | IIO_DEVICE_ATTR(accel_x_offset, _mode, _show, _store, _addr) | ||
10 | |||
11 | #define IIO_DEV_ATTR_ACCEL_Y_OFFSET(_mode, _show, _store, _addr) \ | ||
12 | IIO_DEVICE_ATTR(accel_y_offset, _mode, _show, _store, _addr) | ||
13 | |||
14 | #define IIO_DEV_ATTR_ACCEL_Z_OFFSET(_mode, _show, _store, _addr) \ | ||
15 | IIO_DEVICE_ATTR(accel_z_offset, _mode, _show, _store, _addr) | ||
16 | |||
17 | #define IIO_CONST_ATTR_ACCEL_SCALE(_string) \ | ||
18 | IIO_CONST_ATTR(accel_scale, _string) | ||
19 | |||
20 | #define IIO_DEV_ATTR_ACCEL_SCALE(_mode, _show, _store, _addr) \ | ||
21 | IIO_DEVICE_ATTR(accel_scale, _mode, _show, _store, _addr) | ||
22 | |||
23 | #define IIO_DEV_ATTR_ACCEL_X_SCALE(_mode, _show, _store, _addr) \ | ||
24 | IIO_DEVICE_ATTR(accel_x_scale, _mode, _show, _store, _addr) | ||
25 | |||
26 | #define IIO_DEV_ATTR_ACCEL_Y_SCALE(_mode, _show, _store, _addr) \ | ||
27 | IIO_DEVICE_ATTR(accel_y_scale, _mode, _show, _store, _addr) | ||
28 | |||
29 | #define IIO_DEV_ATTR_ACCEL_Z_SCALE(_mode, _show, _store, _addr) \ | ||
30 | IIO_DEVICE_ATTR(accel_z_scale, _mode, _show, _store, _addr) | ||
31 | |||
32 | #define IIO_DEV_ATTR_ACCEL_CALIBBIAS(_mode, _show, _store, _addr) \ | ||
33 | IIO_DEVICE_ATTR(accel_calibbias, _mode, _show, _store, _addr) | ||
34 | |||
35 | #define IIO_DEV_ATTR_ACCEL_X_CALIBBIAS(_mode, _show, _store, _addr) \ | ||
36 | IIO_DEVICE_ATTR(accel_x_calibbias, _mode, _show, _store, _addr) | ||
37 | |||
38 | #define IIO_DEV_ATTR_ACCEL_Y_CALIBBIAS(_mode, _show, _store, _addr) \ | ||
39 | IIO_DEVICE_ATTR(accel_y_calibbias, _mode, _show, _store, _addr) | ||
40 | |||
41 | #define IIO_DEV_ATTR_ACCEL_Z_CALIBBIAS(_mode, _show, _store, _addr) \ | ||
42 | IIO_DEVICE_ATTR(accel_z_calibbias, _mode, _show, _store, _addr) | ||
43 | |||
44 | #define IIO_DEV_ATTR_ACCEL_CALIBSCALE(_mode, _show, _store, _addr) \ | ||
45 | IIO_DEVICE_ATTR(accel_calibscale, _mode, _show, _store, _addr) | ||
46 | |||
47 | #define IIO_DEV_ATTR_ACCEL_X_CALIBSCALE(_mode, _show, _store, _addr) \ | ||
48 | IIO_DEVICE_ATTR(accel_x_calibscale, _mode, _show, _store, _addr) | ||
49 | |||
50 | #define IIO_DEV_ATTR_ACCEL_Y_CALIBSCALE(_mode, _show, _store, _addr) \ | ||
51 | IIO_DEVICE_ATTR(accel_y_calibscale, _mode, _show, _store, _addr) | ||
52 | |||
53 | #define IIO_DEV_ATTR_ACCEL_Z_CALIBSCALE(_mode, _show, _store, _addr) \ | ||
54 | IIO_DEVICE_ATTR(accel_z_calibscale, _mode, _show, _store, _addr) | ||
55 | |||
56 | #define IIO_DEV_ATTR_ACCEL(_show, _addr) \ | ||
57 | IIO_DEVICE_ATTR(accel_raw, S_IRUGO, _show, NULL, _addr) | ||
58 | |||
59 | #define IIO_DEV_ATTR_ACCEL_X(_show, _addr) \ | ||
60 | IIO_DEVICE_ATTR(accel_x_raw, S_IRUGO, _show, NULL, _addr) | ||
61 | |||
62 | #define IIO_DEV_ATTR_ACCEL_Y(_show, _addr) \ | ||
63 | IIO_DEVICE_ATTR(accel_y_raw, S_IRUGO, _show, NULL, _addr) | ||
64 | |||
65 | #define IIO_DEV_ATTR_ACCEL_Z(_show, _addr) \ | ||
66 | IIO_DEVICE_ATTR(accel_z_raw, S_IRUGO, _show, NULL, _addr) | ||
67 | |||
68 | #define IIO_DEV_ATTR_ACCEL_XY(_show, _addr) \ | ||
69 | IIO_DEVICE_ATTR(accel_xy, S_IRUGO, _show, NULL, _addr) | ||
70 | |||
71 | #define IIO_DEV_ATTR_ACCEL_PEAK(_show, _addr) \ | ||
72 | IIO_DEVICE_ATTR(accel_peak, S_IRUGO, _show, NULL, _addr) | ||
73 | |||
74 | #define IIO_DEV_ATTR_ACCEL_XPEAK(_show, _addr) \ | ||
75 | IIO_DEVICE_ATTR(accel_xpeak, S_IRUGO, _show, NULL, _addr) | ||
76 | |||
77 | #define IIO_DEV_ATTR_ACCEL_YPEAK(_show, _addr) \ | ||
78 | IIO_DEVICE_ATTR(accel_ypeak, S_IRUGO, _show, NULL, _addr) | ||
79 | |||
80 | #define IIO_DEV_ATTR_ACCEL_ZPEAK(_show, _addr) \ | ||
81 | IIO_DEVICE_ATTR(accel_zpeak, S_IRUGO, _show, NULL, _addr) | ||
82 | |||
83 | #define IIO_DEV_ATTR_ACCEL_XYPEAK(_show, _addr) \ | ||
84 | IIO_DEVICE_ATTR(accel_xypeak, S_IRUGO, _show, NULL, _addr) | ||
85 | |||
86 | #define IIO_DEV_ATTR_ACCEL_XYZPEAK(_show, _addr) \ | ||
87 | IIO_DEVICE_ATTR(accel_xyzpeak, S_IRUGO, _show, NULL, _addr) | ||
diff --git a/drivers/staging/iio/accel/adis16201_ring.c b/drivers/staging/iio/accel/adis16201_ring.c new file mode 100644 index 00000000000..66e708ddf8b --- /dev/null +++ b/drivers/staging/iio/accel/adis16201_ring.c | |||
@@ -0,0 +1,152 @@ | |||
1 | #include <linux/interrupt.h> | ||
2 | #include <linux/irq.h> | ||
3 | #include <linux/mutex.h> | ||
4 | #include <linux/device.h> | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/spi/spi.h> | ||
7 | #include <linux/slab.h> | ||
8 | #include <linux/sysfs.h> | ||
9 | |||
10 | #include "../iio.h" | ||
11 | #include "../sysfs.h" | ||
12 | #include "../ring_sw.h" | ||
13 | #include "accel.h" | ||
14 | #include "../trigger.h" | ||
15 | #include "adis16201.h" | ||
16 | |||
17 | |||
18 | /** | ||
19 | * adis16201_read_ring_data() read data registers which will be placed into ring | ||
20 | * @dev: device associated with child of actual device (iio_dev or iio_trig) | ||
21 | * @rx: somewhere to pass back the value read | ||
22 | **/ | ||
23 | static int adis16201_read_ring_data(struct iio_dev *indio_dev, u8 *rx) | ||
24 | { | ||
25 | struct spi_message msg; | ||
26 | struct adis16201_state *st = iio_priv(indio_dev); | ||
27 | struct spi_transfer xfers[ADIS16201_OUTPUTS + 1]; | ||
28 | int ret; | ||
29 | int i; | ||
30 | |||
31 | mutex_lock(&st->buf_lock); | ||
32 | |||
33 | spi_message_init(&msg); | ||
34 | |||
35 | memset(xfers, 0, sizeof(xfers)); | ||
36 | for (i = 0; i <= ADIS16201_OUTPUTS; i++) { | ||
37 | xfers[i].bits_per_word = 8; | ||
38 | xfers[i].cs_change = 1; | ||
39 | xfers[i].len = 2; | ||
40 | xfers[i].delay_usecs = 20; | ||
41 | xfers[i].tx_buf = st->tx + 2 * i; | ||
42 | st->tx[2 * i] = ADIS16201_READ_REG(ADIS16201_SUPPLY_OUT + | ||
43 | 2 * i); | ||
44 | st->tx[2 * i + 1] = 0; | ||
45 | if (i >= 1) | ||
46 | xfers[i].rx_buf = rx + 2 * (i - 1); | ||
47 | spi_message_add_tail(&xfers[i], &msg); | ||
48 | } | ||
49 | |||
50 | ret = spi_sync(st->us, &msg); | ||
51 | if (ret) | ||
52 | dev_err(&st->us->dev, "problem when burst reading"); | ||
53 | |||
54 | mutex_unlock(&st->buf_lock); | ||
55 | |||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | /* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device | ||
60 | * specific to be rolled into the core. | ||
61 | */ | ||
62 | static irqreturn_t adis16201_trigger_handler(int irq, void *p) | ||
63 | { | ||
64 | struct iio_poll_func *pf = p; | ||
65 | struct iio_dev *indio_dev = pf->private_data; | ||
66 | struct adis16201_state *st = iio_priv(indio_dev); | ||
67 | struct iio_ring_buffer *ring = indio_dev->ring; | ||
68 | |||
69 | int i = 0; | ||
70 | s16 *data; | ||
71 | size_t datasize = ring->access->get_bytes_per_datum(ring); | ||
72 | |||
73 | data = kmalloc(datasize, GFP_KERNEL); | ||
74 | if (data == NULL) { | ||
75 | dev_err(&st->us->dev, "memory alloc failed in ring bh"); | ||
76 | return -ENOMEM; | ||
77 | } | ||
78 | |||
79 | if (ring->scan_count) | ||
80 | if (adis16201_read_ring_data(indio_dev, st->rx) >= 0) | ||
81 | for (; i < ring->scan_count; i++) | ||
82 | data[i] = be16_to_cpup( | ||
83 | (__be16 *)&(st->rx[i*2])); | ||
84 | |||
85 | /* Guaranteed to be aligned with 8 byte boundary */ | ||
86 | if (ring->scan_timestamp) | ||
87 | *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; | ||
88 | |||
89 | ring->access->store_to(ring, (u8 *)data, pf->timestamp); | ||
90 | |||
91 | iio_trigger_notify_done(indio_dev->trig); | ||
92 | kfree(data); | ||
93 | |||
94 | return IRQ_HANDLED; | ||
95 | } | ||
96 | |||
97 | void adis16201_unconfigure_ring(struct iio_dev *indio_dev) | ||
98 | { | ||
99 | iio_dealloc_pollfunc(indio_dev->pollfunc); | ||
100 | iio_sw_rb_free(indio_dev->ring); | ||
101 | } | ||
102 | |||
103 | static const struct iio_ring_setup_ops adis16201_ring_setup_ops = { | ||
104 | .preenable = &iio_sw_ring_preenable, | ||
105 | .postenable = &iio_triggered_ring_postenable, | ||
106 | .predisable = &iio_triggered_ring_predisable, | ||
107 | }; | ||
108 | |||
109 | int adis16201_configure_ring(struct iio_dev *indio_dev) | ||
110 | { | ||
111 | int ret = 0; | ||
112 | struct iio_ring_buffer *ring; | ||
113 | |||
114 | ring = iio_sw_rb_allocate(indio_dev); | ||
115 | if (!ring) { | ||
116 | ret = -ENOMEM; | ||
117 | return ret; | ||
118 | } | ||
119 | indio_dev->ring = ring; | ||
120 | /* Effectively select the ring buffer implementation */ | ||
121 | ring->bpe = 2; | ||
122 | ring->scan_timestamp = true; | ||
123 | ring->access = &ring_sw_access_funcs; | ||
124 | ring->setup_ops = &adis16201_ring_setup_ops; | ||
125 | ring->owner = THIS_MODULE; | ||
126 | |||
127 | /* Set default scan mode */ | ||
128 | iio_scan_mask_set(ring, ADIS16201_SCAN_SUPPLY); | ||
129 | iio_scan_mask_set(ring, ADIS16201_SCAN_ACC_X); | ||
130 | iio_scan_mask_set(ring, ADIS16201_SCAN_ACC_Y); | ||
131 | iio_scan_mask_set(ring, ADIS16201_SCAN_AUX_ADC); | ||
132 | iio_scan_mask_set(ring, ADIS16201_SCAN_TEMP); | ||
133 | iio_scan_mask_set(ring, ADIS16201_SCAN_INCLI_X); | ||
134 | iio_scan_mask_set(ring, ADIS16201_SCAN_INCLI_Y); | ||
135 | |||
136 | indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, | ||
137 | &adis16201_trigger_handler, | ||
138 | IRQF_ONESHOT, | ||
139 | indio_dev, | ||
140 | "adis16201_consumer%d", | ||
141 | indio_dev->id); | ||
142 | if (indio_dev->pollfunc == NULL) { | ||
143 | ret = -ENOMEM; | ||
144 | goto error_iio_sw_rb_free; | ||
145 | } | ||
146 | |||
147 | indio_dev->modes |= INDIO_RING_TRIGGERED; | ||
148 | return 0; | ||
149 | error_iio_sw_rb_free: | ||
150 | iio_sw_rb_free(indio_dev->ring); | ||
151 | return ret; | ||
152 | } | ||
diff --git a/drivers/staging/iio/accel/adis16201_trigger.c b/drivers/staging/iio/accel/adis16201_trigger.c new file mode 100644 index 00000000000..3a95c083b45 --- /dev/null +++ b/drivers/staging/iio/accel/adis16201_trigger.c | |||
@@ -0,0 +1,71 @@ | |||
1 | #include <linux/interrupt.h> | ||
2 | #include <linux/irq.h> | ||
3 | #include <linux/mutex.h> | ||
4 | #include <linux/device.h> | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/sysfs.h> | ||
7 | #include <linux/spi/spi.h> | ||
8 | |||
9 | #include "../iio.h" | ||
10 | #include "../sysfs.h" | ||
11 | #include "../trigger.h" | ||
12 | #include "adis16201.h" | ||
13 | |||
14 | /** | ||
15 | * adis16201_data_rdy_trigger_set_state() set datardy interrupt state | ||
16 | **/ | ||
17 | static int adis16201_data_rdy_trigger_set_state(struct iio_trigger *trig, | ||
18 | bool state) | ||
19 | { | ||
20 | struct iio_dev *indio_dev = trig->private_data; | ||
21 | |||
22 | dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); | ||
23 | return adis16201_set_irq(indio_dev, state); | ||
24 | } | ||
25 | |||
26 | int adis16201_probe_trigger(struct iio_dev *indio_dev) | ||
27 | { | ||
28 | int ret; | ||
29 | struct adis16201_state *st = iio_priv(indio_dev); | ||
30 | |||
31 | st->trig = iio_allocate_trigger("adis16201-dev%d", indio_dev->id); | ||
32 | if (st->trig == NULL) { | ||
33 | ret = -ENOMEM; | ||
34 | goto error_ret; | ||
35 | } | ||
36 | ret = request_irq(st->us->irq, | ||
37 | &iio_trigger_generic_data_rdy_poll, | ||
38 | IRQF_TRIGGER_RISING, | ||
39 | "adis16201", | ||
40 | st->trig); | ||
41 | if (ret) | ||
42 | goto error_free_trig; | ||
43 | st->trig->dev.parent = &st->us->dev; | ||
44 | st->trig->owner = THIS_MODULE; | ||
45 | st->trig->private_data = indio_dev; | ||
46 | st->trig->set_trigger_state = &adis16201_data_rdy_trigger_set_state; | ||
47 | ret = iio_trigger_register(st->trig); | ||
48 | |||
49 | /* select default trigger */ | ||
50 | indio_dev->trig = st->trig; | ||
51 | if (ret) | ||
52 | goto error_free_irq; | ||
53 | |||
54 | return 0; | ||
55 | |||
56 | error_free_irq: | ||
57 | free_irq(st->us->irq, st->trig); | ||
58 | error_free_trig: | ||
59 | iio_free_trigger(st->trig); | ||
60 | error_ret: | ||
61 | return ret; | ||
62 | } | ||
63 | |||
64 | void adis16201_remove_trigger(struct iio_dev *indio_dev) | ||
65 | { | ||
66 | struct adis16201_state *state = iio_priv(indio_dev); | ||
67 | |||
68 | iio_trigger_unregister(state->trig); | ||
69 | free_irq(state->us->irq, state->trig); | ||
70 | iio_free_trigger(state->trig); | ||
71 | } | ||
diff --git a/drivers/staging/iio/accel/adis16203_ring.c b/drivers/staging/iio/accel/adis16203_ring.c new file mode 100644 index 00000000000..d2c07c52746 --- /dev/null +++ b/drivers/staging/iio/accel/adis16203_ring.c | |||
@@ -0,0 +1,158 @@ | |||
1 | #include <linux/interrupt.h> | ||
2 | #include <linux/irq.h> | ||
3 | #include <linux/gpio.h> | ||
4 | #include <linux/workqueue.h> | ||
5 | #include <linux/mutex.h> | ||
6 | #include <linux/device.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/spi/spi.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include <linux/sysfs.h> | ||
11 | #include <linux/list.h> | ||
12 | |||
13 | #include "../iio.h" | ||
14 | #include "../sysfs.h" | ||
15 | #include "../ring_sw.h" | ||
16 | #include "accel.h" | ||
17 | #include "../trigger.h" | ||
18 | #include "adis16203.h" | ||
19 | |||
20 | /** | ||
21 | * adis16203_read_ring_data() read data registers which will be placed into ring | ||
22 | * @dev: device associated with child of actual device (iio_dev or iio_trig) | ||
23 | * @rx: somewhere to pass back the value read | ||
24 | **/ | ||
25 | static int adis16203_read_ring_data(struct device *dev, u8 *rx) | ||
26 | { | ||
27 | struct spi_message msg; | ||
28 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
29 | struct adis16203_state *st = iio_priv(indio_dev); | ||
30 | struct spi_transfer xfers[ADIS16203_OUTPUTS + 1]; | ||
31 | int ret; | ||
32 | int i; | ||
33 | |||
34 | mutex_lock(&st->buf_lock); | ||
35 | |||
36 | spi_message_init(&msg); | ||
37 | |||
38 | memset(xfers, 0, sizeof(xfers)); | ||
39 | for (i = 0; i <= ADIS16203_OUTPUTS; i++) { | ||
40 | xfers[i].bits_per_word = 8; | ||
41 | xfers[i].cs_change = 1; | ||
42 | xfers[i].len = 2; | ||
43 | xfers[i].delay_usecs = 20; | ||
44 | xfers[i].tx_buf = st->tx + 2 * i; | ||
45 | if (i < 1) /* SUPPLY_OUT: 0x02, AUX_ADC: 0x08 */ | ||
46 | st->tx[2 * i] = ADIS16203_READ_REG(ADIS16203_SUPPLY_OUT + 2 * i); | ||
47 | else | ||
48 | st->tx[2 * i] = ADIS16203_READ_REG(ADIS16203_SUPPLY_OUT + 2 * i + 6); | ||
49 | st->tx[2 * i + 1] = 0; | ||
50 | if (i >= 1) | ||
51 | xfers[i].rx_buf = rx + 2 * (i - 1); | ||
52 | spi_message_add_tail(&xfers[i], &msg); | ||
53 | } | ||
54 | |||
55 | ret = spi_sync(st->us, &msg); | ||
56 | if (ret) | ||
57 | dev_err(&st->us->dev, "problem when burst reading"); | ||
58 | |||
59 | mutex_unlock(&st->buf_lock); | ||
60 | |||
61 | return ret; | ||
62 | } | ||
63 | |||
64 | /* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device | ||
65 | * specific to be rolled into the core. | ||
66 | */ | ||
67 | static irqreturn_t adis16203_trigger_handler(int irq, void *p) | ||
68 | { | ||
69 | struct iio_poll_func *pf = p; | ||
70 | struct iio_dev *indio_dev = pf->private_data; | ||
71 | struct adis16203_state *st = iio_priv(indio_dev); | ||
72 | struct iio_ring_buffer *ring = indio_dev->ring; | ||
73 | |||
74 | int i = 0; | ||
75 | s16 *data; | ||
76 | size_t datasize = ring->access->get_bytes_per_datum(ring); | ||
77 | |||
78 | data = kmalloc(datasize, GFP_KERNEL); | ||
79 | if (data == NULL) { | ||
80 | dev_err(&st->us->dev, "memory alloc failed in ring bh"); | ||
81 | return -ENOMEM; | ||
82 | } | ||
83 | |||
84 | if (ring->scan_count) | ||
85 | if (adis16203_read_ring_data(&indio_dev->dev, st->rx) >= 0) | ||
86 | for (; i < ring->scan_count; i++) | ||
87 | data[i] = be16_to_cpup( | ||
88 | (__be16 *)&(st->rx[i*2])); | ||
89 | |||
90 | /* Guaranteed to be aligned with 8 byte boundary */ | ||
91 | if (ring->scan_timestamp) | ||
92 | *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; | ||
93 | |||
94 | ring->access->store_to(ring, | ||
95 | (u8 *)data, | ||
96 | pf->timestamp); | ||
97 | |||
98 | iio_trigger_notify_done(indio_dev->trig); | ||
99 | kfree(data); | ||
100 | |||
101 | return IRQ_HANDLED; | ||
102 | } | ||
103 | |||
104 | void adis16203_unconfigure_ring(struct iio_dev *indio_dev) | ||
105 | { | ||
106 | iio_dealloc_pollfunc(indio_dev->pollfunc); | ||
107 | iio_sw_rb_free(indio_dev->ring); | ||
108 | } | ||
109 | |||
110 | static const struct iio_ring_setup_ops adis16203_ring_setup_ops = { | ||
111 | .preenable = &iio_sw_ring_preenable, | ||
112 | .postenable = &iio_triggered_ring_postenable, | ||
113 | .predisable = &iio_triggered_ring_predisable, | ||
114 | }; | ||
115 | |||
116 | int adis16203_configure_ring(struct iio_dev *indio_dev) | ||
117 | { | ||
118 | int ret = 0; | ||
119 | struct iio_ring_buffer *ring; | ||
120 | |||
121 | ring = iio_sw_rb_allocate(indio_dev); | ||
122 | if (!ring) { | ||
123 | ret = -ENOMEM; | ||
124 | return ret; | ||
125 | } | ||
126 | indio_dev->ring = ring; | ||
127 | /* Effectively select the ring buffer implementation */ | ||
128 | ring->bpe = 2; | ||
129 | ring->scan_timestamp = true; | ||
130 | ring->access = &ring_sw_access_funcs; | ||
131 | ring->setup_ops = &adis16203_ring_setup_ops; | ||
132 | ring->owner = THIS_MODULE; | ||
133 | |||
134 | /* Set default scan mode */ | ||
135 | iio_scan_mask_set(ring, ADIS16203_SCAN_SUPPLY); | ||
136 | iio_scan_mask_set(ring, ADIS16203_SCAN_TEMP); | ||
137 | iio_scan_mask_set(ring, ADIS16203_SCAN_AUX_ADC); | ||
138 | iio_scan_mask_set(ring, ADIS16203_SCAN_INCLI_X); | ||
139 | iio_scan_mask_set(ring, ADIS16203_SCAN_INCLI_Y); | ||
140 | |||
141 | indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, | ||
142 | &adis16203_trigger_handler, | ||
143 | IRQF_ONESHOT, | ||
144 | indio_dev, | ||
145 | "adis16203_consumer%d", | ||
146 | indio_dev->id); | ||
147 | if (indio_dev->pollfunc == NULL) { | ||
148 | ret = -ENOMEM; | ||
149 | goto error_iio_sw_rb_free; | ||
150 | } | ||
151 | |||
152 | indio_dev->modes |= INDIO_RING_TRIGGERED; | ||
153 | return 0; | ||
154 | |||
155 | error_iio_sw_rb_free: | ||
156 | iio_sw_rb_free(indio_dev->ring); | ||
157 | return ret; | ||
158 | } | ||
diff --git a/drivers/staging/iio/accel/adis16203_trigger.c b/drivers/staging/iio/accel/adis16203_trigger.c new file mode 100644 index 00000000000..3caf3e8bc9d --- /dev/null +++ b/drivers/staging/iio/accel/adis16203_trigger.c | |||
@@ -0,0 +1,74 @@ | |||
1 | #include <linux/interrupt.h> | ||
2 | #include <linux/irq.h> | ||
3 | #include <linux/mutex.h> | ||
4 | #include <linux/device.h> | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/sysfs.h> | ||
7 | #include <linux/list.h> | ||
8 | #include <linux/spi/spi.h> | ||
9 | |||
10 | #include "../iio.h" | ||
11 | #include "../sysfs.h" | ||
12 | #include "../trigger.h" | ||
13 | #include "adis16203.h" | ||
14 | |||
15 | /** | ||
16 | * adis16203_data_rdy_trigger_set_state() set datardy interrupt state | ||
17 | **/ | ||
18 | static int adis16203_data_rdy_trigger_set_state(struct iio_trigger *trig, | ||
19 | bool state) | ||
20 | { | ||
21 | struct iio_dev *indio_dev = trig->private_data; | ||
22 | |||
23 | dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); | ||
24 | return adis16203_set_irq(indio_dev, state); | ||
25 | } | ||
26 | |||
27 | int adis16203_probe_trigger(struct iio_dev *indio_dev) | ||
28 | { | ||
29 | int ret; | ||
30 | struct adis16203_state *st = iio_priv(indio_dev); | ||
31 | |||
32 | st->trig = iio_allocate_trigger("adis16203-dev%d", indio_dev->id); | ||
33 | if (st->trig == NULL) { | ||
34 | ret = -ENOMEM; | ||
35 | goto error_ret; | ||
36 | } | ||
37 | |||
38 | ret = request_irq(st->us->irq, | ||
39 | &iio_trigger_generic_data_rdy_poll, | ||
40 | IRQF_TRIGGER_RISING, | ||
41 | "adis16203", | ||
42 | st->trig); | ||
43 | if (ret) | ||
44 | goto error_free_trig; | ||
45 | |||
46 | st->trig->dev.parent = &st->us->dev; | ||
47 | st->trig->owner = THIS_MODULE; | ||
48 | st->trig->private_data = indio_dev; | ||
49 | st->trig->set_trigger_state = &adis16203_data_rdy_trigger_set_state; | ||
50 | ret = iio_trigger_register(st->trig); | ||
51 | |||
52 | /* select default trigger */ | ||
53 | indio_dev->trig = st->trig; | ||
54 | if (ret) | ||
55 | goto error_free_irq; | ||
56 | |||
57 | return 0; | ||
58 | |||
59 | error_free_irq: | ||
60 | free_irq(st->us->irq, st->trig); | ||
61 | error_free_trig: | ||
62 | iio_free_trigger(st->trig); | ||
63 | error_ret: | ||
64 | return ret; | ||
65 | } | ||
66 | |||
67 | void adis16203_remove_trigger(struct iio_dev *indio_dev) | ||
68 | { | ||
69 | struct adis16203_state *st = iio_priv(indio_dev); | ||
70 | |||
71 | iio_trigger_unregister(st->trig); | ||
72 | free_irq(st->us->irq, st->trig); | ||
73 | iio_free_trigger(st->trig); | ||
74 | } | ||
diff --git a/drivers/staging/iio/accel/adis16204_ring.c b/drivers/staging/iio/accel/adis16204_ring.c new file mode 100644 index 00000000000..852df06684d --- /dev/null +++ b/drivers/staging/iio/accel/adis16204_ring.c | |||
@@ -0,0 +1,154 @@ | |||
1 | #include <linux/interrupt.h> | ||
2 | #include <linux/irq.h> | ||
3 | #include <linux/gpio.h> | ||
4 | #include <linux/workqueue.h> | ||
5 | #include <linux/mutex.h> | ||
6 | #include <linux/device.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/spi/spi.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include <linux/sysfs.h> | ||
11 | #include <linux/list.h> | ||
12 | |||
13 | #include "../iio.h" | ||
14 | #include "../sysfs.h" | ||
15 | #include "../ring_sw.h" | ||
16 | #include "accel.h" | ||
17 | #include "../trigger.h" | ||
18 | #include "adis16204.h" | ||
19 | |||
20 | /** | ||
21 | * adis16204_read_ring_data() read data registers which will be placed into ring | ||
22 | * @dev: device associated with child of actual device (iio_dev or iio_trig) | ||
23 | * @rx: somewhere to pass back the value read | ||
24 | **/ | ||
25 | static int adis16204_read_ring_data(struct device *dev, u8 *rx) | ||
26 | { | ||
27 | struct spi_message msg; | ||
28 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
29 | struct adis16204_state *st = iio_priv(indio_dev); | ||
30 | struct spi_transfer xfers[ADIS16204_OUTPUTS + 1]; | ||
31 | int ret; | ||
32 | int i; | ||
33 | |||
34 | mutex_lock(&st->buf_lock); | ||
35 | |||
36 | spi_message_init(&msg); | ||
37 | |||
38 | memset(xfers, 0, sizeof(xfers)); | ||
39 | for (i = 0; i <= ADIS16204_OUTPUTS; i++) { | ||
40 | xfers[i].bits_per_word = 8; | ||
41 | xfers[i].cs_change = 1; | ||
42 | xfers[i].len = 2; | ||
43 | xfers[i].delay_usecs = 20; | ||
44 | xfers[i].tx_buf = st->tx + 2 * i; | ||
45 | st->tx[2 * i] | ||
46 | = ADIS16204_READ_REG(ADIS16204_SUPPLY_OUT + 2 * i); | ||
47 | st->tx[2 * i + 1] = 0; | ||
48 | if (i >= 1) | ||
49 | xfers[i].rx_buf = rx + 2 * (i - 1); | ||
50 | spi_message_add_tail(&xfers[i], &msg); | ||
51 | } | ||
52 | |||
53 | ret = spi_sync(st->us, &msg); | ||
54 | if (ret) | ||
55 | dev_err(&st->us->dev, "problem when burst reading"); | ||
56 | |||
57 | mutex_unlock(&st->buf_lock); | ||
58 | |||
59 | return ret; | ||
60 | } | ||
61 | |||
62 | /* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device | ||
63 | * specific to be rolled into the core. | ||
64 | */ | ||
65 | static irqreturn_t adis16204_trigger_handler(int irq, void *p) | ||
66 | { | ||
67 | struct iio_poll_func *pf = p; | ||
68 | struct iio_dev *indio_dev = pf->private_data; | ||
69 | struct adis16204_state *st = iio_priv(indio_dev); | ||
70 | struct iio_ring_buffer *ring = indio_dev->ring; | ||
71 | int i = 0; | ||
72 | s16 *data; | ||
73 | size_t datasize = ring->access->get_bytes_per_datum(ring); | ||
74 | |||
75 | data = kmalloc(datasize, GFP_KERNEL); | ||
76 | if (data == NULL) { | ||
77 | dev_err(&st->us->dev, "memory alloc failed in ring bh"); | ||
78 | return -ENOMEM; | ||
79 | } | ||
80 | |||
81 | if (ring->scan_count) | ||
82 | if (adis16204_read_ring_data(&indio_dev->dev, st->rx) >= 0) | ||
83 | for (; i < ring->scan_count; i++) | ||
84 | data[i] = be16_to_cpup( | ||
85 | (__be16 *)&(st->rx[i*2])); | ||
86 | |||
87 | /* Guaranteed to be aligned with 8 byte boundary */ | ||
88 | if (ring->scan_timestamp) | ||
89 | *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; | ||
90 | |||
91 | ring->access->store_to(ring, (u8 *)data, pf->timestamp); | ||
92 | |||
93 | iio_trigger_notify_done(indio_dev->trig); | ||
94 | kfree(data); | ||
95 | |||
96 | return IRQ_HANDLED; | ||
97 | } | ||
98 | |||
99 | void adis16204_unconfigure_ring(struct iio_dev *indio_dev) | ||
100 | { | ||
101 | iio_dealloc_pollfunc(indio_dev->pollfunc); | ||
102 | iio_sw_rb_free(indio_dev->ring); | ||
103 | } | ||
104 | |||
105 | static const struct iio_ring_setup_ops adis16204_ring_setup_ops = { | ||
106 | .preenable = &iio_sw_ring_preenable, | ||
107 | .postenable = &iio_triggered_ring_postenable, | ||
108 | .predisable = &iio_triggered_ring_predisable, | ||
109 | }; | ||
110 | |||
111 | int adis16204_configure_ring(struct iio_dev *indio_dev) | ||
112 | { | ||
113 | int ret = 0; | ||
114 | struct iio_ring_buffer *ring; | ||
115 | |||
116 | ring = iio_sw_rb_allocate(indio_dev); | ||
117 | if (!ring) { | ||
118 | ret = -ENOMEM; | ||
119 | return ret; | ||
120 | } | ||
121 | indio_dev->ring = ring; | ||
122 | /* Effectively select the ring buffer implementation */ | ||
123 | ring->access = &ring_sw_access_funcs; | ||
124 | ring->bpe = 2; | ||
125 | ring->scan_timestamp = true; | ||
126 | ring->setup_ops = &adis16204_ring_setup_ops; | ||
127 | ring->owner = THIS_MODULE; | ||
128 | |||
129 | /* Set default scan mode */ | ||
130 | iio_scan_mask_set(ring, ADIS16204_SCAN_SUPPLY); | ||
131 | iio_scan_mask_set(ring, ADIS16204_SCAN_ACC_X); | ||
132 | iio_scan_mask_set(ring, ADIS16204_SCAN_ACC_Y); | ||
133 | iio_scan_mask_set(ring, ADIS16204_SCAN_AUX_ADC); | ||
134 | iio_scan_mask_set(ring, ADIS16204_SCAN_TEMP); | ||
135 | |||
136 | indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, | ||
137 | &adis16204_trigger_handler, | ||
138 | IRQF_ONESHOT, | ||
139 | indio_dev, | ||
140 | "%s_consumer%d", | ||
141 | indio_dev->name, | ||
142 | indio_dev->id); | ||
143 | if (indio_dev->pollfunc == NULL) { | ||
144 | ret = -ENOMEM; | ||
145 | goto error_iio_sw_rb_free; | ||
146 | } | ||
147 | |||
148 | indio_dev->modes |= INDIO_RING_TRIGGERED; | ||
149 | return 0; | ||
150 | |||
151 | error_iio_sw_rb_free: | ||
152 | iio_sw_rb_free(indio_dev->ring); | ||
153 | return ret; | ||
154 | } | ||
diff --git a/drivers/staging/iio/accel/adis16204_trigger.c b/drivers/staging/iio/accel/adis16204_trigger.c new file mode 100644 index 00000000000..01f73b9b888 --- /dev/null +++ b/drivers/staging/iio/accel/adis16204_trigger.c | |||
@@ -0,0 +1,74 @@ | |||
1 | #include <linux/interrupt.h> | ||
2 | #include <linux/irq.h> | ||
3 | #include <linux/mutex.h> | ||
4 | #include <linux/device.h> | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/sysfs.h> | ||
7 | #include <linux/list.h> | ||
8 | #include <linux/spi/spi.h> | ||
9 | |||
10 | #include "../iio.h" | ||
11 | #include "../sysfs.h" | ||
12 | #include "../trigger.h" | ||
13 | #include "adis16204.h" | ||
14 | |||
15 | /** | ||
16 | * adis16204_data_rdy_trigger_set_state() set datardy interrupt state | ||
17 | **/ | ||
18 | static int adis16204_data_rdy_trigger_set_state(struct iio_trigger *trig, | ||
19 | bool state) | ||
20 | { | ||
21 | struct iio_dev *indio_dev = trig->private_data; | ||
22 | |||
23 | dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); | ||
24 | return adis16204_set_irq(indio_dev, state); | ||
25 | } | ||
26 | |||
27 | int adis16204_probe_trigger(struct iio_dev *indio_dev) | ||
28 | { | ||
29 | int ret; | ||
30 | struct adis16204_state *st = iio_priv(indio_dev); | ||
31 | |||
32 | st->trig = iio_allocate_trigger("adis16204-dev%d", indio_dev->id); | ||
33 | if (st->trig == NULL) { | ||
34 | ret = -ENOMEM; | ||
35 | goto error_ret; | ||
36 | } | ||
37 | |||
38 | ret = request_irq(st->us->irq, | ||
39 | &iio_trigger_generic_data_rdy_poll, | ||
40 | IRQF_TRIGGER_RISING, | ||
41 | "adis16204", | ||
42 | st->trig); | ||
43 | if (ret) | ||
44 | goto error_free_trig; | ||
45 | |||
46 | st->trig->dev.parent = &st->us->dev; | ||
47 | st->trig->owner = THIS_MODULE; | ||
48 | st->trig->private_data = indio_dev; | ||
49 | st->trig->set_trigger_state = &adis16204_data_rdy_trigger_set_state; | ||
50 | ret = iio_trigger_register(st->trig); | ||
51 | |||
52 | /* select default trigger */ | ||
53 | indio_dev->trig = st->trig; | ||
54 | if (ret) | ||
55 | goto error_free_irq; | ||
56 | |||
57 | return 0; | ||
58 | |||
59 | error_free_irq: | ||
60 | free_irq(st->us->irq, st->trig); | ||
61 | error_free_trig: | ||
62 | iio_free_trigger(st->trig); | ||
63 | error_ret: | ||
64 | return ret; | ||
65 | } | ||
66 | |||
67 | void adis16204_remove_trigger(struct iio_dev *indio_dev) | ||
68 | { | ||
69 | struct adis16204_state *state = iio_priv(indio_dev); | ||
70 | |||
71 | iio_trigger_unregister(state->trig); | ||
72 | free_irq(state->us->irq, state->trig); | ||
73 | iio_free_trigger(state->trig); | ||
74 | } | ||
diff --git a/drivers/staging/iio/accel/adis16209_ring.c b/drivers/staging/iio/accel/adis16209_ring.c new file mode 100644 index 00000000000..45017d3f02f --- /dev/null +++ b/drivers/staging/iio/accel/adis16209_ring.c | |||
@@ -0,0 +1,157 @@ | |||
1 | #include <linux/interrupt.h> | ||
2 | #include <linux/irq.h> | ||
3 | #include <linux/gpio.h> | ||
4 | #include <linux/workqueue.h> | ||
5 | #include <linux/mutex.h> | ||
6 | #include <linux/device.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/spi/spi.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include <linux/sysfs.h> | ||
11 | #include <linux/list.h> | ||
12 | |||
13 | #include "../iio.h" | ||
14 | #include "../sysfs.h" | ||
15 | #include "../ring_sw.h" | ||
16 | #include "accel.h" | ||
17 | #include "../trigger.h" | ||
18 | #include "adis16209.h" | ||
19 | |||
20 | /** | ||
21 | * adis16209_read_ring_data() read data registers which will be placed into ring | ||
22 | * @dev: device associated with child of actual device (iio_dev or iio_trig) | ||
23 | * @rx: somewhere to pass back the value read | ||
24 | **/ | ||
25 | static int adis16209_read_ring_data(struct device *dev, u8 *rx) | ||
26 | { | ||
27 | struct spi_message msg; | ||
28 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
29 | struct adis16209_state *st = iio_priv(indio_dev); | ||
30 | struct spi_transfer xfers[ADIS16209_OUTPUTS + 1]; | ||
31 | int ret; | ||
32 | int i; | ||
33 | |||
34 | mutex_lock(&st->buf_lock); | ||
35 | |||
36 | spi_message_init(&msg); | ||
37 | |||
38 | memset(xfers, 0, sizeof(xfers)); | ||
39 | for (i = 0; i <= ADIS16209_OUTPUTS; i++) { | ||
40 | xfers[i].bits_per_word = 8; | ||
41 | xfers[i].cs_change = 1; | ||
42 | xfers[i].len = 2; | ||
43 | xfers[i].delay_usecs = 30; | ||
44 | xfers[i].tx_buf = st->tx + 2 * i; | ||
45 | st->tx[2 * i] | ||
46 | = ADIS16209_READ_REG(ADIS16209_SUPPLY_OUT + 2 * i); | ||
47 | st->tx[2 * i + 1] = 0; | ||
48 | if (i >= 1) | ||
49 | xfers[i].rx_buf = rx + 2 * (i - 1); | ||
50 | spi_message_add_tail(&xfers[i], &msg); | ||
51 | } | ||
52 | |||
53 | ret = spi_sync(st->us, &msg); | ||
54 | if (ret) | ||
55 | dev_err(&st->us->dev, "problem when burst reading"); | ||
56 | |||
57 | mutex_unlock(&st->buf_lock); | ||
58 | |||
59 | return ret; | ||
60 | } | ||
61 | |||
62 | /* Whilst this makes a lot of calls to iio_sw_ring functions - it is to device | ||
63 | * specific to be rolled into the core. | ||
64 | */ | ||
65 | static irqreturn_t adis16209_trigger_handler(int irq, void *p) | ||
66 | { | ||
67 | struct iio_poll_func *pf = p; | ||
68 | struct iio_dev *indio_dev = pf->private_data; | ||
69 | struct adis16209_state *st = iio_priv(indio_dev); | ||
70 | struct iio_ring_buffer *ring = indio_dev->ring; | ||
71 | |||
72 | int i = 0; | ||
73 | s16 *data; | ||
74 | size_t datasize = ring->access->get_bytes_per_datum(ring); | ||
75 | |||
76 | data = kmalloc(datasize , GFP_KERNEL); | ||
77 | if (data == NULL) { | ||
78 | dev_err(&st->us->dev, "memory alloc failed in ring bh"); | ||
79 | return -ENOMEM; | ||
80 | } | ||
81 | |||
82 | if (ring->scan_count && | ||
83 | adis16209_read_ring_data(&indio_dev->dev, st->rx) >= 0) | ||
84 | for (; i < ring->scan_count; i++) | ||
85 | data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2])); | ||
86 | |||
87 | /* Guaranteed to be aligned with 8 byte boundary */ | ||
88 | if (ring->scan_timestamp) | ||
89 | *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; | ||
90 | |||
91 | ring->access->store_to(ring, (u8 *)data, pf->timestamp); | ||
92 | |||
93 | iio_trigger_notify_done(indio_dev->trig); | ||
94 | kfree(data); | ||
95 | |||
96 | return IRQ_HANDLED; | ||
97 | } | ||
98 | |||
99 | void adis16209_unconfigure_ring(struct iio_dev *indio_dev) | ||
100 | { | ||
101 | iio_dealloc_pollfunc(indio_dev->pollfunc); | ||
102 | iio_sw_rb_free(indio_dev->ring); | ||
103 | } | ||
104 | |||
105 | static const struct iio_ring_setup_ops adis16209_ring_setup_ops = { | ||
106 | .preenable = &iio_sw_ring_preenable, | ||
107 | .postenable = &iio_triggered_ring_postenable, | ||
108 | .predisable = &iio_triggered_ring_predisable, | ||
109 | }; | ||
110 | |||
111 | int adis16209_configure_ring(struct iio_dev *indio_dev) | ||
112 | { | ||
113 | int ret = 0; | ||
114 | struct iio_ring_buffer *ring; | ||
115 | |||
116 | ring = iio_sw_rb_allocate(indio_dev); | ||
117 | if (!ring) { | ||
118 | ret = -ENOMEM; | ||
119 | return ret; | ||
120 | } | ||
121 | indio_dev->ring = ring; | ||
122 | /* Effectively select the ring buffer implementation */ | ||
123 | ring->access = &ring_sw_access_funcs; | ||
124 | ring->bpe = 2; | ||
125 | ring->scan_timestamp = true; | ||
126 | ring->setup_ops = &adis16209_ring_setup_ops; | ||
127 | ring->owner = THIS_MODULE; | ||
128 | |||
129 | /* Set default scan mode */ | ||
130 | iio_scan_mask_set(ring, ADIS16209_SCAN_SUPPLY); | ||
131 | iio_scan_mask_set(ring, ADIS16209_SCAN_ACC_X); | ||
132 | iio_scan_mask_set(ring, ADIS16209_SCAN_ACC_Y); | ||
133 | iio_scan_mask_set(ring, ADIS16209_SCAN_AUX_ADC); | ||
134 | iio_scan_mask_set(ring, ADIS16209_SCAN_TEMP); | ||
135 | iio_scan_mask_set(ring, ADIS16209_SCAN_INCLI_X); | ||
136 | iio_scan_mask_set(ring, ADIS16209_SCAN_INCLI_Y); | ||
137 | iio_scan_mask_set(ring, ADIS16209_SCAN_ROT); | ||
138 | |||
139 | indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, | ||
140 | &adis16209_trigger_handler, | ||
141 | IRQF_ONESHOT, | ||
142 | indio_dev, | ||
143 | "%s_consumer%d", | ||
144 | indio_dev->name, | ||
145 | indio_dev->id); | ||
146 | if (indio_dev->pollfunc == NULL) { | ||
147 | ret = -ENOMEM; | ||
148 | goto error_iio_sw_rb_free; | ||
149 | } | ||
150 | |||
151 | indio_dev->modes |= INDIO_RING_TRIGGERED; | ||
152 | return 0; | ||
153 | |||
154 | error_iio_sw_rb_free: | ||
155 | iio_sw_rb_free(indio_dev->ring); | ||
156 | return ret; | ||
157 | } | ||
diff --git a/drivers/staging/iio/accel/adis16209_trigger.c b/drivers/staging/iio/accel/adis16209_trigger.c new file mode 100644 index 00000000000..6df7b47ec7b --- /dev/null +++ b/drivers/staging/iio/accel/adis16209_trigger.c | |||
@@ -0,0 +1,82 @@ | |||
1 | #include <linux/interrupt.h> | ||
2 | #include <linux/irq.h> | ||
3 | #include <linux/mutex.h> | ||
4 | #include <linux/device.h> | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/sysfs.h> | ||
7 | #include <linux/list.h> | ||
8 | #include <linux/spi/spi.h> | ||
9 | |||
10 | #include "../iio.h" | ||
11 | #include "../sysfs.h" | ||
12 | #include "../trigger.h" | ||
13 | #include "adis16209.h" | ||
14 | |||
15 | /** | ||
16 | * adis16209_data_rdy_trig_poll() the event handler for the data rdy trig | ||
17 | **/ | ||
18 | static irqreturn_t adis16209_data_rdy_trig_poll(int irq, void *trig) | ||
19 | { | ||
20 | iio_trigger_poll(trig, iio_get_time_ns()); | ||
21 | return IRQ_HANDLED; | ||
22 | } | ||
23 | |||
24 | /** | ||
25 | * adis16209_data_rdy_trigger_set_state() set datardy interrupt state | ||
26 | **/ | ||
27 | static int adis16209_data_rdy_trigger_set_state(struct iio_trigger *trig, | ||
28 | bool state) | ||
29 | { | ||
30 | struct iio_dev *indio_dev = trig->private_data; | ||
31 | |||
32 | dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); | ||
33 | return adis16209_set_irq(indio_dev, state); | ||
34 | } | ||
35 | |||
36 | int adis16209_probe_trigger(struct iio_dev *indio_dev) | ||
37 | { | ||
38 | int ret; | ||
39 | struct adis16209_state *st = iio_priv(indio_dev); | ||
40 | |||
41 | st->trig = iio_allocate_trigger("adis16209-dev%d", indio_dev->id); | ||
42 | if (st->trig == NULL) { | ||
43 | ret = -ENOMEM; | ||
44 | goto error_ret; | ||
45 | } | ||
46 | |||
47 | ret = request_irq(st->us->irq, | ||
48 | adis16209_data_rdy_trig_poll, | ||
49 | IRQF_TRIGGER_RISING, | ||
50 | "adis16209", | ||
51 | st->trig); | ||
52 | if (ret) | ||
53 | goto error_free_trig; | ||
54 | st->trig->dev.parent = &st->us->dev; | ||
55 | st->trig->owner = THIS_MODULE; | ||
56 | st->trig->private_data = indio_dev; | ||
57 | st->trig->set_trigger_state = &adis16209_data_rdy_trigger_set_state; | ||
58 | ret = iio_trigger_register(st->trig); | ||
59 | |||
60 | /* select default trigger */ | ||
61 | indio_dev->trig = st->trig; | ||
62 | if (ret) | ||
63 | goto error_free_irq; | ||
64 | |||
65 | return 0; | ||
66 | |||
67 | error_free_irq: | ||
68 | free_irq(st->us->irq, st->trig); | ||
69 | error_free_trig: | ||
70 | iio_free_trigger(st->trig); | ||
71 | error_ret: | ||
72 | return ret; | ||
73 | } | ||
74 | |||
75 | void adis16209_remove_trigger(struct iio_dev *indio_dev) | ||
76 | { | ||
77 | struct adis16209_state *st = iio_priv(indio_dev); | ||
78 | |||
79 | iio_trigger_unregister(st->trig); | ||
80 | free_irq(st->us->irq, st->trig); | ||
81 | iio_free_trigger(st->trig); | ||
82 | } | ||
diff --git a/drivers/staging/iio/accel/adis16240_ring.c b/drivers/staging/iio/accel/adis16240_ring.c new file mode 100644 index 00000000000..c812a34daca --- /dev/null +++ b/drivers/staging/iio/accel/adis16240_ring.c | |||
@@ -0,0 +1,152 @@ | |||
1 | #include <linux/interrupt.h> | ||
2 | #include <linux/irq.h> | ||
3 | #include <linux/gpio.h> | ||
4 | #include <linux/workqueue.h> | ||
5 | #include <linux/mutex.h> | ||
6 | #include <linux/device.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/spi/spi.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include <linux/sysfs.h> | ||
11 | #include <linux/list.h> | ||
12 | |||
13 | #include "../iio.h" | ||
14 | #include "../sysfs.h" | ||
15 | #include "../ring_sw.h" | ||
16 | #include "accel.h" | ||
17 | #include "../trigger.h" | ||
18 | #include "adis16240.h" | ||
19 | |||
20 | /** | ||
21 | * adis16240_read_ring_data() read data registers which will be placed into ring | ||
22 | * @dev: device associated with child of actual device (iio_dev or iio_trig) | ||
23 | * @rx: somewhere to pass back the value read | ||
24 | **/ | ||
25 | static int adis16240_read_ring_data(struct device *dev, u8 *rx) | ||
26 | { | ||
27 | struct spi_message msg; | ||
28 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
29 | struct adis16240_state *st = iio_priv(indio_dev); | ||
30 | struct spi_transfer xfers[ADIS16240_OUTPUTS + 1]; | ||
31 | int ret; | ||
32 | int i; | ||
33 | |||
34 | mutex_lock(&st->buf_lock); | ||
35 | |||
36 | spi_message_init(&msg); | ||
37 | |||
38 | memset(xfers, 0, sizeof(xfers)); | ||
39 | for (i = 0; i <= ADIS16240_OUTPUTS; i++) { | ||
40 | xfers[i].bits_per_word = 8; | ||
41 | xfers[i].cs_change = 1; | ||
42 | xfers[i].len = 2; | ||
43 | xfers[i].delay_usecs = 30; | ||
44 | xfers[i].tx_buf = st->tx + 2 * i; | ||
45 | st->tx[2 * i] | ||
46 | = ADIS16240_READ_REG(ADIS16240_SUPPLY_OUT + 2 * i); | ||
47 | st->tx[2 * i + 1] = 0; | ||
48 | if (i >= 1) | ||
49 | xfers[i].rx_buf = rx + 2 * (i - 1); | ||
50 | spi_message_add_tail(&xfers[i], &msg); | ||
51 | } | ||
52 | |||
53 | ret = spi_sync(st->us, &msg); | ||
54 | if (ret) | ||
55 | dev_err(&st->us->dev, "problem when burst reading"); | ||
56 | |||
57 | mutex_unlock(&st->buf_lock); | ||
58 | |||
59 | return ret; | ||
60 | } | ||
61 | |||
62 | static irqreturn_t adis16240_trigger_handler(int irq, void *p) | ||
63 | { | ||
64 | struct iio_poll_func *pf = p; | ||
65 | struct iio_dev *indio_dev = pf->private_data; | ||
66 | struct adis16240_state *st = iio_priv(indio_dev); | ||
67 | struct iio_ring_buffer *ring = indio_dev->ring; | ||
68 | |||
69 | int i = 0; | ||
70 | s16 *data; | ||
71 | size_t datasize = ring->access->get_bytes_per_datum(ring); | ||
72 | |||
73 | data = kmalloc(datasize, GFP_KERNEL); | ||
74 | if (data == NULL) { | ||
75 | dev_err(&st->us->dev, "memory alloc failed in ring bh"); | ||
76 | return -ENOMEM; | ||
77 | } | ||
78 | |||
79 | if (ring->scan_count && | ||
80 | adis16240_read_ring_data(&indio_dev->dev, st->rx) >= 0) | ||
81 | for (; i < ring->scan_count; i++) | ||
82 | data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2])); | ||
83 | |||
84 | /* Guaranteed to be aligned with 8 byte boundary */ | ||
85 | if (ring->scan_timestamp) | ||
86 | *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; | ||
87 | |||
88 | ring->access->store_to(ring, (u8 *)data, pf->timestamp); | ||
89 | |||
90 | iio_trigger_notify_done(indio_dev->trig); | ||
91 | kfree(data); | ||
92 | |||
93 | return IRQ_HANDLED; | ||
94 | } | ||
95 | |||
96 | void adis16240_unconfigure_ring(struct iio_dev *indio_dev) | ||
97 | { | ||
98 | iio_dealloc_pollfunc(indio_dev->pollfunc); | ||
99 | iio_sw_rb_free(indio_dev->ring); | ||
100 | } | ||
101 | |||
102 | static const struct iio_ring_setup_ops adis16240_ring_setup_ops = { | ||
103 | .preenable = &iio_sw_ring_preenable, | ||
104 | .postenable = &iio_triggered_ring_postenable, | ||
105 | .predisable = &iio_triggered_ring_predisable, | ||
106 | }; | ||
107 | |||
108 | int adis16240_configure_ring(struct iio_dev *indio_dev) | ||
109 | { | ||
110 | int ret = 0; | ||
111 | struct iio_ring_buffer *ring; | ||
112 | |||
113 | ring = iio_sw_rb_allocate(indio_dev); | ||
114 | if (!ring) { | ||
115 | ret = -ENOMEM; | ||
116 | return ret; | ||
117 | } | ||
118 | indio_dev->ring = ring; | ||
119 | /* Effectively select the ring buffer implementation */ | ||
120 | ring->access = &ring_sw_access_funcs; | ||
121 | ring->bpe = 2; | ||
122 | ring->scan_timestamp = true; | ||
123 | ring->setup_ops = &adis16240_ring_setup_ops; | ||
124 | ring->owner = THIS_MODULE; | ||
125 | |||
126 | /* Set default scan mode */ | ||
127 | iio_scan_mask_set(ring, ADIS16240_SCAN_SUPPLY); | ||
128 | iio_scan_mask_set(ring, ADIS16240_SCAN_ACC_X); | ||
129 | iio_scan_mask_set(ring, ADIS16240_SCAN_ACC_Y); | ||
130 | iio_scan_mask_set(ring, ADIS16240_SCAN_ACC_Z); | ||
131 | iio_scan_mask_set(ring, ADIS16240_SCAN_AUX_ADC); | ||
132 | iio_scan_mask_set(ring, ADIS16240_SCAN_TEMP); | ||
133 | |||
134 | indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, | ||
135 | &adis16240_trigger_handler, | ||
136 | IRQF_ONESHOT, | ||
137 | indio_dev, | ||
138 | "%s_consumer%d", | ||
139 | indio_dev->name, | ||
140 | indio_dev->id); | ||
141 | if (indio_dev->pollfunc == NULL) { | ||
142 | ret = -ENOMEM; | ||
143 | goto error_iio_sw_rb_free; | ||
144 | } | ||
145 | |||
146 | indio_dev->modes |= INDIO_RING_TRIGGERED; | ||
147 | return 0; | ||
148 | |||
149 | error_iio_sw_rb_free: | ||
150 | iio_sw_rb_free(indio_dev->ring); | ||
151 | return ret; | ||
152 | } | ||
diff --git a/drivers/staging/iio/accel/adis16240_trigger.c b/drivers/staging/iio/accel/adis16240_trigger.c new file mode 100644 index 00000000000..17135fc33c9 --- /dev/null +++ b/drivers/staging/iio/accel/adis16240_trigger.c | |||
@@ -0,0 +1,83 @@ | |||
1 | #include <linux/interrupt.h> | ||
2 | #include <linux/irq.h> | ||
3 | #include <linux/mutex.h> | ||
4 | #include <linux/device.h> | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/sysfs.h> | ||
7 | #include <linux/list.h> | ||
8 | #include <linux/spi/spi.h> | ||
9 | |||
10 | #include "../iio.h" | ||
11 | #include "../sysfs.h" | ||
12 | #include "../trigger.h" | ||
13 | #include "adis16240.h" | ||
14 | |||
15 | /** | ||
16 | * adis16240_data_rdy_trig_poll() the event handler for the data rdy trig | ||
17 | **/ | ||
18 | static irqreturn_t adis16240_data_rdy_trig_poll(int irq, void *trig) | ||
19 | { | ||
20 | iio_trigger_poll(trig, iio_get_time_ns()); | ||
21 | return IRQ_HANDLED; | ||
22 | } | ||
23 | |||
24 | /** | ||
25 | * adis16240_data_rdy_trigger_set_state() set datardy interrupt state | ||
26 | **/ | ||
27 | static int adis16240_data_rdy_trigger_set_state(struct iio_trigger *trig, | ||
28 | bool state) | ||
29 | { | ||
30 | struct iio_dev *indio_dev = trig->private_data; | ||
31 | |||
32 | dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); | ||
33 | return adis16240_set_irq(indio_dev, state); | ||
34 | } | ||
35 | |||
36 | int adis16240_probe_trigger(struct iio_dev *indio_dev) | ||
37 | { | ||
38 | int ret; | ||
39 | struct adis16240_state *st = iio_priv(indio_dev); | ||
40 | |||
41 | st->trig = iio_allocate_trigger("adis16240-dev%d", indio_dev->id); | ||
42 | if (st->trig == NULL) { | ||
43 | ret = -ENOMEM; | ||
44 | goto error_ret; | ||
45 | } | ||
46 | |||
47 | ret = request_irq(st->us->irq, | ||
48 | adis16240_data_rdy_trig_poll, | ||
49 | IRQF_TRIGGER_RISING, | ||
50 | "adis16240", | ||
51 | st->trig); | ||
52 | if (ret) | ||
53 | goto error_free_trig; | ||
54 | |||
55 | st->trig->dev.parent = &st->us->dev; | ||
56 | st->trig->owner = THIS_MODULE; | ||
57 | st->trig->private_data = indio_dev; | ||
58 | st->trig->set_trigger_state = &adis16240_data_rdy_trigger_set_state; | ||
59 | ret = iio_trigger_register(st->trig); | ||
60 | |||
61 | /* select default trigger */ | ||
62 | indio_dev->trig = st->trig; | ||
63 | if (ret) | ||
64 | goto error_free_irq; | ||
65 | |||
66 | return 0; | ||
67 | |||
68 | error_free_irq: | ||
69 | free_irq(st->us->irq, st->trig); | ||
70 | error_free_trig: | ||
71 | iio_free_trigger(st->trig); | ||
72 | error_ret: | ||
73 | return ret; | ||
74 | } | ||
75 | |||
76 | void adis16240_remove_trigger(struct iio_dev *indio_dev) | ||
77 | { | ||
78 | struct adis16240_state *st = iio_priv(indio_dev); | ||
79 | |||
80 | iio_trigger_unregister(st->trig); | ||
81 | free_irq(st->us->irq, st->trig); | ||
82 | iio_free_trigger(st->trig); | ||
83 | } | ||
diff --git a/drivers/staging/iio/accel/inclinometer.h b/drivers/staging/iio/accel/inclinometer.h new file mode 100644 index 00000000000..faf73d7892e --- /dev/null +++ b/drivers/staging/iio/accel/inclinometer.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * Inclinometer related attributes | ||
3 | */ | ||
4 | #include "../sysfs.h" | ||
5 | |||
6 | #define IIO_DEV_ATTR_INCLI_X(_show, _addr) \ | ||
7 | IIO_DEVICE_ATTR(incli_x_raw, S_IRUGO, _show, NULL, _addr) | ||
8 | |||
9 | #define IIO_DEV_ATTR_INCLI_Y(_show, _addr) \ | ||
10 | IIO_DEVICE_ATTR(incli_y_raw, S_IRUGO, _show, NULL, _addr) | ||
11 | |||
12 | #define IIO_DEV_ATTR_INCLI_Z(_show, _addr) \ | ||
13 | IIO_DEVICE_ATTR(incli_z_raw, S_IRUGO, _show, NULL, _addr) | ||
14 | |||
15 | #define IIO_DEV_ATTR_INCLI_X_OFFSET(_mode, _show, _store, _addr) \ | ||
16 | IIO_DEVICE_ATTR(incli_x_offset, _mode, _show, _store, _addr) | ||
17 | |||
18 | #define IIO_DEV_ATTR_INCLI_Y_OFFSET(_mode, _show, _store, _addr) \ | ||
19 | IIO_DEVICE_ATTR(incli_y_offset, _mode, _show, _store, _addr) | ||
20 | |||
21 | #define IIO_DEV_ATTR_INCLI_Z_OFFSET(_mode, _show, _store, _addr) \ | ||
22 | IIO_DEVICE_ATTR(incli_z_offset, _mode, _show, _store, _addr) | ||
23 | |||
24 | #define IIO_CONST_ATTR_INCLI_SCALE(_string) \ | ||
25 | IIO_CONST_ATTR(incli_scale, _string) | ||
diff --git a/drivers/staging/iio/adc/ad7150.c b/drivers/staging/iio/adc/ad7150.c new file mode 100644 index 00000000000..04017ef6688 --- /dev/null +++ b/drivers/staging/iio/adc/ad7150.c | |||
@@ -0,0 +1,812 @@ | |||
1 | /* | ||
2 | * AD7150 capacitive sensor driver supporting AD7150/1/6 | ||
3 | * | ||
4 | * Copyright 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/device.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/i2c.h> | ||
14 | |||
15 | #include "../iio.h" | ||
16 | #include "../sysfs.h" | ||
17 | |||
18 | /* | ||
19 | * AD7150 registers definition | ||
20 | */ | ||
21 | |||
22 | #define AD7150_STATUS 0 | ||
23 | #define AD7150_STATUS_OUT1 (1 << 3) | ||
24 | #define AD7150_STATUS_OUT2 (1 << 5) | ||
25 | #define AD7150_CH1_DATA_HIGH 1 | ||
26 | #define AD7150_CH1_DATA_LOW 2 | ||
27 | #define AD7150_CH2_DATA_HIGH 3 | ||
28 | #define AD7150_CH2_DATA_LOW 4 | ||
29 | #define AD7150_CH1_AVG_HIGH 5 | ||
30 | #define AD7150_CH1_AVG_LOW 6 | ||
31 | #define AD7150_CH2_AVG_HIGH 7 | ||
32 | #define AD7150_CH2_AVG_LOW 8 | ||
33 | #define AD7150_CH1_SENSITIVITY 9 | ||
34 | #define AD7150_CH1_THR_HOLD_H 9 | ||
35 | #define AD7150_CH1_TIMEOUT 10 | ||
36 | #define AD7150_CH1_THR_HOLD_L 10 | ||
37 | #define AD7150_CH1_SETUP 11 | ||
38 | #define AD7150_CH2_SENSITIVITY 12 | ||
39 | #define AD7150_CH2_THR_HOLD_H 12 | ||
40 | #define AD7150_CH2_TIMEOUT 13 | ||
41 | #define AD7150_CH2_THR_HOLD_L 13 | ||
42 | #define AD7150_CH2_SETUP 14 | ||
43 | #define AD7150_CFG 15 | ||
44 | #define AD7150_CFG_FIX (1 << 7) | ||
45 | #define AD7150_PD_TIMER 16 | ||
46 | #define AD7150_CH1_CAPDAC 17 | ||
47 | #define AD7150_CH2_CAPDAC 18 | ||
48 | #define AD7150_SN3 19 | ||
49 | #define AD7150_SN2 20 | ||
50 | #define AD7150_SN1 21 | ||
51 | #define AD7150_SN0 22 | ||
52 | #define AD7150_ID 23 | ||
53 | |||
54 | #define AD7150_MAX_CONV_MODE 4 | ||
55 | |||
56 | /* | ||
57 | * struct ad7150_chip_info - chip specifc information | ||
58 | */ | ||
59 | |||
60 | struct ad7150_chip_info { | ||
61 | struct i2c_client *client; | ||
62 | bool inter; | ||
63 | u16 ch1_threshold; /* Ch1 Threshold (in fixed threshold mode) */ | ||
64 | u8 ch1_sensitivity; /* Ch1 Sensitivity (in adaptive threshold mode) */ | ||
65 | u8 ch1_timeout; /* Ch1 Timeout (in adaptive threshold mode) */ | ||
66 | u8 ch1_setup; | ||
67 | u16 ch2_threshold; /* Ch2 Threshold (in fixed threshold mode) */ | ||
68 | u8 ch2_sensitivity; /* Ch1 Sensitivity (in adaptive threshold mode) */ | ||
69 | u8 ch2_timeout; /* Ch1 Timeout (in adaptive threshold mode) */ | ||
70 | u8 ch2_setup; | ||
71 | u8 powerdown_timer; | ||
72 | char threshold_mode[10]; /* adaptive/fixed threshold mode */ | ||
73 | int old_state; | ||
74 | char *conversion_mode; | ||
75 | }; | ||
76 | |||
77 | struct ad7150_conversion_mode { | ||
78 | char *name; | ||
79 | u8 reg_cfg; | ||
80 | }; | ||
81 | |||
82 | static struct ad7150_conversion_mode | ||
83 | ad7150_conv_mode_table[AD7150_MAX_CONV_MODE] = { | ||
84 | { "idle", 0 }, | ||
85 | { "continuous-conversion", 1 }, | ||
86 | { "single-conversion", 2 }, | ||
87 | { "power-down", 3 }, | ||
88 | }; | ||
89 | |||
90 | /* | ||
91 | * ad7150 register access by I2C | ||
92 | */ | ||
93 | |||
94 | static int ad7150_i2c_read(struct ad7150_chip_info *chip, u8 reg, u8 *data, int len) | ||
95 | { | ||
96 | struct i2c_client *client = chip->client; | ||
97 | int ret = 0; | ||
98 | |||
99 | ret = i2c_master_send(client, ®, 1); | ||
100 | if (ret < 0) { | ||
101 | dev_err(&client->dev, "I2C write error\n"); | ||
102 | return ret; | ||
103 | } | ||
104 | |||
105 | ret = i2c_master_recv(client, data, len); | ||
106 | if (ret < 0) { | ||
107 | dev_err(&client->dev, "I2C read error\n"); | ||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | return ret; | ||
112 | } | ||
113 | |||
114 | static int ad7150_i2c_write(struct ad7150_chip_info *chip, u8 reg, u8 data) | ||
115 | { | ||
116 | struct i2c_client *client = chip->client; | ||
117 | int ret = 0; | ||
118 | |||
119 | u8 tx[2] = { | ||
120 | reg, | ||
121 | data, | ||
122 | }; | ||
123 | |||
124 | ret = i2c_master_send(client, tx, 2); | ||
125 | if (ret < 0) | ||
126 | dev_err(&client->dev, "I2C write error\n"); | ||
127 | |||
128 | return ret; | ||
129 | } | ||
130 | |||
131 | /* | ||
132 | * sysfs nodes | ||
133 | */ | ||
134 | |||
135 | #define IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(_show) \ | ||
136 | IIO_DEVICE_ATTR(available_conversion_modes, S_IRUGO, _show, NULL, 0) | ||
137 | #define IIO_DEV_ATTR_CONVERSION_MODE(_mode, _show, _store) \ | ||
138 | IIO_DEVICE_ATTR(conversion_mode, _mode, _show, _store, 0) | ||
139 | #define IIO_DEV_ATTR_AVAIL_THRESHOLD_MODES(_show) \ | ||
140 | IIO_DEVICE_ATTR(available_threshold_modes, S_IRUGO, _show, NULL, 0) | ||
141 | #define IIO_DEV_ATTR_THRESHOLD_MODE(_mode, _show, _store) \ | ||
142 | IIO_DEVICE_ATTR(threshold_mode, _mode, _show, _store, 0) | ||
143 | #define IIO_DEV_ATTR_CH1_THRESHOLD(_mode, _show, _store) \ | ||
144 | IIO_DEVICE_ATTR(ch1_threshold, _mode, _show, _store, 0) | ||
145 | #define IIO_DEV_ATTR_CH2_THRESHOLD(_mode, _show, _store) \ | ||
146 | IIO_DEVICE_ATTR(ch2_threshold, _mode, _show, _store, 0) | ||
147 | #define IIO_DEV_ATTR_CH1_SENSITIVITY(_mode, _show, _store) \ | ||
148 | IIO_DEVICE_ATTR(ch1_sensitivity, _mode, _show, _store, 0) | ||
149 | #define IIO_DEV_ATTR_CH2_SENSITIVITY(_mode, _show, _store) \ | ||
150 | IIO_DEVICE_ATTR(ch2_sensitivity, _mode, _show, _store, 0) | ||
151 | #define IIO_DEV_ATTR_CH1_TIMEOUT(_mode, _show, _store) \ | ||
152 | IIO_DEVICE_ATTR(ch1_timeout, _mode, _show, _store, 0) | ||
153 | #define IIO_DEV_ATTR_CH2_TIMEOUT(_mode, _show, _store) \ | ||
154 | IIO_DEVICE_ATTR(ch2_timeout, _mode, _show, _store, 0) | ||
155 | #define IIO_DEV_ATTR_CH1_VALUE(_show) \ | ||
156 | IIO_DEVICE_ATTR(ch1_value, S_IRUGO, _show, NULL, 0) | ||
157 | #define IIO_DEV_ATTR_CH2_VALUE(_show) \ | ||
158 | IIO_DEVICE_ATTR(ch2_value, S_IRUGO, _show, NULL, 0) | ||
159 | #define IIO_DEV_ATTR_CH1_SETUP(_mode, _show, _store) \ | ||
160 | IIO_DEVICE_ATTR(ch1_setup, _mode, _show, _store, 0) | ||
161 | #define IIO_DEV_ATTR_CH2_SETUP(_mode, _show, _store) \ | ||
162 | IIO_DEVICE_ATTR(ch2_setup, _mode, _show, _store, 0) | ||
163 | #define IIO_DEV_ATTR_POWERDOWN_TIMER(_mode, _show, _store) \ | ||
164 | IIO_DEVICE_ATTR(powerdown_timer, _mode, _show, _store, 0) | ||
165 | |||
166 | static ssize_t ad7150_show_conversion_modes(struct device *dev, | ||
167 | struct device_attribute *attr, | ||
168 | char *buf) | ||
169 | { | ||
170 | int i; | ||
171 | int len = 0; | ||
172 | |||
173 | for (i = 0; i < AD7150_MAX_CONV_MODE; i++) | ||
174 | len += sprintf(buf + len, "%s\n", ad7150_conv_mode_table[i].name); | ||
175 | |||
176 | return len; | ||
177 | } | ||
178 | |||
179 | static IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(ad7150_show_conversion_modes); | ||
180 | |||
181 | static ssize_t ad7150_show_conversion_mode(struct device *dev, | ||
182 | struct device_attribute *attr, | ||
183 | char *buf) | ||
184 | { | ||
185 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
186 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
187 | |||
188 | return sprintf(buf, "%s\n", chip->conversion_mode); | ||
189 | } | ||
190 | |||
191 | static ssize_t ad7150_store_conversion_mode(struct device *dev, | ||
192 | struct device_attribute *attr, | ||
193 | const char *buf, | ||
194 | size_t len) | ||
195 | { | ||
196 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
197 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
198 | u8 cfg; | ||
199 | int i; | ||
200 | |||
201 | ad7150_i2c_read(chip, AD7150_CFG, &cfg, 1); | ||
202 | |||
203 | for (i = 0; i < AD7150_MAX_CONV_MODE; i++) { | ||
204 | if (strncmp(buf, ad7150_conv_mode_table[i].name, | ||
205 | strlen(ad7150_conv_mode_table[i].name) - 1) == 0) { | ||
206 | chip->conversion_mode = ad7150_conv_mode_table[i].name; | ||
207 | cfg |= 0x18 | ad7150_conv_mode_table[i].reg_cfg; | ||
208 | ad7150_i2c_write(chip, AD7150_CFG, cfg); | ||
209 | return len; | ||
210 | } | ||
211 | } | ||
212 | |||
213 | dev_err(dev, "not supported conversion mode\n"); | ||
214 | |||
215 | return -EINVAL; | ||
216 | } | ||
217 | |||
218 | static IIO_DEV_ATTR_CONVERSION_MODE(S_IRUGO | S_IWUSR, | ||
219 | ad7150_show_conversion_mode, | ||
220 | ad7150_store_conversion_mode); | ||
221 | |||
222 | static ssize_t ad7150_show_threshold_modes(struct device *dev, | ||
223 | struct device_attribute *attr, | ||
224 | char *buf) | ||
225 | { | ||
226 | return sprintf(buf, "adaptive\nfixed\n"); | ||
227 | } | ||
228 | |||
229 | static IIO_DEV_ATTR_AVAIL_THRESHOLD_MODES(ad7150_show_threshold_modes); | ||
230 | |||
231 | static ssize_t ad7150_show_ch1_value(struct device *dev, | ||
232 | struct device_attribute *attr, | ||
233 | char *buf) | ||
234 | { | ||
235 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
236 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
237 | u8 data[2]; | ||
238 | |||
239 | ad7150_i2c_read(chip, AD7150_CH1_DATA_HIGH, data, 2); | ||
240 | return sprintf(buf, "%d\n", ((int) data[0] << 8) | data[1]); | ||
241 | } | ||
242 | |||
243 | static IIO_DEV_ATTR_CH1_VALUE(ad7150_show_ch1_value); | ||
244 | |||
245 | static ssize_t ad7150_show_ch2_value(struct device *dev, | ||
246 | struct device_attribute *attr, | ||
247 | char *buf) | ||
248 | { | ||
249 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
250 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
251 | u8 data[2]; | ||
252 | |||
253 | ad7150_i2c_read(chip, AD7150_CH2_DATA_HIGH, data, 2); | ||
254 | return sprintf(buf, "%d\n", ((int) data[0] << 8) | data[1]); | ||
255 | } | ||
256 | |||
257 | static IIO_DEV_ATTR_CH2_VALUE(ad7150_show_ch2_value); | ||
258 | |||
259 | static ssize_t ad7150_show_threshold_mode(struct device *dev, | ||
260 | struct device_attribute *attr, | ||
261 | char *buf) | ||
262 | { | ||
263 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
264 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
265 | |||
266 | return sprintf(buf, "%s\n", chip->threshold_mode); | ||
267 | } | ||
268 | |||
269 | static ssize_t ad7150_store_threshold_mode(struct device *dev, | ||
270 | struct device_attribute *attr, | ||
271 | const char *buf, | ||
272 | size_t len) | ||
273 | { | ||
274 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
275 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
276 | u8 cfg; | ||
277 | |||
278 | ad7150_i2c_read(chip, AD7150_CFG, &cfg, 1); | ||
279 | |||
280 | if (strncmp(buf, "fixed", 5) == 0) { | ||
281 | strcpy(chip->threshold_mode, "fixed"); | ||
282 | cfg |= AD7150_CFG_FIX; | ||
283 | ad7150_i2c_write(chip, AD7150_CFG, cfg); | ||
284 | |||
285 | return len; | ||
286 | } else if (strncmp(buf, "adaptive", 8) == 0) { | ||
287 | strcpy(chip->threshold_mode, "adaptive"); | ||
288 | cfg &= ~AD7150_CFG_FIX; | ||
289 | ad7150_i2c_write(chip, AD7150_CFG, cfg); | ||
290 | |||
291 | return len; | ||
292 | } | ||
293 | |||
294 | dev_err(dev, "not supported threshold mode\n"); | ||
295 | return -EINVAL; | ||
296 | } | ||
297 | |||
298 | static IIO_DEV_ATTR_THRESHOLD_MODE(S_IRUGO | S_IWUSR, | ||
299 | ad7150_show_threshold_mode, | ||
300 | ad7150_store_threshold_mode); | ||
301 | |||
302 | static ssize_t ad7150_show_ch1_threshold(struct device *dev, | ||
303 | struct device_attribute *attr, | ||
304 | char *buf) | ||
305 | { | ||
306 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
307 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
308 | |||
309 | return sprintf(buf, "%d\n", chip->ch1_threshold); | ||
310 | } | ||
311 | |||
312 | static ssize_t ad7150_store_ch1_threshold(struct device *dev, | ||
313 | struct device_attribute *attr, | ||
314 | const char *buf, | ||
315 | size_t len) | ||
316 | { | ||
317 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
318 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
319 | unsigned long data; | ||
320 | int ret; | ||
321 | |||
322 | ret = strict_strtoul(buf, 10, &data); | ||
323 | |||
324 | if ((!ret) && (data < 0x10000)) { | ||
325 | ad7150_i2c_write(chip, AD7150_CH1_THR_HOLD_H, data >> 8); | ||
326 | ad7150_i2c_write(chip, AD7150_CH1_THR_HOLD_L, data); | ||
327 | chip->ch1_threshold = data; | ||
328 | return len; | ||
329 | } | ||
330 | |||
331 | return -EINVAL; | ||
332 | } | ||
333 | |||
334 | static IIO_DEV_ATTR_CH1_THRESHOLD(S_IRUGO | S_IWUSR, | ||
335 | ad7150_show_ch1_threshold, | ||
336 | ad7150_store_ch1_threshold); | ||
337 | |||
338 | static ssize_t ad7150_show_ch2_threshold(struct device *dev, | ||
339 | struct device_attribute *attr, | ||
340 | char *buf) | ||
341 | { | ||
342 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
343 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
344 | |||
345 | return sprintf(buf, "%d\n", chip->ch2_threshold); | ||
346 | } | ||
347 | |||
348 | static ssize_t ad7150_store_ch2_threshold(struct device *dev, | ||
349 | struct device_attribute *attr, | ||
350 | const char *buf, | ||
351 | size_t len) | ||
352 | { | ||
353 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
354 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
355 | unsigned long data; | ||
356 | int ret; | ||
357 | |||
358 | ret = strict_strtoul(buf, 10, &data); | ||
359 | |||
360 | if ((!ret) && (data < 0x10000)) { | ||
361 | ad7150_i2c_write(chip, AD7150_CH2_THR_HOLD_H, data >> 8); | ||
362 | ad7150_i2c_write(chip, AD7150_CH2_THR_HOLD_L, data); | ||
363 | chip->ch2_threshold = data; | ||
364 | return len; | ||
365 | } | ||
366 | |||
367 | return -EINVAL; | ||
368 | } | ||
369 | |||
370 | static IIO_DEV_ATTR_CH2_THRESHOLD(S_IRUGO | S_IWUSR, | ||
371 | ad7150_show_ch2_threshold, | ||
372 | ad7150_store_ch2_threshold); | ||
373 | |||
374 | static ssize_t ad7150_show_ch1_sensitivity(struct device *dev, | ||
375 | struct device_attribute *attr, | ||
376 | char *buf) | ||
377 | { | ||
378 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
379 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
380 | |||
381 | return sprintf(buf, "%d\n", chip->ch1_sensitivity); | ||
382 | } | ||
383 | |||
384 | static ssize_t ad7150_store_ch1_sensitivity(struct device *dev, | ||
385 | struct device_attribute *attr, | ||
386 | const char *buf, | ||
387 | size_t len) | ||
388 | { | ||
389 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
390 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
391 | unsigned long data; | ||
392 | int ret; | ||
393 | |||
394 | ret = strict_strtoul(buf, 10, &data); | ||
395 | |||
396 | if ((!ret) && (data < 0x100)) { | ||
397 | ad7150_i2c_write(chip, AD7150_CH1_SENSITIVITY, data); | ||
398 | chip->ch1_sensitivity = data; | ||
399 | return len; | ||
400 | } | ||
401 | |||
402 | return -EINVAL; | ||
403 | } | ||
404 | |||
405 | static IIO_DEV_ATTR_CH1_SENSITIVITY(S_IRUGO | S_IWUSR, | ||
406 | ad7150_show_ch1_sensitivity, | ||
407 | ad7150_store_ch1_sensitivity); | ||
408 | |||
409 | static ssize_t ad7150_show_ch2_sensitivity(struct device *dev, | ||
410 | struct device_attribute *attr, | ||
411 | char *buf) | ||
412 | { | ||
413 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
414 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
415 | |||
416 | return sprintf(buf, "%d\n", chip->ch2_sensitivity); | ||
417 | } | ||
418 | |||
419 | static ssize_t ad7150_store_ch2_sensitivity(struct device *dev, | ||
420 | struct device_attribute *attr, | ||
421 | const char *buf, | ||
422 | size_t len) | ||
423 | { | ||
424 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
425 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
426 | unsigned long data; | ||
427 | int ret; | ||
428 | |||
429 | ret = strict_strtoul(buf, 10, &data); | ||
430 | |||
431 | if ((!ret) && (data < 0x100)) { | ||
432 | ad7150_i2c_write(chip, AD7150_CH2_SENSITIVITY, data); | ||
433 | chip->ch2_sensitivity = data; | ||
434 | return len; | ||
435 | } | ||
436 | |||
437 | return -EINVAL; | ||
438 | } | ||
439 | |||
440 | static IIO_DEV_ATTR_CH2_SENSITIVITY(S_IRUGO | S_IWUSR, | ||
441 | ad7150_show_ch2_sensitivity, | ||
442 | ad7150_store_ch2_sensitivity); | ||
443 | |||
444 | static ssize_t ad7150_show_ch1_timeout(struct device *dev, | ||
445 | struct device_attribute *attr, | ||
446 | char *buf) | ||
447 | { | ||
448 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
449 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
450 | |||
451 | return sprintf(buf, "%d\n", chip->ch1_timeout); | ||
452 | } | ||
453 | |||
454 | static ssize_t ad7150_store_ch1_timeout(struct device *dev, | ||
455 | struct device_attribute *attr, | ||
456 | const char *buf, | ||
457 | size_t len) | ||
458 | { | ||
459 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
460 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
461 | unsigned long data; | ||
462 | int ret; | ||
463 | |||
464 | ret = strict_strtoul(buf, 10, &data); | ||
465 | |||
466 | if ((!ret) && (data < 0x100)) { | ||
467 | ad7150_i2c_write(chip, AD7150_CH1_TIMEOUT, data); | ||
468 | chip->ch1_timeout = data; | ||
469 | return len; | ||
470 | } | ||
471 | |||
472 | return -EINVAL; | ||
473 | } | ||
474 | |||
475 | static IIO_DEV_ATTR_CH1_TIMEOUT(S_IRUGO | S_IWUSR, | ||
476 | ad7150_show_ch1_timeout, | ||
477 | ad7150_store_ch1_timeout); | ||
478 | |||
479 | static ssize_t ad7150_show_ch2_timeout(struct device *dev, | ||
480 | struct device_attribute *attr, | ||
481 | char *buf) | ||
482 | { | ||
483 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
484 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
485 | |||
486 | return sprintf(buf, "%d\n", chip->ch2_timeout); | ||
487 | } | ||
488 | |||
489 | static ssize_t ad7150_store_ch2_timeout(struct device *dev, | ||
490 | struct device_attribute *attr, | ||
491 | const char *buf, | ||
492 | size_t len) | ||
493 | { | ||
494 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
495 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
496 | unsigned long data; | ||
497 | int ret; | ||
498 | |||
499 | ret = strict_strtoul(buf, 10, &data); | ||
500 | |||
501 | if ((!ret) && (data < 0x100)) { | ||
502 | ad7150_i2c_write(chip, AD7150_CH2_TIMEOUT, data); | ||
503 | chip->ch2_timeout = data; | ||
504 | return len; | ||
505 | } | ||
506 | |||
507 | return -EINVAL; | ||
508 | } | ||
509 | |||
510 | static IIO_DEV_ATTR_CH2_TIMEOUT(S_IRUGO | S_IWUSR, | ||
511 | ad7150_show_ch2_timeout, | ||
512 | ad7150_store_ch2_timeout); | ||
513 | |||
514 | static ssize_t ad7150_show_ch1_setup(struct device *dev, | ||
515 | struct device_attribute *attr, | ||
516 | char *buf) | ||
517 | { | ||
518 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
519 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
520 | |||
521 | return sprintf(buf, "0x%02x\n", chip->ch1_setup); | ||
522 | } | ||
523 | |||
524 | static ssize_t ad7150_store_ch1_setup(struct device *dev, | ||
525 | struct device_attribute *attr, | ||
526 | const char *buf, | ||
527 | size_t len) | ||
528 | { | ||
529 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
530 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
531 | unsigned long data; | ||
532 | int ret; | ||
533 | |||
534 | ret = strict_strtoul(buf, 10, &data); | ||
535 | |||
536 | if ((!ret) && (data < 0x100)) { | ||
537 | ad7150_i2c_write(chip, AD7150_CH1_SETUP, data); | ||
538 | chip->ch1_setup = data; | ||
539 | return len; | ||
540 | } | ||
541 | |||
542 | |||
543 | return -EINVAL; | ||
544 | } | ||
545 | |||
546 | static IIO_DEV_ATTR_CH1_SETUP(S_IRUGO | S_IWUSR, | ||
547 | ad7150_show_ch1_setup, | ||
548 | ad7150_store_ch1_setup); | ||
549 | |||
550 | static ssize_t ad7150_show_ch2_setup(struct device *dev, | ||
551 | struct device_attribute *attr, | ||
552 | char *buf) | ||
553 | { | ||
554 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
555 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
556 | |||
557 | return sprintf(buf, "0x%02x\n", chip->ch2_setup); | ||
558 | } | ||
559 | |||
560 | static ssize_t ad7150_store_ch2_setup(struct device *dev, | ||
561 | struct device_attribute *attr, | ||
562 | const char *buf, | ||
563 | size_t len) | ||
564 | { | ||
565 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
566 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
567 | unsigned long data; | ||
568 | int ret; | ||
569 | |||
570 | ret = strict_strtoul(buf, 10, &data); | ||
571 | |||
572 | if ((!ret) && (data < 0x100)) { | ||
573 | ad7150_i2c_write(chip, AD7150_CH2_SETUP, data); | ||
574 | chip->ch2_setup = data; | ||
575 | return len; | ||
576 | } | ||
577 | |||
578 | return -EINVAL; | ||
579 | } | ||
580 | |||
581 | static IIO_DEV_ATTR_CH2_SETUP(S_IRUGO | S_IWUSR, | ||
582 | ad7150_show_ch2_setup, | ||
583 | ad7150_store_ch2_setup); | ||
584 | |||
585 | static ssize_t ad7150_show_powerdown_timer(struct device *dev, | ||
586 | struct device_attribute *attr, | ||
587 | char *buf) | ||
588 | { | ||
589 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
590 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
591 | |||
592 | return sprintf(buf, "0x%02x\n", chip->powerdown_timer); | ||
593 | } | ||
594 | |||
595 | static ssize_t ad7150_store_powerdown_timer(struct device *dev, | ||
596 | struct device_attribute *attr, | ||
597 | const char *buf, | ||
598 | size_t len) | ||
599 | { | ||
600 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
601 | struct ad7150_chip_info *chip = iio_priv(dev_info); | ||
602 | unsigned long data; | ||
603 | int ret; | ||
604 | |||
605 | ret = strict_strtoul(buf, 10, &data); | ||
606 | |||
607 | if ((!ret) && (data < 0x40)) { | ||
608 | chip->powerdown_timer = data; | ||
609 | return len; | ||
610 | } | ||
611 | |||
612 | return -EINVAL; | ||
613 | } | ||
614 | |||
615 | static IIO_DEV_ATTR_POWERDOWN_TIMER(S_IRUGO | S_IWUSR, | ||
616 | ad7150_show_powerdown_timer, | ||
617 | ad7150_store_powerdown_timer); | ||
618 | |||
619 | static struct attribute *ad7150_attributes[] = { | ||
620 | &iio_dev_attr_available_threshold_modes.dev_attr.attr, | ||
621 | &iio_dev_attr_threshold_mode.dev_attr.attr, | ||
622 | &iio_dev_attr_ch1_threshold.dev_attr.attr, | ||
623 | &iio_dev_attr_ch2_threshold.dev_attr.attr, | ||
624 | &iio_dev_attr_ch1_timeout.dev_attr.attr, | ||
625 | &iio_dev_attr_ch2_timeout.dev_attr.attr, | ||
626 | &iio_dev_attr_ch1_setup.dev_attr.attr, | ||
627 | &iio_dev_attr_ch2_setup.dev_attr.attr, | ||
628 | &iio_dev_attr_ch1_sensitivity.dev_attr.attr, | ||
629 | &iio_dev_attr_ch2_sensitivity.dev_attr.attr, | ||
630 | &iio_dev_attr_powerdown_timer.dev_attr.attr, | ||
631 | &iio_dev_attr_ch1_value.dev_attr.attr, | ||
632 | &iio_dev_attr_ch2_value.dev_attr.attr, | ||
633 | NULL, | ||
634 | }; | ||
635 | |||
636 | static const struct attribute_group ad7150_attribute_group = { | ||
637 | .attrs = ad7150_attributes, | ||
638 | }; | ||
639 | |||
640 | /* | ||
641 | * threshold events | ||
642 | */ | ||
643 | |||
644 | static irqreturn_t ad7150_event_handler(int irq, void *private) | ||
645 | { | ||
646 | struct iio_dev *indio_dev = private; | ||
647 | struct ad7150_chip_info *chip = iio_priv(indio_dev); | ||
648 | u8 int_status; | ||
649 | s64 timestamp = iio_get_time_ns(); | ||
650 | |||
651 | ad7150_i2c_read(chip, AD7150_STATUS, &int_status, 1); | ||
652 | |||
653 | if ((int_status & AD7150_STATUS_OUT1) && !(chip->old_state & AD7150_STATUS_OUT1)) | ||
654 | iio_push_event(indio_dev, 0, | ||
655 | IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, | ||
656 | 0, | ||
657 | IIO_EV_TYPE_THRESH, | ||
658 | IIO_EV_DIR_RISING), | ||
659 | timestamp); | ||
660 | else if ((!(int_status & AD7150_STATUS_OUT1)) && (chip->old_state & AD7150_STATUS_OUT1)) | ||
661 | iio_push_event(indio_dev, 0, | ||
662 | IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, | ||
663 | 0, | ||
664 | IIO_EV_TYPE_THRESH, | ||
665 | IIO_EV_DIR_FALLING), | ||
666 | timestamp); | ||
667 | |||
668 | if ((int_status & AD7150_STATUS_OUT2) && !(chip->old_state & AD7150_STATUS_OUT2)) | ||
669 | iio_push_event(indio_dev, 0, | ||
670 | IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, | ||
671 | 1, | ||
672 | IIO_EV_TYPE_THRESH, | ||
673 | IIO_EV_DIR_RISING), | ||
674 | timestamp); | ||
675 | else if ((!(int_status & AD7150_STATUS_OUT2)) && (chip->old_state & AD7150_STATUS_OUT2)) | ||
676 | iio_push_event(indio_dev, 0, | ||
677 | IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, | ||
678 | 1, | ||
679 | IIO_EV_TYPE_THRESH, | ||
680 | IIO_EV_DIR_FALLING), | ||
681 | timestamp); | ||
682 | return IRQ_HANDLED; | ||
683 | } | ||
684 | |||
685 | static IIO_CONST_ATTR(ch1_high_en, "1"); | ||
686 | static IIO_CONST_ATTR(ch2_high_en, "1"); | ||
687 | static IIO_CONST_ATTR(ch1_low_en, "1"); | ||
688 | static IIO_CONST_ATTR(ch2_low_en, "1"); | ||
689 | |||
690 | static struct attribute *ad7150_event_attributes[] = { | ||
691 | &iio_const_attr_ch1_high_en.dev_attr.attr, | ||
692 | &iio_const_attr_ch2_high_en.dev_attr.attr, | ||
693 | &iio_const_attr_ch1_low_en.dev_attr.attr, | ||
694 | &iio_const_attr_ch2_low_en.dev_attr.attr, | ||
695 | NULL, | ||
696 | }; | ||
697 | |||
698 | static struct attribute_group ad7150_event_attribute_group = { | ||
699 | .attrs = ad7150_event_attributes, | ||
700 | }; | ||
701 | |||
702 | static const struct iio_info ad7150_info = { | ||
703 | .attrs = &ad7150_attribute_group, | ||
704 | .num_interrupt_lines = 1, | ||
705 | .event_attrs = &ad7150_event_attribute_group, | ||
706 | .driver_module = THIS_MODULE, | ||
707 | }; | ||
708 | /* | ||
709 | * device probe and remove | ||
710 | */ | ||
711 | |||
712 | static int __devinit ad7150_probe(struct i2c_client *client, | ||
713 | const struct i2c_device_id *id) | ||
714 | { | ||
715 | int ret = 0, regdone = 0; | ||
716 | struct ad7150_chip_info *chip; | ||
717 | struct iio_dev *indio_dev; | ||
718 | |||
719 | indio_dev = iio_allocate_device(sizeof(*chip)); | ||
720 | if (indio_dev == NULL) { | ||
721 | ret = -ENOMEM; | ||
722 | goto error_ret; | ||
723 | } | ||
724 | chip = iio_priv(indio_dev); | ||
725 | /* this is only used for device removal purposes */ | ||
726 | i2c_set_clientdata(client, indio_dev); | ||
727 | |||
728 | chip->client = client; | ||
729 | |||
730 | /* Establish that the iio_dev is a child of the i2c device */ | ||
731 | indio_dev->name = id->name; | ||
732 | indio_dev->dev.parent = &client->dev; | ||
733 | |||
734 | indio_dev->info = &ad7150_info; | ||
735 | |||
736 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
737 | |||
738 | ret = iio_device_register(indio_dev); | ||
739 | if (ret) | ||
740 | goto error_free_dev; | ||
741 | regdone = 1; | ||
742 | |||
743 | if (client->irq) { | ||
744 | ret = request_threaded_irq(client->irq, | ||
745 | NULL, | ||
746 | &ad7150_event_handler, | ||
747 | IRQF_TRIGGER_RISING | | ||
748 | IRQF_TRIGGER_FALLING, | ||
749 | "ad7150", | ||
750 | indio_dev); | ||
751 | if (ret) | ||
752 | goto error_free_dev; | ||
753 | } | ||
754 | |||
755 | dev_err(&client->dev, "%s capacitive sensor registered, irq: %d\n", id->name, client->irq); | ||
756 | |||
757 | return 0; | ||
758 | |||
759 | error_free_dev: | ||
760 | if (regdone) | ||
761 | iio_device_unregister(indio_dev); | ||
762 | else | ||
763 | iio_free_device(indio_dev); | ||
764 | error_ret: | ||
765 | return ret; | ||
766 | } | ||
767 | |||
768 | static int __devexit ad7150_remove(struct i2c_client *client) | ||
769 | { | ||
770 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | ||
771 | |||
772 | if (client->irq) | ||
773 | free_irq(client->irq, indio_dev); | ||
774 | iio_device_unregister(indio_dev); | ||
775 | |||
776 | return 0; | ||
777 | } | ||
778 | |||
779 | static const struct i2c_device_id ad7150_id[] = { | ||
780 | { "ad7150", 0 }, | ||
781 | { "ad7151", 0 }, | ||
782 | { "ad7156", 0 }, | ||
783 | {} | ||
784 | }; | ||
785 | |||
786 | MODULE_DEVICE_TABLE(i2c, ad7150_id); | ||
787 | |||
788 | static struct i2c_driver ad7150_driver = { | ||
789 | .driver = { | ||
790 | .name = "ad7150", | ||
791 | }, | ||
792 | .probe = ad7150_probe, | ||
793 | .remove = __devexit_p(ad7150_remove), | ||
794 | .id_table = ad7150_id, | ||
795 | }; | ||
796 | |||
797 | static __init int ad7150_init(void) | ||
798 | { | ||
799 | return i2c_add_driver(&ad7150_driver); | ||
800 | } | ||
801 | |||
802 | static __exit void ad7150_exit(void) | ||
803 | { | ||
804 | i2c_del_driver(&ad7150_driver); | ||
805 | } | ||
806 | |||
807 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | ||
808 | MODULE_DESCRIPTION("Analog Devices ad7150/1/6 capacitive sensor driver"); | ||
809 | MODULE_LICENSE("GPL v2"); | ||
810 | |||
811 | module_init(ad7150_init); | ||
812 | module_exit(ad7150_exit); | ||
diff --git a/drivers/staging/iio/adc/ad7152.c b/drivers/staging/iio/adc/ad7152.c new file mode 100644 index 00000000000..21f5f380fb5 --- /dev/null +++ b/drivers/staging/iio/adc/ad7152.c | |||
@@ -0,0 +1,586 @@ | |||
1 | /* | ||
2 | * AD7152 capacitive sensor driver supporting AD7152/3 | ||
3 | * | ||
4 | * Copyright 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
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/i2c.h> | ||
15 | |||
16 | #include "../iio.h" | ||
17 | #include "../sysfs.h" | ||
18 | |||
19 | /* | ||
20 | * AD7152 registers definition | ||
21 | */ | ||
22 | |||
23 | #define AD7152_STATUS 0 | ||
24 | #define AD7152_STATUS_RDY1 (1 << 0) | ||
25 | #define AD7152_STATUS_RDY2 (1 << 1) | ||
26 | #define AD7152_CH1_DATA_HIGH 1 | ||
27 | #define AD7152_CH1_DATA_LOW 2 | ||
28 | #define AD7152_CH2_DATA_HIGH 3 | ||
29 | #define AD7152_CH2_DATA_LOW 4 | ||
30 | #define AD7152_CH1_OFFS_HIGH 5 | ||
31 | #define AD7152_CH1_OFFS_LOW 6 | ||
32 | #define AD7152_CH2_OFFS_HIGH 7 | ||
33 | #define AD7152_CH2_OFFS_LOW 8 | ||
34 | #define AD7152_CH1_GAIN_HIGH 9 | ||
35 | #define AD7152_CH1_GAIN_LOW 10 | ||
36 | #define AD7152_CH1_SETUP 11 | ||
37 | #define AD7152_CH2_GAIN_HIGH 12 | ||
38 | #define AD7152_CH2_GAIN_LOW 13 | ||
39 | #define AD7152_CH2_SETUP 14 | ||
40 | #define AD7152_CFG 15 | ||
41 | #define AD7152_RESEVERD 16 | ||
42 | #define AD7152_CAPDAC_POS 17 | ||
43 | #define AD7152_CAPDAC_NEG 18 | ||
44 | #define AD7152_CFG2 26 | ||
45 | |||
46 | #define AD7152_MAX_CONV_MODE 6 | ||
47 | |||
48 | /* | ||
49 | * struct ad7152_chip_info - chip specifc information | ||
50 | */ | ||
51 | |||
52 | struct ad7152_chip_info { | ||
53 | struct i2c_client *client; | ||
54 | u16 ch1_offset; /* Channel 1 offset calibration coefficient */ | ||
55 | u16 ch1_gain; /* Channel 1 gain coefficient */ | ||
56 | u8 ch1_setup; | ||
57 | u16 ch2_offset; /* Channel 2 offset calibration coefficient */ | ||
58 | u16 ch2_gain; /* Channel 1 gain coefficient */ | ||
59 | u8 ch2_setup; | ||
60 | u8 filter_rate_setup; /* Capacitive channel digital filter setup; conversion time/update rate setup per channel */ | ||
61 | char *conversion_mode; | ||
62 | }; | ||
63 | |||
64 | struct ad7152_conversion_mode { | ||
65 | char *name; | ||
66 | u8 reg_cfg; | ||
67 | }; | ||
68 | |||
69 | static struct ad7152_conversion_mode | ||
70 | ad7152_conv_mode_table[AD7152_MAX_CONV_MODE] = { | ||
71 | { "idle", 0 }, | ||
72 | { "continuous-conversion", 1 }, | ||
73 | { "single-conversion", 2 }, | ||
74 | { "power-down", 3 }, | ||
75 | { "offset-calibration", 5 }, | ||
76 | { "gain-calibration", 6 }, | ||
77 | }; | ||
78 | |||
79 | /* | ||
80 | * ad7152 register access by I2C | ||
81 | */ | ||
82 | |||
83 | static int ad7152_i2c_read(struct ad7152_chip_info *chip, u8 reg, u8 *data, int len) | ||
84 | { | ||
85 | struct i2c_client *client = chip->client; | ||
86 | int ret; | ||
87 | |||
88 | ret = i2c_master_send(client, ®, 1); | ||
89 | if (ret < 0) { | ||
90 | dev_err(&client->dev, "I2C write error\n"); | ||
91 | return ret; | ||
92 | } | ||
93 | |||
94 | ret = i2c_master_recv(client, data, len); | ||
95 | if (ret < 0) { | ||
96 | dev_err(&client->dev, "I2C read error\n"); | ||
97 | } | ||
98 | |||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | static int ad7152_i2c_write(struct ad7152_chip_info *chip, u8 reg, u8 data) | ||
103 | { | ||
104 | struct i2c_client *client = chip->client; | ||
105 | int ret; | ||
106 | |||
107 | u8 tx[2] = { | ||
108 | reg, | ||
109 | data, | ||
110 | }; | ||
111 | |||
112 | ret = i2c_master_send(client, tx, 2); | ||
113 | if (ret < 0) | ||
114 | dev_err(&client->dev, "I2C write error\n"); | ||
115 | |||
116 | return ret; | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * sysfs nodes | ||
121 | */ | ||
122 | |||
123 | #define IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(_show) \ | ||
124 | IIO_DEVICE_ATTR(available_conversion_modes, S_IRUGO, _show, NULL, 0) | ||
125 | #define IIO_DEV_ATTR_CONVERSION_MODE(_mode, _show, _store) \ | ||
126 | IIO_DEVICE_ATTR(conversion_mode, _mode, _show, _store, 0) | ||
127 | #define IIO_DEV_ATTR_CH1_OFFSET(_mode, _show, _store) \ | ||
128 | IIO_DEVICE_ATTR(ch1_offset, _mode, _show, _store, 0) | ||
129 | #define IIO_DEV_ATTR_CH2_OFFSET(_mode, _show, _store) \ | ||
130 | IIO_DEVICE_ATTR(ch2_offset, _mode, _show, _store, 0) | ||
131 | #define IIO_DEV_ATTR_CH1_GAIN(_mode, _show, _store) \ | ||
132 | IIO_DEVICE_ATTR(ch1_gain, _mode, _show, _store, 0) | ||
133 | #define IIO_DEV_ATTR_CH2_GAIN(_mode, _show, _store) \ | ||
134 | IIO_DEVICE_ATTR(ch2_gain, _mode, _show, _store, 0) | ||
135 | #define IIO_DEV_ATTR_CH1_VALUE(_show) \ | ||
136 | IIO_DEVICE_ATTR(ch1_value, S_IRUGO, _show, NULL, 0) | ||
137 | #define IIO_DEV_ATTR_CH2_VALUE(_show) \ | ||
138 | IIO_DEVICE_ATTR(ch2_value, S_IRUGO, _show, NULL, 0) | ||
139 | #define IIO_DEV_ATTR_CH1_SETUP(_mode, _show, _store) \ | ||
140 | IIO_DEVICE_ATTR(ch1_setup, _mode, _show, _store, 0) | ||
141 | #define IIO_DEV_ATTR_CH2_SETUP(_mode, _show, _store) \ | ||
142 | IIO_DEVICE_ATTR(ch2_setup, _mode, _show, _store, 0) | ||
143 | #define IIO_DEV_ATTR_FILTER_RATE_SETUP(_mode, _show, _store) \ | ||
144 | IIO_DEVICE_ATTR(filter_rate_setup, _mode, _show, _store, 0) | ||
145 | |||
146 | static ssize_t ad7152_show_conversion_modes(struct device *dev, | ||
147 | struct device_attribute *attr, | ||
148 | char *buf) | ||
149 | { | ||
150 | int i; | ||
151 | int len = 0; | ||
152 | |||
153 | for (i = 0; i < AD7152_MAX_CONV_MODE; i++) | ||
154 | len += sprintf(buf + len, "%s ", ad7152_conv_mode_table[i].name); | ||
155 | |||
156 | len += sprintf(buf + len, "\n"); | ||
157 | |||
158 | return len; | ||
159 | } | ||
160 | |||
161 | static IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(ad7152_show_conversion_modes); | ||
162 | |||
163 | static ssize_t ad7152_show_ch1_value(struct device *dev, | ||
164 | struct device_attribute *attr, | ||
165 | char *buf) | ||
166 | { | ||
167 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
168 | struct ad7152_chip_info *chip = iio_priv(dev_info); | ||
169 | u8 data[2]; | ||
170 | |||
171 | ad7152_i2c_read(chip, AD7152_CH1_DATA_HIGH, data, 2); | ||
172 | return sprintf(buf, "%d\n", ((int)data[0] << 8) | data[1]); | ||
173 | } | ||
174 | |||
175 | static IIO_DEV_ATTR_CH1_VALUE(ad7152_show_ch1_value); | ||
176 | |||
177 | static ssize_t ad7152_show_ch2_value(struct device *dev, | ||
178 | struct device_attribute *attr, | ||
179 | char *buf) | ||
180 | { | ||
181 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
182 | struct ad7152_chip_info *chip = iio_priv(dev_info); | ||
183 | u8 data[2]; | ||
184 | |||
185 | ad7152_i2c_read(chip, AD7152_CH2_DATA_HIGH, data, 2); | ||
186 | return sprintf(buf, "%d\n", ((int)data[0] << 8) | data[1]); | ||
187 | } | ||
188 | |||
189 | static IIO_DEV_ATTR_CH2_VALUE(ad7152_show_ch2_value); | ||
190 | |||
191 | static ssize_t ad7152_show_conversion_mode(struct device *dev, | ||
192 | struct device_attribute *attr, | ||
193 | char *buf) | ||
194 | { | ||
195 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
196 | struct ad7152_chip_info *chip = iio_priv(dev_info); | ||
197 | |||
198 | return sprintf(buf, "%s\n", chip->conversion_mode); | ||
199 | } | ||
200 | |||
201 | static ssize_t ad7152_store_conversion_mode(struct device *dev, | ||
202 | struct device_attribute *attr, | ||
203 | const char *buf, | ||
204 | size_t len) | ||
205 | { | ||
206 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
207 | struct ad7152_chip_info *chip = iio_priv(dev_info); | ||
208 | u8 cfg; | ||
209 | int i; | ||
210 | |||
211 | ad7152_i2c_read(chip, AD7152_CFG, &cfg, 1); | ||
212 | |||
213 | for (i = 0; i < AD7152_MAX_CONV_MODE; i++) | ||
214 | if (strncmp(buf, ad7152_conv_mode_table[i].name, | ||
215 | strlen(ad7152_conv_mode_table[i].name) - 1) == 0) { | ||
216 | chip->conversion_mode = ad7152_conv_mode_table[i].name; | ||
217 | cfg |= 0x18 | ad7152_conv_mode_table[i].reg_cfg; | ||
218 | ad7152_i2c_write(chip, AD7152_CFG, cfg); | ||
219 | return len; | ||
220 | } | ||
221 | |||
222 | dev_err(dev, "not supported conversion mode\n"); | ||
223 | |||
224 | return -EINVAL; | ||
225 | } | ||
226 | |||
227 | static IIO_DEV_ATTR_CONVERSION_MODE(S_IRUGO | S_IWUSR, | ||
228 | ad7152_show_conversion_mode, | ||
229 | ad7152_store_conversion_mode); | ||
230 | |||
231 | static ssize_t ad7152_show_ch1_offset(struct device *dev, | ||
232 | struct device_attribute *attr, | ||
233 | char *buf) | ||
234 | { | ||
235 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
236 | struct ad7152_chip_info *chip = iio_priv(dev_info); | ||
237 | |||
238 | return sprintf(buf, "%d\n", chip->ch1_offset); | ||
239 | } | ||
240 | |||
241 | static ssize_t ad7152_store_ch1_offset(struct device *dev, | ||
242 | struct device_attribute *attr, | ||
243 | const char *buf, | ||
244 | size_t len) | ||
245 | { | ||
246 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
247 | struct ad7152_chip_info *chip = iio_priv(dev_info); | ||
248 | unsigned long data; | ||
249 | int ret; | ||
250 | |||
251 | ret = strict_strtoul(buf, 10, &data); | ||
252 | |||
253 | if ((!ret) && (data < 0x10000)) { | ||
254 | ad7152_i2c_write(chip, AD7152_CH1_OFFS_HIGH, data >> 8); | ||
255 | ad7152_i2c_write(chip, AD7152_CH1_OFFS_LOW, data); | ||
256 | chip->ch1_offset = data; | ||
257 | return len; | ||
258 | } | ||
259 | |||
260 | return -EINVAL; | ||
261 | } | ||
262 | |||
263 | static IIO_DEV_ATTR_CH1_OFFSET(S_IRUGO | S_IWUSR, | ||
264 | ad7152_show_ch1_offset, | ||
265 | ad7152_store_ch1_offset); | ||
266 | |||
267 | static ssize_t ad7152_show_ch2_offset(struct device *dev, | ||
268 | struct device_attribute *attr, | ||
269 | char *buf) | ||
270 | { | ||
271 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
272 | struct ad7152_chip_info *chip = iio_priv(dev_info); | ||
273 | |||
274 | return sprintf(buf, "%d\n", chip->ch2_offset); | ||
275 | } | ||
276 | |||
277 | static ssize_t ad7152_store_ch2_offset(struct device *dev, | ||
278 | struct device_attribute *attr, | ||
279 | const char *buf, | ||
280 | size_t len) | ||
281 | { | ||
282 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
283 | struct ad7152_chip_info *chip = iio_priv(dev_info); | ||
284 | unsigned long data; | ||
285 | int ret; | ||
286 | |||
287 | ret = strict_strtoul(buf, 10, &data); | ||
288 | |||
289 | if ((!ret) && (data < 0x10000)) { | ||
290 | ad7152_i2c_write(chip, AD7152_CH2_OFFS_HIGH, data >> 8); | ||
291 | ad7152_i2c_write(chip, AD7152_CH2_OFFS_LOW, data); | ||
292 | chip->ch2_offset = data; | ||
293 | return len; | ||
294 | } | ||
295 | |||
296 | return -EINVAL; | ||
297 | } | ||
298 | |||
299 | static IIO_DEV_ATTR_CH2_OFFSET(S_IRUGO | S_IWUSR, | ||
300 | ad7152_show_ch2_offset, | ||
301 | ad7152_store_ch2_offset); | ||
302 | |||
303 | static ssize_t ad7152_show_ch1_gain(struct device *dev, | ||
304 | struct device_attribute *attr, | ||
305 | char *buf) | ||
306 | { | ||
307 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
308 | struct ad7152_chip_info *chip = iio_priv(dev_info); | ||
309 | |||
310 | return sprintf(buf, "%d\n", chip->ch1_gain); | ||
311 | } | ||
312 | |||
313 | static ssize_t ad7152_store_ch1_gain(struct device *dev, | ||
314 | struct device_attribute *attr, | ||
315 | const char *buf, | ||
316 | size_t len) | ||
317 | { | ||
318 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
319 | struct ad7152_chip_info *chip = iio_priv(dev_info); | ||
320 | unsigned long data; | ||
321 | int ret; | ||
322 | |||
323 | ret = strict_strtoul(buf, 10, &data); | ||
324 | |||
325 | if ((!ret) && (data < 0x10000)) { | ||
326 | ad7152_i2c_write(chip, AD7152_CH1_GAIN_HIGH, data >> 8); | ||
327 | ad7152_i2c_write(chip, AD7152_CH1_GAIN_LOW, data); | ||
328 | chip->ch1_gain = data; | ||
329 | return len; | ||
330 | } | ||
331 | |||
332 | return -EINVAL; | ||
333 | } | ||
334 | |||
335 | static IIO_DEV_ATTR_CH1_GAIN(S_IRUGO | S_IWUSR, | ||
336 | ad7152_show_ch1_gain, | ||
337 | ad7152_store_ch1_gain); | ||
338 | |||
339 | static ssize_t ad7152_show_ch2_gain(struct device *dev, | ||
340 | struct device_attribute *attr, | ||
341 | char *buf) | ||
342 | { | ||
343 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
344 | struct ad7152_chip_info *chip = iio_priv(dev_info); | ||
345 | |||
346 | return sprintf(buf, "%d\n", chip->ch2_gain); | ||
347 | } | ||
348 | |||
349 | static ssize_t ad7152_store_ch2_gain(struct device *dev, | ||
350 | struct device_attribute *attr, | ||
351 | const char *buf, | ||
352 | size_t len) | ||
353 | { | ||
354 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
355 | struct ad7152_chip_info *chip = iio_priv(dev_info); | ||
356 | unsigned long data; | ||
357 | int ret; | ||
358 | |||
359 | ret = strict_strtoul(buf, 10, &data); | ||
360 | |||
361 | if ((!ret) && (data < 0x10000)) { | ||
362 | ad7152_i2c_write(chip, AD7152_CH2_GAIN_HIGH, data >> 8); | ||
363 | ad7152_i2c_write(chip, AD7152_CH2_GAIN_LOW, data); | ||
364 | chip->ch2_gain = data; | ||
365 | return len; | ||
366 | } | ||
367 | |||
368 | return -EINVAL; | ||
369 | } | ||
370 | |||
371 | static IIO_DEV_ATTR_CH2_GAIN(S_IRUGO | S_IWUSR, | ||
372 | ad7152_show_ch2_gain, | ||
373 | ad7152_store_ch2_gain); | ||
374 | |||
375 | static ssize_t ad7152_show_ch1_setup(struct device *dev, | ||
376 | struct device_attribute *attr, | ||
377 | char *buf) | ||
378 | { | ||
379 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
380 | struct ad7152_chip_info *chip = iio_priv(dev_info); | ||
381 | |||
382 | return sprintf(buf, "0x%02x\n", chip->ch1_setup); | ||
383 | } | ||
384 | |||
385 | static ssize_t ad7152_store_ch1_setup(struct device *dev, | ||
386 | struct device_attribute *attr, | ||
387 | const char *buf, | ||
388 | size_t len) | ||
389 | { | ||
390 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
391 | struct ad7152_chip_info *chip = iio_priv(dev_info); | ||
392 | unsigned long data; | ||
393 | int ret; | ||
394 | |||
395 | ret = strict_strtoul(buf, 10, &data); | ||
396 | |||
397 | if ((!ret) && (data < 0x100)) { | ||
398 | ad7152_i2c_write(chip, AD7152_CH1_SETUP, data); | ||
399 | chip->ch1_setup = data; | ||
400 | return len; | ||
401 | } | ||
402 | |||
403 | return -EINVAL; | ||
404 | } | ||
405 | |||
406 | static IIO_DEV_ATTR_CH1_SETUP(S_IRUGO | S_IWUSR, | ||
407 | ad7152_show_ch1_setup, | ||
408 | ad7152_store_ch1_setup); | ||
409 | |||
410 | static ssize_t ad7152_show_ch2_setup(struct device *dev, | ||
411 | struct device_attribute *attr, | ||
412 | char *buf) | ||
413 | { | ||
414 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
415 | struct ad7152_chip_info *chip = iio_priv(dev_info); | ||
416 | |||
417 | return sprintf(buf, "0x%02x\n", chip->ch2_setup); | ||
418 | } | ||
419 | |||
420 | static ssize_t ad7152_store_ch2_setup(struct device *dev, | ||
421 | struct device_attribute *attr, | ||
422 | const char *buf, | ||
423 | size_t len) | ||
424 | { | ||
425 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
426 | struct ad7152_chip_info *chip = iio_priv(dev_info); | ||
427 | unsigned long data; | ||
428 | int ret; | ||
429 | |||
430 | ret = strict_strtoul(buf, 10, &data); | ||
431 | |||
432 | if ((!ret) && (data < 0x100)) { | ||
433 | ad7152_i2c_write(chip, AD7152_CH2_SETUP, data); | ||
434 | chip->ch2_setup = data; | ||
435 | return len; | ||
436 | } | ||
437 | |||
438 | return -EINVAL; | ||
439 | } | ||
440 | |||
441 | static IIO_DEV_ATTR_CH2_SETUP(S_IRUGO | S_IWUSR, | ||
442 | ad7152_show_ch2_setup, | ||
443 | ad7152_store_ch2_setup); | ||
444 | |||
445 | static ssize_t ad7152_show_filter_rate_setup(struct device *dev, | ||
446 | struct device_attribute *attr, | ||
447 | char *buf) | ||
448 | { | ||
449 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
450 | struct ad7152_chip_info *chip = iio_priv(dev_info); | ||
451 | |||
452 | return sprintf(buf, "0x%02x\n", chip->filter_rate_setup); | ||
453 | } | ||
454 | |||
455 | static ssize_t ad7152_store_filter_rate_setup(struct device *dev, | ||
456 | struct device_attribute *attr, | ||
457 | const char *buf, | ||
458 | size_t len) | ||
459 | { | ||
460 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
461 | struct ad7152_chip_info *chip = iio_priv(dev_info); | ||
462 | unsigned long data; | ||
463 | int ret; | ||
464 | |||
465 | ret = strict_strtoul(buf, 10, &data); | ||
466 | |||
467 | if ((!ret) && (data < 0x100)) { | ||
468 | ad7152_i2c_write(chip, AD7152_CFG2, data); | ||
469 | chip->filter_rate_setup = data; | ||
470 | return len; | ||
471 | } | ||
472 | |||
473 | return -EINVAL; | ||
474 | } | ||
475 | |||
476 | static IIO_DEV_ATTR_FILTER_RATE_SETUP(S_IRUGO | S_IWUSR, | ||
477 | ad7152_show_filter_rate_setup, | ||
478 | ad7152_store_filter_rate_setup); | ||
479 | |||
480 | static struct attribute *ad7152_attributes[] = { | ||
481 | &iio_dev_attr_available_conversion_modes.dev_attr.attr, | ||
482 | &iio_dev_attr_conversion_mode.dev_attr.attr, | ||
483 | &iio_dev_attr_ch1_gain.dev_attr.attr, | ||
484 | &iio_dev_attr_ch2_gain.dev_attr.attr, | ||
485 | &iio_dev_attr_ch1_offset.dev_attr.attr, | ||
486 | &iio_dev_attr_ch2_offset.dev_attr.attr, | ||
487 | &iio_dev_attr_ch1_value.dev_attr.attr, | ||
488 | &iio_dev_attr_ch2_value.dev_attr.attr, | ||
489 | &iio_dev_attr_ch1_setup.dev_attr.attr, | ||
490 | &iio_dev_attr_ch2_setup.dev_attr.attr, | ||
491 | &iio_dev_attr_filter_rate_setup.dev_attr.attr, | ||
492 | NULL, | ||
493 | }; | ||
494 | |||
495 | static const struct attribute_group ad7152_attribute_group = { | ||
496 | .attrs = ad7152_attributes, | ||
497 | }; | ||
498 | |||
499 | static const struct iio_info ad7152_info = { | ||
500 | .attrs = &ad7152_attribute_group, | ||
501 | .driver_module = THIS_MODULE, | ||
502 | }; | ||
503 | /* | ||
504 | * device probe and remove | ||
505 | */ | ||
506 | |||
507 | static int __devinit ad7152_probe(struct i2c_client *client, | ||
508 | const struct i2c_device_id *id) | ||
509 | { | ||
510 | int ret = 0; | ||
511 | struct ad7152_chip_info *chip; | ||
512 | struct iio_dev *indio_dev; | ||
513 | |||
514 | indio_dev = iio_allocate_device(sizeof(*chip)); | ||
515 | if (indio_dev == NULL) { | ||
516 | ret = -ENOMEM; | ||
517 | goto error_ret; | ||
518 | } | ||
519 | chip = iio_priv(indio_dev); | ||
520 | /* this is only used for device removal purposes */ | ||
521 | i2c_set_clientdata(client, indio_dev); | ||
522 | |||
523 | chip->client = client; | ||
524 | |||
525 | /* Echipabilish that the iio_dev is a child of the i2c device */ | ||
526 | indio_dev->name = id->name; | ||
527 | indio_dev->dev.parent = &client->dev; | ||
528 | indio_dev->info = &ad7152_info; | ||
529 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
530 | |||
531 | ret = iio_device_register(indio_dev); | ||
532 | if (ret) | ||
533 | goto error_free_dev; | ||
534 | |||
535 | dev_err(&client->dev, "%s capacitive sensor registered\n", id->name); | ||
536 | |||
537 | return 0; | ||
538 | |||
539 | error_free_dev: | ||
540 | iio_free_device(indio_dev); | ||
541 | error_ret: | ||
542 | return ret; | ||
543 | } | ||
544 | |||
545 | static int __devexit ad7152_remove(struct i2c_client *client) | ||
546 | { | ||
547 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | ||
548 | |||
549 | iio_device_unregister(indio_dev); | ||
550 | |||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | static const struct i2c_device_id ad7152_id[] = { | ||
555 | { "ad7152", 0 }, | ||
556 | { "ad7153", 0 }, | ||
557 | {} | ||
558 | }; | ||
559 | |||
560 | MODULE_DEVICE_TABLE(i2c, ad7152_id); | ||
561 | |||
562 | static struct i2c_driver ad7152_driver = { | ||
563 | .driver = { | ||
564 | .name = "ad7152", | ||
565 | }, | ||
566 | .probe = ad7152_probe, | ||
567 | .remove = __devexit_p(ad7152_remove), | ||
568 | .id_table = ad7152_id, | ||
569 | }; | ||
570 | |||
571 | static __init int ad7152_init(void) | ||
572 | { | ||
573 | return i2c_add_driver(&ad7152_driver); | ||
574 | } | ||
575 | |||
576 | static __exit void ad7152_exit(void) | ||
577 | { | ||
578 | i2c_del_driver(&ad7152_driver); | ||
579 | } | ||
580 | |||
581 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | ||
582 | MODULE_DESCRIPTION("Analog Devices ad7152/3 capacitive sensor driver"); | ||
583 | MODULE_LICENSE("GPL v2"); | ||
584 | |||
585 | module_init(ad7152_init); | ||
586 | module_exit(ad7152_exit); | ||
diff --git a/drivers/staging/iio/adc/ad7298.h b/drivers/staging/iio/adc/ad7298.h new file mode 100644 index 00000000000..628f5adcf0c --- /dev/null +++ b/drivers/staging/iio/adc/ad7298.h | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * AD7298 SPI ADC driver | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #ifndef IIO_ADC_AD7298_H_ | ||
10 | #define IIO_ADC_AD7298_H_ | ||
11 | |||
12 | #define AD7298_WRITE (1 << 15) /* write to the control register */ | ||
13 | #define AD7298_REPEAT (1 << 14) /* repeated conversion enable */ | ||
14 | #define AD7298_CH(x) (1 << (13 - (x))) /* channel select */ | ||
15 | #define AD7298_TSENSE (1 << 5) /* temperature conversion enable */ | ||
16 | #define AD7298_EXTREF (1 << 2) /* external reference enable */ | ||
17 | #define AD7298_TAVG (1 << 1) /* temperature sensor averaging enable */ | ||
18 | #define AD7298_PDD (1 << 0) /* partial power down enable */ | ||
19 | |||
20 | #define AD7298_MAX_CHAN 8 | ||
21 | #define AD7298_BITS 12 | ||
22 | #define AD7298_STORAGE_BITS 16 | ||
23 | #define AD7298_INTREF_mV 2500 | ||
24 | |||
25 | #define AD7298_CH_TEMP 9 | ||
26 | |||
27 | #define RES_MASK(bits) ((1 << (bits)) - 1) | ||
28 | |||
29 | /* | ||
30 | * TODO: struct ad7298_platform_data needs to go into include/linux/iio | ||
31 | */ | ||
32 | |||
33 | struct ad7298_platform_data { | ||
34 | /* External Vref voltage applied */ | ||
35 | u16 vref_mv; | ||
36 | }; | ||
37 | |||
38 | struct ad7298_state { | ||
39 | struct spi_device *spi; | ||
40 | struct regulator *reg; | ||
41 | size_t d_size; | ||
42 | u16 int_vref_mv; | ||
43 | unsigned ext_ref; | ||
44 | struct spi_transfer ring_xfer[10]; | ||
45 | struct spi_transfer scan_single_xfer[3]; | ||
46 | struct spi_message ring_msg; | ||
47 | struct spi_message scan_single_msg; | ||
48 | /* | ||
49 | * DMA (thus cache coherency maintenance) requires the | ||
50 | * transfer buffers to live in their own cache lines. | ||
51 | */ | ||
52 | unsigned short rx_buf[8] ____cacheline_aligned; | ||
53 | unsigned short tx_buf[2]; | ||
54 | }; | ||
55 | |||
56 | #ifdef CONFIG_IIO_RING_BUFFER | ||
57 | int ad7298_scan_from_ring(struct iio_dev *indio_dev, long ch); | ||
58 | int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev); | ||
59 | void ad7298_ring_cleanup(struct iio_dev *indio_dev); | ||
60 | #else /* CONFIG_IIO_RING_BUFFER */ | ||
61 | static inline int ad7298_scan_from_ring(struct iio_dev *indio_dev, long ch) | ||
62 | { | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static inline int | ||
67 | ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev) | ||
68 | { | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static inline void ad7298_ring_cleanup(struct iio_dev *indio_dev) | ||
73 | { | ||
74 | } | ||
75 | #endif /* CONFIG_IIO_RING_BUFFER */ | ||
76 | #endif /* IIO_ADC_AD7298_H_ */ | ||
diff --git a/drivers/staging/iio/adc/ad7298_core.c b/drivers/staging/iio/adc/ad7298_core.c new file mode 100644 index 00000000000..b8e4ae29b0b --- /dev/null +++ b/drivers/staging/iio/adc/ad7298_core.c | |||
@@ -0,0 +1,299 @@ | |||
1 | /* | ||
2 | * AD7298 SPI ADC driver | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/device.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/sysfs.h> | ||
13 | #include <linux/spi/spi.h> | ||
14 | #include <linux/regulator/consumer.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/delay.h> | ||
17 | |||
18 | #include "../iio.h" | ||
19 | #include "../sysfs.h" | ||
20 | #include "../ring_generic.h" | ||
21 | #include "adc.h" | ||
22 | |||
23 | #include "ad7298.h" | ||
24 | |||
25 | static struct iio_chan_spec ad7298_channels[] = { | ||
26 | IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, | ||
27 | (1 << IIO_CHAN_INFO_SCALE_SEPARATE), | ||
28 | 9, AD7298_CH_TEMP, IIO_ST('s', 32, 32, 0), 0), | ||
29 | IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, | ||
30 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
31 | 0, 0, IIO_ST('u', 12, 16, 0), 0), | ||
32 | IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, | ||
33 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
34 | 1, 1, IIO_ST('u', 12, 16, 0), 0), | ||
35 | IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, | ||
36 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
37 | 2, 2, IIO_ST('u', 12, 16, 0), 0), | ||
38 | IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, | ||
39 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
40 | 3, 3, IIO_ST('u', 12, 16, 0), 0), | ||
41 | IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 4, 0, | ||
42 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
43 | 4, 4, IIO_ST('u', 12, 16, 0), 0), | ||
44 | IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 5, 0, | ||
45 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
46 | 5, 5, IIO_ST('u', 12, 16, 0), 0), | ||
47 | IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 6, 0, | ||
48 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
49 | 6, 6, IIO_ST('u', 12, 16, 0), 0), | ||
50 | IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 7, 0, | ||
51 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
52 | 7, 7, IIO_ST('u', 12, 16, 0), 0), | ||
53 | IIO_CHAN_SOFT_TIMESTAMP(8), | ||
54 | }; | ||
55 | |||
56 | static int ad7298_scan_direct(struct ad7298_state *st, unsigned ch) | ||
57 | { | ||
58 | int ret; | ||
59 | st->tx_buf[0] = cpu_to_be16(AD7298_WRITE | st->ext_ref | | ||
60 | (AD7298_CH(0) >> ch)); | ||
61 | |||
62 | ret = spi_sync(st->spi, &st->scan_single_msg); | ||
63 | if (ret) | ||
64 | return ret; | ||
65 | |||
66 | return be16_to_cpu(st->rx_buf[0]); | ||
67 | } | ||
68 | |||
69 | static int ad7298_scan_temp(struct ad7298_state *st, int *val) | ||
70 | { | ||
71 | int tmp, ret; | ||
72 | |||
73 | tmp = cpu_to_be16(AD7298_WRITE | AD7298_TSENSE | | ||
74 | AD7298_TAVG | st->ext_ref); | ||
75 | |||
76 | ret = spi_write(st->spi, (u8 *)&tmp, 2); | ||
77 | if (ret) | ||
78 | return ret; | ||
79 | |||
80 | tmp = 0; | ||
81 | |||
82 | ret = spi_write(st->spi, (u8 *)&tmp, 2); | ||
83 | if (ret) | ||
84 | return ret; | ||
85 | |||
86 | usleep_range(101, 1000); /* sleep > 100us */ | ||
87 | |||
88 | ret = spi_read(st->spi, (u8 *)&tmp, 2); | ||
89 | if (ret) | ||
90 | return ret; | ||
91 | |||
92 | tmp = be16_to_cpu(tmp) & RES_MASK(AD7298_BITS); | ||
93 | |||
94 | /* | ||
95 | * One LSB of the ADC corresponds to 0.25 deg C. | ||
96 | * The temperature reading is in 12-bit twos complement format | ||
97 | */ | ||
98 | |||
99 | if (tmp & (1 << (AD7298_BITS - 1))) { | ||
100 | tmp = (4096 - tmp) * 250; | ||
101 | tmp -= (2 * tmp); | ||
102 | |||
103 | } else { | ||
104 | tmp *= 250; /* temperature in milli degrees Celsius */ | ||
105 | } | ||
106 | |||
107 | *val = tmp; | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int ad7298_read_raw(struct iio_dev *dev_info, | ||
113 | struct iio_chan_spec const *chan, | ||
114 | int *val, | ||
115 | int *val2, | ||
116 | long m) | ||
117 | { | ||
118 | int ret; | ||
119 | struct ad7298_state *st = iio_priv(dev_info); | ||
120 | unsigned int scale_uv; | ||
121 | |||
122 | switch (m) { | ||
123 | case 0: | ||
124 | mutex_lock(&dev_info->mlock); | ||
125 | if (iio_ring_enabled(dev_info)) { | ||
126 | if (chan->address == AD7298_CH_TEMP) | ||
127 | ret = -ENODEV; | ||
128 | else | ||
129 | ret = ad7298_scan_from_ring(dev_info, | ||
130 | chan->address); | ||
131 | } else { | ||
132 | if (chan->address == AD7298_CH_TEMP) | ||
133 | ret = ad7298_scan_temp(st, val); | ||
134 | else | ||
135 | ret = ad7298_scan_direct(st, chan->address); | ||
136 | } | ||
137 | mutex_unlock(&dev_info->mlock); | ||
138 | |||
139 | if (ret < 0) | ||
140 | return ret; | ||
141 | |||
142 | if (chan->address != AD7298_CH_TEMP) | ||
143 | *val = ret & RES_MASK(AD7298_BITS); | ||
144 | |||
145 | return IIO_VAL_INT; | ||
146 | case (1 << IIO_CHAN_INFO_SCALE_SHARED): | ||
147 | scale_uv = (st->int_vref_mv * 1000) >> AD7298_BITS; | ||
148 | *val = scale_uv / 1000; | ||
149 | *val2 = (scale_uv % 1000) * 1000; | ||
150 | return IIO_VAL_INT_PLUS_MICRO; | ||
151 | case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): | ||
152 | *val = 1; | ||
153 | *val2 = 0; | ||
154 | return IIO_VAL_INT_PLUS_MICRO; | ||
155 | } | ||
156 | return -EINVAL; | ||
157 | } | ||
158 | |||
159 | static const struct iio_info ad7298_info = { | ||
160 | .read_raw = &ad7298_read_raw, | ||
161 | .driver_module = THIS_MODULE, | ||
162 | }; | ||
163 | |||
164 | static int __devinit ad7298_probe(struct spi_device *spi) | ||
165 | { | ||
166 | struct ad7298_platform_data *pdata = spi->dev.platform_data; | ||
167 | struct ad7298_state *st; | ||
168 | int ret, regdone = 0; | ||
169 | struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); | ||
170 | |||
171 | if (indio_dev == NULL) | ||
172 | return -ENOMEM; | ||
173 | |||
174 | st = iio_priv(indio_dev); | ||
175 | |||
176 | st->reg = regulator_get(&spi->dev, "vcc"); | ||
177 | if (!IS_ERR(st->reg)) { | ||
178 | ret = regulator_enable(st->reg); | ||
179 | if (ret) | ||
180 | goto error_put_reg; | ||
181 | } | ||
182 | |||
183 | spi_set_drvdata(spi, indio_dev); | ||
184 | |||
185 | st->spi = spi; | ||
186 | |||
187 | indio_dev->name = spi_get_device_id(spi)->name; | ||
188 | indio_dev->dev.parent = &spi->dev; | ||
189 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
190 | indio_dev->channels = ad7298_channels; | ||
191 | indio_dev->num_channels = ARRAY_SIZE(ad7298_channels); | ||
192 | indio_dev->info = &ad7298_info; | ||
193 | |||
194 | /* Setup default message */ | ||
195 | |||
196 | st->scan_single_xfer[0].tx_buf = &st->tx_buf[0]; | ||
197 | st->scan_single_xfer[0].len = 2; | ||
198 | st->scan_single_xfer[0].cs_change = 1; | ||
199 | st->scan_single_xfer[1].tx_buf = &st->tx_buf[1]; | ||
200 | st->scan_single_xfer[1].len = 2; | ||
201 | st->scan_single_xfer[1].cs_change = 1; | ||
202 | st->scan_single_xfer[2].rx_buf = &st->rx_buf[0]; | ||
203 | st->scan_single_xfer[2].len = 2; | ||
204 | |||
205 | spi_message_init(&st->scan_single_msg); | ||
206 | spi_message_add_tail(&st->scan_single_xfer[0], &st->scan_single_msg); | ||
207 | spi_message_add_tail(&st->scan_single_xfer[1], &st->scan_single_msg); | ||
208 | spi_message_add_tail(&st->scan_single_xfer[2], &st->scan_single_msg); | ||
209 | |||
210 | if (pdata && pdata->vref_mv) { | ||
211 | st->int_vref_mv = pdata->vref_mv; | ||
212 | st->ext_ref = AD7298_EXTREF; | ||
213 | } else { | ||
214 | st->int_vref_mv = AD7298_INTREF_mV; | ||
215 | } | ||
216 | |||
217 | ret = ad7298_register_ring_funcs_and_init(indio_dev); | ||
218 | if (ret) | ||
219 | goto error_disable_reg; | ||
220 | |||
221 | ret = iio_device_register(indio_dev); | ||
222 | if (ret) | ||
223 | goto error_disable_reg; | ||
224 | regdone = 1; | ||
225 | |||
226 | ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, | ||
227 | &ad7298_channels[1], /* skip temp0 */ | ||
228 | ARRAY_SIZE(ad7298_channels) - 1); | ||
229 | if (ret) | ||
230 | goto error_cleanup_ring; | ||
231 | |||
232 | return 0; | ||
233 | |||
234 | error_cleanup_ring: | ||
235 | ad7298_ring_cleanup(indio_dev); | ||
236 | error_disable_reg: | ||
237 | if (!IS_ERR(st->reg)) | ||
238 | regulator_disable(st->reg); | ||
239 | error_put_reg: | ||
240 | if (!IS_ERR(st->reg)) | ||
241 | regulator_put(st->reg); | ||
242 | |||
243 | if (regdone) | ||
244 | iio_device_unregister(indio_dev); | ||
245 | else | ||
246 | iio_free_device(indio_dev); | ||
247 | |||
248 | return ret; | ||
249 | } | ||
250 | |||
251 | static int __devexit ad7298_remove(struct spi_device *spi) | ||
252 | { | ||
253 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
254 | struct ad7298_state *st = iio_priv(indio_dev); | ||
255 | |||
256 | iio_ring_buffer_unregister(indio_dev->ring); | ||
257 | ad7298_ring_cleanup(indio_dev); | ||
258 | iio_device_unregister(indio_dev); | ||
259 | if (!IS_ERR(st->reg)) { | ||
260 | regulator_disable(st->reg); | ||
261 | regulator_put(st->reg); | ||
262 | } | ||
263 | iio_device_unregister(indio_dev); | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | static const struct spi_device_id ad7298_id[] = { | ||
269 | {"ad7298", 0}, | ||
270 | {} | ||
271 | }; | ||
272 | |||
273 | static struct spi_driver ad7298_driver = { | ||
274 | .driver = { | ||
275 | .name = "ad7298", | ||
276 | .bus = &spi_bus_type, | ||
277 | .owner = THIS_MODULE, | ||
278 | }, | ||
279 | .probe = ad7298_probe, | ||
280 | .remove = __devexit_p(ad7298_remove), | ||
281 | .id_table = ad7298_id, | ||
282 | }; | ||
283 | |||
284 | static int __init ad7298_init(void) | ||
285 | { | ||
286 | return spi_register_driver(&ad7298_driver); | ||
287 | } | ||
288 | module_init(ad7298_init); | ||
289 | |||
290 | static void __exit ad7298_exit(void) | ||
291 | { | ||
292 | spi_unregister_driver(&ad7298_driver); | ||
293 | } | ||
294 | module_exit(ad7298_exit); | ||
295 | |||
296 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
297 | MODULE_DESCRIPTION("Analog Devices AD7298 ADC"); | ||
298 | MODULE_LICENSE("GPL v2"); | ||
299 | MODULE_ALIAS("spi:ad7298"); | ||
diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c new file mode 100644 index 00000000000..a04c0335262 --- /dev/null +++ b/drivers/staging/iio/adc/ad7298_ring.c | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | * AD7298 SPI ADC driver | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
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 | |||
16 | #include "../iio.h" | ||
17 | #include "../ring_generic.h" | ||
18 | #include "../ring_sw.h" | ||
19 | #include "../trigger.h" | ||
20 | #include "../sysfs.h" | ||
21 | |||
22 | #include "ad7298.h" | ||
23 | |||
24 | int ad7298_scan_from_ring(struct iio_dev *dev_info, long ch) | ||
25 | { | ||
26 | struct iio_ring_buffer *ring = dev_info->ring; | ||
27 | int ret; | ||
28 | u16 *ring_data; | ||
29 | |||
30 | if (!(ring->scan_mask & (1 << ch))) { | ||
31 | ret = -EBUSY; | ||
32 | goto error_ret; | ||
33 | } | ||
34 | |||
35 | ring_data = kmalloc(ring->access->get_bytes_per_datum(ring), | ||
36 | GFP_KERNEL); | ||
37 | if (ring_data == NULL) { | ||
38 | ret = -ENOMEM; | ||
39 | goto error_ret; | ||
40 | } | ||
41 | ret = ring->access->read_last(ring, (u8 *) ring_data); | ||
42 | if (ret) | ||
43 | goto error_free_ring_data; | ||
44 | |||
45 | ret = be16_to_cpu(ring_data[ch]); | ||
46 | |||
47 | error_free_ring_data: | ||
48 | kfree(ring_data); | ||
49 | error_ret: | ||
50 | return ret; | ||
51 | } | ||
52 | |||
53 | /** | ||
54 | * ad7298_ring_preenable() setup the parameters of the ring before enabling | ||
55 | * | ||
56 | * The complex nature of the setting of the number of bytes per datum is due | ||
57 | * to this driver currently ensuring that the timestamp is stored at an 8 | ||
58 | * byte boundary. | ||
59 | **/ | ||
60 | static int ad7298_ring_preenable(struct iio_dev *indio_dev) | ||
61 | { | ||
62 | struct ad7298_state *st = iio_priv(indio_dev); | ||
63 | struct iio_ring_buffer *ring = indio_dev->ring; | ||
64 | size_t d_size; | ||
65 | int i, m; | ||
66 | unsigned short command; | ||
67 | |||
68 | d_size = ring->scan_count * (AD7298_STORAGE_BITS / 8); | ||
69 | |||
70 | if (ring->scan_timestamp) { | ||
71 | d_size += sizeof(s64); | ||
72 | |||
73 | if (d_size % sizeof(s64)) | ||
74 | d_size += sizeof(s64) - (d_size % sizeof(s64)); | ||
75 | } | ||
76 | |||
77 | if (ring->access->set_bytes_per_datum) | ||
78 | ring->access->set_bytes_per_datum(ring, d_size); | ||
79 | |||
80 | st->d_size = d_size; | ||
81 | |||
82 | command = AD7298_WRITE | st->ext_ref; | ||
83 | |||
84 | for (i = 0, m = AD7298_CH(0); i < AD7298_MAX_CHAN; i++, m >>= 1) | ||
85 | if (ring->scan_mask & (1 << i)) | ||
86 | command |= m; | ||
87 | |||
88 | st->tx_buf[0] = cpu_to_be16(command); | ||
89 | |||
90 | /* build spi ring message */ | ||
91 | st->ring_xfer[0].tx_buf = &st->tx_buf[0]; | ||
92 | st->ring_xfer[0].len = 2; | ||
93 | st->ring_xfer[0].cs_change = 1; | ||
94 | st->ring_xfer[1].tx_buf = &st->tx_buf[1]; | ||
95 | st->ring_xfer[1].len = 2; | ||
96 | st->ring_xfer[1].cs_change = 1; | ||
97 | |||
98 | spi_message_init(&st->ring_msg); | ||
99 | spi_message_add_tail(&st->ring_xfer[0], &st->ring_msg); | ||
100 | spi_message_add_tail(&st->ring_xfer[1], &st->ring_msg); | ||
101 | |||
102 | for (i = 0; i < ring->scan_count; i++) { | ||
103 | st->ring_xfer[i + 2].rx_buf = &st->rx_buf[i]; | ||
104 | st->ring_xfer[i + 2].len = 2; | ||
105 | st->ring_xfer[i + 2].cs_change = 1; | ||
106 | spi_message_add_tail(&st->ring_xfer[i + 2], &st->ring_msg); | ||
107 | } | ||
108 | /* make sure last transfer cs_change is not set */ | ||
109 | st->ring_xfer[i + 1].cs_change = 0; | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * ad7298_trigger_handler() bh of trigger launched polling to ring buffer | ||
116 | * | ||
117 | * Currently there is no option in this driver to disable the saving of | ||
118 | * timestamps within the ring. | ||
119 | **/ | ||
120 | static irqreturn_t ad7298_trigger_handler(int irq, void *p) | ||
121 | { | ||
122 | struct iio_poll_func *pf = p; | ||
123 | struct iio_dev *indio_dev = pf->private_data; | ||
124 | struct ad7298_state *st = iio_priv(indio_dev); | ||
125 | struct iio_ring_buffer *ring = indio_dev->ring; | ||
126 | s64 time_ns; | ||
127 | __u16 buf[16]; | ||
128 | int b_sent, i; | ||
129 | |||
130 | b_sent = spi_sync(st->spi, &st->ring_msg); | ||
131 | if (b_sent) | ||
132 | return b_sent; | ||
133 | |||
134 | if (ring->scan_timestamp) { | ||
135 | time_ns = iio_get_time_ns(); | ||
136 | memcpy((u8 *)buf + st->d_size - sizeof(s64), | ||
137 | &time_ns, sizeof(time_ns)); | ||
138 | } | ||
139 | |||
140 | for (i = 0; i < ring->scan_count; i++) | ||
141 | buf[i] = be16_to_cpu(st->rx_buf[i]); | ||
142 | |||
143 | indio_dev->ring->access->store_to(ring, (u8 *)buf, time_ns); | ||
144 | iio_trigger_notify_done(indio_dev->trig); | ||
145 | |||
146 | return IRQ_HANDLED; | ||
147 | } | ||
148 | |||
149 | static const struct iio_ring_setup_ops ad7298_ring_setup_ops = { | ||
150 | .preenable = &ad7298_ring_preenable, | ||
151 | .postenable = &iio_triggered_ring_postenable, | ||
152 | .predisable = &iio_triggered_ring_predisable, | ||
153 | }; | ||
154 | |||
155 | int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev) | ||
156 | { | ||
157 | int ret; | ||
158 | |||
159 | indio_dev->ring = iio_sw_rb_allocate(indio_dev); | ||
160 | if (!indio_dev->ring) { | ||
161 | ret = -ENOMEM; | ||
162 | goto error_ret; | ||
163 | } | ||
164 | /* Effectively select the ring buffer implementation */ | ||
165 | indio_dev->ring->access = &ring_sw_access_funcs; | ||
166 | |||
167 | indio_dev->pollfunc = iio_alloc_pollfunc(NULL, | ||
168 | &ad7298_trigger_handler, | ||
169 | IRQF_ONESHOT, | ||
170 | indio_dev, | ||
171 | "ad7298_consumer%d", | ||
172 | indio_dev->id); | ||
173 | |||
174 | if (indio_dev->pollfunc == NULL) { | ||
175 | ret = -ENOMEM; | ||
176 | goto error_deallocate_sw_rb; | ||
177 | } | ||
178 | |||
179 | /* Ring buffer functions - here trigger setup related */ | ||
180 | indio_dev->ring->setup_ops = &ad7298_ring_setup_ops; | ||
181 | indio_dev->ring->scan_timestamp = true; | ||
182 | |||
183 | /* Flag that polled ring buffering is possible */ | ||
184 | indio_dev->modes |= INDIO_RING_TRIGGERED; | ||
185 | return 0; | ||
186 | |||
187 | error_deallocate_sw_rb: | ||
188 | iio_sw_rb_free(indio_dev->ring); | ||
189 | error_ret: | ||
190 | return ret; | ||
191 | } | ||
192 | |||
193 | void ad7298_ring_cleanup(struct iio_dev *indio_dev) | ||
194 | { | ||
195 | if (indio_dev->trig) { | ||
196 | iio_put_trigger(indio_dev->trig); | ||
197 | iio_trigger_dettach_poll_func(indio_dev->trig, | ||
198 | indio_dev->pollfunc); | ||
199 | } | ||
200 | iio_dealloc_pollfunc(indio_dev->pollfunc); | ||
201 | iio_sw_rb_free(indio_dev->ring); | ||
202 | } | ||
diff --git a/drivers/staging/iio/adc/ad7314.c b/drivers/staging/iio/adc/ad7314.c new file mode 100644 index 00000000000..9070d9cac72 --- /dev/null +++ b/drivers/staging/iio/adc/ad7314.c | |||
@@ -0,0 +1,281 @@ | |||
1 | /* | ||
2 | * AD7314 digital temperature sensor driver for AD7314, ADT7301 and ADT7302 | ||
3 | * | ||
4 | * Copyright 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/device.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/sysfs.h> | ||
13 | #include <linux/spi/spi.h> | ||
14 | |||
15 | #include "../iio.h" | ||
16 | #include "../sysfs.h" | ||
17 | |||
18 | /* | ||
19 | * AD7314 power mode | ||
20 | */ | ||
21 | #define AD7314_PD 0x2000 | ||
22 | |||
23 | /* | ||
24 | * AD7314 temperature masks | ||
25 | */ | ||
26 | #define AD7314_TEMP_SIGN 0x200 | ||
27 | #define AD7314_TEMP_MASK 0x7FE0 | ||
28 | #define AD7314_TEMP_OFFSET 5 | ||
29 | #define AD7314_TEMP_FLOAT_OFFSET 2 | ||
30 | #define AD7314_TEMP_FLOAT_MASK 0x3 | ||
31 | |||
32 | /* | ||
33 | * ADT7301 and ADT7302 temperature masks | ||
34 | */ | ||
35 | #define ADT7301_TEMP_SIGN 0x2000 | ||
36 | #define ADT7301_TEMP_MASK 0x2FFF | ||
37 | #define ADT7301_TEMP_FLOAT_OFFSET 5 | ||
38 | #define ADT7301_TEMP_FLOAT_MASK 0x1F | ||
39 | |||
40 | /* | ||
41 | * struct ad7314_chip_info - chip specifc information | ||
42 | */ | ||
43 | |||
44 | struct ad7314_chip_info { | ||
45 | struct spi_device *spi_dev; | ||
46 | s64 last_timestamp; | ||
47 | u8 mode; | ||
48 | }; | ||
49 | |||
50 | /* | ||
51 | * ad7314 register access by SPI | ||
52 | */ | ||
53 | |||
54 | static int ad7314_spi_read(struct ad7314_chip_info *chip, u16 *data) | ||
55 | { | ||
56 | struct spi_device *spi_dev = chip->spi_dev; | ||
57 | int ret = 0; | ||
58 | u16 value; | ||
59 | |||
60 | ret = spi_read(spi_dev, (u8 *)&value, sizeof(value)); | ||
61 | if (ret < 0) { | ||
62 | dev_err(&spi_dev->dev, "SPI read error\n"); | ||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | *data = be16_to_cpu((u16)value); | ||
67 | |||
68 | return ret; | ||
69 | } | ||
70 | |||
71 | static int ad7314_spi_write(struct ad7314_chip_info *chip, u16 data) | ||
72 | { | ||
73 | struct spi_device *spi_dev = chip->spi_dev; | ||
74 | int ret = 0; | ||
75 | u16 value = cpu_to_be16(data); | ||
76 | |||
77 | ret = spi_write(spi_dev, (u8 *)&value, sizeof(value)); | ||
78 | if (ret < 0) | ||
79 | dev_err(&spi_dev->dev, "SPI write error\n"); | ||
80 | |||
81 | return ret; | ||
82 | } | ||
83 | |||
84 | static ssize_t ad7314_show_mode(struct device *dev, | ||
85 | struct device_attribute *attr, | ||
86 | char *buf) | ||
87 | { | ||
88 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
89 | struct ad7314_chip_info *chip = iio_priv(dev_info); | ||
90 | |||
91 | if (chip->mode) | ||
92 | return sprintf(buf, "power-save\n"); | ||
93 | else | ||
94 | return sprintf(buf, "full\n"); | ||
95 | } | ||
96 | |||
97 | static ssize_t ad7314_store_mode(struct device *dev, | ||
98 | struct device_attribute *attr, | ||
99 | const char *buf, | ||
100 | size_t len) | ||
101 | { | ||
102 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
103 | struct ad7314_chip_info *chip = iio_priv(dev_info); | ||
104 | u16 mode = 0; | ||
105 | int ret; | ||
106 | |||
107 | if (!strcmp(buf, "full")) | ||
108 | mode = AD7314_PD; | ||
109 | |||
110 | ret = ad7314_spi_write(chip, mode); | ||
111 | if (ret) | ||
112 | return -EIO; | ||
113 | |||
114 | chip->mode = mode; | ||
115 | |||
116 | return len; | ||
117 | } | ||
118 | |||
119 | static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, | ||
120 | ad7314_show_mode, | ||
121 | ad7314_store_mode, | ||
122 | 0); | ||
123 | |||
124 | static ssize_t ad7314_show_available_modes(struct device *dev, | ||
125 | struct device_attribute *attr, | ||
126 | char *buf) | ||
127 | { | ||
128 | return sprintf(buf, "full\npower-save\n"); | ||
129 | } | ||
130 | |||
131 | static IIO_DEVICE_ATTR(available_modes, S_IRUGO, ad7314_show_available_modes, NULL, 0); | ||
132 | |||
133 | static ssize_t ad7314_show_temperature(struct device *dev, | ||
134 | struct device_attribute *attr, | ||
135 | char *buf) | ||
136 | { | ||
137 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
138 | struct ad7314_chip_info *chip = iio_priv(dev_info); | ||
139 | u16 data; | ||
140 | char sign = ' '; | ||
141 | int ret; | ||
142 | |||
143 | if (chip->mode) { | ||
144 | ret = ad7314_spi_write(chip, 0); | ||
145 | if (ret) | ||
146 | return -EIO; | ||
147 | } | ||
148 | |||
149 | ret = ad7314_spi_read(chip, &data); | ||
150 | if (ret) | ||
151 | return -EIO; | ||
152 | |||
153 | if (chip->mode) | ||
154 | ad7314_spi_write(chip, chip->mode); | ||
155 | |||
156 | if (strcmp(dev_info->name, "ad7314")) { | ||
157 | data = (data & AD7314_TEMP_MASK) >> | ||
158 | AD7314_TEMP_OFFSET; | ||
159 | if (data & AD7314_TEMP_SIGN) { | ||
160 | data = (AD7314_TEMP_SIGN << 1) - data; | ||
161 | sign = '-'; | ||
162 | } | ||
163 | |||
164 | return sprintf(buf, "%c%d.%.2d\n", sign, | ||
165 | data >> AD7314_TEMP_FLOAT_OFFSET, | ||
166 | (data & AD7314_TEMP_FLOAT_MASK) * 25); | ||
167 | } else { | ||
168 | data &= ADT7301_TEMP_MASK; | ||
169 | if (data & ADT7301_TEMP_SIGN) { | ||
170 | data = (ADT7301_TEMP_SIGN << 1) - data; | ||
171 | sign = '-'; | ||
172 | } | ||
173 | |||
174 | return sprintf(buf, "%c%d.%.5d\n", sign, | ||
175 | data >> ADT7301_TEMP_FLOAT_OFFSET, | ||
176 | (data & ADT7301_TEMP_FLOAT_MASK) * 3125); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | static IIO_DEVICE_ATTR(temperature, S_IRUGO, ad7314_show_temperature, NULL, 0); | ||
181 | |||
182 | static struct attribute *ad7314_attributes[] = { | ||
183 | &iio_dev_attr_available_modes.dev_attr.attr, | ||
184 | &iio_dev_attr_mode.dev_attr.attr, | ||
185 | &iio_dev_attr_temperature.dev_attr.attr, | ||
186 | NULL, | ||
187 | }; | ||
188 | |||
189 | static const struct attribute_group ad7314_attribute_group = { | ||
190 | .attrs = ad7314_attributes, | ||
191 | }; | ||
192 | |||
193 | static const struct iio_info ad7314_info = { | ||
194 | .attrs = &ad7314_attribute_group, | ||
195 | .driver_module = THIS_MODULE, | ||
196 | }; | ||
197 | /* | ||
198 | * device probe and remove | ||
199 | */ | ||
200 | |||
201 | static int __devinit ad7314_probe(struct spi_device *spi_dev) | ||
202 | { | ||
203 | struct ad7314_chip_info *chip; | ||
204 | struct iio_dev *indio_dev; | ||
205 | int ret = 0; | ||
206 | |||
207 | indio_dev = iio_allocate_device(sizeof(*chip)); | ||
208 | if (indio_dev == NULL) { | ||
209 | ret = -ENOMEM; | ||
210 | goto error_ret; | ||
211 | } | ||
212 | chip = iio_priv(indio_dev); | ||
213 | /* this is only used for device removal purposes */ | ||
214 | dev_set_drvdata(&spi_dev->dev, chip); | ||
215 | |||
216 | chip->spi_dev = spi_dev; | ||
217 | |||
218 | indio_dev->name = spi_get_device_id(spi_dev)->name; | ||
219 | indio_dev->dev.parent = &spi_dev->dev; | ||
220 | indio_dev->info = &ad7314_info; | ||
221 | |||
222 | ret = iio_device_register(indio_dev); | ||
223 | if (ret) | ||
224 | goto error_free_dev; | ||
225 | |||
226 | dev_info(&spi_dev->dev, "%s temperature sensor registered.\n", | ||
227 | indio_dev->name); | ||
228 | |||
229 | return 0; | ||
230 | error_free_dev: | ||
231 | iio_free_device(indio_dev); | ||
232 | error_ret: | ||
233 | return ret; | ||
234 | } | ||
235 | |||
236 | static int __devexit ad7314_remove(struct spi_device *spi_dev) | ||
237 | { | ||
238 | struct iio_dev *indio_dev = dev_get_drvdata(&spi_dev->dev); | ||
239 | |||
240 | dev_set_drvdata(&spi_dev->dev, NULL); | ||
241 | iio_device_unregister(indio_dev); | ||
242 | iio_free_device(indio_dev); | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static const struct spi_device_id ad7314_id[] = { | ||
248 | { "adt7301", 0 }, | ||
249 | { "adt7302", 0 }, | ||
250 | { "ad7314", 0 }, | ||
251 | {} | ||
252 | }; | ||
253 | |||
254 | static struct spi_driver ad7314_driver = { | ||
255 | .driver = { | ||
256 | .name = "ad7314", | ||
257 | .bus = &spi_bus_type, | ||
258 | .owner = THIS_MODULE, | ||
259 | }, | ||
260 | .probe = ad7314_probe, | ||
261 | .remove = __devexit_p(ad7314_remove), | ||
262 | .id_table = ad7314_id, | ||
263 | }; | ||
264 | |||
265 | static __init int ad7314_init(void) | ||
266 | { | ||
267 | return spi_register_driver(&ad7314_driver); | ||
268 | } | ||
269 | |||
270 | static __exit void ad7314_exit(void) | ||
271 | { | ||
272 | spi_unregister_driver(&ad7314_driver); | ||
273 | } | ||
274 | |||
275 | MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>"); | ||
276 | MODULE_DESCRIPTION("Analog Devices AD7314, ADT7301 and ADT7302 digital" | ||
277 | " temperature sensor driver"); | ||
278 | MODULE_LICENSE("GPL v2"); | ||
279 | |||
280 | module_init(ad7314_init); | ||
281 | module_exit(ad7314_exit); | ||
diff --git a/drivers/staging/iio/adc/ad7476.h b/drivers/staging/iio/adc/ad7476.h new file mode 100644 index 00000000000..0d44976e846 --- /dev/null +++ b/drivers/staging/iio/adc/ad7476.h | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * AD7476/5/7/8 (A) SPI ADC driver | ||
3 | * | ||
4 | * Copyright 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | #ifndef IIO_ADC_AD7476_H_ | ||
9 | #define IIO_ADC_AD7476_H_ | ||
10 | |||
11 | #define RES_MASK(bits) ((1 << (bits)) - 1) | ||
12 | |||
13 | /* | ||
14 | * TODO: struct ad7476_platform_data needs to go into include/linux/iio | ||
15 | */ | ||
16 | |||
17 | struct ad7476_platform_data { | ||
18 | u16 vref_mv; | ||
19 | }; | ||
20 | |||
21 | struct ad7476_chip_info { | ||
22 | u16 int_vref_mv; | ||
23 | struct iio_chan_spec channel[2]; | ||
24 | }; | ||
25 | |||
26 | struct ad7476_state { | ||
27 | struct spi_device *spi; | ||
28 | const struct ad7476_chip_info *chip_info; | ||
29 | struct regulator *reg; | ||
30 | size_t d_size; | ||
31 | u16 int_vref_mv; | ||
32 | struct spi_transfer xfer; | ||
33 | struct spi_message msg; | ||
34 | /* | ||
35 | * DMA (thus cache coherency maintenance) requires the | ||
36 | * transfer buffers to live in their own cache lines. | ||
37 | */ | ||
38 | unsigned char data[2] ____cacheline_aligned; | ||
39 | }; | ||
40 | |||
41 | enum ad7476_supported_device_ids { | ||
42 | ID_AD7466, | ||
43 | ID_AD7467, | ||
44 | ID_AD7468, | ||
45 | ID_AD7475, | ||
46 | ID_AD7476, | ||
47 | ID_AD7477, | ||
48 | ID_AD7478, | ||
49 | ID_AD7495 | ||
50 | }; | ||
51 | |||
52 | #ifdef CONFIG_IIO_RING_BUFFER | ||
53 | int ad7476_scan_from_ring(struct iio_dev *indio_dev); | ||
54 | int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev); | ||
55 | void ad7476_ring_cleanup(struct iio_dev *indio_dev); | ||
56 | #else /* CONFIG_IIO_RING_BUFFER */ | ||
57 | static inline int ad7476_scan_from_ring(struct iio_dev *indio_dev) | ||
58 | { | ||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | static inline int | ||
63 | ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev) | ||
64 | { | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static inline void ad7476_ring_cleanup(struct iio_dev *indio_dev) | ||
69 | { | ||
70 | } | ||
71 | #endif /* CONFIG_IIO_RING_BUFFER */ | ||
72 | #endif /* IIO_ADC_AD7476_H_ */ | ||
diff --git a/drivers/staging/iio/adc/ad7476_core.c b/drivers/staging/iio/adc/ad7476_core.c new file mode 100644 index 00000000000..c21089894d2 --- /dev/null +++ b/drivers/staging/iio/adc/ad7476_core.c | |||
@@ -0,0 +1,270 @@ | |||
1 | /* | ||
2 | * AD7466/7/8 AD7476/5/7/8 (A) SPI ADC driver | ||
3 | * | ||
4 | * Copyright 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/device.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/sysfs.h> | ||
13 | #include <linux/spi/spi.h> | ||
14 | #include <linux/regulator/consumer.h> | ||
15 | #include <linux/err.h> | ||
16 | |||
17 | #include "../iio.h" | ||
18 | #include "../sysfs.h" | ||
19 | #include "../ring_generic.h" | ||
20 | #include "adc.h" | ||
21 | |||
22 | #include "ad7476.h" | ||
23 | |||
24 | static int ad7476_scan_direct(struct ad7476_state *st) | ||
25 | { | ||
26 | int ret; | ||
27 | |||
28 | ret = spi_sync(st->spi, &st->msg); | ||
29 | if (ret) | ||
30 | return ret; | ||
31 | |||
32 | return (st->data[0] << 8) | st->data[1]; | ||
33 | } | ||
34 | |||
35 | static int ad7476_read_raw(struct iio_dev *dev_info, | ||
36 | struct iio_chan_spec const *chan, | ||
37 | int *val, | ||
38 | int *val2, | ||
39 | long m) | ||
40 | { | ||
41 | int ret; | ||
42 | struct ad7476_state *st = iio_priv(dev_info); | ||
43 | unsigned int scale_uv; | ||
44 | |||
45 | switch (m) { | ||
46 | case 0: | ||
47 | mutex_lock(&dev_info->mlock); | ||
48 | if (iio_ring_enabled(dev_info)) | ||
49 | ret = ad7476_scan_from_ring(dev_info); | ||
50 | else | ||
51 | ret = ad7476_scan_direct(st); | ||
52 | mutex_unlock(&dev_info->mlock); | ||
53 | |||
54 | if (ret < 0) | ||
55 | return ret; | ||
56 | *val = (ret >> st->chip_info->channel[0].scan_type.shift) & | ||
57 | RES_MASK(st->chip_info->channel[0].scan_type.realbits); | ||
58 | return IIO_VAL_INT; | ||
59 | case (1 << IIO_CHAN_INFO_SCALE_SHARED): | ||
60 | scale_uv = (st->int_vref_mv * 1000) | ||
61 | >> st->chip_info->channel[0].scan_type.realbits; | ||
62 | *val = scale_uv/1000; | ||
63 | *val2 = (scale_uv%1000)*1000; | ||
64 | return IIO_VAL_INT_PLUS_MICRO; | ||
65 | } | ||
66 | return -EINVAL; | ||
67 | } | ||
68 | |||
69 | static const struct ad7476_chip_info ad7476_chip_info_tbl[] = { | ||
70 | [ID_AD7466] = { | ||
71 | .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, | ||
72 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
73 | 0, 0, IIO_ST('u', 12, 16, 0), 0), | ||
74 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | ||
75 | }, | ||
76 | [ID_AD7467] = { | ||
77 | .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, | ||
78 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
79 | 0, 0, IIO_ST('u', 10, 16, 2), 0), | ||
80 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | ||
81 | }, | ||
82 | [ID_AD7468] = { | ||
83 | .channel[0] = IIO_CHAN(IIO_IN, 0, 1 , 0, NULL, 0, 0, | ||
84 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
85 | 0, 0, IIO_ST('u', 8, 16, 4), 0), | ||
86 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | ||
87 | }, | ||
88 | [ID_AD7475] = { | ||
89 | .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, | ||
90 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
91 | 0, 0, IIO_ST('u', 12, 16, 0), 0), | ||
92 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | ||
93 | }, | ||
94 | [ID_AD7476] = { | ||
95 | .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, | ||
96 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
97 | 0, 0, IIO_ST('u', 12, 16, 0), 0), | ||
98 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | ||
99 | }, | ||
100 | [ID_AD7477] = { | ||
101 | .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, | ||
102 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
103 | 0, 0, IIO_ST('u', 10, 16, 2), 0), | ||
104 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | ||
105 | }, | ||
106 | [ID_AD7478] = { | ||
107 | .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, | ||
108 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
109 | 0, 0, IIO_ST('u', 8, 16, 4), 0), | ||
110 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | ||
111 | }, | ||
112 | [ID_AD7495] = { | ||
113 | .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, | ||
114 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
115 | 0, 0, IIO_ST('u', 12, 16, 0), 0), | ||
116 | .channel[1] = IIO_CHAN_SOFT_TIMESTAMP(1), | ||
117 | .int_vref_mv = 2500, | ||
118 | }, | ||
119 | }; | ||
120 | |||
121 | static const struct iio_info ad7476_info = { | ||
122 | .driver_module = THIS_MODULE, | ||
123 | .read_raw = &ad7476_read_raw, | ||
124 | }; | ||
125 | |||
126 | static int __devinit ad7476_probe(struct spi_device *spi) | ||
127 | { | ||
128 | struct ad7476_platform_data *pdata = spi->dev.platform_data; | ||
129 | struct ad7476_state *st; | ||
130 | struct iio_dev *indio_dev; | ||
131 | int ret, voltage_uv = 0; | ||
132 | bool reg_done = false; | ||
133 | struct regulator *reg; | ||
134 | |||
135 | indio_dev = iio_allocate_device(sizeof(*st)); | ||
136 | if (indio_dev == NULL) { | ||
137 | ret = -ENOMEM; | ||
138 | goto error_ret; | ||
139 | } | ||
140 | st = iio_priv(indio_dev); | ||
141 | reg = regulator_get(&spi->dev, "vcc"); | ||
142 | if (!IS_ERR(reg)) { | ||
143 | ret = regulator_enable(reg); | ||
144 | if (ret) | ||
145 | goto error_put_reg; | ||
146 | |||
147 | voltage_uv = regulator_get_voltage(reg); | ||
148 | } | ||
149 | st->reg = reg; | ||
150 | st->chip_info = | ||
151 | &ad7476_chip_info_tbl[spi_get_device_id(spi)->driver_data]; | ||
152 | |||
153 | if (st->chip_info->int_vref_mv) | ||
154 | st->int_vref_mv = st->chip_info->int_vref_mv; | ||
155 | else if (pdata && pdata->vref_mv) | ||
156 | st->int_vref_mv = pdata->vref_mv; | ||
157 | else if (voltage_uv) | ||
158 | st->int_vref_mv = voltage_uv / 1000; | ||
159 | else | ||
160 | dev_warn(&spi->dev, "reference voltage unspecified\n"); | ||
161 | |||
162 | spi_set_drvdata(spi, indio_dev); | ||
163 | |||
164 | st->spi = spi; | ||
165 | |||
166 | /* Establish that the iio_dev is a child of the spi device */ | ||
167 | indio_dev->dev.parent = &spi->dev; | ||
168 | indio_dev->name = spi_get_device_id(spi)->name; | ||
169 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
170 | indio_dev->channels = st->chip_info->channel; | ||
171 | indio_dev->num_channels = 2; | ||
172 | indio_dev->info = &ad7476_info; | ||
173 | /* Setup default message */ | ||
174 | |||
175 | st->xfer.rx_buf = &st->data; | ||
176 | st->xfer.len = st->chip_info->channel[0].scan_type.storagebits / 8; | ||
177 | |||
178 | spi_message_init(&st->msg); | ||
179 | spi_message_add_tail(&st->xfer, &st->msg); | ||
180 | |||
181 | ret = ad7476_register_ring_funcs_and_init(indio_dev); | ||
182 | if (ret) | ||
183 | goto error_disable_reg; | ||
184 | |||
185 | ret = iio_device_register(indio_dev); | ||
186 | if (ret) | ||
187 | goto error_disable_reg; | ||
188 | |||
189 | ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, | ||
190 | st->chip_info->channel, | ||
191 | ARRAY_SIZE(st->chip_info->channel)); | ||
192 | if (ret) | ||
193 | goto error_cleanup_ring; | ||
194 | return 0; | ||
195 | |||
196 | error_cleanup_ring: | ||
197 | ad7476_ring_cleanup(indio_dev); | ||
198 | iio_device_unregister(indio_dev); | ||
199 | error_disable_reg: | ||
200 | if (!IS_ERR(reg)) | ||
201 | regulator_disable(st->reg); | ||
202 | error_put_reg: | ||
203 | if (!IS_ERR(reg)) | ||
204 | regulator_put(reg); | ||
205 | if (!reg_done) | ||
206 | iio_free_device(indio_dev); | ||
207 | error_ret: | ||
208 | return ret; | ||
209 | } | ||
210 | |||
211 | static int ad7476_remove(struct spi_device *spi) | ||
212 | { | ||
213 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
214 | struct ad7476_state *st = iio_priv(indio_dev); | ||
215 | /* copy needed as st will have been freed */ | ||
216 | struct regulator *reg = st->reg; | ||
217 | |||
218 | iio_ring_buffer_unregister(indio_dev->ring); | ||
219 | ad7476_ring_cleanup(indio_dev); | ||
220 | iio_device_unregister(indio_dev); | ||
221 | if (!IS_ERR(reg)) { | ||
222 | regulator_disable(reg); | ||
223 | regulator_put(reg); | ||
224 | } | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static const struct spi_device_id ad7476_id[] = { | ||
230 | {"ad7466", ID_AD7466}, | ||
231 | {"ad7467", ID_AD7467}, | ||
232 | {"ad7468", ID_AD7468}, | ||
233 | {"ad7475", ID_AD7475}, | ||
234 | {"ad7476", ID_AD7476}, | ||
235 | {"ad7476a", ID_AD7476}, | ||
236 | {"ad7477", ID_AD7477}, | ||
237 | {"ad7477a", ID_AD7477}, | ||
238 | {"ad7478", ID_AD7478}, | ||
239 | {"ad7478a", ID_AD7478}, | ||
240 | {"ad7495", ID_AD7495}, | ||
241 | {} | ||
242 | }; | ||
243 | |||
244 | static struct spi_driver ad7476_driver = { | ||
245 | .driver = { | ||
246 | .name = "ad7476", | ||
247 | .bus = &spi_bus_type, | ||
248 | .owner = THIS_MODULE, | ||
249 | }, | ||
250 | .probe = ad7476_probe, | ||
251 | .remove = __devexit_p(ad7476_remove), | ||
252 | .id_table = ad7476_id, | ||
253 | }; | ||
254 | |||
255 | static int __init ad7476_init(void) | ||
256 | { | ||
257 | return spi_register_driver(&ad7476_driver); | ||
258 | } | ||
259 | module_init(ad7476_init); | ||
260 | |||
261 | static void __exit ad7476_exit(void) | ||
262 | { | ||
263 | spi_unregister_driver(&ad7476_driver); | ||
264 | } | ||
265 | module_exit(ad7476_exit); | ||
266 | |||
267 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
268 | MODULE_DESCRIPTION("Analog Devices AD7475/6/7/8(A) AD7466/7/8 ADC"); | ||
269 | MODULE_LICENSE("GPL v2"); | ||
270 | MODULE_ALIAS("spi:ad7476"); | ||
diff --git a/drivers/staging/iio/adc/ad7476_ring.c b/drivers/staging/iio/adc/ad7476_ring.c new file mode 100644 index 00000000000..a92fc5a1a60 --- /dev/null +++ b/drivers/staging/iio/adc/ad7476_ring.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Analog Devices Inc. | ||
3 | * Copyright (C) 2008 Jonathan Cameron | ||
4 | * | ||
5 | * Licensed under the GPL-2 or later. | ||
6 | * | ||
7 | * ad7476_ring.c | ||
8 | */ | ||
9 | |||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/device.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/sysfs.h> | ||
15 | #include <linux/spi/spi.h> | ||
16 | |||
17 | #include "../iio.h" | ||
18 | #include "../ring_generic.h" | ||
19 | #include "../ring_sw.h" | ||
20 | #include "../trigger.h" | ||
21 | #include "../sysfs.h" | ||
22 | |||
23 | #include "ad7476.h" | ||
24 | |||
25 | int ad7476_scan_from_ring(struct iio_dev *indio_dev) | ||
26 | { | ||
27 | struct iio_ring_buffer *ring = indio_dev->ring; | ||
28 | int ret; | ||
29 | u8 *ring_data; | ||
30 | |||
31 | ring_data = kmalloc(ring->access->get_bytes_per_datum(ring), | ||
32 | GFP_KERNEL); | ||
33 | if (ring_data == NULL) { | ||
34 | ret = -ENOMEM; | ||
35 | goto error_ret; | ||
36 | } | ||
37 | ret = ring->access->read_last(ring, ring_data); | ||
38 | if (ret) | ||
39 | goto error_free_ring_data; | ||
40 | |||
41 | ret = (ring_data[0] << 8) | ring_data[1]; | ||
42 | |||
43 | error_free_ring_data: | ||
44 | kfree(ring_data); | ||
45 | error_ret: | ||
46 | return ret; | ||
47 | } | ||
48 | |||
49 | /** | ||
50 | * ad7476_ring_preenable() setup the parameters of the ring before enabling | ||
51 | * | ||
52 | * The complex nature of the setting of the nuber of bytes per datum is due | ||
53 | * to this driver currently ensuring that the timestamp is stored at an 8 | ||
54 | * byte boundary. | ||
55 | **/ | ||
56 | static int ad7476_ring_preenable(struct iio_dev *indio_dev) | ||
57 | { | ||
58 | struct ad7476_state *st = iio_priv(indio_dev); | ||
59 | struct iio_ring_buffer *ring = indio_dev->ring; | ||
60 | |||
61 | st->d_size = ring->scan_count * | ||
62 | st->chip_info->channel[0].scan_type.storagebits / 8; | ||
63 | |||
64 | if (ring->scan_timestamp) { | ||
65 | st->d_size += sizeof(s64); | ||
66 | |||
67 | if (st->d_size % sizeof(s64)) | ||
68 | st->d_size += sizeof(s64) - (st->d_size % sizeof(s64)); | ||
69 | } | ||
70 | |||
71 | if (indio_dev->ring->access->set_bytes_per_datum) | ||
72 | indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring, | ||
73 | st->d_size); | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static irqreturn_t ad7476_trigger_handler(int irq, void *p) | ||
79 | { | ||
80 | struct iio_poll_func *pf = p; | ||
81 | struct iio_dev *indio_dev = pf->private_data; | ||
82 | struct ad7476_state *st = iio_priv(indio_dev); | ||
83 | s64 time_ns; | ||
84 | __u8 *rxbuf; | ||
85 | int b_sent; | ||
86 | |||
87 | rxbuf = kzalloc(st->d_size, GFP_KERNEL); | ||
88 | if (rxbuf == NULL) | ||
89 | return -ENOMEM; | ||
90 | |||
91 | b_sent = spi_read(st->spi, rxbuf, | ||
92 | st->chip_info->channel[0].scan_type.storagebits / 8); | ||
93 | if (b_sent < 0) | ||
94 | goto done; | ||
95 | |||
96 | time_ns = iio_get_time_ns(); | ||
97 | |||
98 | if (indio_dev->ring->scan_timestamp) | ||
99 | memcpy(rxbuf + st->d_size - sizeof(s64), | ||
100 | &time_ns, sizeof(time_ns)); | ||
101 | |||
102 | indio_dev->ring->access->store_to(indio_dev->ring, rxbuf, time_ns); | ||
103 | done: | ||
104 | iio_trigger_notify_done(indio_dev->trig); | ||
105 | kfree(rxbuf); | ||
106 | |||
107 | return IRQ_HANDLED; | ||
108 | } | ||
109 | |||
110 | static const struct iio_ring_setup_ops ad7476_ring_setup_ops = { | ||
111 | .preenable = &ad7476_ring_preenable, | ||
112 | .postenable = &iio_triggered_ring_postenable, | ||
113 | .predisable = &iio_triggered_ring_predisable, | ||
114 | }; | ||
115 | |||
116 | int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev) | ||
117 | { | ||
118 | struct ad7476_state *st = iio_priv(indio_dev); | ||
119 | int ret = 0; | ||
120 | |||
121 | indio_dev->ring = iio_sw_rb_allocate(indio_dev); | ||
122 | if (!indio_dev->ring) { | ||
123 | ret = -ENOMEM; | ||
124 | goto error_ret; | ||
125 | } | ||
126 | /* Effectively select the ring buffer implementation */ | ||
127 | indio_dev->ring->access = &ring_sw_access_funcs; | ||
128 | indio_dev->pollfunc | ||
129 | = iio_alloc_pollfunc(NULL, | ||
130 | &ad7476_trigger_handler, | ||
131 | IRQF_ONESHOT, | ||
132 | indio_dev, | ||
133 | "%s_consumer%d", | ||
134 | spi_get_device_id(st->spi)->name, | ||
135 | indio_dev->id); | ||
136 | if (indio_dev->pollfunc == NULL) { | ||
137 | ret = -ENOMEM; | ||
138 | goto error_deallocate_sw_rb; | ||
139 | } | ||
140 | |||
141 | /* Ring buffer functions - here trigger setup related */ | ||
142 | indio_dev->ring->setup_ops = &ad7476_ring_setup_ops; | ||
143 | indio_dev->ring->scan_timestamp = true; | ||
144 | |||
145 | /* Flag that polled ring buffering is possible */ | ||
146 | indio_dev->modes |= INDIO_RING_TRIGGERED; | ||
147 | return 0; | ||
148 | |||
149 | error_deallocate_sw_rb: | ||
150 | iio_sw_rb_free(indio_dev->ring); | ||
151 | error_ret: | ||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | void ad7476_ring_cleanup(struct iio_dev *indio_dev) | ||
156 | { | ||
157 | /* ensure that the trigger has been detached */ | ||
158 | if (indio_dev->trig) { | ||
159 | iio_put_trigger(indio_dev->trig); | ||
160 | iio_trigger_dettach_poll_func(indio_dev->trig, | ||
161 | indio_dev->pollfunc); | ||
162 | } | ||
163 | iio_dealloc_pollfunc(indio_dev->pollfunc); | ||
164 | iio_sw_rb_free(indio_dev->ring); | ||
165 | } | ||
diff --git a/drivers/staging/iio/adc/ad7745.c b/drivers/staging/iio/adc/ad7745.c new file mode 100644 index 00000000000..4c13f26aa9a --- /dev/null +++ b/drivers/staging/iio/adc/ad7745.c | |||
@@ -0,0 +1,674 @@ | |||
1 | /* | ||
2 | * AD774X capacitive sensor driver supporting AD7745/6/7 | ||
3 | * | ||
4 | * Copyright 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/gpio.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/i2c.h> | ||
17 | |||
18 | #include "../iio.h" | ||
19 | #include "../sysfs.h" | ||
20 | |||
21 | /* | ||
22 | * AD774X registers definition | ||
23 | */ | ||
24 | |||
25 | #define AD774X_STATUS 0 | ||
26 | #define AD774X_STATUS_RDY (1 << 2) | ||
27 | #define AD774X_STATUS_RDYVT (1 << 1) | ||
28 | #define AD774X_STATUS_RDYCAP (1 << 0) | ||
29 | #define AD774X_CAP_DATA_HIGH 1 | ||
30 | #define AD774X_CAP_DATA_MID 2 | ||
31 | #define AD774X_CAP_DATA_LOW 3 | ||
32 | #define AD774X_VT_DATA_HIGH 4 | ||
33 | #define AD774X_VT_DATA_MID 5 | ||
34 | #define AD774X_VT_DATA_LOW 6 | ||
35 | #define AD774X_CAP_SETUP 7 | ||
36 | #define AD774X_VT_SETUP 8 | ||
37 | #define AD774X_EXEC_SETUP 9 | ||
38 | #define AD774X_CFG 10 | ||
39 | #define AD774X_CAPDACA 11 | ||
40 | #define AD774X_CAPDACB 12 | ||
41 | #define AD774X_CAPDAC_EN (1 << 7) | ||
42 | #define AD774X_CAP_OFFH 13 | ||
43 | #define AD774X_CAP_OFFL 14 | ||
44 | #define AD774X_CAP_GAINH 15 | ||
45 | #define AD774X_CAP_GAINL 16 | ||
46 | #define AD774X_VOLT_GAINH 17 | ||
47 | #define AD774X_VOLT_GAINL 18 | ||
48 | |||
49 | #define AD774X_MAX_CONV_MODE 6 | ||
50 | |||
51 | /* | ||
52 | * struct ad774x_chip_info - chip specifc information | ||
53 | */ | ||
54 | |||
55 | struct ad774x_chip_info { | ||
56 | struct i2c_client *client; | ||
57 | bool inter; | ||
58 | u16 cap_offs; /* Capacitive offset */ | ||
59 | u16 cap_gain; /* Capacitive gain calibration */ | ||
60 | u16 volt_gain; /* Voltage gain calibration */ | ||
61 | u8 cap_setup; | ||
62 | u8 vt_setup; | ||
63 | u8 exec_setup; | ||
64 | |||
65 | char *conversion_mode; | ||
66 | }; | ||
67 | |||
68 | struct ad774x_conversion_mode { | ||
69 | char *name; | ||
70 | u8 reg_cfg; | ||
71 | }; | ||
72 | |||
73 | static struct ad774x_conversion_mode | ||
74 | ad774x_conv_mode_table[AD774X_MAX_CONV_MODE] = { | ||
75 | { "idle", 0 }, | ||
76 | { "continuous-conversion", 1 }, | ||
77 | { "single-conversion", 2 }, | ||
78 | { "power-down", 3 }, | ||
79 | { "offset-calibration", 5 }, | ||
80 | { "gain-calibration", 6 }, | ||
81 | }; | ||
82 | |||
83 | /* | ||
84 | * ad774x register access by I2C | ||
85 | */ | ||
86 | |||
87 | static int ad774x_i2c_read(struct ad774x_chip_info *chip, u8 reg, u8 *data, int len) | ||
88 | { | ||
89 | struct i2c_client *client = chip->client; | ||
90 | int ret; | ||
91 | |||
92 | ret = i2c_master_send(client, ®, 1); | ||
93 | if (ret < 0) { | ||
94 | dev_err(&client->dev, "I2C write error\n"); | ||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | ret = i2c_master_recv(client, data, len); | ||
99 | if (ret < 0) { | ||
100 | dev_err(&client->dev, "I2C read error\n"); | ||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | return ret; | ||
105 | } | ||
106 | |||
107 | static int ad774x_i2c_write(struct ad774x_chip_info *chip, u8 reg, u8 data) | ||
108 | { | ||
109 | struct i2c_client *client = chip->client; | ||
110 | int ret; | ||
111 | |||
112 | u8 tx[2] = { | ||
113 | reg, | ||
114 | data, | ||
115 | }; | ||
116 | |||
117 | ret = i2c_master_send(client, tx, 2); | ||
118 | if (ret < 0) | ||
119 | dev_err(&client->dev, "I2C write error\n"); | ||
120 | |||
121 | return ret; | ||
122 | } | ||
123 | |||
124 | /* | ||
125 | * sysfs nodes | ||
126 | */ | ||
127 | |||
128 | #define IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(_show) \ | ||
129 | IIO_DEVICE_ATTR(available_conversion_modes, S_IRUGO, _show, NULL, 0) | ||
130 | #define IIO_DEV_ATTR_CONVERSION_MODE(_mode, _show, _store) \ | ||
131 | IIO_DEVICE_ATTR(conversion_mode, _mode, _show, _store, 0) | ||
132 | #define IIO_DEV_ATTR_CAP_SETUP(_mode, _show, _store) \ | ||
133 | IIO_DEVICE_ATTR(cap_setup, _mode, _show, _store, 0) | ||
134 | #define IIO_DEV_ATTR_VT_SETUP(_mode, _show, _store) \ | ||
135 | IIO_DEVICE_ATTR(in0_setup, _mode, _show, _store, 0) | ||
136 | #define IIO_DEV_ATTR_EXEC_SETUP(_mode, _show, _store) \ | ||
137 | IIO_DEVICE_ATTR(exec_setup, _mode, _show, _store, 0) | ||
138 | #define IIO_DEV_ATTR_VOLT_GAIN(_mode, _show, _store) \ | ||
139 | IIO_DEVICE_ATTR(in0_gain, _mode, _show, _store, 0) | ||
140 | #define IIO_DEV_ATTR_CAP_OFFS(_mode, _show, _store) \ | ||
141 | IIO_DEVICE_ATTR(cap_offs, _mode, _show, _store, 0) | ||
142 | #define IIO_DEV_ATTR_CAP_GAIN(_mode, _show, _store) \ | ||
143 | IIO_DEVICE_ATTR(cap_gain, _mode, _show, _store, 0) | ||
144 | #define IIO_DEV_ATTR_CAP_DATA(_show) \ | ||
145 | IIO_DEVICE_ATTR(cap0_raw, S_IRUGO, _show, NULL, 0) | ||
146 | #define IIO_DEV_ATTR_VT_DATA(_show) \ | ||
147 | IIO_DEVICE_ATTR(in0_raw, S_IRUGO, _show, NULL, 0) | ||
148 | |||
149 | static ssize_t ad774x_show_conversion_modes(struct device *dev, | ||
150 | struct device_attribute *attr, | ||
151 | char *buf) | ||
152 | { | ||
153 | int i; | ||
154 | int len = 0; | ||
155 | |||
156 | for (i = 0; i < AD774X_MAX_CONV_MODE; i++) | ||
157 | len += sprintf(buf + len, "%s ", ad774x_conv_mode_table[i].name); | ||
158 | |||
159 | len += sprintf(buf + len, "\n"); | ||
160 | |||
161 | return len; | ||
162 | } | ||
163 | |||
164 | static IIO_DEV_ATTR_AVAIL_CONVERSION_MODES(ad774x_show_conversion_modes); | ||
165 | |||
166 | static ssize_t ad774x_show_conversion_mode(struct device *dev, | ||
167 | struct device_attribute *attr, | ||
168 | char *buf) | ||
169 | { | ||
170 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
171 | struct ad774x_chip_info *chip = iio_priv(dev_info); | ||
172 | |||
173 | return sprintf(buf, "%s\n", chip->conversion_mode); | ||
174 | } | ||
175 | |||
176 | static ssize_t ad774x_store_conversion_mode(struct device *dev, | ||
177 | struct device_attribute *attr, | ||
178 | const char *buf, | ||
179 | size_t len) | ||
180 | { | ||
181 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
182 | struct ad774x_chip_info *chip = iio_priv(dev_info); | ||
183 | u8 cfg; | ||
184 | int i; | ||
185 | |||
186 | ad774x_i2c_read(chip, AD774X_CFG, &cfg, 1); | ||
187 | |||
188 | for (i = 0; i < AD774X_MAX_CONV_MODE; i++) { | ||
189 | if (strncmp(buf, ad774x_conv_mode_table[i].name, | ||
190 | strlen(ad774x_conv_mode_table[i].name) - 1) == 0) { | ||
191 | chip->conversion_mode = ad774x_conv_mode_table[i].name; | ||
192 | cfg |= 0x18 | ad774x_conv_mode_table[i].reg_cfg; | ||
193 | ad774x_i2c_write(chip, AD774X_CFG, cfg); | ||
194 | return len; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | dev_err(dev, "not supported conversion mode\n"); | ||
199 | |||
200 | return -EINVAL; | ||
201 | } | ||
202 | |||
203 | static IIO_DEV_ATTR_CONVERSION_MODE(S_IRUGO | S_IWUSR, | ||
204 | ad774x_show_conversion_mode, | ||
205 | ad774x_store_conversion_mode); | ||
206 | |||
207 | static ssize_t ad774x_show_dac_value(struct device *dev, | ||
208 | struct device_attribute *attr, | ||
209 | char *buf) | ||
210 | { | ||
211 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
212 | struct ad774x_chip_info *chip = iio_priv(dev_info); | ||
213 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
214 | u8 data; | ||
215 | |||
216 | ad774x_i2c_read(chip, this_attr->address, &data, 1); | ||
217 | |||
218 | return sprintf(buf, "%02x\n", data & 0x7F); | ||
219 | } | ||
220 | |||
221 | static ssize_t ad774x_store_dac_value(struct device *dev, | ||
222 | struct device_attribute *attr, | ||
223 | const char *buf, | ||
224 | size_t len) | ||
225 | { | ||
226 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
227 | struct ad774x_chip_info *chip = iio_priv(dev_info); | ||
228 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
229 | unsigned long data; | ||
230 | int ret; | ||
231 | |||
232 | ret = strict_strtoul(buf, 10, &data); | ||
233 | |||
234 | if (!ret) { | ||
235 | ad774x_i2c_write(chip, this_attr->address, | ||
236 | (data ? AD774X_CAPDAC_EN : 0) | (data & 0x7F)); | ||
237 | return len; | ||
238 | } | ||
239 | |||
240 | return -EINVAL; | ||
241 | } | ||
242 | |||
243 | static IIO_DEVICE_ATTR(capdac0_raw, S_IRUGO | S_IWUSR, | ||
244 | ad774x_show_dac_value, | ||
245 | ad774x_store_dac_value, | ||
246 | AD774X_CAPDACA); | ||
247 | |||
248 | static IIO_DEVICE_ATTR(capdac1_raw, S_IRUGO | S_IWUSR, | ||
249 | ad774x_show_dac_value, | ||
250 | ad774x_store_dac_value, | ||
251 | AD774X_CAPDACB); | ||
252 | |||
253 | static ssize_t ad774x_show_cap_setup(struct device *dev, | ||
254 | struct device_attribute *attr, | ||
255 | char *buf) | ||
256 | { | ||
257 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
258 | struct ad774x_chip_info *chip = iio_priv(dev_info); | ||
259 | |||
260 | return sprintf(buf, "0x%02x\n", chip->cap_setup); | ||
261 | } | ||
262 | |||
263 | static ssize_t ad774x_store_cap_setup(struct device *dev, | ||
264 | struct device_attribute *attr, | ||
265 | const char *buf, | ||
266 | size_t len) | ||
267 | { | ||
268 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
269 | struct ad774x_chip_info *chip = iio_priv(dev_info); | ||
270 | unsigned long data; | ||
271 | int ret; | ||
272 | |||
273 | ret = strict_strtoul(buf, 10, &data); | ||
274 | |||
275 | if ((!ret) && (data < 0x100)) { | ||
276 | ad774x_i2c_write(chip, AD774X_CAP_SETUP, data); | ||
277 | chip->cap_setup = data; | ||
278 | return len; | ||
279 | } | ||
280 | |||
281 | return -EINVAL; | ||
282 | } | ||
283 | |||
284 | static IIO_DEV_ATTR_CAP_SETUP(S_IRUGO | S_IWUSR, | ||
285 | ad774x_show_cap_setup, | ||
286 | ad774x_store_cap_setup); | ||
287 | |||
288 | static ssize_t ad774x_show_vt_setup(struct device *dev, | ||
289 | struct device_attribute *attr, | ||
290 | char *buf) | ||
291 | { | ||
292 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
293 | struct ad774x_chip_info *chip = iio_priv(dev_info); | ||
294 | |||
295 | return sprintf(buf, "0x%02x\n", chip->vt_setup); | ||
296 | } | ||
297 | |||
298 | static ssize_t ad774x_store_vt_setup(struct device *dev, | ||
299 | struct device_attribute *attr, | ||
300 | const char *buf, | ||
301 | size_t len) | ||
302 | { | ||
303 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
304 | struct ad774x_chip_info *chip = iio_priv(dev_info); | ||
305 | unsigned long data; | ||
306 | int ret; | ||
307 | |||
308 | ret = strict_strtoul(buf, 10, &data); | ||
309 | |||
310 | if ((!ret) && (data < 0x100)) { | ||
311 | ad774x_i2c_write(chip, AD774X_VT_SETUP, data); | ||
312 | chip->vt_setup = data; | ||
313 | return len; | ||
314 | } | ||
315 | |||
316 | return -EINVAL; | ||
317 | } | ||
318 | |||
319 | static IIO_DEV_ATTR_VT_SETUP(S_IRUGO | S_IWUSR, | ||
320 | ad774x_show_vt_setup, | ||
321 | ad774x_store_vt_setup); | ||
322 | |||
323 | static ssize_t ad774x_show_exec_setup(struct device *dev, | ||
324 | struct device_attribute *attr, | ||
325 | char *buf) | ||
326 | { | ||
327 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
328 | struct ad774x_chip_info *chip = iio_priv(dev_info); | ||
329 | |||
330 | return sprintf(buf, "0x%02x\n", chip->exec_setup); | ||
331 | } | ||
332 | |||
333 | static ssize_t ad774x_store_exec_setup(struct device *dev, | ||
334 | struct device_attribute *attr, | ||
335 | const char *buf, | ||
336 | size_t len) | ||
337 | { | ||
338 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
339 | struct ad774x_chip_info *chip = iio_priv(dev_info); | ||
340 | unsigned long data; | ||
341 | int ret; | ||
342 | |||
343 | ret = strict_strtoul(buf, 10, &data); | ||
344 | |||
345 | if ((!ret) && (data < 0x100)) { | ||
346 | ad774x_i2c_write(chip, AD774X_EXEC_SETUP, data); | ||
347 | chip->exec_setup = data; | ||
348 | return len; | ||
349 | } | ||
350 | |||
351 | return -EINVAL; | ||
352 | } | ||
353 | |||
354 | static IIO_DEV_ATTR_EXEC_SETUP(S_IRUGO | S_IWUSR, | ||
355 | ad774x_show_exec_setup, | ||
356 | ad774x_store_exec_setup); | ||
357 | |||
358 | static ssize_t ad774x_show_volt_gain(struct device *dev, | ||
359 | struct device_attribute *attr, | ||
360 | char *buf) | ||
361 | { | ||
362 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
363 | struct ad774x_chip_info *chip = iio_priv(dev_info); | ||
364 | |||
365 | return sprintf(buf, "%d\n", chip->volt_gain); | ||
366 | } | ||
367 | |||
368 | static ssize_t ad774x_store_volt_gain(struct device *dev, | ||
369 | struct device_attribute *attr, | ||
370 | const char *buf, | ||
371 | size_t len) | ||
372 | { | ||
373 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
374 | struct ad774x_chip_info *chip = iio_priv(dev_info); | ||
375 | unsigned long data; | ||
376 | int ret; | ||
377 | |||
378 | ret = strict_strtoul(buf, 10, &data); | ||
379 | |||
380 | if ((!ret) && (data < 0x10000)) { | ||
381 | ad774x_i2c_write(chip, AD774X_VOLT_GAINH, data >> 8); | ||
382 | ad774x_i2c_write(chip, AD774X_VOLT_GAINL, data); | ||
383 | chip->volt_gain = data; | ||
384 | return len; | ||
385 | } | ||
386 | |||
387 | return -EINVAL; | ||
388 | } | ||
389 | |||
390 | static IIO_DEV_ATTR_VOLT_GAIN(S_IRUGO | S_IWUSR, | ||
391 | ad774x_show_volt_gain, | ||
392 | ad774x_store_volt_gain); | ||
393 | |||
394 | static ssize_t ad774x_show_cap_data(struct device *dev, | ||
395 | struct device_attribute *attr, | ||
396 | char *buf) | ||
397 | { | ||
398 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
399 | struct ad774x_chip_info *chip = iio_priv(dev_info); | ||
400 | unsigned long data; | ||
401 | char tmp[3]; | ||
402 | |||
403 | ad774x_i2c_read(chip, AD774X_CAP_DATA_HIGH, tmp, 3); | ||
404 | data = ((int)tmp[0] << 16) | ((int)tmp[1] << 8) | (int)tmp[2]; | ||
405 | |||
406 | return sprintf(buf, "%ld\n", data); | ||
407 | } | ||
408 | |||
409 | static IIO_DEV_ATTR_CAP_DATA(ad774x_show_cap_data); | ||
410 | |||
411 | static ssize_t ad774x_show_vt_data(struct device *dev, | ||
412 | struct device_attribute *attr, | ||
413 | char *buf) | ||
414 | { | ||
415 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
416 | struct ad774x_chip_info *chip = iio_priv(dev_info); | ||
417 | unsigned long data; | ||
418 | char tmp[3]; | ||
419 | |||
420 | ad774x_i2c_read(chip, AD774X_VT_DATA_HIGH, tmp, 3); | ||
421 | data = ((int)tmp[0] << 16) | ((int)tmp[1] << 8) | (int)tmp[2]; | ||
422 | |||
423 | return sprintf(buf, "%ld\n", data); | ||
424 | } | ||
425 | |||
426 | static IIO_DEV_ATTR_VT_DATA(ad774x_show_vt_data); | ||
427 | |||
428 | static ssize_t ad774x_show_cap_offs(struct device *dev, | ||
429 | struct device_attribute *attr, | ||
430 | char *buf) | ||
431 | { | ||
432 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
433 | struct ad774x_chip_info *chip = iio_priv(dev_info); | ||
434 | |||
435 | return sprintf(buf, "%d\n", chip->cap_offs); | ||
436 | } | ||
437 | |||
438 | static ssize_t ad774x_store_cap_offs(struct device *dev, | ||
439 | struct device_attribute *attr, | ||
440 | const char *buf, | ||
441 | size_t len) | ||
442 | { | ||
443 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
444 | struct ad774x_chip_info *chip = iio_priv(dev_info); | ||
445 | unsigned long data; | ||
446 | int ret; | ||
447 | |||
448 | ret = strict_strtoul(buf, 10, &data); | ||
449 | |||
450 | if ((!ret) && (data < 0x10000)) { | ||
451 | ad774x_i2c_write(chip, AD774X_CAP_OFFH, data >> 8); | ||
452 | ad774x_i2c_write(chip, AD774X_CAP_OFFL, data); | ||
453 | chip->cap_offs = data; | ||
454 | return len; | ||
455 | } | ||
456 | |||
457 | return -EINVAL; | ||
458 | } | ||
459 | |||
460 | static IIO_DEV_ATTR_CAP_OFFS(S_IRUGO | S_IWUSR, | ||
461 | ad774x_show_cap_offs, | ||
462 | ad774x_store_cap_offs); | ||
463 | |||
464 | static ssize_t ad774x_show_cap_gain(struct device *dev, | ||
465 | struct device_attribute *attr, | ||
466 | char *buf) | ||
467 | { | ||
468 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
469 | struct ad774x_chip_info *chip = iio_priv(dev_info); | ||
470 | |||
471 | return sprintf(buf, "%d\n", chip->cap_gain); | ||
472 | } | ||
473 | |||
474 | static ssize_t ad774x_store_cap_gain(struct device *dev, | ||
475 | struct device_attribute *attr, | ||
476 | const char *buf, | ||
477 | size_t len) | ||
478 | { | ||
479 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
480 | struct ad774x_chip_info *chip = iio_priv(dev_info); | ||
481 | unsigned long data; | ||
482 | int ret; | ||
483 | |||
484 | ret = strict_strtoul(buf, 10, &data); | ||
485 | |||
486 | if ((!ret) && (data < 0x10000)) { | ||
487 | ad774x_i2c_write(chip, AD774X_CAP_GAINH, data >> 8); | ||
488 | ad774x_i2c_write(chip, AD774X_CAP_GAINL, data); | ||
489 | chip->cap_gain = data; | ||
490 | return len; | ||
491 | } | ||
492 | |||
493 | return -EINVAL; | ||
494 | } | ||
495 | |||
496 | static IIO_DEV_ATTR_CAP_GAIN(S_IRUGO | S_IWUSR, | ||
497 | ad774x_show_cap_gain, | ||
498 | ad774x_store_cap_gain); | ||
499 | |||
500 | static struct attribute *ad774x_attributes[] = { | ||
501 | &iio_dev_attr_available_conversion_modes.dev_attr.attr, | ||
502 | &iio_dev_attr_conversion_mode.dev_attr.attr, | ||
503 | &iio_dev_attr_cap_setup.dev_attr.attr, | ||
504 | &iio_dev_attr_in0_setup.dev_attr.attr, | ||
505 | &iio_dev_attr_exec_setup.dev_attr.attr, | ||
506 | &iio_dev_attr_cap_offs.dev_attr.attr, | ||
507 | &iio_dev_attr_cap_gain.dev_attr.attr, | ||
508 | &iio_dev_attr_in0_gain.dev_attr.attr, | ||
509 | &iio_dev_attr_in0_raw.dev_attr.attr, | ||
510 | &iio_dev_attr_cap0_raw.dev_attr.attr, | ||
511 | &iio_dev_attr_capdac0_raw.dev_attr.attr, | ||
512 | &iio_dev_attr_capdac1_raw.dev_attr.attr, | ||
513 | NULL, | ||
514 | }; | ||
515 | |||
516 | static const struct attribute_group ad774x_attribute_group = { | ||
517 | .attrs = ad774x_attributes, | ||
518 | }; | ||
519 | |||
520 | /* | ||
521 | * data ready events | ||
522 | */ | ||
523 | |||
524 | #define IIO_EVENT_CODE_CAP_RDY 0 | ||
525 | #define IIO_EVENT_CODE_VT_RDY 1 | ||
526 | |||
527 | #define IIO_EVENT_ATTR_CAP_RDY_SH(_evlist, _show, _store, _mask) \ | ||
528 | IIO_EVENT_ATTR_SH(cap_rdy, _evlist, _show, _store, _mask) | ||
529 | |||
530 | #define IIO_EVENT_ATTR_VT_RDY_SH(_evlist, _show, _store, _mask) \ | ||
531 | IIO_EVENT_ATTR_SH(vt_rdy, _evlist, _show, _store, _mask) | ||
532 | |||
533 | static irqreturn_t ad774x_event_handler(int irq, void *private) | ||
534 | { | ||
535 | struct iio_dev *indio_dev = private; | ||
536 | struct ad774x_chip_info *chip = iio_priv(indio_dev); | ||
537 | u8 int_status; | ||
538 | |||
539 | ad774x_i2c_read(chip, AD774X_STATUS, &int_status, 1); | ||
540 | |||
541 | if (int_status & AD774X_STATUS_RDYCAP) | ||
542 | iio_push_event(indio_dev, 0, | ||
543 | IIO_EVENT_CODE_CAP_RDY, | ||
544 | iio_get_time_ns()); | ||
545 | |||
546 | if (int_status & AD774X_STATUS_RDYVT) | ||
547 | iio_push_event(indio_dev, 0, | ||
548 | IIO_EVENT_CODE_VT_RDY, | ||
549 | iio_get_time_ns()); | ||
550 | |||
551 | return IRQ_HANDLED; | ||
552 | } | ||
553 | |||
554 | static IIO_CONST_ATTR(cap_rdy_en, "1"); | ||
555 | static IIO_CONST_ATTR(vt_rdy_en, "1"); | ||
556 | |||
557 | static struct attribute *ad774x_event_attributes[] = { | ||
558 | &iio_const_attr_cap_rdy_en.dev_attr.attr, | ||
559 | &iio_const_attr_vt_rdy_en.dev_attr.attr, | ||
560 | NULL, | ||
561 | }; | ||
562 | |||
563 | static struct attribute_group ad774x_event_attribute_group = { | ||
564 | .attrs = ad774x_event_attributes, | ||
565 | }; | ||
566 | |||
567 | static const struct iio_info ad774x_info = { | ||
568 | .attrs = &ad774x_event_attribute_group, | ||
569 | .event_attrs = &ad774x_event_attribute_group, | ||
570 | .num_interrupt_lines = 1, | ||
571 | .driver_module = THIS_MODULE, | ||
572 | }; | ||
573 | /* | ||
574 | * device probe and remove | ||
575 | */ | ||
576 | |||
577 | static int __devinit ad774x_probe(struct i2c_client *client, | ||
578 | const struct i2c_device_id *id) | ||
579 | { | ||
580 | int ret = 0, regdone = 0; | ||
581 | struct ad774x_chip_info *chip; | ||
582 | struct iio_dev *indio_dev; | ||
583 | |||
584 | indio_dev = iio_allocate_device(sizeof(*chip)); | ||
585 | if (indio_dev == NULL) { | ||
586 | ret = -ENOMEM; | ||
587 | goto error_ret; | ||
588 | } | ||
589 | chip = iio_priv(indio_dev); | ||
590 | /* this is only used for device removal purposes */ | ||
591 | i2c_set_clientdata(client, indio_dev); | ||
592 | |||
593 | chip->client = client; | ||
594 | |||
595 | /* Establish that the iio_dev is a child of the i2c device */ | ||
596 | indio_dev->name = id->name; | ||
597 | indio_dev->dev.parent = &client->dev; | ||
598 | indio_dev->info = &ad774x_info; | ||
599 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
600 | |||
601 | ret = iio_device_register(indio_dev); | ||
602 | if (ret) | ||
603 | goto error_free_dev; | ||
604 | regdone = 1; | ||
605 | |||
606 | if (client->irq) { | ||
607 | ret = request_threaded_irq(client->irq, | ||
608 | NULL, | ||
609 | &ad774x_event_handler, | ||
610 | IRQF_TRIGGER_FALLING, | ||
611 | "ad774x", | ||
612 | indio_dev); | ||
613 | if (ret) | ||
614 | goto error_free_dev; | ||
615 | } | ||
616 | |||
617 | dev_err(&client->dev, "%s capacitive sensor registered, irq: %d\n", id->name, client->irq); | ||
618 | |||
619 | return 0; | ||
620 | |||
621 | error_free_dev: | ||
622 | if (regdone) | ||
623 | free_irq(client->irq, indio_dev); | ||
624 | else | ||
625 | iio_free_device(indio_dev); | ||
626 | error_ret: | ||
627 | return ret; | ||
628 | } | ||
629 | |||
630 | static int __devexit ad774x_remove(struct i2c_client *client) | ||
631 | { | ||
632 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | ||
633 | |||
634 | if (client->irq) | ||
635 | free_irq(client->irq, indio_dev); | ||
636 | iio_device_unregister(indio_dev); | ||
637 | |||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | static const struct i2c_device_id ad774x_id[] = { | ||
642 | { "ad7745", 0 }, | ||
643 | { "ad7746", 0 }, | ||
644 | { "ad7747", 0 }, | ||
645 | {} | ||
646 | }; | ||
647 | |||
648 | MODULE_DEVICE_TABLE(i2c, ad774x_id); | ||
649 | |||
650 | static struct i2c_driver ad774x_driver = { | ||
651 | .driver = { | ||
652 | .name = "ad774x", | ||
653 | }, | ||
654 | .probe = ad774x_probe, | ||
655 | .remove = __devexit_p(ad774x_remove), | ||
656 | .id_table = ad774x_id, | ||
657 | }; | ||
658 | |||
659 | static __init int ad774x_init(void) | ||
660 | { | ||
661 | return i2c_add_driver(&ad774x_driver); | ||
662 | } | ||
663 | |||
664 | static __exit void ad774x_exit(void) | ||
665 | { | ||
666 | i2c_del_driver(&ad774x_driver); | ||
667 | } | ||
668 | |||
669 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | ||
670 | MODULE_DESCRIPTION("Analog Devices ad7745/6/7 capacitive sensor driver"); | ||
671 | MODULE_LICENSE("GPL v2"); | ||
672 | |||
673 | module_init(ad774x_init); | ||
674 | module_exit(ad774x_exit); | ||
diff --git a/drivers/staging/iio/adc/ad7793.c b/drivers/staging/iio/adc/ad7793.c new file mode 100644 index 00000000000..90f6c039d6c --- /dev/null +++ b/drivers/staging/iio/adc/ad7793.c | |||
@@ -0,0 +1,987 @@ | |||
1 | /* | ||
2 | * AD7792/AD7793 SPI ADC driver | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
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/delay.h> | ||
19 | |||
20 | #include "../iio.h" | ||
21 | #include "../sysfs.h" | ||
22 | #include "../ring_generic.h" | ||
23 | #include "../ring_sw.h" | ||
24 | #include "../trigger.h" | ||
25 | #include "adc.h" | ||
26 | |||
27 | #include "ad7793.h" | ||
28 | |||
29 | /* NOTE: | ||
30 | * The AD7792/AD7793 features a dual use data out ready DOUT/RDY output. | ||
31 | * In order to avoid contentions on the SPI bus, it's therefore necessary | ||
32 | * to use spi bus locking. | ||
33 | * | ||
34 | * The DOUT/RDY output must also be wired to an interrupt capable GPIO. | ||
35 | */ | ||
36 | |||
37 | struct ad7793_chip_info { | ||
38 | struct iio_chan_spec channel[7]; | ||
39 | }; | ||
40 | |||
41 | struct ad7793_state { | ||
42 | struct spi_device *spi; | ||
43 | struct iio_trigger *trig; | ||
44 | const struct ad7793_chip_info *chip_info; | ||
45 | struct regulator *reg; | ||
46 | struct ad7793_platform_data *pdata; | ||
47 | wait_queue_head_t wq_data_avail; | ||
48 | bool done; | ||
49 | bool irq_dis; | ||
50 | u16 int_vref_mv; | ||
51 | u16 mode; | ||
52 | u16 conf; | ||
53 | u32 scale_avail[8][2]; | ||
54 | u32 available_scan_masks[7]; | ||
55 | /* | ||
56 | * DMA (thus cache coherency maintenance) requires the | ||
57 | * transfer buffers to live in their own cache lines. | ||
58 | */ | ||
59 | u8 data[4] ____cacheline_aligned; | ||
60 | }; | ||
61 | |||
62 | enum ad7793_supported_device_ids { | ||
63 | ID_AD7792, | ||
64 | ID_AD7793, | ||
65 | }; | ||
66 | |||
67 | static int __ad7793_write_reg(struct ad7793_state *st, bool locked, | ||
68 | bool cs_change, unsigned char reg, | ||
69 | unsigned size, unsigned val) | ||
70 | { | ||
71 | u8 *data = st->data; | ||
72 | struct spi_transfer t = { | ||
73 | .tx_buf = data, | ||
74 | .len = size + 1, | ||
75 | .cs_change = cs_change, | ||
76 | }; | ||
77 | struct spi_message m; | ||
78 | |||
79 | data[0] = AD7793_COMM_WRITE | AD7793_COMM_ADDR(reg); | ||
80 | |||
81 | switch (size) { | ||
82 | case 3: | ||
83 | data[1] = val >> 16; | ||
84 | data[2] = val >> 8; | ||
85 | data[3] = val; | ||
86 | break; | ||
87 | case 2: | ||
88 | data[1] = val >> 8; | ||
89 | data[2] = val; | ||
90 | break; | ||
91 | case 1: | ||
92 | data[1] = val; | ||
93 | break; | ||
94 | default: | ||
95 | return -EINVAL; | ||
96 | } | ||
97 | |||
98 | spi_message_init(&m); | ||
99 | spi_message_add_tail(&t, &m); | ||
100 | |||
101 | if (locked) | ||
102 | return spi_sync_locked(st->spi, &m); | ||
103 | else | ||
104 | return spi_sync(st->spi, &m); | ||
105 | } | ||
106 | |||
107 | static int ad7793_write_reg(struct ad7793_state *st, | ||
108 | unsigned reg, unsigned size, unsigned val) | ||
109 | { | ||
110 | return __ad7793_write_reg(st, false, false, reg, size, val); | ||
111 | } | ||
112 | |||
113 | static int __ad7793_read_reg(struct ad7793_state *st, bool locked, | ||
114 | bool cs_change, unsigned char reg, | ||
115 | int *val, unsigned size) | ||
116 | { | ||
117 | u8 *data = st->data; | ||
118 | int ret; | ||
119 | struct spi_transfer t[] = { | ||
120 | { | ||
121 | .tx_buf = data, | ||
122 | .len = 1, | ||
123 | }, { | ||
124 | .rx_buf = data, | ||
125 | .len = size, | ||
126 | .cs_change = cs_change, | ||
127 | }, | ||
128 | }; | ||
129 | struct spi_message m; | ||
130 | |||
131 | data[0] = AD7793_COMM_READ | AD7793_COMM_ADDR(reg); | ||
132 | |||
133 | spi_message_init(&m); | ||
134 | spi_message_add_tail(&t[0], &m); | ||
135 | spi_message_add_tail(&t[1], &m); | ||
136 | |||
137 | if (locked) | ||
138 | ret = spi_sync_locked(st->spi, &m); | ||
139 | else | ||
140 | ret = spi_sync(st->spi, &m); | ||
141 | |||
142 | if (ret < 0) | ||
143 | return ret; | ||
144 | |||
145 | switch (size) { | ||
146 | case 3: | ||
147 | *val = data[0] << 16 | data[1] << 8 | data[2]; | ||
148 | break; | ||
149 | case 2: | ||
150 | *val = data[0] << 8 | data[1]; | ||
151 | break; | ||
152 | case 1: | ||
153 | *val = data[0]; | ||
154 | break; | ||
155 | default: | ||
156 | return -EINVAL; | ||
157 | } | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static int ad7793_read_reg(struct ad7793_state *st, | ||
163 | unsigned reg, int *val, unsigned size) | ||
164 | { | ||
165 | return __ad7793_read_reg(st, 0, 0, reg, val, size); | ||
166 | } | ||
167 | |||
168 | static int ad7793_read(struct ad7793_state *st, unsigned ch, | ||
169 | unsigned len, int *val) | ||
170 | { | ||
171 | int ret; | ||
172 | st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) | AD7793_CONF_CHAN(ch); | ||
173 | st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | | ||
174 | AD7793_MODE_SEL(AD7793_MODE_SINGLE); | ||
175 | |||
176 | ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf); | ||
177 | |||
178 | spi_bus_lock(st->spi->master); | ||
179 | st->done = false; | ||
180 | |||
181 | ret = __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE, | ||
182 | sizeof(st->mode), st->mode); | ||
183 | if (ret < 0) | ||
184 | goto out; | ||
185 | |||
186 | st->irq_dis = false; | ||
187 | enable_irq(st->spi->irq); | ||
188 | wait_event_interruptible(st->wq_data_avail, st->done); | ||
189 | |||
190 | ret = __ad7793_read_reg(st, 1, 0, AD7793_REG_DATA, val, len); | ||
191 | out: | ||
192 | spi_bus_unlock(st->spi->master); | ||
193 | |||
194 | return ret; | ||
195 | } | ||
196 | |||
197 | static int ad7793_calibrate(struct ad7793_state *st, unsigned mode, unsigned ch) | ||
198 | { | ||
199 | int ret; | ||
200 | |||
201 | st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) | AD7793_CONF_CHAN(ch); | ||
202 | st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | AD7793_MODE_SEL(mode); | ||
203 | |||
204 | ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf); | ||
205 | |||
206 | spi_bus_lock(st->spi->master); | ||
207 | st->done = false; | ||
208 | |||
209 | ret = __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE, | ||
210 | sizeof(st->mode), st->mode); | ||
211 | if (ret < 0) | ||
212 | goto out; | ||
213 | |||
214 | st->irq_dis = false; | ||
215 | enable_irq(st->spi->irq); | ||
216 | wait_event_interruptible(st->wq_data_avail, st->done); | ||
217 | |||
218 | st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | | ||
219 | AD7793_MODE_SEL(AD7793_MODE_IDLE); | ||
220 | |||
221 | ret = __ad7793_write_reg(st, 1, 0, AD7793_REG_MODE, | ||
222 | sizeof(st->mode), st->mode); | ||
223 | out: | ||
224 | spi_bus_unlock(st->spi->master); | ||
225 | |||
226 | return ret; | ||
227 | } | ||
228 | |||
229 | static const u8 ad7793_calib_arr[6][2] = { | ||
230 | {AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN1P_AIN1M}, | ||
231 | {AD7793_MODE_CAL_INT_FULL, AD7793_CH_AIN1P_AIN1M}, | ||
232 | {AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN2P_AIN2M}, | ||
233 | {AD7793_MODE_CAL_INT_FULL, AD7793_CH_AIN2P_AIN2M}, | ||
234 | {AD7793_MODE_CAL_INT_ZERO, AD7793_CH_AIN3P_AIN3M}, | ||
235 | {AD7793_MODE_CAL_INT_FULL, AD7793_CH_AIN3P_AIN3M} | ||
236 | }; | ||
237 | |||
238 | static int ad7793_calibrate_all(struct ad7793_state *st) | ||
239 | { | ||
240 | int i, ret; | ||
241 | |||
242 | for (i = 0; i < ARRAY_SIZE(ad7793_calib_arr); i++) { | ||
243 | ret = ad7793_calibrate(st, ad7793_calib_arr[i][0], | ||
244 | ad7793_calib_arr[i][1]); | ||
245 | if (ret) | ||
246 | goto out; | ||
247 | } | ||
248 | |||
249 | return 0; | ||
250 | out: | ||
251 | dev_err(&st->spi->dev, "Calibration failed\n"); | ||
252 | return ret; | ||
253 | } | ||
254 | |||
255 | static int ad7793_setup(struct ad7793_state *st) | ||
256 | { | ||
257 | int i, ret = -1; | ||
258 | unsigned long long scale_uv; | ||
259 | u32 id; | ||
260 | |||
261 | /* reset the serial interface */ | ||
262 | ret = spi_write(st->spi, (u8 *)&ret, sizeof(ret)); | ||
263 | if (ret < 0) | ||
264 | goto out; | ||
265 | msleep(1); /* Wait for at least 500us */ | ||
266 | |||
267 | /* write/read test for device presence */ | ||
268 | ret = ad7793_read_reg(st, AD7793_REG_ID, &id, 1); | ||
269 | if (ret) | ||
270 | goto out; | ||
271 | |||
272 | id &= AD7793_ID_MASK; | ||
273 | |||
274 | if (!((id == AD7792_ID) || (id == AD7793_ID))) { | ||
275 | dev_err(&st->spi->dev, "device ID query failed\n"); | ||
276 | goto out; | ||
277 | } | ||
278 | |||
279 | st->mode = (st->pdata->mode & ~AD7793_MODE_SEL(-1)) | | ||
280 | AD7793_MODE_SEL(AD7793_MODE_IDLE); | ||
281 | st->conf = st->pdata->conf & ~AD7793_CONF_CHAN(-1); | ||
282 | |||
283 | ret = ad7793_write_reg(st, AD7793_REG_MODE, sizeof(st->mode), st->mode); | ||
284 | if (ret) | ||
285 | goto out; | ||
286 | |||
287 | ret = ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf); | ||
288 | if (ret) | ||
289 | goto out; | ||
290 | |||
291 | ret = ad7793_write_reg(st, AD7793_REG_IO, | ||
292 | sizeof(st->pdata->io), st->pdata->io); | ||
293 | if (ret) | ||
294 | goto out; | ||
295 | |||
296 | ret = ad7793_calibrate_all(st); | ||
297 | if (ret) | ||
298 | goto out; | ||
299 | |||
300 | /* Populate available ADC input ranges */ | ||
301 | for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) { | ||
302 | scale_uv = ((u64)st->int_vref_mv * 100000000) | ||
303 | >> (st->chip_info->channel[0].scan_type.realbits - | ||
304 | (!!(st->conf & AD7793_CONF_UNIPOLAR) ? 0 : 1)); | ||
305 | scale_uv >>= i; | ||
306 | |||
307 | st->scale_avail[i][1] = do_div(scale_uv, 100000000) * 10; | ||
308 | st->scale_avail[i][0] = scale_uv; | ||
309 | } | ||
310 | |||
311 | return 0; | ||
312 | out: | ||
313 | dev_err(&st->spi->dev, "setup failed\n"); | ||
314 | return ret; | ||
315 | } | ||
316 | |||
317 | static int ad7793_scan_from_ring(struct ad7793_state *st, unsigned ch, int *val) | ||
318 | { | ||
319 | struct iio_ring_buffer *ring = iio_priv_to_dev(st)->ring; | ||
320 | int ret; | ||
321 | s64 dat64[2]; | ||
322 | u32 *dat32 = (u32 *)dat64; | ||
323 | |||
324 | if (!(ring->scan_mask & (1 << ch))) | ||
325 | return -EBUSY; | ||
326 | |||
327 | ret = ring->access->read_last(ring, (u8 *) &dat64); | ||
328 | if (ret) | ||
329 | return ret; | ||
330 | |||
331 | *val = *dat32; | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static int ad7793_ring_preenable(struct iio_dev *indio_dev) | ||
337 | { | ||
338 | struct ad7793_state *st = iio_priv(indio_dev); | ||
339 | struct iio_ring_buffer *ring = indio_dev->ring; | ||
340 | size_t d_size; | ||
341 | unsigned channel; | ||
342 | |||
343 | if (!ring->scan_count) | ||
344 | return -EINVAL; | ||
345 | |||
346 | channel = __ffs(ring->scan_mask); | ||
347 | |||
348 | d_size = ring->scan_count * | ||
349 | indio_dev->channels[0].scan_type.storagebits / 8; | ||
350 | |||
351 | if (ring->scan_timestamp) { | ||
352 | d_size += sizeof(s64); | ||
353 | |||
354 | if (d_size % sizeof(s64)) | ||
355 | d_size += sizeof(s64) - (d_size % sizeof(s64)); | ||
356 | } | ||
357 | |||
358 | if (indio_dev->ring->access->set_bytes_per_datum) | ||
359 | indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring, | ||
360 | d_size); | ||
361 | |||
362 | st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | | ||
363 | AD7793_MODE_SEL(AD7793_MODE_CONT); | ||
364 | st->conf = (st->conf & ~AD7793_CONF_CHAN(-1)) | | ||
365 | AD7793_CONF_CHAN(indio_dev->channels[channel].address); | ||
366 | |||
367 | ad7793_write_reg(st, AD7793_REG_CONF, sizeof(st->conf), st->conf); | ||
368 | |||
369 | spi_bus_lock(st->spi->master); | ||
370 | __ad7793_write_reg(st, 1, 1, AD7793_REG_MODE, | ||
371 | sizeof(st->mode), st->mode); | ||
372 | |||
373 | st->irq_dis = false; | ||
374 | enable_irq(st->spi->irq); | ||
375 | |||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | static int ad7793_ring_postdisable(struct iio_dev *indio_dev) | ||
380 | { | ||
381 | struct ad7793_state *st = iio_priv(indio_dev); | ||
382 | |||
383 | st->mode = (st->mode & ~AD7793_MODE_SEL(-1)) | | ||
384 | AD7793_MODE_SEL(AD7793_MODE_IDLE); | ||
385 | |||
386 | st->done = false; | ||
387 | wait_event_interruptible(st->wq_data_avail, st->done); | ||
388 | |||
389 | if (!st->irq_dis) | ||
390 | disable_irq_nosync(st->spi->irq); | ||
391 | |||
392 | __ad7793_write_reg(st, 1, 0, AD7793_REG_MODE, | ||
393 | sizeof(st->mode), st->mode); | ||
394 | |||
395 | return spi_bus_unlock(st->spi->master); | ||
396 | } | ||
397 | |||
398 | /** | ||
399 | * ad7793_trigger_handler() bh of trigger launched polling to ring buffer | ||
400 | **/ | ||
401 | |||
402 | static irqreturn_t ad7793_trigger_handler(int irq, void *p) | ||
403 | { | ||
404 | struct iio_poll_func *pf = p; | ||
405 | struct iio_dev *indio_dev = pf->private_data; | ||
406 | struct iio_ring_buffer *ring = indio_dev->ring; | ||
407 | struct ad7793_state *st = iio_priv(indio_dev); | ||
408 | s64 dat64[2]; | ||
409 | s32 *dat32 = (s32 *)dat64; | ||
410 | |||
411 | if (ring->scan_count) | ||
412 | __ad7793_read_reg(st, 1, 1, AD7793_REG_DATA, | ||
413 | dat32, | ||
414 | indio_dev->channels[0].scan_type.realbits/8); | ||
415 | |||
416 | /* Guaranteed to be aligned with 8 byte boundary */ | ||
417 | if (ring->scan_timestamp) | ||
418 | dat64[1] = pf->timestamp; | ||
419 | |||
420 | ring->access->store_to(ring, (u8 *)dat64, pf->timestamp); | ||
421 | |||
422 | iio_trigger_notify_done(indio_dev->trig); | ||
423 | st->irq_dis = false; | ||
424 | enable_irq(st->spi->irq); | ||
425 | |||
426 | return IRQ_HANDLED; | ||
427 | } | ||
428 | |||
429 | static const struct iio_ring_setup_ops ad7793_ring_setup_ops = { | ||
430 | .preenable = &ad7793_ring_preenable, | ||
431 | .postenable = &iio_triggered_ring_postenable, | ||
432 | .predisable = &iio_triggered_ring_predisable, | ||
433 | .postdisable = &ad7793_ring_postdisable, | ||
434 | }; | ||
435 | |||
436 | static int ad7793_register_ring_funcs_and_init(struct iio_dev *indio_dev) | ||
437 | { | ||
438 | int ret; | ||
439 | |||
440 | indio_dev->ring = iio_sw_rb_allocate(indio_dev); | ||
441 | if (!indio_dev->ring) { | ||
442 | ret = -ENOMEM; | ||
443 | goto error_ret; | ||
444 | } | ||
445 | /* Effectively select the ring buffer implementation */ | ||
446 | indio_dev->ring->access = &ring_sw_access_funcs; | ||
447 | indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, | ||
448 | &ad7793_trigger_handler, | ||
449 | IRQF_ONESHOT, | ||
450 | indio_dev, | ||
451 | "ad7793_consumer%d", | ||
452 | indio_dev->id); | ||
453 | if (indio_dev->pollfunc == NULL) { | ||
454 | ret = -ENOMEM; | ||
455 | goto error_deallocate_sw_rb; | ||
456 | } | ||
457 | |||
458 | /* Ring buffer functions - here trigger setup related */ | ||
459 | indio_dev->ring->setup_ops = &ad7793_ring_setup_ops; | ||
460 | |||
461 | /* Flag that polled ring buffering is possible */ | ||
462 | indio_dev->modes |= INDIO_RING_TRIGGERED; | ||
463 | return 0; | ||
464 | |||
465 | error_deallocate_sw_rb: | ||
466 | iio_sw_rb_free(indio_dev->ring); | ||
467 | error_ret: | ||
468 | return ret; | ||
469 | } | ||
470 | |||
471 | static void ad7793_ring_cleanup(struct iio_dev *indio_dev) | ||
472 | { | ||
473 | /* ensure that the trigger has been detached */ | ||
474 | if (indio_dev->trig) { | ||
475 | iio_put_trigger(indio_dev->trig); | ||
476 | iio_trigger_dettach_poll_func(indio_dev->trig, | ||
477 | indio_dev->pollfunc); | ||
478 | } | ||
479 | iio_dealloc_pollfunc(indio_dev->pollfunc); | ||
480 | iio_sw_rb_free(indio_dev->ring); | ||
481 | } | ||
482 | |||
483 | /** | ||
484 | * ad7793_data_rdy_trig_poll() the event handler for the data rdy trig | ||
485 | **/ | ||
486 | static irqreturn_t ad7793_data_rdy_trig_poll(int irq, void *private) | ||
487 | { | ||
488 | struct ad7793_state *st = iio_priv(private); | ||
489 | |||
490 | st->done = true; | ||
491 | wake_up_interruptible(&st->wq_data_avail); | ||
492 | disable_irq_nosync(irq); | ||
493 | st->irq_dis = true; | ||
494 | iio_trigger_poll(st->trig, iio_get_time_ns()); | ||
495 | |||
496 | return IRQ_HANDLED; | ||
497 | } | ||
498 | |||
499 | static int ad7793_probe_trigger(struct iio_dev *indio_dev) | ||
500 | { | ||
501 | struct ad7793_state *st = iio_priv(indio_dev); | ||
502 | int ret; | ||
503 | |||
504 | st->trig = iio_allocate_trigger("%s-dev%d", | ||
505 | spi_get_device_id(st->spi)->name, | ||
506 | indio_dev->id); | ||
507 | if (st->trig == NULL) { | ||
508 | ret = -ENOMEM; | ||
509 | goto error_ret; | ||
510 | } | ||
511 | |||
512 | ret = request_irq(st->spi->irq, | ||
513 | ad7793_data_rdy_trig_poll, | ||
514 | IRQF_TRIGGER_LOW, | ||
515 | spi_get_device_id(st->spi)->name, | ||
516 | indio_dev); | ||
517 | if (ret) | ||
518 | goto error_free_trig; | ||
519 | |||
520 | disable_irq_nosync(st->spi->irq); | ||
521 | st->irq_dis = true; | ||
522 | st->trig->dev.parent = &st->spi->dev; | ||
523 | st->trig->owner = THIS_MODULE; | ||
524 | st->trig->private_data = indio_dev; | ||
525 | |||
526 | ret = iio_trigger_register(st->trig); | ||
527 | |||
528 | /* select default trigger */ | ||
529 | indio_dev->trig = st->trig; | ||
530 | if (ret) | ||
531 | goto error_free_irq; | ||
532 | |||
533 | return 0; | ||
534 | |||
535 | error_free_irq: | ||
536 | free_irq(st->spi->irq, indio_dev); | ||
537 | error_free_trig: | ||
538 | iio_free_trigger(st->trig); | ||
539 | error_ret: | ||
540 | return ret; | ||
541 | } | ||
542 | |||
543 | static void ad7793_remove_trigger(struct iio_dev *indio_dev) | ||
544 | { | ||
545 | struct ad7793_state *st = iio_priv(indio_dev); | ||
546 | |||
547 | iio_trigger_unregister(st->trig); | ||
548 | free_irq(st->spi->irq, indio_dev); | ||
549 | iio_free_trigger(st->trig); | ||
550 | } | ||
551 | |||
552 | static const u16 sample_freq_avail[16] = {0, 470, 242, 123, 62, 50, 39, 33, 19, | ||
553 | 17, 16, 12, 10, 8, 6, 4}; | ||
554 | |||
555 | static ssize_t ad7793_read_frequency(struct device *dev, | ||
556 | struct device_attribute *attr, | ||
557 | char *buf) | ||
558 | { | ||
559 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
560 | struct ad7793_state *st = iio_priv(indio_dev); | ||
561 | |||
562 | return sprintf(buf, "%d\n", | ||
563 | sample_freq_avail[AD7793_MODE_RATE(st->mode)]); | ||
564 | } | ||
565 | |||
566 | static ssize_t ad7793_write_frequency(struct device *dev, | ||
567 | struct device_attribute *attr, | ||
568 | const char *buf, | ||
569 | size_t len) | ||
570 | { | ||
571 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
572 | struct ad7793_state *st = iio_priv(indio_dev); | ||
573 | long lval; | ||
574 | int i, ret; | ||
575 | |||
576 | mutex_lock(&indio_dev->mlock); | ||
577 | if (iio_ring_enabled(indio_dev)) { | ||
578 | mutex_unlock(&indio_dev->mlock); | ||
579 | return -EBUSY; | ||
580 | } | ||
581 | mutex_unlock(&indio_dev->mlock); | ||
582 | |||
583 | ret = strict_strtol(buf, 10, &lval); | ||
584 | if (ret) | ||
585 | return ret; | ||
586 | |||
587 | ret = -EINVAL; | ||
588 | |||
589 | for (i = 0; i < ARRAY_SIZE(sample_freq_avail); i++) | ||
590 | if (lval == sample_freq_avail[i]) { | ||
591 | mutex_lock(&indio_dev->mlock); | ||
592 | st->mode &= ~AD7793_MODE_RATE(-1); | ||
593 | st->mode |= AD7793_MODE_RATE(i); | ||
594 | ad7793_write_reg(st, AD7793_REG_MODE, | ||
595 | sizeof(st->mode), st->mode); | ||
596 | mutex_unlock(&indio_dev->mlock); | ||
597 | ret = 0; | ||
598 | } | ||
599 | |||
600 | return ret ? ret : len; | ||
601 | } | ||
602 | |||
603 | static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO, | ||
604 | ad7793_read_frequency, | ||
605 | ad7793_write_frequency); | ||
606 | |||
607 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( | ||
608 | "470 242 123 62 50 39 33 19 17 16 12 10 8 6 4"); | ||
609 | |||
610 | static ssize_t ad7793_show_scale_available(struct device *dev, | ||
611 | struct device_attribute *attr, char *buf) | ||
612 | { | ||
613 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
614 | struct ad7793_state *st = iio_priv(indio_dev); | ||
615 | int i, len = 0; | ||
616 | |||
617 | for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) | ||
618 | len += sprintf(buf + len, "%d.%09u ", st->scale_avail[i][0], | ||
619 | st->scale_avail[i][1]); | ||
620 | |||
621 | len += sprintf(buf + len, "\n"); | ||
622 | |||
623 | return len; | ||
624 | } | ||
625 | |||
626 | static IIO_DEVICE_ATTR_NAMED(in_m_in_scale_available, in-in_scale_available, | ||
627 | S_IRUGO, ad7793_show_scale_available, NULL, 0); | ||
628 | |||
629 | static struct attribute *ad7793_attributes[] = { | ||
630 | &iio_dev_attr_sampling_frequency.dev_attr.attr, | ||
631 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, | ||
632 | &iio_dev_attr_in_m_in_scale_available.dev_attr.attr, | ||
633 | NULL | ||
634 | }; | ||
635 | |||
636 | static const struct attribute_group ad7793_attribute_group = { | ||
637 | .attrs = ad7793_attributes, | ||
638 | }; | ||
639 | |||
640 | static int ad7793_read_raw(struct iio_dev *indio_dev, | ||
641 | struct iio_chan_spec const *chan, | ||
642 | int *val, | ||
643 | int *val2, | ||
644 | long m) | ||
645 | { | ||
646 | struct ad7793_state *st = iio_priv(indio_dev); | ||
647 | int ret, smpl = 0; | ||
648 | unsigned long long scale_uv; | ||
649 | bool unipolar = !!(st->conf & AD7793_CONF_UNIPOLAR); | ||
650 | |||
651 | switch (m) { | ||
652 | case 0: | ||
653 | mutex_lock(&indio_dev->mlock); | ||
654 | if (iio_ring_enabled(indio_dev)) | ||
655 | ret = ad7793_scan_from_ring(st, | ||
656 | chan->scan_index, &smpl); | ||
657 | else | ||
658 | ret = ad7793_read(st, chan->address, | ||
659 | chan->scan_type.realbits / 8, &smpl); | ||
660 | mutex_unlock(&indio_dev->mlock); | ||
661 | |||
662 | if (ret < 0) | ||
663 | return ret; | ||
664 | |||
665 | *val = (smpl >> chan->scan_type.shift) & | ||
666 | ((1 << (chan->scan_type.realbits)) - 1); | ||
667 | |||
668 | if (!unipolar) | ||
669 | *val -= (1 << (chan->scan_type.realbits - 1)); | ||
670 | |||
671 | return IIO_VAL_INT; | ||
672 | |||
673 | case (1 << IIO_CHAN_INFO_SCALE_SHARED): | ||
674 | *val = st->scale_avail[(st->conf >> 8) & 0x7][0]; | ||
675 | *val2 = st->scale_avail[(st->conf >> 8) & 0x7][1]; | ||
676 | |||
677 | return IIO_VAL_INT_PLUS_NANO; | ||
678 | |||
679 | case (1 << IIO_CHAN_INFO_SCALE_SEPARATE): | ||
680 | switch (chan->type) { | ||
681 | case IIO_IN: | ||
682 | /* 1170mV / 2^23 * 6 */ | ||
683 | scale_uv = (1170ULL * 100000000ULL * 6ULL) | ||
684 | >> (chan->scan_type.realbits - | ||
685 | (unipolar ? 0 : 1)); | ||
686 | break; | ||
687 | case IIO_TEMP: | ||
688 | /* Always uses unity gain and internal ref */ | ||
689 | scale_uv = (2500ULL * 100000000ULL) | ||
690 | >> (chan->scan_type.realbits - | ||
691 | (unipolar ? 0 : 1)); | ||
692 | break; | ||
693 | default: | ||
694 | return -EINVAL; | ||
695 | } | ||
696 | |||
697 | *val2 = do_div(scale_uv, 100000000) * 10; | ||
698 | *val = scale_uv; | ||
699 | |||
700 | return IIO_VAL_INT_PLUS_NANO; | ||
701 | } | ||
702 | return -EINVAL; | ||
703 | } | ||
704 | |||
705 | static int ad7793_write_raw(struct iio_dev *indio_dev, | ||
706 | struct iio_chan_spec const *chan, | ||
707 | int val, | ||
708 | int val2, | ||
709 | long mask) | ||
710 | { | ||
711 | struct ad7793_state *st = iio_priv(indio_dev); | ||
712 | int ret, i; | ||
713 | unsigned int tmp; | ||
714 | |||
715 | mutex_lock(&indio_dev->mlock); | ||
716 | if (iio_ring_enabled(indio_dev)) { | ||
717 | mutex_unlock(&indio_dev->mlock); | ||
718 | return -EBUSY; | ||
719 | } | ||
720 | |||
721 | switch (mask) { | ||
722 | case (1 << IIO_CHAN_INFO_SCALE_SHARED): | ||
723 | ret = -EINVAL; | ||
724 | for (i = 0; i < ARRAY_SIZE(st->scale_avail); i++) | ||
725 | if (val2 == st->scale_avail[i][1]) { | ||
726 | tmp = st->conf; | ||
727 | st->conf &= ~AD7793_CONF_GAIN(-1); | ||
728 | st->conf |= AD7793_CONF_GAIN(i); | ||
729 | |||
730 | if (tmp != st->conf) { | ||
731 | ad7793_write_reg(st, AD7793_REG_CONF, | ||
732 | sizeof(st->conf), | ||
733 | st->conf); | ||
734 | ad7793_calibrate_all(st); | ||
735 | } | ||
736 | ret = 0; | ||
737 | } | ||
738 | |||
739 | default: | ||
740 | ret = -EINVAL; | ||
741 | } | ||
742 | |||
743 | mutex_unlock(&indio_dev->mlock); | ||
744 | return ret; | ||
745 | } | ||
746 | |||
747 | static int ad7793_validate_trigger(struct iio_dev *indio_dev, | ||
748 | struct iio_trigger *trig) | ||
749 | { | ||
750 | if (indio_dev->trig != trig) | ||
751 | return -EINVAL; | ||
752 | |||
753 | return 0; | ||
754 | } | ||
755 | |||
756 | static int ad7793_write_raw_get_fmt(struct iio_dev *indio_dev, | ||
757 | struct iio_chan_spec const *chan, | ||
758 | long mask) | ||
759 | { | ||
760 | return IIO_VAL_INT_PLUS_NANO; | ||
761 | } | ||
762 | |||
763 | static const struct iio_info ad7793_info = { | ||
764 | .read_raw = &ad7793_read_raw, | ||
765 | .write_raw = &ad7793_write_raw, | ||
766 | .write_raw_get_fmt = &ad7793_write_raw_get_fmt, | ||
767 | .attrs = &ad7793_attribute_group, | ||
768 | .validate_trigger = ad7793_validate_trigger, | ||
769 | .driver_module = THIS_MODULE, | ||
770 | }; | ||
771 | |||
772 | static const struct ad7793_chip_info ad7793_chip_info_tbl[] = { | ||
773 | [ID_AD7793] = { | ||
774 | .channel[0] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 0, 0, | ||
775 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
776 | AD7793_CH_AIN1P_AIN1M, | ||
777 | 0, IIO_ST('s', 24, 32, 0), 0), | ||
778 | .channel[1] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 1, 1, | ||
779 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
780 | AD7793_CH_AIN2P_AIN2M, | ||
781 | 1, IIO_ST('s', 24, 32, 0), 0), | ||
782 | .channel[2] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 2, 2, | ||
783 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
784 | AD7793_CH_AIN3P_AIN3M, | ||
785 | 2, IIO_ST('s', 24, 32, 0), 0), | ||
786 | .channel[3] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, "shorted", 0, 0, | ||
787 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
788 | AD7793_CH_AIN1M_AIN1M, | ||
789 | 3, IIO_ST('s', 24, 32, 0), 0), | ||
790 | .channel[4] = IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, | ||
791 | (1 << IIO_CHAN_INFO_SCALE_SEPARATE), | ||
792 | AD7793_CH_TEMP, | ||
793 | 4, IIO_ST('s', 24, 32, 0), 0), | ||
794 | .channel[5] = IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 4, 0, | ||
795 | (1 << IIO_CHAN_INFO_SCALE_SEPARATE), | ||
796 | AD7793_CH_AVDD_MONITOR, | ||
797 | 5, IIO_ST('s', 24, 32, 0), 0), | ||
798 | .channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6), | ||
799 | }, | ||
800 | [ID_AD7792] = { | ||
801 | .channel[0] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 0, 0, | ||
802 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
803 | AD7793_CH_AIN1P_AIN1M, | ||
804 | 0, IIO_ST('s', 16, 32, 0), 0), | ||
805 | .channel[1] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 1, 1, | ||
806 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
807 | AD7793_CH_AIN2P_AIN2M, | ||
808 | 1, IIO_ST('s', 16, 32, 0), 0), | ||
809 | .channel[2] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 2, 2, | ||
810 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
811 | AD7793_CH_AIN3P_AIN3M, | ||
812 | 2, IIO_ST('s', 16, 32, 0), 0), | ||
813 | .channel[3] = IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, "shorted", 0, 0, | ||
814 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
815 | AD7793_CH_AIN1M_AIN1M, | ||
816 | 3, IIO_ST('s', 16, 32, 0), 0), | ||
817 | .channel[4] = IIO_CHAN(IIO_TEMP, 0, 1, 0, NULL, 0, 0, | ||
818 | (1 << IIO_CHAN_INFO_SCALE_SEPARATE), | ||
819 | AD7793_CH_TEMP, | ||
820 | 4, IIO_ST('s', 16, 32, 0), 0), | ||
821 | .channel[5] = IIO_CHAN(IIO_IN, 0, 1, 0, "supply", 4, 0, | ||
822 | (1 << IIO_CHAN_INFO_SCALE_SEPARATE), | ||
823 | AD7793_CH_AVDD_MONITOR, | ||
824 | 5, IIO_ST('s', 16, 32, 0), 0), | ||
825 | .channel[6] = IIO_CHAN_SOFT_TIMESTAMP(6), | ||
826 | }, | ||
827 | }; | ||
828 | |||
829 | static int __devinit ad7793_probe(struct spi_device *spi) | ||
830 | { | ||
831 | struct ad7793_platform_data *pdata = spi->dev.platform_data; | ||
832 | struct ad7793_state *st; | ||
833 | struct iio_dev *indio_dev; | ||
834 | int ret, i, voltage_uv = 0, regdone = 0; | ||
835 | |||
836 | if (!pdata) { | ||
837 | dev_err(&spi->dev, "no platform data?\n"); | ||
838 | return -ENODEV; | ||
839 | } | ||
840 | |||
841 | if (!spi->irq) { | ||
842 | dev_err(&spi->dev, "no IRQ?\n"); | ||
843 | return -ENODEV; | ||
844 | } | ||
845 | |||
846 | indio_dev = iio_allocate_device(sizeof(*st)); | ||
847 | if (indio_dev == NULL) | ||
848 | return -ENOMEM; | ||
849 | |||
850 | st = iio_priv(indio_dev); | ||
851 | |||
852 | st->reg = regulator_get(&spi->dev, "vcc"); | ||
853 | if (!IS_ERR(st->reg)) { | ||
854 | ret = regulator_enable(st->reg); | ||
855 | if (ret) | ||
856 | goto error_put_reg; | ||
857 | |||
858 | voltage_uv = regulator_get_voltage(st->reg); | ||
859 | } | ||
860 | |||
861 | st->chip_info = | ||
862 | &ad7793_chip_info_tbl[spi_get_device_id(spi)->driver_data]; | ||
863 | |||
864 | st->pdata = pdata; | ||
865 | |||
866 | if (pdata && pdata->vref_mv) | ||
867 | st->int_vref_mv = pdata->vref_mv; | ||
868 | else if (voltage_uv) | ||
869 | st->int_vref_mv = voltage_uv / 1000; | ||
870 | else | ||
871 | st->int_vref_mv = 2500; /* Build-in ref */ | ||
872 | |||
873 | spi_set_drvdata(spi, indio_dev); | ||
874 | st->spi = spi; | ||
875 | |||
876 | indio_dev->dev.parent = &spi->dev; | ||
877 | indio_dev->name = spi_get_device_id(spi)->name; | ||
878 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
879 | indio_dev->channels = st->chip_info->channel; | ||
880 | indio_dev->available_scan_masks = st->available_scan_masks; | ||
881 | indio_dev->num_channels = 7; | ||
882 | indio_dev->info = &ad7793_info; | ||
883 | |||
884 | for (i = 0; i < indio_dev->num_channels; i++) | ||
885 | st->available_scan_masks[i] = (1 << i) | (1 << | ||
886 | indio_dev->channels[indio_dev->num_channels - 1]. | ||
887 | scan_index); | ||
888 | |||
889 | init_waitqueue_head(&st->wq_data_avail); | ||
890 | |||
891 | ret = ad7793_register_ring_funcs_and_init(indio_dev); | ||
892 | if (ret) | ||
893 | goto error_disable_reg; | ||
894 | |||
895 | ret = iio_device_register(indio_dev); | ||
896 | if (ret) | ||
897 | goto error_unreg_ring; | ||
898 | regdone = 1; | ||
899 | |||
900 | ret = ad7793_probe_trigger(indio_dev); | ||
901 | if (ret) | ||
902 | goto error_unreg_ring; | ||
903 | |||
904 | ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, | ||
905 | indio_dev->channels, | ||
906 | indio_dev->num_channels); | ||
907 | if (ret) | ||
908 | goto error_remove_trigger; | ||
909 | |||
910 | ret = ad7793_setup(st); | ||
911 | if (ret) | ||
912 | goto error_uninitialize_ring; | ||
913 | |||
914 | return 0; | ||
915 | |||
916 | error_uninitialize_ring: | ||
917 | iio_ring_buffer_unregister(indio_dev->ring); | ||
918 | error_remove_trigger: | ||
919 | ad7793_remove_trigger(indio_dev); | ||
920 | error_unreg_ring: | ||
921 | ad7793_ring_cleanup(indio_dev); | ||
922 | error_disable_reg: | ||
923 | if (!IS_ERR(st->reg)) | ||
924 | regulator_disable(st->reg); | ||
925 | error_put_reg: | ||
926 | if (!IS_ERR(st->reg)) | ||
927 | regulator_put(st->reg); | ||
928 | |||
929 | if (regdone) | ||
930 | iio_device_unregister(indio_dev); | ||
931 | else | ||
932 | iio_free_device(indio_dev); | ||
933 | |||
934 | return ret; | ||
935 | } | ||
936 | |||
937 | static int ad7793_remove(struct spi_device *spi) | ||
938 | { | ||
939 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
940 | struct ad7793_state *st = iio_priv(indio_dev); | ||
941 | |||
942 | iio_ring_buffer_unregister(indio_dev->ring); | ||
943 | ad7793_remove_trigger(indio_dev); | ||
944 | ad7793_ring_cleanup(indio_dev); | ||
945 | |||
946 | if (!IS_ERR(st->reg)) { | ||
947 | regulator_disable(st->reg); | ||
948 | regulator_put(st->reg); | ||
949 | } | ||
950 | |||
951 | iio_device_unregister(indio_dev); | ||
952 | |||
953 | return 0; | ||
954 | } | ||
955 | |||
956 | static const struct spi_device_id ad7793_id[] = { | ||
957 | {"ad7792", ID_AD7792}, | ||
958 | {"ad7793", ID_AD7793}, | ||
959 | {} | ||
960 | }; | ||
961 | |||
962 | static struct spi_driver ad7793_driver = { | ||
963 | .driver = { | ||
964 | .name = "ad7793", | ||
965 | .bus = &spi_bus_type, | ||
966 | .owner = THIS_MODULE, | ||
967 | }, | ||
968 | .probe = ad7793_probe, | ||
969 | .remove = __devexit_p(ad7793_remove), | ||
970 | .id_table = ad7793_id, | ||
971 | }; | ||
972 | |||
973 | static int __init ad7793_init(void) | ||
974 | { | ||
975 | return spi_register_driver(&ad7793_driver); | ||
976 | } | ||
977 | module_init(ad7793_init); | ||
978 | |||
979 | static void __exit ad7793_exit(void) | ||
980 | { | ||
981 | spi_unregister_driver(&ad7793_driver); | ||
982 | } | ||
983 | module_exit(ad7793_exit); | ||
984 | |||
985 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
986 | MODULE_DESCRIPTION("Analog Devices AD7792/3 ADC"); | ||
987 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/staging/iio/adc/ad7793.h b/drivers/staging/iio/adc/ad7793.h new file mode 100644 index 00000000000..64f7d41dc45 --- /dev/null +++ b/drivers/staging/iio/adc/ad7793.h | |||
@@ -0,0 +1,107 @@ | |||
1 | /* | ||
2 | * AD7792/AD7793 SPI ADC driver | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | #ifndef IIO_ADC_AD7793_H_ | ||
9 | #define IIO_ADC_AD7793_H_ | ||
10 | |||
11 | /* | ||
12 | * TODO: struct ad7793_platform_data needs to go into include/linux/iio | ||
13 | */ | ||
14 | |||
15 | /* Registers */ | ||
16 | #define AD7793_REG_COMM 0 /* Communications Register (WO, 8-bit) */ | ||
17 | #define AD7793_REG_STAT 0 /* Status Register (RO, 8-bit) */ | ||
18 | #define AD7793_REG_MODE 1 /* Mode Register (RW, 16-bit */ | ||
19 | #define AD7793_REG_CONF 2 /* Configuration Register (RW, 16-bit) */ | ||
20 | #define AD7793_REG_DATA 3 /* Data Register (RO, 16-/24-bit) */ | ||
21 | #define AD7793_REG_ID 4 /* ID Register (RO, 8-bit) */ | ||
22 | #define AD7793_REG_IO 5 /* IO Register (RO, 8-bit) */ | ||
23 | #define AD7793_REG_OFFSET 6 /* Offset Register (RW, 16-bit | ||
24 | * (AD7792)/24-bit (AD7793)) */ | ||
25 | #define AD7793_REG_FULLSALE 7 /* Full-Scale Register | ||
26 | * (RW, 16-bit (AD7792)/24-bit (AD7793)) */ | ||
27 | |||
28 | /* Communications Register Bit Designations (AD7793_REG_COMM) */ | ||
29 | #define AD7793_COMM_WEN (1 << 7) /* Write Enable */ | ||
30 | #define AD7793_COMM_WRITE (0 << 6) /* Write Operation */ | ||
31 | #define AD7793_COMM_READ (1 << 6) /* Read Operation */ | ||
32 | #define AD7793_COMM_ADDR(x) (((x) & 0x7) << 3) /* Register Address */ | ||
33 | #define AD7793_COMM_CREAD (1 << 2) /* Continuous Read of Data Register */ | ||
34 | |||
35 | /* Status Register Bit Designations (AD7793_REG_STAT) */ | ||
36 | #define AD7793_STAT_RDY (1 << 7) /* Ready */ | ||
37 | #define AD7793_STAT_ERR (1 << 6) /* Error (Overrange, Underrange) */ | ||
38 | #define AD7793_STAT_CH3 (1 << 2) /* Channel 3 */ | ||
39 | #define AD7793_STAT_CH2 (1 << 1) /* Channel 2 */ | ||
40 | #define AD7793_STAT_CH1 (1 << 0) /* Channel 1 */ | ||
41 | |||
42 | /* Mode Register Bit Designations (AD7793_REG_MODE) */ | ||
43 | #define AD7793_MODE_SEL(x) (((x) & 0x7) << 13) /* Operation Mode Select */ | ||
44 | #define AD7793_MODE_CLKSRC(x) (((x) & 0x3) << 6) /* ADC Clock Source Select */ | ||
45 | #define AD7793_MODE_RATE(x) ((x) & 0xF) /* Filter Update Rate Select */ | ||
46 | |||
47 | #define AD7793_MODE_CONT 0 /* Continuous Conversion Mode */ | ||
48 | #define AD7793_MODE_SINGLE 1 /* Single Conversion Mode */ | ||
49 | #define AD7793_MODE_IDLE 2 /* Idle Mode */ | ||
50 | #define AD7793_MODE_PWRDN 3 /* Power-Down Mode */ | ||
51 | #define AD7793_MODE_CAL_INT_ZERO 4 /* Internal Zero-Scale Calibration */ | ||
52 | #define AD7793_MODE_CAL_INT_FULL 5 /* Internal Full-Scale Calibration */ | ||
53 | #define AD7793_MODE_CAL_SYS_ZERO 6 /* System Zero-Scale Calibration */ | ||
54 | #define AD7793_MODE_CAL_SYS_FULL 7 /* System Full-Scale Calibration */ | ||
55 | |||
56 | #define AD7793_CLK_INT 0 /* Internal 64 kHz Clock not | ||
57 | * available at the CLK pin */ | ||
58 | #define AD7793_CLK_INT_CO 1 /* Internal 64 kHz Clock available | ||
59 | * at the CLK pin */ | ||
60 | #define AD7793_CLK_EXT 2 /* External 64 kHz Clock */ | ||
61 | #define AD7793_CLK_EXT_DIV2 3 /* External Clock divided by 2 */ | ||
62 | |||
63 | /* Configuration Register Bit Designations (AD7793_REG_CONF) */ | ||
64 | #define AD7793_CONF_VBIAS(x) (((x) & 0x3) << 14) /* Bias Voltage | ||
65 | * Generator Enable */ | ||
66 | #define AD7793_CONF_BO_EN (1 << 13) /* Burnout Current Enable */ | ||
67 | #define AD7793_CONF_UNIPOLAR (1 << 12) /* Unipolar/Bipolar Enable */ | ||
68 | #define AD7793_CONF_BOOST (1 << 11) /* Boost Enable */ | ||
69 | #define AD7793_CONF_GAIN(x) (((x) & 0x7) << 8) /* Gain Select */ | ||
70 | #define AD7793_CONF_REFSEL (1 << 7) /* INT/EXT Reference Select */ | ||
71 | #define AD7793_CONF_BUF (1 << 4) /* Buffered Mode Enable */ | ||
72 | #define AD7793_CONF_CHAN(x) ((x) & 0x7) /* Channel select */ | ||
73 | |||
74 | #define AD7793_CH_AIN1P_AIN1M 0 /* AIN1(+) - AIN1(-) */ | ||
75 | #define AD7793_CH_AIN2P_AIN2M 1 /* AIN2(+) - AIN2(-) */ | ||
76 | #define AD7793_CH_AIN3P_AIN3M 2 /* AIN3(+) - AIN3(-) */ | ||
77 | #define AD7793_CH_AIN1M_AIN1M 3 /* AIN1(-) - AIN1(-) */ | ||
78 | #define AD7793_CH_TEMP 6 /* Temp Sensor */ | ||
79 | #define AD7793_CH_AVDD_MONITOR 7 /* AVDD Monitor */ | ||
80 | |||
81 | /* ID Register Bit Designations (AD7793_REG_ID) */ | ||
82 | #define AD7792_ID 0xA | ||
83 | #define AD7793_ID 0xB | ||
84 | #define AD7793_ID_MASK 0xF | ||
85 | |||
86 | /* IO (Excitation Current Sources) Register Bit Designations (AD7793_REG_IO) */ | ||
87 | #define AD7793_IO_IEXC1_IOUT1_IEXC2_IOUT2 0 /* IEXC1 connect to IOUT1, | ||
88 | * IEXC2 connect to IOUT2 */ | ||
89 | #define AD7793_IO_IEXC1_IOUT2_IEXC2_IOUT1 1 /* IEXC1 connect to IOUT2, | ||
90 | * IEXC2 connect to IOUT1 */ | ||
91 | #define AD7793_IO_IEXC1_IEXC2_IOUT1 2 /* Both current sources | ||
92 | * IEXC1,2 connect to IOUT1 */ | ||
93 | #define AD7793_IO_IEXC1_IEXC2_IOUT2 3 /* Both current sources | ||
94 | * IEXC1,2 connect to IOUT2 */ | ||
95 | |||
96 | #define AD7793_IO_IXCEN_10uA (1 << 0) /* Excitation Current 10uA */ | ||
97 | #define AD7793_IO_IXCEN_210uA (2 << 0) /* Excitation Current 210uA */ | ||
98 | #define AD7793_IO_IXCEN_1mA (3 << 0) /* Excitation Current 1mA */ | ||
99 | |||
100 | struct ad7793_platform_data { | ||
101 | u16 vref_mv; | ||
102 | u16 mode; | ||
103 | u16 conf; | ||
104 | u8 io; | ||
105 | }; | ||
106 | |||
107 | #endif /* IIO_ADC_AD7793_H_ */ | ||
diff --git a/drivers/staging/iio/adc/ad7887.h b/drivers/staging/iio/adc/ad7887.h new file mode 100644 index 00000000000..837046c7b89 --- /dev/null +++ b/drivers/staging/iio/adc/ad7887.h | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * AD7887 SPI ADC driver | ||
3 | * | ||
4 | * Copyright 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | #ifndef IIO_ADC_AD7887_H_ | ||
9 | #define IIO_ADC_AD7887_H_ | ||
10 | |||
11 | #define AD7887_REF_DIS (1 << 5) /* on-chip reference disable */ | ||
12 | #define AD7887_DUAL (1 << 4) /* dual-channel mode */ | ||
13 | #define AD7887_CH_AIN1 (1 << 3) /* convert on channel 1, DUAL=1 */ | ||
14 | #define AD7887_CH_AIN0 (0 << 3) /* convert on channel 0, DUAL=0,1 */ | ||
15 | #define AD7887_PM_MODE1 (0) /* CS based shutdown */ | ||
16 | #define AD7887_PM_MODE2 (1) /* full on */ | ||
17 | #define AD7887_PM_MODE3 (2) /* auto shutdown after conversion */ | ||
18 | #define AD7887_PM_MODE4 (3) /* standby mode */ | ||
19 | |||
20 | enum ad7887_channels { | ||
21 | AD7887_CH0, | ||
22 | AD7887_CH0_CH1, | ||
23 | AD7887_CH1, | ||
24 | }; | ||
25 | |||
26 | #define RES_MASK(bits) ((1 << (bits)) - 1) /* TODO: move this into a common header */ | ||
27 | |||
28 | /* | ||
29 | * TODO: struct ad7887_platform_data needs to go into include/linux/iio | ||
30 | */ | ||
31 | |||
32 | struct ad7887_platform_data { | ||
33 | /* External Vref voltage applied */ | ||
34 | u16 vref_mv; | ||
35 | /* | ||
36 | * AD7887: | ||
37 | * In single channel mode en_dual = flase, AIN1/Vref pins assumes its | ||
38 | * Vref function. In dual channel mode en_dual = true, AIN1 becomes the | ||
39 | * second input channel, and Vref is internally connected to Vdd. | ||
40 | */ | ||
41 | bool en_dual; | ||
42 | /* | ||
43 | * AD7887: | ||
44 | * use_onchip_ref = true, the Vref is internally connected to the 2.500V | ||
45 | * Voltage reference. If use_onchip_ref = false, the reference voltage | ||
46 | * is supplied by AIN1/Vref | ||
47 | */ | ||
48 | bool use_onchip_ref; | ||
49 | }; | ||
50 | |||
51 | /** | ||
52 | * struct ad7887_chip_info - chip specifc information | ||
53 | * @int_vref_mv: the internal reference voltage | ||
54 | * @channel: channel specification | ||
55 | */ | ||
56 | |||
57 | struct ad7887_chip_info { | ||
58 | u16 int_vref_mv; | ||
59 | struct iio_chan_spec channel[3]; | ||
60 | }; | ||
61 | |||
62 | struct ad7887_state { | ||
63 | struct spi_device *spi; | ||
64 | const struct ad7887_chip_info *chip_info; | ||
65 | struct regulator *reg; | ||
66 | size_t d_size; | ||
67 | u16 int_vref_mv; | ||
68 | struct spi_transfer xfer[4]; | ||
69 | struct spi_message msg[3]; | ||
70 | struct spi_message *ring_msg; | ||
71 | unsigned char tx_cmd_buf[8]; | ||
72 | |||
73 | /* | ||
74 | * DMA (thus cache coherency maintenance) requires the | ||
75 | * transfer buffers to live in their own cache lines. | ||
76 | */ | ||
77 | |||
78 | unsigned char data[4] ____cacheline_aligned; | ||
79 | }; | ||
80 | |||
81 | enum ad7887_supported_device_ids { | ||
82 | ID_AD7887 | ||
83 | }; | ||
84 | |||
85 | #ifdef CONFIG_IIO_RING_BUFFER | ||
86 | int ad7887_scan_from_ring(struct ad7887_state *st, long mask); | ||
87 | int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev); | ||
88 | void ad7887_ring_cleanup(struct iio_dev *indio_dev); | ||
89 | #else /* CONFIG_IIO_RING_BUFFER */ | ||
90 | static inline int ad7887_scan_from_ring(struct ad7887_state *st, long mask) | ||
91 | { | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static inline int | ||
96 | ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev) | ||
97 | { | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static inline void ad7887_ring_cleanup(struct iio_dev *indio_dev) | ||
102 | { | ||
103 | } | ||
104 | #endif /* CONFIG_IIO_RING_BUFFER */ | ||
105 | #endif /* IIO_ADC_AD7887_H_ */ | ||
diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887_core.c new file mode 100644 index 00000000000..3d9121e5c37 --- /dev/null +++ b/drivers/staging/iio/adc/ad7887_core.c | |||
@@ -0,0 +1,266 @@ | |||
1 | /* | ||
2 | * AD7887 SPI ADC driver | ||
3 | * | ||
4 | * Copyright 2010-2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/device.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/sysfs.h> | ||
13 | #include <linux/spi/spi.h> | ||
14 | #include <linux/regulator/consumer.h> | ||
15 | #include <linux/err.h> | ||
16 | |||
17 | #include "../iio.h" | ||
18 | #include "../sysfs.h" | ||
19 | #include "../ring_generic.h" | ||
20 | #include "adc.h" | ||
21 | |||
22 | #include "ad7887.h" | ||
23 | |||
24 | static int ad7887_scan_direct(struct ad7887_state *st, unsigned ch) | ||
25 | { | ||
26 | int ret = spi_sync(st->spi, &st->msg[ch]); | ||
27 | if (ret) | ||
28 | return ret; | ||
29 | |||
30 | return (st->data[(ch * 2)] << 8) | st->data[(ch * 2) + 1]; | ||
31 | } | ||
32 | |||
33 | static int ad7887_read_raw(struct iio_dev *dev_info, | ||
34 | struct iio_chan_spec const *chan, | ||
35 | int *val, | ||
36 | int *val2, | ||
37 | long m) | ||
38 | { | ||
39 | int ret; | ||
40 | struct ad7887_state *st = iio_priv(dev_info); | ||
41 | unsigned int scale_uv; | ||
42 | |||
43 | switch (m) { | ||
44 | case 0: | ||
45 | mutex_lock(&dev_info->mlock); | ||
46 | if (iio_ring_enabled(dev_info)) | ||
47 | ret = ad7887_scan_from_ring(st, 1 << chan->address); | ||
48 | else | ||
49 | ret = ad7887_scan_direct(st, chan->address); | ||
50 | mutex_unlock(&dev_info->mlock); | ||
51 | |||
52 | if (ret < 0) | ||
53 | return ret; | ||
54 | *val = (ret >> st->chip_info->channel[0].scan_type.shift) & | ||
55 | RES_MASK(st->chip_info->channel[0].scan_type.realbits); | ||
56 | return IIO_VAL_INT; | ||
57 | case (1 << IIO_CHAN_INFO_SCALE_SHARED): | ||
58 | scale_uv = (st->int_vref_mv * 1000) | ||
59 | >> st->chip_info->channel[0].scan_type.realbits; | ||
60 | *val = scale_uv/1000; | ||
61 | *val2 = (scale_uv%1000)*1000; | ||
62 | return IIO_VAL_INT_PLUS_MICRO; | ||
63 | } | ||
64 | return -EINVAL; | ||
65 | } | ||
66 | |||
67 | |||
68 | static const struct ad7887_chip_info ad7887_chip_info_tbl[] = { | ||
69 | /* | ||
70 | * More devices added in future | ||
71 | */ | ||
72 | [ID_AD7887] = { | ||
73 | .channel[0] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, | ||
74 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
75 | 1, 1, IIO_ST('u', 12, 16, 0), 0), | ||
76 | |||
77 | .channel[1] = IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, | ||
78 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
79 | 0, 0, IIO_ST('u', 12, 16, 0), 0), | ||
80 | |||
81 | .channel[2] = IIO_CHAN_SOFT_TIMESTAMP(2), | ||
82 | .int_vref_mv = 2500, | ||
83 | }, | ||
84 | }; | ||
85 | |||
86 | static const struct iio_info ad7887_info = { | ||
87 | .read_raw = &ad7887_read_raw, | ||
88 | .driver_module = THIS_MODULE, | ||
89 | }; | ||
90 | |||
91 | static int __devinit ad7887_probe(struct spi_device *spi) | ||
92 | { | ||
93 | struct ad7887_platform_data *pdata = spi->dev.platform_data; | ||
94 | struct ad7887_state *st; | ||
95 | int ret, voltage_uv = 0, regdone = 0; | ||
96 | struct iio_dev *indio_dev = iio_allocate_device(sizeof(*st)); | ||
97 | |||
98 | if (indio_dev == NULL) | ||
99 | return -ENOMEM; | ||
100 | |||
101 | st = iio_priv(indio_dev); | ||
102 | |||
103 | st->reg = regulator_get(&spi->dev, "vcc"); | ||
104 | if (!IS_ERR(st->reg)) { | ||
105 | ret = regulator_enable(st->reg); | ||
106 | if (ret) | ||
107 | goto error_put_reg; | ||
108 | |||
109 | voltage_uv = regulator_get_voltage(st->reg); | ||
110 | } | ||
111 | |||
112 | st->chip_info = | ||
113 | &ad7887_chip_info_tbl[spi_get_device_id(spi)->driver_data]; | ||
114 | |||
115 | spi_set_drvdata(spi, indio_dev); | ||
116 | st->spi = spi; | ||
117 | |||
118 | /* Estabilish that the iio_dev is a child of the spi device */ | ||
119 | indio_dev->dev.parent = &spi->dev; | ||
120 | indio_dev->name = spi_get_device_id(spi)->name; | ||
121 | indio_dev->info = &ad7887_info; | ||
122 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
123 | |||
124 | /* Setup default message */ | ||
125 | |||
126 | st->tx_cmd_buf[0] = AD7887_CH_AIN0 | AD7887_PM_MODE4 | | ||
127 | ((pdata && pdata->use_onchip_ref) ? | ||
128 | 0 : AD7887_REF_DIS); | ||
129 | |||
130 | st->xfer[0].rx_buf = &st->data[0]; | ||
131 | st->xfer[0].tx_buf = &st->tx_cmd_buf[0]; | ||
132 | st->xfer[0].len = 2; | ||
133 | |||
134 | spi_message_init(&st->msg[AD7887_CH0]); | ||
135 | spi_message_add_tail(&st->xfer[0], &st->msg[AD7887_CH0]); | ||
136 | |||
137 | if (pdata && pdata->en_dual) { | ||
138 | st->tx_cmd_buf[0] |= AD7887_DUAL | AD7887_REF_DIS; | ||
139 | |||
140 | st->tx_cmd_buf[2] = AD7887_CH_AIN1 | AD7887_DUAL | | ||
141 | AD7887_REF_DIS | AD7887_PM_MODE4; | ||
142 | st->tx_cmd_buf[4] = AD7887_CH_AIN0 | AD7887_DUAL | | ||
143 | AD7887_REF_DIS | AD7887_PM_MODE4; | ||
144 | st->tx_cmd_buf[6] = AD7887_CH_AIN1 | AD7887_DUAL | | ||
145 | AD7887_REF_DIS | AD7887_PM_MODE4; | ||
146 | |||
147 | st->xfer[1].rx_buf = &st->data[0]; | ||
148 | st->xfer[1].tx_buf = &st->tx_cmd_buf[2]; | ||
149 | st->xfer[1].len = 2; | ||
150 | |||
151 | st->xfer[2].rx_buf = &st->data[2]; | ||
152 | st->xfer[2].tx_buf = &st->tx_cmd_buf[4]; | ||
153 | st->xfer[2].len = 2; | ||
154 | |||
155 | spi_message_init(&st->msg[AD7887_CH0_CH1]); | ||
156 | spi_message_add_tail(&st->xfer[1], &st->msg[AD7887_CH0_CH1]); | ||
157 | spi_message_add_tail(&st->xfer[2], &st->msg[AD7887_CH0_CH1]); | ||
158 | |||
159 | st->xfer[3].rx_buf = &st->data[0]; | ||
160 | st->xfer[3].tx_buf = &st->tx_cmd_buf[6]; | ||
161 | st->xfer[3].len = 2; | ||
162 | |||
163 | spi_message_init(&st->msg[AD7887_CH1]); | ||
164 | spi_message_add_tail(&st->xfer[3], &st->msg[AD7887_CH1]); | ||
165 | |||
166 | if (pdata && pdata->vref_mv) | ||
167 | st->int_vref_mv = pdata->vref_mv; | ||
168 | else if (voltage_uv) | ||
169 | st->int_vref_mv = voltage_uv / 1000; | ||
170 | else | ||
171 | dev_warn(&spi->dev, "reference voltage unspecified\n"); | ||
172 | |||
173 | indio_dev->channels = st->chip_info->channel; | ||
174 | indio_dev->num_channels = 3; | ||
175 | } else { | ||
176 | if (pdata && pdata->vref_mv) | ||
177 | st->int_vref_mv = pdata->vref_mv; | ||
178 | else if (pdata && pdata->use_onchip_ref) | ||
179 | st->int_vref_mv = st->chip_info->int_vref_mv; | ||
180 | else | ||
181 | dev_warn(&spi->dev, "reference voltage unspecified\n"); | ||
182 | |||
183 | indio_dev->channels = &st->chip_info->channel[1]; | ||
184 | indio_dev->num_channels = 2; | ||
185 | } | ||
186 | |||
187 | ret = ad7887_register_ring_funcs_and_init(indio_dev); | ||
188 | if (ret) | ||
189 | goto error_disable_reg; | ||
190 | |||
191 | ret = iio_device_register(indio_dev); | ||
192 | if (ret) | ||
193 | goto error_disable_reg; | ||
194 | regdone = 1; | ||
195 | |||
196 | ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, | ||
197 | indio_dev->channels, | ||
198 | indio_dev->num_channels); | ||
199 | if (ret) | ||
200 | goto error_cleanup_ring; | ||
201 | return 0; | ||
202 | |||
203 | error_cleanup_ring: | ||
204 | ad7887_ring_cleanup(indio_dev); | ||
205 | error_disable_reg: | ||
206 | if (!IS_ERR(st->reg)) | ||
207 | regulator_disable(st->reg); | ||
208 | error_put_reg: | ||
209 | if (!IS_ERR(st->reg)) | ||
210 | regulator_put(st->reg); | ||
211 | if (regdone) | ||
212 | iio_device_unregister(indio_dev); | ||
213 | else | ||
214 | iio_free_device(indio_dev); | ||
215 | |||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | static int ad7887_remove(struct spi_device *spi) | ||
220 | { | ||
221 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
222 | struct ad7887_state *st = iio_priv(indio_dev); | ||
223 | |||
224 | iio_ring_buffer_unregister(indio_dev->ring); | ||
225 | ad7887_ring_cleanup(indio_dev); | ||
226 | if (!IS_ERR(st->reg)) { | ||
227 | regulator_disable(st->reg); | ||
228 | regulator_put(st->reg); | ||
229 | } | ||
230 | iio_device_unregister(indio_dev); | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static const struct spi_device_id ad7887_id[] = { | ||
236 | {"ad7887", ID_AD7887}, | ||
237 | {} | ||
238 | }; | ||
239 | |||
240 | static struct spi_driver ad7887_driver = { | ||
241 | .driver = { | ||
242 | .name = "ad7887", | ||
243 | .bus = &spi_bus_type, | ||
244 | .owner = THIS_MODULE, | ||
245 | }, | ||
246 | .probe = ad7887_probe, | ||
247 | .remove = __devexit_p(ad7887_remove), | ||
248 | .id_table = ad7887_id, | ||
249 | }; | ||
250 | |||
251 | static int __init ad7887_init(void) | ||
252 | { | ||
253 | return spi_register_driver(&ad7887_driver); | ||
254 | } | ||
255 | module_init(ad7887_init); | ||
256 | |||
257 | static void __exit ad7887_exit(void) | ||
258 | { | ||
259 | spi_unregister_driver(&ad7887_driver); | ||
260 | } | ||
261 | module_exit(ad7887_exit); | ||
262 | |||
263 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
264 | MODULE_DESCRIPTION("Analog Devices AD7887 ADC"); | ||
265 | MODULE_LICENSE("GPL v2"); | ||
266 | MODULE_ALIAS("spi:ad7887"); | ||
diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c new file mode 100644 index 00000000000..0ac7c0b9d71 --- /dev/null +++ b/drivers/staging/iio/adc/ad7887_ring.c | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | * Copyright 2010-2011 Analog Devices Inc. | ||
3 | * Copyright (C) 2008 Jonathan Cameron | ||
4 | * | ||
5 | * Licensed under the GPL-2. | ||
6 | * | ||
7 | * ad7887_ring.c | ||
8 | */ | ||
9 | |||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/device.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/sysfs.h> | ||
15 | #include <linux/spi/spi.h> | ||
16 | |||
17 | #include "../iio.h" | ||
18 | #include "../ring_generic.h" | ||
19 | #include "../ring_sw.h" | ||
20 | #include "../trigger.h" | ||
21 | #include "../sysfs.h" | ||
22 | |||
23 | #include "ad7887.h" | ||
24 | |||
25 | int ad7887_scan_from_ring(struct ad7887_state *st, long mask) | ||
26 | { | ||
27 | struct iio_ring_buffer *ring = iio_priv_to_dev(st)->ring; | ||
28 | int count = 0, ret; | ||
29 | u16 *ring_data; | ||
30 | |||
31 | if (!(ring->scan_mask & mask)) { | ||
32 | ret = -EBUSY; | ||
33 | goto error_ret; | ||
34 | } | ||
35 | |||
36 | ring_data = kmalloc(ring->access->get_bytes_per_datum(ring), | ||
37 | GFP_KERNEL); | ||
38 | if (ring_data == NULL) { | ||
39 | ret = -ENOMEM; | ||
40 | goto error_ret; | ||
41 | } | ||
42 | ret = ring->access->read_last(ring, (u8 *) ring_data); | ||
43 | if (ret) | ||
44 | goto error_free_ring_data; | ||
45 | |||
46 | /* for single channel scan the result is stored with zero offset */ | ||
47 | if ((ring->scan_mask == ((1 << 1) | (1 << 0))) && (mask == (1 << 1))) | ||
48 | count = 1; | ||
49 | |||
50 | ret = be16_to_cpu(ring_data[count]); | ||
51 | |||
52 | error_free_ring_data: | ||
53 | kfree(ring_data); | ||
54 | error_ret: | ||
55 | return ret; | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * ad7887_ring_preenable() setup the parameters of the ring before enabling | ||
60 | * | ||
61 | * The complex nature of the setting of the nuber of bytes per datum is due | ||
62 | * to this driver currently ensuring that the timestamp is stored at an 8 | ||
63 | * byte boundary. | ||
64 | **/ | ||
65 | static int ad7887_ring_preenable(struct iio_dev *indio_dev) | ||
66 | { | ||
67 | struct ad7887_state *st = iio_priv(indio_dev); | ||
68 | struct iio_ring_buffer *ring = indio_dev->ring; | ||
69 | |||
70 | st->d_size = ring->scan_count * | ||
71 | st->chip_info->channel[0].scan_type.storagebits / 8; | ||
72 | |||
73 | if (ring->scan_timestamp) { | ||
74 | st->d_size += sizeof(s64); | ||
75 | |||
76 | if (st->d_size % sizeof(s64)) | ||
77 | st->d_size += sizeof(s64) - (st->d_size % sizeof(s64)); | ||
78 | } | ||
79 | |||
80 | if (indio_dev->ring->access->set_bytes_per_datum) | ||
81 | indio_dev->ring->access->set_bytes_per_datum(indio_dev->ring, | ||
82 | st->d_size); | ||
83 | |||
84 | switch (ring->scan_mask) { | ||
85 | case (1 << 0): | ||
86 | st->ring_msg = &st->msg[AD7887_CH0]; | ||
87 | break; | ||
88 | case (1 << 1): | ||
89 | st->ring_msg = &st->msg[AD7887_CH1]; | ||
90 | /* Dummy read: push CH1 setting down to hardware */ | ||
91 | spi_sync(st->spi, st->ring_msg); | ||
92 | break; | ||
93 | case ((1 << 1) | (1 << 0)): | ||
94 | st->ring_msg = &st->msg[AD7887_CH0_CH1]; | ||
95 | break; | ||
96 | } | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static int ad7887_ring_postdisable(struct iio_dev *indio_dev) | ||
102 | { | ||
103 | struct ad7887_state *st = iio_priv(indio_dev); | ||
104 | |||
105 | /* dummy read: restore default CH0 settin */ | ||
106 | return spi_sync(st->spi, &st->msg[AD7887_CH0]); | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * ad7887_trigger_handler() bh of trigger launched polling to ring buffer | ||
111 | * | ||
112 | * Currently there is no option in this driver to disable the saving of | ||
113 | * timestamps within the ring. | ||
114 | **/ | ||
115 | static irqreturn_t ad7887_trigger_handler(int irq, void *p) | ||
116 | { | ||
117 | struct iio_poll_func *pf = p; | ||
118 | struct iio_dev *indio_dev = pf->private_data; | ||
119 | struct ad7887_state *st = iio_priv(indio_dev); | ||
120 | struct iio_ring_buffer *ring = indio_dev->ring; | ||
121 | s64 time_ns; | ||
122 | __u8 *buf; | ||
123 | int b_sent; | ||
124 | |||
125 | unsigned int bytes = ring->scan_count * | ||
126 | st->chip_info->channel[0].scan_type.storagebits / 8; | ||
127 | |||
128 | buf = kzalloc(st->d_size, GFP_KERNEL); | ||
129 | if (buf == NULL) | ||
130 | return -ENOMEM; | ||
131 | |||
132 | b_sent = spi_sync(st->spi, st->ring_msg); | ||
133 | if (b_sent) | ||
134 | goto done; | ||
135 | |||
136 | time_ns = iio_get_time_ns(); | ||
137 | |||
138 | memcpy(buf, st->data, bytes); | ||
139 | if (ring->scan_timestamp) | ||
140 | memcpy(buf + st->d_size - sizeof(s64), | ||
141 | &time_ns, sizeof(time_ns)); | ||
142 | |||
143 | indio_dev->ring->access->store_to(indio_dev->ring, buf, time_ns); | ||
144 | done: | ||
145 | kfree(buf); | ||
146 | iio_trigger_notify_done(indio_dev->trig); | ||
147 | |||
148 | return IRQ_HANDLED; | ||
149 | } | ||
150 | |||
151 | static const struct iio_ring_setup_ops ad7887_ring_setup_ops = { | ||
152 | .preenable = &ad7887_ring_preenable, | ||
153 | .postenable = &iio_triggered_ring_postenable, | ||
154 | .predisable = &iio_triggered_ring_predisable, | ||
155 | .postdisable = &ad7887_ring_postdisable, | ||
156 | }; | ||
157 | |||
158 | int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev) | ||
159 | { | ||
160 | int ret; | ||
161 | |||
162 | indio_dev->ring = iio_sw_rb_allocate(indio_dev); | ||
163 | if (!indio_dev->ring) { | ||
164 | ret = -ENOMEM; | ||
165 | goto error_ret; | ||
166 | } | ||
167 | /* Effectively select the ring buffer implementation */ | ||
168 | indio_dev->ring->access = &ring_sw_access_funcs; | ||
169 | indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, | ||
170 | &ad7887_trigger_handler, | ||
171 | IRQF_ONESHOT, | ||
172 | indio_dev, | ||
173 | "ad7887_consumer%d", | ||
174 | indio_dev->id); | ||
175 | if (indio_dev->pollfunc == NULL) { | ||
176 | ret = -ENOMEM; | ||
177 | goto error_deallocate_sw_rb; | ||
178 | } | ||
179 | /* Ring buffer functions - here trigger setup related */ | ||
180 | indio_dev->ring->setup_ops = &ad7887_ring_setup_ops; | ||
181 | |||
182 | /* Flag that polled ring buffering is possible */ | ||
183 | indio_dev->modes |= INDIO_RING_TRIGGERED; | ||
184 | return 0; | ||
185 | |||
186 | error_deallocate_sw_rb: | ||
187 | iio_sw_rb_free(indio_dev->ring); | ||
188 | error_ret: | ||
189 | return ret; | ||
190 | } | ||
191 | |||
192 | void ad7887_ring_cleanup(struct iio_dev *indio_dev) | ||
193 | { | ||
194 | /* ensure that the trigger has been detached */ | ||
195 | if (indio_dev->trig) { | ||
196 | iio_put_trigger(indio_dev->trig); | ||
197 | iio_trigger_dettach_poll_func(indio_dev->trig, | ||
198 | indio_dev->pollfunc); | ||
199 | } | ||
200 | iio_dealloc_pollfunc(indio_dev->pollfunc); | ||
201 | iio_sw_rb_free(indio_dev->ring); | ||
202 | } | ||
diff --git a/drivers/staging/iio/adc/adc.h b/drivers/staging/iio/adc/adc.h new file mode 100644 index 00000000000..40c5949880b --- /dev/null +++ b/drivers/staging/iio/adc/adc.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * adc.h - sysfs attributes associated with ADCs | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License version 2 as published by | ||
6 | * the Free Software Foundation. | ||
7 | * | ||
8 | * Copyright (c) 2008 Jonathan Cameron <jic23@cam.ac.uk> | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | /* Deprecated */ | ||
13 | #define IIO_DEV_ATTR_ADC(_num, _show, _addr) \ | ||
14 | IIO_DEVICE_ATTR(adc_##_num, S_IRUGO, _show, NULL, _addr) | ||
15 | |||
16 | #define IIO_DEV_ATTR_IN_RAW(_num, _show, _addr) \ | ||
17 | IIO_DEVICE_ATTR(in##_num##_raw, S_IRUGO, _show, NULL, _addr) | ||
18 | |||
19 | #define IIO_DEV_ATTR_IN_NAMED_RAW(_num, _name, _show, _addr) \ | ||
20 | IIO_DEVICE_ATTR(in##_num##_##_name##_raw, S_IRUGO, _show, NULL, _addr) | ||
21 | |||
22 | #define IIO_DEV_ATTR_IN_DIFF_RAW(_nump, _numn, _show, _addr) \ | ||
23 | IIO_DEVICE_ATTR_NAMED(in##_nump##min##_numn##_raw, \ | ||
24 | in##_nump-in##_numn##_raw, \ | ||
25 | S_IRUGO, \ | ||
26 | _show, \ | ||
27 | NULL, \ | ||
28 | _addr) | ||
29 | |||
30 | |||
31 | #define IIO_CONST_ATTR_IN_NAMED_OFFSET(_num, _name, _string) \ | ||
32 | IIO_CONST_ATTR(in##_num##_##_name##_offset, _string) | ||
33 | |||
34 | #define IIO_CONST_ATTR_IN_NAMED_SCALE(_num, _name, _string) \ | ||
35 | IIO_CONST_ATTR(in##_num##_##_name##_scale, _string) | ||
36 | |||
37 | #define IIO_EVENT_CODE_IN_HIGH_THRESH(a) \ | ||
38 | IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, a, IIO_EV_TYPE_THRESH, \ | ||
39 | IIO_EV_DIR_RISING) | ||
40 | #define IIO_EVENT_CODE_IN_LOW_THRESH(a) \ | ||
41 | IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_IN, a, IIO_EV_TYPE_THRESH, \ | ||
42 | IIO_EV_DIR_FALLING) | ||
diff --git a/drivers/staging/iio/adc/adt7310.c b/drivers/staging/iio/adc/adt7310.c new file mode 100644 index 00000000000..1a41b803440 --- /dev/null +++ b/drivers/staging/iio/adc/adt7310.c | |||
@@ -0,0 +1,904 @@ | |||
1 | /* | ||
2 | * ADT7310 digital temperature sensor driver supporting ADT7310 | ||
3 | * | ||
4 | * Copyright 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
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/list.h> | ||
15 | #include <linux/spi/spi.h> | ||
16 | |||
17 | #include "../iio.h" | ||
18 | #include "../sysfs.h" | ||
19 | |||
20 | /* | ||
21 | * ADT7310 registers definition | ||
22 | */ | ||
23 | |||
24 | #define ADT7310_STATUS 0 | ||
25 | #define ADT7310_CONFIG 1 | ||
26 | #define ADT7310_TEMPERATURE 2 | ||
27 | #define ADT7310_ID 3 | ||
28 | #define ADT7310_T_CRIT 4 | ||
29 | #define ADT7310_T_HYST 5 | ||
30 | #define ADT7310_T_ALARM_HIGH 6 | ||
31 | #define ADT7310_T_ALARM_LOW 7 | ||
32 | |||
33 | /* | ||
34 | * ADT7310 status | ||
35 | */ | ||
36 | #define ADT7310_STAT_T_LOW 0x10 | ||
37 | #define ADT7310_STAT_T_HIGH 0x20 | ||
38 | #define ADT7310_STAT_T_CRIT 0x40 | ||
39 | #define ADT7310_STAT_NOT_RDY 0x80 | ||
40 | |||
41 | /* | ||
42 | * ADT7310 config | ||
43 | */ | ||
44 | #define ADT7310_FAULT_QUEUE_MASK 0x3 | ||
45 | #define ADT7310_CT_POLARITY 0x4 | ||
46 | #define ADT7310_INT_POLARITY 0x8 | ||
47 | #define ADT7310_EVENT_MODE 0x10 | ||
48 | #define ADT7310_MODE_MASK 0x60 | ||
49 | #define ADT7310_ONESHOT 0x20 | ||
50 | #define ADT7310_SPS 0x40 | ||
51 | #define ADT7310_PD 0x60 | ||
52 | #define ADT7310_RESOLUTION 0x80 | ||
53 | |||
54 | /* | ||
55 | * ADT7310 masks | ||
56 | */ | ||
57 | #define ADT7310_T16_VALUE_SIGN 0x8000 | ||
58 | #define ADT7310_T16_VALUE_FLOAT_OFFSET 7 | ||
59 | #define ADT7310_T16_VALUE_FLOAT_MASK 0x7F | ||
60 | #define ADT7310_T13_VALUE_SIGN 0x1000 | ||
61 | #define ADT7310_T13_VALUE_OFFSET 3 | ||
62 | #define ADT7310_T13_VALUE_FLOAT_OFFSET 4 | ||
63 | #define ADT7310_T13_VALUE_FLOAT_MASK 0xF | ||
64 | #define ADT7310_T_HYST_MASK 0xF | ||
65 | #define ADT7310_DEVICE_ID_MASK 0x7 | ||
66 | #define ADT7310_MANUFACTORY_ID_MASK 0xF8 | ||
67 | #define ADT7310_MANUFACTORY_ID_OFFSET 3 | ||
68 | |||
69 | |||
70 | #define ADT7310_CMD_REG_MASK 0x28 | ||
71 | #define ADT7310_CMD_REG_OFFSET 3 | ||
72 | #define ADT7310_CMD_READ 0x40 | ||
73 | #define ADT7310_CMD_CON_READ 0x4 | ||
74 | |||
75 | #define ADT7310_IRQS 2 | ||
76 | |||
77 | /* | ||
78 | * struct adt7310_chip_info - chip specifc information | ||
79 | */ | ||
80 | |||
81 | struct adt7310_chip_info { | ||
82 | struct spi_device *spi_dev; | ||
83 | u8 config; | ||
84 | }; | ||
85 | |||
86 | /* | ||
87 | * adt7310 register access by SPI | ||
88 | */ | ||
89 | |||
90 | static int adt7310_spi_read_word(struct adt7310_chip_info *chip, u8 reg, u16 *data) | ||
91 | { | ||
92 | struct spi_device *spi_dev = chip->spi_dev; | ||
93 | u8 command = (reg << ADT7310_CMD_REG_OFFSET) & ADT7310_CMD_REG_MASK; | ||
94 | int ret = 0; | ||
95 | |||
96 | command |= ADT7310_CMD_READ; | ||
97 | ret = spi_write(spi_dev, &command, sizeof(command)); | ||
98 | if (ret < 0) { | ||
99 | dev_err(&spi_dev->dev, "SPI write command error\n"); | ||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | ret = spi_read(spi_dev, (u8 *)data, sizeof(*data)); | ||
104 | if (ret < 0) { | ||
105 | dev_err(&spi_dev->dev, "SPI read word error\n"); | ||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | *data = be16_to_cpu(*data); | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static int adt7310_spi_write_word(struct adt7310_chip_info *chip, u8 reg, u16 data) | ||
115 | { | ||
116 | struct spi_device *spi_dev = chip->spi_dev; | ||
117 | u8 buf[3]; | ||
118 | int ret = 0; | ||
119 | |||
120 | buf[0] = (reg << ADT7310_CMD_REG_OFFSET) & ADT7310_CMD_REG_MASK; | ||
121 | buf[1] = (u8)(data >> 8); | ||
122 | buf[2] = (u8)(data & 0xFF); | ||
123 | |||
124 | ret = spi_write(spi_dev, buf, 3); | ||
125 | if (ret < 0) { | ||
126 | dev_err(&spi_dev->dev, "SPI write word error\n"); | ||
127 | return ret; | ||
128 | } | ||
129 | |||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | static int adt7310_spi_read_byte(struct adt7310_chip_info *chip, u8 reg, u8 *data) | ||
134 | { | ||
135 | struct spi_device *spi_dev = chip->spi_dev; | ||
136 | u8 command = (reg << ADT7310_CMD_REG_OFFSET) & ADT7310_CMD_REG_MASK; | ||
137 | int ret = 0; | ||
138 | |||
139 | command |= ADT7310_CMD_READ; | ||
140 | ret = spi_write(spi_dev, &command, sizeof(command)); | ||
141 | if (ret < 0) { | ||
142 | dev_err(&spi_dev->dev, "SPI write command error\n"); | ||
143 | return ret; | ||
144 | } | ||
145 | |||
146 | ret = spi_read(spi_dev, data, sizeof(*data)); | ||
147 | if (ret < 0) { | ||
148 | dev_err(&spi_dev->dev, "SPI read byte error\n"); | ||
149 | return ret; | ||
150 | } | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static int adt7310_spi_write_byte(struct adt7310_chip_info *chip, u8 reg, u8 data) | ||
156 | { | ||
157 | struct spi_device *spi_dev = chip->spi_dev; | ||
158 | u8 buf[2]; | ||
159 | int ret = 0; | ||
160 | |||
161 | buf[0] = (reg << ADT7310_CMD_REG_OFFSET) & ADT7310_CMD_REG_MASK; | ||
162 | buf[1] = data; | ||
163 | |||
164 | ret = spi_write(spi_dev, buf, 2); | ||
165 | if (ret < 0) { | ||
166 | dev_err(&spi_dev->dev, "SPI write byte error\n"); | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | return ret; | ||
171 | } | ||
172 | |||
173 | static ssize_t adt7310_show_mode(struct device *dev, | ||
174 | struct device_attribute *attr, | ||
175 | char *buf) | ||
176 | { | ||
177 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
178 | struct adt7310_chip_info *chip = iio_priv(dev_info); | ||
179 | u8 config; | ||
180 | |||
181 | config = chip->config & ADT7310_MODE_MASK; | ||
182 | |||
183 | switch (config) { | ||
184 | case ADT7310_PD: | ||
185 | return sprintf(buf, "power-down\n"); | ||
186 | case ADT7310_ONESHOT: | ||
187 | return sprintf(buf, "one-shot\n"); | ||
188 | case ADT7310_SPS: | ||
189 | return sprintf(buf, "sps\n"); | ||
190 | default: | ||
191 | return sprintf(buf, "full\n"); | ||
192 | } | ||
193 | } | ||
194 | |||
195 | static ssize_t adt7310_store_mode(struct device *dev, | ||
196 | struct device_attribute *attr, | ||
197 | const char *buf, | ||
198 | size_t len) | ||
199 | { | ||
200 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
201 | struct adt7310_chip_info *chip = iio_priv(dev_info); | ||
202 | u16 config; | ||
203 | int ret; | ||
204 | |||
205 | ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); | ||
206 | if (ret) | ||
207 | return -EIO; | ||
208 | |||
209 | config = chip->config & (~ADT7310_MODE_MASK); | ||
210 | if (strcmp(buf, "power-down")) | ||
211 | config |= ADT7310_PD; | ||
212 | else if (strcmp(buf, "one-shot")) | ||
213 | config |= ADT7310_ONESHOT; | ||
214 | else if (strcmp(buf, "sps")) | ||
215 | config |= ADT7310_SPS; | ||
216 | |||
217 | ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, config); | ||
218 | if (ret) | ||
219 | return -EIO; | ||
220 | |||
221 | chip->config = config; | ||
222 | |||
223 | return len; | ||
224 | } | ||
225 | |||
226 | static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, | ||
227 | adt7310_show_mode, | ||
228 | adt7310_store_mode, | ||
229 | 0); | ||
230 | |||
231 | static ssize_t adt7310_show_available_modes(struct device *dev, | ||
232 | struct device_attribute *attr, | ||
233 | char *buf) | ||
234 | { | ||
235 | return sprintf(buf, "full\none-shot\nsps\npower-down\n"); | ||
236 | } | ||
237 | |||
238 | static IIO_DEVICE_ATTR(available_modes, S_IRUGO, adt7310_show_available_modes, NULL, 0); | ||
239 | |||
240 | static ssize_t adt7310_show_resolution(struct device *dev, | ||
241 | struct device_attribute *attr, | ||
242 | char *buf) | ||
243 | { | ||
244 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
245 | struct adt7310_chip_info *chip = iio_priv(dev_info); | ||
246 | int ret; | ||
247 | int bits; | ||
248 | |||
249 | ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); | ||
250 | if (ret) | ||
251 | return -EIO; | ||
252 | |||
253 | if (chip->config & ADT7310_RESOLUTION) | ||
254 | bits = 16; | ||
255 | else | ||
256 | bits = 13; | ||
257 | |||
258 | return sprintf(buf, "%d bits\n", bits); | ||
259 | } | ||
260 | |||
261 | static ssize_t adt7310_store_resolution(struct device *dev, | ||
262 | struct device_attribute *attr, | ||
263 | const char *buf, | ||
264 | size_t len) | ||
265 | { | ||
266 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
267 | struct adt7310_chip_info *chip = iio_priv(dev_info); | ||
268 | unsigned long data; | ||
269 | u16 config; | ||
270 | int ret; | ||
271 | |||
272 | ret = strict_strtoul(buf, 10, &data); | ||
273 | if (ret) | ||
274 | return -EINVAL; | ||
275 | |||
276 | ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); | ||
277 | if (ret) | ||
278 | return -EIO; | ||
279 | |||
280 | config = chip->config & (~ADT7310_RESOLUTION); | ||
281 | if (data) | ||
282 | config |= ADT7310_RESOLUTION; | ||
283 | |||
284 | ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, config); | ||
285 | if (ret) | ||
286 | return -EIO; | ||
287 | |||
288 | chip->config = config; | ||
289 | |||
290 | return len; | ||
291 | } | ||
292 | |||
293 | static IIO_DEVICE_ATTR(resolution, S_IRUGO | S_IWUSR, | ||
294 | adt7310_show_resolution, | ||
295 | adt7310_store_resolution, | ||
296 | 0); | ||
297 | |||
298 | static ssize_t adt7310_show_id(struct device *dev, | ||
299 | struct device_attribute *attr, | ||
300 | char *buf) | ||
301 | { | ||
302 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
303 | struct adt7310_chip_info *chip = iio_priv(dev_info); | ||
304 | u8 id; | ||
305 | int ret; | ||
306 | |||
307 | ret = adt7310_spi_read_byte(chip, ADT7310_ID, &id); | ||
308 | if (ret) | ||
309 | return -EIO; | ||
310 | |||
311 | return sprintf(buf, "device id: 0x%x\nmanufactory id: 0x%x\n", | ||
312 | id & ADT7310_DEVICE_ID_MASK, | ||
313 | (id & ADT7310_MANUFACTORY_ID_MASK) >> ADT7310_MANUFACTORY_ID_OFFSET); | ||
314 | } | ||
315 | |||
316 | static IIO_DEVICE_ATTR(id, S_IRUGO | S_IWUSR, | ||
317 | adt7310_show_id, | ||
318 | NULL, | ||
319 | 0); | ||
320 | |||
321 | static ssize_t adt7310_convert_temperature(struct adt7310_chip_info *chip, | ||
322 | u16 data, char *buf) | ||
323 | { | ||
324 | char sign = ' '; | ||
325 | |||
326 | if (chip->config & ADT7310_RESOLUTION) { | ||
327 | if (data & ADT7310_T16_VALUE_SIGN) { | ||
328 | /* convert supplement to positive value */ | ||
329 | data = (u16)((ADT7310_T16_VALUE_SIGN << 1) - (u32)data); | ||
330 | sign = '-'; | ||
331 | } | ||
332 | return sprintf(buf, "%c%d.%.7d\n", sign, | ||
333 | (data >> ADT7310_T16_VALUE_FLOAT_OFFSET), | ||
334 | (data & ADT7310_T16_VALUE_FLOAT_MASK) * 78125); | ||
335 | } else { | ||
336 | if (data & ADT7310_T13_VALUE_SIGN) { | ||
337 | /* convert supplement to positive value */ | ||
338 | data >>= ADT7310_T13_VALUE_OFFSET; | ||
339 | data = (ADT7310_T13_VALUE_SIGN << 1) - data; | ||
340 | sign = '-'; | ||
341 | } | ||
342 | return sprintf(buf, "%c%d.%.4d\n", sign, | ||
343 | (data >> ADT7310_T13_VALUE_FLOAT_OFFSET), | ||
344 | (data & ADT7310_T13_VALUE_FLOAT_MASK) * 625); | ||
345 | } | ||
346 | } | ||
347 | |||
348 | static ssize_t adt7310_show_value(struct device *dev, | ||
349 | struct device_attribute *attr, | ||
350 | char *buf) | ||
351 | { | ||
352 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
353 | struct adt7310_chip_info *chip = iio_priv(dev_info); | ||
354 | u8 status; | ||
355 | u16 data; | ||
356 | int ret, i = 0; | ||
357 | |||
358 | do { | ||
359 | ret = adt7310_spi_read_byte(chip, ADT7310_STATUS, &status); | ||
360 | if (ret) | ||
361 | return -EIO; | ||
362 | i++; | ||
363 | if (i == 10000) | ||
364 | return -EIO; | ||
365 | } while (status & ADT7310_STAT_NOT_RDY); | ||
366 | |||
367 | ret = adt7310_spi_read_word(chip, ADT7310_TEMPERATURE, &data); | ||
368 | if (ret) | ||
369 | return -EIO; | ||
370 | |||
371 | return adt7310_convert_temperature(chip, data, buf); | ||
372 | } | ||
373 | |||
374 | static IIO_DEVICE_ATTR(value, S_IRUGO, adt7310_show_value, NULL, 0); | ||
375 | |||
376 | static struct attribute *adt7310_attributes[] = { | ||
377 | &iio_dev_attr_available_modes.dev_attr.attr, | ||
378 | &iio_dev_attr_mode.dev_attr.attr, | ||
379 | &iio_dev_attr_resolution.dev_attr.attr, | ||
380 | &iio_dev_attr_id.dev_attr.attr, | ||
381 | &iio_dev_attr_value.dev_attr.attr, | ||
382 | NULL, | ||
383 | }; | ||
384 | |||
385 | static const struct attribute_group adt7310_attribute_group = { | ||
386 | .attrs = adt7310_attributes, | ||
387 | }; | ||
388 | |||
389 | static irqreturn_t adt7310_event_handler(int irq, void *private) | ||
390 | { | ||
391 | struct iio_dev *indio_dev = private; | ||
392 | struct adt7310_chip_info *chip = iio_priv(indio_dev); | ||
393 | s64 timestamp = iio_get_time_ns(); | ||
394 | u8 status; | ||
395 | int ret; | ||
396 | |||
397 | ret = adt7310_spi_read_byte(chip, ADT7310_STATUS, &status); | ||
398 | if (ret) | ||
399 | return ret; | ||
400 | |||
401 | if (status & ADT7310_STAT_T_HIGH) | ||
402 | iio_push_event(indio_dev, 0, | ||
403 | IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, | ||
404 | IIO_EV_TYPE_THRESH, | ||
405 | IIO_EV_DIR_RISING), | ||
406 | timestamp); | ||
407 | if (status & ADT7310_STAT_T_LOW) | ||
408 | iio_push_event(indio_dev, 0, | ||
409 | IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, | ||
410 | IIO_EV_TYPE_THRESH, | ||
411 | IIO_EV_DIR_FALLING), | ||
412 | timestamp); | ||
413 | if (status & ADT7310_STAT_T_CRIT) | ||
414 | iio_push_event(indio_dev, 0, | ||
415 | IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, | ||
416 | IIO_EV_TYPE_THRESH, | ||
417 | IIO_EV_DIR_RISING), | ||
418 | timestamp); | ||
419 | return IRQ_HANDLED; | ||
420 | } | ||
421 | |||
422 | static ssize_t adt7310_show_event_mode(struct device *dev, | ||
423 | struct device_attribute *attr, | ||
424 | char *buf) | ||
425 | { | ||
426 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
427 | struct adt7310_chip_info *chip = iio_priv(dev_info); | ||
428 | int ret; | ||
429 | |||
430 | ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); | ||
431 | if (ret) | ||
432 | return -EIO; | ||
433 | |||
434 | if (chip->config & ADT7310_EVENT_MODE) | ||
435 | return sprintf(buf, "interrupt\n"); | ||
436 | else | ||
437 | return sprintf(buf, "comparator\n"); | ||
438 | } | ||
439 | |||
440 | static ssize_t adt7310_set_event_mode(struct device *dev, | ||
441 | struct device_attribute *attr, | ||
442 | const char *buf, | ||
443 | size_t len) | ||
444 | { | ||
445 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
446 | struct adt7310_chip_info *chip = iio_priv(dev_info); | ||
447 | u16 config; | ||
448 | int ret; | ||
449 | |||
450 | ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); | ||
451 | if (ret) | ||
452 | return -EIO; | ||
453 | |||
454 | config = chip->config &= ~ADT7310_EVENT_MODE; | ||
455 | if (strcmp(buf, "comparator") != 0) | ||
456 | config |= ADT7310_EVENT_MODE; | ||
457 | |||
458 | ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, config); | ||
459 | if (ret) | ||
460 | return -EIO; | ||
461 | |||
462 | chip->config = config; | ||
463 | |||
464 | return len; | ||
465 | } | ||
466 | |||
467 | static ssize_t adt7310_show_available_event_modes(struct device *dev, | ||
468 | struct device_attribute *attr, | ||
469 | char *buf) | ||
470 | { | ||
471 | return sprintf(buf, "comparator\ninterrupt\n"); | ||
472 | } | ||
473 | |||
474 | static ssize_t adt7310_show_fault_queue(struct device *dev, | ||
475 | struct device_attribute *attr, | ||
476 | char *buf) | ||
477 | { | ||
478 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
479 | struct adt7310_chip_info *chip = iio_priv(dev_info); | ||
480 | int ret; | ||
481 | |||
482 | ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); | ||
483 | if (ret) | ||
484 | return -EIO; | ||
485 | |||
486 | return sprintf(buf, "%d\n", chip->config & ADT7310_FAULT_QUEUE_MASK); | ||
487 | } | ||
488 | |||
489 | static ssize_t adt7310_set_fault_queue(struct device *dev, | ||
490 | struct device_attribute *attr, | ||
491 | const char *buf, | ||
492 | size_t len) | ||
493 | { | ||
494 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
495 | struct adt7310_chip_info *chip = iio_priv(dev_info); | ||
496 | unsigned long data; | ||
497 | int ret; | ||
498 | u8 config; | ||
499 | |||
500 | ret = strict_strtoul(buf, 10, &data); | ||
501 | if (ret || data > 3) | ||
502 | return -EINVAL; | ||
503 | |||
504 | ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); | ||
505 | if (ret) | ||
506 | return -EIO; | ||
507 | |||
508 | config = chip->config & ~ADT7310_FAULT_QUEUE_MASK; | ||
509 | config |= data; | ||
510 | ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, config); | ||
511 | if (ret) | ||
512 | return -EIO; | ||
513 | |||
514 | chip->config = config; | ||
515 | |||
516 | return len; | ||
517 | } | ||
518 | |||
519 | static inline ssize_t adt7310_show_t_bound(struct device *dev, | ||
520 | struct device_attribute *attr, | ||
521 | u8 bound_reg, | ||
522 | char *buf) | ||
523 | { | ||
524 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
525 | struct adt7310_chip_info *chip = iio_priv(dev_info); | ||
526 | u16 data; | ||
527 | int ret; | ||
528 | |||
529 | ret = adt7310_spi_read_word(chip, bound_reg, &data); | ||
530 | if (ret) | ||
531 | return -EIO; | ||
532 | |||
533 | return adt7310_convert_temperature(chip, data, buf); | ||
534 | } | ||
535 | |||
536 | static inline ssize_t adt7310_set_t_bound(struct device *dev, | ||
537 | struct device_attribute *attr, | ||
538 | u8 bound_reg, | ||
539 | const char *buf, | ||
540 | size_t len) | ||
541 | { | ||
542 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
543 | struct adt7310_chip_info *chip = iio_priv(dev_info); | ||
544 | long tmp1, tmp2; | ||
545 | u16 data; | ||
546 | char *pos; | ||
547 | int ret; | ||
548 | |||
549 | pos = strchr(buf, '.'); | ||
550 | |||
551 | ret = strict_strtol(buf, 10, &tmp1); | ||
552 | |||
553 | if (ret || tmp1 > 127 || tmp1 < -128) | ||
554 | return -EINVAL; | ||
555 | |||
556 | if (pos) { | ||
557 | len = strlen(pos); | ||
558 | |||
559 | if (chip->config & ADT7310_RESOLUTION) { | ||
560 | if (len > ADT7310_T16_VALUE_FLOAT_OFFSET) | ||
561 | len = ADT7310_T16_VALUE_FLOAT_OFFSET; | ||
562 | pos[len] = 0; | ||
563 | ret = strict_strtol(pos, 10, &tmp2); | ||
564 | |||
565 | if (!ret) | ||
566 | tmp2 = (tmp2 / 78125) * 78125; | ||
567 | } else { | ||
568 | if (len > ADT7310_T13_VALUE_FLOAT_OFFSET) | ||
569 | len = ADT7310_T13_VALUE_FLOAT_OFFSET; | ||
570 | pos[len] = 0; | ||
571 | ret = strict_strtol(pos, 10, &tmp2); | ||
572 | |||
573 | if (!ret) | ||
574 | tmp2 = (tmp2 / 625) * 625; | ||
575 | } | ||
576 | } | ||
577 | |||
578 | if (tmp1 < 0) | ||
579 | data = (u16)(-tmp1); | ||
580 | else | ||
581 | data = (u16)tmp1; | ||
582 | |||
583 | if (chip->config & ADT7310_RESOLUTION) { | ||
584 | data = (data << ADT7310_T16_VALUE_FLOAT_OFFSET) | | ||
585 | (tmp2 & ADT7310_T16_VALUE_FLOAT_MASK); | ||
586 | |||
587 | if (tmp1 < 0) | ||
588 | /* convert positive value to supplyment */ | ||
589 | data = (u16)((ADT7310_T16_VALUE_SIGN << 1) - (u32)data); | ||
590 | } else { | ||
591 | data = (data << ADT7310_T13_VALUE_FLOAT_OFFSET) | | ||
592 | (tmp2 & ADT7310_T13_VALUE_FLOAT_MASK); | ||
593 | |||
594 | if (tmp1 < 0) | ||
595 | /* convert positive value to supplyment */ | ||
596 | data = (ADT7310_T13_VALUE_SIGN << 1) - data; | ||
597 | data <<= ADT7310_T13_VALUE_OFFSET; | ||
598 | } | ||
599 | |||
600 | ret = adt7310_spi_write_word(chip, bound_reg, data); | ||
601 | if (ret) | ||
602 | return -EIO; | ||
603 | |||
604 | return len; | ||
605 | } | ||
606 | |||
607 | static ssize_t adt7310_show_t_alarm_high(struct device *dev, | ||
608 | struct device_attribute *attr, | ||
609 | char *buf) | ||
610 | { | ||
611 | return adt7310_show_t_bound(dev, attr, | ||
612 | ADT7310_T_ALARM_HIGH, buf); | ||
613 | } | ||
614 | |||
615 | static inline ssize_t adt7310_set_t_alarm_high(struct device *dev, | ||
616 | struct device_attribute *attr, | ||
617 | const char *buf, | ||
618 | size_t len) | ||
619 | { | ||
620 | return adt7310_set_t_bound(dev, attr, | ||
621 | ADT7310_T_ALARM_HIGH, buf, len); | ||
622 | } | ||
623 | |||
624 | static ssize_t adt7310_show_t_alarm_low(struct device *dev, | ||
625 | struct device_attribute *attr, | ||
626 | char *buf) | ||
627 | { | ||
628 | return adt7310_show_t_bound(dev, attr, | ||
629 | ADT7310_T_ALARM_LOW, buf); | ||
630 | } | ||
631 | |||
632 | static inline ssize_t adt7310_set_t_alarm_low(struct device *dev, | ||
633 | struct device_attribute *attr, | ||
634 | const char *buf, | ||
635 | size_t len) | ||
636 | { | ||
637 | return adt7310_set_t_bound(dev, attr, | ||
638 | ADT7310_T_ALARM_LOW, buf, len); | ||
639 | } | ||
640 | |||
641 | static ssize_t adt7310_show_t_crit(struct device *dev, | ||
642 | struct device_attribute *attr, | ||
643 | char *buf) | ||
644 | { | ||
645 | return adt7310_show_t_bound(dev, attr, | ||
646 | ADT7310_T_CRIT, buf); | ||
647 | } | ||
648 | |||
649 | static inline ssize_t adt7310_set_t_crit(struct device *dev, | ||
650 | struct device_attribute *attr, | ||
651 | const char *buf, | ||
652 | size_t len) | ||
653 | { | ||
654 | return adt7310_set_t_bound(dev, attr, | ||
655 | ADT7310_T_CRIT, buf, len); | ||
656 | } | ||
657 | |||
658 | static ssize_t adt7310_show_t_hyst(struct device *dev, | ||
659 | struct device_attribute *attr, | ||
660 | char *buf) | ||
661 | { | ||
662 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
663 | struct adt7310_chip_info *chip = iio_priv(dev_info); | ||
664 | int ret; | ||
665 | u8 t_hyst; | ||
666 | |||
667 | ret = adt7310_spi_read_byte(chip, ADT7310_T_HYST, &t_hyst); | ||
668 | if (ret) | ||
669 | return -EIO; | ||
670 | |||
671 | return sprintf(buf, "%d\n", t_hyst & ADT7310_T_HYST_MASK); | ||
672 | } | ||
673 | |||
674 | static inline ssize_t adt7310_set_t_hyst(struct device *dev, | ||
675 | struct device_attribute *attr, | ||
676 | const char *buf, | ||
677 | size_t len) | ||
678 | { | ||
679 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
680 | struct adt7310_chip_info *chip = iio_priv(dev_info); | ||
681 | int ret; | ||
682 | unsigned long data; | ||
683 | u8 t_hyst; | ||
684 | |||
685 | ret = strict_strtol(buf, 10, &data); | ||
686 | |||
687 | if (ret || data > ADT7310_T_HYST_MASK) | ||
688 | return -EINVAL; | ||
689 | |||
690 | t_hyst = (u8)data; | ||
691 | |||
692 | ret = adt7310_spi_write_byte(chip, ADT7310_T_HYST, t_hyst); | ||
693 | if (ret) | ||
694 | return -EIO; | ||
695 | |||
696 | return len; | ||
697 | } | ||
698 | |||
699 | static IIO_DEVICE_ATTR(event_mode, | ||
700 | S_IRUGO | S_IWUSR, | ||
701 | adt7310_show_event_mode, adt7310_set_event_mode, 0); | ||
702 | static IIO_DEVICE_ATTR(available_event_modes, | ||
703 | S_IRUGO | S_IWUSR, | ||
704 | adt7310_show_available_event_modes, NULL, 0); | ||
705 | static IIO_DEVICE_ATTR(fault_queue, | ||
706 | S_IRUGO | S_IWUSR, | ||
707 | adt7310_show_fault_queue, adt7310_set_fault_queue, 0); | ||
708 | static IIO_DEVICE_ATTR(t_alarm_high, | ||
709 | S_IRUGO | S_IWUSR, | ||
710 | adt7310_show_t_alarm_high, adt7310_set_t_alarm_high, 0); | ||
711 | static IIO_DEVICE_ATTR(t_alarm_low, | ||
712 | S_IRUGO | S_IWUSR, | ||
713 | adt7310_show_t_alarm_low, adt7310_set_t_alarm_low, 0); | ||
714 | static IIO_DEVICE_ATTR(t_crit, | ||
715 | S_IRUGO | S_IWUSR, | ||
716 | adt7310_show_t_crit, adt7310_set_t_crit, 0); | ||
717 | static IIO_DEVICE_ATTR(t_hyst, | ||
718 | S_IRUGO | S_IWUSR, | ||
719 | adt7310_show_t_hyst, adt7310_set_t_hyst, 0); | ||
720 | |||
721 | static struct attribute *adt7310_event_int_attributes[] = { | ||
722 | &iio_dev_attr_event_mode.dev_attr.attr, | ||
723 | &iio_dev_attr_available_event_modes.dev_attr.attr, | ||
724 | &iio_dev_attr_fault_queue.dev_attr.attr, | ||
725 | &iio_dev_attr_t_alarm_high.dev_attr.attr, | ||
726 | &iio_dev_attr_t_alarm_low.dev_attr.attr, | ||
727 | &iio_dev_attr_t_hyst.dev_attr.attr, | ||
728 | NULL, | ||
729 | }; | ||
730 | |||
731 | static struct attribute *adt7310_event_ct_attributes[] = { | ||
732 | &iio_dev_attr_event_mode.dev_attr.attr, | ||
733 | &iio_dev_attr_available_event_modes.dev_attr.attr, | ||
734 | &iio_dev_attr_fault_queue.dev_attr.attr, | ||
735 | &iio_dev_attr_t_crit.dev_attr.attr, | ||
736 | &iio_dev_attr_t_hyst.dev_attr.attr, | ||
737 | NULL, | ||
738 | }; | ||
739 | |||
740 | static struct attribute_group adt7310_event_attribute_group[ADT7310_IRQS] = { | ||
741 | { | ||
742 | .attrs = adt7310_event_int_attributes, | ||
743 | }, { | ||
744 | .attrs = adt7310_event_ct_attributes, | ||
745 | } | ||
746 | }; | ||
747 | |||
748 | static const struct iio_info adt7310_info = { | ||
749 | .attrs = &adt7310_attribute_group, | ||
750 | .num_interrupt_lines = ADT7310_IRQS, | ||
751 | .event_attrs = adt7310_event_attribute_group, | ||
752 | .driver_module = THIS_MODULE, | ||
753 | }; | ||
754 | |||
755 | /* | ||
756 | * device probe and remove | ||
757 | */ | ||
758 | |||
759 | static int __devinit adt7310_probe(struct spi_device *spi_dev) | ||
760 | { | ||
761 | struct adt7310_chip_info *chip; | ||
762 | struct iio_dev *indio_dev; | ||
763 | int ret = 0; | ||
764 | unsigned long *adt7310_platform_data = spi_dev->dev.platform_data; | ||
765 | unsigned long irq_flags; | ||
766 | |||
767 | indio_dev = iio_allocate_device(sizeof(*chip)); | ||
768 | if (indio_dev == NULL) { | ||
769 | ret = -ENOMEM; | ||
770 | goto error_ret; | ||
771 | } | ||
772 | chip = iio_priv(indio_dev); | ||
773 | /* this is only used for device removal purposes */ | ||
774 | dev_set_drvdata(&spi_dev->dev, indio_dev); | ||
775 | |||
776 | chip->spi_dev = spi_dev; | ||
777 | |||
778 | indio_dev->dev.parent = &spi_dev->dev; | ||
779 | indio_dev->name = spi_get_device_id(spi_dev)->name; | ||
780 | indio_dev->info = &adt7310_info; | ||
781 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
782 | |||
783 | ret = iio_device_register(indio_dev); | ||
784 | if (ret) | ||
785 | goto error_free_dev; | ||
786 | |||
787 | /* CT critcal temperature event. line 0 */ | ||
788 | if (spi_dev->irq) { | ||
789 | if (adt7310_platform_data[2]) | ||
790 | irq_flags = adt7310_platform_data[2]; | ||
791 | else | ||
792 | irq_flags = IRQF_TRIGGER_LOW; | ||
793 | ret = request_threaded_irq(spi_dev->irq, | ||
794 | NULL, | ||
795 | &adt7310_event_handler, | ||
796 | irq_flags, | ||
797 | indio_dev->name, | ||
798 | indio_dev); | ||
799 | if (ret) | ||
800 | goto error_unreg_dev; | ||
801 | } | ||
802 | |||
803 | /* INT bound temperature alarm event. line 1 */ | ||
804 | if (adt7310_platform_data[0]) { | ||
805 | ret = request_threaded_irq(adt7310_platform_data[0], | ||
806 | NULL, | ||
807 | &adt7310_event_handler, | ||
808 | adt7310_platform_data[1], | ||
809 | indio_dev->name, | ||
810 | indio_dev); | ||
811 | if (ret) | ||
812 | goto error_unreg_ct_irq; | ||
813 | } | ||
814 | |||
815 | if (spi_dev->irq && adt7310_platform_data[0]) { | ||
816 | ret = adt7310_spi_read_byte(chip, ADT7310_CONFIG, &chip->config); | ||
817 | if (ret) { | ||
818 | ret = -EIO; | ||
819 | goto error_unreg_int_irq; | ||
820 | } | ||
821 | |||
822 | /* set irq polarity low level */ | ||
823 | chip->config &= ~ADT7310_CT_POLARITY; | ||
824 | |||
825 | if (adt7310_platform_data[1] & IRQF_TRIGGER_HIGH) | ||
826 | chip->config |= ADT7310_INT_POLARITY; | ||
827 | else | ||
828 | chip->config &= ~ADT7310_INT_POLARITY; | ||
829 | |||
830 | ret = adt7310_spi_write_byte(chip, ADT7310_CONFIG, chip->config); | ||
831 | if (ret) { | ||
832 | ret = -EIO; | ||
833 | goto error_unreg_int_irq; | ||
834 | } | ||
835 | } | ||
836 | |||
837 | dev_info(&spi_dev->dev, "%s temperature sensor registered.\n", | ||
838 | indio_dev->name); | ||
839 | |||
840 | return 0; | ||
841 | |||
842 | error_unreg_int_irq: | ||
843 | free_irq(adt7310_platform_data[0], indio_dev); | ||
844 | error_unreg_ct_irq: | ||
845 | free_irq(spi_dev->irq, indio_dev); | ||
846 | error_unreg_dev: | ||
847 | iio_device_unregister(indio_dev); | ||
848 | error_free_dev: | ||
849 | iio_free_device(indio_dev); | ||
850 | error_ret: | ||
851 | return ret; | ||
852 | } | ||
853 | |||
854 | static int __devexit adt7310_remove(struct spi_device *spi_dev) | ||
855 | { | ||
856 | struct iio_dev *indio_dev = dev_get_drvdata(&spi_dev->dev); | ||
857 | unsigned long *adt7310_platform_data = spi_dev->dev.platform_data; | ||
858 | |||
859 | dev_set_drvdata(&spi_dev->dev, NULL); | ||
860 | if (adt7310_platform_data[0]) | ||
861 | free_irq(adt7310_platform_data[0], indio_dev); | ||
862 | if (spi_dev->irq) | ||
863 | free_irq(spi_dev->irq, indio_dev); | ||
864 | iio_device_unregister(indio_dev); | ||
865 | iio_free_device(indio_dev); | ||
866 | |||
867 | return 0; | ||
868 | } | ||
869 | |||
870 | static const struct spi_device_id adt7310_id[] = { | ||
871 | { "adt7310", 0 }, | ||
872 | {} | ||
873 | }; | ||
874 | |||
875 | MODULE_DEVICE_TABLE(spi, adt7310_id); | ||
876 | |||
877 | static struct spi_driver adt7310_driver = { | ||
878 | .driver = { | ||
879 | .name = "adt7310", | ||
880 | .bus = &spi_bus_type, | ||
881 | .owner = THIS_MODULE, | ||
882 | }, | ||
883 | .probe = adt7310_probe, | ||
884 | .remove = __devexit_p(adt7310_remove), | ||
885 | .id_table = adt7310_id, | ||
886 | }; | ||
887 | |||
888 | static __init int adt7310_init(void) | ||
889 | { | ||
890 | return spi_register_driver(&adt7310_driver); | ||
891 | } | ||
892 | |||
893 | static __exit void adt7310_exit(void) | ||
894 | { | ||
895 | spi_unregister_driver(&adt7310_driver); | ||
896 | } | ||
897 | |||
898 | MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>"); | ||
899 | MODULE_DESCRIPTION("Analog Devices ADT7310 digital" | ||
900 | " temperature sensor driver"); | ||
901 | MODULE_LICENSE("GPL v2"); | ||
902 | |||
903 | module_init(adt7310_init); | ||
904 | module_exit(adt7310_exit); | ||
diff --git a/drivers/staging/iio/adc/adt75.c b/drivers/staging/iio/adc/adt75.c new file mode 100644 index 00000000000..38f141de6a4 --- /dev/null +++ b/drivers/staging/iio/adc/adt75.c | |||
@@ -0,0 +1,657 @@ | |||
1 | /* | ||
2 | * ADT75 digital temperature sensor driver supporting ADT75 | ||
3 | * | ||
4 | * Copyright 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
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/i2c.h> | ||
15 | |||
16 | #include "../iio.h" | ||
17 | #include "../sysfs.h" | ||
18 | |||
19 | /* | ||
20 | * ADT75 registers definition | ||
21 | */ | ||
22 | |||
23 | #define ADT75_TEMPERATURE 0 | ||
24 | #define ADT75_CONFIG 1 | ||
25 | #define ADT75_T_HYST 2 | ||
26 | #define ADT75_T_OS 3 | ||
27 | #define ADT75_ONESHOT 4 | ||
28 | |||
29 | /* | ||
30 | * ADT75 config | ||
31 | */ | ||
32 | #define ADT75_PD 0x1 | ||
33 | #define ADT75_OS_INT 0x2 | ||
34 | #define ADT75_OS_POLARITY 0x4 | ||
35 | #define ADT75_FAULT_QUEUE_MASK 0x18 | ||
36 | #define ADT75_FAULT_QUEUE_OFFSET 3 | ||
37 | #define ADT75_SMBUS_ALART 0x8 | ||
38 | |||
39 | /* | ||
40 | * ADT75 masks | ||
41 | */ | ||
42 | #define ADT75_VALUE_SIGN 0x800 | ||
43 | #define ADT75_VALUE_OFFSET 4 | ||
44 | #define ADT75_VALUE_FLOAT_OFFSET 4 | ||
45 | #define ADT75_VALUE_FLOAT_MASK 0xF | ||
46 | |||
47 | |||
48 | /* | ||
49 | * struct adt75_chip_info - chip specifc information | ||
50 | */ | ||
51 | |||
52 | struct adt75_chip_info { | ||
53 | struct i2c_client *client; | ||
54 | u8 config; | ||
55 | }; | ||
56 | |||
57 | /* | ||
58 | * adt75 register access by I2C | ||
59 | */ | ||
60 | |||
61 | static int adt75_i2c_read(struct iio_dev *dev_info, u8 reg, u8 *data) | ||
62 | { | ||
63 | struct adt75_chip_info *chip = iio_priv(dev_info); | ||
64 | struct i2c_client *client = chip->client; | ||
65 | int ret = 0, len; | ||
66 | |||
67 | ret = i2c_smbus_write_byte(client, reg); | ||
68 | if (ret < 0) { | ||
69 | dev_err(&client->dev, "I2C read register address error\n"); | ||
70 | return ret; | ||
71 | } | ||
72 | |||
73 | if (reg == ADT75_CONFIG || reg == ADT75_ONESHOT) | ||
74 | len = 1; | ||
75 | else | ||
76 | len = 2; | ||
77 | |||
78 | ret = i2c_master_recv(client, data, len); | ||
79 | if (ret < 0) { | ||
80 | dev_err(&client->dev, "I2C read error\n"); | ||
81 | return ret; | ||
82 | } | ||
83 | |||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | static int adt75_i2c_write(struct iio_dev *dev_info, u8 reg, u8 data) | ||
88 | { | ||
89 | struct adt75_chip_info *chip = iio_priv(dev_info); | ||
90 | struct i2c_client *client = chip->client; | ||
91 | int ret = 0; | ||
92 | |||
93 | if (reg == ADT75_CONFIG || reg == ADT75_ONESHOT) | ||
94 | ret = i2c_smbus_write_byte_data(client, reg, data); | ||
95 | else | ||
96 | ret = i2c_smbus_write_word_data(client, reg, data); | ||
97 | |||
98 | if (ret < 0) | ||
99 | dev_err(&client->dev, "I2C write error\n"); | ||
100 | |||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | static ssize_t adt75_show_mode(struct device *dev, | ||
105 | struct device_attribute *attr, | ||
106 | char *buf) | ||
107 | { | ||
108 | struct adt75_chip_info *chip = iio_priv(dev_get_drvdata(dev)); | ||
109 | |||
110 | if (chip->config & ADT75_PD) | ||
111 | return sprintf(buf, "power-save\n"); | ||
112 | else | ||
113 | return sprintf(buf, "full\n"); | ||
114 | } | ||
115 | |||
116 | static ssize_t adt75_store_mode(struct device *dev, | ||
117 | struct device_attribute *attr, | ||
118 | const char *buf, | ||
119 | size_t len) | ||
120 | { | ||
121 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
122 | struct adt75_chip_info *chip = iio_priv(dev_info); | ||
123 | int ret; | ||
124 | u8 config; | ||
125 | |||
126 | ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config); | ||
127 | if (ret) | ||
128 | return -EIO; | ||
129 | |||
130 | config = chip->config & ~ADT75_PD; | ||
131 | if (!strcmp(buf, "full")) | ||
132 | config |= ADT75_PD; | ||
133 | |||
134 | ret = adt75_i2c_write(dev_info, ADT75_CONFIG, config); | ||
135 | if (ret) | ||
136 | return -EIO; | ||
137 | |||
138 | chip->config = config; | ||
139 | |||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, | ||
144 | adt75_show_mode, | ||
145 | adt75_store_mode, | ||
146 | 0); | ||
147 | |||
148 | static ssize_t adt75_show_available_modes(struct device *dev, | ||
149 | struct device_attribute *attr, | ||
150 | char *buf) | ||
151 | { | ||
152 | return sprintf(buf, "full\npower-down\n"); | ||
153 | } | ||
154 | |||
155 | static IIO_DEVICE_ATTR(available_modes, S_IRUGO, adt75_show_available_modes, NULL, 0); | ||
156 | |||
157 | static ssize_t adt75_show_oneshot(struct device *dev, | ||
158 | struct device_attribute *attr, | ||
159 | char *buf) | ||
160 | { | ||
161 | struct adt75_chip_info *chip = iio_priv(dev_get_drvdata(dev)); | ||
162 | |||
163 | return sprintf(buf, "%d\n", !!(chip->config & ADT75_ONESHOT)); | ||
164 | } | ||
165 | |||
166 | static ssize_t adt75_store_oneshot(struct device *dev, | ||
167 | struct device_attribute *attr, | ||
168 | const char *buf, | ||
169 | size_t len) | ||
170 | { | ||
171 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
172 | struct adt75_chip_info *chip = iio_priv(dev_info); | ||
173 | unsigned long data = 0; | ||
174 | int ret; | ||
175 | u8 config; | ||
176 | |||
177 | ret = strict_strtoul(buf, 10, &data); | ||
178 | if (ret) | ||
179 | return -EINVAL; | ||
180 | |||
181 | |||
182 | ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config); | ||
183 | if (ret) | ||
184 | return -EIO; | ||
185 | |||
186 | config = chip->config & ~ADT75_ONESHOT; | ||
187 | if (data) | ||
188 | config |= ADT75_ONESHOT; | ||
189 | |||
190 | ret = adt75_i2c_write(dev_info, ADT75_CONFIG, config); | ||
191 | if (ret) | ||
192 | return -EIO; | ||
193 | |||
194 | chip->config = config; | ||
195 | |||
196 | return ret; | ||
197 | } | ||
198 | |||
199 | static IIO_DEVICE_ATTR(oneshot, S_IRUGO | S_IWUSR, | ||
200 | adt75_show_oneshot, | ||
201 | adt75_store_oneshot, | ||
202 | 0); | ||
203 | |||
204 | static ssize_t adt75_show_value(struct device *dev, | ||
205 | struct device_attribute *attr, | ||
206 | char *buf) | ||
207 | { | ||
208 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
209 | struct adt75_chip_info *chip = iio_priv(dev_info); | ||
210 | u16 data; | ||
211 | char sign = ' '; | ||
212 | int ret; | ||
213 | |||
214 | if (chip->config & ADT75_PD) { | ||
215 | dev_err(dev, "Can't read value in power-down mode.\n"); | ||
216 | return -EIO; | ||
217 | } | ||
218 | |||
219 | if (chip->config & ADT75_ONESHOT) { | ||
220 | /* write to active converter */ | ||
221 | ret = i2c_smbus_write_byte(chip->client, ADT75_ONESHOT); | ||
222 | if (ret) | ||
223 | return -EIO; | ||
224 | } | ||
225 | |||
226 | ret = adt75_i2c_read(dev_info, ADT75_TEMPERATURE, (u8 *)&data); | ||
227 | if (ret) | ||
228 | return -EIO; | ||
229 | |||
230 | data = swab16(data) >> ADT75_VALUE_OFFSET; | ||
231 | if (data & ADT75_VALUE_SIGN) { | ||
232 | /* convert supplement to positive value */ | ||
233 | data = (ADT75_VALUE_SIGN << 1) - data; | ||
234 | sign = '-'; | ||
235 | } | ||
236 | |||
237 | return sprintf(buf, "%c%d.%.4d\n", sign, | ||
238 | (data >> ADT75_VALUE_FLOAT_OFFSET), | ||
239 | (data & ADT75_VALUE_FLOAT_MASK) * 625); | ||
240 | } | ||
241 | |||
242 | static IIO_DEVICE_ATTR(value, S_IRUGO, adt75_show_value, NULL, 0); | ||
243 | |||
244 | static struct attribute *adt75_attributes[] = { | ||
245 | &iio_dev_attr_available_modes.dev_attr.attr, | ||
246 | &iio_dev_attr_mode.dev_attr.attr, | ||
247 | &iio_dev_attr_oneshot.dev_attr.attr, | ||
248 | &iio_dev_attr_value.dev_attr.attr, | ||
249 | NULL, | ||
250 | }; | ||
251 | |||
252 | static const struct attribute_group adt75_attribute_group = { | ||
253 | .attrs = adt75_attributes, | ||
254 | }; | ||
255 | |||
256 | /* | ||
257 | * temperature bound events | ||
258 | */ | ||
259 | |||
260 | #define IIO_EVENT_CODE_ADT75_OTI IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_TEMP, \ | ||
261 | 0, \ | ||
262 | IIO_EV_TYPE_THRESH, \ | ||
263 | IIO_EV_DIR_FALLING) | ||
264 | |||
265 | static irqreturn_t adt75_event_handler(int irq, void *private) | ||
266 | { | ||
267 | iio_push_event(private, 0, | ||
268 | IIO_EVENT_CODE_ADT75_OTI, | ||
269 | iio_get_time_ns()); | ||
270 | |||
271 | return IRQ_HANDLED; | ||
272 | } | ||
273 | |||
274 | static ssize_t adt75_show_oti_mode(struct device *dev, | ||
275 | struct device_attribute *attr, | ||
276 | char *buf) | ||
277 | { | ||
278 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
279 | struct adt75_chip_info *chip = iio_priv(dev_info); | ||
280 | int ret; | ||
281 | |||
282 | /* retrive ALART status */ | ||
283 | ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config); | ||
284 | if (ret) | ||
285 | return -EIO; | ||
286 | |||
287 | if (chip->config & ADT75_OS_INT) | ||
288 | return sprintf(buf, "interrupt\n"); | ||
289 | else | ||
290 | return sprintf(buf, "comparator\n"); | ||
291 | } | ||
292 | |||
293 | static ssize_t adt75_set_oti_mode(struct device *dev, | ||
294 | struct device_attribute *attr, | ||
295 | const char *buf, | ||
296 | size_t len) | ||
297 | { | ||
298 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
299 | struct adt75_chip_info *chip = iio_priv(dev_info); | ||
300 | int ret; | ||
301 | u8 config; | ||
302 | |||
303 | /* retrive ALART status */ | ||
304 | ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config); | ||
305 | if (ret) | ||
306 | return -EIO; | ||
307 | |||
308 | config = chip->config & ~ADT75_OS_INT; | ||
309 | if (strcmp(buf, "comparator") != 0) | ||
310 | config |= ADT75_OS_INT; | ||
311 | |||
312 | ret = adt75_i2c_write(dev_info, ADT75_CONFIG, config); | ||
313 | if (ret) | ||
314 | return -EIO; | ||
315 | |||
316 | chip->config = config; | ||
317 | |||
318 | return ret; | ||
319 | } | ||
320 | |||
321 | static ssize_t adt75_show_available_oti_modes(struct device *dev, | ||
322 | struct device_attribute *attr, | ||
323 | char *buf) | ||
324 | { | ||
325 | return sprintf(buf, "comparator\ninterrupt\n"); | ||
326 | } | ||
327 | |||
328 | static ssize_t adt75_show_smbus_alart(struct device *dev, | ||
329 | struct device_attribute *attr, | ||
330 | char *buf) | ||
331 | { | ||
332 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
333 | struct adt75_chip_info *chip = iio_priv(dev_info); | ||
334 | int ret; | ||
335 | |||
336 | /* retrive ALART status */ | ||
337 | ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config); | ||
338 | if (ret) | ||
339 | return -EIO; | ||
340 | |||
341 | return sprintf(buf, "%d\n", !!(chip->config & ADT75_SMBUS_ALART)); | ||
342 | } | ||
343 | |||
344 | static ssize_t adt75_set_smbus_alart(struct device *dev, | ||
345 | struct device_attribute *attr, | ||
346 | const char *buf, | ||
347 | size_t len) | ||
348 | { | ||
349 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
350 | struct adt75_chip_info *chip = iio_priv(dev_info); | ||
351 | unsigned long data = 0; | ||
352 | int ret; | ||
353 | u8 config; | ||
354 | |||
355 | ret = strict_strtoul(buf, 10, &data); | ||
356 | if (ret) | ||
357 | return -EINVAL; | ||
358 | |||
359 | /* retrive ALART status */ | ||
360 | ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config); | ||
361 | if (ret) | ||
362 | return -EIO; | ||
363 | |||
364 | config = chip->config & ~ADT75_SMBUS_ALART; | ||
365 | if (data) | ||
366 | config |= ADT75_SMBUS_ALART; | ||
367 | |||
368 | ret = adt75_i2c_write(dev_info, ADT75_CONFIG, config); | ||
369 | if (ret) | ||
370 | return -EIO; | ||
371 | |||
372 | chip->config = config; | ||
373 | |||
374 | return ret; | ||
375 | } | ||
376 | |||
377 | static ssize_t adt75_show_fault_queue(struct device *dev, | ||
378 | struct device_attribute *attr, | ||
379 | char *buf) | ||
380 | { | ||
381 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
382 | struct adt75_chip_info *chip = iio_priv(dev_info); | ||
383 | int ret; | ||
384 | |||
385 | /* retrive ALART status */ | ||
386 | ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config); | ||
387 | if (ret) | ||
388 | return -EIO; | ||
389 | |||
390 | return sprintf(buf, "%d\n", (chip->config & ADT75_FAULT_QUEUE_MASK) >> | ||
391 | ADT75_FAULT_QUEUE_OFFSET); | ||
392 | } | ||
393 | |||
394 | static ssize_t adt75_set_fault_queue(struct device *dev, | ||
395 | struct device_attribute *attr, | ||
396 | const char *buf, | ||
397 | size_t len) | ||
398 | { | ||
399 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
400 | struct adt75_chip_info *chip = iio_priv(dev_info); | ||
401 | unsigned long data; | ||
402 | int ret; | ||
403 | u8 config; | ||
404 | |||
405 | ret = strict_strtoul(buf, 10, &data); | ||
406 | if (ret || data > 3) | ||
407 | return -EINVAL; | ||
408 | |||
409 | /* retrive ALART status */ | ||
410 | ret = adt75_i2c_read(dev_info, ADT75_CONFIG, &chip->config); | ||
411 | if (ret) | ||
412 | return -EIO; | ||
413 | |||
414 | config = chip->config & ~ADT75_FAULT_QUEUE_MASK; | ||
415 | config |= (data << ADT75_FAULT_QUEUE_OFFSET); | ||
416 | ret = adt75_i2c_write(dev_info, ADT75_CONFIG, config); | ||
417 | if (ret) | ||
418 | return -EIO; | ||
419 | |||
420 | chip->config = config; | ||
421 | |||
422 | return ret; | ||
423 | } | ||
424 | static inline ssize_t adt75_show_t_bound(struct device *dev, | ||
425 | struct device_attribute *attr, | ||
426 | char *buf) | ||
427 | { | ||
428 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
429 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
430 | u16 data; | ||
431 | char sign = ' '; | ||
432 | int ret; | ||
433 | |||
434 | ret = adt75_i2c_read(dev_info, this_attr->address, (u8 *)&data); | ||
435 | if (ret) | ||
436 | return -EIO; | ||
437 | |||
438 | data = swab16(data) >> ADT75_VALUE_OFFSET; | ||
439 | if (data & ADT75_VALUE_SIGN) { | ||
440 | /* convert supplement to positive value */ | ||
441 | data = (ADT75_VALUE_SIGN << 1) - data; | ||
442 | sign = '-'; | ||
443 | } | ||
444 | |||
445 | return sprintf(buf, "%c%d.%.4d\n", sign, | ||
446 | (data >> ADT75_VALUE_FLOAT_OFFSET), | ||
447 | (data & ADT75_VALUE_FLOAT_MASK) * 625); | ||
448 | } | ||
449 | |||
450 | static inline ssize_t adt75_set_t_bound(struct device *dev, | ||
451 | struct device_attribute *attr, | ||
452 | const char *buf, | ||
453 | size_t len) | ||
454 | { | ||
455 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
456 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
457 | long tmp1, tmp2; | ||
458 | u16 data; | ||
459 | char *pos; | ||
460 | int ret; | ||
461 | |||
462 | pos = strchr(buf, '.'); | ||
463 | |||
464 | ret = strict_strtol(buf, 10, &tmp1); | ||
465 | |||
466 | if (ret || tmp1 > 127 || tmp1 < -128) | ||
467 | return -EINVAL; | ||
468 | |||
469 | if (pos) { | ||
470 | len = strlen(pos); | ||
471 | if (len > ADT75_VALUE_FLOAT_OFFSET) | ||
472 | len = ADT75_VALUE_FLOAT_OFFSET; | ||
473 | pos[len] = 0; | ||
474 | ret = strict_strtol(pos, 10, &tmp2); | ||
475 | |||
476 | if (!ret) | ||
477 | tmp2 = (tmp2 / 625) * 625; | ||
478 | } | ||
479 | |||
480 | if (tmp1 < 0) | ||
481 | data = (u16)(-tmp1); | ||
482 | else | ||
483 | data = (u16)tmp1; | ||
484 | data = (data << ADT75_VALUE_FLOAT_OFFSET) | (tmp2 & ADT75_VALUE_FLOAT_MASK); | ||
485 | if (tmp1 < 0) | ||
486 | /* convert positive value to supplyment */ | ||
487 | data = (ADT75_VALUE_SIGN << 1) - data; | ||
488 | data <<= ADT75_VALUE_OFFSET; | ||
489 | data = swab16(data); | ||
490 | |||
491 | ret = adt75_i2c_write(dev_info, this_attr->address, (u8)data); | ||
492 | if (ret) | ||
493 | return -EIO; | ||
494 | |||
495 | return ret; | ||
496 | } | ||
497 | |||
498 | |||
499 | static IIO_DEVICE_ATTR(oti_mode, | ||
500 | S_IRUGO | S_IWUSR, | ||
501 | adt75_show_oti_mode, adt75_set_oti_mode, 0); | ||
502 | static IIO_DEVICE_ATTR(available_oti_modes, | ||
503 | S_IRUGO, | ||
504 | adt75_show_available_oti_modes, NULL, 0); | ||
505 | static IIO_DEVICE_ATTR(smbus_alart, | ||
506 | S_IRUGO | S_IWUSR, | ||
507 | adt75_show_smbus_alart, adt75_set_smbus_alart, 0); | ||
508 | static IIO_DEVICE_ATTR(fault_queue, | ||
509 | S_IRUGO | S_IWUSR, | ||
510 | adt75_show_fault_queue, adt75_set_fault_queue, 0); | ||
511 | static IIO_DEVICE_ATTR(t_os_value, | ||
512 | S_IRUGO | S_IWUSR, | ||
513 | adt75_show_t_bound, adt75_set_t_bound, | ||
514 | ADT75_T_OS); | ||
515 | static IIO_DEVICE_ATTR(t_hyst_value, | ||
516 | S_IRUGO | S_IWUSR, | ||
517 | adt75_show_t_bound, adt75_set_t_bound, | ||
518 | ADT75_T_HYST); | ||
519 | |||
520 | static struct attribute *adt75_event_attributes[] = { | ||
521 | &iio_dev_attr_oti_mode.dev_attr.attr, | ||
522 | &iio_dev_attr_available_oti_modes.dev_attr.attr, | ||
523 | &iio_dev_attr_smbus_alart.dev_attr.attr, | ||
524 | &iio_dev_attr_fault_queue.dev_attr.attr, | ||
525 | &iio_dev_attr_t_os_value.dev_attr.attr, | ||
526 | &iio_dev_attr_t_hyst_value.dev_attr.attr, | ||
527 | NULL, | ||
528 | }; | ||
529 | |||
530 | static struct attribute_group adt75_event_attribute_group = { | ||
531 | .attrs = adt75_event_attributes, | ||
532 | }; | ||
533 | |||
534 | static const struct iio_info adt75_info = { | ||
535 | .attrs = &adt75_attribute_group, | ||
536 | .num_interrupt_lines = 1, | ||
537 | .event_attrs = &adt75_event_attribute_group, | ||
538 | .driver_module = THIS_MODULE, | ||
539 | }; | ||
540 | |||
541 | /* | ||
542 | * device probe and remove | ||
543 | */ | ||
544 | |||
545 | static int __devinit adt75_probe(struct i2c_client *client, | ||
546 | const struct i2c_device_id *id) | ||
547 | { | ||
548 | struct adt75_chip_info *chip; | ||
549 | struct iio_dev *indio_dev; | ||
550 | int ret = 0; | ||
551 | |||
552 | indio_dev = iio_allocate_device(sizeof(*chip)); | ||
553 | if (indio_dev == NULL) { | ||
554 | ret = -ENOMEM; | ||
555 | goto error_ret; | ||
556 | } | ||
557 | chip = iio_priv(indio_dev); | ||
558 | |||
559 | /* this is only used for device removal purposes */ | ||
560 | i2c_set_clientdata(client, indio_dev); | ||
561 | |||
562 | chip->client = client; | ||
563 | |||
564 | indio_dev->name = id->name; | ||
565 | indio_dev->dev.parent = &client->dev; | ||
566 | indio_dev->info = &adt75_info; | ||
567 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
568 | |||
569 | ret = iio_device_register(indio_dev); | ||
570 | if (ret) | ||
571 | goto error_free_dev; | ||
572 | |||
573 | if (client->irq > 0) { | ||
574 | ret = request_threaded_irq(client->irq, | ||
575 | NULL, | ||
576 | &adt75_event_handler, | ||
577 | IRQF_TRIGGER_LOW, | ||
578 | indio_dev->name, | ||
579 | indio_dev); | ||
580 | if (ret) | ||
581 | goto error_unreg_dev; | ||
582 | |||
583 | ret = adt75_i2c_read(indio_dev, ADT75_CONFIG, &chip->config); | ||
584 | if (ret) { | ||
585 | ret = -EIO; | ||
586 | goto error_unreg_irq; | ||
587 | } | ||
588 | |||
589 | /* set irq polarity low level */ | ||
590 | chip->config &= ~ADT75_OS_POLARITY; | ||
591 | |||
592 | ret = adt75_i2c_write(indio_dev, ADT75_CONFIG, chip->config); | ||
593 | if (ret) { | ||
594 | ret = -EIO; | ||
595 | goto error_unreg_irq; | ||
596 | } | ||
597 | } | ||
598 | |||
599 | dev_info(&client->dev, "%s temperature sensor registered.\n", | ||
600 | indio_dev->name); | ||
601 | |||
602 | return 0; | ||
603 | error_unreg_irq: | ||
604 | free_irq(client->irq, indio_dev); | ||
605 | error_unreg_dev: | ||
606 | iio_device_unregister(indio_dev); | ||
607 | error_free_dev: | ||
608 | iio_free_device(indio_dev); | ||
609 | error_ret: | ||
610 | return ret; | ||
611 | } | ||
612 | |||
613 | static int __devexit adt75_remove(struct i2c_client *client) | ||
614 | { | ||
615 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | ||
616 | |||
617 | if (client->irq) | ||
618 | free_irq(client->irq, indio_dev); | ||
619 | iio_device_unregister(indio_dev); | ||
620 | iio_free_device(indio_dev); | ||
621 | |||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static const struct i2c_device_id adt75_id[] = { | ||
626 | { "adt75", 0 }, | ||
627 | {} | ||
628 | }; | ||
629 | |||
630 | MODULE_DEVICE_TABLE(i2c, adt75_id); | ||
631 | |||
632 | static struct i2c_driver adt75_driver = { | ||
633 | .driver = { | ||
634 | .name = "adt75", | ||
635 | }, | ||
636 | .probe = adt75_probe, | ||
637 | .remove = __devexit_p(adt75_remove), | ||
638 | .id_table = adt75_id, | ||
639 | }; | ||
640 | |||
641 | static __init int adt75_init(void) | ||
642 | { | ||
643 | return i2c_add_driver(&adt75_driver); | ||
644 | } | ||
645 | |||
646 | static __exit void adt75_exit(void) | ||
647 | { | ||
648 | i2c_del_driver(&adt75_driver); | ||
649 | } | ||
650 | |||
651 | MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>"); | ||
652 | MODULE_DESCRIPTION("Analog Devices ADT75 digital" | ||
653 | " temperature sensor driver"); | ||
654 | MODULE_LICENSE("GPL v2"); | ||
655 | |||
656 | module_init(adt75_init); | ||
657 | module_exit(adt75_exit); | ||
diff --git a/drivers/staging/iio/adc/max1363.h b/drivers/staging/iio/adc/max1363.h new file mode 100644 index 00000000000..360bfc5398f --- /dev/null +++ b/drivers/staging/iio/adc/max1363.h | |||
@@ -0,0 +1,175 @@ | |||
1 | #ifndef _MAX1363_H_ | ||
2 | #define _MAX1363_H_ | ||
3 | |||
4 | #define MAX1363_SETUP_BYTE(a) ((a) | 0x80) | ||
5 | |||
6 | /* There is a fair bit more defined here than currently | ||
7 | * used, but the intention is to support everything these | ||
8 | * chips do in the long run */ | ||
9 | |||
10 | /* see data sheets */ | ||
11 | /* max1363 and max1236, max1237, max1238, max1239 */ | ||
12 | #define MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD 0x00 | ||
13 | #define MAX1363_SETUP_AIN3_IS_REF_EXT_TO_REF 0x20 | ||
14 | #define MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_INT 0x40 | ||
15 | #define MAX1363_SETUP_AIN3_IS_REF_REF_IS_INT 0x60 | ||
16 | #define MAX1363_SETUP_POWER_UP_INT_REF 0x10 | ||
17 | #define MAX1363_SETUP_POWER_DOWN_INT_REF 0x00 | ||
18 | |||
19 | /* think about includeing max11600 etc - more settings */ | ||
20 | #define MAX1363_SETUP_EXT_CLOCK 0x08 | ||
21 | #define MAX1363_SETUP_INT_CLOCK 0x00 | ||
22 | #define MAX1363_SETUP_UNIPOLAR 0x00 | ||
23 | #define MAX1363_SETUP_BIPOLAR 0x04 | ||
24 | #define MAX1363_SETUP_RESET 0x00 | ||
25 | #define MAX1363_SETUP_NORESET 0x02 | ||
26 | /* max1363 only - though don't care on others. | ||
27 | * For now monitor modes are not implemented as the relevant | ||
28 | * line is not connected on my test board. | ||
29 | * The definitions are here as I intend to add this soon. | ||
30 | */ | ||
31 | #define MAX1363_SETUP_MONITOR_SETUP 0x01 | ||
32 | |||
33 | /* Specific to the max1363 */ | ||
34 | #define MAX1363_MON_RESET_CHAN(a) (1 << ((a) + 4)) | ||
35 | #define MAX1363_MON_INT_ENABLE 0x01 | ||
36 | |||
37 | /* defined for readability reasons */ | ||
38 | /* All chips */ | ||
39 | #define MAX1363_CONFIG_BYTE(a) ((a)) | ||
40 | |||
41 | #define MAX1363_CONFIG_SE 0x01 | ||
42 | #define MAX1363_CONFIG_DE 0x00 | ||
43 | #define MAX1363_CONFIG_SCAN_TO_CS 0x00 | ||
44 | #define MAX1363_CONFIG_SCAN_SINGLE_8 0x20 | ||
45 | #define MAX1363_CONFIG_SCAN_MONITOR_MODE 0x40 | ||
46 | #define MAX1363_CONFIG_SCAN_SINGLE_1 0x60 | ||
47 | /* max123{6-9} only */ | ||
48 | #define MAX1236_SCAN_MID_TO_CHANNEL 0x40 | ||
49 | |||
50 | /* max1363 only - merely part of channel selects or don't care for others*/ | ||
51 | #define MAX1363_CONFIG_EN_MON_MODE_READ 0x18 | ||
52 | |||
53 | #define MAX1363_CHANNEL_SEL(a) ((a) << 1) | ||
54 | |||
55 | /* max1363 strictly 0x06 - but doesn't matter */ | ||
56 | #define MAX1363_CHANNEL_SEL_MASK 0x1E | ||
57 | #define MAX1363_SCAN_MASK 0x60 | ||
58 | #define MAX1363_SE_DE_MASK 0x01 | ||
59 | |||
60 | /** | ||
61 | * struct max1363_mode - scan mode information | ||
62 | * @conf: The corresponding value of the configuration register | ||
63 | * @modemask: Bit mask corresponding to channels enabled in this mode | ||
64 | */ | ||
65 | struct max1363_mode { | ||
66 | int8_t conf; | ||
67 | long modemask; | ||
68 | }; | ||
69 | |||
70 | /* This must be maintained along side the max1363_mode_table in max1363_core */ | ||
71 | enum max1363_modes { | ||
72 | /* Single read of a single channel */ | ||
73 | _s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11, | ||
74 | /* Differential single read */ | ||
75 | d0m1, d2m3, d4m5, d6m7, d8m9, d10m11, | ||
76 | d1m0, d3m2, d5m4, d7m6, d9m8, d11m10, | ||
77 | /* Scan to channel and mid to channel where overlapping */ | ||
78 | s0to1, s0to2, s2to3, s0to3, s0to4, s0to5, s0to6, | ||
79 | s6to7, s0to7, s6to8, s0to8, s6to9, | ||
80 | s0to9, s6to10, s0to10, s6to11, s0to11, | ||
81 | /* Differential scan to channel and mid to channel where overlapping */ | ||
82 | d0m1to2m3, d0m1to4m5, d0m1to6m7, d6m7to8m9, | ||
83 | d0m1to8m9, d6m7to10m11, d0m1to10m11, d1m0to3m2, | ||
84 | d1m0to5m4, d1m0to7m6, d7m6to9m8, d1m0to9m8, | ||
85 | d7m6to11m10, d1m0to11m10, | ||
86 | }; | ||
87 | |||
88 | /** | ||
89 | * struct max1363_chip_info - chip specifc information | ||
90 | * @name: indentification string for chip | ||
91 | * @bits: accuracy of the adc in bits | ||
92 | * @int_vref_mv: the internal reference voltage | ||
93 | * @info: iio core function callbacks structure | ||
94 | * @mode_list: array of available scan modes | ||
95 | * @num_modes: the number of scan modes available | ||
96 | * @default_mode: the scan mode in which the chip starts up | ||
97 | * @channel: channel specification | ||
98 | * @num_channels: number of channels | ||
99 | */ | ||
100 | struct max1363_chip_info { | ||
101 | const struct iio_info *info; | ||
102 | struct iio_chan_spec *channels; | ||
103 | int num_channels; | ||
104 | const enum max1363_modes *mode_list; | ||
105 | enum max1363_modes default_mode; | ||
106 | u16 int_vref_mv; | ||
107 | u8 num_modes; | ||
108 | u8 bits; | ||
109 | }; | ||
110 | |||
111 | /** | ||
112 | * struct max1363_state - driver instance specific data | ||
113 | * @client: i2c_client | ||
114 | * @setupbyte: cache of current device setup byte | ||
115 | * @configbyte: cache of current device config byte | ||
116 | * @chip_info: chip model specific constants, available modes etc | ||
117 | * @current_mode: the scan mode of this chip | ||
118 | * @requestedmask: a valid requested set of channels | ||
119 | * @reg: supply regulator | ||
120 | * @monitor_on: whether monitor mode is enabled | ||
121 | * @monitor_speed: parameter corresponding to device monitor speed setting | ||
122 | * @mask_high: bitmask for enabled high thresholds | ||
123 | * @mask_low: bitmask for enabled low thresholds | ||
124 | * @thresh_high: high threshold values | ||
125 | * @thresh_low: low threshold values | ||
126 | */ | ||
127 | struct max1363_state { | ||
128 | struct i2c_client *client; | ||
129 | u8 setupbyte; | ||
130 | u8 configbyte; | ||
131 | const struct max1363_chip_info *chip_info; | ||
132 | const struct max1363_mode *current_mode; | ||
133 | u32 requestedmask; | ||
134 | struct regulator *reg; | ||
135 | |||
136 | /* Using monitor modes and buffer at the same time is | ||
137 | currently not supported */ | ||
138 | bool monitor_on; | ||
139 | unsigned int monitor_speed:3; | ||
140 | u8 mask_high; | ||
141 | u8 mask_low; | ||
142 | /* 4x unipolar first then the fours bipolar ones */ | ||
143 | s16 thresh_high[8]; | ||
144 | s16 thresh_low[8]; | ||
145 | }; | ||
146 | |||
147 | const struct max1363_mode | ||
148 | *max1363_match_mode(u32 mask, const struct max1363_chip_info *ci); | ||
149 | |||
150 | int max1363_set_scan_mode(struct max1363_state *st); | ||
151 | |||
152 | #ifdef CONFIG_MAX1363_RING_BUFFER | ||
153 | |||
154 | int max1363_single_channel_from_ring(long mask, struct max1363_state *st); | ||
155 | int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev); | ||
156 | void max1363_ring_cleanup(struct iio_dev *indio_dev); | ||
157 | |||
158 | #else /* CONFIG_MAX1363_RING_BUFFER */ | ||
159 | |||
160 | int max1363_single_channel_from_ring(long mask, struct max1363_state *st) | ||
161 | { | ||
162 | return -EINVAL; | ||
163 | } | ||
164 | |||
165 | static inline int | ||
166 | max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) | ||
167 | { | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | static inline void max1363_ring_cleanup(struct iio_dev *indio_dev) | ||
172 | { | ||
173 | } | ||
174 | #endif /* CONFIG_MAX1363_RING_BUFFER */ | ||
175 | #endif /* _MAX1363_H_ */ | ||
diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c new file mode 100644 index 00000000000..72b0917412e --- /dev/null +++ b/drivers/staging/iio/adc/max1363_core.c | |||
@@ -0,0 +1,1433 @@ | |||
1 | /* | ||
2 | * iio/adc/max1363.c | ||
3 | * Copyright (C) 2008-2010 Jonathan Cameron | ||
4 | * | ||
5 | * based on linux/drivers/i2c/chips/max123x | ||
6 | * Copyright (C) 2002-2004 Stefan Eletzhofer | ||
7 | * | ||
8 | * based on linux/drivers/acron/char/pcf8583.c | ||
9 | * Copyright (C) 2000 Russell King | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | * | ||
15 | * max1363.c | ||
16 | * | ||
17 | * Partial support for max1363 and similar chips. | ||
18 | * | ||
19 | * Not currently implemented. | ||
20 | * | ||
21 | * - Control of internal reference. | ||
22 | */ | ||
23 | |||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/device.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/sysfs.h> | ||
28 | #include <linux/list.h> | ||
29 | #include <linux/i2c.h> | ||
30 | #include <linux/regulator/consumer.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/err.h> | ||
33 | |||
34 | #include "../iio.h" | ||
35 | #include "../sysfs.h" | ||
36 | |||
37 | #include "../ring_generic.h" | ||
38 | #include "adc.h" | ||
39 | #include "max1363.h" | ||
40 | |||
41 | #define MAX1363_MODE_SINGLE(_num, _mask) { \ | ||
42 | .conf = MAX1363_CHANNEL_SEL(_num) \ | ||
43 | | MAX1363_CONFIG_SCAN_SINGLE_1 \ | ||
44 | | MAX1363_CONFIG_SE, \ | ||
45 | .modemask = _mask, \ | ||
46 | } | ||
47 | |||
48 | #define MAX1363_MODE_SCAN_TO_CHANNEL(_num, _mask) { \ | ||
49 | .conf = MAX1363_CHANNEL_SEL(_num) \ | ||
50 | | MAX1363_CONFIG_SCAN_TO_CS \ | ||
51 | | MAX1363_CONFIG_SE, \ | ||
52 | .modemask = _mask, \ | ||
53 | } | ||
54 | |||
55 | /* note not available for max1363 hence naming */ | ||
56 | #define MAX1236_MODE_SCAN_MID_TO_CHANNEL(_mid, _num, _mask) { \ | ||
57 | .conf = MAX1363_CHANNEL_SEL(_num) \ | ||
58 | | MAX1236_SCAN_MID_TO_CHANNEL \ | ||
59 | | MAX1363_CONFIG_SE, \ | ||
60 | .modemask = _mask \ | ||
61 | } | ||
62 | |||
63 | #define MAX1363_MODE_DIFF_SINGLE(_nump, _numm, _mask) { \ | ||
64 | .conf = MAX1363_CHANNEL_SEL(_nump) \ | ||
65 | | MAX1363_CONFIG_SCAN_SINGLE_1 \ | ||
66 | | MAX1363_CONFIG_DE, \ | ||
67 | .modemask = _mask \ | ||
68 | } | ||
69 | |||
70 | /* Can't think how to automate naming so specify for now */ | ||
71 | #define MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(_num, _numvals, _mask) { \ | ||
72 | .conf = MAX1363_CHANNEL_SEL(_num) \ | ||
73 | | MAX1363_CONFIG_SCAN_TO_CS \ | ||
74 | | MAX1363_CONFIG_DE, \ | ||
75 | .modemask = _mask \ | ||
76 | } | ||
77 | |||
78 | /* note only available for max1363 hence naming */ | ||
79 | #define MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(_num, _numvals, _mask) { \ | ||
80 | .conf = MAX1363_CHANNEL_SEL(_num) \ | ||
81 | | MAX1236_SCAN_MID_TO_CHANNEL \ | ||
82 | | MAX1363_CONFIG_SE, \ | ||
83 | .modemask = _mask \ | ||
84 | } | ||
85 | |||
86 | static const struct max1363_mode max1363_mode_table[] = { | ||
87 | /* All of the single channel options first */ | ||
88 | MAX1363_MODE_SINGLE(0, 1 << 0), | ||
89 | MAX1363_MODE_SINGLE(1, 1 << 1), | ||
90 | MAX1363_MODE_SINGLE(2, 1 << 2), | ||
91 | MAX1363_MODE_SINGLE(3, 1 << 3), | ||
92 | MAX1363_MODE_SINGLE(4, 1 << 4), | ||
93 | MAX1363_MODE_SINGLE(5, 1 << 5), | ||
94 | MAX1363_MODE_SINGLE(6, 1 << 6), | ||
95 | MAX1363_MODE_SINGLE(7, 1 << 7), | ||
96 | MAX1363_MODE_SINGLE(8, 1 << 8), | ||
97 | MAX1363_MODE_SINGLE(9, 1 << 9), | ||
98 | MAX1363_MODE_SINGLE(10, 1 << 10), | ||
99 | MAX1363_MODE_SINGLE(11, 1 << 11), | ||
100 | |||
101 | MAX1363_MODE_DIFF_SINGLE(0, 1, 1 << 12), | ||
102 | MAX1363_MODE_DIFF_SINGLE(2, 3, 1 << 13), | ||
103 | MAX1363_MODE_DIFF_SINGLE(4, 5, 1 << 14), | ||
104 | MAX1363_MODE_DIFF_SINGLE(6, 7, 1 << 15), | ||
105 | MAX1363_MODE_DIFF_SINGLE(8, 9, 1 << 16), | ||
106 | MAX1363_MODE_DIFF_SINGLE(10, 11, 1 << 17), | ||
107 | MAX1363_MODE_DIFF_SINGLE(1, 0, 1 << 18), | ||
108 | MAX1363_MODE_DIFF_SINGLE(3, 2, 1 << 19), | ||
109 | MAX1363_MODE_DIFF_SINGLE(5, 4, 1 << 20), | ||
110 | MAX1363_MODE_DIFF_SINGLE(7, 6, 1 << 21), | ||
111 | MAX1363_MODE_DIFF_SINGLE(9, 8, 1 << 22), | ||
112 | MAX1363_MODE_DIFF_SINGLE(11, 10, 1 << 23), | ||
113 | |||
114 | /* The multichannel scans next */ | ||
115 | MAX1363_MODE_SCAN_TO_CHANNEL(1, 0x003), | ||
116 | MAX1363_MODE_SCAN_TO_CHANNEL(2, 0x007), | ||
117 | MAX1236_MODE_SCAN_MID_TO_CHANNEL(2, 3, 0x00C), | ||
118 | MAX1363_MODE_SCAN_TO_CHANNEL(3, 0x00F), | ||
119 | MAX1363_MODE_SCAN_TO_CHANNEL(4, 0x01F), | ||
120 | MAX1363_MODE_SCAN_TO_CHANNEL(5, 0x03F), | ||
121 | MAX1363_MODE_SCAN_TO_CHANNEL(6, 0x07F), | ||
122 | MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 7, 0x0C0), | ||
123 | MAX1363_MODE_SCAN_TO_CHANNEL(7, 0x0FF), | ||
124 | MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 8, 0x1C0), | ||
125 | MAX1363_MODE_SCAN_TO_CHANNEL(8, 0x1FF), | ||
126 | MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 9, 0x3C0), | ||
127 | MAX1363_MODE_SCAN_TO_CHANNEL(9, 0x3FF), | ||
128 | MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 10, 0x7C0), | ||
129 | MAX1363_MODE_SCAN_TO_CHANNEL(10, 0x7FF), | ||
130 | MAX1236_MODE_SCAN_MID_TO_CHANNEL(6, 11, 0xFC0), | ||
131 | MAX1363_MODE_SCAN_TO_CHANNEL(11, 0xFFF), | ||
132 | |||
133 | MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(2, 2, 0x003000), | ||
134 | MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(4, 3, 0x007000), | ||
135 | MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(6, 4, 0x00F000), | ||
136 | MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(8, 2, 0x018000), | ||
137 | MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(8, 5, 0x01F000), | ||
138 | MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(10, 3, 0x038000), | ||
139 | MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(10, 6, 0x3F000), | ||
140 | MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(3, 2, 0x0C0000), | ||
141 | MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(5, 3, 0x1C0000), | ||
142 | MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(7, 4, 0x3C0000), | ||
143 | MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(9, 2, 0x600000), | ||
144 | MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(9, 5, 0x7C0000), | ||
145 | MAX1236_MODE_DIFF_SCAN_MID_TO_CHANNEL(11, 3, 0xE00000), | ||
146 | MAX1363_MODE_DIFF_SCAN_TO_CHANNEL(11, 6, 0xFC0000), | ||
147 | }; | ||
148 | |||
149 | const struct max1363_mode | ||
150 | *max1363_match_mode(u32 mask, const struct max1363_chip_info *ci) | ||
151 | { | ||
152 | int i; | ||
153 | if (mask) | ||
154 | for (i = 0; i < ci->num_modes; i++) | ||
155 | if (!((~max1363_mode_table[ci->mode_list[i]].modemask) & | ||
156 | mask)) | ||
157 | return &max1363_mode_table[ci->mode_list[i]]; | ||
158 | return NULL; | ||
159 | } | ||
160 | |||
161 | static int max1363_write_basic_config(struct i2c_client *client, | ||
162 | unsigned char d1, | ||
163 | unsigned char d2) | ||
164 | { | ||
165 | u8 tx_buf[2] = {d1, d2}; | ||
166 | |||
167 | return i2c_master_send(client, tx_buf, 2); | ||
168 | } | ||
169 | |||
170 | int max1363_set_scan_mode(struct max1363_state *st) | ||
171 | { | ||
172 | st->configbyte &= ~(MAX1363_CHANNEL_SEL_MASK | ||
173 | | MAX1363_SCAN_MASK | ||
174 | | MAX1363_SE_DE_MASK); | ||
175 | st->configbyte |= st->current_mode->conf; | ||
176 | |||
177 | return max1363_write_basic_config(st->client, | ||
178 | st->setupbyte, | ||
179 | st->configbyte); | ||
180 | } | ||
181 | |||
182 | static int max1363_read_single_chan(struct iio_dev *indio_dev, | ||
183 | struct iio_chan_spec const *chan, | ||
184 | int *val, | ||
185 | long m) | ||
186 | { | ||
187 | int ret = 0; | ||
188 | s32 data; | ||
189 | char rxbuf[2]; | ||
190 | long mask; | ||
191 | struct max1363_state *st = iio_priv(indio_dev); | ||
192 | struct i2c_client *client = st->client; | ||
193 | |||
194 | mutex_lock(&indio_dev->mlock); | ||
195 | /* | ||
196 | * If monitor mode is enabled, the method for reading a single | ||
197 | * channel will have to be rather different and has not yet | ||
198 | * been implemented. | ||
199 | */ | ||
200 | if (st->monitor_on) { | ||
201 | ret = -EBUSY; | ||
202 | goto error_ret; | ||
203 | } | ||
204 | |||
205 | /* If ring buffer capture is occurring, query the buffer */ | ||
206 | if (iio_ring_enabled(indio_dev)) { | ||
207 | mask = max1363_mode_table[chan->address].modemask; | ||
208 | data = max1363_single_channel_from_ring(mask, st); | ||
209 | if (data < 0) { | ||
210 | ret = data; | ||
211 | goto error_ret; | ||
212 | } | ||
213 | } else { | ||
214 | /* Check to see if current scan mode is correct */ | ||
215 | if (st->current_mode != &max1363_mode_table[chan->address]) { | ||
216 | /* Update scan mode if needed */ | ||
217 | st->current_mode = &max1363_mode_table[chan->address]; | ||
218 | ret = max1363_set_scan_mode(st); | ||
219 | if (ret < 0) | ||
220 | goto error_ret; | ||
221 | } | ||
222 | if (st->chip_info->bits != 8) { | ||
223 | /* Get reading */ | ||
224 | data = i2c_master_recv(client, rxbuf, 2); | ||
225 | if (data < 0) { | ||
226 | ret = data; | ||
227 | goto error_ret; | ||
228 | } | ||
229 | data = (s32)(rxbuf[1]) | ((s32)(rxbuf[0] & 0x0F)) << 8; | ||
230 | } else { | ||
231 | /* Get reading */ | ||
232 | data = i2c_master_recv(client, rxbuf, 1); | ||
233 | if (data < 0) { | ||
234 | ret = data; | ||
235 | goto error_ret; | ||
236 | } | ||
237 | data = rxbuf[0]; | ||
238 | } | ||
239 | } | ||
240 | *val = data; | ||
241 | error_ret: | ||
242 | mutex_unlock(&indio_dev->mlock); | ||
243 | return ret; | ||
244 | |||
245 | } | ||
246 | |||
247 | static int max1363_read_raw(struct iio_dev *indio_dev, | ||
248 | struct iio_chan_spec const *chan, | ||
249 | int *val, | ||
250 | int *val2, | ||
251 | long m) | ||
252 | { | ||
253 | struct max1363_state *st = iio_priv(indio_dev); | ||
254 | int ret; | ||
255 | switch (m) { | ||
256 | case 0: | ||
257 | ret = max1363_read_single_chan(indio_dev, chan, val, m); | ||
258 | if (ret) | ||
259 | return ret; | ||
260 | return IIO_VAL_INT; | ||
261 | case (1 << IIO_CHAN_INFO_SCALE_SHARED): | ||
262 | if ((1 << (st->chip_info->bits + 1)) > | ||
263 | st->chip_info->int_vref_mv) { | ||
264 | *val = 0; | ||
265 | *val2 = 500000; | ||
266 | return IIO_VAL_INT_PLUS_MICRO; | ||
267 | } else { | ||
268 | *val = (st->chip_info->int_vref_mv) | ||
269 | >> st->chip_info->bits; | ||
270 | return IIO_VAL_INT; | ||
271 | } | ||
272 | default: | ||
273 | return -EINVAL; | ||
274 | } | ||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | /* Applies to max1363 */ | ||
279 | static const enum max1363_modes max1363_mode_list[] = { | ||
280 | _s0, _s1, _s2, _s3, | ||
281 | s0to1, s0to2, s0to3, | ||
282 | d0m1, d2m3, d1m0, d3m2, | ||
283 | d0m1to2m3, d1m0to3m2, | ||
284 | }; | ||
285 | |||
286 | #define MAX1363_EV_M \ | ||
287 | (IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING) \ | ||
288 | | IIO_EV_BIT(IIO_EV_TYPE_THRESH, IIO_EV_DIR_FALLING)) | ||
289 | #define MAX1363_INFO_MASK (1 << IIO_CHAN_INFO_SCALE_SHARED) | ||
290 | |||
291 | static struct iio_chan_spec max1363_channels[] = { | ||
292 | IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, MAX1363_INFO_MASK, | ||
293 | _s0, 0, IIO_ST('u', 12, 16, 0), MAX1363_EV_M), | ||
294 | IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, MAX1363_INFO_MASK, | ||
295 | _s1, 1, IIO_ST('u', 12, 16, 0), MAX1363_EV_M), | ||
296 | IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, MAX1363_INFO_MASK, | ||
297 | _s2, 2, IIO_ST('u', 12, 16, 0), MAX1363_EV_M), | ||
298 | IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, MAX1363_INFO_MASK, | ||
299 | _s3, 3, IIO_ST('u', 12, 16, 0), MAX1363_EV_M), | ||
300 | IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 0, 1, MAX1363_INFO_MASK, | ||
301 | d0m1, 4, IIO_ST('s', 12, 16, 0), MAX1363_EV_M), | ||
302 | IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 2, 3, MAX1363_INFO_MASK, | ||
303 | d2m3, 5, IIO_ST('s', 12, 16, 0), MAX1363_EV_M), | ||
304 | IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 1, 0, MAX1363_INFO_MASK, | ||
305 | d1m0, 6, IIO_ST('s', 12, 16, 0), MAX1363_EV_M), | ||
306 | IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 3, 2, MAX1363_INFO_MASK, | ||
307 | d3m2, 7, IIO_ST('s', 12, 16, 0), MAX1363_EV_M), | ||
308 | IIO_CHAN_SOFT_TIMESTAMP(8) | ||
309 | }; | ||
310 | |||
311 | static struct iio_chan_spec max1361_channels[] = { | ||
312 | IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 0, 0, MAX1363_INFO_MASK, | ||
313 | _s0, 0, IIO_ST('u', 10, 16, 0), MAX1363_EV_M), | ||
314 | IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 1, 0, MAX1363_INFO_MASK, | ||
315 | _s1, 1, IIO_ST('u', 10, 16, 0), MAX1363_EV_M), | ||
316 | IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 2, 0, MAX1363_INFO_MASK, | ||
317 | _s2, 2, IIO_ST('u', 10, 16, 0), MAX1363_EV_M), | ||
318 | IIO_CHAN(IIO_IN, 0, 1, 0, NULL, 3, 0, MAX1363_INFO_MASK, | ||
319 | _s3, 3, IIO_ST('u', 10, 16, 0), MAX1363_EV_M), | ||
320 | IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 0, 1, MAX1363_INFO_MASK, | ||
321 | d0m1, 4, IIO_ST('s', 10, 16, 0), MAX1363_EV_M), | ||
322 | IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 2, 3, MAX1363_INFO_MASK, | ||
323 | d2m3, 5, IIO_ST('s', 10, 16, 0), MAX1363_EV_M), | ||
324 | IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 1, 0, MAX1363_INFO_MASK, | ||
325 | d1m0, 6, IIO_ST('s', 10, 16, 0), MAX1363_EV_M), | ||
326 | IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, 3, 2, MAX1363_INFO_MASK, | ||
327 | d3m2, 7, IIO_ST('s', 10, 16, 0), MAX1363_EV_M), | ||
328 | IIO_CHAN_SOFT_TIMESTAMP(8) | ||
329 | }; | ||
330 | |||
331 | #define MAX1363_CHAN_U(num, address, scan_index, bits) \ | ||
332 | IIO_CHAN(IIO_IN, 0, 1, 0, NULL, num, 0, MAX1363_INFO_MASK, \ | ||
333 | address, scan_index, IIO_ST('u', bits, \ | ||
334 | (bits == 8) ? 8 : 16, 0), 0) | ||
335 | /* bipolar channel */ | ||
336 | #define MAX1363_CHAN_B(num, num2, address, scan_index, bits) \ | ||
337 | IIO_CHAN(IIO_IN_DIFF, 0, 1, 0, NULL, num, num2, MAX1363_INFO_MASK,\ | ||
338 | address, scan_index, IIO_ST('s', bits, \ | ||
339 | (bits == 8) ? 8 : 16, 0), 0) | ||
340 | |||
341 | #define MAX1363_4X_CHANS(bits) { \ | ||
342 | MAX1363_CHAN_U(0, _s0, 0, bits), \ | ||
343 | MAX1363_CHAN_U(1, _s1, 1, bits), \ | ||
344 | MAX1363_CHAN_U(2, _s2, 2, bits), \ | ||
345 | MAX1363_CHAN_U(3, _s3, 3, bits), \ | ||
346 | MAX1363_CHAN_B(0, 1, d0m1, 4, bits), \ | ||
347 | MAX1363_CHAN_B(2, 3, d2m3, 5, bits), \ | ||
348 | MAX1363_CHAN_B(1, 0, d1m0, 6, bits), \ | ||
349 | MAX1363_CHAN_B(3, 2, d3m2, 7, bits), \ | ||
350 | IIO_CHAN_SOFT_TIMESTAMP(8) \ | ||
351 | } | ||
352 | |||
353 | static struct iio_chan_spec max1036_channels[] = MAX1363_4X_CHANS(8); | ||
354 | static struct iio_chan_spec max1136_channels[] = MAX1363_4X_CHANS(10); | ||
355 | static struct iio_chan_spec max1236_channels[] = MAX1363_4X_CHANS(12); | ||
356 | |||
357 | /* Appies to max1236, max1237 */ | ||
358 | static const enum max1363_modes max1236_mode_list[] = { | ||
359 | _s0, _s1, _s2, _s3, | ||
360 | s0to1, s0to2, s0to3, | ||
361 | d0m1, d2m3, d1m0, d3m2, | ||
362 | d0m1to2m3, d1m0to3m2, | ||
363 | s2to3, | ||
364 | }; | ||
365 | |||
366 | /* Applies to max1238, max1239 */ | ||
367 | static const enum max1363_modes max1238_mode_list[] = { | ||
368 | _s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, _s8, _s9, _s10, _s11, | ||
369 | s0to1, s0to2, s0to3, s0to4, s0to5, s0to6, | ||
370 | s0to7, s0to8, s0to9, s0to10, s0to11, | ||
371 | d0m1, d2m3, d4m5, d6m7, d8m9, d10m11, | ||
372 | d1m0, d3m2, d5m4, d7m6, d9m8, d11m10, | ||
373 | d0m1to2m3, d0m1to4m5, d0m1to6m7, d0m1to8m9, d0m1to10m11, | ||
374 | d1m0to3m2, d1m0to5m4, d1m0to7m6, d1m0to9m8, d1m0to11m10, | ||
375 | s6to7, s6to8, s6to9, s6to10, s6to11, | ||
376 | d6m7to8m9, d6m7to10m11, d7m6to9m8, d7m6to11m10, | ||
377 | }; | ||
378 | |||
379 | #define MAX1363_12X_CHANS(bits) { \ | ||
380 | MAX1363_CHAN_U(0, _s0, 0, bits), \ | ||
381 | MAX1363_CHAN_U(1, _s1, 1, bits), \ | ||
382 | MAX1363_CHAN_U(2, _s2, 2, bits), \ | ||
383 | MAX1363_CHAN_U(3, _s3, 3, bits), \ | ||
384 | MAX1363_CHAN_U(4, _s4, 4, bits), \ | ||
385 | MAX1363_CHAN_U(5, _s5, 5, bits), \ | ||
386 | MAX1363_CHAN_U(6, _s6, 6, bits), \ | ||
387 | MAX1363_CHAN_U(7, _s7, 7, bits), \ | ||
388 | MAX1363_CHAN_U(8, _s8, 8, bits), \ | ||
389 | MAX1363_CHAN_U(9, _s9, 9, bits), \ | ||
390 | MAX1363_CHAN_U(10, _s10, 10, bits), \ | ||
391 | MAX1363_CHAN_U(11, _s11, 11, bits), \ | ||
392 | MAX1363_CHAN_B(0, 1, d0m1, 12, bits), \ | ||
393 | MAX1363_CHAN_B(2, 3, d2m3, 13, bits), \ | ||
394 | MAX1363_CHAN_B(4, 5, d4m5, 14, bits), \ | ||
395 | MAX1363_CHAN_B(6, 7, d6m7, 15, bits), \ | ||
396 | MAX1363_CHAN_B(8, 9, d8m9, 16, bits), \ | ||
397 | MAX1363_CHAN_B(10, 11, d10m11, 17, bits), \ | ||
398 | MAX1363_CHAN_B(1, 0, d1m0, 18, bits), \ | ||
399 | MAX1363_CHAN_B(3, 2, d3m2, 19, bits), \ | ||
400 | MAX1363_CHAN_B(5, 4, d5m4, 20, bits), \ | ||
401 | MAX1363_CHAN_B(7, 6, d7m6, 21, bits), \ | ||
402 | MAX1363_CHAN_B(9, 8, d9m8, 22, bits), \ | ||
403 | MAX1363_CHAN_B(11, 10, d11m10, 23, bits), \ | ||
404 | IIO_CHAN_SOFT_TIMESTAMP(24) \ | ||
405 | } | ||
406 | static struct iio_chan_spec max1038_channels[] = MAX1363_12X_CHANS(8); | ||
407 | static struct iio_chan_spec max1138_channels[] = MAX1363_12X_CHANS(10); | ||
408 | static struct iio_chan_spec max1238_channels[] = MAX1363_12X_CHANS(12); | ||
409 | |||
410 | static const enum max1363_modes max11607_mode_list[] = { | ||
411 | _s0, _s1, _s2, _s3, | ||
412 | s0to1, s0to2, s0to3, | ||
413 | s2to3, | ||
414 | d0m1, d2m3, d1m0, d3m2, | ||
415 | d0m1to2m3, d1m0to3m2, | ||
416 | }; | ||
417 | |||
418 | static const enum max1363_modes max11608_mode_list[] = { | ||
419 | _s0, _s1, _s2, _s3, _s4, _s5, _s6, _s7, | ||
420 | s0to1, s0to2, s0to3, s0to4, s0to5, s0to6, s0to7, | ||
421 | s6to7, | ||
422 | d0m1, d2m3, d4m5, d6m7, | ||
423 | d1m0, d3m2, d5m4, d7m6, | ||
424 | d0m1to2m3, d0m1to4m5, d0m1to6m7, | ||
425 | d1m0to3m2, d1m0to5m4, d1m0to7m6, | ||
426 | }; | ||
427 | |||
428 | #define MAX1363_8X_CHANS(bits) { \ | ||
429 | MAX1363_CHAN_U(0, _s0, 0, bits), \ | ||
430 | MAX1363_CHAN_U(1, _s1, 1, bits), \ | ||
431 | MAX1363_CHAN_U(2, _s2, 2, bits), \ | ||
432 | MAX1363_CHAN_U(3, _s3, 3, bits), \ | ||
433 | MAX1363_CHAN_U(4, _s4, 4, bits), \ | ||
434 | MAX1363_CHAN_U(5, _s5, 5, bits), \ | ||
435 | MAX1363_CHAN_U(6, _s6, 6, bits), \ | ||
436 | MAX1363_CHAN_U(7, _s7, 7, bits), \ | ||
437 | MAX1363_CHAN_B(0, 1, d0m1, 8, bits), \ | ||
438 | MAX1363_CHAN_B(2, 3, d2m3, 9, bits), \ | ||
439 | MAX1363_CHAN_B(4, 5, d4m5, 10, bits), \ | ||
440 | MAX1363_CHAN_B(6, 7, d6m7, 11, bits), \ | ||
441 | MAX1363_CHAN_B(1, 0, d1m0, 12, bits), \ | ||
442 | MAX1363_CHAN_B(3, 2, d3m2, 13, bits), \ | ||
443 | MAX1363_CHAN_B(5, 4, d5m4, 14, bits), \ | ||
444 | MAX1363_CHAN_B(7, 6, d7m6, 15, bits), \ | ||
445 | IIO_CHAN_SOFT_TIMESTAMP(16) \ | ||
446 | } | ||
447 | static struct iio_chan_spec max11602_channels[] = MAX1363_8X_CHANS(8); | ||
448 | static struct iio_chan_spec max11608_channels[] = MAX1363_8X_CHANS(10); | ||
449 | static struct iio_chan_spec max11614_channels[] = MAX1363_8X_CHANS(12); | ||
450 | |||
451 | static const enum max1363_modes max11644_mode_list[] = { | ||
452 | _s0, _s1, s0to1, d0m1, d1m0, | ||
453 | }; | ||
454 | |||
455 | #define MAX1363_2X_CHANS(bits) { \ | ||
456 | MAX1363_CHAN_U(0, _s0, 0, bits), \ | ||
457 | MAX1363_CHAN_U(1, _s1, 1, bits), \ | ||
458 | MAX1363_CHAN_B(0, 1, d0m1, 2, bits), \ | ||
459 | MAX1363_CHAN_B(1, 0, d1m0, 3, bits), \ | ||
460 | IIO_CHAN_SOFT_TIMESTAMP(4) \ | ||
461 | } | ||
462 | |||
463 | static struct iio_chan_spec max11646_channels[] = MAX1363_2X_CHANS(10); | ||
464 | static struct iio_chan_spec max11644_channels[] = MAX1363_2X_CHANS(12); | ||
465 | |||
466 | enum { max1361, | ||
467 | max1362, | ||
468 | max1363, | ||
469 | max1364, | ||
470 | max1036, | ||
471 | max1037, | ||
472 | max1038, | ||
473 | max1039, | ||
474 | max1136, | ||
475 | max1137, | ||
476 | max1138, | ||
477 | max1139, | ||
478 | max1236, | ||
479 | max1237, | ||
480 | max1238, | ||
481 | max1239, | ||
482 | max11600, | ||
483 | max11601, | ||
484 | max11602, | ||
485 | max11603, | ||
486 | max11604, | ||
487 | max11605, | ||
488 | max11606, | ||
489 | max11607, | ||
490 | max11608, | ||
491 | max11609, | ||
492 | max11610, | ||
493 | max11611, | ||
494 | max11612, | ||
495 | max11613, | ||
496 | max11614, | ||
497 | max11615, | ||
498 | max11616, | ||
499 | max11617, | ||
500 | max11644, | ||
501 | max11645, | ||
502 | max11646, | ||
503 | max11647 | ||
504 | }; | ||
505 | |||
506 | static const int max1363_monitor_speeds[] = { 133000, 665000, 33300, 16600, | ||
507 | 8300, 4200, 2000, 1000 }; | ||
508 | |||
509 | static ssize_t max1363_monitor_show_freq(struct device *dev, | ||
510 | struct device_attribute *attr, | ||
511 | char *buf) | ||
512 | { | ||
513 | struct max1363_state *st = iio_priv(dev_get_drvdata(dev)); | ||
514 | return sprintf(buf, "%d\n", max1363_monitor_speeds[st->monitor_speed]); | ||
515 | } | ||
516 | |||
517 | static ssize_t max1363_monitor_store_freq(struct device *dev, | ||
518 | struct device_attribute *attr, | ||
519 | const char *buf, | ||
520 | size_t len) | ||
521 | { | ||
522 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
523 | struct max1363_state *st = iio_priv(indio_dev); | ||
524 | int i, ret; | ||
525 | unsigned long val; | ||
526 | bool found = false; | ||
527 | |||
528 | ret = strict_strtoul(buf, 10, &val); | ||
529 | if (ret) | ||
530 | return -EINVAL; | ||
531 | for (i = 0; i < ARRAY_SIZE(max1363_monitor_speeds); i++) | ||
532 | if (val == max1363_monitor_speeds[i]) { | ||
533 | found = true; | ||
534 | break; | ||
535 | } | ||
536 | if (!found) | ||
537 | return -EINVAL; | ||
538 | |||
539 | mutex_lock(&indio_dev->mlock); | ||
540 | st->monitor_speed = i; | ||
541 | mutex_unlock(&indio_dev->mlock); | ||
542 | |||
543 | return 0; | ||
544 | } | ||
545 | |||
546 | static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR, | ||
547 | max1363_monitor_show_freq, | ||
548 | max1363_monitor_store_freq); | ||
549 | |||
550 | static IIO_CONST_ATTR(sampling_frequency_available, | ||
551 | "133000 665000 33300 16600 8300 4200 2000 1000"); | ||
552 | |||
553 | static int max1363_read_thresh(struct iio_dev *indio_dev, | ||
554 | int event_code, | ||
555 | int *val) | ||
556 | { | ||
557 | struct max1363_state *st = iio_priv(indio_dev); | ||
558 | if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING) | ||
559 | *val = st->thresh_low[IIO_EVENT_CODE_EXTRACT_NUM(event_code)]; | ||
560 | else | ||
561 | *val = st->thresh_high[IIO_EVENT_CODE_EXTRACT_NUM(event_code)]; | ||
562 | return 0; | ||
563 | } | ||
564 | |||
565 | static int max1363_write_thresh(struct iio_dev *indio_dev, | ||
566 | int event_code, | ||
567 | int val) | ||
568 | { | ||
569 | struct max1363_state *st = iio_priv(indio_dev); | ||
570 | /* make it handle signed correctly as well */ | ||
571 | switch (st->chip_info->bits) { | ||
572 | case 10: | ||
573 | if (val > 0x3FF) | ||
574 | return -EINVAL; | ||
575 | break; | ||
576 | case 12: | ||
577 | if (val > 0xFFF) | ||
578 | return -EINVAL; | ||
579 | break; | ||
580 | } | ||
581 | |||
582 | switch (IIO_EVENT_CODE_EXTRACT_DIR(event_code)) { | ||
583 | case IIO_EV_DIR_FALLING: | ||
584 | st->thresh_low[IIO_EVENT_CODE_EXTRACT_NUM(event_code)] = val; | ||
585 | break; | ||
586 | case IIO_EV_DIR_RISING: | ||
587 | st->thresh_high[IIO_EVENT_CODE_EXTRACT_NUM(event_code)] = val; | ||
588 | break; | ||
589 | } | ||
590 | |||
591 | return 0; | ||
592 | } | ||
593 | |||
594 | static const int max1363_event_codes[] = { | ||
595 | IIO_EVENT_CODE_IN_LOW_THRESH(3), IIO_EVENT_CODE_IN_HIGH_THRESH(3), | ||
596 | IIO_EVENT_CODE_IN_LOW_THRESH(2), IIO_EVENT_CODE_IN_HIGH_THRESH(2), | ||
597 | IIO_EVENT_CODE_IN_LOW_THRESH(1), IIO_EVENT_CODE_IN_HIGH_THRESH(1), | ||
598 | IIO_EVENT_CODE_IN_LOW_THRESH(0), IIO_EVENT_CODE_IN_HIGH_THRESH(0) | ||
599 | }; | ||
600 | |||
601 | static irqreturn_t max1363_event_handler(int irq, void *private) | ||
602 | { | ||
603 | struct iio_dev *indio_dev = private; | ||
604 | struct max1363_state *st = iio_priv(indio_dev); | ||
605 | s64 timestamp = iio_get_time_ns(); | ||
606 | unsigned long mask, loc; | ||
607 | u8 rx; | ||
608 | u8 tx[2] = { st->setupbyte, | ||
609 | MAX1363_MON_INT_ENABLE | (st->monitor_speed << 1) | 0xF0 }; | ||
610 | |||
611 | i2c_master_recv(st->client, &rx, 1); | ||
612 | mask = rx; | ||
613 | for_each_set_bit(loc, &mask, 8) | ||
614 | iio_push_event(indio_dev, 0, max1363_event_codes[loc], | ||
615 | timestamp); | ||
616 | i2c_master_send(st->client, tx, 2); | ||
617 | |||
618 | return IRQ_HANDLED; | ||
619 | } | ||
620 | |||
621 | static int max1363_read_event_config(struct iio_dev *indio_dev, | ||
622 | int event_code) | ||
623 | { | ||
624 | struct max1363_state *st = iio_priv(indio_dev); | ||
625 | |||
626 | int val; | ||
627 | int number = IIO_EVENT_CODE_EXTRACT_NUM(event_code); | ||
628 | mutex_lock(&indio_dev->mlock); | ||
629 | if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING) | ||
630 | val = (1 << number) & st->mask_low; | ||
631 | else | ||
632 | val = (1 << number) & st->mask_high; | ||
633 | mutex_unlock(&indio_dev->mlock); | ||
634 | |||
635 | return val; | ||
636 | } | ||
637 | |||
638 | static int max1363_monitor_mode_update(struct max1363_state *st, int enabled) | ||
639 | { | ||
640 | u8 *tx_buf; | ||
641 | int ret, i = 3, j; | ||
642 | unsigned long numelements; | ||
643 | int len; | ||
644 | long modemask; | ||
645 | |||
646 | if (!enabled) { | ||
647 | /* transition to ring capture is not currently supported */ | ||
648 | st->setupbyte &= ~MAX1363_SETUP_MONITOR_SETUP; | ||
649 | st->configbyte &= ~MAX1363_SCAN_MASK; | ||
650 | st->monitor_on = false; | ||
651 | return max1363_write_basic_config(st->client, | ||
652 | st->setupbyte, | ||
653 | st->configbyte); | ||
654 | } | ||
655 | |||
656 | /* Ensure we are in the relevant mode */ | ||
657 | st->setupbyte |= MAX1363_SETUP_MONITOR_SETUP; | ||
658 | st->configbyte &= ~(MAX1363_CHANNEL_SEL_MASK | ||
659 | | MAX1363_SCAN_MASK | ||
660 | | MAX1363_SE_DE_MASK); | ||
661 | st->configbyte |= MAX1363_CONFIG_SCAN_MONITOR_MODE; | ||
662 | if ((st->mask_low | st->mask_high) & 0x0F) { | ||
663 | st->configbyte |= max1363_mode_table[s0to3].conf; | ||
664 | modemask = max1363_mode_table[s0to3].modemask; | ||
665 | } else if ((st->mask_low | st->mask_high) & 0x30) { | ||
666 | st->configbyte |= max1363_mode_table[d0m1to2m3].conf; | ||
667 | modemask = max1363_mode_table[d0m1to2m3].modemask; | ||
668 | } else { | ||
669 | st->configbyte |= max1363_mode_table[d1m0to3m2].conf; | ||
670 | modemask = max1363_mode_table[d1m0to3m2].modemask; | ||
671 | } | ||
672 | numelements = hweight_long(modemask); | ||
673 | len = 3 * numelements + 3; | ||
674 | tx_buf = kmalloc(len, GFP_KERNEL); | ||
675 | if (!tx_buf) { | ||
676 | ret = -ENOMEM; | ||
677 | goto error_ret; | ||
678 | } | ||
679 | tx_buf[0] = st->configbyte; | ||
680 | tx_buf[1] = st->setupbyte; | ||
681 | tx_buf[2] = (st->monitor_speed << 1); | ||
682 | |||
683 | /* | ||
684 | * So we need to do yet another bit of nefarious scan mode | ||
685 | * setup to match what we need. | ||
686 | */ | ||
687 | for (j = 0; j < 8; j++) | ||
688 | if (modemask & (1 << j)) { | ||
689 | /* Establish the mode is in the scan */ | ||
690 | if (st->mask_low & (1 << j)) { | ||
691 | tx_buf[i] = (st->thresh_low[j] >> 4) & 0xFF; | ||
692 | tx_buf[i + 1] = (st->thresh_low[j] << 4) & 0xF0; | ||
693 | } else if (j < 4) { | ||
694 | tx_buf[i] = 0; | ||
695 | tx_buf[i + 1] = 0; | ||
696 | } else { | ||
697 | tx_buf[i] = 0x80; | ||
698 | tx_buf[i + 1] = 0; | ||
699 | } | ||
700 | if (st->mask_high & (1 << j)) { | ||
701 | tx_buf[i + 1] |= | ||
702 | (st->thresh_high[j] >> 8) & 0x0F; | ||
703 | tx_buf[i + 2] = st->thresh_high[j] & 0xFF; | ||
704 | } else if (j < 4) { | ||
705 | tx_buf[i + 1] |= 0x0F; | ||
706 | tx_buf[i + 2] = 0xFF; | ||
707 | } else { | ||
708 | tx_buf[i + 1] |= 0x07; | ||
709 | tx_buf[i + 2] = 0xFF; | ||
710 | } | ||
711 | i += 3; | ||
712 | } | ||
713 | |||
714 | |||
715 | ret = i2c_master_send(st->client, tx_buf, len); | ||
716 | if (ret < 0) | ||
717 | goto error_ret; | ||
718 | if (ret != len) { | ||
719 | ret = -EIO; | ||
720 | goto error_ret; | ||
721 | } | ||
722 | |||
723 | /* | ||
724 | * Now that we hopefully have sensible thresholds in place it is | ||
725 | * time to turn the interrupts on. | ||
726 | * It is unclear from the data sheet if this should be necessary | ||
727 | * (i.e. whether monitor mode setup is atomic) but it appears to | ||
728 | * be in practice. | ||
729 | */ | ||
730 | tx_buf[0] = st->setupbyte; | ||
731 | tx_buf[1] = MAX1363_MON_INT_ENABLE | (st->monitor_speed << 1) | 0xF0; | ||
732 | ret = i2c_master_send(st->client, tx_buf, 2); | ||
733 | if (ret < 0) | ||
734 | goto error_ret; | ||
735 | if (ret != 2) { | ||
736 | ret = -EIO; | ||
737 | goto error_ret; | ||
738 | } | ||
739 | ret = 0; | ||
740 | st->monitor_on = true; | ||
741 | error_ret: | ||
742 | |||
743 | kfree(tx_buf); | ||
744 | |||
745 | return ret; | ||
746 | } | ||
747 | |||
748 | /* | ||
749 | * To keep this manageable we always use one of 3 scan modes. | ||
750 | * Scan 0...3, 0-1,2-3 and 1-0,3-2 | ||
751 | */ | ||
752 | |||
753 | static inline int __max1363_check_event_mask(int thismask, int checkmask) | ||
754 | { | ||
755 | int ret = 0; | ||
756 | /* Is it unipolar */ | ||
757 | if (thismask < 4) { | ||
758 | if (checkmask & ~0x0F) { | ||
759 | ret = -EBUSY; | ||
760 | goto error_ret; | ||
761 | } | ||
762 | } else if (thismask < 6) { | ||
763 | if (checkmask & ~0x30) { | ||
764 | ret = -EBUSY; | ||
765 | goto error_ret; | ||
766 | } | ||
767 | } else if (checkmask & ~0xC0) | ||
768 | ret = -EBUSY; | ||
769 | error_ret: | ||
770 | return ret; | ||
771 | } | ||
772 | |||
773 | static int max1363_write_event_config(struct iio_dev *indio_dev, | ||
774 | int event_code, | ||
775 | int state) | ||
776 | { | ||
777 | int ret = 0; | ||
778 | struct max1363_state *st = iio_priv(indio_dev); | ||
779 | u16 unifiedmask; | ||
780 | int number = IIO_EVENT_CODE_EXTRACT_NUM(event_code); | ||
781 | |||
782 | mutex_lock(&indio_dev->mlock); | ||
783 | unifiedmask = st->mask_low | st->mask_high; | ||
784 | if (IIO_EVENT_CODE_EXTRACT_DIR(event_code) == IIO_EV_DIR_FALLING) { | ||
785 | |||
786 | if (state == 0) | ||
787 | st->mask_low &= ~(1 << number); | ||
788 | else { | ||
789 | ret = __max1363_check_event_mask((1 << number), | ||
790 | unifiedmask); | ||
791 | if (ret) | ||
792 | goto error_ret; | ||
793 | st->mask_low |= (1 << number); | ||
794 | } | ||
795 | } else { | ||
796 | if (state == 0) | ||
797 | st->mask_high &= ~(1 << number); | ||
798 | else { | ||
799 | ret = __max1363_check_event_mask((1 << number), | ||
800 | unifiedmask); | ||
801 | if (ret) | ||
802 | goto error_ret; | ||
803 | st->mask_high |= (1 << number); | ||
804 | } | ||
805 | } | ||
806 | |||
807 | max1363_monitor_mode_update(st, !!(st->mask_high | st->mask_low)); | ||
808 | error_ret: | ||
809 | mutex_unlock(&indio_dev->mlock); | ||
810 | |||
811 | return ret; | ||
812 | } | ||
813 | |||
814 | /* | ||
815 | * As with scan_elements, only certain sets of these can | ||
816 | * be combined. | ||
817 | */ | ||
818 | static struct attribute *max1363_event_attributes[] = { | ||
819 | &iio_dev_attr_sampling_frequency.dev_attr.attr, | ||
820 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, | ||
821 | NULL, | ||
822 | }; | ||
823 | |||
824 | static struct attribute_group max1363_event_attribute_group = { | ||
825 | .attrs = max1363_event_attributes, | ||
826 | }; | ||
827 | |||
828 | #define MAX1363_EVENT_FUNCS \ | ||
829 | |||
830 | |||
831 | static const struct iio_info max1238_info = { | ||
832 | .read_raw = &max1363_read_raw, | ||
833 | .driver_module = THIS_MODULE, | ||
834 | }; | ||
835 | |||
836 | static const struct iio_info max1363_info = { | ||
837 | .read_event_value = &max1363_read_thresh, | ||
838 | .write_event_value = &max1363_write_thresh, | ||
839 | .read_event_config = &max1363_read_event_config, | ||
840 | .write_event_config = &max1363_write_event_config, | ||
841 | .read_raw = &max1363_read_raw, | ||
842 | .driver_module = THIS_MODULE, | ||
843 | .num_interrupt_lines = 1, | ||
844 | .event_attrs = &max1363_event_attribute_group, | ||
845 | }; | ||
846 | |||
847 | /* max1363 and max1368 tested - rest from data sheet */ | ||
848 | static const struct max1363_chip_info max1363_chip_info_tbl[] = { | ||
849 | [max1361] = { | ||
850 | .bits = 10, | ||
851 | .int_vref_mv = 2048, | ||
852 | .mode_list = max1363_mode_list, | ||
853 | .num_modes = ARRAY_SIZE(max1363_mode_list), | ||
854 | .default_mode = s0to3, | ||
855 | .channels = max1361_channels, | ||
856 | .num_channels = ARRAY_SIZE(max1361_channels), | ||
857 | .info = &max1363_info, | ||
858 | }, | ||
859 | [max1362] = { | ||
860 | .bits = 10, | ||
861 | .int_vref_mv = 4096, | ||
862 | .mode_list = max1363_mode_list, | ||
863 | .num_modes = ARRAY_SIZE(max1363_mode_list), | ||
864 | .default_mode = s0to3, | ||
865 | .channels = max1361_channels, | ||
866 | .num_channels = ARRAY_SIZE(max1361_channels), | ||
867 | .info = &max1363_info, | ||
868 | }, | ||
869 | [max1363] = { | ||
870 | .bits = 12, | ||
871 | .int_vref_mv = 2048, | ||
872 | .mode_list = max1363_mode_list, | ||
873 | .num_modes = ARRAY_SIZE(max1363_mode_list), | ||
874 | .default_mode = s0to3, | ||
875 | .channels = max1363_channels, | ||
876 | .num_channels = ARRAY_SIZE(max1363_channels), | ||
877 | .info = &max1363_info, | ||
878 | }, | ||
879 | [max1364] = { | ||
880 | .bits = 12, | ||
881 | .int_vref_mv = 4096, | ||
882 | .mode_list = max1363_mode_list, | ||
883 | .num_modes = ARRAY_SIZE(max1363_mode_list), | ||
884 | .default_mode = s0to3, | ||
885 | .channels = max1363_channels, | ||
886 | .num_channels = ARRAY_SIZE(max1363_channels), | ||
887 | .info = &max1363_info, | ||
888 | }, | ||
889 | [max1036] = { | ||
890 | .bits = 8, | ||
891 | .int_vref_mv = 4096, | ||
892 | .mode_list = max1236_mode_list, | ||
893 | .num_modes = ARRAY_SIZE(max1236_mode_list), | ||
894 | .default_mode = s0to3, | ||
895 | .info = &max1238_info, | ||
896 | .channels = max1036_channels, | ||
897 | .num_channels = ARRAY_SIZE(max1036_channels), | ||
898 | }, | ||
899 | [max1037] = { | ||
900 | .bits = 8, | ||
901 | .int_vref_mv = 2048, | ||
902 | .mode_list = max1236_mode_list, | ||
903 | .num_modes = ARRAY_SIZE(max1236_mode_list), | ||
904 | .default_mode = s0to3, | ||
905 | .info = &max1238_info, | ||
906 | .channels = max1036_channels, | ||
907 | .num_channels = ARRAY_SIZE(max1036_channels), | ||
908 | }, | ||
909 | [max1038] = { | ||
910 | .bits = 8, | ||
911 | .int_vref_mv = 4096, | ||
912 | .mode_list = max1238_mode_list, | ||
913 | .num_modes = ARRAY_SIZE(max1238_mode_list), | ||
914 | .default_mode = s0to11, | ||
915 | .info = &max1238_info, | ||
916 | .channels = max1038_channels, | ||
917 | .num_channels = ARRAY_SIZE(max1038_channels), | ||
918 | }, | ||
919 | [max1039] = { | ||
920 | .bits = 8, | ||
921 | .int_vref_mv = 2048, | ||
922 | .mode_list = max1238_mode_list, | ||
923 | .num_modes = ARRAY_SIZE(max1238_mode_list), | ||
924 | .default_mode = s0to11, | ||
925 | .info = &max1238_info, | ||
926 | .channels = max1038_channels, | ||
927 | .num_channels = ARRAY_SIZE(max1038_channels), | ||
928 | }, | ||
929 | [max1136] = { | ||
930 | .bits = 10, | ||
931 | .int_vref_mv = 4096, | ||
932 | .mode_list = max1236_mode_list, | ||
933 | .num_modes = ARRAY_SIZE(max1236_mode_list), | ||
934 | .default_mode = s0to3, | ||
935 | .info = &max1238_info, | ||
936 | .channels = max1136_channels, | ||
937 | .num_channels = ARRAY_SIZE(max1136_channels), | ||
938 | }, | ||
939 | [max1137] = { | ||
940 | .bits = 10, | ||
941 | .int_vref_mv = 2048, | ||
942 | .mode_list = max1236_mode_list, | ||
943 | .num_modes = ARRAY_SIZE(max1236_mode_list), | ||
944 | .default_mode = s0to3, | ||
945 | .info = &max1238_info, | ||
946 | .channels = max1136_channels, | ||
947 | .num_channels = ARRAY_SIZE(max1136_channels), | ||
948 | }, | ||
949 | [max1138] = { | ||
950 | .bits = 10, | ||
951 | .int_vref_mv = 4096, | ||
952 | .mode_list = max1238_mode_list, | ||
953 | .num_modes = ARRAY_SIZE(max1238_mode_list), | ||
954 | .default_mode = s0to11, | ||
955 | .info = &max1238_info, | ||
956 | .channels = max1138_channels, | ||
957 | .num_channels = ARRAY_SIZE(max1138_channels), | ||
958 | }, | ||
959 | [max1139] = { | ||
960 | .bits = 10, | ||
961 | .int_vref_mv = 2048, | ||
962 | .mode_list = max1238_mode_list, | ||
963 | .num_modes = ARRAY_SIZE(max1238_mode_list), | ||
964 | .default_mode = s0to11, | ||
965 | .info = &max1238_info, | ||
966 | .channels = max1138_channels, | ||
967 | .num_channels = ARRAY_SIZE(max1138_channels), | ||
968 | }, | ||
969 | [max1236] = { | ||
970 | .bits = 12, | ||
971 | .int_vref_mv = 4096, | ||
972 | .mode_list = max1236_mode_list, | ||
973 | .num_modes = ARRAY_SIZE(max1236_mode_list), | ||
974 | .default_mode = s0to3, | ||
975 | .info = &max1238_info, | ||
976 | .channels = max1236_channels, | ||
977 | .num_channels = ARRAY_SIZE(max1236_channels), | ||
978 | }, | ||
979 | [max1237] = { | ||
980 | .bits = 12, | ||
981 | .int_vref_mv = 2048, | ||
982 | .mode_list = max1236_mode_list, | ||
983 | .num_modes = ARRAY_SIZE(max1236_mode_list), | ||
984 | .default_mode = s0to3, | ||
985 | .info = &max1238_info, | ||
986 | .channels = max1236_channels, | ||
987 | .num_channels = ARRAY_SIZE(max1236_channels), | ||
988 | }, | ||
989 | [max1238] = { | ||
990 | .bits = 12, | ||
991 | .int_vref_mv = 4096, | ||
992 | .mode_list = max1238_mode_list, | ||
993 | .num_modes = ARRAY_SIZE(max1238_mode_list), | ||
994 | .default_mode = s0to11, | ||
995 | .info = &max1238_info, | ||
996 | .channels = max1238_channels, | ||
997 | .num_channels = ARRAY_SIZE(max1238_channels), | ||
998 | }, | ||
999 | [max1239] = { | ||
1000 | .bits = 12, | ||
1001 | .int_vref_mv = 2048, | ||
1002 | .mode_list = max1238_mode_list, | ||
1003 | .num_modes = ARRAY_SIZE(max1238_mode_list), | ||
1004 | .default_mode = s0to11, | ||
1005 | .info = &max1238_info, | ||
1006 | .channels = max1238_channels, | ||
1007 | .num_channels = ARRAY_SIZE(max1238_channels), | ||
1008 | }, | ||
1009 | [max11600] = { | ||
1010 | .bits = 8, | ||
1011 | .int_vref_mv = 4096, | ||
1012 | .mode_list = max11607_mode_list, | ||
1013 | .num_modes = ARRAY_SIZE(max11607_mode_list), | ||
1014 | .default_mode = s0to3, | ||
1015 | .info = &max1238_info, | ||
1016 | .channels = max1036_channels, | ||
1017 | .num_channels = ARRAY_SIZE(max1036_channels), | ||
1018 | }, | ||
1019 | [max11601] = { | ||
1020 | .bits = 8, | ||
1021 | .int_vref_mv = 2048, | ||
1022 | .mode_list = max11607_mode_list, | ||
1023 | .num_modes = ARRAY_SIZE(max11607_mode_list), | ||
1024 | .default_mode = s0to3, | ||
1025 | .info = &max1238_info, | ||
1026 | .channels = max1036_channels, | ||
1027 | .num_channels = ARRAY_SIZE(max1036_channels), | ||
1028 | }, | ||
1029 | [max11602] = { | ||
1030 | .bits = 8, | ||
1031 | .int_vref_mv = 4096, | ||
1032 | .mode_list = max11608_mode_list, | ||
1033 | .num_modes = ARRAY_SIZE(max11608_mode_list), | ||
1034 | .default_mode = s0to7, | ||
1035 | .info = &max1238_info, | ||
1036 | .channels = max11602_channels, | ||
1037 | .num_channels = ARRAY_SIZE(max11602_channels), | ||
1038 | }, | ||
1039 | [max11603] = { | ||
1040 | .bits = 8, | ||
1041 | .int_vref_mv = 2048, | ||
1042 | .mode_list = max11608_mode_list, | ||
1043 | .num_modes = ARRAY_SIZE(max11608_mode_list), | ||
1044 | .default_mode = s0to7, | ||
1045 | .info = &max1238_info, | ||
1046 | .channels = max11602_channels, | ||
1047 | .num_channels = ARRAY_SIZE(max11602_channels), | ||
1048 | }, | ||
1049 | [max11604] = { | ||
1050 | .bits = 8, | ||
1051 | .int_vref_mv = 4098, | ||
1052 | .mode_list = max1238_mode_list, | ||
1053 | .num_modes = ARRAY_SIZE(max1238_mode_list), | ||
1054 | .default_mode = s0to11, | ||
1055 | .info = &max1238_info, | ||
1056 | .channels = max1238_channels, | ||
1057 | .num_channels = ARRAY_SIZE(max1238_channels), | ||
1058 | }, | ||
1059 | [max11605] = { | ||
1060 | .bits = 8, | ||
1061 | .int_vref_mv = 2048, | ||
1062 | .mode_list = max1238_mode_list, | ||
1063 | .num_modes = ARRAY_SIZE(max1238_mode_list), | ||
1064 | .default_mode = s0to11, | ||
1065 | .info = &max1238_info, | ||
1066 | .channels = max1238_channels, | ||
1067 | .num_channels = ARRAY_SIZE(max1238_channels), | ||
1068 | }, | ||
1069 | [max11606] = { | ||
1070 | .bits = 10, | ||
1071 | .int_vref_mv = 4096, | ||
1072 | .mode_list = max11607_mode_list, | ||
1073 | .num_modes = ARRAY_SIZE(max11607_mode_list), | ||
1074 | .default_mode = s0to3, | ||
1075 | .info = &max1238_info, | ||
1076 | .channels = max1136_channels, | ||
1077 | .num_channels = ARRAY_SIZE(max1136_channels), | ||
1078 | }, | ||
1079 | [max11607] = { | ||
1080 | .bits = 10, | ||
1081 | .int_vref_mv = 2048, | ||
1082 | .mode_list = max11607_mode_list, | ||
1083 | .num_modes = ARRAY_SIZE(max11607_mode_list), | ||
1084 | .default_mode = s0to3, | ||
1085 | .info = &max1238_info, | ||
1086 | .channels = max1136_channels, | ||
1087 | .num_channels = ARRAY_SIZE(max1136_channels), | ||
1088 | }, | ||
1089 | [max11608] = { | ||
1090 | .bits = 10, | ||
1091 | .int_vref_mv = 4096, | ||
1092 | .mode_list = max11608_mode_list, | ||
1093 | .num_modes = ARRAY_SIZE(max11608_mode_list), | ||
1094 | .default_mode = s0to7, | ||
1095 | .info = &max1238_info, | ||
1096 | .channels = max11608_channels, | ||
1097 | .num_channels = ARRAY_SIZE(max11608_channels), | ||
1098 | }, | ||
1099 | [max11609] = { | ||
1100 | .bits = 10, | ||
1101 | .int_vref_mv = 2048, | ||
1102 | .mode_list = max11608_mode_list, | ||
1103 | .num_modes = ARRAY_SIZE(max11608_mode_list), | ||
1104 | .default_mode = s0to7, | ||
1105 | .info = &max1238_info, | ||
1106 | .channels = max11608_channels, | ||
1107 | .num_channels = ARRAY_SIZE(max11608_channels), | ||
1108 | }, | ||
1109 | [max11610] = { | ||
1110 | .bits = 10, | ||
1111 | .int_vref_mv = 4098, | ||
1112 | .mode_list = max1238_mode_list, | ||
1113 | .num_modes = ARRAY_SIZE(max1238_mode_list), | ||
1114 | .default_mode = s0to11, | ||
1115 | .info = &max1238_info, | ||
1116 | .channels = max1238_channels, | ||
1117 | .num_channels = ARRAY_SIZE(max1238_channels), | ||
1118 | }, | ||
1119 | [max11611] = { | ||
1120 | .bits = 10, | ||
1121 | .int_vref_mv = 2048, | ||
1122 | .mode_list = max1238_mode_list, | ||
1123 | .num_modes = ARRAY_SIZE(max1238_mode_list), | ||
1124 | .default_mode = s0to11, | ||
1125 | .info = &max1238_info, | ||
1126 | .channels = max1238_channels, | ||
1127 | .num_channels = ARRAY_SIZE(max1238_channels), | ||
1128 | }, | ||
1129 | [max11612] = { | ||
1130 | .bits = 12, | ||
1131 | .int_vref_mv = 4096, | ||
1132 | .mode_list = max11607_mode_list, | ||
1133 | .num_modes = ARRAY_SIZE(max11607_mode_list), | ||
1134 | .default_mode = s0to3, | ||
1135 | .info = &max1238_info, | ||
1136 | .channels = max1363_channels, | ||
1137 | .num_channels = ARRAY_SIZE(max1363_channels), | ||
1138 | }, | ||
1139 | [max11613] = { | ||
1140 | .bits = 12, | ||
1141 | .int_vref_mv = 2048, | ||
1142 | .mode_list = max11607_mode_list, | ||
1143 | .num_modes = ARRAY_SIZE(max11607_mode_list), | ||
1144 | .default_mode = s0to3, | ||
1145 | .info = &max1238_info, | ||
1146 | .channels = max1363_channels, | ||
1147 | .num_channels = ARRAY_SIZE(max1363_channels), | ||
1148 | }, | ||
1149 | [max11614] = { | ||
1150 | .bits = 12, | ||
1151 | .int_vref_mv = 4096, | ||
1152 | .mode_list = max11608_mode_list, | ||
1153 | .num_modes = ARRAY_SIZE(max11608_mode_list), | ||
1154 | .default_mode = s0to7, | ||
1155 | .info = &max1238_info, | ||
1156 | .channels = max11614_channels, | ||
1157 | .num_channels = ARRAY_SIZE(max11614_channels), | ||
1158 | }, | ||
1159 | [max11615] = { | ||
1160 | .bits = 12, | ||
1161 | .int_vref_mv = 2048, | ||
1162 | .mode_list = max11608_mode_list, | ||
1163 | .num_modes = ARRAY_SIZE(max11608_mode_list), | ||
1164 | .default_mode = s0to7, | ||
1165 | .info = &max1238_info, | ||
1166 | .channels = max11614_channels, | ||
1167 | .num_channels = ARRAY_SIZE(max11614_channels), | ||
1168 | }, | ||
1169 | [max11616] = { | ||
1170 | .bits = 12, | ||
1171 | .int_vref_mv = 4098, | ||
1172 | .mode_list = max1238_mode_list, | ||
1173 | .num_modes = ARRAY_SIZE(max1238_mode_list), | ||
1174 | .default_mode = s0to11, | ||
1175 | .info = &max1238_info, | ||
1176 | .channels = max1238_channels, | ||
1177 | .num_channels = ARRAY_SIZE(max1238_channels), | ||
1178 | }, | ||
1179 | [max11617] = { | ||
1180 | .bits = 12, | ||
1181 | .int_vref_mv = 2048, | ||
1182 | .mode_list = max1238_mode_list, | ||
1183 | .num_modes = ARRAY_SIZE(max1238_mode_list), | ||
1184 | .default_mode = s0to11, | ||
1185 | .info = &max1238_info, | ||
1186 | .channels = max1238_channels, | ||
1187 | .num_channels = ARRAY_SIZE(max1238_channels), | ||
1188 | }, | ||
1189 | [max11644] = { | ||
1190 | .bits = 12, | ||
1191 | .int_vref_mv = 2048, | ||
1192 | .mode_list = max11644_mode_list, | ||
1193 | .num_modes = ARRAY_SIZE(max11644_mode_list), | ||
1194 | .default_mode = s0to1, | ||
1195 | .info = &max1238_info, | ||
1196 | .channels = max11644_channels, | ||
1197 | .num_channels = ARRAY_SIZE(max11644_channels), | ||
1198 | }, | ||
1199 | [max11645] = { | ||
1200 | .bits = 12, | ||
1201 | .int_vref_mv = 4096, | ||
1202 | .mode_list = max11644_mode_list, | ||
1203 | .num_modes = ARRAY_SIZE(max11644_mode_list), | ||
1204 | .default_mode = s0to1, | ||
1205 | .info = &max1238_info, | ||
1206 | .channels = max11644_channels, | ||
1207 | .num_channels = ARRAY_SIZE(max11644_channels), | ||
1208 | }, | ||
1209 | [max11646] = { | ||
1210 | .bits = 10, | ||
1211 | .int_vref_mv = 2048, | ||
1212 | .mode_list = max11644_mode_list, | ||
1213 | .num_modes = ARRAY_SIZE(max11644_mode_list), | ||
1214 | .default_mode = s0to1, | ||
1215 | .info = &max1238_info, | ||
1216 | .channels = max11646_channels, | ||
1217 | .num_channels = ARRAY_SIZE(max11646_channels), | ||
1218 | }, | ||
1219 | [max11647] = { | ||
1220 | .bits = 10, | ||
1221 | .int_vref_mv = 4096, | ||
1222 | .mode_list = max11644_mode_list, | ||
1223 | .num_modes = ARRAY_SIZE(max11644_mode_list), | ||
1224 | .default_mode = s0to1, | ||
1225 | .info = &max1238_info, | ||
1226 | .channels = max11646_channels, | ||
1227 | .num_channels = ARRAY_SIZE(max11646_channels), | ||
1228 | }, | ||
1229 | }; | ||
1230 | |||
1231 | |||
1232 | |||
1233 | static int max1363_initial_setup(struct max1363_state *st) | ||
1234 | { | ||
1235 | st->setupbyte = MAX1363_SETUP_AIN3_IS_AIN3_REF_IS_VDD | ||
1236 | | MAX1363_SETUP_POWER_UP_INT_REF | ||
1237 | | MAX1363_SETUP_INT_CLOCK | ||
1238 | | MAX1363_SETUP_UNIPOLAR | ||
1239 | | MAX1363_SETUP_NORESET; | ||
1240 | |||
1241 | /* Set scan mode writes the config anyway so wait until then*/ | ||
1242 | st->setupbyte = MAX1363_SETUP_BYTE(st->setupbyte); | ||
1243 | st->current_mode = &max1363_mode_table[st->chip_info->default_mode]; | ||
1244 | st->configbyte = MAX1363_CONFIG_BYTE(st->configbyte); | ||
1245 | |||
1246 | return max1363_set_scan_mode(st); | ||
1247 | } | ||
1248 | |||
1249 | static int __devinit max1363_probe(struct i2c_client *client, | ||
1250 | const struct i2c_device_id *id) | ||
1251 | { | ||
1252 | int ret, i, regdone = 0; | ||
1253 | struct max1363_state *st; | ||
1254 | struct iio_dev *indio_dev; | ||
1255 | struct regulator *reg; | ||
1256 | |||
1257 | reg = regulator_get(&client->dev, "vcc"); | ||
1258 | if (IS_ERR(reg)) { | ||
1259 | ret = PTR_ERR(reg); | ||
1260 | goto error_out; | ||
1261 | } | ||
1262 | |||
1263 | ret = regulator_enable(reg); | ||
1264 | if (ret) | ||
1265 | goto error_put_reg; | ||
1266 | |||
1267 | indio_dev = iio_allocate_device(sizeof(struct max1363_state)); | ||
1268 | if (indio_dev == NULL) { | ||
1269 | ret = -ENOMEM; | ||
1270 | goto error_disable_reg; | ||
1271 | } | ||
1272 | st = iio_priv(indio_dev); | ||
1273 | st->reg = reg; | ||
1274 | /* this is only used for device removal purposes */ | ||
1275 | i2c_set_clientdata(client, indio_dev); | ||
1276 | |||
1277 | st->chip_info = &max1363_chip_info_tbl[id->driver_data]; | ||
1278 | st->client = client; | ||
1279 | |||
1280 | indio_dev->available_scan_masks | ||
1281 | = kzalloc(sizeof(*indio_dev->available_scan_masks)* | ||
1282 | (st->chip_info->num_modes + 1), GFP_KERNEL); | ||
1283 | if (!indio_dev->available_scan_masks) { | ||
1284 | ret = -ENOMEM; | ||
1285 | goto error_free_device; | ||
1286 | } | ||
1287 | |||
1288 | for (i = 0; i < st->chip_info->num_modes; i++) | ||
1289 | indio_dev->available_scan_masks[i] = | ||
1290 | max1363_mode_table[st->chip_info->mode_list[i]] | ||
1291 | .modemask; | ||
1292 | /* Estabilish that the iio_dev is a child of the i2c device */ | ||
1293 | indio_dev->dev.parent = &client->dev; | ||
1294 | indio_dev->name = id->name; | ||
1295 | |||
1296 | indio_dev->info = st->chip_info->info; | ||
1297 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
1298 | ret = max1363_initial_setup(st); | ||
1299 | if (ret < 0) | ||
1300 | goto error_free_available_scan_masks; | ||
1301 | |||
1302 | ret = max1363_register_ring_funcs_and_init(indio_dev); | ||
1303 | if (ret) | ||
1304 | goto error_free_available_scan_masks; | ||
1305 | |||
1306 | ret = iio_device_register(indio_dev); | ||
1307 | if (ret) | ||
1308 | goto error_cleanup_ring; | ||
1309 | regdone = 1; | ||
1310 | ret = iio_ring_buffer_register_ex(indio_dev->ring, 0, | ||
1311 | st->chip_info->channels, | ||
1312 | st->chip_info->num_channels); | ||
1313 | if (ret) | ||
1314 | goto error_cleanup_ring; | ||
1315 | |||
1316 | if (client->irq) { | ||
1317 | ret = request_threaded_irq(st->client->irq, | ||
1318 | NULL, | ||
1319 | &max1363_event_handler, | ||
1320 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | ||
1321 | "max1363_event", | ||
1322 | indio_dev); | ||
1323 | |||
1324 | if (ret) | ||
1325 | goto error_uninit_ring; | ||
1326 | } | ||
1327 | |||
1328 | return 0; | ||
1329 | |||
1330 | error_uninit_ring: | ||
1331 | iio_ring_buffer_unregister(indio_dev->ring); | ||
1332 | error_cleanup_ring: | ||
1333 | max1363_ring_cleanup(indio_dev); | ||
1334 | error_free_available_scan_masks: | ||
1335 | kfree(indio_dev->available_scan_masks); | ||
1336 | error_free_device: | ||
1337 | if (!regdone) | ||
1338 | iio_free_device(indio_dev); | ||
1339 | else | ||
1340 | iio_device_unregister(indio_dev); | ||
1341 | error_disable_reg: | ||
1342 | regulator_disable(reg); | ||
1343 | error_put_reg: | ||
1344 | regulator_put(reg); | ||
1345 | error_out: | ||
1346 | return ret; | ||
1347 | } | ||
1348 | |||
1349 | static int max1363_remove(struct i2c_client *client) | ||
1350 | { | ||
1351 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | ||
1352 | struct max1363_state *st = iio_priv(indio_dev); | ||
1353 | struct regulator *reg = st->reg; | ||
1354 | |||
1355 | if (client->irq) | ||
1356 | free_irq(st->client->irq, indio_dev); | ||
1357 | iio_ring_buffer_unregister(indio_dev->ring); | ||
1358 | max1363_ring_cleanup(indio_dev); | ||
1359 | kfree(indio_dev->available_scan_masks); | ||
1360 | if (!IS_ERR(reg)) { | ||
1361 | regulator_disable(reg); | ||
1362 | regulator_put(reg); | ||
1363 | } | ||
1364 | iio_device_unregister(indio_dev); | ||
1365 | |||
1366 | return 0; | ||
1367 | } | ||
1368 | |||
1369 | static const struct i2c_device_id max1363_id[] = { | ||
1370 | { "max1361", max1361 }, | ||
1371 | { "max1362", max1362 }, | ||
1372 | { "max1363", max1363 }, | ||
1373 | { "max1364", max1364 }, | ||
1374 | { "max1036", max1036 }, | ||
1375 | { "max1037", max1037 }, | ||
1376 | { "max1038", max1038 }, | ||
1377 | { "max1039", max1039 }, | ||
1378 | { "max1136", max1136 }, | ||
1379 | { "max1137", max1137 }, | ||
1380 | { "max1138", max1138 }, | ||
1381 | { "max1139", max1139 }, | ||
1382 | { "max1236", max1236 }, | ||
1383 | { "max1237", max1237 }, | ||
1384 | { "max1238", max1238 }, | ||
1385 | { "max1239", max1239 }, | ||
1386 | { "max11600", max11600 }, | ||
1387 | { "max11601", max11601 }, | ||
1388 | { "max11602", max11602 }, | ||
1389 | { "max11603", max11603 }, | ||
1390 | { "max11604", max11604 }, | ||
1391 | { "max11605", max11605 }, | ||
1392 | { "max11606", max11606 }, | ||
1393 | { "max11607", max11607 }, | ||
1394 | { "max11608", max11608 }, | ||
1395 | { "max11609", max11609 }, | ||
1396 | { "max11610", max11610 }, | ||
1397 | { "max11611", max11611 }, | ||
1398 | { "max11612", max11612 }, | ||
1399 | { "max11613", max11613 }, | ||
1400 | { "max11614", max11614 }, | ||
1401 | { "max11615", max11615 }, | ||
1402 | { "max11616", max11616 }, | ||
1403 | { "max11617", max11617 }, | ||
1404 | {} | ||
1405 | }; | ||
1406 | |||
1407 | MODULE_DEVICE_TABLE(i2c, max1363_id); | ||
1408 | |||
1409 | static struct i2c_driver max1363_driver = { | ||
1410 | .driver = { | ||
1411 | .name = "max1363", | ||
1412 | }, | ||
1413 | .probe = max1363_probe, | ||
1414 | .remove = max1363_remove, | ||
1415 | .id_table = max1363_id, | ||
1416 | }; | ||
1417 | |||
1418 | static __init int max1363_init(void) | ||
1419 | { | ||
1420 | return i2c_add_driver(&max1363_driver); | ||
1421 | } | ||
1422 | |||
1423 | static __exit void max1363_exit(void) | ||
1424 | { | ||
1425 | i2c_del_driver(&max1363_driver); | ||
1426 | } | ||
1427 | |||
1428 | MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); | ||
1429 | MODULE_DESCRIPTION("Maxim 1363 ADC"); | ||
1430 | MODULE_LICENSE("GPL v2"); | ||
1431 | |||
1432 | module_init(max1363_init); | ||
1433 | module_exit(max1363_exit); | ||
diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c new file mode 100644 index 00000000000..f43befd1f77 --- /dev/null +++ b/drivers/staging/iio/adc/max1363_ring.c | |||
@@ -0,0 +1,209 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Jonathan Cameron | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * max1363_ring.c | ||
9 | */ | ||
10 | |||
11 | #include <linux/interrupt.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/sysfs.h> | ||
16 | #include <linux/list.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/bitops.h> | ||
19 | |||
20 | #include "../iio.h" | ||
21 | #include "../ring_generic.h" | ||
22 | #include "../ring_sw.h" | ||
23 | #include "../trigger.h" | ||
24 | #include "../sysfs.h" | ||
25 | |||
26 | #include "max1363.h" | ||
27 | |||
28 | int max1363_single_channel_from_ring(long mask, struct max1363_state *st) | ||
29 | { | ||
30 | struct iio_ring_buffer *ring = iio_priv_to_dev(st)->ring; | ||
31 | int count = 0, ret; | ||
32 | u8 *ring_data; | ||
33 | if (!(st->current_mode->modemask & mask)) { | ||
34 | ret = -EBUSY; | ||
35 | goto error_ret; | ||
36 | } | ||
37 | |||
38 | ring_data = kmalloc(ring->access->get_bytes_per_datum(ring), | ||
39 | GFP_KERNEL); | ||
40 | if (ring_data == NULL) { | ||
41 | ret = -ENOMEM; | ||
42 | goto error_ret; | ||
43 | } | ||
44 | ret = ring->access->read_last(ring, ring_data); | ||
45 | if (ret) | ||
46 | goto error_free_ring_data; | ||
47 | /* Need a count of channels prior to this one */ | ||
48 | mask >>= 1; | ||
49 | while (mask) { | ||
50 | if (mask & st->current_mode->modemask) | ||
51 | count++; | ||
52 | mask >>= 1; | ||
53 | } | ||
54 | if (st->chip_info->bits != 8) | ||
55 | ret = ((int)(ring_data[count*2 + 0] & 0x0F) << 8) | ||
56 | + (int)(ring_data[count*2 + 1]); | ||
57 | else | ||
58 | ret = ring_data[count]; | ||
59 | |||
60 | error_free_ring_data: | ||
61 | kfree(ring_data); | ||
62 | error_ret: | ||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | |||
67 | /** | ||
68 | * max1363_ring_preenable() - setup the parameters of the ring before enabling | ||
69 | * | ||
70 | * The complex nature of the setting of the nuber of bytes per datum is due | ||
71 | * to this driver currently ensuring that the timestamp is stored at an 8 | ||
72 | * byte boundary. | ||
73 | **/ | ||
74 | static int max1363_ring_preenable(struct iio_dev *indio_dev) | ||
75 | { | ||
76 | struct max1363_state *st = iio_priv(indio_dev); | ||
77 | struct iio_ring_buffer *ring = indio_dev->ring; | ||
78 | size_t d_size = 0; | ||
79 | unsigned long numvals; | ||
80 | |||
81 | /* | ||
82 | * Need to figure out the current mode based upon the requested | ||
83 | * scan mask in iio_dev | ||
84 | */ | ||
85 | st->current_mode = max1363_match_mode(ring->scan_mask, | ||
86 | st->chip_info); | ||
87 | if (!st->current_mode) | ||
88 | return -EINVAL; | ||
89 | |||
90 | max1363_set_scan_mode(st); | ||
91 | |||
92 | numvals = hweight_long(st->current_mode->modemask); | ||
93 | if (ring->access->set_bytes_per_datum) { | ||
94 | if (ring->scan_timestamp) | ||
95 | d_size += sizeof(s64); | ||
96 | if (st->chip_info->bits != 8) | ||
97 | d_size += numvals*2; | ||
98 | else | ||
99 | d_size += numvals; | ||
100 | if (ring->scan_timestamp && (d_size % 8)) | ||
101 | d_size += 8 - (d_size % 8); | ||
102 | ring->access->set_bytes_per_datum(ring, d_size); | ||
103 | } | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static irqreturn_t max1363_trigger_handler(int irq, void *p) | ||
109 | { | ||
110 | struct iio_poll_func *pf = p; | ||
111 | struct iio_dev *indio_dev = pf->private_data; | ||
112 | struct max1363_state *st = iio_priv(indio_dev); | ||
113 | s64 time_ns; | ||
114 | __u8 *rxbuf; | ||
115 | int b_sent; | ||
116 | size_t d_size; | ||
117 | unsigned long numvals = hweight_long(st->current_mode->modemask); | ||
118 | |||
119 | /* Ensure the timestamp is 8 byte aligned */ | ||
120 | if (st->chip_info->bits != 8) | ||
121 | d_size = numvals*2 + sizeof(s64); | ||
122 | else | ||
123 | d_size = numvals + sizeof(s64); | ||
124 | if (d_size % sizeof(s64)) | ||
125 | d_size += sizeof(s64) - (d_size % sizeof(s64)); | ||
126 | |||
127 | /* Monitor mode prevents reading. Whilst not currently implemented | ||
128 | * might as well have this test in here in the meantime as it does | ||
129 | * no harm. | ||
130 | */ | ||
131 | if (numvals == 0) | ||
132 | return IRQ_HANDLED; | ||
133 | |||
134 | rxbuf = kmalloc(d_size, GFP_KERNEL); | ||
135 | if (rxbuf == NULL) | ||
136 | return -ENOMEM; | ||
137 | if (st->chip_info->bits != 8) | ||
138 | b_sent = i2c_master_recv(st->client, rxbuf, numvals*2); | ||
139 | else | ||
140 | b_sent = i2c_master_recv(st->client, rxbuf, numvals); | ||
141 | if (b_sent < 0) | ||
142 | goto done; | ||
143 | |||
144 | time_ns = iio_get_time_ns(); | ||
145 | |||
146 | memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns)); | ||
147 | |||
148 | indio_dev->ring->access->store_to(indio_dev->ring, rxbuf, time_ns); | ||
149 | done: | ||
150 | iio_trigger_notify_done(indio_dev->trig); | ||
151 | kfree(rxbuf); | ||
152 | |||
153 | return IRQ_HANDLED; | ||
154 | } | ||
155 | |||
156 | static const struct iio_ring_setup_ops max1363_ring_setup_ops = { | ||
157 | .postenable = &iio_triggered_ring_postenable, | ||
158 | .preenable = &max1363_ring_preenable, | ||
159 | .predisable = &iio_triggered_ring_predisable, | ||
160 | }; | ||
161 | |||
162 | int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev) | ||
163 | { | ||
164 | struct max1363_state *st = iio_priv(indio_dev); | ||
165 | int ret = 0; | ||
166 | |||
167 | indio_dev->ring = iio_sw_rb_allocate(indio_dev); | ||
168 | if (!indio_dev->ring) { | ||
169 | ret = -ENOMEM; | ||
170 | goto error_ret; | ||
171 | } | ||
172 | indio_dev->pollfunc = iio_alloc_pollfunc(NULL, | ||
173 | &max1363_trigger_handler, | ||
174 | IRQF_ONESHOT, | ||
175 | indio_dev, | ||
176 | "%s_consumer%d", | ||
177 | st->client->name, | ||
178 | indio_dev->id); | ||
179 | if (indio_dev->pollfunc == NULL) { | ||
180 | ret = -ENOMEM; | ||
181 | goto error_deallocate_sw_rb; | ||
182 | } | ||
183 | /* Effectively select the ring buffer implementation */ | ||
184 | indio_dev->ring->access = &ring_sw_access_funcs; | ||
185 | /* Ring buffer functions - here trigger setup related */ | ||
186 | indio_dev->ring->setup_ops = &max1363_ring_setup_ops; | ||
187 | |||
188 | /* Flag that polled ring buffering is possible */ | ||
189 | indio_dev->modes |= INDIO_RING_TRIGGERED; | ||
190 | |||
191 | return 0; | ||
192 | |||
193 | error_deallocate_sw_rb: | ||
194 | iio_sw_rb_free(indio_dev->ring); | ||
195 | error_ret: | ||
196 | return ret; | ||
197 | } | ||
198 | |||
199 | void max1363_ring_cleanup(struct iio_dev *indio_dev) | ||
200 | { | ||
201 | /* ensure that the trigger has been detached */ | ||
202 | if (indio_dev->trig) { | ||
203 | iio_put_trigger(indio_dev->trig); | ||
204 | iio_trigger_dettach_poll_func(indio_dev->trig, | ||
205 | indio_dev->pollfunc); | ||
206 | } | ||
207 | iio_dealloc_pollfunc(indio_dev->pollfunc); | ||
208 | iio_sw_rb_free(indio_dev->ring); | ||
209 | } | ||
diff --git a/drivers/staging/iio/chrdev.h b/drivers/staging/iio/chrdev.h new file mode 100644 index 00000000000..3e31ee6220e --- /dev/null +++ b/drivers/staging/iio/chrdev.h | |||
@@ -0,0 +1,75 @@ | |||
1 | /* The industrial I/O core - character device related | ||
2 | * | ||
3 | * Copyright (c) 2008 Jonathan Cameron | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 2 as published by | ||
7 | * the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #ifndef _IIO_CHRDEV_H_ | ||
11 | #define _IIO_CHRDEV_H_ | ||
12 | struct iio_dev; | ||
13 | |||
14 | /** | ||
15 | * struct iio_handler - Structure used to specify file operations | ||
16 | * for a particular chrdev | ||
17 | * @chrdev: character device structure | ||
18 | * @id: the location in the handler table - used for deallocation. | ||
19 | * @flags: file operations related flags including busy flag. | ||
20 | * @private: handler specific data used by the fileops registered with | ||
21 | * the chrdev. | ||
22 | */ | ||
23 | struct iio_handler { | ||
24 | struct cdev chrdev; | ||
25 | int id; | ||
26 | unsigned long flags; | ||
27 | void *private; | ||
28 | }; | ||
29 | |||
30 | #define iio_cdev_to_handler(cd) \ | ||
31 | container_of(cd, struct iio_handler, chrdev) | ||
32 | |||
33 | /** | ||
34 | * struct iio_event_data - The actual event being pushed to userspace | ||
35 | * @id: event identifier | ||
36 | * @timestamp: best estimate of time of event occurrence (often from | ||
37 | * the interrupt handler) | ||
38 | */ | ||
39 | struct iio_event_data { | ||
40 | int id; | ||
41 | s64 timestamp; | ||
42 | }; | ||
43 | |||
44 | /** | ||
45 | * struct iio_detected_event_list - list element for events that have occurred | ||
46 | * @list: linked list header | ||
47 | * @ev: the event itself | ||
48 | */ | ||
49 | struct iio_detected_event_list { | ||
50 | struct list_head list; | ||
51 | struct iio_event_data ev; | ||
52 | }; | ||
53 | |||
54 | /** | ||
55 | * struct iio_event_interface - chrdev interface for an event line | ||
56 | * @dev: device assocated with event interface | ||
57 | * @handler: fileoperations and related control for the chrdev | ||
58 | * @wait: wait queue to allow blocking reads of events | ||
59 | * @event_list_lock: mutex to protect the list of detected events | ||
60 | * @det_events: list of detected events | ||
61 | * @max_events: maximum number of events before new ones are dropped | ||
62 | * @current_events: number of events in detected list | ||
63 | */ | ||
64 | struct iio_event_interface { | ||
65 | struct device dev; | ||
66 | struct iio_handler handler; | ||
67 | wait_queue_head_t wait; | ||
68 | struct mutex event_list_lock; | ||
69 | struct list_head det_events; | ||
70 | int max_events; | ||
71 | int current_events; | ||
72 | struct list_head dev_attr_list; | ||
73 | }; | ||
74 | |||
75 | #endif | ||
diff --git a/drivers/staging/iio/dac/Kconfig b/drivers/staging/iio/dac/Kconfig new file mode 100644 index 00000000000..7ddae357f20 --- /dev/null +++ b/drivers/staging/iio/dac/Kconfig | |||
@@ -0,0 +1,64 @@ | |||
1 | # | ||
2 | # DAC drivers | ||
3 | # | ||
4 | comment "Digital to analog convertors" | ||
5 | |||
6 | config AD5624R_SPI | ||
7 | tristate "Analog Devices AD5624/44/64R DAC spi driver" | ||
8 | depends on SPI | ||
9 | help | ||
10 | Say yes here to build support for Analog Devices AD5624R, AD5644R and | ||
11 | AD5664R convertors (DAC). This driver uses the common SPI interface. | ||
12 | |||
13 | config AD5446 | ||
14 | tristate "Analog Devices AD5444/6, AD5620/40/60 and AD5542A/12A DAC SPI driver" | ||
15 | depends on SPI | ||
16 | help | ||
17 | Say yes here to build support for Analog Devices AD5444, AD5446, | ||
18 | AD5512A, AD5542A, AD5543, AD5553, AD5601, AD5611, AD5620, AD5621, | ||
19 | AD5640, AD5660 DACs. | ||
20 | |||
21 | To compile this driver as a module, choose M here: the | ||
22 | module will be called ad5446. | ||
23 | |||
24 | config AD5504 | ||
25 | tristate "Analog Devices AD5504/AD5501 DAC SPI driver" | ||
26 | depends on SPI | ||
27 | help | ||
28 | Say yes here to build support for Analog Devices AD5504, AD5501, | ||
29 | High Voltage Digital to Analog Converter. | ||
30 | |||
31 | To compile this driver as a module, choose M here: the | ||
32 | module will be called ad5504. | ||
33 | |||
34 | config AD5791 | ||
35 | tristate "Analog Devices AD5760/AD5780/AD5781/AD5791 DAC SPI driver" | ||
36 | depends on SPI | ||
37 | help | ||
38 | Say yes here to build support for Analog Devices AD5760, AD5780, | ||
39 | AD5781, AD5791 High Resolution Voltage Output Digital to | ||
40 | Analog Converter. | ||
41 | |||
42 | To compile this driver as a module, choose M here: the | ||
43 | module will be called ad5791. | ||
44 | |||
45 | config AD5686 | ||
46 | tristate "Analog Devices AD5686R/AD5685R/AD5684R DAC SPI driver" | ||
47 | depends on SPI | ||
48 | help | ||
49 | Say yes here to build support for Analog Devices AD5686R, AD5685R, | ||
50 | AD5684R, AD5791 Voltage Output Digital to | ||
51 | Analog Converter. | ||
52 | |||
53 | To compile this driver as a module, choose M here: the | ||
54 | module will be called ad5686. | ||
55 | |||
56 | config MAX517 | ||
57 | tristate "Maxim MAX517/518/519 DAC driver" | ||
58 | depends on I2C && EXPERIMENTAL | ||
59 | help | ||
60 | If you say yes here you get support for the Maxim chips MAX517, | ||
61 | MAX518 and MAX519 (I2C 8-Bit DACs with rail-to-rail outputs). | ||
62 | |||
63 | This driver can also be built as a module. If so, the module | ||
64 | will be called max517. | ||
diff --git a/drivers/staging/iio/dac/Makefile b/drivers/staging/iio/dac/Makefile new file mode 100644 index 00000000000..7f4f2ed031e --- /dev/null +++ b/drivers/staging/iio/dac/Makefile | |||
@@ -0,0 +1,10 @@ | |||
1 | # | ||
2 | # Makefile for industrial I/O DAC drivers | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o | ||
6 | obj-$(CONFIG_AD5504) += ad5504.o | ||
7 | obj-$(CONFIG_AD5446) += ad5446.o | ||
8 | obj-$(CONFIG_AD5791) += ad5791.o | ||
9 | obj-$(CONFIG_AD5686) += ad5686.o | ||
10 | obj-$(CONFIG_MAX517) += max517.o | ||
diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c new file mode 100644 index 00000000000..e8a9d0bf1ed --- /dev/null +++ b/drivers/staging/iio/dac/ad5446.c | |||
@@ -0,0 +1,480 @@ | |||
1 | /* | ||
2 | * AD5446 SPI DAC driver | ||
3 | * | ||
4 | * Copyright 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
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 | |||
20 | #include "../iio.h" | ||
21 | #include "../sysfs.h" | ||
22 | #include "dac.h" | ||
23 | |||
24 | #include "ad5446.h" | ||
25 | |||
26 | static void ad5446_store_sample(struct ad5446_state *st, unsigned val) | ||
27 | { | ||
28 | st->data.d16 = cpu_to_be16(AD5446_LOAD | | ||
29 | (val << st->chip_info->left_shift)); | ||
30 | } | ||
31 | |||
32 | static void ad5542_store_sample(struct ad5446_state *st, unsigned val) | ||
33 | { | ||
34 | st->data.d16 = cpu_to_be16(val << st->chip_info->left_shift); | ||
35 | } | ||
36 | |||
37 | static void ad5620_store_sample(struct ad5446_state *st, unsigned val) | ||
38 | { | ||
39 | st->data.d16 = cpu_to_be16(AD5620_LOAD | | ||
40 | (val << st->chip_info->left_shift)); | ||
41 | } | ||
42 | |||
43 | static void ad5660_store_sample(struct ad5446_state *st, unsigned val) | ||
44 | { | ||
45 | val |= AD5660_LOAD; | ||
46 | st->data.d24[0] = (val >> 16) & 0xFF; | ||
47 | st->data.d24[1] = (val >> 8) & 0xFF; | ||
48 | st->data.d24[2] = val & 0xFF; | ||
49 | } | ||
50 | |||
51 | static void ad5620_store_pwr_down(struct ad5446_state *st, unsigned mode) | ||
52 | { | ||
53 | st->data.d16 = cpu_to_be16(mode << 14); | ||
54 | } | ||
55 | |||
56 | static void ad5660_store_pwr_down(struct ad5446_state *st, unsigned mode) | ||
57 | { | ||
58 | unsigned val = mode << 16; | ||
59 | |||
60 | st->data.d24[0] = (val >> 16) & 0xFF; | ||
61 | st->data.d24[1] = (val >> 8) & 0xFF; | ||
62 | st->data.d24[2] = val & 0xFF; | ||
63 | } | ||
64 | |||
65 | static ssize_t ad5446_write(struct device *dev, | ||
66 | struct device_attribute *attr, | ||
67 | const char *buf, | ||
68 | size_t len) | ||
69 | { | ||
70 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
71 | struct ad5446_state *st = iio_priv(dev_info); | ||
72 | int ret; | ||
73 | long val; | ||
74 | |||
75 | ret = strict_strtol(buf, 10, &val); | ||
76 | if (ret) | ||
77 | goto error_ret; | ||
78 | |||
79 | if (val > RES_MASK(st->chip_info->bits)) { | ||
80 | ret = -EINVAL; | ||
81 | goto error_ret; | ||
82 | } | ||
83 | |||
84 | mutex_lock(&dev_info->mlock); | ||
85 | st->cached_val = val; | ||
86 | st->chip_info->store_sample(st, val); | ||
87 | ret = spi_sync(st->spi, &st->msg); | ||
88 | mutex_unlock(&dev_info->mlock); | ||
89 | |||
90 | error_ret: | ||
91 | return ret ? ret : len; | ||
92 | } | ||
93 | |||
94 | static IIO_DEV_ATTR_OUT_RAW(0, ad5446_write, 0); | ||
95 | |||
96 | static ssize_t ad5446_show_scale(struct device *dev, | ||
97 | struct device_attribute *attr, | ||
98 | char *buf) | ||
99 | { | ||
100 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
101 | struct ad5446_state *st = iio_priv(dev_info); | ||
102 | /* Corresponds to Vref / 2^(bits) */ | ||
103 | unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits; | ||
104 | |||
105 | return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); | ||
106 | } | ||
107 | static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5446_show_scale, NULL, 0); | ||
108 | |||
109 | static ssize_t ad5446_write_powerdown_mode(struct device *dev, | ||
110 | struct device_attribute *attr, | ||
111 | const char *buf, size_t len) | ||
112 | { | ||
113 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
114 | struct ad5446_state *st = iio_priv(dev_info); | ||
115 | |||
116 | if (sysfs_streq(buf, "1kohm_to_gnd")) | ||
117 | st->pwr_down_mode = MODE_PWRDWN_1k; | ||
118 | else if (sysfs_streq(buf, "100kohm_to_gnd")) | ||
119 | st->pwr_down_mode = MODE_PWRDWN_100k; | ||
120 | else if (sysfs_streq(buf, "three_state")) | ||
121 | st->pwr_down_mode = MODE_PWRDWN_TRISTATE; | ||
122 | else | ||
123 | return -EINVAL; | ||
124 | |||
125 | return len; | ||
126 | } | ||
127 | |||
128 | static ssize_t ad5446_read_powerdown_mode(struct device *dev, | ||
129 | struct device_attribute *attr, char *buf) | ||
130 | { | ||
131 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
132 | struct ad5446_state *st = iio_priv(dev_info); | ||
133 | |||
134 | char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"}; | ||
135 | |||
136 | return sprintf(buf, "%s\n", mode[st->pwr_down_mode]); | ||
137 | } | ||
138 | |||
139 | static ssize_t ad5446_read_dac_powerdown(struct device *dev, | ||
140 | struct device_attribute *attr, | ||
141 | char *buf) | ||
142 | { | ||
143 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
144 | struct ad5446_state *st = iio_priv(dev_info); | ||
145 | |||
146 | return sprintf(buf, "%d\n", st->pwr_down); | ||
147 | } | ||
148 | |||
149 | static ssize_t ad5446_write_dac_powerdown(struct device *dev, | ||
150 | struct device_attribute *attr, | ||
151 | const char *buf, size_t len) | ||
152 | { | ||
153 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
154 | struct ad5446_state *st = iio_priv(dev_info); | ||
155 | unsigned long readin; | ||
156 | int ret; | ||
157 | |||
158 | ret = strict_strtol(buf, 10, &readin); | ||
159 | if (ret) | ||
160 | return ret; | ||
161 | |||
162 | if (readin > 1) | ||
163 | ret = -EINVAL; | ||
164 | |||
165 | mutex_lock(&dev_info->mlock); | ||
166 | st->pwr_down = readin; | ||
167 | |||
168 | if (st->pwr_down) | ||
169 | st->chip_info->store_pwr_down(st, st->pwr_down_mode); | ||
170 | else | ||
171 | st->chip_info->store_sample(st, st->cached_val); | ||
172 | |||
173 | ret = spi_sync(st->spi, &st->msg); | ||
174 | mutex_unlock(&dev_info->mlock); | ||
175 | |||
176 | return ret ? ret : len; | ||
177 | } | ||
178 | |||
179 | static IIO_DEVICE_ATTR(out_powerdown_mode, S_IRUGO | S_IWUSR, | ||
180 | ad5446_read_powerdown_mode, | ||
181 | ad5446_write_powerdown_mode, 0); | ||
182 | |||
183 | static IIO_CONST_ATTR(out_powerdown_mode_available, | ||
184 | "1kohm_to_gnd 100kohm_to_gnd three_state"); | ||
185 | |||
186 | static IIO_DEVICE_ATTR(out0_powerdown, S_IRUGO | S_IWUSR, | ||
187 | ad5446_read_dac_powerdown, | ||
188 | ad5446_write_dac_powerdown, 0); | ||
189 | |||
190 | static struct attribute *ad5446_attributes[] = { | ||
191 | &iio_dev_attr_out0_raw.dev_attr.attr, | ||
192 | &iio_dev_attr_out_scale.dev_attr.attr, | ||
193 | &iio_dev_attr_out0_powerdown.dev_attr.attr, | ||
194 | &iio_dev_attr_out_powerdown_mode.dev_attr.attr, | ||
195 | &iio_const_attr_out_powerdown_mode_available.dev_attr.attr, | ||
196 | NULL, | ||
197 | }; | ||
198 | |||
199 | static mode_t ad5446_attr_is_visible(struct kobject *kobj, | ||
200 | struct attribute *attr, int n) | ||
201 | { | ||
202 | struct device *dev = container_of(kobj, struct device, kobj); | ||
203 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
204 | struct ad5446_state *st = iio_priv(dev_info); | ||
205 | |||
206 | mode_t mode = attr->mode; | ||
207 | |||
208 | if (!st->chip_info->store_pwr_down && | ||
209 | (attr == &iio_dev_attr_out0_powerdown.dev_attr.attr || | ||
210 | attr == &iio_dev_attr_out_powerdown_mode.dev_attr.attr || | ||
211 | attr == | ||
212 | &iio_const_attr_out_powerdown_mode_available.dev_attr.attr)) | ||
213 | mode = 0; | ||
214 | |||
215 | return mode; | ||
216 | } | ||
217 | |||
218 | static const struct attribute_group ad5446_attribute_group = { | ||
219 | .attrs = ad5446_attributes, | ||
220 | .is_visible = ad5446_attr_is_visible, | ||
221 | }; | ||
222 | |||
223 | static const struct ad5446_chip_info ad5446_chip_info_tbl[] = { | ||
224 | [ID_AD5444] = { | ||
225 | .bits = 12, | ||
226 | .storagebits = 16, | ||
227 | .left_shift = 2, | ||
228 | .store_sample = ad5446_store_sample, | ||
229 | }, | ||
230 | [ID_AD5446] = { | ||
231 | .bits = 14, | ||
232 | .storagebits = 16, | ||
233 | .left_shift = 0, | ||
234 | .store_sample = ad5446_store_sample, | ||
235 | }, | ||
236 | [ID_AD5541A] = { | ||
237 | .bits = 16, | ||
238 | .storagebits = 16, | ||
239 | .left_shift = 0, | ||
240 | .store_sample = ad5542_store_sample, | ||
241 | }, | ||
242 | [ID_AD5542A] = { | ||
243 | .bits = 16, | ||
244 | .storagebits = 16, | ||
245 | .left_shift = 0, | ||
246 | .store_sample = ad5542_store_sample, | ||
247 | }, | ||
248 | [ID_AD5543] = { | ||
249 | .bits = 16, | ||
250 | .storagebits = 16, | ||
251 | .left_shift = 0, | ||
252 | .store_sample = ad5542_store_sample, | ||
253 | }, | ||
254 | [ID_AD5512A] = { | ||
255 | .bits = 12, | ||
256 | .storagebits = 16, | ||
257 | .left_shift = 4, | ||
258 | .store_sample = ad5542_store_sample, | ||
259 | }, | ||
260 | [ID_AD5553] = { | ||
261 | .bits = 14, | ||
262 | .storagebits = 16, | ||
263 | .left_shift = 0, | ||
264 | .store_sample = ad5542_store_sample, | ||
265 | }, | ||
266 | [ID_AD5601] = { | ||
267 | .bits = 8, | ||
268 | .storagebits = 16, | ||
269 | .left_shift = 6, | ||
270 | .store_sample = ad5542_store_sample, | ||
271 | .store_pwr_down = ad5620_store_pwr_down, | ||
272 | }, | ||
273 | [ID_AD5611] = { | ||
274 | .bits = 10, | ||
275 | .storagebits = 16, | ||
276 | .left_shift = 4, | ||
277 | .store_sample = ad5542_store_sample, | ||
278 | .store_pwr_down = ad5620_store_pwr_down, | ||
279 | }, | ||
280 | [ID_AD5621] = { | ||
281 | .bits = 12, | ||
282 | .storagebits = 16, | ||
283 | .left_shift = 2, | ||
284 | .store_sample = ad5542_store_sample, | ||
285 | .store_pwr_down = ad5620_store_pwr_down, | ||
286 | }, | ||
287 | [ID_AD5620_2500] = { | ||
288 | .bits = 12, | ||
289 | .storagebits = 16, | ||
290 | .left_shift = 2, | ||
291 | .int_vref_mv = 2500, | ||
292 | .store_sample = ad5620_store_sample, | ||
293 | .store_pwr_down = ad5620_store_pwr_down, | ||
294 | }, | ||
295 | [ID_AD5620_1250] = { | ||
296 | .bits = 12, | ||
297 | .storagebits = 16, | ||
298 | .left_shift = 2, | ||
299 | .int_vref_mv = 1250, | ||
300 | .store_sample = ad5620_store_sample, | ||
301 | .store_pwr_down = ad5620_store_pwr_down, | ||
302 | }, | ||
303 | [ID_AD5640_2500] = { | ||
304 | .bits = 14, | ||
305 | .storagebits = 16, | ||
306 | .left_shift = 0, | ||
307 | .int_vref_mv = 2500, | ||
308 | .store_sample = ad5620_store_sample, | ||
309 | .store_pwr_down = ad5620_store_pwr_down, | ||
310 | }, | ||
311 | [ID_AD5640_1250] = { | ||
312 | .bits = 14, | ||
313 | .storagebits = 16, | ||
314 | .left_shift = 0, | ||
315 | .int_vref_mv = 1250, | ||
316 | .store_sample = ad5620_store_sample, | ||
317 | .store_pwr_down = ad5620_store_pwr_down, | ||
318 | }, | ||
319 | [ID_AD5660_2500] = { | ||
320 | .bits = 16, | ||
321 | .storagebits = 24, | ||
322 | .left_shift = 0, | ||
323 | .int_vref_mv = 2500, | ||
324 | .store_sample = ad5660_store_sample, | ||
325 | .store_pwr_down = ad5660_store_pwr_down, | ||
326 | }, | ||
327 | [ID_AD5660_1250] = { | ||
328 | .bits = 16, | ||
329 | .storagebits = 24, | ||
330 | .left_shift = 0, | ||
331 | .int_vref_mv = 1250, | ||
332 | .store_sample = ad5660_store_sample, | ||
333 | .store_pwr_down = ad5660_store_pwr_down, | ||
334 | }, | ||
335 | }; | ||
336 | |||
337 | static const struct iio_info ad5446_info = { | ||
338 | .attrs = &ad5446_attribute_group, | ||
339 | .driver_module = THIS_MODULE, | ||
340 | }; | ||
341 | |||
342 | static int __devinit ad5446_probe(struct spi_device *spi) | ||
343 | { | ||
344 | struct ad5446_state *st; | ||
345 | struct iio_dev *indio_dev; | ||
346 | struct regulator *reg; | ||
347 | int ret, voltage_uv = 0; | ||
348 | |||
349 | reg = regulator_get(&spi->dev, "vcc"); | ||
350 | if (!IS_ERR(reg)) { | ||
351 | ret = regulator_enable(reg); | ||
352 | if (ret) | ||
353 | goto error_put_reg; | ||
354 | |||
355 | voltage_uv = regulator_get_voltage(reg); | ||
356 | } | ||
357 | |||
358 | indio_dev = iio_allocate_device(sizeof(*st)); | ||
359 | if (indio_dev == NULL) { | ||
360 | ret = -ENOMEM; | ||
361 | goto error_disable_reg; | ||
362 | } | ||
363 | st = iio_priv(indio_dev); | ||
364 | st->chip_info = | ||
365 | &ad5446_chip_info_tbl[spi_get_device_id(spi)->driver_data]; | ||
366 | |||
367 | spi_set_drvdata(spi, indio_dev); | ||
368 | st->reg = reg; | ||
369 | st->spi = spi; | ||
370 | |||
371 | /* Estabilish that the iio_dev is a child of the spi device */ | ||
372 | indio_dev->dev.parent = &spi->dev; | ||
373 | indio_dev->name = spi_get_device_id(spi)->name; | ||
374 | indio_dev->info = &ad5446_info; | ||
375 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
376 | |||
377 | /* Setup default message */ | ||
378 | |||
379 | st->xfer.tx_buf = &st->data; | ||
380 | st->xfer.len = st->chip_info->storagebits / 8; | ||
381 | |||
382 | spi_message_init(&st->msg); | ||
383 | spi_message_add_tail(&st->xfer, &st->msg); | ||
384 | |||
385 | switch (spi_get_device_id(spi)->driver_data) { | ||
386 | case ID_AD5620_2500: | ||
387 | case ID_AD5620_1250: | ||
388 | case ID_AD5640_2500: | ||
389 | case ID_AD5640_1250: | ||
390 | case ID_AD5660_2500: | ||
391 | case ID_AD5660_1250: | ||
392 | st->vref_mv = st->chip_info->int_vref_mv; | ||
393 | break; | ||
394 | default: | ||
395 | if (voltage_uv) | ||
396 | st->vref_mv = voltage_uv / 1000; | ||
397 | else | ||
398 | dev_warn(&spi->dev, | ||
399 | "reference voltage unspecified\n"); | ||
400 | } | ||
401 | |||
402 | ret = iio_device_register(indio_dev); | ||
403 | if (ret) | ||
404 | goto error_free_device; | ||
405 | |||
406 | return 0; | ||
407 | |||
408 | error_free_device: | ||
409 | iio_free_device(indio_dev); | ||
410 | error_disable_reg: | ||
411 | if (!IS_ERR(reg)) | ||
412 | regulator_disable(reg); | ||
413 | error_put_reg: | ||
414 | if (!IS_ERR(reg)) | ||
415 | regulator_put(reg); | ||
416 | |||
417 | return ret; | ||
418 | } | ||
419 | |||
420 | static int ad5446_remove(struct spi_device *spi) | ||
421 | { | ||
422 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
423 | struct ad5446_state *st = iio_priv(indio_dev); | ||
424 | struct regulator *reg = st->reg; | ||
425 | |||
426 | iio_device_unregister(indio_dev); | ||
427 | if (!IS_ERR(reg)) { | ||
428 | regulator_disable(reg); | ||
429 | regulator_put(reg); | ||
430 | } | ||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | static const struct spi_device_id ad5446_id[] = { | ||
435 | {"ad5444", ID_AD5444}, | ||
436 | {"ad5446", ID_AD5446}, | ||
437 | {"ad5512a", ID_AD5512A}, | ||
438 | {"ad5541a", ID_AD5541A}, | ||
439 | {"ad5542a", ID_AD5542A}, | ||
440 | {"ad5543", ID_AD5543}, | ||
441 | {"ad5553", ID_AD5553}, | ||
442 | {"ad5601", ID_AD5601}, | ||
443 | {"ad5611", ID_AD5611}, | ||
444 | {"ad5621", ID_AD5621}, | ||
445 | {"ad5620-2500", ID_AD5620_2500}, /* AD5620/40/60: */ | ||
446 | {"ad5620-1250", ID_AD5620_1250}, /* part numbers may look differently */ | ||
447 | {"ad5640-2500", ID_AD5640_2500}, | ||
448 | {"ad5640-1250", ID_AD5640_1250}, | ||
449 | {"ad5660-2500", ID_AD5660_2500}, | ||
450 | {"ad5660-1250", ID_AD5660_1250}, | ||
451 | {} | ||
452 | }; | ||
453 | |||
454 | static struct spi_driver ad5446_driver = { | ||
455 | .driver = { | ||
456 | .name = "ad5446", | ||
457 | .bus = &spi_bus_type, | ||
458 | .owner = THIS_MODULE, | ||
459 | }, | ||
460 | .probe = ad5446_probe, | ||
461 | .remove = __devexit_p(ad5446_remove), | ||
462 | .id_table = ad5446_id, | ||
463 | }; | ||
464 | |||
465 | static int __init ad5446_init(void) | ||
466 | { | ||
467 | return spi_register_driver(&ad5446_driver); | ||
468 | } | ||
469 | module_init(ad5446_init); | ||
470 | |||
471 | static void __exit ad5446_exit(void) | ||
472 | { | ||
473 | spi_unregister_driver(&ad5446_driver); | ||
474 | } | ||
475 | module_exit(ad5446_exit); | ||
476 | |||
477 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
478 | MODULE_DESCRIPTION("Analog Devices AD5444/AD5446 DAC"); | ||
479 | MODULE_LICENSE("GPL v2"); | ||
480 | MODULE_ALIAS("spi:ad5446"); | ||
diff --git a/drivers/staging/iio/dac/ad5446.h b/drivers/staging/iio/dac/ad5446.h new file mode 100644 index 00000000000..7118d653ac3 --- /dev/null +++ b/drivers/staging/iio/dac/ad5446.h | |||
@@ -0,0 +1,109 @@ | |||
1 | /* | ||
2 | * AD5446 SPI DAC driver | ||
3 | * | ||
4 | * Copyright 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | #ifndef IIO_DAC_AD5446_H_ | ||
9 | #define IIO_DAC_AD5446_H_ | ||
10 | |||
11 | /* DAC Control Bits */ | ||
12 | |||
13 | #define AD5446_LOAD (0x0 << 14) /* Load and update */ | ||
14 | #define AD5446_SDO_DIS (0x1 << 14) /* Disable SDO */ | ||
15 | #define AD5446_NOP (0x2 << 14) /* No operation */ | ||
16 | #define AD5446_CLK_RISING (0x3 << 14) /* Clock data on rising edge */ | ||
17 | |||
18 | #define AD5620_LOAD (0x0 << 14) /* Load and update Norm Operation*/ | ||
19 | #define AD5620_PWRDWN_1k (0x1 << 14) /* Power-down: 1kOhm to GND */ | ||
20 | #define AD5620_PWRDWN_100k (0x2 << 14) /* Power-down: 100kOhm to GND */ | ||
21 | #define AD5620_PWRDWN_TRISTATE (0x3 << 14) /* Power-down: Three-state */ | ||
22 | |||
23 | #define AD5660_LOAD (0x0 << 16) /* Load and update Norm Operation*/ | ||
24 | #define AD5660_PWRDWN_1k (0x1 << 16) /* Power-down: 1kOhm to GND */ | ||
25 | #define AD5660_PWRDWN_100k (0x2 << 16) /* Power-down: 100kOhm to GND */ | ||
26 | #define AD5660_PWRDWN_TRISTATE (0x3 << 16) /* Power-down: Three-state */ | ||
27 | |||
28 | #define RES_MASK(bits) ((1 << (bits)) - 1) | ||
29 | |||
30 | #define MODE_PWRDWN_1k 0x1 | ||
31 | #define MODE_PWRDWN_100k 0x2 | ||
32 | #define MODE_PWRDWN_TRISTATE 0x3 | ||
33 | |||
34 | /** | ||
35 | * struct ad5446_state - driver instance specific data | ||
36 | * @spi: spi_device | ||
37 | * @chip_info: chip model specific constants, available modes etc | ||
38 | * @reg: supply regulator | ||
39 | * @poll_work: bottom half of polling interrupt handler | ||
40 | * @vref_mv: actual reference voltage used | ||
41 | * @xfer: default spi transfer | ||
42 | * @msg: default spi message | ||
43 | * @data: spi transmit buffer | ||
44 | */ | ||
45 | |||
46 | struct ad5446_state { | ||
47 | struct spi_device *spi; | ||
48 | const struct ad5446_chip_info *chip_info; | ||
49 | struct regulator *reg; | ||
50 | struct work_struct poll_work; | ||
51 | unsigned short vref_mv; | ||
52 | unsigned cached_val; | ||
53 | unsigned pwr_down_mode; | ||
54 | unsigned pwr_down; | ||
55 | struct spi_transfer xfer; | ||
56 | struct spi_message msg; | ||
57 | union { | ||
58 | unsigned short d16; | ||
59 | unsigned char d24[3]; | ||
60 | } data; | ||
61 | }; | ||
62 | |||
63 | /** | ||
64 | * struct ad5446_chip_info - chip specific information | ||
65 | * @bits: accuracy of the DAC in bits | ||
66 | * @storagebits: number of bits written to the DAC | ||
67 | * @left_shift: number of bits the datum must be shifted | ||
68 | * @int_vref_mv: AD5620/40/60: the internal reference voltage | ||
69 | * @store_sample: chip specific helper function to store the datum | ||
70 | * @store_sample: chip specific helper function to store the powerpown cmd | ||
71 | */ | ||
72 | |||
73 | struct ad5446_chip_info { | ||
74 | u8 bits; | ||
75 | u8 storagebits; | ||
76 | u8 left_shift; | ||
77 | u16 int_vref_mv; | ||
78 | void (*store_sample) (struct ad5446_state *st, unsigned val); | ||
79 | void (*store_pwr_down) (struct ad5446_state *st, unsigned mode); | ||
80 | }; | ||
81 | |||
82 | /** | ||
83 | * ad5446_supported_device_ids: | ||
84 | * The AD5620/40/60 parts are available in different fixed internal reference | ||
85 | * voltage options. The actual part numbers may look differently | ||
86 | * (and a bit cryptic), however this style is used to make clear which | ||
87 | * parts are supported here. | ||
88 | */ | ||
89 | |||
90 | enum ad5446_supported_device_ids { | ||
91 | ID_AD5444, | ||
92 | ID_AD5446, | ||
93 | ID_AD5541A, | ||
94 | ID_AD5542A, | ||
95 | ID_AD5543, | ||
96 | ID_AD5512A, | ||
97 | ID_AD5553, | ||
98 | ID_AD5601, | ||
99 | ID_AD5611, | ||
100 | ID_AD5621, | ||
101 | ID_AD5620_2500, | ||
102 | ID_AD5620_1250, | ||
103 | ID_AD5640_2500, | ||
104 | ID_AD5640_1250, | ||
105 | ID_AD5660_2500, | ||
106 | ID_AD5660_1250, | ||
107 | }; | ||
108 | |||
109 | #endif /* IIO_DAC_AD5446_H_ */ | ||
diff --git a/drivers/staging/iio/dac/ad5504.c b/drivers/staging/iio/dac/ad5504.c new file mode 100644 index 00000000000..1915f459868 --- /dev/null +++ b/drivers/staging/iio/dac/ad5504.c | |||
@@ -0,0 +1,397 @@ | |||
1 | /* | ||
2 | * AD5504, AD5501 High Voltage Digital to Analog Converter | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/gpio.h> | ||
11 | #include <linux/fs.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/spi/spi.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/sysfs.h> | ||
17 | #include <linux/regulator/consumer.h> | ||
18 | |||
19 | #include "../iio.h" | ||
20 | #include "../sysfs.h" | ||
21 | #include "dac.h" | ||
22 | #include "ad5504.h" | ||
23 | |||
24 | static int ad5504_spi_write(struct spi_device *spi, u8 addr, u16 val) | ||
25 | { | ||
26 | u16 tmp = cpu_to_be16(AD5504_CMD_WRITE | | ||
27 | AD5504_ADDR(addr) | | ||
28 | (val & AD5504_RES_MASK)); | ||
29 | |||
30 | return spi_write(spi, (u8 *)&tmp, 2); | ||
31 | } | ||
32 | |||
33 | static int ad5504_spi_read(struct spi_device *spi, u8 addr, u16 *val) | ||
34 | { | ||
35 | u16 tmp = cpu_to_be16(AD5504_CMD_READ | AD5504_ADDR(addr)); | ||
36 | int ret; | ||
37 | struct spi_transfer t = { | ||
38 | .tx_buf = &tmp, | ||
39 | .rx_buf = val, | ||
40 | .len = 2, | ||
41 | }; | ||
42 | struct spi_message m; | ||
43 | |||
44 | spi_message_init(&m); | ||
45 | spi_message_add_tail(&t, &m); | ||
46 | ret = spi_sync(spi, &m); | ||
47 | |||
48 | *val = be16_to_cpu(*val) & AD5504_RES_MASK; | ||
49 | |||
50 | return ret; | ||
51 | } | ||
52 | |||
53 | static ssize_t ad5504_write_dac(struct device *dev, | ||
54 | struct device_attribute *attr, | ||
55 | const char *buf, size_t len) | ||
56 | { | ||
57 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
58 | struct ad5504_state *st = iio_priv(indio_dev); | ||
59 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
60 | long readin; | ||
61 | int ret; | ||
62 | |||
63 | ret = strict_strtol(buf, 10, &readin); | ||
64 | if (ret) | ||
65 | return ret; | ||
66 | |||
67 | ret = ad5504_spi_write(st->spi, this_attr->address, readin); | ||
68 | return ret ? ret : len; | ||
69 | } | ||
70 | |||
71 | static ssize_t ad5504_read_dac(struct device *dev, | ||
72 | struct device_attribute *attr, | ||
73 | char *buf) | ||
74 | { | ||
75 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
76 | struct ad5504_state *st = iio_priv(indio_dev); | ||
77 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
78 | int ret; | ||
79 | u16 val; | ||
80 | |||
81 | ret = ad5504_spi_read(st->spi, this_attr->address, &val); | ||
82 | if (ret) | ||
83 | return ret; | ||
84 | |||
85 | return sprintf(buf, "%d\n", val); | ||
86 | } | ||
87 | |||
88 | static ssize_t ad5504_read_powerdown_mode(struct device *dev, | ||
89 | struct device_attribute *attr, char *buf) | ||
90 | { | ||
91 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
92 | struct ad5504_state *st = iio_priv(indio_dev); | ||
93 | |||
94 | const char mode[][14] = {"20kohm_to_gnd", "three_state"}; | ||
95 | |||
96 | return sprintf(buf, "%s\n", mode[st->pwr_down_mode]); | ||
97 | } | ||
98 | |||
99 | static ssize_t ad5504_write_powerdown_mode(struct device *dev, | ||
100 | struct device_attribute *attr, | ||
101 | const char *buf, size_t len) | ||
102 | { | ||
103 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
104 | struct ad5504_state *st = iio_priv(indio_dev); | ||
105 | int ret; | ||
106 | |||
107 | if (sysfs_streq(buf, "20kohm_to_gnd")) | ||
108 | st->pwr_down_mode = AD5504_DAC_PWRDN_20K; | ||
109 | else if (sysfs_streq(buf, "three_state")) | ||
110 | st->pwr_down_mode = AD5504_DAC_PWRDN_3STATE; | ||
111 | else | ||
112 | ret = -EINVAL; | ||
113 | |||
114 | return ret ? ret : len; | ||
115 | } | ||
116 | |||
117 | static ssize_t ad5504_read_dac_powerdown(struct device *dev, | ||
118 | struct device_attribute *attr, | ||
119 | char *buf) | ||
120 | { | ||
121 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
122 | struct ad5504_state *st = iio_priv(indio_dev); | ||
123 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
124 | |||
125 | return sprintf(buf, "%d\n", | ||
126 | !(st->pwr_down_mask & (1 << this_attr->address))); | ||
127 | } | ||
128 | |||
129 | static ssize_t ad5504_write_dac_powerdown(struct device *dev, | ||
130 | struct device_attribute *attr, | ||
131 | const char *buf, size_t len) | ||
132 | { | ||
133 | long readin; | ||
134 | int ret; | ||
135 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
136 | struct ad5504_state *st = iio_priv(indio_dev); | ||
137 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
138 | |||
139 | ret = strict_strtol(buf, 10, &readin); | ||
140 | if (ret) | ||
141 | return ret; | ||
142 | |||
143 | if (readin == 0) | ||
144 | st->pwr_down_mask |= (1 << this_attr->address); | ||
145 | else if (readin == 1) | ||
146 | st->pwr_down_mask &= ~(1 << this_attr->address); | ||
147 | else | ||
148 | ret = -EINVAL; | ||
149 | |||
150 | ret = ad5504_spi_write(st->spi, AD5504_ADDR_CTRL, | ||
151 | AD5504_DAC_PWRDWN_MODE(st->pwr_down_mode) | | ||
152 | AD5504_DAC_PWR(st->pwr_down_mask)); | ||
153 | |||
154 | /* writes to the CTRL register must be followed by a NOOP */ | ||
155 | ad5504_spi_write(st->spi, AD5504_ADDR_NOOP, 0); | ||
156 | |||
157 | return ret ? ret : len; | ||
158 | } | ||
159 | |||
160 | static ssize_t ad5504_show_scale(struct device *dev, | ||
161 | struct device_attribute *attr, | ||
162 | char *buf) | ||
163 | { | ||
164 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
165 | struct ad5504_state *st = iio_priv(indio_dev); | ||
166 | /* Corresponds to Vref / 2^(bits) */ | ||
167 | unsigned int scale_uv = (st->vref_mv * 1000) >> AD5505_BITS; | ||
168 | |||
169 | return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); | ||
170 | } | ||
171 | static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5504_show_scale, NULL, 0); | ||
172 | |||
173 | #define IIO_DEV_ATTR_OUT_RW_RAW(_num, _show, _store, _addr) \ | ||
174 | IIO_DEVICE_ATTR(out##_num##_raw, \ | ||
175 | S_IRUGO | S_IWUSR, _show, _store, _addr) | ||
176 | |||
177 | static IIO_DEV_ATTR_OUT_RW_RAW(0, ad5504_read_dac, | ||
178 | ad5504_write_dac, AD5504_ADDR_DAC0); | ||
179 | static IIO_DEV_ATTR_OUT_RW_RAW(1, ad5504_read_dac, | ||
180 | ad5504_write_dac, AD5504_ADDR_DAC1); | ||
181 | static IIO_DEV_ATTR_OUT_RW_RAW(2, ad5504_read_dac, | ||
182 | ad5504_write_dac, AD5504_ADDR_DAC2); | ||
183 | static IIO_DEV_ATTR_OUT_RW_RAW(3, ad5504_read_dac, | ||
184 | ad5504_write_dac, AD5504_ADDR_DAC3); | ||
185 | |||
186 | static IIO_DEVICE_ATTR(out_powerdown_mode, S_IRUGO | | ||
187 | S_IWUSR, ad5504_read_powerdown_mode, | ||
188 | ad5504_write_powerdown_mode, 0); | ||
189 | |||
190 | static IIO_CONST_ATTR(out_powerdown_mode_available, | ||
191 | "20kohm_to_gnd three_state"); | ||
192 | |||
193 | #define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr) \ | ||
194 | IIO_DEVICE_ATTR(out##_num##_powerdown, \ | ||
195 | S_IRUGO | S_IWUSR, _show, _store, _addr) | ||
196 | |||
197 | static IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5504_read_dac_powerdown, | ||
198 | ad5504_write_dac_powerdown, 0); | ||
199 | static IIO_DEV_ATTR_DAC_POWERDOWN(1, ad5504_read_dac_powerdown, | ||
200 | ad5504_write_dac_powerdown, 1); | ||
201 | static IIO_DEV_ATTR_DAC_POWERDOWN(2, ad5504_read_dac_powerdown, | ||
202 | ad5504_write_dac_powerdown, 2); | ||
203 | static IIO_DEV_ATTR_DAC_POWERDOWN(3, ad5504_read_dac_powerdown, | ||
204 | ad5504_write_dac_powerdown, 3); | ||
205 | |||
206 | static struct attribute *ad5504_attributes[] = { | ||
207 | &iio_dev_attr_out0_raw.dev_attr.attr, | ||
208 | &iio_dev_attr_out1_raw.dev_attr.attr, | ||
209 | &iio_dev_attr_out2_raw.dev_attr.attr, | ||
210 | &iio_dev_attr_out3_raw.dev_attr.attr, | ||
211 | &iio_dev_attr_out0_powerdown.dev_attr.attr, | ||
212 | &iio_dev_attr_out1_powerdown.dev_attr.attr, | ||
213 | &iio_dev_attr_out2_powerdown.dev_attr.attr, | ||
214 | &iio_dev_attr_out3_powerdown.dev_attr.attr, | ||
215 | &iio_dev_attr_out_powerdown_mode.dev_attr.attr, | ||
216 | &iio_const_attr_out_powerdown_mode_available.dev_attr.attr, | ||
217 | &iio_dev_attr_out_scale.dev_attr.attr, | ||
218 | NULL, | ||
219 | }; | ||
220 | |||
221 | static const struct attribute_group ad5504_attribute_group = { | ||
222 | .attrs = ad5504_attributes, | ||
223 | }; | ||
224 | |||
225 | static struct attribute *ad5501_attributes[] = { | ||
226 | &iio_dev_attr_out0_raw.dev_attr.attr, | ||
227 | &iio_dev_attr_out0_powerdown.dev_attr.attr, | ||
228 | &iio_dev_attr_out_powerdown_mode.dev_attr.attr, | ||
229 | &iio_const_attr_out_powerdown_mode_available.dev_attr.attr, | ||
230 | &iio_dev_attr_out_scale.dev_attr.attr, | ||
231 | NULL, | ||
232 | }; | ||
233 | |||
234 | static const struct attribute_group ad5501_attribute_group = { | ||
235 | .attrs = ad5501_attributes, | ||
236 | }; | ||
237 | |||
238 | static IIO_CONST_ATTR(temp0_thresh_rising_value, "110000"); | ||
239 | static IIO_CONST_ATTR(temp0_thresh_rising_en, "1"); | ||
240 | |||
241 | static struct attribute *ad5504_ev_attributes[] = { | ||
242 | &iio_const_attr_temp0_thresh_rising_value.dev_attr.attr, | ||
243 | &iio_const_attr_temp0_thresh_rising_en.dev_attr.attr, | ||
244 | NULL, | ||
245 | }; | ||
246 | |||
247 | static struct attribute_group ad5504_ev_attribute_group = { | ||
248 | .attrs = ad5504_ev_attributes, | ||
249 | }; | ||
250 | |||
251 | static irqreturn_t ad5504_event_handler(int irq, void *private) | ||
252 | { | ||
253 | iio_push_event(private, 0, | ||
254 | IIO_UNMOD_EVENT_CODE(IIO_EV_CLASS_TEMP, | ||
255 | 0, | ||
256 | IIO_EV_TYPE_THRESH, | ||
257 | IIO_EV_DIR_RISING), | ||
258 | iio_get_time_ns()); | ||
259 | |||
260 | return IRQ_HANDLED; | ||
261 | } | ||
262 | |||
263 | static const struct iio_info ad5504_info = { | ||
264 | .attrs = &ad5504_attribute_group, | ||
265 | .num_interrupt_lines = 1, | ||
266 | .event_attrs = &ad5504_ev_attribute_group, | ||
267 | .driver_module = THIS_MODULE, | ||
268 | }; | ||
269 | |||
270 | static const struct iio_info ad5501_info = { | ||
271 | .attrs = &ad5501_attribute_group, | ||
272 | .num_interrupt_lines = 1, | ||
273 | .event_attrs = &ad5504_ev_attribute_group, | ||
274 | .driver_module = THIS_MODULE, | ||
275 | }; | ||
276 | |||
277 | static int __devinit ad5504_probe(struct spi_device *spi) | ||
278 | { | ||
279 | struct ad5504_platform_data *pdata = spi->dev.platform_data; | ||
280 | struct iio_dev *indio_dev; | ||
281 | struct ad5504_state *st; | ||
282 | struct regulator *reg; | ||
283 | int ret, voltage_uv = 0; | ||
284 | |||
285 | reg = regulator_get(&spi->dev, "vcc"); | ||
286 | if (!IS_ERR(reg)) { | ||
287 | ret = regulator_enable(reg); | ||
288 | if (ret) | ||
289 | goto error_put_reg; | ||
290 | |||
291 | voltage_uv = regulator_get_voltage(reg); | ||
292 | } | ||
293 | |||
294 | indio_dev = iio_allocate_device(sizeof(*st)); | ||
295 | if (indio_dev == NULL) { | ||
296 | ret = -ENOMEM; | ||
297 | goto error_disable_reg; | ||
298 | } | ||
299 | spi_set_drvdata(spi, indio_dev); | ||
300 | st = iio_priv(indio_dev); | ||
301 | if (voltage_uv) | ||
302 | st->vref_mv = voltage_uv / 1000; | ||
303 | else if (pdata) | ||
304 | st->vref_mv = pdata->vref_mv; | ||
305 | else | ||
306 | dev_warn(&spi->dev, "reference voltage unspecified\n"); | ||
307 | |||
308 | st->reg = reg; | ||
309 | st->spi = spi; | ||
310 | indio_dev->dev.parent = &spi->dev; | ||
311 | indio_dev->name = spi_get_device_id(st->spi)->name; | ||
312 | if (spi_get_device_id(st->spi)->driver_data == ID_AD5501) | ||
313 | indio_dev->info = &ad5501_info; | ||
314 | else | ||
315 | indio_dev->info = &ad5504_info; | ||
316 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
317 | |||
318 | ret = iio_device_register(indio_dev); | ||
319 | if (ret) | ||
320 | goto error_free_dev; | ||
321 | |||
322 | if (spi->irq) { | ||
323 | ret = request_threaded_irq(spi->irq, | ||
324 | NULL, | ||
325 | &ad5504_event_handler, | ||
326 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
327 | spi_get_device_id(st->spi)->name, | ||
328 | indio_dev); | ||
329 | if (ret) | ||
330 | goto error_unreg_iio_device; | ||
331 | } | ||
332 | |||
333 | return 0; | ||
334 | |||
335 | error_unreg_iio_device: | ||
336 | iio_device_unregister(indio_dev); | ||
337 | error_free_dev: | ||
338 | iio_free_device(indio_dev); | ||
339 | error_disable_reg: | ||
340 | if (!IS_ERR(reg)) | ||
341 | regulator_disable(st->reg); | ||
342 | error_put_reg: | ||
343 | if (!IS_ERR(reg)) | ||
344 | regulator_put(reg); | ||
345 | |||
346 | return ret; | ||
347 | } | ||
348 | |||
349 | static int __devexit ad5504_remove(struct spi_device *spi) | ||
350 | { | ||
351 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
352 | struct ad5504_state *st = iio_priv(indio_dev); | ||
353 | struct regulator *reg = st->reg; | ||
354 | if (spi->irq) | ||
355 | free_irq(spi->irq, indio_dev); | ||
356 | |||
357 | iio_device_unregister(indio_dev); | ||
358 | |||
359 | if (!IS_ERR(reg)) { | ||
360 | regulator_disable(reg); | ||
361 | regulator_put(reg); | ||
362 | } | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | static const struct spi_device_id ad5504_id[] = { | ||
368 | {"ad5504", ID_AD5504}, | ||
369 | {"ad5501", ID_AD5501}, | ||
370 | {} | ||
371 | }; | ||
372 | |||
373 | static struct spi_driver ad5504_driver = { | ||
374 | .driver = { | ||
375 | .name = "ad5504", | ||
376 | .owner = THIS_MODULE, | ||
377 | }, | ||
378 | .probe = ad5504_probe, | ||
379 | .remove = __devexit_p(ad5504_remove), | ||
380 | .id_table = ad5504_id, | ||
381 | }; | ||
382 | |||
383 | static __init int ad5504_spi_init(void) | ||
384 | { | ||
385 | return spi_register_driver(&ad5504_driver); | ||
386 | } | ||
387 | module_init(ad5504_spi_init); | ||
388 | |||
389 | static __exit void ad5504_spi_exit(void) | ||
390 | { | ||
391 | spi_unregister_driver(&ad5504_driver); | ||
392 | } | ||
393 | module_exit(ad5504_spi_exit); | ||
394 | |||
395 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
396 | MODULE_DESCRIPTION("Analog Devices AD5501/AD5501 DAC"); | ||
397 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/staging/iio/dac/ad5504.h b/drivers/staging/iio/dac/ad5504.h new file mode 100644 index 00000000000..85beb1dd29b --- /dev/null +++ b/drivers/staging/iio/dac/ad5504.h | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * AD5504 SPI DAC driver | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #ifndef SPI_AD5504_H_ | ||
10 | #define SPI_AD5504_H_ | ||
11 | |||
12 | #define AD5505_BITS 12 | ||
13 | #define AD5504_RES_MASK ((1 << (AD5505_BITS)) - 1) | ||
14 | |||
15 | #define AD5504_CMD_READ (1 << 15) | ||
16 | #define AD5504_CMD_WRITE (0 << 15) | ||
17 | #define AD5504_ADDR(addr) ((addr) << 12) | ||
18 | |||
19 | /* Registers */ | ||
20 | #define AD5504_ADDR_NOOP 0 | ||
21 | #define AD5504_ADDR_DAC0 1 | ||
22 | #define AD5504_ADDR_DAC1 2 | ||
23 | #define AD5504_ADDR_DAC2 3 | ||
24 | #define AD5504_ADDR_DAC3 4 | ||
25 | #define AD5504_ADDR_ALL_DAC 5 | ||
26 | #define AD5504_ADDR_CTRL 7 | ||
27 | |||
28 | /* Control Register */ | ||
29 | #define AD5504_DAC_PWR(ch) ((ch) << 2) | ||
30 | #define AD5504_DAC_PWRDWN_MODE(mode) ((mode) << 6) | ||
31 | #define AD5504_DAC_PWRDN_20K 0 | ||
32 | #define AD5504_DAC_PWRDN_3STATE 1 | ||
33 | |||
34 | /* | ||
35 | * TODO: struct ad5504_platform_data needs to go into include/linux/iio | ||
36 | */ | ||
37 | |||
38 | struct ad5504_platform_data { | ||
39 | u16 vref_mv; | ||
40 | }; | ||
41 | |||
42 | /** | ||
43 | * struct ad5446_state - driver instance specific data | ||
44 | * @us: spi_device | ||
45 | * @reg: supply regulator | ||
46 | * @vref_mv: actual reference voltage used | ||
47 | * @pwr_down_mask power down mask | ||
48 | * @pwr_down_mode current power down mode | ||
49 | */ | ||
50 | |||
51 | struct ad5504_state { | ||
52 | struct spi_device *spi; | ||
53 | struct regulator *reg; | ||
54 | unsigned short vref_mv; | ||
55 | unsigned pwr_down_mask; | ||
56 | unsigned pwr_down_mode; | ||
57 | }; | ||
58 | |||
59 | /** | ||
60 | * ad5504_supported_device_ids: | ||
61 | */ | ||
62 | |||
63 | enum ad5504_supported_device_ids { | ||
64 | ID_AD5504, | ||
65 | ID_AD5501, | ||
66 | }; | ||
67 | |||
68 | #endif /* SPI_AD5504_H_ */ | ||
diff --git a/drivers/staging/iio/dac/ad5624r.h b/drivers/staging/iio/dac/ad5624r.h new file mode 100644 index 00000000000..b71c6a03e78 --- /dev/null +++ b/drivers/staging/iio/dac/ad5624r.h | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * AD5624R SPI DAC driver | ||
3 | * | ||
4 | * Copyright 2010-2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | #ifndef SPI_AD5624R_H_ | ||
9 | #define SPI_AD5624R_H_ | ||
10 | |||
11 | #define AD5624R_DAC_CHANNELS 4 | ||
12 | |||
13 | #define AD5624R_ADDR_DAC0 0x0 | ||
14 | #define AD5624R_ADDR_DAC1 0x1 | ||
15 | #define AD5624R_ADDR_DAC2 0x2 | ||
16 | #define AD5624R_ADDR_DAC3 0x3 | ||
17 | #define AD5624R_ADDR_ALL_DAC 0x7 | ||
18 | |||
19 | #define AD5624R_CMD_WRITE_INPUT_N 0x0 | ||
20 | #define AD5624R_CMD_UPDATE_DAC_N 0x1 | ||
21 | #define AD5624R_CMD_WRITE_INPUT_N_UPDATE_ALL 0x2 | ||
22 | #define AD5624R_CMD_WRITE_INPUT_N_UPDATE_N 0x3 | ||
23 | #define AD5624R_CMD_POWERDOWN_DAC 0x4 | ||
24 | #define AD5624R_CMD_RESET 0x5 | ||
25 | #define AD5624R_CMD_LDAC_SETUP 0x6 | ||
26 | #define AD5624R_CMD_INTERNAL_REFER_SETUP 0x7 | ||
27 | |||
28 | #define AD5624R_LDAC_PWRDN_NONE 0x0 | ||
29 | #define AD5624R_LDAC_PWRDN_1K 0x1 | ||
30 | #define AD5624R_LDAC_PWRDN_100K 0x2 | ||
31 | #define AD5624R_LDAC_PWRDN_3STATE 0x3 | ||
32 | |||
33 | /** | ||
34 | * struct ad5624r_chip_info - chip specific information | ||
35 | * @bits: accuracy of the DAC in bits | ||
36 | * @int_vref_mv: AD5620/40/60: the internal reference voltage | ||
37 | */ | ||
38 | |||
39 | struct ad5624r_chip_info { | ||
40 | u8 bits; | ||
41 | u16 int_vref_mv; | ||
42 | }; | ||
43 | |||
44 | /** | ||
45 | * struct ad5446_state - driver instance specific data | ||
46 | * @indio_dev: the industrial I/O device | ||
47 | * @us: spi_device | ||
48 | * @chip_info: chip model specific constants, available modes etc | ||
49 | * @reg: supply regulator | ||
50 | * @vref_mv: actual reference voltage used | ||
51 | * @pwr_down_mask power down mask | ||
52 | * @pwr_down_mode current power down mode | ||
53 | */ | ||
54 | |||
55 | struct ad5624r_state { | ||
56 | struct spi_device *us; | ||
57 | const struct ad5624r_chip_info *chip_info; | ||
58 | struct regulator *reg; | ||
59 | unsigned short vref_mv; | ||
60 | unsigned pwr_down_mask; | ||
61 | unsigned pwr_down_mode; | ||
62 | }; | ||
63 | |||
64 | /** | ||
65 | * ad5624r_supported_device_ids: | ||
66 | * The AD5624/44/64 parts are available in different | ||
67 | * fixed internal reference voltage options. | ||
68 | */ | ||
69 | |||
70 | enum ad5624r_supported_device_ids { | ||
71 | ID_AD5624R3, | ||
72 | ID_AD5644R3, | ||
73 | ID_AD5664R3, | ||
74 | ID_AD5624R5, | ||
75 | ID_AD5644R5, | ||
76 | ID_AD5664R5, | ||
77 | }; | ||
78 | |||
79 | #endif /* SPI_AD5624R_H_ */ | ||
diff --git a/drivers/staging/iio/dac/ad5624r_spi.c b/drivers/staging/iio/dac/ad5624r_spi.c new file mode 100644 index 00000000000..a5b3776718e --- /dev/null +++ b/drivers/staging/iio/dac/ad5624r_spi.c | |||
@@ -0,0 +1,336 @@ | |||
1 | /* | ||
2 | * AD5624R, AD5644R, AD5664R Digital to analog convertors spi driver | ||
3 | * | ||
4 | * Copyright 2010-2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/gpio.h> | ||
11 | #include <linux/fs.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/spi/spi.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/sysfs.h> | ||
17 | #include <linux/regulator/consumer.h> | ||
18 | |||
19 | #include "../iio.h" | ||
20 | #include "../sysfs.h" | ||
21 | #include "dac.h" | ||
22 | #include "ad5624r.h" | ||
23 | |||
24 | static const struct ad5624r_chip_info ad5624r_chip_info_tbl[] = { | ||
25 | [ID_AD5624R3] = { | ||
26 | .bits = 12, | ||
27 | .int_vref_mv = 1250, | ||
28 | }, | ||
29 | [ID_AD5644R3] = { | ||
30 | .bits = 14, | ||
31 | .int_vref_mv = 1250, | ||
32 | }, | ||
33 | [ID_AD5664R3] = { | ||
34 | .bits = 16, | ||
35 | .int_vref_mv = 1250, | ||
36 | }, | ||
37 | [ID_AD5624R5] = { | ||
38 | .bits = 12, | ||
39 | .int_vref_mv = 2500, | ||
40 | }, | ||
41 | [ID_AD5644R5] = { | ||
42 | .bits = 14, | ||
43 | .int_vref_mv = 2500, | ||
44 | }, | ||
45 | [ID_AD5664R5] = { | ||
46 | .bits = 16, | ||
47 | .int_vref_mv = 2500, | ||
48 | }, | ||
49 | }; | ||
50 | |||
51 | static int ad5624r_spi_write(struct spi_device *spi, | ||
52 | u8 cmd, u8 addr, u16 val, u8 len) | ||
53 | { | ||
54 | u32 data; | ||
55 | u8 msg[3]; | ||
56 | |||
57 | /* | ||
58 | * The input shift register is 24 bits wide. The first two bits are | ||
59 | * don't care bits. The next three are the command bits, C2 to C0, | ||
60 | * followed by the 3-bit DAC address, A2 to A0, and then the | ||
61 | * 16-, 14-, 12-bit data-word. The data-word comprises the 16-, | ||
62 | * 14-, 12-bit input code followed by 0, 2, or 4 don't care bits, | ||
63 | * for the AD5664R, AD5644R, and AD5624R, respectively. | ||
64 | */ | ||
65 | data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << (16 - len)); | ||
66 | msg[0] = data >> 16; | ||
67 | msg[1] = data >> 8; | ||
68 | msg[2] = data; | ||
69 | |||
70 | return spi_write(spi, msg, 3); | ||
71 | } | ||
72 | |||
73 | static ssize_t ad5624r_write_dac(struct device *dev, | ||
74 | struct device_attribute *attr, | ||
75 | const char *buf, size_t len) | ||
76 | { | ||
77 | long readin; | ||
78 | int ret; | ||
79 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
80 | struct ad5624r_state *st = iio_priv(indio_dev); | ||
81 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
82 | |||
83 | ret = strict_strtol(buf, 10, &readin); | ||
84 | if (ret) | ||
85 | return ret; | ||
86 | |||
87 | ret = ad5624r_spi_write(st->us, AD5624R_CMD_WRITE_INPUT_N_UPDATE_N, | ||
88 | this_attr->address, readin, | ||
89 | st->chip_info->bits); | ||
90 | return ret ? ret : len; | ||
91 | } | ||
92 | |||
93 | static ssize_t ad5624r_read_powerdown_mode(struct device *dev, | ||
94 | struct device_attribute *attr, char *buf) | ||
95 | { | ||
96 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
97 | struct ad5624r_state *st = iio_priv(indio_dev); | ||
98 | |||
99 | char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"}; | ||
100 | |||
101 | return sprintf(buf, "%s\n", mode[st->pwr_down_mode]); | ||
102 | } | ||
103 | |||
104 | static ssize_t ad5624r_write_powerdown_mode(struct device *dev, | ||
105 | struct device_attribute *attr, | ||
106 | const char *buf, size_t len) | ||
107 | { | ||
108 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
109 | struct ad5624r_state *st = iio_priv(indio_dev); | ||
110 | int ret; | ||
111 | |||
112 | if (sysfs_streq(buf, "1kohm_to_gnd")) | ||
113 | st->pwr_down_mode = AD5624R_LDAC_PWRDN_1K; | ||
114 | else if (sysfs_streq(buf, "100kohm_to_gnd")) | ||
115 | st->pwr_down_mode = AD5624R_LDAC_PWRDN_100K; | ||
116 | else if (sysfs_streq(buf, "three_state")) | ||
117 | st->pwr_down_mode = AD5624R_LDAC_PWRDN_3STATE; | ||
118 | else | ||
119 | ret = -EINVAL; | ||
120 | |||
121 | return ret ? ret : len; | ||
122 | } | ||
123 | |||
124 | static ssize_t ad5624r_read_dac_powerdown(struct device *dev, | ||
125 | struct device_attribute *attr, | ||
126 | char *buf) | ||
127 | { | ||
128 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
129 | struct ad5624r_state *st = iio_priv(indio_dev); | ||
130 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
131 | |||
132 | return sprintf(buf, "%d\n", | ||
133 | !!(st->pwr_down_mask & (1 << this_attr->address))); | ||
134 | } | ||
135 | |||
136 | static ssize_t ad5624r_write_dac_powerdown(struct device *dev, | ||
137 | struct device_attribute *attr, | ||
138 | const char *buf, size_t len) | ||
139 | { | ||
140 | long readin; | ||
141 | int ret; | ||
142 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
143 | struct ad5624r_state *st = iio_priv(indio_dev); | ||
144 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
145 | |||
146 | ret = strict_strtol(buf, 10, &readin); | ||
147 | if (ret) | ||
148 | return ret; | ||
149 | |||
150 | if (readin == 1) | ||
151 | st->pwr_down_mask |= (1 << this_attr->address); | ||
152 | else if (!readin) | ||
153 | st->pwr_down_mask &= ~(1 << this_attr->address); | ||
154 | else | ||
155 | ret = -EINVAL; | ||
156 | |||
157 | ret = ad5624r_spi_write(st->us, AD5624R_CMD_POWERDOWN_DAC, 0, | ||
158 | (st->pwr_down_mode << 4) | | ||
159 | st->pwr_down_mask, 16); | ||
160 | |||
161 | return ret ? ret : len; | ||
162 | } | ||
163 | |||
164 | static ssize_t ad5624r_show_scale(struct device *dev, | ||
165 | struct device_attribute *attr, | ||
166 | char *buf) | ||
167 | { | ||
168 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
169 | struct ad5624r_state *st = iio_priv(indio_dev); | ||
170 | /* Corresponds to Vref / 2^(bits) */ | ||
171 | unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits; | ||
172 | |||
173 | return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); | ||
174 | } | ||
175 | static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5624r_show_scale, NULL, 0); | ||
176 | |||
177 | static IIO_DEV_ATTR_OUT_RAW(0, ad5624r_write_dac, AD5624R_ADDR_DAC0); | ||
178 | static IIO_DEV_ATTR_OUT_RAW(1, ad5624r_write_dac, AD5624R_ADDR_DAC1); | ||
179 | static IIO_DEV_ATTR_OUT_RAW(2, ad5624r_write_dac, AD5624R_ADDR_DAC2); | ||
180 | static IIO_DEV_ATTR_OUT_RAW(3, ad5624r_write_dac, AD5624R_ADDR_DAC3); | ||
181 | |||
182 | static IIO_DEVICE_ATTR(out_powerdown_mode, S_IRUGO | | ||
183 | S_IWUSR, ad5624r_read_powerdown_mode, | ||
184 | ad5624r_write_powerdown_mode, 0); | ||
185 | |||
186 | static IIO_CONST_ATTR(out_powerdown_mode_available, | ||
187 | "1kohm_to_gnd 100kohm_to_gnd three_state"); | ||
188 | |||
189 | #define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr) \ | ||
190 | IIO_DEVICE_ATTR(out##_num##_powerdown, \ | ||
191 | S_IRUGO | S_IWUSR, _show, _store, _addr) | ||
192 | |||
193 | static IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5624r_read_dac_powerdown, | ||
194 | ad5624r_write_dac_powerdown, 0); | ||
195 | static IIO_DEV_ATTR_DAC_POWERDOWN(1, ad5624r_read_dac_powerdown, | ||
196 | ad5624r_write_dac_powerdown, 1); | ||
197 | static IIO_DEV_ATTR_DAC_POWERDOWN(2, ad5624r_read_dac_powerdown, | ||
198 | ad5624r_write_dac_powerdown, 2); | ||
199 | static IIO_DEV_ATTR_DAC_POWERDOWN(3, ad5624r_read_dac_powerdown, | ||
200 | ad5624r_write_dac_powerdown, 3); | ||
201 | |||
202 | static struct attribute *ad5624r_attributes[] = { | ||
203 | &iio_dev_attr_out0_raw.dev_attr.attr, | ||
204 | &iio_dev_attr_out1_raw.dev_attr.attr, | ||
205 | &iio_dev_attr_out2_raw.dev_attr.attr, | ||
206 | &iio_dev_attr_out3_raw.dev_attr.attr, | ||
207 | &iio_dev_attr_out0_powerdown.dev_attr.attr, | ||
208 | &iio_dev_attr_out1_powerdown.dev_attr.attr, | ||
209 | &iio_dev_attr_out2_powerdown.dev_attr.attr, | ||
210 | &iio_dev_attr_out3_powerdown.dev_attr.attr, | ||
211 | &iio_dev_attr_out_powerdown_mode.dev_attr.attr, | ||
212 | &iio_const_attr_out_powerdown_mode_available.dev_attr.attr, | ||
213 | &iio_dev_attr_out_scale.dev_attr.attr, | ||
214 | NULL, | ||
215 | }; | ||
216 | |||
217 | static const struct attribute_group ad5624r_attribute_group = { | ||
218 | .attrs = ad5624r_attributes, | ||
219 | }; | ||
220 | |||
221 | static const struct iio_info ad5624r_info = { | ||
222 | .attrs = &ad5624r_attribute_group, | ||
223 | .driver_module = THIS_MODULE, | ||
224 | }; | ||
225 | |||
226 | static int __devinit ad5624r_probe(struct spi_device *spi) | ||
227 | { | ||
228 | struct ad5624r_state *st; | ||
229 | struct iio_dev *indio_dev; | ||
230 | struct regulator *reg; | ||
231 | int ret, voltage_uv = 0; | ||
232 | |||
233 | reg = regulator_get(&spi->dev, "vcc"); | ||
234 | if (!IS_ERR(reg)) { | ||
235 | ret = regulator_enable(reg); | ||
236 | if (ret) | ||
237 | goto error_put_reg; | ||
238 | |||
239 | voltage_uv = regulator_get_voltage(reg); | ||
240 | } | ||
241 | indio_dev = iio_allocate_device(sizeof(*st)); | ||
242 | if (indio_dev == NULL) { | ||
243 | ret = -ENOMEM; | ||
244 | goto error_disable_reg; | ||
245 | } | ||
246 | st = iio_priv(indio_dev); | ||
247 | st->reg = reg; | ||
248 | spi_set_drvdata(spi, indio_dev); | ||
249 | st->chip_info = | ||
250 | &ad5624r_chip_info_tbl[spi_get_device_id(spi)->driver_data]; | ||
251 | |||
252 | if (voltage_uv) | ||
253 | st->vref_mv = voltage_uv / 1000; | ||
254 | else | ||
255 | st->vref_mv = st->chip_info->int_vref_mv; | ||
256 | |||
257 | st->us = spi; | ||
258 | |||
259 | indio_dev->dev.parent = &spi->dev; | ||
260 | indio_dev->name = spi_get_device_id(spi)->name; | ||
261 | indio_dev->info = &ad5624r_info; | ||
262 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
263 | |||
264 | ret = iio_device_register(indio_dev); | ||
265 | if (ret) | ||
266 | goto error_free_dev; | ||
267 | |||
268 | ret = ad5624r_spi_write(spi, AD5624R_CMD_INTERNAL_REFER_SETUP, 0, | ||
269 | !!voltage_uv, 16); | ||
270 | if (ret) | ||
271 | goto error_free_dev; | ||
272 | |||
273 | return 0; | ||
274 | |||
275 | error_free_dev: | ||
276 | iio_free_device(indio_dev); | ||
277 | error_disable_reg: | ||
278 | if (!IS_ERR(reg)) | ||
279 | regulator_disable(reg); | ||
280 | error_put_reg: | ||
281 | if (!IS_ERR(reg)) | ||
282 | regulator_put(reg); | ||
283 | |||
284 | return ret; | ||
285 | } | ||
286 | |||
287 | static int __devexit ad5624r_remove(struct spi_device *spi) | ||
288 | { | ||
289 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
290 | struct ad5624r_state *st = iio_priv(indio_dev); | ||
291 | struct regulator *reg = st->reg; | ||
292 | |||
293 | iio_device_unregister(indio_dev); | ||
294 | if (!IS_ERR(reg)) { | ||
295 | regulator_disable(reg); | ||
296 | regulator_put(reg); | ||
297 | } | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | static const struct spi_device_id ad5624r_id[] = { | ||
303 | {"ad5624r3", ID_AD5624R3}, | ||
304 | {"ad5644r3", ID_AD5644R3}, | ||
305 | {"ad5664r3", ID_AD5664R3}, | ||
306 | {"ad5624r5", ID_AD5624R5}, | ||
307 | {"ad5644r5", ID_AD5644R5}, | ||
308 | {"ad5664r5", ID_AD5664R5}, | ||
309 | {} | ||
310 | }; | ||
311 | |||
312 | static struct spi_driver ad5624r_driver = { | ||
313 | .driver = { | ||
314 | .name = "ad5624r", | ||
315 | .owner = THIS_MODULE, | ||
316 | }, | ||
317 | .probe = ad5624r_probe, | ||
318 | .remove = __devexit_p(ad5624r_remove), | ||
319 | .id_table = ad5624r_id, | ||
320 | }; | ||
321 | |||
322 | static __init int ad5624r_spi_init(void) | ||
323 | { | ||
324 | return spi_register_driver(&ad5624r_driver); | ||
325 | } | ||
326 | module_init(ad5624r_spi_init); | ||
327 | |||
328 | static __exit void ad5624r_spi_exit(void) | ||
329 | { | ||
330 | spi_unregister_driver(&ad5624r_driver); | ||
331 | } | ||
332 | module_exit(ad5624r_spi_exit); | ||
333 | |||
334 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | ||
335 | MODULE_DESCRIPTION("Analog Devices AD5624/44/64R DAC spi driver"); | ||
336 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/staging/iio/dac/ad5686.c b/drivers/staging/iio/dac/ad5686.c new file mode 100644 index 00000000000..fd67cfa5edb --- /dev/null +++ b/drivers/staging/iio/dac/ad5686.c | |||
@@ -0,0 +1,497 @@ | |||
1 | /* | ||
2 | * AD5686R, AD5685R, AD5684R Digital to analog converters driver | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/gpio.h> | ||
11 | #include <linux/fs.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/spi/spi.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/sysfs.h> | ||
17 | #include <linux/regulator/consumer.h> | ||
18 | |||
19 | #include "../iio.h" | ||
20 | #include "../sysfs.h" | ||
21 | #include "dac.h" | ||
22 | |||
23 | #define AD5686_DAC_CHANNELS 4 | ||
24 | |||
25 | #define AD5686_ADDR(x) ((x) << 16) | ||
26 | #define AD5686_CMD(x) ((x) << 20) | ||
27 | |||
28 | #define AD5686_ADDR_DAC0 0x1 | ||
29 | #define AD5686_ADDR_DAC1 0x2 | ||
30 | #define AD5686_ADDR_DAC2 0x4 | ||
31 | #define AD5686_ADDR_DAC3 0x8 | ||
32 | #define AD5686_ADDR_ALL_DAC 0xF | ||
33 | |||
34 | #define AD5686_CMD_NOOP 0x0 | ||
35 | #define AD5686_CMD_WRITE_INPUT_N 0x1 | ||
36 | #define AD5686_CMD_UPDATE_DAC_N 0x2 | ||
37 | #define AD5686_CMD_WRITE_INPUT_N_UPDATE_N 0x3 | ||
38 | #define AD5686_CMD_POWERDOWN_DAC 0x4 | ||
39 | #define AD5686_CMD_LDAC_MASK 0x5 | ||
40 | #define AD5686_CMD_RESET 0x6 | ||
41 | #define AD5686_CMD_INTERNAL_REFER_SETUP 0x7 | ||
42 | #define AD5686_CMD_DAISY_CHAIN_ENABLE 0x8 | ||
43 | #define AD5686_CMD_READBACK_ENABLE 0x9 | ||
44 | |||
45 | #define AD5686_LDAC_PWRDN_NONE 0x0 | ||
46 | #define AD5686_LDAC_PWRDN_1K 0x1 | ||
47 | #define AD5686_LDAC_PWRDN_100K 0x2 | ||
48 | #define AD5686_LDAC_PWRDN_3STATE 0x3 | ||
49 | |||
50 | /** | ||
51 | * struct ad5686_chip_info - chip specific information | ||
52 | * @int_vref_mv: AD5620/40/60: the internal reference voltage | ||
53 | * @channel: channel specification | ||
54 | */ | ||
55 | |||
56 | struct ad5686_chip_info { | ||
57 | u16 int_vref_mv; | ||
58 | struct iio_chan_spec channel[AD5686_DAC_CHANNELS]; | ||
59 | }; | ||
60 | |||
61 | /** | ||
62 | * struct ad5446_state - driver instance specific data | ||
63 | * @spi: spi_device | ||
64 | * @chip_info: chip model specific constants, available modes etc | ||
65 | * @reg: supply regulator | ||
66 | * @vref_mv: actual reference voltage used | ||
67 | * @pwr_down_mask: power down mask | ||
68 | * @pwr_down_mode: current power down mode | ||
69 | * @data: spi transfer buffers | ||
70 | */ | ||
71 | |||
72 | struct ad5686_state { | ||
73 | struct spi_device *spi; | ||
74 | const struct ad5686_chip_info *chip_info; | ||
75 | struct regulator *reg; | ||
76 | unsigned short vref_mv; | ||
77 | unsigned pwr_down_mask; | ||
78 | unsigned pwr_down_mode; | ||
79 | /* | ||
80 | * DMA (thus cache coherency maintenance) requires the | ||
81 | * transfer buffers to live in their own cache lines. | ||
82 | */ | ||
83 | |||
84 | union { | ||
85 | u32 d32; | ||
86 | u8 d8[4]; | ||
87 | } data[3] ____cacheline_aligned; | ||
88 | }; | ||
89 | |||
90 | /** | ||
91 | * ad5686_supported_device_ids: | ||
92 | */ | ||
93 | |||
94 | enum ad5686_supported_device_ids { | ||
95 | ID_AD5684, | ||
96 | ID_AD5685, | ||
97 | ID_AD5686, | ||
98 | }; | ||
99 | |||
100 | static const struct ad5686_chip_info ad5686_chip_info_tbl[] = { | ||
101 | [ID_AD5684] = { | ||
102 | .channel[0] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 0, 0, | ||
103 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
104 | AD5686_ADDR_DAC0, | ||
105 | 0, IIO_ST('u', 12, 16, 4), 0), | ||
106 | .channel[1] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 1, 0, | ||
107 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
108 | AD5686_ADDR_DAC1, | ||
109 | 1, IIO_ST('u', 12, 16, 4), 0), | ||
110 | .channel[2] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 2, 0, | ||
111 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
112 | AD5686_ADDR_DAC2, | ||
113 | 2, IIO_ST('u', 12, 16, 4), 0), | ||
114 | .channel[3] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 3, 0, | ||
115 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
116 | AD5686_ADDR_DAC3, | ||
117 | 3, IIO_ST('u', 12, 16, 4), 0), | ||
118 | .int_vref_mv = 2500, | ||
119 | }, | ||
120 | [ID_AD5685] = { | ||
121 | .channel[0] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 0, 0, | ||
122 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
123 | AD5686_ADDR_DAC0, | ||
124 | 0, IIO_ST('u', 14, 16, 2), 0), | ||
125 | .channel[1] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 1, 0, | ||
126 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
127 | AD5686_ADDR_DAC1, | ||
128 | 1, IIO_ST('u', 14, 16, 2), 0), | ||
129 | .channel[2] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 2, 0, | ||
130 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
131 | AD5686_ADDR_DAC2, | ||
132 | 2, IIO_ST('u', 14, 16, 2), 0), | ||
133 | .channel[3] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 3, 0, | ||
134 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
135 | AD5686_ADDR_DAC3, | ||
136 | 3, IIO_ST('u', 14, 16, 2), 0), | ||
137 | .int_vref_mv = 2500, | ||
138 | }, | ||
139 | [ID_AD5686] = { | ||
140 | .channel[0] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 0, 0, | ||
141 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
142 | AD5686_ADDR_DAC0, | ||
143 | 0, IIO_ST('u', 16, 16, 0), 0), | ||
144 | .channel[1] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 1, 0, | ||
145 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
146 | AD5686_ADDR_DAC1, | ||
147 | 1, IIO_ST('u', 16, 16, 0), 0), | ||
148 | .channel[2] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 2, 0, | ||
149 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
150 | AD5686_ADDR_DAC2, | ||
151 | 2, IIO_ST('u', 16, 16, 0), 0), | ||
152 | .channel[3] = IIO_CHAN(IIO_OUT, 0, 1, 0, NULL, 3, 0, | ||
153 | (1 << IIO_CHAN_INFO_SCALE_SHARED), | ||
154 | AD5686_ADDR_DAC3, | ||
155 | 3, IIO_ST('u', 16, 16, 0), 0), | ||
156 | .int_vref_mv = 2500, | ||
157 | }, | ||
158 | }; | ||
159 | |||
160 | static int ad5686_spi_write(struct ad5686_state *st, | ||
161 | u8 cmd, u8 addr, u16 val, u8 shift) | ||
162 | { | ||
163 | val <<= shift; | ||
164 | |||
165 | st->data[0].d32 = cpu_to_be32(AD5686_CMD(cmd) | | ||
166 | AD5686_ADDR(addr) | | ||
167 | val); | ||
168 | |||
169 | return spi_write(st->spi, &st->data[0].d8[1], 3); | ||
170 | } | ||
171 | |||
172 | static int ad5686_spi_read(struct ad5686_state *st, u8 addr) | ||
173 | { | ||
174 | struct spi_transfer t[] = { | ||
175 | { | ||
176 | .tx_buf = &st->data[0].d8[1], | ||
177 | .len = 3, | ||
178 | .cs_change = 1, | ||
179 | }, { | ||
180 | .tx_buf = &st->data[1].d8[1], | ||
181 | .rx_buf = &st->data[2].d8[1], | ||
182 | .len = 3, | ||
183 | }, | ||
184 | }; | ||
185 | struct spi_message m; | ||
186 | int ret; | ||
187 | |||
188 | spi_message_init(&m); | ||
189 | spi_message_add_tail(&t[0], &m); | ||
190 | spi_message_add_tail(&t[1], &m); | ||
191 | |||
192 | st->data[0].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_READBACK_ENABLE) | | ||
193 | AD5686_ADDR(addr)); | ||
194 | st->data[1].d32 = cpu_to_be32(AD5686_CMD(AD5686_CMD_NOOP)); | ||
195 | |||
196 | ret = spi_sync(st->spi, &m); | ||
197 | if (ret < 0) | ||
198 | return ret; | ||
199 | |||
200 | return be32_to_cpu(st->data[2].d32); | ||
201 | } | ||
202 | |||
203 | static ssize_t ad5686_read_powerdown_mode(struct device *dev, | ||
204 | struct device_attribute *attr, char *buf) | ||
205 | { | ||
206 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
207 | struct ad5686_state *st = iio_priv(indio_dev); | ||
208 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
209 | |||
210 | char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"}; | ||
211 | |||
212 | return sprintf(buf, "%s\n", mode[(st->pwr_down_mode >> | ||
213 | (this_attr->address * 2)) & 0x3]); | ||
214 | } | ||
215 | |||
216 | static ssize_t ad5686_write_powerdown_mode(struct device *dev, | ||
217 | struct device_attribute *attr, | ||
218 | const char *buf, size_t len) | ||
219 | { | ||
220 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
221 | struct ad5686_state *st = iio_priv(indio_dev); | ||
222 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
223 | unsigned mode; | ||
224 | |||
225 | if (sysfs_streq(buf, "1kohm_to_gnd")) | ||
226 | mode = AD5686_LDAC_PWRDN_1K; | ||
227 | else if (sysfs_streq(buf, "100kohm_to_gnd")) | ||
228 | mode = AD5686_LDAC_PWRDN_100K; | ||
229 | else if (sysfs_streq(buf, "three_state")) | ||
230 | mode = AD5686_LDAC_PWRDN_3STATE; | ||
231 | else | ||
232 | return -EINVAL; | ||
233 | |||
234 | st->pwr_down_mode &= ~(0x3 << (this_attr->address * 2)); | ||
235 | st->pwr_down_mode |= (mode << (this_attr->address * 2)); | ||
236 | |||
237 | return len; | ||
238 | } | ||
239 | |||
240 | static ssize_t ad5686_read_dac_powerdown(struct device *dev, | ||
241 | struct device_attribute *attr, | ||
242 | char *buf) | ||
243 | { | ||
244 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
245 | struct ad5686_state *st = iio_priv(indio_dev); | ||
246 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
247 | |||
248 | return sprintf(buf, "%d\n", !!(st->pwr_down_mask & | ||
249 | (0x3 << (this_attr->address * 2)))); | ||
250 | } | ||
251 | |||
252 | static ssize_t ad5686_write_dac_powerdown(struct device *dev, | ||
253 | struct device_attribute *attr, | ||
254 | const char *buf, size_t len) | ||
255 | { | ||
256 | bool readin; | ||
257 | int ret; | ||
258 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
259 | struct ad5686_state *st = iio_priv(indio_dev); | ||
260 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
261 | |||
262 | ret = strtobool(buf, &readin); | ||
263 | if (ret) | ||
264 | return ret; | ||
265 | |||
266 | if (readin == true) | ||
267 | st->pwr_down_mask |= (0x3 << (this_attr->address * 2)); | ||
268 | else | ||
269 | st->pwr_down_mask &= ~(0x3 << (this_attr->address * 2)); | ||
270 | |||
271 | ret = ad5686_spi_write(st, AD5686_CMD_POWERDOWN_DAC, 0, | ||
272 | st->pwr_down_mask & st->pwr_down_mode, 0); | ||
273 | |||
274 | return ret ? ret : len; | ||
275 | } | ||
276 | |||
277 | static IIO_CONST_ATTR(out_powerdown_mode_available, | ||
278 | "1kohm_to_gnd 100kohm_to_gnd three_state"); | ||
279 | |||
280 | #define IIO_DEV_ATTR_DAC_POWERDOWN_MODE(_num) \ | ||
281 | IIO_DEVICE_ATTR(out##_num##_powerdown_mode, S_IRUGO | S_IWUSR, \ | ||
282 | ad5686_read_powerdown_mode, \ | ||
283 | ad5686_write_powerdown_mode, _num) | ||
284 | |||
285 | static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(0); | ||
286 | static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(1); | ||
287 | static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(2); | ||
288 | static IIO_DEV_ATTR_DAC_POWERDOWN_MODE(3); | ||
289 | |||
290 | #define IIO_DEV_ATTR_DAC_POWERDOWN(_num) \ | ||
291 | IIO_DEVICE_ATTR(out##_num##_powerdown, S_IRUGO | S_IWUSR, \ | ||
292 | ad5686_read_dac_powerdown, \ | ||
293 | ad5686_write_dac_powerdown, _num) | ||
294 | |||
295 | static IIO_DEV_ATTR_DAC_POWERDOWN(0); | ||
296 | static IIO_DEV_ATTR_DAC_POWERDOWN(1); | ||
297 | static IIO_DEV_ATTR_DAC_POWERDOWN(2); | ||
298 | static IIO_DEV_ATTR_DAC_POWERDOWN(3); | ||
299 | |||
300 | static struct attribute *ad5686_attributes[] = { | ||
301 | &iio_dev_attr_out0_powerdown.dev_attr.attr, | ||
302 | &iio_dev_attr_out1_powerdown.dev_attr.attr, | ||
303 | &iio_dev_attr_out2_powerdown.dev_attr.attr, | ||
304 | &iio_dev_attr_out3_powerdown.dev_attr.attr, | ||
305 | &iio_dev_attr_out0_powerdown_mode.dev_attr.attr, | ||
306 | &iio_dev_attr_out1_powerdown_mode.dev_attr.attr, | ||
307 | &iio_dev_attr_out2_powerdown_mode.dev_attr.attr, | ||
308 | &iio_dev_attr_out3_powerdown_mode.dev_attr.attr, | ||
309 | &iio_const_attr_out_powerdown_mode_available.dev_attr.attr, | ||
310 | NULL, | ||
311 | }; | ||
312 | |||
313 | static const struct attribute_group ad5686_attribute_group = { | ||
314 | .attrs = ad5686_attributes, | ||
315 | }; | ||
316 | |||
317 | static int ad5686_read_raw(struct iio_dev *indio_dev, | ||
318 | struct iio_chan_spec const *chan, | ||
319 | int *val, | ||
320 | int *val2, | ||
321 | long m) | ||
322 | { | ||
323 | struct ad5686_state *st = iio_priv(indio_dev); | ||
324 | unsigned long scale_uv; | ||
325 | int ret; | ||
326 | |||
327 | switch (m) { | ||
328 | case 0: | ||
329 | mutex_lock(&indio_dev->mlock); | ||
330 | ret = ad5686_spi_read(st, chan->address); | ||
331 | mutex_unlock(&indio_dev->mlock); | ||
332 | if (ret < 0) | ||
333 | return ret; | ||
334 | *val = ret; | ||
335 | return IIO_VAL_INT; | ||
336 | break; | ||
337 | case (1 << IIO_CHAN_INFO_SCALE_SHARED): | ||
338 | scale_uv = (st->vref_mv * 100000) | ||
339 | >> (chan->scan_type.realbits); | ||
340 | *val = scale_uv / 100000; | ||
341 | *val2 = (scale_uv % 100000) * 10; | ||
342 | return IIO_VAL_INT_PLUS_MICRO; | ||
343 | |||
344 | } | ||
345 | return -EINVAL; | ||
346 | } | ||
347 | |||
348 | static int ad5686_write_raw(struct iio_dev *indio_dev, | ||
349 | struct iio_chan_spec const *chan, | ||
350 | int val, | ||
351 | int val2, | ||
352 | long mask) | ||
353 | { | ||
354 | struct ad5686_state *st = iio_priv(indio_dev); | ||
355 | int ret; | ||
356 | |||
357 | switch (mask) { | ||
358 | case 0: | ||
359 | if (val > (1 << chan->scan_type.realbits)) | ||
360 | return -EINVAL; | ||
361 | |||
362 | mutex_lock(&indio_dev->mlock); | ||
363 | ret = ad5686_spi_write(st, | ||
364 | AD5686_CMD_WRITE_INPUT_N_UPDATE_N, | ||
365 | chan->address, | ||
366 | val, | ||
367 | chan->scan_type.shift); | ||
368 | mutex_unlock(&indio_dev->mlock); | ||
369 | break; | ||
370 | default: | ||
371 | ret = -EINVAL; | ||
372 | } | ||
373 | |||
374 | return ret; | ||
375 | } | ||
376 | |||
377 | static const struct iio_info ad5686_info = { | ||
378 | .read_raw = ad5686_read_raw, | ||
379 | .write_raw = ad5686_write_raw, | ||
380 | .attrs = &ad5686_attribute_group, | ||
381 | .driver_module = THIS_MODULE, | ||
382 | }; | ||
383 | |||
384 | static int __devinit ad5686_probe(struct spi_device *spi) | ||
385 | { | ||
386 | struct ad5686_state *st; | ||
387 | struct iio_dev *indio_dev; | ||
388 | int ret, regdone = 0, voltage_uv = 0; | ||
389 | |||
390 | indio_dev = iio_allocate_device(sizeof(*st)); | ||
391 | if (indio_dev == NULL) | ||
392 | return -ENOMEM; | ||
393 | |||
394 | st = iio_priv(indio_dev); | ||
395 | spi_set_drvdata(spi, indio_dev); | ||
396 | |||
397 | st->reg = regulator_get(&spi->dev, "vcc"); | ||
398 | if (!IS_ERR(st->reg)) { | ||
399 | ret = regulator_enable(st->reg); | ||
400 | if (ret) | ||
401 | goto error_put_reg; | ||
402 | |||
403 | voltage_uv = regulator_get_voltage(st->reg); | ||
404 | } | ||
405 | |||
406 | st->chip_info = | ||
407 | &ad5686_chip_info_tbl[spi_get_device_id(spi)->driver_data]; | ||
408 | |||
409 | if (voltage_uv) | ||
410 | st->vref_mv = voltage_uv / 1000; | ||
411 | else | ||
412 | st->vref_mv = st->chip_info->int_vref_mv; | ||
413 | |||
414 | st->spi = spi; | ||
415 | |||
416 | indio_dev->dev.parent = &spi->dev; | ||
417 | indio_dev->name = spi_get_device_id(spi)->name; | ||
418 | indio_dev->info = &ad5686_info; | ||
419 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
420 | indio_dev->channels = st->chip_info->channel; | ||
421 | indio_dev->num_channels = AD5686_DAC_CHANNELS; | ||
422 | |||
423 | ret = iio_device_register(indio_dev); | ||
424 | if (ret) | ||
425 | goto error_disable_reg; | ||
426 | |||
427 | regdone = 1; | ||
428 | ret = ad5686_spi_write(st, AD5686_CMD_INTERNAL_REFER_SETUP, 0, | ||
429 | !!voltage_uv, 0); | ||
430 | if (ret) | ||
431 | goto error_disable_reg; | ||
432 | |||
433 | return 0; | ||
434 | |||
435 | error_disable_reg: | ||
436 | if (!IS_ERR(st->reg)) | ||
437 | regulator_disable(st->reg); | ||
438 | error_put_reg: | ||
439 | if (!IS_ERR(st->reg)) | ||
440 | regulator_put(st->reg); | ||
441 | |||
442 | if (regdone) | ||
443 | iio_device_unregister(indio_dev); | ||
444 | else | ||
445 | iio_free_device(indio_dev); | ||
446 | |||
447 | return ret; | ||
448 | } | ||
449 | |||
450 | static int __devexit ad5686_remove(struct spi_device *spi) | ||
451 | { | ||
452 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
453 | struct ad5686_state *st = iio_priv(indio_dev); | ||
454 | struct regulator *reg = st->reg; | ||
455 | |||
456 | if (!IS_ERR(reg)) { | ||
457 | regulator_disable(reg); | ||
458 | regulator_put(reg); | ||
459 | } | ||
460 | |||
461 | iio_device_unregister(indio_dev); | ||
462 | |||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | static const struct spi_device_id ad5686_id[] = { | ||
467 | {"ad5684", ID_AD5684}, | ||
468 | {"ad5685", ID_AD5685}, | ||
469 | {"ad5686", ID_AD5686}, | ||
470 | {} | ||
471 | }; | ||
472 | |||
473 | static struct spi_driver ad5686_driver = { | ||
474 | .driver = { | ||
475 | .name = "ad5686", | ||
476 | .owner = THIS_MODULE, | ||
477 | }, | ||
478 | .probe = ad5686_probe, | ||
479 | .remove = __devexit_p(ad5686_remove), | ||
480 | .id_table = ad5686_id, | ||
481 | }; | ||
482 | |||
483 | static __init int ad5686_spi_init(void) | ||
484 | { | ||
485 | return spi_register_driver(&ad5686_driver); | ||
486 | } | ||
487 | module_init(ad5686_spi_init); | ||
488 | |||
489 | static __exit void ad5686_spi_exit(void) | ||
490 | { | ||
491 | spi_unregister_driver(&ad5686_driver); | ||
492 | } | ||
493 | module_exit(ad5686_spi_exit); | ||
494 | |||
495 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
496 | MODULE_DESCRIPTION("Analog Devices AD5686/85/84 DAC"); | ||
497 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/staging/iio/dac/ad5791.c b/drivers/staging/iio/dac/ad5791.c new file mode 100644 index 00000000000..64770d2a1b4 --- /dev/null +++ b/drivers/staging/iio/dac/ad5791.c | |||
@@ -0,0 +1,442 @@ | |||
1 | /* | ||
2 | * AD5760, AD5780, AD5781, AD5791 Voltage Output Digital to Analog Converter | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/interrupt.h> | ||
10 | #include <linux/gpio.h> | ||
11 | #include <linux/fs.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/spi/spi.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/sysfs.h> | ||
17 | #include <linux/regulator/consumer.h> | ||
18 | |||
19 | #include "../iio.h" | ||
20 | #include "../sysfs.h" | ||
21 | #include "dac.h" | ||
22 | #include "ad5791.h" | ||
23 | |||
24 | static int ad5791_spi_write(struct spi_device *spi, u8 addr, u32 val) | ||
25 | { | ||
26 | union { | ||
27 | u32 d32; | ||
28 | u8 d8[4]; | ||
29 | } data; | ||
30 | |||
31 | data.d32 = cpu_to_be32(AD5791_CMD_WRITE | | ||
32 | AD5791_ADDR(addr) | | ||
33 | (val & AD5791_DAC_MASK)); | ||
34 | |||
35 | return spi_write(spi, &data.d8[1], 3); | ||
36 | } | ||
37 | |||
38 | static int ad5791_spi_read(struct spi_device *spi, u8 addr, u32 *val) | ||
39 | { | ||
40 | union { | ||
41 | u32 d32; | ||
42 | u8 d8[4]; | ||
43 | } data[3]; | ||
44 | int ret; | ||
45 | struct spi_message msg; | ||
46 | struct spi_transfer xfers[] = { | ||
47 | { | ||
48 | .tx_buf = &data[0].d8[1], | ||
49 | .bits_per_word = 8, | ||
50 | .len = 3, | ||
51 | .cs_change = 1, | ||
52 | }, { | ||
53 | .tx_buf = &data[1].d8[1], | ||
54 | .rx_buf = &data[2].d8[1], | ||
55 | .bits_per_word = 8, | ||
56 | .len = 3, | ||
57 | }, | ||
58 | }; | ||
59 | |||
60 | data[0].d32 = cpu_to_be32(AD5791_CMD_READ | | ||
61 | AD5791_ADDR(addr)); | ||
62 | data[1].d32 = cpu_to_be32(AD5791_ADDR(AD5791_ADDR_NOOP)); | ||
63 | |||
64 | spi_message_init(&msg); | ||
65 | spi_message_add_tail(&xfers[0], &msg); | ||
66 | spi_message_add_tail(&xfers[1], &msg); | ||
67 | ret = spi_sync(spi, &msg); | ||
68 | |||
69 | *val = be32_to_cpu(data[2].d32); | ||
70 | |||
71 | return ret; | ||
72 | } | ||
73 | |||
74 | static ssize_t ad5791_write_dac(struct device *dev, | ||
75 | struct device_attribute *attr, | ||
76 | const char *buf, size_t len) | ||
77 | { | ||
78 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
79 | struct ad5791_state *st = iio_priv(indio_dev); | ||
80 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
81 | long readin; | ||
82 | int ret; | ||
83 | |||
84 | ret = strict_strtol(buf, 10, &readin); | ||
85 | if (ret) | ||
86 | return ret; | ||
87 | |||
88 | readin += (1 << (st->chip_info->bits - 1)); | ||
89 | readin &= AD5791_RES_MASK(st->chip_info->bits); | ||
90 | readin <<= st->chip_info->left_shift; | ||
91 | |||
92 | ret = ad5791_spi_write(st->spi, this_attr->address, readin); | ||
93 | return ret ? ret : len; | ||
94 | } | ||
95 | |||
96 | static ssize_t ad5791_read_dac(struct device *dev, | ||
97 | struct device_attribute *attr, | ||
98 | char *buf) | ||
99 | { | ||
100 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
101 | struct ad5791_state *st = iio_priv(indio_dev); | ||
102 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
103 | int ret; | ||
104 | int val; | ||
105 | |||
106 | ret = ad5791_spi_read(st->spi, this_attr->address, &val); | ||
107 | if (ret) | ||
108 | return ret; | ||
109 | |||
110 | val &= AD5791_DAC_MASK; | ||
111 | val >>= st->chip_info->left_shift; | ||
112 | val -= (1 << (st->chip_info->bits - 1)); | ||
113 | |||
114 | return sprintf(buf, "%d\n", val); | ||
115 | } | ||
116 | |||
117 | static ssize_t ad5791_read_powerdown_mode(struct device *dev, | ||
118 | struct device_attribute *attr, char *buf) | ||
119 | { | ||
120 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
121 | struct ad5791_state *st = iio_priv(indio_dev); | ||
122 | |||
123 | const char mode[][14] = {"6kohm_to_gnd", "three_state"}; | ||
124 | |||
125 | return sprintf(buf, "%s\n", mode[st->pwr_down_mode]); | ||
126 | } | ||
127 | |||
128 | static ssize_t ad5791_write_powerdown_mode(struct device *dev, | ||
129 | struct device_attribute *attr, | ||
130 | const char *buf, size_t len) | ||
131 | { | ||
132 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
133 | struct ad5791_state *st = iio_priv(indio_dev); | ||
134 | int ret; | ||
135 | |||
136 | if (sysfs_streq(buf, "6kohm_to_gnd")) | ||
137 | st->pwr_down_mode = AD5791_DAC_PWRDN_6K; | ||
138 | else if (sysfs_streq(buf, "three_state")) | ||
139 | st->pwr_down_mode = AD5791_DAC_PWRDN_3STATE; | ||
140 | else | ||
141 | ret = -EINVAL; | ||
142 | |||
143 | return ret ? ret : len; | ||
144 | } | ||
145 | |||
146 | static ssize_t ad5791_read_dac_powerdown(struct device *dev, | ||
147 | struct device_attribute *attr, | ||
148 | char *buf) | ||
149 | { | ||
150 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
151 | struct ad5791_state *st = iio_priv(indio_dev); | ||
152 | |||
153 | return sprintf(buf, "%d\n", st->pwr_down); | ||
154 | } | ||
155 | |||
156 | static ssize_t ad5791_write_dac_powerdown(struct device *dev, | ||
157 | struct device_attribute *attr, | ||
158 | const char *buf, size_t len) | ||
159 | { | ||
160 | long readin; | ||
161 | int ret; | ||
162 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
163 | struct ad5791_state *st = iio_priv(indio_dev); | ||
164 | |||
165 | ret = strict_strtol(buf, 10, &readin); | ||
166 | if (ret) | ||
167 | return ret; | ||
168 | |||
169 | if (readin == 0) { | ||
170 | st->pwr_down = false; | ||
171 | st->ctrl &= ~(AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI); | ||
172 | } else if (readin == 1) { | ||
173 | st->pwr_down = true; | ||
174 | if (st->pwr_down_mode == AD5791_DAC_PWRDN_6K) | ||
175 | st->ctrl |= AD5791_CTRL_OPGND; | ||
176 | else if (st->pwr_down_mode == AD5791_DAC_PWRDN_3STATE) | ||
177 | st->ctrl |= AD5791_CTRL_DACTRI; | ||
178 | } else | ||
179 | ret = -EINVAL; | ||
180 | |||
181 | ret = ad5791_spi_write(st->spi, AD5791_ADDR_CTRL, st->ctrl); | ||
182 | |||
183 | return ret ? ret : len; | ||
184 | } | ||
185 | |||
186 | static ssize_t ad5791_show_scale(struct device *dev, | ||
187 | struct device_attribute *attr, | ||
188 | char *buf) | ||
189 | { | ||
190 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
191 | struct ad5791_state *st = iio_priv(indio_dev); | ||
192 | /* Corresponds to Vref / 2^(bits) */ | ||
193 | unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits; | ||
194 | |||
195 | return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); | ||
196 | } | ||
197 | static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5791_show_scale, NULL, 0); | ||
198 | |||
199 | static ssize_t ad5791_show_name(struct device *dev, | ||
200 | struct device_attribute *attr, | ||
201 | char *buf) | ||
202 | { | ||
203 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
204 | struct ad5791_state *st = iio_priv(indio_dev); | ||
205 | |||
206 | return sprintf(buf, "%s\n", spi_get_device_id(st->spi)->name); | ||
207 | } | ||
208 | static IIO_DEVICE_ATTR(name, S_IRUGO, ad5791_show_name, NULL, 0); | ||
209 | |||
210 | #define IIO_DEV_ATTR_OUT_RW_RAW(_num, _show, _store, _addr) \ | ||
211 | IIO_DEVICE_ATTR(out##_num##_raw, \ | ||
212 | S_IRUGO | S_IWUSR, _show, _store, _addr) | ||
213 | |||
214 | static IIO_DEV_ATTR_OUT_RW_RAW(0, ad5791_read_dac, | ||
215 | ad5791_write_dac, AD5791_ADDR_DAC0); | ||
216 | |||
217 | static IIO_DEVICE_ATTR(out_powerdown_mode, S_IRUGO | | ||
218 | S_IWUSR, ad5791_read_powerdown_mode, | ||
219 | ad5791_write_powerdown_mode, 0); | ||
220 | |||
221 | static IIO_CONST_ATTR(out_powerdown_mode_available, | ||
222 | "6kohm_to_gnd three_state"); | ||
223 | |||
224 | #define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr) \ | ||
225 | IIO_DEVICE_ATTR(out##_num##_powerdown, \ | ||
226 | S_IRUGO | S_IWUSR, _show, _store, _addr) | ||
227 | |||
228 | static IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5791_read_dac_powerdown, | ||
229 | ad5791_write_dac_powerdown, 0); | ||
230 | |||
231 | static struct attribute *ad5791_attributes[] = { | ||
232 | &iio_dev_attr_out0_raw.dev_attr.attr, | ||
233 | &iio_dev_attr_out0_powerdown.dev_attr.attr, | ||
234 | &iio_dev_attr_out_powerdown_mode.dev_attr.attr, | ||
235 | &iio_const_attr_out_powerdown_mode_available.dev_attr.attr, | ||
236 | &iio_dev_attr_out_scale.dev_attr.attr, | ||
237 | &iio_dev_attr_name.dev_attr.attr, | ||
238 | NULL, | ||
239 | }; | ||
240 | |||
241 | static const struct attribute_group ad5791_attribute_group = { | ||
242 | .attrs = ad5791_attributes, | ||
243 | }; | ||
244 | |||
245 | static int ad5791_get_lin_comp(unsigned int span) | ||
246 | { | ||
247 | if (span <= 10000) | ||
248 | return AD5791_LINCOMP_0_10; | ||
249 | else if (span <= 12000) | ||
250 | return AD5791_LINCOMP_10_12; | ||
251 | else if (span <= 16000) | ||
252 | return AD5791_LINCOMP_12_16; | ||
253 | else if (span <= 19000) | ||
254 | return AD5791_LINCOMP_16_19; | ||
255 | else | ||
256 | return AD5791_LINCOMP_19_20; | ||
257 | } | ||
258 | |||
259 | static int ad5780_get_lin_comp(unsigned int span) | ||
260 | { | ||
261 | if (span <= 10000) | ||
262 | return AD5780_LINCOMP_0_10; | ||
263 | else | ||
264 | return AD5780_LINCOMP_10_20; | ||
265 | } | ||
266 | |||
267 | static const struct ad5791_chip_info ad5791_chip_info_tbl[] = { | ||
268 | [ID_AD5760] = { | ||
269 | .bits = 16, | ||
270 | .left_shift = 4, | ||
271 | .get_lin_comp = ad5780_get_lin_comp, | ||
272 | }, | ||
273 | [ID_AD5780] = { | ||
274 | .bits = 18, | ||
275 | .left_shift = 2, | ||
276 | .get_lin_comp = ad5780_get_lin_comp, | ||
277 | }, | ||
278 | [ID_AD5781] = { | ||
279 | .bits = 18, | ||
280 | .left_shift = 2, | ||
281 | .get_lin_comp = ad5791_get_lin_comp, | ||
282 | }, | ||
283 | [ID_AD5791] = { | ||
284 | .bits = 20, | ||
285 | .left_shift = 0, | ||
286 | .get_lin_comp = ad5791_get_lin_comp, | ||
287 | }, | ||
288 | }; | ||
289 | |||
290 | static const struct iio_info ad5791_info = { | ||
291 | .attrs = &ad5791_attribute_group, | ||
292 | .driver_module = THIS_MODULE, | ||
293 | }; | ||
294 | |||
295 | static int __devinit ad5791_probe(struct spi_device *spi) | ||
296 | { | ||
297 | struct ad5791_platform_data *pdata = spi->dev.platform_data; | ||
298 | struct iio_dev *indio_dev; | ||
299 | struct regulator *reg_vdd, *reg_vss; | ||
300 | struct ad5791_state *st; | ||
301 | int ret, pos_voltage_uv = 0, neg_voltage_uv = 0; | ||
302 | |||
303 | reg_vdd = regulator_get(&spi->dev, "vdd"); | ||
304 | if (!IS_ERR(reg_vdd)) { | ||
305 | ret = regulator_enable(reg_vdd); | ||
306 | if (ret) | ||
307 | goto error_put_reg_pos; | ||
308 | |||
309 | pos_voltage_uv = regulator_get_voltage(reg_vdd); | ||
310 | } | ||
311 | |||
312 | reg_vss = regulator_get(&spi->dev, "vss"); | ||
313 | if (!IS_ERR(reg_vss)) { | ||
314 | ret = regulator_enable(reg_vss); | ||
315 | if (ret) | ||
316 | goto error_put_reg_neg; | ||
317 | |||
318 | neg_voltage_uv = regulator_get_voltage(reg_vss); | ||
319 | } | ||
320 | |||
321 | indio_dev = iio_allocate_device(sizeof(*st)); | ||
322 | if (indio_dev == NULL) { | ||
323 | ret = -ENOMEM; | ||
324 | goto error_disable_reg_neg; | ||
325 | } | ||
326 | st = iio_priv(indio_dev); | ||
327 | st->pwr_down = true; | ||
328 | st->spi = spi; | ||
329 | |||
330 | if (!IS_ERR(reg_vss) && !IS_ERR(reg_vdd)) | ||
331 | st->vref_mv = (pos_voltage_uv - neg_voltage_uv) / 1000; | ||
332 | else if (pdata) | ||
333 | st->vref_mv = pdata->vref_pos_mv - pdata->vref_neg_mv; | ||
334 | else | ||
335 | dev_warn(&spi->dev, "reference voltage unspecified\n"); | ||
336 | |||
337 | ret = ad5791_spi_write(spi, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET); | ||
338 | if (ret) | ||
339 | goto error_free_dev; | ||
340 | |||
341 | st->chip_info = | ||
342 | &ad5791_chip_info_tbl[spi_get_device_id(spi)->driver_data]; | ||
343 | |||
344 | |||
345 | st->ctrl = AD5761_CTRL_LINCOMP(st->chip_info->get_lin_comp(st->vref_mv)) | ||
346 | | ((pdata && pdata->use_rbuf_gain2) ? 0 : AD5791_CTRL_RBUF) | | ||
347 | AD5791_CTRL_BIN2SC; | ||
348 | |||
349 | ret = ad5791_spi_write(spi, AD5791_ADDR_CTRL, st->ctrl | | ||
350 | AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI); | ||
351 | if (ret) | ||
352 | goto error_free_dev; | ||
353 | |||
354 | st->reg_vdd = reg_vdd; | ||
355 | st->reg_vss = reg_vss; | ||
356 | |||
357 | spi_set_drvdata(spi, indio_dev); | ||
358 | indio_dev->dev.parent = &spi->dev; | ||
359 | indio_dev->info = &ad5791_info; | ||
360 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
361 | |||
362 | ret = iio_device_register(indio_dev); | ||
363 | if (ret) | ||
364 | goto error_free_dev; | ||
365 | |||
366 | return 0; | ||
367 | |||
368 | error_free_dev: | ||
369 | iio_free_device(indio_dev); | ||
370 | |||
371 | error_disable_reg_neg: | ||
372 | if (!IS_ERR(reg_vss)) | ||
373 | regulator_disable(reg_vss); | ||
374 | error_put_reg_neg: | ||
375 | if (!IS_ERR(reg_vss)) | ||
376 | regulator_put(reg_vss); | ||
377 | |||
378 | if (!IS_ERR(reg_vdd)) | ||
379 | regulator_disable(reg_vdd); | ||
380 | error_put_reg_pos: | ||
381 | if (!IS_ERR(reg_vdd)) | ||
382 | regulator_put(reg_vdd); | ||
383 | |||
384 | error_ret: | ||
385 | return ret; | ||
386 | } | ||
387 | |||
388 | static int __devexit ad5791_remove(struct spi_device *spi) | ||
389 | { | ||
390 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
391 | struct ad5791_state *st = iio_priv(indio_dev); | ||
392 | struct regulator *reg_vdd = st->reg_vdd; | ||
393 | struct regulator *reg_vss = st->reg_vss; | ||
394 | |||
395 | iio_device_unregister(indio_dev); | ||
396 | |||
397 | if (!IS_ERR(st->reg_vdd)) { | ||
398 | regulator_disable(reg_vdd); | ||
399 | regulator_put(reg_vdd); | ||
400 | } | ||
401 | |||
402 | if (!IS_ERR(st->reg_vss)) { | ||
403 | regulator_disable(reg_vss); | ||
404 | regulator_put(reg_vss); | ||
405 | } | ||
406 | |||
407 | return 0; | ||
408 | } | ||
409 | |||
410 | static const struct spi_device_id ad5791_id[] = { | ||
411 | {"ad5760", ID_AD5760}, | ||
412 | {"ad5780", ID_AD5780}, | ||
413 | {"ad5781", ID_AD5781}, | ||
414 | {"ad5791", ID_AD5791}, | ||
415 | {} | ||
416 | }; | ||
417 | |||
418 | static struct spi_driver ad5791_driver = { | ||
419 | .driver = { | ||
420 | .name = "ad5791", | ||
421 | .owner = THIS_MODULE, | ||
422 | }, | ||
423 | .probe = ad5791_probe, | ||
424 | .remove = __devexit_p(ad5791_remove), | ||
425 | .id_table = ad5791_id, | ||
426 | }; | ||
427 | |||
428 | static __init int ad5791_spi_init(void) | ||
429 | { | ||
430 | return spi_register_driver(&ad5791_driver); | ||
431 | } | ||
432 | module_init(ad5791_spi_init); | ||
433 | |||
434 | static __exit void ad5791_spi_exit(void) | ||
435 | { | ||
436 | spi_unregister_driver(&ad5791_driver); | ||
437 | } | ||
438 | module_exit(ad5791_spi_exit); | ||
439 | |||
440 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
441 | MODULE_DESCRIPTION("Analog Devices AD5760/AD5780/AD5781/AD5791 DAC"); | ||
442 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/staging/iio/dac/ad5791.h b/drivers/staging/iio/dac/ad5791.h new file mode 100644 index 00000000000..c807f26539d --- /dev/null +++ b/drivers/staging/iio/dac/ad5791.h | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * AD5791 SPI DAC driver | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #ifndef SPI_AD5791_H_ | ||
10 | #define SPI_AD5791_H_ | ||
11 | |||
12 | #define AD5791_RES_MASK(x) ((1 << (x)) - 1) | ||
13 | #define AD5791_DAC_MASK AD5791_RES_MASK(20) | ||
14 | #define AD5791_DAC_MSB (1 << 19) | ||
15 | |||
16 | #define AD5791_CMD_READ (1 << 23) | ||
17 | #define AD5791_CMD_WRITE (0 << 23) | ||
18 | #define AD5791_ADDR(addr) ((addr) << 20) | ||
19 | |||
20 | /* Registers */ | ||
21 | #define AD5791_ADDR_NOOP 0 | ||
22 | #define AD5791_ADDR_DAC0 1 | ||
23 | #define AD5791_ADDR_CTRL 2 | ||
24 | #define AD5791_ADDR_CLRCODE 3 | ||
25 | #define AD5791_ADDR_SW_CTRL 4 | ||
26 | |||
27 | /* Control Register */ | ||
28 | #define AD5791_CTRL_RBUF (1 << 1) | ||
29 | #define AD5791_CTRL_OPGND (1 << 2) | ||
30 | #define AD5791_CTRL_DACTRI (1 << 3) | ||
31 | #define AD5791_CTRL_BIN2SC (1 << 4) | ||
32 | #define AD5791_CTRL_SDODIS (1 << 5) | ||
33 | #define AD5761_CTRL_LINCOMP(x) ((x) << 6) | ||
34 | |||
35 | #define AD5791_LINCOMP_0_10 0 | ||
36 | #define AD5791_LINCOMP_10_12 1 | ||
37 | #define AD5791_LINCOMP_12_16 2 | ||
38 | #define AD5791_LINCOMP_16_19 3 | ||
39 | #define AD5791_LINCOMP_19_20 12 | ||
40 | |||
41 | #define AD5780_LINCOMP_0_10 0 | ||
42 | #define AD5780_LINCOMP_10_20 12 | ||
43 | |||
44 | /* Software Control Register */ | ||
45 | #define AD5791_SWCTRL_LDAC (1 << 0) | ||
46 | #define AD5791_SWCTRL_CLR (1 << 1) | ||
47 | #define AD5791_SWCTRL_RESET (1 << 2) | ||
48 | |||
49 | #define AD5791_DAC_PWRDN_6K 0 | ||
50 | #define AD5791_DAC_PWRDN_3STATE 1 | ||
51 | |||
52 | /* | ||
53 | * TODO: struct ad5791_platform_data needs to go into include/linux/iio | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * struct ad5791_platform_data - platform specific information | ||
58 | * @vref_pos_mv: Vdd Positive Analog Supply Volatge (mV) | ||
59 | * @vref_neg_mv: Vdd Negative Analog Supply Volatge (mV) | ||
60 | * @use_rbuf_gain2: ext. amplifier connected in gain of two configuration | ||
61 | */ | ||
62 | |||
63 | struct ad5791_platform_data { | ||
64 | u16 vref_pos_mv; | ||
65 | u16 vref_neg_mv; | ||
66 | bool use_rbuf_gain2; | ||
67 | }; | ||
68 | |||
69 | /** | ||
70 | * struct ad5791_chip_info - chip specific information | ||
71 | * @bits: accuracy of the DAC in bits | ||
72 | * @left_shift: number of bits the datum must be shifted | ||
73 | * @get_lin_comp: function pointer to the device specific function | ||
74 | */ | ||
75 | |||
76 | struct ad5791_chip_info { | ||
77 | u8 bits; | ||
78 | u8 left_shift; | ||
79 | int (*get_lin_comp) (unsigned int span); | ||
80 | }; | ||
81 | |||
82 | /** | ||
83 | * struct ad5791_state - driver instance specific data | ||
84 | * @us: spi_device | ||
85 | * @reg_vdd: positive supply regulator | ||
86 | * @reg_vss: negative supply regulator | ||
87 | * @chip_info: chip model specific constants | ||
88 | * @vref_mv: actual reference voltage used | ||
89 | * @pwr_down_mode current power down mode | ||
90 | */ | ||
91 | |||
92 | struct ad5791_state { | ||
93 | struct spi_device *spi; | ||
94 | struct regulator *reg_vdd; | ||
95 | struct regulator *reg_vss; | ||
96 | const struct ad5791_chip_info *chip_info; | ||
97 | unsigned short vref_mv; | ||
98 | unsigned ctrl; | ||
99 | unsigned pwr_down_mode; | ||
100 | bool pwr_down; | ||
101 | }; | ||
102 | |||
103 | /** | ||
104 | * ad5791_supported_device_ids: | ||
105 | */ | ||
106 | |||
107 | enum ad5791_supported_device_ids { | ||
108 | ID_AD5760, | ||
109 | ID_AD5780, | ||
110 | ID_AD5781, | ||
111 | ID_AD5791, | ||
112 | }; | ||
113 | |||
114 | #endif /* SPI_AD5791_H_ */ | ||
diff --git a/drivers/staging/iio/dac/dac.h b/drivers/staging/iio/dac/dac.h new file mode 100644 index 00000000000..1d82f353241 --- /dev/null +++ b/drivers/staging/iio/dac/dac.h | |||
@@ -0,0 +1,6 @@ | |||
1 | /* | ||
2 | * dac.h - sysfs attributes associated with DACs | ||
3 | */ | ||
4 | |||
5 | #define IIO_DEV_ATTR_OUT_RAW(_num, _store, _addr) \ | ||
6 | IIO_DEVICE_ATTR(out##_num##_raw, S_IWUSR, NULL, _store, _addr) | ||
diff --git a/drivers/staging/iio/dac/max517.c b/drivers/staging/iio/dac/max517.c new file mode 100644 index 00000000000..ed5d351b238 --- /dev/null +++ b/drivers/staging/iio/dac/max517.c | |||
@@ -0,0 +1,295 @@ | |||
1 | /* | ||
2 | * max517.c - Support for Maxim MAX517, MAX518 and MAX519 | ||
3 | * | ||
4 | * Copyright (C) 2010, 2011 Roland Stigge <stigge@antcom.de> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/jiffies.h> | ||
25 | #include <linux/i2c.h> | ||
26 | #include <linux/err.h> | ||
27 | |||
28 | #include "../iio.h" | ||
29 | #include "dac.h" | ||
30 | |||
31 | #include "max517.h" | ||
32 | |||
33 | #define MAX517_DRV_NAME "max517" | ||
34 | |||
35 | /* Commands */ | ||
36 | #define COMMAND_CHANNEL0 0x00 | ||
37 | #define COMMAND_CHANNEL1 0x01 /* for MAX518 and MAX519 */ | ||
38 | #define COMMAND_PD 0x08 /* Power Down */ | ||
39 | |||
40 | enum max517_device_ids { | ||
41 | ID_MAX517, | ||
42 | ID_MAX518, | ||
43 | ID_MAX519, | ||
44 | }; | ||
45 | |||
46 | struct max517_data { | ||
47 | struct iio_dev *indio_dev; | ||
48 | struct i2c_client *client; | ||
49 | unsigned short vref_mv[2]; | ||
50 | }; | ||
51 | |||
52 | /* | ||
53 | * channel: bit 0: channel 1 | ||
54 | * bit 1: channel 2 | ||
55 | * (this way, it's possible to set both channels at once) | ||
56 | */ | ||
57 | static ssize_t max517_set_value(struct device *dev, | ||
58 | struct device_attribute *attr, | ||
59 | const char *buf, size_t count, int channel) | ||
60 | { | ||
61 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
62 | struct max517_data *data = iio_priv(dev_info); | ||
63 | struct i2c_client *client = data->client; | ||
64 | u8 outbuf[4]; /* 1x or 2x command + value */ | ||
65 | int outbuf_size = 0; | ||
66 | int res; | ||
67 | long val; | ||
68 | |||
69 | res = strict_strtol(buf, 10, &val); | ||
70 | |||
71 | if (res) | ||
72 | return res; | ||
73 | |||
74 | if (val < 0 || val > 255) | ||
75 | return -EINVAL; | ||
76 | |||
77 | if (channel & 1) { | ||
78 | outbuf[outbuf_size++] = COMMAND_CHANNEL0; | ||
79 | outbuf[outbuf_size++] = val; | ||
80 | } | ||
81 | if (channel & 2) { | ||
82 | outbuf[outbuf_size++] = COMMAND_CHANNEL1; | ||
83 | outbuf[outbuf_size++] = val; | ||
84 | } | ||
85 | |||
86 | /* | ||
87 | * At this point, there are always 1 or 2 two-byte commands in | ||
88 | * outbuf. With 2 commands, the device can set two outputs | ||
89 | * simultaneously, latching the values upon the end of the I2C | ||
90 | * transfer. | ||
91 | */ | ||
92 | |||
93 | res = i2c_master_send(client, outbuf, outbuf_size); | ||
94 | if (res < 0) | ||
95 | return res; | ||
96 | |||
97 | return count; | ||
98 | } | ||
99 | |||
100 | static ssize_t max517_set_value_1(struct device *dev, | ||
101 | struct device_attribute *attr, | ||
102 | const char *buf, size_t count) | ||
103 | { | ||
104 | return max517_set_value(dev, attr, buf, count, 1); | ||
105 | } | ||
106 | static IIO_DEV_ATTR_OUT_RAW(1, max517_set_value_1, 0); | ||
107 | |||
108 | static ssize_t max517_set_value_2(struct device *dev, | ||
109 | struct device_attribute *attr, | ||
110 | const char *buf, size_t count) | ||
111 | { | ||
112 | return max517_set_value(dev, attr, buf, count, 2); | ||
113 | } | ||
114 | static IIO_DEV_ATTR_OUT_RAW(2, max517_set_value_2, 1); | ||
115 | |||
116 | static ssize_t max517_set_value_both(struct device *dev, | ||
117 | struct device_attribute *attr, | ||
118 | const char *buf, size_t count) | ||
119 | { | ||
120 | return max517_set_value(dev, attr, buf, count, 3); | ||
121 | } | ||
122 | static IIO_DEVICE_ATTR_NAMED(out1and2_raw, out1&2_raw, S_IWUSR, NULL, | ||
123 | max517_set_value_both, -1); | ||
124 | |||
125 | static ssize_t max517_show_scale(struct device *dev, | ||
126 | struct device_attribute *attr, | ||
127 | char *buf, int channel) | ||
128 | { | ||
129 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
130 | struct max517_data *data = iio_priv(dev_info); | ||
131 | /* Corresponds to Vref / 2^(bits) */ | ||
132 | unsigned int scale_uv = (data->vref_mv[channel - 1] * 1000) >> 8; | ||
133 | |||
134 | return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); | ||
135 | } | ||
136 | |||
137 | static ssize_t max517_show_scale1(struct device *dev, | ||
138 | struct device_attribute *attr, | ||
139 | char *buf) | ||
140 | { | ||
141 | return max517_show_scale(dev, attr, buf, 1); | ||
142 | } | ||
143 | static IIO_DEVICE_ATTR(out1_scale, S_IRUGO, max517_show_scale1, NULL, 0); | ||
144 | |||
145 | static ssize_t max517_show_scale2(struct device *dev, | ||
146 | struct device_attribute *attr, | ||
147 | char *buf) | ||
148 | { | ||
149 | return max517_show_scale(dev, attr, buf, 2); | ||
150 | } | ||
151 | static IIO_DEVICE_ATTR(out2_scale, S_IRUGO, max517_show_scale2, NULL, 0); | ||
152 | |||
153 | /* On MAX517 variant, we have one output */ | ||
154 | static struct attribute *max517_attributes[] = { | ||
155 | &iio_dev_attr_out1_raw.dev_attr.attr, | ||
156 | &iio_dev_attr_out1_scale.dev_attr.attr, | ||
157 | NULL | ||
158 | }; | ||
159 | |||
160 | static struct attribute_group max517_attribute_group = { | ||
161 | .attrs = max517_attributes, | ||
162 | }; | ||
163 | |||
164 | /* On MAX518 and MAX519 variant, we have two outputs */ | ||
165 | static struct attribute *max518_attributes[] = { | ||
166 | &iio_dev_attr_out1_raw.dev_attr.attr, | ||
167 | &iio_dev_attr_out1_scale.dev_attr.attr, | ||
168 | &iio_dev_attr_out2_raw.dev_attr.attr, | ||
169 | &iio_dev_attr_out2_scale.dev_attr.attr, | ||
170 | &iio_dev_attr_out1and2_raw.dev_attr.attr, | ||
171 | NULL | ||
172 | }; | ||
173 | |||
174 | static struct attribute_group max518_attribute_group = { | ||
175 | .attrs = max518_attributes, | ||
176 | }; | ||
177 | |||
178 | static int max517_suspend(struct i2c_client *client, pm_message_t mesg) | ||
179 | { | ||
180 | u8 outbuf = COMMAND_PD; | ||
181 | |||
182 | return i2c_master_send(client, &outbuf, 1); | ||
183 | } | ||
184 | |||
185 | static int max517_resume(struct i2c_client *client) | ||
186 | { | ||
187 | u8 outbuf = 0; | ||
188 | |||
189 | return i2c_master_send(client, &outbuf, 1); | ||
190 | } | ||
191 | |||
192 | static const struct iio_info max517_info = { | ||
193 | .attrs = &max517_attribute_group, | ||
194 | .driver_module = THIS_MODULE, | ||
195 | }; | ||
196 | |||
197 | static const struct iio_info max518_info = { | ||
198 | .attrs = &max518_attribute_group, | ||
199 | .driver_module = THIS_MODULE, | ||
200 | }; | ||
201 | |||
202 | static int max517_probe(struct i2c_client *client, | ||
203 | const struct i2c_device_id *id) | ||
204 | { | ||
205 | struct max517_data *data; | ||
206 | struct iio_dev *indio_dev; | ||
207 | struct max517_platform_data *platform_data = client->dev.platform_data; | ||
208 | int err; | ||
209 | |||
210 | indio_dev = iio_allocate_device(sizeof(*data)); | ||
211 | if (indio_dev == NULL) { | ||
212 | err = -ENOMEM; | ||
213 | goto exit; | ||
214 | } | ||
215 | data = iio_priv(indio_dev); | ||
216 | i2c_set_clientdata(client, indio_dev); | ||
217 | data->client = client; | ||
218 | |||
219 | /* establish that the iio_dev is a child of the i2c device */ | ||
220 | indio_dev->dev.parent = &client->dev; | ||
221 | |||
222 | /* reduced attribute set for MAX517 */ | ||
223 | if (id->driver_data == ID_MAX517) | ||
224 | indio_dev->info = &max517_info; | ||
225 | else | ||
226 | indio_dev->info = &max518_info; | ||
227 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
228 | |||
229 | /* | ||
230 | * Reference voltage on MAX518 and default is 5V, else take vref_mv | ||
231 | * from platform_data | ||
232 | */ | ||
233 | if (id->driver_data == ID_MAX518 || !platform_data) { | ||
234 | data->vref_mv[0] = data->vref_mv[1] = 5000; /* mV */ | ||
235 | } else { | ||
236 | data->vref_mv[0] = platform_data->vref_mv[0]; | ||
237 | data->vref_mv[1] = platform_data->vref_mv[1]; | ||
238 | } | ||
239 | |||
240 | err = iio_device_register(indio_dev); | ||
241 | if (err) | ||
242 | goto exit_free_device; | ||
243 | |||
244 | dev_info(&client->dev, "DAC registered\n"); | ||
245 | |||
246 | return 0; | ||
247 | |||
248 | exit_free_device: | ||
249 | iio_free_device(indio_dev); | ||
250 | exit: | ||
251 | return err; | ||
252 | } | ||
253 | |||
254 | static int max517_remove(struct i2c_client *client) | ||
255 | { | ||
256 | iio_free_device(i2c_get_clientdata(client)); | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | |||
261 | static const struct i2c_device_id max517_id[] = { | ||
262 | { "max517", ID_MAX517 }, | ||
263 | { "max518", ID_MAX518 }, | ||
264 | { "max519", ID_MAX519 }, | ||
265 | { } | ||
266 | }; | ||
267 | MODULE_DEVICE_TABLE(i2c, max517_id); | ||
268 | |||
269 | static struct i2c_driver max517_driver = { | ||
270 | .driver = { | ||
271 | .name = MAX517_DRV_NAME, | ||
272 | }, | ||
273 | .probe = max517_probe, | ||
274 | .remove = max517_remove, | ||
275 | .suspend = max517_suspend, | ||
276 | .resume = max517_resume, | ||
277 | .id_table = max517_id, | ||
278 | }; | ||
279 | |||
280 | static int __init max517_init(void) | ||
281 | { | ||
282 | return i2c_add_driver(&max517_driver); | ||
283 | } | ||
284 | |||
285 | static void __exit max517_exit(void) | ||
286 | { | ||
287 | i2c_del_driver(&max517_driver); | ||
288 | } | ||
289 | |||
290 | MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>"); | ||
291 | MODULE_DESCRIPTION("MAX517/MAX518/MAX519 8-bit DAC"); | ||
292 | MODULE_LICENSE("GPL"); | ||
293 | |||
294 | module_init(max517_init); | ||
295 | module_exit(max517_exit); | ||
diff --git a/drivers/staging/iio/dac/max517.h b/drivers/staging/iio/dac/max517.h new file mode 100644 index 00000000000..8106cf24642 --- /dev/null +++ b/drivers/staging/iio/dac/max517.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* | ||
2 | * MAX517 DAC driver | ||
3 | * | ||
4 | * Copyright 2011 Roland Stigge <stigge@antcom.de> | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | #ifndef IIO_DAC_MAX517_H_ | ||
9 | #define IIO_DAC_MAX517_H_ | ||
10 | |||
11 | /* | ||
12 | * TODO: struct max517_platform_data needs to go into include/linux/iio | ||
13 | */ | ||
14 | |||
15 | struct max517_platform_data { | ||
16 | u16 vref_mv[2]; | ||
17 | }; | ||
18 | |||
19 | #endif /* IIO_DAC_MAX517_H_ */ | ||
diff --git a/drivers/staging/iio/dds/Kconfig b/drivers/staging/iio/dds/Kconfig new file mode 100644 index 00000000000..e07431d8009 --- /dev/null +++ b/drivers/staging/iio/dds/Kconfig | |||
@@ -0,0 +1,59 @@ | |||
1 | # | ||
2 | # Direct Digital Synthesis drivers | ||
3 | # | ||
4 | comment "Direct Digital Synthesis" | ||
5 | |||
6 | config AD5930 | ||
7 | tristate "Analog Devices ad5930/5932 driver" | ||
8 | depends on SPI | ||
9 | help | ||
10 | Say yes here to build support for Analog Devices DDS chip | ||
11 | ad5930/ad5932, provides direct access via sysfs. | ||
12 | |||
13 | config AD9832 | ||
14 | tristate "Analog Devices ad9832/5 driver" | ||
15 | depends on SPI | ||
16 | help | ||
17 | Say yes here to build support for Analog Devices DDS chip | ||
18 | AD9832 and AD9835, provides direct access via sysfs. | ||
19 | |||
20 | To compile this driver as a module, choose M here: the | ||
21 | module will be called ad9832. | ||
22 | |||
23 | config AD9834 | ||
24 | tristate "Analog Devices AD9833/4/7/8 driver" | ||
25 | depends on SPI | ||
26 | help | ||
27 | Say yes here to build support for Analog Devices DDS chip | ||
28 | AD9833, AD9834, AD9837 and AD9838, provides direct access via sysfs. | ||
29 | |||
30 | To compile this driver as a module, choose M here: the | ||
31 | module will be called ad9834. | ||
32 | |||
33 | config AD9850 | ||
34 | tristate "Analog Devices ad9850/1 driver" | ||
35 | depends on SPI | ||
36 | help | ||
37 | Say yes here to build support for Analog Devices DDS chip | ||
38 | ad9850/1, provides direct access via sysfs. | ||
39 | |||
40 | config AD9852 | ||
41 | tristate "Analog Devices ad9852/4 driver" | ||
42 | depends on SPI | ||
43 | help | ||
44 | Say yes here to build support for Analog Devices DDS chip | ||
45 | ad9852/4, provides direct access via sysfs. | ||
46 | |||
47 | config AD9910 | ||
48 | tristate "Analog Devices ad9910 driver" | ||
49 | depends on SPI | ||
50 | help | ||
51 | Say yes here to build support for Analog Devices DDS chip | ||
52 | ad9910, provides direct access via sysfs. | ||
53 | |||
54 | config AD9951 | ||
55 | tristate "Analog Devices ad9951 driver" | ||
56 | depends on SPI | ||
57 | help | ||
58 | Say yes here to build support for Analog Devices DDS chip | ||
59 | ad9951, provides direct access via sysfs. | ||
diff --git a/drivers/staging/iio/dds/Makefile b/drivers/staging/iio/dds/Makefile new file mode 100644 index 00000000000..147746176b9 --- /dev/null +++ b/drivers/staging/iio/dds/Makefile | |||
@@ -0,0 +1,11 @@ | |||
1 | # | ||
2 | # Makefile for Direct Digital Synthesis drivers | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_AD5930) += ad5930.o | ||
6 | obj-$(CONFIG_AD9832) += ad9832.o | ||
7 | obj-$(CONFIG_AD9834) += ad9834.o | ||
8 | obj-$(CONFIG_AD9850) += ad9850.o | ||
9 | obj-$(CONFIG_AD9852) += ad9852.o | ||
10 | obj-$(CONFIG_AD9910) += ad9910.o | ||
11 | obj-$(CONFIG_AD9951) += ad9951.o | ||
diff --git a/drivers/staging/iio/dds/ad5930.c b/drivers/staging/iio/dds/ad5930.c new file mode 100644 index 00000000000..0b2aa4cafdd --- /dev/null +++ b/drivers/staging/iio/dds/ad5930.c | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | * Driver for ADI Direct Digital Synthesis ad5930 | ||
3 | * | ||
4 | * Copyright (c) 2010-2010 Analog Devices Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/types.h> | ||
12 | #include <linux/mutex.h> | ||
13 | #include <linux/device.h> | ||
14 | #include <linux/spi/spi.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/sysfs.h> | ||
17 | |||
18 | #include "../iio.h" | ||
19 | #include "../sysfs.h" | ||
20 | |||
21 | #define DRV_NAME "ad5930" | ||
22 | |||
23 | #define value_mask (u16)0xf000 | ||
24 | #define addr_shift 12 | ||
25 | |||
26 | /* Register format: 4 bits addr + 12 bits value */ | ||
27 | struct ad5903_config { | ||
28 | u16 control; | ||
29 | u16 incnum; | ||
30 | u16 frqdelt[2]; | ||
31 | u16 incitvl; | ||
32 | u16 buritvl; | ||
33 | u16 strtfrq[2]; | ||
34 | }; | ||
35 | |||
36 | struct ad5930_state { | ||
37 | struct mutex lock; | ||
38 | struct spi_device *sdev; | ||
39 | }; | ||
40 | |||
41 | static ssize_t ad5930_set_parameter(struct device *dev, | ||
42 | struct device_attribute *attr, | ||
43 | const char *buf, | ||
44 | size_t len) | ||
45 | { | ||
46 | struct spi_message msg; | ||
47 | struct spi_transfer xfer; | ||
48 | int ret; | ||
49 | struct ad5903_config *config = (struct ad5903_config *)buf; | ||
50 | struct iio_dev *idev = dev_get_drvdata(dev); | ||
51 | struct ad5930_state *st = iio_priv(idev); | ||
52 | |||
53 | config->control = (config->control & ~value_mask); | ||
54 | config->incnum = (config->control & ~value_mask) | (1 << addr_shift); | ||
55 | config->frqdelt[0] = (config->control & ~value_mask) | (2 << addr_shift); | ||
56 | config->frqdelt[1] = (config->control & ~value_mask) | 3 << addr_shift; | ||
57 | config->incitvl = (config->control & ~value_mask) | 4 << addr_shift; | ||
58 | config->buritvl = (config->control & ~value_mask) | 8 << addr_shift; | ||
59 | config->strtfrq[0] = (config->control & ~value_mask) | 0xc << addr_shift; | ||
60 | config->strtfrq[1] = (config->control & ~value_mask) | 0xd << addr_shift; | ||
61 | |||
62 | xfer.len = len; | ||
63 | xfer.tx_buf = config; | ||
64 | mutex_lock(&st->lock); | ||
65 | |||
66 | spi_message_init(&msg); | ||
67 | spi_message_add_tail(&xfer, &msg); | ||
68 | ret = spi_sync(st->sdev, &msg); | ||
69 | if (ret) | ||
70 | goto error_ret; | ||
71 | error_ret: | ||
72 | mutex_unlock(&st->lock); | ||
73 | |||
74 | return ret ? ret : len; | ||
75 | } | ||
76 | |||
77 | static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad5930_set_parameter, 0); | ||
78 | |||
79 | static struct attribute *ad5930_attributes[] = { | ||
80 | &iio_dev_attr_dds.dev_attr.attr, | ||
81 | NULL, | ||
82 | }; | ||
83 | |||
84 | static const struct attribute_group ad5930_attribute_group = { | ||
85 | .attrs = ad5930_attributes, | ||
86 | }; | ||
87 | |||
88 | static const struct iio_info ad5930_info = { | ||
89 | .attrs = &ad5930_attribute_group, | ||
90 | .driver_module = THIS_MODULE, | ||
91 | }; | ||
92 | |||
93 | static int __devinit ad5930_probe(struct spi_device *spi) | ||
94 | { | ||
95 | struct ad5930_state *st; | ||
96 | struct iio_dev *idev; | ||
97 | int ret = 0; | ||
98 | |||
99 | idev = iio_allocate_device(sizeof(*st)); | ||
100 | if (idev == NULL) { | ||
101 | ret = -ENOMEM; | ||
102 | goto error_ret; | ||
103 | } | ||
104 | spi_set_drvdata(spi, idev); | ||
105 | st = iio_priv(idev); | ||
106 | |||
107 | mutex_init(&st->lock); | ||
108 | st->sdev = spi; | ||
109 | idev->dev.parent = &spi->dev; | ||
110 | idev->info = &ad5930_info; | ||
111 | idev->modes = INDIO_DIRECT_MODE; | ||
112 | |||
113 | ret = iio_device_register(idev); | ||
114 | if (ret) | ||
115 | goto error_free_dev; | ||
116 | spi->max_speed_hz = 2000000; | ||
117 | spi->mode = SPI_MODE_3; | ||
118 | spi->bits_per_word = 16; | ||
119 | spi_setup(spi); | ||
120 | |||
121 | return 0; | ||
122 | |||
123 | error_free_dev: | ||
124 | iio_free_device(idev); | ||
125 | error_ret: | ||
126 | return ret; | ||
127 | } | ||
128 | |||
129 | static int __devexit ad5930_remove(struct spi_device *spi) | ||
130 | { | ||
131 | iio_device_unregister(spi_get_drvdata(spi)); | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static struct spi_driver ad5930_driver = { | ||
137 | .driver = { | ||
138 | .name = DRV_NAME, | ||
139 | .owner = THIS_MODULE, | ||
140 | }, | ||
141 | .probe = ad5930_probe, | ||
142 | .remove = __devexit_p(ad5930_remove), | ||
143 | }; | ||
144 | |||
145 | static __init int ad5930_spi_init(void) | ||
146 | { | ||
147 | return spi_register_driver(&ad5930_driver); | ||
148 | } | ||
149 | module_init(ad5930_spi_init); | ||
150 | |||
151 | static __exit void ad5930_spi_exit(void) | ||
152 | { | ||
153 | spi_unregister_driver(&ad5930_driver); | ||
154 | } | ||
155 | module_exit(ad5930_spi_exit); | ||
156 | |||
157 | MODULE_AUTHOR("Cliff Cai"); | ||
158 | MODULE_DESCRIPTION("Analog Devices ad5930 driver"); | ||
159 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/staging/iio/dds/ad9832.c b/drivers/staging/iio/dds/ad9832.c new file mode 100644 index 00000000000..e3e61a469bb --- /dev/null +++ b/drivers/staging/iio/dds/ad9832.c | |||
@@ -0,0 +1,372 @@ | |||
1 | /* | ||
2 | * AD9832 SPI DDS driver | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/device.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/sysfs.h> | ||
13 | #include <linux/spi/spi.h> | ||
14 | #include <linux/regulator/consumer.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <asm/div64.h> | ||
17 | |||
18 | #include "../iio.h" | ||
19 | #include "../sysfs.h" | ||
20 | #include "dds.h" | ||
21 | |||
22 | #include "ad9832.h" | ||
23 | |||
24 | static unsigned long ad9832_calc_freqreg(unsigned long mclk, unsigned long fout) | ||
25 | { | ||
26 | unsigned long long freqreg = (u64) fout * | ||
27 | (u64) ((u64) 1L << AD9832_FREQ_BITS); | ||
28 | do_div(freqreg, mclk); | ||
29 | return freqreg; | ||
30 | } | ||
31 | |||
32 | static int ad9832_write_frequency(struct ad9832_state *st, | ||
33 | unsigned addr, unsigned long fout) | ||
34 | { | ||
35 | unsigned long regval; | ||
36 | |||
37 | if (fout > (st->mclk / 2)) | ||
38 | return -EINVAL; | ||
39 | |||
40 | regval = ad9832_calc_freqreg(st->mclk, fout); | ||
41 | |||
42 | st->freq_data[0] = cpu_to_be16((AD9832_CMD_FRE8BITSW << CMD_SHIFT) | | ||
43 | (addr << ADD_SHIFT) | | ||
44 | ((regval >> 24) & 0xFF)); | ||
45 | st->freq_data[1] = cpu_to_be16((AD9832_CMD_FRE16BITSW << CMD_SHIFT) | | ||
46 | ((addr - 1) << ADD_SHIFT) | | ||
47 | ((regval >> 16) & 0xFF)); | ||
48 | st->freq_data[2] = cpu_to_be16((AD9832_CMD_FRE8BITSW << CMD_SHIFT) | | ||
49 | ((addr - 2) << ADD_SHIFT) | | ||
50 | ((regval >> 8) & 0xFF)); | ||
51 | st->freq_data[3] = cpu_to_be16((AD9832_CMD_FRE16BITSW << CMD_SHIFT) | | ||
52 | ((addr - 3) << ADD_SHIFT) | | ||
53 | ((regval >> 0) & 0xFF)); | ||
54 | |||
55 | return spi_sync(st->spi, &st->freq_msg);; | ||
56 | } | ||
57 | |||
58 | static int ad9832_write_phase(struct ad9832_state *st, | ||
59 | unsigned long addr, unsigned long phase) | ||
60 | { | ||
61 | if (phase > (1 << AD9832_PHASE_BITS)) | ||
62 | return -EINVAL; | ||
63 | |||
64 | st->phase_data[0] = cpu_to_be16((AD9832_CMD_PHA8BITSW << CMD_SHIFT) | | ||
65 | (addr << ADD_SHIFT) | | ||
66 | ((phase >> 8) & 0xFF)); | ||
67 | st->phase_data[1] = cpu_to_be16((AD9832_CMD_PHA16BITSW << CMD_SHIFT) | | ||
68 | ((addr - 1) << ADD_SHIFT) | | ||
69 | (phase & 0xFF)); | ||
70 | |||
71 | return spi_sync(st->spi, &st->phase_msg); | ||
72 | } | ||
73 | |||
74 | static ssize_t ad9832_write(struct device *dev, | ||
75 | struct device_attribute *attr, | ||
76 | const char *buf, | ||
77 | size_t len) | ||
78 | { | ||
79 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
80 | struct ad9832_state *st = iio_priv(dev_info); | ||
81 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
82 | int ret; | ||
83 | long val; | ||
84 | |||
85 | ret = strict_strtoul(buf, 10, &val); | ||
86 | if (ret) | ||
87 | goto error_ret; | ||
88 | |||
89 | mutex_lock(&dev_info->mlock); | ||
90 | switch (this_attr->address) { | ||
91 | case AD9832_FREQ0HM: | ||
92 | case AD9832_FREQ1HM: | ||
93 | ret = ad9832_write_frequency(st, this_attr->address, val); | ||
94 | break; | ||
95 | case AD9832_PHASE0H: | ||
96 | case AD9832_PHASE1H: | ||
97 | case AD9832_PHASE2H: | ||
98 | case AD9832_PHASE3H: | ||
99 | ret = ad9832_write_phase(st, this_attr->address, val); | ||
100 | break; | ||
101 | case AD9832_PINCTRL_EN: | ||
102 | if (val) | ||
103 | st->ctrl_ss &= ~AD9832_SELSRC; | ||
104 | else | ||
105 | st->ctrl_ss |= AD9832_SELSRC; | ||
106 | st->data = cpu_to_be16((AD9832_CMD_SYNCSELSRC << CMD_SHIFT) | | ||
107 | st->ctrl_ss); | ||
108 | ret = spi_sync(st->spi, &st->msg); | ||
109 | break; | ||
110 | case AD9832_FREQ_SYM: | ||
111 | if (val == 1) | ||
112 | st->ctrl_fp |= AD9832_FREQ; | ||
113 | else if (val == 0) | ||
114 | st->ctrl_fp &= ~AD9832_FREQ; | ||
115 | else { | ||
116 | ret = -EINVAL; | ||
117 | break; | ||
118 | } | ||
119 | st->data = cpu_to_be16((AD9832_CMD_FPSELECT << CMD_SHIFT) | | ||
120 | st->ctrl_fp); | ||
121 | ret = spi_sync(st->spi, &st->msg); | ||
122 | break; | ||
123 | case AD9832_PHASE_SYM: | ||
124 | if (val < 0 || val > 3) { | ||
125 | ret = -EINVAL; | ||
126 | break; | ||
127 | } | ||
128 | |||
129 | st->ctrl_fp &= ~AD9832_PHASE(3); | ||
130 | st->ctrl_fp |= AD9832_PHASE(val); | ||
131 | |||
132 | st->data = cpu_to_be16((AD9832_CMD_FPSELECT << CMD_SHIFT) | | ||
133 | st->ctrl_fp); | ||
134 | ret = spi_sync(st->spi, &st->msg); | ||
135 | break; | ||
136 | case AD9832_OUTPUT_EN: | ||
137 | if (val) | ||
138 | st->ctrl_src &= ~(AD9832_RESET | AD9832_SLEEP | | ||
139 | AD9832_CLR); | ||
140 | else | ||
141 | st->ctrl_src |= AD9832_RESET; | ||
142 | |||
143 | st->data = cpu_to_be16((AD9832_CMD_SLEEPRESCLR << CMD_SHIFT) | | ||
144 | st->ctrl_src); | ||
145 | ret = spi_sync(st->spi, &st->msg); | ||
146 | break; | ||
147 | default: | ||
148 | ret = -ENODEV; | ||
149 | } | ||
150 | mutex_unlock(&dev_info->mlock); | ||
151 | |||
152 | error_ret: | ||
153 | return ret ? ret : len; | ||
154 | } | ||
155 | |||
156 | /** | ||
157 | * see dds.h for further information | ||
158 | */ | ||
159 | |||
160 | static IIO_DEV_ATTR_FREQ(0, 0, S_IWUSR, NULL, ad9832_write, AD9832_FREQ0HM); | ||
161 | static IIO_DEV_ATTR_FREQ(0, 1, S_IWUSR, NULL, ad9832_write, AD9832_FREQ1HM); | ||
162 | static IIO_DEV_ATTR_FREQSYMBOL(0, S_IWUSR, NULL, ad9832_write, AD9832_FREQ_SYM); | ||
163 | static IIO_CONST_ATTR_FREQ_SCALE(0, "1"); /* 1Hz */ | ||
164 | |||
165 | static IIO_DEV_ATTR_PHASE(0, 0, S_IWUSR, NULL, ad9832_write, AD9832_PHASE0H); | ||
166 | static IIO_DEV_ATTR_PHASE(0, 1, S_IWUSR, NULL, ad9832_write, AD9832_PHASE1H); | ||
167 | static IIO_DEV_ATTR_PHASE(0, 2, S_IWUSR, NULL, ad9832_write, AD9832_PHASE2H); | ||
168 | static IIO_DEV_ATTR_PHASE(0, 3, S_IWUSR, NULL, ad9832_write, AD9832_PHASE3H); | ||
169 | static IIO_DEV_ATTR_PHASESYMBOL(0, S_IWUSR, NULL, | ||
170 | ad9832_write, AD9832_PHASE_SYM); | ||
171 | static IIO_CONST_ATTR_PHASE_SCALE(0, "0.0015339808"); /* 2PI/2^12 rad*/ | ||
172 | |||
173 | static IIO_DEV_ATTR_PINCONTROL_EN(0, S_IWUSR, NULL, | ||
174 | ad9832_write, AD9832_PINCTRL_EN); | ||
175 | static IIO_DEV_ATTR_OUT_ENABLE(0, S_IWUSR, NULL, | ||
176 | ad9832_write, AD9832_OUTPUT_EN); | ||
177 | |||
178 | static struct attribute *ad9832_attributes[] = { | ||
179 | &iio_dev_attr_dds0_freq0.dev_attr.attr, | ||
180 | &iio_dev_attr_dds0_freq1.dev_attr.attr, | ||
181 | &iio_const_attr_dds0_freq_scale.dev_attr.attr, | ||
182 | &iio_dev_attr_dds0_phase0.dev_attr.attr, | ||
183 | &iio_dev_attr_dds0_phase1.dev_attr.attr, | ||
184 | &iio_dev_attr_dds0_phase2.dev_attr.attr, | ||
185 | &iio_dev_attr_dds0_phase3.dev_attr.attr, | ||
186 | &iio_const_attr_dds0_phase_scale.dev_attr.attr, | ||
187 | &iio_dev_attr_dds0_pincontrol_en.dev_attr.attr, | ||
188 | &iio_dev_attr_dds0_freqsymbol.dev_attr.attr, | ||
189 | &iio_dev_attr_dds0_phasesymbol.dev_attr.attr, | ||
190 | &iio_dev_attr_dds0_out_enable.dev_attr.attr, | ||
191 | NULL, | ||
192 | }; | ||
193 | |||
194 | static const struct attribute_group ad9832_attribute_group = { | ||
195 | .attrs = ad9832_attributes, | ||
196 | }; | ||
197 | |||
198 | static const struct iio_info ad9832_info = { | ||
199 | .attrs = &ad9832_attribute_group, | ||
200 | .driver_module = THIS_MODULE, | ||
201 | }; | ||
202 | |||
203 | static int __devinit ad9832_probe(struct spi_device *spi) | ||
204 | { | ||
205 | struct ad9832_platform_data *pdata = spi->dev.platform_data; | ||
206 | struct iio_dev *indio_dev; | ||
207 | struct ad9832_state *st; | ||
208 | struct regulator *reg; | ||
209 | int ret; | ||
210 | |||
211 | if (!pdata) { | ||
212 | dev_dbg(&spi->dev, "no platform data?\n"); | ||
213 | return -ENODEV; | ||
214 | } | ||
215 | |||
216 | reg = regulator_get(&spi->dev, "vcc"); | ||
217 | if (!IS_ERR(reg)) { | ||
218 | ret = regulator_enable(reg); | ||
219 | if (ret) | ||
220 | goto error_put_reg; | ||
221 | } | ||
222 | |||
223 | indio_dev = iio_allocate_device(sizeof(*st)); | ||
224 | if (indio_dev == NULL) { | ||
225 | ret = -ENOMEM; | ||
226 | goto error_disable_reg; | ||
227 | } | ||
228 | spi_set_drvdata(spi, indio_dev); | ||
229 | st = iio_priv(indio_dev); | ||
230 | st->reg = reg; | ||
231 | st->mclk = pdata->mclk; | ||
232 | st->spi = spi; | ||
233 | |||
234 | indio_dev->dev.parent = &spi->dev; | ||
235 | indio_dev->name = spi_get_device_id(spi)->name; | ||
236 | indio_dev->info = &ad9832_info; | ||
237 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
238 | |||
239 | /* Setup default messages */ | ||
240 | |||
241 | st->xfer.tx_buf = &st->data; | ||
242 | st->xfer.len = 2; | ||
243 | |||
244 | spi_message_init(&st->msg); | ||
245 | spi_message_add_tail(&st->xfer, &st->msg); | ||
246 | |||
247 | st->freq_xfer[0].tx_buf = &st->freq_data[0]; | ||
248 | st->freq_xfer[0].len = 2; | ||
249 | st->freq_xfer[0].cs_change = 1; | ||
250 | st->freq_xfer[1].tx_buf = &st->freq_data[1]; | ||
251 | st->freq_xfer[1].len = 2; | ||
252 | st->freq_xfer[1].cs_change = 1; | ||
253 | st->freq_xfer[2].tx_buf = &st->freq_data[2]; | ||
254 | st->freq_xfer[2].len = 2; | ||
255 | st->freq_xfer[2].cs_change = 1; | ||
256 | st->freq_xfer[3].tx_buf = &st->freq_data[3]; | ||
257 | st->freq_xfer[3].len = 2; | ||
258 | |||
259 | spi_message_init(&st->freq_msg); | ||
260 | spi_message_add_tail(&st->freq_xfer[0], &st->freq_msg); | ||
261 | spi_message_add_tail(&st->freq_xfer[1], &st->freq_msg); | ||
262 | spi_message_add_tail(&st->freq_xfer[2], &st->freq_msg); | ||
263 | spi_message_add_tail(&st->freq_xfer[3], &st->freq_msg); | ||
264 | |||
265 | st->phase_xfer[0].tx_buf = &st->phase_data[0]; | ||
266 | st->phase_xfer[0].len = 2; | ||
267 | st->phase_xfer[0].cs_change = 1; | ||
268 | st->phase_xfer[1].tx_buf = &st->phase_data[1]; | ||
269 | st->phase_xfer[1].len = 2; | ||
270 | |||
271 | spi_message_init(&st->phase_msg); | ||
272 | spi_message_add_tail(&st->phase_xfer[0], &st->phase_msg); | ||
273 | spi_message_add_tail(&st->phase_xfer[1], &st->phase_msg); | ||
274 | |||
275 | st->ctrl_src = AD9832_SLEEP | AD9832_RESET | AD9832_CLR; | ||
276 | st->data = cpu_to_be16((AD9832_CMD_SLEEPRESCLR << CMD_SHIFT) | | ||
277 | st->ctrl_src); | ||
278 | ret = spi_sync(st->spi, &st->msg); | ||
279 | if (ret) { | ||
280 | dev_err(&spi->dev, "device init failed\n"); | ||
281 | goto error_free_device; | ||
282 | } | ||
283 | |||
284 | ret = ad9832_write_frequency(st, AD9832_FREQ0HM, pdata->freq0); | ||
285 | if (ret) | ||
286 | goto error_free_device; | ||
287 | |||
288 | ret = ad9832_write_frequency(st, AD9832_FREQ1HM, pdata->freq1); | ||
289 | if (ret) | ||
290 | goto error_free_device; | ||
291 | |||
292 | ret = ad9832_write_phase(st, AD9832_PHASE0H, pdata->phase0); | ||
293 | if (ret) | ||
294 | goto error_free_device; | ||
295 | |||
296 | ret = ad9832_write_phase(st, AD9832_PHASE1H, pdata->phase1); | ||
297 | if (ret) | ||
298 | goto error_free_device; | ||
299 | |||
300 | ret = ad9832_write_phase(st, AD9832_PHASE2H, pdata->phase2); | ||
301 | if (ret) | ||
302 | goto error_free_device; | ||
303 | |||
304 | ret = ad9832_write_phase(st, AD9832_PHASE3H, pdata->phase3); | ||
305 | if (ret) | ||
306 | goto error_free_device; | ||
307 | |||
308 | ret = iio_device_register(indio_dev); | ||
309 | if (ret) | ||
310 | goto error_free_device; | ||
311 | |||
312 | return 0; | ||
313 | |||
314 | error_free_device: | ||
315 | iio_free_device(indio_dev); | ||
316 | error_disable_reg: | ||
317 | if (!IS_ERR(reg)) | ||
318 | regulator_disable(reg); | ||
319 | error_put_reg: | ||
320 | if (!IS_ERR(reg)) | ||
321 | regulator_put(reg); | ||
322 | |||
323 | return ret; | ||
324 | } | ||
325 | |||
326 | static int __devexit ad9832_remove(struct spi_device *spi) | ||
327 | { | ||
328 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
329 | struct ad9832_state *st = iio_priv(indio_dev); | ||
330 | struct regulator *reg = st->reg; | ||
331 | |||
332 | iio_device_unregister(indio_dev); | ||
333 | if (!IS_ERR(reg)) { | ||
334 | regulator_disable(reg); | ||
335 | regulator_put(reg); | ||
336 | } | ||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static const struct spi_device_id ad9832_id[] = { | ||
341 | {"ad9832", 0}, | ||
342 | {"ad9835", 0}, | ||
343 | {} | ||
344 | }; | ||
345 | |||
346 | static struct spi_driver ad9832_driver = { | ||
347 | .driver = { | ||
348 | .name = "ad9832", | ||
349 | .bus = &spi_bus_type, | ||
350 | .owner = THIS_MODULE, | ||
351 | }, | ||
352 | .probe = ad9832_probe, | ||
353 | .remove = __devexit_p(ad9832_remove), | ||
354 | .id_table = ad9832_id, | ||
355 | }; | ||
356 | |||
357 | static int __init ad9832_init(void) | ||
358 | { | ||
359 | return spi_register_driver(&ad9832_driver); | ||
360 | } | ||
361 | module_init(ad9832_init); | ||
362 | |||
363 | static void __exit ad9832_exit(void) | ||
364 | { | ||
365 | spi_unregister_driver(&ad9832_driver); | ||
366 | } | ||
367 | module_exit(ad9832_exit); | ||
368 | |||
369 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
370 | MODULE_DESCRIPTION("Analog Devices AD9832/AD9835 DDS"); | ||
371 | MODULE_LICENSE("GPL v2"); | ||
372 | MODULE_ALIAS("spi:ad9832"); | ||
diff --git a/drivers/staging/iio/dds/ad9832.h b/drivers/staging/iio/dds/ad9832.h new file mode 100644 index 00000000000..c5b701f8aab --- /dev/null +++ b/drivers/staging/iio/dds/ad9832.h | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | * AD9832 SPI DDS driver | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | #ifndef IIO_DDS_AD9832_H_ | ||
9 | #define IIO_DDS_AD9832_H_ | ||
10 | |||
11 | /* Registers */ | ||
12 | |||
13 | #define AD9832_FREQ0LL 0x0 | ||
14 | #define AD9832_FREQ0HL 0x1 | ||
15 | #define AD9832_FREQ0LM 0x2 | ||
16 | #define AD9832_FREQ0HM 0x3 | ||
17 | #define AD9832_FREQ1LL 0x4 | ||
18 | #define AD9832_FREQ1HL 0x5 | ||
19 | #define AD9832_FREQ1LM 0x6 | ||
20 | #define AD9832_FREQ1HM 0x7 | ||
21 | #define AD9832_PHASE0L 0x8 | ||
22 | #define AD9832_PHASE0H 0x9 | ||
23 | #define AD9832_PHASE1L 0xA | ||
24 | #define AD9832_PHASE1H 0xB | ||
25 | #define AD9832_PHASE2L 0xC | ||
26 | #define AD9832_PHASE2H 0xD | ||
27 | #define AD9832_PHASE3L 0xE | ||
28 | #define AD9832_PHASE3H 0xF | ||
29 | |||
30 | #define AD9832_PHASE_SYM 0x10 | ||
31 | #define AD9832_FREQ_SYM 0x11 | ||
32 | #define AD9832_PINCTRL_EN 0x12 | ||
33 | #define AD9832_OUTPUT_EN 0x13 | ||
34 | |||
35 | /* Command Control Bits */ | ||
36 | |||
37 | #define AD9832_CMD_PHA8BITSW 0x1 | ||
38 | #define AD9832_CMD_PHA16BITSW 0x0 | ||
39 | #define AD9832_CMD_FRE8BITSW 0x3 | ||
40 | #define AD9832_CMD_FRE16BITSW 0x2 | ||
41 | #define AD9832_CMD_FPSELECT 0x6 | ||
42 | #define AD9832_CMD_SYNCSELSRC 0x8 | ||
43 | #define AD9832_CMD_SLEEPRESCLR 0xC | ||
44 | |||
45 | #define AD9832_FREQ (1 << 11) | ||
46 | #define AD9832_PHASE(x) (((x) & 3) << 9) | ||
47 | #define AD9832_SYNC (1 << 13) | ||
48 | #define AD9832_SELSRC (1 << 12) | ||
49 | #define AD9832_SLEEP (1 << 13) | ||
50 | #define AD9832_RESET (1 << 12) | ||
51 | #define AD9832_CLR (1 << 11) | ||
52 | #define CMD_SHIFT 12 | ||
53 | #define ADD_SHIFT 8 | ||
54 | #define AD9832_FREQ_BITS 32 | ||
55 | #define AD9832_PHASE_BITS 12 | ||
56 | #define RES_MASK(bits) ((1 << (bits)) - 1) | ||
57 | |||
58 | /** | ||
59 | * struct ad9832_state - driver instance specific data | ||
60 | * @spi: spi_device | ||
61 | * @reg: supply regulator | ||
62 | * @mclk: external master clock | ||
63 | * @ctrl_fp: cached frequency/phase control word | ||
64 | * @ctrl_ss: cached sync/selsrc control word | ||
65 | * @ctrl_src: cached sleep/reset/clr word | ||
66 | * @xfer: default spi transfer | ||
67 | * @msg: default spi message | ||
68 | * @freq_xfer: tuning word spi transfer | ||
69 | * @freq_msg: tuning word spi message | ||
70 | * @phase_xfer: tuning word spi transfer | ||
71 | * @phase_msg: tuning word spi message | ||
72 | * @data: spi transmit buffer | ||
73 | * @phase_data: tuning word spi transmit buffer | ||
74 | * @freq_data: tuning word spi transmit buffer | ||
75 | */ | ||
76 | |||
77 | struct ad9832_state { | ||
78 | struct spi_device *spi; | ||
79 | struct regulator *reg; | ||
80 | unsigned long mclk; | ||
81 | unsigned short ctrl_fp; | ||
82 | unsigned short ctrl_ss; | ||
83 | unsigned short ctrl_src; | ||
84 | struct spi_transfer xfer; | ||
85 | struct spi_message msg; | ||
86 | struct spi_transfer freq_xfer[4]; | ||
87 | struct spi_message freq_msg; | ||
88 | struct spi_transfer phase_xfer[2]; | ||
89 | struct spi_message phase_msg; | ||
90 | /* | ||
91 | * DMA (thus cache coherency maintenance) requires the | ||
92 | * transfer buffers to live in their own cache lines. | ||
93 | */ | ||
94 | union { | ||
95 | unsigned short freq_data[4]____cacheline_aligned; | ||
96 | unsigned short phase_data[2]; | ||
97 | unsigned short data; | ||
98 | }; | ||
99 | }; | ||
100 | |||
101 | /* | ||
102 | * TODO: struct ad9832_platform_data needs to go into include/linux/iio | ||
103 | */ | ||
104 | |||
105 | /** | ||
106 | * struct ad9832_platform_data - platform specific information | ||
107 | * @mclk: master clock in Hz | ||
108 | * @freq0: power up freq0 tuning word in Hz | ||
109 | * @freq1: power up freq1 tuning word in Hz | ||
110 | * @phase0: power up phase0 value [0..4095] correlates with 0..2PI | ||
111 | * @phase1: power up phase1 value [0..4095] correlates with 0..2PI | ||
112 | * @phase2: power up phase2 value [0..4095] correlates with 0..2PI | ||
113 | * @phase3: power up phase3 value [0..4095] correlates with 0..2PI | ||
114 | */ | ||
115 | |||
116 | struct ad9832_platform_data { | ||
117 | unsigned long mclk; | ||
118 | unsigned long freq0; | ||
119 | unsigned long freq1; | ||
120 | unsigned short phase0; | ||
121 | unsigned short phase1; | ||
122 | unsigned short phase2; | ||
123 | unsigned short phase3; | ||
124 | }; | ||
125 | |||
126 | #endif /* IIO_DDS_AD9832_H_ */ | ||
diff --git a/drivers/staging/iio/dds/ad9834.c b/drivers/staging/iio/dds/ad9834.c new file mode 100644 index 00000000000..e6454d58fe4 --- /dev/null +++ b/drivers/staging/iio/dds/ad9834.c | |||
@@ -0,0 +1,464 @@ | |||
1 | /* | ||
2 | * AD9833/AD9834/AD9837/AD9838 SPI DDS driver | ||
3 | * | ||
4 | * Copyright 2010-2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | |||
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 <asm/div64.h> | ||
20 | |||
21 | #include "../iio.h" | ||
22 | #include "../sysfs.h" | ||
23 | #include "dds.h" | ||
24 | |||
25 | #include "ad9834.h" | ||
26 | |||
27 | static unsigned int ad9834_calc_freqreg(unsigned long mclk, unsigned long fout) | ||
28 | { | ||
29 | unsigned long long freqreg = (u64) fout * (u64) (1 << AD9834_FREQ_BITS); | ||
30 | do_div(freqreg, mclk); | ||
31 | return freqreg; | ||
32 | } | ||
33 | |||
34 | static int ad9834_write_frequency(struct ad9834_state *st, | ||
35 | unsigned long addr, unsigned long fout) | ||
36 | { | ||
37 | unsigned long regval; | ||
38 | |||
39 | if (fout > (st->mclk / 2)) | ||
40 | return -EINVAL; | ||
41 | |||
42 | regval = ad9834_calc_freqreg(st->mclk, fout); | ||
43 | |||
44 | st->freq_data[0] = cpu_to_be16(addr | (regval & | ||
45 | RES_MASK(AD9834_FREQ_BITS / 2))); | ||
46 | st->freq_data[1] = cpu_to_be16(addr | ((regval >> | ||
47 | (AD9834_FREQ_BITS / 2)) & | ||
48 | RES_MASK(AD9834_FREQ_BITS / 2))); | ||
49 | |||
50 | return spi_sync(st->spi, &st->freq_msg); | ||
51 | } | ||
52 | |||
53 | static int ad9834_write_phase(struct ad9834_state *st, | ||
54 | unsigned long addr, unsigned long phase) | ||
55 | { | ||
56 | if (phase > (1 << AD9834_PHASE_BITS)) | ||
57 | return -EINVAL; | ||
58 | st->data = cpu_to_be16(addr | phase); | ||
59 | |||
60 | return spi_sync(st->spi, &st->msg); | ||
61 | } | ||
62 | |||
63 | static ssize_t ad9834_write(struct device *dev, | ||
64 | struct device_attribute *attr, | ||
65 | const char *buf, | ||
66 | size_t len) | ||
67 | { | ||
68 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
69 | struct ad9834_state *st = iio_priv(dev_info); | ||
70 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
71 | int ret; | ||
72 | long val; | ||
73 | |||
74 | ret = strict_strtoul(buf, 10, &val); | ||
75 | if (ret) | ||
76 | goto error_ret; | ||
77 | |||
78 | mutex_lock(&dev_info->mlock); | ||
79 | switch (this_attr->address) { | ||
80 | case AD9834_REG_FREQ0: | ||
81 | case AD9834_REG_FREQ1: | ||
82 | ret = ad9834_write_frequency(st, this_attr->address, val); | ||
83 | break; | ||
84 | case AD9834_REG_PHASE0: | ||
85 | case AD9834_REG_PHASE1: | ||
86 | ret = ad9834_write_phase(st, this_attr->address, val); | ||
87 | break; | ||
88 | case AD9834_OPBITEN: | ||
89 | if (st->control & AD9834_MODE) { | ||
90 | ret = -EINVAL; /* AD9843 reserved mode */ | ||
91 | break; | ||
92 | } | ||
93 | |||
94 | if (val) | ||
95 | st->control |= AD9834_OPBITEN; | ||
96 | else | ||
97 | st->control &= ~AD9834_OPBITEN; | ||
98 | |||
99 | st->data = cpu_to_be16(AD9834_REG_CMD | st->control); | ||
100 | ret = spi_sync(st->spi, &st->msg); | ||
101 | break; | ||
102 | case AD9834_PIN_SW: | ||
103 | if (val) | ||
104 | st->control |= AD9834_PIN_SW; | ||
105 | else | ||
106 | st->control &= ~AD9834_PIN_SW; | ||
107 | st->data = cpu_to_be16(AD9834_REG_CMD | st->control); | ||
108 | ret = spi_sync(st->spi, &st->msg); | ||
109 | break; | ||
110 | case AD9834_FSEL: | ||
111 | case AD9834_PSEL: | ||
112 | if (val == 0) | ||
113 | st->control &= ~(this_attr->address | AD9834_PIN_SW); | ||
114 | else if (val == 1) { | ||
115 | st->control |= this_attr->address; | ||
116 | st->control &= ~AD9834_PIN_SW; | ||
117 | } else { | ||
118 | ret = -EINVAL; | ||
119 | break; | ||
120 | } | ||
121 | st->data = cpu_to_be16(AD9834_REG_CMD | st->control); | ||
122 | ret = spi_sync(st->spi, &st->msg); | ||
123 | break; | ||
124 | case AD9834_RESET: | ||
125 | if (val) | ||
126 | st->control &= ~AD9834_RESET; | ||
127 | else | ||
128 | st->control |= AD9834_RESET; | ||
129 | |||
130 | st->data = cpu_to_be16(AD9834_REG_CMD | st->control); | ||
131 | ret = spi_sync(st->spi, &st->msg); | ||
132 | break; | ||
133 | default: | ||
134 | ret = -ENODEV; | ||
135 | } | ||
136 | mutex_unlock(&dev_info->mlock); | ||
137 | |||
138 | error_ret: | ||
139 | return ret ? ret : len; | ||
140 | } | ||
141 | |||
142 | static ssize_t ad9834_store_wavetype(struct device *dev, | ||
143 | struct device_attribute *attr, | ||
144 | const char *buf, | ||
145 | size_t len) | ||
146 | { | ||
147 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
148 | struct ad9834_state *st = iio_priv(dev_info); | ||
149 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
150 | int ret = 0; | ||
151 | bool is_ad9833_7 = (st->devid == ID_AD9833) || (st->devid == ID_AD9837); | ||
152 | |||
153 | mutex_lock(&dev_info->mlock); | ||
154 | |||
155 | switch (this_attr->address) { | ||
156 | case 0: | ||
157 | if (sysfs_streq(buf, "sine")) { | ||
158 | st->control &= ~AD9834_MODE; | ||
159 | if (is_ad9833_7) | ||
160 | st->control &= ~AD9834_OPBITEN; | ||
161 | } else if (sysfs_streq(buf, "triangle")) { | ||
162 | if (is_ad9833_7) { | ||
163 | st->control &= ~AD9834_OPBITEN; | ||
164 | st->control |= AD9834_MODE; | ||
165 | } else if (st->control & AD9834_OPBITEN) { | ||
166 | ret = -EINVAL; /* AD9843 reserved mode */ | ||
167 | } else { | ||
168 | st->control |= AD9834_MODE; | ||
169 | } | ||
170 | } else if (is_ad9833_7 && sysfs_streq(buf, "square")) { | ||
171 | st->control &= ~AD9834_MODE; | ||
172 | st->control |= AD9834_OPBITEN; | ||
173 | } else { | ||
174 | ret = -EINVAL; | ||
175 | } | ||
176 | |||
177 | break; | ||
178 | case 1: | ||
179 | if (sysfs_streq(buf, "square") && | ||
180 | !(st->control & AD9834_MODE)) { | ||
181 | st->control &= ~AD9834_MODE; | ||
182 | st->control |= AD9834_OPBITEN; | ||
183 | } else { | ||
184 | ret = -EINVAL; | ||
185 | } | ||
186 | break; | ||
187 | default: | ||
188 | ret = -EINVAL; | ||
189 | break; | ||
190 | } | ||
191 | |||
192 | if (!ret) { | ||
193 | st->data = cpu_to_be16(AD9834_REG_CMD | st->control); | ||
194 | ret = spi_sync(st->spi, &st->msg); | ||
195 | } | ||
196 | mutex_unlock(&dev_info->mlock); | ||
197 | |||
198 | return ret ? ret : len; | ||
199 | } | ||
200 | |||
201 | static ssize_t ad9834_show_out0_wavetype_available(struct device *dev, | ||
202 | struct device_attribute *attr, | ||
203 | char *buf) | ||
204 | { | ||
205 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
206 | struct ad9834_state *st = iio_priv(dev_info); | ||
207 | char *str; | ||
208 | |||
209 | if ((st->devid == ID_AD9833) || (st->devid == ID_AD9837)) | ||
210 | str = "sine triangle square"; | ||
211 | else if (st->control & AD9834_OPBITEN) | ||
212 | str = "sine"; | ||
213 | else | ||
214 | str = "sine triangle"; | ||
215 | |||
216 | return sprintf(buf, "%s\n", str); | ||
217 | } | ||
218 | |||
219 | |||
220 | static IIO_DEVICE_ATTR(dds0_out0_wavetype_available, S_IRUGO, | ||
221 | ad9834_show_out0_wavetype_available, NULL, 0); | ||
222 | |||
223 | static ssize_t ad9834_show_out1_wavetype_available(struct device *dev, | ||
224 | struct device_attribute *attr, | ||
225 | char *buf) | ||
226 | { | ||
227 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
228 | struct ad9834_state *st = iio_priv(dev_info); | ||
229 | char *str; | ||
230 | |||
231 | if (st->control & AD9834_MODE) | ||
232 | str = ""; | ||
233 | else | ||
234 | str = "square"; | ||
235 | |||
236 | return sprintf(buf, "%s\n", str); | ||
237 | } | ||
238 | |||
239 | static IIO_DEVICE_ATTR(dds0_out1_wavetype_available, S_IRUGO, | ||
240 | ad9834_show_out1_wavetype_available, NULL, 0); | ||
241 | |||
242 | /** | ||
243 | * see dds.h for further information | ||
244 | */ | ||
245 | |||
246 | static IIO_DEV_ATTR_FREQ(0, 0, S_IWUSR, NULL, ad9834_write, AD9834_REG_FREQ0); | ||
247 | static IIO_DEV_ATTR_FREQ(0, 1, S_IWUSR, NULL, ad9834_write, AD9834_REG_FREQ1); | ||
248 | static IIO_DEV_ATTR_FREQSYMBOL(0, S_IWUSR, NULL, ad9834_write, AD9834_FSEL); | ||
249 | static IIO_CONST_ATTR_FREQ_SCALE(0, "1"); /* 1Hz */ | ||
250 | |||
251 | static IIO_DEV_ATTR_PHASE(0, 0, S_IWUSR, NULL, ad9834_write, AD9834_REG_PHASE0); | ||
252 | static IIO_DEV_ATTR_PHASE(0, 1, S_IWUSR, NULL, ad9834_write, AD9834_REG_PHASE1); | ||
253 | static IIO_DEV_ATTR_PHASESYMBOL(0, S_IWUSR, NULL, ad9834_write, AD9834_PSEL); | ||
254 | static IIO_CONST_ATTR_PHASE_SCALE(0, "0.0015339808"); /* 2PI/2^12 rad*/ | ||
255 | |||
256 | static IIO_DEV_ATTR_PINCONTROL_EN(0, S_IWUSR, NULL, | ||
257 | ad9834_write, AD9834_PIN_SW); | ||
258 | static IIO_DEV_ATTR_OUT_ENABLE(0, S_IWUSR, NULL, ad9834_write, AD9834_RESET); | ||
259 | static IIO_DEV_ATTR_OUTY_ENABLE(0, 1, S_IWUSR, NULL, | ||
260 | ad9834_write, AD9834_OPBITEN); | ||
261 | static IIO_DEV_ATTR_OUT_WAVETYPE(0, 0, ad9834_store_wavetype, 0); | ||
262 | static IIO_DEV_ATTR_OUT_WAVETYPE(0, 1, ad9834_store_wavetype, 1); | ||
263 | |||
264 | static struct attribute *ad9834_attributes[] = { | ||
265 | &iio_dev_attr_dds0_freq0.dev_attr.attr, | ||
266 | &iio_dev_attr_dds0_freq1.dev_attr.attr, | ||
267 | &iio_const_attr_dds0_freq_scale.dev_attr.attr, | ||
268 | &iio_dev_attr_dds0_phase0.dev_attr.attr, | ||
269 | &iio_dev_attr_dds0_phase1.dev_attr.attr, | ||
270 | &iio_const_attr_dds0_phase_scale.dev_attr.attr, | ||
271 | &iio_dev_attr_dds0_pincontrol_en.dev_attr.attr, | ||
272 | &iio_dev_attr_dds0_freqsymbol.dev_attr.attr, | ||
273 | &iio_dev_attr_dds0_phasesymbol.dev_attr.attr, | ||
274 | &iio_dev_attr_dds0_out_enable.dev_attr.attr, | ||
275 | &iio_dev_attr_dds0_out1_enable.dev_attr.attr, | ||
276 | &iio_dev_attr_dds0_out0_wavetype.dev_attr.attr, | ||
277 | &iio_dev_attr_dds0_out1_wavetype.dev_attr.attr, | ||
278 | &iio_dev_attr_dds0_out0_wavetype_available.dev_attr.attr, | ||
279 | &iio_dev_attr_dds0_out1_wavetype_available.dev_attr.attr, | ||
280 | NULL, | ||
281 | }; | ||
282 | |||
283 | static mode_t ad9834_attr_is_visible(struct kobject *kobj, | ||
284 | struct attribute *attr, int n) | ||
285 | { | ||
286 | struct device *dev = container_of(kobj, struct device, kobj); | ||
287 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
288 | struct ad9834_state *st = iio_priv(dev_info); | ||
289 | |||
290 | mode_t mode = attr->mode; | ||
291 | |||
292 | if (((st->devid == ID_AD9833) || (st->devid == ID_AD9837)) && | ||
293 | ((attr == &iio_dev_attr_dds0_out1_enable.dev_attr.attr) || | ||
294 | (attr == &iio_dev_attr_dds0_out1_wavetype.dev_attr.attr) || | ||
295 | (attr == | ||
296 | &iio_dev_attr_dds0_out1_wavetype_available.dev_attr.attr) || | ||
297 | (attr == &iio_dev_attr_dds0_pincontrol_en.dev_attr.attr))) | ||
298 | mode = 0; | ||
299 | |||
300 | return mode; | ||
301 | } | ||
302 | |||
303 | static const struct attribute_group ad9834_attribute_group = { | ||
304 | .attrs = ad9834_attributes, | ||
305 | .is_visible = ad9834_attr_is_visible, | ||
306 | }; | ||
307 | |||
308 | static const struct iio_info ad9834_info = { | ||
309 | .attrs = &ad9834_attribute_group, | ||
310 | .driver_module = THIS_MODULE, | ||
311 | }; | ||
312 | |||
313 | static int __devinit ad9834_probe(struct spi_device *spi) | ||
314 | { | ||
315 | struct ad9834_platform_data *pdata = spi->dev.platform_data; | ||
316 | struct ad9834_state *st; | ||
317 | struct iio_dev *indio_dev; | ||
318 | struct regulator *reg; | ||
319 | int ret; | ||
320 | |||
321 | if (!pdata) { | ||
322 | dev_dbg(&spi->dev, "no platform data?\n"); | ||
323 | return -ENODEV; | ||
324 | } | ||
325 | |||
326 | reg = regulator_get(&spi->dev, "vcc"); | ||
327 | if (!IS_ERR(reg)) { | ||
328 | ret = regulator_enable(reg); | ||
329 | if (ret) | ||
330 | goto error_put_reg; | ||
331 | } | ||
332 | |||
333 | indio_dev = iio_allocate_device(sizeof(*st)); | ||
334 | if (indio_dev == NULL) { | ||
335 | ret = -ENOMEM; | ||
336 | goto error_disable_reg; | ||
337 | } | ||
338 | spi_set_drvdata(spi, indio_dev); | ||
339 | st = iio_priv(indio_dev); | ||
340 | st->mclk = pdata->mclk; | ||
341 | st->spi = spi; | ||
342 | st->devid = spi_get_device_id(spi)->driver_data; | ||
343 | st->reg = reg; | ||
344 | indio_dev->dev.parent = &spi->dev; | ||
345 | indio_dev->name = spi_get_device_id(spi)->name; | ||
346 | indio_dev->info = &ad9834_info; | ||
347 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
348 | |||
349 | /* Setup default messages */ | ||
350 | |||
351 | st->xfer.tx_buf = &st->data; | ||
352 | st->xfer.len = 2; | ||
353 | |||
354 | spi_message_init(&st->msg); | ||
355 | spi_message_add_tail(&st->xfer, &st->msg); | ||
356 | |||
357 | st->freq_xfer[0].tx_buf = &st->freq_data[0]; | ||
358 | st->freq_xfer[0].len = 2; | ||
359 | st->freq_xfer[0].cs_change = 1; | ||
360 | st->freq_xfer[1].tx_buf = &st->freq_data[1]; | ||
361 | st->freq_xfer[1].len = 2; | ||
362 | |||
363 | spi_message_init(&st->freq_msg); | ||
364 | spi_message_add_tail(&st->freq_xfer[0], &st->freq_msg); | ||
365 | spi_message_add_tail(&st->freq_xfer[1], &st->freq_msg); | ||
366 | |||
367 | st->control = AD9834_B28 | AD9834_RESET; | ||
368 | |||
369 | if (!pdata->en_div2) | ||
370 | st->control |= AD9834_DIV2; | ||
371 | |||
372 | if (!pdata->en_signbit_msb_out && (st->devid == ID_AD9834)) | ||
373 | st->control |= AD9834_SIGN_PIB; | ||
374 | |||
375 | st->data = cpu_to_be16(AD9834_REG_CMD | st->control); | ||
376 | ret = spi_sync(st->spi, &st->msg); | ||
377 | if (ret) { | ||
378 | dev_err(&spi->dev, "device init failed\n"); | ||
379 | goto error_free_device; | ||
380 | } | ||
381 | |||
382 | ret = ad9834_write_frequency(st, AD9834_REG_FREQ0, pdata->freq0); | ||
383 | if (ret) | ||
384 | goto error_free_device; | ||
385 | |||
386 | ret = ad9834_write_frequency(st, AD9834_REG_FREQ1, pdata->freq1); | ||
387 | if (ret) | ||
388 | goto error_free_device; | ||
389 | |||
390 | ret = ad9834_write_phase(st, AD9834_REG_PHASE0, pdata->phase0); | ||
391 | if (ret) | ||
392 | goto error_free_device; | ||
393 | |||
394 | ret = ad9834_write_phase(st, AD9834_REG_PHASE1, pdata->phase1); | ||
395 | if (ret) | ||
396 | goto error_free_device; | ||
397 | |||
398 | ret = iio_device_register(indio_dev); | ||
399 | if (ret) | ||
400 | goto error_free_device; | ||
401 | |||
402 | return 0; | ||
403 | |||
404 | error_free_device: | ||
405 | iio_free_device(indio_dev); | ||
406 | error_disable_reg: | ||
407 | if (!IS_ERR(reg)) | ||
408 | regulator_disable(reg); | ||
409 | error_put_reg: | ||
410 | if (!IS_ERR(reg)) | ||
411 | regulator_put(reg); | ||
412 | return ret; | ||
413 | } | ||
414 | |||
415 | static int __devexit ad9834_remove(struct spi_device *spi) | ||
416 | { | ||
417 | struct iio_dev *indio_dev = spi_get_drvdata(spi); | ||
418 | struct ad9834_state *st = iio_priv(indio_dev); | ||
419 | struct regulator *reg = st->reg; | ||
420 | |||
421 | iio_device_unregister(indio_dev); | ||
422 | if (!IS_ERR(reg)) { | ||
423 | regulator_disable(reg); | ||
424 | regulator_put(reg); | ||
425 | } | ||
426 | |||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | static const struct spi_device_id ad9834_id[] = { | ||
431 | {"ad9833", ID_AD9833}, | ||
432 | {"ad9834", ID_AD9834}, | ||
433 | {"ad9837", ID_AD9837}, | ||
434 | {"ad9838", ID_AD9838}, | ||
435 | {} | ||
436 | }; | ||
437 | |||
438 | static struct spi_driver ad9834_driver = { | ||
439 | .driver = { | ||
440 | .name = "ad9834", | ||
441 | .bus = &spi_bus_type, | ||
442 | .owner = THIS_MODULE, | ||
443 | }, | ||
444 | .probe = ad9834_probe, | ||
445 | .remove = __devexit_p(ad9834_remove), | ||
446 | .id_table = ad9834_id, | ||
447 | }; | ||
448 | |||
449 | static int __init ad9834_init(void) | ||
450 | { | ||
451 | return spi_register_driver(&ad9834_driver); | ||
452 | } | ||
453 | module_init(ad9834_init); | ||
454 | |||
455 | static void __exit ad9834_exit(void) | ||
456 | { | ||
457 | spi_unregister_driver(&ad9834_driver); | ||
458 | } | ||
459 | module_exit(ad9834_exit); | ||
460 | |||
461 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
462 | MODULE_DESCRIPTION("Analog Devices AD9833/AD9834/AD9837/AD9838 DDS"); | ||
463 | MODULE_LICENSE("GPL v2"); | ||
464 | MODULE_ALIAS("spi:ad9834"); | ||
diff --git a/drivers/staging/iio/dds/ad9834.h b/drivers/staging/iio/dds/ad9834.h new file mode 100644 index 00000000000..ed5ed8d0007 --- /dev/null +++ b/drivers/staging/iio/dds/ad9834.h | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * AD9833/AD9834/AD9837/AD9838 SPI DDS driver | ||
3 | * | ||
4 | * Copyright 2010-2011 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2. | ||
7 | */ | ||
8 | #ifndef IIO_DDS_AD9834_H_ | ||
9 | #define IIO_DDS_AD9834_H_ | ||
10 | |||
11 | /* Registers */ | ||
12 | |||
13 | #define AD9834_REG_CMD (0 << 14) | ||
14 | #define AD9834_REG_FREQ0 (1 << 14) | ||
15 | #define AD9834_REG_FREQ1 (2 << 14) | ||
16 | #define AD9834_REG_PHASE0 (6 << 13) | ||
17 | #define AD9834_REG_PHASE1 (7 << 13) | ||
18 | |||
19 | /* Command Control Bits */ | ||
20 | |||
21 | #define AD9834_B28 (1 << 13) | ||
22 | #define AD9834_HLB (1 << 12) | ||
23 | #define AD9834_FSEL (1 << 11) | ||
24 | #define AD9834_PSEL (1 << 10) | ||
25 | #define AD9834_PIN_SW (1 << 9) | ||
26 | #define AD9834_RESET (1 << 8) | ||
27 | #define AD9834_SLEEP1 (1 << 7) | ||
28 | #define AD9834_SLEEP12 (1 << 6) | ||
29 | #define AD9834_OPBITEN (1 << 5) | ||
30 | #define AD9834_SIGN_PIB (1 << 4) | ||
31 | #define AD9834_DIV2 (1 << 3) | ||
32 | #define AD9834_MODE (1 << 1) | ||
33 | |||
34 | #define AD9834_FREQ_BITS 28 | ||
35 | #define AD9834_PHASE_BITS 12 | ||
36 | |||
37 | #define RES_MASK(bits) ((1 << (bits)) - 1) | ||
38 | |||
39 | /** | ||
40 | * struct ad9834_state - driver instance specific data | ||
41 | * @spi: spi_device | ||
42 | * @reg: supply regulator | ||
43 | * @mclk: external master clock | ||
44 | * @control: cached control word | ||
45 | * @xfer: default spi transfer | ||
46 | * @msg: default spi message | ||
47 | * @freq_xfer: tuning word spi transfer | ||
48 | * @freq_msg: tuning word spi message | ||
49 | * @data: spi transmit buffer | ||
50 | * @freq_data: tuning word spi transmit buffer | ||
51 | */ | ||
52 | |||
53 | struct ad9834_state { | ||
54 | struct spi_device *spi; | ||
55 | struct regulator *reg; | ||
56 | unsigned int mclk; | ||
57 | unsigned short control; | ||
58 | unsigned short devid; | ||
59 | struct spi_transfer xfer; | ||
60 | struct spi_message msg; | ||
61 | struct spi_transfer freq_xfer[2]; | ||
62 | struct spi_message freq_msg; | ||
63 | |||
64 | /* | ||
65 | * DMA (thus cache coherency maintenance) requires the | ||
66 | * transfer buffers to live in their own cache lines. | ||
67 | */ | ||
68 | unsigned short data ____cacheline_aligned; | ||
69 | unsigned short freq_data[2] ; | ||
70 | }; | ||
71 | |||
72 | |||
73 | /* | ||
74 | * TODO: struct ad7887_platform_data needs to go into include/linux/iio | ||
75 | */ | ||
76 | |||
77 | /** | ||
78 | * struct ad9834_platform_data - platform specific information | ||
79 | * @mclk: master clock in Hz | ||
80 | * @freq0: power up freq0 tuning word in Hz | ||
81 | * @freq1: power up freq1 tuning word in Hz | ||
82 | * @phase0: power up phase0 value [0..4095] correlates with 0..2PI | ||
83 | * @phase1: power up phase1 value [0..4095] correlates with 0..2PI | ||
84 | * @en_div2: digital output/2 is passed to the SIGN BIT OUT pin | ||
85 | * @en_signbit_msb_out: the MSB (or MSB/2) of the DAC data is connected to the | ||
86 | * SIGN BIT OUT pin. en_div2 controls whether it is the MSB | ||
87 | * or MSB/2 that is output. if en_signbit_msb_out=false, | ||
88 | * the on-board comparator is connected to SIGN BIT OUT | ||
89 | */ | ||
90 | |||
91 | struct ad9834_platform_data { | ||
92 | unsigned int mclk; | ||
93 | unsigned int freq0; | ||
94 | unsigned int freq1; | ||
95 | unsigned short phase0; | ||
96 | unsigned short phase1; | ||
97 | bool en_div2; | ||
98 | bool en_signbit_msb_out; | ||
99 | }; | ||
100 | |||
101 | /** | ||
102 | * ad9834_supported_device_ids: | ||
103 | */ | ||
104 | |||
105 | enum ad9834_supported_device_ids { | ||
106 | ID_AD9833, | ||
107 | ID_AD9834, | ||
108 | ID_AD9837, | ||
109 | ID_AD9838, | ||
110 | }; | ||
111 | |||
112 | #endif /* IIO_DDS_AD9834_H_ */ | ||
diff --git a/drivers/staging/iio/dds/ad9850.c b/drivers/staging/iio/dds/ad9850.c new file mode 100644 index 00000000000..d7c9d05f635 --- /dev/null +++ b/drivers/staging/iio/dds/ad9850.c | |||
@@ -0,0 +1,145 @@ | |||
1 | /* | ||
2 | * Driver for ADI Direct Digital Synthesis ad9850 | ||
3 | * | ||
4 | * Copyright (c) 2010-2010 Analog Devices Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/types.h> | ||
12 | #include <linux/mutex.h> | ||
13 | #include <linux/device.h> | ||
14 | #include <linux/spi/spi.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/sysfs.h> | ||
17 | |||
18 | #include "../iio.h" | ||
19 | #include "../sysfs.h" | ||
20 | |||
21 | #define DRV_NAME "ad9850" | ||
22 | |||
23 | #define value_mask (u16)0xf000 | ||
24 | #define addr_shift 12 | ||
25 | |||
26 | /* Register format: 4 bits addr + 12 bits value */ | ||
27 | struct ad9850_config { | ||
28 | u8 control[5]; | ||
29 | }; | ||
30 | |||
31 | struct ad9850_state { | ||
32 | struct mutex lock; | ||
33 | struct spi_device *sdev; | ||
34 | }; | ||
35 | |||
36 | static ssize_t ad9850_set_parameter(struct device *dev, | ||
37 | struct device_attribute *attr, | ||
38 | const char *buf, | ||
39 | size_t len) | ||
40 | { | ||
41 | struct spi_message msg; | ||
42 | struct spi_transfer xfer; | ||
43 | int ret; | ||
44 | struct ad9850_config *config = (struct ad9850_config *)buf; | ||
45 | struct iio_dev *idev = dev_get_drvdata(dev); | ||
46 | struct ad9850_state *st = iio_priv(idev); | ||
47 | |||
48 | xfer.len = len; | ||
49 | xfer.tx_buf = config; | ||
50 | mutex_lock(&st->lock); | ||
51 | |||
52 | spi_message_init(&msg); | ||
53 | spi_message_add_tail(&xfer, &msg); | ||
54 | ret = spi_sync(st->sdev, &msg); | ||
55 | if (ret) | ||
56 | goto error_ret; | ||
57 | error_ret: | ||
58 | mutex_unlock(&st->lock); | ||
59 | |||
60 | return ret ? ret : len; | ||
61 | } | ||
62 | |||
63 | static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9850_set_parameter, 0); | ||
64 | |||
65 | static struct attribute *ad9850_attributes[] = { | ||
66 | &iio_dev_attr_dds.dev_attr.attr, | ||
67 | NULL, | ||
68 | }; | ||
69 | |||
70 | static const struct attribute_group ad9850_attribute_group = { | ||
71 | .attrs = ad9850_attributes, | ||
72 | }; | ||
73 | |||
74 | static const struct iio_info ad9850_info = { | ||
75 | .attrs = &ad9850_attribute_group, | ||
76 | .driver_module = THIS_MODULE, | ||
77 | }; | ||
78 | |||
79 | static int __devinit ad9850_probe(struct spi_device *spi) | ||
80 | { | ||
81 | struct ad9850_state *st; | ||
82 | struct iio_dev *idev; | ||
83 | int ret = 0; | ||
84 | |||
85 | idev = iio_allocate_device(sizeof(*st)); | ||
86 | if (idev == NULL) { | ||
87 | ret = -ENOMEM; | ||
88 | goto error_ret; | ||
89 | } | ||
90 | spi_set_drvdata(spi, idev); | ||
91 | st = iio_priv(idev); | ||
92 | mutex_init(&st->lock); | ||
93 | st->sdev = spi; | ||
94 | |||
95 | idev->dev.parent = &spi->dev; | ||
96 | idev->info = &ad9850_info; | ||
97 | idev->modes = INDIO_DIRECT_MODE; | ||
98 | |||
99 | ret = iio_device_register(idev); | ||
100 | if (ret) | ||
101 | goto error_free_dev; | ||
102 | spi->max_speed_hz = 2000000; | ||
103 | spi->mode = SPI_MODE_3; | ||
104 | spi->bits_per_word = 16; | ||
105 | spi_setup(spi); | ||
106 | |||
107 | return 0; | ||
108 | |||
109 | error_free_dev: | ||
110 | iio_free_device(idev); | ||
111 | error_ret: | ||
112 | return ret; | ||
113 | } | ||
114 | |||
115 | static int __devexit ad9850_remove(struct spi_device *spi) | ||
116 | { | ||
117 | iio_device_unregister(spi_get_drvdata(spi)); | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static struct spi_driver ad9850_driver = { | ||
123 | .driver = { | ||
124 | .name = DRV_NAME, | ||
125 | .owner = THIS_MODULE, | ||
126 | }, | ||
127 | .probe = ad9850_probe, | ||
128 | .remove = __devexit_p(ad9850_remove), | ||
129 | }; | ||
130 | |||
131 | static __init int ad9850_spi_init(void) | ||
132 | { | ||
133 | return spi_register_driver(&ad9850_driver); | ||
134 | } | ||
135 | module_init(ad9850_spi_init); | ||
136 | |||
137 | static __exit void ad9850_spi_exit(void) | ||
138 | { | ||
139 | spi_unregister_driver(&ad9850_driver); | ||
140 | } | ||
141 | module_exit(ad9850_spi_exit); | ||
142 | |||
143 | MODULE_AUTHOR("Cliff Cai"); | ||
144 | MODULE_DESCRIPTION("Analog Devices ad9850 driver"); | ||
145 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/staging/iio/dds/ad9852.c b/drivers/staging/iio/dds/ad9852.c new file mode 100644 index 00000000000..0184585425d --- /dev/null +++ b/drivers/staging/iio/dds/ad9852.c | |||
@@ -0,0 +1,297 @@ | |||
1 | /* | ||
2 | * Driver for ADI Direct Digital Synthesis ad9852 | ||
3 | * | ||
4 | * Copyright (c) 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/types.h> | ||
12 | #include <linux/mutex.h> | ||
13 | #include <linux/device.h> | ||
14 | #include <linux/spi/spi.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/sysfs.h> | ||
17 | |||
18 | #include "../iio.h" | ||
19 | #include "../sysfs.h" | ||
20 | |||
21 | #define DRV_NAME "ad9852" | ||
22 | |||
23 | #define addr_phaad1 0x0 | ||
24 | #define addr_phaad2 0x1 | ||
25 | #define addr_fretu1 0x2 | ||
26 | #define addr_fretu2 0x3 | ||
27 | #define addr_delfre 0x4 | ||
28 | #define addr_updclk 0x5 | ||
29 | #define addr_ramclk 0x6 | ||
30 | #define addr_contrl 0x7 | ||
31 | #define addr_optskm 0x8 | ||
32 | #define addr_optskr 0xa | ||
33 | #define addr_dacctl 0xb | ||
34 | |||
35 | #define COMPPD (1 << 4) | ||
36 | #define REFMULT2 (1 << 2) | ||
37 | #define BYPPLL (1 << 5) | ||
38 | #define PLLRANG (1 << 6) | ||
39 | #define IEUPCLK (1) | ||
40 | #define OSKEN (1 << 5) | ||
41 | |||
42 | #define read_bit (1 << 7) | ||
43 | |||
44 | /* Register format: 1 byte addr + value */ | ||
45 | struct ad9852_config { | ||
46 | u8 phajst0[3]; | ||
47 | u8 phajst1[3]; | ||
48 | u8 fretun1[6]; | ||
49 | u8 fretun2[6]; | ||
50 | u8 dltafre[6]; | ||
51 | u8 updtclk[5]; | ||
52 | u8 ramprat[4]; | ||
53 | u8 control[5]; | ||
54 | u8 outpskm[3]; | ||
55 | u8 outpskr[2]; | ||
56 | u8 daccntl[3]; | ||
57 | }; | ||
58 | |||
59 | struct ad9852_state { | ||
60 | struct mutex lock; | ||
61 | struct spi_device *sdev; | ||
62 | }; | ||
63 | |||
64 | static ssize_t ad9852_set_parameter(struct device *dev, | ||
65 | struct device_attribute *attr, | ||
66 | const char *buf, | ||
67 | size_t len) | ||
68 | { | ||
69 | struct spi_message msg; | ||
70 | struct spi_transfer xfer; | ||
71 | int ret; | ||
72 | struct ad9852_config *config = (struct ad9852_config *)buf; | ||
73 | struct iio_dev *idev = dev_get_drvdata(dev); | ||
74 | struct ad9852_state *st = iio_priv(idev); | ||
75 | |||
76 | xfer.len = 3; | ||
77 | xfer.tx_buf = &config->phajst0[0]; | ||
78 | mutex_lock(&st->lock); | ||
79 | |||
80 | spi_message_init(&msg); | ||
81 | spi_message_add_tail(&xfer, &msg); | ||
82 | ret = spi_sync(st->sdev, &msg); | ||
83 | if (ret) | ||
84 | goto error_ret; | ||
85 | |||
86 | xfer.len = 3; | ||
87 | xfer.tx_buf = &config->phajst1[0]; | ||
88 | |||
89 | spi_message_init(&msg); | ||
90 | spi_message_add_tail(&xfer, &msg); | ||
91 | ret = spi_sync(st->sdev, &msg); | ||
92 | if (ret) | ||
93 | goto error_ret; | ||
94 | |||
95 | xfer.len = 6; | ||
96 | xfer.tx_buf = &config->fretun1[0]; | ||
97 | |||
98 | spi_message_init(&msg); | ||
99 | spi_message_add_tail(&xfer, &msg); | ||
100 | ret = spi_sync(st->sdev, &msg); | ||
101 | if (ret) | ||
102 | goto error_ret; | ||
103 | |||
104 | xfer.len = 6; | ||
105 | xfer.tx_buf = &config->fretun2[0]; | ||
106 | |||
107 | spi_message_init(&msg); | ||
108 | spi_message_add_tail(&xfer, &msg); | ||
109 | ret = spi_sync(st->sdev, &msg); | ||
110 | if (ret) | ||
111 | goto error_ret; | ||
112 | |||
113 | xfer.len = 6; | ||
114 | xfer.tx_buf = &config->dltafre[0]; | ||
115 | |||
116 | spi_message_init(&msg); | ||
117 | spi_message_add_tail(&xfer, &msg); | ||
118 | ret = spi_sync(st->sdev, &msg); | ||
119 | if (ret) | ||
120 | goto error_ret; | ||
121 | |||
122 | xfer.len = 5; | ||
123 | xfer.tx_buf = &config->updtclk[0]; | ||
124 | |||
125 | spi_message_init(&msg); | ||
126 | spi_message_add_tail(&xfer, &msg); | ||
127 | ret = spi_sync(st->sdev, &msg); | ||
128 | if (ret) | ||
129 | goto error_ret; | ||
130 | |||
131 | xfer.len = 4; | ||
132 | xfer.tx_buf = &config->ramprat[0]; | ||
133 | |||
134 | spi_message_init(&msg); | ||
135 | spi_message_add_tail(&xfer, &msg); | ||
136 | ret = spi_sync(st->sdev, &msg); | ||
137 | if (ret) | ||
138 | goto error_ret; | ||
139 | |||
140 | xfer.len = 5; | ||
141 | xfer.tx_buf = &config->control[0]; | ||
142 | |||
143 | spi_message_init(&msg); | ||
144 | spi_message_add_tail(&xfer, &msg); | ||
145 | ret = spi_sync(st->sdev, &msg); | ||
146 | if (ret) | ||
147 | goto error_ret; | ||
148 | |||
149 | xfer.len = 3; | ||
150 | xfer.tx_buf = &config->outpskm[0]; | ||
151 | |||
152 | spi_message_init(&msg); | ||
153 | spi_message_add_tail(&xfer, &msg); | ||
154 | ret = spi_sync(st->sdev, &msg); | ||
155 | if (ret) | ||
156 | goto error_ret; | ||
157 | |||
158 | xfer.len = 2; | ||
159 | xfer.tx_buf = &config->outpskr[0]; | ||
160 | |||
161 | spi_message_init(&msg); | ||
162 | spi_message_add_tail(&xfer, &msg); | ||
163 | ret = spi_sync(st->sdev, &msg); | ||
164 | if (ret) | ||
165 | goto error_ret; | ||
166 | |||
167 | xfer.len = 3; | ||
168 | xfer.tx_buf = &config->daccntl[0]; | ||
169 | |||
170 | spi_message_init(&msg); | ||
171 | spi_message_add_tail(&xfer, &msg); | ||
172 | ret = spi_sync(st->sdev, &msg); | ||
173 | if (ret) | ||
174 | goto error_ret; | ||
175 | error_ret: | ||
176 | mutex_unlock(&st->lock); | ||
177 | |||
178 | return ret ? ret : len; | ||
179 | } | ||
180 | |||
181 | static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9852_set_parameter, 0); | ||
182 | |||
183 | static void ad9852_init(struct ad9852_state *st) | ||
184 | { | ||
185 | struct spi_message msg; | ||
186 | struct spi_transfer xfer; | ||
187 | int ret; | ||
188 | u8 config[5]; | ||
189 | |||
190 | config[0] = addr_contrl; | ||
191 | config[1] = COMPPD; | ||
192 | config[2] = REFMULT2 | BYPPLL | PLLRANG; | ||
193 | config[3] = IEUPCLK; | ||
194 | config[4] = OSKEN; | ||
195 | |||
196 | mutex_lock(&st->lock); | ||
197 | |||
198 | xfer.len = 5; | ||
199 | xfer.tx_buf = &config; | ||
200 | |||
201 | spi_message_init(&msg); | ||
202 | spi_message_add_tail(&xfer, &msg); | ||
203 | ret = spi_sync(st->sdev, &msg); | ||
204 | if (ret) | ||
205 | goto error_ret; | ||
206 | |||
207 | error_ret: | ||
208 | mutex_unlock(&st->lock); | ||
209 | |||
210 | |||
211 | |||
212 | } | ||
213 | |||
214 | static struct attribute *ad9852_attributes[] = { | ||
215 | &iio_dev_attr_dds.dev_attr.attr, | ||
216 | NULL, | ||
217 | }; | ||
218 | |||
219 | static const struct attribute_group ad9852_attribute_group = { | ||
220 | .name = DRV_NAME, | ||
221 | .attrs = ad9852_attributes, | ||
222 | }; | ||
223 | |||
224 | static const struct iio_info ad9852_info = { | ||
225 | .attrs = &ad9852_attribute_group, | ||
226 | .driver_module = THIS_MODULE, | ||
227 | }; | ||
228 | |||
229 | static int __devinit ad9852_probe(struct spi_device *spi) | ||
230 | { | ||
231 | struct ad9852_state *st; | ||
232 | struct iio_dev *idev; | ||
233 | int ret = 0; | ||
234 | |||
235 | idev = iio_allocate_device(sizeof(*st)); | ||
236 | if (idev == NULL) { | ||
237 | ret = -ENOMEM; | ||
238 | goto error_ret; | ||
239 | } | ||
240 | st = iio_priv(idev); | ||
241 | spi_set_drvdata(spi, idev); | ||
242 | mutex_init(&st->lock); | ||
243 | st->sdev = spi; | ||
244 | |||
245 | idev->dev.parent = &spi->dev; | ||
246 | idev->info = &ad9852_info; | ||
247 | idev->modes = INDIO_DIRECT_MODE; | ||
248 | |||
249 | ret = iio_device_register(idev); | ||
250 | if (ret) | ||
251 | goto error_free_dev; | ||
252 | spi->max_speed_hz = 2000000; | ||
253 | spi->mode = SPI_MODE_3; | ||
254 | spi->bits_per_word = 8; | ||
255 | spi_setup(spi); | ||
256 | ad9852_init(st); | ||
257 | |||
258 | return 0; | ||
259 | |||
260 | error_free_dev: | ||
261 | iio_free_device(idev); | ||
262 | |||
263 | error_ret: | ||
264 | return ret; | ||
265 | } | ||
266 | |||
267 | static int __devexit ad9852_remove(struct spi_device *spi) | ||
268 | { | ||
269 | iio_device_unregister(spi_get_drvdata(spi)); | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static struct spi_driver ad9852_driver = { | ||
275 | .driver = { | ||
276 | .name = DRV_NAME, | ||
277 | .owner = THIS_MODULE, | ||
278 | }, | ||
279 | .probe = ad9852_probe, | ||
280 | .remove = __devexit_p(ad9852_remove), | ||
281 | }; | ||
282 | |||
283 | static __init int ad9852_spi_init(void) | ||
284 | { | ||
285 | return spi_register_driver(&ad9852_driver); | ||
286 | } | ||
287 | module_init(ad9852_spi_init); | ||
288 | |||
289 | static __exit void ad9852_spi_exit(void) | ||
290 | { | ||
291 | spi_unregister_driver(&ad9852_driver); | ||
292 | } | ||
293 | module_exit(ad9852_spi_exit); | ||
294 | |||
295 | MODULE_AUTHOR("Cliff Cai"); | ||
296 | MODULE_DESCRIPTION("Analog Devices ad9852 driver"); | ||
297 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/staging/iio/dds/ad9910.c b/drivers/staging/iio/dds/ad9910.c new file mode 100644 index 00000000000..0fa217f7b90 --- /dev/null +++ b/drivers/staging/iio/dds/ad9910.c | |||
@@ -0,0 +1,430 @@ | |||
1 | /* | ||
2 | * Driver for ADI Direct Digital Synthesis ad9910 | ||
3 | * | ||
4 | * Copyright (c) 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/types.h> | ||
12 | #include <linux/mutex.h> | ||
13 | #include <linux/device.h> | ||
14 | #include <linux/spi/spi.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/sysfs.h> | ||
17 | |||
18 | #include "../iio.h" | ||
19 | #include "../sysfs.h" | ||
20 | |||
21 | #define DRV_NAME "ad9910" | ||
22 | |||
23 | #define CFR1 0x0 | ||
24 | #define CFR2 0x1 | ||
25 | #define CFR3 0x2 | ||
26 | |||
27 | #define AUXDAC 0x3 | ||
28 | #define IOUPD 0x4 | ||
29 | #define FTW 0x7 | ||
30 | #define POW 0x8 | ||
31 | #define ASF 0x9 | ||
32 | #define MULTC 0x0A | ||
33 | #define DIG_RAMPL 0x0B | ||
34 | #define DIG_RAMPS 0x0C | ||
35 | #define DIG_RAMPR 0x0D | ||
36 | #define SIN_TONEP0 0x0E | ||
37 | #define SIN_TONEP1 0x0F | ||
38 | #define SIN_TONEP2 0x10 | ||
39 | #define SIN_TONEP3 0x11 | ||
40 | #define SIN_TONEP4 0x12 | ||
41 | #define SIN_TONEP5 0x13 | ||
42 | #define SIN_TONEP6 0x14 | ||
43 | #define SIN_TONEP7 0x15 | ||
44 | |||
45 | #define RAM_ENABLE (1 << 7) | ||
46 | |||
47 | #define MANUAL_OSK (1 << 7) | ||
48 | #define INVSIC (1 << 6) | ||
49 | #define DDS_SINEOP (1) | ||
50 | |||
51 | #define AUTO_OSK (1) | ||
52 | #define OSKEN (1 << 1) | ||
53 | #define LOAD_ARR (1 << 2) | ||
54 | #define CLR_PHA (1 << 3) | ||
55 | #define CLR_DIG (1 << 4) | ||
56 | #define ACLR_PHA (1 << 5) | ||
57 | #define ACLR_DIG (1 << 6) | ||
58 | #define LOAD_LRR (1 << 7) | ||
59 | |||
60 | #define LSB_FST (1) | ||
61 | #define SDIO_IPT (1 << 1) | ||
62 | #define EXT_PWD (1 << 3) | ||
63 | #define ADAC_PWD (1 << 4) | ||
64 | #define REFCLK_PWD (1 << 5) | ||
65 | #define DAC_PWD (1 << 6) | ||
66 | #define DIG_PWD (1 << 7) | ||
67 | |||
68 | #define ENA_AMP (1) | ||
69 | #define READ_FTW (1) | ||
70 | #define DIGR_LOW (1 << 1) | ||
71 | #define DIGR_HIGH (1 << 2) | ||
72 | #define DIGR_ENA (1 << 3) | ||
73 | #define SYNCCLK_ENA (1 << 6) | ||
74 | #define ITER_IOUPD (1 << 7) | ||
75 | |||
76 | #define TX_ENA (1 << 1) | ||
77 | #define PDCLK_INV (1 << 2) | ||
78 | #define PDCLK_ENB (1 << 3) | ||
79 | |||
80 | #define PARA_ENA (1 << 4) | ||
81 | #define SYNC_DIS (1 << 5) | ||
82 | #define DATA_ASS (1 << 6) | ||
83 | #define MATCH_ENA (1 << 7) | ||
84 | |||
85 | #define PLL_ENA (1) | ||
86 | #define PFD_RST (1 << 2) | ||
87 | #define REFCLK_RST (1 << 6) | ||
88 | #define REFCLK_BYP (1 << 7) | ||
89 | |||
90 | /* Register format: 1 byte addr + value */ | ||
91 | struct ad9910_config { | ||
92 | u8 auxdac[5]; | ||
93 | u8 ioupd[5]; | ||
94 | u8 ftw[5]; | ||
95 | u8 pow[3]; | ||
96 | u8 asf[5]; | ||
97 | u8 multc[5]; | ||
98 | u8 dig_rampl[9]; | ||
99 | u8 dig_ramps[9]; | ||
100 | u8 dig_rampr[5]; | ||
101 | u8 sin_tonep0[9]; | ||
102 | u8 sin_tonep1[9]; | ||
103 | u8 sin_tonep2[9]; | ||
104 | u8 sin_tonep3[9]; | ||
105 | u8 sin_tonep4[9]; | ||
106 | u8 sin_tonep5[9]; | ||
107 | u8 sin_tonep6[9]; | ||
108 | u8 sin_tonep7[9]; | ||
109 | }; | ||
110 | |||
111 | struct ad9910_state { | ||
112 | struct mutex lock; | ||
113 | struct spi_device *sdev; | ||
114 | }; | ||
115 | |||
116 | static ssize_t ad9910_set_parameter(struct device *dev, | ||
117 | struct device_attribute *attr, | ||
118 | const char *buf, | ||
119 | size_t len) | ||
120 | { | ||
121 | struct spi_message msg; | ||
122 | struct spi_transfer xfer; | ||
123 | int ret; | ||
124 | struct ad9910_config *config = (struct ad9910_config *)buf; | ||
125 | struct iio_dev *idev = dev_get_drvdata(dev); | ||
126 | struct ad9910_state *st = iio_priv(idev); | ||
127 | |||
128 | xfer.len = 5; | ||
129 | xfer.tx_buf = &config->auxdac[0]; | ||
130 | mutex_lock(&st->lock); | ||
131 | |||
132 | spi_message_init(&msg); | ||
133 | spi_message_add_tail(&xfer, &msg); | ||
134 | ret = spi_sync(st->sdev, &msg); | ||
135 | if (ret) | ||
136 | goto error_ret; | ||
137 | |||
138 | xfer.len = 5; | ||
139 | xfer.tx_buf = &config->ioupd[0]; | ||
140 | |||
141 | spi_message_init(&msg); | ||
142 | spi_message_add_tail(&xfer, &msg); | ||
143 | ret = spi_sync(st->sdev, &msg); | ||
144 | if (ret) | ||
145 | goto error_ret; | ||
146 | |||
147 | xfer.len = 5; | ||
148 | xfer.tx_buf = &config->ftw[0]; | ||
149 | |||
150 | spi_message_init(&msg); | ||
151 | spi_message_add_tail(&xfer, &msg); | ||
152 | ret = spi_sync(st->sdev, &msg); | ||
153 | if (ret) | ||
154 | goto error_ret; | ||
155 | |||
156 | xfer.len = 3; | ||
157 | xfer.tx_buf = &config->pow[0]; | ||
158 | |||
159 | spi_message_init(&msg); | ||
160 | spi_message_add_tail(&xfer, &msg); | ||
161 | ret = spi_sync(st->sdev, &msg); | ||
162 | if (ret) | ||
163 | goto error_ret; | ||
164 | |||
165 | xfer.len = 5; | ||
166 | xfer.tx_buf = &config->asf[0]; | ||
167 | |||
168 | spi_message_init(&msg); | ||
169 | spi_message_add_tail(&xfer, &msg); | ||
170 | ret = spi_sync(st->sdev, &msg); | ||
171 | if (ret) | ||
172 | goto error_ret; | ||
173 | |||
174 | xfer.len = 5; | ||
175 | xfer.tx_buf = &config->multc[0]; | ||
176 | |||
177 | spi_message_init(&msg); | ||
178 | spi_message_add_tail(&xfer, &msg); | ||
179 | ret = spi_sync(st->sdev, &msg); | ||
180 | if (ret) | ||
181 | goto error_ret; | ||
182 | |||
183 | xfer.len = 9; | ||
184 | xfer.tx_buf = &config->dig_rampl[0]; | ||
185 | |||
186 | spi_message_init(&msg); | ||
187 | spi_message_add_tail(&xfer, &msg); | ||
188 | ret = spi_sync(st->sdev, &msg); | ||
189 | if (ret) | ||
190 | goto error_ret; | ||
191 | |||
192 | xfer.len = 9; | ||
193 | xfer.tx_buf = &config->dig_ramps[0]; | ||
194 | |||
195 | spi_message_init(&msg); | ||
196 | spi_message_add_tail(&xfer, &msg); | ||
197 | ret = spi_sync(st->sdev, &msg); | ||
198 | if (ret) | ||
199 | goto error_ret; | ||
200 | |||
201 | xfer.len = 5; | ||
202 | xfer.tx_buf = &config->dig_rampr[0]; | ||
203 | |||
204 | spi_message_init(&msg); | ||
205 | spi_message_add_tail(&xfer, &msg); | ||
206 | ret = spi_sync(st->sdev, &msg); | ||
207 | if (ret) | ||
208 | goto error_ret; | ||
209 | |||
210 | xfer.len = 9; | ||
211 | xfer.tx_buf = &config->sin_tonep0[0]; | ||
212 | |||
213 | spi_message_init(&msg); | ||
214 | spi_message_add_tail(&xfer, &msg); | ||
215 | ret = spi_sync(st->sdev, &msg); | ||
216 | if (ret) | ||
217 | goto error_ret; | ||
218 | |||
219 | xfer.len = 9; | ||
220 | xfer.tx_buf = &config->sin_tonep1[0]; | ||
221 | |||
222 | spi_message_init(&msg); | ||
223 | spi_message_add_tail(&xfer, &msg); | ||
224 | ret = spi_sync(st->sdev, &msg); | ||
225 | if (ret) | ||
226 | goto error_ret; | ||
227 | |||
228 | xfer.len = 9; | ||
229 | xfer.tx_buf = &config->sin_tonep2[0]; | ||
230 | |||
231 | spi_message_init(&msg); | ||
232 | spi_message_add_tail(&xfer, &msg); | ||
233 | ret = spi_sync(st->sdev, &msg); | ||
234 | if (ret) | ||
235 | goto error_ret; | ||
236 | xfer.len = 9; | ||
237 | xfer.tx_buf = &config->sin_tonep3[0]; | ||
238 | |||
239 | spi_message_init(&msg); | ||
240 | spi_message_add_tail(&xfer, &msg); | ||
241 | ret = spi_sync(st->sdev, &msg); | ||
242 | if (ret) | ||
243 | goto error_ret; | ||
244 | |||
245 | xfer.len = 9; | ||
246 | xfer.tx_buf = &config->sin_tonep4[0]; | ||
247 | |||
248 | spi_message_init(&msg); | ||
249 | spi_message_add_tail(&xfer, &msg); | ||
250 | ret = spi_sync(st->sdev, &msg); | ||
251 | if (ret) | ||
252 | goto error_ret; | ||
253 | |||
254 | xfer.len = 9; | ||
255 | xfer.tx_buf = &config->sin_tonep5[0]; | ||
256 | |||
257 | spi_message_init(&msg); | ||
258 | spi_message_add_tail(&xfer, &msg); | ||
259 | ret = spi_sync(st->sdev, &msg); | ||
260 | if (ret) | ||
261 | goto error_ret; | ||
262 | |||
263 | xfer.len = 9; | ||
264 | xfer.tx_buf = &config->sin_tonep6[0]; | ||
265 | |||
266 | spi_message_init(&msg); | ||
267 | spi_message_add_tail(&xfer, &msg); | ||
268 | ret = spi_sync(st->sdev, &msg); | ||
269 | if (ret) | ||
270 | goto error_ret; | ||
271 | |||
272 | xfer.len = 9; | ||
273 | xfer.tx_buf = &config->sin_tonep7[0]; | ||
274 | |||
275 | spi_message_init(&msg); | ||
276 | spi_message_add_tail(&xfer, &msg); | ||
277 | ret = spi_sync(st->sdev, &msg); | ||
278 | if (ret) | ||
279 | goto error_ret; | ||
280 | error_ret: | ||
281 | mutex_unlock(&st->lock); | ||
282 | |||
283 | return ret ? ret : len; | ||
284 | } | ||
285 | |||
286 | static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9910_set_parameter, 0); | ||
287 | |||
288 | static void ad9910_init(struct ad9910_state *st) | ||
289 | { | ||
290 | struct spi_message msg; | ||
291 | struct spi_transfer xfer; | ||
292 | int ret; | ||
293 | u8 cfr[5]; | ||
294 | |||
295 | cfr[0] = CFR1; | ||
296 | cfr[1] = 0; | ||
297 | cfr[2] = MANUAL_OSK | INVSIC | DDS_SINEOP; | ||
298 | cfr[3] = AUTO_OSK | OSKEN | ACLR_PHA | ACLR_DIG | LOAD_LRR; | ||
299 | cfr[4] = 0; | ||
300 | |||
301 | mutex_lock(&st->lock); | ||
302 | |||
303 | xfer.len = 5; | ||
304 | xfer.tx_buf = 𝔠 | ||
305 | |||
306 | spi_message_init(&msg); | ||
307 | spi_message_add_tail(&xfer, &msg); | ||
308 | ret = spi_sync(st->sdev, &msg); | ||
309 | if (ret) | ||
310 | goto error_ret; | ||
311 | |||
312 | cfr[0] = CFR2; | ||
313 | cfr[1] = ENA_AMP; | ||
314 | cfr[2] = READ_FTW | DIGR_ENA | ITER_IOUPD; | ||
315 | cfr[3] = TX_ENA | PDCLK_INV | PDCLK_ENB; | ||
316 | cfr[4] = PARA_ENA; | ||
317 | |||
318 | xfer.len = 5; | ||
319 | xfer.tx_buf = 𝔠 | ||
320 | |||
321 | spi_message_init(&msg); | ||
322 | spi_message_add_tail(&xfer, &msg); | ||
323 | ret = spi_sync(st->sdev, &msg); | ||
324 | if (ret) | ||
325 | goto error_ret; | ||
326 | |||
327 | cfr[0] = CFR3; | ||
328 | cfr[1] = PLL_ENA; | ||
329 | cfr[2] = 0; | ||
330 | cfr[3] = REFCLK_RST | REFCLK_BYP; | ||
331 | cfr[4] = 0; | ||
332 | |||
333 | xfer.len = 5; | ||
334 | xfer.tx_buf = 𝔠 | ||
335 | |||
336 | spi_message_init(&msg); | ||
337 | spi_message_add_tail(&xfer, &msg); | ||
338 | ret = spi_sync(st->sdev, &msg); | ||
339 | if (ret) | ||
340 | goto error_ret; | ||
341 | |||
342 | error_ret: | ||
343 | mutex_unlock(&st->lock); | ||
344 | |||
345 | |||
346 | |||
347 | } | ||
348 | |||
349 | static struct attribute *ad9910_attributes[] = { | ||
350 | &iio_dev_attr_dds.dev_attr.attr, | ||
351 | NULL, | ||
352 | }; | ||
353 | |||
354 | static const struct attribute_group ad9910_attribute_group = { | ||
355 | .name = DRV_NAME, | ||
356 | .attrs = ad9910_attributes, | ||
357 | }; | ||
358 | |||
359 | static const struct iio_info ad9910_info = { | ||
360 | .attrs = &ad9910_attribute_group, | ||
361 | .driver_module = THIS_MODULE, | ||
362 | }; | ||
363 | |||
364 | static int __devinit ad9910_probe(struct spi_device *spi) | ||
365 | { | ||
366 | struct ad9910_state *st; | ||
367 | struct iio_dev *idev; | ||
368 | int ret = 0; | ||
369 | |||
370 | idev = iio_allocate_device(sizeof(*st)); | ||
371 | if (idev == NULL) { | ||
372 | ret = -ENOMEM; | ||
373 | goto error_ret; | ||
374 | } | ||
375 | spi_set_drvdata(spi, idev); | ||
376 | st = iio_priv(idev); | ||
377 | mutex_init(&st->lock); | ||
378 | st->sdev = spi; | ||
379 | |||
380 | idev->dev.parent = &spi->dev; | ||
381 | idev->info = &ad9910_info; | ||
382 | idev->modes = INDIO_DIRECT_MODE; | ||
383 | |||
384 | ret = iio_device_register(idev); | ||
385 | if (ret) | ||
386 | goto error_free_dev; | ||
387 | spi->max_speed_hz = 2000000; | ||
388 | spi->mode = SPI_MODE_3; | ||
389 | spi->bits_per_word = 8; | ||
390 | spi_setup(spi); | ||
391 | ad9910_init(st); | ||
392 | return 0; | ||
393 | |||
394 | error_free_dev: | ||
395 | iio_free_device(idev); | ||
396 | error_ret: | ||
397 | return ret; | ||
398 | } | ||
399 | |||
400 | static int __devexit ad9910_remove(struct spi_device *spi) | ||
401 | { | ||
402 | iio_device_unregister(spi_get_drvdata(spi)); | ||
403 | |||
404 | return 0; | ||
405 | } | ||
406 | |||
407 | static struct spi_driver ad9910_driver = { | ||
408 | .driver = { | ||
409 | .name = DRV_NAME, | ||
410 | .owner = THIS_MODULE, | ||
411 | }, | ||
412 | .probe = ad9910_probe, | ||
413 | .remove = __devexit_p(ad9910_remove), | ||
414 | }; | ||
415 | |||
416 | static __init int ad9910_spi_init(void) | ||
417 | { | ||
418 | return spi_register_driver(&ad9910_driver); | ||
419 | } | ||
420 | module_init(ad9910_spi_init); | ||
421 | |||
422 | static __exit void ad9910_spi_exit(void) | ||
423 | { | ||
424 | spi_unregister_driver(&ad9910_driver); | ||
425 | } | ||
426 | module_exit(ad9910_spi_exit); | ||
427 | |||
428 | MODULE_AUTHOR("Cliff Cai"); | ||
429 | MODULE_DESCRIPTION("Analog Devices ad9910 driver"); | ||
430 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/staging/iio/dds/ad9951.c b/drivers/staging/iio/dds/ad9951.c new file mode 100644 index 00000000000..d361d1f125d --- /dev/null +++ b/drivers/staging/iio/dds/ad9951.c | |||
@@ -0,0 +1,241 @@ | |||
1 | /* | ||
2 | * Driver for ADI Direct Digital Synthesis ad9951 | ||
3 | * | ||
4 | * Copyright (c) 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/types.h> | ||
12 | #include <linux/mutex.h> | ||
13 | #include <linux/device.h> | ||
14 | #include <linux/spi/spi.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/sysfs.h> | ||
17 | |||
18 | #include "../iio.h" | ||
19 | #include "../sysfs.h" | ||
20 | |||
21 | #define DRV_NAME "ad9951" | ||
22 | |||
23 | #define CFR1 0x0 | ||
24 | #define CFR2 0x1 | ||
25 | |||
26 | #define AUTO_OSK (1) | ||
27 | #define OSKEN (1 << 1) | ||
28 | #define LOAD_ARR (1 << 2) | ||
29 | |||
30 | #define AUTO_SYNC (1 << 7) | ||
31 | |||
32 | #define LSB_FST (1) | ||
33 | #define SDIO_IPT (1 << 1) | ||
34 | #define CLR_PHA (1 << 2) | ||
35 | #define SINE_OPT (1 << 4) | ||
36 | #define ACLR_PHA (1 << 5) | ||
37 | |||
38 | #define VCO_RANGE (1 << 2) | ||
39 | |||
40 | #define CRS_OPT (1 << 1) | ||
41 | #define HMANU_SYNC (1 << 2) | ||
42 | #define HSPD_SYNC (1 << 3) | ||
43 | |||
44 | /* Register format: 1 byte addr + value */ | ||
45 | struct ad9951_config { | ||
46 | u8 asf[3]; | ||
47 | u8 arr[2]; | ||
48 | u8 ftw0[5]; | ||
49 | u8 ftw1[3]; | ||
50 | }; | ||
51 | |||
52 | struct ad9951_state { | ||
53 | struct mutex lock; | ||
54 | struct spi_device *sdev; | ||
55 | }; | ||
56 | |||
57 | static ssize_t ad9951_set_parameter(struct device *dev, | ||
58 | struct device_attribute *attr, | ||
59 | const char *buf, | ||
60 | size_t len) | ||
61 | { | ||
62 | struct spi_message msg; | ||
63 | struct spi_transfer xfer; | ||
64 | int ret; | ||
65 | struct ad9951_config *config = (struct ad9951_config *)buf; | ||
66 | struct iio_dev *idev = dev_get_drvdata(dev); | ||
67 | struct ad9951_state *st = iio_priv(idev); | ||
68 | |||
69 | xfer.len = 3; | ||
70 | xfer.tx_buf = &config->asf[0]; | ||
71 | mutex_lock(&st->lock); | ||
72 | |||
73 | spi_message_init(&msg); | ||
74 | spi_message_add_tail(&xfer, &msg); | ||
75 | ret = spi_sync(st->sdev, &msg); | ||
76 | if (ret) | ||
77 | goto error_ret; | ||
78 | |||
79 | xfer.len = 2; | ||
80 | xfer.tx_buf = &config->arr[0]; | ||
81 | |||
82 | spi_message_init(&msg); | ||
83 | spi_message_add_tail(&xfer, &msg); | ||
84 | ret = spi_sync(st->sdev, &msg); | ||
85 | if (ret) | ||
86 | goto error_ret; | ||
87 | |||
88 | xfer.len = 5; | ||
89 | xfer.tx_buf = &config->ftw0[0]; | ||
90 | |||
91 | spi_message_init(&msg); | ||
92 | spi_message_add_tail(&xfer, &msg); | ||
93 | ret = spi_sync(st->sdev, &msg); | ||
94 | if (ret) | ||
95 | goto error_ret; | ||
96 | |||
97 | xfer.len = 3; | ||
98 | xfer.tx_buf = &config->ftw1[0]; | ||
99 | |||
100 | spi_message_init(&msg); | ||
101 | spi_message_add_tail(&xfer, &msg); | ||
102 | ret = spi_sync(st->sdev, &msg); | ||
103 | if (ret) | ||
104 | goto error_ret; | ||
105 | error_ret: | ||
106 | mutex_unlock(&st->lock); | ||
107 | |||
108 | return ret ? ret : len; | ||
109 | } | ||
110 | |||
111 | static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9951_set_parameter, 0); | ||
112 | |||
113 | static void ad9951_init(struct ad9951_state *st) | ||
114 | { | ||
115 | struct spi_message msg; | ||
116 | struct spi_transfer xfer; | ||
117 | int ret; | ||
118 | u8 cfr[5]; | ||
119 | |||
120 | cfr[0] = CFR1; | ||
121 | cfr[1] = 0; | ||
122 | cfr[2] = LSB_FST | CLR_PHA | SINE_OPT | ACLR_PHA; | ||
123 | cfr[3] = AUTO_OSK | OSKEN | LOAD_ARR; | ||
124 | cfr[4] = 0; | ||
125 | |||
126 | mutex_lock(&st->lock); | ||
127 | |||
128 | xfer.len = 5; | ||
129 | xfer.tx_buf = 𝔠 | ||
130 | |||
131 | spi_message_init(&msg); | ||
132 | spi_message_add_tail(&xfer, &msg); | ||
133 | ret = spi_sync(st->sdev, &msg); | ||
134 | if (ret) | ||
135 | goto error_ret; | ||
136 | |||
137 | cfr[0] = CFR2; | ||
138 | cfr[1] = VCO_RANGE; | ||
139 | cfr[2] = HSPD_SYNC; | ||
140 | cfr[3] = 0; | ||
141 | |||
142 | xfer.len = 4; | ||
143 | xfer.tx_buf = 𝔠 | ||
144 | |||
145 | spi_message_init(&msg); | ||
146 | spi_message_add_tail(&xfer, &msg); | ||
147 | ret = spi_sync(st->sdev, &msg); | ||
148 | if (ret) | ||
149 | goto error_ret; | ||
150 | |||
151 | error_ret: | ||
152 | mutex_unlock(&st->lock); | ||
153 | |||
154 | |||
155 | |||
156 | } | ||
157 | |||
158 | static struct attribute *ad9951_attributes[] = { | ||
159 | &iio_dev_attr_dds.dev_attr.attr, | ||
160 | NULL, | ||
161 | }; | ||
162 | |||
163 | static const struct attribute_group ad9951_attribute_group = { | ||
164 | .name = DRV_NAME, | ||
165 | .attrs = ad9951_attributes, | ||
166 | }; | ||
167 | |||
168 | static const struct iio_info ad9951_info = { | ||
169 | .attrs = &ad9951_attribute_group, | ||
170 | .driver_module = THIS_MODULE, | ||
171 | }; | ||
172 | |||
173 | static int __devinit ad9951_probe(struct spi_device *spi) | ||
174 | { | ||
175 | struct ad9951_state *st; | ||
176 | struct iio_dev *idev; | ||
177 | int ret = 0; | ||
178 | |||
179 | idev = iio_allocate_device(sizeof(*st)); | ||
180 | if (idev == NULL) { | ||
181 | ret = -ENOMEM; | ||
182 | goto error_ret; | ||
183 | } | ||
184 | spi_set_drvdata(spi, idev); | ||
185 | st = iio_priv(idev); | ||
186 | mutex_init(&st->lock); | ||
187 | st->sdev = spi; | ||
188 | |||
189 | idev->dev.parent = &spi->dev; | ||
190 | |||
191 | idev->info = &ad9951_info; | ||
192 | idev->modes = INDIO_DIRECT_MODE; | ||
193 | |||
194 | ret = iio_device_register(idev); | ||
195 | if (ret) | ||
196 | goto error_free_dev; | ||
197 | spi->max_speed_hz = 2000000; | ||
198 | spi->mode = SPI_MODE_3; | ||
199 | spi->bits_per_word = 8; | ||
200 | spi_setup(spi); | ||
201 | ad9951_init(st); | ||
202 | return 0; | ||
203 | |||
204 | error_free_dev: | ||
205 | iio_free_device(idev); | ||
206 | |||
207 | error_ret: | ||
208 | return ret; | ||
209 | } | ||
210 | |||
211 | static int __devexit ad9951_remove(struct spi_device *spi) | ||
212 | { | ||
213 | iio_device_unregister(spi_get_drvdata(spi)); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static struct spi_driver ad9951_driver = { | ||
219 | .driver = { | ||
220 | .name = DRV_NAME, | ||
221 | .owner = THIS_MODULE, | ||
222 | }, | ||
223 | .probe = ad9951_probe, | ||
224 | .remove = __devexit_p(ad9951_remove), | ||
225 | }; | ||
226 | |||
227 | static __init int ad9951_spi_init(void) | ||
228 | { | ||
229 | return spi_register_driver(&ad9951_driver); | ||
230 | } | ||
231 | module_init(ad9951_spi_init); | ||
232 | |||
233 | static __exit void ad9951_spi_exit(void) | ||
234 | { | ||
235 | spi_unregister_driver(&ad9951_driver); | ||
236 | } | ||
237 | module_exit(ad9951_spi_exit); | ||
238 | |||
239 | MODULE_AUTHOR("Cliff Cai"); | ||
240 | MODULE_DESCRIPTION("Analog Devices ad9951 driver"); | ||
241 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/staging/iio/dds/dds.h b/drivers/staging/iio/dds/dds.h new file mode 100644 index 00000000000..d8ac3a93baf --- /dev/null +++ b/drivers/staging/iio/dds/dds.h | |||
@@ -0,0 +1,110 @@ | |||
1 | /* | ||
2 | * dds.h - sysfs attributes associated with DDS devices | ||
3 | * | ||
4 | * Copyright (c) 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | /** | ||
10 | * /sys/bus/iio/devices/.../ddsX_freqY | ||
11 | */ | ||
12 | |||
13 | #define IIO_DEV_ATTR_FREQ(_channel, _num, _mode, _show, _store, _addr) \ | ||
14 | IIO_DEVICE_ATTR(dds##_channel##_freq##_num, \ | ||
15 | _mode, _show, _store, _addr) | ||
16 | |||
17 | /** | ||
18 | * /sys/bus/iio/devices/.../ddsX_freqY_scale | ||
19 | */ | ||
20 | |||
21 | #define IIO_CONST_ATTR_FREQ_SCALE(_channel, _string) \ | ||
22 | IIO_CONST_ATTR(dds##_channel##_freq_scale, _string) | ||
23 | |||
24 | /** | ||
25 | * /sys/bus/iio/devices/.../ddsX_freqsymbol | ||
26 | */ | ||
27 | |||
28 | #define IIO_DEV_ATTR_FREQSYMBOL(_channel, _mode, _show, _store, _addr) \ | ||
29 | IIO_DEVICE_ATTR(dds##_channel##_freqsymbol, \ | ||
30 | _mode, _show, _store, _addr); | ||
31 | |||
32 | /** | ||
33 | * /sys/bus/iio/devices/.../ddsX_phaseY | ||
34 | */ | ||
35 | |||
36 | #define IIO_DEV_ATTR_PHASE(_channel, _num, _mode, _show, _store, _addr) \ | ||
37 | IIO_DEVICE_ATTR(dds##_channel##_phase##_num, \ | ||
38 | _mode, _show, _store, _addr) | ||
39 | |||
40 | /** | ||
41 | * /sys/bus/iio/devices/.../ddsX_phaseY_scale | ||
42 | */ | ||
43 | |||
44 | #define IIO_CONST_ATTR_PHASE_SCALE(_channel, _string) \ | ||
45 | IIO_CONST_ATTR(dds##_channel##_phase_scale, _string) | ||
46 | |||
47 | /** | ||
48 | * /sys/bus/iio/devices/.../ddsX_phasesymbol | ||
49 | */ | ||
50 | |||
51 | #define IIO_DEV_ATTR_PHASESYMBOL(_channel, _mode, _show, _store, _addr) \ | ||
52 | IIO_DEVICE_ATTR(dds##_channel##_phasesymbol, \ | ||
53 | _mode, _show, _store, _addr); | ||
54 | |||
55 | /** | ||
56 | * /sys/bus/iio/devices/.../ddsX_pincontrol_en | ||
57 | */ | ||
58 | |||
59 | #define IIO_DEV_ATTR_PINCONTROL_EN(_channel, _mode, _show, _store, _addr)\ | ||
60 | IIO_DEVICE_ATTR(dds##_channel##_pincontrol_en, \ | ||
61 | _mode, _show, _store, _addr); | ||
62 | |||
63 | /** | ||
64 | * /sys/bus/iio/devices/.../ddsX_pincontrol_freq_en | ||
65 | */ | ||
66 | |||
67 | #define IIO_DEV_ATTR_PINCONTROL_FREQ_EN(_channel, _mode, _show, _store, _addr)\ | ||
68 | IIO_DEVICE_ATTR(dds##_channel##_pincontrol_freq_en, \ | ||
69 | _mode, _show, _store, _addr); | ||
70 | |||
71 | /** | ||
72 | * /sys/bus/iio/devices/.../ddsX_pincontrol_phase_en | ||
73 | */ | ||
74 | |||
75 | #define IIO_DEV_ATTR_PINCONTROL_PHASE_EN(_channel, _mode, _show, _store, _addr)\ | ||
76 | IIO_DEVICE_ATTR(dds##_channel##_pincontrol_phase_en, \ | ||
77 | _mode, _show, _store, _addr); | ||
78 | |||
79 | /** | ||
80 | * /sys/bus/iio/devices/.../ddsX_out_enable | ||
81 | */ | ||
82 | |||
83 | #define IIO_DEV_ATTR_OUT_ENABLE(_channel, _mode, _show, _store, _addr) \ | ||
84 | IIO_DEVICE_ATTR(dds##_channel##_out_enable, \ | ||
85 | _mode, _show, _store, _addr); | ||
86 | |||
87 | /** | ||
88 | * /sys/bus/iio/devices/.../ddsX_outY_enable | ||
89 | */ | ||
90 | |||
91 | #define IIO_DEV_ATTR_OUTY_ENABLE(_channel, _output, \ | ||
92 | _mode, _show, _store, _addr) \ | ||
93 | IIO_DEVICE_ATTR(dds##_channel##_out##_output##_enable, \ | ||
94 | _mode, _show, _store, _addr); | ||
95 | |||
96 | /** | ||
97 | * /sys/bus/iio/devices/.../ddsX_outY_wavetype | ||
98 | */ | ||
99 | |||
100 | #define IIO_DEV_ATTR_OUT_WAVETYPE(_channel, _output, _store, _addr) \ | ||
101 | IIO_DEVICE_ATTR(dds##_channel##_out##_output##_wavetype, \ | ||
102 | S_IWUSR, NULL, _store, _addr); | ||
103 | |||
104 | /** | ||
105 | * /sys/bus/iio/devices/.../ddsX_outY_wavetype_available | ||
106 | */ | ||
107 | |||
108 | #define IIO_CONST_ATTR_OUT_WAVETYPES_AVAILABLE(_channel, _output, _modes)\ | ||
109 | IIO_CONST_ATTR(dds##_channel##_out##_output##_wavetype_available,\ | ||
110 | _modes); | ||
diff --git a/drivers/staging/iio/gyro/adis16260_ring.c b/drivers/staging/iio/gyro/adis16260_ring.c new file mode 100644 index 00000000000..a4df8b32251 --- /dev/null +++ b/drivers/staging/iio/gyro/adis16260_ring.c | |||
@@ -0,0 +1,155 @@ | |||
1 | #include <linux/interrupt.h> | ||
2 | #include <linux/irq.h> | ||
3 | #include <linux/gpio.h> | ||
4 | #include <linux/workqueue.h> | ||
5 | #include <linux/mutex.h> | ||
6 | #include <linux/device.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/spi/spi.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include <linux/sysfs.h> | ||
11 | #include <linux/list.h> | ||
12 | |||
13 | #include "../iio.h" | ||
14 | #include "../sysfs.h" | ||
15 | #include "../ring_sw.h" | ||
16 | #include "../accel/accel.h" | ||
17 | #include "../trigger.h" | ||
18 | #include "adis16260.h" | ||
19 | |||
20 | /** | ||
21 | * adis16260_read_ring_data() read data registers which will be placed into ring | ||
22 | * @dev: device associated with child of actual device (iio_dev or iio_trig) | ||
23 | * @rx: somewhere to pass back the value read | ||
24 | **/ | ||
25 | static int adis16260_read_ring_data(struct device *dev, u8 *rx) | ||
26 | { | ||
27 | struct spi_message msg; | ||
28 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
29 | struct adis16260_state *st = iio_priv(indio_dev); | ||
30 | struct spi_transfer xfers[ADIS16260_OUTPUTS + 1]; | ||
31 | int ret; | ||
32 | int i; | ||
33 | |||
34 | mutex_lock(&st->buf_lock); | ||
35 | |||
36 | spi_message_init(&msg); | ||
37 | |||
38 | memset(xfers, 0, sizeof(xfers)); | ||
39 | for (i = 0; i <= ADIS16260_OUTPUTS; i++) { | ||
40 | xfers[i].bits_per_word = 8; | ||
41 | xfers[i].cs_change = 1; | ||
42 | xfers[i].len = 2; | ||
43 | xfers[i].delay_usecs = 30; | ||
44 | xfers[i].tx_buf = st->tx + 2 * i; | ||
45 | if (i < 2) /* SUPPLY_OUT:0x02 GYRO_OUT:0x04 */ | ||
46 | st->tx[2 * i] | ||
47 | = ADIS16260_READ_REG(ADIS16260_SUPPLY_OUT | ||
48 | + 2 * i); | ||
49 | else /* 0x06 to 0x09 is reserved */ | ||
50 | st->tx[2 * i] | ||
51 | = ADIS16260_READ_REG(ADIS16260_SUPPLY_OUT | ||
52 | + 2 * i + 4); | ||
53 | st->tx[2 * i + 1] = 0; | ||
54 | if (i >= 1) | ||
55 | xfers[i].rx_buf = rx + 2 * (i - 1); | ||
56 | spi_message_add_tail(&xfers[i], &msg); | ||
57 | } | ||
58 | |||
59 | ret = spi_sync(st->us, &msg); | ||
60 | if (ret) | ||
61 | dev_err(&st->us->dev, "problem when burst reading"); | ||
62 | |||
63 | mutex_unlock(&st->buf_lock); | ||
64 | |||
65 | return ret; | ||
66 | } | ||
67 | |||
68 | static irqreturn_t adis16260_trigger_handler(int irq, void *p) | ||
69 | { | ||
70 | struct iio_poll_func *pf = p; | ||
71 | struct iio_dev *indio_dev = pf->private_data; | ||
72 | struct adis16260_state *st = iio_priv(indio_dev); | ||
73 | struct iio_ring_buffer *ring = indio_dev->ring; | ||
74 | int i = 0; | ||
75 | s16 *data; | ||
76 | size_t datasize = ring->access->get_bytes_per_datum(ring); | ||
77 | |||
78 | data = kmalloc(datasize , GFP_KERNEL); | ||
79 | if (data == NULL) { | ||
80 | dev_err(&st->us->dev, "memory alloc failed in ring bh"); | ||
81 | return -ENOMEM; | ||
82 | } | ||
83 | |||
84 | if (ring->scan_count && | ||
85 | adis16260_read_ring_data(&indio_dev->dev, st->rx) >= 0) | ||
86 | for (; i < ring->scan_count; i++) | ||
87 | data[i] = be16_to_cpup((__be16 *)&(st->rx[i*2])); | ||
88 | |||
89 | /* Guaranteed to be aligned with 8 byte boundary */ | ||
90 | if (ring->scan_timestamp) | ||
91 | *((s64 *)(data + ((i + 3)/4)*4)) = pf->timestamp; | ||
92 | |||
93 | ring->access->store_to(ring, (u8 *)data, pf->timestamp); | ||
94 | |||
95 | iio_trigger_notify_done(indio_dev->trig); | ||
96 | kfree(data); | ||
97 | |||
98 | return IRQ_HANDLED; | ||
99 | } | ||
100 | |||
101 | void adis16260_unconfigure_ring(struct iio_dev *indio_dev) | ||
102 | { | ||
103 | iio_dealloc_pollfunc(indio_dev->pollfunc); | ||
104 | iio_sw_rb_free(indio_dev->ring); | ||
105 | } | ||
106 | |||
107 | static const struct iio_ring_setup_ops adis16260_ring_setup_ops = { | ||
108 | .preenable = &iio_sw_ring_preenable, | ||
109 | .postenable = &iio_triggered_ring_postenable, | ||
110 | .predisable = &iio_triggered_ring_predisable, | ||
111 | }; | ||
112 | |||
113 | int adis16260_configure_ring(struct iio_dev *indio_dev) | ||
114 | { | ||
115 | int ret = 0; | ||
116 | struct iio_ring_buffer *ring; | ||
117 | |||
118 | ring = iio_sw_rb_allocate(indio_dev); | ||
119 | if (!ring) { | ||
120 | ret = -ENOMEM; | ||
121 | return ret; | ||
122 | } | ||
123 | indio_dev->ring = ring; | ||
124 | /* Effectively select the ring buffer implementation */ | ||
125 | ring->access = &ring_sw_access_funcs; | ||
126 | ring->bpe = 2; | ||
127 | ring->scan_timestamp = true; | ||
128 | ring->setup_ops = &adis16260_ring_setup_ops; | ||
129 | ring->owner = THIS_MODULE; | ||
130 | |||
131 | /* Set default scan mode */ | ||
132 | iio_scan_mask_set(ring, ADIS16260_SCAN_SUPPLY); | ||
133 | iio_scan_mask_set(ring, ADIS16260_SCAN_GYRO); | ||
134 | iio_scan_mask_set(ring, ADIS16260_SCAN_AUX_ADC); | ||
135 | iio_scan_mask_set(ring, ADIS16260_SCAN_TEMP); | ||
136 | iio_scan_mask_set(ring, ADIS16260_SCAN_ANGL); | ||
137 | |||
138 | indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, | ||
139 | &adis16260_trigger_handler, | ||
140 | IRQF_ONESHOT, | ||
141 | indio_dev, | ||
142 | "adis16260_consumer%d", | ||
143 | indio_dev->id); | ||
144 | if (indio_dev->pollfunc == NULL) { | ||
145 | ret = -ENOMEM; | ||
146 | goto error_iio_sw_rb_free; | ||
147 | } | ||
148 | |||
149 | indio_dev->modes |= INDIO_RING_TRIGGERED; | ||
150 | return 0; | ||
151 | |||
152 | error_iio_sw_rb_free: | ||
153 | iio_sw_rb_free(indio_dev->ring); | ||
154 | return ret; | ||
155 | } | ||
diff --git a/drivers/staging/iio/gyro/adis16260_trigger.c b/drivers/staging/iio/gyro/adis16260_trigger.c new file mode 100644 index 00000000000..01094d0e714 --- /dev/null +++ b/drivers/staging/iio/gyro/adis16260_trigger.c | |||
@@ -0,0 +1,76 @@ | |||
1 | #include <linux/interrupt.h> | ||
2 | #include <linux/irq.h> | ||
3 | #include <linux/mutex.h> | ||
4 | #include <linux/device.h> | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/sysfs.h> | ||
7 | #include <linux/list.h> | ||
8 | #include <linux/spi/spi.h> | ||
9 | |||
10 | #include "../iio.h" | ||
11 | #include "../sysfs.h" | ||
12 | #include "../trigger.h" | ||
13 | #include "adis16260.h" | ||
14 | |||
15 | /** | ||
16 | * adis16260_data_rdy_trigger_set_state() set datardy interrupt state | ||
17 | **/ | ||
18 | static int adis16260_data_rdy_trigger_set_state(struct iio_trigger *trig, | ||
19 | bool state) | ||
20 | { | ||
21 | struct iio_dev *indio_dev = trig->private_data; | ||
22 | |||
23 | dev_dbg(&indio_dev->dev, "%s (%d)\n", __func__, state); | ||
24 | return adis16260_set_irq(indio_dev, state); | ||
25 | } | ||
26 | |||
27 | int adis16260_probe_trigger(struct iio_dev *indio_dev) | ||
28 | { | ||
29 | int ret; | ||
30 | struct adis16260_state *st = iio_priv(indio_dev); | ||
31 | |||
32 | st->trig = iio_allocate_trigger("%s-dev%d", | ||
33 | spi_get_device_id(st->us)->name, | ||
34 | indio_dev->id); | ||
35 | if (st->trig == NULL) { | ||
36 | ret = -ENOMEM; | ||
37 | goto error_ret; | ||
38 | } | ||
39 | |||
40 | ret = request_irq(st->us->irq, | ||
41 | &iio_trigger_generic_data_rdy_poll, | ||
42 | IRQF_TRIGGER_RISING, | ||
43 | "adis16260", | ||
44 | st->trig); | ||
45 | if (ret) | ||
46 | goto error_free_trig; | ||
47 | |||
48 | st->trig->dev.parent = &st->us->dev; | ||
49 | st->trig->owner = THIS_MODULE; | ||
50 | st->trig->private_data = indio_dev; | ||
51 | st->trig->set_trigger_state = &adis16260_data_rdy_trigger_set_state; | ||
52 | ret = iio_trigger_register(st->trig); | ||
53 | |||
54 | /* select default trigger */ | ||
55 | indio_dev->trig = st->trig; | ||
56 | if (ret) | ||
57 | goto error_free_irq; | ||
58 | |||
59 | return 0; | ||
60 | |||
61 | error_free_irq: | ||
62 | free_irq(st->us->irq, st->trig); | ||
63 | error_free_trig: | ||
64 | iio_free_trigger(st->trig); | ||
65 | error_ret: | ||
66 | return ret; | ||
67 | } | ||
68 | |||
69 | void adis16260_remove_trigger(struct iio_dev *indio_dev) | ||
70 | { | ||
71 | struct adis16260_state *st = iio_priv(indio_dev); | ||
72 | |||
73 | iio_trigger_unregister(st->trig); | ||
74 | free_irq(st->us->irq, st->trig); | ||
75 | iio_free_trigger(st->trig); | ||
76 | } | ||
diff --git a/drivers/staging/iio/gyro/gyro.h b/drivers/staging/iio/gyro/gyro.h new file mode 100644 index 00000000000..b5495613407 --- /dev/null +++ b/drivers/staging/iio/gyro/gyro.h | |||
@@ -0,0 +1,85 @@ | |||
1 | |||
2 | #include "../sysfs.h" | ||
3 | |||
4 | /* Gyroscope types of attribute */ | ||
5 | |||
6 | #define IIO_CONST_ATTR_GYRO_OFFSET(_string) \ | ||
7 | IIO_CONST_ATTR(gyro_offset, _string) | ||
8 | |||
9 | #define IIO_DEV_ATTR_GYRO_OFFSET(_mode, _show, _store, _addr) \ | ||
10 | IIO_DEVICE_ATTR(gyro_offset, _mode, _show, _store, _addr) | ||
11 | |||
12 | #define IIO_DEV_ATTR_GYRO_X_OFFSET(_mode, _show, _store, _addr) \ | ||
13 | IIO_DEVICE_ATTR(gyro_x_offset, _mode, _show, _store, _addr) | ||
14 | |||
15 | #define IIO_DEV_ATTR_GYRO_Y_OFFSET(_mode, _show, _store, _addr) \ | ||
16 | IIO_DEVICE_ATTR(gyro_y_offset, _mode, _show, _store, _addr) | ||
17 | |||
18 | #define IIO_DEV_ATTR_GYRO_Z_OFFSET(_mode, _show, _store, _addr) \ | ||
19 | IIO_DEVICE_ATTR(gyro_z_offset, _mode, _show, _store, _addr) | ||
20 | |||
21 | #define IIO_CONST_ATTR_GYRO_SCALE(_string) \ | ||
22 | IIO_CONST_ATTR(gyro_scale, _string) | ||
23 | |||
24 | #define IIO_DEV_ATTR_GYRO_SCALE(_mode, _show, _store, _addr) \ | ||
25 | IIO_DEVICE_ATTR(gyro_scale, S_IRUGO, _show, _store, _addr) | ||
26 | |||
27 | #define IIO_DEV_ATTR_GYRO_X_SCALE(_mode, _show, _store, _addr) \ | ||
28 | IIO_DEVICE_ATTR(gyro_x_scale, _mode, _show, _store, _addr) | ||
29 | |||
30 | #define IIO_DEV_ATTR_GYRO_Y_SCALE(_mode, _show, _store, _addr) \ | ||
31 | IIO_DEVICE_ATTR(gyro_y_scale, _mode, _show, _store, _addr) | ||
32 | |||
33 | #define IIO_DEV_ATTR_GYRO_Z_SCALE(_mode, _show, _store, _addr) \ | ||
34 | IIO_DEVICE_ATTR(gyro_z_scale, _mode, _show, _store, _addr) | ||
35 | |||
36 | #define IIO_DEV_ATTR_GYRO_CALIBBIAS(_mode, _show, _store, _addr) \ | ||
37 | IIO_DEVICE_ATTR(gyro_calibbias, S_IRUGO, _show, _store, _addr) | ||
38 | |||
39 | #define IIO_DEV_ATTR_GYRO_X_CALIBBIAS(_mode, _show, _store, _addr) \ | ||
40 | IIO_DEVICE_ATTR(gyro_x_calibbias, _mode, _show, _store, _addr) | ||
41 | |||
42 | #define IIO_DEV_ATTR_GYRO_Y_CALIBBIAS(_mode, _show, _store, _addr) \ | ||
43 | IIO_DEVICE_ATTR(gyro_y_calibbias, _mode, _show, _store, _addr) | ||
44 | |||
45 | #define IIO_DEV_ATTR_GYRO_Z_CALIBBIAS(_mode, _show, _store, _addr) \ | ||
46 | IIO_DEVICE_ATTR(gyro_z_calibbias, _mode, _show, _store, _addr) | ||
47 | |||
48 | #define IIO_DEV_ATTR_GYRO_CALIBSCALE(_mode, _show, _store, _addr) \ | ||
49 | IIO_DEVICE_ATTR(gyro_calibscale, S_IRUGO, _show, _store, _addr) | ||
50 | |||
51 | #define IIO_DEV_ATTR_GYRO_X_CALIBSCALE(_mode, _show, _store, _addr) \ | ||
52 | IIO_DEVICE_ATTR(gyro_x_calibscale, _mode, _show, _store, _addr) | ||
53 | |||
54 | #define IIO_DEV_ATTR_GYRO_Y_CALIBSCALE(_mode, _show, _store, _addr) \ | ||
55 | IIO_DEVICE_ATTR(gyro_y_calibscale, _mode, _show, _store, _addr) | ||
56 | |||
57 | #define IIO_DEV_ATTR_GYRO_Z_CALIBSCALE(_mode, _show, _store, _addr) \ | ||
58 | IIO_DEVICE_ATTR(gyro_z_calibscale, _mode, _show, _store, _addr) | ||
59 | |||
60 | #define IIO_DEV_ATTR_GYRO_Z_QUADRATURE_CORRECTION(_show, _addr) \ | ||
61 | IIO_DEVICE_ATTR(gyro_z_quadrature_correction_raw, S_IRUGO, _show, NULL, _addr) | ||
62 | |||
63 | #define IIO_DEV_ATTR_GYRO(_show, _addr) \ | ||
64 | IIO_DEVICE_ATTR(gyro_raw, S_IRUGO, _show, NULL, _addr) | ||
65 | |||
66 | #define IIO_DEV_ATTR_GYRO_X(_show, _addr) \ | ||
67 | IIO_DEVICE_ATTR(gyro_x_raw, S_IRUGO, _show, NULL, _addr) | ||
68 | |||
69 | #define IIO_DEV_ATTR_GYRO_Y(_show, _addr) \ | ||
70 | IIO_DEVICE_ATTR(gyro_y_raw, S_IRUGO, _show, NULL, _addr) | ||
71 | |||
72 | #define IIO_DEV_ATTR_GYRO_Z(_show, _addr) \ | ||
73 | IIO_DEVICE_ATTR(gyro_z_raw, S_IRUGO, _show, NULL, _addr) | ||
74 | |||
75 | #define IIO_DEV_ATTR_ANGL(_show, _addr) \ | ||
76 | IIO_DEVICE_ATTR(angl_raw, S_IRUGO, _show, NULL, _addr) | ||
77 | |||
78 | #define IIO_DEV_ATTR_ANGL_X(_show, _addr) \ | ||
79 | IIO_DEVICE_ATTR(angl_x_raw, S_IRUGO, _show, NULL, _addr) | ||
80 | |||
81 | #define IIO_DEV_ATTR_ANGL_Y(_show, _addr) \ | ||
82 | IIO_DEVICE_ATTR(angl_y_raw, S_IRUGO, _show, NULL, _addr) | ||
83 | |||
84 | #define IIO_DEV_ATTR_ANGL_Z(_show, _addr) \ | ||
85 | IIO_DEVICE_ATTR(angl_z_raw, S_IRUGO, _show, NULL, _addr) | ||
diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h new file mode 100644 index 00000000000..7a6ce4d0fb7 --- /dev/null +++ b/drivers/staging/iio/iio.h | |||
@@ -0,0 +1,439 @@ | |||
1 | /* The industrial I/O core | ||
2 | * | ||
3 | * Copyright (c) 2008 Jonathan Cameron | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 2 as published by | ||
7 | * the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #ifndef _INDUSTRIAL_IO_H_ | ||
11 | #define _INDUSTRIAL_IO_H_ | ||
12 | |||
13 | #include <linux/device.h> | ||
14 | #include <linux/cdev.h> | ||
15 | #include <linux/irq.h> | ||
16 | #include "sysfs.h" | ||
17 | #include "chrdev.h" | ||
18 | |||
19 | /* IIO TODO LIST */ | ||
20 | /* | ||
21 | * Provide means of adjusting timer accuracy. | ||
22 | * Currently assumes nano seconds. | ||
23 | */ | ||
24 | |||
25 | /* Event interface flags */ | ||
26 | #define IIO_BUSY_BIT_POS 1 | ||
27 | |||
28 | /* naughty temporary hack to match these against the event version | ||
29 | - need to flattern these together */ | ||
30 | enum iio_chan_type { | ||
31 | /* real channel types */ | ||
32 | IIO_IN, | ||
33 | IIO_OUT, | ||
34 | IIO_CURRENT, | ||
35 | IIO_POWER, | ||
36 | IIO_ACCEL, | ||
37 | IIO_IN_DIFF, | ||
38 | IIO_GYRO, | ||
39 | IIO_MAGN, | ||
40 | IIO_LIGHT, | ||
41 | IIO_INTENSITY, | ||
42 | IIO_PROXIMITY, | ||
43 | IIO_TEMP, | ||
44 | IIO_INCLI, | ||
45 | IIO_ROT, | ||
46 | IIO_ANGL, | ||
47 | IIO_TIMESTAMP, | ||
48 | }; | ||
49 | |||
50 | #define IIO_MOD_X 0 | ||
51 | #define IIO_MOD_LIGHT_BOTH 0 | ||
52 | #define IIO_MOD_Y 1 | ||
53 | #define IIO_MOD_LIGHT_IR 1 | ||
54 | #define IIO_MOD_Z 2 | ||
55 | #define IIO_MOD_X_AND_Y 3 | ||
56 | #define IIO_MOD_X_ANX_Z 4 | ||
57 | #define IIO_MOD_Y_AND_Z 5 | ||
58 | #define IIO_MOD_X_AND_Y_AND_Z 6 | ||
59 | #define IIO_MOD_X_OR_Y 7 | ||
60 | #define IIO_MOD_X_OR_Z 8 | ||
61 | #define IIO_MOD_Y_OR_Z 9 | ||
62 | #define IIO_MOD_X_OR_Y_OR_Z 10 | ||
63 | |||
64 | /* Could add the raw attributes as well - allowing buffer only devices */ | ||
65 | enum iio_chan_info_enum { | ||
66 | IIO_CHAN_INFO_SCALE_SHARED, | ||
67 | IIO_CHAN_INFO_SCALE_SEPARATE, | ||
68 | IIO_CHAN_INFO_OFFSET_SHARED, | ||
69 | IIO_CHAN_INFO_OFFSET_SEPARATE, | ||
70 | IIO_CHAN_INFO_CALIBSCALE_SHARED, | ||
71 | IIO_CHAN_INFO_CALIBSCALE_SEPARATE, | ||
72 | IIO_CHAN_INFO_CALIBBIAS_SHARED, | ||
73 | IIO_CHAN_INFO_CALIBBIAS_SEPARATE, | ||
74 | IIO_CHAN_INFO_PEAK_SHARED, | ||
75 | IIO_CHAN_INFO_PEAK_SEPARATE, | ||
76 | IIO_CHAN_INFO_PEAK_SCALE_SHARED, | ||
77 | IIO_CHAN_INFO_PEAK_SCALE_SEPARATE, | ||
78 | }; | ||
79 | |||
80 | /** | ||
81 | * struct iio_chan_spec - specification of a single channel | ||
82 | * @type: What type of measurement is the channel making. | ||
83 | * @channel: What number or name do we wish to asign the channel. | ||
84 | * @channel2: If there is a second number for a differential | ||
85 | * channel then this is it. If modified is set then the | ||
86 | * value here specifies the modifier. | ||
87 | * @address: Driver specific identifier. | ||
88 | * @scan_index: Monotonic index to give ordering in scans when read | ||
89 | * from a buffer. | ||
90 | * @scan_type: Sign: 's' or 'u' to specify signed or unsigned | ||
91 | * realbits: Number of valid bits of data | ||
92 | * storage_bits: Realbits + padding | ||
93 | * shift: Shift right by this before masking out | ||
94 | * realbits. | ||
95 | * @info_mask: What information is to be exported about this channel. | ||
96 | * This includes calibbias, scale etc. | ||
97 | * @event_mask: What events can this channel produce. | ||
98 | * @extend_name: Allows labeling of channel attributes with an | ||
99 | * informative name. Note this has no effect codes etc, | ||
100 | * unlike modifiers. | ||
101 | * @processed_val: Flag to specify the data access attribute should be | ||
102 | * *_input rather than *_raw. | ||
103 | * @modified: Does a modifier apply to this channel. What these are | ||
104 | * depends on the channel type. Modifier is set in | ||
105 | * channel2. Examples are IIO_MOD_X for axial sensors about | ||
106 | * the 'x' axis. | ||
107 | * @indexed: Specify the channel has a numerical index. If not, | ||
108 | * the value in channel will be suppressed for attribute | ||
109 | * but not for event codes. Typically set it to 0 when | ||
110 | * the index is false. | ||
111 | */ | ||
112 | struct iio_chan_spec { | ||
113 | enum iio_chan_type type; | ||
114 | int channel; | ||
115 | int channel2; | ||
116 | unsigned long address; | ||
117 | int scan_index; | ||
118 | struct { | ||
119 | char sign; | ||
120 | u8 realbits; | ||
121 | u8 storagebits; | ||
122 | u8 shift; | ||
123 | } scan_type; | ||
124 | const long info_mask; | ||
125 | const long event_mask; | ||
126 | const char *extend_name; | ||
127 | unsigned processed_val:1; | ||
128 | unsigned modified:1; | ||
129 | unsigned indexed:1; | ||
130 | }; | ||
131 | /* Meant for internal use only */ | ||
132 | void __iio_device_attr_deinit(struct device_attribute *dev_attr); | ||
133 | int __iio_device_attr_init(struct device_attribute *dev_attr, | ||
134 | const char *postfix, | ||
135 | struct iio_chan_spec const *chan, | ||
136 | ssize_t (*readfunc)(struct device *dev, | ||
137 | struct device_attribute *attr, | ||
138 | char *buf), | ||
139 | ssize_t (*writefunc)(struct device *dev, | ||
140 | struct device_attribute *attr, | ||
141 | const char *buf, | ||
142 | size_t len), | ||
143 | bool generic); | ||
144 | #define IIO_ST(si, rb, sb, sh) \ | ||
145 | { .sign = si, .realbits = rb, .storagebits = sb, .shift = sh } | ||
146 | |||
147 | #define IIO_CHAN(_type, _mod, _indexed, _proc, _name, _chan, _chan2, \ | ||
148 | _inf_mask, _address, _si, _stype, _event_mask) \ | ||
149 | { .type = _type, \ | ||
150 | .modified = _mod, \ | ||
151 | .indexed = _indexed, \ | ||
152 | .processed_val = _proc, \ | ||
153 | .extend_name = _name, \ | ||
154 | .channel = _chan, \ | ||
155 | .channel2 = _chan2, \ | ||
156 | .info_mask = _inf_mask, \ | ||
157 | .address = _address, \ | ||
158 | .scan_index = _si, \ | ||
159 | .scan_type = _stype, \ | ||
160 | .event_mask = _event_mask } | ||
161 | |||
162 | #define IIO_CHAN_SOFT_TIMESTAMP(_si) \ | ||
163 | { .type = IIO_TIMESTAMP, .channel = -1, \ | ||
164 | .scan_index = _si, .scan_type = IIO_ST('s', 64, 64, 0) } | ||
165 | |||
166 | int __iio_add_chan_devattr(const char *postfix, | ||
167 | const char *group, | ||
168 | struct iio_chan_spec const *chan, | ||
169 | ssize_t (*func)(struct device *dev, | ||
170 | struct device_attribute *attr, | ||
171 | char *buf), | ||
172 | ssize_t (*writefunc)(struct device *dev, | ||
173 | struct device_attribute *attr, | ||
174 | const char *buf, | ||
175 | size_t len), | ||
176 | int mask, | ||
177 | bool generic, | ||
178 | struct device *dev, | ||
179 | struct list_head *attr_list); | ||
180 | /** | ||
181 | * iio_get_time_ns() - utility function to get a time stamp for events etc | ||
182 | **/ | ||
183 | static inline s64 iio_get_time_ns(void) | ||
184 | { | ||
185 | struct timespec ts; | ||
186 | /* | ||
187 | * calls getnstimeofday. | ||
188 | * If hrtimers then up to ns accurate, if not microsecond. | ||
189 | */ | ||
190 | ktime_get_real_ts(&ts); | ||
191 | |||
192 | return timespec_to_ns(&ts); | ||
193 | } | ||
194 | |||
195 | /* Device operating modes */ | ||
196 | #define INDIO_DIRECT_MODE 0x01 | ||
197 | #define INDIO_RING_TRIGGERED 0x02 | ||
198 | #define INDIO_RING_HARDWARE_BUFFER 0x08 | ||
199 | |||
200 | #define INDIO_ALL_RING_MODES (INDIO_RING_TRIGGERED | INDIO_RING_HARDWARE_BUFFER) | ||
201 | |||
202 | /* Vast majority of this is set by the industrialio subsystem on a | ||
203 | * call to iio_device_register. */ | ||
204 | #define IIO_VAL_INT 1 | ||
205 | #define IIO_VAL_INT_PLUS_MICRO 2 | ||
206 | #define IIO_VAL_INT_PLUS_NANO 3 | ||
207 | |||
208 | struct iio_trigger; /* forward declaration */ | ||
209 | |||
210 | /** | ||
211 | * struct iio_info - constant information about device | ||
212 | * @driver_module: module structure used to ensure correct | ||
213 | * ownership of chrdevs etc | ||
214 | * @num_interrupt_lines:number of physical interrupt lines from device | ||
215 | * @event_attrs: event control attributes | ||
216 | * @attrs: general purpose device attributes | ||
217 | * @read_raw: function to request a value from the device. | ||
218 | * mask specifies which value. Note 0 means a reading of | ||
219 | * the channel in question. Return value will specify the | ||
220 | * type of value returned by the device. val and val2 will | ||
221 | * contain the elements making up the returned value. | ||
222 | * @write_raw: function to write a value to the device. | ||
223 | * Parameters are the same as for read_raw. | ||
224 | * @write_raw_get_fmt: callback function to query the expected | ||
225 | * format/precision. If not set by the driver, write_raw | ||
226 | * returns IIO_VAL_INT_PLUS_MICRO. | ||
227 | * @read_event_config: find out if the event is enabled. | ||
228 | * @write_event_config: set if the event is enabled. | ||
229 | * @read_event_value: read a value associated with the event. Meaning | ||
230 | * is event dependant. event_code specifies which event. | ||
231 | * @write_event_value: write the value associate with the event. | ||
232 | * Meaning is event dependent. | ||
233 | * @validate_trigger: function to validate the trigger when the | ||
234 | * current trigger gets changed. | ||
235 | **/ | ||
236 | struct iio_info { | ||
237 | struct module *driver_module; | ||
238 | int num_interrupt_lines; | ||
239 | struct attribute_group *event_attrs; | ||
240 | const struct attribute_group *attrs; | ||
241 | |||
242 | int (*read_raw)(struct iio_dev *indio_dev, | ||
243 | struct iio_chan_spec const *chan, | ||
244 | int *val, | ||
245 | int *val2, | ||
246 | long mask); | ||
247 | |||
248 | int (*write_raw)(struct iio_dev *indio_dev, | ||
249 | struct iio_chan_spec const *chan, | ||
250 | int val, | ||
251 | int val2, | ||
252 | long mask); | ||
253 | |||
254 | int (*write_raw_get_fmt)(struct iio_dev *indio_dev, | ||
255 | struct iio_chan_spec const *chan, | ||
256 | long mask); | ||
257 | |||
258 | int (*read_event_config)(struct iio_dev *indio_dev, | ||
259 | int event_code); | ||
260 | |||
261 | int (*write_event_config)(struct iio_dev *indio_dev, | ||
262 | int event_code, | ||
263 | int state); | ||
264 | |||
265 | int (*read_event_value)(struct iio_dev *indio_dev, | ||
266 | int event_code, | ||
267 | int *val); | ||
268 | int (*write_event_value)(struct iio_dev *indio_dev, | ||
269 | int event_code, | ||
270 | int val); | ||
271 | int (*validate_trigger)(struct iio_dev *indio_dev, | ||
272 | struct iio_trigger *trig); | ||
273 | |||
274 | }; | ||
275 | |||
276 | /** | ||
277 | * struct iio_dev - industrial I/O device | ||
278 | * @id: [INTERN] used to identify device internally | ||
279 | * @dev_data: [DRIVER] device specific data | ||
280 | * @modes: [DRIVER] operating modes supported by device | ||
281 | * @currentmode: [DRIVER] current operating mode | ||
282 | * @dev: [DRIVER] device structure, should be assigned a parent | ||
283 | * and owner | ||
284 | * @event_interfaces: [INTERN] event chrdevs associated with interrupt lines | ||
285 | * @ring: [DRIVER] any ring buffer present | ||
286 | * @mlock: [INTERN] lock used to prevent simultaneous device state | ||
287 | * changes | ||
288 | * @available_scan_masks: [DRIVER] optional array of allowed bitmasks | ||
289 | * @trig: [INTERN] current device trigger (ring buffer modes) | ||
290 | * @pollfunc: [DRIVER] function run on trigger being received | ||
291 | * @channels: [DRIVER] channel specification structure table | ||
292 | * @num_channels: [DRIVER] number of chanels specified in @channels. | ||
293 | * @channel_attr_list: [INTERN] keep track of automatically created channel | ||
294 | * attributes. | ||
295 | * @name: [DRIVER] name of the device. | ||
296 | **/ | ||
297 | struct iio_dev { | ||
298 | int id; | ||
299 | void *dev_data; | ||
300 | int modes; | ||
301 | int currentmode; | ||
302 | struct device dev; | ||
303 | |||
304 | struct iio_event_interface *event_interfaces; | ||
305 | |||
306 | struct iio_ring_buffer *ring; | ||
307 | struct mutex mlock; | ||
308 | |||
309 | u32 *available_scan_masks; | ||
310 | struct iio_trigger *trig; | ||
311 | struct iio_poll_func *pollfunc; | ||
312 | |||
313 | struct iio_chan_spec const *channels; | ||
314 | int num_channels; | ||
315 | |||
316 | struct list_head channel_attr_list; | ||
317 | const char *name; | ||
318 | const struct iio_info *info; | ||
319 | }; | ||
320 | |||
321 | /** | ||
322 | * iio_device_register() - register a device with the IIO subsystem | ||
323 | * @dev_info: Device structure filled by the device driver | ||
324 | **/ | ||
325 | int iio_device_register(struct iio_dev *dev_info); | ||
326 | |||
327 | /** | ||
328 | * iio_device_unregister() - unregister a device from the IIO subsystem | ||
329 | * @dev_info: Device structure representing the device. | ||
330 | **/ | ||
331 | void iio_device_unregister(struct iio_dev *dev_info); | ||
332 | |||
333 | /** | ||
334 | * iio_push_event() - try to add event to the list for userspace reading | ||
335 | * @dev_info: IIO device structure | ||
336 | * @ev_line: Which event line (hardware interrupt) | ||
337 | * @ev_code: What event | ||
338 | * @timestamp: When the event occurred | ||
339 | **/ | ||
340 | int iio_push_event(struct iio_dev *dev_info, | ||
341 | int ev_line, | ||
342 | int ev_code, | ||
343 | s64 timestamp); | ||
344 | |||
345 | /* Used to distinguish between bipolar and unipolar scan elemenents. | ||
346 | * Whilst this may seem obvious, we may well want to change the representation | ||
347 | * in the future!*/ | ||
348 | #define IIO_SIGNED(a) -(a) | ||
349 | #define IIO_UNSIGNED(a) (a) | ||
350 | |||
351 | extern dev_t iio_devt; | ||
352 | extern struct bus_type iio_bus_type; | ||
353 | |||
354 | /** | ||
355 | * iio_put_device() - reference counted deallocation of struct device | ||
356 | * @dev: the iio_device containing the device | ||
357 | **/ | ||
358 | static inline void iio_put_device(struct iio_dev *dev) | ||
359 | { | ||
360 | if (dev) | ||
361 | put_device(&dev->dev); | ||
362 | }; | ||
363 | |||
364 | /** | ||
365 | * to_iio_dev() - get iio_dev for which we have the struct device | ||
366 | * @d: the struct device | ||
367 | **/ | ||
368 | static inline struct iio_dev *to_iio_dev(struct device *d) | ||
369 | { | ||
370 | return container_of(d, struct iio_dev, dev); | ||
371 | }; | ||
372 | |||
373 | /** | ||
374 | * iio_dev_get_devdata() - helper function gets device specific data | ||
375 | * @d: the iio_dev associated with the device | ||
376 | **/ | ||
377 | static inline void *iio_dev_get_devdata(struct iio_dev *d) | ||
378 | { | ||
379 | return d->dev_data; | ||
380 | } | ||
381 | |||
382 | |||
383 | /* Can we make this smaller? */ | ||
384 | #define IIO_ALIGN L1_CACHE_BYTES | ||
385 | /** | ||
386 | * iio_allocate_device() - allocate an iio_dev from a driver | ||
387 | * @sizeof_priv: Space to allocate for private structure. | ||
388 | **/ | ||
389 | struct iio_dev *iio_allocate_device(int sizeof_priv); | ||
390 | |||
391 | static inline void *iio_priv(const struct iio_dev *dev) | ||
392 | { | ||
393 | return (char *)dev + ALIGN(sizeof(struct iio_dev), IIO_ALIGN); | ||
394 | } | ||
395 | |||
396 | static inline struct iio_dev *iio_priv_to_dev(void *priv) | ||
397 | { | ||
398 | return (struct iio_dev *)((char *)priv - | ||
399 | ALIGN(sizeof(struct iio_dev), IIO_ALIGN)); | ||
400 | } | ||
401 | |||
402 | /** | ||
403 | * iio_free_device() - free an iio_dev from a driver | ||
404 | * @dev: the iio_dev associated with the device | ||
405 | **/ | ||
406 | void iio_free_device(struct iio_dev *dev); | ||
407 | |||
408 | /** | ||
409 | * iio_put() - internal module reference count reduce | ||
410 | **/ | ||
411 | void iio_put(void); | ||
412 | |||
413 | /** | ||
414 | * iio_get() - internal module reference count increase | ||
415 | **/ | ||
416 | void iio_get(void); | ||
417 | |||
418 | /** | ||
419 | * iio_device_get_chrdev_minor() - get an unused minor number | ||
420 | **/ | ||
421 | int iio_device_get_chrdev_minor(void); | ||
422 | void iio_device_free_chrdev_minor(int val); | ||
423 | |||
424 | /** | ||
425 | * iio_ring_enabled() - helper function to test if any form of ring is enabled | ||
426 | * @dev_info: IIO device info structure for device | ||
427 | **/ | ||
428 | static inline bool iio_ring_enabled(struct iio_dev *dev_info) | ||
429 | { | ||
430 | return dev_info->currentmode | ||
431 | & (INDIO_RING_TRIGGERED | ||
432 | | INDIO_RING_HARDWARE_BUFFER); | ||
433 | }; | ||
434 | |||
435 | struct ida; | ||
436 | |||
437 | int iio_get_new_ida_val(struct ida *this_ida); | ||
438 | void iio_free_ida_val(struct ida *this_ida, int id); | ||
439 | #endif /* _INDUSTRIAL_IO_H_ */ | ||
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c new file mode 100644 index 00000000000..19819e7578c --- /dev/null +++ b/drivers/staging/iio/industrialio-core.c | |||
@@ -0,0 +1,1245 @@ | |||
1 | /* The industrial I/O core | ||
2 | * | ||
3 | * Copyright (c) 2008 Jonathan Cameron | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 2 as published by | ||
7 | * the Free Software Foundation. | ||
8 | * | ||
9 | * Based on elements of hwmon and input subsystems. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/idr.h> | ||
15 | #include <linux/kdev_t.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/poll.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/wait.h> | ||
22 | #include <linux/cdev.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include "iio.h" | ||
25 | #include "trigger_consumer.h" | ||
26 | |||
27 | #define IIO_ID_PREFIX "device" | ||
28 | #define IIO_ID_FORMAT IIO_ID_PREFIX "%d" | ||
29 | |||
30 | /* IDR to assign each registered device a unique id*/ | ||
31 | static DEFINE_IDA(iio_ida); | ||
32 | /* IDR to allocate character device minor numbers */ | ||
33 | static DEFINE_IDA(iio_chrdev_ida); | ||
34 | /* Lock used to protect both of the above */ | ||
35 | static DEFINE_SPINLOCK(iio_ida_lock); | ||
36 | |||
37 | dev_t iio_devt; | ||
38 | EXPORT_SYMBOL(iio_devt); | ||
39 | |||
40 | #define IIO_DEV_MAX 256 | ||
41 | struct bus_type iio_bus_type = { | ||
42 | .name = "iio", | ||
43 | }; | ||
44 | EXPORT_SYMBOL(iio_bus_type); | ||
45 | |||
46 | static const char * const iio_chan_type_name_spec_shared[] = { | ||
47 | [IIO_IN] = "in", | ||
48 | [IIO_OUT] = "out", | ||
49 | [IIO_CURRENT] = "current", | ||
50 | [IIO_POWER] = "power", | ||
51 | [IIO_ACCEL] = "accel", | ||
52 | [IIO_IN_DIFF] = "in-in", | ||
53 | [IIO_GYRO] = "gyro", | ||
54 | [IIO_MAGN] = "magn", | ||
55 | [IIO_LIGHT] = "illuminance", | ||
56 | [IIO_INTENSITY] = "intensity", | ||
57 | [IIO_PROXIMITY] = "proximity", | ||
58 | [IIO_TEMP] = "temp", | ||
59 | [IIO_INCLI] = "incli", | ||
60 | [IIO_ROT] = "rot", | ||
61 | [IIO_ANGL] = "angl", | ||
62 | [IIO_TIMESTAMP] = "timestamp", | ||
63 | }; | ||
64 | |||
65 | static const char * const iio_chan_type_name_spec_complex[] = { | ||
66 | [IIO_IN_DIFF] = "in%d-in%d", | ||
67 | }; | ||
68 | |||
69 | static const char * const iio_modifier_names_light[] = { | ||
70 | [IIO_MOD_LIGHT_BOTH] = "both", | ||
71 | [IIO_MOD_LIGHT_IR] = "ir", | ||
72 | }; | ||
73 | |||
74 | static const char * const iio_modifier_names_axial[] = { | ||
75 | [IIO_MOD_X] = "x", | ||
76 | [IIO_MOD_Y] = "y", | ||
77 | [IIO_MOD_Z] = "z", | ||
78 | }; | ||
79 | |||
80 | /* relies on pairs of these shared then separate */ | ||
81 | static const char * const iio_chan_info_postfix[] = { | ||
82 | [IIO_CHAN_INFO_SCALE_SHARED/2] = "scale", | ||
83 | [IIO_CHAN_INFO_OFFSET_SHARED/2] = "offset", | ||
84 | [IIO_CHAN_INFO_CALIBSCALE_SHARED/2] = "calibscale", | ||
85 | [IIO_CHAN_INFO_CALIBBIAS_SHARED/2] = "calibbias", | ||
86 | [IIO_CHAN_INFO_PEAK_SHARED/2] = "peak_raw", | ||
87 | [IIO_CHAN_INFO_PEAK_SCALE_SHARED/2] = "peak_scale", | ||
88 | }; | ||
89 | |||
90 | int iio_push_event(struct iio_dev *dev_info, | ||
91 | int ev_line, | ||
92 | int ev_code, | ||
93 | s64 timestamp) | ||
94 | { | ||
95 | struct iio_event_interface *ev_int | ||
96 | = &dev_info->event_interfaces[ev_line]; | ||
97 | struct iio_detected_event_list *ev; | ||
98 | int ret = 0; | ||
99 | |||
100 | /* Does anyone care? */ | ||
101 | mutex_lock(&ev_int->event_list_lock); | ||
102 | if (test_bit(IIO_BUSY_BIT_POS, &ev_int->handler.flags)) { | ||
103 | if (ev_int->current_events == ev_int->max_events) { | ||
104 | mutex_unlock(&ev_int->event_list_lock); | ||
105 | return 0; | ||
106 | } | ||
107 | ev = kmalloc(sizeof(*ev), GFP_KERNEL); | ||
108 | if (ev == NULL) { | ||
109 | ret = -ENOMEM; | ||
110 | mutex_unlock(&ev_int->event_list_lock); | ||
111 | goto error_ret; | ||
112 | } | ||
113 | ev->ev.id = ev_code; | ||
114 | ev->ev.timestamp = timestamp; | ||
115 | |||
116 | list_add_tail(&ev->list, &ev_int->det_events); | ||
117 | ev_int->current_events++; | ||
118 | mutex_unlock(&ev_int->event_list_lock); | ||
119 | wake_up_interruptible(&ev_int->wait); | ||
120 | } else | ||
121 | mutex_unlock(&ev_int->event_list_lock); | ||
122 | |||
123 | error_ret: | ||
124 | return ret; | ||
125 | } | ||
126 | EXPORT_SYMBOL(iio_push_event); | ||
127 | |||
128 | |||
129 | /* This turns up an awful lot */ | ||
130 | ssize_t iio_read_const_attr(struct device *dev, | ||
131 | struct device_attribute *attr, | ||
132 | char *buf) | ||
133 | { | ||
134 | return sprintf(buf, "%s\n", to_iio_const_attr(attr)->string); | ||
135 | } | ||
136 | EXPORT_SYMBOL(iio_read_const_attr); | ||
137 | |||
138 | |||
139 | static ssize_t iio_event_chrdev_read(struct file *filep, | ||
140 | char __user *buf, | ||
141 | size_t count, | ||
142 | loff_t *f_ps) | ||
143 | { | ||
144 | struct iio_event_interface *ev_int = filep->private_data; | ||
145 | struct iio_detected_event_list *el; | ||
146 | int ret; | ||
147 | size_t len; | ||
148 | |||
149 | mutex_lock(&ev_int->event_list_lock); | ||
150 | if (list_empty(&ev_int->det_events)) { | ||
151 | if (filep->f_flags & O_NONBLOCK) { | ||
152 | ret = -EAGAIN; | ||
153 | goto error_mutex_unlock; | ||
154 | } | ||
155 | mutex_unlock(&ev_int->event_list_lock); | ||
156 | /* Blocking on device; waiting for something to be there */ | ||
157 | ret = wait_event_interruptible(ev_int->wait, | ||
158 | !list_empty(&ev_int | ||
159 | ->det_events)); | ||
160 | if (ret) | ||
161 | goto error_ret; | ||
162 | /* Single access device so no one else can get the data */ | ||
163 | mutex_lock(&ev_int->event_list_lock); | ||
164 | } | ||
165 | |||
166 | el = list_first_entry(&ev_int->det_events, | ||
167 | struct iio_detected_event_list, | ||
168 | list); | ||
169 | len = sizeof el->ev; | ||
170 | if (copy_to_user(buf, &(el->ev), len)) { | ||
171 | ret = -EFAULT; | ||
172 | goto error_mutex_unlock; | ||
173 | } | ||
174 | list_del(&el->list); | ||
175 | ev_int->current_events--; | ||
176 | mutex_unlock(&ev_int->event_list_lock); | ||
177 | kfree(el); | ||
178 | |||
179 | return len; | ||
180 | |||
181 | error_mutex_unlock: | ||
182 | mutex_unlock(&ev_int->event_list_lock); | ||
183 | error_ret: | ||
184 | |||
185 | return ret; | ||
186 | } | ||
187 | |||
188 | static int iio_event_chrdev_release(struct inode *inode, struct file *filep) | ||
189 | { | ||
190 | struct iio_handler *hand = iio_cdev_to_handler(inode->i_cdev); | ||
191 | struct iio_event_interface *ev_int = hand->private; | ||
192 | struct iio_detected_event_list *el, *t; | ||
193 | |||
194 | mutex_lock(&ev_int->event_list_lock); | ||
195 | clear_bit(IIO_BUSY_BIT_POS, &ev_int->handler.flags); | ||
196 | /* | ||
197 | * In order to maintain a clean state for reopening, | ||
198 | * clear out any awaiting events. The mask will prevent | ||
199 | * any new __iio_push_event calls running. | ||
200 | */ | ||
201 | list_for_each_entry_safe(el, t, &ev_int->det_events, list) { | ||
202 | list_del(&el->list); | ||
203 | kfree(el); | ||
204 | } | ||
205 | mutex_unlock(&ev_int->event_list_lock); | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static int iio_event_chrdev_open(struct inode *inode, struct file *filep) | ||
211 | { | ||
212 | struct iio_handler *hand = iio_cdev_to_handler(inode->i_cdev); | ||
213 | struct iio_event_interface *ev_int = hand->private; | ||
214 | |||
215 | mutex_lock(&ev_int->event_list_lock); | ||
216 | if (test_and_set_bit(IIO_BUSY_BIT_POS, &hand->flags)) { | ||
217 | fops_put(filep->f_op); | ||
218 | mutex_unlock(&ev_int->event_list_lock); | ||
219 | return -EBUSY; | ||
220 | } | ||
221 | filep->private_data = hand->private; | ||
222 | mutex_unlock(&ev_int->event_list_lock); | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static const struct file_operations iio_event_chrdev_fileops = { | ||
228 | .read = iio_event_chrdev_read, | ||
229 | .release = iio_event_chrdev_release, | ||
230 | .open = iio_event_chrdev_open, | ||
231 | .owner = THIS_MODULE, | ||
232 | .llseek = noop_llseek, | ||
233 | }; | ||
234 | |||
235 | static void iio_event_dev_release(struct device *dev) | ||
236 | { | ||
237 | struct iio_event_interface *ev_int | ||
238 | = container_of(dev, struct iio_event_interface, dev); | ||
239 | cdev_del(&ev_int->handler.chrdev); | ||
240 | iio_device_free_chrdev_minor(MINOR(dev->devt)); | ||
241 | }; | ||
242 | |||
243 | static struct device_type iio_event_type = { | ||
244 | .release = iio_event_dev_release, | ||
245 | }; | ||
246 | |||
247 | int iio_device_get_chrdev_minor(void) | ||
248 | { | ||
249 | int ret, val; | ||
250 | |||
251 | ida_again: | ||
252 | if (unlikely(ida_pre_get(&iio_chrdev_ida, GFP_KERNEL) == 0)) | ||
253 | return -ENOMEM; | ||
254 | spin_lock(&iio_ida_lock); | ||
255 | ret = ida_get_new(&iio_chrdev_ida, &val); | ||
256 | spin_unlock(&iio_ida_lock); | ||
257 | if (unlikely(ret == -EAGAIN)) | ||
258 | goto ida_again; | ||
259 | else if (unlikely(ret)) | ||
260 | return ret; | ||
261 | if (val > IIO_DEV_MAX) | ||
262 | return -ENOMEM; | ||
263 | return val; | ||
264 | } | ||
265 | |||
266 | void iio_device_free_chrdev_minor(int val) | ||
267 | { | ||
268 | spin_lock(&iio_ida_lock); | ||
269 | ida_remove(&iio_chrdev_ida, val); | ||
270 | spin_unlock(&iio_ida_lock); | ||
271 | } | ||
272 | |||
273 | static int iio_setup_ev_int(struct iio_event_interface *ev_int, | ||
274 | const char *dev_name, | ||
275 | int index, | ||
276 | struct module *owner, | ||
277 | struct device *dev) | ||
278 | { | ||
279 | int ret, minor; | ||
280 | |||
281 | ev_int->dev.bus = &iio_bus_type; | ||
282 | ev_int->dev.parent = dev; | ||
283 | ev_int->dev.type = &iio_event_type; | ||
284 | device_initialize(&ev_int->dev); | ||
285 | |||
286 | minor = iio_device_get_chrdev_minor(); | ||
287 | if (minor < 0) { | ||
288 | ret = minor; | ||
289 | goto error_device_put; | ||
290 | } | ||
291 | ev_int->dev.devt = MKDEV(MAJOR(iio_devt), minor); | ||
292 | dev_set_name(&ev_int->dev, "%s:event%d", dev_name, index); | ||
293 | |||
294 | ret = device_add(&ev_int->dev); | ||
295 | if (ret) | ||
296 | goto error_free_minor; | ||
297 | |||
298 | cdev_init(&ev_int->handler.chrdev, &iio_event_chrdev_fileops); | ||
299 | ev_int->handler.chrdev.owner = owner; | ||
300 | |||
301 | mutex_init(&ev_int->event_list_lock); | ||
302 | /* discussion point - make this variable? */ | ||
303 | ev_int->max_events = 10; | ||
304 | ev_int->current_events = 0; | ||
305 | INIT_LIST_HEAD(&ev_int->det_events); | ||
306 | init_waitqueue_head(&ev_int->wait); | ||
307 | ev_int->handler.private = ev_int; | ||
308 | ev_int->handler.flags = 0; | ||
309 | |||
310 | ret = cdev_add(&ev_int->handler.chrdev, ev_int->dev.devt, 1); | ||
311 | if (ret) | ||
312 | goto error_unreg_device; | ||
313 | |||
314 | return 0; | ||
315 | |||
316 | error_unreg_device: | ||
317 | device_unregister(&ev_int->dev); | ||
318 | error_free_minor: | ||
319 | iio_device_free_chrdev_minor(minor); | ||
320 | error_device_put: | ||
321 | put_device(&ev_int->dev); | ||
322 | |||
323 | return ret; | ||
324 | } | ||
325 | |||
326 | static void iio_free_ev_int(struct iio_event_interface *ev_int) | ||
327 | { | ||
328 | device_unregister(&ev_int->dev); | ||
329 | put_device(&ev_int->dev); | ||
330 | } | ||
331 | |||
332 | static int __init iio_dev_init(void) | ||
333 | { | ||
334 | int err; | ||
335 | |||
336 | err = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio"); | ||
337 | if (err < 0) | ||
338 | printk(KERN_ERR "%s: failed to allocate char dev region\n", | ||
339 | __FILE__); | ||
340 | |||
341 | return err; | ||
342 | } | ||
343 | |||
344 | static void __exit iio_dev_exit(void) | ||
345 | { | ||
346 | if (iio_devt) | ||
347 | unregister_chrdev_region(iio_devt, IIO_DEV_MAX); | ||
348 | } | ||
349 | |||
350 | static int __init iio_init(void) | ||
351 | { | ||
352 | int ret; | ||
353 | |||
354 | /* Register sysfs bus */ | ||
355 | ret = bus_register(&iio_bus_type); | ||
356 | if (ret < 0) { | ||
357 | printk(KERN_ERR | ||
358 | "%s could not register bus type\n", | ||
359 | __FILE__); | ||
360 | goto error_nothing; | ||
361 | } | ||
362 | |||
363 | ret = iio_dev_init(); | ||
364 | if (ret < 0) | ||
365 | goto error_unregister_bus_type; | ||
366 | |||
367 | return 0; | ||
368 | |||
369 | error_unregister_bus_type: | ||
370 | bus_unregister(&iio_bus_type); | ||
371 | error_nothing: | ||
372 | return ret; | ||
373 | } | ||
374 | |||
375 | static void __exit iio_exit(void) | ||
376 | { | ||
377 | iio_dev_exit(); | ||
378 | bus_unregister(&iio_bus_type); | ||
379 | } | ||
380 | |||
381 | static ssize_t iio_read_channel_info(struct device *dev, | ||
382 | struct device_attribute *attr, | ||
383 | char *buf) | ||
384 | { | ||
385 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
386 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
387 | int val, val2; | ||
388 | int ret = indio_dev->info->read_raw(indio_dev, this_attr->c, | ||
389 | &val, &val2, this_attr->address); | ||
390 | |||
391 | if (ret < 0) | ||
392 | return ret; | ||
393 | |||
394 | if (ret == IIO_VAL_INT) | ||
395 | return sprintf(buf, "%d\n", val); | ||
396 | else if (ret == IIO_VAL_INT_PLUS_MICRO) { | ||
397 | if (val2 < 0) | ||
398 | return sprintf(buf, "-%d.%06u\n", val, -val2); | ||
399 | else | ||
400 | return sprintf(buf, "%d.%06u\n", val, val2); | ||
401 | } else if (ret == IIO_VAL_INT_PLUS_NANO) { | ||
402 | if (val2 < 0) | ||
403 | return sprintf(buf, "-%d.%09u\n", val, -val2); | ||
404 | else | ||
405 | return sprintf(buf, "%d.%09u\n", val, val2); | ||
406 | } else | ||
407 | return 0; | ||
408 | } | ||
409 | |||
410 | static ssize_t iio_write_channel_info(struct device *dev, | ||
411 | struct device_attribute *attr, | ||
412 | const char *buf, | ||
413 | size_t len) | ||
414 | { | ||
415 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
416 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
417 | int ret, integer = 0, fract = 0, fract_mult = 100000; | ||
418 | bool integer_part = true, negative = false; | ||
419 | |||
420 | /* Assumes decimal - precision based on number of digits */ | ||
421 | if (!indio_dev->info->write_raw) | ||
422 | return -EINVAL; | ||
423 | |||
424 | if (indio_dev->info->write_raw_get_fmt) | ||
425 | switch (indio_dev->info->write_raw_get_fmt(indio_dev, | ||
426 | this_attr->c, this_attr->address)) { | ||
427 | case IIO_VAL_INT_PLUS_MICRO: | ||
428 | fract_mult = 100000; | ||
429 | break; | ||
430 | case IIO_VAL_INT_PLUS_NANO: | ||
431 | fract_mult = 100000000; | ||
432 | break; | ||
433 | default: | ||
434 | return -EINVAL; | ||
435 | } | ||
436 | |||
437 | if (buf[0] == '-') { | ||
438 | negative = true; | ||
439 | buf++; | ||
440 | } | ||
441 | |||
442 | while (*buf) { | ||
443 | if ('0' <= *buf && *buf <= '9') { | ||
444 | if (integer_part) | ||
445 | integer = integer*10 + *buf - '0'; | ||
446 | else { | ||
447 | fract += fract_mult*(*buf - '0'); | ||
448 | if (fract_mult == 1) | ||
449 | break; | ||
450 | fract_mult /= 10; | ||
451 | } | ||
452 | } else if (*buf == '\n') { | ||
453 | if (*(buf + 1) == '\0') | ||
454 | break; | ||
455 | else | ||
456 | return -EINVAL; | ||
457 | } else if (*buf == '.') { | ||
458 | integer_part = false; | ||
459 | } else { | ||
460 | return -EINVAL; | ||
461 | } | ||
462 | buf++; | ||
463 | } | ||
464 | if (negative) { | ||
465 | if (integer) | ||
466 | integer = -integer; | ||
467 | else | ||
468 | fract = -fract; | ||
469 | } | ||
470 | |||
471 | ret = indio_dev->info->write_raw(indio_dev, this_attr->c, | ||
472 | integer, fract, this_attr->address); | ||
473 | if (ret) | ||
474 | return ret; | ||
475 | |||
476 | return len; | ||
477 | } | ||
478 | |||
479 | static int __iio_build_postfix(struct iio_chan_spec const *chan, | ||
480 | bool generic, | ||
481 | const char *postfix, | ||
482 | char **result) | ||
483 | { | ||
484 | char *all_post; | ||
485 | /* 3 options - generic, extend_name, modified - if generic, extend_name | ||
486 | * and modified cannot apply.*/ | ||
487 | |||
488 | if (generic || (!chan->modified && !chan->extend_name)) { | ||
489 | all_post = kasprintf(GFP_KERNEL, "%s", postfix); | ||
490 | } else if (chan->modified) { | ||
491 | const char *intermediate; | ||
492 | switch (chan->type) { | ||
493 | case IIO_INTENSITY: | ||
494 | intermediate | ||
495 | = iio_modifier_names_light[chan->channel2]; | ||
496 | break; | ||
497 | case IIO_ACCEL: | ||
498 | case IIO_GYRO: | ||
499 | case IIO_MAGN: | ||
500 | case IIO_INCLI: | ||
501 | case IIO_ROT: | ||
502 | case IIO_ANGL: | ||
503 | intermediate | ||
504 | = iio_modifier_names_axial[chan->channel2]; | ||
505 | break; | ||
506 | default: | ||
507 | return -EINVAL; | ||
508 | } | ||
509 | if (chan->extend_name) | ||
510 | all_post = kasprintf(GFP_KERNEL, "%s_%s_%s", | ||
511 | intermediate, | ||
512 | chan->extend_name, | ||
513 | postfix); | ||
514 | else | ||
515 | all_post = kasprintf(GFP_KERNEL, "%s_%s", | ||
516 | intermediate, | ||
517 | postfix); | ||
518 | } else | ||
519 | all_post = kasprintf(GFP_KERNEL, "%s_%s", chan->extend_name, | ||
520 | postfix); | ||
521 | if (all_post == NULL) | ||
522 | return -ENOMEM; | ||
523 | *result = all_post; | ||
524 | return 0; | ||
525 | } | ||
526 | |||
527 | int __iio_device_attr_init(struct device_attribute *dev_attr, | ||
528 | const char *postfix, | ||
529 | struct iio_chan_spec const *chan, | ||
530 | ssize_t (*readfunc)(struct device *dev, | ||
531 | struct device_attribute *attr, | ||
532 | char *buf), | ||
533 | ssize_t (*writefunc)(struct device *dev, | ||
534 | struct device_attribute *attr, | ||
535 | const char *buf, | ||
536 | size_t len), | ||
537 | bool generic) | ||
538 | { | ||
539 | int ret; | ||
540 | char *name_format, *full_postfix; | ||
541 | sysfs_attr_init(&dev_attr->attr); | ||
542 | ret = __iio_build_postfix(chan, generic, postfix, &full_postfix); | ||
543 | if (ret) | ||
544 | goto error_ret; | ||
545 | |||
546 | /* Special case for types that uses both channel numbers in naming */ | ||
547 | if (chan->type == IIO_IN_DIFF && !generic) | ||
548 | name_format | ||
549 | = kasprintf(GFP_KERNEL, "%s_%s", | ||
550 | iio_chan_type_name_spec_complex[chan->type], | ||
551 | full_postfix); | ||
552 | else if (generic || !chan->indexed) | ||
553 | name_format | ||
554 | = kasprintf(GFP_KERNEL, "%s_%s", | ||
555 | iio_chan_type_name_spec_shared[chan->type], | ||
556 | full_postfix); | ||
557 | else | ||
558 | name_format | ||
559 | = kasprintf(GFP_KERNEL, "%s%d_%s", | ||
560 | iio_chan_type_name_spec_shared[chan->type], | ||
561 | chan->channel, | ||
562 | full_postfix); | ||
563 | |||
564 | if (name_format == NULL) { | ||
565 | ret = -ENOMEM; | ||
566 | goto error_free_full_postfix; | ||
567 | } | ||
568 | dev_attr->attr.name = kasprintf(GFP_KERNEL, | ||
569 | name_format, | ||
570 | chan->channel, | ||
571 | chan->channel2); | ||
572 | if (dev_attr->attr.name == NULL) { | ||
573 | ret = -ENOMEM; | ||
574 | goto error_free_name_format; | ||
575 | } | ||
576 | |||
577 | if (readfunc) { | ||
578 | dev_attr->attr.mode |= S_IRUGO; | ||
579 | dev_attr->show = readfunc; | ||
580 | } | ||
581 | |||
582 | if (writefunc) { | ||
583 | dev_attr->attr.mode |= S_IWUSR; | ||
584 | dev_attr->store = writefunc; | ||
585 | } | ||
586 | kfree(name_format); | ||
587 | kfree(full_postfix); | ||
588 | |||
589 | return 0; | ||
590 | |||
591 | error_free_name_format: | ||
592 | kfree(name_format); | ||
593 | error_free_full_postfix: | ||
594 | kfree(full_postfix); | ||
595 | error_ret: | ||
596 | return ret; | ||
597 | } | ||
598 | |||
599 | void __iio_device_attr_deinit(struct device_attribute *dev_attr) | ||
600 | { | ||
601 | kfree(dev_attr->attr.name); | ||
602 | } | ||
603 | |||
604 | int __iio_add_chan_devattr(const char *postfix, | ||
605 | const char *group, | ||
606 | struct iio_chan_spec const *chan, | ||
607 | ssize_t (*readfunc)(struct device *dev, | ||
608 | struct device_attribute *attr, | ||
609 | char *buf), | ||
610 | ssize_t (*writefunc)(struct device *dev, | ||
611 | struct device_attribute *attr, | ||
612 | const char *buf, | ||
613 | size_t len), | ||
614 | int mask, | ||
615 | bool generic, | ||
616 | struct device *dev, | ||
617 | struct list_head *attr_list) | ||
618 | { | ||
619 | int ret; | ||
620 | struct iio_dev_attr *iio_attr, *t; | ||
621 | |||
622 | iio_attr = kzalloc(sizeof *iio_attr, GFP_KERNEL); | ||
623 | if (iio_attr == NULL) { | ||
624 | ret = -ENOMEM; | ||
625 | goto error_ret; | ||
626 | } | ||
627 | ret = __iio_device_attr_init(&iio_attr->dev_attr, | ||
628 | postfix, chan, | ||
629 | readfunc, writefunc, generic); | ||
630 | if (ret) | ||
631 | goto error_iio_dev_attr_free; | ||
632 | iio_attr->c = chan; | ||
633 | iio_attr->address = mask; | ||
634 | list_for_each_entry(t, attr_list, l) | ||
635 | if (strcmp(t->dev_attr.attr.name, | ||
636 | iio_attr->dev_attr.attr.name) == 0) { | ||
637 | if (!generic) | ||
638 | dev_err(dev, "tried to double register : %s\n", | ||
639 | t->dev_attr.attr.name); | ||
640 | ret = -EBUSY; | ||
641 | goto error_device_attr_deinit; | ||
642 | } | ||
643 | |||
644 | ret = sysfs_add_file_to_group(&dev->kobj, | ||
645 | &iio_attr->dev_attr.attr, group); | ||
646 | if (ret < 0) | ||
647 | goto error_device_attr_deinit; | ||
648 | |||
649 | list_add(&iio_attr->l, attr_list); | ||
650 | |||
651 | return 0; | ||
652 | |||
653 | error_device_attr_deinit: | ||
654 | __iio_device_attr_deinit(&iio_attr->dev_attr); | ||
655 | error_iio_dev_attr_free: | ||
656 | kfree(iio_attr); | ||
657 | error_ret: | ||
658 | return ret; | ||
659 | } | ||
660 | |||
661 | static int iio_device_add_channel_sysfs(struct iio_dev *dev_info, | ||
662 | struct iio_chan_spec const *chan) | ||
663 | { | ||
664 | int ret, i; | ||
665 | |||
666 | |||
667 | if (chan->channel < 0) | ||
668 | return 0; | ||
669 | if (chan->processed_val) | ||
670 | ret = __iio_add_chan_devattr("input", NULL, chan, | ||
671 | &iio_read_channel_info, | ||
672 | NULL, | ||
673 | 0, | ||
674 | 0, | ||
675 | &dev_info->dev, | ||
676 | &dev_info->channel_attr_list); | ||
677 | else | ||
678 | ret = __iio_add_chan_devattr("raw", NULL, chan, | ||
679 | &iio_read_channel_info, | ||
680 | (chan->type == IIO_OUT ? | ||
681 | &iio_write_channel_info : NULL), | ||
682 | 0, | ||
683 | 0, | ||
684 | &dev_info->dev, | ||
685 | &dev_info->channel_attr_list); | ||
686 | if (ret) | ||
687 | goto error_ret; | ||
688 | |||
689 | for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) { | ||
690 | ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2], | ||
691 | NULL, chan, | ||
692 | &iio_read_channel_info, | ||
693 | &iio_write_channel_info, | ||
694 | (1 << i), | ||
695 | !(i%2), | ||
696 | &dev_info->dev, | ||
697 | &dev_info->channel_attr_list); | ||
698 | if (ret == -EBUSY && (i%2 == 0)) { | ||
699 | ret = 0; | ||
700 | continue; | ||
701 | } | ||
702 | if (ret < 0) | ||
703 | goto error_ret; | ||
704 | } | ||
705 | error_ret: | ||
706 | return ret; | ||
707 | } | ||
708 | |||
709 | static void iio_device_remove_and_free_read_attr(struct iio_dev *dev_info, | ||
710 | struct iio_dev_attr *p) | ||
711 | { | ||
712 | sysfs_remove_file_from_group(&dev_info->dev.kobj, | ||
713 | &p->dev_attr.attr, NULL); | ||
714 | kfree(p->dev_attr.attr.name); | ||
715 | kfree(p); | ||
716 | } | ||
717 | |||
718 | static ssize_t iio_show_dev_name(struct device *dev, | ||
719 | struct device_attribute *attr, | ||
720 | char *buf) | ||
721 | { | ||
722 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
723 | return sprintf(buf, "%s\n", indio_dev->name); | ||
724 | } | ||
725 | |||
726 | static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL); | ||
727 | |||
728 | static int iio_device_register_sysfs(struct iio_dev *dev_info) | ||
729 | { | ||
730 | int i, ret = 0; | ||
731 | struct iio_dev_attr *p, *n; | ||
732 | |||
733 | if (dev_info->info->attrs) { | ||
734 | ret = sysfs_create_group(&dev_info->dev.kobj, | ||
735 | dev_info->info->attrs); | ||
736 | if (ret) { | ||
737 | dev_err(dev_info->dev.parent, | ||
738 | "Failed to register sysfs hooks\n"); | ||
739 | goto error_ret; | ||
740 | } | ||
741 | } | ||
742 | |||
743 | /* | ||
744 | * New channel registration method - relies on the fact a group does | ||
745 | * not need to be initialized if it is name is NULL. | ||
746 | */ | ||
747 | INIT_LIST_HEAD(&dev_info->channel_attr_list); | ||
748 | if (dev_info->channels) | ||
749 | for (i = 0; i < dev_info->num_channels; i++) { | ||
750 | ret = iio_device_add_channel_sysfs(dev_info, | ||
751 | &dev_info | ||
752 | ->channels[i]); | ||
753 | if (ret < 0) | ||
754 | goto error_clear_attrs; | ||
755 | } | ||
756 | if (dev_info->name) { | ||
757 | ret = sysfs_add_file_to_group(&dev_info->dev.kobj, | ||
758 | &dev_attr_name.attr, | ||
759 | NULL); | ||
760 | if (ret) | ||
761 | goto error_clear_attrs; | ||
762 | } | ||
763 | return 0; | ||
764 | |||
765 | error_clear_attrs: | ||
766 | list_for_each_entry_safe(p, n, | ||
767 | &dev_info->channel_attr_list, l) { | ||
768 | list_del(&p->l); | ||
769 | iio_device_remove_and_free_read_attr(dev_info, p); | ||
770 | } | ||
771 | if (dev_info->info->attrs) | ||
772 | sysfs_remove_group(&dev_info->dev.kobj, dev_info->info->attrs); | ||
773 | error_ret: | ||
774 | return ret; | ||
775 | |||
776 | } | ||
777 | |||
778 | static void iio_device_unregister_sysfs(struct iio_dev *dev_info) | ||
779 | { | ||
780 | |||
781 | struct iio_dev_attr *p, *n; | ||
782 | if (dev_info->name) | ||
783 | sysfs_remove_file_from_group(&dev_info->dev.kobj, | ||
784 | &dev_attr_name.attr, | ||
785 | NULL); | ||
786 | list_for_each_entry_safe(p, n, &dev_info->channel_attr_list, l) { | ||
787 | list_del(&p->l); | ||
788 | iio_device_remove_and_free_read_attr(dev_info, p); | ||
789 | } | ||
790 | |||
791 | if (dev_info->info->attrs) | ||
792 | sysfs_remove_group(&dev_info->dev.kobj, dev_info->info->attrs); | ||
793 | } | ||
794 | |||
795 | /* Return a negative errno on failure */ | ||
796 | int iio_get_new_ida_val(struct ida *this_ida) | ||
797 | { | ||
798 | int ret; | ||
799 | int val; | ||
800 | |||
801 | ida_again: | ||
802 | if (unlikely(ida_pre_get(this_ida, GFP_KERNEL) == 0)) | ||
803 | return -ENOMEM; | ||
804 | |||
805 | spin_lock(&iio_ida_lock); | ||
806 | ret = ida_get_new(this_ida, &val); | ||
807 | spin_unlock(&iio_ida_lock); | ||
808 | if (unlikely(ret == -EAGAIN)) | ||
809 | goto ida_again; | ||
810 | else if (unlikely(ret)) | ||
811 | return ret; | ||
812 | |||
813 | return val; | ||
814 | } | ||
815 | EXPORT_SYMBOL(iio_get_new_ida_val); | ||
816 | |||
817 | void iio_free_ida_val(struct ida *this_ida, int id) | ||
818 | { | ||
819 | spin_lock(&iio_ida_lock); | ||
820 | ida_remove(this_ida, id); | ||
821 | spin_unlock(&iio_ida_lock); | ||
822 | } | ||
823 | EXPORT_SYMBOL(iio_free_ida_val); | ||
824 | |||
825 | static const char * const iio_ev_type_text[] = { | ||
826 | [IIO_EV_TYPE_THRESH] = "thresh", | ||
827 | [IIO_EV_TYPE_MAG] = "mag", | ||
828 | [IIO_EV_TYPE_ROC] = "roc" | ||
829 | }; | ||
830 | |||
831 | static const char * const iio_ev_dir_text[] = { | ||
832 | [IIO_EV_DIR_EITHER] = "either", | ||
833 | [IIO_EV_DIR_RISING] = "rising", | ||
834 | [IIO_EV_DIR_FALLING] = "falling" | ||
835 | }; | ||
836 | |||
837 | static ssize_t iio_ev_state_store(struct device *dev, | ||
838 | struct device_attribute *attr, | ||
839 | const char *buf, | ||
840 | size_t len) | ||
841 | { | ||
842 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
843 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
844 | int ret; | ||
845 | bool val; | ||
846 | |||
847 | ret = strtobool(buf, &val); | ||
848 | if (ret < 0) | ||
849 | return ret; | ||
850 | |||
851 | ret = indio_dev->info->write_event_config(indio_dev, | ||
852 | this_attr->address, | ||
853 | val); | ||
854 | return (ret < 0) ? ret : len; | ||
855 | } | ||
856 | |||
857 | static ssize_t iio_ev_state_show(struct device *dev, | ||
858 | struct device_attribute *attr, | ||
859 | char *buf) | ||
860 | { | ||
861 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
862 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
863 | int val = indio_dev->info->read_event_config(indio_dev, | ||
864 | this_attr->address); | ||
865 | |||
866 | if (val < 0) | ||
867 | return val; | ||
868 | else | ||
869 | return sprintf(buf, "%d\n", val); | ||
870 | } | ||
871 | |||
872 | static ssize_t iio_ev_value_show(struct device *dev, | ||
873 | struct device_attribute *attr, | ||
874 | char *buf) | ||
875 | { | ||
876 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
877 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
878 | int val, ret; | ||
879 | |||
880 | ret = indio_dev->info->read_event_value(indio_dev, | ||
881 | this_attr->address, &val); | ||
882 | if (ret < 0) | ||
883 | return ret; | ||
884 | |||
885 | return sprintf(buf, "%d\n", val); | ||
886 | } | ||
887 | |||
888 | static ssize_t iio_ev_value_store(struct device *dev, | ||
889 | struct device_attribute *attr, | ||
890 | const char *buf, | ||
891 | size_t len) | ||
892 | { | ||
893 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
894 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
895 | unsigned long val; | ||
896 | int ret; | ||
897 | |||
898 | ret = strict_strtoul(buf, 10, &val); | ||
899 | if (ret) | ||
900 | return ret; | ||
901 | |||
902 | ret = indio_dev->info->write_event_value(indio_dev, this_attr->address, | ||
903 | val); | ||
904 | if (ret < 0) | ||
905 | return ret; | ||
906 | |||
907 | return len; | ||
908 | } | ||
909 | |||
910 | static int iio_device_add_event_sysfs(struct iio_dev *dev_info, | ||
911 | struct iio_chan_spec const *chan) | ||
912 | { | ||
913 | |||
914 | int ret = 0, i, mask; | ||
915 | char *postfix; | ||
916 | if (!chan->event_mask) | ||
917 | return 0; | ||
918 | |||
919 | for_each_set_bit(i, &chan->event_mask, sizeof(chan->event_mask)*8) { | ||
920 | postfix = kasprintf(GFP_KERNEL, "%s_%s_en", | ||
921 | iio_ev_type_text[i/IIO_EV_TYPE_MAX], | ||
922 | iio_ev_dir_text[i%IIO_EV_TYPE_MAX]); | ||
923 | if (postfix == NULL) { | ||
924 | ret = -ENOMEM; | ||
925 | goto error_ret; | ||
926 | } | ||
927 | switch (chan->type) { | ||
928 | /* Switch this to a table at some point */ | ||
929 | case IIO_IN: | ||
930 | mask = IIO_UNMOD_EVENT_CODE(chan->type, chan->channel, | ||
931 | i/IIO_EV_TYPE_MAX, | ||
932 | i%IIO_EV_TYPE_MAX); | ||
933 | break; | ||
934 | case IIO_ACCEL: | ||
935 | mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel, | ||
936 | i/IIO_EV_TYPE_MAX, | ||
937 | i%IIO_EV_TYPE_MAX); | ||
938 | break; | ||
939 | case IIO_IN_DIFF: | ||
940 | mask = IIO_MOD_EVENT_CODE(chan->type, chan->channel, | ||
941 | chan->channel2, | ||
942 | i/IIO_EV_TYPE_MAX, | ||
943 | i%IIO_EV_TYPE_MAX); | ||
944 | break; | ||
945 | default: | ||
946 | printk(KERN_INFO "currently unhandled type of event\n"); | ||
947 | } | ||
948 | ret = __iio_add_chan_devattr(postfix, | ||
949 | NULL, | ||
950 | chan, | ||
951 | &iio_ev_state_show, | ||
952 | iio_ev_state_store, | ||
953 | mask, | ||
954 | /*HACK. - limits us to one | ||
955 | event interface - fix by | ||
956 | extending the bitmask - but | ||
957 | how far*/ | ||
958 | 0, | ||
959 | &dev_info->event_interfaces[0].dev, | ||
960 | &dev_info->event_interfaces[0]. | ||
961 | dev_attr_list); | ||
962 | kfree(postfix); | ||
963 | if (ret) | ||
964 | goto error_ret; | ||
965 | |||
966 | postfix = kasprintf(GFP_KERNEL, "%s_%s_value", | ||
967 | iio_ev_type_text[i/IIO_EV_TYPE_MAX], | ||
968 | iio_ev_dir_text[i%IIO_EV_TYPE_MAX]); | ||
969 | if (postfix == NULL) { | ||
970 | ret = -ENOMEM; | ||
971 | goto error_ret; | ||
972 | } | ||
973 | ret = __iio_add_chan_devattr(postfix, NULL, chan, | ||
974 | iio_ev_value_show, | ||
975 | iio_ev_value_store, | ||
976 | mask, | ||
977 | 0, | ||
978 | &dev_info->event_interfaces[0] | ||
979 | .dev, | ||
980 | &dev_info->event_interfaces[0] | ||
981 | .dev_attr_list); | ||
982 | kfree(postfix); | ||
983 | if (ret) | ||
984 | goto error_ret; | ||
985 | |||
986 | } | ||
987 | |||
988 | error_ret: | ||
989 | return ret; | ||
990 | } | ||
991 | |||
992 | static inline void __iio_remove_all_event_sysfs(struct iio_dev *dev_info, | ||
993 | const char *groupname, | ||
994 | int num) | ||
995 | { | ||
996 | struct iio_dev_attr *p, *n; | ||
997 | list_for_each_entry_safe(p, n, | ||
998 | &dev_info->event_interfaces[num]. | ||
999 | dev_attr_list, l) { | ||
1000 | sysfs_remove_file_from_group(&dev_info | ||
1001 | ->event_interfaces[num].dev.kobj, | ||
1002 | &p->dev_attr.attr, | ||
1003 | groupname); | ||
1004 | kfree(p->dev_attr.attr.name); | ||
1005 | kfree(p); | ||
1006 | } | ||
1007 | } | ||
1008 | |||
1009 | static inline int __iio_add_event_config_attrs(struct iio_dev *dev_info, int i) | ||
1010 | { | ||
1011 | int j; | ||
1012 | int ret; | ||
1013 | INIT_LIST_HEAD(&dev_info->event_interfaces[0].dev_attr_list); | ||
1014 | /* Dynically created from the channels array */ | ||
1015 | if (dev_info->channels) { | ||
1016 | for (j = 0; j < dev_info->num_channels; j++) { | ||
1017 | ret = iio_device_add_event_sysfs(dev_info, | ||
1018 | &dev_info | ||
1019 | ->channels[j]); | ||
1020 | if (ret) | ||
1021 | goto error_clear_attrs; | ||
1022 | } | ||
1023 | } | ||
1024 | return 0; | ||
1025 | |||
1026 | error_clear_attrs: | ||
1027 | __iio_remove_all_event_sysfs(dev_info, NULL, i); | ||
1028 | |||
1029 | return ret; | ||
1030 | } | ||
1031 | |||
1032 | static inline int __iio_remove_event_config_attrs(struct iio_dev *dev_info, | ||
1033 | int i) | ||
1034 | { | ||
1035 | __iio_remove_all_event_sysfs(dev_info, NULL, i); | ||
1036 | return 0; | ||
1037 | } | ||
1038 | |||
1039 | static int iio_device_register_eventset(struct iio_dev *dev_info) | ||
1040 | { | ||
1041 | int ret = 0, i, j; | ||
1042 | |||
1043 | if (dev_info->info->num_interrupt_lines == 0) | ||
1044 | return 0; | ||
1045 | |||
1046 | dev_info->event_interfaces = | ||
1047 | kzalloc(sizeof(struct iio_event_interface) | ||
1048 | *dev_info->info->num_interrupt_lines, | ||
1049 | GFP_KERNEL); | ||
1050 | if (dev_info->event_interfaces == NULL) { | ||
1051 | ret = -ENOMEM; | ||
1052 | goto error_ret; | ||
1053 | } | ||
1054 | |||
1055 | for (i = 0; i < dev_info->info->num_interrupt_lines; i++) { | ||
1056 | ret = iio_setup_ev_int(&dev_info->event_interfaces[i], | ||
1057 | dev_name(&dev_info->dev), | ||
1058 | i, | ||
1059 | dev_info->info->driver_module, | ||
1060 | &dev_info->dev); | ||
1061 | if (ret) { | ||
1062 | dev_err(&dev_info->dev, | ||
1063 | "Could not get chrdev interface\n"); | ||
1064 | goto error_free_setup_ev_ints; | ||
1065 | } | ||
1066 | |||
1067 | dev_set_drvdata(&dev_info->event_interfaces[i].dev, | ||
1068 | (void *)dev_info); | ||
1069 | |||
1070 | if (dev_info->info->event_attrs != NULL) | ||
1071 | ret = sysfs_create_group(&dev_info | ||
1072 | ->event_interfaces[i] | ||
1073 | .dev.kobj, | ||
1074 | &dev_info->info | ||
1075 | ->event_attrs[i]); | ||
1076 | |||
1077 | if (ret) { | ||
1078 | dev_err(&dev_info->dev, | ||
1079 | "Failed to register sysfs for event attrs"); | ||
1080 | goto error_remove_sysfs_interfaces; | ||
1081 | } | ||
1082 | } | ||
1083 | |||
1084 | for (i = 0; i < dev_info->info->num_interrupt_lines; i++) { | ||
1085 | ret = __iio_add_event_config_attrs(dev_info, i); | ||
1086 | if (ret) | ||
1087 | goto error_unregister_config_attrs; | ||
1088 | } | ||
1089 | |||
1090 | return 0; | ||
1091 | |||
1092 | error_unregister_config_attrs: | ||
1093 | for (j = 0; j < i; j++) | ||
1094 | __iio_remove_event_config_attrs(dev_info, i); | ||
1095 | i = dev_info->info->num_interrupt_lines - 1; | ||
1096 | error_remove_sysfs_interfaces: | ||
1097 | for (j = 0; j < i; j++) | ||
1098 | if (dev_info->info->event_attrs != NULL) | ||
1099 | sysfs_remove_group(&dev_info | ||
1100 | ->event_interfaces[j].dev.kobj, | ||
1101 | &dev_info->info->event_attrs[j]); | ||
1102 | error_free_setup_ev_ints: | ||
1103 | for (j = 0; j < i; j++) | ||
1104 | iio_free_ev_int(&dev_info->event_interfaces[j]); | ||
1105 | kfree(dev_info->event_interfaces); | ||
1106 | error_ret: | ||
1107 | |||
1108 | return ret; | ||
1109 | } | ||
1110 | |||
1111 | static void iio_device_unregister_eventset(struct iio_dev *dev_info) | ||
1112 | { | ||
1113 | int i; | ||
1114 | |||
1115 | if (dev_info->info->num_interrupt_lines == 0) | ||
1116 | return; | ||
1117 | for (i = 0; i < dev_info->info->num_interrupt_lines; i++) { | ||
1118 | __iio_remove_event_config_attrs(dev_info, i); | ||
1119 | if (dev_info->info->event_attrs != NULL) | ||
1120 | sysfs_remove_group(&dev_info | ||
1121 | ->event_interfaces[i].dev.kobj, | ||
1122 | &dev_info->info->event_attrs[i]); | ||
1123 | } | ||
1124 | |||
1125 | for (i = 0; i < dev_info->info->num_interrupt_lines; i++) | ||
1126 | iio_free_ev_int(&dev_info->event_interfaces[i]); | ||
1127 | kfree(dev_info->event_interfaces); | ||
1128 | } | ||
1129 | |||
1130 | static void iio_dev_release(struct device *device) | ||
1131 | { | ||
1132 | iio_put(); | ||
1133 | kfree(to_iio_dev(device)); | ||
1134 | } | ||
1135 | |||
1136 | static struct device_type iio_dev_type = { | ||
1137 | .name = "iio_device", | ||
1138 | .release = iio_dev_release, | ||
1139 | }; | ||
1140 | |||
1141 | struct iio_dev *iio_allocate_device(int sizeof_priv) | ||
1142 | { | ||
1143 | struct iio_dev *dev; | ||
1144 | size_t alloc_size; | ||
1145 | |||
1146 | alloc_size = sizeof(struct iio_dev); | ||
1147 | if (sizeof_priv) { | ||
1148 | alloc_size = ALIGN(alloc_size, IIO_ALIGN); | ||
1149 | alloc_size += sizeof_priv; | ||
1150 | } | ||
1151 | /* ensure 32-byte alignment of whole construct ? */ | ||
1152 | alloc_size += IIO_ALIGN - 1; | ||
1153 | |||
1154 | dev = kzalloc(alloc_size, GFP_KERNEL); | ||
1155 | |||
1156 | if (dev) { | ||
1157 | dev->dev.type = &iio_dev_type; | ||
1158 | dev->dev.bus = &iio_bus_type; | ||
1159 | device_initialize(&dev->dev); | ||
1160 | dev_set_drvdata(&dev->dev, (void *)dev); | ||
1161 | mutex_init(&dev->mlock); | ||
1162 | iio_get(); | ||
1163 | } | ||
1164 | |||
1165 | return dev; | ||
1166 | } | ||
1167 | EXPORT_SYMBOL(iio_allocate_device); | ||
1168 | |||
1169 | void iio_free_device(struct iio_dev *dev) | ||
1170 | { | ||
1171 | if (dev) | ||
1172 | iio_put_device(dev); | ||
1173 | } | ||
1174 | EXPORT_SYMBOL(iio_free_device); | ||
1175 | |||
1176 | int iio_device_register(struct iio_dev *dev_info) | ||
1177 | { | ||
1178 | int ret; | ||
1179 | |||
1180 | dev_info->id = iio_get_new_ida_val(&iio_ida); | ||
1181 | if (dev_info->id < 0) { | ||
1182 | ret = dev_info->id; | ||
1183 | dev_err(&dev_info->dev, "Failed to get id\n"); | ||
1184 | goto error_ret; | ||
1185 | } | ||
1186 | dev_set_name(&dev_info->dev, "device%d", dev_info->id); | ||
1187 | |||
1188 | ret = device_add(&dev_info->dev); | ||
1189 | if (ret) | ||
1190 | goto error_free_ida; | ||
1191 | ret = iio_device_register_sysfs(dev_info); | ||
1192 | if (ret) { | ||
1193 | dev_err(dev_info->dev.parent, | ||
1194 | "Failed to register sysfs interfaces\n"); | ||
1195 | goto error_del_device; | ||
1196 | } | ||
1197 | ret = iio_device_register_eventset(dev_info); | ||
1198 | if (ret) { | ||
1199 | dev_err(dev_info->dev.parent, | ||
1200 | "Failed to register event set\n"); | ||
1201 | goto error_free_sysfs; | ||
1202 | } | ||
1203 | if (dev_info->modes & INDIO_RING_TRIGGERED) | ||
1204 | iio_device_register_trigger_consumer(dev_info); | ||
1205 | |||
1206 | return 0; | ||
1207 | |||
1208 | error_free_sysfs: | ||
1209 | iio_device_unregister_sysfs(dev_info); | ||
1210 | error_del_device: | ||
1211 | device_del(&dev_info->dev); | ||
1212 | error_free_ida: | ||
1213 | iio_free_ida_val(&iio_ida, dev_info->id); | ||
1214 | error_ret: | ||
1215 | return ret; | ||
1216 | } | ||
1217 | EXPORT_SYMBOL(iio_device_register); | ||
1218 | |||
1219 | void iio_device_unregister(struct iio_dev *dev_info) | ||
1220 | { | ||
1221 | if (dev_info->modes & INDIO_RING_TRIGGERED) | ||
1222 | iio_device_unregister_trigger_consumer(dev_info); | ||
1223 | iio_device_unregister_eventset(dev_info); | ||
1224 | iio_device_unregister_sysfs(dev_info); | ||
1225 | iio_free_ida_val(&iio_ida, dev_info->id); | ||
1226 | device_unregister(&dev_info->dev); | ||
1227 | } | ||
1228 | EXPORT_SYMBOL(iio_device_unregister); | ||
1229 | |||
1230 | void iio_put(void) | ||
1231 | { | ||
1232 | module_put(THIS_MODULE); | ||
1233 | } | ||
1234 | |||
1235 | void iio_get(void) | ||
1236 | { | ||
1237 | __module_get(THIS_MODULE); | ||
1238 | } | ||
1239 | |||
1240 | subsys_initcall(iio_init); | ||
1241 | module_exit(iio_exit); | ||
1242 | |||
1243 | MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); | ||
1244 | MODULE_DESCRIPTION("Industrial I/O core"); | ||
1245 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/iio/industrialio-ring.c b/drivers/staging/iio/industrialio-ring.c new file mode 100644 index 00000000000..843eb82a69b --- /dev/null +++ b/drivers/staging/iio/industrialio-ring.c | |||
@@ -0,0 +1,596 @@ | |||
1 | /* The industrial I/O core | ||
2 | * | ||
3 | * Copyright (c) 2008 Jonathan Cameron | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 2 as published by | ||
7 | * the Free Software Foundation. | ||
8 | * | ||
9 | * Handling of ring allocation / resizing. | ||
10 | * | ||
11 | * | ||
12 | * Things to look at here. | ||
13 | * - Better memory allocation techniques? | ||
14 | * - Alternative access techniques? | ||
15 | */ | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/cdev.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/poll.h> | ||
22 | |||
23 | #include "iio.h" | ||
24 | #include "ring_generic.h" | ||
25 | |||
26 | /** | ||
27 | * iio_ring_open() - chrdev file open for ring buffer access | ||
28 | * | ||
29 | * This function relies on all ring buffer implementations having an | ||
30 | * iio_ring_buffer as their first element. | ||
31 | **/ | ||
32 | static int iio_ring_open(struct inode *inode, struct file *filp) | ||
33 | { | ||
34 | struct iio_handler *hand | ||
35 | = container_of(inode->i_cdev, struct iio_handler, chrdev); | ||
36 | struct iio_ring_buffer *rb = hand->private; | ||
37 | |||
38 | filp->private_data = hand->private; | ||
39 | if (rb->access->mark_in_use) | ||
40 | rb->access->mark_in_use(rb); | ||
41 | |||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | /** | ||
46 | * iio_ring_release() - chrdev file close ring buffer access | ||
47 | * | ||
48 | * This function relies on all ring buffer implementations having an | ||
49 | * iio_ring_buffer as their first element. | ||
50 | **/ | ||
51 | static int iio_ring_release(struct inode *inode, struct file *filp) | ||
52 | { | ||
53 | struct cdev *cd = inode->i_cdev; | ||
54 | struct iio_handler *hand = iio_cdev_to_handler(cd); | ||
55 | struct iio_ring_buffer *rb = hand->private; | ||
56 | |||
57 | clear_bit(IIO_BUSY_BIT_POS, &rb->access_handler.flags); | ||
58 | if (rb->access->unmark_in_use) | ||
59 | rb->access->unmark_in_use(rb); | ||
60 | |||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | /** | ||
65 | * iio_ring_read_first_n_outer() - chrdev read for ring buffer access | ||
66 | * | ||
67 | * This function relies on all ring buffer implementations having an | ||
68 | * iio_ring _bufer as their first element. | ||
69 | **/ | ||
70 | static ssize_t iio_ring_read_first_n_outer(struct file *filp, char __user *buf, | ||
71 | size_t n, loff_t *f_ps) | ||
72 | { | ||
73 | struct iio_ring_buffer *rb = filp->private_data; | ||
74 | |||
75 | if (!rb->access->read_first_n) | ||
76 | return -EINVAL; | ||
77 | return rb->access->read_first_n(rb, n, buf); | ||
78 | } | ||
79 | |||
80 | /** | ||
81 | * iio_ring_poll() - poll the ring to find out if it has data | ||
82 | */ | ||
83 | static unsigned int iio_ring_poll(struct file *filp, | ||
84 | struct poll_table_struct *wait) | ||
85 | { | ||
86 | struct iio_ring_buffer *rb = filp->private_data; | ||
87 | |||
88 | poll_wait(filp, &rb->pollq, wait); | ||
89 | if (rb->stufftoread) | ||
90 | return POLLIN | POLLRDNORM; | ||
91 | /* need a way of knowing if there may be enough data... */ | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static const struct file_operations iio_ring_fileops = { | ||
96 | .read = iio_ring_read_first_n_outer, | ||
97 | .release = iio_ring_release, | ||
98 | .open = iio_ring_open, | ||
99 | .poll = iio_ring_poll, | ||
100 | .owner = THIS_MODULE, | ||
101 | .llseek = noop_llseek, | ||
102 | }; | ||
103 | |||
104 | void iio_ring_access_release(struct device *dev) | ||
105 | { | ||
106 | struct iio_ring_buffer *buf | ||
107 | = container_of(dev, struct iio_ring_buffer, dev); | ||
108 | cdev_del(&buf->access_handler.chrdev); | ||
109 | iio_device_free_chrdev_minor(MINOR(dev->devt)); | ||
110 | } | ||
111 | EXPORT_SYMBOL(iio_ring_access_release); | ||
112 | |||
113 | static inline int | ||
114 | __iio_request_ring_buffer_chrdev(struct iio_ring_buffer *buf, | ||
115 | struct module *owner, | ||
116 | int id) | ||
117 | { | ||
118 | int ret; | ||
119 | |||
120 | buf->access_handler.flags = 0; | ||
121 | buf->dev.bus = &iio_bus_type; | ||
122 | device_initialize(&buf->dev); | ||
123 | |||
124 | ret = iio_device_get_chrdev_minor(); | ||
125 | if (ret < 0) | ||
126 | goto error_device_put; | ||
127 | |||
128 | buf->dev.devt = MKDEV(MAJOR(iio_devt), ret); | ||
129 | dev_set_name(&buf->dev, "%s:buffer%d", | ||
130 | dev_name(buf->dev.parent), | ||
131 | id); | ||
132 | ret = device_add(&buf->dev); | ||
133 | if (ret < 0) { | ||
134 | printk(KERN_ERR "failed to add the ring dev\n"); | ||
135 | goto error_device_put; | ||
136 | } | ||
137 | cdev_init(&buf->access_handler.chrdev, &iio_ring_fileops); | ||
138 | buf->access_handler.chrdev.owner = owner; | ||
139 | ret = cdev_add(&buf->access_handler.chrdev, buf->dev.devt, 1); | ||
140 | if (ret) { | ||
141 | printk(KERN_ERR "failed to allocate ring chrdev\n"); | ||
142 | goto error_device_unregister; | ||
143 | } | ||
144 | return 0; | ||
145 | |||
146 | error_device_unregister: | ||
147 | device_unregister(&buf->dev); | ||
148 | error_device_put: | ||
149 | put_device(&buf->dev); | ||
150 | |||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | static void __iio_free_ring_buffer_chrdev(struct iio_ring_buffer *buf) | ||
155 | { | ||
156 | device_unregister(&buf->dev); | ||
157 | } | ||
158 | |||
159 | void iio_ring_buffer_init(struct iio_ring_buffer *ring, | ||
160 | struct iio_dev *dev_info) | ||
161 | { | ||
162 | ring->indio_dev = dev_info; | ||
163 | ring->access_handler.private = ring; | ||
164 | init_waitqueue_head(&ring->pollq); | ||
165 | } | ||
166 | EXPORT_SYMBOL(iio_ring_buffer_init); | ||
167 | |||
168 | static ssize_t iio_show_scan_index(struct device *dev, | ||
169 | struct device_attribute *attr, | ||
170 | char *buf) | ||
171 | { | ||
172 | return sprintf(buf, "%u\n", to_iio_dev_attr(attr)->c->scan_index); | ||
173 | } | ||
174 | |||
175 | static ssize_t iio_show_fixed_type(struct device *dev, | ||
176 | struct device_attribute *attr, | ||
177 | char *buf) | ||
178 | { | ||
179 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
180 | return sprintf(buf, "%c%d/%d>>%u\n", | ||
181 | this_attr->c->scan_type.sign, | ||
182 | this_attr->c->scan_type.realbits, | ||
183 | this_attr->c->scan_type.storagebits, | ||
184 | this_attr->c->scan_type.shift); | ||
185 | } | ||
186 | |||
187 | static ssize_t iio_scan_el_show(struct device *dev, | ||
188 | struct device_attribute *attr, | ||
189 | char *buf) | ||
190 | { | ||
191 | int ret; | ||
192 | struct iio_ring_buffer *ring = dev_get_drvdata(dev); | ||
193 | |||
194 | ret = iio_scan_mask_query(ring, to_iio_dev_attr(attr)->address); | ||
195 | if (ret < 0) | ||
196 | return ret; | ||
197 | return sprintf(buf, "%d\n", ret); | ||
198 | } | ||
199 | |||
200 | static int iio_scan_mask_clear(struct iio_ring_buffer *ring, int bit) | ||
201 | { | ||
202 | if (bit > IIO_MAX_SCAN_LENGTH) | ||
203 | return -EINVAL; | ||
204 | ring->scan_mask &= ~(1 << bit); | ||
205 | ring->scan_count--; | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static ssize_t iio_scan_el_store(struct device *dev, | ||
210 | struct device_attribute *attr, | ||
211 | const char *buf, | ||
212 | size_t len) | ||
213 | { | ||
214 | int ret = 0; | ||
215 | bool state; | ||
216 | struct iio_ring_buffer *ring = dev_get_drvdata(dev); | ||
217 | struct iio_dev *indio_dev = ring->indio_dev; | ||
218 | struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); | ||
219 | |||
220 | state = !(buf[0] == '0'); | ||
221 | mutex_lock(&indio_dev->mlock); | ||
222 | if (indio_dev->currentmode == INDIO_RING_TRIGGERED) { | ||
223 | ret = -EBUSY; | ||
224 | goto error_ret; | ||
225 | } | ||
226 | ret = iio_scan_mask_query(ring, this_attr->address); | ||
227 | if (ret < 0) | ||
228 | goto error_ret; | ||
229 | if (!state && ret) { | ||
230 | ret = iio_scan_mask_clear(ring, this_attr->address); | ||
231 | if (ret) | ||
232 | goto error_ret; | ||
233 | } else if (state && !ret) { | ||
234 | ret = iio_scan_mask_set(ring, this_attr->address); | ||
235 | if (ret) | ||
236 | goto error_ret; | ||
237 | } | ||
238 | |||
239 | error_ret: | ||
240 | mutex_unlock(&indio_dev->mlock); | ||
241 | |||
242 | return ret ? ret : len; | ||
243 | |||
244 | } | ||
245 | |||
246 | static ssize_t iio_scan_el_ts_show(struct device *dev, | ||
247 | struct device_attribute *attr, | ||
248 | char *buf) | ||
249 | { | ||
250 | struct iio_ring_buffer *ring = dev_get_drvdata(dev); | ||
251 | return sprintf(buf, "%d\n", ring->scan_timestamp); | ||
252 | } | ||
253 | |||
254 | static ssize_t iio_scan_el_ts_store(struct device *dev, | ||
255 | struct device_attribute *attr, | ||
256 | const char *buf, | ||
257 | size_t len) | ||
258 | { | ||
259 | int ret = 0; | ||
260 | struct iio_ring_buffer *ring = dev_get_drvdata(dev); | ||
261 | struct iio_dev *indio_dev = ring->indio_dev; | ||
262 | bool state; | ||
263 | state = !(buf[0] == '0'); | ||
264 | mutex_lock(&indio_dev->mlock); | ||
265 | if (indio_dev->currentmode == INDIO_RING_TRIGGERED) { | ||
266 | ret = -EBUSY; | ||
267 | goto error_ret; | ||
268 | } | ||
269 | ring->scan_timestamp = state; | ||
270 | error_ret: | ||
271 | mutex_unlock(&indio_dev->mlock); | ||
272 | |||
273 | return ret ? ret : len; | ||
274 | } | ||
275 | |||
276 | static int iio_ring_add_channel_sysfs(struct iio_ring_buffer *ring, | ||
277 | const struct iio_chan_spec *chan) | ||
278 | { | ||
279 | int ret; | ||
280 | |||
281 | ret = __iio_add_chan_devattr("index", "scan_elements", | ||
282 | chan, | ||
283 | &iio_show_scan_index, | ||
284 | NULL, | ||
285 | 0, | ||
286 | 0, | ||
287 | &ring->dev, | ||
288 | &ring->scan_el_dev_attr_list); | ||
289 | if (ret) | ||
290 | goto error_ret; | ||
291 | |||
292 | ret = __iio_add_chan_devattr("type", "scan_elements", | ||
293 | chan, | ||
294 | &iio_show_fixed_type, | ||
295 | NULL, | ||
296 | 0, | ||
297 | 0, | ||
298 | &ring->dev, | ||
299 | &ring->scan_el_dev_attr_list); | ||
300 | if (ret) | ||
301 | goto error_ret; | ||
302 | |||
303 | if (chan->type != IIO_TIMESTAMP) | ||
304 | ret = __iio_add_chan_devattr("en", "scan_elements", | ||
305 | chan, | ||
306 | &iio_scan_el_show, | ||
307 | &iio_scan_el_store, | ||
308 | chan->scan_index, | ||
309 | 0, | ||
310 | &ring->dev, | ||
311 | &ring->scan_el_dev_attr_list); | ||
312 | else | ||
313 | ret = __iio_add_chan_devattr("en", "scan_elements", | ||
314 | chan, | ||
315 | &iio_scan_el_ts_show, | ||
316 | &iio_scan_el_ts_store, | ||
317 | chan->scan_index, | ||
318 | 0, | ||
319 | &ring->dev, | ||
320 | &ring->scan_el_dev_attr_list); | ||
321 | error_ret: | ||
322 | return ret; | ||
323 | } | ||
324 | |||
325 | static void iio_ring_remove_and_free_scan_dev_attr(struct iio_ring_buffer *ring, | ||
326 | struct iio_dev_attr *p) | ||
327 | { | ||
328 | sysfs_remove_file_from_group(&ring->dev.kobj, | ||
329 | &p->dev_attr.attr, "scan_elements"); | ||
330 | kfree(p->dev_attr.attr.name); | ||
331 | kfree(p); | ||
332 | } | ||
333 | |||
334 | static struct attribute *iio_scan_el_dummy_attrs[] = { | ||
335 | NULL | ||
336 | }; | ||
337 | |||
338 | static struct attribute_group iio_scan_el_dummy_group = { | ||
339 | .name = "scan_elements", | ||
340 | .attrs = iio_scan_el_dummy_attrs | ||
341 | }; | ||
342 | |||
343 | static void __iio_ring_attr_cleanup(struct iio_ring_buffer *ring) | ||
344 | { | ||
345 | struct iio_dev_attr *p, *n; | ||
346 | int anydynamic = !list_empty(&ring->scan_el_dev_attr_list); | ||
347 | list_for_each_entry_safe(p, n, | ||
348 | &ring->scan_el_dev_attr_list, l) | ||
349 | iio_ring_remove_and_free_scan_dev_attr(ring, p); | ||
350 | |||
351 | if (ring->scan_el_attrs) | ||
352 | sysfs_remove_group(&ring->dev.kobj, | ||
353 | ring->scan_el_attrs); | ||
354 | else if (anydynamic) | ||
355 | sysfs_remove_group(&ring->dev.kobj, | ||
356 | &iio_scan_el_dummy_group); | ||
357 | } | ||
358 | |||
359 | int iio_ring_buffer_register_ex(struct iio_ring_buffer *ring, int id, | ||
360 | const struct iio_chan_spec *channels, | ||
361 | int num_channels) | ||
362 | { | ||
363 | int ret, i; | ||
364 | |||
365 | ret = __iio_request_ring_buffer_chrdev(ring, ring->owner, id); | ||
366 | if (ret) | ||
367 | goto error_ret; | ||
368 | |||
369 | if (ring->scan_el_attrs) { | ||
370 | ret = sysfs_create_group(&ring->dev.kobj, | ||
371 | ring->scan_el_attrs); | ||
372 | if (ret) { | ||
373 | dev_err(&ring->dev, | ||
374 | "Failed to add sysfs scan elements\n"); | ||
375 | goto error_free_ring_buffer_chrdev; | ||
376 | } | ||
377 | } else if (channels) { | ||
378 | ret = sysfs_create_group(&ring->dev.kobj, | ||
379 | &iio_scan_el_dummy_group); | ||
380 | if (ret) | ||
381 | goto error_free_ring_buffer_chrdev; | ||
382 | } | ||
383 | |||
384 | INIT_LIST_HEAD(&ring->scan_el_dev_attr_list); | ||
385 | if (channels) { | ||
386 | /* new magic */ | ||
387 | for (i = 0; i < num_channels; i++) { | ||
388 | ret = iio_ring_add_channel_sysfs(ring, &channels[i]); | ||
389 | if (ret < 0) | ||
390 | goto error_cleanup_dynamic; | ||
391 | } | ||
392 | } | ||
393 | |||
394 | return 0; | ||
395 | error_cleanup_dynamic: | ||
396 | __iio_ring_attr_cleanup(ring); | ||
397 | error_free_ring_buffer_chrdev: | ||
398 | __iio_free_ring_buffer_chrdev(ring); | ||
399 | error_ret: | ||
400 | return ret; | ||
401 | } | ||
402 | EXPORT_SYMBOL(iio_ring_buffer_register_ex); | ||
403 | |||
404 | void iio_ring_buffer_unregister(struct iio_ring_buffer *ring) | ||
405 | { | ||
406 | __iio_ring_attr_cleanup(ring); | ||
407 | __iio_free_ring_buffer_chrdev(ring); | ||
408 | } | ||
409 | EXPORT_SYMBOL(iio_ring_buffer_unregister); | ||
410 | |||
411 | ssize_t iio_read_ring_length(struct device *dev, | ||
412 | struct device_attribute *attr, | ||
413 | char *buf) | ||
414 | { | ||
415 | struct iio_ring_buffer *ring = dev_get_drvdata(dev); | ||
416 | |||
417 | if (ring->access->get_length) | ||
418 | return sprintf(buf, "%d\n", | ||
419 | ring->access->get_length(ring)); | ||
420 | |||
421 | return 0; | ||
422 | } | ||
423 | EXPORT_SYMBOL(iio_read_ring_length); | ||
424 | |||
425 | ssize_t iio_write_ring_length(struct device *dev, | ||
426 | struct device_attribute *attr, | ||
427 | const char *buf, | ||
428 | size_t len) | ||
429 | { | ||
430 | int ret; | ||
431 | ulong val; | ||
432 | struct iio_ring_buffer *ring = dev_get_drvdata(dev); | ||
433 | |||
434 | ret = strict_strtoul(buf, 10, &val); | ||
435 | if (ret) | ||
436 | return ret; | ||
437 | |||
438 | if (ring->access->get_length) | ||
439 | if (val == ring->access->get_length(ring)) | ||
440 | return len; | ||
441 | |||
442 | if (ring->access->set_length) { | ||
443 | ring->access->set_length(ring, val); | ||
444 | if (ring->access->mark_param_change) | ||
445 | ring->access->mark_param_change(ring); | ||
446 | } | ||
447 | |||
448 | return len; | ||
449 | } | ||
450 | EXPORT_SYMBOL(iio_write_ring_length); | ||
451 | |||
452 | ssize_t iio_read_ring_bytes_per_datum(struct device *dev, | ||
453 | struct device_attribute *attr, | ||
454 | char *buf) | ||
455 | { | ||
456 | struct iio_ring_buffer *ring = dev_get_drvdata(dev); | ||
457 | |||
458 | if (ring->access->get_bytes_per_datum) | ||
459 | return sprintf(buf, "%d\n", | ||
460 | ring->access->get_bytes_per_datum(ring)); | ||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | EXPORT_SYMBOL(iio_read_ring_bytes_per_datum); | ||
465 | |||
466 | ssize_t iio_store_ring_enable(struct device *dev, | ||
467 | struct device_attribute *attr, | ||
468 | const char *buf, | ||
469 | size_t len) | ||
470 | { | ||
471 | int ret; | ||
472 | bool requested_state, current_state; | ||
473 | int previous_mode; | ||
474 | struct iio_ring_buffer *ring = dev_get_drvdata(dev); | ||
475 | struct iio_dev *dev_info = ring->indio_dev; | ||
476 | |||
477 | mutex_lock(&dev_info->mlock); | ||
478 | previous_mode = dev_info->currentmode; | ||
479 | requested_state = !(buf[0] == '0'); | ||
480 | current_state = !!(previous_mode & INDIO_ALL_RING_MODES); | ||
481 | if (current_state == requested_state) { | ||
482 | printk(KERN_INFO "iio-ring, current state requested again\n"); | ||
483 | goto done; | ||
484 | } | ||
485 | if (requested_state) { | ||
486 | if (ring->setup_ops->preenable) { | ||
487 | ret = ring->setup_ops->preenable(dev_info); | ||
488 | if (ret) { | ||
489 | printk(KERN_ERR | ||
490 | "Buffer not started:" | ||
491 | "ring preenable failed\n"); | ||
492 | goto error_ret; | ||
493 | } | ||
494 | } | ||
495 | if (ring->access->request_update) { | ||
496 | ret = ring->access->request_update(ring); | ||
497 | if (ret) { | ||
498 | printk(KERN_INFO | ||
499 | "Buffer not started:" | ||
500 | "ring parameter update failed\n"); | ||
501 | goto error_ret; | ||
502 | } | ||
503 | } | ||
504 | if (ring->access->mark_in_use) | ||
505 | ring->access->mark_in_use(ring); | ||
506 | /* Definitely possible for devices to support both of these.*/ | ||
507 | if (dev_info->modes & INDIO_RING_TRIGGERED) { | ||
508 | if (!dev_info->trig) { | ||
509 | printk(KERN_INFO | ||
510 | "Buffer not started: no trigger\n"); | ||
511 | ret = -EINVAL; | ||
512 | if (ring->access->unmark_in_use) | ||
513 | ring->access->unmark_in_use(ring); | ||
514 | goto error_ret; | ||
515 | } | ||
516 | dev_info->currentmode = INDIO_RING_TRIGGERED; | ||
517 | } else if (dev_info->modes & INDIO_RING_HARDWARE_BUFFER) | ||
518 | dev_info->currentmode = INDIO_RING_HARDWARE_BUFFER; | ||
519 | else { /* should never be reached */ | ||
520 | ret = -EINVAL; | ||
521 | goto error_ret; | ||
522 | } | ||
523 | |||
524 | if (ring->setup_ops->postenable) { | ||
525 | ret = ring->setup_ops->postenable(dev_info); | ||
526 | if (ret) { | ||
527 | printk(KERN_INFO | ||
528 | "Buffer not started:" | ||
529 | "postenable failed\n"); | ||
530 | if (ring->access->unmark_in_use) | ||
531 | ring->access->unmark_in_use(ring); | ||
532 | dev_info->currentmode = previous_mode; | ||
533 | if (ring->setup_ops->postdisable) | ||
534 | ring->setup_ops->postdisable(dev_info); | ||
535 | goto error_ret; | ||
536 | } | ||
537 | } | ||
538 | } else { | ||
539 | if (ring->setup_ops->predisable) { | ||
540 | ret = ring->setup_ops->predisable(dev_info); | ||
541 | if (ret) | ||
542 | goto error_ret; | ||
543 | } | ||
544 | if (ring->access->unmark_in_use) | ||
545 | ring->access->unmark_in_use(ring); | ||
546 | dev_info->currentmode = INDIO_DIRECT_MODE; | ||
547 | if (ring->setup_ops->postdisable) { | ||
548 | ret = ring->setup_ops->postdisable(dev_info); | ||
549 | if (ret) | ||
550 | goto error_ret; | ||
551 | } | ||
552 | } | ||
553 | done: | ||
554 | mutex_unlock(&dev_info->mlock); | ||
555 | return len; | ||
556 | |||
557 | error_ret: | ||
558 | mutex_unlock(&dev_info->mlock); | ||
559 | return ret; | ||
560 | } | ||
561 | EXPORT_SYMBOL(iio_store_ring_enable); | ||
562 | |||
563 | ssize_t iio_show_ring_enable(struct device *dev, | ||
564 | struct device_attribute *attr, | ||
565 | char *buf) | ||
566 | { | ||
567 | struct iio_ring_buffer *ring = dev_get_drvdata(dev); | ||
568 | return sprintf(buf, "%d\n", !!(ring->indio_dev->currentmode | ||
569 | & INDIO_ALL_RING_MODES)); | ||
570 | } | ||
571 | EXPORT_SYMBOL(iio_show_ring_enable); | ||
572 | |||
573 | int iio_sw_ring_preenable(struct iio_dev *indio_dev) | ||
574 | { | ||
575 | struct iio_ring_buffer *ring = indio_dev->ring; | ||
576 | size_t size; | ||
577 | dev_dbg(&indio_dev->dev, "%s\n", __func__); | ||
578 | /* Check if there are any scan elements enabled, if not fail*/ | ||
579 | if (!(ring->scan_count || ring->scan_timestamp)) | ||
580 | return -EINVAL; | ||
581 | if (ring->scan_timestamp) | ||
582 | if (ring->scan_count) | ||
583 | /* Timestamp (aligned to s64) and data */ | ||
584 | size = (((ring->scan_count * ring->bpe) | ||
585 | + sizeof(s64) - 1) | ||
586 | & ~(sizeof(s64) - 1)) | ||
587 | + sizeof(s64); | ||
588 | else /* Timestamp only */ | ||
589 | size = sizeof(s64); | ||
590 | else /* Data only */ | ||
591 | size = ring->scan_count * ring->bpe; | ||
592 | ring->access->set_bytes_per_datum(ring, size); | ||
593 | |||
594 | return 0; | ||
595 | } | ||
596 | EXPORT_SYMBOL(iio_sw_ring_preenable); | ||
diff --git a/drivers/staging/iio/industrialio-trigger.c b/drivers/staging/iio/industrialio-trigger.c new file mode 100644 index 00000000000..90ca2df23ea --- /dev/null +++ b/drivers/staging/iio/industrialio-trigger.c | |||
@@ -0,0 +1,525 @@ | |||
1 | /* The industrial I/O core, trigger handling functions | ||
2 | * | ||
3 | * Copyright (c) 2008 Jonathan Cameron | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 2 as published by | ||
7 | * the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/idr.h> | ||
13 | #include <linux/err.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/list.h> | ||
17 | #include <linux/slab.h> | ||
18 | |||
19 | #include "iio.h" | ||
20 | #include "trigger.h" | ||
21 | #include "trigger_consumer.h" | ||
22 | |||
23 | /* RFC - Question of approach | ||
24 | * Make the common case (single sensor single trigger) | ||
25 | * simple by starting trigger capture from when first sensors | ||
26 | * is added. | ||
27 | * | ||
28 | * Complex simultaneous start requires use of 'hold' functionality | ||
29 | * of the trigger. (not implemented) | ||
30 | * | ||
31 | * Any other suggestions? | ||
32 | */ | ||
33 | |||
34 | static DEFINE_IDR(iio_trigger_idr); | ||
35 | static DEFINE_SPINLOCK(iio_trigger_idr_lock); | ||
36 | |||
37 | /* Single list of all available triggers */ | ||
38 | static LIST_HEAD(iio_trigger_list); | ||
39 | static DEFINE_MUTEX(iio_trigger_list_lock); | ||
40 | |||
41 | /** | ||
42 | * iio_trigger_read_name() - retrieve useful identifying name | ||
43 | **/ | ||
44 | static ssize_t iio_trigger_read_name(struct device *dev, | ||
45 | struct device_attribute *attr, | ||
46 | char *buf) | ||
47 | { | ||
48 | struct iio_trigger *trig = dev_get_drvdata(dev); | ||
49 | return sprintf(buf, "%s\n", trig->name); | ||
50 | } | ||
51 | |||
52 | static DEVICE_ATTR(name, S_IRUGO, iio_trigger_read_name, NULL); | ||
53 | |||
54 | /** | ||
55 | * iio_trigger_register_sysfs() - create a device for this trigger | ||
56 | * @trig_info: the trigger | ||
57 | * | ||
58 | * Also adds any control attribute registered by the trigger driver | ||
59 | **/ | ||
60 | static int iio_trigger_register_sysfs(struct iio_trigger *trig_info) | ||
61 | { | ||
62 | return sysfs_add_file_to_group(&trig_info->dev.kobj, | ||
63 | &dev_attr_name.attr, | ||
64 | NULL); | ||
65 | } | ||
66 | |||
67 | static void iio_trigger_unregister_sysfs(struct iio_trigger *trig_info) | ||
68 | { | ||
69 | sysfs_remove_file_from_group(&trig_info->dev.kobj, | ||
70 | &dev_attr_name.attr, | ||
71 | NULL); | ||
72 | } | ||
73 | |||
74 | |||
75 | /** | ||
76 | * iio_trigger_register_id() - get a unique id for this trigger | ||
77 | * @trig_info: the trigger | ||
78 | **/ | ||
79 | static int iio_trigger_register_id(struct iio_trigger *trig_info) | ||
80 | { | ||
81 | int ret = 0; | ||
82 | |||
83 | idr_again: | ||
84 | if (unlikely(idr_pre_get(&iio_trigger_idr, GFP_KERNEL) == 0)) | ||
85 | return -ENOMEM; | ||
86 | |||
87 | spin_lock(&iio_trigger_idr_lock); | ||
88 | ret = idr_get_new(&iio_trigger_idr, NULL, &trig_info->id); | ||
89 | spin_unlock(&iio_trigger_idr_lock); | ||
90 | if (unlikely(ret == -EAGAIN)) | ||
91 | goto idr_again; | ||
92 | else if (likely(!ret)) | ||
93 | trig_info->id = trig_info->id & MAX_ID_MASK; | ||
94 | |||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * iio_trigger_unregister_id() - free up unique id for use by another trigger | ||
100 | * @trig_info: the trigger | ||
101 | **/ | ||
102 | static void iio_trigger_unregister_id(struct iio_trigger *trig_info) | ||
103 | { | ||
104 | spin_lock(&iio_trigger_idr_lock); | ||
105 | idr_remove(&iio_trigger_idr, trig_info->id); | ||
106 | spin_unlock(&iio_trigger_idr_lock); | ||
107 | } | ||
108 | |||
109 | int iio_trigger_register(struct iio_trigger *trig_info) | ||
110 | { | ||
111 | int ret; | ||
112 | |||
113 | ret = iio_trigger_register_id(trig_info); | ||
114 | if (ret) | ||
115 | goto error_ret; | ||
116 | /* Set the name used for the sysfs directory etc */ | ||
117 | dev_set_name(&trig_info->dev, "trigger%ld", | ||
118 | (unsigned long) trig_info->id); | ||
119 | |||
120 | ret = device_add(&trig_info->dev); | ||
121 | if (ret) | ||
122 | goto error_unregister_id; | ||
123 | |||
124 | ret = iio_trigger_register_sysfs(trig_info); | ||
125 | if (ret) | ||
126 | goto error_device_del; | ||
127 | |||
128 | /* Add to list of available triggers held by the IIO core */ | ||
129 | mutex_lock(&iio_trigger_list_lock); | ||
130 | list_add_tail(&trig_info->list, &iio_trigger_list); | ||
131 | mutex_unlock(&iio_trigger_list_lock); | ||
132 | |||
133 | return 0; | ||
134 | |||
135 | error_device_del: | ||
136 | device_del(&trig_info->dev); | ||
137 | error_unregister_id: | ||
138 | iio_trigger_unregister_id(trig_info); | ||
139 | error_ret: | ||
140 | return ret; | ||
141 | } | ||
142 | EXPORT_SYMBOL(iio_trigger_register); | ||
143 | |||
144 | void iio_trigger_unregister(struct iio_trigger *trig_info) | ||
145 | { | ||
146 | mutex_lock(&iio_trigger_list_lock); | ||
147 | list_del(&trig_info->list); | ||
148 | mutex_unlock(&iio_trigger_list_lock); | ||
149 | |||
150 | iio_trigger_unregister_sysfs(trig_info); | ||
151 | iio_trigger_unregister_id(trig_info); | ||
152 | /* Possible issue in here */ | ||
153 | device_unregister(&trig_info->dev); | ||
154 | } | ||
155 | EXPORT_SYMBOL(iio_trigger_unregister); | ||
156 | |||
157 | static struct iio_trigger *iio_trigger_find_by_name(const char *name, | ||
158 | size_t len) | ||
159 | { | ||
160 | struct iio_trigger *trig = NULL, *iter; | ||
161 | |||
162 | mutex_lock(&iio_trigger_list_lock); | ||
163 | list_for_each_entry(iter, &iio_trigger_list, list) | ||
164 | if (sysfs_streq(iter->name, name)) { | ||
165 | trig = iter; | ||
166 | break; | ||
167 | } | ||
168 | mutex_unlock(&iio_trigger_list_lock); | ||
169 | |||
170 | return trig; | ||
171 | } | ||
172 | |||
173 | void iio_trigger_poll(struct iio_trigger *trig, s64 time) | ||
174 | { | ||
175 | int i; | ||
176 | if (!trig->use_count) { | ||
177 | for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) | ||
178 | if (trig->subirqs[i].enabled) { | ||
179 | trig->use_count++; | ||
180 | generic_handle_irq(trig->subirq_base + i); | ||
181 | } | ||
182 | } | ||
183 | } | ||
184 | EXPORT_SYMBOL(iio_trigger_poll); | ||
185 | |||
186 | irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private) | ||
187 | { | ||
188 | iio_trigger_poll(private, iio_get_time_ns()); | ||
189 | return IRQ_HANDLED; | ||
190 | } | ||
191 | EXPORT_SYMBOL(iio_trigger_generic_data_rdy_poll); | ||
192 | |||
193 | void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time) | ||
194 | { | ||
195 | int i; | ||
196 | if (!trig->use_count) { | ||
197 | for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) | ||
198 | if (trig->subirqs[i].enabled) { | ||
199 | trig->use_count++; | ||
200 | handle_nested_irq(trig->subirq_base + i); | ||
201 | } | ||
202 | } | ||
203 | } | ||
204 | EXPORT_SYMBOL(iio_trigger_poll_chained); | ||
205 | |||
206 | void iio_trigger_notify_done(struct iio_trigger *trig) | ||
207 | { | ||
208 | trig->use_count--; | ||
209 | if (trig->use_count == 0 && trig->try_reenable) | ||
210 | if (trig->try_reenable(trig)) { | ||
211 | /* Missed and interrupt so launch new poll now */ | ||
212 | iio_trigger_poll(trig, 0); | ||
213 | } | ||
214 | } | ||
215 | EXPORT_SYMBOL(iio_trigger_notify_done); | ||
216 | |||
217 | /* Trigger Consumer related functions */ | ||
218 | |||
219 | /* Complexity in here. With certain triggers (datardy) an acknowledgement | ||
220 | * may be needed if the pollfuncs do not include the data read for the | ||
221 | * triggering device. | ||
222 | * This is not currently handled. Alternative of not enabling trigger unless | ||
223 | * the relevant function is in there may be the best option. | ||
224 | */ | ||
225 | /* Worth protecting against double additions?*/ | ||
226 | int iio_trigger_attach_poll_func(struct iio_trigger *trig, | ||
227 | struct iio_poll_func *pf) | ||
228 | { | ||
229 | int ret = 0; | ||
230 | bool notinuse | ||
231 | = bitmap_empty(trig->pool, CONFIG_IIO_CONSUMERS_PER_TRIGGER); | ||
232 | |||
233 | pf->irq = iio_trigger_get_irq(trig); | ||
234 | ret = request_threaded_irq(pf->irq, pf->h, pf->thread, | ||
235 | pf->type, pf->name, | ||
236 | pf); | ||
237 | if (trig->set_trigger_state && notinuse) | ||
238 | ret = trig->set_trigger_state(trig, true); | ||
239 | |||
240 | return ret; | ||
241 | } | ||
242 | EXPORT_SYMBOL(iio_trigger_attach_poll_func); | ||
243 | |||
244 | int iio_trigger_dettach_poll_func(struct iio_trigger *trig, | ||
245 | struct iio_poll_func *pf) | ||
246 | { | ||
247 | int ret = 0; | ||
248 | bool no_other_users | ||
249 | = (bitmap_weight(trig->pool, | ||
250 | CONFIG_IIO_CONSUMERS_PER_TRIGGER) | ||
251 | == 1); | ||
252 | if (trig->set_trigger_state && no_other_users) { | ||
253 | ret = trig->set_trigger_state(trig, false); | ||
254 | if (ret) | ||
255 | goto error_ret; | ||
256 | } | ||
257 | iio_trigger_put_irq(trig, pf->irq); | ||
258 | free_irq(pf->irq, pf); | ||
259 | |||
260 | error_ret: | ||
261 | return ret; | ||
262 | } | ||
263 | EXPORT_SYMBOL(iio_trigger_dettach_poll_func); | ||
264 | |||
265 | irqreturn_t iio_pollfunc_store_time(int irq, void *p) | ||
266 | { | ||
267 | struct iio_poll_func *pf = p; | ||
268 | pf->timestamp = iio_get_time_ns(); | ||
269 | return IRQ_WAKE_THREAD; | ||
270 | } | ||
271 | EXPORT_SYMBOL(iio_pollfunc_store_time); | ||
272 | |||
273 | struct iio_poll_func | ||
274 | *iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p), | ||
275 | irqreturn_t (*thread)(int irq, void *p), | ||
276 | int type, | ||
277 | void *private, | ||
278 | const char *fmt, | ||
279 | ...) | ||
280 | { | ||
281 | va_list vargs; | ||
282 | struct iio_poll_func *pf; | ||
283 | |||
284 | pf = kmalloc(sizeof *pf, GFP_KERNEL); | ||
285 | if (pf == NULL) | ||
286 | return NULL; | ||
287 | va_start(vargs, fmt); | ||
288 | pf->name = kvasprintf(GFP_KERNEL, fmt, vargs); | ||
289 | va_end(vargs); | ||
290 | if (pf->name == NULL) { | ||
291 | kfree(pf); | ||
292 | return NULL; | ||
293 | } | ||
294 | pf->h = h; | ||
295 | pf->thread = thread; | ||
296 | pf->type = type; | ||
297 | pf->private_data = private; | ||
298 | |||
299 | return pf; | ||
300 | } | ||
301 | EXPORT_SYMBOL_GPL(iio_alloc_pollfunc); | ||
302 | |||
303 | void iio_dealloc_pollfunc(struct iio_poll_func *pf) | ||
304 | { | ||
305 | kfree(pf->name); | ||
306 | kfree(pf); | ||
307 | } | ||
308 | EXPORT_SYMBOL_GPL(iio_dealloc_pollfunc); | ||
309 | |||
310 | /** | ||
311 | * iio_trigger_read_currrent() - trigger consumer sysfs query which trigger | ||
312 | * | ||
313 | * For trigger consumers the current_trigger interface allows the trigger | ||
314 | * used by the device to be queried. | ||
315 | **/ | ||
316 | static ssize_t iio_trigger_read_current(struct device *dev, | ||
317 | struct device_attribute *attr, | ||
318 | char *buf) | ||
319 | { | ||
320 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
321 | int len = 0; | ||
322 | if (dev_info->trig) | ||
323 | len = sprintf(buf, | ||
324 | "%s\n", | ||
325 | dev_info->trig->name); | ||
326 | return len; | ||
327 | } | ||
328 | |||
329 | /** | ||
330 | * iio_trigger_write_current() trigger consumer sysfs set current trigger | ||
331 | * | ||
332 | * For trigger consumers the current_trigger interface allows the trigger | ||
333 | * used for this device to be specified at run time based on the triggers | ||
334 | * name. | ||
335 | **/ | ||
336 | static ssize_t iio_trigger_write_current(struct device *dev, | ||
337 | struct device_attribute *attr, | ||
338 | const char *buf, | ||
339 | size_t len) | ||
340 | { | ||
341 | struct iio_dev *dev_info = dev_get_drvdata(dev); | ||
342 | struct iio_trigger *oldtrig = dev_info->trig; | ||
343 | struct iio_trigger *trig; | ||
344 | int ret; | ||
345 | |||
346 | mutex_lock(&dev_info->mlock); | ||
347 | if (dev_info->currentmode == INDIO_RING_TRIGGERED) { | ||
348 | mutex_unlock(&dev_info->mlock); | ||
349 | return -EBUSY; | ||
350 | } | ||
351 | mutex_unlock(&dev_info->mlock); | ||
352 | |||
353 | trig = iio_trigger_find_by_name(buf, len); | ||
354 | |||
355 | if (trig && dev_info->info->validate_trigger) { | ||
356 | ret = dev_info->info->validate_trigger(dev_info, trig); | ||
357 | if (ret) | ||
358 | return ret; | ||
359 | } | ||
360 | |||
361 | if (trig && trig->validate_device) { | ||
362 | ret = trig->validate_device(trig, dev_info); | ||
363 | if (ret) | ||
364 | return ret; | ||
365 | } | ||
366 | |||
367 | dev_info->trig = trig; | ||
368 | |||
369 | if (oldtrig && dev_info->trig != oldtrig) | ||
370 | iio_put_trigger(oldtrig); | ||
371 | if (dev_info->trig) | ||
372 | iio_get_trigger(dev_info->trig); | ||
373 | |||
374 | return len; | ||
375 | } | ||
376 | |||
377 | static DEVICE_ATTR(current_trigger, S_IRUGO | S_IWUSR, | ||
378 | iio_trigger_read_current, | ||
379 | iio_trigger_write_current); | ||
380 | |||
381 | static struct attribute *iio_trigger_consumer_attrs[] = { | ||
382 | &dev_attr_current_trigger.attr, | ||
383 | NULL, | ||
384 | }; | ||
385 | |||
386 | static const struct attribute_group iio_trigger_consumer_attr_group = { | ||
387 | .name = "trigger", | ||
388 | .attrs = iio_trigger_consumer_attrs, | ||
389 | }; | ||
390 | |||
391 | static void iio_trig_release(struct device *device) | ||
392 | { | ||
393 | struct iio_trigger *trig = to_iio_trigger(device); | ||
394 | int i; | ||
395 | |||
396 | if (trig->subirq_base) { | ||
397 | for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) { | ||
398 | irq_modify_status(trig->subirq_base + i, | ||
399 | IRQ_NOAUTOEN, | ||
400 | IRQ_NOREQUEST | IRQ_NOPROBE); | ||
401 | irq_set_chip(trig->subirq_base + i, | ||
402 | NULL); | ||
403 | irq_set_handler(trig->subirq_base + i, | ||
404 | NULL); | ||
405 | } | ||
406 | |||
407 | irq_free_descs(trig->subirq_base, | ||
408 | CONFIG_IIO_CONSUMERS_PER_TRIGGER); | ||
409 | } | ||
410 | kfree(trig->name); | ||
411 | kfree(trig); | ||
412 | iio_put(); | ||
413 | } | ||
414 | |||
415 | static struct device_type iio_trig_type = { | ||
416 | .release = iio_trig_release, | ||
417 | }; | ||
418 | |||
419 | static void iio_trig_subirqmask(struct irq_data *d) | ||
420 | { | ||
421 | struct irq_chip *chip = irq_data_get_irq_chip(d); | ||
422 | struct iio_trigger *trig | ||
423 | = container_of(chip, | ||
424 | struct iio_trigger, subirq_chip); | ||
425 | trig->subirqs[d->irq - trig->subirq_base].enabled = false; | ||
426 | } | ||
427 | |||
428 | static void iio_trig_subirqunmask(struct irq_data *d) | ||
429 | { | ||
430 | struct irq_chip *chip = irq_data_get_irq_chip(d); | ||
431 | struct iio_trigger *trig | ||
432 | = container_of(chip, | ||
433 | struct iio_trigger, subirq_chip); | ||
434 | trig->subirqs[d->irq - trig->subirq_base].enabled = true; | ||
435 | } | ||
436 | |||
437 | struct iio_trigger *iio_allocate_trigger(const char *fmt, ...) | ||
438 | { | ||
439 | va_list vargs; | ||
440 | struct iio_trigger *trig; | ||
441 | trig = kzalloc(sizeof *trig, GFP_KERNEL); | ||
442 | if (trig) { | ||
443 | int i; | ||
444 | trig->dev.type = &iio_trig_type; | ||
445 | trig->dev.bus = &iio_bus_type; | ||
446 | device_initialize(&trig->dev); | ||
447 | dev_set_drvdata(&trig->dev, (void *)trig); | ||
448 | |||
449 | mutex_init(&trig->pool_lock); | ||
450 | trig->subirq_base | ||
451 | = irq_alloc_descs(-1, 0, | ||
452 | CONFIG_IIO_CONSUMERS_PER_TRIGGER, | ||
453 | 0); | ||
454 | if (trig->subirq_base < 0) { | ||
455 | kfree(trig); | ||
456 | return NULL; | ||
457 | } | ||
458 | va_start(vargs, fmt); | ||
459 | trig->name = kvasprintf(GFP_KERNEL, fmt, vargs); | ||
460 | va_end(vargs); | ||
461 | if (trig->name == NULL) { | ||
462 | irq_free_descs(trig->subirq_base, | ||
463 | CONFIG_IIO_CONSUMERS_PER_TRIGGER); | ||
464 | kfree(trig); | ||
465 | return NULL; | ||
466 | } | ||
467 | trig->subirq_chip.name = trig->name; | ||
468 | trig->subirq_chip.irq_mask = &iio_trig_subirqmask; | ||
469 | trig->subirq_chip.irq_unmask = &iio_trig_subirqunmask; | ||
470 | for (i = 0; i < CONFIG_IIO_CONSUMERS_PER_TRIGGER; i++) { | ||
471 | irq_set_chip(trig->subirq_base + i, | ||
472 | &trig->subirq_chip); | ||
473 | irq_set_handler(trig->subirq_base + i, | ||
474 | &handle_simple_irq); | ||
475 | irq_modify_status(trig->subirq_base + i, | ||
476 | IRQ_NOREQUEST | IRQ_NOAUTOEN, | ||
477 | IRQ_NOPROBE); | ||
478 | } | ||
479 | iio_get(); | ||
480 | } | ||
481 | return trig; | ||
482 | } | ||
483 | EXPORT_SYMBOL(iio_allocate_trigger); | ||
484 | |||
485 | void iio_free_trigger(struct iio_trigger *trig) | ||
486 | { | ||
487 | if (trig) | ||
488 | put_device(&trig->dev); | ||
489 | } | ||
490 | EXPORT_SYMBOL(iio_free_trigger); | ||
491 | |||
492 | int iio_device_register_trigger_consumer(struct iio_dev *dev_info) | ||
493 | { | ||
494 | int ret; | ||
495 | ret = sysfs_create_group(&dev_info->dev.kobj, | ||
496 | &iio_trigger_consumer_attr_group); | ||
497 | return ret; | ||
498 | } | ||
499 | EXPORT_SYMBOL(iio_device_register_trigger_consumer); | ||
500 | |||
501 | int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info) | ||
502 | { | ||
503 | sysfs_remove_group(&dev_info->dev.kobj, | ||
504 | &iio_trigger_consumer_attr_group); | ||
505 | return 0; | ||
506 | } | ||
507 | EXPORT_SYMBOL(iio_device_unregister_trigger_consumer); | ||
508 | |||
509 | int iio_triggered_ring_postenable(struct iio_dev *indio_dev) | ||
510 | { | ||
511 | return indio_dev->trig | ||
512 | ? iio_trigger_attach_poll_func(indio_dev->trig, | ||
513 | indio_dev->pollfunc) | ||
514 | : 0; | ||
515 | } | ||
516 | EXPORT_SYMBOL(iio_triggered_ring_postenable); | ||
517 | |||
518 | int iio_triggered_ring_predisable(struct iio_dev *indio_dev) | ||
519 | { | ||
520 | return indio_dev->trig | ||
521 | ? iio_trigger_dettach_poll_func(indio_dev->trig, | ||
522 | indio_dev->pollfunc) | ||
523 | : 0; | ||
524 | } | ||
525 | EXPORT_SYMBOL(iio_triggered_ring_predisable); | ||
diff --git a/drivers/staging/iio/kfifo_buf.c b/drivers/staging/iio/kfifo_buf.c new file mode 100644 index 00000000000..6002368fdcf --- /dev/null +++ b/drivers/staging/iio/kfifo_buf.c | |||
@@ -0,0 +1,203 @@ | |||
1 | #include <linux/slab.h> | ||
2 | #include <linux/kernel.h> | ||
3 | #include <linux/module.h> | ||
4 | #include <linux/device.h> | ||
5 | #include <linux/workqueue.h> | ||
6 | #include <linux/kfifo.h> | ||
7 | #include <linux/mutex.h> | ||
8 | |||
9 | #include "kfifo_buf.h" | ||
10 | |||
11 | #define iio_to_kfifo(r) container_of(r, struct iio_kfifo, ring) | ||
12 | |||
13 | static inline int __iio_allocate_kfifo(struct iio_kfifo *buf, | ||
14 | int bytes_per_datum, int length) | ||
15 | { | ||
16 | if ((length == 0) || (bytes_per_datum == 0)) | ||
17 | return -EINVAL; | ||
18 | |||
19 | __iio_update_ring_buffer(&buf->ring, bytes_per_datum, length); | ||
20 | return kfifo_alloc(&buf->kf, bytes_per_datum*length, GFP_KERNEL); | ||
21 | } | ||
22 | |||
23 | static int iio_request_update_kfifo(struct iio_ring_buffer *r) | ||
24 | { | ||
25 | int ret = 0; | ||
26 | struct iio_kfifo *buf = iio_to_kfifo(r); | ||
27 | |||
28 | mutex_lock(&buf->use_lock); | ||
29 | if (!buf->update_needed) | ||
30 | goto error_ret; | ||
31 | if (buf->use_count) { | ||
32 | ret = -EAGAIN; | ||
33 | goto error_ret; | ||
34 | } | ||
35 | kfifo_free(&buf->kf); | ||
36 | ret = __iio_allocate_kfifo(buf, buf->ring.bytes_per_datum, | ||
37 | buf->ring.length); | ||
38 | error_ret: | ||
39 | mutex_unlock(&buf->use_lock); | ||
40 | return ret; | ||
41 | } | ||
42 | |||
43 | static void iio_mark_kfifo_in_use(struct iio_ring_buffer *r) | ||
44 | { | ||
45 | struct iio_kfifo *buf = iio_to_kfifo(r); | ||
46 | mutex_lock(&buf->use_lock); | ||
47 | buf->use_count++; | ||
48 | mutex_unlock(&buf->use_lock); | ||
49 | } | ||
50 | |||
51 | static void iio_unmark_kfifo_in_use(struct iio_ring_buffer *r) | ||
52 | { | ||
53 | struct iio_kfifo *buf = iio_to_kfifo(r); | ||
54 | mutex_lock(&buf->use_lock); | ||
55 | buf->use_count--; | ||
56 | mutex_unlock(&buf->use_lock); | ||
57 | } | ||
58 | |||
59 | static int iio_get_length_kfifo(struct iio_ring_buffer *r) | ||
60 | { | ||
61 | return r->length; | ||
62 | } | ||
63 | |||
64 | static inline void __iio_init_kfifo(struct iio_kfifo *kf) | ||
65 | { | ||
66 | mutex_init(&kf->use_lock); | ||
67 | } | ||
68 | |||
69 | static IIO_RING_ENABLE_ATTR; | ||
70 | static IIO_RING_BYTES_PER_DATUM_ATTR; | ||
71 | static IIO_RING_LENGTH_ATTR; | ||
72 | |||
73 | static struct attribute *iio_kfifo_attributes[] = { | ||
74 | &dev_attr_length.attr, | ||
75 | &dev_attr_bytes_per_datum.attr, | ||
76 | &dev_attr_enable.attr, | ||
77 | NULL, | ||
78 | }; | ||
79 | |||
80 | static struct attribute_group iio_kfifo_attribute_group = { | ||
81 | .attrs = iio_kfifo_attributes, | ||
82 | }; | ||
83 | |||
84 | static const struct attribute_group *iio_kfifo_attribute_groups[] = { | ||
85 | &iio_kfifo_attribute_group, | ||
86 | NULL | ||
87 | }; | ||
88 | |||
89 | static void iio_kfifo_release(struct device *dev) | ||
90 | { | ||
91 | struct iio_ring_buffer *r = to_iio_ring_buffer(dev); | ||
92 | struct iio_kfifo *kf = iio_to_kfifo(r); | ||
93 | kfifo_free(&kf->kf); | ||
94 | kfree(kf); | ||
95 | } | ||
96 | |||
97 | static struct device_type iio_kfifo_type = { | ||
98 | .release = iio_kfifo_release, | ||
99 | .groups = iio_kfifo_attribute_groups, | ||
100 | }; | ||
101 | |||
102 | struct iio_ring_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev) | ||
103 | { | ||
104 | struct iio_kfifo *kf; | ||
105 | |||
106 | kf = kzalloc(sizeof *kf, GFP_KERNEL); | ||
107 | if (!kf) | ||
108 | return NULL; | ||
109 | kf->update_needed = true; | ||
110 | iio_ring_buffer_init(&kf->ring, indio_dev); | ||
111 | __iio_init_kfifo(kf); | ||
112 | kf->ring.dev.type = &iio_kfifo_type; | ||
113 | kf->ring.dev.parent = &indio_dev->dev; | ||
114 | dev_set_drvdata(&kf->ring.dev, (void *)&(kf->ring)); | ||
115 | |||
116 | return &kf->ring; | ||
117 | } | ||
118 | EXPORT_SYMBOL(iio_kfifo_allocate); | ||
119 | |||
120 | static int iio_get_bytes_per_datum_kfifo(struct iio_ring_buffer *r) | ||
121 | { | ||
122 | return r->bytes_per_datum; | ||
123 | } | ||
124 | |||
125 | static int iio_set_bytes_per_datum_kfifo(struct iio_ring_buffer *r, size_t bpd) | ||
126 | { | ||
127 | if (r->bytes_per_datum != bpd) { | ||
128 | r->bytes_per_datum = bpd; | ||
129 | if (r->access->mark_param_change) | ||
130 | r->access->mark_param_change(r); | ||
131 | } | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int iio_mark_update_needed_kfifo(struct iio_ring_buffer *r) | ||
136 | { | ||
137 | struct iio_kfifo *kf = iio_to_kfifo(r); | ||
138 | kf->update_needed = true; | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static int iio_set_length_kfifo(struct iio_ring_buffer *r, int length) | ||
143 | { | ||
144 | if (r->length != length) { | ||
145 | r->length = length; | ||
146 | if (r->access->mark_param_change) | ||
147 | r->access->mark_param_change(r); | ||
148 | } | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | void iio_kfifo_free(struct iio_ring_buffer *r) | ||
153 | { | ||
154 | if (r) | ||
155 | iio_put_ring_buffer(r); | ||
156 | } | ||
157 | EXPORT_SYMBOL(iio_kfifo_free); | ||
158 | |||
159 | static int iio_store_to_kfifo(struct iio_ring_buffer *r, | ||
160 | u8 *data, | ||
161 | s64 timestamp) | ||
162 | { | ||
163 | int ret; | ||
164 | struct iio_kfifo *kf = iio_to_kfifo(r); | ||
165 | u8 *datal = kmalloc(r->bytes_per_datum, GFP_KERNEL); | ||
166 | memcpy(datal, data, r->bytes_per_datum - sizeof(timestamp)); | ||
167 | memcpy(datal + r->bytes_per_datum - sizeof(timestamp), | ||
168 | ×tamp, sizeof(timestamp)); | ||
169 | ret = kfifo_in(&kf->kf, data, r->bytes_per_datum); | ||
170 | if (ret != r->bytes_per_datum) { | ||
171 | kfree(datal); | ||
172 | return -EBUSY; | ||
173 | } | ||
174 | kfree(datal); | ||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static int iio_read_first_n_kfifo(struct iio_ring_buffer *r, | ||
179 | size_t n, char __user *buf) | ||
180 | { | ||
181 | int ret, copied; | ||
182 | struct iio_kfifo *kf = iio_to_kfifo(r); | ||
183 | |||
184 | ret = kfifo_to_user(&kf->kf, buf, r->bytes_per_datum*n, &copied); | ||
185 | |||
186 | return copied; | ||
187 | } | ||
188 | |||
189 | const struct iio_ring_access_funcs kfifo_access_funcs = { | ||
190 | .mark_in_use = &iio_mark_kfifo_in_use, | ||
191 | .unmark_in_use = &iio_unmark_kfifo_in_use, | ||
192 | .store_to = &iio_store_to_kfifo, | ||
193 | .read_first_n = &iio_read_first_n_kfifo, | ||
194 | .mark_param_change = &iio_mark_update_needed_kfifo, | ||
195 | .request_update = &iio_request_update_kfifo, | ||
196 | .get_bytes_per_datum = &iio_get_bytes_per_datum_kfifo, | ||
197 | .set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo, | ||
198 | .get_length = &iio_get_length_kfifo, | ||
199 | .set_length = &iio_set_length_kfifo, | ||
200 | }; | ||
201 | EXPORT_SYMBOL(kfifo_access_funcs); | ||
202 | |||
203 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/iio/kfifo_buf.h b/drivers/staging/iio/kfifo_buf.h new file mode 100644 index 00000000000..aac30539b2c --- /dev/null +++ b/drivers/staging/iio/kfifo_buf.h | |||
@@ -0,0 +1,18 @@ | |||
1 | |||
2 | #include <linux/kfifo.h> | ||
3 | #include "iio.h" | ||
4 | #include "ring_generic.h" | ||
5 | |||
6 | struct iio_kfifo { | ||
7 | struct iio_ring_buffer ring; | ||
8 | struct kfifo kf; | ||
9 | int use_count; | ||
10 | int update_needed; | ||
11 | struct mutex use_lock; | ||
12 | }; | ||
13 | |||
14 | extern const struct iio_ring_access_funcs kfifo_access_funcs; | ||
15 | |||
16 | struct iio_ring_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev); | ||
17 | void iio_kfifo_free(struct iio_ring_buffer *r); | ||
18 | |||
diff --git a/drivers/staging/iio/light/ltr558als.c b/drivers/staging/iio/light/ltr558als.c new file mode 100644 index 00000000000..01e410b191f --- /dev/null +++ b/drivers/staging/iio/light/ltr558als.c | |||
@@ -0,0 +1,883 @@ | |||
1 | /* Lite-On LTR-558ALS Linux Driver | ||
2 | * | ||
3 | * Copyright (c) 2012, NVIDIA Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | */ | ||
10 | |||
11 | #include <linux/delay.h> | ||
12 | #include <linux/earlysuspend.h> | ||
13 | #include <linux/fs.h> | ||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/input.h> | ||
17 | #include <linux/irq.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/mutex.h> | ||
21 | #include <linux/pm.h> | ||
22 | #include <linux/wakelock.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <asm/gpio.h> | ||
26 | #include <asm/uaccess.h> | ||
27 | |||
28 | #include "ltr558als.h" | ||
29 | #include "../iio.h" | ||
30 | |||
31 | #define DRIVER_VERSION "1.0" | ||
32 | #define DEVICE_NAME "LTR_558ALS" | ||
33 | |||
34 | struct ltr558_chip { | ||
35 | struct i2c_client *client; | ||
36 | struct mutex lock; | ||
37 | struct iio_dev *indio_dev; | ||
38 | int irq; | ||
39 | |||
40 | bool is_als_enable; | ||
41 | bool als_enabled_before_suspend; | ||
42 | int als_gainrange; | ||
43 | int als_persist; | ||
44 | int als_reading; | ||
45 | int als_high_thres; | ||
46 | int als_low_thres; | ||
47 | |||
48 | bool is_prox_enable; | ||
49 | bool prox_enabled_before_suspend; | ||
50 | int ps_gainrange; | ||
51 | int prox_persist; | ||
52 | int prox_reading; | ||
53 | int prox_low_thres; | ||
54 | int prox_high_thres; | ||
55 | }; | ||
56 | |||
57 | static int ltr558_i2c_read_reg(struct i2c_client *client, u8 regnum) | ||
58 | { | ||
59 | return i2c_smbus_read_byte_data(client, regnum); | ||
60 | } | ||
61 | |||
62 | static int ltr558_i2c_write_reg(struct i2c_client *client, u8 regnum, u8 value) | ||
63 | { | ||
64 | int writeerror; | ||
65 | |||
66 | writeerror = i2c_smbus_write_byte_data(client, regnum, value); | ||
67 | if (writeerror < 0) | ||
68 | return writeerror; | ||
69 | else | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int ltr558_ps_enable(struct i2c_client *client, int gainrange) | ||
74 | { | ||
75 | int error; | ||
76 | int setgain; | ||
77 | |||
78 | switch (gainrange) { | ||
79 | case PS_RANGE4: | ||
80 | setgain = MODE_PS_ON_Gain4; | ||
81 | break; | ||
82 | |||
83 | case PS_RANGE8: | ||
84 | setgain = MODE_PS_ON_Gain8; | ||
85 | break; | ||
86 | |||
87 | case PS_RANGE16: | ||
88 | setgain = MODE_PS_ON_Gain16; | ||
89 | break; | ||
90 | |||
91 | case PS_RANGE1: | ||
92 | default: | ||
93 | setgain = MODE_PS_ON_Gain1; | ||
94 | break; | ||
95 | } | ||
96 | |||
97 | error = ltr558_i2c_write_reg(client, LTR558_PS_CONTR, setgain); | ||
98 | mdelay(WAKEUP_DELAY); | ||
99 | return error; | ||
100 | } | ||
101 | |||
102 | static int ltr558_ps_disable(struct i2c_client *client) | ||
103 | { | ||
104 | return ltr558_i2c_write_reg(client, LTR558_PS_CONTR, MODE_PS_StdBy); | ||
105 | } | ||
106 | |||
107 | static int ltr558_ps_read(struct i2c_client *client) | ||
108 | { | ||
109 | int psval_lo = 0, psval_hi = 0, psdata = 0; | ||
110 | psval_lo = ltr558_i2c_read_reg(client, LTR558_PS_DATA_0); | ||
111 | if (psval_lo < 0){ | ||
112 | psdata = psval_lo; | ||
113 | goto out; | ||
114 | } | ||
115 | |||
116 | psval_hi = ltr558_i2c_read_reg(client, LTR558_PS_DATA_1); | ||
117 | if (psval_hi < 0){ | ||
118 | psdata = psval_hi; | ||
119 | goto out; | ||
120 | } | ||
121 | |||
122 | psdata = ((psval_hi & 0x07) * 256) + psval_lo; | ||
123 | out: | ||
124 | return psdata; | ||
125 | } | ||
126 | |||
127 | static int ltr558_als_enable(struct i2c_client *client, int gainrange) | ||
128 | { | ||
129 | int error = -1; | ||
130 | |||
131 | if (gainrange == ALS_RANGE1_320) | ||
132 | error = ltr558_i2c_write_reg(client, LTR558_ALS_CONTR, | ||
133 | MODE_ALS_ON_Range1); | ||
134 | else if (gainrange == ALS_RANGE2_64K) | ||
135 | error = ltr558_i2c_write_reg(client, LTR558_ALS_CONTR, | ||
136 | MODE_ALS_ON_Range2); | ||
137 | |||
138 | mdelay(WAKEUP_DELAY); | ||
139 | return error; | ||
140 | } | ||
141 | |||
142 | static int ltr558_als_disable(struct i2c_client *client) | ||
143 | { | ||
144 | return ltr558_i2c_write_reg(client, LTR558_ALS_CONTR, MODE_ALS_StdBy); | ||
145 | } | ||
146 | |||
147 | static int ltr558_als_read(struct i2c_client *client) | ||
148 | { | ||
149 | int alsval_ch0_lo, alsval_ch0_hi; | ||
150 | int alsval_ch1_lo, alsval_ch1_hi; | ||
151 | unsigned int alsval_ch0 = 0, alsval_ch1 = 0; | ||
152 | int luxdata = 0, ratio = 0; | ||
153 | long ch0_coeff = 0, ch1_coeff = 0; | ||
154 | |||
155 | alsval_ch1_lo = ltr558_i2c_read_reg(client, LTR558_ALS_DATA_CH1_0); | ||
156 | alsval_ch1_hi = ltr558_i2c_read_reg(client, LTR558_ALS_DATA_CH1_1); | ||
157 | alsval_ch1 = (alsval_ch1_hi * 256) + alsval_ch1_lo; | ||
158 | |||
159 | alsval_ch0_lo = ltr558_i2c_read_reg(client, LTR558_ALS_DATA_CH0_0); | ||
160 | alsval_ch0_hi = ltr558_i2c_read_reg(client, LTR558_ALS_DATA_CH0_1); | ||
161 | alsval_ch0 = (alsval_ch0_hi * 256) + alsval_ch0_lo; | ||
162 | |||
163 | if (alsval_ch0 == 0 && alsval_ch1 == 0) | ||
164 | return 0; | ||
165 | |||
166 | /* lux formula */ | ||
167 | ratio = (100 * alsval_ch1)/(alsval_ch1 + alsval_ch0); | ||
168 | |||
169 | if (ratio < 45) { | ||
170 | ch0_coeff = 17743; | ||
171 | ch1_coeff = -11059; | ||
172 | } | ||
173 | else if ((ratio >= 45) && (ratio < 64)) { | ||
174 | ch0_coeff = 37725; | ||
175 | ch1_coeff = 13363; | ||
176 | } | ||
177 | else if ((ratio >= 64) && (ratio < 85)) { | ||
178 | ch0_coeff = 16900; | ||
179 | ch1_coeff = 1690; | ||
180 | } | ||
181 | else if (ratio >= 85) { | ||
182 | ch0_coeff = 0; | ||
183 | ch1_coeff = 0; | ||
184 | } | ||
185 | |||
186 | luxdata = ((alsval_ch0 * ch0_coeff) - (alsval_ch1 * ch1_coeff))/10000; | ||
187 | return luxdata; | ||
188 | } | ||
189 | |||
190 | static bool ltr558_set_proxim_high_threshold(struct i2c_client *client, | ||
191 | u32 thresh) | ||
192 | { | ||
193 | bool st; | ||
194 | st = ltr558_i2c_write_reg(client, LTR558_PS_THRES_UP_0, | ||
195 | thresh & 0xFF); | ||
196 | if (st) | ||
197 | st = ltr558_i2c_write_reg(client, LTR558_PS_THRES_UP_1, | ||
198 | (thresh >> 8) & 0x07); | ||
199 | return st; | ||
200 | } | ||
201 | |||
202 | static bool ltr558_set_proxim_low_threshold(struct i2c_client *client, | ||
203 | u32 thresh) | ||
204 | { | ||
205 | bool st; | ||
206 | st = ltr558_i2c_write_reg(client, LTR558_PS_THRES_LOW_0, | ||
207 | thresh & 0xFF); | ||
208 | if (st) | ||
209 | st = ltr558_i2c_write_reg(client, LTR558_PS_THRES_LOW_1, | ||
210 | (thresh >> 8) & 0x07); | ||
211 | return st; | ||
212 | } | ||
213 | |||
214 | static bool ltr558_set_als_high_threshold(struct i2c_client *client, u32 thresh) | ||
215 | { | ||
216 | bool st; | ||
217 | st = ltr558_i2c_write_reg(client, LTR558_ALS_THRES_UP_0, | ||
218 | thresh & 0xFF); | ||
219 | if (st) | ||
220 | st = ltr558_i2c_write_reg(client, LTR558_ALS_THRES_UP_1, | ||
221 | (thresh >> 8) & 0xFF); | ||
222 | return st; | ||
223 | } | ||
224 | |||
225 | static bool ltr558_set_als_low_threshold(struct i2c_client *client, u32 thresh) | ||
226 | { | ||
227 | bool st; | ||
228 | st = ltr558_i2c_write_reg(client, LTR558_ALS_THRES_LOW_0, | ||
229 | thresh & 0xFF); | ||
230 | if (st) | ||
231 | st = ltr558_i2c_write_reg(client, LTR558_ALS_THRES_LOW_1, | ||
232 | ((thresh >> 8) & 0xFF)); | ||
233 | return st; | ||
234 | } | ||
235 | |||
236 | /* Sysfs interface */ | ||
237 | |||
238 | /* proximity enable/disable */ | ||
239 | static ssize_t show_prox_enable(struct device *dev, | ||
240 | struct device_attribute *attr, char *buf) | ||
241 | { | ||
242 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
243 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
244 | |||
245 | dev_vdbg(dev, "%s()\n", __func__); | ||
246 | if (chip->is_prox_enable) | ||
247 | return sprintf(buf, "1\n"); | ||
248 | else | ||
249 | return sprintf(buf, "0\n"); | ||
250 | } | ||
251 | |||
252 | static ssize_t store_prox_enable(struct device *dev, | ||
253 | struct device_attribute *attr, const char *buf, size_t count) | ||
254 | { | ||
255 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
256 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
257 | struct i2c_client *client = chip->client; | ||
258 | int err = 0; | ||
259 | unsigned long lval; | ||
260 | |||
261 | dev_vdbg(dev, "%s()\n", __func__); | ||
262 | |||
263 | if (strict_strtoul(buf, 10, &lval)) | ||
264 | return -EINVAL; | ||
265 | if ((lval != 1) && (lval != 0)) { | ||
266 | dev_err(dev, "illegal value %lu\n", lval); | ||
267 | return -EINVAL; | ||
268 | } | ||
269 | |||
270 | mutex_lock(&chip->lock); | ||
271 | if (lval == 1) | ||
272 | err = ltr558_ps_enable(client, PS_RANGE1); | ||
273 | else | ||
274 | err = ltr558_ps_disable(client); | ||
275 | |||
276 | if (err < 0) | ||
277 | dev_err(dev, "Error in enabling proximity\n"); | ||
278 | else | ||
279 | chip->is_prox_enable = (lval) ? true : false; | ||
280 | |||
281 | mutex_unlock(&chip->lock); | ||
282 | return count; | ||
283 | } | ||
284 | |||
285 | /* Proximity low thresholds */ | ||
286 | static ssize_t show_proxim_low_threshold(struct device *dev, | ||
287 | struct device_attribute *attr, char *buf) | ||
288 | { | ||
289 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
290 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
291 | |||
292 | dev_vdbg(dev, "%s()\n", __func__); | ||
293 | return sprintf(buf, "%d\n", chip->prox_low_thres); | ||
294 | } | ||
295 | |||
296 | static ssize_t store_proxim_low_threshold(struct device *dev, | ||
297 | struct device_attribute *attr, const char *buf, size_t count) | ||
298 | { | ||
299 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
300 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
301 | struct i2c_client *client = chip->client; | ||
302 | bool st; | ||
303 | unsigned long lval; | ||
304 | |||
305 | dev_vdbg(dev, "%s()\n", __func__); | ||
306 | |||
307 | if (strict_strtoul(buf, 10, &lval)) | ||
308 | return -EINVAL; | ||
309 | |||
310 | if ((lval > 0x7FF) || (lval < 0x0)) { | ||
311 | dev_err(dev, "The threshold is not supported\n"); | ||
312 | return -EINVAL; | ||
313 | } | ||
314 | |||
315 | mutex_lock(&chip->lock); | ||
316 | st = ltr558_set_proxim_low_threshold(client, (u8)lval); | ||
317 | if (st) | ||
318 | chip->prox_low_thres = (int)lval; | ||
319 | else | ||
320 | dev_err(dev, "Error in setting proximity low threshold\n"); | ||
321 | |||
322 | mutex_unlock(&chip->lock); | ||
323 | return count; | ||
324 | } | ||
325 | |||
326 | /* Proximity high thresholds */ | ||
327 | static ssize_t show_proxim_high_threshold(struct device *dev, | ||
328 | struct device_attribute *attr, char *buf) | ||
329 | { | ||
330 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
331 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
332 | |||
333 | dev_vdbg(dev, "%s()\n", __func__); | ||
334 | return sprintf(buf, "%d\n", chip->prox_high_thres); | ||
335 | } | ||
336 | |||
337 | static ssize_t store_proxim_high_threshold(struct device *dev, | ||
338 | struct device_attribute *attr, const char *buf, size_t count) | ||
339 | { | ||
340 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
341 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
342 | struct i2c_client *client = chip->client; | ||
343 | bool st; | ||
344 | unsigned long lval; | ||
345 | |||
346 | dev_vdbg(dev, "%s()\n", __func__); | ||
347 | |||
348 | if (strict_strtoul(buf, 10, &lval)) | ||
349 | return -EINVAL; | ||
350 | |||
351 | if ((lval > 0x7FF) || (lval < 0x0)) { | ||
352 | dev_err(dev, "The threshold is not supported\n"); | ||
353 | return -EINVAL; | ||
354 | } | ||
355 | |||
356 | mutex_lock(&chip->lock); | ||
357 | st = ltr558_set_proxim_high_threshold(client, lval); | ||
358 | if (st) | ||
359 | chip->prox_high_thres = (int)lval; | ||
360 | else | ||
361 | dev_err(dev, "Error in setting proximity high threshold\n"); | ||
362 | |||
363 | mutex_unlock(&chip->lock); | ||
364 | return count; | ||
365 | } | ||
366 | |||
367 | /* als enable/disable */ | ||
368 | static ssize_t show_als_enable(struct device *dev, | ||
369 | struct device_attribute *attr, char *buf) | ||
370 | { | ||
371 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
372 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
373 | |||
374 | dev_vdbg(dev, "%s()\n", __func__); | ||
375 | if (chip->is_als_enable) | ||
376 | return sprintf(buf, "1\n"); | ||
377 | else | ||
378 | return sprintf(buf, "0\n"); | ||
379 | } | ||
380 | |||
381 | static ssize_t store_als_enable(struct device *dev, | ||
382 | struct device_attribute *attr, const char *buf, size_t count) | ||
383 | { | ||
384 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
385 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
386 | struct i2c_client *client = chip->client; | ||
387 | int err = 0; | ||
388 | unsigned long lval; | ||
389 | |||
390 | dev_vdbg(dev, "%s()\n", __func__); | ||
391 | |||
392 | if (strict_strtoul(buf, 10, &lval)) | ||
393 | return -EINVAL; | ||
394 | if ((lval != 1) && (lval != 0)) { | ||
395 | dev_err(dev, "illegal value %lu\n", lval); | ||
396 | return -EINVAL; | ||
397 | } | ||
398 | |||
399 | mutex_lock(&chip->lock); | ||
400 | if (lval == 1) | ||
401 | err = ltr558_als_enable(client, chip->als_gainrange); | ||
402 | else | ||
403 | err = ltr558_als_disable(client); | ||
404 | |||
405 | if (err < 0) | ||
406 | dev_err(dev, "Error in enabling ALS\n"); | ||
407 | else | ||
408 | chip->is_als_enable = (lval) ? true : false; | ||
409 | |||
410 | mutex_unlock(&chip->lock); | ||
411 | return count; | ||
412 | } | ||
413 | |||
414 | /* als low thresholds */ | ||
415 | static ssize_t show_als_low_threshold(struct device *dev, | ||
416 | struct device_attribute *attr, char *buf) | ||
417 | { | ||
418 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
419 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
420 | |||
421 | dev_vdbg(dev, "%s()\n", __func__); | ||
422 | return sprintf(buf, "%d\n", chip->als_low_thres); | ||
423 | } | ||
424 | |||
425 | static ssize_t store_als_low_threshold(struct device *dev, | ||
426 | struct device_attribute *attr, const char *buf, size_t count) | ||
427 | { | ||
428 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
429 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
430 | struct i2c_client *client = chip->client; | ||
431 | bool st; | ||
432 | unsigned long lval; | ||
433 | |||
434 | dev_vdbg(dev, "%s()\n", __func__); | ||
435 | |||
436 | if (strict_strtoul(buf, 10, &lval)) | ||
437 | return -EINVAL; | ||
438 | |||
439 | if ((lval > 0xFFFF) || (lval < 0x0)) { | ||
440 | dev_err(dev, "The ALS threshold is not supported\n"); | ||
441 | return -EINVAL; | ||
442 | } | ||
443 | |||
444 | mutex_lock(&chip->lock); | ||
445 | st = ltr558_set_als_low_threshold(client, (int)lval); | ||
446 | if (st) | ||
447 | chip->als_low_thres = (int)lval; | ||
448 | else | ||
449 | dev_err(dev, "Error in setting als low threshold\n"); | ||
450 | mutex_unlock(&chip->lock); | ||
451 | return count; | ||
452 | } | ||
453 | |||
454 | /* Als high thresholds */ | ||
455 | static ssize_t show_als_high_threshold(struct device *dev, | ||
456 | struct device_attribute *attr, char *buf) | ||
457 | { | ||
458 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
459 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
460 | |||
461 | dev_vdbg(dev, "%s()\n", __func__); | ||
462 | return sprintf(buf, "%d\n", chip->als_high_thres); | ||
463 | } | ||
464 | |||
465 | static ssize_t store_als_high_threshold(struct device *dev, | ||
466 | struct device_attribute *attr, const char *buf, size_t count) | ||
467 | { | ||
468 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
469 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
470 | struct i2c_client *client = chip->client; | ||
471 | bool st; | ||
472 | unsigned long lval; | ||
473 | |||
474 | dev_vdbg(dev, "%s()\n", __func__); | ||
475 | |||
476 | if (strict_strtoul(buf, 10, &lval)) | ||
477 | return -EINVAL; | ||
478 | |||
479 | if ((lval > 0xFFFF) || (lval < 0x0)) { | ||
480 | dev_err(dev, "The als threshold is not supported\n"); | ||
481 | return -EINVAL; | ||
482 | } | ||
483 | |||
484 | mutex_lock(&chip->lock); | ||
485 | st = ltr558_set_als_high_threshold(client, (int)lval); | ||
486 | if (st) | ||
487 | chip->als_high_thres = (int)lval; | ||
488 | else | ||
489 | dev_err(dev, "Error in setting als high threshold\n"); | ||
490 | mutex_unlock(&chip->lock); | ||
491 | return count; | ||
492 | } | ||
493 | |||
494 | /* Proximity persist */ | ||
495 | static ssize_t show_proxim_persist(struct device *dev, | ||
496 | struct device_attribute *attr, char *buf) | ||
497 | { | ||
498 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
499 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
500 | |||
501 | dev_vdbg(dev, "%s()\n", __func__); | ||
502 | return sprintf(buf, "%d\n", chip->prox_persist); | ||
503 | } | ||
504 | |||
505 | static ssize_t store_proxim_persist(struct device *dev, | ||
506 | struct device_attribute *attr, const char *buf, size_t count) | ||
507 | { | ||
508 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
509 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
510 | unsigned long lval; | ||
511 | |||
512 | dev_vdbg(dev, "%s()\n", __func__); | ||
513 | |||
514 | if (strict_strtoul(buf, 10, &lval)) | ||
515 | return -EINVAL; | ||
516 | |||
517 | if ((lval > 16) || (lval < 0x0)) { | ||
518 | dev_err(dev, "The proximity persist is not supported\n"); | ||
519 | return -EINVAL; | ||
520 | } | ||
521 | |||
522 | mutex_lock(&chip->lock); | ||
523 | chip->prox_persist = (int)lval; | ||
524 | mutex_unlock(&chip->lock); | ||
525 | return count; | ||
526 | } | ||
527 | |||
528 | /* als/ir persist */ | ||
529 | static ssize_t show_als_persist(struct device *dev, | ||
530 | struct device_attribute *attr, char *buf) | ||
531 | { | ||
532 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
533 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
534 | |||
535 | dev_vdbg(dev, "%s()\n", __func__); | ||
536 | return sprintf(buf, "%d\n", chip->als_persist); | ||
537 | } | ||
538 | |||
539 | static ssize_t store_als_persist(struct device *dev, | ||
540 | struct device_attribute *attr, const char *buf, size_t count) | ||
541 | { | ||
542 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
543 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
544 | unsigned long lval; | ||
545 | |||
546 | dev_vdbg(dev, "%s()\n", __func__); | ||
547 | |||
548 | if (strict_strtoul(buf, 10, &lval)) | ||
549 | return -EINVAL; | ||
550 | |||
551 | if ((lval > 16) || (lval < 0x0)) { | ||
552 | dev_err(dev, "The als persist is not supported\n"); | ||
553 | return -EINVAL; | ||
554 | } | ||
555 | |||
556 | mutex_lock(&chip->lock); | ||
557 | chip->als_persist = (int)lval; | ||
558 | mutex_unlock(&chip->lock); | ||
559 | return count; | ||
560 | } | ||
561 | |||
562 | /* Display proxim data */ | ||
563 | static ssize_t show_proxim_data(struct device *dev, | ||
564 | struct device_attribute *attr, char *buf) | ||
565 | { | ||
566 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
567 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
568 | int prox_data = 0; | ||
569 | ssize_t buf_count = 0; | ||
570 | |||
571 | dev_vdbg(dev, "%s()\n", __func__); | ||
572 | mutex_lock(&chip->lock); | ||
573 | |||
574 | if (chip->is_prox_enable) { | ||
575 | prox_data = ltr558_ps_read(chip->client); | ||
576 | chip->prox_reading = prox_data; | ||
577 | buf_count = sprintf(buf, "%d\n", prox_data); | ||
578 | } | ||
579 | else | ||
580 | buf_count = sprintf(buf, "%d\n", chip->prox_reading); | ||
581 | mutex_unlock(&chip->lock); | ||
582 | return buf_count; | ||
583 | } | ||
584 | |||
585 | /* Display als data */ | ||
586 | static ssize_t show_als_data(struct device *dev, | ||
587 | struct device_attribute *attr, char *buf) | ||
588 | { | ||
589 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
590 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
591 | ssize_t buf_count = 0; | ||
592 | int als_data = 0; | ||
593 | |||
594 | dev_vdbg(dev, "%s()\n", __func__); | ||
595 | |||
596 | mutex_lock(&chip->lock); | ||
597 | if (chip->is_als_enable) { | ||
598 | als_data = ltr558_als_read(chip->client); | ||
599 | buf_count = sprintf(buf, "%d\n", als_data); | ||
600 | chip->als_reading = als_data; | ||
601 | } | ||
602 | else | ||
603 | buf_count = sprintf(buf, "%d\n", chip->als_reading); | ||
604 | mutex_unlock(&chip->lock); | ||
605 | |||
606 | return buf_count; | ||
607 | } | ||
608 | |||
609 | /* Read name */ | ||
610 | static ssize_t show_name(struct device *dev, | ||
611 | struct device_attribute *attr, char *buf) | ||
612 | { | ||
613 | struct iio_dev *indio_dev = dev_get_drvdata(dev); | ||
614 | struct ltr558_chip *chip = indio_dev->dev_data; | ||
615 | return sprintf(buf, "%s\n", chip->client->name); | ||
616 | } | ||
617 | |||
618 | static IIO_DEVICE_ATTR(proximity_low_threshold, S_IRUGO | S_IWUSR, | ||
619 | show_proxim_low_threshold, store_proxim_low_threshold, 0); | ||
620 | static IIO_DEVICE_ATTR(proximity_high_threshold, S_IRUGO | S_IWUSR, | ||
621 | show_proxim_high_threshold, store_proxim_high_threshold, 0); | ||
622 | static IIO_DEVICE_ATTR(proximity_persist, S_IRUGO | S_IWUSR, | ||
623 | show_proxim_persist, store_proxim_persist, 0); | ||
624 | static IIO_DEVICE_ATTR(proximity_enable, S_IRUGO | S_IWUSR, | ||
625 | show_prox_enable, store_prox_enable, 0); | ||
626 | static IIO_DEVICE_ATTR(proximity_value, S_IRUGO, | ||
627 | show_proxim_data, NULL, 0); | ||
628 | |||
629 | static IIO_DEVICE_ATTR(als_low_threshold, S_IRUGO | S_IWUSR, | ||
630 | show_als_low_threshold, store_als_low_threshold, 0); | ||
631 | static IIO_DEVICE_ATTR(als_high_threshold, S_IRUGO | S_IWUSR, | ||
632 | show_als_high_threshold, store_als_high_threshold, 0); | ||
633 | static IIO_DEVICE_ATTR(als_persist, S_IRUGO | S_IWUSR, | ||
634 | show_als_persist, store_als_persist, 0); | ||
635 | static IIO_DEVICE_ATTR(als_enable, S_IRUGO | S_IWUSR, | ||
636 | show_als_enable, store_als_enable, 0); | ||
637 | static IIO_DEVICE_ATTR(als_value, S_IRUGO, | ||
638 | show_als_data, NULL, 0); | ||
639 | |||
640 | static IIO_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); | ||
641 | |||
642 | static struct attribute *ltr558_attributes[] = { | ||
643 | &iio_dev_attr_name.dev_attr.attr, | ||
644 | |||
645 | &iio_dev_attr_als_low_threshold.dev_attr.attr, | ||
646 | &iio_dev_attr_als_high_threshold.dev_attr.attr, | ||
647 | &iio_dev_attr_als_enable.dev_attr.attr, | ||
648 | &iio_dev_attr_als_persist.dev_attr.attr, | ||
649 | &iio_dev_attr_als_value.dev_attr.attr, | ||
650 | |||
651 | &iio_dev_attr_proximity_low_threshold.dev_attr.attr, | ||
652 | &iio_dev_attr_proximity_high_threshold.dev_attr.attr, | ||
653 | &iio_dev_attr_proximity_enable.dev_attr.attr, | ||
654 | &iio_dev_attr_proximity_persist.dev_attr.attr, | ||
655 | &iio_dev_attr_proximity_value.dev_attr.attr, | ||
656 | NULL | ||
657 | }; | ||
658 | |||
659 | static const struct attribute_group ltr558_group = { | ||
660 | .attrs = ltr558_attributes, | ||
661 | }; | ||
662 | |||
663 | static int ltr558_chip_init(struct i2c_client *client) | ||
664 | { | ||
665 | struct ltr558_chip *chip = i2c_get_clientdata(client); | ||
666 | int error = 0; | ||
667 | |||
668 | mdelay(PON_DELAY); | ||
669 | |||
670 | chip->is_prox_enable = 0; | ||
671 | chip->prox_low_thres = 0; | ||
672 | chip->prox_high_thres = 0x7FF; | ||
673 | chip->prox_reading = 0; | ||
674 | |||
675 | chip->als_low_thres = 0; | ||
676 | chip->als_high_thres = 0xFFFF; | ||
677 | chip->als_reading = 0; | ||
678 | |||
679 | chip->is_als_enable = 0; | ||
680 | chip->prox_persist = 0; | ||
681 | chip->als_persist = 0; | ||
682 | |||
683 | /* Enable PS to Gain1 at startup */ | ||
684 | chip->ps_gainrange = PS_RANGE1; | ||
685 | error = ltr558_ps_enable(client, chip->ps_gainrange); | ||
686 | if (error < 0) | ||
687 | goto out; | ||
688 | |||
689 | |||
690 | /* Enable ALS to Full Range at startup */ | ||
691 | chip->als_gainrange = ALS_RANGE2_64K; | ||
692 | error = ltr558_als_enable(client, chip->als_gainrange); | ||
693 | if (error < 0) | ||
694 | goto out; | ||
695 | |||
696 | out: | ||
697 | return error; | ||
698 | } | ||
699 | |||
700 | static const struct iio_info ltr558_info = { | ||
701 | .attrs = <r558_group, | ||
702 | .driver_module = THIS_MODULE, | ||
703 | }; | ||
704 | |||
705 | static irqreturn_t threshold_isr(int irq, void *irq_data) | ||
706 | { | ||
707 | struct ltr558_chip *chip = (struct ltr558_chip *)irq_data; | ||
708 | s32 int_reg; | ||
709 | struct i2c_client *client = chip->client; | ||
710 | |||
711 | int_reg = i2c_smbus_read_byte_data(client, LTR558_ALS_PS_STATUS); | ||
712 | if (int_reg < 0) { | ||
713 | dev_err(&client->dev, "Error in reading register %d, error %d\n", | ||
714 | LTR558_ALS_PS_STATUS, int_reg); | ||
715 | return IRQ_HANDLED; | ||
716 | } | ||
717 | |||
718 | if (int_reg & STATUS_ALS_INT_TRIGGER) { | ||
719 | if (int_reg & STATUS_ALS_NEW_DATA) | ||
720 | chip->als_reading = ltr558_als_read(client); | ||
721 | } | ||
722 | |||
723 | if (int_reg & STATUS_PS_INT_TRIGGER) { | ||
724 | if (int_reg & STATUS_PS_NEW_DATA) | ||
725 | chip->prox_reading = ltr558_ps_read(client); | ||
726 | } | ||
727 | |||
728 | return IRQ_HANDLED; | ||
729 | } | ||
730 | |||
731 | static int ltr558_probe(struct i2c_client *client, | ||
732 | const struct i2c_device_id *id) | ||
733 | { | ||
734 | int ret = 0; | ||
735 | struct ltr558_chip *chip; | ||
736 | |||
737 | /* data memory allocation */ | ||
738 | chip = kzalloc(sizeof(struct ltr558_chip), GFP_KERNEL); | ||
739 | if (chip == NULL) { | ||
740 | printk(KERN_ALERT "%s: LTR-558ALS kzalloc failed.\n", __func__); | ||
741 | ret = -ENOMEM; | ||
742 | goto exit; | ||
743 | } | ||
744 | |||
745 | i2c_set_clientdata(client, chip); | ||
746 | chip->client = client; | ||
747 | chip->irq = client->irq; | ||
748 | |||
749 | if (chip->irq > 0) { | ||
750 | ret = request_threaded_irq(chip->irq, NULL, threshold_isr, | ||
751 | IRQF_SHARED, "LTR558_ALS", chip); | ||
752 | if (ret) { | ||
753 | dev_err(&client->dev, "Unable to register irq %d; " | ||
754 | "ret %d\n", chip->irq, ret); | ||
755 | goto exit_free; | ||
756 | } | ||
757 | } | ||
758 | |||
759 | mutex_init(&chip->lock); | ||
760 | |||
761 | ret = ltr558_chip_init(client); | ||
762 | if (ret) | ||
763 | goto exit_free; | ||
764 | |||
765 | chip->indio_dev = iio_allocate_device(0); | ||
766 | if (!chip->indio_dev) { | ||
767 | dev_err(&client->dev, "iio allocation fails\n"); | ||
768 | goto exit_irq; | ||
769 | } | ||
770 | |||
771 | chip->indio_dev->info = <r558_info; | ||
772 | chip->indio_dev->dev.parent = &client->dev; | ||
773 | chip->indio_dev->dev_data = (void *)(chip); | ||
774 | chip->indio_dev->modes = INDIO_DIRECT_MODE; | ||
775 | ret = iio_device_register(chip->indio_dev); | ||
776 | if (ret) { | ||
777 | dev_err(&client->dev, "iio registration fails\n"); | ||
778 | goto exit_iio_free; | ||
779 | } | ||
780 | |||
781 | dev_dbg(&client->dev, "%s() success\n", __func__); | ||
782 | return 0; | ||
783 | |||
784 | exit_iio_free: | ||
785 | iio_free_device(chip->indio_dev); | ||
786 | exit_irq: | ||
787 | if (chip->irq > 0) | ||
788 | free_irq(chip->irq, chip); | ||
789 | exit_free: | ||
790 | kfree(chip); | ||
791 | exit: | ||
792 | return ret; | ||
793 | } | ||
794 | |||
795 | |||
796 | static int ltr558_remove(struct i2c_client *client) | ||
797 | { | ||
798 | struct ltr558_chip *chip = i2c_get_clientdata(client); | ||
799 | |||
800 | dev_dbg(&client->dev, "%s()\n", __func__); | ||
801 | iio_device_unregister(chip->indio_dev); | ||
802 | if (chip->irq > 0) | ||
803 | free_irq(chip->irq, chip); | ||
804 | ltr558_ps_disable(client); | ||
805 | ltr558_als_disable(client); | ||
806 | kfree(chip); | ||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | |||
811 | static int ltr558_suspend(struct i2c_client *client, pm_message_t mesg) | ||
812 | { | ||
813 | struct ltr558_chip *chip = i2c_get_clientdata(client); | ||
814 | int ret; | ||
815 | |||
816 | if (chip->is_als_enable == 1) | ||
817 | chip->als_enabled_before_suspend = 1; | ||
818 | if (chip->is_prox_enable == 1) | ||
819 | chip->prox_enabled_before_suspend = 1; | ||
820 | |||
821 | ret = ltr558_ps_disable(client); | ||
822 | if (ret == 0) | ||
823 | ret = ltr558_als_disable(client); | ||
824 | |||
825 | return ret; | ||
826 | } | ||
827 | |||
828 | |||
829 | static int ltr558_resume(struct i2c_client *client) | ||
830 | { | ||
831 | struct ltr558_chip *chip = i2c_get_clientdata(client); | ||
832 | int error = 0; | ||
833 | |||
834 | mdelay(PON_DELAY); | ||
835 | |||
836 | if (chip->prox_enabled_before_suspend == 1) { | ||
837 | error = ltr558_ps_enable(client, chip->ps_gainrange); | ||
838 | if (error < 0) | ||
839 | goto out; | ||
840 | } | ||
841 | |||
842 | if (chip->als_enabled_before_suspend == 1) { | ||
843 | error = ltr558_als_enable(client, chip->als_gainrange); | ||
844 | } | ||
845 | out: | ||
846 | return error; | ||
847 | } | ||
848 | |||
849 | |||
850 | static const struct i2c_device_id ltr558_id[] = { | ||
851 | { DEVICE_NAME, 0 }, | ||
852 | {} | ||
853 | }; | ||
854 | |||
855 | |||
856 | static struct i2c_driver ltr558_driver = { | ||
857 | .class = I2C_CLASS_HWMON, | ||
858 | .probe = ltr558_probe, | ||
859 | .remove = ltr558_remove, | ||
860 | .id_table = ltr558_id, | ||
861 | .driver = { | ||
862 | .owner = THIS_MODULE, | ||
863 | .name = DEVICE_NAME, | ||
864 | }, | ||
865 | .suspend = ltr558_suspend, | ||
866 | .resume = ltr558_resume, | ||
867 | }; | ||
868 | |||
869 | |||
870 | static int __init ltr558_driverinit(void) | ||
871 | { | ||
872 | return i2c_add_driver(<r558_driver); | ||
873 | } | ||
874 | |||
875 | |||
876 | static void __exit ltr558_driverexit(void) | ||
877 | { | ||
878 | i2c_del_driver(<r558_driver); | ||
879 | } | ||
880 | |||
881 | |||
882 | module_init(ltr558_driverinit) | ||
883 | module_exit(ltr558_driverexit) | ||
diff --git a/drivers/staging/iio/light/ltr558als.h b/drivers/staging/iio/light/ltr558als.h new file mode 100644 index 00000000000..17e1b903f66 --- /dev/null +++ b/drivers/staging/iio/light/ltr558als.h | |||
@@ -0,0 +1,76 @@ | |||
1 | /* Lite-On LTR-558ALS Linux Driver | ||
2 | * | ||
3 | * Copyright (c) 2012, NVIDIA Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | */ | ||
10 | |||
11 | #ifndef _LTR558_H | ||
12 | #define _LTR558_H | ||
13 | |||
14 | |||
15 | /* LTR-558 Registers */ | ||
16 | #define LTR558_ALS_CONTR 0x80 | ||
17 | #define LTR558_PS_CONTR 0x81 | ||
18 | #define LTR558_PS_LED 0x82 | ||
19 | #define LTR558_PS_N_PULSES 0x83 | ||
20 | #define LTR558_PS_MEAS_RATE 0x84 | ||
21 | #define LTR558_ALS_MEAS_RATE 0x85 | ||
22 | #define LTR558_MANUFACTURER_ID 0x87 | ||
23 | |||
24 | #define LTR558_INTERRUPT 0x8F | ||
25 | #define LTR558_PS_THRES_UP_0 0x90 | ||
26 | #define LTR558_PS_THRES_UP_1 0x91 | ||
27 | #define LTR558_PS_THRES_LOW_0 0x92 | ||
28 | #define LTR558_PS_THRES_LOW_1 0x93 | ||
29 | |||
30 | #define LTR558_ALS_THRES_UP_0 0x97 | ||
31 | #define LTR558_ALS_THRES_UP_1 0x98 | ||
32 | #define LTR558_ALS_THRES_LOW_0 0x99 | ||
33 | #define LTR558_ALS_THRES_LOW_1 0x9A | ||
34 | |||
35 | #define LTR558_INTERRUPT_PERSIST 0x9E | ||
36 | |||
37 | /* 558's Read Only Registers */ | ||
38 | #define LTR558_ALS_DATA_CH1_0 0x88 | ||
39 | #define LTR558_ALS_DATA_CH1_1 0x89 | ||
40 | #define LTR558_ALS_DATA_CH0_0 0x8A | ||
41 | #define LTR558_ALS_DATA_CH0_1 0x8B | ||
42 | #define LTR558_ALS_PS_STATUS 0x8C | ||
43 | #define LTR558_PS_DATA_0 0x8D | ||
44 | #define LTR558_PS_DATA_1 0x8E | ||
45 | |||
46 | /* ALS PS STATUS 0x8C */ | ||
47 | #define STATUS_ALS_GAIN_RANGE1 0x10 | ||
48 | #define STATUS_ALS_INT_TRIGGER 0x08 | ||
49 | #define STATUS_ALS_NEW_DATA 0x04 | ||
50 | #define STATUS_PS_INT_TRIGGER 0x02 | ||
51 | #define STATUS_PS_NEW_DATA 0x01 | ||
52 | |||
53 | /* Basic Operating Modes */ | ||
54 | #define MODE_ALS_ON_Range1 0x0B | ||
55 | #define MODE_ALS_ON_Range2 0x03 | ||
56 | #define MODE_ALS_StdBy 0x00 | ||
57 | |||
58 | #define MODE_PS_ON_Gain1 0x03 | ||
59 | #define MODE_PS_ON_Gain4 0x07 | ||
60 | #define MODE_PS_ON_Gain8 0x0B | ||
61 | #define MODE_PS_ON_Gain16 0x0F | ||
62 | #define MODE_PS_StdBy 0x00 | ||
63 | |||
64 | #define PS_RANGE1 1 | ||
65 | #define PS_RANGE4 2 | ||
66 | #define PS_RANGE8 4 | ||
67 | #define PS_RANGE16 8 | ||
68 | |||
69 | #define ALS_RANGE1_320 1 | ||
70 | #define ALS_RANGE2_64K 2 | ||
71 | |||
72 | /* Power On response time in ms */ | ||
73 | #define PON_DELAY 600 | ||
74 | #define WAKEUP_DELAY 10 | ||
75 | |||
76 | #endif | ||
diff --git a/drivers/staging/iio/magnetometer/magnet.h b/drivers/staging/iio/magnetometer/magnet.h new file mode 100644 index 00000000000..1260eb7bd41 --- /dev/null +++ b/drivers/staging/iio/magnetometer/magnet.h | |||
@@ -0,0 +1,31 @@ | |||
1 | |||
2 | #include "../sysfs.h" | ||
3 | |||
4 | /* Magnetometer types of attribute */ | ||
5 | |||
6 | #define IIO_DEV_ATTR_MAGN_X_OFFSET(_mode, _show, _store, _addr) \ | ||
7 | IIO_DEVICE_ATTR(magn_x_offset, _mode, _show, _store, _addr) | ||
8 | |||
9 | #define IIO_DEV_ATTR_MAGN_Y_OFFSET(_mode, _show, _store, _addr) \ | ||
10 | IIO_DEVICE_ATTR(magn_y_offset, _mode, _show, _store, _addr) | ||
11 | |||
12 | #define IIO_DEV_ATTR_MAGN_Z_OFFSET(_mode, _show, _store, _addr) \ | ||
13 | IIO_DEVICE_ATTR(magn_z_offset, _mode, _show, _store, _addr) | ||
14 | |||
15 | #define IIO_DEV_ATTR_MAGN_X_SCALE(_mode, _show, _store, _addr) \ | ||
16 | IIO_DEVICE_ATTR(magn_x_scale, _mode, _show, _store, _addr) | ||
17 | |||
18 | #define IIO_DEV_ATTR_MAGN_Y_SCALE(_mode, _show, _store, _addr) \ | ||
19 | IIO_DEVICE_ATTR(magn_y_scale, _mode, _show, _store, _addr) | ||
20 | |||
21 | #define IIO_DEV_ATTR_MAGN_Z_SCALE(_mode, _show, _store, _addr) \ | ||
22 | IIO_DEVICE_ATTR(magn_z_scale, _mode, _show, _store, _addr) | ||
23 | |||
24 | #define IIO_DEV_ATTR_MAGN_X(_show, _addr) \ | ||
25 | IIO_DEVICE_ATTR(magn_x_raw, S_IRUGO, _show, NULL, _addr) | ||
26 | |||
27 | #define IIO_DEV_ATTR_MAGN_Y(_show, _addr) \ | ||
28 | IIO_DEVICE_ATTR(magn_y_raw, S_IRUGO, _show, NULL, _addr) | ||
29 | |||
30 | #define IIO_DEV_ATTR_MAGN_Z(_show, _addr) \ | ||
31 | IIO_DEVICE_ATTR(magn_z_raw, S_IRUGO, _show, NULL, _addr) | ||
diff --git a/drivers/staging/iio/resolver/ad2s120x.c b/drivers/staging/iio/resolver/ad2s120x.c new file mode 100644 index 00000000000..bed4c725f2d --- /dev/null +++ b/drivers/staging/iio/resolver/ad2s120x.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | * ad2s120x.c simple support for the ADI Resolver to Digital Converters: AD2S1200/1205 | ||
3 | * | ||
4 | * Copyright (c) 2010-2010 Analog Devices Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/types.h> | ||
12 | #include <linux/mutex.h> | ||
13 | #include <linux/device.h> | ||
14 | #include <linux/spi/spi.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/sysfs.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/gpio.h> | ||
19 | |||
20 | #include "../iio.h" | ||
21 | #include "../sysfs.h" | ||
22 | |||
23 | #define DRV_NAME "ad2s120x" | ||
24 | |||
25 | /* input pin sample and rdvel is controlled by driver */ | ||
26 | #define AD2S120X_PN 2 | ||
27 | |||
28 | /* input clock on serial interface */ | ||
29 | #define AD2S120X_HZ 8192000 | ||
30 | /* clock period in nano second */ | ||
31 | #define AD2S120X_TSCLK (1000000000/AD2S120X_HZ) | ||
32 | |||
33 | struct ad2s120x_state { | ||
34 | struct mutex lock; | ||
35 | struct spi_device *sdev; | ||
36 | int sample; | ||
37 | int rdvel; | ||
38 | u8 rx[2] ____cacheline_aligned; | ||
39 | }; | ||
40 | |||
41 | static ssize_t ad2s120x_show_val(struct device *dev, | ||
42 | struct device_attribute *attr, char *buf) | ||
43 | { | ||
44 | int ret = 0; | ||
45 | ssize_t len = 0; | ||
46 | u16 pos; | ||
47 | s16 vel; | ||
48 | u8 status; | ||
49 | struct ad2s120x_state *st = iio_priv(dev_get_drvdata(dev)); | ||
50 | struct iio_dev_attr *iattr = to_iio_dev_attr(attr); | ||
51 | |||
52 | mutex_lock(&st->lock); | ||
53 | |||
54 | gpio_set_value(st->sample, 0); | ||
55 | /* delay (6 * AD2S120X_TSCLK + 20) nano seconds */ | ||
56 | udelay(1); | ||
57 | gpio_set_value(st->sample, 1); | ||
58 | gpio_set_value(st->rdvel, iattr->address); | ||
59 | ret = spi_read(st->sdev, st->rx, 2); | ||
60 | if (ret < 0) | ||
61 | goto error_ret; | ||
62 | status = st->rx[1]; | ||
63 | if (iattr->address) | ||
64 | pos = (((u16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4); | ||
65 | else { | ||
66 | vel = (st->rx[0] & 0x80) ? 0xf000 : 0; | ||
67 | vel |= (((s16)(st->rx[0])) << 4) | ((st->rx[1] & 0xF0) >> 4); | ||
68 | } | ||
69 | len = sprintf(buf, "%d %c%c%c%c ", iattr->address ? pos : vel, | ||
70 | (status & 0x8) ? 'P' : 'V', | ||
71 | (status & 0x4) ? 'd' : '_', | ||
72 | (status & 0x2) ? 'l' : '_', | ||
73 | (status & 0x1) ? '1' : '0'); | ||
74 | error_ret: | ||
75 | /* delay (2 * AD2S120X_TSCLK + 20) ns for sample pulse */ | ||
76 | udelay(1); | ||
77 | mutex_unlock(&st->lock); | ||
78 | |||
79 | return ret ? ret : len; | ||
80 | } | ||
81 | |||
82 | static IIO_DEVICE_ATTR(pos, S_IRUGO, ad2s120x_show_val, NULL, 1); | ||
83 | static IIO_DEVICE_ATTR(vel, S_IRUGO, ad2s120x_show_val, NULL, 0); | ||
84 | |||
85 | static struct attribute *ad2s120x_attributes[] = { | ||
86 | &iio_dev_attr_pos.dev_attr.attr, | ||
87 | &iio_dev_attr_vel.dev_attr.attr, | ||
88 | NULL, | ||
89 | }; | ||
90 | |||
91 | static const struct attribute_group ad2s120x_attribute_group = { | ||
92 | .attrs = ad2s120x_attributes, | ||
93 | }; | ||
94 | |||
95 | static const struct iio_info ad2s120x_info = { | ||
96 | .attrs = &ad2s120x_attribute_group, | ||
97 | .driver_module = THIS_MODULE, | ||
98 | }; | ||
99 | |||
100 | static int __devinit ad2s120x_probe(struct spi_device *spi) | ||
101 | { | ||
102 | struct ad2s120x_state *st; | ||
103 | struct iio_dev *indio_dev; | ||
104 | int pn, ret = 0; | ||
105 | unsigned short *pins = spi->dev.platform_data; | ||
106 | |||
107 | for (pn = 0; pn < AD2S120X_PN; pn++) | ||
108 | if (gpio_request_one(pins[pn], GPIOF_DIR_OUT, DRV_NAME)) { | ||
109 | pr_err("%s: request gpio pin %d failed\n", | ||
110 | DRV_NAME, pins[pn]); | ||
111 | goto error_ret; | ||
112 | } | ||
113 | indio_dev = iio_allocate_device(sizeof(*st)); | ||
114 | if (indio_dev == NULL) { | ||
115 | ret = -ENOMEM; | ||
116 | goto error_ret; | ||
117 | } | ||
118 | spi_set_drvdata(spi, indio_dev); | ||
119 | st = iio_priv(indio_dev); | ||
120 | mutex_init(&st->lock); | ||
121 | st->sdev = spi; | ||
122 | st->sample = pins[0]; | ||
123 | st->rdvel = pins[1]; | ||
124 | |||
125 | indio_dev->dev.parent = &spi->dev; | ||
126 | indio_dev->info = &ad2s120x_info; | ||
127 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
128 | |||
129 | ret = iio_device_register(indio_dev); | ||
130 | if (ret) | ||
131 | goto error_free_dev; | ||
132 | |||
133 | spi->max_speed_hz = AD2S120X_HZ; | ||
134 | spi->mode = SPI_MODE_3; | ||
135 | spi_setup(spi); | ||
136 | |||
137 | return 0; | ||
138 | |||
139 | error_free_dev: | ||
140 | iio_free_device(indio_dev); | ||
141 | error_ret: | ||
142 | for (--pn; pn >= 0; pn--) | ||
143 | gpio_free(pins[pn]); | ||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | static int __devexit ad2s120x_remove(struct spi_device *spi) | ||
148 | { | ||
149 | iio_device_unregister(spi_get_drvdata(spi)); | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static struct spi_driver ad2s120x_driver = { | ||
155 | .driver = { | ||
156 | .name = DRV_NAME, | ||
157 | .owner = THIS_MODULE, | ||
158 | }, | ||
159 | .probe = ad2s120x_probe, | ||
160 | .remove = __devexit_p(ad2s120x_remove), | ||
161 | }; | ||
162 | |||
163 | static __init int ad2s120x_spi_init(void) | ||
164 | { | ||
165 | return spi_register_driver(&ad2s120x_driver); | ||
166 | } | ||
167 | module_init(ad2s120x_spi_init); | ||
168 | |||
169 | static __exit void ad2s120x_spi_exit(void) | ||
170 | { | ||
171 | spi_unregister_driver(&ad2s120x_driver); | ||
172 | } | ||
173 | module_exit(ad2s120x_spi_exit); | ||
174 | |||
175 | MODULE_AUTHOR("Graff Yang <graff.yang@gmail.com>"); | ||
176 | MODULE_DESCRIPTION("Analog Devices AD2S1200/1205 Resolver to Digital SPI driver"); | ||
177 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/staging/iio/ring_generic.h b/drivers/staging/iio/ring_generic.h new file mode 100644 index 00000000000..3f26f7175b6 --- /dev/null +++ b/drivers/staging/iio/ring_generic.h | |||
@@ -0,0 +1,288 @@ | |||
1 | /* The industrial I/O core - generic ring buffer interfaces. | ||
2 | * | ||
3 | * Copyright (c) 2008 Jonathan Cameron | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 2 as published by | ||
7 | * the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #ifndef _IIO_RING_GENERIC_H_ | ||
11 | #define _IIO_RING_GENERIC_H_ | ||
12 | #include "iio.h" | ||
13 | |||
14 | #ifdef CONFIG_IIO_RING_BUFFER | ||
15 | |||
16 | struct iio_ring_buffer; | ||
17 | |||
18 | /** | ||
19 | * struct iio_ring_access_funcs - access functions for ring buffers. | ||
20 | * @mark_in_use: reference counting, typically to prevent module removal | ||
21 | * @unmark_in_use: reduce reference count when no longer using ring buffer | ||
22 | * @store_to: actually store stuff to the ring buffer | ||
23 | * @read_last: get the last element stored | ||
24 | * @read_first_n: try to get a specified number of elements (must exist) | ||
25 | * @mark_param_change: notify ring that some relevant parameter has changed | ||
26 | * Often this means the underlying storage may need to | ||
27 | * change. | ||
28 | * @request_update: if a parameter change has been marked, update underlying | ||
29 | * storage. | ||
30 | * @get_bytes_per_datum:get current bytes per datum | ||
31 | * @set_bytes_per_datum:set number of bytes per datum | ||
32 | * @get_length: get number of datums in ring | ||
33 | * @set_length: set number of datums in ring | ||
34 | * @is_enabled: query if ring is currently being used | ||
35 | * @enable: enable the ring | ||
36 | * | ||
37 | * The purpose of this structure is to make the ring buffer element | ||
38 | * modular as event for a given driver, different usecases may require | ||
39 | * different ring designs (space efficiency vs speed for example). | ||
40 | * | ||
41 | * It is worth noting that a given ring implementation may only support a small | ||
42 | * proportion of these functions. The core code 'should' cope fine with any of | ||
43 | * them not existing. | ||
44 | **/ | ||
45 | struct iio_ring_access_funcs { | ||
46 | void (*mark_in_use)(struct iio_ring_buffer *ring); | ||
47 | void (*unmark_in_use)(struct iio_ring_buffer *ring); | ||
48 | |||
49 | int (*store_to)(struct iio_ring_buffer *ring, u8 *data, s64 timestamp); | ||
50 | int (*read_last)(struct iio_ring_buffer *ring, u8 *data); | ||
51 | int (*read_first_n)(struct iio_ring_buffer *ring, | ||
52 | size_t n, | ||
53 | char __user *buf); | ||
54 | |||
55 | int (*mark_param_change)(struct iio_ring_buffer *ring); | ||
56 | int (*request_update)(struct iio_ring_buffer *ring); | ||
57 | |||
58 | int (*get_bytes_per_datum)(struct iio_ring_buffer *ring); | ||
59 | int (*set_bytes_per_datum)(struct iio_ring_buffer *ring, size_t bpd); | ||
60 | int (*get_length)(struct iio_ring_buffer *ring); | ||
61 | int (*set_length)(struct iio_ring_buffer *ring, int length); | ||
62 | |||
63 | int (*is_enabled)(struct iio_ring_buffer *ring); | ||
64 | int (*enable)(struct iio_ring_buffer *ring); | ||
65 | }; | ||
66 | |||
67 | struct iio_ring_setup_ops { | ||
68 | int (*preenable)(struct iio_dev *); | ||
69 | int (*postenable)(struct iio_dev *); | ||
70 | int (*predisable)(struct iio_dev *); | ||
71 | int (*postdisable)(struct iio_dev *); | ||
72 | }; | ||
73 | |||
74 | /** | ||
75 | * struct iio_ring_buffer - general ring buffer structure | ||
76 | * @dev: ring buffer device struct | ||
77 | * @indio_dev: industrial I/O device structure | ||
78 | * @owner: module that owns the ring buffer (for ref counting) | ||
79 | * @length: [DEVICE] number of datums in ring | ||
80 | * @bytes_per_datum: [DEVICE] size of individual datum including timestamp | ||
81 | * @bpe: [DEVICE] size of individual channel value | ||
82 | * @scan_el_attrs: [DRIVER] control of scan elements if that scan mode | ||
83 | * control method is used | ||
84 | * @scan_count: [INTERN] the number of elements in the current scan mode | ||
85 | * @scan_mask: [INTERN] bitmask used in masking scan mode elements | ||
86 | * @scan_timestamp: [INTERN] does the scan mode include a timestamp | ||
87 | * @access_handler: [INTERN] chrdev access handling | ||
88 | * @access: [DRIVER] ring access functions associated with the | ||
89 | * implementation. | ||
90 | * @preenable: [DRIVER] function to run prior to marking ring enabled | ||
91 | * @postenable: [DRIVER] function to run after marking ring enabled | ||
92 | * @predisable: [DRIVER] function to run prior to marking ring disabled | ||
93 | * @postdisable: [DRIVER] function to run after marking ring disabled | ||
94 | **/ | ||
95 | struct iio_ring_buffer { | ||
96 | struct device dev; | ||
97 | struct iio_dev *indio_dev; | ||
98 | struct module *owner; | ||
99 | int length; | ||
100 | int bytes_per_datum; | ||
101 | int bpe; | ||
102 | struct attribute_group *scan_el_attrs; | ||
103 | int scan_count; | ||
104 | unsigned long scan_mask; | ||
105 | bool scan_timestamp; | ||
106 | struct iio_handler access_handler; | ||
107 | const struct iio_ring_access_funcs *access; | ||
108 | const struct iio_ring_setup_ops *setup_ops; | ||
109 | struct list_head scan_el_dev_attr_list; | ||
110 | |||
111 | wait_queue_head_t pollq; | ||
112 | bool stufftoread; | ||
113 | }; | ||
114 | |||
115 | /** | ||
116 | * iio_ring_buffer_init() - Initialize the buffer structure | ||
117 | * @ring: buffer to be initialized | ||
118 | * @dev_info: the iio device the buffer is assocated with | ||
119 | **/ | ||
120 | void iio_ring_buffer_init(struct iio_ring_buffer *ring, | ||
121 | struct iio_dev *dev_info); | ||
122 | |||
123 | /** | ||
124 | * __iio_update_ring_buffer() - update common elements of ring buffers | ||
125 | * @ring: ring buffer that is the event source | ||
126 | * @bytes_per_datum: size of individual datum including timestamp | ||
127 | * @length: number of datums in ring | ||
128 | **/ | ||
129 | static inline void __iio_update_ring_buffer(struct iio_ring_buffer *ring, | ||
130 | int bytes_per_datum, int length) | ||
131 | { | ||
132 | ring->bytes_per_datum = bytes_per_datum; | ||
133 | ring->length = length; | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * These are mainly provided to allow for a change of implementation if a device | ||
138 | * has a large number of scan elements | ||
139 | */ | ||
140 | #define IIO_MAX_SCAN_LENGTH 31 | ||
141 | |||
142 | /* note 0 used as error indicator as it doesn't make sense. */ | ||
143 | static inline u32 iio_scan_mask_match(u32 *av_masks, u32 mask) | ||
144 | { | ||
145 | while (*av_masks) { | ||
146 | if (!(~*av_masks & mask)) | ||
147 | return *av_masks; | ||
148 | av_masks++; | ||
149 | } | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static inline int iio_scan_mask_query(struct iio_ring_buffer *ring, int bit) | ||
154 | { | ||
155 | struct iio_dev *dev_info = ring->indio_dev; | ||
156 | u32 mask; | ||
157 | |||
158 | if (bit > IIO_MAX_SCAN_LENGTH) | ||
159 | return -EINVAL; | ||
160 | |||
161 | if (!ring->scan_mask) | ||
162 | return 0; | ||
163 | |||
164 | if (dev_info->available_scan_masks) | ||
165 | mask = iio_scan_mask_match(dev_info->available_scan_masks, | ||
166 | ring->scan_mask); | ||
167 | else | ||
168 | mask = ring->scan_mask; | ||
169 | |||
170 | if (!mask) | ||
171 | return -EINVAL; | ||
172 | |||
173 | return !!(mask & (1 << bit)); | ||
174 | }; | ||
175 | |||
176 | /** | ||
177 | * iio_scan_mask_set() - set particular bit in the scan mask | ||
178 | * @ring: the ring buffer whose scan mask we are interested in | ||
179 | * @bit: the bit to be set. | ||
180 | **/ | ||
181 | static inline int iio_scan_mask_set(struct iio_ring_buffer *ring, int bit) | ||
182 | { | ||
183 | struct iio_dev *dev_info = ring->indio_dev; | ||
184 | u32 mask; | ||
185 | u32 trialmask = ring->scan_mask | (1 << bit); | ||
186 | |||
187 | if (bit > IIO_MAX_SCAN_LENGTH) | ||
188 | return -EINVAL; | ||
189 | if (dev_info->available_scan_masks) { | ||
190 | mask = iio_scan_mask_match(dev_info->available_scan_masks, | ||
191 | trialmask); | ||
192 | if (!mask) | ||
193 | return -EINVAL; | ||
194 | } | ||
195 | ring->scan_mask = trialmask; | ||
196 | ring->scan_count++; | ||
197 | |||
198 | return 0; | ||
199 | }; | ||
200 | |||
201 | /** | ||
202 | * iio_put_ring_buffer() - notify done with buffer | ||
203 | * @ring: the buffer we are done with. | ||
204 | **/ | ||
205 | static inline void iio_put_ring_buffer(struct iio_ring_buffer *ring) | ||
206 | { | ||
207 | put_device(&ring->dev); | ||
208 | }; | ||
209 | |||
210 | #define to_iio_ring_buffer(d) \ | ||
211 | container_of(d, struct iio_ring_buffer, dev) | ||
212 | |||
213 | /** | ||
214 | * iio_ring_buffer_register_ex() - register the buffer with IIO core | ||
215 | * @ring: the buffer to be registered | ||
216 | * @id: the id of the buffer (typically 0) | ||
217 | **/ | ||
218 | int iio_ring_buffer_register_ex(struct iio_ring_buffer *ring, int id, | ||
219 | const struct iio_chan_spec *channels, | ||
220 | int num_channels); | ||
221 | |||
222 | void iio_ring_access_release(struct device *dev); | ||
223 | |||
224 | /** | ||
225 | * iio_ring_buffer_unregister() - unregister the buffer from IIO core | ||
226 | * @ring: the buffer to be unregistered | ||
227 | **/ | ||
228 | void iio_ring_buffer_unregister(struct iio_ring_buffer *ring); | ||
229 | |||
230 | /** | ||
231 | * iio_read_ring_length() - attr func to get number of datums in the buffer | ||
232 | **/ | ||
233 | ssize_t iio_read_ring_length(struct device *dev, | ||
234 | struct device_attribute *attr, | ||
235 | char *buf); | ||
236 | /** | ||
237 | * iio_write_ring_length() - attr func to set number of datums in the buffer | ||
238 | **/ | ||
239 | ssize_t iio_write_ring_length(struct device *dev, | ||
240 | struct device_attribute *attr, | ||
241 | const char *buf, | ||
242 | size_t len); | ||
243 | /** | ||
244 | * iio_read_ring_bytes_per_datum() - attr for number of bytes in whole datum | ||
245 | **/ | ||
246 | ssize_t iio_read_ring_bytes_per_datum(struct device *dev, | ||
247 | struct device_attribute *attr, | ||
248 | char *buf); | ||
249 | /** | ||
250 | * iio_store_ring_enable() - attr to turn the buffer on | ||
251 | **/ | ||
252 | ssize_t iio_store_ring_enable(struct device *dev, | ||
253 | struct device_attribute *attr, | ||
254 | const char *buf, | ||
255 | size_t len); | ||
256 | /** | ||
257 | * iio_show_ring_enable() - attr to see if the buffer is on | ||
258 | **/ | ||
259 | ssize_t iio_show_ring_enable(struct device *dev, | ||
260 | struct device_attribute *attr, | ||
261 | char *buf); | ||
262 | #define IIO_RING_LENGTH_ATTR DEVICE_ATTR(length, S_IRUGO | S_IWUSR, \ | ||
263 | iio_read_ring_length, \ | ||
264 | iio_write_ring_length) | ||
265 | #define IIO_RING_BYTES_PER_DATUM_ATTR DEVICE_ATTR(bytes_per_datum, S_IRUGO | S_IWUSR, \ | ||
266 | iio_read_ring_bytes_per_datum, NULL) | ||
267 | #define IIO_RING_ENABLE_ATTR DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, \ | ||
268 | iio_show_ring_enable, \ | ||
269 | iio_store_ring_enable) | ||
270 | |||
271 | int iio_sw_ring_preenable(struct iio_dev *indio_dev); | ||
272 | |||
273 | #else /* CONFIG_IIO_RING_BUFFER */ | ||
274 | |||
275 | static inline int iio_ring_buffer_register_ex(struct iio_ring_buffer *ring, | ||
276 | int id, | ||
277 | struct iio_chan_spec *channels, | ||
278 | int num_channels) | ||
279 | { | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static inline void iio_ring_buffer_unregister(struct iio_ring_buffer *ring) | ||
284 | {}; | ||
285 | |||
286 | #endif /* CONFIG_IIO_RING_BUFFER */ | ||
287 | |||
288 | #endif /* _IIO_RING_GENERIC_H_ */ | ||
diff --git a/drivers/staging/iio/sysfs.h b/drivers/staging/iio/sysfs.h new file mode 100644 index 00000000000..dd79b584421 --- /dev/null +++ b/drivers/staging/iio/sysfs.h | |||
@@ -0,0 +1,222 @@ | |||
1 | /* The industrial I/O core | ||
2 | * | ||
3 | *Copyright (c) 2008 Jonathan Cameron | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 2 as published by | ||
7 | * the Free Software Foundation. | ||
8 | * | ||
9 | * General attributes | ||
10 | */ | ||
11 | |||
12 | #ifndef _INDUSTRIAL_IO_SYSFS_H_ | ||
13 | #define _INDUSTRIAL_IO_SYSFS_H_ | ||
14 | |||
15 | #include "iio.h" | ||
16 | |||
17 | /** | ||
18 | * struct iio_dev_attr - iio specific device attribute | ||
19 | * @dev_attr: underlying device attribute | ||
20 | * @address: associated register address | ||
21 | * @val2: secondary attribute value | ||
22 | * @l: list head for maintaining list of dynamically created attrs. | ||
23 | */ | ||
24 | struct iio_dev_attr { | ||
25 | struct device_attribute dev_attr; | ||
26 | int address; | ||
27 | int val2; | ||
28 | struct list_head l; | ||
29 | struct iio_chan_spec const *c; | ||
30 | }; | ||
31 | |||
32 | #define to_iio_dev_attr(_dev_attr) \ | ||
33 | container_of(_dev_attr, struct iio_dev_attr, dev_attr) | ||
34 | |||
35 | ssize_t iio_read_const_attr(struct device *dev, | ||
36 | struct device_attribute *attr, | ||
37 | char *len); | ||
38 | |||
39 | /** | ||
40 | * struct iio_const_attr - constant device specific attribute | ||
41 | * often used for things like available modes | ||
42 | * @string: attribute string | ||
43 | * @dev_attr: underlying device attribute | ||
44 | */ | ||
45 | struct iio_const_attr { | ||
46 | const char *string; | ||
47 | struct device_attribute dev_attr; | ||
48 | }; | ||
49 | |||
50 | #define to_iio_const_attr(_dev_attr) \ | ||
51 | container_of(_dev_attr, struct iio_const_attr, dev_attr) | ||
52 | |||
53 | /* Some attributes will be hard coded (device dependent) and not require an | ||
54 | address, in these cases pass a negative */ | ||
55 | #define IIO_ATTR(_name, _mode, _show, _store, _addr) \ | ||
56 | { .dev_attr = __ATTR(_name, _mode, _show, _store), \ | ||
57 | .address = _addr } | ||
58 | |||
59 | #define IIO_DEVICE_ATTR(_name, _mode, _show, _store, _addr) \ | ||
60 | struct iio_dev_attr iio_dev_attr_##_name \ | ||
61 | = IIO_ATTR(_name, _mode, _show, _store, _addr) | ||
62 | |||
63 | #define IIO_DEVICE_ATTR_NAMED(_vname, _name, _mode, _show, _store, _addr) \ | ||
64 | struct iio_dev_attr iio_dev_attr_##_vname \ | ||
65 | = IIO_ATTR(_name, _mode, _show, _store, _addr) | ||
66 | |||
67 | #define IIO_DEVICE_ATTR_2(_name, _mode, _show, _store, _addr, _val2) \ | ||
68 | struct iio_dev_attr iio_dev_attr_##_name \ | ||
69 | = IIO_ATTR_2(_name, _mode, _show, _store, _addr, _val2) | ||
70 | |||
71 | #define IIO_CONST_ATTR(_name, _string) \ | ||
72 | struct iio_const_attr iio_const_attr_##_name \ | ||
73 | = { .string = _string, \ | ||
74 | .dev_attr = __ATTR(_name, S_IRUGO, iio_read_const_attr, NULL)} | ||
75 | |||
76 | #define IIO_CONST_ATTR_NAMED(_vname, _name, _string) \ | ||
77 | struct iio_const_attr iio_const_attr_##_vname \ | ||
78 | = { .string = _string, \ | ||
79 | .dev_attr = __ATTR(_name, S_IRUGO, iio_read_const_attr, NULL)} | ||
80 | /* Generic attributes of onetype or another */ | ||
81 | |||
82 | /** | ||
83 | * IIO_DEV_ATTR_REV - revision number for the device | ||
84 | * @_show: output method for the attribute | ||
85 | * | ||
86 | * Very much device dependent. | ||
87 | **/ | ||
88 | #define IIO_DEV_ATTR_REV(_show) \ | ||
89 | IIO_DEVICE_ATTR(revision, S_IRUGO, _show, NULL, 0) | ||
90 | |||
91 | /** | ||
92 | * IIO_DEV_ATTR_RESET: resets the device | ||
93 | **/ | ||
94 | #define IIO_DEV_ATTR_RESET(_store) \ | ||
95 | IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, _store, 0) | ||
96 | |||
97 | /** | ||
98 | * IIO_CONST_ATTR_NAME - constant identifier | ||
99 | * @_string: the name | ||
100 | **/ | ||
101 | #define IIO_CONST_ATTR_NAME(_string) \ | ||
102 | IIO_CONST_ATTR(name, _string) | ||
103 | |||
104 | /** | ||
105 | * IIO_DEV_ATTR_SAMP_FREQ - sets any internal clock frequency | ||
106 | * @_mode: sysfs file mode/permissions | ||
107 | * @_show: output method for the attribute | ||
108 | * @_store: input method for the attribute | ||
109 | **/ | ||
110 | #define IIO_DEV_ATTR_SAMP_FREQ(_mode, _show, _store) \ | ||
111 | IIO_DEVICE_ATTR(sampling_frequency, _mode, _show, _store, 0) | ||
112 | |||
113 | /** | ||
114 | * IIO_DEV_ATTR_AVAIL_SAMP_FREQ - list available sampling frequencies | ||
115 | * @_show: output method for the attribute | ||
116 | * | ||
117 | * May be mode dependent on some devices | ||
118 | **/ | ||
119 | /* Deprecated */ | ||
120 | #define IIO_DEV_ATTR_AVAIL_SAMP_FREQ(_show) \ | ||
121 | IIO_DEVICE_ATTR(available_sampling_frequency, S_IRUGO, _show, NULL, 0) | ||
122 | |||
123 | #define IIO_DEV_ATTR_SAMP_FREQ_AVAIL(_show) \ | ||
124 | IIO_DEVICE_ATTR(sampling_frequency_available, S_IRUGO, _show, NULL, 0) | ||
125 | /** | ||
126 | * IIO_CONST_ATTR_AVAIL_SAMP_FREQ - list available sampling frequencies | ||
127 | * @_string: frequency string for the attribute | ||
128 | * | ||
129 | * Constant version | ||
130 | **/ | ||
131 | #define IIO_CONST_ATTR_SAMP_FREQ_AVAIL(_string) \ | ||
132 | IIO_CONST_ATTR(sampling_frequency_available, _string) | ||
133 | |||
134 | /** | ||
135 | * IIO_DEV_ATTR_SW_RING_ENABLE - enable software ring buffer | ||
136 | * @_show: output method for the attribute | ||
137 | * @_store: input method for the attribute | ||
138 | * | ||
139 | * Success may be dependent on attachment of trigger previously. | ||
140 | **/ | ||
141 | #define IIO_DEV_ATTR_SW_RING_ENABLE(_show, _store) \ | ||
142 | IIO_DEVICE_ATTR(sw_ring_enable, S_IRUGO | S_IWUSR, _show, _store, 0) | ||
143 | |||
144 | /** | ||
145 | * IIO_DEV_ATTR_HW_RING_ENABLE - enable hardware ring buffer | ||
146 | * @_show: output method for the attribute | ||
147 | * @_store: input method for the attribute | ||
148 | * | ||
149 | * This is a different attribute from the software one as one can envision | ||
150 | * schemes where a combination of the two may be used. | ||
151 | **/ | ||
152 | #define IIO_DEV_ATTR_HW_RING_ENABLE(_show, _store) \ | ||
153 | IIO_DEVICE_ATTR(hw_ring_enable, S_IRUGO | S_IWUSR, _show, _store, 0) | ||
154 | |||
155 | #define IIO_DEV_ATTR_TEMP_RAW(_show) \ | ||
156 | IIO_DEVICE_ATTR(temp_raw, S_IRUGO, _show, NULL, 0) | ||
157 | |||
158 | #define IIO_CONST_ATTR_TEMP_OFFSET(_string) \ | ||
159 | IIO_CONST_ATTR(temp_offset, _string) | ||
160 | |||
161 | #define IIO_CONST_ATTR_TEMP_SCALE(_string) \ | ||
162 | IIO_CONST_ATTR(temp_scale, _string) | ||
163 | |||
164 | /* must match our channel defs */ | ||
165 | #define IIO_EV_CLASS_IN IIO_IN | ||
166 | #define IIO_EV_CLASS_IN_DIFF IIO_IN_DIFF | ||
167 | #define IIO_EV_CLASS_ACCEL IIO_ACCEL | ||
168 | #define IIO_EV_CLASS_GYRO IIO_GYRO | ||
169 | #define IIO_EV_CLASS_MAGN IIO_MAGN | ||
170 | #define IIO_EV_CLASS_LIGHT IIO_LIGHT | ||
171 | #define IIO_EV_CLASS_PROXIMITY IIO_PROXIMITY | ||
172 | #define IIO_EV_CLASS_TEMP IIO_TEMP | ||
173 | |||
174 | #define IIO_EV_MOD_X IIO_MOD_X | ||
175 | #define IIO_EV_MOD_Y IIO_MOD_Y | ||
176 | #define IIO_EV_MOD_Z IIO_MOD_Z | ||
177 | #define IIO_EV_MOD_X_AND_Y IIO_MOD_X_AND_Y | ||
178 | #define IIO_EV_MOD_X_ANX_Z IIO_MOD_X_AND_Z | ||
179 | #define IIO_EV_MOD_Y_AND_Z IIO_MOD_Y_AND_Z | ||
180 | #define IIO_EV_MOD_X_AND_Y_AND_Z IIO_MOD_X_AND_Y_AND_Z | ||
181 | #define IIO_EV_MOD_X_OR_Y IIO_MOD_X_OR_Y | ||
182 | #define IIO_EV_MOD_X_OR_Z IIO_MOD_X_OR_Z | ||
183 | #define IIO_EV_MOD_Y_OR_Z IIO_MOD_Y_OR_Z | ||
184 | #define IIO_EV_MOD_X_OR_Y_OR_Z IIO_MOD_X_OR_Y_OR_Z | ||
185 | |||
186 | #define IIO_EV_TYPE_THRESH 0 | ||
187 | #define IIO_EV_TYPE_MAG 1 | ||
188 | #define IIO_EV_TYPE_ROC 2 | ||
189 | |||
190 | #define IIO_EV_DIR_EITHER 0 | ||
191 | #define IIO_EV_DIR_RISING 1 | ||
192 | #define IIO_EV_DIR_FALLING 2 | ||
193 | |||
194 | #define IIO_EV_TYPE_MAX 8 | ||
195 | #define IIO_EV_BIT(type, direction) \ | ||
196 | (1 << (type*IIO_EV_TYPE_MAX + direction)) | ||
197 | |||
198 | #define IIO_EVENT_CODE(channelclass, orient_bit, number, \ | ||
199 | modifier, type, direction) \ | ||
200 | (channelclass | (orient_bit << 8) | ((number) << 9) | \ | ||
201 | ((modifier) << 13) | ((type) << 16) | ((direction) << 24)) | ||
202 | |||
203 | #define IIO_MOD_EVENT_CODE(channelclass, number, modifier, \ | ||
204 | type, direction) \ | ||
205 | IIO_EVENT_CODE(channelclass, 1, number, modifier, type, direction) | ||
206 | |||
207 | #define IIO_UNMOD_EVENT_CODE(channelclass, number, type, direction) \ | ||
208 | IIO_EVENT_CODE(channelclass, 0, number, 0, type, direction) | ||
209 | |||
210 | |||
211 | #define IIO_BUFFER_EVENT_CODE(code) \ | ||
212 | (IIO_EV_CLASS_BUFFER | (code << 8)) | ||
213 | |||
214 | #define IIO_EVENT_CODE_EXTRACT_DIR(mask) ((mask >> 24) & 0xf) | ||
215 | |||
216 | /* Event code number extraction depends on which type of event we have. | ||
217 | * Perhaps review this function in the future*/ | ||
218 | #define IIO_EVENT_CODE_EXTRACT_NUM(mask) ((mask >> 9) & 0x0f) | ||
219 | |||
220 | #define IIO_EVENT_CODE_EXTRACT_MODIFIER(mask) ((mask >> 13) & 0x7) | ||
221 | |||
222 | #endif /* _INDUSTRIAL_IO_SYSFS_H_ */ | ||
diff --git a/drivers/staging/iio/trigger.h b/drivers/staging/iio/trigger.h new file mode 100644 index 00000000000..e0b58ed749b --- /dev/null +++ b/drivers/staging/iio/trigger.h | |||
@@ -0,0 +1,188 @@ | |||
1 | /* The industrial I/O core, trigger handling functions | ||
2 | * | ||
3 | * Copyright (c) 2008 Jonathan Cameron | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 2 as published by | ||
7 | * the Free Software Foundation. | ||
8 | */ | ||
9 | #include <linux/irq.h> | ||
10 | |||
11 | #ifndef _IIO_TRIGGER_H_ | ||
12 | #define _IIO_TRIGGER_H_ | ||
13 | |||
14 | struct iio_subirq { | ||
15 | bool enabled; | ||
16 | }; | ||
17 | |||
18 | /** | ||
19 | * struct iio_trigger - industrial I/O trigger device | ||
20 | * | ||
21 | * @id: [INTERN] unique id number | ||
22 | * @name: [DRIVER] unique name | ||
23 | * @dev: [DRIVER] associated device (if relevant) | ||
24 | * @private_data: [DRIVER] device specific data | ||
25 | * @list: [INTERN] used in maintenance of global trigger list | ||
26 | * @alloc_list: [DRIVER] used for driver specific trigger list | ||
27 | * @owner: [DRIVER] used to monitor usage count of the trigger. | ||
28 | * @use_count: use count for the trigger | ||
29 | * @set_trigger_state: [DRIVER] switch on/off the trigger on demand | ||
30 | * @try_reenable: function to reenable the trigger when the | ||
31 | * use count is zero (may be NULL) | ||
32 | * @validate_device: function to validate the device when the | ||
33 | * current trigger gets changed. | ||
34 | * @subirq_chip: [INTERN] associate 'virtual' irq chip. | ||
35 | * @subirq_base: [INTERN] base number for irqs provided by trigger. | ||
36 | * @subirqs: [INTERN] information about the 'child' irqs. | ||
37 | * @pool: [INTERN] bitmap of irqs currently in use. | ||
38 | * @pool_lock: [INTERN] protection of the irq pool. | ||
39 | **/ | ||
40 | struct iio_trigger { | ||
41 | int id; | ||
42 | const char *name; | ||
43 | struct device dev; | ||
44 | |||
45 | void *private_data; | ||
46 | struct list_head list; | ||
47 | struct list_head alloc_list; | ||
48 | struct module *owner; | ||
49 | int use_count; | ||
50 | |||
51 | int (*set_trigger_state)(struct iio_trigger *trig, bool state); | ||
52 | int (*try_reenable)(struct iio_trigger *trig); | ||
53 | int (*validate_device)(struct iio_trigger *trig, | ||
54 | struct iio_dev *indio_dev); | ||
55 | |||
56 | struct irq_chip subirq_chip; | ||
57 | int subirq_base; | ||
58 | |||
59 | struct iio_subirq subirqs[CONFIG_IIO_CONSUMERS_PER_TRIGGER]; | ||
60 | unsigned long pool[BITS_TO_LONGS(CONFIG_IIO_CONSUMERS_PER_TRIGGER)]; | ||
61 | struct mutex pool_lock; | ||
62 | }; | ||
63 | |||
64 | /** | ||
65 | * struct iio_poll_func - poll function pair | ||
66 | * | ||
67 | * @private_data: data specific to device (passed into poll func) | ||
68 | * @h: the function that is actually run on trigger | ||
69 | * @thread: threaded interrupt part | ||
70 | * @type: the type of interrupt (basically if oneshot) | ||
71 | * @name: name used to identify the trigger consumer. | ||
72 | * @irq: the corresponding irq as allocated from the | ||
73 | * trigger pool | ||
74 | * @timestamp: some devices need a timestamp grabbed as soon | ||
75 | * as possible after the trigger - hence handler | ||
76 | * passes it via here. | ||
77 | **/ | ||
78 | struct iio_poll_func { | ||
79 | void *private_data; | ||
80 | irqreturn_t (*h)(int irq, void *p); | ||
81 | irqreturn_t (*thread)(int irq, void *p); | ||
82 | int type; | ||
83 | char *name; | ||
84 | int irq; | ||
85 | s64 timestamp; | ||
86 | }; | ||
87 | |||
88 | static inline struct iio_trigger *to_iio_trigger(struct device *d) | ||
89 | { | ||
90 | return container_of(d, struct iio_trigger, dev); | ||
91 | }; | ||
92 | |||
93 | static inline void iio_put_trigger(struct iio_trigger *trig) | ||
94 | { | ||
95 | put_device(&trig->dev); | ||
96 | module_put(trig->owner); | ||
97 | }; | ||
98 | |||
99 | static inline void iio_get_trigger(struct iio_trigger *trig) | ||
100 | { | ||
101 | __module_get(trig->owner); | ||
102 | get_device(&trig->dev); | ||
103 | }; | ||
104 | |||
105 | /** | ||
106 | * iio_trigger_register() - register a trigger with the IIO core | ||
107 | * @trig_info: trigger to be registered | ||
108 | **/ | ||
109 | int iio_trigger_register(struct iio_trigger *trig_info); | ||
110 | |||
111 | /** | ||
112 | * iio_trigger_unregister() - unregister a trigger from the core | ||
113 | * @trig_info: trigger to be unregistered | ||
114 | **/ | ||
115 | void iio_trigger_unregister(struct iio_trigger *trig_info); | ||
116 | |||
117 | /** | ||
118 | * iio_trigger_attach_poll_func() - add a function pair to be run on trigger | ||
119 | * @trig: trigger to which the function pair are being added | ||
120 | * @pf: poll function pair | ||
121 | **/ | ||
122 | int iio_trigger_attach_poll_func(struct iio_trigger *trig, | ||
123 | struct iio_poll_func *pf); | ||
124 | |||
125 | /** | ||
126 | * iio_trigger_dettach_poll_func() - remove function pair from those to be | ||
127 | * run on trigger | ||
128 | * @trig: trigger from which the function is being removed | ||
129 | * @pf: poll function pair | ||
130 | **/ | ||
131 | int iio_trigger_dettach_poll_func(struct iio_trigger *trig, | ||
132 | struct iio_poll_func *pf); | ||
133 | |||
134 | /** | ||
135 | * iio_trigger_poll() - called on a trigger occurring | ||
136 | * @trig: trigger which occurred | ||
137 | * | ||
138 | * Typically called in relevant hardware interrupt handler. | ||
139 | **/ | ||
140 | void iio_trigger_poll(struct iio_trigger *trig, s64 time); | ||
141 | void iio_trigger_poll_chained(struct iio_trigger *trig, s64 time); | ||
142 | void iio_trigger_notify_done(struct iio_trigger *trig); | ||
143 | |||
144 | irqreturn_t iio_trigger_generic_data_rdy_poll(int irq, void *private); | ||
145 | |||
146 | static inline int iio_trigger_get_irq(struct iio_trigger *trig) | ||
147 | { | ||
148 | int ret; | ||
149 | mutex_lock(&trig->pool_lock); | ||
150 | ret = bitmap_find_free_region(trig->pool, | ||
151 | CONFIG_IIO_CONSUMERS_PER_TRIGGER, | ||
152 | ilog2(1)); | ||
153 | mutex_unlock(&trig->pool_lock); | ||
154 | if (ret >= 0) | ||
155 | ret += trig->subirq_base; | ||
156 | |||
157 | return ret; | ||
158 | }; | ||
159 | |||
160 | static inline void iio_trigger_put_irq(struct iio_trigger *trig, int irq) | ||
161 | { | ||
162 | mutex_lock(&trig->pool_lock); | ||
163 | clear_bit(irq - trig->subirq_base, trig->pool); | ||
164 | mutex_unlock(&trig->pool_lock); | ||
165 | }; | ||
166 | |||
167 | struct iio_poll_func | ||
168 | *iio_alloc_pollfunc(irqreturn_t (*h)(int irq, void *p), | ||
169 | irqreturn_t (*thread)(int irq, void *p), | ||
170 | int type, | ||
171 | void *private, | ||
172 | const char *fmt, | ||
173 | ...); | ||
174 | void iio_dealloc_pollfunc(struct iio_poll_func *pf); | ||
175 | irqreturn_t iio_pollfunc_store_time(int irq, void *p); | ||
176 | |||
177 | /* | ||
178 | * Two functions for common case where all that happens is a pollfunc | ||
179 | * is attached and detached from a trigger | ||
180 | */ | ||
181 | int iio_triggered_ring_postenable(struct iio_dev *indio_dev); | ||
182 | int iio_triggered_ring_predisable(struct iio_dev *indio_dev); | ||
183 | |||
184 | struct iio_trigger *iio_allocate_trigger(const char *fmt, ...) | ||
185 | __attribute__((format(printf, 1, 2))); | ||
186 | void iio_free_trigger(struct iio_trigger *trig); | ||
187 | |||
188 | #endif /* _IIO_TRIGGER_H_ */ | ||
diff --git a/drivers/staging/iio/trigger_consumer.h b/drivers/staging/iio/trigger_consumer.h new file mode 100644 index 00000000000..9d52d963777 --- /dev/null +++ b/drivers/staging/iio/trigger_consumer.h | |||
@@ -0,0 +1,47 @@ | |||
1 | |||
2 | /* The industrial I/O core, trigger consumer handling functions | ||
3 | * | ||
4 | * Copyright (c) 2008 Jonathan Cameron | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #ifdef CONFIG_IIO_TRIGGER | ||
12 | /** | ||
13 | * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers | ||
14 | * @dev_info: iio_dev associated with the device that will consume the trigger | ||
15 | **/ | ||
16 | int iio_device_register_trigger_consumer(struct iio_dev *dev_info); | ||
17 | |||
18 | /** | ||
19 | * iio_device_unregister_trigger_consumer() - reverse the registration process | ||
20 | * @dev_info: iio_dev associated with the device that consumed the trigger | ||
21 | **/ | ||
22 | int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info); | ||
23 | |||
24 | #else | ||
25 | |||
26 | /** | ||
27 | * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers | ||
28 | * @dev_info: iio_dev associated with the device that will consume the trigger | ||
29 | **/ | ||
30 | static int iio_device_register_trigger_consumer(struct iio_dev *dev_info) | ||
31 | { | ||
32 | return 0; | ||
33 | }; | ||
34 | |||
35 | /** | ||
36 | * iio_device_unregister_trigger_consumer() - reverse the registration process | ||
37 | * @dev_info: iio_dev associated with the device that consumed the trigger | ||
38 | **/ | ||
39 | static int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info) | ||
40 | { | ||
41 | return 0; | ||
42 | }; | ||
43 | |||
44 | #endif /* CONFIG_TRIGGER_CONSUMER */ | ||
45 | |||
46 | |||
47 | |||