Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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#include <linux/of.h>
 14
 15#include <linux/iio/iio.h>
 16#include "iio_core.h"
 17#include <linux/iio/machine.h>
 18#include <linux/iio/driver.h>
 19#include <linux/iio/consumer.h>
 20
 21struct iio_map_internal {
 22	struct iio_dev *indio_dev;
 23	struct iio_map *map;
 24	struct list_head l;
 25};
 26
 27static LIST_HEAD(iio_map_list);
 28static DEFINE_MUTEX(iio_map_list_lock);
 29
 30int iio_map_array_register(struct iio_dev *indio_dev, struct iio_map *maps)
 31{
 32	int i = 0, ret = 0;
 33	struct iio_map_internal *mapi;
 34
 35	if (maps == NULL)
 36		return 0;
 37
 38	mutex_lock(&iio_map_list_lock);
 39	while (maps[i].consumer_dev_name != NULL) {
 40		mapi = kzalloc(sizeof(*mapi), GFP_KERNEL);
 41		if (mapi == NULL) {
 42			ret = -ENOMEM;
 43			goto error_ret;
 44		}
 45		mapi->map = &maps[i];
 46		mapi->indio_dev = indio_dev;
 47		list_add_tail(&mapi->l, &iio_map_list);
 48		i++;
 49	}
 50error_ret:
 51	mutex_unlock(&iio_map_list_lock);
 52
 53	return ret;
 54}
 55EXPORT_SYMBOL_GPL(iio_map_array_register);
 56
 57
 58/*
 59 * Remove all map entries associated with the given iio device
 60 */
 61int iio_map_array_unregister(struct iio_dev *indio_dev)
 62{
 63	int ret = -ENODEV;
 64	struct iio_map_internal *mapi, *next;
 65
 66	mutex_lock(&iio_map_list_lock);
 67	list_for_each_entry_safe(mapi, next, &iio_map_list, l) {
 68		if (indio_dev == mapi->indio_dev) {
 69			list_del(&mapi->l);
 70			kfree(mapi);
 71			ret = 0;
 72		}
 73	}
 74	mutex_unlock(&iio_map_list_lock);
 75	return ret;
 76}
 77EXPORT_SYMBOL_GPL(iio_map_array_unregister);
 78
 79static const struct iio_chan_spec
 80*iio_chan_spec_from_name(const struct iio_dev *indio_dev, const char *name)
 81{
 82	int i;
 83	const struct iio_chan_spec *chan = NULL;
 84
 85	for (i = 0; i < indio_dev->num_channels; i++)
 86		if (indio_dev->channels[i].datasheet_name &&
 87		    strcmp(name, indio_dev->channels[i].datasheet_name) == 0) {
 88			chan = &indio_dev->channels[i];
 89			break;
 90		}
 91	return chan;
 92}
 93
 94#ifdef CONFIG_OF
 95
 96static int iio_dev_node_match(struct device *dev, void *data)
 97{
 98	return dev->of_node == data && dev->type == &iio_device_type;
 99}
100
101/**
102 * __of_iio_simple_xlate - translate iiospec to the IIO channel index
103 * @indio_dev:	pointer to the iio_dev structure
104 * @iiospec:	IIO specifier as found in the device tree
105 *
106 * This is simple translation function, suitable for the most 1:1 mapped
107 * channels in IIO chips. This function performs only one sanity check:
108 * whether IIO index is less than num_channels (that is specified in the
109 * iio_dev).
110 */
111static int __of_iio_simple_xlate(struct iio_dev *indio_dev,
112				const struct of_phandle_args *iiospec)
113{
114	if (!iiospec->args_count)
115		return 0;
116
117	if (iiospec->args[0] >= indio_dev->num_channels) {
118		dev_err(&indio_dev->dev, "invalid channel index %u\n",
119			iiospec->args[0]);
120		return -EINVAL;
121	}
122
123	return iiospec->args[0];
124}
125
126static int __of_iio_channel_get(struct iio_channel *channel,
127				struct device_node *np, int index)
128{
129	struct device *idev;
130	struct iio_dev *indio_dev;
131	int err;
132	struct of_phandle_args iiospec;
133
134	err = of_parse_phandle_with_args(np, "io-channels",
135					 "#io-channel-cells",
136					 index, &iiospec);
137	if (err)
138		return err;
139
140	idev = bus_find_device(&iio_bus_type, NULL, iiospec.np,
141			       iio_dev_node_match);
142	of_node_put(iiospec.np);
143	if (idev == NULL)
144		return -EPROBE_DEFER;
145
146	indio_dev = dev_to_iio_dev(idev);
147	channel->indio_dev = indio_dev;
148	if (indio_dev->info->of_xlate)
149		index = indio_dev->info->of_xlate(indio_dev, &iiospec);
150	else
151		index = __of_iio_simple_xlate(indio_dev, &iiospec);
152	if (index < 0)
153		goto err_put;
154	channel->channel = &indio_dev->channels[index];
155
156	return 0;
157
158err_put:
159	iio_device_put(indio_dev);
160	return index;
161}
162
163static struct iio_channel *of_iio_channel_get(struct device_node *np, int index)
164{
165	struct iio_channel *channel;
166	int err;
167
168	if (index < 0)
169		return ERR_PTR(-EINVAL);
170
171	channel = kzalloc(sizeof(*channel), GFP_KERNEL);
172	if (channel == NULL)
173		return ERR_PTR(-ENOMEM);
174
175	err = __of_iio_channel_get(channel, np, index);
176	if (err)
177		goto err_free_channel;
178
179	return channel;
180
181err_free_channel:
182	kfree(channel);
183	return ERR_PTR(err);
184}
185
186static struct iio_channel *of_iio_channel_get_by_name(struct device_node *np,
187						      const char *name)
188{
189	struct iio_channel *chan = NULL;
190
191	/* Walk up the tree of devices looking for a matching iio channel */
192	while (np) {
193		int index = 0;
194
195		/*
196		 * For named iio channels, first look up the name in the
197		 * "io-channel-names" property.  If it cannot be found, the
198		 * index will be an error code, and of_iio_channel_get()
199		 * will fail.
200		 */
201		if (name)
202			index = of_property_match_string(np, "io-channel-names",
203							 name);
204		chan = of_iio_channel_get(np, index);
205		if (!IS_ERR(chan) || PTR_ERR(chan) == -EPROBE_DEFER)
206			break;
207		else if (name && index >= 0) {
208			pr_err("ERROR: could not get IIO channel %pOF:%s(%i)\n",
209				np, name ? name : "", index);
210			return NULL;
211		}
212
213		/*
214		 * No matching IIO channel found on this node.
215		 * If the parent node has a "io-channel-ranges" property,
216		 * then we can try one of its channels.
217		 */
218		np = np->parent;
219		if (np && !of_get_property(np, "io-channel-ranges", NULL))
220			return NULL;
221	}
222
223	return chan;
224}
225
226static struct iio_channel *of_iio_channel_get_all(struct device *dev)
227{
228	struct iio_channel *chans;
229	int i, mapind, nummaps = 0;
230	int ret;
231
232	do {
233		ret = of_parse_phandle_with_args(dev->of_node,
234						 "io-channels",
235						 "#io-channel-cells",
236						 nummaps, NULL);
237		if (ret < 0)
238			break;
239	} while (++nummaps);
240
241	if (nummaps == 0)	/* no error, return NULL to search map table */
242		return NULL;
243
244	/* NULL terminated array to save passing size */
245	chans = kcalloc(nummaps + 1, sizeof(*chans), GFP_KERNEL);
246	if (chans == NULL)
247		return ERR_PTR(-ENOMEM);
248
249	/* Search for OF matches */
250	for (mapind = 0; mapind < nummaps; mapind++) {
251		ret = __of_iio_channel_get(&chans[mapind], dev->of_node,
252					   mapind);
253		if (ret)
254			goto error_free_chans;
255	}
256	return chans;
257
258error_free_chans:
259	for (i = 0; i < mapind; i++)
260		iio_device_put(chans[i].indio_dev);
261	kfree(chans);
262	return ERR_PTR(ret);
263}
264
265#else /* CONFIG_OF */
266
267static inline struct iio_channel *
268of_iio_channel_get_by_name(struct device_node *np, const char *name)
269{
270	return NULL;
271}
272
273static inline struct iio_channel *of_iio_channel_get_all(struct device *dev)
274{
275	return NULL;
276}
277
278#endif /* CONFIG_OF */
279
280static struct iio_channel *iio_channel_get_sys(const char *name,
281					       const char *channel_name)
282{
283	struct iio_map_internal *c_i = NULL, *c = NULL;
284	struct iio_channel *channel;
285	int err;
286
287	if (name == NULL && channel_name == NULL)
288		return ERR_PTR(-ENODEV);
289
290	/* first find matching entry the channel map */
291	mutex_lock(&iio_map_list_lock);
292	list_for_each_entry(c_i, &iio_map_list, l) {
293		if ((name && strcmp(name, c_i->map->consumer_dev_name) != 0) ||
294		    (channel_name &&
295		     strcmp(channel_name, c_i->map->consumer_channel) != 0))
296			continue;
297		c = c_i;
298		iio_device_get(c->indio_dev);
299		break;
300	}
301	mutex_unlock(&iio_map_list_lock);
302	if (c == NULL)
303		return ERR_PTR(-ENODEV);
304
305	channel = kzalloc(sizeof(*channel), GFP_KERNEL);
306	if (channel == NULL) {
307		err = -ENOMEM;
308		goto error_no_mem;
309	}
310
311	channel->indio_dev = c->indio_dev;
312
313	if (c->map->adc_channel_label) {
314		channel->channel =
315			iio_chan_spec_from_name(channel->indio_dev,
316						c->map->adc_channel_label);
317
318		if (channel->channel == NULL) {
319			err = -EINVAL;
320			goto error_no_chan;
321		}
322	}
323
324	return channel;
325
326error_no_chan:
327	kfree(channel);
328error_no_mem:
329	iio_device_put(c->indio_dev);
330	return ERR_PTR(err);
331}
332
333struct iio_channel *iio_channel_get(struct device *dev,
334				    const char *channel_name)
335{
336	const char *name = dev ? dev_name(dev) : NULL;
337	struct iio_channel *channel;
338
339	if (dev) {
340		channel = of_iio_channel_get_by_name(dev->of_node,
341						     channel_name);
342		if (channel != NULL)
343			return channel;
344	}
345
346	return iio_channel_get_sys(name, channel_name);
347}
348EXPORT_SYMBOL_GPL(iio_channel_get);
349
350void iio_channel_release(struct iio_channel *channel)
351{
352	if (!channel)
353		return;
354	iio_device_put(channel->indio_dev);
355	kfree(channel);
356}
357EXPORT_SYMBOL_GPL(iio_channel_release);
358
359static void devm_iio_channel_free(struct device *dev, void *res)
360{
361	struct iio_channel *channel = *(struct iio_channel **)res;
362
363	iio_channel_release(channel);
364}
365
366static int devm_iio_channel_match(struct device *dev, void *res, void *data)
367{
368	struct iio_channel **r = res;
369
370	if (!r || !*r) {
371		WARN_ON(!r || !*r);
372		return 0;
373	}
374
375	return *r == data;
376}
377
378struct iio_channel *devm_iio_channel_get(struct device *dev,
379					 const char *channel_name)
380{
381	struct iio_channel **ptr, *channel;
382
383	ptr = devres_alloc(devm_iio_channel_free, sizeof(*ptr), GFP_KERNEL);
384	if (!ptr)
385		return ERR_PTR(-ENOMEM);
386
387	channel = iio_channel_get(dev, channel_name);
388	if (IS_ERR(channel)) {
389		devres_free(ptr);
390		return channel;
391	}
392
393	*ptr = channel;
394	devres_add(dev, ptr);
395
396	return channel;
397}
398EXPORT_SYMBOL_GPL(devm_iio_channel_get);
399
400void devm_iio_channel_release(struct device *dev, struct iio_channel *channel)
401{
402	WARN_ON(devres_release(dev, devm_iio_channel_free,
403			       devm_iio_channel_match, channel));
404}
405EXPORT_SYMBOL_GPL(devm_iio_channel_release);
406
407struct iio_channel *iio_channel_get_all(struct device *dev)
408{
409	const char *name;
410	struct iio_channel *chans;
411	struct iio_map_internal *c = NULL;
412	int nummaps = 0;
413	int mapind = 0;
414	int i, ret;
415
416	if (dev == NULL)
417		return ERR_PTR(-EINVAL);
418
419	chans = of_iio_channel_get_all(dev);
420	if (chans)
421		return chans;
422
423	name = dev_name(dev);
424
425	mutex_lock(&iio_map_list_lock);
426	/* first count the matching maps */
427	list_for_each_entry(c, &iio_map_list, l)
428		if (name && strcmp(name, c->map->consumer_dev_name) != 0)
429			continue;
430		else
431			nummaps++;
432
433	if (nummaps == 0) {
434		ret = -ENODEV;
435		goto error_ret;
436	}
437
438	/* NULL terminated array to save passing size */
439	chans = kzalloc(sizeof(*chans)*(nummaps + 1), GFP_KERNEL);
440	if (chans == NULL) {
441		ret = -ENOMEM;
442		goto error_ret;
443	}
444
445	/* for each map fill in the chans element */
446	list_for_each_entry(c, &iio_map_list, l) {
447		if (name && strcmp(name, c->map->consumer_dev_name) != 0)
448			continue;
449		chans[mapind].indio_dev = c->indio_dev;
450		chans[mapind].data = c->map->consumer_data;
451		chans[mapind].channel =
452			iio_chan_spec_from_name(chans[mapind].indio_dev,
453						c->map->adc_channel_label);
454		if (chans[mapind].channel == NULL) {
455			ret = -EINVAL;
456			goto error_free_chans;
457		}
458		iio_device_get(chans[mapind].indio_dev);
459		mapind++;
460	}
461	if (mapind == 0) {
462		ret = -ENODEV;
463		goto error_free_chans;
464	}
465	mutex_unlock(&iio_map_list_lock);
466
467	return chans;
468
469error_free_chans:
470	for (i = 0; i < nummaps; i++)
471		iio_device_put(chans[i].indio_dev);
472	kfree(chans);
473error_ret:
474	mutex_unlock(&iio_map_list_lock);
475
476	return ERR_PTR(ret);
477}
478EXPORT_SYMBOL_GPL(iio_channel_get_all);
479
480void iio_channel_release_all(struct iio_channel *channels)
481{
482	struct iio_channel *chan = &channels[0];
483
484	while (chan->indio_dev) {
485		iio_device_put(chan->indio_dev);
486		chan++;
487	}
488	kfree(channels);
489}
490EXPORT_SYMBOL_GPL(iio_channel_release_all);
491
492static void devm_iio_channel_free_all(struct device *dev, void *res)
493{
494	struct iio_channel *channels = *(struct iio_channel **)res;
495
496	iio_channel_release_all(channels);
497}
498
499struct iio_channel *devm_iio_channel_get_all(struct device *dev)
500{
501	struct iio_channel **ptr, *channels;
502
503	ptr = devres_alloc(devm_iio_channel_free_all, sizeof(*ptr), GFP_KERNEL);
504	if (!ptr)
505		return ERR_PTR(-ENOMEM);
506
507	channels = iio_channel_get_all(dev);
508	if (IS_ERR(channels)) {
509		devres_free(ptr);
510		return channels;
511	}
512
513	*ptr = channels;
514	devres_add(dev, ptr);
515
516	return channels;
517}
518EXPORT_SYMBOL_GPL(devm_iio_channel_get_all);
519
520void devm_iio_channel_release_all(struct device *dev,
521				  struct iio_channel *channels)
522{
523	WARN_ON(devres_release(dev, devm_iio_channel_free_all,
524			       devm_iio_channel_match, channels));
525}
526EXPORT_SYMBOL_GPL(devm_iio_channel_release_all);
527
528static int iio_channel_read(struct iio_channel *chan, int *val, int *val2,
529	enum iio_chan_info_enum info)
530{
531	int unused;
532	int vals[INDIO_MAX_RAW_ELEMENTS];
533	int ret;
534	int val_len = 2;
535
536	if (val2 == NULL)
537		val2 = &unused;
538
539	if (!iio_channel_has_info(chan->channel, info))
540		return -EINVAL;
541
542	if (chan->indio_dev->info->read_raw_multi) {
543		ret = chan->indio_dev->info->read_raw_multi(chan->indio_dev,
544					chan->channel, INDIO_MAX_RAW_ELEMENTS,
545					vals, &val_len, info);
546		*val = vals[0];
547		*val2 = vals[1];
548	} else
549		ret = chan->indio_dev->info->read_raw(chan->indio_dev,
550					chan->channel, val, val2, info);
551
552	return ret;
553}
554
555int iio_read_channel_raw(struct iio_channel *chan, int *val)
556{
557	int ret;
558
559	mutex_lock(&chan->indio_dev->info_exist_lock);
560	if (chan->indio_dev->info == NULL) {
561		ret = -ENODEV;
562		goto err_unlock;
563	}
564
565	ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW);
566err_unlock:
567	mutex_unlock(&chan->indio_dev->info_exist_lock);
568
569	return ret;
570}
571EXPORT_SYMBOL_GPL(iio_read_channel_raw);
572
573int iio_read_channel_average_raw(struct iio_channel *chan, int *val)
574{
575	int ret;
576
577	mutex_lock(&chan->indio_dev->info_exist_lock);
578	if (chan->indio_dev->info == NULL) {
579		ret = -ENODEV;
580		goto err_unlock;
581	}
582
583	ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_AVERAGE_RAW);
584err_unlock:
585	mutex_unlock(&chan->indio_dev->info_exist_lock);
586
587	return ret;
588}
589EXPORT_SYMBOL_GPL(iio_read_channel_average_raw);
590
591static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan,
592	int raw, int *processed, unsigned int scale)
593{
594	int scale_type, scale_val, scale_val2, offset;
595	s64 raw64 = raw;
596	int ret;
597
598	ret = iio_channel_read(chan, &offset, NULL, IIO_CHAN_INFO_OFFSET);
599	if (ret >= 0)
600		raw64 += offset;
601
602	scale_type = iio_channel_read(chan, &scale_val, &scale_val2,
603					IIO_CHAN_INFO_SCALE);
604	if (scale_type < 0) {
605		/*
606		 * Just pass raw values as processed if no scaling is
607		 * available.
608		 */
609		*processed = raw;
610		return 0;
611	}
612
613	switch (scale_type) {
614	case IIO_VAL_INT:
615		*processed = raw64 * scale_val;
616		break;
617	case IIO_VAL_INT_PLUS_MICRO:
618		if (scale_val2 < 0)
619			*processed = -raw64 * scale_val;
620		else
621			*processed = raw64 * scale_val;
622		*processed += div_s64(raw64 * (s64)scale_val2 * scale,
623				      1000000LL);
624		break;
625	case IIO_VAL_INT_PLUS_NANO:
626		if (scale_val2 < 0)
627			*processed = -raw64 * scale_val;
628		else
629			*processed = raw64 * scale_val;
630		*processed += div_s64(raw64 * (s64)scale_val2 * scale,
631				      1000000000LL);
632		break;
633	case IIO_VAL_FRACTIONAL:
634		*processed = div_s64(raw64 * (s64)scale_val * scale,
635				     scale_val2);
636		break;
637	case IIO_VAL_FRACTIONAL_LOG2:
638		*processed = (raw64 * (s64)scale_val * scale) >> scale_val2;
639		break;
640	default:
641		return -EINVAL;
642	}
643
644	return 0;
645}
646
647int iio_convert_raw_to_processed(struct iio_channel *chan, int raw,
648	int *processed, unsigned int scale)
649{
650	int ret;
651
652	mutex_lock(&chan->indio_dev->info_exist_lock);
653	if (chan->indio_dev->info == NULL) {
654		ret = -ENODEV;
655		goto err_unlock;
656	}
657
658	ret = iio_convert_raw_to_processed_unlocked(chan, raw, processed,
659							scale);
660err_unlock:
661	mutex_unlock(&chan->indio_dev->info_exist_lock);
662
663	return ret;
664}
665EXPORT_SYMBOL_GPL(iio_convert_raw_to_processed);
666
667int iio_read_channel_attribute(struct iio_channel *chan, int *val, int *val2,
668			       enum iio_chan_info_enum attribute)
669{
670	int ret;
671
672	mutex_lock(&chan->indio_dev->info_exist_lock);
673	if (chan->indio_dev->info == NULL) {
674		ret = -ENODEV;
675		goto err_unlock;
676	}
677
678	ret = iio_channel_read(chan, val, val2, attribute);
679err_unlock:
680	mutex_unlock(&chan->indio_dev->info_exist_lock);
681
682	return ret;
683}
684EXPORT_SYMBOL_GPL(iio_read_channel_attribute);
685
686int iio_read_channel_offset(struct iio_channel *chan, int *val, int *val2)
687{
688	return iio_read_channel_attribute(chan, val, val2, IIO_CHAN_INFO_OFFSET);
689}
690EXPORT_SYMBOL_GPL(iio_read_channel_offset);
691
692int iio_read_channel_processed(struct iio_channel *chan, int *val)
693{
694	int ret;
695
696	mutex_lock(&chan->indio_dev->info_exist_lock);
697	if (chan->indio_dev->info == NULL) {
698		ret = -ENODEV;
699		goto err_unlock;
700	}
701
702	if (iio_channel_has_info(chan->channel, IIO_CHAN_INFO_PROCESSED)) {
703		ret = iio_channel_read(chan, val, NULL,
704				       IIO_CHAN_INFO_PROCESSED);
705	} else {
706		ret = iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW);
707		if (ret < 0)
708			goto err_unlock;
709		ret = iio_convert_raw_to_processed_unlocked(chan, *val, val, 1);
710	}
711
712err_unlock:
713	mutex_unlock(&chan->indio_dev->info_exist_lock);
714
715	return ret;
716}
717EXPORT_SYMBOL_GPL(iio_read_channel_processed);
718
719int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2)
720{
721	return iio_read_channel_attribute(chan, val, val2, IIO_CHAN_INFO_SCALE);
722}
723EXPORT_SYMBOL_GPL(iio_read_channel_scale);
724
725static int iio_channel_read_avail(struct iio_channel *chan,
726				  const int **vals, int *type, int *length,
727				  enum iio_chan_info_enum info)
728{
729	if (!iio_channel_has_available(chan->channel, info))
730		return -EINVAL;
731
732	return chan->indio_dev->info->read_avail(chan->indio_dev, chan->channel,
733						 vals, type, length, info);
734}
735
736int iio_read_avail_channel_raw(struct iio_channel *chan,
737			       const int **vals, int *length)
738{
739	int ret;
740	int type;
741
742	mutex_lock(&chan->indio_dev->info_exist_lock);
743	if (!chan->indio_dev->info) {
744		ret = -ENODEV;
745		goto err_unlock;
746	}
747
748	ret = iio_channel_read_avail(chan,
749				     vals, &type, length, IIO_CHAN_INFO_RAW);
750err_unlock:
751	mutex_unlock(&chan->indio_dev->info_exist_lock);
752
753	if (ret >= 0 && type != IIO_VAL_INT)
754		/* raw values are assumed to be IIO_VAL_INT */
755		ret = -EINVAL;
756
757	return ret;
758}
759EXPORT_SYMBOL_GPL(iio_read_avail_channel_raw);
760
761static int iio_channel_read_max(struct iio_channel *chan,
762				int *val, int *val2, int *type,
763				enum iio_chan_info_enum info)
764{
765	int unused;
766	const int *vals;
767	int length;
768	int ret;
769
770	if (!val2)
771		val2 = &unused;
772
773	ret = iio_channel_read_avail(chan, &vals, type, &length, info);
774	switch (ret) {
775	case IIO_AVAIL_RANGE:
776		switch (*type) {
777		case IIO_VAL_INT:
778			*val = vals[2];
779			break;
780		default:
781			*val = vals[4];
782			*val2 = vals[5];
783		}
784		return 0;
785
786	case IIO_AVAIL_LIST:
787		if (length <= 0)
788			return -EINVAL;
789		switch (*type) {
790		case IIO_VAL_INT:
791			*val = vals[--length];
792			while (length) {
793				if (vals[--length] > *val)
794					*val = vals[length];
795			}
796			break;
797		default:
798			/* FIXME: learn about max for other iio values */
799			return -EINVAL;
800		}
801		return 0;
802
803	default:
804		return ret;
805	}
806}
807
808int iio_read_max_channel_raw(struct iio_channel *chan, int *val)
809{
810	int ret;
811	int type;
812
813	mutex_lock(&chan->indio_dev->info_exist_lock);
814	if (!chan->indio_dev->info) {
815		ret = -ENODEV;
816		goto err_unlock;
817	}
818
819	ret = iio_channel_read_max(chan, val, NULL, &type, IIO_CHAN_INFO_RAW);
820err_unlock:
821	mutex_unlock(&chan->indio_dev->info_exist_lock);
822
823	return ret;
824}
825EXPORT_SYMBOL_GPL(iio_read_max_channel_raw);
826
827int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type)
828{
829	int ret = 0;
830	/* Need to verify underlying driver has not gone away */
831
832	mutex_lock(&chan->indio_dev->info_exist_lock);
833	if (chan->indio_dev->info == NULL) {
834		ret = -ENODEV;
835		goto err_unlock;
836	}
837
838	*type = chan->channel->type;
839err_unlock:
840	mutex_unlock(&chan->indio_dev->info_exist_lock);
841
842	return ret;
843}
844EXPORT_SYMBOL_GPL(iio_get_channel_type);
845
846static int iio_channel_write(struct iio_channel *chan, int val, int val2,
847			     enum iio_chan_info_enum info)
848{
849	return chan->indio_dev->info->write_raw(chan->indio_dev,
850						chan->channel, val, val2, info);
851}
852
853int iio_write_channel_attribute(struct iio_channel *chan, int val, int val2,
854				enum iio_chan_info_enum attribute)
855{
856	int ret;
857
858	mutex_lock(&chan->indio_dev->info_exist_lock);
859	if (chan->indio_dev->info == NULL) {
860		ret = -ENODEV;
861		goto err_unlock;
862	}
863
864	ret = iio_channel_write(chan, val, val2, attribute);
865err_unlock:
866	mutex_unlock(&chan->indio_dev->info_exist_lock);
867
868	return ret;
869}
870EXPORT_SYMBOL_GPL(iio_write_channel_attribute);
871
872int iio_write_channel_raw(struct iio_channel *chan, int val)
873{
874	return iio_write_channel_attribute(chan, val, 0, IIO_CHAN_INFO_RAW);
875}
876EXPORT_SYMBOL_GPL(iio_write_channel_raw);
877
878unsigned int iio_get_channel_ext_info_count(struct iio_channel *chan)
879{
880	const struct iio_chan_spec_ext_info *ext_info;
881	unsigned int i = 0;
882
883	if (!chan->channel->ext_info)
884		return i;
885
886	for (ext_info = chan->channel->ext_info; ext_info->name; ext_info++)
887		++i;
888
889	return i;
890}
891EXPORT_SYMBOL_GPL(iio_get_channel_ext_info_count);
892
893static const struct iio_chan_spec_ext_info *iio_lookup_ext_info(
894						const struct iio_channel *chan,
895						const char *attr)
896{
897	const struct iio_chan_spec_ext_info *ext_info;
898
899	if (!chan->channel->ext_info)
900		return NULL;
901
902	for (ext_info = chan->channel->ext_info; ext_info->name; ++ext_info) {
903		if (!strcmp(attr, ext_info->name))
904			return ext_info;
905	}
906
907	return NULL;
908}
909
910ssize_t iio_read_channel_ext_info(struct iio_channel *chan,
911				  const char *attr, char *buf)
912{
913	const struct iio_chan_spec_ext_info *ext_info;
914
915	ext_info = iio_lookup_ext_info(chan, attr);
916	if (!ext_info)
917		return -EINVAL;
918
919	return ext_info->read(chan->indio_dev, ext_info->private,
920			      chan->channel, buf);
921}
922EXPORT_SYMBOL_GPL(iio_read_channel_ext_info);
923
924ssize_t iio_write_channel_ext_info(struct iio_channel *chan, const char *attr,
925				   const char *buf, size_t len)
926{
927	const struct iio_chan_spec_ext_info *ext_info;
928
929	ext_info = iio_lookup_ext_info(chan, attr);
930	if (!ext_info)
931		return -EINVAL;
932
933	return ext_info->write(chan->indio_dev, ext_info->private,
934			       chan->channel, buf, len);
935}
936EXPORT_SYMBOL_GPL(iio_write_channel_ext_info);