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