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