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> 248e7d967244a8eebcdadb048efc5e66849ec0a6b6Jonathan Cameron#include <linux/anon_inodes.h> 25e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich#include <linux/debugfs.h> 26847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include "iio.h" 27df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameron#include "iio_core.h" 286aea1c364cde5b28b551844b7b8925f523310a18Jonathan Cameron#include "iio_core_trigger.h" 299dd1cb303c18f4508abc69f5b40f423ff36a9626Jonathan Cameron#include "sysfs.h" 30af5046af1c812839f085030f358a01814666fc80Jonathan Cameron#include "events.h" 319dd1cb303c18f4508abc69f5b40f423ff36a9626Jonathan Cameron 3247c24fdd4253a2c8d730b978a186923b1af5e879Jonathan Cameron/* IDA to assign each registered device a unique id*/ 33b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameronstatic DEFINE_IDA(iio_ida); 34847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 35f625cb97d4d58f311a9606a4bcf9d9a334ca9952Jonathan Cameronstatic dev_t iio_devt; 36847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 37847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#define IIO_DEV_MAX 256 385aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameronstruct bus_type iio_bus_type = { 39847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron .name = "iio", 40847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}; 415aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan CameronEXPORT_SYMBOL(iio_bus_type); 42847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 43e553f182d55bd268fea3f106368e2344141c212aMichael Hennerichstatic struct dentry *iio_debugfs_dentry; 44e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 451e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameronstatic const char * const iio_data_type_name[] = { 461e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron [IIO_RAW] = "raw", 471e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron [IIO_PROCESSED] = "input", 481e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron}; 491e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 50c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameronstatic const char * const iio_direction[] = { 51c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron [0] = "in", 52c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron [1] = "out", 53c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron}; 54c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron 55ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameronstatic const char * const iio_chan_type_name_spec[] = { 56c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron [IIO_VOLTAGE] = "voltage", 57faf290e867fd51e227165d0bef113b022520a58fMichael Hennerich [IIO_CURRENT] = "current", 58faf290e867fd51e227165d0bef113b022520a58fMichael Hennerich [IIO_POWER] = "power", 599bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed [IIO_ACCEL] = "accel", 6041ea040c7b6daf05d4884097b0168e7b74c6c0d0Jonathan Cameron [IIO_ANGL_VEL] = "anglvel", 611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_MAGN] = "magn", 629bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed [IIO_LIGHT] = "illuminance", 639bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed [IIO_INTENSITY] = "intensity", 64f09f2c8142d275b0d9321d2ea93c8bd0d8dc32ecBryan Freed [IIO_PROXIMITY] = "proximity", 659bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed [IIO_TEMP] = "temp", 661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_INCLI] = "incli", 671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_ROT] = "rot", 681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_ANGL] = "angl", 699bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed [IIO_TIMESTAMP] = "timestamp", 7066dbe70437b561c241d1117dd291c11db21072fdJonathan Cameron [IIO_CAPACITANCE] = "capacitance", 711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}; 721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 73330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameronstatic const char * const iio_modifier_names[] = { 741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_MOD_X] = "x", 751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_MOD_Y] = "y", 761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_MOD_Z] = "z", 77330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron [IIO_MOD_LIGHT_BOTH] = "both", 78330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron [IIO_MOD_LIGHT_IR] = "ir", 791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}; 801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron/* relies on pairs of these shared then separate */ 821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_chan_info_postfix[] = { 83c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_SCALE] = "scale", 84c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_OFFSET] = "offset", 85c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_CALIBSCALE] = "calibscale", 86c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_CALIBBIAS] = "calibbias", 87c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_PEAK] = "peak_raw", 88c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_PEAK_SCALE] = "peak_scale", 89c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW] = "quadrature_correction_raw", 90c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw", 91df94aba81f81c50ff3f4774c121217b03aaf4f27Jonathan Cameron [IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY] 92df94aba81f81c50ff3f4774c121217b03aaf4f27Jonathan Cameron = "filter_low_pass_3db_frequency", 931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}; 941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 955fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameronconst struct iio_chan_spec 965fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron*iio_find_channel_from_si(struct iio_dev *indio_dev, int si) 975fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron{ 985fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron int i; 995fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron 1005fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron for (i = 0; i < indio_dev->num_channels; i++) 1015fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron if (indio_dev->channels[i].scan_index == si) 1025fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron return &indio_dev->channels[i]; 1035fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron return NULL; 1045fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron} 1055fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron 106847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron/* This turns up an awful lot */ 107847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronssize_t iio_read_const_attr(struct device *dev, 108847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron struct device_attribute *attr, 109847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron char *buf) 110847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 111847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return sprintf(buf, "%s\n", to_iio_const_attr(attr)->string); 112847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 113847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_read_const_attr); 114847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 115847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic int __init iio_init(void) 116847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 117847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron int ret; 118847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1195aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron /* Register sysfs bus */ 1205aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron ret = bus_register(&iio_bus_type); 121847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (ret < 0) { 122847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron printk(KERN_ERR 1235aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron "%s could not register bus type\n", 124847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron __FILE__); 125847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron goto error_nothing; 126847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 127847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1289aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio"); 1299aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron if (ret < 0) { 1309aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron printk(KERN_ERR "%s: failed to allocate char dev region\n", 1319aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron __FILE__); 1325aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron goto error_unregister_bus_type; 1339aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron } 134847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 135e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich iio_debugfs_dentry = debugfs_create_dir("iio", NULL); 136e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 137847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return 0; 138847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1395aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameronerror_unregister_bus_type: 1405aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron bus_unregister(&iio_bus_type); 141847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_nothing: 142847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return ret; 143847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 144847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 145847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void __exit iio_exit(void) 146847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 1479aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron if (iio_devt) 1489aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron unregister_chrdev_region(iio_devt, IIO_DEV_MAX); 1495aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron bus_unregister(&iio_bus_type); 150e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich debugfs_remove(iio_debugfs_dentry); 151e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich} 152e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 153e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich#if defined(CONFIG_DEBUG_FS) 154e553f182d55bd268fea3f106368e2344141c212aMichael Hennerichstatic int iio_debugfs_open(struct inode *inode, struct file *file) 155e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich{ 156e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich if (inode->i_private) 157e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich file->private_data = inode->i_private; 158e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 159e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich return 0; 160e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich} 161e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 162e553f182d55bd268fea3f106368e2344141c212aMichael Hennerichstatic ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf, 163e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich size_t count, loff_t *ppos) 164e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich{ 165e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich struct iio_dev *indio_dev = file->private_data; 166e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich char buf[20]; 167e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich unsigned val = 0; 168e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich ssize_t len; 169e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich int ret; 170e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 171e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich ret = indio_dev->info->debugfs_reg_access(indio_dev, 172e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich indio_dev->cached_reg_addr, 173e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 0, &val); 174e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich if (ret) 175e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich dev_err(indio_dev->dev.parent, "%s: read failed\n", __func__); 176e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 177e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich len = snprintf(buf, sizeof(buf), "0x%X\n", val); 178e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 179e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich return simple_read_from_buffer(userbuf, count, ppos, buf, len); 180e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich} 181e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 182e553f182d55bd268fea3f106368e2344141c212aMichael Hennerichstatic ssize_t iio_debugfs_write_reg(struct file *file, 183e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich const char __user *userbuf, size_t count, loff_t *ppos) 184e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich{ 185e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich struct iio_dev *indio_dev = file->private_data; 186e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich unsigned reg, val; 187e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich char buf[80]; 188e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich int ret; 189e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 190e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich count = min_t(size_t, count, (sizeof(buf)-1)); 191e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich if (copy_from_user(buf, userbuf, count)) 192e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich return -EFAULT; 193e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 194e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich buf[count] = 0; 195e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 196e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich ret = sscanf(buf, "%i %i", ®, &val); 197e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 198e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich switch (ret) { 199e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich case 1: 200e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich indio_dev->cached_reg_addr = reg; 201e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich break; 202e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich case 2: 203e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich indio_dev->cached_reg_addr = reg; 204e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich ret = indio_dev->info->debugfs_reg_access(indio_dev, reg, 205e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich val, NULL); 206e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich if (ret) { 207e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich dev_err(indio_dev->dev.parent, "%s: write failed\n", 208e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich __func__); 209e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich return ret; 210e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich } 211e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich break; 212e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich default: 213e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich return -EINVAL; 214e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich } 215e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 216e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich return count; 217e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich} 218e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 219e553f182d55bd268fea3f106368e2344141c212aMichael Hennerichstatic const struct file_operations iio_debugfs_reg_fops = { 220e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich .open = iio_debugfs_open, 221e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich .read = iio_debugfs_read_reg, 222e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich .write = iio_debugfs_write_reg, 223e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich}; 224e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 225e553f182d55bd268fea3f106368e2344141c212aMichael Hennerichstatic void iio_device_unregister_debugfs(struct iio_dev *indio_dev) 226e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich{ 227e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich debugfs_remove_recursive(indio_dev->debugfs_dentry); 228847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 229847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 230e553f182d55bd268fea3f106368e2344141c212aMichael Hennerichstatic int iio_device_register_debugfs(struct iio_dev *indio_dev) 231e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich{ 232e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich struct dentry *d; 233e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 234e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich if (indio_dev->info->debugfs_reg_access == NULL) 235e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich return 0; 236e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 237e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich if (IS_ERR(iio_debugfs_dentry)) 238e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich return 0; 239e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 240e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich indio_dev->debugfs_dentry = 241e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich debugfs_create_dir(dev_name(&indio_dev->dev), 242e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich iio_debugfs_dentry); 243e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich if (IS_ERR(indio_dev->debugfs_dentry)) 244e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich return PTR_ERR(indio_dev->debugfs_dentry); 245e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 246e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich if (indio_dev->debugfs_dentry == NULL) { 247e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich dev_warn(indio_dev->dev.parent, 248e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich "Failed to create debugfs directory\n"); 249e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich return -EFAULT; 250e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich } 251e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 252e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich d = debugfs_create_file("direct_reg_access", 0644, 253e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich indio_dev->debugfs_dentry, 254e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich indio_dev, &iio_debugfs_reg_fops); 255e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich if (!d) { 256e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich iio_device_unregister_debugfs(indio_dev); 257e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich return -ENOMEM; 258e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich } 259e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 260e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich return 0; 261e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich} 262e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich#else 263e553f182d55bd268fea3f106368e2344141c212aMichael Hennerichstatic int iio_device_register_debugfs(struct iio_dev *indio_dev) 264e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich{ 265e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich return 0; 266e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich} 267e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 268e553f182d55bd268fea3f106368e2344141c212aMichael Hennerichstatic void iio_device_unregister_debugfs(struct iio_dev *indio_dev) 269e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich{ 270e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich} 271e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich#endif /* CONFIG_DEBUG_FS */ 272e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich 2734fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausenstatic ssize_t iio_read_channel_ext_info(struct device *dev, 2744fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen struct device_attribute *attr, 2754fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen char *buf) 2764fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen{ 2774fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen struct iio_dev *indio_dev = dev_get_drvdata(dev); 2784fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 2794fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen const struct iio_chan_spec_ext_info *ext_info; 2804fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen 2814fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen ext_info = &this_attr->c->ext_info[this_attr->address]; 2824fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen 2834fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen return ext_info->read(indio_dev, this_attr->c, buf); 2844fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen} 2854fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen 2864fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausenstatic ssize_t iio_write_channel_ext_info(struct device *dev, 2874fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen struct device_attribute *attr, 2884fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen const char *buf, 2894fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen size_t len) 2904fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen{ 2914fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen struct iio_dev *indio_dev = dev_get_drvdata(dev); 2924fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 2934fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen const struct iio_chan_spec_ext_info *ext_info; 2944fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen 2954fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen ext_info = &this_attr->c->ext_info[this_attr->address]; 2964fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen 2974fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen return ext_info->write(indio_dev, this_attr->c, buf, len); 2984fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen} 2994fee7e168ba08ed067ee9aafe4a0a19387117be4Lars-Peter Clausen 3001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_read_channel_info(struct device *dev, 3011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 3021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *buf) 303847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 3041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 3051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 3061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron int val, val2; 3076fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron int ret = indio_dev->info->read_raw(indio_dev, this_attr->c, 3086fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron &val, &val2, this_attr->address); 3091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret < 0) 3111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 312847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 3131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret == IIO_VAL_INT) 3141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return sprintf(buf, "%d\n", val); 3151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else if (ret == IIO_VAL_INT_PLUS_MICRO) { 3161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (val2 < 0) 3171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return sprintf(buf, "-%d.%06u\n", val, -val2); 3181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else 3191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return sprintf(buf, "%d.%06u\n", val, val2); 32071646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich } else if (ret == IIO_VAL_INT_PLUS_NANO) { 32171646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich if (val2 < 0) 32271646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich return sprintf(buf, "-%d.%09u\n", val, -val2); 32371646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich else 32471646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich return sprintf(buf, "%d.%09u\n", val, val2); 3251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } else 3261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 3271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 3281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_write_channel_info(struct device *dev, 3301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 3311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *buf, 3321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron size_t len) 3331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 3341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 3351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 3365c04af04835269c194662be63fe168893fad667fMichael Hennerich int ret, integer = 0, fract = 0, fract_mult = 100000; 3371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron bool integer_part = true, negative = false; 3381d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron /* Assumes decimal - precision based on number of digits */ 3406fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron if (!indio_dev->info->write_raw) 3411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return -EINVAL; 3425c04af04835269c194662be63fe168893fad667fMichael Hennerich 3435c04af04835269c194662be63fe168893fad667fMichael Hennerich if (indio_dev->info->write_raw_get_fmt) 3445c04af04835269c194662be63fe168893fad667fMichael Hennerich switch (indio_dev->info->write_raw_get_fmt(indio_dev, 3455c04af04835269c194662be63fe168893fad667fMichael Hennerich this_attr->c, this_attr->address)) { 3465c04af04835269c194662be63fe168893fad667fMichael Hennerich case IIO_VAL_INT_PLUS_MICRO: 3475c04af04835269c194662be63fe168893fad667fMichael Hennerich fract_mult = 100000; 3485c04af04835269c194662be63fe168893fad667fMichael Hennerich break; 3495c04af04835269c194662be63fe168893fad667fMichael Hennerich case IIO_VAL_INT_PLUS_NANO: 3505c04af04835269c194662be63fe168893fad667fMichael Hennerich fract_mult = 100000000; 3515c04af04835269c194662be63fe168893fad667fMichael Hennerich break; 3525c04af04835269c194662be63fe168893fad667fMichael Hennerich default: 3535c04af04835269c194662be63fe168893fad667fMichael Hennerich return -EINVAL; 3545c04af04835269c194662be63fe168893fad667fMichael Hennerich } 3555c04af04835269c194662be63fe168893fad667fMichael Hennerich 3561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (buf[0] == '-') { 3571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron negative = true; 3581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron buf++; 3591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3605c04af04835269c194662be63fe168893fad667fMichael Hennerich 3611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron while (*buf) { 3621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if ('0' <= *buf && *buf <= '9') { 3631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (integer_part) 3641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron integer = integer*10 + *buf - '0'; 3651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else { 3665c04af04835269c194662be63fe168893fad667fMichael Hennerich fract += fract_mult*(*buf - '0'); 3675c04af04835269c194662be63fe168893fad667fMichael Hennerich if (fract_mult == 1) 3681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron break; 3695c04af04835269c194662be63fe168893fad667fMichael Hennerich fract_mult /= 10; 3701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } else if (*buf == '\n') { 3721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (*(buf + 1) == '\0') 3731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron break; 3741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else 3751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return -EINVAL; 3761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } else if (*buf == '.') { 3771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron integer_part = false; 3781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } else { 3791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return -EINVAL; 3801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron buf++; 3821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (negative) { 3841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (integer) 3851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron integer = -integer; 3861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else 3875c04af04835269c194662be63fe168893fad667fMichael Hennerich fract = -fract; 3881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3906fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron ret = indio_dev->info->write_raw(indio_dev, this_attr->c, 3915c04af04835269c194662be63fe168893fad667fMichael Hennerich integer, fract, this_attr->address); 3921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret) 3931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 3941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return len; 3961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 3971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 398df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameronstatic 3991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronint __iio_device_attr_init(struct device_attribute *dev_attr, 4001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *postfix, 4011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_chan_spec const *chan, 4021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ssize_t (*readfunc)(struct device *dev, 4031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 4041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *buf), 4051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ssize_t (*writefunc)(struct device *dev, 4061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 4071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *buf, 4081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron size_t len), 4091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron bool generic) 4101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 4111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron int ret; 4121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *name_format, *full_postfix; 4131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron sysfs_attr_init(&dev_attr->attr); 4141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 415ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron /* Build up postfix of <extend_name>_<modifier>_postfix */ 4160403e0d643809f1608448ada38a1877f26b7bf5dJonathan Cameron if (chan->modified && !generic) { 417ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (chan->extend_name) 418ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", 419ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_modifier_names[chan 420ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron ->channel2], 421ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->extend_name, 422ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron postfix); 423ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else 424ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix = kasprintf(GFP_KERNEL, "%s_%s", 425ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_modifier_names[chan 426ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron ->channel2], 427ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron postfix); 428ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } else { 429ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (chan->extend_name == NULL) 430ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix = kstrdup(postfix, GFP_KERNEL); 431ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else 432ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix = kasprintf(GFP_KERNEL, 433ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron "%s_%s", 434ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->extend_name, 435ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron postfix); 436ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } 437ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (full_postfix == NULL) { 438ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron ret = -ENOMEM; 439ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron goto error_ret; 440ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } 4411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 4424abf6f8b29e37f492078173a9d4cb808ce327ec0Justin P. Mattock if (chan->differential) { /* Differential can not have modifier */ 443ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (generic) 444ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 445ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s-%s_%s", 446ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 447ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 448ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 449ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 450ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else if (chan->indexed) 451ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 452ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s%d-%s%d_%s", 453ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 454ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 455ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->channel, 456ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 457ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->channel2, 458ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 459ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else { 460ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron WARN_ON("Differential channels must be indexed\n"); 461ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron ret = -EINVAL; 462ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron goto error_free_full_postfix; 463ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } 464ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } else { /* Single ended */ 465ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (generic) 466ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 467ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s_%s", 468ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 469ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 470ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 471ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else if (chan->indexed) 472ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 473ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s%d_%s", 474ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 475ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 476ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->channel, 477ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 478ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else 479ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 480ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s_%s", 481ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 482ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 483ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 484ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } 4851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (name_format == NULL) { 4861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -ENOMEM; 4871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_free_full_postfix; 4881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 4891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->attr.name = kasprintf(GFP_KERNEL, 4901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron name_format, 4911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron chan->channel, 4921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron chan->channel2); 4931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (dev_attr->attr.name == NULL) { 4941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -ENOMEM; 4951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_free_name_format; 4961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 4971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 4981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (readfunc) { 4991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->attr.mode |= S_IRUGO; 5001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->show = readfunc; 5011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 5021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (writefunc) { 5041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->attr.mode |= S_IWUSR; 5051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->store = writefunc; 5061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 5071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(name_format); 5081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(full_postfix); 5091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 5111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_free_name_format: 5131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(name_format); 5141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_free_full_postfix: 5151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(full_postfix); 5161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret: 5171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 5181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 5191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 520df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameronstatic void __iio_device_attr_deinit(struct device_attribute *dev_attr) 5211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 5221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(dev_attr->attr.name); 5231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 5241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronint __iio_add_chan_devattr(const char *postfix, 5261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_chan_spec const *chan, 5271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ssize_t (*readfunc)(struct device *dev, 5281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 5291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *buf), 5301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ssize_t (*writefunc)(struct device *dev, 5311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 5321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *buf, 5331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron size_t len), 534e614a54b296185b266b4bd91193e08a5fbd32422Jonathan Cameron u64 mask, 5351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron bool generic, 5361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device *dev, 5371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct list_head *attr_list) 5381d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 5391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron int ret; 5401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *iio_attr, *t; 5411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_attr = kzalloc(sizeof *iio_attr, GFP_KERNEL); 5431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (iio_attr == NULL) { 5441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -ENOMEM; 5451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 5461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 5471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = __iio_device_attr_init(&iio_attr->dev_attr, 5481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron postfix, chan, 5491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron readfunc, writefunc, generic); 5501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret) 5511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_iio_dev_attr_free; 5521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_attr->c = chan; 5531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_attr->address = mask; 5541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_for_each_entry(t, attr_list, l) 5551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (strcmp(t->dev_attr.attr.name, 5561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_attr->dev_attr.attr.name) == 0) { 5571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (!generic) 5581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_err(dev, "tried to double register : %s\n", 5591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron t->dev_attr.attr.name); 5601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -EBUSY; 5611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_device_attr_deinit; 5621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 5631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_add(&iio_attr->l, attr_list); 5641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 5661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_device_attr_deinit: 5681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron __iio_device_attr_deinit(&iio_attr->dev_attr); 5691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_iio_dev_attr_free: 5701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(iio_attr); 5711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret: 5721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 5731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 5741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 575f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, 5761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_chan_spec const *chan) 5771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 57826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron int ret, i, attrcount = 0; 5795f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen const struct iio_chan_spec_ext_info *ext_info; 5801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (chan->channel < 0) 5821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 5831e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 5841e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron ret = __iio_add_chan_devattr(iio_data_type_name[chan->processed_val], 58526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron chan, 5861e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron &iio_read_channel_info, 587c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron (chan->output ? 5881e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron &iio_write_channel_info : NULL), 5891e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 0, 5901e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 0, 591f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->dev, 592f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->channel_attr_list); 5931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret) 5941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 59526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount++; 5961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) { 5981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2], 59926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron chan, 6001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron &iio_read_channel_info, 6011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron &iio_write_channel_info, 602c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron i/2, 6031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron !(i%2), 604f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->dev, 605f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->channel_attr_list); 6061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret == -EBUSY && (i%2 == 0)) { 6071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = 0; 6081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron continue; 6091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 6101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret < 0) 6111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 61226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount++; 6131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 6145f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen 6155f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen if (chan->ext_info) { 6165f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen unsigned int i = 0; 6175f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen for (ext_info = chan->ext_info; ext_info->name; ext_info++) { 6185f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen ret = __iio_add_chan_devattr(ext_info->name, 6195f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen chan, 6205f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen ext_info->read ? 6215f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen &iio_read_channel_ext_info : NULL, 6225f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen ext_info->write ? 6235f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen &iio_write_channel_ext_info : NULL, 6245f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen i, 6255f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen ext_info->shared, 6265f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen &indio_dev->dev, 6275f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen &indio_dev->channel_attr_list); 6285f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen i++; 6295f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen if (ret == -EBUSY && ext_info->shared) 6305f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen continue; 6315f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen 6325f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen if (ret) 6335f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen goto error_ret; 6345f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen 6355f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen attrcount++; 6365f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen } 6375f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen } 6385f420b42079c115daf3b45bbd15bcb6b7b05ad21Lars-Peter Clausen 63926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron ret = attrcount; 6401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret: 6411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 6421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 6431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 644f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic void iio_device_remove_and_free_read_attr(struct iio_dev *indio_dev, 6451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *p) 6461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 6471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(p->dev_attr.attr.name); 6481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(p); 6491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 6501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 6511b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameronstatic ssize_t iio_show_dev_name(struct device *dev, 6521b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron struct device_attribute *attr, 6531b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron char *buf) 6541b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron{ 6551b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 6561b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron return sprintf(buf, "%s\n", indio_dev->name); 6571b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron} 6581b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron 6591b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameronstatic DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL); 6601b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron 661f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_register_sysfs(struct iio_dev *indio_dev) 6621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 66326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron int i, ret = 0, attrcount, attrn, attrcount_orig = 0; 6641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *p, *n; 66526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron struct attribute **attr; 6661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 66726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron /* First count elements in any existing group */ 668f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->info->attrs) { 669f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron attr = indio_dev->info->attrs->attrs; 67026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron while (*attr++ != NULL) 67126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount_orig++; 672847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 67326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount = attrcount_orig; 6741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron /* 6751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron * New channel registration method - relies on the fact a group does 6764abf6f8b29e37f492078173a9d4cb808ce327ec0Justin P. Mattock * not need to be initialized if it is name is NULL. 6771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron */ 678f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron INIT_LIST_HEAD(&indio_dev->channel_attr_list); 679f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->channels) 680f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron for (i = 0; i < indio_dev->num_channels; i++) { 681f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = iio_device_add_channel_sysfs(indio_dev, 682f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev 6831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ->channels[i]); 6841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret < 0) 6851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_clear_attrs; 68626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount += ret; 6871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 68826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 689f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->name) 69026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount++; 69126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 692d83fb184945cd2daaafd33a702bba9cb7ed502bfThomas Meyer indio_dev->chan_attr_group.attrs = kcalloc(attrcount + 1, 693d83fb184945cd2daaafd33a702bba9cb7ed502bfThomas Meyer sizeof(indio_dev->chan_attr_group.attrs[0]), 694d83fb184945cd2daaafd33a702bba9cb7ed502bfThomas Meyer GFP_KERNEL); 695f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->chan_attr_group.attrs == NULL) { 69626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron ret = -ENOMEM; 69726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron goto error_clear_attrs; 6981b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron } 69926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron /* Copy across original attributes */ 700f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->info->attrs) 701f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron memcpy(indio_dev->chan_attr_group.attrs, 702f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->info->attrs->attrs, 703f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron sizeof(indio_dev->chan_attr_group.attrs[0]) 70426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron *attrcount_orig); 70526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrn = attrcount_orig; 70626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron /* Add all elements from the list. */ 707f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron list_for_each_entry(p, &indio_dev->channel_attr_list, l) 708f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr; 709f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->name) 710f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr; 71126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 712f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->groups[indio_dev->groupcounter++] = 713f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->chan_attr_group; 71426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 7151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 7161b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron 7171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_clear_attrs: 7181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_for_each_entry_safe(p, n, 719f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->channel_attr_list, l) { 7201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_del(&p->l); 721f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_remove_and_free_read_attr(indio_dev, p); 7221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 7231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 72426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron return ret; 725847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 726847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 727f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic void iio_device_unregister_sysfs(struct iio_dev *indio_dev) 728847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 7291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 7301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *p, *n; 73126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 732f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron list_for_each_entry_safe(p, n, &indio_dev->channel_attr_list, l) { 7331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_del(&p->l); 734f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_remove_and_free_read_attr(indio_dev, p); 7351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 736f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron kfree(indio_dev->chan_attr_group.attrs); 737847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 738847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 739847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void iio_dev_release(struct device *device) 740847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 741f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron struct iio_dev *indio_dev = container_of(device, struct iio_dev, dev); 742f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron cdev_del(&indio_dev->chrdev); 743f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) 744f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_trigger_consumer(indio_dev); 745f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_eventset(indio_dev); 746f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_sysfs(indio_dev); 747e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich iio_device_unregister_debugfs(indio_dev); 748847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 749847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 750847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic struct device_type iio_dev_type = { 751847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron .name = "iio_device", 752847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron .release = iio_dev_release, 753847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}; 754847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 7556f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameronstruct iio_dev *iio_allocate_device(int sizeof_priv) 756847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 7576f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron struct iio_dev *dev; 7586f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron size_t alloc_size; 7596f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron 7606f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron alloc_size = sizeof(struct iio_dev); 7616f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron if (sizeof_priv) { 7626f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron alloc_size = ALIGN(alloc_size, IIO_ALIGN); 7636f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron alloc_size += sizeof_priv; 7646f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron } 7656f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron /* ensure 32-byte alignment of whole construct ? */ 7666f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron alloc_size += IIO_ALIGN - 1; 7676f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron 7686f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron dev = kzalloc(alloc_size, GFP_KERNEL); 769847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 770847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (dev) { 77126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron dev->dev.groups = dev->groups; 772847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron dev->dev.type = &iio_dev_type; 7735aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron dev->dev.bus = &iio_bus_type; 774847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron device_initialize(&dev->dev); 775847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron dev_set_drvdata(&dev->dev, (void *)dev); 776847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_init(&dev->mlock); 777ac917a81117ce0286847666b55dd265f6cda8383Jonathan Cameron mutex_init(&dev->info_exist_lock); 778a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron 779a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); 780a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron if (dev->id < 0) { 781a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron /* cannot use a dev_err as the name isn't available */ 782a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron printk(KERN_ERR "Failed to get id\n"); 783a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron kfree(dev); 784a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron return NULL; 785a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron } 786a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron dev_set_name(&dev->dev, "iio:device%d", dev->id); 787847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 788847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 789847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return dev; 790847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 791847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_allocate_device); 792847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 793847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronvoid iio_free_device(struct iio_dev *dev) 794847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 795a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron if (dev) { 796a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron ida_simple_remove(&iio_ida, dev->id); 7971aa042783251c27a93e31929c24647729db326d4Jonathan Cameron kfree(dev); 798a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron } 799847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 800847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_free_device); 801847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 8021aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/** 80314555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron * iio_chrdev_open() - chrdev file open for buffer access and ioctls 8041aa042783251c27a93e31929c24647729db326d4Jonathan Cameron **/ 8051aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic int iio_chrdev_open(struct inode *inode, struct file *filp) 8061aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{ 807f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron struct iio_dev *indio_dev = container_of(inode->i_cdev, 8081aa042783251c27a93e31929c24647729db326d4Jonathan Cameron struct iio_dev, chrdev); 809bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen 810bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags)) 811bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen return -EBUSY; 812bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen 813f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron filp->private_data = indio_dev; 81430eb82f05dd1f12b18a0ad054401a0b5690fb3c3Jonathan Cameron 8157933514043d42e69663a5123a53fab50eb0b4abaLars-Peter Clausen return 0; 8161aa042783251c27a93e31929c24647729db326d4Jonathan Cameron} 8171aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 8181aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/** 81914555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron * iio_chrdev_release() - chrdev file close buffer access and ioctls 8201aa042783251c27a93e31929c24647729db326d4Jonathan Cameron **/ 8211aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic int iio_chrdev_release(struct inode *inode, struct file *filp) 8221aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{ 823bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen struct iio_dev *indio_dev = container_of(inode->i_cdev, 824bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen struct iio_dev, chrdev); 825bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags); 8261aa042783251c27a93e31929c24647729db326d4Jonathan Cameron return 0; 8271aa042783251c27a93e31929c24647729db326d4Jonathan Cameron} 8281aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 8291aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/* Somewhat of a cross file organization violation - ioctls here are actually 8301aa042783251c27a93e31929c24647729db326d4Jonathan Cameron * event related */ 8311aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 8321aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{ 8331aa042783251c27a93e31929c24647729db326d4Jonathan Cameron struct iio_dev *indio_dev = filp->private_data; 8341aa042783251c27a93e31929c24647729db326d4Jonathan Cameron int __user *ip = (int __user *)arg; 8351aa042783251c27a93e31929c24647729db326d4Jonathan Cameron int fd; 8361aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 8371aa042783251c27a93e31929c24647729db326d4Jonathan Cameron if (cmd == IIO_GET_EVENT_FD_IOCTL) { 8381aa042783251c27a93e31929c24647729db326d4Jonathan Cameron fd = iio_event_getfd(indio_dev); 8391aa042783251c27a93e31929c24647729db326d4Jonathan Cameron if (copy_to_user(ip, &fd, sizeof(fd))) 8401aa042783251c27a93e31929c24647729db326d4Jonathan Cameron return -EFAULT; 8411aa042783251c27a93e31929c24647729db326d4Jonathan Cameron return 0; 8421aa042783251c27a93e31929c24647729db326d4Jonathan Cameron } 8431aa042783251c27a93e31929c24647729db326d4Jonathan Cameron return -EINVAL; 8441aa042783251c27a93e31929c24647729db326d4Jonathan Cameron} 8451aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 84614555b14455f9acbdf0e500ae96140828a970796Jonathan Cameronstatic const struct file_operations iio_buffer_fileops = { 84714555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron .read = iio_buffer_read_first_n_outer_addr, 8481aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .release = iio_chrdev_release, 8491aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .open = iio_chrdev_open, 85014555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron .poll = iio_buffer_poll_addr, 8511aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .owner = THIS_MODULE, 8521aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .llseek = noop_llseek, 8531aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .unlocked_ioctl = iio_ioctl, 8541aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .compat_ioctl = iio_ioctl, 8551aa042783251c27a93e31929c24647729db326d4Jonathan Cameron}; 8561aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 8570f1acee5f5e2ceaef3244dc4c1f3895b907669cdMichael Hennerichstatic const struct iio_buffer_setup_ops noop_ring_setup_ops; 8580f1acee5f5e2ceaef3244dc4c1f3895b907669cdMichael Hennerich 859f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronint iio_device_register(struct iio_dev *indio_dev) 860847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 861847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron int ret; 862847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 8631aa042783251c27a93e31929c24647729db326d4Jonathan Cameron /* configure elements for the chrdev */ 864f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id); 865847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 866e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich ret = iio_device_register_debugfs(indio_dev); 867e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich if (ret) { 868e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich dev_err(indio_dev->dev.parent, 869e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich "Failed to register debugfs interfaces\n"); 870e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich goto error_ret; 871e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich } 872f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = iio_device_register_sysfs(indio_dev); 873847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (ret) { 874f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron dev_err(indio_dev->dev.parent, 875847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron "Failed to register sysfs interfaces\n"); 876e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich goto error_unreg_debugfs; 877847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 878f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = iio_device_register_eventset(indio_dev); 879847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (ret) { 880f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron dev_err(indio_dev->dev.parent, 881c849d2538ebeef1ac26fad7a10c18b1e0fc35161Roel Van Nyen "Failed to register event set\n"); 882847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron goto error_free_sysfs; 883847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 884f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) 885f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_register_trigger_consumer(indio_dev); 886847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 8870f1acee5f5e2ceaef3244dc4c1f3895b907669cdMichael Hennerich if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) && 8880f1acee5f5e2ceaef3244dc4c1f3895b907669cdMichael Hennerich indio_dev->setup_ops == NULL) 8890f1acee5f5e2ceaef3244dc4c1f3895b907669cdMichael Hennerich indio_dev->setup_ops = &noop_ring_setup_ops; 8900f1acee5f5e2ceaef3244dc4c1f3895b907669cdMichael Hennerich 891f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = device_add(&indio_dev->dev); 89226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron if (ret < 0) 89326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron goto error_unreg_eventset; 894f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron cdev_init(&indio_dev->chrdev, &iio_buffer_fileops); 895f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->chrdev.owner = indio_dev->info->driver_module; 896f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1); 89726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron if (ret < 0) 89826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron goto error_del_device; 899847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return 0; 900847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 901847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_del_device: 902f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron device_del(&indio_dev->dev); 90326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameronerror_unreg_eventset: 904f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_eventset(indio_dev); 90526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameronerror_free_sysfs: 906f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_sysfs(indio_dev); 907e553f182d55bd268fea3f106368e2344141c212aMichael Hennericherror_unreg_debugfs: 908e553f182d55bd268fea3f106368e2344141c212aMichael Hennerich iio_device_unregister_debugfs(indio_dev); 909847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret: 910847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return ret; 911847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 912847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_device_register); 913847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 914f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronvoid iio_device_unregister(struct iio_dev *indio_dev) 915847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 916ac917a81117ce0286847666b55dd265f6cda8383Jonathan Cameron mutex_lock(&indio_dev->info_exist_lock); 917ac917a81117ce0286847666b55dd265f6cda8383Jonathan Cameron indio_dev->info = NULL; 918ac917a81117ce0286847666b55dd265f6cda8383Jonathan Cameron mutex_unlock(&indio_dev->info_exist_lock); 919f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron device_unregister(&indio_dev->dev); 920847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 921847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_device_unregister); 922847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronsubsys_initcall(iio_init); 923847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronmodule_exit(iio_exit); 924847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 925847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); 926847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_DESCRIPTION("Industrial I/O core"); 927847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_LICENSE("GPL"); 928