industrialio-core.c revision 71646e2c7ae4edb92dfa89eccb354d81be1cbbbd
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>
24847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include "iio.h"
25847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include "trigger_consumer.h"
26847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
27847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#define IIO_ID_PREFIX "device"
28847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#define IIO_ID_FORMAT IIO_ID_PREFIX "%d"
29847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
30847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron/* IDR to assign each registered device a unique id*/
31b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameronstatic DEFINE_IDA(iio_ida);
32847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron/* IDR to allocate character device minor numbers */
33b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameronstatic DEFINE_IDA(iio_chrdev_ida);
34847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron/* Lock used to protect both of the above */
35b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameronstatic DEFINE_SPINLOCK(iio_ida_lock);
36847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
37847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Camerondev_t iio_devt;
38847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_devt);
39847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
40847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#define IIO_DEV_MAX 256
415aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameronstruct bus_type iio_bus_type = {
42847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.name = "iio",
43847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron};
445aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan CameronEXPORT_SYMBOL(iio_bus_type);
45847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_chan_type_name_spec_shared[] = {
471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_TIMESTAMP] = "timestamp",
481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_ACCEL] = "accel",
491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_IN] = "in",
50faf290e867fd51e227165d0bef113b022520a58fMichael Hennerich	[IIO_CURRENT] = "current",
51faf290e867fd51e227165d0bef113b022520a58fMichael Hennerich	[IIO_POWER] = "power",
521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_IN_DIFF] = "in-in",
531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_GYRO] = "gyro",
541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_TEMP] = "temp",
551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_MAGN] = "magn",
561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_INCLI] = "incli",
571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_ROT] = "rot",
581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_INTENSITY] = "intensity",
591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_LIGHT] = "illuminance",
601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_ANGL] = "angl",
611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_chan_type_name_spec_complex[] = {
641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_IN_DIFF] = "in%d-in%d",
651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_modifier_names_light[] = {
681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_MOD_LIGHT_BOTH] = "both",
691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_MOD_LIGHT_IR] = "ir",
701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_modifier_names_axial[] = {
731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_MOD_X] = "x",
741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_MOD_Y] = "y",
751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_MOD_Z] = "z",
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",
861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
88aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameronint iio_push_event(struct iio_dev *dev_info,
89aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron		   int ev_line,
90aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron		   int ev_code,
91aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron		   s64 timestamp)
92847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
93aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron	struct iio_event_interface *ev_int
94aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron		= &dev_info->event_interfaces[ev_line];
95847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_detected_event_list *ev;
96847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret = 0;
97847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
98847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	/* Does anyone care? */
99847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_lock(&ev_int->event_list_lock);
100847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (test_bit(IIO_BUSY_BIT_POS, &ev_int->handler.flags)) {
10175c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron		if (ev_int->current_events == ev_int->max_events) {
10275c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron			mutex_unlock(&ev_int->event_list_lock);
103847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			return 0;
10475c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron		}
105847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ev = kmalloc(sizeof(*ev), GFP_KERNEL);
106847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		if (ev == NULL) {
107847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			ret = -ENOMEM;
10875c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron			mutex_unlock(&ev_int->event_list_lock);
109847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			goto error_ret;
110847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		}
111847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ev->ev.id = ev_code;
112847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ev->ev.timestamp = timestamp;
113847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1143b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron		list_add_tail(&ev->list, &ev_int->det_events);
115847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ev_int->current_events++;
116847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_unlock(&ev_int->event_list_lock);
117847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		wake_up_interruptible(&ev_int->wait);
118847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	} else
119847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_unlock(&ev_int->event_list_lock);
120847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
121847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
122847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
123847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
124847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_push_event);
125847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
126847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
127847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron/* This turns up an awful lot */
128847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronssize_t iio_read_const_attr(struct device *dev,
129847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			    struct device_attribute *attr,
130847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			    char *buf)
131847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
132847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return sprintf(buf, "%s\n", to_iio_const_attr(attr)->string);
133847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
134847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_read_const_attr);
135847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
136847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
13777712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brownstatic ssize_t iio_event_chrdev_read(struct file *filep,
13877712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brown				     char __user *buf,
13977712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brown				     size_t count,
14077712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brown				     loff_t *f_ps)
141847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
142847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_event_interface *ev_int = filep->private_data;
143847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_detected_event_list *el;
144847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret;
145847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	size_t len;
146847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
147847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_lock(&ev_int->event_list_lock);
1483b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron	if (list_empty(&ev_int->det_events)) {
149847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		if (filep->f_flags & O_NONBLOCK) {
150847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			ret = -EAGAIN;
151847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			goto error_mutex_unlock;
152847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		}
153847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_unlock(&ev_int->event_list_lock);
154847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		/* Blocking on device; waiting for something to be there */
155847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ret = wait_event_interruptible(ev_int->wait,
156847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron					       !list_empty(&ev_int
1573b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron							   ->det_events));
158847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		if (ret)
159847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			goto error_ret;
16025985edcedea6396277003854657b5f3cb31a628Lucas De Marchi		/* Single access device so no one else can get the data */
161847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_lock(&ev_int->event_list_lock);
162847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
163847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1643b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron	el = list_first_entry(&ev_int->det_events,
165847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			      struct iio_detected_event_list,
166847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			      list);
167847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	len = sizeof el->ev;
168847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (copy_to_user(buf, &(el->ev), len)) {
169847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ret = -EFAULT;
170847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_mutex_unlock;
171847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
172847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	list_del(&el->list);
173847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->current_events--;
174847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_unlock(&ev_int->event_list_lock);
175847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	kfree(el);
176847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
177847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return len;
178847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
179847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_mutex_unlock:
180847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_unlock(&ev_int->event_list_lock);
181847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
182847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
183847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
184847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
185847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
18677712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brownstatic int iio_event_chrdev_release(struct inode *inode, struct file *filep)
187847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
188847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_handler *hand = iio_cdev_to_handler(inode->i_cdev);
189847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_event_interface *ev_int = hand->private;
190847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_detected_event_list *el, *t;
191847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
192847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_lock(&ev_int->event_list_lock);
193847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	clear_bit(IIO_BUSY_BIT_POS, &ev_int->handler.flags);
194847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	/*
195847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	 * In order to maintain a clean state for reopening,
196847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	 * clear out any awaiting events. The mask will prevent
197847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	 * any new __iio_push_event calls running.
198847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	 */
1993b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron	list_for_each_entry_safe(el, t, &ev_int->det_events, list) {
200847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		list_del(&el->list);
201847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		kfree(el);
202847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
203847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_unlock(&ev_int->event_list_lock);
204847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
205847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
206847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
207847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
20877712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brownstatic int iio_event_chrdev_open(struct inode *inode, struct file *filep)
209847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
210847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_handler *hand = iio_cdev_to_handler(inode->i_cdev);
211847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_event_interface *ev_int = hand->private;
212847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
213847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_lock(&ev_int->event_list_lock);
214847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (test_and_set_bit(IIO_BUSY_BIT_POS, &hand->flags)) {
215847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		fops_put(filep->f_op);
216847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_unlock(&ev_int->event_list_lock);
217847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		return -EBUSY;
218847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
219847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	filep->private_data = hand->private;
220847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_unlock(&ev_int->event_list_lock);
221847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
222847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
223847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
224847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
225847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic const struct file_operations iio_event_chrdev_fileops = {
226847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.read =  iio_event_chrdev_read,
227847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.release = iio_event_chrdev_release,
228847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.open = iio_event_chrdev_open,
229847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.owner = THIS_MODULE,
2306038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann	.llseek = noop_llseek,
231847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron};
232847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
233847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void iio_event_dev_release(struct device *dev)
234847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
235847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_event_interface *ev_int
236847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		= container_of(dev, struct iio_event_interface, dev);
237847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	cdev_del(&ev_int->handler.chrdev);
238847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	iio_device_free_chrdev_minor(MINOR(dev->devt));
239847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron};
240847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
241847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic struct device_type iio_event_type = {
242847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.release = iio_event_dev_release,
243847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron};
244847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
245847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronint iio_device_get_chrdev_minor(void)
246847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
247847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret, val;
248847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
249b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameronida_again:
250b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameron	if (unlikely(ida_pre_get(&iio_chrdev_ida, GFP_KERNEL) == 0))
251847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		return -ENOMEM;
252b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameron	spin_lock(&iio_ida_lock);
253b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameron	ret = ida_get_new(&iio_chrdev_ida, &val);
254b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameron	spin_unlock(&iio_ida_lock);
255847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (unlikely(ret == -EAGAIN))
256b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameron		goto ida_again;
257847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	else if (unlikely(ret))
258847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		return ret;
259847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (val > IIO_DEV_MAX)
260847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		return -ENOMEM;
261847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return val;
262847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
263847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
264847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronvoid iio_device_free_chrdev_minor(int val)
265847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
266b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameron	spin_lock(&iio_ida_lock);
267b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameron	ida_remove(&iio_chrdev_ida, val);
268b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameron	spin_unlock(&iio_ida_lock);
269847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
270847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
271b9d40a9d5583a530372b4e1888e4f643ed05aca6Jonathan Cameronstatic int iio_setup_ev_int(struct iio_event_interface *ev_int,
272c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron			    const char *dev_name,
273c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron			    int index,
274c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron			    struct module *owner,
275c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron			    struct device *dev)
276847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
277847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret, minor;
278847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
2795aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	ev_int->dev.bus = &iio_bus_type;
280847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->dev.parent = dev;
281847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->dev.type = &iio_event_type;
282847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	device_initialize(&ev_int->dev);
283847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
284847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	minor = iio_device_get_chrdev_minor();
285847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (minor < 0) {
286847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ret = minor;
287847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_device_put;
288847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
289847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->dev.devt = MKDEV(MAJOR(iio_devt), minor);
290c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	dev_set_name(&ev_int->dev, "%s:event%d", dev_name, index);
291847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
292847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ret = device_add(&ev_int->dev);
293847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret)
294847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_free_minor;
295847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
296847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	cdev_init(&ev_int->handler.chrdev, &iio_event_chrdev_fileops);
297847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->handler.chrdev.owner = owner;
298847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
299847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_init(&ev_int->event_list_lock);
300847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	/* discussion point - make this variable? */
301847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->max_events = 10;
302847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->current_events = 0;
3033b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron	INIT_LIST_HEAD(&ev_int->det_events);
304847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	init_waitqueue_head(&ev_int->wait);
305847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->handler.private = ev_int;
306847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->handler.flags = 0;
307847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
308847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ret = cdev_add(&ev_int->handler.chrdev, ev_int->dev.devt, 1);
309847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret)
310847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_unreg_device;
311847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
312847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
313847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
314847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_unreg_device:
315847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	device_unregister(&ev_int->dev);
316847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_free_minor:
317847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	iio_device_free_chrdev_minor(minor);
318847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_device_put:
319847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	put_device(&ev_int->dev);
320847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
321847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
322847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
323847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
324b9d40a9d5583a530372b4e1888e4f643ed05aca6Jonathan Cameronstatic void iio_free_ev_int(struct iio_event_interface *ev_int)
325847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
326847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	device_unregister(&ev_int->dev);
327847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	put_device(&ev_int->dev);
328847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
329847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
330847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic int __init iio_dev_init(void)
331847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
332847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int err;
333847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
334847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	err = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio");
335847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (err < 0)
336847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		printk(KERN_ERR "%s: failed to allocate char dev region\n",
337847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		       __FILE__);
338847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
339847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return err;
340847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
341847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
342847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void __exit iio_dev_exit(void)
343847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
344847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (iio_devt)
345847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		unregister_chrdev_region(iio_devt, IIO_DEV_MAX);
346847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
347847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
348847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic int __init iio_init(void)
349847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
350847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret;
351847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
3525aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	/* Register sysfs bus */
3535aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	ret  = bus_register(&iio_bus_type);
354847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret < 0) {
355847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		printk(KERN_ERR
3565aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron		       "%s could not register bus type\n",
357847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			__FILE__);
358847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_nothing;
359847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
360847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
361847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ret = iio_dev_init();
362847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret < 0)
3635aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron		goto error_unregister_bus_type;
364847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
365847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
366847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
3675aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameronerror_unregister_bus_type:
3685aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	bus_unregister(&iio_bus_type);
369847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_nothing:
370847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
371847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
372847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
373847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void __exit iio_exit(void)
374847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
375847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	iio_dev_exit();
3765aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	bus_unregister(&iio_bus_type);
377847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
378847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
3791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_read_channel_info(struct device *dev,
3801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     struct device_attribute *attr,
3811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     char *buf)
382847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
3831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
3841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
3851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int val, val2;
3866fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	int ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
3876fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron					    &val, &val2, this_attr->address);
3881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
3891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret < 0)
3901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
391847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
3921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret == IIO_VAL_INT)
3931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return sprintf(buf, "%d\n", val);
3941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	else if (ret == IIO_VAL_INT_PLUS_MICRO) {
3951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (val2 < 0)
3961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			return sprintf(buf, "-%d.%06u\n", val, -val2);
3971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		else
3981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			return sprintf(buf, "%d.%06u\n", val, val2);
39971646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich	} else if (ret == IIO_VAL_INT_PLUS_NANO) {
40071646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich		if (val2 < 0)
40171646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich			return sprintf(buf, "-%d.%09u\n", val, -val2);
40271646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich		else
40371646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich			return sprintf(buf, "%d.%09u\n", val, val2);
4041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	} else
4051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return 0;
4061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
4071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_write_channel_info(struct device *dev,
4091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      struct device_attribute *attr,
4101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      const char *buf,
4111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      size_t len)
4121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
4131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
4141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
4151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret, integer = 0, micro = 0, micro_mult = 100000;
4161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	bool integer_part = true, negative = false;
4171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	/* Assumes decimal - precision based on number of digits */
4196fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	if (!indio_dev->info->write_raw)
4201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return -EINVAL;
4211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (buf[0] == '-') {
4221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		negative = true;
4231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		buf++;
4241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
4251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	while (*buf) {
4261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if ('0' <= *buf && *buf <= '9') {
4271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (integer_part)
4281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				integer = integer*10 + *buf - '0';
4291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			else {
4301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				micro += micro_mult*(*buf - '0');
4311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				if (micro_mult == 1)
4321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					break;
4331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				micro_mult /= 10;
4341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			}
4351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		} else if (*buf == '\n') {
4361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (*(buf + 1) == '\0')
4371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				break;
4381d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			else
4391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				return -EINVAL;
4401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		} else if (*buf == '.') {
4411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			integer_part = false;
4421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		} else {
4431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			return -EINVAL;
4441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
4451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		buf++;
4461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
4471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (negative) {
4481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (integer)
4491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			integer = -integer;
4501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		else
4511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			micro = -micro;
4521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
4531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4546fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	ret = indio_dev->info->write_raw(indio_dev, this_attr->c,
4556fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron					 integer, micro, this_attr->address);
4561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
4571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
4581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return len;
4601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
4611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic int __iio_build_postfix(struct iio_chan_spec const *chan,
4631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			       bool generic,
4641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			       const char *postfix,
4651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			       char **result)
4661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
4671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	char *all_post;
4681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	/* 3 options - generic, extend_name, modified - if generic, extend_name
4691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	* and modified cannot apply.*/
4701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (generic || (!chan->modified && !chan->extend_name)) {
4721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		all_post = kasprintf(GFP_KERNEL, "%s", postfix);
4731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	} else if (chan->modified) {
4741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		const char *intermediate;
4751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		switch (chan->type) {
4761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_INTENSITY:
4771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			intermediate
4781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				= iio_modifier_names_light[chan->channel2];
4791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			break;
4801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_ACCEL:
4811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_GYRO:
4821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_MAGN:
4831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_INCLI:
4841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_ROT:
4851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_ANGL:
4861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			intermediate
4871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				= iio_modifier_names_axial[chan->channel2];
4881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			break;
4891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		default:
4901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			return -EINVAL;
4911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
4921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (chan->extend_name)
4931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			all_post = kasprintf(GFP_KERNEL, "%s_%s_%s",
4941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     intermediate,
4951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     chan->extend_name,
4961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     postfix);
4971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		else
4981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			all_post = kasprintf(GFP_KERNEL, "%s_%s",
4991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     intermediate,
5001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     postfix);
5011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	} else
5021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		all_post = kasprintf(GFP_KERNEL, "%s_%s", chan->extend_name,
5031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     postfix);
5041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (all_post == NULL)
5051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return -ENOMEM;
5061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	*result = all_post;
5071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return 0;
5081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
5091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronint __iio_device_attr_init(struct device_attribute *dev_attr,
5111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   const char *postfix,
5121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct iio_chan_spec const *chan,
5131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*readfunc)(struct device *dev,
5141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       struct device_attribute *attr,
5151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       char *buf),
5161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*writefunc)(struct device *dev,
5171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						struct device_attribute *attr,
5181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						const char *buf,
5191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						size_t len),
5201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   bool generic)
5211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
5221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret;
5231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	char *name_format, *full_postfix;
5241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	sysfs_attr_init(&dev_attr->attr);
5251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	ret = __iio_build_postfix(chan, generic, postfix, &full_postfix);
5261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
527847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_ret;
5281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	/* Special case for types that uses both channel numbers in naming */
5301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (chan->type == IIO_IN_DIFF && !generic)
5311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		name_format
5321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			= kasprintf(GFP_KERNEL, "%s_%s",
5331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    iio_chan_type_name_spec_complex[chan->type],
5341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    full_postfix);
5351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	else if (generic || !chan->indexed)
5361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		name_format
5371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			= kasprintf(GFP_KERNEL, "%s_%s",
5381d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    iio_chan_type_name_spec_shared[chan->type],
5391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    full_postfix);
5401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	else
5411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		name_format
5421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			= kasprintf(GFP_KERNEL, "%s%d_%s",
5431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    iio_chan_type_name_spec_shared[chan->type],
5441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    chan->channel,
5451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    full_postfix);
5461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (name_format == NULL) {
5481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = -ENOMEM;
5491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_free_full_postfix;
5501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
5511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	dev_attr->attr.name = kasprintf(GFP_KERNEL,
5521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					name_format,
5531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					chan->channel,
5541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					chan->channel2);
5551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (dev_attr->attr.name == NULL) {
5561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = -ENOMEM;
5571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_free_name_format;
5581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
5591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (readfunc) {
5611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->attr.mode |= S_IRUGO;
5621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->show = readfunc;
5631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
5641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (writefunc) {
5661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->attr.mode |= S_IWUSR;
5671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->store = writefunc;
5681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
5691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(name_format);
5701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(full_postfix);
5711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return 0;
5731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_free_name_format:
5751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(name_format);
5761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_free_full_postfix:
5771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(full_postfix);
5781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
5791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
5801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
5811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronvoid __iio_device_attr_deinit(struct device_attribute *dev_attr)
5831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
5841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(dev_attr->attr.name);
5851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
5861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronint __iio_add_chan_devattr(const char *postfix,
5881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   const char *group,
5891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct iio_chan_spec const *chan,
5901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*readfunc)(struct device *dev,
5911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       struct device_attribute *attr,
5921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       char *buf),
5931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*writefunc)(struct device *dev,
5941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						struct device_attribute *attr,
5951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						const char *buf,
5961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						size_t len),
5971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   int mask,
5981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   bool generic,
5991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct device *dev,
6001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct list_head *attr_list)
6011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
6021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret;
6031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *iio_attr, *t;
6041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	iio_attr = kzalloc(sizeof *iio_attr, GFP_KERNEL);
6061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (iio_attr == NULL) {
6071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = -ENOMEM;
6081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_ret;
6091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
6101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	ret = __iio_device_attr_init(&iio_attr->dev_attr,
6111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     postfix, chan,
6121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     readfunc, writefunc, generic);
6131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
6141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_iio_dev_attr_free;
6151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	iio_attr->c = chan;
6161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	iio_attr->address = mask;
6171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_for_each_entry(t, attr_list, l)
6181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (strcmp(t->dev_attr.attr.name,
6191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   iio_attr->dev_attr.attr.name) == 0) {
6201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (!generic)
6211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				dev_err(dev, "tried to double register : %s\n",
6221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					t->dev_attr.attr.name);
6231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = -EBUSY;
6241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_device_attr_deinit;
6251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
6261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	ret = sysfs_add_file_to_group(&dev->kobj,
6281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      &iio_attr->dev_attr.attr, group);
6291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret < 0)
6301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_device_attr_deinit;
6311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_add(&iio_attr->l, attr_list);
6331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return 0;
6351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_device_attr_deinit:
6371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	__iio_device_attr_deinit(&iio_attr->dev_attr);
6381d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_iio_dev_attr_free:
6391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(iio_attr);
6401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
6411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
6421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
6431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic int iio_device_add_channel_sysfs(struct iio_dev *dev_info,
6451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					struct iio_chan_spec const *chan)
6461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
6471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret, i;
6481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (chan->channel < 0)
6511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return 0;
6521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (chan->processed_val)
6531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = __iio_add_chan_devattr("input", NULL, chan,
6541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &iio_read_channel_info,
6551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     NULL,
6561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     0,
6571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     0,
6581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &dev_info->dev,
6591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &dev_info->channel_attr_list);
6601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	else
6611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = __iio_add_chan_devattr("raw", NULL, chan,
6621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &iio_read_channel_info,
6631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     NULL,
6641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     0,
6651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     0,
6661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &dev_info->dev,
6671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &dev_info->channel_attr_list);
6681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
6691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_ret;
6701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) {
6721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2],
6731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     NULL, chan,
6741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &iio_read_channel_info,
6751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &iio_write_channel_info,
6761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     (1 << i),
6771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     !(i%2),
6781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &dev_info->dev,
6791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &dev_info->channel_attr_list);
6801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret == -EBUSY && (i%2 == 0)) {
6811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = 0;
6821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			continue;
6831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
6841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret < 0)
6851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
6861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
6871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
6881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
6891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
6901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic void iio_device_remove_and_free_read_attr(struct iio_dev *dev_info,
6921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						 struct iio_dev_attr *p)
6931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
6941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	sysfs_remove_file_from_group(&dev_info->dev.kobj,
6951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     &p->dev_attr.attr, NULL);
6961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(p->dev_attr.attr.name);
6971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(p);
6981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
6991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7001b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameronstatic ssize_t iio_show_dev_name(struct device *dev,
7011b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron				 struct device_attribute *attr,
7021b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron				 char *buf)
7031b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron{
7041b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
7051b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron	return sprintf(buf, "%s\n", indio_dev->name);
7061b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron}
7071b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron
7081b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameronstatic DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
7091b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron
7101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic int iio_device_register_sysfs(struct iio_dev *dev_info)
7111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
7121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int i, ret = 0;
7131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *p, *n;
7141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7156fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	if (dev_info->info->attrs) {
7166fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron		ret = sysfs_create_group(&dev_info->dev.kobj,
7176fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron					 dev_info->info->attrs);
7181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret) {
7191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			dev_err(dev_info->dev.parent,
7201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				"Failed to register sysfs hooks\n");
7211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
7221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
723847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
724847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
7251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	/*
7261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	 * New channel registration method - relies on the fact a group does
7271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	 *  not need to be initialized if it is name is NULL.
7281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	 */
7291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	INIT_LIST_HEAD(&dev_info->channel_attr_list);
7301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (dev_info->channels)
7311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		for (i = 0; i < dev_info->num_channels; i++) {
7321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = iio_device_add_channel_sysfs(dev_info,
7331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron							   &dev_info
7341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron							   ->channels[i]);
7351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (ret < 0)
7361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				goto error_clear_attrs;
7371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
7381b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron	if (dev_info->name) {
7391b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron		ret = sysfs_add_file_to_group(&dev_info->dev.kobj,
7401b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron					      &dev_attr_name.attr,
7411b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron					      NULL);
7421b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron		if (ret)
7431b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron			goto error_clear_attrs;
7441b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron	}
7451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return 0;
7461b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron
7471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_clear_attrs:
7481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_for_each_entry_safe(p, n,
7491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 &dev_info->channel_attr_list, l) {
7501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		list_del(&p->l);
7511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		iio_device_remove_and_free_read_attr(dev_info, p);
7521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
7536fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	if (dev_info->info->attrs)
7546fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron		sysfs_remove_group(&dev_info->dev.kobj, dev_info->info->attrs);
755847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
756847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
7571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
758847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
759847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
760847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void iio_device_unregister_sysfs(struct iio_dev *dev_info)
761847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
7621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *p, *n;
7641b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron	if (dev_info->name)
7651b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron		sysfs_remove_file_from_group(&dev_info->dev.kobj,
7661b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron					     &dev_attr_name.attr,
7671b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron					     NULL);
7681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_for_each_entry_safe(p, n, &dev_info->channel_attr_list, l) {
7691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		list_del(&p->l);
7701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		iio_device_remove_and_free_read_attr(dev_info, p);
7711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
7721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7736fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	if (dev_info->info->attrs)
7746fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron		sysfs_remove_group(&dev_info->dev.kobj, dev_info->info->attrs);
775847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
776847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
777f3cdc28520a059feb8b5001655f01536ab1e0167Andrew Morton/* Return a negative errno on failure */
778b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameronint iio_get_new_ida_val(struct ida *this_ida)
779847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
780847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret;
781847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int val;
782847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
783b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameronida_again:
784b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameron	if (unlikely(ida_pre_get(this_ida, GFP_KERNEL) == 0))
785847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		return -ENOMEM;
786847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
787b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameron	spin_lock(&iio_ida_lock);
788b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameron	ret = ida_get_new(this_ida, &val);
789b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameron	spin_unlock(&iio_ida_lock);
790847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (unlikely(ret == -EAGAIN))
791b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameron		goto ida_again;
792847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	else if (unlikely(ret))
793847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		return ret;
794847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
795847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return val;
796847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
797b156cf70e1f4befc4856baaf9681dede9a143888Jonathan CameronEXPORT_SYMBOL(iio_get_new_ida_val);
798847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
799b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameronvoid iio_free_ida_val(struct ida *this_ida, int id)
800847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
801b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameron	spin_lock(&iio_ida_lock);
802b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameron	ida_remove(this_ida, id);
803b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameron	spin_unlock(&iio_ida_lock);
804847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
805b156cf70e1f4befc4856baaf9681dede9a143888Jonathan CameronEXPORT_SYMBOL(iio_free_ida_val);
806847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
8071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_ev_type_text[] = {
8081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_TYPE_THRESH] = "thresh",
8091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_TYPE_MAG] = "mag",
8101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_TYPE_ROC] = "roc"
8111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
8121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_ev_dir_text[] = {
8141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_DIR_EITHER] = "either",
8151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_DIR_RISING] = "rising",
8161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_DIR_FALLING] = "falling"
8171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
8181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_state_store(struct device *dev,
8201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  struct device_attribute *attr,
8211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  const char *buf,
8221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  size_t len)
8231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
8241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
825aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
8261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret;
827c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	bool val;
828c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron
829c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	ret = strtobool(buf, &val);
830c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	if (ret < 0)
831c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron		return ret;
8321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8336fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	ret = indio_dev->info->write_event_config(indio_dev,
8346fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						  this_attr->address,
8356fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						  val);
8361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return (ret < 0) ? ret : len;
8371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
8381d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_state_show(struct device *dev,
8401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 struct device_attribute *attr,
8411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 char *buf)
8421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
8431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
844aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
8456fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	int val = indio_dev->info->read_event_config(indio_dev,
8466fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						     this_attr->address);
8471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (val < 0)
8491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return val;
8501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	else
8511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return sprintf(buf, "%d\n", val);
8521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
8531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_value_show(struct device *dev,
8551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 struct device_attribute *attr,
8561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 char *buf)
8571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
8581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
8591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
8601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int val, ret;
8611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8626fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	ret = indio_dev->info->read_event_value(indio_dev,
8636fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						this_attr->address, &val);
8641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret < 0)
8651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
8661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return sprintf(buf, "%d\n", val);
8681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
8691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_value_store(struct device *dev,
8711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  struct device_attribute *attr,
8721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  const char *buf,
8731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  size_t len)
8741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
8751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
8761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
8771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	unsigned long val;
8781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret;
8791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	ret = strict_strtoul(buf, 10, &val);
8811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
8821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
8831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8846fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	ret = indio_dev->info->write_event_value(indio_dev, this_attr->address,
8856fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						 val);
8861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret < 0)
8871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
8881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return len;
8901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
8911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic int iio_device_add_event_sysfs(struct iio_dev *dev_info,
8931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      struct iio_chan_spec const *chan)
8941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
8951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret = 0, i, mask;
8971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	char *postfix;
8981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (!chan->event_mask)
8991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return 0;
9001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
9011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	for_each_set_bit(i, &chan->event_mask, sizeof(chan->event_mask)*8) {
9021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		postfix = kasprintf(GFP_KERNEL, "%s_%s_en",
9031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    iio_ev_type_text[i/IIO_EV_TYPE_MAX],
9041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    iio_ev_dir_text[i%IIO_EV_TYPE_MAX]);
9051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (postfix == NULL) {
9061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = -ENOMEM;
9071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
9081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
9091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		switch (chan->type) {
9101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			/* Switch this to a table at some point */
9111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_IN:
9121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			mask = IIO_UNMOD_EVENT_CODE(chan->type, chan->channel,
9131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						    i/IIO_EV_TYPE_MAX,
9141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						    i%IIO_EV_TYPE_MAX);
9151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			break;
9161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_ACCEL:
9171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel,
9181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						  i/IIO_EV_TYPE_MAX,
9191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						  i%IIO_EV_TYPE_MAX);
9201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			break;
9211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_IN_DIFF:
9221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			mask = IIO_MOD_EVENT_CODE(chan->type, chan->channel,
9231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						  chan->channel2,
9241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						  i/IIO_EV_TYPE_MAX,
9251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						  i%IIO_EV_TYPE_MAX);
9261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			break;
9271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		default:
9281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			printk(KERN_INFO "currently unhandled type of event\n");
9291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
930aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron		ret = __iio_add_chan_devattr(postfix,
931aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     NULL,
932aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     chan,
933aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     &iio_ev_state_show,
934aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     iio_ev_state_store,
935aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     mask,
936aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     /*HACK. - limits us to one
937aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					       event interface - fix by
938aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					       extending the bitmask - but
939aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					       how far*/
940aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     0,
9416fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron					     &dev_info->event_interfaces[0].dev,
942aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     &dev_info->event_interfaces[0].
943aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     dev_attr_list);
9441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		kfree(postfix);
9451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret)
9461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
9471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
9481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		postfix = kasprintf(GFP_KERNEL, "%s_%s_value",
9491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    iio_ev_type_text[i/IIO_EV_TYPE_MAX],
9501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    iio_ev_dir_text[i%IIO_EV_TYPE_MAX]);
9511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (postfix == NULL) {
9521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = -ENOMEM;
9531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
9541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
9551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = __iio_add_chan_devattr(postfix, NULL, chan,
9561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     iio_ev_value_show,
9571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     iio_ev_value_store,
9581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     mask,
9591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     0,
9601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &dev_info->event_interfaces[0]
9611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     .dev,
9621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &dev_info->event_interfaces[0]
9631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     .dev_attr_list);
9641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		kfree(postfix);
9651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret)
9661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
9671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
9681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
9691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
9701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
9711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
9721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
9731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
9741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic inline void __iio_remove_all_event_sysfs(struct iio_dev *dev_info,
9751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						const char *groupname,
9761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						int num)
9771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
9781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *p, *n;
9791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_for_each_entry_safe(p, n,
9801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 &dev_info->event_interfaces[num].
9811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 dev_attr_list, l) {
9821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		sysfs_remove_file_from_group(&dev_info
9831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     ->event_interfaces[num].dev.kobj,
9841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &p->dev_attr.attr,
9851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     groupname);
9861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		kfree(p->dev_attr.attr.name);
9871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		kfree(p);
9881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
9891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
9901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
991847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic inline int __iio_add_event_config_attrs(struct iio_dev *dev_info, int i)
992847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
9931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int j;
994847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret;
9951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	INIT_LIST_HEAD(&dev_info->event_interfaces[0].dev_attr_list);
9961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	/* Dynically created from the channels array */
9971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (dev_info->channels) {
9981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		for (j = 0; j < dev_info->num_channels; j++) {
9991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = iio_device_add_event_sysfs(dev_info,
10001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron							 &dev_info
10011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron							 ->channels[j]);
10021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (ret)
10031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				goto error_clear_attrs;
10041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
10051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
1006847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
1007847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
10081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_clear_attrs:
100941c775240a78fac3e2bd7f024c3cf0d61547249eJonathan Cameron	__iio_remove_all_event_sysfs(dev_info, NULL, i);
1010847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1011847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
1012847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1013847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1014847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic inline int __iio_remove_event_config_attrs(struct iio_dev *dev_info,
1015847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron						  int i)
1016847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
101741c775240a78fac3e2bd7f024c3cf0d61547249eJonathan Cameron	__iio_remove_all_event_sysfs(dev_info, NULL, i);
1018847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
1019847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1020847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1021847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic int iio_device_register_eventset(struct iio_dev *dev_info)
1022847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1023847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret = 0, i, j;
1024847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
10256fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	if (dev_info->info->num_interrupt_lines == 0)
1026847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		return 0;
1027847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1028847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	dev_info->event_interfaces =
1029847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		kzalloc(sizeof(struct iio_event_interface)
10306fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron			*dev_info->info->num_interrupt_lines,
1031847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			GFP_KERNEL);
1032847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (dev_info->event_interfaces == NULL) {
1033847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ret = -ENOMEM;
1034847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_ret;
1035847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1036847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
10376fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	for (i = 0; i < dev_info->info->num_interrupt_lines; i++) {
1038847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ret = iio_setup_ev_int(&dev_info->event_interfaces[i],
1039c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron				       dev_name(&dev_info->dev),
1040c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron				       i,
10416fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron				       dev_info->info->driver_module,
1042847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron				       &dev_info->dev);
1043847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		if (ret) {
1044847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			dev_err(&dev_info->dev,
1045847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron				"Could not get chrdev interface\n");
1046847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			goto error_free_setup_ev_ints;
1047847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		}
1048847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
10495cba220b0a3211befd5514cbd822a97578ef5ed4Jonathan Cameron		dev_set_drvdata(&dev_info->event_interfaces[i].dev,
10505cba220b0a3211befd5514cbd822a97578ef5ed4Jonathan Cameron				(void *)dev_info);
10511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
10526fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron		if (dev_info->info->event_attrs != NULL)
10531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = sysfs_create_group(&dev_info
10541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						 ->event_interfaces[i]
10551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						 .dev.kobj,
10566fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						 &dev_info->info
10576fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						 ->event_attrs[i]);
10585cba220b0a3211befd5514cbd822a97578ef5ed4Jonathan Cameron
1059847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		if (ret) {
1060847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			dev_err(&dev_info->dev,
1061847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron				"Failed to register sysfs for event attrs");
1062847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			goto error_remove_sysfs_interfaces;
1063847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		}
1064847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1065847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
10666fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	for (i = 0; i < dev_info->info->num_interrupt_lines; i++) {
1067847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ret = __iio_add_event_config_attrs(dev_info, i);
1068847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		if (ret)
1069847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			goto error_unregister_config_attrs;
1070847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1071847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1072847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
1073847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1074847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_unregister_config_attrs:
1075847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	for (j = 0; j < i; j++)
1076847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		__iio_remove_event_config_attrs(dev_info, i);
10776fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	i = dev_info->info->num_interrupt_lines - 1;
1078847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_remove_sysfs_interfaces:
1079847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	for (j = 0; j < i; j++)
10806fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron		if (dev_info->info->event_attrs != NULL)
10811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			sysfs_remove_group(&dev_info
10825cba220b0a3211befd5514cbd822a97578ef5ed4Jonathan Cameron				   ->event_interfaces[j].dev.kobj,
10836fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron				   &dev_info->info->event_attrs[j]);
1084847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_free_setup_ev_ints:
10853d550fbace94a79b97cde94dca46f5477c817fedJonathan Cameron	for (j = 0; j < i; j++)
1086847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		iio_free_ev_int(&dev_info->event_interfaces[j]);
1087847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	kfree(dev_info->event_interfaces);
1088847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
1089847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1090847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
1091847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1092847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1093847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void iio_device_unregister_eventset(struct iio_dev *dev_info)
1094847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1095847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int i;
1096847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
10976fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	if (dev_info->info->num_interrupt_lines == 0)
1098847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		return;
10996fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	for (i = 0; i < dev_info->info->num_interrupt_lines; i++) {
11001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		__iio_remove_event_config_attrs(dev_info, i);
11016fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron		if (dev_info->info->event_attrs != NULL)
11021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			sysfs_remove_group(&dev_info
11031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					   ->event_interfaces[i].dev.kobj,
11046fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron					   &dev_info->info->event_attrs[i]);
11051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
1106847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
11076fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	for (i = 0; i < dev_info->info->num_interrupt_lines; i++)
1108847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		iio_free_ev_int(&dev_info->event_interfaces[i]);
1109847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	kfree(dev_info->event_interfaces);
1110847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1111847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1112847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void iio_dev_release(struct device *device)
1113847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1114847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	iio_put();
1115c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	kfree(to_iio_dev(device));
1116847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1117847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1118847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic struct device_type iio_dev_type = {
1119847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.name = "iio_device",
1120847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.release = iio_dev_release,
1121847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron};
1122847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
11236f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameronstruct iio_dev *iio_allocate_device(int sizeof_priv)
1124847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
11256f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	struct iio_dev *dev;
11266f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	size_t alloc_size;
11276f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron
11286f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	alloc_size = sizeof(struct iio_dev);
11296f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	if (sizeof_priv) {
11306f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron		alloc_size = ALIGN(alloc_size, IIO_ALIGN);
11316f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron		alloc_size += sizeof_priv;
11326f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	}
11336f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	/* ensure 32-byte alignment of whole construct ? */
11346f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	alloc_size += IIO_ALIGN - 1;
11356f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron
11366f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	dev = kzalloc(alloc_size, GFP_KERNEL);
1137847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1138847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (dev) {
1139847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		dev->dev.type = &iio_dev_type;
11405aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron		dev->dev.bus = &iio_bus_type;
1141847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		device_initialize(&dev->dev);
1142847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		dev_set_drvdata(&dev->dev, (void *)dev);
1143847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_init(&dev->mlock);
1144847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		iio_get();
1145847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1146847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1147847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return dev;
1148847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1149847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_allocate_device);
1150847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1151847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronvoid iio_free_device(struct iio_dev *dev)
1152847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1153847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (dev)
1154847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		iio_put_device(dev);
1155847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1156847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_free_device);
1157847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1158847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronint iio_device_register(struct iio_dev *dev_info)
1159847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1160847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret;
1161847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1162c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	dev_info->id = iio_get_new_ida_val(&iio_ida);
1163c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	if (dev_info->id < 0) {
1164c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron		ret = dev_info->id;
1165847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		dev_err(&dev_info->dev, "Failed to get id\n");
1166847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_ret;
1167847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1168847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	dev_set_name(&dev_info->dev, "device%d", dev_info->id);
1169847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1170847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ret = device_add(&dev_info->dev);
1171847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret)
1172b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameron		goto error_free_ida;
1173847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ret = iio_device_register_sysfs(dev_info);
1174847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret) {
1175847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		dev_err(dev_info->dev.parent,
1176847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			"Failed to register sysfs interfaces\n");
1177847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_del_device;
1178847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1179847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ret = iio_device_register_eventset(dev_info);
1180847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret) {
1181847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		dev_err(dev_info->dev.parent,
1182c849d2538ebeef1ac26fad7a10c18b1e0fc35161Roel Van Nyen			"Failed to register event set\n");
1183847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_free_sysfs;
1184847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1185847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (dev_info->modes & INDIO_RING_TRIGGERED)
1186847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		iio_device_register_trigger_consumer(dev_info);
1187847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1188847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
1189847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1190847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_free_sysfs:
1191847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	iio_device_unregister_sysfs(dev_info);
1192847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_del_device:
1193847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	device_del(&dev_info->dev);
1194b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameronerror_free_ida:
1195c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	iio_free_ida_val(&iio_ida, dev_info->id);
1196847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
1197847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
1198847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1199847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_device_register);
1200847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1201847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronvoid iio_device_unregister(struct iio_dev *dev_info)
1202847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1203847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (dev_info->modes & INDIO_RING_TRIGGERED)
1204847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		iio_device_unregister_trigger_consumer(dev_info);
1205847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	iio_device_unregister_eventset(dev_info);
1206847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	iio_device_unregister_sysfs(dev_info);
1207c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	iio_free_ida_val(&iio_ida, dev_info->id);
1208847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	device_unregister(&dev_info->dev);
1209847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1210847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_device_unregister);
1211847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1212847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronvoid iio_put(void)
1213847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1214847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	module_put(THIS_MODULE);
1215847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1216847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1217847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronvoid iio_get(void)
1218847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1219847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	__module_get(THIS_MODULE);
1220847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1221847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1222847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronsubsys_initcall(iio_init);
1223847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronmodule_exit(iio_exit);
1224847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1225847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
1226847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_DESCRIPTION("Industrial I/O core");
1227847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_LICENSE("GPL");
1228