industrialio-core.c revision ac917a81117ce0286847666b55dd265f6cda8383
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> 25847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#include "iio.h" 26df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameron#include "iio_core.h" 276aea1c364cde5b28b551844b7b8925f523310a18Jonathan Cameron#include "iio_core_trigger.h" 289dd1cb303c18f4508abc69f5b40f423ff36a9626Jonathan Cameron#include "sysfs.h" 29af5046af1c812839f085030f358a01814666fc80Jonathan Cameron#include "events.h" 309dd1cb303c18f4508abc69f5b40f423ff36a9626Jonathan Cameron 3147c24fdd4253a2c8d730b978a186923b1af5e879Jonathan Cameron/* IDA to assign each registered device a unique id*/ 32b156cf70e1f4befc4856baaf9681dede9a143888Jonathan Cameronstatic DEFINE_IDA(iio_ida); 33847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 34f625cb97d4d58f311a9606a4bcf9d9a334ca9952Jonathan Cameronstatic dev_t iio_devt; 35847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 36847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron#define IIO_DEV_MAX 256 375aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameronstruct bus_type iio_bus_type = { 38847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron .name = "iio", 39847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}; 405aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan CameronEXPORT_SYMBOL(iio_bus_type); 41847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 421e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameronstatic const char * const iio_data_type_name[] = { 431e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron [IIO_RAW] = "raw", 441e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron [IIO_PROCESSED] = "input", 451e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron}; 461e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 47c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameronstatic const char * const iio_direction[] = { 48c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron [0] = "in", 49c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron [1] = "out", 50c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron}; 51c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron 52ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameronstatic const char * const iio_chan_type_name_spec[] = { 53c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron [IIO_VOLTAGE] = "voltage", 54faf290e867fd51e227165d0bef113b022520a58fMichael Hennerich [IIO_CURRENT] = "current", 55faf290e867fd51e227165d0bef113b022520a58fMichael Hennerich [IIO_POWER] = "power", 569bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed [IIO_ACCEL] = "accel", 5741ea040c7b6daf05d4884097b0168e7b74c6c0d0Jonathan Cameron [IIO_ANGL_VEL] = "anglvel", 581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_MAGN] = "magn", 599bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed [IIO_LIGHT] = "illuminance", 609bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed [IIO_INTENSITY] = "intensity", 61f09f2c8142d275b0d9321d2ea93c8bd0d8dc32ecBryan Freed [IIO_PROXIMITY] = "proximity", 629bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed [IIO_TEMP] = "temp", 631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_INCLI] = "incli", 641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_ROT] = "rot", 651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_ANGL] = "angl", 669bff02f8f71c4366efd6f5d79150f9786884bd1cBryan Freed [IIO_TIMESTAMP] = "timestamp", 6766dbe70437b561c241d1117dd291c11db21072fdJonathan Cameron [IIO_CAPACITANCE] = "capacitance", 681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}; 691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 70330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameronstatic const char * const iio_modifier_names[] = { 711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_MOD_X] = "x", 721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_MOD_Y] = "y", 731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron [IIO_MOD_Z] = "z", 74330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron [IIO_MOD_LIGHT_BOTH] = "both", 75330c6c57e6284a755d7e8a031b3c917571ee6dc3Jonathan Cameron [IIO_MOD_LIGHT_IR] = "ir", 761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}; 771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron/* relies on pairs of these shared then separate */ 791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic const char * const iio_chan_info_postfix[] = { 80c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_SCALE] = "scale", 81c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_OFFSET] = "offset", 82c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_CALIBSCALE] = "calibscale", 83c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_CALIBBIAS] = "calibbias", 84c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_PEAK] = "peak_raw", 85c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_PEAK_SCALE] = "peak_scale", 86c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW] = "quadrature_correction_raw", 87c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron [IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw", 88df94aba81f81c50ff3f4774c121217b03aaf4f27Jonathan Cameron [IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY] 89df94aba81f81c50ff3f4774c121217b03aaf4f27Jonathan Cameron = "filter_low_pass_3db_frequency", 901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron}; 911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 925fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameronconst struct iio_chan_spec 935fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron*iio_find_channel_from_si(struct iio_dev *indio_dev, int si) 945fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron{ 955fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron int i; 965fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron 975fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron for (i = 0; i < indio_dev->num_channels; i++) 985fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron if (indio_dev->channels[i].scan_index == si) 995fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron return &indio_dev->channels[i]; 1005fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron return NULL; 1015fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron} 1025fb21c824e8ff22ae9361a789e8b845d72ae0557Jonathan Cameron 103847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron/* This turns up an awful lot */ 104847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronssize_t iio_read_const_attr(struct device *dev, 105847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron struct device_attribute *attr, 106847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron char *buf) 107847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 108847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return sprintf(buf, "%s\n", to_iio_const_attr(attr)->string); 109847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 110847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_read_const_attr); 111847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 112847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic int __init iio_init(void) 113847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 114847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron int ret; 115847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1165aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron /* Register sysfs bus */ 1175aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron ret = bus_register(&iio_bus_type); 118847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (ret < 0) { 119847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron printk(KERN_ERR 1205aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron "%s could not register bus type\n", 121847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron __FILE__); 122847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron goto error_nothing; 123847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 124847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1259aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio"); 1269aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron if (ret < 0) { 1279aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron printk(KERN_ERR "%s: failed to allocate char dev region\n", 1289aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron __FILE__); 1295aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron goto error_unregister_bus_type; 1309aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron } 131847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 132847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return 0; 133847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1345aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameronerror_unregister_bus_type: 1355aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron bus_unregister(&iio_bus_type); 136847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_nothing: 137847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return ret; 138847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 139847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 140847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void __exit iio_exit(void) 141847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 1429aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron if (iio_devt) 1439aa1a167f0b8d6a58fe012992fd801bd78bf91f1Jonathan Cameron unregister_chrdev_region(iio_devt, IIO_DEV_MAX); 1445aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron bus_unregister(&iio_bus_type); 145847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 146847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_read_channel_info(struct device *dev, 1481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 1491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *buf) 150847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 1511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 1521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 1531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron int val, val2; 1546fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron int ret = indio_dev->info->read_raw(indio_dev, this_attr->c, 1556fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron &val, &val2, this_attr->address); 1561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 1571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret < 0) 1581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 159847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 1601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret == IIO_VAL_INT) 1611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return sprintf(buf, "%d\n", val); 1621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else if (ret == IIO_VAL_INT_PLUS_MICRO) { 1631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (val2 < 0) 1641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return sprintf(buf, "-%d.%06u\n", val, -val2); 1651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else 1661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return sprintf(buf, "%d.%06u\n", val, val2); 16771646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich } else if (ret == IIO_VAL_INT_PLUS_NANO) { 16871646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich if (val2 < 0) 16971646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich return sprintf(buf, "-%d.%09u\n", val, -val2); 17071646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich else 17171646e2c7ae4edb92dfa89eccb354d81be1cbbbdMichael Hennerich return sprintf(buf, "%d.%09u\n", val, val2); 1721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } else 1731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 1741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 1751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 1761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronstatic ssize_t iio_write_channel_info(struct device *dev, 1771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 1781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *buf, 1791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron size_t len) 1801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 1811d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 1821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *this_attr = to_iio_dev_attr(attr); 1835c04af04835269c194662be63fe168893fad667fMichael Hennerich int ret, integer = 0, fract = 0, fract_mult = 100000; 1841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron bool integer_part = true, negative = false; 1851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 1861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron /* Assumes decimal - precision based on number of digits */ 1876fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron if (!indio_dev->info->write_raw) 1881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return -EINVAL; 1895c04af04835269c194662be63fe168893fad667fMichael Hennerich 1905c04af04835269c194662be63fe168893fad667fMichael Hennerich if (indio_dev->info->write_raw_get_fmt) 1915c04af04835269c194662be63fe168893fad667fMichael Hennerich switch (indio_dev->info->write_raw_get_fmt(indio_dev, 1925c04af04835269c194662be63fe168893fad667fMichael Hennerich this_attr->c, this_attr->address)) { 1935c04af04835269c194662be63fe168893fad667fMichael Hennerich case IIO_VAL_INT_PLUS_MICRO: 1945c04af04835269c194662be63fe168893fad667fMichael Hennerich fract_mult = 100000; 1955c04af04835269c194662be63fe168893fad667fMichael Hennerich break; 1965c04af04835269c194662be63fe168893fad667fMichael Hennerich case IIO_VAL_INT_PLUS_NANO: 1975c04af04835269c194662be63fe168893fad667fMichael Hennerich fract_mult = 100000000; 1985c04af04835269c194662be63fe168893fad667fMichael Hennerich break; 1995c04af04835269c194662be63fe168893fad667fMichael Hennerich default: 2005c04af04835269c194662be63fe168893fad667fMichael Hennerich return -EINVAL; 2015c04af04835269c194662be63fe168893fad667fMichael Hennerich } 2025c04af04835269c194662be63fe168893fad667fMichael Hennerich 2031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (buf[0] == '-') { 2041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron negative = true; 2051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron buf++; 2061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 2075c04af04835269c194662be63fe168893fad667fMichael Hennerich 2081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron while (*buf) { 2091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if ('0' <= *buf && *buf <= '9') { 2101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (integer_part) 2111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron integer = integer*10 + *buf - '0'; 2121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else { 2135c04af04835269c194662be63fe168893fad667fMichael Hennerich fract += fract_mult*(*buf - '0'); 2145c04af04835269c194662be63fe168893fad667fMichael Hennerich if (fract_mult == 1) 2151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron break; 2165c04af04835269c194662be63fe168893fad667fMichael Hennerich fract_mult /= 10; 2171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 2181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } else if (*buf == '\n') { 2191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (*(buf + 1) == '\0') 2201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron break; 2211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else 2221d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return -EINVAL; 2231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } else if (*buf == '.') { 2241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron integer_part = false; 2251d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } else { 2261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return -EINVAL; 2271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 2281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron buf++; 2291d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 2301d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (negative) { 2311d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (integer) 2321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron integer = -integer; 2331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron else 2345c04af04835269c194662be63fe168893fad667fMichael Hennerich fract = -fract; 2351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 2361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 2376fe8135fccd66aedcc55ded70824342587fd2499Jonathan Cameron ret = indio_dev->info->write_raw(indio_dev, this_attr->c, 2385c04af04835269c194662be63fe168893fad667fMichael Hennerich integer, fract, this_attr->address); 2391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret) 2401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 2411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 2421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return len; 2431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 2441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 245df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameronstatic 2461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronint __iio_device_attr_init(struct device_attribute *dev_attr, 2471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *postfix, 2481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_chan_spec const *chan, 2491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ssize_t (*readfunc)(struct device *dev, 2501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 2511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *buf), 2521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ssize_t (*writefunc)(struct device *dev, 2531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 2541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *buf, 2551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron size_t len), 2561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron bool generic) 2571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 2581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron int ret; 2591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *name_format, *full_postfix; 2601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron sysfs_attr_init(&dev_attr->attr); 2611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 262ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron /* Build up postfix of <extend_name>_<modifier>_postfix */ 2630403e0d643809f1608448ada38a1877f26b7bf5dJonathan Cameron if (chan->modified && !generic) { 264ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (chan->extend_name) 265ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s", 266ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_modifier_names[chan 267ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron ->channel2], 268ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->extend_name, 269ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron postfix); 270ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else 271ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix = kasprintf(GFP_KERNEL, "%s_%s", 272ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_modifier_names[chan 273ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron ->channel2], 274ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron postfix); 275ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } else { 276ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (chan->extend_name == NULL) 277ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix = kstrdup(postfix, GFP_KERNEL); 278ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else 279ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix = kasprintf(GFP_KERNEL, 280ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron "%s_%s", 281ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->extend_name, 282ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron postfix); 283ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } 284ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (full_postfix == NULL) { 285ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron ret = -ENOMEM; 286ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron goto error_ret; 287ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } 2881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 289ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (chan->differential) { /* Differential can not have modifier */ 290ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (generic) 291ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 292ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s-%s_%s", 293ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 294ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 295ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 296ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 297ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else if (chan->indexed) 298ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 299ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s%d-%s%d_%s", 300ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 301ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 302ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->channel, 303ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 304ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->channel2, 305ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 306ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else { 307ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron WARN_ON("Differential channels must be indexed\n"); 308ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron ret = -EINVAL; 309ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron goto error_free_full_postfix; 310ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } 311ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } else { /* Single ended */ 312ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron if (generic) 313ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 314ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s_%s", 315ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 316ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 317ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 318ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else if (chan->indexed) 319ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 320ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s%d_%s", 321ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 322ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 323ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron chan->channel, 324ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 325ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron else 326ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron name_format 327ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron = kasprintf(GFP_KERNEL, "%s_%s_%s", 328ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_direction[chan->output], 329ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron iio_chan_type_name_spec[chan->type], 330ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron full_postfix); 331ade7ef7ba3bf888b90269f8ca864841b2cd9803fJonathan Cameron } 3321d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (name_format == NULL) { 3331d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -ENOMEM; 3341d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_free_full_postfix; 3351d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->attr.name = kasprintf(GFP_KERNEL, 3371d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron name_format, 3381d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron chan->channel, 3391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron chan->channel2); 3401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (dev_attr->attr.name == NULL) { 3411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -ENOMEM; 3421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_free_name_format; 3431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3451d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (readfunc) { 3461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->attr.mode |= S_IRUGO; 3471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->show = readfunc; 3481d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (writefunc) { 3511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->attr.mode |= S_IWUSR; 3521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_attr->store = writefunc; 3531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(name_format); 3551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(full_postfix); 3561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 3581d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_free_name_format: 3601d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(name_format); 3611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_free_full_postfix: 3621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(full_postfix); 3631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret: 3641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 3651d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 3661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 367df9c1c42c26f9a516dd44c956cff301741a0884eJonathan Cameronstatic void __iio_device_attr_deinit(struct device_attribute *dev_attr) 3681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 3691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(dev_attr->attr.name); 3701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 3711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3721d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronint __iio_add_chan_devattr(const char *postfix, 3731d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_chan_spec const *chan, 3741d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ssize_t (*readfunc)(struct device *dev, 3751d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 3761d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron char *buf), 3771d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ssize_t (*writefunc)(struct device *dev, 3781d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device_attribute *attr, 3791d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron const char *buf, 3801d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron size_t len), 381e614a54b296185b266b4bd91193e08a5fbd32422Jonathan Cameron u64 mask, 3821d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron bool generic, 3831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct device *dev, 3841d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct list_head *attr_list) 3851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 3861d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron int ret; 3871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *iio_attr, *t; 3881d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 3891d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_attr = kzalloc(sizeof *iio_attr, GFP_KERNEL); 3901d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (iio_attr == NULL) { 3911d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -ENOMEM; 3921d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 3931d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 3941d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = __iio_device_attr_init(&iio_attr->dev_attr, 3951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron postfix, chan, 3961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron readfunc, writefunc, generic); 3971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret) 3981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_iio_dev_attr_free; 3991d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_attr->c = chan; 4001d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_attr->address = mask; 4011d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_for_each_entry(t, attr_list, l) 4021d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (strcmp(t->dev_attr.attr.name, 4031d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron iio_attr->dev_attr.attr.name) == 0) { 4041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (!generic) 4051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron dev_err(dev, "tried to double register : %s\n", 4061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron t->dev_attr.attr.name); 4071d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = -EBUSY; 4081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_device_attr_deinit; 4091d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 4101d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_add(&iio_attr->l, attr_list); 4111d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 4121d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 4131d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 4141d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_device_attr_deinit: 4151d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron __iio_device_attr_deinit(&iio_attr->dev_attr); 4161d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_iio_dev_attr_free: 4171d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(iio_attr); 4181d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret: 4191d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 4201d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 4211d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 422f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_add_channel_sysfs(struct iio_dev *indio_dev, 4231d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_chan_spec const *chan) 4241d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 42526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron int ret, i, attrcount = 0; 4261d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 4271d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (chan->channel < 0) 4281d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 4291e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 4301e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron ret = __iio_add_chan_devattr(iio_data_type_name[chan->processed_val], 43126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron chan, 4321e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron &iio_read_channel_info, 433c6fc806247be874c2e6d9a9494489a0430f92718Jonathan Cameron (chan->output ? 4341e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron &iio_write_channel_info : NULL), 4351e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 0, 4361e8dfcc6c3d36dabc77925104fc5769f79340be5Jonathan Cameron 0, 437f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->dev, 438f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->channel_attr_list); 4391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret) 4401d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 44126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount++; 4421d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 4431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) { 4441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2], 44526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron chan, 4461d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron &iio_read_channel_info, 4471d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron &iio_write_channel_info, 448c8a9f8056f40f6201b84fdddb49a1c62630902c5Jonathan Cameron i/2, 4491d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron !(i%2), 450f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->dev, 451f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->channel_attr_list); 4521d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret == -EBUSY && (i%2 == 0)) { 4531d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ret = 0; 4541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron continue; 4551d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 4561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret < 0) 4571d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_ret; 45826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount++; 4591d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 46026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron ret = attrcount; 4611d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_ret: 4621d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return ret; 4631d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 4641d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 465f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic void iio_device_remove_and_free_read_attr(struct iio_dev *indio_dev, 4661d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *p) 4671d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 4681d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(p->dev_attr.attr.name); 4691d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron kfree(p); 4701d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron} 4711d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 4721b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameronstatic ssize_t iio_show_dev_name(struct device *dev, 4731b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron struct device_attribute *attr, 4741b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron char *buf) 4751b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron{ 4761b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron struct iio_dev *indio_dev = dev_get_drvdata(dev); 4771b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron return sprintf(buf, "%s\n", indio_dev->name); 4781b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron} 4791b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron 4801b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameronstatic DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL); 4811b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron 482f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic int iio_device_register_sysfs(struct iio_dev *indio_dev) 4831d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron{ 48426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron int i, ret = 0, attrcount, attrn, attrcount_orig = 0; 4851d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *p, *n; 48626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron struct attribute **attr; 4871d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 48826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron /* First count elements in any existing group */ 489f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->info->attrs) { 490f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron attr = indio_dev->info->attrs->attrs; 49126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron while (*attr++ != NULL) 49226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount_orig++; 493847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 49426d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount = attrcount_orig; 4951d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron /* 4961d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron * New channel registration method - relies on the fact a group does 4971d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron * not need to be initialized if it is name is NULL. 4981d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron */ 499f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron INIT_LIST_HEAD(&indio_dev->channel_attr_list); 500f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->channels) 501f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron for (i = 0; i < indio_dev->num_channels; i++) { 502f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = iio_device_add_channel_sysfs(indio_dev, 503f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev 5041d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron ->channels[i]); 5051d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron if (ret < 0) 5061d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron goto error_clear_attrs; 50726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount += ret; 5081d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 50926d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 510f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->name) 51126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrcount++; 51226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 513d83fb184945cd2daaafd33a702bba9cb7ed502bfThomas Meyer indio_dev->chan_attr_group.attrs = kcalloc(attrcount + 1, 514d83fb184945cd2daaafd33a702bba9cb7ed502bfThomas Meyer sizeof(indio_dev->chan_attr_group.attrs[0]), 515d83fb184945cd2daaafd33a702bba9cb7ed502bfThomas Meyer GFP_KERNEL); 516f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->chan_attr_group.attrs == NULL) { 51726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron ret = -ENOMEM; 51826d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron goto error_clear_attrs; 5191b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron } 52026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron /* Copy across original attributes */ 521f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->info->attrs) 522f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron memcpy(indio_dev->chan_attr_group.attrs, 523f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->info->attrs->attrs, 524f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron sizeof(indio_dev->chan_attr_group.attrs[0]) 52526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron *attrcount_orig); 52626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron attrn = attrcount_orig; 52726d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron /* Add all elements from the list. */ 528f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron list_for_each_entry(p, &indio_dev->channel_attr_list, l) 529f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr; 530f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->name) 531f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr; 53226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 533f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->groups[indio_dev->groupcounter++] = 534f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->chan_attr_group; 53526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 5361d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron return 0; 5371b732888d83f71a31a4bd26290ca8a00df1bf928Jonathan Cameron 5381d892719e70e477156f62e060e0805d991d450e5Jonathan Cameronerror_clear_attrs: 5391d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_for_each_entry_safe(p, n, 540f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron &indio_dev->channel_attr_list, l) { 5411d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_del(&p->l); 542f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_remove_and_free_read_attr(indio_dev, p); 5431d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 5441d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 54526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron return ret; 546847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 547847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 548f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronstatic void iio_device_unregister_sysfs(struct iio_dev *indio_dev) 549847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 5501d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron 5511d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron struct iio_dev_attr *p, *n; 55226d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron 553f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron list_for_each_entry_safe(p, n, &indio_dev->channel_attr_list, l) { 5541d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron list_del(&p->l); 555f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_remove_and_free_read_attr(indio_dev, p); 5561d892719e70e477156f62e060e0805d991d450e5Jonathan Cameron } 557f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron kfree(indio_dev->chan_attr_group.attrs); 558847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 559847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 560847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic void iio_dev_release(struct device *device) 561847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 562f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron struct iio_dev *indio_dev = container_of(device, struct iio_dev, dev); 563f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron cdev_del(&indio_dev->chrdev); 564f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) 565f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_trigger_consumer(indio_dev); 566f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_eventset(indio_dev); 567f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_sysfs(indio_dev); 568847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 569847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 570847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronstatic struct device_type iio_dev_type = { 571847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron .name = "iio_device", 572847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron .release = iio_dev_release, 573847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron}; 574847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 5756f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameronstruct iio_dev *iio_allocate_device(int sizeof_priv) 576847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 5776f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron struct iio_dev *dev; 5786f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron size_t alloc_size; 5796f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron 5806f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron alloc_size = sizeof(struct iio_dev); 5816f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron if (sizeof_priv) { 5826f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron alloc_size = ALIGN(alloc_size, IIO_ALIGN); 5836f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron alloc_size += sizeof_priv; 5846f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron } 5856f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron /* ensure 32-byte alignment of whole construct ? */ 5866f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron alloc_size += IIO_ALIGN - 1; 5876f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron 5886f7c8ee585e9db54cb29af1bdb93f29837824933Jonathan Cameron dev = kzalloc(alloc_size, GFP_KERNEL); 589847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 590847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (dev) { 59126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron dev->dev.groups = dev->groups; 592847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron dev->dev.type = &iio_dev_type; 5935aaaeba82e00958ecb2c890b4953a249bbde9426Jonathan Cameron dev->dev.bus = &iio_bus_type; 594847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron device_initialize(&dev->dev); 595847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron dev_set_drvdata(&dev->dev, (void *)dev); 596847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron mutex_init(&dev->mlock); 597ac917a81117ce0286847666b55dd265f6cda8383Jonathan Cameron mutex_init(&dev->info_exist_lock); 598a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron 599a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL); 600a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron if (dev->id < 0) { 601a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron /* cannot use a dev_err as the name isn't available */ 602a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron printk(KERN_ERR "Failed to get id\n"); 603a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron kfree(dev); 604a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron return NULL; 605a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron } 606a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron dev_set_name(&dev->dev, "iio:device%d", dev->id); 607847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 608847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 609847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return dev; 610847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 611847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_allocate_device); 612847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 613847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronvoid iio_free_device(struct iio_dev *dev) 614847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 615a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron if (dev) { 616a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron ida_simple_remove(&iio_ida, dev->id); 6171aa042783251c27a93e31929c24647729db326d4Jonathan Cameron kfree(dev); 618a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron } 619847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 620847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_free_device); 621847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 6221aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/** 62314555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron * iio_chrdev_open() - chrdev file open for buffer access and ioctls 6241aa042783251c27a93e31929c24647729db326d4Jonathan Cameron **/ 6251aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic int iio_chrdev_open(struct inode *inode, struct file *filp) 6261aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{ 627f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron struct iio_dev *indio_dev = container_of(inode->i_cdev, 6281aa042783251c27a93e31929c24647729db326d4Jonathan Cameron struct iio_dev, chrdev); 629bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen 630bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags)) 631bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen return -EBUSY; 632bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen 633f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron filp->private_data = indio_dev; 63430eb82f05dd1f12b18a0ad054401a0b5690fb3c3Jonathan Cameron 6357933514043d42e69663a5123a53fab50eb0b4abaLars-Peter Clausen return 0; 6361aa042783251c27a93e31929c24647729db326d4Jonathan Cameron} 6371aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 6381aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/** 63914555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron * iio_chrdev_release() - chrdev file close buffer access and ioctls 6401aa042783251c27a93e31929c24647729db326d4Jonathan Cameron **/ 6411aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic int iio_chrdev_release(struct inode *inode, struct file *filp) 6421aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{ 643bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen struct iio_dev *indio_dev = container_of(inode->i_cdev, 644bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen struct iio_dev, chrdev); 645bb01443e2cdad4ff5b98e00252e93110d00f4392Lars-Peter Clausen clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags); 6461aa042783251c27a93e31929c24647729db326d4Jonathan Cameron return 0; 6471aa042783251c27a93e31929c24647729db326d4Jonathan Cameron} 6481aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 6491aa042783251c27a93e31929c24647729db326d4Jonathan Cameron/* Somewhat of a cross file organization violation - ioctls here are actually 6501aa042783251c27a93e31929c24647729db326d4Jonathan Cameron * event related */ 6511aa042783251c27a93e31929c24647729db326d4Jonathan Cameronstatic long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 6521aa042783251c27a93e31929c24647729db326d4Jonathan Cameron{ 6531aa042783251c27a93e31929c24647729db326d4Jonathan Cameron struct iio_dev *indio_dev = filp->private_data; 6541aa042783251c27a93e31929c24647729db326d4Jonathan Cameron int __user *ip = (int __user *)arg; 6551aa042783251c27a93e31929c24647729db326d4Jonathan Cameron int fd; 6561aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 6571aa042783251c27a93e31929c24647729db326d4Jonathan Cameron if (cmd == IIO_GET_EVENT_FD_IOCTL) { 6581aa042783251c27a93e31929c24647729db326d4Jonathan Cameron fd = iio_event_getfd(indio_dev); 6591aa042783251c27a93e31929c24647729db326d4Jonathan Cameron if (copy_to_user(ip, &fd, sizeof(fd))) 6601aa042783251c27a93e31929c24647729db326d4Jonathan Cameron return -EFAULT; 6611aa042783251c27a93e31929c24647729db326d4Jonathan Cameron return 0; 6621aa042783251c27a93e31929c24647729db326d4Jonathan Cameron } 6631aa042783251c27a93e31929c24647729db326d4Jonathan Cameron return -EINVAL; 6641aa042783251c27a93e31929c24647729db326d4Jonathan Cameron} 6651aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 66614555b14455f9acbdf0e500ae96140828a970796Jonathan Cameronstatic const struct file_operations iio_buffer_fileops = { 66714555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron .read = iio_buffer_read_first_n_outer_addr, 6681aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .release = iio_chrdev_release, 6691aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .open = iio_chrdev_open, 67014555b14455f9acbdf0e500ae96140828a970796Jonathan Cameron .poll = iio_buffer_poll_addr, 6711aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .owner = THIS_MODULE, 6721aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .llseek = noop_llseek, 6731aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .unlocked_ioctl = iio_ioctl, 6741aa042783251c27a93e31929c24647729db326d4Jonathan Cameron .compat_ioctl = iio_ioctl, 6751aa042783251c27a93e31929c24647729db326d4Jonathan Cameron}; 6761aa042783251c27a93e31929c24647729db326d4Jonathan Cameron 677f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronint iio_device_register(struct iio_dev *indio_dev) 678847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 679847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron int ret; 680847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 6811aa042783251c27a93e31929c24647729db326d4Jonathan Cameron /* configure elements for the chrdev */ 682f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id); 683847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 684f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = iio_device_register_sysfs(indio_dev); 685847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (ret) { 686f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron dev_err(indio_dev->dev.parent, 687847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron "Failed to register sysfs interfaces\n"); 688a9e39f9e80ac24367e375c8ea110dfaec837b020Jonathan Cameron goto error_ret; 689847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 690f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = iio_device_register_eventset(indio_dev); 691847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron if (ret) { 692f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron dev_err(indio_dev->dev.parent, 693c849d2538ebeef1ac26fad7a10c18b1e0fc35161Roel Van Nyen "Failed to register event set\n"); 694847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron goto error_free_sysfs; 695847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron } 696f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron if (indio_dev->modes & INDIO_BUFFER_TRIGGERED) 697f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_register_trigger_consumer(indio_dev); 698847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 699f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = device_add(&indio_dev->dev); 70026d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron if (ret < 0) 70126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron goto error_unreg_eventset; 702f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron cdev_init(&indio_dev->chrdev, &iio_buffer_fileops); 703f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron indio_dev->chrdev.owner = indio_dev->info->driver_module; 704f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron ret = cdev_add(&indio_dev->chrdev, indio_dev->dev.devt, 1); 70526d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron if (ret < 0) 70626d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameron goto error_del_device; 707847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return 0; 708847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 709847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_del_device: 710f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron device_del(&indio_dev->dev); 71126d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameronerror_unreg_eventset: 712f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_eventset(indio_dev); 71326d25ae3f0d8ffe350aacc75b71198d6b35bd1f4Jonathan Cameronerror_free_sysfs: 714f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron iio_device_unregister_sysfs(indio_dev); 715847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronerror_ret: 716847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron return ret; 717847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 718847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_device_register); 719847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 720f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameronvoid iio_device_unregister(struct iio_dev *indio_dev) 721847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron{ 722ac917a81117ce0286847666b55dd265f6cda8383Jonathan Cameron mutex_lock(&indio_dev->info_exist_lock); 723ac917a81117ce0286847666b55dd265f6cda8383Jonathan Cameron indio_dev->info = NULL; 724ac917a81117ce0286847666b55dd265f6cda8383Jonathan Cameron mutex_unlock(&indio_dev->info_exist_lock); 725f8c6f4e9a40d47ce86a641eb20fb7c5a59f06ff0Jonathan Cameron device_unregister(&indio_dev->dev); 726847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron} 727847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronEXPORT_SYMBOL(iio_device_unregister); 728847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronsubsys_initcall(iio_init); 729847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameronmodule_exit(iio_exit); 730847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan Cameron 731847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>"); 732847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_DESCRIPTION("Industrial I/O core"); 733847ec80bbaa76aae41062d6802cea9c1b2289f14Jonathan CameronMODULE_LICENSE("GPL"); 734