industrialio-core.c revision c8a9f8056f40f6201b84fdddb49a1c62630902c5
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",
881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
907ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron/**
917ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * struct iio_detected_event_list - list element for events that have occurred
927ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @list:		linked list header
937ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @ev:			the event itself
947ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron */
957ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameronstruct iio_detected_event_list {
967ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron	struct list_head		list;
977ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron	struct iio_event_data		ev;
987ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron};
997ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron
1007ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron/**
1017ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * struct iio_event_interface - chrdev interface for an event line
1027ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @dev:		device assocated with event interface
1037ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @wait:		wait queue to allow blocking reads of events
1047ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @event_list_lock:	mutex to protect the list of detected events
1057ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @det_events:		list of detected events
1067ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @max_events:		maximum number of events before new ones are dropped
1077ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @current_events:	number of events in detected list
1086356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron * @flags:		file operations related flags including busy flag.
1097ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron */
1107ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameronstruct iio_event_interface {
1117ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron	wait_queue_head_t			wait;
1127ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron	struct mutex				event_list_lock;
1137ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron	struct list_head			det_events;
1147ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron	int					max_events;
1157ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron	int					current_events;
1167ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron	struct list_head dev_attr_list;
1176356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron	unsigned long flags;
11826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	struct attribute_group			group;
1197ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron};
1207ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron
121f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronint iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
122847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
123f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	struct iio_event_interface *ev_int = indio_dev->event_interface;
124847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_detected_event_list *ev;
125847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret = 0;
126847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
127847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	/* Does anyone care? */
128847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_lock(&ev_int->event_list_lock);
1296356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron	if (test_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) {
13075c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron		if (ev_int->current_events == ev_int->max_events) {
13175c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron			mutex_unlock(&ev_int->event_list_lock);
132847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			return 0;
13375c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron		}
134847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ev = kmalloc(sizeof(*ev), GFP_KERNEL);
135847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		if (ev == NULL) {
136847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			ret = -ENOMEM;
13775c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron			mutex_unlock(&ev_int->event_list_lock);
138847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			goto error_ret;
139847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		}
140847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ev->ev.id = ev_code;
141847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ev->ev.timestamp = timestamp;
142847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1433b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron		list_add_tail(&ev->list, &ev_int->det_events);
144847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ev_int->current_events++;
145847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_unlock(&ev_int->event_list_lock);
146847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		wake_up_interruptible(&ev_int->wait);
147847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	} else
148847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_unlock(&ev_int->event_list_lock);
149847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
150847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
151847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
152847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
153847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_push_event);
154847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
155847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron/* This turns up an awful lot */
156847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronssize_t iio_read_const_attr(struct device *dev,
157847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			    struct device_attribute *attr,
158847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			    char *buf)
159847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
160847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return sprintf(buf, "%s\n", to_iio_const_attr(attr)->string);
161847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
162847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_read_const_attr);
163847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
16477712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brownstatic ssize_t iio_event_chrdev_read(struct file *filep,
16577712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brown				     char __user *buf,
16677712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brown				     size_t count,
16777712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brown				     loff_t *f_ps)
168847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
169847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_event_interface *ev_int = filep->private_data;
170847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_detected_event_list *el;
171dc8f52643d494eaa844002ca866d30fda142db4fLars-Peter Clausen	size_t len = sizeof(el->ev);
172847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret;
173dc8f52643d494eaa844002ca866d30fda142db4fLars-Peter Clausen
174dc8f52643d494eaa844002ca866d30fda142db4fLars-Peter Clausen	if (count < len)
175dc8f52643d494eaa844002ca866d30fda142db4fLars-Peter Clausen		return -EINVAL;
1766356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron
177847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_lock(&ev_int->event_list_lock);
1783b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron	if (list_empty(&ev_int->det_events)) {
179847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		if (filep->f_flags & O_NONBLOCK) {
180847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			ret = -EAGAIN;
181847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			goto error_mutex_unlock;
182847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		}
183847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_unlock(&ev_int->event_list_lock);
184847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		/* Blocking on device; waiting for something to be there */
185847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ret = wait_event_interruptible(ev_int->wait,
186847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron					       !list_empty(&ev_int
1873b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron							   ->det_events));
188847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		if (ret)
189847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			goto error_ret;
19025985edcedea6396277003854657b5f3cb31a628Lucas De Marchi		/* Single access device so no one else can get the data */
191847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_lock(&ev_int->event_list_lock);
192847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
193847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1943b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron	el = list_first_entry(&ev_int->det_events,
195847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			      struct iio_detected_event_list,
196847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			      list);
197847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (copy_to_user(buf, &(el->ev), len)) {
198847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ret = -EFAULT;
199847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_mutex_unlock;
200847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
201847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	list_del(&el->list);
202847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->current_events--;
203847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_unlock(&ev_int->event_list_lock);
204847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	kfree(el);
205847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
206847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return len;
207847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
208847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_mutex_unlock:
209847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_unlock(&ev_int->event_list_lock);
210847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
211847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
212847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
213847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
214847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
21577712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brownstatic int iio_event_chrdev_release(struct inode *inode, struct file *filep)
216847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
2178e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron	struct iio_event_interface *ev_int = filep->private_data;
218847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_detected_event_list *el, *t;
2196356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron
220847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_lock(&ev_int->event_list_lock);
2216356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron	clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
222847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	/*
223847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	 * In order to maintain a clean state for reopening,
224847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	 * clear out any awaiting events. The mask will prevent
225847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	 * any new __iio_push_event calls running.
226847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	 */
2273b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron	list_for_each_entry_safe(el, t, &ev_int->det_events, list) {
228847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		list_del(&el->list);
229847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		kfree(el);
230847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
2318e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron	ev_int->current_events = 0;
232847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_unlock(&ev_int->event_list_lock);
233847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
234847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
235847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
236847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
237847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic const struct file_operations iio_event_chrdev_fileops = {
238847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.read =  iio_event_chrdev_read,
239847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.release = iio_event_chrdev_release,
240847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.owner = THIS_MODULE,
2416038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann	.llseek = noop_llseek,
242847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron};
243847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
2441aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic int iio_event_getfd(struct iio_dev *indio_dev)
2458e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron{
246b46413367961c2e8bd827e067a231be982aaeee2Al Viro	int fd;
247b46413367961c2e8bd827e067a231be982aaeee2Al Viro
2485aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron	if (indio_dev->event_interface == NULL)
2498e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron		return -ENODEV;
2508e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron
2515aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron	mutex_lock(&indio_dev->event_interface->event_list_lock);
2528e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron	if (test_and_set_bit(IIO_BUSY_BIT_POS,
2535aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron			     &indio_dev->event_interface->flags)) {
2545aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron		mutex_unlock(&indio_dev->event_interface->event_list_lock);
2558e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron		return -EBUSY;
2568e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron	}
2575aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron	mutex_unlock(&indio_dev->event_interface->event_list_lock);
258b46413367961c2e8bd827e067a231be982aaeee2Al Viro	fd = anon_inode_getfd("iio:event",
2598e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron				&iio_event_chrdev_fileops,
2605aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron				indio_dev->event_interface, O_RDONLY);
261b46413367961c2e8bd827e067a231be982aaeee2Al Viro	if (fd < 0) {
262b46413367961c2e8bd827e067a231be982aaeee2Al Viro		mutex_lock(&indio_dev->event_interface->event_list_lock);
263f791cec85073298d00f18b8492b79a8b4e9b0580Greg Kroah-Hartman		clear_bit(IIO_BUSY_BIT_POS, &indio_dev->event_interface->flags);
264b46413367961c2e8bd827e067a231be982aaeee2Al Viro		mutex_unlock(&indio_dev->event_interface->event_list_lock);
265b46413367961c2e8bd827e067a231be982aaeee2Al Viro	}
266b46413367961c2e8bd827e067a231be982aaeee2Al Viro	return fd;
2678e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron}
2688e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron
269847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic int __init iio_init(void)
270847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
271847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret;
272847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
2735aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	/* Register sysfs bus */
2745aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	ret  = bus_register(&iio_bus_type);
275847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret < 0) {
276847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		printk(KERN_ERR
2775aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron		       "%s could not register bus type\n",
278847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			__FILE__);
279847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_nothing;
280847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
281847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
2829aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio");
2839aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	if (ret < 0) {
2849aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron		printk(KERN_ERR "%s: failed to allocate char dev region\n",
2859aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron		       __FILE__);
2865aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron		goto error_unregister_bus_type;
2879aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	}
288847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
289847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
290847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
2915aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameronerror_unregister_bus_type:
2925aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	bus_unregister(&iio_bus_type);
293847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_nothing:
294847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
295847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
296847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
297847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void __exit iio_exit(void)
298847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
2999aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	if (iio_devt)
3009aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron		unregister_chrdev_region(iio_devt, IIO_DEV_MAX);
3015aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	bus_unregister(&iio_bus_type);
302847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
303847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
3041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_read_channel_info(struct device *dev,
3051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     struct device_attribute *attr,
3061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     char *buf)
307847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
3081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
3091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
3101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int val, val2;
3116fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	int ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
3126fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron					    &val, &val2, this_attr->address);
3131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
3141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret < 0)
3151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
316847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
3171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret == IIO_VAL_INT)
3181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return sprintf(buf, "%d\n", val);
3191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	else if (ret == IIO_VAL_INT_PLUS_MICRO) {
3201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (val2 < 0)
3211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			return sprintf(buf, "-%d.%06u\n", val, -val2);
3221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		else
3231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			return sprintf(buf, "%d.%06u\n", val, val2);
32471646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich	} else if (ret == IIO_VAL_INT_PLUS_NANO) {
32571646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich		if (val2 < 0)
32671646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich			return sprintf(buf, "-%d.%09u\n", val, -val2);
32771646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich		else
32871646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich			return sprintf(buf, "%d.%09u\n", val, val2);
3291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	} else
3301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return 0;
3311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
3321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
3331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_write_channel_info(struct device *dev,
3341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      struct device_attribute *attr,
3351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      const char *buf,
3361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      size_t len)
3371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
3381d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
3391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
3405c04af04835269c194662be63fe168893fad667fMichael Hennerich	int ret, integer = 0, fract = 0, fract_mult = 100000;
3411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	bool integer_part = true, negative = false;
3421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
3431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	/* Assumes decimal - precision based on number of digits */
3446fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	if (!indio_dev->info->write_raw)
3451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return -EINVAL;
3465c04af04835269c194662be63fe168893fad667fMichael Hennerich
3475c04af04835269c194662be63fe168893fad667fMichael Hennerich	if (indio_dev->info->write_raw_get_fmt)
3485c04af04835269c194662be63fe168893fad667fMichael Hennerich		switch (indio_dev->info->write_raw_get_fmt(indio_dev,
3495c04af04835269c194662be63fe168893fad667fMichael Hennerich			this_attr->c, this_attr->address)) {
3505c04af04835269c194662be63fe168893fad667fMichael Hennerich		case IIO_VAL_INT_PLUS_MICRO:
3515c04af04835269c194662be63fe168893fad667fMichael Hennerich			fract_mult = 100000;
3525c04af04835269c194662be63fe168893fad667fMichael Hennerich			break;
3535c04af04835269c194662be63fe168893fad667fMichael Hennerich		case IIO_VAL_INT_PLUS_NANO:
3545c04af04835269c194662be63fe168893fad667fMichael Hennerich			fract_mult = 100000000;
3555c04af04835269c194662be63fe168893fad667fMichael Hennerich			break;
3565c04af04835269c194662be63fe168893fad667fMichael Hennerich		default:
3575c04af04835269c194662be63fe168893fad667fMichael Hennerich			return -EINVAL;
3585c04af04835269c194662be63fe168893fad667fMichael Hennerich		}
3595c04af04835269c194662be63fe168893fad667fMichael Hennerich
3601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (buf[0] == '-') {
3611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		negative = true;
3621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		buf++;
3631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
3645c04af04835269c194662be63fe168893fad667fMichael Hennerich
3651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	while (*buf) {
3661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if ('0' <= *buf && *buf <= '9') {
3671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (integer_part)
3681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				integer = integer*10 + *buf - '0';
3691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			else {
3705c04af04835269c194662be63fe168893fad667fMichael Hennerich				fract += fract_mult*(*buf - '0');
3715c04af04835269c194662be63fe168893fad667fMichael Hennerich				if (fract_mult == 1)
3721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					break;
3735c04af04835269c194662be63fe168893fad667fMichael Hennerich				fract_mult /= 10;
3741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			}
3751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		} else if (*buf == '\n') {
3761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (*(buf + 1) == '\0')
3771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				break;
3781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			else
3791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				return -EINVAL;
3801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		} else if (*buf == '.') {
3811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			integer_part = false;
3821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		} else {
3831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			return -EINVAL;
3841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
3851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		buf++;
3861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
3871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (negative) {
3881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (integer)
3891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			integer = -integer;
3901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		else
3915c04af04835269c194662be63fe168893fad667fMichael Hennerich			fract = -fract;
3921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
3931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
3946fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	ret = indio_dev->info->write_raw(indio_dev, this_attr->c,
3955c04af04835269c194662be63fe168893fad667fMichael Hennerich					 integer, fract, this_attr->address);
3961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
3971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
3981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
3991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return len;
4001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
4011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
402df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameronstatic
4031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronint __iio_device_attr_init(struct device_attribute *dev_attr,
4041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   const char *postfix,
4051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct iio_chan_spec const *chan,
4061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*readfunc)(struct device *dev,
4071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       struct device_attribute *attr,
4081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       char *buf),
4091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*writefunc)(struct device *dev,
4101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						struct device_attribute *attr,
4111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						const char *buf,
4121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						size_t len),
4131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   bool generic)
4141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
4151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret;
4161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	char *name_format, *full_postfix;
4171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	sysfs_attr_init(&dev_attr->attr);
4181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
419ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	/* Build up postfix of <extend_name>_<modifier>_postfix */
4200403e0d643809f1608448ada38a1877f26b7bf5dJonathan Cameron	if (chan->modified && !generic) {
421ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		if (chan->extend_name)
422ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s",
423ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 iio_modifier_names[chan
424ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron								    ->channel2],
425ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 chan->extend_name,
426ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 postfix);
427ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else
428ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			full_postfix = kasprintf(GFP_KERNEL, "%s_%s",
429ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 iio_modifier_names[chan
430ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron								    ->channel2],
431ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 postfix);
432ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	} else {
433ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		if (chan->extend_name == NULL)
434ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			full_postfix = kstrdup(postfix, GFP_KERNEL);
435ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else
436ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			full_postfix = kasprintf(GFP_KERNEL,
437ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 "%s_%s",
438ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 chan->extend_name,
439ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 postfix);
440ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	}
441ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	if (full_postfix == NULL) {
442ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		ret = -ENOMEM;
443ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		goto error_ret;
444ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	}
4451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
446ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	if (chan->differential) { /* Differential  can not have modifier */
447ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		if (generic)
448ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			name_format
449ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron				= kasprintf(GFP_KERNEL, "%s_%s-%s_%s",
450ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_direction[chan->output],
451ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
452ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
453ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    full_postfix);
454ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else if (chan->indexed)
455ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			name_format
456ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron				= kasprintf(GFP_KERNEL, "%s_%s%d-%s%d_%s",
457ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_direction[chan->output],
458ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
459ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    chan->channel,
460ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
461ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    chan->channel2,
462ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    full_postfix);
463ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else {
464ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			WARN_ON("Differential channels must be indexed\n");
465ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			ret = -EINVAL;
466ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			goto error_free_full_postfix;
467ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		}
468ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	} else { /* Single ended */
469ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		if (generic)
470ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			name_format
471ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron				= kasprintf(GFP_KERNEL, "%s_%s_%s",
472ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_direction[chan->output],
473ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
474ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    full_postfix);
475ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else if (chan->indexed)
476ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			name_format
477ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron				= kasprintf(GFP_KERNEL, "%s_%s%d_%s",
478ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_direction[chan->output],
479ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
480ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    chan->channel,
481ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    full_postfix);
482ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else
483ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			name_format
484ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron				= kasprintf(GFP_KERNEL, "%s_%s_%s",
485ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_direction[chan->output],
486ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
487ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    full_postfix);
488ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	}
4891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (name_format == NULL) {
4901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = -ENOMEM;
4911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_free_full_postfix;
4921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
4931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	dev_attr->attr.name = kasprintf(GFP_KERNEL,
4941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					name_format,
4951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					chan->channel,
4961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					chan->channel2);
4971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (dev_attr->attr.name == NULL) {
4981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = -ENOMEM;
4991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_free_name_format;
5001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
5011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (readfunc) {
5031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->attr.mode |= S_IRUGO;
5041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->show = readfunc;
5051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
5061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (writefunc) {
5081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->attr.mode |= S_IWUSR;
5091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->store = writefunc;
5101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
5111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(name_format);
5121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(full_postfix);
5131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return 0;
5151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_free_name_format:
5171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(name_format);
5181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_free_full_postfix:
5191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(full_postfix);
5201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
5211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
5221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
5231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
524df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameronstatic void __iio_device_attr_deinit(struct device_attribute *dev_attr)
5251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
5261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(dev_attr->attr.name);
5271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
5281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronint __iio_add_chan_devattr(const char *postfix,
5301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct iio_chan_spec const *chan,
5311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*readfunc)(struct device *dev,
5321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       struct device_attribute *attr,
5331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       char *buf),
5341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*writefunc)(struct device *dev,
5351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						struct device_attribute *attr,
5361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						const char *buf,
5371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						size_t len),
538e614a54b296185b266b4bd91193e08a5fbd32422Jonathan Cameron			   u64 mask,
5391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   bool generic,
5401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct device *dev,
5411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct list_head *attr_list)
5421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
5431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret;
5441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *iio_attr, *t;
5451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	iio_attr = kzalloc(sizeof *iio_attr, GFP_KERNEL);
5471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (iio_attr == NULL) {
5481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = -ENOMEM;
5491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_ret;
5501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
5511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	ret = __iio_device_attr_init(&iio_attr->dev_attr,
5521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     postfix, chan,
5531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     readfunc, writefunc, generic);
5541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
5551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_iio_dev_attr_free;
5561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	iio_attr->c = chan;
5571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	iio_attr->address = mask;
5581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_for_each_entry(t, attr_list, l)
5591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (strcmp(t->dev_attr.attr.name,
5601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   iio_attr->dev_attr.attr.name) == 0) {
5611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (!generic)
5621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				dev_err(dev, "tried to double register : %s\n",
5631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					t->dev_attr.attr.name);
5641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = -EBUSY;
5651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_device_attr_deinit;
5661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
5671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_add(&iio_attr->l, attr_list);
5681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return 0;
5701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_device_attr_deinit:
5721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	__iio_device_attr_deinit(&iio_attr->dev_attr);
5731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_iio_dev_attr_free:
5741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(iio_attr);
5751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
5761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
5771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
5781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
579f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
5801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					struct iio_chan_spec const *chan)
5811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
58226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	int ret, i, attrcount = 0;
5831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (chan->channel < 0)
5851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return 0;
5861e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron
5871e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron	ret = __iio_add_chan_devattr(iio_data_type_name[chan->processed_val],
58826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron				     chan,
5891e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron				     &iio_read_channel_info,
590c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron				     (chan->output ?
5911e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron				      &iio_write_channel_info : NULL),
5921e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron				     0,
5931e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron				     0,
594f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron				     &indio_dev->dev,
595f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron				     &indio_dev->channel_attr_list);
5961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
5971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_ret;
59826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	attrcount++;
5991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) {
6011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2],
60226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron					     chan,
6031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &iio_read_channel_info,
6041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &iio_write_channel_info,
605c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron					     i/2,
6061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     !(i%2),
607f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron					     &indio_dev->dev,
608f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron					     &indio_dev->channel_attr_list);
6091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret == -EBUSY && (i%2 == 0)) {
6101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = 0;
6111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			continue;
6121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
6131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret < 0)
6141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
61526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		attrcount++;
6161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
61726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	ret = attrcount;
6181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
6191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
6201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
6211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
622f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic void iio_device_remove_and_free_read_attr(struct iio_dev *indio_dev,
6231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						 struct iio_dev_attr *p)
6241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
6251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(p->dev_attr.attr.name);
6261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(p);
6271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
6281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6291b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameronstatic ssize_t iio_show_dev_name(struct device *dev,
6301b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron				 struct device_attribute *attr,
6311b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron				 char *buf)
6321b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron{
6331b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
6341b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron	return sprintf(buf, "%s\n", indio_dev->name);
6351b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron}
6361b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron
6371b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameronstatic DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
6381b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron
639f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_register_sysfs(struct iio_dev *indio_dev)
6401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
64126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	int i, ret = 0, attrcount, attrn, attrcount_orig = 0;
6421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *p, *n;
64326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	struct attribute **attr;
6441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
64526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	/* First count elements in any existing group */
646f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->info->attrs) {
647f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		attr = indio_dev->info->attrs->attrs;
64826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		while (*attr++ != NULL)
64926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			attrcount_orig++;
650847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
65126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	attrcount = attrcount_orig;
6521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	/*
6531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	 * New channel registration method - relies on the fact a group does
6541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	 *  not need to be initialized if it is name is NULL.
6551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	 */
656f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	INIT_LIST_HEAD(&indio_dev->channel_attr_list);
657f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->channels)
658f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		for (i = 0; i < indio_dev->num_channels; i++) {
659f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron			ret = iio_device_add_channel_sysfs(indio_dev,
660f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron							   &indio_dev
6611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron							   ->channels[i]);
6621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (ret < 0)
6631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				goto error_clear_attrs;
66426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			attrcount += ret;
6651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
66626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
667f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->name)
66826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		attrcount++;
66926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
670f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->chan_attr_group.attrs
671f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		= kzalloc(sizeof(indio_dev->chan_attr_group.attrs[0])*
67226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			  (attrcount + 1),
67326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			  GFP_KERNEL);
674f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->chan_attr_group.attrs == NULL) {
67526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		ret = -ENOMEM;
67626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		goto error_clear_attrs;
6771b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron	}
67826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	/* Copy across original attributes */
679f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->info->attrs)
680f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		memcpy(indio_dev->chan_attr_group.attrs,
681f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		       indio_dev->info->attrs->attrs,
682f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		       sizeof(indio_dev->chan_attr_group.attrs[0])
68326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		       *attrcount_orig);
68426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	attrn = attrcount_orig;
68526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	/* Add all elements from the list. */
686f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	list_for_each_entry(p, &indio_dev->channel_attr_list, l)
687f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr;
688f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->name)
689f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr;
69026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
691f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->groups[indio_dev->groupcounter++] =
692f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		&indio_dev->chan_attr_group;
69326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
6941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return 0;
6951b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron
6961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_clear_attrs:
6971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_for_each_entry_safe(p, n,
698f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron				 &indio_dev->channel_attr_list, l) {
6991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		list_del(&p->l);
700f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		iio_device_remove_and_free_read_attr(indio_dev, p);
7011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
7021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
70326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	return ret;
704847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
705847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
706f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic void iio_device_unregister_sysfs(struct iio_dev *indio_dev)
707847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
7081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *p, *n;
71026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
711f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	list_for_each_entry_safe(p, n, &indio_dev->channel_attr_list, l) {
7121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		list_del(&p->l);
713f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		iio_device_remove_and_free_read_attr(indio_dev, p);
7141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
715f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	kfree(indio_dev->chan_attr_group.attrs);
716847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
717847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
7181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_ev_type_text[] = {
7191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_TYPE_THRESH] = "thresh",
7201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_TYPE_MAG] = "mag",
7218ce7375be7036d6e536b6341ec83e5db849cda6eJonathan Cameron	[IIO_EV_TYPE_ROC] = "roc",
7228ce7375be7036d6e536b6341ec83e5db849cda6eJonathan Cameron	[IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive",
7238ce7375be7036d6e536b6341ec83e5db849cda6eJonathan Cameron	[IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive",
7241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
7251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_ev_dir_text[] = {
7271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_DIR_EITHER] = "either",
7281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_DIR_RISING] = "rising",
7291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_DIR_FALLING] = "falling"
7301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
7311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_state_store(struct device *dev,
7331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  struct device_attribute *attr,
7341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  const char *buf,
7351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  size_t len)
7361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
7371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
738aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
7391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret;
740c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	bool val;
741c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron
742c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	ret = strtobool(buf, &val);
743c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	if (ret < 0)
744c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron		return ret;
7451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7466fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	ret = indio_dev->info->write_event_config(indio_dev,
7476fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						  this_attr->address,
7486fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						  val);
7491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return (ret < 0) ? ret : len;
7501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
7511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_state_show(struct device *dev,
7531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 struct device_attribute *attr,
7541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 char *buf)
7551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
7561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
757aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
7586fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	int val = indio_dev->info->read_event_config(indio_dev,
7596fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						     this_attr->address);
7601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (val < 0)
7621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return val;
7631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	else
7641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return sprintf(buf, "%d\n", val);
7651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
7661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_value_show(struct device *dev,
7681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 struct device_attribute *attr,
7691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 char *buf)
7701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
7711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
7721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
7731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int val, ret;
7741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7756fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	ret = indio_dev->info->read_event_value(indio_dev,
7766fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						this_attr->address, &val);
7771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret < 0)
7781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
7791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return sprintf(buf, "%d\n", val);
7811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
7821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_value_store(struct device *dev,
7841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  struct device_attribute *attr,
7851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  const char *buf,
7861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  size_t len)
7871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
7881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
7891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
7901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	unsigned long val;
7911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret;
7921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	ret = strict_strtoul(buf, 10, &val);
7941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
7951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
7961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7976fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	ret = indio_dev->info->write_event_value(indio_dev, this_attr->address,
7986fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						 val);
7991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret < 0)
8001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
8011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return len;
8031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
8041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
805f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_add_event_sysfs(struct iio_dev *indio_dev,
8061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      struct iio_chan_spec const *chan)
8071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
808e614a54b296185b266b4bd91193e08a5fbd32422Jonathan Cameron	int ret = 0, i, attrcount = 0;
809e614a54b296185b266b4bd91193e08a5fbd32422Jonathan Cameron	u64 mask = 0;
8101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	char *postfix;
8111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (!chan->event_mask)
8121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return 0;
8131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	for_each_set_bit(i, &chan->event_mask, sizeof(chan->event_mask)*8) {
8151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		postfix = kasprintf(GFP_KERNEL, "%s_%s_en",
816c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron				    iio_ev_type_text[i/IIO_EV_DIR_MAX],
817c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron				    iio_ev_dir_text[i%IIO_EV_DIR_MAX]);
8181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (postfix == NULL) {
8191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = -ENOMEM;
8201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
8211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
822330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron		if (chan->modified)
8231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel,
824c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron						  i/IIO_EV_DIR_MAX,
825c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron						  i%IIO_EV_DIR_MAX);
826ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else if (chan->differential)
827ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			mask = IIO_EVENT_CODE(chan->type,
828ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					      0, 0,
829ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					      i%IIO_EV_DIR_MAX,
830ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					      i/IIO_EV_DIR_MAX,
831ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					      0,
832ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					      chan->channel,
833ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					      chan->channel2);
834330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron		else
835330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron			mask = IIO_UNMOD_EVENT_CODE(chan->type,
836330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron						    chan->channel,
837c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron						    i/IIO_EV_DIR_MAX,
838c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron						    i%IIO_EV_DIR_MAX);
839330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron
840aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron		ret = __iio_add_chan_devattr(postfix,
841aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     chan,
842aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     &iio_ev_state_show,
843aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     iio_ev_state_store,
844aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     mask,
845aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     0,
846f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron					     &indio_dev->dev,
847f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron					     &indio_dev->event_interface->
848aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     dev_attr_list);
8491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		kfree(postfix);
8501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret)
8511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
85226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		attrcount++;
8531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		postfix = kasprintf(GFP_KERNEL, "%s_%s_value",
854c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron				    iio_ev_type_text[i/IIO_EV_DIR_MAX],
855c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron				    iio_ev_dir_text[i%IIO_EV_DIR_MAX]);
8561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (postfix == NULL) {
8571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = -ENOMEM;
8581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
8591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
86026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		ret = __iio_add_chan_devattr(postfix, chan,
8611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     iio_ev_value_show,
8621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     iio_ev_value_store,
8631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     mask,
8641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     0,
865f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron					     &indio_dev->dev,
866f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron					     &indio_dev->event_interface->
8675aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron					     dev_attr_list);
8681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		kfree(postfix);
8691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret)
8701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
87126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		attrcount++;
8721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
87326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	ret = attrcount;
8741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
8751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
8761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
8771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
878f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic inline void __iio_remove_event_config_attrs(struct iio_dev *indio_dev)
8791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
8801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *p, *n;
8811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_for_each_entry_safe(p, n,
882f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron				 &indio_dev->event_interface->
8831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 dev_attr_list, l) {
8841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		kfree(p->dev_attr.attr.name);
8851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		kfree(p);
8861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
8871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
8881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
889f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev)
890847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
89126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	int j, ret, attrcount = 0;
8921e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron
893f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list);
8941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	/* Dynically created from the channels array */
895f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	for (j = 0; j < indio_dev->num_channels; j++) {
896f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		ret = iio_device_add_event_sysfs(indio_dev,
897f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron						 &indio_dev->channels[j]);
89826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		if (ret < 0)
8995aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron			goto error_clear_attrs;
90026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		attrcount += ret;
9011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
90226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	return attrcount;
903847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
9041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_clear_attrs:
905f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	__iio_remove_event_config_attrs(indio_dev);
906847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
907847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
908847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
909847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
910f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic bool iio_check_for_dynamic_events(struct iio_dev *indio_dev)
9115aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron{
9125aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron	int j;
9131e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron
914f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	for (j = 0; j < indio_dev->num_channels; j++)
915f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		if (indio_dev->channels[j].event_mask != 0)
9165aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron			return true;
9175aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron	return false;
9185aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron}
9195aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron
9201e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameronstatic void iio_setup_ev_int(struct iio_event_interface *ev_int)
9211e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron{
9221e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron	mutex_init(&ev_int->event_list_lock);
9231e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron	/* discussion point - make this variable? */
9241e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron	ev_int->max_events = 10;
9251e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron	ev_int->current_events = 0;
9261e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron	INIT_LIST_HEAD(&ev_int->det_events);
9271e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron	init_waitqueue_head(&ev_int->wait);
9281e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron}
9291e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron
93026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameronstatic const char *iio_event_group_name = "events";
931f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_register_eventset(struct iio_dev *indio_dev)
932847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
93326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	struct iio_dev_attr *p;
93426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	int ret = 0, attrcount_orig = 0, attrcount, attrn;
93526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	struct attribute **attr;
936847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
937f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (!(indio_dev->info->event_attrs ||
938f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	      iio_check_for_dynamic_events(indio_dev)))
939847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		return 0;
940847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
941f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->event_interface =
9425aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron		kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL);
943f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->event_interface == NULL) {
944847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ret = -ENOMEM;
945847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_ret;
946847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
947847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
948f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	iio_setup_ev_int(indio_dev->event_interface);
949f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->info->event_attrs != NULL) {
950f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		attr = indio_dev->info->event_attrs->attrs;
95126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		while (*attr++ != NULL)
95226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			attrcount_orig++;
9535aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron	}
95426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	attrcount = attrcount_orig;
955f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->channels) {
956f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		ret = __iio_add_event_config_attrs(indio_dev);
95726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		if (ret < 0)
958cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron			goto error_free_setup_event_lines;
95926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		attrcount += ret;
960847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
961847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
962f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->event_interface->group.name = iio_event_group_name;
963f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->event_interface->group.attrs =
964f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		kzalloc(sizeof(indio_dev->event_interface->group.attrs[0])
96526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			*(attrcount + 1),
96626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			GFP_KERNEL);
967f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->event_interface->group.attrs == NULL) {
96826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		ret = -ENOMEM;
96926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		goto error_free_setup_event_lines;
97026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	}
971f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->info->event_attrs)
972f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		memcpy(indio_dev->event_interface->group.attrs,
973f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		       indio_dev->info->event_attrs->attrs,
974f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		       sizeof(indio_dev->event_interface->group.attrs[0])
97526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		       *attrcount_orig);
97626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	attrn = attrcount_orig;
97726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	/* Add all elements from the list. */
97826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	list_for_each_entry(p,
979f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron			    &indio_dev->event_interface->dev_attr_list,
98026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			    l)
981f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		indio_dev->event_interface->group.attrs[attrn++] =
98226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			&p->dev_attr.attr;
983f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->groups[indio_dev->groupcounter++] =
984f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		&indio_dev->event_interface->group;
98526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
986847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
987847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
988cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameronerror_free_setup_event_lines:
989f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	__iio_remove_event_config_attrs(indio_dev);
990f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	kfree(indio_dev->event_interface);
991847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
992847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
993847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
994847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
995847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
996f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic void iio_device_unregister_eventset(struct iio_dev *indio_dev)
997847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
998f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->event_interface == NULL)
999847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		return;
1000f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	__iio_remove_event_config_attrs(indio_dev);
1001f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	kfree(indio_dev->event_interface->group.attrs);
1002f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	kfree(indio_dev->event_interface);
1003847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1004847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1005847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void iio_dev_release(struct device *device)
1006847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1007f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	struct iio_dev *indio_dev = container_of(device, struct iio_dev, dev);
1008f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	cdev_del(&indio_dev->chrdev);
1009f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
1010f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		iio_device_unregister_trigger_consumer(indio_dev);
1011f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	iio_device_unregister_eventset(indio_dev);
1012f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	iio_device_unregister_sysfs(indio_dev);
1013847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1014847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1015847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic struct device_type iio_dev_type = {
1016847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.name = "iio_device",
1017847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.release = iio_dev_release,
1018847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron};
1019847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
10206f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameronstruct iio_dev *iio_allocate_device(int sizeof_priv)
1021847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
10226f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	struct iio_dev *dev;
10236f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	size_t alloc_size;
10246f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron
10256f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	alloc_size = sizeof(struct iio_dev);
10266f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	if (sizeof_priv) {
10276f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron		alloc_size = ALIGN(alloc_size, IIO_ALIGN);
10286f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron		alloc_size += sizeof_priv;
10296f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	}
10306f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	/* ensure 32-byte alignment of whole construct ? */
10316f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	alloc_size += IIO_ALIGN - 1;
10326f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron
10336f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	dev = kzalloc(alloc_size, GFP_KERNEL);
1034847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1035847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (dev) {
103626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		dev->dev.groups = dev->groups;
1037847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		dev->dev.type = &iio_dev_type;
10385aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron		dev->dev.bus = &iio_bus_type;
1039847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		device_initialize(&dev->dev);
1040847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		dev_set_drvdata(&dev->dev, (void *)dev);
1041847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_init(&dev->mlock);
1042a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron
1043a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron		dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL);
1044a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron		if (dev->id < 0) {
1045a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron			/* cannot use a dev_err as the name isn't available */
1046a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron			printk(KERN_ERR "Failed to get id\n");
1047a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron			kfree(dev);
1048a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron			return NULL;
1049a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron		}
1050a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron		dev_set_name(&dev->dev, "iio:device%d", dev->id);
1051847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1052847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1053847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return dev;
1054847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1055847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_allocate_device);
1056847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1057847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronvoid iio_free_device(struct iio_dev *dev)
1058847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1059a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron	if (dev) {
1060a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron		ida_simple_remove(&iio_ida, dev->id);
10611aa042783251c27a93e31929c24647729db326d4Jonathan Cameron		kfree(dev);
1062a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron	}
1063847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1064847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_free_device);
1065847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
10661aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/**
106714555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron * iio_chrdev_open() - chrdev file open for buffer access and ioctls
10681aa042783251c27a93e31929c24647729db326d4Jonathan Cameron **/
10691aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic int iio_chrdev_open(struct inode *inode, struct file *filp)
10701aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{
1071f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	struct iio_dev *indio_dev = container_of(inode->i_cdev,
10721aa042783251c27a93e31929c24647729db326d4Jonathan Cameron						struct iio_dev, chrdev);
1073f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	filp->private_data = indio_dev;
107430eb82f05dd1f12b18a0ad054401a0b5690fb3c3Jonathan Cameron
1075f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	return iio_chrdev_buffer_open(indio_dev);
10761aa042783251c27a93e31929c24647729db326d4Jonathan Cameron}
10771aa042783251c27a93e31929c24647729db326d4Jonathan Cameron
10781aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/**
107914555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron * iio_chrdev_release() - chrdev file close buffer access and ioctls
10801aa042783251c27a93e31929c24647729db326d4Jonathan Cameron **/
10811aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic int iio_chrdev_release(struct inode *inode, struct file *filp)
10821aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{
108314555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron	iio_chrdev_buffer_release(container_of(inode->i_cdev,
10841aa042783251c27a93e31929c24647729db326d4Jonathan Cameron					     struct iio_dev, chrdev));
10851aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	return 0;
10861aa042783251c27a93e31929c24647729db326d4Jonathan Cameron}
10871aa042783251c27a93e31929c24647729db326d4Jonathan Cameron
10881aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/* Somewhat of a cross file organization violation - ioctls here are actually
10891aa042783251c27a93e31929c24647729db326d4Jonathan Cameron * event related */
10901aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
10911aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{
10921aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	struct iio_dev *indio_dev = filp->private_data;
10931aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	int __user *ip = (int __user *)arg;
10941aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	int fd;
10951aa042783251c27a93e31929c24647729db326d4Jonathan Cameron
10961aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	if (cmd == IIO_GET_EVENT_FD_IOCTL) {
10971aa042783251c27a93e31929c24647729db326d4Jonathan Cameron		fd = iio_event_getfd(indio_dev);
10981aa042783251c27a93e31929c24647729db326d4Jonathan Cameron		if (copy_to_user(ip, &fd, sizeof(fd)))
10991aa042783251c27a93e31929c24647729db326d4Jonathan Cameron			return -EFAULT;
11001aa042783251c27a93e31929c24647729db326d4Jonathan Cameron		return 0;
11011aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	}
11021aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	return -EINVAL;
11031aa042783251c27a93e31929c24647729db326d4Jonathan Cameron}
11041aa042783251c27a93e31929c24647729db326d4Jonathan Cameron
110514555b14455f9acbdf0e500ae96140828a970796Jonathan Cameronstatic const struct file_operations iio_buffer_fileops = {
110614555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron	.read = iio_buffer_read_first_n_outer_addr,
11071aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	.release = iio_chrdev_release,
11081aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	.open = iio_chrdev_open,
110914555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron	.poll = iio_buffer_poll_addr,
11101aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	.owner = THIS_MODULE,
11111aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	.llseek = noop_llseek,
11121aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	.unlocked_ioctl = iio_ioctl,
11131aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	.compat_ioctl = iio_ioctl,
11141aa042783251c27a93e31929c24647729db326d4Jonathan Cameron};
11151aa042783251c27a93e31929c24647729db326d4Jonathan Cameron
1116f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronint iio_device_register(struct iio_dev *indio_dev)
1117847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1118847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret;
1119847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
11201aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	/* configure elements for the chrdev */
1121f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id);
1122847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1123f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	ret = iio_device_register_sysfs(indio_dev);
1124847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret) {
1125f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		dev_err(indio_dev->dev.parent,
1126847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			"Failed to register sysfs interfaces\n");
1127a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron		goto error_ret;
1128847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1129f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	ret = iio_device_register_eventset(indio_dev);
1130847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret) {
1131f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		dev_err(indio_dev->dev.parent,
1132c849d2538ebeef1ac26fad7a10c18b1e0fc35161Roel Van Nyen			"Failed to register event set\n");
1133847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_free_sysfs;
1134847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1135f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
1136f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		iio_device_register_trigger_consumer(indio_dev);
1137847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1138f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	ret = device_add(&indio_dev->dev);
113926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	if (ret < 0)
114026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		goto error_unreg_eventset;
1141f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	cdev_init(&indio_dev->chrdev, &iio_buffer_fileops);
1142f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->chrdev.owner = indio_dev->info->driver_module;
1143f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1);
114426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	if (ret < 0)
114526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		goto error_del_device;
1146847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
1147847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1148847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_del_device:
1149f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	device_del(&indio_dev->dev);
115026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameronerror_unreg_eventset:
1151f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	iio_device_unregister_eventset(indio_dev);
115226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameronerror_free_sysfs:
1153f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	iio_device_unregister_sysfs(indio_dev);
1154847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
1155847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
1156847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1157847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_device_register);
1158847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1159f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronvoid iio_device_unregister(struct iio_dev *indio_dev)
1160847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1161f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	device_unregister(&indio_dev->dev);
1162847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1163847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_device_unregister);
1164847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronsubsys_initcall(iio_init);
1165847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronmodule_exit(iio_exit);
1166847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1167847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
1168847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_DESCRIPTION("Industrial I/O core");
1169847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_LICENSE("GPL");
1170