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