xref: /openbmc/linux/drivers/iio/inkern.c (revision 840ef8b7)
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);
408