industrialio-core.c revision f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0
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"
287ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron#include "chrdev.h"
299dd1cb303c18f4508abc69f5b40f423ff36a9626Jonathan Cameron#include "sysfs.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[] = {
801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_CHAN_INFO_SCALE_SHARED/2] = "scale",
811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_CHAN_INFO_OFFSET_SHARED/2] = "offset",
821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_CHAN_INFO_CALIBSCALE_SHARED/2] = "calibscale",
831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_CHAN_INFO_CALIBBIAS_SHARED/2] = "calibbias",
84eb7fea53e53ed47e82b4cc9911dd8fdc7f953de5Jonathan Cameron	[IIO_CHAN_INFO_PEAK_SHARED/2] = "peak_raw",
85eb7fea53e53ed47e82b4cc9911dd8fdc7f953de5Jonathan Cameron	[IIO_CHAN_INFO_PEAK_SCALE_SHARED/2] = "peak_scale",
867d43817803c6a1786d60834ea1a110360b098085Jonathan Cameron	[IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED/2]
877d43817803c6a1786d60834ea1a110360b098085Jonathan Cameron	= "quadrature_correction_raw",
8866dbe70437b561c241d1117dd291c11db21072fdJonathan Cameron	[IIO_CHAN_INFO_AVERAGE_RAW_SHARED/2] = "mean_raw",
891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
917ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron/**
927ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * struct iio_detected_event_list - list element for events that have occurred
937ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @list:		linked list header
947ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @ev:			the event itself
957ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron */
967ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameronstruct iio_detected_event_list {
977ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron	struct list_head		list;
987ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron	struct iio_event_data		ev;
997ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron};
1007ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron
1017ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron/**
1027ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * struct iio_event_interface - chrdev interface for an event line
1037ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @dev:		device assocated with event interface
1047ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @wait:		wait queue to allow blocking reads of events
1057ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @event_list_lock:	mutex to protect the list of detected events
1067ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @det_events:		list of detected events
1077ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @max_events:		maximum number of events before new ones are dropped
1087ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron * @current_events:	number of events in detected list
1096356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron * @flags:		file operations related flags including busy flag.
1107ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron */
1117ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameronstruct iio_event_interface {
1127ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron	wait_queue_head_t			wait;
1137ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron	struct mutex				event_list_lock;
1147ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron	struct list_head			det_events;
1157ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron	int					max_events;
1167ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron	int					current_events;
1177ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron	struct list_head dev_attr_list;
1186356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron	unsigned long flags;
11926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	struct attribute_group			group;
1207ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron};
1217ae8cf6275589a9ebb733eb5bdd093859ba1be36Jonathan Cameron
122f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronint iio_push_event(struct iio_dev *indio_dev, u64 ev_code, s64 timestamp)
123847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
124f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	struct iio_event_interface *ev_int = indio_dev->event_interface;
125847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_detected_event_list *ev;
126847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret = 0;
127847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
128847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	/* Does anyone care? */
129847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_lock(&ev_int->event_list_lock);
1306356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron	if (test_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) {
13175c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron		if (ev_int->current_events == ev_int->max_events) {
13275c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron			mutex_unlock(&ev_int->event_list_lock);
133847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			return 0;
13475c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron		}
135847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ev = kmalloc(sizeof(*ev), GFP_KERNEL);
136847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		if (ev == NULL) {
137847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			ret = -ENOMEM;
13875c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron			mutex_unlock(&ev_int->event_list_lock);
139847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			goto error_ret;
140847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		}
141847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ev->ev.id = ev_code;
142847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ev->ev.timestamp = timestamp;
143847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1443b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron		list_add_tail(&ev->list, &ev_int->det_events);
145847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ev_int->current_events++;
146847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_unlock(&ev_int->event_list_lock);
147847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		wake_up_interruptible(&ev_int->wait);
148847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	} else
149847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_unlock(&ev_int->event_list_lock);
150847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
151847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
152847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
153847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
154847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_push_event);
155847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
156847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron/* This turns up an awful lot */
157847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronssize_t iio_read_const_attr(struct device *dev,
158847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			    struct device_attribute *attr,
159847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			    char *buf)
160847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
161847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return sprintf(buf, "%s\n", to_iio_const_attr(attr)->string);
162847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
163847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_read_const_attr);
164847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
16577712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brownstatic ssize_t iio_event_chrdev_read(struct file *filep,
16677712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brown				     char __user *buf,
16777712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brown				     size_t count,
16877712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brown				     loff_t *f_ps)
169847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
170847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_event_interface *ev_int = filep->private_data;
171847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_detected_event_list *el;
172847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret;
173847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	size_t len;
1746356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron
175847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_lock(&ev_int->event_list_lock);
1763b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron	if (list_empty(&ev_int->det_events)) {
177847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		if (filep->f_flags & O_NONBLOCK) {
178847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			ret = -EAGAIN;
179847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			goto error_mutex_unlock;
180847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		}
181847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_unlock(&ev_int->event_list_lock);
182847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		/* Blocking on device; waiting for something to be there */
183847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ret = wait_event_interruptible(ev_int->wait,
184847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron					       !list_empty(&ev_int
1853b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron							   ->det_events));
186847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		if (ret)
187847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			goto error_ret;
18825985edcedea6396277003854657b5f3cb31a628Lucas De Marchi		/* Single access device so no one else can get the data */
189847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_lock(&ev_int->event_list_lock);
190847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
191847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1923b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron	el = list_first_entry(&ev_int->det_events,
193847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			      struct iio_detected_event_list,
194847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			      list);
195847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	len = sizeof el->ev;
196847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (copy_to_user(buf, &(el->ev), len)) {
197847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ret = -EFAULT;
198847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_mutex_unlock;
199847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
200847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	list_del(&el->list);
201847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->current_events--;
202847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_unlock(&ev_int->event_list_lock);
203847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	kfree(el);
204847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
205847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return len;
206847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
207847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_mutex_unlock:
208847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_unlock(&ev_int->event_list_lock);
209847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
210847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
211847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
212847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
213847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
21477712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brownstatic int iio_event_chrdev_release(struct inode *inode, struct file *filep)
215847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
2168e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron	struct iio_event_interface *ev_int = filep->private_data;
217847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_detected_event_list *el, *t;
2186356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron
219847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_lock(&ev_int->event_list_lock);
2206356463cf4627f599547f0698853ef419b2d2f1dJonathan Cameron	clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
221847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	/*
222847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	 * In order to maintain a clean state for reopening,
223847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	 * clear out any awaiting events. The mask will prevent
224847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	 * any new __iio_push_event calls running.
225847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	 */
2263b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron	list_for_each_entry_safe(el, t, &ev_int->det_events, list) {
227847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		list_del(&el->list);
228847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		kfree(el);
229847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
2308e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron	ev_int->current_events = 0;
231847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_unlock(&ev_int->event_list_lock);
232847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
233847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
234847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
235847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
236847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic const struct file_operations iio_event_chrdev_fileops = {
237847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.read =  iio_event_chrdev_read,
238847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.release = iio_event_chrdev_release,
239847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.owner = THIS_MODULE,
2406038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann	.llseek = noop_llseek,
241847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron};
242847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
2431aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic int iio_event_getfd(struct iio_dev *indio_dev)
2448e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron{
2455aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron	if (indio_dev->event_interface == NULL)
2468e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron		return -ENODEV;
2478e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron
2485aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron	mutex_lock(&indio_dev->event_interface->event_list_lock);
2498e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron	if (test_and_set_bit(IIO_BUSY_BIT_POS,
2505aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron			     &indio_dev->event_interface->flags)) {
2515aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron		mutex_unlock(&indio_dev->event_interface->event_list_lock);
2528e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron		return -EBUSY;
2538e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron	}
2545aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron	mutex_unlock(&indio_dev->event_interface->event_list_lock);
2558e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron	return anon_inode_getfd("iio:event",
2568e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron				&iio_event_chrdev_fileops,
2575aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron				indio_dev->event_interface, O_RDONLY);
2588e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron}
2598e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron
260847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic int __init iio_init(void)
261847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
262847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret;
263847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
2645aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	/* Register sysfs bus */
2655aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	ret  = bus_register(&iio_bus_type);
266847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret < 0) {
267847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		printk(KERN_ERR
2685aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron		       "%s could not register bus type\n",
269847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			__FILE__);
270847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_nothing;
271847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
272847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
2739aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio");
2749aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	if (ret < 0) {
2759aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron		printk(KERN_ERR "%s: failed to allocate char dev region\n",
2769aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron		       __FILE__);
2775aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron		goto error_unregister_bus_type;
2789aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	}
279847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
280847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
281847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
2825aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameronerror_unregister_bus_type:
2835aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	bus_unregister(&iio_bus_type);
284847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_nothing:
285847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
286847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
287847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
288847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void __exit iio_exit(void)
289847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
2909aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	if (iio_devt)
2919aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron		unregister_chrdev_region(iio_devt, IIO_DEV_MAX);
2925aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	bus_unregister(&iio_bus_type);
293847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
294847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
2951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_read_channel_info(struct device *dev,
2961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     struct device_attribute *attr,
2971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     char *buf)
298847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
2991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
3001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
3011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int val, val2;
3026fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	int ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
3036fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron					    &val, &val2, this_attr->address);
3041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
3051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret < 0)
3061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
307847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
3081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret == IIO_VAL_INT)
3091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return sprintf(buf, "%d\n", val);
3101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	else if (ret == IIO_VAL_INT_PLUS_MICRO) {
3111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (val2 < 0)
3121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			return sprintf(buf, "-%d.%06u\n", val, -val2);
3131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		else
3141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			return sprintf(buf, "%d.%06u\n", val, val2);
31571646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich	} else if (ret == IIO_VAL_INT_PLUS_NANO) {
31671646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich		if (val2 < 0)
31771646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich			return sprintf(buf, "-%d.%09u\n", val, -val2);
31871646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich		else
31971646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich			return sprintf(buf, "%d.%09u\n", val, val2);
3201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	} else
3211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return 0;
3221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
3231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
3241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_write_channel_info(struct device *dev,
3251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      struct device_attribute *attr,
3261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      const char *buf,
3271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      size_t len)
3281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
3291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
3301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
3315c04af04835269c194662be63fe168893fad667fMichael Hennerich	int ret, integer = 0, fract = 0, fract_mult = 100000;
3321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	bool integer_part = true, negative = false;
3331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
3341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	/* Assumes decimal - precision based on number of digits */
3356fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	if (!indio_dev->info->write_raw)
3361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return -EINVAL;
3375c04af04835269c194662be63fe168893fad667fMichael Hennerich
3385c04af04835269c194662be63fe168893fad667fMichael Hennerich	if (indio_dev->info->write_raw_get_fmt)
3395c04af04835269c194662be63fe168893fad667fMichael Hennerich		switch (indio_dev->info->write_raw_get_fmt(indio_dev,
3405c04af04835269c194662be63fe168893fad667fMichael Hennerich			this_attr->c, this_attr->address)) {
3415c04af04835269c194662be63fe168893fad667fMichael Hennerich		case IIO_VAL_INT_PLUS_MICRO:
3425c04af04835269c194662be63fe168893fad667fMichael Hennerich			fract_mult = 100000;
3435c04af04835269c194662be63fe168893fad667fMichael Hennerich			break;
3445c04af04835269c194662be63fe168893fad667fMichael Hennerich		case IIO_VAL_INT_PLUS_NANO:
3455c04af04835269c194662be63fe168893fad667fMichael Hennerich			fract_mult = 100000000;
3465c04af04835269c194662be63fe168893fad667fMichael Hennerich			break;
3475c04af04835269c194662be63fe168893fad667fMichael Hennerich		default:
3485c04af04835269c194662be63fe168893fad667fMichael Hennerich			return -EINVAL;
3495c04af04835269c194662be63fe168893fad667fMichael Hennerich		}
3505c04af04835269c194662be63fe168893fad667fMichael Hennerich
3511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (buf[0] == '-') {
3521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		negative = true;
3531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		buf++;
3541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
3555c04af04835269c194662be63fe168893fad667fMichael Hennerich
3561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	while (*buf) {
3571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if ('0' <= *buf && *buf <= '9') {
3581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (integer_part)
3591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				integer = integer*10 + *buf - '0';
3601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			else {
3615c04af04835269c194662be63fe168893fad667fMichael Hennerich				fract += fract_mult*(*buf - '0');
3625c04af04835269c194662be63fe168893fad667fMichael Hennerich				if (fract_mult == 1)
3631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					break;
3645c04af04835269c194662be63fe168893fad667fMichael Hennerich				fract_mult /= 10;
3651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			}
3661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		} else if (*buf == '\n') {
3671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (*(buf + 1) == '\0')
3681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				break;
3691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			else
3701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				return -EINVAL;
3711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		} else if (*buf == '.') {
3721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			integer_part = false;
3731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		} else {
3741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			return -EINVAL;
3751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
3761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		buf++;
3771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
3781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (negative) {
3791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (integer)
3801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			integer = -integer;
3811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		else
3825c04af04835269c194662be63fe168893fad667fMichael Hennerich			fract = -fract;
3831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
3841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
3856fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	ret = indio_dev->info->write_raw(indio_dev, this_attr->c,
3865c04af04835269c194662be63fe168893fad667fMichael Hennerich					 integer, fract, this_attr->address);
3871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
3881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
3891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
3901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return len;
3911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
3921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
393df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameronstatic
3941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronint __iio_device_attr_init(struct device_attribute *dev_attr,
3951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   const char *postfix,
3961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct iio_chan_spec const *chan,
3971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*readfunc)(struct device *dev,
3981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       struct device_attribute *attr,
3991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       char *buf),
4001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*writefunc)(struct device *dev,
4011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						struct device_attribute *attr,
4021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						const char *buf,
4031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						size_t len),
4041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   bool generic)
4051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
4061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret;
4071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	char *name_format, *full_postfix;
4081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	sysfs_attr_init(&dev_attr->attr);
4091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
410ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	/* Build up postfix of <extend_name>_<modifier>_postfix */
411ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	if (chan->modified) {
412ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		if (chan->extend_name)
413ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s",
414ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 iio_modifier_names[chan
415ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron								    ->channel2],
416ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 chan->extend_name,
417ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 postfix);
418ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else
419ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			full_postfix = kasprintf(GFP_KERNEL, "%s_%s",
420ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 iio_modifier_names[chan
421ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron								    ->channel2],
422ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 postfix);
423ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	} else {
424ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		if (chan->extend_name == NULL)
425ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			full_postfix = kstrdup(postfix, GFP_KERNEL);
426ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else
427ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			full_postfix = kasprintf(GFP_KERNEL,
428ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 "%s_%s",
429ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 chan->extend_name,
430ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron						 postfix);
431ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	}
432ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	if (full_postfix == NULL) {
433ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		ret = -ENOMEM;
434ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		goto error_ret;
435ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	}
4361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
437ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	if (chan->differential) { /* Differential  can not have modifier */
438ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		if (generic)
439ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			name_format
440ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron				= kasprintf(GFP_KERNEL, "%s_%s-%s_%s",
441ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_direction[chan->output],
442ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
443ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
444ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    full_postfix);
445ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else if (chan->indexed)
446ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			name_format
447ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron				= kasprintf(GFP_KERNEL, "%s_%s%d-%s%d_%s",
448ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_direction[chan->output],
449ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
450ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    chan->channel,
451ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
452ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    chan->channel2,
453ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    full_postfix);
454ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else {
455ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			WARN_ON("Differential channels must be indexed\n");
456ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			ret = -EINVAL;
457ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			goto error_free_full_postfix;
458ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		}
459ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	} else { /* Single ended */
460ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		if (generic)
461ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			name_format
462ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron				= kasprintf(GFP_KERNEL, "%s_%s_%s",
463ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_direction[chan->output],
464ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
465ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    full_postfix);
466ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else if (chan->indexed)
467ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			name_format
468ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron				= kasprintf(GFP_KERNEL, "%s_%s%d_%s",
469ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_direction[chan->output],
470ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
471ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    chan->channel,
472ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    full_postfix);
473ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else
474ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			name_format
475ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron				= kasprintf(GFP_KERNEL, "%s_%s_%s",
476ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_direction[chan->output],
477ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    iio_chan_type_name_spec[chan->type],
478ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					    full_postfix);
479ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron	}
4801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (name_format == NULL) {
4811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = -ENOMEM;
4821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_free_full_postfix;
4831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
4841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	dev_attr->attr.name = kasprintf(GFP_KERNEL,
4851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					name_format,
4861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					chan->channel,
4871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					chan->channel2);
4881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (dev_attr->attr.name == NULL) {
4891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = -ENOMEM;
4901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_free_name_format;
4911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
4921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (readfunc) {
4941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->attr.mode |= S_IRUGO;
4951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->show = readfunc;
4961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
4971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (writefunc) {
4991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->attr.mode |= S_IWUSR;
5001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->store = writefunc;
5011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
5021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(name_format);
5031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(full_postfix);
5041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return 0;
5061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_free_name_format:
5081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(name_format);
5091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_free_full_postfix:
5101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(full_postfix);
5111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
5121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
5131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
5141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
515df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameronstatic void __iio_device_attr_deinit(struct device_attribute *dev_attr)
5161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
5171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(dev_attr->attr.name);
5181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
5191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronint __iio_add_chan_devattr(const char *postfix,
5211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct iio_chan_spec const *chan,
5221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*readfunc)(struct device *dev,
5231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       struct device_attribute *attr,
5241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       char *buf),
5251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*writefunc)(struct device *dev,
5261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						struct device_attribute *attr,
5271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						const char *buf,
5281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						size_t len),
529e614a54b296185b266b4bd91193e08a5fbd32422Jonathan Cameron			   u64 mask,
5301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   bool generic,
5311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct device *dev,
5321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct list_head *attr_list)
5331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
5341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret;
5351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *iio_attr, *t;
5361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	iio_attr = kzalloc(sizeof *iio_attr, GFP_KERNEL);
5381d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (iio_attr == NULL) {
5391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = -ENOMEM;
5401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_ret;
5411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
5421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	ret = __iio_device_attr_init(&iio_attr->dev_attr,
5431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     postfix, chan,
5441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     readfunc, writefunc, generic);
5451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
5461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_iio_dev_attr_free;
5471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	iio_attr->c = chan;
5481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	iio_attr->address = mask;
5491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_for_each_entry(t, attr_list, l)
5501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (strcmp(t->dev_attr.attr.name,
5511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   iio_attr->dev_attr.attr.name) == 0) {
5521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (!generic)
5531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				dev_err(dev, "tried to double register : %s\n",
5541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					t->dev_attr.attr.name);
5551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = -EBUSY;
5561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_device_attr_deinit;
5571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
5581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_add(&iio_attr->l, attr_list);
5591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return 0;
5611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_device_attr_deinit:
5631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	__iio_device_attr_deinit(&iio_attr->dev_attr);
5641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_iio_dev_attr_free:
5651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(iio_attr);
5661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
5671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
5681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
5691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
570f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
5711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					struct iio_chan_spec const *chan)
5721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
57326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	int ret, i, attrcount = 0;
5741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (chan->channel < 0)
5761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return 0;
5771e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron
5781e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron	ret = __iio_add_chan_devattr(iio_data_type_name[chan->processed_val],
57926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron				     chan,
5801e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron				     &iio_read_channel_info,
581c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron				     (chan->output ?
5821e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron				      &iio_write_channel_info : NULL),
5831e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron				     0,
5841e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron				     0,
585f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron				     &indio_dev->dev,
586f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron				     &indio_dev->channel_attr_list);
5871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
5881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_ret;
58926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	attrcount++;
5901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) {
5921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2],
59326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron					     chan,
5941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &iio_read_channel_info,
5951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &iio_write_channel_info,
5961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     (1 << i),
5971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     !(i%2),
598f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron					     &indio_dev->dev,
599f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron					     &indio_dev->channel_attr_list);
6001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret == -EBUSY && (i%2 == 0)) {
6011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = 0;
6021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			continue;
6031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
6041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret < 0)
6051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
60626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		attrcount++;
6071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
60826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	ret = attrcount;
6091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
6101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
6111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
6121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
613f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic void iio_device_remove_and_free_read_attr(struct iio_dev *indio_dev,
6141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						 struct iio_dev_attr *p)
6151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
6161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(p->dev_attr.attr.name);
6171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(p);
6181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
6191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6201b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameronstatic ssize_t iio_show_dev_name(struct device *dev,
6211b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron				 struct device_attribute *attr,
6221b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron				 char *buf)
6231b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron{
6241b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
6251b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron	return sprintf(buf, "%s\n", indio_dev->name);
6261b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron}
6271b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron
6281b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameronstatic DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
6291b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron
630f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_register_sysfs(struct iio_dev *indio_dev)
6311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
63226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	int i, ret = 0, attrcount, attrn, attrcount_orig = 0;
6331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *p, *n;
63426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	struct attribute **attr;
6351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
63626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	/* First count elements in any existing group */
637f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->info->attrs) {
638f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		attr = indio_dev->info->attrs->attrs;
63926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		while (*attr++ != NULL)
64026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			attrcount_orig++;
641847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
64226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	attrcount = attrcount_orig;
6431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	/*
6441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	 * New channel registration method - relies on the fact a group does
6451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	 *  not need to be initialized if it is name is NULL.
6461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	 */
647f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	INIT_LIST_HEAD(&indio_dev->channel_attr_list);
648f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->channels)
649f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		for (i = 0; i < indio_dev->num_channels; i++) {
650f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron			ret = iio_device_add_channel_sysfs(indio_dev,
651f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron							   &indio_dev
6521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron							   ->channels[i]);
6531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (ret < 0)
6541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				goto error_clear_attrs;
65526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			attrcount += ret;
6561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
65726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
658f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->name)
65926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		attrcount++;
66026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
661f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->chan_attr_group.attrs
662f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		= kzalloc(sizeof(indio_dev->chan_attr_group.attrs[0])*
66326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			  (attrcount + 1),
66426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			  GFP_KERNEL);
665f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->chan_attr_group.attrs == NULL) {
66626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		ret = -ENOMEM;
66726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		goto error_clear_attrs;
6681b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron	}
66926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	/* Copy across original attributes */
670f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->info->attrs)
671f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		memcpy(indio_dev->chan_attr_group.attrs,
672f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		       indio_dev->info->attrs->attrs,
673f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		       sizeof(indio_dev->chan_attr_group.attrs[0])
67426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		       *attrcount_orig);
67526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	attrn = attrcount_orig;
67626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	/* Add all elements from the list. */
677f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	list_for_each_entry(p, &indio_dev->channel_attr_list, l)
678f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr;
679f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->name)
680f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr;
68126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
682f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->groups[indio_dev->groupcounter++] =
683f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		&indio_dev->chan_attr_group;
68426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
6851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return 0;
6861b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron
6871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_clear_attrs:
6881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_for_each_entry_safe(p, n,
689f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron				 &indio_dev->channel_attr_list, l) {
6901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		list_del(&p->l);
691f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		iio_device_remove_and_free_read_attr(indio_dev, p);
6921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
6931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
69426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	return ret;
695847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
696847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
697f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic void iio_device_unregister_sysfs(struct iio_dev *indio_dev)
698847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
6991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *p, *n;
70126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
702f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	list_for_each_entry_safe(p, n, &indio_dev->channel_attr_list, l) {
7031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		list_del(&p->l);
704f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		iio_device_remove_and_free_read_attr(indio_dev, p);
7051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
706f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	kfree(indio_dev->chan_attr_group.attrs);
707847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
708847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
7091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_ev_type_text[] = {
7101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_TYPE_THRESH] = "thresh",
7111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_TYPE_MAG] = "mag",
7128ce7375be7036d6e536b6341ec83e5db849cda6eJonathan Cameron	[IIO_EV_TYPE_ROC] = "roc",
7138ce7375be7036d6e536b6341ec83e5db849cda6eJonathan Cameron	[IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive",
7148ce7375be7036d6e536b6341ec83e5db849cda6eJonathan Cameron	[IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive",
7151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
7161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_ev_dir_text[] = {
7181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_DIR_EITHER] = "either",
7191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_DIR_RISING] = "rising",
7201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_DIR_FALLING] = "falling"
7211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
7221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_state_store(struct device *dev,
7241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  struct device_attribute *attr,
7251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  const char *buf,
7261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  size_t len)
7271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
7281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
729aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
7301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret;
731c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	bool val;
732c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron
733c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	ret = strtobool(buf, &val);
734c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	if (ret < 0)
735c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron		return ret;
7361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7376fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	ret = indio_dev->info->write_event_config(indio_dev,
7386fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						  this_attr->address,
7396fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						  val);
7401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return (ret < 0) ? ret : len;
7411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
7421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_state_show(struct device *dev,
7441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 struct device_attribute *attr,
7451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 char *buf)
7461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
7471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
748aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
7496fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	int val = indio_dev->info->read_event_config(indio_dev,
7506fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						     this_attr->address);
7511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (val < 0)
7531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return val;
7541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	else
7551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return sprintf(buf, "%d\n", val);
7561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
7571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_value_show(struct device *dev,
7591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 struct device_attribute *attr,
7601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 char *buf)
7611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
7621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
7631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
7641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int val, ret;
7651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7666fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	ret = indio_dev->info->read_event_value(indio_dev,
7676fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						this_attr->address, &val);
7681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret < 0)
7691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
7701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return sprintf(buf, "%d\n", val);
7721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
7731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_value_store(struct device *dev,
7751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  struct device_attribute *attr,
7761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  const char *buf,
7771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  size_t len)
7781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
7791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
7801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
7811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	unsigned long val;
7821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret;
7831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	ret = strict_strtoul(buf, 10, &val);
7851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
7861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
7871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7886fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	ret = indio_dev->info->write_event_value(indio_dev, this_attr->address,
7896fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						 val);
7901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret < 0)
7911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
7921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return len;
7941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
7951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
796f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_add_event_sysfs(struct iio_dev *indio_dev,
7971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      struct iio_chan_spec const *chan)
7981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
799e614a54b296185b266b4bd91193e08a5fbd32422Jonathan Cameron	int ret = 0, i, attrcount = 0;
800e614a54b296185b266b4bd91193e08a5fbd32422Jonathan Cameron	u64 mask = 0;
8011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	char *postfix;
8021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (!chan->event_mask)
8031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return 0;
8041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	for_each_set_bit(i, &chan->event_mask, sizeof(chan->event_mask)*8) {
8061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		postfix = kasprintf(GFP_KERNEL, "%s_%s_en",
807c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron				    iio_ev_type_text[i/IIO_EV_DIR_MAX],
808c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron				    iio_ev_dir_text[i%IIO_EV_DIR_MAX]);
8091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (postfix == NULL) {
8101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = -ENOMEM;
8111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
8121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
813330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron		if (chan->modified)
8141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel,
815c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron						  i/IIO_EV_DIR_MAX,
816c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron						  i%IIO_EV_DIR_MAX);
817ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron		else if (chan->differential)
818ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron			mask = IIO_EVENT_CODE(chan->type,
819ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					      0, 0,
820ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					      i%IIO_EV_DIR_MAX,
821ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					      i/IIO_EV_DIR_MAX,
822ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					      0,
823ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					      chan->channel,
824ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron					      chan->channel2);
825330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron		else
826330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron			mask = IIO_UNMOD_EVENT_CODE(chan->type,
827330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron						    chan->channel,
828c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron						    i/IIO_EV_DIR_MAX,
829c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron						    i%IIO_EV_DIR_MAX);
830330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron
831aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron		ret = __iio_add_chan_devattr(postfix,
832aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     chan,
833aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     &iio_ev_state_show,
834aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     iio_ev_state_store,
835aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     mask,
836aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     0,
837f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron					     &indio_dev->dev,
838f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron					     &indio_dev->event_interface->
839aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     dev_attr_list);
8401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		kfree(postfix);
8411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret)
8421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
84326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		attrcount++;
8441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		postfix = kasprintf(GFP_KERNEL, "%s_%s_value",
845c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron				    iio_ev_type_text[i/IIO_EV_DIR_MAX],
846c04ea8ae99d71182b525cb8e4d48dc2fde0dd0eeJonathan Cameron				    iio_ev_dir_text[i%IIO_EV_DIR_MAX]);
8471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (postfix == NULL) {
8481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = -ENOMEM;
8491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
8501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
85126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		ret = __iio_add_chan_devattr(postfix, chan,
8521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     iio_ev_value_show,
8531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     iio_ev_value_store,
8541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     mask,
8551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     0,
856f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron					     &indio_dev->dev,
857f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron					     &indio_dev->event_interface->
8585aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron					     dev_attr_list);
8591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		kfree(postfix);
8601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret)
8611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
86226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		attrcount++;
8631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
86426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	ret = attrcount;
8651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
8661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
8671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
8681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
869f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic inline void __iio_remove_event_config_attrs(struct iio_dev *indio_dev)
8701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
8711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *p, *n;
8721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_for_each_entry_safe(p, n,
873f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron				 &indio_dev->event_interface->
8741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 dev_attr_list, l) {
8751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		kfree(p->dev_attr.attr.name);
8761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		kfree(p);
8771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
8781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
8791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
880f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic inline int __iio_add_event_config_attrs(struct iio_dev *indio_dev)
881847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
88226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	int j, ret, attrcount = 0;
8831e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron
884f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	INIT_LIST_HEAD(&indio_dev->event_interface->dev_attr_list);
8851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	/* Dynically created from the channels array */
886f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	for (j = 0; j < indio_dev->num_channels; j++) {
887f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		ret = iio_device_add_event_sysfs(indio_dev,
888f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron						 &indio_dev->channels[j]);
88926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		if (ret < 0)
8905aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron			goto error_clear_attrs;
89126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		attrcount += ret;
8921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
89326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	return attrcount;
894847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
8951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_clear_attrs:
896f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	__iio_remove_event_config_attrs(indio_dev);
897847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
898847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
899847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
900847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
901f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic bool iio_check_for_dynamic_events(struct iio_dev *indio_dev)
9025aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron{
9035aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron	int j;
9041e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron
905f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	for (j = 0; j < indio_dev->num_channels; j++)
906f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		if (indio_dev->channels[j].event_mask != 0)
9075aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron			return true;
9085aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron	return false;
9095aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron}
9105aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron
9111e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameronstatic void iio_setup_ev_int(struct iio_event_interface *ev_int)
9121e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron{
9131e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron	mutex_init(&ev_int->event_list_lock);
9141e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron	/* discussion point - make this variable? */
9151e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron	ev_int->max_events = 10;
9161e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron	ev_int->current_events = 0;
9171e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron	INIT_LIST_HEAD(&ev_int->det_events);
9181e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron	init_waitqueue_head(&ev_int->wait);
9191e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron}
9201e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron
92126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameronstatic const char *iio_event_group_name = "events";
922f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_register_eventset(struct iio_dev *indio_dev)
923847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
92426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	struct iio_dev_attr *p;
92526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	int ret = 0, attrcount_orig = 0, attrcount, attrn;
92626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	struct attribute **attr;
927847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
928f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (!(indio_dev->info->event_attrs ||
929f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	      iio_check_for_dynamic_events(indio_dev)))
930847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		return 0;
931847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
932f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->event_interface =
9335aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron		kzalloc(sizeof(struct iio_event_interface), GFP_KERNEL);
934f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->event_interface == NULL) {
935847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ret = -ENOMEM;
936847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_ret;
937847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
938847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
939f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	iio_setup_ev_int(indio_dev->event_interface);
940f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->info->event_attrs != NULL) {
941f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		attr = indio_dev->info->event_attrs->attrs;
94226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		while (*attr++ != NULL)
94326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			attrcount_orig++;
9445aa9618896e0ba49b444731f9fafa7f7c18a13abJonathan Cameron	}
94526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	attrcount = attrcount_orig;
946f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->channels) {
947f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		ret = __iio_add_event_config_attrs(indio_dev);
94826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		if (ret < 0)
949cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron			goto error_free_setup_event_lines;
95026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		attrcount += ret;
951847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
952847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
953f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->event_interface->group.name = iio_event_group_name;
954f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->event_interface->group.attrs =
955f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		kzalloc(sizeof(indio_dev->event_interface->group.attrs[0])
95626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			*(attrcount + 1),
95726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			GFP_KERNEL);
958f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->event_interface->group.attrs == NULL) {
95926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		ret = -ENOMEM;
96026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		goto error_free_setup_event_lines;
96126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	}
962f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->info->event_attrs)
963f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		memcpy(indio_dev->event_interface->group.attrs,
964f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		       indio_dev->info->event_attrs->attrs,
965f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		       sizeof(indio_dev->event_interface->group.attrs[0])
96626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		       *attrcount_orig);
96726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	attrn = attrcount_orig;
96826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	/* Add all elements from the list. */
96926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	list_for_each_entry(p,
970f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron			    &indio_dev->event_interface->dev_attr_list,
97126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			    l)
972f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		indio_dev->event_interface->group.attrs[attrn++] =
97326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron			&p->dev_attr.attr;
97426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
975f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->groups[indio_dev->groupcounter++] =
976f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		&indio_dev->event_interface->group;
97726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron
978847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
979847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
980cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameronerror_free_setup_event_lines:
981f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	__iio_remove_event_config_attrs(indio_dev);
982f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	kfree(indio_dev->event_interface);
983847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
984847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
985847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
986847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
987847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
988f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic void iio_device_unregister_eventset(struct iio_dev *indio_dev)
989847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
990f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->event_interface == NULL)
991847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		return;
992f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	__iio_remove_event_config_attrs(indio_dev);
993f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	kfree(indio_dev->event_interface->group.attrs);
994f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	kfree(indio_dev->event_interface);
995847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
996847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
997847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void iio_dev_release(struct device *device)
998847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
999f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	struct iio_dev *indio_dev = container_of(device, struct iio_dev, dev);
1000f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	cdev_del(&indio_dev->chrdev);
1001f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
1002f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		iio_device_unregister_trigger_consumer(indio_dev);
1003f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	iio_device_unregister_eventset(indio_dev);
1004f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	iio_device_unregister_sysfs(indio_dev);
1005f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	ida_simple_remove(&iio_ida, indio_dev->id);
1006f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	kfree(indio_dev);
1007847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1008847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1009847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic struct device_type iio_dev_type = {
1010847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.name = "iio_device",
1011847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.release = iio_dev_release,
1012847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron};
1013847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
10146f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameronstruct iio_dev *iio_allocate_device(int sizeof_priv)
1015847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
10166f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	struct iio_dev *dev;
10176f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	size_t alloc_size;
10186f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron
10196f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	alloc_size = sizeof(struct iio_dev);
10206f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	if (sizeof_priv) {
10216f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron		alloc_size = ALIGN(alloc_size, IIO_ALIGN);
10226f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron		alloc_size += sizeof_priv;
10236f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	}
10246f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	/* ensure 32-byte alignment of whole construct ? */
10256f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	alloc_size += IIO_ALIGN - 1;
10266f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron
10276f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	dev = kzalloc(alloc_size, GFP_KERNEL);
1028847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1029847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (dev) {
103026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		dev->dev.groups = dev->groups;
1031847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		dev->dev.type = &iio_dev_type;
10325aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron		dev->dev.bus = &iio_bus_type;
1033847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		device_initialize(&dev->dev);
1034847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		dev_set_drvdata(&dev->dev, (void *)dev);
1035847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_init(&dev->mlock);
1036a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron
1037a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron		dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL);
1038a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron		if (dev->id < 0) {
1039a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron			/* cannot use a dev_err as the name isn't available */
1040a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron			printk(KERN_ERR "Failed to get id\n");
1041a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron			kfree(dev);
1042a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron			return NULL;
1043a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron		}
1044a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron		dev_set_name(&dev->dev, "iio:device%d", dev->id);
1045847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1046847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1047847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return dev;
1048847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1049847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_allocate_device);
1050847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1051847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronvoid iio_free_device(struct iio_dev *dev)
1052847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1053a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron	if (dev) {
1054a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron		ida_simple_remove(&iio_ida, dev->id);
10551aa042783251c27a93e31929c24647729db326d4Jonathan Cameron		kfree(dev);
1056a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron	}
1057847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1058847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_free_device);
1059847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
10601aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/**
106114555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron * iio_chrdev_open() - chrdev file open for buffer access and ioctls
10621aa042783251c27a93e31929c24647729db326d4Jonathan Cameron **/
10631aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic int iio_chrdev_open(struct inode *inode, struct file *filp)
10641aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{
1065f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	struct iio_dev *indio_dev = container_of(inode->i_cdev,
10661aa042783251c27a93e31929c24647729db326d4Jonathan Cameron						struct iio_dev, chrdev);
1067f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	filp->private_data = indio_dev;
106830eb82f05dd1f12b18a0ad054401a0b5690fb3c3Jonathan Cameron
1069f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	return iio_chrdev_buffer_open(indio_dev);
10701aa042783251c27a93e31929c24647729db326d4Jonathan Cameron}
10711aa042783251c27a93e31929c24647729db326d4Jonathan Cameron
10721aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/**
107314555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron * iio_chrdev_release() - chrdev file close buffer access and ioctls
10741aa042783251c27a93e31929c24647729db326d4Jonathan Cameron **/
10751aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic int iio_chrdev_release(struct inode *inode, struct file *filp)
10761aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{
107714555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron	iio_chrdev_buffer_release(container_of(inode->i_cdev,
10781aa042783251c27a93e31929c24647729db326d4Jonathan Cameron					     struct iio_dev, chrdev));
10791aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	return 0;
10801aa042783251c27a93e31929c24647729db326d4Jonathan Cameron}
10811aa042783251c27a93e31929c24647729db326d4Jonathan Cameron
10821aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/* Somewhat of a cross file organization violation - ioctls here are actually
10831aa042783251c27a93e31929c24647729db326d4Jonathan Cameron * event related */
10841aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
10851aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{
10861aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	struct iio_dev *indio_dev = filp->private_data;
10871aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	int __user *ip = (int __user *)arg;
10881aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	int fd;
10891aa042783251c27a93e31929c24647729db326d4Jonathan Cameron
10901aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	if (cmd == IIO_GET_EVENT_FD_IOCTL) {
10911aa042783251c27a93e31929c24647729db326d4Jonathan Cameron		fd = iio_event_getfd(indio_dev);
10921aa042783251c27a93e31929c24647729db326d4Jonathan Cameron		if (copy_to_user(ip, &fd, sizeof(fd)))
10931aa042783251c27a93e31929c24647729db326d4Jonathan Cameron			return -EFAULT;
10941aa042783251c27a93e31929c24647729db326d4Jonathan Cameron		return 0;
10951aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	}
10961aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	return -EINVAL;
10971aa042783251c27a93e31929c24647729db326d4Jonathan Cameron}
10981aa042783251c27a93e31929c24647729db326d4Jonathan Cameron
109914555b14455f9acbdf0e500ae96140828a970796Jonathan Cameronstatic const struct file_operations iio_buffer_fileops = {
110014555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron	.read = iio_buffer_read_first_n_outer_addr,
11011aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	.release = iio_chrdev_release,
11021aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	.open = iio_chrdev_open,
110314555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron	.poll = iio_buffer_poll_addr,
11041aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	.owner = THIS_MODULE,
11051aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	.llseek = noop_llseek,
11061aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	.unlocked_ioctl = iio_ioctl,
11071aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	.compat_ioctl = iio_ioctl,
11081aa042783251c27a93e31929c24647729db326d4Jonathan Cameron};
11091aa042783251c27a93e31929c24647729db326d4Jonathan Cameron
1110f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronint iio_device_register(struct iio_dev *indio_dev)
1111847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1112847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret;
1113847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
11141aa042783251c27a93e31929c24647729db326d4Jonathan Cameron	/* configure elements for the chrdev */
1115f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id);
1116847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1117f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	ret = iio_device_register_sysfs(indio_dev);
1118847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret) {
1119f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		dev_err(indio_dev->dev.parent,
1120847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			"Failed to register sysfs interfaces\n");
1121a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron		goto error_ret;
1122847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1123f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	ret = iio_device_register_eventset(indio_dev);
1124847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret) {
1125f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		dev_err(indio_dev->dev.parent,
1126c849d2538ebeef1ac26fad7a10c18b1e0fc35161Roel Van Nyen			"Failed to register event set\n");
1127847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_free_sysfs;
1128847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1129f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
1130f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron		iio_device_register_trigger_consumer(indio_dev);
1131847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1132f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	ret = device_add(&indio_dev->dev);
113326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	if (ret < 0)
113426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		goto error_unreg_eventset;
1135f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	cdev_init(&indio_dev->chrdev, &iio_buffer_fileops);
1136f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	indio_dev->chrdev.owner = indio_dev->info->driver_module;
1137f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1);
113826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron	if (ret < 0)
113926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron		goto error_del_device;
1140847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
1141847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1142847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_del_device:
1143f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	device_del(&indio_dev->dev);
114426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameronerror_unreg_eventset:
1145f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	iio_device_unregister_eventset(indio_dev);
114626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameronerror_free_sysfs:
1147f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	iio_device_unregister_sysfs(indio_dev);
1148847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
1149847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
1150847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1151847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_device_register);
1152847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1153f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronvoid iio_device_unregister(struct iio_dev *indio_dev)
1154847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1155f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron	device_unregister(&indio_dev->dev);
1156847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1157847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_device_unregister);
1158847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronsubsys_initcall(iio_init);
1159847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronmodule_exit(iio_exit);
1160847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1161847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
1162847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_DESCRIPTION("Industrial I/O core");
1163847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_LICENSE("GPL");
1164