iio: Use spi_sync_transfer()
[pandora-kernel.git] / drivers / iio / inkern.c
1 /* The industrial I/O core in kernel channel mapping
2  *
3  * Copyright (c) 2011 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/err.h>
10 #include <linux/export.h>
11 #include <linux/slab.h>
12 #include <linux/mutex.h>
13
14 #include <linux/iio/iio.h>
15 #include "iio_core.h"
16 #include <linux/iio/machine.h>
17 #include <linux/iio/driver.h>
18 #include <linux/iio/consumer.h>
19
20 struct iio_map_internal {
21         struct iio_dev *indio_dev;
22         struct iio_map *map;
23         struct list_head l;
24 };
25
26 static LIST_HEAD(iio_map_list);
27 static DEFINE_MUTEX(iio_map_list_lock);
28
29 int iio_map_array_register(struct iio_dev *indio_dev, struct iio_map *maps)
30 {
31         int i = 0, ret = 0;
32         struct iio_map_internal *mapi;
33
34         if (maps == NULL)
35                 return 0;
36
37         mutex_lock(&iio_map_list_lock);
38         while (maps[i].consumer_dev_name != NULL) {
39                 mapi = kzalloc(sizeof(*mapi), GFP_KERNEL);
40                 if (mapi == NULL) {
41                         ret = -ENOMEM;
42                         goto error_ret;
43                 }
44                 mapi->map = &maps[i];
45                 mapi->indio_dev = indio_dev;
46                 list_add(&mapi->l, &iio_map_list);
47                 i++;
48         }
49 error_ret:
50         mutex_unlock(&iio_map_list_lock);
51
52         return ret;
53 }
54 EXPORT_SYMBOL_GPL(iio_map_array_register);
55
56
57 /*
58  * Remove all map entries associated with the given iio device
59  */
60 int iio_map_array_unregister(struct iio_dev *indio_dev)
61 {
62         int ret = -ENODEV;
63         struct iio_map_internal *mapi;
64         struct list_head *pos, *tmp;
65
66         mutex_lock(&iio_map_list_lock);
67         list_for_each_safe(pos, tmp, &iio_map_list) {
68                 mapi = list_entry(pos, struct iio_map_internal, l);
69                 if (indio_dev == mapi->indio_dev) {
70                         list_del(&mapi->l);
71                         kfree(mapi);
72                         ret = 0;
73                 }
74         }
75         mutex_unlock(&iio_map_list_lock);
76         return ret;
77 }
78 EXPORT_SYMBOL_GPL(iio_map_array_unregister);
79
80 static const struct iio_chan_spec
81 *iio_chan_spec_from_name(const struct iio_dev *indio_dev, const char *name)
82 {
83         int i;
84         const struct iio_chan_spec *chan = NULL;
85
86         for (i = 0; i < indio_dev->num_channels; i++)
87                 if (indio_dev->channels[i].datasheet_name &&
88                     strcmp(name, indio_dev->channels[i].datasheet_name) == 0) {
89                         chan = &indio_dev->channels[i];
90                         break;
91                 }
92         return chan;
93 }
94
95
96 static struct iio_channel *iio_channel_get_sys(const char *name,
97                                                const char *channel_name)
98 {
99         struct iio_map_internal *c_i = NULL, *c = NULL;
100         struct iio_channel *channel;
101         int err;
102
103         if (name == NULL && channel_name == NULL)
104                 return ERR_PTR(-ENODEV);
105
106         /* first find matching entry the channel map */
107         mutex_lock(&iio_map_list_lock);
108         list_for_each_entry(c_i, &iio_map_list, l) {
109                 if ((name && strcmp(name, c_i->map->consumer_dev_name) != 0) ||
110                     (channel_name &&
111                      strcmp(channel_name, c_i->map->consumer_channel) != 0))
112                         continue;
113                 c = c_i;
114                 iio_device_get(c->indio_dev);
115                 break;
116         }
117         mutex_unlock(&iio_map_list_lock);
118         if (c == NULL)
119                 return ERR_PTR(-ENODEV);
120
121         channel = kzalloc(sizeof(*channel), GFP_KERNEL);
122         if (channel == NULL) {
123                 err = -ENOMEM;
124                 goto error_no_mem;
125         }
126
127         channel->indio_dev = c->indio_dev;
128
129         if (c->map->adc_channel_label) {
130                 channel->channel =
131                         iio_chan_spec_from_name(channel->indio_dev,
132                                                 c->map->adc_channel_label);
133
134                 if (channel->channel == NULL) {
135                         err = -EINVAL;
136                         goto error_no_chan;
137                 }
138         }
139
140         return channel;
141
142 error_no_chan:
143         kfree(channel);
144 error_no_mem:
145         iio_device_put(c->indio_dev);
146         return ERR_PTR(err);
147 }
148
149 struct iio_channel *iio_channel_get(struct device *dev,
150                                     const char *channel_name)
151 {
152         const char *name = dev ? dev_name(dev) : NULL;
153
154         return iio_channel_get_sys(name, channel_name);
155 }
156 EXPORT_SYMBOL_GPL(iio_channel_get);
157
158 void iio_channel_release(struct iio_channel *channel)
159 {
160         iio_device_put(channel->indio_dev);
161         kfree(channel);
162 }
163 EXPORT_SYMBOL_GPL(iio_channel_release);
164
165 struct iio_channel *iio_channel_get_all(struct device *dev)
166 {
167         const char *name;
168         struct iio_channel *chans;
169         struct iio_map_internal *c = NULL;
170         int nummaps = 0;
171         int mapind = 0;
172         int i, ret;
173
174         if (dev == NULL)
175                 return ERR_PTR(-EINVAL);
176         name = dev_name(dev);
177
178         mutex_lock(&iio_map_list_lock);
179         /* first count the matching maps */
180         list_for_each_entry(c, &iio_map_list, l)
181                 if (name && strcmp(name, c->map->consumer_dev_name) != 0)
182                         continue;
183                 else
184                         nummaps++;
185
186         if (nummaps == 0) {
187                 ret = -ENODEV;
188                 goto error_ret;
189         }
190
191         /* NULL terminated array to save passing size */
192         chans = kzalloc(sizeof(*chans)*(nummaps + 1), GFP_KERNEL);
193         if (chans == NULL) {
194                 ret = -ENOMEM;
195                 goto error_ret;
196         }
197
198         /* for each map fill in the chans element */
199         list_for_each_entry(c, &iio_map_list, l) {
200                 if (name && strcmp(name, c->map->consumer_dev_name) != 0)
201                         continue;
202                 chans[mapind].indio_dev = c->indio_dev;
203                 chans[mapind].data = c->map->consumer_data;
204                 chans[mapind].channel =
205                         iio_chan_spec_from_name(chans[mapind].indio_dev,
206                                                 c->map->adc_channel_label);
207                 if (chans[mapind].channel == NULL) {
208                         ret = -EINVAL;
209                         goto error_free_chans;
210                 }
211                 iio_device_get(chans[mapind].indio_dev);
212                 mapind++;
213         }
214         if (mapind == 0) {
215                 ret = -ENODEV;
216                 goto error_free_chans;
217         }
218         mutex_unlock(&iio_map_list_lock);
219
220         return chans;
221
222 error_free_chans:
223         for (i = 0; i < nummaps; i++)
224                 iio_device_put(chans[i].indio_dev);
225         kfree(chans);
226 error_ret:
227         mutex_unlock(&iio_map_list_lock);
228
229         return ERR_PTR(ret);
230 }
231 EXPORT_SYMBOL_GPL(iio_channel_get_all);
232
233 void iio_channel_release_all(struct iio_channel *channels)
234 {
235         struct iio_channel *chan = &channels[0];
236
237         while (chan->indio_dev) {
238                 iio_device_put(chan->indio_dev);
239                 chan++;
240         }
241         kfree(channels);
242 }
243 EXPORT_SYMBOL_GPL(iio_channel_release_all);
244
245 static int iio_channel_read(struct iio_channel *chan, int *val, int *val2,
246         enum iio_chan_info_enum info)
247 {
248         int unused;
249
250         if (val2 == NULL)
251                 val2 = &unused;
252
253         return chan->indio_dev->info->read_raw(chan->indio_dev, chan->channel,
254                                                 val, val2, info);
255 }
256
257 int iio_read_channel_raw(struct iio_channel *chan, int *val)
258 {
259         int ret;
260
261         mutex_lock(&chan->indio_dev->info_exist_lock);
262         if (chan->indio_dev->info == NULL) {
263                 ret = -ENODEV;
264                 goto err_unlock;
265         }
266
267         ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW);
268 err_unlock:
269         mutex_unlock(&chan->indio_dev->info_exist_lock);
270
271         return ret;
272 }
273 EXPORT_SYMBOL_GPL(iio_read_channel_raw);
274
275 static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan,
276         int raw, int *processed, unsigned int scale)
277 {
278         int scale_type, scale_val, scale_val2, offset;
279         s64 raw64 = raw;
280         int ret;
281
282         ret = iio_channel_read(chan, &offset, NULL, IIO_CHAN_INFO_SCALE);
283         if (ret == 0)
284                 raw64 += offset;
285
286         scale_type = iio_channel_read(chan, &scale_val, &scale_val2,
287                                         IIO_CHAN_INFO_SCALE);
288         if (scale_type < 0)
289                 return scale_type;
290
291         switch (scale_type) {
292         case IIO_VAL_INT:
293                 *processed = raw64 * scale_val;
294                 break;
295         case IIO_VAL_INT_PLUS_MICRO:
296                 if (scale_val2 < 0)
297                         *processed = -raw64 * scale_val;
298                 else
299                         *processed = raw64 * scale_val;
300                 *processed += div_s64(raw64 * (s64)scale_val2 * scale,
301                                       1000000LL);
302                 break;
303         case IIO_VAL_INT_PLUS_NANO:
304                 if (scale_val2 < 0)
305                         *processed = -raw64 * scale_val;
306                 else
307                         *processed = raw64 * scale_val;
308                 *processed += div_s64(raw64 * (s64)scale_val2 * scale,
309                                       1000000000LL);
310                 break;
311         case IIO_VAL_FRACTIONAL:
312                 *processed = div_s64(raw64 * (s64)scale_val * scale,
313                                      scale_val2);
314                 break;
315         case IIO_VAL_FRACTIONAL_LOG2:
316                 *processed = (raw64 * (s64)scale_val * scale) >> scale_val2;
317                 break;
318         default:
319                 return -EINVAL;
320         }
321
322         return 0;
323 }
324
325 int iio_convert_raw_to_processed(struct iio_channel *chan, int raw,
326         int *processed, unsigned int scale)
327 {
328         int ret;
329
330         mutex_lock(&chan->indio_dev->info_exist_lock);
331         if (chan->indio_dev->info == NULL) {
332                 ret = -ENODEV;
333                 goto err_unlock;
334         }
335
336         ret = iio_convert_raw_to_processed_unlocked(chan, raw, processed,
337                                                         scale);
338 err_unlock:
339         mutex_unlock(&chan->indio_dev->info_exist_lock);
340
341         return ret;
342 }
343 EXPORT_SYMBOL_GPL(iio_convert_raw_to_processed);
344
345 int iio_read_channel_processed(struct iio_channel *chan, int *val)
346 {
347         int ret;
348
349         mutex_lock(&chan->indio_dev->info_exist_lock);
350         if (chan->indio_dev->info == NULL) {
351                 ret = -ENODEV;
352                 goto err_unlock;
353         }
354
355         if (iio_channel_has_info(chan->channel, IIO_CHAN_INFO_PROCESSED)) {
356                 ret = iio_channel_read(chan, val, NULL,
357                                        IIO_CHAN_INFO_PROCESSED);
358         } else {
359                 ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW);
360                 if (ret < 0)
361                         goto err_unlock;
362                 ret = iio_convert_raw_to_processed_unlocked(chan, *val, val, 1);
363         }
364
365 err_unlock:
366         mutex_unlock(&chan->indio_dev->info_exist_lock);
367
368         return ret;
369 }
370 EXPORT_SYMBOL_GPL(iio_read_channel_processed);
371
372 int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2)
373 {
374         int ret;
375
376         mutex_lock(&chan->indio_dev->info_exist_lock);
377         if (chan->indio_dev->info == NULL) {
378                 ret = -ENODEV;
379                 goto err_unlock;
380         }
381
382         ret = iio_channel_read(chan, val, val2, IIO_CHAN_INFO_SCALE);
383 err_unlock:
384         mutex_unlock(&chan->indio_dev->info_exist_lock);
385
386         return ret;
387 }
388 EXPORT_SYMBOL_GPL(iio_read_channel_scale);
389
390 int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type)
391 {
392         int ret = 0;
393         /* Need to verify underlying driver has not gone away */
394
395         mutex_lock(&chan->indio_dev->info_exist_lock);
396         if (chan->indio_dev->info == NULL) {
397                 ret = -ENODEV;
398                 goto err_unlock;
399         }
400
401         *type = chan->channel->type;
402 err_unlock:
403         mutex_unlock(&chan->indio_dev->info_exist_lock);
404
405         return ret;
406 }
407 EXPORT_SYMBOL_GPL(iio_get_channel_type);