diff options
author | Jonathan Cameron <jic23@cam.ac.uk> | 2009-08-18 13:06:19 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-09-15 15:02:24 -0400 |
commit | 847ec80bbaa76aae41062d6802cea9c1b2289f14 (patch) | |
tree | fd68009e13b5abd5e02704c29b6639be9df3d630 | |
parent | a5ca2dfc4ebd33e18f981f562833c39efdc2585c (diff) |
Staging: IIO: core support for device registration and management
Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/staging/Kconfig | 2 | ||||
-rw-r--r-- | drivers/staging/Makefile | 1 | ||||
-rw-r--r-- | drivers/staging/iio/Kconfig | 11 | ||||
-rw-r--r-- | drivers/staging/iio/Makefile | 6 | ||||
-rw-r--r-- | drivers/staging/iio/chrdev.h | 118 | ||||
-rw-r--r-- | drivers/staging/iio/iio.h | 411 | ||||
-rw-r--r-- | drivers/staging/iio/industrialio-core.c | 851 | ||||
-rw-r--r-- | drivers/staging/iio/sysfs.h | 293 | ||||
-rw-r--r-- | drivers/staging/iio/trigger_consumer.h | 26 |
9 files changed, 1719 insertions, 0 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index d08cd8d56317..4d836a023439 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig | |||
@@ -137,5 +137,7 @@ source "drivers/staging/rar/Kconfig" | |||
137 | 137 | ||
138 | source "drivers/staging/sep/Kconfig" | 138 | source "drivers/staging/sep/Kconfig" |
139 | 139 | ||
140 | source "drivers/staging/iio/Kconfig" | ||
141 | |||
140 | endif # !STAGING_EXCLUDE_BUILD | 142 | endif # !STAGING_EXCLUDE_BUILD |
141 | endif # STAGING | 143 | endif # STAGING |
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 9a23438bf7cb..f0c33eec012d 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile | |||
@@ -50,3 +50,4 @@ obj-$(CONFIG_HYPERV) += hv/ | |||
50 | obj-$(CONFIG_VME_BUS) += vme/ | 50 | obj-$(CONFIG_VME_BUS) += vme/ |
51 | obj-$(CONFIG_RAR_REGISTER) += rar/ | 51 | obj-$(CONFIG_RAR_REGISTER) += rar/ |
52 | obj-$(CONFIG_DX_SEP) += sep/ | 52 | obj-$(CONFIG_DX_SEP) += sep/ |
53 | obj-$(CONFIG_IIO) += iio/ | ||
diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig new file mode 100644 index 000000000000..09e4101939ef --- /dev/null +++ b/drivers/staging/iio/Kconfig | |||
@@ -0,0 +1,11 @@ | |||
1 | # | ||
2 | # Industrial I/O subsytem configuration | ||
3 | # | ||
4 | |||
5 | menuconfig IIO | ||
6 | tristate "Industrial I/O support" | ||
7 | ---help--- | ||
8 | The industrial I/O subsystem provides a unified framework for | ||
9 | drivers for many different types of embedded sensors using a | ||
10 | number of different physical interfaces (i2c, spi etc). See | ||
11 | Documentation/industrialio for more information. | ||
diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile new file mode 100644 index 000000000000..92b462a125e8 --- /dev/null +++ b/drivers/staging/iio/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # | ||
2 | # Makefile for the industrial I/O core. | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_IIO) += industrialio.o | ||
6 | industrialio-y := industrialio-core.o | ||
diff --git a/drivers/staging/iio/chrdev.h b/drivers/staging/iio/chrdev.h new file mode 100644 index 000000000000..8bc64bf08459 --- /dev/null +++ b/drivers/staging/iio/chrdev.h | |||
@@ -0,0 +1,118 @@ | |||
1 | /* The industrial I/O core - character device related | ||
2 | * | ||
3 | * Copyright (c) 2008 Jonathan Cameron | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 2 as published by | ||
7 | * the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #ifndef _IIO_CHRDEV_H_ | ||
11 | #define _IIO_CHRDEV_H_ | ||
12 | struct iio_dev; | ||
13 | |||
14 | /** | ||
15 | * struct iio_handler - Structure used to specify file operations | ||
16 | * for a particular chrdev | ||
17 | * @chrdev: character device structure | ||
18 | * @id: the location in the handler table - used for deallocation. | ||
19 | * @flags: file operations related flags including busy flag. | ||
20 | * @private: handler specific data used by the fileops registered with | ||
21 | * the chrdev. | ||
22 | */ | ||
23 | struct iio_handler { | ||
24 | struct cdev chrdev; | ||
25 | int id; | ||
26 | unsigned long flags; | ||
27 | void *private; | ||
28 | }; | ||
29 | |||
30 | #define iio_cdev_to_handler(cd) \ | ||
31 | container_of(cd, struct iio_handler, chrdev) | ||
32 | |||
33 | /** | ||
34 | * struct iio_event_data - The actual event being pushed to userspace | ||
35 | * @id: event identifier | ||
36 | * @timestamp: best estimate of time of event occurance (often from | ||
37 | * the interrupt handler) | ||
38 | */ | ||
39 | struct iio_event_data { | ||
40 | int id; | ||
41 | s64 timestamp; | ||
42 | }; | ||
43 | |||
44 | /** | ||
45 | * struct iio_detected_event_list - list element for events that have occured | ||
46 | * @list: linked list header | ||
47 | * @ev: the event itself | ||
48 | * @shared_pointer: used when the event is shared - i.e. can be escallated | ||
49 | * on demand (eg ring buffer 50%->100% full) | ||
50 | */ | ||
51 | struct iio_detected_event_list { | ||
52 | struct list_head list; | ||
53 | struct iio_event_data ev; | ||
54 | struct iio_shared_ev_pointer *shared_pointer; | ||
55 | }; | ||
56 | /** | ||
57 | * struct iio_shared_ev_pointer - allows shared events to identify if currently | ||
58 | * in the detected event list | ||
59 | * @ev_p: pointer to detected event list element (null if not in list) | ||
60 | * @lock: protect this element to prevent simultaneous edit and remove | ||
61 | */ | ||
62 | struct iio_shared_ev_pointer { | ||
63 | struct iio_detected_event_list *ev_p; | ||
64 | spinlock_t lock; | ||
65 | }; | ||
66 | |||
67 | /** | ||
68 | * struct iio_event_interface - chrdev interface for an event line | ||
69 | * @dev: device assocated with event interface | ||
70 | * @handler: fileoperations and related control for the chrdev | ||
71 | * @wait: wait queue to allow blocking reads of events | ||
72 | * @event_list_lock: mutex to protect the list of detected events | ||
73 | * @det_events: list of detected events | ||
74 | * @max_events: maximum number of events before new ones are dropped | ||
75 | * @current_events: number of events in detected list | ||
76 | * @id: indentifier to allow the event interface to know which | ||
77 | * physical line it corresponds to | ||
78 | * @owner: ensure the driver module owns the file, not iio | ||
79 | * @private: driver specific data | ||
80 | * @_name: used internally to store the sysfs name for minor id | ||
81 | * attribute | ||
82 | */ | ||
83 | struct iio_event_interface { | ||
84 | struct device dev; | ||
85 | struct iio_handler handler; | ||
86 | wait_queue_head_t wait; | ||
87 | struct mutex event_list_lock; | ||
88 | struct iio_detected_event_list det_events; | ||
89 | int max_events; | ||
90 | int current_events; | ||
91 | int id; | ||
92 | struct iio_chrdev_minor_attr attr; | ||
93 | struct module *owner; | ||
94 | void *private; | ||
95 | char _name[20]; | ||
96 | char _attrname[20]; | ||
97 | }; | ||
98 | |||
99 | /** | ||
100 | * struct iio_event_handler_list - element in list of handlers for events | ||
101 | * @list: list header | ||
102 | * @refcount: as the handler may be shared between multiple device | ||
103 | * side events, reference counting ensures clean removal | ||
104 | * @exist_lock: prevents race conditions related to refcount useage. | ||
105 | * @handler: event handler function - called on event if this | ||
106 | * event_handler is enabled. | ||
107 | * | ||
108 | * Each device has one list of these per interrupt line | ||
109 | **/ | ||
110 | struct iio_event_handler_list { | ||
111 | struct list_head list; | ||
112 | int refcount; | ||
113 | struct mutex exist_lock; | ||
114 | int (*handler)(struct iio_dev *dev_info, int index, s64 timestamp, | ||
115 | int no_test); | ||
116 | }; | ||
117 | |||
118 | #endif | ||
diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h new file mode 100644 index 000000000000..25ccb809221e --- /dev/null +++ b/drivers/staging/iio/iio.h | |||
@@ -0,0 +1,411 @@ | |||
1 | /* The industrial I/O core | ||
2 | * | ||
3 | * Copyright (c) 2008 Jonathan Cameron | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 2 as published by | ||
7 | * the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #ifndef _INDUSTRIAL_IO_H_ | ||
11 | #define _INDUSTRIAL_IO_H_ | ||
12 | |||
13 | #include <linux/device.h> | ||
14 | #include <linux/cdev.h> | ||
15 | #include "sysfs.h" | ||
16 | #include "chrdev.h" | ||
17 | |||
18 | /* IIO TODO LIST */ | ||
19 | /* Static device specific elements (conversion factors etc) | ||
20 | * should be exported via sysfs | ||
21 | * | ||
22 | * Provide means of adjusting timer accuracy. | ||
23 | * Currently assumes nano seconds. | ||
24 | */ | ||
25 | |||
26 | /* Event interface flags */ | ||
27 | #define IIO_BUSY_BIT_POS 1 | ||
28 | |||
29 | struct iio_dev; | ||
30 | |||
31 | /** | ||
32 | * iio_get_time_ns() - utility function to get a time stamp for events etc | ||
33 | **/ | ||
34 | static inline s64 iio_get_time_ns(void) | ||
35 | { | ||
36 | struct timespec ts; | ||
37 | /* | ||
38 | * calls getnstimeofday. | ||
39 | * If hrtimers then up to ns accurate, if not microsecond. | ||
40 | */ | ||
41 | ktime_get_real_ts(&ts); | ||
42 | |||
43 | return timespec_to_ns(&ts); | ||
44 | } | ||
45 | |||
46 | /** | ||
47 | * iio_add_event_to_list() - Wraps adding to event lists | ||
48 | * @el: the list element of the event to be handled. | ||
49 | * @head: the list associated with the event handler being used. | ||
50 | * | ||
51 | * Does reference counting to allow shared handlers. | ||
52 | **/ | ||
53 | void iio_add_event_to_list(struct iio_event_handler_list *el, | ||
54 | struct list_head *head); | ||
55 | |||
56 | /** | ||
57 | * iio_remove_event_from_list() - Wraps removing from event list | ||
58 | * @el: element to be removed | ||
59 | * @head: associate list head for the interrupt handler. | ||
60 | * | ||
61 | * Does reference counting to allow shared handlers. | ||
62 | **/ | ||
63 | void iio_remove_event_from_list(struct iio_event_handler_list *el, | ||
64 | struct list_head *head); | ||
65 | |||
66 | /* Device operating modes */ | ||
67 | #define INDIO_DIRECT_MODE 0x01 | ||
68 | #define INDIO_RING_TRIGGERED 0x02 | ||
69 | #define INDIO_RING_HARDWARE_BUFFER 0x08 | ||
70 | |||
71 | #define INDIO_ALL_RING_MODES (INDIO_RING_TRIGGERED | INDIO_RING_HARDWARE_BUFFER) | ||
72 | |||
73 | /* Vast majority of this is set by the industrialio subsystem on a | ||
74 | * call to iio_device_register. */ | ||
75 | |||
76 | /** | ||
77 | * struct iio_dev - industrial I/O device | ||
78 | * @id: [INTERN] used to identify device internally | ||
79 | * @dev_data: [DRIVER] device specific data | ||
80 | * @modes: [DRIVER] operating modes supported by device | ||
81 | * @currentmode: [DRIVER] current operating mode | ||
82 | * @dev: [DRIVER] device structure, should be assigned a parent | ||
83 | * and owner | ||
84 | * @attrs: [DRIVER] general purpose device attributes | ||
85 | * @driver_module: [DRIVER] module structure used to ensure correct | ||
86 | * ownership of chrdevs etc | ||
87 | * @num_interrupt_lines:[DRIVER] number of physical interrupt lines from device | ||
88 | * @interrupts: [INTERN] interrupt line specific event lists etc | ||
89 | * @event_attrs: [DRIVER] event control attributes | ||
90 | * @event_conf_attrs: [DRIVER] event configuration attributes | ||
91 | * @event_interfaces: [INTERN] event chrdevs associated with interrupt lines | ||
92 | * @ring: [DRIVER] any ring buffer present | ||
93 | * @mlock: [INTERN] lock used to prevent simultaneous device state | ||
94 | * changes | ||
95 | * @scan_el_attrs: [DRIVER] control of scan elements if that scan mode | ||
96 | * control method is used | ||
97 | * @scan_count: [INTERN] the number of elements in the current scan mode | ||
98 | * @scan_mask: [INTERN] bitmask used in masking scan mode elements | ||
99 | * @scan_timestamp: [INTERN] does the scan mode include a timestamp | ||
100 | * @trig: [INTERN] current device trigger (ring buffer modes) | ||
101 | * @pollfunc: [DRIVER] function run on trigger being recieved | ||
102 | **/ | ||
103 | struct iio_dev { | ||
104 | int id; | ||
105 | void *dev_data; | ||
106 | int modes; | ||
107 | int currentmode; | ||
108 | struct device dev; | ||
109 | const struct attribute_group *attrs; | ||
110 | struct module *driver_module; | ||
111 | |||
112 | int num_interrupt_lines; | ||
113 | struct iio_interrupt **interrupts; | ||
114 | struct attribute_group *event_attrs; | ||
115 | struct attribute_group *event_conf_attrs; | ||
116 | |||
117 | struct iio_event_interface *event_interfaces; | ||
118 | |||
119 | struct iio_ring_buffer *ring; | ||
120 | struct mutex mlock; | ||
121 | |||
122 | struct attribute_group *scan_el_attrs; | ||
123 | int scan_count; | ||
124 | |||
125 | u16 scan_mask; | ||
126 | bool scan_timestamp; | ||
127 | struct iio_trigger *trig; | ||
128 | struct iio_poll_func *pollfunc; | ||
129 | }; | ||
130 | |||
131 | /* | ||
132 | * These are mainly provided to allow for a change of implementation if a device | ||
133 | * has a large number of scan elements | ||
134 | */ | ||
135 | #define IIO_MAX_SCAN_LENGTH 15 | ||
136 | |||
137 | static inline int iio_scan_mask_query(struct iio_dev *dev_info, int bit) | ||
138 | { | ||
139 | if (bit > IIO_MAX_SCAN_LENGTH) | ||
140 | return -EINVAL; | ||
141 | else | ||
142 | return !!(dev_info->scan_mask & (1 << bit)); | ||
143 | }; | ||
144 | |||
145 | static inline int iio_scan_mask_set(struct iio_dev *dev_info, int bit) | ||
146 | { | ||
147 | if (bit > IIO_MAX_SCAN_LENGTH) | ||
148 | return -EINVAL; | ||
149 | dev_info->scan_mask |= (1 << bit); | ||
150 | dev_info->scan_count++; | ||
151 | return 0; | ||
152 | }; | ||
153 | |||
154 | static inline int iio_scan_mask_clear(struct iio_dev *dev_info, int bit) | ||
155 | { | ||
156 | if (bit > IIO_MAX_SCAN_LENGTH) | ||
157 | return -EINVAL; | ||
158 | dev_info->scan_mask &= ~(1 << bit); | ||
159 | dev_info->scan_count--; | ||
160 | return 0; | ||
161 | }; | ||
162 | |||
163 | /** | ||
164 | * iio_scan_mask_count_to_right() - how many scan elements occur before here | ||
165 | * @dev_info: the iio_device whose scan mode we are querying | ||
166 | * @bit: which number scan element is this | ||
167 | **/ | ||
168 | static inline int iio_scan_mask_count_to_right(struct iio_dev *dev_info, | ||
169 | int bit) | ||
170 | { | ||
171 | int count = 0; | ||
172 | int mask = (1 << bit); | ||
173 | if (bit > IIO_MAX_SCAN_LENGTH) | ||
174 | return -EINVAL; | ||
175 | while (mask) { | ||
176 | mask >>= 1; | ||
177 | if (mask & dev_info->scan_mask) | ||
178 | count++; | ||
179 | } | ||
180 | |||
181 | return count; | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * iio_device_register() - register a device with the IIO subsystem | ||
186 | * @dev_info: Device structure filled by the device driver | ||
187 | **/ | ||
188 | int iio_device_register(struct iio_dev *dev_info); | ||
189 | |||
190 | /** | ||
191 | * iio_device_unregister() - unregister a device from the IIO subsystem | ||
192 | * @dev_info: Device structure representing the device. | ||
193 | **/ | ||
194 | void iio_device_unregister(struct iio_dev *dev_info); | ||
195 | |||
196 | /** | ||
197 | * struct iio_interrupt - wrapper used to allow easy handling of multiple | ||
198 | * physical interrupt lines | ||
199 | * @dev_info: the iio device for which the is an interrupt line | ||
200 | * @line_number: associated line number | ||
201 | * @id: idr allocated unique id number | ||
202 | * @irq: associate interrupt number | ||
203 | * @ev_list: event handler list for associated events | ||
204 | * @ev_list_lock: ensure only one access to list at a time | ||
205 | **/ | ||
206 | struct iio_interrupt { | ||
207 | struct iio_dev *dev_info; | ||
208 | int line_number; | ||
209 | int id; | ||
210 | int irq; | ||
211 | struct list_head ev_list; | ||
212 | spinlock_t ev_list_lock; | ||
213 | }; | ||
214 | |||
215 | #define to_iio_interrupt(i) container_of(i, struct iio_interrupt, ev_list) | ||
216 | |||
217 | /** | ||
218 | * iio_register_interrupt_line() - Tell IIO about interrupt lines | ||
219 | * | ||
220 | * @irq: Typically provided via platform data | ||
221 | * @dev_info: IIO device info structure for device | ||
222 | * @line_number: Which interrupt line of the device is this? | ||
223 | * @type: Interrupt type (e.g. edge triggered etc) | ||
224 | * @name: Identifying name. | ||
225 | **/ | ||
226 | int iio_register_interrupt_line(unsigned int irq, | ||
227 | struct iio_dev *dev_info, | ||
228 | int line_number, | ||
229 | unsigned long type, | ||
230 | const char *name); | ||
231 | |||
232 | void iio_unregister_interrupt_line(struct iio_dev *dev_info, | ||
233 | int line_number); | ||
234 | |||
235 | |||
236 | |||
237 | /** | ||
238 | * iio_push_event() - try to add event to the list for userspace reading | ||
239 | * @dev_info: IIO device structure | ||
240 | * @ev_line: Which event line (hardware interrupt) | ||
241 | * @ev_code: What event | ||
242 | * @timestamp: When the event occured | ||
243 | **/ | ||
244 | int iio_push_event(struct iio_dev *dev_info, | ||
245 | int ev_line, | ||
246 | int ev_code, | ||
247 | s64 timestamp); | ||
248 | |||
249 | /** | ||
250 | * struct iio_work_cont - container for when singleton handler case matters | ||
251 | * @ws: [DEVICE]work_struct when not only possible event | ||
252 | * @ws_nocheck: [DEVICE]work_struct when only possible event | ||
253 | * @address: [DEVICE]associated register address | ||
254 | * @mask: [DEVICE]associated mask for identifying event source | ||
255 | * @st: [DEVICE]device specific state information | ||
256 | **/ | ||
257 | struct iio_work_cont { | ||
258 | struct work_struct ws; | ||
259 | struct work_struct ws_nocheck; | ||
260 | int address; | ||
261 | int mask; | ||
262 | void *st; | ||
263 | }; | ||
264 | |||
265 | #define to_iio_work_cont_check(_ws) \ | ||
266 | container_of(_ws, struct iio_work_cont, ws) | ||
267 | |||
268 | #define to_iio_work_cont_no_check(_ws) \ | ||
269 | container_of(_ws, struct iio_work_cont, ws_nocheck) | ||
270 | |||
271 | /** | ||
272 | * iio_init_work_cont() - intiialize the elements of a work container | ||
273 | * @cont: the work container | ||
274 | * @_checkfunc: function called when there are multiple possible int sources | ||
275 | * @_nocheckfunc: function for when there is only one int source | ||
276 | * @_add: driver dependant, typically a register address | ||
277 | * @_mask: driver dependant, typically a bit mask for a register | ||
278 | * @_st: driver dependant, typically pointer to a device state structure | ||
279 | **/ | ||
280 | static inline void | ||
281 | iio_init_work_cont(struct iio_work_cont *cont, | ||
282 | void (*_checkfunc)(struct work_struct *), | ||
283 | void (*_nocheckfunc)(struct work_struct *), | ||
284 | int _add, int _mask, void *_st) | ||
285 | { | ||
286 | INIT_WORK(&(cont)->ws, _checkfunc); | ||
287 | INIT_WORK(&(cont)->ws_nocheck, _nocheckfunc); | ||
288 | cont->address = _add; | ||
289 | cont->mask = _mask; | ||
290 | cont->st = _st; | ||
291 | } | ||
292 | /** | ||
293 | * __iio_push_event() tries to add an event to the list associated with a chrdev | ||
294 | * @ev_int: the event interface to which we are pushing the event | ||
295 | * @ev_code: the outgoing event code | ||
296 | * @timestamp: timestamp of the event | ||
297 | * @shared_pointer_p: the shared event pointer | ||
298 | **/ | ||
299 | int __iio_push_event(struct iio_event_interface *ev_int, | ||
300 | int ev_code, | ||
301 | s64 timestamp, | ||
302 | struct iio_shared_ev_pointer* | ||
303 | shared_pointer_p); | ||
304 | /** | ||
305 | * __iio_change_event() change an event code in case of event escallation | ||
306 | * @ev: the evnet to be changed | ||
307 | * @ev_code: new event code | ||
308 | * @timestamp: new timestamp | ||
309 | **/ | ||
310 | void __iio_change_event(struct iio_detected_event_list *ev, | ||
311 | int ev_code, | ||
312 | s64 timestamp); | ||
313 | |||
314 | /** | ||
315 | * iio_setup_ev_int() Configure an event interface (chrdev) | ||
316 | * @name: name used for resulting sysfs directory etc. | ||
317 | * @ev_int: interface we are configuring | ||
318 | * @owner: module that is responsible for registering this ev_int | ||
319 | * @dev: device whose ev_int this is | ||
320 | **/ | ||
321 | int iio_setup_ev_int(struct iio_event_interface *ev_int, | ||
322 | const char *name, | ||
323 | struct module *owner, | ||
324 | struct device *dev); | ||
325 | |||
326 | void iio_free_ev_int(struct iio_event_interface *ev_int); | ||
327 | |||
328 | /** | ||
329 | * iio_allocate_chrdev() - Allocate a chrdev | ||
330 | * @handler: struct that contains relevant file handling for chrdev | ||
331 | * @dev_info: iio_dev for which chrdev is being created | ||
332 | **/ | ||
333 | int iio_allocate_chrdev(struct iio_handler *handler, struct iio_dev *dev_info); | ||
334 | void iio_deallocate_chrdev(struct iio_handler *handler); | ||
335 | |||
336 | /* Used to distinguish between bipolar and unipolar scan elemenents. | ||
337 | * Whilst this may seem obvious, we may well want to change the representation | ||
338 | * in the future!*/ | ||
339 | #define IIO_SIGNED(a) -(a) | ||
340 | #define IIO_UNSIGNED(a) (a) | ||
341 | |||
342 | extern dev_t iio_devt; | ||
343 | extern struct class iio_class; | ||
344 | |||
345 | /** | ||
346 | * iio_put_device() - reference counted deallocated of struct device | ||
347 | * @dev: the iio_device containing the device | ||
348 | **/ | ||
349 | static inline void iio_put_device(struct iio_dev *dev) | ||
350 | { | ||
351 | if (dev) | ||
352 | put_device(&dev->dev); | ||
353 | }; | ||
354 | |||
355 | /** | ||
356 | * to_iio_dev() - get iio_dev for which we have have the struct device | ||
357 | * @d: the struct device | ||
358 | **/ | ||
359 | static inline struct iio_dev *to_iio_dev(struct device *d) | ||
360 | { | ||
361 | return container_of(d, struct iio_dev, dev); | ||
362 | }; | ||
363 | |||
364 | /** | ||
365 | * iio_dev_get_devdata() - helper function gets device specific data | ||
366 | * @d: the iio_dev associated with the device | ||
367 | **/ | ||
368 | static inline void *iio_dev_get_devdata(struct iio_dev *d) | ||
369 | { | ||
370 | return d->dev_data; | ||
371 | } | ||
372 | |||
373 | /** | ||
374 | * iio_allocate_device() - allocate an iio_dev from a driver | ||
375 | **/ | ||
376 | struct iio_dev *iio_allocate_device(void); | ||
377 | |||
378 | /** | ||
379 | * iio_free_device() - free an iio_dev from a driver | ||
380 | **/ | ||
381 | void iio_free_device(struct iio_dev *dev); | ||
382 | |||
383 | /** | ||
384 | * iio_put() - internal module reference count reduce | ||
385 | **/ | ||
386 | void iio_put(void); | ||
387 | |||
388 | /** | ||
389 | * iio_get() - internal module reference count increase | ||
390 | **/ | ||
391 | void iio_get(void); | ||
392 | |||
393 | /* Ring buffer related */ | ||
394 | int iio_device_get_chrdev_minor(void); | ||
395 | void iio_device_free_chrdev_minor(int val); | ||
396 | |||
397 | /** | ||
398 | * iio_ring_enabled() helper function to test if any form of ring enabled | ||
399 | **/ | ||
400 | static inline bool iio_ring_enabled(struct iio_dev *dev_info) | ||
401 | { | ||
402 | return dev_info->currentmode | ||
403 | & (INDIO_RING_TRIGGERED | ||
404 | | INDIO_RING_HARDWARE_BUFFER); | ||
405 | }; | ||
406 | |||
407 | struct idr; | ||
408 | |||
409 | int iio_get_new_idr_val(struct idr *this_idr); | ||
410 | void iio_free_idr_val(struct idr *this_idr, int id); | ||
411 | #endif /* _INDUSTRIAL_IO_H_ */ | ||
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c new file mode 100644 index 000000000000..660a9c1a1f3f --- /dev/null +++ b/drivers/staging/iio/industrialio-core.c | |||
@@ -0,0 +1,851 @@ | |||
1 | /* The industrial I/O core | ||
2 | * | ||
3 | * Copyright (c) 2008 Jonathan Cameron | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 2 as published by | ||
7 | * the Free Software Foundation. | ||
8 | * | ||
9 | * Based on elements of hwmon and input subsystems. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/idr.h> | ||
15 | #include <linux/kdev_t.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/poll.h> | ||
21 | #include <linux/cdev.h> | ||
22 | #include "iio.h" | ||
23 | #include "trigger_consumer.h" | ||
24 | |||
25 | #define IIO_ID_PREFIX "device" | ||
26 | #define IIO_ID_FORMAT IIO_ID_PREFIX "%d" | ||
27 | |||
28 | /* IDR to assign each registered device a unique id*/ | ||
29 | static DEFINE_IDR(iio_idr); | ||
30 | |||
31 | /* IDR for general event identifiers */ | ||
32 | static DEFINE_IDR(iio_event_idr); | ||
33 | /* IDR to allocate character device minor numbers */ | ||
34 | static DEFINE_IDR(iio_chrdev_idr); | ||
35 | /* Lock used to protect both of the above */ | ||
36 | static DEFINE_SPINLOCK(iio_idr_lock); | ||
37 | |||
38 | dev_t iio_devt; | ||
39 | EXPORT_SYMBOL(iio_devt); | ||
40 | |||
41 | #define IIO_DEV_MAX 256 | ||
42 | static char *iio_nodename(struct device *dev) | ||
43 | { | ||
44 | return kasprintf(GFP_KERNEL, "iio/%s", dev_name(dev)); | ||
45 | } | ||
46 | |||
47 | struct class iio_class = { | ||
48 | .name = "iio", | ||
49 | .nodename = iio_nodename, | ||
50 | }; | ||
51 | EXPORT_SYMBOL(iio_class); | ||
52 | |||
53 | void __iio_change_event(struct iio_detected_event_list *ev, | ||
54 | int ev_code, | ||
55 | s64 timestamp) | ||
56 | { | ||
57 | ev->ev.id = ev_code; | ||
58 | ev->ev.timestamp = timestamp; | ||
59 | } | ||
60 | EXPORT_SYMBOL(__iio_change_event); | ||
61 | |||
62 | /* Used both in the interrupt line put events and the ring buffer ones */ | ||
63 | |||
64 | /* Note that in it's current form someone has to be listening before events | ||
65 | * are queued. Hence a client MUST open the chrdev before the ring buffer is | ||
66 | * switched on. | ||
67 | */ | ||
68 | int __iio_push_event(struct iio_event_interface *ev_int, | ||
69 | int ev_code, | ||
70 | s64 timestamp, | ||
71 | struct iio_shared_ev_pointer * | ||
72 | shared_pointer_p) | ||
73 | { | ||
74 | struct iio_detected_event_list *ev; | ||
75 | int ret = 0; | ||
76 | |||
77 | /* Does anyone care? */ | ||
78 | mutex_lock(&ev_int->event_list_lock); | ||
79 | if (test_bit(IIO_BUSY_BIT_POS, &ev_int->handler.flags)) { | ||
80 | if (ev_int->current_events == ev_int->max_events) | ||
81 | return 0; | ||
82 | ev = kmalloc(sizeof(*ev), GFP_KERNEL); | ||
83 | if (ev == NULL) { | ||
84 | ret = -ENOMEM; | ||
85 | goto error_ret; | ||
86 | } | ||
87 | ev->ev.id = ev_code; | ||
88 | ev->ev.timestamp = timestamp; | ||
89 | ev->shared_pointer = shared_pointer_p; | ||
90 | if (ev->shared_pointer) | ||
91 | shared_pointer_p->ev_p = ev; | ||
92 | |||
93 | list_add_tail(&ev->list, &ev_int->det_events.list); | ||
94 | ev_int->current_events++; | ||
95 | mutex_unlock(&ev_int->event_list_lock); | ||
96 | wake_up_interruptible(&ev_int->wait); | ||
97 | } else | ||
98 | mutex_unlock(&ev_int->event_list_lock); | ||
99 | |||
100 | error_ret: | ||
101 | return ret; | ||
102 | } | ||
103 | EXPORT_SYMBOL(__iio_push_event); | ||
104 | |||
105 | int iio_push_event(struct iio_dev *dev_info, | ||
106 | int ev_line, | ||
107 | int ev_code, | ||
108 | s64 timestamp) | ||
109 | { | ||
110 | return __iio_push_event(&dev_info->event_interfaces[ev_line], | ||
111 | ev_code, timestamp, NULL); | ||
112 | } | ||
113 | EXPORT_SYMBOL(iio_push_event); | ||
114 | |||
115 | /* Generic interrupt line interrupt handler */ | ||
116 | irqreturn_t iio_interrupt_handler(int irq, void *_int_info) | ||
117 | { | ||
118 | struct iio_interrupt *int_info = _int_info; | ||
119 | struct iio_dev *dev_info = int_info->dev_info; | ||
120 | struct iio_event_handler_list *p; | ||
121 | s64 time_ns; | ||
122 | unsigned long flags; | ||
123 | |||
124 | spin_lock_irqsave(&int_info->ev_list_lock, flags); | ||
125 | if (list_empty(&int_info->ev_list)) { | ||
126 | spin_unlock_irqrestore(&int_info->ev_list_lock, flags); | ||
127 | return IRQ_NONE; | ||
128 | } | ||
129 | |||
130 | time_ns = iio_get_time_ns(); | ||
131 | /* detect single element list*/ | ||
132 | if (list_is_singular(&int_info->ev_list)) { | ||
133 | disable_irq_nosync(irq); | ||
134 | p = list_first_entry(&int_info->ev_list, | ||
135 | struct iio_event_handler_list, | ||
136 | list); | ||
137 | /* single event handler - maybe shared */ | ||
138 | p->handler(dev_info, 1, time_ns, !(p->refcount > 1)); | ||
139 | } else | ||
140 | list_for_each_entry(p, &int_info->ev_list, list) { | ||
141 | disable_irq_nosync(irq); | ||
142 | p->handler(dev_info, 1, time_ns, 0); | ||
143 | } | ||
144 | spin_unlock_irqrestore(&int_info->ev_list_lock, flags); | ||
145 | |||
146 | return IRQ_HANDLED; | ||
147 | } | ||
148 | |||
149 | static struct iio_interrupt *iio_allocate_interrupt(void) | ||
150 | { | ||
151 | struct iio_interrupt *i = kmalloc(sizeof *i, GFP_KERNEL); | ||
152 | if (i) { | ||
153 | spin_lock_init(&i->ev_list_lock); | ||
154 | INIT_LIST_HEAD(&i->ev_list); | ||
155 | } | ||
156 | return i; | ||
157 | } | ||
158 | |||
159 | /* Confirming the validity of supplied irq is left to drivers.*/ | ||
160 | int iio_register_interrupt_line(unsigned int irq, | ||
161 | struct iio_dev *dev_info, | ||
162 | int line_number, | ||
163 | unsigned long type, | ||
164 | const char *name) | ||
165 | { | ||
166 | int ret; | ||
167 | |||
168 | dev_info->interrupts[line_number] = iio_allocate_interrupt(); | ||
169 | if (dev_info->interrupts[line_number] == NULL) { | ||
170 | ret = -ENOMEM; | ||
171 | goto error_ret; | ||
172 | } | ||
173 | dev_info->interrupts[line_number]->line_number = line_number; | ||
174 | dev_info->interrupts[line_number]->irq = irq; | ||
175 | dev_info->interrupts[line_number]->dev_info = dev_info; | ||
176 | |||
177 | /* Possibly only request on demand? | ||
178 | * Can see this may complicate the handling of interrupts. | ||
179 | * However, with this approach we might end up handling lots of | ||
180 | * events no-one cares about.*/ | ||
181 | ret = request_irq(irq, | ||
182 | &iio_interrupt_handler, | ||
183 | type, | ||
184 | name, | ||
185 | dev_info->interrupts[line_number]); | ||
186 | |||
187 | error_ret: | ||
188 | return ret; | ||
189 | } | ||
190 | EXPORT_SYMBOL(iio_register_interrupt_line); | ||
191 | |||
192 | /* This turns up an awful lot */ | ||
193 | ssize_t iio_read_const_attr(struct device *dev, | ||
194 | struct device_attribute *attr, | ||
195 | char *buf) | ||
196 | { | ||
197 | return sprintf(buf, "%s\n", to_iio_const_attr(attr)->string); | ||
198 | } | ||
199 | EXPORT_SYMBOL(iio_read_const_attr); | ||
200 | |||
201 | /* Before this runs the interrupt generator must have been disabled */ | ||
202 | void iio_unregister_interrupt_line(struct iio_dev *dev_info, int line_number) | ||
203 | { | ||
204 | /* make sure the interrupt handlers are all done */ | ||
205 | flush_scheduled_work(); | ||
206 | free_irq(dev_info->interrupts[line_number]->irq, | ||
207 | dev_info->interrupts[line_number]); | ||
208 | kfree(dev_info->interrupts[line_number]); | ||
209 | } | ||
210 | EXPORT_SYMBOL(iio_unregister_interrupt_line); | ||
211 | |||
212 | /* Reference counted add and remove */ | ||
213 | void iio_add_event_to_list(struct iio_event_handler_list *el, | ||
214 | struct list_head *head) | ||
215 | { | ||
216 | unsigned long flags; | ||
217 | struct iio_interrupt *inter = to_iio_interrupt(head); | ||
218 | |||
219 | /* take mutex to protect this element */ | ||
220 | mutex_lock(&el->exist_lock); | ||
221 | if (el->refcount == 0) { | ||
222 | /* Take the event list spin lock */ | ||
223 | spin_lock_irqsave(&inter->ev_list_lock, flags); | ||
224 | list_add(&el->list, head); | ||
225 | spin_unlock_irqrestore(&inter->ev_list_lock, flags); | ||
226 | } | ||
227 | el->refcount++; | ||
228 | mutex_unlock(&el->exist_lock); | ||
229 | } | ||
230 | EXPORT_SYMBOL(iio_add_event_to_list); | ||
231 | |||
232 | void iio_remove_event_from_list(struct iio_event_handler_list *el, | ||
233 | struct list_head *head) | ||
234 | { | ||
235 | unsigned long flags; | ||
236 | struct iio_interrupt *inter = to_iio_interrupt(head); | ||
237 | |||
238 | mutex_lock(&el->exist_lock); | ||
239 | el->refcount--; | ||
240 | if (el->refcount == 0) { | ||
241 | /* Take the event list spin lock */ | ||
242 | spin_lock_irqsave(&inter->ev_list_lock, flags); | ||
243 | list_del_init(&el->list); | ||
244 | spin_unlock_irqrestore(&inter->ev_list_lock, flags); | ||
245 | } | ||
246 | mutex_unlock(&el->exist_lock); | ||
247 | } | ||
248 | EXPORT_SYMBOL(iio_remove_event_from_list); | ||
249 | |||
250 | ssize_t iio_event_chrdev_read(struct file *filep, | ||
251 | char *buf, | ||
252 | size_t count, | ||
253 | loff_t *f_ps) | ||
254 | { | ||
255 | struct iio_event_interface *ev_int = filep->private_data; | ||
256 | struct iio_detected_event_list *el; | ||
257 | int ret; | ||
258 | size_t len; | ||
259 | |||
260 | mutex_lock(&ev_int->event_list_lock); | ||
261 | if (list_empty(&ev_int->det_events.list)) { | ||
262 | if (filep->f_flags & O_NONBLOCK) { | ||
263 | ret = -EAGAIN; | ||
264 | goto error_mutex_unlock; | ||
265 | } | ||
266 | mutex_unlock(&ev_int->event_list_lock); | ||
267 | /* Blocking on device; waiting for something to be there */ | ||
268 | ret = wait_event_interruptible(ev_int->wait, | ||
269 | !list_empty(&ev_int | ||
270 | ->det_events.list)); | ||
271 | if (ret) | ||
272 | goto error_ret; | ||
273 | /* Single access device so noone else can get the data */ | ||
274 | mutex_lock(&ev_int->event_list_lock); | ||
275 | } | ||
276 | |||
277 | el = list_first_entry(&ev_int->det_events.list, | ||
278 | struct iio_detected_event_list, | ||
279 | list); | ||
280 | len = sizeof el->ev; | ||
281 | if (copy_to_user(buf, &(el->ev), len)) { | ||
282 | ret = -EFAULT; | ||
283 | goto error_mutex_unlock; | ||
284 | } | ||
285 | list_del(&el->list); | ||
286 | ev_int->current_events--; | ||
287 | mutex_unlock(&ev_int->event_list_lock); | ||
288 | /* | ||
289 | * Possible concurency issue if an update of this event is on its way | ||
290 | * through. May lead to new even being removed whilst the reported event | ||
291 | * was the unescalated event. In typical use case this is not a problem | ||
292 | * as userspace will say read half the buffer due to a 50% full event | ||
293 | * which would make the correct 100% full incorrect anyway. | ||
294 | */ | ||
295 | spin_lock(&el->shared_pointer->lock); | ||
296 | if (el->shared_pointer) | ||
297 | (el->shared_pointer->ev_p) = NULL; | ||
298 | spin_unlock(&el->shared_pointer->lock); | ||
299 | |||
300 | kfree(el); | ||
301 | |||
302 | return len; | ||
303 | |||
304 | error_mutex_unlock: | ||
305 | mutex_unlock(&ev_int->event_list_lock); | ||
306 | error_ret: | ||
307 | |||
308 | return ret; | ||
309 | } | ||
310 | |||
311 | int iio_event_chrdev_release(struct inode *inode, struct file *filep) | ||
312 | { | ||
313 | struct iio_handler *hand = iio_cdev_to_handler(inode->i_cdev); | ||
314 | struct iio_event_interface *ev_int = hand->private; | ||
315 | struct iio_detected_event_list *el, *t; | ||
316 | |||
317 | mutex_lock(&ev_int->event_list_lock); | ||
318 | clear_bit(IIO_BUSY_BIT_POS, &ev_int->handler.flags); | ||
319 | /* | ||
320 | * In order to maintain a clean state for reopening, | ||
321 | * clear out any awaiting events. The mask will prevent | ||
322 | * any new __iio_push_event calls running. | ||
323 | */ | ||
324 | list_for_each_entry_safe(el, t, &ev_int->det_events.list, list) { | ||
325 | list_del(&el->list); | ||
326 | kfree(el); | ||
327 | } | ||
328 | mutex_unlock(&ev_int->event_list_lock); | ||
329 | |||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | int iio_event_chrdev_open(struct inode *inode, struct file *filep) | ||
334 | { | ||
335 | struct iio_handler *hand = iio_cdev_to_handler(inode->i_cdev); | ||
336 | struct iio_event_interface *ev_int = hand->private; | ||
337 | |||
338 | mutex_lock(&ev_int->event_list_lock); | ||
339 | if (test_and_set_bit(IIO_BUSY_BIT_POS, &hand->flags)) { | ||
340 | fops_put(filep->f_op); | ||
341 | mutex_unlock(&ev_int->event_list_lock); | ||
342 | return -EBUSY; | ||
343 | } | ||
344 | filep->private_data = hand->private; | ||
345 | mutex_unlock(&ev_int->event_list_lock); | ||
346 | |||
347 | return 0; | ||
348 | } | ||
349 | |||
350 | static const struct file_operations iio_event_chrdev_fileops = { | ||
351 | .read = iio_event_chrdev_read, | ||
352 | .release = iio_event_chrdev_release, | ||
353 | .open = iio_event_chrdev_open, | ||
354 | .owner = THIS_MODULE, | ||
355 | }; | ||
356 | |||
357 | static void iio_event_dev_release(struct device *dev) | ||
358 | { | ||
359 | struct iio_event_interface *ev_int | ||
360 | = container_of(dev, struct iio_event_interface, dev); | ||
361 | cdev_del(&ev_int->handler.chrdev); | ||
362 | iio_device_free_chrdev_minor(MINOR(dev->devt)); | ||
363 | }; | ||
364 | |||
365 | static struct device_type iio_event_type = { | ||
366 | .release = iio_event_dev_release, | ||
367 | }; | ||
368 | |||
369 | int iio_device_get_chrdev_minor(void) | ||
370 | { | ||
371 | int ret, val; | ||
372 | |||
373 | idr_again: | ||
374 | if (unlikely(idr_pre_get(&iio_chrdev_idr, GFP_KERNEL) == 0)) | ||
375 | return -ENOMEM; | ||
376 | spin_lock(&iio_idr_lock); | ||
377 | ret = idr_get_new(&iio_chrdev_idr, NULL, &val); | ||
378 | spin_unlock(&iio_idr_lock); | ||
379 | if (unlikely(ret == -EAGAIN)) | ||
380 | goto idr_again; | ||
381 | else if (unlikely(ret)) | ||
382 | return ret; | ||
383 | if (val > IIO_DEV_MAX) | ||
384 | return -ENOMEM; | ||
385 | return val; | ||
386 | } | ||
387 | |||
388 | void iio_device_free_chrdev_minor(int val) | ||
389 | { | ||
390 | spin_lock(&iio_idr_lock); | ||
391 | idr_remove(&iio_chrdev_idr, val); | ||
392 | spin_unlock(&iio_idr_lock); | ||
393 | } | ||
394 | |||
395 | int iio_setup_ev_int(struct iio_event_interface *ev_int, | ||
396 | const char *name, | ||
397 | struct module *owner, | ||
398 | struct device *dev) | ||
399 | { | ||
400 | int ret, minor; | ||
401 | |||
402 | ev_int->dev.class = &iio_class; | ||
403 | ev_int->dev.parent = dev; | ||
404 | ev_int->dev.type = &iio_event_type; | ||
405 | device_initialize(&ev_int->dev); | ||
406 | |||
407 | minor = iio_device_get_chrdev_minor(); | ||
408 | if (minor < 0) { | ||
409 | ret = minor; | ||
410 | goto error_device_put; | ||
411 | } | ||
412 | ev_int->dev.devt = MKDEV(MAJOR(iio_devt), minor); | ||
413 | dev_set_name(&ev_int->dev, "%s", name); | ||
414 | |||
415 | ret = device_add(&ev_int->dev); | ||
416 | if (ret) | ||
417 | goto error_free_minor; | ||
418 | |||
419 | cdev_init(&ev_int->handler.chrdev, &iio_event_chrdev_fileops); | ||
420 | ev_int->handler.chrdev.owner = owner; | ||
421 | |||
422 | mutex_init(&ev_int->event_list_lock); | ||
423 | /* discussion point - make this variable? */ | ||
424 | ev_int->max_events = 10; | ||
425 | ev_int->current_events = 0; | ||
426 | INIT_LIST_HEAD(&ev_int->det_events.list); | ||
427 | init_waitqueue_head(&ev_int->wait); | ||
428 | ev_int->handler.private = ev_int; | ||
429 | ev_int->handler.flags = 0; | ||
430 | |||
431 | ret = cdev_add(&ev_int->handler.chrdev, ev_int->dev.devt, 1); | ||
432 | if (ret) | ||
433 | goto error_unreg_device; | ||
434 | |||
435 | return 0; | ||
436 | |||
437 | error_unreg_device: | ||
438 | device_unregister(&ev_int->dev); | ||
439 | error_free_minor: | ||
440 | iio_device_free_chrdev_minor(minor); | ||
441 | error_device_put: | ||
442 | put_device(&ev_int->dev); | ||
443 | |||
444 | return ret; | ||
445 | } | ||
446 | |||
447 | void iio_free_ev_int(struct iio_event_interface *ev_int) | ||
448 | { | ||
449 | device_unregister(&ev_int->dev); | ||
450 | put_device(&ev_int->dev); | ||
451 | } | ||
452 | |||
453 | static int __init iio_dev_init(void) | ||
454 | { | ||
455 | int err; | ||
456 | |||
457 | err = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio"); | ||
458 | if (err < 0) | ||
459 | printk(KERN_ERR "%s: failed to allocate char dev region\n", | ||
460 | __FILE__); | ||
461 | |||
462 | return err; | ||
463 | } | ||
464 | |||
465 | static void __exit iio_dev_exit(void) | ||
466 | { | ||
467 | if (iio_devt) | ||
468 | unregister_chrdev_region(iio_devt, IIO_DEV_MAX); | ||
469 | } | ||
470 | |||
471 | static int __init iio_init(void) | ||
472 | { | ||
473 | int ret; | ||
474 | |||
475 | /* Create sysfs class */ | ||
476 | ret = class_register(&iio_class); | ||
477 | if (ret < 0) { | ||
478 | printk(KERN_ERR | ||
479 | "%s could not create sysfs class\n", | ||
480 | __FILE__); | ||
481 | goto error_nothing; | ||
482 | } | ||
483 | |||
484 | ret = iio_dev_init(); | ||
485 | if (ret < 0) | ||
486 | goto error_unregister_class; | ||
487 | |||
488 | return 0; | ||
489 | |||
490 | error_unregister_class: | ||
491 | class_unregister(&iio_class); | ||
492 | error_nothing: | ||
493 | return ret; | ||
494 | } | ||
495 | |||
496 | static void __exit iio_exit(void) | ||
497 | { | ||
498 | iio_dev_exit(); | ||
499 | class_unregister(&iio_class); | ||
500 | } | ||
501 | |||
502 | static int iio_device_register_sysfs(struct iio_dev *dev_info) | ||
503 | { | ||
504 | int ret = 0; | ||
505 | |||
506 | ret = sysfs_create_group(&dev_info->dev.kobj, dev_info->attrs); | ||
507 | if (ret) { | ||
508 | dev_err(dev_info->dev.parent, | ||
509 | "Failed to register sysfs hooks\n"); | ||
510 | goto error_ret; | ||
511 | } | ||
512 | |||
513 | if (dev_info->scan_el_attrs) { | ||
514 | ret = sysfs_create_group(&dev_info->dev.kobj, | ||
515 | dev_info->scan_el_attrs); | ||
516 | if (ret) | ||
517 | dev_err(&dev_info->dev, | ||
518 | "Failed to add sysfs scan els\n"); | ||
519 | } | ||
520 | |||
521 | error_ret: | ||
522 | return ret; | ||
523 | } | ||
524 | |||
525 | static void iio_device_unregister_sysfs(struct iio_dev *dev_info) | ||
526 | { | ||
527 | if (dev_info->scan_el_attrs) | ||
528 | sysfs_remove_group(&dev_info->dev.kobj, | ||
529 | dev_info->scan_el_attrs); | ||
530 | |||
531 | sysfs_remove_group(&dev_info->dev.kobj, dev_info->attrs); | ||
532 | } | ||
533 | |||
534 | int iio_get_new_idr_val(struct idr *this_idr) | ||
535 | { | ||
536 | int ret; | ||
537 | int val; | ||
538 | |||
539 | idr_again: | ||
540 | if (unlikely(idr_pre_get(this_idr, GFP_KERNEL) == 0)) | ||
541 | return -ENOMEM; | ||
542 | |||
543 | spin_lock(&iio_idr_lock); | ||
544 | ret = idr_get_new(this_idr, NULL, &val); | ||
545 | spin_unlock(&iio_idr_lock); | ||
546 | if (unlikely(ret == -EAGAIN)) | ||
547 | goto idr_again; | ||
548 | else if (unlikely(ret)) | ||
549 | return ret; | ||
550 | |||
551 | return val; | ||
552 | } | ||
553 | EXPORT_SYMBOL(iio_get_new_idr_val); | ||
554 | |||
555 | void iio_free_idr_val(struct idr *this_idr, int id) | ||
556 | { | ||
557 | spin_lock(&iio_idr_lock); | ||
558 | idr_remove(this_idr, id); | ||
559 | spin_unlock(&iio_idr_lock); | ||
560 | } | ||
561 | EXPORT_SYMBOL(iio_free_idr_val); | ||
562 | |||
563 | static int iio_device_register_id(struct iio_dev *dev_info, | ||
564 | struct idr *this_idr) | ||
565 | { | ||
566 | |||
567 | dev_info->id = iio_get_new_idr_val(&iio_idr); | ||
568 | if (dev_info->id < 0) | ||
569 | return dev_info->id; | ||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | static void iio_device_unregister_id(struct iio_dev *dev_info) | ||
574 | { | ||
575 | iio_free_idr_val(&iio_idr, dev_info->id); | ||
576 | } | ||
577 | |||
578 | static inline int __iio_add_event_config_attrs(struct iio_dev *dev_info, int i) | ||
579 | { | ||
580 | int ret; | ||
581 | /*p for adding, q for removing */ | ||
582 | struct attribute **attrp, **attrq; | ||
583 | |||
584 | if (dev_info->event_conf_attrs && dev_info->event_conf_attrs[i].attrs) { | ||
585 | attrp = dev_info->event_conf_attrs[i].attrs; | ||
586 | while (*attrp) { | ||
587 | ret = sysfs_add_file_to_group(&dev_info->dev.kobj, | ||
588 | *attrp, | ||
589 | dev_info | ||
590 | ->event_attrs[i].name); | ||
591 | if (ret) | ||
592 | goto error_ret; | ||
593 | attrp++; | ||
594 | } | ||
595 | } | ||
596 | return 0; | ||
597 | |||
598 | error_ret: | ||
599 | attrq = dev_info->event_conf_attrs[i].attrs; | ||
600 | while (attrq != attrp) { | ||
601 | sysfs_remove_file_from_group(&dev_info->dev.kobj, | ||
602 | *attrq, | ||
603 | dev_info->event_attrs[i].name); | ||
604 | attrq++; | ||
605 | } | ||
606 | |||
607 | return ret; | ||
608 | } | ||
609 | |||
610 | static inline int __iio_remove_event_config_attrs(struct iio_dev *dev_info, | ||
611 | int i) | ||
612 | { | ||
613 | struct attribute **attrq; | ||
614 | |||
615 | if (dev_info->event_conf_attrs | ||
616 | && dev_info->event_conf_attrs[i].attrs) { | ||
617 | attrq = dev_info->event_conf_attrs[i].attrs; | ||
618 | while (*attrq) { | ||
619 | sysfs_remove_file_from_group(&dev_info->dev.kobj, | ||
620 | *attrq, | ||
621 | dev_info | ||
622 | ->event_attrs[i].name); | ||
623 | attrq++; | ||
624 | } | ||
625 | } | ||
626 | |||
627 | return 0; | ||
628 | } | ||
629 | |||
630 | static int iio_device_register_eventset(struct iio_dev *dev_info) | ||
631 | { | ||
632 | int ret = 0, i, j; | ||
633 | |||
634 | if (dev_info->num_interrupt_lines == 0) | ||
635 | return 0; | ||
636 | |||
637 | dev_info->event_interfaces = | ||
638 | kzalloc(sizeof(struct iio_event_interface) | ||
639 | *dev_info->num_interrupt_lines, | ||
640 | GFP_KERNEL); | ||
641 | if (dev_info->event_interfaces == NULL) { | ||
642 | ret = -ENOMEM; | ||
643 | goto error_ret; | ||
644 | } | ||
645 | |||
646 | dev_info->interrupts = kzalloc(sizeof(struct iio_interrupt *) | ||
647 | *dev_info->num_interrupt_lines, | ||
648 | GFP_KERNEL); | ||
649 | if (dev_info->interrupts == NULL) { | ||
650 | ret = -ENOMEM; | ||
651 | goto error_free_event_interfaces; | ||
652 | } | ||
653 | |||
654 | for (i = 0; i < dev_info->num_interrupt_lines; i++) { | ||
655 | dev_info->event_interfaces[i].owner = dev_info->driver_module; | ||
656 | ret = iio_get_new_idr_val(&iio_event_idr); | ||
657 | if (ret) | ||
658 | goto error_free_setup_ev_ints; | ||
659 | else | ||
660 | dev_info->event_interfaces[i].id = ret; | ||
661 | |||
662 | snprintf(dev_info->event_interfaces[i]._name, 20, | ||
663 | "event_line%d", | ||
664 | dev_info->event_interfaces[i].id); | ||
665 | |||
666 | ret = iio_setup_ev_int(&dev_info->event_interfaces[i], | ||
667 | (const char *)(dev_info | ||
668 | ->event_interfaces[i] | ||
669 | ._name), | ||
670 | dev_info->driver_module, | ||
671 | &dev_info->dev); | ||
672 | if (ret) { | ||
673 | dev_err(&dev_info->dev, | ||
674 | "Could not get chrdev interface\n"); | ||
675 | iio_free_idr_val(&iio_event_idr, | ||
676 | dev_info->event_interfaces[i].id); | ||
677 | goto error_free_setup_ev_ints; | ||
678 | } | ||
679 | } | ||
680 | |||
681 | for (i = 0; i < dev_info->num_interrupt_lines; i++) { | ||
682 | snprintf(dev_info->event_interfaces[i]._attrname, 20, | ||
683 | "event_line%d_sources", i); | ||
684 | dev_info->event_attrs[i].name | ||
685 | = (const char *) | ||
686 | (dev_info->event_interfaces[i]._attrname); | ||
687 | ret = sysfs_create_group(&dev_info->dev.kobj, | ||
688 | &dev_info->event_attrs[i]); | ||
689 | if (ret) { | ||
690 | dev_err(&dev_info->dev, | ||
691 | "Failed to register sysfs for event attrs"); | ||
692 | goto error_remove_sysfs_interfaces; | ||
693 | } | ||
694 | } | ||
695 | |||
696 | for (i = 0; i < dev_info->num_interrupt_lines; i++) { | ||
697 | ret = __iio_add_event_config_attrs(dev_info, i); | ||
698 | if (ret) | ||
699 | goto error_unregister_config_attrs; | ||
700 | } | ||
701 | |||
702 | return 0; | ||
703 | |||
704 | error_unregister_config_attrs: | ||
705 | for (j = 0; j < i; j++) | ||
706 | __iio_remove_event_config_attrs(dev_info, i); | ||
707 | i = dev_info->num_interrupt_lines - 1; | ||
708 | error_remove_sysfs_interfaces: | ||
709 | for (j = 0; j < i; j++) | ||
710 | sysfs_remove_group(&dev_info->dev.kobj, | ||
711 | &dev_info->event_attrs[j]); | ||
712 | i = dev_info->num_interrupt_lines - 1; | ||
713 | error_free_setup_ev_ints: | ||
714 | for (j = 0; j < i; j++) { | ||
715 | iio_free_idr_val(&iio_event_idr, | ||
716 | dev_info->event_interfaces[i].id); | ||
717 | iio_free_ev_int(&dev_info->event_interfaces[j]); | ||
718 | } | ||
719 | kfree(dev_info->interrupts); | ||
720 | error_free_event_interfaces: | ||
721 | kfree(dev_info->event_interfaces); | ||
722 | error_ret: | ||
723 | |||
724 | return ret; | ||
725 | } | ||
726 | |||
727 | static void iio_device_unregister_eventset(struct iio_dev *dev_info) | ||
728 | { | ||
729 | int i; | ||
730 | |||
731 | if (dev_info->num_interrupt_lines == 0) | ||
732 | return; | ||
733 | for (i = 0; i < dev_info->num_interrupt_lines; i++) | ||
734 | sysfs_remove_group(&dev_info->dev.kobj, | ||
735 | &dev_info->event_attrs[i]); | ||
736 | |||
737 | for (i = 0; i < dev_info->num_interrupt_lines; i++) { | ||
738 | iio_free_idr_val(&iio_event_idr, | ||
739 | dev_info->event_interfaces[i].id); | ||
740 | iio_free_ev_int(&dev_info->event_interfaces[i]); | ||
741 | } | ||
742 | kfree(dev_info->interrupts); | ||
743 | kfree(dev_info->event_interfaces); | ||
744 | } | ||
745 | |||
746 | static void iio_dev_release(struct device *device) | ||
747 | { | ||
748 | struct iio_dev *dev = to_iio_dev(device); | ||
749 | |||
750 | iio_put(); | ||
751 | kfree(dev); | ||
752 | } | ||
753 | |||
754 | static struct device_type iio_dev_type = { | ||
755 | .name = "iio_device", | ||
756 | .release = iio_dev_release, | ||
757 | }; | ||
758 | |||
759 | struct iio_dev *iio_allocate_device(void) | ||
760 | { | ||
761 | struct iio_dev *dev = kzalloc(sizeof *dev, GFP_KERNEL); | ||
762 | |||
763 | if (dev) { | ||
764 | dev->dev.type = &iio_dev_type; | ||
765 | dev->dev.class = &iio_class; | ||
766 | device_initialize(&dev->dev); | ||
767 | dev_set_drvdata(&dev->dev, (void *)dev); | ||
768 | mutex_init(&dev->mlock); | ||
769 | iio_get(); | ||
770 | } | ||
771 | |||
772 | return dev; | ||
773 | } | ||
774 | EXPORT_SYMBOL(iio_allocate_device); | ||
775 | |||
776 | void iio_free_device(struct iio_dev *dev) | ||
777 | { | ||
778 | if (dev) | ||
779 | iio_put_device(dev); | ||
780 | } | ||
781 | EXPORT_SYMBOL(iio_free_device); | ||
782 | |||
783 | int iio_device_register(struct iio_dev *dev_info) | ||
784 | { | ||
785 | int ret; | ||
786 | |||
787 | ret = iio_device_register_id(dev_info, &iio_idr); | ||
788 | if (ret) { | ||
789 | dev_err(&dev_info->dev, "Failed to get id\n"); | ||
790 | goto error_ret; | ||
791 | } | ||
792 | dev_set_name(&dev_info->dev, "device%d", dev_info->id); | ||
793 | |||
794 | ret = device_add(&dev_info->dev); | ||
795 | if (ret) | ||
796 | goto error_free_idr; | ||
797 | ret = iio_device_register_sysfs(dev_info); | ||
798 | if (ret) { | ||
799 | dev_err(dev_info->dev.parent, | ||
800 | "Failed to register sysfs interfaces\n"); | ||
801 | goto error_del_device; | ||
802 | } | ||
803 | ret = iio_device_register_eventset(dev_info); | ||
804 | if (ret) { | ||
805 | dev_err(dev_info->dev.parent, | ||
806 | "Failed to register event set \n"); | ||
807 | goto error_free_sysfs; | ||
808 | } | ||
809 | if (dev_info->modes & INDIO_RING_TRIGGERED) | ||
810 | iio_device_register_trigger_consumer(dev_info); | ||
811 | |||
812 | return 0; | ||
813 | |||
814 | error_free_sysfs: | ||
815 | iio_device_unregister_sysfs(dev_info); | ||
816 | error_del_device: | ||
817 | device_del(&dev_info->dev); | ||
818 | error_free_idr: | ||
819 | iio_device_unregister_id(dev_info); | ||
820 | error_ret: | ||
821 | return ret; | ||
822 | } | ||
823 | EXPORT_SYMBOL(iio_device_register); | ||
824 | |||
825 | void iio_device_unregister(struct iio_dev *dev_info) | ||
826 | { | ||
827 | if (dev_info->modes & INDIO_RING_TRIGGERED) | ||
828 | iio_device_unregister_trigger_consumer(dev_info); | ||
829 | iio_device_unregister_eventset(dev_info); | ||
830 | iio_device_unregister_sysfs(dev_info); | ||
831 | iio_device_unregister_id(dev_info); | ||
832 | device_unregister(&dev_info->dev); | ||
833 | } | ||
834 | EXPORT_SYMBOL(iio_device_unregister); | ||
835 | |||
836 | void iio_put(void) | ||
837 | { | ||
838 | module_put(THIS_MODULE); | ||
839 | } | ||
840 | |||
841 | void iio_get(void) | ||
842 | { | ||
843 | __module_get(THIS_MODULE); | ||
844 | } | ||
845 | |||
846 | subsys_initcall(iio_init); | ||
847 | module_exit(iio_exit); | ||
848 | |||
849 | MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); | ||
850 | MODULE_DESCRIPTION("Industrial I/O core"); | ||
851 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/iio/sysfs.h b/drivers/staging/iio/sysfs.h new file mode 100644 index 000000000000..bfe4055c0ed2 --- /dev/null +++ b/drivers/staging/iio/sysfs.h | |||
@@ -0,0 +1,293 @@ | |||
1 | /* The industrial I/O core | ||
2 | * | ||
3 | *Copyright (c) 2008 Jonathan Cameron | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 2 as published by | ||
7 | * the Free Software Foundation. | ||
8 | * | ||
9 | * General attributes | ||
10 | */ | ||
11 | |||
12 | #ifndef _INDUSTRIAL_IO_SYSFS_H_ | ||
13 | #define _INDUSTRIAL_IO_SYSFS_H_ | ||
14 | |||
15 | #include "iio.h" | ||
16 | |||
17 | /** | ||
18 | * struct iio_event_attribute - event control attribute | ||
19 | * @dev_attr: underlying device attribute | ||
20 | * @mask: mask for the event when detecting | ||
21 | * @listel: list header to allow addition to list of event handlers | ||
22 | */ | ||
23 | struct iio_event_attr { | ||
24 | struct device_attribute dev_attr; | ||
25 | int mask; | ||
26 | struct iio_event_handler_list *listel; | ||
27 | }; | ||
28 | |||
29 | #define to_iio_event_attr(_dev_attr) \ | ||
30 | container_of(_dev_attr, struct iio_event_attr, dev_attr) | ||
31 | |||
32 | /** | ||
33 | * struct iio_chrdev_minor_attr - simple attribute to allow reading of chrdev | ||
34 | * minor number | ||
35 | * @dev_attr: underlying device attribute | ||
36 | * @minor: the minor number | ||
37 | */ | ||
38 | struct iio_chrdev_minor_attr { | ||
39 | struct device_attribute dev_attr; | ||
40 | int minor; | ||
41 | }; | ||
42 | |||
43 | void | ||
44 | __init_iio_chrdev_minor_attr(struct iio_chrdev_minor_attr *minor_attr, | ||
45 | const char *name, | ||
46 | struct module *owner, | ||
47 | int id); | ||
48 | |||
49 | |||
50 | #define to_iio_chrdev_minor_attr(_dev_attr) \ | ||
51 | container_of(_dev_attr, struct iio_chrdev_minor_attr, dev_attr); | ||
52 | |||
53 | /** | ||
54 | * struct iio_dev_attr - iio specific device attribute | ||
55 | * @dev_attr: underlying device attribute | ||
56 | * @address: associated register address | ||
57 | */ | ||
58 | struct iio_dev_attr { | ||
59 | struct device_attribute dev_attr; | ||
60 | int address; | ||
61 | int val2; | ||
62 | }; | ||
63 | |||
64 | #define to_iio_dev_attr(_dev_attr) \ | ||
65 | container_of(_dev_attr, struct iio_dev_attr, dev_attr) | ||
66 | |||
67 | ssize_t iio_read_const_attr(struct device *dev, | ||
68 | struct device_attribute *attr, | ||
69 | char *len); | ||
70 | |||
71 | /** | ||
72 | * struct iio_const_attr - constant device specific attribute | ||
73 | * often used for things like available modes | ||
74 | */ | ||
75 | struct iio_const_attr { | ||
76 | const char *string; | ||
77 | struct device_attribute dev_attr; | ||
78 | }; | ||
79 | |||
80 | #define to_iio_const_attr(_dev_attr) \ | ||
81 | container_of(_dev_attr, struct iio_const_attr, dev_attr) | ||
82 | |||
83 | /* Some attributes will be hard coded (device dependant) and not require an | ||
84 | address, in these cases pass a negative */ | ||
85 | #define IIO_ATTR(_name, _mode, _show, _store, _addr) \ | ||
86 | { .dev_attr = __ATTR(_name, _mode, _show, _store), \ | ||
87 | .address = _addr } | ||
88 | |||
89 | #define IIO_ATTR_2(_name, _mode, _show, _store, _addr, _val2) \ | ||
90 | { .dev_attr = __ATTR(_name, _mode, _show, _store), \ | ||
91 | .address = _addr, \ | ||
92 | .val2 = _val2 } | ||
93 | |||
94 | #define IIO_DEVICE_ATTR(_name, _mode, _show, _store, _addr) \ | ||
95 | struct iio_dev_attr iio_dev_attr_##_name \ | ||
96 | = IIO_ATTR(_name, _mode, _show, _store, _addr) | ||
97 | |||
98 | |||
99 | #define IIO_DEVICE_ATTR_2(_name, _mode, _show, _store, _addr, _val2) \ | ||
100 | struct iio_dev_attr iio_dev_attr_##_name \ | ||
101 | = IIO_ATTR_2(_name, _mode, _show, _store, _addr, _val2) | ||
102 | |||
103 | #define IIO_CONST_ATTR(_name, _string) \ | ||
104 | struct iio_const_attr iio_const_attr_##_name \ | ||
105 | = { .string = _string, \ | ||
106 | .dev_attr = __ATTR(_name, S_IRUGO, iio_read_const_attr, NULL)} | ||
107 | |||
108 | /* Generic attributes of onetype or another */ | ||
109 | |||
110 | /** | ||
111 | * IIO_DEV_ATTR_REG: revision number for the device | ||
112 | * | ||
113 | * Very much device dependent. | ||
114 | **/ | ||
115 | #define IIO_DEV_ATTR_REV(_show) \ | ||
116 | IIO_DEVICE_ATTR(revision, S_IRUGO, _show, NULL, 0) | ||
117 | /** | ||
118 | * IIO_DEV_ATTR_NAME: chip type dependant identifier | ||
119 | **/ | ||
120 | #define IIO_DEV_ATTR_NAME(_show) \ | ||
121 | IIO_DEVICE_ATTR(name, S_IRUGO, _show, NULL, 0) | ||
122 | |||
123 | /** | ||
124 | * IIO_DEV_ATTR_SAMP_FREQ: sets any internal clock frequency | ||
125 | **/ | ||
126 | #define IIO_DEV_ATTR_SAMP_FREQ(_mode, _show, _store) \ | ||
127 | IIO_DEVICE_ATTR(sampling_frequency, _mode, _show, _store, 0) | ||
128 | |||
129 | /** | ||
130 | * IIO_DEV_ATTR_AVAIL_SAMP_FREQ: list available sampling frequencies. | ||
131 | * | ||
132 | * May be mode dependant on some devices | ||
133 | **/ | ||
134 | #define IIO_DEV_ATTR_AVAIL_SAMP_FREQ(_show) \ | ||
135 | IIO_DEVICE_ATTR(available_sampling_frequency, S_IRUGO, _show, NULL, 0) | ||
136 | |||
137 | /** | ||
138 | * IIO_DEV_ATTR_CONST_AVAIL_SAMP_FREQ: list available sampling frequencies. | ||
139 | * | ||
140 | * Constant version | ||
141 | **/ | ||
142 | #define IIO_CONST_ATTR_AVAIL_SAMP_FREQ(_string) \ | ||
143 | IIO_CONST_ATTR(available_sampling_frequency, _string) | ||
144 | /** | ||
145 | * IIO_DEV_ATTR_SCAN_MODE: select a scan mode | ||
146 | * | ||
147 | * This is used when only certain combinations of inputs may be read in one | ||
148 | * scan. | ||
149 | **/ | ||
150 | #define IIO_DEV_ATTR_SCAN_MODE(_mode, _show, _store) \ | ||
151 | IIO_DEVICE_ATTR(scan_mode, _mode, _show, _store, 0) | ||
152 | /** | ||
153 | * IIO_DEV_ATTR_AVAIL_SCAN_MODES: list available scan modes | ||
154 | **/ | ||
155 | #define IIO_DEV_ATTR_AVAIL_SCAN_MODES(_show) \ | ||
156 | IIO_DEVICE_ATTR(available_scan_modes, S_IRUGO, _show, NULL, 0) | ||
157 | |||
158 | /** | ||
159 | * IIO_DEV_ATTR_SCAN: result of scan of multiple channels | ||
160 | **/ | ||
161 | #define IIO_DEV_ATTR_SCAN(_show) \ | ||
162 | IIO_DEVICE_ATTR(scan, S_IRUGO, _show, NULL, 0); | ||
163 | |||
164 | /** | ||
165 | * IIO_DEV_ATTR_INPUT: direct read of a single input channel | ||
166 | **/ | ||
167 | #define IIO_DEV_ATTR_INPUT(_number, _show) \ | ||
168 | IIO_DEVICE_ATTR(in##_number, S_IRUGO, _show, NULL, _number) | ||
169 | |||
170 | |||
171 | /** | ||
172 | * IIO_DEV_ATTR_SW_RING_ENABLE: enable software ring buffer | ||
173 | * | ||
174 | * Success may be dependant on attachment of trigger previously | ||
175 | **/ | ||
176 | #define IIO_DEV_ATTR_SW_RING_ENABLE(_show, _store) \ | ||
177 | IIO_DEVICE_ATTR(sw_ring_enable, S_IRUGO | S_IWUSR, _show, _store, 0) | ||
178 | |||
179 | /** | ||
180 | * IIO_DEV_ATTR_HW_RING_ENABLE: enable hardware ring buffer | ||
181 | * | ||
182 | * This is a different attribute from the software one as one can invision | ||
183 | * schemes where a combination of the two may be used. | ||
184 | **/ | ||
185 | #define IIO_DEV_ATTR_HW_RING_ENABLE(_show, _store) \ | ||
186 | IIO_DEVICE_ATTR(hw_ring_enable, S_IRUGO | S_IWUSR, _show, _store, 0) | ||
187 | |||
188 | /** | ||
189 | * IIO_DEV_ATTR_BPSE: set number of bits per scan element | ||
190 | **/ | ||
191 | #define IIO_DEV_ATTR_BPSE(_mode, _show, _store) \ | ||
192 | IIO_DEVICE_ATTR(bpse, _mode, _show, _store, 0) | ||
193 | |||
194 | /** | ||
195 | * IIO_DEV_ATTR_BPSE_AVAILABLE: no of bits per scan element supported | ||
196 | **/ | ||
197 | #define IIO_DEV_ATTR_BPSE_AVAILABLE(_show) \ | ||
198 | IIO_DEVICE_ATTR(bpse_available, S_IRUGO, _show, NULL, 0) | ||
199 | |||
200 | /** | ||
201 | * IIO_DEV_ATTR_TEMP: many sensors have auxiliary temperature sensors | ||
202 | **/ | ||
203 | #define IIO_DEV_ATTR_TEMP(_show) \ | ||
204 | IIO_DEVICE_ATTR(temp, S_IRUGO, _show, NULL, 0) | ||
205 | /** | ||
206 | * IIO_EVENT_SH: generic shared event handler | ||
207 | * | ||
208 | * This is used in cases where more than one event may result from a single | ||
209 | * handler. Often the case that some alarm register must be read and multiple | ||
210 | * alarms may have been triggered. | ||
211 | **/ | ||
212 | #define IIO_EVENT_SH(_name, _handler) \ | ||
213 | static struct iio_event_handler_list \ | ||
214 | iio_event_##_name = { \ | ||
215 | .handler = _handler, \ | ||
216 | .refcount = 0, \ | ||
217 | .exist_lock = __MUTEX_INITIALIZER(iio_event_##_name \ | ||
218 | .exist_lock), \ | ||
219 | .list = { \ | ||
220 | .next = &iio_event_##_name.list, \ | ||
221 | .prev = &iio_event_##_name.list, \ | ||
222 | }, \ | ||
223 | }; | ||
224 | /** | ||
225 | * IIO_EVENT_ATTR_SH: generic shared event attribute | ||
226 | * | ||
227 | * An attribute with an associated IIO_EVENT_SH | ||
228 | **/ | ||
229 | #define IIO_EVENT_ATTR_SH(_name, _ev_list, _show, _store, _mask) \ | ||
230 | static struct iio_event_attr \ | ||
231 | iio_event_attr_##_name \ | ||
232 | = { .dev_attr = __ATTR(_name, S_IRUGO | S_IWUSR, \ | ||
233 | _show, _store), \ | ||
234 | .mask = _mask, \ | ||
235 | .listel = &_ev_list }; | ||
236 | |||
237 | /** | ||
238 | * IIO_EVENT_ATTR: non shared event attribute | ||
239 | **/ | ||
240 | #define IIO_EVENT_ATTR(_name, _show, _store, _mask, _handler) \ | ||
241 | static struct iio_event_handler_list \ | ||
242 | iio_event_##_name = { \ | ||
243 | .handler = _handler, \ | ||
244 | }; \ | ||
245 | static struct \ | ||
246 | iio_event_attr \ | ||
247 | iio_event_attr_##_name \ | ||
248 | = { .dev_attr = __ATTR(_name, S_IRUGO | S_IWUSR, \ | ||
249 | _show, _store), \ | ||
250 | .mask = _mask, \ | ||
251 | .listel = &iio_event_##_name }; \ | ||
252 | |||
253 | /** | ||
254 | * IIO_EVENT_ATTR_DATA_RDY: event driven by data ready signal | ||
255 | * | ||
256 | * Not typically implemented in devices where full triggering support | ||
257 | * has been implemented | ||
258 | **/ | ||
259 | #define IIO_EVENT_ATTR_DATA_RDY(_show, _store, _mask, _handler) \ | ||
260 | IIO_EVENT_ATTR(data_rdy, _show, _store, _mask, _handler) | ||
261 | |||
262 | #define IIO_EVENT_CODE_DATA_RDY 100 | ||
263 | #define IIO_EVENT_CODE_RING_BASE 200 | ||
264 | #define IIO_EVENT_CODE_ACCEL_BASE 300 | ||
265 | #define IIO_EVENT_CODE_GYRO_BASE 400 | ||
266 | #define IIO_EVENT_CODE_ADC_BASE 500 | ||
267 | #define IIO_EVENT_CODE_MISC_BASE 600 | ||
268 | |||
269 | #define IIO_EVENT_CODE_DEVICE_SPECIFIC 1000 | ||
270 | |||
271 | /** | ||
272 | * IIO_EVENT_ATTR_RING_50_FULL: ring buffer event to indicate 50% full | ||
273 | **/ | ||
274 | #define IIO_EVENT_ATTR_RING_50_FULL(_show, _store, _mask, _handler) \ | ||
275 | IIO_EVENT_ATTR(ring_50_full, _show, _store, _mask, _handler) | ||
276 | |||
277 | /** | ||
278 | * IIO_EVENT_ATTR_RING_50_FULL_SH: shared ring event to indicate 50% full | ||
279 | **/ | ||
280 | #define IIO_EVENT_ATTR_RING_50_FULL_SH(_evlist, _show, _store, _mask) \ | ||
281 | IIO_EVENT_ATTR_SH(ring_50_full, _evlist, _show, _store, _mask) | ||
282 | |||
283 | /** | ||
284 | * IIO_EVENT_ATTR_RING_75_FULL_SH: shared ring event to indicate 75% full | ||
285 | **/ | ||
286 | #define IIO_EVENT_ATTR_RING_75_FULL_SH(_evlist, _show, _store, _mask) \ | ||
287 | IIO_EVENT_ATTR_SH(ring_75_full, _evlist, _show, _store, _mask) | ||
288 | |||
289 | #define IIO_EVENT_CODE_RING_50_FULL IIO_EVENT_CODE_RING_BASE | ||
290 | #define IIO_EVENT_CODE_RING_75_FULL (IIO_EVENT_CODE_RING_BASE + 1) | ||
291 | #define IIO_EVENT_CODE_RING_100_FULL (IIO_EVENT_CODE_RING_BASE + 2) | ||
292 | |||
293 | #endif /* _INDUSTRIAL_IO_SYSFS_H_ */ | ||
diff --git a/drivers/staging/iio/trigger_consumer.h b/drivers/staging/iio/trigger_consumer.h new file mode 100644 index 000000000000..a6053892893f --- /dev/null +++ b/drivers/staging/iio/trigger_consumer.h | |||
@@ -0,0 +1,26 @@ | |||
1 | |||
2 | /* The industrial I/O core, trigger consumer handling functions | ||
3 | * | ||
4 | * Copyright (c) 2008 Jonathan Cameron | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | /** | ||
12 | * iio_device_register_trigger_consumer() - set up an iio_dev to use triggers. | ||
13 | * @dev_info: iio_dev associated with the device that will consume the trigger | ||
14 | **/ | ||
15 | int iio_device_register_trigger_consumer(struct iio_dev *dev_info) | ||
16 | { | ||
17 | return 0; | ||
18 | }; | ||
19 | /** | ||
20 | * iio_device_unregister_trigger_consumer() - reverse the registration process | ||
21 | . * @dev_info: iio_dev associated with the device that consumed the trigger | ||
22 | **/ | ||
23 | int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info) | ||
24 | { | ||
25 | return 0; | ||
26 | }; | ||