industrialio-core.c revision ac917a81117ce0286847666b55dd265f6cda8383
1847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron/* The industrial I/O core
2847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron *
3847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * Copyright (c) 2008 Jonathan Cameron
4847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron *
5847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * This program is free software; you can redistribute it and/or modify it
6847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * under the terms of the GNU General Public License version 2 as published by
7847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * the Free Software Foundation.
8847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron *
9847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron * Based on elements of hwmon and input subsystems.
10847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron */
11847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
12847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include <linux/kernel.h>
13847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include <linux/module.h>
14847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include <linux/idr.h>
15847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include <linux/kdev_t.h>
16847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include <linux/err.h>
17847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include <linux/device.h>
18847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include <linux/fs.h>
19847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include <linux/poll.h>
20ffc18afa11f32d59839b5f3c605c64c63d38c218Jonathan Cameron#include <linux/sched.h>
214439c9353589f4def506b94f8f6344433333a4b9Jeff Mahoney#include <linux/wait.h>
22847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include <linux/cdev.h>
235a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
248e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron#include <linux/anon_inodes.h>
25847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include "iio.h"
26df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameron#include "iio_core.h"
276aea1c364cde5b28b551844b7b8925f523310a18Jonathan Cameron#include "iio_core_trigger.h"
289dd1cb303c18f4508abc69f5b40f423ff36a9626Jonathan Cameron#include "sysfs.h"
29af5046af1c812839f085030f358a01814666fc80Jonathan Cameron#include "events.h"
309dd1cb303c18f4508abc69f5b40f423ff36a9626Jonathan Cameron
3147c24fdd4253a2c8d730b978a186923b1af5e879Jonathan Cameron/* IDA to assign each registered device a unique id*/
32b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameronstatic DEFINE_IDA(iio_ida);
33847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
34f625cb97d4d58f311a9606a4bcf9d9a334ca9952Jonathan Cameronstatic dev_t iio_devt;
35847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
36847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#define IIO_DEV_MAX 256
375aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameronstruct bus_type iio_bus_type = {
38847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.name = "iio",
39847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron};
405aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan CameronEXPORT_SYMBOL(iio_bus_type);
41847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
421e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameronstatic const char * const iio_data_type_name[] = {
431e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron	[IIO_RAW] = "raw",
441e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron	[IIO_PROCESSED] = "input",
451e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron};
461e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron
47c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameronstatic const char * const iio_direction[] = {
48c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron	[0] = "in",
49c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron	[1] = "out",
50c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron};
51c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron
52ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameronstatic const char * const iio_chan_type_name_spec[] = {
53c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron	[IIO_VOLTAGE] = "voltage",
54faf290e867fd51e227165d0bef113b022520a58fMichael Hennerich	[IIO_CURRENT] = "current",
55faf290e867fd51e227165d0bef113b022520a58fMichael Hennerich	[IIO_POWER] = "power",
569bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed	[IIO_ACCEL] = "accel",
5741ea040c7b6daf05d4884097b0168e7b74c6c0d0Jonathan Cameron	[IIO_ANGL_VEL] = "anglvel",
581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_MAGN] = "magn",
599bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed	[IIO_LIGHT] = "illuminance",
609bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed	[IIO_INTENSITY] = "intensity",
61f09f2c8142d275b0d9321d2ea93c8bd0d8dc32ecBryan Freed	[IIO_PROXIMITY] = "proximity",
629bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed	[IIO_TEMP] = "temp",
631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_INCLI] = "incli",
641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_ROT] = "rot",
651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_ANGL] = "angl",
669bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed	[IIO_TIMESTAMP] = "timestamp",
6766dbe70437b561c241d1117dd291c11db21072fdJonathan Cameron	[IIO_CAPACITANCE] = "capacitance",
681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
70330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameronstatic const char * const iio_modifier_names[] = {
711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_MOD_X] = "x",
721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_MOD_Y] = "y",
731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_MOD_Z] = "z",
74330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron	[IIO_MOD_LIGHT_BOTH] = "both",
75330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron	[IIO_MOD_LIGHT_IR] = "ir",
761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron/* relies on pairs of these shared then separate */
791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_chan_info_postfix[] = {
80c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	[IIO_CHAN_INFO_SCALE] = "scale",
81c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	[IIO_CHAN_INFO_OFFSET] = "offset",
82c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	[IIO_CHAN_INFO_CALIBSCALE] = "calibscale",
83c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	[IIO_CHAN_INFO_CALIBBIAS] = "calibbias",
84c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	[IIO_CHAN_INFO_PEAK] = "peak_raw",
85c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	[IIO_CHAN_INFO_PEAK_SCALE] = "peak_scale",
86c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	[IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW] = "quadrature_correction_raw",
87c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron	[IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw",
88df94aba81f81c50ff3f4774c121217b03aaf4f27Jonathan Cameron	[IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY]
89df94aba81f81c50ff3f4774c121217b03aaf4f27Jonathan Cameron	= "filter_low_pass_3db_frequency",
901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
925fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameronconst struct iio_chan_spec
935fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron*iio_find_channel_from_si(struct iio_dev *indio_dev, int si)
945fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron{
955fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron	int i;
965fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron
975fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron	for (i = 0; i < indio_dev->num_channels; i++)
985fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron		if (indio_dev->channels[i].scan_index == si)
995fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron			return &indio_dev->channels[i];
1005fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron	return NULL;
1015fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron}
1025fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron
103847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron/* This turns up an awful lot */
104847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronssize_t iio_read_const_attr(struct device *dev,
105847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			    struct device_attribute *attr,
106847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			    char *buf)
107847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
108847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return sprintf(buf, "%s\n", to_iio_const_attr(attr)->string);
109847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
110847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_read_const_attr);
111847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
112847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic int __init iio_init(void)
113847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
114847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret;
115847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1165aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	/* Register sysfs bus */
1175aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	ret  = bus_register(&iio_bus_type);
118847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret < 0) {
119847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		printk(KERN_ERR
1205aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron		       "%s could not register bus type\n",
121847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			__FILE__);
122847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_nothing;
123847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
124847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1259aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio");
1269aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	if (ret < 0) {
1279aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron		printk(KERN_ERR "%s: failed to allocate char dev region\n",
1289aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron		       __FILE__);
1295aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron		goto error_unregister_bus_type;
1309aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	}
131847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
132847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
133847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1345aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameronerror_unregister_bus_type:
1355aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	bus_unregister(&iio_bus_type);
136847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_nothing:
137847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
138847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
139847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
140847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void __exit iio_exit(void)
141847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1429aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	if (iio_devt)
1439aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron		unregister_chrdev_region(iio_devt, IIO_DEV_MAX);
1445aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	bus_unregister(&iio_bus_type);
145847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
146847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_read_channel_info(struct device *dev,
1481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     struct device_attribute *attr,
1491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     char *buf)
150847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
1521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
1531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int val, val2;
1546fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	int ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
1556fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron					    &val, &val2, this_attr->address);
1561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
1571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret < 0)
1581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
159847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret == IIO_VAL_INT)
1611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return sprintf(buf, "%d\n", val);
1621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	else if (ret == IIO_VAL_INT_PLUS_MICRO) {
1631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (val2 < 0)
1641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			return sprintf(buf, "-%d.%06u\n", val, -val2);
1651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		else
1661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			return sprintf(buf, "%d.%06u\n", val, val2);
16771646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich	} else if (ret == IIO_VAL_INT_PLUS_NANO) {
16871646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich		if (val2 < 0)
16971646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich			return sprintf(buf, "-%d.%09u\n", val, -val2);
17071646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich		else
17171646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich			return sprintf(buf, "%d.%09u\n", val, val2);
1721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	} else
1731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return 0;
1741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
1751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
1761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_write_channel_info(struct device *dev,
1771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      struct device_attribute *attr,
1781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      const char *buf,
1791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      size_t len)
1801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
1811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
1821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
1835c04af04835269c194662be63fe168893fad667fMichael Hennerich	int ret, integer = 0, fract = 0, fract_mult = 100000;
1841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	bool integer_part = true, negative = false;
1851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
1861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	/* Assumes decimal - precision based on number of digits */
1876fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	if (!indio_dev->info->write_raw)
1881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return -EINVAL;
1895c04af04835269c194662be63fe168893fad667fMichael Hennerich
1905c04af04835269c194662be63fe168893fad667fMichael Hennerich	if (indio_dev->info->write_raw_get_fmt)
1915c04af04835269c194662be63fe168893fad667fMichael Hennerich		switch (indio_dev->info->write_raw_get_fmt(indio_dev,
1925c04af04835269c194662be63fe168893fad667fMichael Hennerich			this_attr->c, this_attr->address)) {
1935c04af04835269c194662be63fe168893fad667fMichael Hennerich		case IIO_VAL_INT_PLUS_MICRO:
1945c04af04835269c194662be63fe168893fad667fMichael Hennerich			fract_mult = 100000;
1955c04af04835269c194662be63fe168893fad667fMichael Hennerich			break;
1965c04af04835269c194662be63fe168893fad667fMichael Hennerich		case IIO_VAL_INT_PLUS_NANO:
1975c04af04835269c194662be63fe168893fad667fMichael Hennerich			fract_mult = 100000000;
1985c04af04835269c194662be63fe168893fad667fMichael Hennerich			break;
1995c04af04835269c194662be63fe168893fad667fMichael Hennerich		default:
2005c04af04835269c194662be63fe168893fad667fMichael Hennerich			return -EINVAL;
2015c04af04835269c194662be63fe168893fad667fMichael Hennerich		}
2025c04af04835269c194662be63fe168893fad667fMichael Hennerich
2031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (buf[0] == '-') {
2041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		negative = true;
2051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		buf++;
2061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
2075c04af04835269c194662be63fe168893fad667fMichael Hennerich
2081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	while (*buf) {
2091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if ('0' <= *buf && *buf <= '9') {
2101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (integer_part)
2111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				integer = integer*10 + *buf - '0';
2121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			else {
2135c04af04835269c194662be63fe168893fad667fMichael Hennerich				fract += fract_mult*(*buf - '0');
2145c04af04835269c194662be63fe168893fad667fMichael Hennerich				if (fract_mult == 1)
2151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					break;
2165c04af04835269c194662be63fe168893fad667fMichael Hennerich				fract_mult /= 10;
2171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			}
2181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		} else if (*buf == '\n') {
2191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (*(buf + 1) == '\0')
2201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				break;
2211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			else
2221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				return -EINVAL;
2231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		} else if (*buf == '.') {
2241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			integer_part = false;
2251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		} else {
2261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			return -EINVAL;
2271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
2281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		buf++;
2291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
2301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (negative) {
2311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (integer)
2321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			integer = -integer;
2331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		else
2345c04af04835269c194662be63fe168893fad667fMichael Hennerich			fract = -fract;
2351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
2361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
2376fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	ret = indio_dev->info->write_raw(indio_dev, this_attr->c,
2385c04af04835269c194662be63fe168893fad667fMichael Hennerich					 integer, fract, this_attr->address);
2391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
2401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
2411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
2421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return len;
2431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
2441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
245df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameronstatic
2461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronint __iio_device_attr_init(struct device_attribute *dev_attr,
2471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   const char *postfix,
2481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct iio_chan_spec const *chan,
2491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*readfunc)(struct device *dev,
2501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       struct device_attribute *attr,
2511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       char *buf),
2521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*writefunc)(struct device *dev,
2531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						struct device_attribute *attr,
2541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						const char *buf,
2551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						size_t len),
2561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   bool generic)
2571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
2581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret;
2591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	char *name_format, *full_postfix;
2601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	sysfs_attr_init(&dev_attr->attr);
2611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
262ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	/* Build up postfix of <extend_name>_<modifier>_postfix */
2630403e0d643809f1608448ada38a1877f26b7bf5dJonathan Cameron	if (chan->modified && !generic) {
264ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		if (chan->extend_name)
265ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s",
266ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 iio_modifier_names[chan
267ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron								    ->channel2],
268ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 chan->extend_name,
269ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 postfix);
270ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else
271ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			full_postfix = kasprintf(GFP_KERNEL, "%s_%s",
272ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 iio_modifier_names[chan
273ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron								    ->channel2],
274ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 postfix);
275ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	} else {
276ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		if (chan->extend_name == NULL)
277ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			full_postfix = kstrdup(postfix, GFP_KERNEL);
278ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else
279ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			full_postfix = kasprintf(GFP_KERNEL,
280ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 "%s_%s",
281ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 chan->extend_name,
282ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 postfix);
283ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	}
284ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	if (full_postfix == NULL) {
285ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		ret = -ENOMEM;
286ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		goto error_ret;
287ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	}
2881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
289ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	if (chan->differential) { /* Differential  can not have modifier */
290ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		if (generic)
291ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			name_format
292ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron				= kasprintf(GFP_KERNEL, "%s_%s-%s_%s",
293ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_direction[chan->output],
294ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
295ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
296ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    full_postfix);
297ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else if (chan->indexed)
298ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			name_format
299ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron				= kasprintf(GFP_KERNEL, "%s_%s%d-%s%d_%s",
300ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_direction[chan->output],
301ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
302ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    chan->channel,
303ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
304ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    chan->channel2,
305ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    full_postfix);
306ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else {
307ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			WARN_ON("Differential channels must be indexed\n");
308ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			ret = -EINVAL;
309ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			goto error_free_full_postfix;
310ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		}
311ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	} else { /* Single ended */
312ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		if (generic)
313ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			name_format
314ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron				= kasprintf(GFP_KERNEL, "%s_%s_%s",
315ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_direction[chan->output],
316ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
317ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    full_postfix);
318ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else if (chan->indexed)
319ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			name_format
320ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron				= kasprintf(GFP_KERNEL, "%s_%s%d_%s",
321ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_direction[chan->output],
322ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
323ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    chan->channel,
324ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    full_postfix);
325ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else
326ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			name_format
327ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron				= kasprintf(GFP_KERNEL, "%s_%s_%s",
328ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_direction[chan->output],
329ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
330ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    full_postfix);
331ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	}
3321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (name_format == NULL) {
3331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = -ENOMEM;
3341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_free_full_postfix;
3351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
3361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	dev_attr->attr.name = kasprintf(GFP_KERNEL,
3371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					name_format,
3381d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					chan->channel,
3391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					chan->channel2);
3401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (dev_attr->attr.name == NULL) {
3411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = -ENOMEM;
3421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_free_name_format;
3431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
3441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
3451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (readfunc) {
3461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->attr.mode |= S_IRUGO;
3471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->show = readfunc;
3481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
3491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
3501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (writefunc) {
3511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->attr.mode |= S_IWUSR;
3521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->store = writefunc;
3531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
3541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(name_format);
3551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(full_postfix);
3561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
3571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return 0;
3581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
3591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_free_name_format:
3601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(name_format);
3611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_free_full_postfix:
3621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(full_postfix);
3631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
3641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
3651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
3661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
367df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameronstatic void __iio_device_attr_deinit(struct device_attribute *dev_attr)
3681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
3691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(dev_attr->attr.name);
3701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
3711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
3721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronint __iio_add_chan_devattr(const char *postfix,
3731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct iio_chan_spec const *chan,
3741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*readfunc)(struct device *dev,
3751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       struct device_attribute *attr,
3761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       char *buf),
3771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*writefunc)(struct device *dev,
3781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						struct device_attribute *attr,
3791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						const char *buf,
3801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						size_t len),
381e614a54b296185b266b4bd91193e08a5fbd32422Jonathan Cameron			   u64 mask,
3821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   bool generic,
3831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct device *dev,
3841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct list_head *attr_list)
3851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
3861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret;
3871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *iio_attr, *t;
3881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
3891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	iio_attr = kzalloc(sizeof *iio_attr, GFP_KERNEL);
3901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (iio_attr == NULL) {
3911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = -ENOMEM;
3921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_ret;
3931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
3941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	ret = __iio_device_attr_init(&iio_attr->dev_attr,
3951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     postfix, chan,
3961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     readfunc, writefunc, generic);
3971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
3981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_iio_dev_attr_free;
3991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	iio_attr->c = chan;
4001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	iio_attr->address = mask;
4011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_for_each_entry(t, attr_list, l)
4021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (strcmp(t->dev_attr.attr.name,
4031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   iio_attr->dev_attr.attr.name) == 0) {
4041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (!generic)
4051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				dev_err(dev, "tried to double register : %s\n",
4061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					t->dev_attr.attr.name);
4071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = -EBUSY;
4081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_device_attr_deinit;
4091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
4101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_add(&iio_attr->l, attr_list);
4111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return 0;
4131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_device_attr_deinit:
4151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	__iio_device_attr_deinit(&iio_attr->dev_attr);
4161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_iio_dev_attr_free:
4171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(iio_attr);
4181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
4191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
4201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
4211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
422f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
4231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					struct iio_chan_spec const *chan)
4241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
42526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	int ret, i, attrcount = 0;
4261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (chan->channel < 0)
4281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return 0;
4291e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron
4301e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron	ret = __iio_add_chan_devattr(iio_data_type_name[chan->processed_val],
43126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron				     chan,
4321e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron				     &iio_read_channel_info,
433c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron				     (chan->output ?
4341e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron				      &iio_write_channel_info : NULL),
4351e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron				     0,
4361e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron				     0,
437f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron				     &indio_dev->dev,
438f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron				     &indio_dev->channel_attr_list);
4391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
4401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_ret;
44126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	attrcount++;
4421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) {
4441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2],
44526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron					     chan,
4461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &iio_read_channel_info,
4471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &iio_write_channel_info,
448c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron					     i/2,
4491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     !(i%2),
450f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron					     &indio_dev->dev,
451f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron					     &indio_dev->channel_attr_list);
4521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret == -EBUSY && (i%2 == 0)) {
4531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = 0;
4541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			continue;
4551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
4561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret < 0)
4571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
45826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		attrcount++;
4591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
46026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	ret = attrcount;
4611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
4621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
4631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
4641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
465f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic void iio_device_remove_and_free_read_attr(struct iio_dev *indio_dev,
4661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						 struct iio_dev_attr *p)
4671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
4681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(p->dev_attr.attr.name);
4691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(p);
4701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
4711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4721b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameronstatic ssize_t iio_show_dev_name(struct device *dev,
4731b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron				 struct device_attribute *attr,
4741b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron				 char *buf)
4751b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron{
4761b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
4771b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron	return sprintf(buf, "%s\n", indio_dev->name);
4781b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron}
4791b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron
4801b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameronstatic DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
4811b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron
482f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_register_sysfs(struct iio_dev *indio_dev)
4831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
48426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	int i, ret = 0, attrcount, attrn, attrcount_orig = 0;
4851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *p, *n;
48626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	struct attribute **attr;
4871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
48826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	/* First count elements in any existing group */
489f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->info->attrs) {
490f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		attr = indio_dev->info->attrs->attrs;
49126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		while (*attr++ != NULL)
49226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			attrcount_orig++;
493847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
49426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	attrcount = attrcount_orig;
4951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	/*
4961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	 * New channel registration method - relies on the fact a group does
4971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	 *  not need to be initialized if it is name is NULL.
4981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	 */
499f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	INIT_LIST_HEAD(&indio_dev->channel_attr_list);
500f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->channels)
501f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		for (i = 0; i < indio_dev->num_channels; i++) {
502f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron			ret = iio_device_add_channel_sysfs(indio_dev,
503f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron							   &indio_dev
5041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron							   ->channels[i]);
5051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (ret < 0)
5061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				goto error_clear_attrs;
50726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			attrcount += ret;
5081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
50926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
510f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->name)
51126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		attrcount++;
51226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
513d83fb184945cd2daaafd33a702bba9cb7ed502bfThomas Meyer	indio_dev->chan_attr_group.attrs = kcalloc(attrcount + 1,
514d83fb184945cd2daaafd33a702bba9cb7ed502bfThomas Meyer						   sizeof(indio_dev->chan_attr_group.attrs[0]),
515d83fb184945cd2daaafd33a702bba9cb7ed502bfThomas Meyer						   GFP_KERNEL);
516f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->chan_attr_group.attrs == NULL) {
51726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		ret = -ENOMEM;
51826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		goto error_clear_attrs;
5191b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron	}
52026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	/* Copy across original attributes */
521f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->info->attrs)
522f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		memcpy(indio_dev->chan_attr_group.attrs,
523f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		       indio_dev->info->attrs->attrs,
524f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		       sizeof(indio_dev->chan_attr_group.attrs[0])
52526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		       *attrcount_orig);
52626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	attrn = attrcount_orig;
52726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	/* Add all elements from the list. */
528f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	list_for_each_entry(p, &indio_dev->channel_attr_list, l)
529f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr;
530f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->name)
531f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr;
53226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
533f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->groups[indio_dev->groupcounter++] =
534f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		&indio_dev->chan_attr_group;
53526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
5361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return 0;
5371b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron
5381d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_clear_attrs:
5391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_for_each_entry_safe(p, n,
540f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron				 &indio_dev->channel_attr_list, l) {
5411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		list_del(&p->l);
542f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		iio_device_remove_and_free_read_attr(indio_dev, p);
5431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
5441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
54526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	return ret;
546847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
547847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
548f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic void iio_device_unregister_sysfs(struct iio_dev *indio_dev)
549847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
5501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *p, *n;
55226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
553f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	list_for_each_entry_safe(p, n, &indio_dev->channel_attr_list, l) {
5541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		list_del(&p->l);
555f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		iio_device_remove_and_free_read_attr(indio_dev, p);
5561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
557f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	kfree(indio_dev->chan_attr_group.attrs);
558847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
559847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
560847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void iio_dev_release(struct device *device)
561847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
562f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	struct iio_dev *indio_dev = container_of(device, struct iio_dev, dev);
563f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	cdev_del(&indio_dev->chrdev);
564f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
565f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		iio_device_unregister_trigger_consumer(indio_dev);
566f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	iio_device_unregister_eventset(indio_dev);
567f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	iio_device_unregister_sysfs(indio_dev);
568847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
569847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
570847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic struct device_type iio_dev_type = {
571847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.name = "iio_device",
572847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.release = iio_dev_release,
573847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron};
574847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
5756f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameronstruct iio_dev *iio_allocate_device(int sizeof_priv)
576847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
5776f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	struct iio_dev *dev;
5786f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	size_t alloc_size;
5796f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron
5806f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	alloc_size = sizeof(struct iio_dev);
5816f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	if (sizeof_priv) {
5826f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron		alloc_size = ALIGN(alloc_size, IIO_ALIGN);
5836f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron		alloc_size += sizeof_priv;
5846f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	}
5856f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	/* ensure 32-byte alignment of whole construct ? */
5866f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	alloc_size += IIO_ALIGN - 1;
5876f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron
5886f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	dev = kzalloc(alloc_size, GFP_KERNEL);
589847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
590847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (dev) {
59126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		dev->dev.groups = dev->groups;
592847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		dev->dev.type = &iio_dev_type;
5935aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron		dev->dev.bus = &iio_bus_type;
594847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		device_initialize(&dev->dev);
595847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		dev_set_drvdata(&dev->dev, (void *)dev);
596847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_init(&dev->mlock);
597ac917a81117ce0286847666b55dd265f6cda8383Jonathan Cameron		mutex_init(&dev->info_exist_lock);
598a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron
599a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron		dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL);
600a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron		if (dev->id < 0) {
601a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron			/* cannot use a dev_err as the name isn't available */
602a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron			printk(KERN_ERR "Failed to get id\n");
603a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron			kfree(dev);
604a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron			return NULL;
605a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron		}
606a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron		dev_set_name(&dev->dev, "iio:device%d", dev->id);
607847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
608847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
609847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return dev;
610847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
611847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_allocate_device);
612847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
613847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronvoid iio_free_device(struct iio_dev *dev)
614847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
615a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron	if (dev) {
616a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron		ida_simple_remove(&iio_ida, dev->id);
6171aa042783251c27a93e31929c24647729db326d4Jonathan Cameron		kfree(dev);
618a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron	}
619847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
620847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_free_device);
621847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
6221aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/**
62314555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron * iio_chrdev_open() - chrdev file open for buffer access and ioctls
6241aa042783251c27a93e31929c24647729db326d4Jonathan Cameron **/
6251aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic int iio_chrdev_open(struct inode *inode, struct file *filp)
6261aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{
627f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	struct iio_dev *indio_dev = container_of(inode->i_cdev,
6281aa042783251c27a93e31929c24647729db326d4Jonathan Cameron						struct iio_dev, chrdev);
629bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen
630bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen	if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags))
631bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen		return -EBUSY;
632bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen
633f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	filp->private_data = indio_dev;
63430eb82f05dd1f12b18a0ad054401a0b5690fb3c3Jonathan Cameron
6357933514043d42e69663a5123a53fab50eb0b4abaLars-Peter Clausen	return 0;
6361aa042783251c27a93e31929c24647729db326d4Jonathan Cameron}
6371aa042783251c27a93e31929c24647729db326d4Jonathan Cameron
6381aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/**
63914555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron * iio_chrdev_release() - chrdev file close buffer access and ioctls
6401aa042783251c27a93e31929c24647729db326d4Jonathan Cameron **/
6411aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic int iio_chrdev_release(struct inode *inode, struct file *filp)
6421aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{
643bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen	struct iio_dev *indio_dev = container_of(inode->i_cdev,
644bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen						struct iio_dev, chrdev);
645bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen	clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags);
6461aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	return 0;
6471aa042783251c27a93e31929c24647729db326d4Jonathan Cameron}
6481aa042783251c27a93e31929c24647729db326d4Jonathan Cameron
6491aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/* Somewhat of a cross file organization violation - ioctls here are actually
6501aa042783251c27a93e31929c24647729db326d4Jonathan Cameron * event related */
6511aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
6521aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{
6531aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	struct iio_dev *indio_dev = filp->private_data;
6541aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	int __user *ip = (int __user *)arg;
6551aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	int fd;
6561aa042783251c27a93e31929c24647729db326d4Jonathan Cameron
6571aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	if (cmd == IIO_GET_EVENT_FD_IOCTL) {
6581aa042783251c27a93e31929c24647729db326d4Jonathan Cameron		fd = iio_event_getfd(indio_dev);
6591aa042783251c27a93e31929c24647729db326d4Jonathan Cameron		if (copy_to_user(ip, &fd, sizeof(fd)))
6601aa042783251c27a93e31929c24647729db326d4Jonathan Cameron			return -EFAULT;
6611aa042783251c27a93e31929c24647729db326d4Jonathan Cameron		return 0;
6621aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	}
6631aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	return -EINVAL;
6641aa042783251c27a93e31929c24647729db326d4Jonathan Cameron}
6651aa042783251c27a93e31929c24647729db326d4Jonathan Cameron
66614555b14455f9acbdf0e500ae96140828a970796Jonathan Cameronstatic const struct file_operations iio_buffer_fileops = {
66714555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron	.read = iio_buffer_read_first_n_outer_addr,
6681aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	.release = iio_chrdev_release,
6691aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	.open = iio_chrdev_open,
67014555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron	.poll = iio_buffer_poll_addr,
6711aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	.owner = THIS_MODULE,
6721aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	.llseek = noop_llseek,
6731aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	.unlocked_ioctl = iio_ioctl,
6741aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	.compat_ioctl = iio_ioctl,
6751aa042783251c27a93e31929c24647729db326d4Jonathan Cameron};
6761aa042783251c27a93e31929c24647729db326d4Jonathan Cameron
677f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronint iio_device_register(struct iio_dev *indio_dev)
678847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
679847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret;
680847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
6811aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	/* configure elements for the chrdev */
682f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id);
683847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
684f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	ret = iio_device_register_sysfs(indio_dev);
685847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret) {
686f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		dev_err(indio_dev->dev.parent,
687847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			"Failed to register sysfs interfaces\n");
688a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron		goto error_ret;
689847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
690f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	ret = iio_device_register_eventset(indio_dev);
691847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret) {
692f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		dev_err(indio_dev->dev.parent,
693c849d2538ebeef1ac26fad7a10c18b1e0fc35161Roel Van Nyen			"Failed to register event set\n");
694847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_free_sysfs;
695847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
696f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
697f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		iio_device_register_trigger_consumer(indio_dev);
698847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
699f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	ret = device_add(&indio_dev->dev);
70026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	if (ret < 0)
70126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		goto error_unreg_eventset;
702f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	cdev_init(&indio_dev->chrdev, &iio_buffer_fileops);
703f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->chrdev.owner = indio_dev->info->driver_module;
704f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1);
70526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	if (ret < 0)
70626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		goto error_del_device;
707847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
708847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
709847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_del_device:
710f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	device_del(&indio_dev->dev);
71126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameronerror_unreg_eventset:
712f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	iio_device_unregister_eventset(indio_dev);
71326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameronerror_free_sysfs:
714f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	iio_device_unregister_sysfs(indio_dev);
715847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
716847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
717847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
718847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_device_register);
719847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
720f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronvoid iio_device_unregister(struct iio_dev *indio_dev)
721847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
722ac917a81117ce0286847666b55dd265f6cda8383Jonathan Cameron	mutex_lock(&indio_dev->info_exist_lock);
723ac917a81117ce0286847666b55dd265f6cda8383Jonathan Cameron	indio_dev->info = NULL;
724ac917a81117ce0286847666b55dd265f6cda8383Jonathan Cameron	mutex_unlock(&indio_dev->info_exist_lock);
725f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	device_unregister(&indio_dev->dev);
726847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
727847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_device_unregister);
728847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronsubsys_initcall(iio_init);
729847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronmodule_exit(iio_exit);
730847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
731847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
732847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_DESCRIPTION("Industrial I/O core");
733847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_LICENSE("GPL");
734