industrialio-core.c revision 6aea1c364cde5b28b551844b7b8925f523310a18
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"
25df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameron#include "iio_core.h"
266aea1c364cde5b28b551844b7b8925f523310a18Jonathan Cameron#include "iio_core_trigger.h"
27847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
28847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#define IIO_ID_PREFIX "device"
29847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#define IIO_ID_FORMAT IIO_ID_PREFIX "%d"
30847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
31847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron/* IDR to assign each registered device a unique id*/
32b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameronstatic DEFINE_IDA(iio_ida);
33847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron/* IDR to allocate character device minor numbers */
34b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameronstatic DEFINE_IDA(iio_chrdev_ida);
35847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron/* Lock used to protect both of the above */
36b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameronstatic DEFINE_SPINLOCK(iio_ida_lock);
37847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
38847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Camerondev_t 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_IN] = "in",
48ae19178eacfab141afdd886e002bb80c99dba63aMichael Hennerich	[IIO_OUT] = "out",
49faf290e867fd51e227165d0bef113b022520a58fMichael Hennerich	[IIO_CURRENT] = "current",
50faf290e867fd51e227165d0bef113b022520a58fMichael Hennerich	[IIO_POWER] = "power",
519bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed	[IIO_ACCEL] = "accel",
521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_IN_DIFF] = "in-in",
531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_GYRO] = "gyro",
541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_MAGN] = "magn",
559bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed	[IIO_LIGHT] = "illuminance",
569bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed	[IIO_INTENSITY] = "intensity",
57f09f2c8142d275b0d9321d2ea93c8bd0d8dc32ecBryan Freed	[IIO_PROXIMITY] = "proximity",
589bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed	[IIO_TEMP] = "temp",
591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_INCLI] = "incli",
601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_ROT] = "rot",
611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_ANGL] = "angl",
629bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed	[IIO_TIMESTAMP] = "timestamp",
631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_chan_type_name_spec_complex[] = {
661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_IN_DIFF] = "in%d-in%d",
671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_modifier_names_light[] = {
701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_MOD_LIGHT_BOTH] = "both",
711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_MOD_LIGHT_IR] = "ir",
721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_modifier_names_axial[] = {
751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_MOD_X] = "x",
761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_MOD_Y] = "y",
771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_MOD_Z] = "z",
781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron/* relies on pairs of these shared then separate */
811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_chan_info_postfix[] = {
821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_CHAN_INFO_SCALE_SHARED/2] = "scale",
831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_CHAN_INFO_OFFSET_SHARED/2] = "offset",
841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_CHAN_INFO_CALIBSCALE_SHARED/2] = "calibscale",
851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_CHAN_INFO_CALIBBIAS_SHARED/2] = "calibbias",
86eb7fea53e53ed47e82b4cc9911dd8fdc7f953de5Jonathan Cameron	[IIO_CHAN_INFO_PEAK_SHARED/2] = "peak_raw",
87eb7fea53e53ed47e82b4cc9911dd8fdc7f953de5Jonathan Cameron	[IIO_CHAN_INFO_PEAK_SCALE_SHARED/2] = "peak_scale",
887d43817803c6a1786d60834ea1a110360b098085Jonathan Cameron	[IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW_SHARED/2]
897d43817803c6a1786d60834ea1a110360b098085Jonathan Cameron	= "quadrature_correction_raw",
901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
929aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron/* Return a negative errno on failure */
93df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameronstatic int iio_get_new_ida_val(struct ida *this_ida)
949aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron{
959aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	int ret;
969aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	int val;
979aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron
989aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameronida_again:
999aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	if (unlikely(ida_pre_get(this_ida, GFP_KERNEL) == 0))
1009aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron		return -ENOMEM;
1019aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron
1029aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	spin_lock(&iio_ida_lock);
1039aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	ret = ida_get_new(this_ida, &val);
1049aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	spin_unlock(&iio_ida_lock);
1059aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	if (unlikely(ret == -EAGAIN))
1069aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron		goto ida_again;
1079aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	else if (unlikely(ret))
1089aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron		return ret;
1099aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron
1109aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	return val;
1119aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron}
1129aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron
113df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameronstatic void iio_free_ida_val(struct ida *this_ida, int id)
1149aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron{
1159aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	spin_lock(&iio_ida_lock);
1169aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	ida_remove(this_ida, id);
1179aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	spin_unlock(&iio_ida_lock);
1189aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron}
1199aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron
120aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameronint iio_push_event(struct iio_dev *dev_info,
121aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron		   int ev_line,
122aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron		   int ev_code,
123aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron		   s64 timestamp)
124847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
125aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron	struct iio_event_interface *ev_int
126aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron		= &dev_info->event_interfaces[ev_line];
127847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_detected_event_list *ev;
128847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret = 0;
129847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
130847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	/* Does anyone care? */
131847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_lock(&ev_int->event_list_lock);
132847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (test_bit(IIO_BUSY_BIT_POS, &ev_int->handler.flags)) {
13375c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron		if (ev_int->current_events == ev_int->max_events) {
13475c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron			mutex_unlock(&ev_int->event_list_lock);
135847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			return 0;
13675c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron		}
137847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ev = kmalloc(sizeof(*ev), GFP_KERNEL);
138847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		if (ev == NULL) {
139847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			ret = -ENOMEM;
14075c8075394906b4bda4b056328bd9b401277d9b8Jonathan Cameron			mutex_unlock(&ev_int->event_list_lock);
141847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			goto error_ret;
142847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		}
143847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ev->ev.id = ev_code;
144847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ev->ev.timestamp = timestamp;
145847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1463b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron		list_add_tail(&ev->list, &ev_int->det_events);
147847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ev_int->current_events++;
148847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_unlock(&ev_int->event_list_lock);
149847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		wake_up_interruptible(&ev_int->wait);
150847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	} else
151847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_unlock(&ev_int->event_list_lock);
152847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
153847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
154847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
155847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
156847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_push_event);
157847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
158847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
159847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron/* This turns up an awful lot */
160847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronssize_t iio_read_const_attr(struct device *dev,
161847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			    struct device_attribute *attr,
162847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			    char *buf)
163847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
164847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return sprintf(buf, "%s\n", to_iio_const_attr(attr)->string);
165847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
166847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_read_const_attr);
167847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
168847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
16977712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brownstatic ssize_t iio_event_chrdev_read(struct file *filep,
17077712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brown				     char __user *buf,
17177712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brown				     size_t count,
17277712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brown				     loff_t *f_ps)
173847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
174847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_event_interface *ev_int = filep->private_data;
175847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_detected_event_list *el;
176847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret;
177847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	size_t len;
178847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
179847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_lock(&ev_int->event_list_lock);
1803b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron	if (list_empty(&ev_int->det_events)) {
181847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		if (filep->f_flags & O_NONBLOCK) {
182847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			ret = -EAGAIN;
183847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			goto error_mutex_unlock;
184847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		}
185847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_unlock(&ev_int->event_list_lock);
186847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		/* Blocking on device; waiting for something to be there */
187847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ret = wait_event_interruptible(ev_int->wait,
188847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron					       !list_empty(&ev_int
1893b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron							   ->det_events));
190847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		if (ret)
191847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			goto error_ret;
19225985edcedea6396277003854657b5f3cb31a628Lucas De Marchi		/* Single access device so no one else can get the data */
193847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_lock(&ev_int->event_list_lock);
194847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
195847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1963b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron	el = list_first_entry(&ev_int->det_events,
197847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			      struct iio_detected_event_list,
198847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			      list);
199847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	len = sizeof el->ev;
200847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (copy_to_user(buf, &(el->ev), len)) {
201847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ret = -EFAULT;
202847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_mutex_unlock;
203847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
204847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	list_del(&el->list);
205847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->current_events--;
206847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_unlock(&ev_int->event_list_lock);
207847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	kfree(el);
208847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
209847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return len;
210847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
211847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_mutex_unlock:
212847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_unlock(&ev_int->event_list_lock);
213847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
214847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
215847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
216847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
217847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
21877712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brownstatic int iio_event_chrdev_release(struct inode *inode, struct file *filep)
219847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
220847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_handler *hand = iio_cdev_to_handler(inode->i_cdev);
221847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_event_interface *ev_int = hand->private;
222847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_detected_event_list *el, *t;
223847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
224847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_lock(&ev_int->event_list_lock);
225847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	clear_bit(IIO_BUSY_BIT_POS, &ev_int->handler.flags);
226847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	/*
227847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	 * In order to maintain a clean state for reopening,
228847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	 * clear out any awaiting events. The mask will prevent
229847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	 * any new __iio_push_event calls running.
230847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	 */
2313b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron	list_for_each_entry_safe(el, t, &ev_int->det_events, list) {
232847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		list_del(&el->list);
233847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		kfree(el);
234847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
235847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_unlock(&ev_int->event_list_lock);
236847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
237847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
238847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
239847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
24077712e5fbe2e47476823f4853d756cc5ad1dfabcMark Brownstatic int iio_event_chrdev_open(struct inode *inode, struct file *filep)
241847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
242847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_handler *hand = iio_cdev_to_handler(inode->i_cdev);
243847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_event_interface *ev_int = hand->private;
244847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
245847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_lock(&ev_int->event_list_lock);
246847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (test_and_set_bit(IIO_BUSY_BIT_POS, &hand->flags)) {
247847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		fops_put(filep->f_op);
248847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_unlock(&ev_int->event_list_lock);
249847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		return -EBUSY;
250847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
251847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	filep->private_data = hand->private;
252847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_unlock(&ev_int->event_list_lock);
253847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
254847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
255847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
256847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
257847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic const struct file_operations iio_event_chrdev_fileops = {
258847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.read =  iio_event_chrdev_read,
259847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.release = iio_event_chrdev_release,
260847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.open = iio_event_chrdev_open,
261847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.owner = THIS_MODULE,
2626038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann	.llseek = noop_llseek,
263847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron};
264847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
265847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void iio_event_dev_release(struct device *dev)
266847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
267847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	struct iio_event_interface *ev_int
268847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		= container_of(dev, struct iio_event_interface, dev);
269847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	cdev_del(&ev_int->handler.chrdev);
270847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	iio_device_free_chrdev_minor(MINOR(dev->devt));
271847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron};
272847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
273847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic struct device_type iio_event_type = {
274847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.release = iio_event_dev_release,
275847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron};
276847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
277847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronint iio_device_get_chrdev_minor(void)
278847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
2799aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	int ret;
280847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
2819aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	ret = iio_get_new_ida_val(&iio_chrdev_ida);
2829aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	if (ret < IIO_DEV_MAX) /* both errors and valid */
283847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		return ret;
2849aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	else
285847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		return -ENOMEM;
286847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
287847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
288847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronvoid iio_device_free_chrdev_minor(int val)
289847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
2909aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	iio_free_ida_val(&iio_chrdev_ida, val);
291847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
292847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
293b9d40a9d5583a530372b4e1888e4f643ed05aca6Jonathan Cameronstatic int iio_setup_ev_int(struct iio_event_interface *ev_int,
294c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron			    const char *dev_name,
295c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron			    int index,
296c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron			    struct module *owner,
297c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron			    struct device *dev)
298847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
299847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret, minor;
300847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
3015aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	ev_int->dev.bus = &iio_bus_type;
302847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->dev.parent = dev;
303847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->dev.type = &iio_event_type;
304847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	device_initialize(&ev_int->dev);
305847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
306847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	minor = iio_device_get_chrdev_minor();
307847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (minor < 0) {
308847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ret = minor;
309847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_device_put;
310847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
311847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->dev.devt = MKDEV(MAJOR(iio_devt), minor);
312c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	dev_set_name(&ev_int->dev, "%s:event%d", dev_name, index);
313847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
314847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ret = device_add(&ev_int->dev);
315847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret)
316847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_free_minor;
317847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
318847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	cdev_init(&ev_int->handler.chrdev, &iio_event_chrdev_fileops);
319847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->handler.chrdev.owner = owner;
320847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
321847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	mutex_init(&ev_int->event_list_lock);
322847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	/* discussion point - make this variable? */
323847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->max_events = 10;
324847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->current_events = 0;
3253b8ebfb47f0cacc82c88b6f886ad84d78d6fdd61Jonathan Cameron	INIT_LIST_HEAD(&ev_int->det_events);
326847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	init_waitqueue_head(&ev_int->wait);
327847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->handler.private = ev_int;
328847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ev_int->handler.flags = 0;
329847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
330847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ret = cdev_add(&ev_int->handler.chrdev, ev_int->dev.devt, 1);
331847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret)
332847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_unreg_device;
333847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
334847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
335847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
336847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_unreg_device:
337847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	device_unregister(&ev_int->dev);
338847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_free_minor:
339847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	iio_device_free_chrdev_minor(minor);
340847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_device_put:
341847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	put_device(&ev_int->dev);
342847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
343847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
344847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
345847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
346b9d40a9d5583a530372b4e1888e4f643ed05aca6Jonathan Cameronstatic void iio_free_ev_int(struct iio_event_interface *ev_int)
347847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
348847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	device_unregister(&ev_int->dev);
349847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	put_device(&ev_int->dev);
350847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
351847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
352847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic int __init iio_init(void)
353847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
354847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret;
355847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
3565aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	/* Register sysfs bus */
3575aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	ret  = bus_register(&iio_bus_type);
358847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret < 0) {
359847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		printk(KERN_ERR
3605aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron		       "%s could not register bus type\n",
361847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			__FILE__);
362847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_nothing;
363847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
364847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
3659aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio");
3669aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	if (ret < 0) {
3679aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron		printk(KERN_ERR "%s: failed to allocate char dev region\n",
3689aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron		       __FILE__);
3695aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron		goto error_unregister_bus_type;
3709aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	}
371847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
372847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
373847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
3745aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameronerror_unregister_bus_type:
3755aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	bus_unregister(&iio_bus_type);
376847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_nothing:
377847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
378847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
379847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
380847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void __exit iio_exit(void)
381847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
3829aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron	if (iio_devt)
3839aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron		unregister_chrdev_region(iio_devt, IIO_DEV_MAX);
3845aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron	bus_unregister(&iio_bus_type);
385847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
386847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
3871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_read_channel_info(struct device *dev,
3881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     struct device_attribute *attr,
3891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     char *buf)
390847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
3911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
3921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
3931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int val, val2;
3946fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	int ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
3956fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron					    &val, &val2, this_attr->address);
3961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
3971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret < 0)
3981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
399847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
4001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret == IIO_VAL_INT)
4011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return sprintf(buf, "%d\n", val);
4021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	else if (ret == IIO_VAL_INT_PLUS_MICRO) {
4031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (val2 < 0)
4041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			return sprintf(buf, "-%d.%06u\n", val, -val2);
4051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		else
4061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			return sprintf(buf, "%d.%06u\n", val, val2);
40771646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich	} else if (ret == IIO_VAL_INT_PLUS_NANO) {
40871646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich		if (val2 < 0)
40971646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich			return sprintf(buf, "-%d.%09u\n", val, -val2);
41071646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich		else
41171646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich			return sprintf(buf, "%d.%09u\n", val, val2);
4121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	} else
4131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return 0;
4141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
4151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_write_channel_info(struct device *dev,
4171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      struct device_attribute *attr,
4181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      const char *buf,
4191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      size_t len)
4201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
4211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
4221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
4235c04af04835269c194662be63fe168893fad667fMichael Hennerich	int ret, integer = 0, fract = 0, fract_mult = 100000;
4241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	bool integer_part = true, negative = false;
4251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	/* Assumes decimal - precision based on number of digits */
4276fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	if (!indio_dev->info->write_raw)
4281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return -EINVAL;
4295c04af04835269c194662be63fe168893fad667fMichael Hennerich
4305c04af04835269c194662be63fe168893fad667fMichael Hennerich	if (indio_dev->info->write_raw_get_fmt)
4315c04af04835269c194662be63fe168893fad667fMichael Hennerich		switch (indio_dev->info->write_raw_get_fmt(indio_dev,
4325c04af04835269c194662be63fe168893fad667fMichael Hennerich			this_attr->c, this_attr->address)) {
4335c04af04835269c194662be63fe168893fad667fMichael Hennerich		case IIO_VAL_INT_PLUS_MICRO:
4345c04af04835269c194662be63fe168893fad667fMichael Hennerich			fract_mult = 100000;
4355c04af04835269c194662be63fe168893fad667fMichael Hennerich			break;
4365c04af04835269c194662be63fe168893fad667fMichael Hennerich		case IIO_VAL_INT_PLUS_NANO:
4375c04af04835269c194662be63fe168893fad667fMichael Hennerich			fract_mult = 100000000;
4385c04af04835269c194662be63fe168893fad667fMichael Hennerich			break;
4395c04af04835269c194662be63fe168893fad667fMichael Hennerich		default:
4405c04af04835269c194662be63fe168893fad667fMichael Hennerich			return -EINVAL;
4415c04af04835269c194662be63fe168893fad667fMichael Hennerich		}
4425c04af04835269c194662be63fe168893fad667fMichael Hennerich
4431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (buf[0] == '-') {
4441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		negative = true;
4451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		buf++;
4461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
4475c04af04835269c194662be63fe168893fad667fMichael Hennerich
4481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	while (*buf) {
4491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if ('0' <= *buf && *buf <= '9') {
4501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (integer_part)
4511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				integer = integer*10 + *buf - '0';
4521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			else {
4535c04af04835269c194662be63fe168893fad667fMichael Hennerich				fract += fract_mult*(*buf - '0');
4545c04af04835269c194662be63fe168893fad667fMichael Hennerich				if (fract_mult == 1)
4551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					break;
4565c04af04835269c194662be63fe168893fad667fMichael Hennerich				fract_mult /= 10;
4571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			}
4581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		} else if (*buf == '\n') {
4591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (*(buf + 1) == '\0')
4601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				break;
4611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			else
4621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				return -EINVAL;
4631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		} else if (*buf == '.') {
4641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			integer_part = false;
4651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		} else {
4661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			return -EINVAL;
4671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
4681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		buf++;
4691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
4701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (negative) {
4711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (integer)
4721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			integer = -integer;
4731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		else
4745c04af04835269c194662be63fe168893fad667fMichael Hennerich			fract = -fract;
4751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
4761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4776fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	ret = indio_dev->info->write_raw(indio_dev, this_attr->c,
4785c04af04835269c194662be63fe168893fad667fMichael Hennerich					 integer, fract, this_attr->address);
4791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
4801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
4811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return len;
4831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
4841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic int __iio_build_postfix(struct iio_chan_spec const *chan,
4861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			       bool generic,
4871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			       const char *postfix,
4881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			       char **result)
4891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
4901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	char *all_post;
4911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	/* 3 options - generic, extend_name, modified - if generic, extend_name
4921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	* and modified cannot apply.*/
4931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
4941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (generic || (!chan->modified && !chan->extend_name)) {
4951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		all_post = kasprintf(GFP_KERNEL, "%s", postfix);
4961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	} else if (chan->modified) {
4971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		const char *intermediate;
4981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		switch (chan->type) {
4991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_INTENSITY:
5001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			intermediate
5011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				= iio_modifier_names_light[chan->channel2];
5021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			break;
5031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_ACCEL:
5041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_GYRO:
5051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_MAGN:
5061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_INCLI:
5071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_ROT:
5081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_ANGL:
5091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			intermediate
5101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				= iio_modifier_names_axial[chan->channel2];
5111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			break;
5121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		default:
5131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			return -EINVAL;
5141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
5151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (chan->extend_name)
5161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			all_post = kasprintf(GFP_KERNEL, "%s_%s_%s",
5171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     intermediate,
5181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     chan->extend_name,
5191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     postfix);
5201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		else
5211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			all_post = kasprintf(GFP_KERNEL, "%s_%s",
5221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     intermediate,
5231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     postfix);
5241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	} else
5251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		all_post = kasprintf(GFP_KERNEL, "%s_%s", chan->extend_name,
5261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     postfix);
5271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (all_post == NULL)
5281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return -ENOMEM;
5291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	*result = all_post;
5301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return 0;
5311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
5321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
533df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameronstatic
5341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronint __iio_device_attr_init(struct device_attribute *dev_attr,
5351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   const char *postfix,
5361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct iio_chan_spec const *chan,
5371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*readfunc)(struct device *dev,
5381d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       struct device_attribute *attr,
5391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       char *buf),
5401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*writefunc)(struct device *dev,
5411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						struct device_attribute *attr,
5421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						const char *buf,
5431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						size_t len),
5441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   bool generic)
5451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
5461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret;
5471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	char *name_format, *full_postfix;
5481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	sysfs_attr_init(&dev_attr->attr);
5491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	ret = __iio_build_postfix(chan, generic, postfix, &full_postfix);
5501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
551847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_ret;
5521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	/* Special case for types that uses both channel numbers in naming */
5541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (chan->type == IIO_IN_DIFF && !generic)
5551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		name_format
5561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			= kasprintf(GFP_KERNEL, "%s_%s",
5571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    iio_chan_type_name_spec_complex[chan->type],
5581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    full_postfix);
5591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	else if (generic || !chan->indexed)
5601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		name_format
5611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			= kasprintf(GFP_KERNEL, "%s_%s",
5621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    iio_chan_type_name_spec_shared[chan->type],
5631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    full_postfix);
5641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	else
5651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		name_format
5661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			= kasprintf(GFP_KERNEL, "%s%d_%s",
5671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    iio_chan_type_name_spec_shared[chan->type],
5681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    chan->channel,
5691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    full_postfix);
5701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (name_format == NULL) {
5721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = -ENOMEM;
5731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_free_full_postfix;
5741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
5751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	dev_attr->attr.name = kasprintf(GFP_KERNEL,
5761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					name_format,
5771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					chan->channel,
5781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					chan->channel2);
5791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (dev_attr->attr.name == NULL) {
5801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = -ENOMEM;
5811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_free_name_format;
5821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
5831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (readfunc) {
5851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->attr.mode |= S_IRUGO;
5861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->show = readfunc;
5871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
5881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (writefunc) {
5901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->attr.mode |= S_IWUSR;
5911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		dev_attr->store = writefunc;
5921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
5931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(name_format);
5941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(full_postfix);
5951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return 0;
5971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
5981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_free_name_format:
5991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(name_format);
6001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_free_full_postfix:
6011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(full_postfix);
6021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
6031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
6041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
6051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
606df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameronstatic void __iio_device_attr_deinit(struct device_attribute *dev_attr)
6071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
6081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(dev_attr->attr.name);
6091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
6101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronint __iio_add_chan_devattr(const char *postfix,
6121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   const char *group,
6131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct iio_chan_spec const *chan,
6141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*readfunc)(struct device *dev,
6151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       struct device_attribute *attr,
6161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					       char *buf),
6171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   ssize_t (*writefunc)(struct device *dev,
6181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						struct device_attribute *attr,
6191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						const char *buf,
6201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						size_t len),
6211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   int mask,
6221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   bool generic,
6231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct device *dev,
6241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   struct list_head *attr_list)
6251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
6261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret;
6271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *iio_attr, *t;
6281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	iio_attr = kzalloc(sizeof *iio_attr, GFP_KERNEL);
6301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (iio_attr == NULL) {
6311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = -ENOMEM;
6321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_ret;
6331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
6341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	ret = __iio_device_attr_init(&iio_attr->dev_attr,
6351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     postfix, chan,
6361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     readfunc, writefunc, generic);
6371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
6381d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_iio_dev_attr_free;
6391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	iio_attr->c = chan;
6401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	iio_attr->address = mask;
6411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_for_each_entry(t, attr_list, l)
6421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (strcmp(t->dev_attr.attr.name,
6431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			   iio_attr->dev_attr.attr.name) == 0) {
6441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (!generic)
6451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				dev_err(dev, "tried to double register : %s\n",
6461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					t->dev_attr.attr.name);
6471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = -EBUSY;
6481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_device_attr_deinit;
6491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
6501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	ret = sysfs_add_file_to_group(&dev->kobj,
6521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      &iio_attr->dev_attr.attr, group);
6531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret < 0)
6541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_device_attr_deinit;
6551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_add(&iio_attr->l, attr_list);
6571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return 0;
6591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_device_attr_deinit:
6611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	__iio_device_attr_deinit(&iio_attr->dev_attr);
6621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_iio_dev_attr_free:
6631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(iio_attr);
6641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
6651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
6661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
6671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic int iio_device_add_channel_sysfs(struct iio_dev *dev_info,
6691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					struct iio_chan_spec const *chan)
6701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
6711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret, i;
6721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (chan->channel < 0)
6751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return 0;
6761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (chan->processed_val)
6771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = __iio_add_chan_devattr("input", NULL, chan,
6781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &iio_read_channel_info,
6791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     NULL,
6801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     0,
6811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     0,
6821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &dev_info->dev,
6831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &dev_info->channel_attr_list);
6841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	else
6851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = __iio_add_chan_devattr("raw", NULL, chan,
6861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &iio_read_channel_info,
687ae19178eacfab141afdd886e002bb80c99dba63aMichael Hennerich					     (chan->type == IIO_OUT ?
688ae19178eacfab141afdd886e002bb80c99dba63aMichael Hennerich					     &iio_write_channel_info : NULL),
6891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     0,
6901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     0,
6911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &dev_info->dev,
6921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &dev_info->channel_attr_list);
6931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
6941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		goto error_ret;
6951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
6961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) {
6971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2],
6981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     NULL, chan,
6991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &iio_read_channel_info,
7001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &iio_write_channel_info,
7011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     (1 << i),
7021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     !(i%2),
7031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &dev_info->dev,
7041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &dev_info->channel_attr_list);
7051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret == -EBUSY && (i%2 == 0)) {
7061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = 0;
7071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			continue;
7081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
7091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret < 0)
7101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
7111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
7121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
7131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
7141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
7151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic void iio_device_remove_and_free_read_attr(struct iio_dev *dev_info,
7171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						 struct iio_dev_attr *p)
7181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
7191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	sysfs_remove_file_from_group(&dev_info->dev.kobj,
7201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				     &p->dev_attr.attr, NULL);
7211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(p->dev_attr.attr.name);
7221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	kfree(p);
7231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
7241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
7251b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameronstatic ssize_t iio_show_dev_name(struct device *dev,
7261b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron				 struct device_attribute *attr,
7271b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron				 char *buf)
7281b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron{
7291b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
7301b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron	return sprintf(buf, "%s\n", indio_dev->name);
7311b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron}
7321b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron
7331b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameronstatic DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
7341b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron
735f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameronstatic struct attribute *iio_base_dummy_attrs[] = {
736f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron	NULL
737f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron};
738f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameronstatic struct attribute_group iio_base_dummy_group = {
739f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron	.attrs = iio_base_dummy_attrs,
740f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron};
741f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron
7421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic int iio_device_register_sysfs(struct iio_dev *dev_info)
7431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
7441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int i, ret = 0;
7451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *p, *n;
7461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
747f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron	if (dev_info->info->attrs)
7486fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron		ret = sysfs_create_group(&dev_info->dev.kobj,
7496fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron					 dev_info->info->attrs);
750f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron	else
751f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron		ret = sysfs_create_group(&dev_info->dev.kobj,
752f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron					 &iio_base_dummy_group);
753f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron
754f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron	if (ret) {
755f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron		dev_err(dev_info->dev.parent,
756f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron			"Failed to register sysfs hooks\n");
757f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron		goto error_ret;
758847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
759847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
7601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	/*
7611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	 * New channel registration method - relies on the fact a group does
7621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	 *  not need to be initialized if it is name is NULL.
7631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	 */
7641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	INIT_LIST_HEAD(&dev_info->channel_attr_list);
7651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (dev_info->channels)
7661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		for (i = 0; i < dev_info->num_channels; i++) {
7671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = iio_device_add_channel_sysfs(dev_info,
7681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron							   &dev_info
7691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron							   ->channels[i]);
7701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (ret < 0)
7711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				goto error_clear_attrs;
7721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
773f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron	if (dev_info->name) {
7741b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron		ret = sysfs_add_file_to_group(&dev_info->dev.kobj,
7751b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron					      &dev_attr_name.attr,
7761b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron					      NULL);
7771b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron		if (ret)
7781b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron			goto error_clear_attrs;
7791b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron	}
7801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return 0;
7811b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron
7821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_clear_attrs:
7831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_for_each_entry_safe(p, n,
7841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 &dev_info->channel_attr_list, l) {
7851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		list_del(&p->l);
7861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		iio_device_remove_and_free_read_attr(dev_info, p);
7871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
7886fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	if (dev_info->info->attrs)
7896fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron		sysfs_remove_group(&dev_info->dev.kobj, dev_info->info->attrs);
790f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron	else
791f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron		sysfs_remove_group(&dev_info->dev.kobj, &iio_base_dummy_group);
792847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
793847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
7941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
795847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
796847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
797847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void iio_device_unregister_sysfs(struct iio_dev *dev_info)
798847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
7991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *p, *n;
8011b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron	if (dev_info->name)
8021b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron		sysfs_remove_file_from_group(&dev_info->dev.kobj,
8031b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron					     &dev_attr_name.attr,
8041b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron					     NULL);
8051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_for_each_entry_safe(p, n, &dev_info->channel_attr_list, l) {
8061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		list_del(&p->l);
8071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		iio_device_remove_and_free_read_attr(dev_info, p);
8081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
8091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8106fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	if (dev_info->info->attrs)
8116fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron		sysfs_remove_group(&dev_info->dev.kobj, dev_info->info->attrs);
812f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron	else
813f7256877c777d08f3af445840d94e37b11038fe2Jonathan Cameron		sysfs_remove_group(&dev_info->dev.kobj, &iio_base_dummy_group);
814847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
815847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
8161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_ev_type_text[] = {
8171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_TYPE_THRESH] = "thresh",
8181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_TYPE_MAG] = "mag",
8191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_TYPE_ROC] = "roc"
8201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
8211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_ev_dir_text[] = {
8231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_DIR_EITHER] = "either",
8241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_DIR_RISING] = "rising",
8251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	[IIO_EV_DIR_FALLING] = "falling"
8261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron};
8271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_state_store(struct device *dev,
8291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  struct device_attribute *attr,
8301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  const char *buf,
8311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  size_t len)
8321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
8331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
834aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
8351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret;
836c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	bool val;
837c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron
838c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	ret = strtobool(buf, &val);
839c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	if (ret < 0)
840c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron		return ret;
8411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8426fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	ret = indio_dev->info->write_event_config(indio_dev,
8436fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						  this_attr->address,
8446fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						  val);
8451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return (ret < 0) ? ret : len;
8461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
8471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_state_show(struct device *dev,
8491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 struct device_attribute *attr,
8501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 char *buf)
8511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
8521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
853aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
8546fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	int val = indio_dev->info->read_event_config(indio_dev,
8556fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						     this_attr->address);
8561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (val < 0)
8581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return val;
8591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	else
8601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return sprintf(buf, "%d\n", val);
8611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
8621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_value_show(struct device *dev,
8641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 struct device_attribute *attr,
8651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 char *buf)
8661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
8671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
8681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
8691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int val, ret;
8701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8716fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	ret = indio_dev->info->read_event_value(indio_dev,
8726fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						this_attr->address, &val);
8731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret < 0)
8741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
8751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return sprintf(buf, "%d\n", val);
8771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
8781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_ev_value_store(struct device *dev,
8801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  struct device_attribute *attr,
8811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  const char *buf,
8821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				  size_t len)
8831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
8841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev *indio_dev = dev_get_drvdata(dev);
8851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
8861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	unsigned long val;
8871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int ret;
8881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	ret = strict_strtoul(buf, 10, &val);
8901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret)
8911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
8921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8936fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	ret = indio_dev->info->write_event_value(indio_dev, this_attr->address,
8946fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						 val);
8951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (ret < 0)
8961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return ret;
8971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
8981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return len;
8991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
9001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
9011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic int iio_device_add_event_sysfs(struct iio_dev *dev_info,
9021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				      struct iio_chan_spec const *chan)
9031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
9041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
905df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameron	int ret = 0, i, mask = 0;
9061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	char *postfix;
9071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (!chan->event_mask)
9081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		return 0;
9091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
9101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	for_each_set_bit(i, &chan->event_mask, sizeof(chan->event_mask)*8) {
9111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		postfix = kasprintf(GFP_KERNEL, "%s_%s_en",
9121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    iio_ev_type_text[i/IIO_EV_TYPE_MAX],
9131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    iio_ev_dir_text[i%IIO_EV_TYPE_MAX]);
9141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (postfix == NULL) {
9151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = -ENOMEM;
9161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
9171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
9181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		switch (chan->type) {
9191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			/* Switch this to a table at some point */
9201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_IN:
9211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			mask = IIO_UNMOD_EVENT_CODE(chan->type, chan->channel,
9221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						    i/IIO_EV_TYPE_MAX,
9231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						    i%IIO_EV_TYPE_MAX);
9241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			break;
9251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_ACCEL:
9261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			mask = IIO_MOD_EVENT_CODE(chan->type, 0, chan->channel,
9271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						  i/IIO_EV_TYPE_MAX,
9281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						  i%IIO_EV_TYPE_MAX);
9291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			break;
9301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		case IIO_IN_DIFF:
9311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			mask = IIO_MOD_EVENT_CODE(chan->type, chan->channel,
9321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						  chan->channel2,
9331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						  i/IIO_EV_TYPE_MAX,
9341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						  i%IIO_EV_TYPE_MAX);
9351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			break;
9361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		default:
9371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			printk(KERN_INFO "currently unhandled type of event\n");
9389076faa9af99e6eb69fb8939b97ab701d14b3145Jonathan Cameron			continue;
9391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
940aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron		ret = __iio_add_chan_devattr(postfix,
941aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     NULL,
942aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     chan,
943aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     &iio_ev_state_show,
944aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     iio_ev_state_store,
945aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     mask,
946aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     /*HACK. - limits us to one
947aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					       event interface - fix by
948aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					       extending the bitmask - but
949aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					       how far*/
950aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     0,
9516fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron					     &dev_info->event_interfaces[0].dev,
952aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     &dev_info->event_interfaces[0].
953aaf370db7dad574e166f64cd9ad4129f12198145Jonathan Cameron					     dev_attr_list);
9541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		kfree(postfix);
9551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret)
9561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
9571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
9581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		postfix = kasprintf(GFP_KERNEL, "%s_%s_value",
9591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    iio_ev_type_text[i/IIO_EV_TYPE_MAX],
9601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				    iio_ev_dir_text[i%IIO_EV_TYPE_MAX]);
9611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (postfix == NULL) {
9621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = -ENOMEM;
9631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
9641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
9651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		ret = __iio_add_chan_devattr(postfix, NULL, chan,
9661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     iio_ev_value_show,
9671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     iio_ev_value_store,
9681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     mask,
9691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     0,
9701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &dev_info->event_interfaces[0]
9711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     .dev,
9721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &dev_info->event_interfaces[0]
9731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     .dev_attr_list);
9741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		kfree(postfix);
9751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		if (ret)
9761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			goto error_ret;
9771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
9781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
9791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
9801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret:
9811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	return ret;
9821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
9831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
984232b9cba130025d47531c5c539d6affc64950213Jonathan Cameronstatic inline void __iio_remove_event_config_attrs(struct iio_dev *dev_info,
985232b9cba130025d47531c5c539d6affc64950213Jonathan Cameron						  int i)
9861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{
9871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	struct iio_dev_attr *p, *n;
9881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	list_for_each_entry_safe(p, n,
989232b9cba130025d47531c5c539d6affc64950213Jonathan Cameron				 &dev_info->event_interfaces[i].
9901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				 dev_attr_list, l) {
9911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		sysfs_remove_file_from_group(&dev_info
992232b9cba130025d47531c5c539d6affc64950213Jonathan Cameron					     ->event_interfaces[i].dev.kobj,
9931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					     &p->dev_attr.attr,
994232b9cba130025d47531c5c539d6affc64950213Jonathan Cameron					     NULL);
9951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		kfree(p->dev_attr.attr.name);
9961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		kfree(p);
9971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
9981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}
9991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
1000847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic inline int __iio_add_event_config_attrs(struct iio_dev *dev_info, int i)
1001847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
10021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	int j;
1003847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret;
1004232b9cba130025d47531c5c539d6affc64950213Jonathan Cameron	INIT_LIST_HEAD(&dev_info->event_interfaces[i].dev_attr_list);
10051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	/* Dynically created from the channels array */
10061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	if (dev_info->channels) {
10071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		for (j = 0; j < dev_info->num_channels; j++) {
10081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = iio_device_add_event_sysfs(dev_info,
10091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron							 &dev_info
10101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron							 ->channels[j]);
10111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			if (ret)
10121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron				goto error_clear_attrs;
10131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		}
10141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron	}
1015847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
1016847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
10171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_clear_attrs:
1018232b9cba130025d47531c5c539d6affc64950213Jonathan Cameron	__iio_remove_event_config_attrs(dev_info, i);
1019847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1020847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
1021847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1022847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1023847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic int iio_device_register_eventset(struct iio_dev *dev_info)
1024847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1025847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret = 0, i, j;
1026847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
10276fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	if (dev_info->info->num_interrupt_lines == 0)
1028847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		return 0;
1029847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1030847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	dev_info->event_interfaces =
1031847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		kzalloc(sizeof(struct iio_event_interface)
10326fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron			*dev_info->info->num_interrupt_lines,
1033847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			GFP_KERNEL);
1034847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (dev_info->event_interfaces == NULL) {
1035847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ret = -ENOMEM;
1036847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_ret;
1037847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1038847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
10396fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	for (i = 0; i < dev_info->info->num_interrupt_lines; i++) {
1040847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ret = iio_setup_ev_int(&dev_info->event_interfaces[i],
1041c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron				       dev_name(&dev_info->dev),
1042c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron				       i,
10436fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron				       dev_info->info->driver_module,
1044847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron				       &dev_info->dev);
1045847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		if (ret) {
1046847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			dev_err(&dev_info->dev,
1047847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron				"Could not get chrdev interface\n");
1048cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron			goto error_free_setup_event_lines;
1049847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		}
1050847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
10515cba220b0a3211befd5514cbd822a97578ef5ed4Jonathan Cameron		dev_set_drvdata(&dev_info->event_interfaces[i].dev,
10525cba220b0a3211befd5514cbd822a97578ef5ed4Jonathan Cameron				(void *)dev_info);
10531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron
10546fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron		if (dev_info->info->event_attrs != NULL)
10551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			ret = sysfs_create_group(&dev_info
10561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						 ->event_interfaces[i]
10571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron						 .dev.kobj,
10586fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						 &dev_info->info
10596fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron						 ->event_attrs[i]);
10605cba220b0a3211befd5514cbd822a97578ef5ed4Jonathan Cameron
1061847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		if (ret) {
1062847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			dev_err(&dev_info->dev,
1063847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron				"Failed to register sysfs for event attrs");
1064cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron			iio_free_ev_int(&dev_info->event_interfaces[i]);
1065cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron			goto error_free_setup_event_lines;
1066847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		}
1067847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		ret = __iio_add_event_config_attrs(dev_info, i);
1068cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron		if (ret) {
1069cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron			if (dev_info->info->event_attrs != NULL)
1070cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron				sysfs_remove_group(&dev_info
1071cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron						   ->event_interfaces[i]
1072cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron						   .dev.kobj,
1073cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron						   &dev_info->info
1074cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron						   ->event_attrs[i]);
1075cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron			iio_free_ev_int(&dev_info->event_interfaces[i]);
1076cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron			goto error_free_setup_event_lines;
1077cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron		}
1078847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1079847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1080847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
1081847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1082cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameronerror_free_setup_event_lines:
1083cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron	for (j = 0; j < i; j++) {
1084cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron		__iio_remove_event_config_attrs(dev_info, j);
10856fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron		if (dev_info->info->event_attrs != NULL)
10861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			sysfs_remove_group(&dev_info
1087cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron					   ->event_interfaces[j].dev.kobj,
1088cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron					   &dev_info->info->event_attrs[j]);
1089847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		iio_free_ev_int(&dev_info->event_interfaces[j]);
1090cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron	}
1091847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	kfree(dev_info->event_interfaces);
1092847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
1093847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1094847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
1095847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1096847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1097847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void iio_device_unregister_eventset(struct iio_dev *dev_info)
1098847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1099847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int i;
1100847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
11016fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	if (dev_info->info->num_interrupt_lines == 0)
1102847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		return;
11036fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron	for (i = 0; i < dev_info->info->num_interrupt_lines; i++) {
11041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron		__iio_remove_event_config_attrs(dev_info, i);
11056fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron		if (dev_info->info->event_attrs != NULL)
11061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron			sysfs_remove_group(&dev_info
11071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron					   ->event_interfaces[i].dev.kobj,
11086fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron					   &dev_info->info->event_attrs[i]);
1109847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		iio_free_ev_int(&dev_info->event_interfaces[i]);
1110cc2439fdecb85f27866cab0ae1cbf21a9b61c423Jonathan Cameron	}
1111847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	kfree(dev_info->event_interfaces);
1112847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1113847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1114847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void iio_dev_release(struct device *device)
1115847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1116df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameron	struct iio_dev *dev_info = container_of(device, struct iio_dev, dev);
1117847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	iio_put();
1118df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameron	kfree(dev_info);
1119847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1120847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1121847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic struct device_type iio_dev_type = {
1122847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.name = "iio_device",
1123847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	.release = iio_dev_release,
1124847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron};
1125847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
11266f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameronstruct iio_dev *iio_allocate_device(int sizeof_priv)
1127847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
11286f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	struct iio_dev *dev;
11296f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	size_t alloc_size;
11306f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron
11316f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	alloc_size = sizeof(struct iio_dev);
11326f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	if (sizeof_priv) {
11336f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron		alloc_size = ALIGN(alloc_size, IIO_ALIGN);
11346f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron		alloc_size += sizeof_priv;
11356f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	}
11366f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	/* ensure 32-byte alignment of whole construct ? */
11376f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	alloc_size += IIO_ALIGN - 1;
11386f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron
11396f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron	dev = kzalloc(alloc_size, GFP_KERNEL);
1140847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1141847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (dev) {
1142847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		dev->dev.type = &iio_dev_type;
11435aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron		dev->dev.bus = &iio_bus_type;
1144847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		device_initialize(&dev->dev);
1145847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		dev_set_drvdata(&dev->dev, (void *)dev);
1146847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		mutex_init(&dev->mlock);
1147847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		iio_get();
1148847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1149847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1150847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return dev;
1151847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1152847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_allocate_device);
1153847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1154847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronvoid iio_free_device(struct iio_dev *dev)
1155847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1156847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (dev)
1157847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		iio_put_device(dev);
1158847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1159847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_free_device);
1160847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1161847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronint iio_device_register(struct iio_dev *dev_info)
1162847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1163847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	int ret;
1164847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1165c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	dev_info->id = iio_get_new_ida_val(&iio_ida);
1166c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	if (dev_info->id < 0) {
1167c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron		ret = dev_info->id;
1168847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		dev_err(&dev_info->dev, "Failed to get id\n");
1169847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_ret;
1170847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1171847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	dev_set_name(&dev_info->dev, "device%d", dev_info->id);
1172847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1173847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ret = device_add(&dev_info->dev);
1174847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret)
1175b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameron		goto error_free_ida;
1176847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ret = iio_device_register_sysfs(dev_info);
1177847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret) {
1178847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		dev_err(dev_info->dev.parent,
1179847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron			"Failed to register sysfs interfaces\n");
1180847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_del_device;
1181847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1182847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	ret = iio_device_register_eventset(dev_info);
1183847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (ret) {
1184847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		dev_err(dev_info->dev.parent,
1185c849d2538ebeef1ac26fad7a10c18b1e0fc35161Roel Van Nyen			"Failed to register event set\n");
1186847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		goto error_free_sysfs;
1187847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	}
1188847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (dev_info->modes & INDIO_RING_TRIGGERED)
1189847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		iio_device_register_trigger_consumer(dev_info);
1190847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1191847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return 0;
1192847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1193847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_free_sysfs:
1194847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	iio_device_unregister_sysfs(dev_info);
1195847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_del_device:
1196847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	device_del(&dev_info->dev);
1197b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameronerror_free_ida:
1198c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	iio_free_ida_val(&iio_ida, dev_info->id);
1199847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret:
1200847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	return ret;
1201847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1202847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_device_register);
1203847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1204847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronvoid iio_device_unregister(struct iio_dev *dev_info)
1205847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1206847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	if (dev_info->modes & INDIO_RING_TRIGGERED)
1207847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron		iio_device_unregister_trigger_consumer(dev_info);
1208847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	iio_device_unregister_eventset(dev_info);
1209847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	iio_device_unregister_sysfs(dev_info);
1210c74b0de1666f8b8f6c65e1e944deff71fed0769aJonathan Cameron	iio_free_ida_val(&iio_ida, dev_info->id);
1211847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	device_unregister(&dev_info->dev);
1212847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1213847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_device_unregister);
1214847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1215847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronvoid iio_put(void)
1216847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1217847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	module_put(THIS_MODULE);
1218847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1219847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1220847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronvoid iio_get(void)
1221847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{
1222847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron	__module_get(THIS_MODULE);
1223847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}
1224847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1225847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronsubsys_initcall(iio_init);
1226847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronmodule_exit(iio_exit);
1227847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron
1228847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
1229847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_DESCRIPTION("Industrial I/O core");
1230847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_LICENSE("GPL");
1231