summaryrefslogtreecommitdiff
path: root/drivers/staging/iio/iio.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/iio/iio.h')
-rw-r--r--drivers/staging/iio/iio.h356
1 files changed, 235 insertions, 121 deletions
diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h
index 7127f26f8d26..38f1425f4645 100644
--- a/drivers/staging/iio/iio.h
+++ b/drivers/staging/iio/iio.h
@@ -12,6 +12,7 @@
#include <linux/device.h>
#include <linux/cdev.h>
+#include <linux/irq.h>
#include "sysfs.h"
#include "chrdev.h"
@@ -24,9 +25,158 @@
/* Event interface flags */
#define IIO_BUSY_BIT_POS 1
-struct iio_dev;
+/* naughty temporary hack to match these against the event version
+ - need to flattern these together */
+enum iio_chan_type {
+ /* real channel types */
+ IIO_IN,
+ IIO_CURRENT,
+ IIO_POWER,
+ IIO_ACCEL,
+ IIO_IN_DIFF,
+ IIO_GYRO,
+ IIO_MAGN,
+ IIO_LIGHT,
+ IIO_INTENSITY,
+ IIO_PROXIMITY,
+ IIO_TEMP,
+ IIO_INCLI,
+ IIO_ROT,
+ IIO_ANGL,
+ IIO_TIMESTAMP,
+};
+
+#define IIO_MOD_X 0
+#define IIO_MOD_LIGHT_BOTH 0
+#define IIO_MOD_Y 1
+#define IIO_MOD_LIGHT_IR 1
+#define IIO_MOD_Z 2
+#define IIO_MOD_X_AND_Y 3
+#define IIO_MOD_X_ANX_Z 4
+#define IIO_MOD_Y_AND_Z 5
+#define IIO_MOD_X_AND_Y_AND_Z 6
+#define IIO_MOD_X_OR_Y 7
+#define IIO_MOD_X_OR_Z 8
+#define IIO_MOD_Y_OR_Z 9
+#define IIO_MOD_X_OR_Y_OR_Z 10
+
+/* Could add the raw attributes as well - allowing buffer only devices */
+enum iio_chan_info_enum {
+ IIO_CHAN_INFO_SCALE_SHARED,
+ IIO_CHAN_INFO_SCALE_SEPARATE,
+ IIO_CHAN_INFO_OFFSET_SHARED,
+ IIO_CHAN_INFO_OFFSET_SEPARATE,
+ IIO_CHAN_INFO_CALIBSCALE_SHARED,
+ IIO_CHAN_INFO_CALIBSCALE_SEPARATE,
+ IIO_CHAN_INFO_CALIBBIAS_SHARED,
+ IIO_CHAN_INFO_CALIBBIAS_SEPARATE,
+ IIO_CHAN_INFO_PEAK_SHARED,
+ IIO_CHAN_INFO_PEAK_SEPARATE,
+ IIO_CHAN_INFO_PEAK_SCALE_SHARED,
+ IIO_CHAN_INFO_PEAK_SCALE_SEPARATE,
+};
/**
+ * struct iio_chan_spec - specification of a single channel
+ * @type: What type of measurement is the channel making.
+ * @channel: What number or name do we wish to asign the channel.
+ * @channel2: If there is a second number for a differential
+ * channel then this is it. If modified is set then the
+ * value here specifies the modifier.
+ * @address: Driver specific identifier.
+ * @scan_index: Monotonic index to give ordering in scans when read
+ * from a buffer.
+ * @scan_type: Sign: 's' or 'u' to specify signed or unsigned
+ * realbits: Number of valid bits of data
+ * storage_bits: Realbits + padding
+ * shift: Shift right by this before masking out
+ * realbits.
+ * @info_mask: What information is to be exported about this channel.
+ * This includes calibbias, scale etc.
+ * @event_mask: What events can this channel produce.
+ * @extend_name: Allows labeling of channel attributes with an
+ * informative name. Note this has no effect codes etc,
+ * unlike modifiers.
+ * @processed_val: Flag to specify the data access attribute should be
+ * *_input rather than *_raw.
+ * @modified: Does a modifier apply to this channel. What these are
+ * depends on the channel type. Modifier is set in
+ * channel2. Examples are IIO_MOD_X for axial sensors about
+ * the 'x' axis.
+ * @indexed: Specify the channel has a numerical index. If not,
+ * the value in channel will be suppressed for attribute
+ * but not for event codes. Typically set it to 0 when
+ * the index is false.
+ */
+struct iio_chan_spec {
+ enum iio_chan_type type;
+ int channel;
+ int channel2;
+ unsigned long address;
+ int scan_index;
+ struct {
+ char sign;
+ u8 realbits;
+ u8 storagebits;
+ u8 shift;
+ } scan_type;
+ const long info_mask;
+ const long event_mask;
+ const char *extend_name;
+ unsigned processed_val:1;
+ unsigned modified:1;
+ unsigned indexed:1;
+};
+/* Meant for internal use only */
+void __iio_device_attr_deinit(struct device_attribute *dev_attr);
+int __iio_device_attr_init(struct device_attribute *dev_attr,
+ const char *postfix,
+ struct iio_chan_spec const *chan,
+ ssize_t (*readfunc)(struct device *dev,
+ struct device_attribute *attr,
+ char *buf),
+ ssize_t (*writefunc)(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len),
+ bool generic);
+#define IIO_ST(si, rb, sb, sh) \
+ { .sign = si, .realbits = rb, .storagebits = sb, .shift = sh }
+
+#define IIO_CHAN(_type, _mod, _indexed, _proc, _name, _chan, _chan2, \
+ _inf_mask, _address, _si, _stype, _event_mask) \
+ { .type = _type, \
+ .modified = _mod, \
+ .indexed = _indexed, \
+ .processed_val = _proc, \
+ .extend_name = _name, \
+ .channel = _chan, \
+ .channel2 = _chan2, \
+ .info_mask = _inf_mask, \
+ .address = _address, \
+ .scan_index = _si, \
+ .scan_type = _stype, \
+ .event_mask = _event_mask }
+
+#define IIO_CHAN_SOFT_TIMESTAMP(_si) \
+ { .type = IIO_TIMESTAMP, .channel = -1, \
+ .scan_index = _si, .scan_type = IIO_ST('s', 64, 64, 0) }
+
+int __iio_add_chan_devattr(const char *postfix,
+ const char *group,
+ struct iio_chan_spec const *chan,
+ ssize_t (*func)(struct device *dev,
+ struct device_attribute *attr,
+ char *buf),
+ ssize_t (*writefunc)(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t len),
+ int mask,
+ bool generic,
+ struct device *dev,
+ struct list_head *attr_list);
+/**
* iio_get_time_ns() - utility function to get a time stamp for events etc
**/
static inline s64 iio_get_time_ns(void)
@@ -41,26 +191,6 @@ static inline s64 iio_get_time_ns(void)
return timespec_to_ns(&ts);
}
-/**
- * iio_add_event_to_list() - Wraps adding to event lists
- * @el: the list element of the event to be handled.
- * @head: the list associated with the event handler being used.
- *
- * Does reference counting to allow shared handlers.
- **/
-void iio_add_event_to_list(struct iio_event_handler_list *el,
- struct list_head *head);
-
-/**
- * iio_remove_event_from_list() - Wraps removing from event list
- * @el: element to be removed
- * @head: associate list head for the interrupt handler.
- *
- * Does reference counting to allow shared handlers.
- **/
-void iio_remove_event_from_list(struct iio_event_handler_list *el,
- struct list_head *head);
-
/* Device operating modes */
#define INDIO_DIRECT_MODE 0x01
#define INDIO_RING_TRIGGERED 0x02
@@ -70,6 +200,62 @@ void iio_remove_event_from_list(struct iio_event_handler_list *el,
/* Vast majority of this is set by the industrialio subsystem on a
* call to iio_device_register. */
+#define IIO_VAL_INT 1
+#define IIO_VAL_INT_PLUS_MICRO 2
+
+/**
+ * struct iio_info - constant information about device
+ * @driver_module: module structure used to ensure correct
+ * ownership of chrdevs etc
+ * @num_interrupt_lines:number of physical interrupt lines from device
+ * @event_attrs: event control attributes
+ * @attrs: general purpose device attributes
+ * @read_raw: function to request a value from the device.
+ * mask specifies which value. Note 0 means a reading of
+ * the channel in question. Return value will specify the
+ * type of value returned by the device. val and val2 will
+ * contain the elements making up the returned value.
+ * @write_raw: function to write a value to the device.
+ * Parameters are the same as for read_raw.
+ * @read_event_config: find out if the event is enabled.
+ * @write_event_config: set if the event is enabled.
+ * @read_event_value: read a value associated with the event. Meaning
+ * is event dependant. event_code specifies which event.
+ * @write_event_value: write the value associate with the event.
+ * Meaning is event dependent.
+ **/
+struct iio_info {
+ struct module *driver_module;
+ int num_interrupt_lines;
+ struct attribute_group *event_attrs;
+ const struct attribute_group *attrs;
+
+ int (*read_raw)(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val,
+ int *val2,
+ long mask);
+
+ int (*write_raw)(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val,
+ int val2,
+ long mask);
+
+ int (*read_event_config)(struct iio_dev *indio_dev,
+ int event_code);
+
+ int (*write_event_config)(struct iio_dev *indio_dev,
+ int event_code,
+ int state);
+
+ int (*read_event_value)(struct iio_dev *indio_dev,
+ int event_code,
+ int *val);
+ int (*write_event_value)(struct iio_dev *indio_dev,
+ int event_code,
+ int val);
+};
/**
* struct iio_dev - industrial I/O device
@@ -79,13 +265,6 @@ void iio_remove_event_from_list(struct iio_event_handler_list *el,
* @currentmode: [DRIVER] current operating mode
* @dev: [DRIVER] device structure, should be assigned a parent
* and owner
- * @attrs: [DRIVER] general purpose device attributes
- * @driver_module: [DRIVER] module structure used to ensure correct
- * ownership of chrdevs etc
- * @num_interrupt_lines:[DRIVER] number of physical interrupt lines from device
- * @interrupts: [INTERN] interrupt line specific event lists etc
- * @event_attrs: [DRIVER] event control attributes
- * @event_conf_attrs: [DRIVER] event configuration attributes
* @event_interfaces: [INTERN] event chrdevs associated with interrupt lines
* @ring: [DRIVER] any ring buffer present
* @mlock: [INTERN] lock used to prevent simultaneous device state
@@ -93,6 +272,11 @@ void iio_remove_event_from_list(struct iio_event_handler_list *el,
* @available_scan_masks: [DRIVER] optional array of allowed bitmasks
* @trig: [INTERN] current device trigger (ring buffer modes)
* @pollfunc: [DRIVER] function run on trigger being received
+ * @channels: [DRIVER] channel specification structure table
+ * @num_channels: [DRIVER] number of chanels specified in @channels.
+ * @channel_attr_list: [INTERN] keep track of automatically created channel
+ * attributes.
+ * @name: [DRIVER] name of the device.
**/
struct iio_dev {
int id;
@@ -100,13 +284,6 @@ struct iio_dev {
int modes;
int currentmode;
struct device dev;
- const struct attribute_group *attrs;
- struct module *driver_module;
-
- int num_interrupt_lines;
- struct iio_interrupt **interrupts;
- struct attribute_group *event_attrs;
- struct attribute_group *event_conf_attrs;
struct iio_event_interface *event_interfaces;
@@ -116,6 +293,13 @@ struct iio_dev {
u32 *available_scan_masks;
struct iio_trigger *trig;
struct iio_poll_func *pollfunc;
+
+ struct iio_chan_spec const *channels;
+ int num_channels;
+
+ struct list_head channel_attr_list;
+ const char *name;
+ const struct iio_info *info;
};
/**
@@ -131,47 +315,6 @@ int iio_device_register(struct iio_dev *dev_info);
void iio_device_unregister(struct iio_dev *dev_info);
/**
- * struct iio_interrupt - wrapper used to allow easy handling of multiple
- * physical interrupt lines
- * @dev_info: the iio device for which the is an interrupt line
- * @line_number: associated line number
- * @id: ida allocated unique id number
- * @irq: associate interrupt number
- * @ev_list: event handler list for associated events
- * @ev_list_lock: ensure only one access to list at a time
- **/
-struct iio_interrupt {
- struct iio_dev *dev_info;
- int line_number;
- int id;
- int irq;
- struct list_head ev_list;
- spinlock_t ev_list_lock;
-};
-
-#define to_iio_interrupt(i) container_of(i, struct iio_interrupt, ev_list)
-
-/**
- * iio_register_interrupt_line() - Tell IIO about interrupt lines
- *
- * @irq: Typically provided via platform data
- * @dev_info: IIO device info structure for device
- * @line_number: Which interrupt line of the device is this?
- * @type: Interrupt type (e.g. edge triggered etc)
- * @name: Identifying name.
- **/
-int iio_register_interrupt_line(unsigned int irq,
- struct iio_dev *dev_info,
- int line_number,
- unsigned long type,
- const char *name);
-
-void iio_unregister_interrupt_line(struct iio_dev *dev_info,
- int line_number);
-
-
-
-/**
* iio_push_event() - try to add event to the list for userspace reading
* @dev_info: IIO device structure
* @ev_line: Which event line (hardware interrupt)
@@ -183,50 +326,6 @@ int iio_push_event(struct iio_dev *dev_info,
int ev_code,
s64 timestamp);
-/**
- * __iio_push_event() - tries to add an event to the list associated with a chrdev
- * @ev_int: the event interface to which we are pushing the event
- * @ev_code: the outgoing event code
- * @timestamp: timestamp of the event
- * @shared_pointer_p: the shared event pointer
- **/
-int __iio_push_event(struct iio_event_interface *ev_int,
- int ev_code,
- s64 timestamp,
- struct iio_shared_ev_pointer*
- shared_pointer_p);
-/**
- * __iio_change_event() - change an event code in case of event escalation
- * @ev: the event to be changed
- * @ev_code: new event code
- * @timestamp: new timestamp
- **/
-void __iio_change_event(struct iio_detected_event_list *ev,
- int ev_code,
- s64 timestamp);
-
-/**
- * iio_setup_ev_int() - configure an event interface (chrdev)
- * @name: name used for resulting sysfs directory etc.
- * @ev_int: interface we are configuring
- * @owner: module that is responsible for registering this ev_int
- * @dev: device whose ev_int this is
- **/
-int iio_setup_ev_int(struct iio_event_interface *ev_int,
- const char *name,
- struct module *owner,
- struct device *dev);
-
-void iio_free_ev_int(struct iio_event_interface *ev_int);
-
-/**
- * iio_allocate_chrdev() - Allocate a chrdev
- * @handler: struct that contains relevant file handling for chrdev
- * @dev_info: iio_dev for which chrdev is being created
- **/
-int iio_allocate_chrdev(struct iio_handler *handler, struct iio_dev *dev_info);
-void iio_deallocate_chrdev(struct iio_handler *handler);
-
/* Used to distinguish between bipolar and unipolar scan elemenents.
* Whilst this may seem obvious, we may well want to change the representation
* in the future!*/
@@ -264,10 +363,25 @@ static inline void *iio_dev_get_devdata(struct iio_dev *d)
return d->dev_data;
}
+
+/* Can we make this smaller? */
+#define IIO_ALIGN L1_CACHE_BYTES
/**
* iio_allocate_device() - allocate an iio_dev from a driver
+ * @sizeof_priv: Space to allocate for private structure.
**/
-struct iio_dev *iio_allocate_device(void);
+struct iio_dev *iio_allocate_device(int sizeof_priv);
+
+static inline void *iio_priv(const struct iio_dev *dev)
+{
+ return (char *)dev + ALIGN(sizeof(struct iio_dev), IIO_ALIGN);
+}
+
+static inline struct iio_dev *iio_priv_to_dev(void *priv)
+{
+ return (struct iio_dev *)((char *)priv -
+ ALIGN(sizeof(struct iio_dev), IIO_ALIGN));
+}
/**
* iio_free_device() - free an iio_dev from a driver