blob: 35253334270202b4f93eb283f70e37f02c1b6e0b [file] [log] [blame]
Thomas Gleixnerd2912cb2019-06-04 10:11:33 +02001// SPDX-License-Identifier: GPL-2.0-only
Jonathan Cameron847ec802009-08-18 18:06:19 +01002/* The industrial I/O core
3 *
4 * Copyright (c) 2008 Jonathan Cameron
5 *
Jonathan Cameron847ec802009-08-18 18:06:19 +01006 * Based on elements of hwmon and input subsystems.
7 */
8
Sachin Kamat3176dd52013-10-24 12:53:00 +01009#define pr_fmt(fmt) "iio-core: " fmt
10
Jonathan Cameron847ec802009-08-18 18:06:19 +010011#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/idr.h>
14#include <linux/kdev_t.h>
15#include <linux/err.h>
16#include <linux/device.h>
17#include <linux/fs.h>
Jonathan Cameron847ec802009-08-18 18:06:19 +010018#include <linux/poll.h>
Andy Shevchenkofb158972019-02-21 18:02:46 +010019#include <linux/property.h>
Jonathan Cameronffc18af2009-10-12 19:18:09 +010020#include <linux/sched.h>
Jeff Mahoney4439c932009-10-12 17:10:34 -040021#include <linux/wait.h>
Jonathan Cameron847ec802009-08-18 18:06:19 +010022#include <linux/cdev.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090023#include <linux/slab.h>
Jonathan Cameron8e7d9672011-08-30 12:32:45 +010024#include <linux/anon_inodes.h>
Michael Henneriche553f182012-03-01 10:51:03 +010025#include <linux/debugfs.h>
Alison Schofield08a33802016-03-09 11:30:12 -080026#include <linux/mutex.h>
Jonathan Cameron06458e22012-04-25 15:54:58 +010027#include <linux/iio/iio.h>
Jonathan Camerondf9c1c42011-08-12 17:56:03 +010028#include "iio_core.h"
Jonathan Cameron6aea1c32011-08-24 17:28:38 +010029#include "iio_core_trigger.h"
Jonathan Cameron06458e22012-04-25 15:54:58 +010030#include <linux/iio/sysfs.h>
31#include <linux/iio/events.h>
Lars-Peter Clausen9e69c932013-10-04 12:06:00 +010032#include <linux/iio/buffer.h>
Jonathan Cameron33dd94c2017-01-02 19:28:34 +000033#include <linux/iio/buffer_impl.h>
Jonathan Cameron9dd1cb32011-08-30 12:41:15 +010034
Peter Meerwald99698b42012-08-26 13:43:00 +010035/* IDA to assign each registered device a unique id */
Jonathan Cameronb156cf72010-09-04 17:54:43 +010036static DEFINE_IDA(iio_ida);
Jonathan Cameron847ec802009-08-18 18:06:19 +010037
Jonathan Cameronf625cb92011-08-30 12:32:48 +010038static dev_t iio_devt;
Jonathan Cameron847ec802009-08-18 18:06:19 +010039
40#define IIO_DEV_MAX 256
Jonathan Cameron5aaaeba2010-05-04 14:43:00 +010041struct bus_type iio_bus_type = {
Jonathan Cameron847ec802009-08-18 18:06:19 +010042 .name = "iio",
Jonathan Cameron847ec802009-08-18 18:06:19 +010043};
Jonathan Cameron5aaaeba2010-05-04 14:43:00 +010044EXPORT_SYMBOL(iio_bus_type);
Jonathan Cameron847ec802009-08-18 18:06:19 +010045
Michael Henneriche553f182012-03-01 10:51:03 +010046static struct dentry *iio_debugfs_dentry;
47
Jonathan Cameronc6fc8062011-09-02 17:14:34 +010048static const char * const iio_direction[] = {
49 [0] = "in",
50 [1] = "out",
51};
52
Jonathan Cameronade7ef72011-09-02 17:14:45 +010053static const char * const iio_chan_type_name_spec[] = {
Jonathan Cameronc6fc8062011-09-02 17:14:34 +010054 [IIO_VOLTAGE] = "voltage",
Michael Hennerichfaf290e2011-05-18 14:42:02 +010055 [IIO_CURRENT] = "current",
56 [IIO_POWER] = "power",
Bryan Freed9bff02f2011-07-07 12:01:54 -070057 [IIO_ACCEL] = "accel",
Jonathan Cameron41ea0402011-10-05 15:27:59 +010058 [IIO_ANGL_VEL] = "anglvel",
Jonathan Cameron1d892712011-05-18 14:40:51 +010059 [IIO_MAGN] = "magn",
Bryan Freed9bff02f2011-07-07 12:01:54 -070060 [IIO_LIGHT] = "illuminance",
61 [IIO_INTENSITY] = "intensity",
Bryan Freedf09f2c82011-07-07 12:01:55 -070062 [IIO_PROXIMITY] = "proximity",
Bryan Freed9bff02f2011-07-07 12:01:54 -070063 [IIO_TEMP] = "temp",
Jonathan Cameron1d892712011-05-18 14:40:51 +010064 [IIO_INCLI] = "incli",
65 [IIO_ROT] = "rot",
Jonathan Cameron1d892712011-05-18 14:40:51 +010066 [IIO_ANGL] = "angl",
Bryan Freed9bff02f2011-07-07 12:01:54 -070067 [IIO_TIMESTAMP] = "timestamp",
Jonathan Cameron66dbe702011-09-02 17:14:43 +010068 [IIO_CAPACITANCE] = "capacitance",
Michael Hennericha6b12852012-04-27 10:58:34 +020069 [IIO_ALTVOLTAGE] = "altvoltage",
Jon Brenner21cd1fa2012-05-16 10:46:42 -050070 [IIO_CCT] = "cct",
Lars-Peter Clausenc4f0c692012-11-20 13:36:00 +000071 [IIO_PRESSURE] = "pressure",
Harald Geyerac216aa2013-12-01 15:08:00 +000072 [IIO_HUMIDITYRELATIVE] = "humidityrelative",
Daniel Baluta55aebeb2014-11-10 14:45:30 +020073 [IIO_ACTIVITY] = "activity",
Irina Tirdeaa88bfe72014-11-10 14:45:32 +020074 [IIO_STEPS] = "steps",
Irina Tirdea72c66642015-01-11 21:10:07 +020075 [IIO_ENERGY] = "energy",
Irina Tirdeacc3c9ee2015-01-11 21:10:08 +020076 [IIO_DISTANCE] = "distance",
Irina Tirdea5a1a9322015-01-11 21:10:09 +020077 [IIO_VELOCITY] = "velocity",
Matt Ranostay8ff6b3b2015-09-13 20:26:11 -070078 [IIO_CONCENTRATION] = "concentration",
Matt Ranostayd38d5462015-09-13 20:26:12 -070079 [IIO_RESISTANCE] = "resistance",
Matt Ranostayecb3a7c2016-01-26 18:34:30 -080080 [IIO_PH] = "ph",
Peter Meerwald-Stadlerd4094042016-03-20 16:20:23 +010081 [IIO_UVINDEX] = "uvindex",
Matt Ranostay4b9d2092016-05-24 21:29:19 -070082 [IIO_ELECTRICALCONDUCTIVITY] = "electricalconductivity",
William Breathitt Gray1a8f3242016-09-28 13:59:49 -040083 [IIO_COUNT] = "count",
84 [IIO_INDEX] = "index",
Song Hongyan571299d2017-01-05 18:24:03 +080085 [IIO_GRAVITY] = "gravity",
Eugen Hristev3055a6c2018-05-22 10:52:32 +030086 [IIO_POSITIONRELATIVE] = "positionrelative",
Mathieu Othacehec73314e2018-07-20 19:34:25 +020087 [IIO_PHASE] = "phase",
Tomasz Duszynski17abc9e2018-12-14 19:28:01 +010088 [IIO_MASSCONCENTRATION] = "massconcentration",
Jonathan Cameron1d892712011-05-18 14:40:51 +010089};
90
Jonathan Cameron330c6c52011-09-02 17:14:39 +010091static const char * const iio_modifier_names[] = {
Jonathan Cameron1d892712011-05-18 14:40:51 +010092 [IIO_MOD_X] = "x",
93 [IIO_MOD_Y] = "y",
94 [IIO_MOD_Z] = "z",
Peter Meerwald4b8d8012015-06-20 23:52:30 +020095 [IIO_MOD_X_AND_Y] = "x&y",
96 [IIO_MOD_X_AND_Z] = "x&z",
97 [IIO_MOD_Y_AND_Z] = "y&z",
98 [IIO_MOD_X_AND_Y_AND_Z] = "x&y&z",
99 [IIO_MOD_X_OR_Y] = "x|y",
100 [IIO_MOD_X_OR_Z] = "x|z",
101 [IIO_MOD_Y_OR_Z] = "y|z",
102 [IIO_MOD_X_OR_Y_OR_Z] = "x|y|z",
Jonathan Cameron8f5879b2012-05-05 10:39:22 +0100103 [IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)",
Jonathan Cameroncf82cb82012-05-05 10:56:41 +0100104 [IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2",
Jonathan Cameron330c6c52011-09-02 17:14:39 +0100105 [IIO_MOD_LIGHT_BOTH] = "both",
106 [IIO_MOD_LIGHT_IR] = "ir",
Jon Brenner21cd1fa2012-05-16 10:46:42 -0500107 [IIO_MOD_LIGHT_CLEAR] = "clear",
108 [IIO_MOD_LIGHT_RED] = "red",
109 [IIO_MOD_LIGHT_GREEN] = "green",
110 [IIO_MOD_LIGHT_BLUE] = "blue",
Peter Meerwald-Stadler2c5ff1f2016-03-20 16:20:22 +0100111 [IIO_MOD_LIGHT_UV] = "uv",
Maxime Roussin-Bélangerc0e4e0f2018-07-19 16:26:24 -0400112 [IIO_MOD_LIGHT_DUV] = "duv",
Srinivas Pandruvada5082f402014-04-29 00:51:00 +0100113 [IIO_MOD_QUATERNION] = "quaternion",
Peter Meerwald638b43b2014-02-05 16:57:00 +0000114 [IIO_MOD_TEMP_AMBIENT] = "ambient",
115 [IIO_MOD_TEMP_OBJECT] = "object",
Reyad Attiyat11b8dda2014-07-17 19:18:00 +0100116 [IIO_MOD_NORTH_MAGN] = "from_north_magnetic",
117 [IIO_MOD_NORTH_TRUE] = "from_north_true",
118 [IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp",
119 [IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp",
Daniel Baluta55aebeb2014-11-10 14:45:30 +0200120 [IIO_MOD_RUNNING] = "running",
121 [IIO_MOD_JOGGING] = "jogging",
122 [IIO_MOD_WALKING] = "walking",
123 [IIO_MOD_STILL] = "still",
Irina Tirdea5a1a9322015-01-11 21:10:09 +0200124 [IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)",
Lars-Peter Clausen1ce87f22015-05-22 18:17:38 +0200125 [IIO_MOD_I] = "i",
126 [IIO_MOD_Q] = "q",
Matt Ranostay8ff6b3b2015-09-13 20:26:11 -0700127 [IIO_MOD_CO2] = "co2",
128 [IIO_MOD_VOC] = "voc",
Tomasz Duszynski17abc9e2018-12-14 19:28:01 +0100129 [IIO_MOD_PM1] = "pm1",
130 [IIO_MOD_PM2P5] = "pm2p5",
131 [IIO_MOD_PM4] = "pm4",
132 [IIO_MOD_PM10] = "pm10",
Matt Ranostay25f02d32020-06-09 06:01:16 +0300133 [IIO_MOD_ETHANOL] = "ethanol",
134 [IIO_MOD_H2] = "h2",
Jonathan Cameron1d892712011-05-18 14:40:51 +0100135};
136
137/* relies on pairs of these shared then separate */
138static const char * const iio_chan_info_postfix[] = {
Jonathan Cameron75a973c2012-04-15 17:41:30 +0100139 [IIO_CHAN_INFO_RAW] = "raw",
140 [IIO_CHAN_INFO_PROCESSED] = "input",
Jonathan Cameronc8a9f802011-10-26 17:41:36 +0100141 [IIO_CHAN_INFO_SCALE] = "scale",
142 [IIO_CHAN_INFO_OFFSET] = "offset",
143 [IIO_CHAN_INFO_CALIBSCALE] = "calibscale",
144 [IIO_CHAN_INFO_CALIBBIAS] = "calibbias",
145 [IIO_CHAN_INFO_PEAK] = "peak_raw",
146 [IIO_CHAN_INFO_PEAK_SCALE] = "peak_scale",
147 [IIO_CHAN_INFO_QUADRATURE_CORRECTION_RAW] = "quadrature_correction_raw",
148 [IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw",
Jonathan Camerondf94aba2011-11-27 11:39:12 +0000149 [IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY]
150 = "filter_low_pass_3db_frequency",
Martin Fuzzey3f7f6422015-05-13 12:26:42 +0200151 [IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY]
152 = "filter_high_pass_3db_frequency",
Laxman Dewangance85a1c2012-04-13 16:03:31 +0530153 [IIO_CHAN_INFO_SAMP_FREQ] = "sampling_frequency",
Michael Hennericha6b12852012-04-27 10:58:34 +0200154 [IIO_CHAN_INFO_FREQUENCY] = "frequency",
155 [IIO_CHAN_INFO_PHASE] = "phase",
Michael Hennerichb65d6212012-05-11 11:36:53 +0200156 [IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain",
srinivas pandruvada7c9ab032012-09-05 13:56:00 +0100157 [IIO_CHAN_INFO_HYSTERESIS] = "hysteresis",
Peter Meerwald899d90b2013-09-08 16:20:00 +0100158 [IIO_CHAN_INFO_INT_TIME] = "integration_time",
Irina Tirdeaa88bfe72014-11-10 14:45:32 +0200159 [IIO_CHAN_INFO_ENABLE] = "en",
Irina Tirdeabcdf28f2014-11-10 14:45:33 +0200160 [IIO_CHAN_INFO_CALIBHEIGHT] = "calibheight",
Irina Tirdead37f6832015-01-11 21:10:10 +0200161 [IIO_CHAN_INFO_CALIBWEIGHT] = "calibweight",
Irina Tirdea2f0ecb72015-01-27 20:41:52 +0200162 [IIO_CHAN_INFO_DEBOUNCE_COUNT] = "debounce_count",
163 [IIO_CHAN_INFO_DEBOUNCE_TIME] = "debounce_time",
Vianney le Clément de Saint-Marcqc8a85852015-03-30 10:34:58 +0200164 [IIO_CHAN_INFO_CALIBEMISSIVITY] = "calibemissivity",
Irina Tirdeafaaa4492015-04-29 21:16:39 +0300165 [IIO_CHAN_INFO_OVERSAMPLING_RATIO] = "oversampling_ratio",
Andrea Merelloddfb97d2019-11-20 15:47:52 +0100166 [IIO_CHAN_INFO_THERMOCOUPLE_TYPE] = "thermocouple_type",
Jonathan Cameron1d892712011-05-18 14:40:51 +0100167};
168
Sachin Kamata7e57dc2013-10-29 11:39:00 +0000169/**
170 * iio_find_channel_from_si() - get channel from its scan index
171 * @indio_dev: device
172 * @si: scan index to match
173 */
Jonathan Cameron5fb21c82011-12-05 21:37:10 +0000174const struct iio_chan_spec
175*iio_find_channel_from_si(struct iio_dev *indio_dev, int si)
176{
177 int i;
178
179 for (i = 0; i < indio_dev->num_channels; i++)
180 if (indio_dev->channels[i].scan_index == si)
181 return &indio_dev->channels[i];
182 return NULL;
183}
184
Jonathan Cameron847ec802009-08-18 18:06:19 +0100185/* This turns up an awful lot */
186ssize_t iio_read_const_attr(struct device *dev,
187 struct device_attribute *attr,
188 char *buf)
189{
190 return sprintf(buf, "%s\n", to_iio_const_attr(attr)->string);
191}
192EXPORT_SYMBOL(iio_read_const_attr);
193
Gwendal Grignou69f07932020-03-27 15:34:37 -0700194/**
195 * iio_device_set_clock() - Set current timestamping clock for the device
196 * @indio_dev: IIO device structure containing the device
197 * @clock_id: timestamping clock posix identifier to set.
198 */
199int iio_device_set_clock(struct iio_dev *indio_dev, clockid_t clock_id)
Gregor Boiriebc2b7da2016-03-09 19:05:49 +0100200{
201 int ret;
202 const struct iio_event_interface *ev_int = indio_dev->event_interface;
203
204 ret = mutex_lock_interruptible(&indio_dev->mlock);
205 if (ret)
206 return ret;
207 if ((ev_int && iio_event_enabled(ev_int)) ||
208 iio_buffer_enabled(indio_dev)) {
209 mutex_unlock(&indio_dev->mlock);
210 return -EBUSY;
211 }
212 indio_dev->clock_id = clock_id;
213 mutex_unlock(&indio_dev->mlock);
214
215 return 0;
216}
Gwendal Grignou69f07932020-03-27 15:34:37 -0700217EXPORT_SYMBOL(iio_device_set_clock);
Gregor Boiriebc2b7da2016-03-09 19:05:49 +0100218
219/**
220 * iio_get_time_ns() - utility function to get a time stamp for events etc
221 * @indio_dev: device
222 */
223s64 iio_get_time_ns(const struct iio_dev *indio_dev)
224{
Arnd Bergmann45e7f5d2018-06-18 17:31:36 +0200225 struct timespec64 tp;
Gregor Boiriebc2b7da2016-03-09 19:05:49 +0100226
227 switch (iio_device_get_clock(indio_dev)) {
228 case CLOCK_REALTIME:
Arnd Bergmann45e7f5d2018-06-18 17:31:36 +0200229 return ktime_get_real_ns();
Gregor Boiriebc2b7da2016-03-09 19:05:49 +0100230 case CLOCK_MONOTONIC:
Arnd Bergmann45e7f5d2018-06-18 17:31:36 +0200231 return ktime_get_ns();
Gregor Boiriebc2b7da2016-03-09 19:05:49 +0100232 case CLOCK_MONOTONIC_RAW:
Arnd Bergmann45e7f5d2018-06-18 17:31:36 +0200233 return ktime_get_raw_ns();
Gregor Boiriebc2b7da2016-03-09 19:05:49 +0100234 case CLOCK_REALTIME_COARSE:
Arnd Bergmann45e7f5d2018-06-18 17:31:36 +0200235 return ktime_to_ns(ktime_get_coarse_real());
Gregor Boiriebc2b7da2016-03-09 19:05:49 +0100236 case CLOCK_MONOTONIC_COARSE:
Arnd Bergmann45e7f5d2018-06-18 17:31:36 +0200237 ktime_get_coarse_ts64(&tp);
238 return timespec64_to_ns(&tp);
Gregor Boiriebc2b7da2016-03-09 19:05:49 +0100239 case CLOCK_BOOTTIME:
Jason A. Donenfeld9285ec42019-06-21 22:32:48 +0200240 return ktime_get_boottime_ns();
Gregor Boiriebc2b7da2016-03-09 19:05:49 +0100241 case CLOCK_TAI:
Jason A. Donenfeld9285ec42019-06-21 22:32:48 +0200242 return ktime_get_clocktai_ns();
Gregor Boiriebc2b7da2016-03-09 19:05:49 +0100243 default:
244 BUG();
245 }
Gregor Boiriebc2b7da2016-03-09 19:05:49 +0100246}
247EXPORT_SYMBOL(iio_get_time_ns);
248
249/**
250 * iio_get_time_res() - utility function to get time stamp clock resolution in
251 * nano seconds.
252 * @indio_dev: device
253 */
254unsigned int iio_get_time_res(const struct iio_dev *indio_dev)
255{
256 switch (iio_device_get_clock(indio_dev)) {
257 case CLOCK_REALTIME:
258 case CLOCK_MONOTONIC:
259 case CLOCK_MONOTONIC_RAW:
260 case CLOCK_BOOTTIME:
261 case CLOCK_TAI:
262 return hrtimer_resolution;
263 case CLOCK_REALTIME_COARSE:
264 case CLOCK_MONOTONIC_COARSE:
265 return LOW_RES_NSEC;
266 default:
267 BUG();
268 }
269}
270EXPORT_SYMBOL(iio_get_time_res);
271
Jonathan Cameron847ec802009-08-18 18:06:19 +0100272static int __init iio_init(void)
273{
274 int ret;
275
Jonathan Cameron5aaaeba2010-05-04 14:43:00 +0100276 /* Register sysfs bus */
277 ret = bus_register(&iio_bus_type);
Jonathan Cameron847ec802009-08-18 18:06:19 +0100278 if (ret < 0) {
Sachin Kamat3176dd52013-10-24 12:53:00 +0100279 pr_err("could not register bus type\n");
Jonathan Cameron847ec802009-08-18 18:06:19 +0100280 goto error_nothing;
281 }
282
Jonathan Cameron9aa1a162011-08-12 17:08:50 +0100283 ret = alloc_chrdev_region(&iio_devt, 0, IIO_DEV_MAX, "iio");
284 if (ret < 0) {
Sachin Kamat3176dd52013-10-24 12:53:00 +0100285 pr_err("failed to allocate char dev region\n");
Jonathan Cameron5aaaeba2010-05-04 14:43:00 +0100286 goto error_unregister_bus_type;
Jonathan Cameron9aa1a162011-08-12 17:08:50 +0100287 }
Jonathan Cameron847ec802009-08-18 18:06:19 +0100288
Michael Henneriche553f182012-03-01 10:51:03 +0100289 iio_debugfs_dentry = debugfs_create_dir("iio", NULL);
290
Jonathan Cameron847ec802009-08-18 18:06:19 +0100291 return 0;
292
Jonathan Cameron5aaaeba2010-05-04 14:43:00 +0100293error_unregister_bus_type:
294 bus_unregister(&iio_bus_type);
Jonathan Cameron847ec802009-08-18 18:06:19 +0100295error_nothing:
296 return ret;
297}
298
299static void __exit iio_exit(void)
300{
Jonathan Cameron9aa1a162011-08-12 17:08:50 +0100301 if (iio_devt)
302 unregister_chrdev_region(iio_devt, IIO_DEV_MAX);
Jonathan Cameron5aaaeba2010-05-04 14:43:00 +0100303 bus_unregister(&iio_bus_type);
Michael Henneriche553f182012-03-01 10:51:03 +0100304 debugfs_remove(iio_debugfs_dentry);
305}
306
307#if defined(CONFIG_DEBUG_FS)
Michael Henneriche553f182012-03-01 10:51:03 +0100308static ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf,
309 size_t count, loff_t *ppos)
310{
311 struct iio_dev *indio_dev = file->private_data;
Michael Henneriche553f182012-03-01 10:51:03 +0100312 unsigned val = 0;
Michael Henneriche553f182012-03-01 10:51:03 +0100313 int ret;
314
Alexandru Tachici2ddc9822020-02-21 14:06:55 +0200315 if (*ppos > 0)
316 return simple_read_from_buffer(userbuf, count, ppos,
317 indio_dev->read_buf,
318 indio_dev->read_buf_len);
319
Michael Henneriche553f182012-03-01 10:51:03 +0100320 ret = indio_dev->info->debugfs_reg_access(indio_dev,
321 indio_dev->cached_reg_addr,
322 0, &val);
Matt Fornero3d62c782017-09-05 16:34:10 +0200323 if (ret) {
Michael Henneriche553f182012-03-01 10:51:03 +0100324 dev_err(indio_dev->dev.parent, "%s: read failed\n", __func__);
Matt Fornero3d62c782017-09-05 16:34:10 +0200325 return ret;
326 }
Michael Henneriche553f182012-03-01 10:51:03 +0100327
Alexandru Tachici2ddc9822020-02-21 14:06:55 +0200328 indio_dev->read_buf_len = snprintf(indio_dev->read_buf,
329 sizeof(indio_dev->read_buf),
330 "0x%X\n", val);
Michael Henneriche553f182012-03-01 10:51:03 +0100331
Alexandru Tachici2ddc9822020-02-21 14:06:55 +0200332 return simple_read_from_buffer(userbuf, count, ppos,
333 indio_dev->read_buf,
334 indio_dev->read_buf_len);
Michael Henneriche553f182012-03-01 10:51:03 +0100335}
336
337static ssize_t iio_debugfs_write_reg(struct file *file,
338 const char __user *userbuf, size_t count, loff_t *ppos)
339{
340 struct iio_dev *indio_dev = file->private_data;
341 unsigned reg, val;
342 char buf[80];
343 int ret;
344
345 count = min_t(size_t, count, (sizeof(buf)-1));
346 if (copy_from_user(buf, userbuf, count))
347 return -EFAULT;
348
349 buf[count] = 0;
350
351 ret = sscanf(buf, "%i %i", &reg, &val);
352
353 switch (ret) {
354 case 1:
355 indio_dev->cached_reg_addr = reg;
356 break;
357 case 2:
358 indio_dev->cached_reg_addr = reg;
359 ret = indio_dev->info->debugfs_reg_access(indio_dev, reg,
360 val, NULL);
361 if (ret) {
362 dev_err(indio_dev->dev.parent, "%s: write failed\n",
363 __func__);
364 return ret;
365 }
366 break;
367 default:
368 return -EINVAL;
369 }
370
371 return count;
372}
373
374static const struct file_operations iio_debugfs_reg_fops = {
Axel Lin5a28c872012-05-03 09:50:51 +0800375 .open = simple_open,
Michael Henneriche553f182012-03-01 10:51:03 +0100376 .read = iio_debugfs_read_reg,
377 .write = iio_debugfs_write_reg,
378};
379
380static void iio_device_unregister_debugfs(struct iio_dev *indio_dev)
381{
382 debugfs_remove_recursive(indio_dev->debugfs_dentry);
Jonathan Cameron847ec802009-08-18 18:06:19 +0100383}
384
Greg Kroah-Hartman8915aac2019-06-18 17:54:40 +0200385static void iio_device_register_debugfs(struct iio_dev *indio_dev)
Michael Henneriche553f182012-03-01 10:51:03 +0100386{
Michael Henneriche553f182012-03-01 10:51:03 +0100387 if (indio_dev->info->debugfs_reg_access == NULL)
Greg Kroah-Hartman8915aac2019-06-18 17:54:40 +0200388 return;
Michael Henneriche553f182012-03-01 10:51:03 +0100389
Axel Linabd5a2f2012-05-03 22:56:58 +0800390 if (!iio_debugfs_dentry)
Greg Kroah-Hartman8915aac2019-06-18 17:54:40 +0200391 return;
Michael Henneriche553f182012-03-01 10:51:03 +0100392
393 indio_dev->debugfs_dentry =
394 debugfs_create_dir(dev_name(&indio_dev->dev),
395 iio_debugfs_dentry);
Michael Henneriche553f182012-03-01 10:51:03 +0100396
Greg Kroah-Hartman8915aac2019-06-18 17:54:40 +0200397 debugfs_create_file("direct_reg_access", 0644,
398 indio_dev->debugfs_dentry, indio_dev,
399 &iio_debugfs_reg_fops);
Michael Henneriche553f182012-03-01 10:51:03 +0100400}
401#else
Greg Kroah-Hartman8915aac2019-06-18 17:54:40 +0200402static void iio_device_register_debugfs(struct iio_dev *indio_dev)
Michael Henneriche553f182012-03-01 10:51:03 +0100403{
Michael Henneriche553f182012-03-01 10:51:03 +0100404}
405
406static void iio_device_unregister_debugfs(struct iio_dev *indio_dev)
407{
408}
409#endif /* CONFIG_DEBUG_FS */
410
Lars-Peter Clausen4fee7e162012-03-06 20:43:45 +0100411static ssize_t iio_read_channel_ext_info(struct device *dev,
412 struct device_attribute *attr,
413 char *buf)
414{
Lars-Peter Clausene53f5ac2012-05-12 15:39:33 +0200415 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
Lars-Peter Clausen4fee7e162012-03-06 20:43:45 +0100416 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
417 const struct iio_chan_spec_ext_info *ext_info;
418
419 ext_info = &this_attr->c->ext_info[this_attr->address];
420
Michael Hennerichfc6d1132012-04-27 10:58:36 +0200421 return ext_info->read(indio_dev, ext_info->private, this_attr->c, buf);
Lars-Peter Clausen4fee7e162012-03-06 20:43:45 +0100422}
423
424static ssize_t iio_write_channel_ext_info(struct device *dev,
425 struct device_attribute *attr,
426 const char *buf,
427 size_t len)
428{
Lars-Peter Clausene53f5ac2012-05-12 15:39:33 +0200429 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
Lars-Peter Clausen4fee7e162012-03-06 20:43:45 +0100430 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
431 const struct iio_chan_spec_ext_info *ext_info;
432
433 ext_info = &this_attr->c->ext_info[this_attr->address];
434
Michael Hennerichfc6d1132012-04-27 10:58:36 +0200435 return ext_info->write(indio_dev, ext_info->private,
436 this_attr->c, buf, len);
Lars-Peter Clausen4fee7e162012-03-06 20:43:45 +0100437}
438
Lars-Peter Clausen5212cc82012-06-04 11:36:11 +0200439ssize_t iio_enum_available_read(struct iio_dev *indio_dev,
440 uintptr_t priv, const struct iio_chan_spec *chan, char *buf)
441{
442 const struct iio_enum *e = (const struct iio_enum *)priv;
443 unsigned int i;
444 size_t len = 0;
445
446 if (!e->num_items)
447 return 0;
448
449 for (i = 0; i < e->num_items; ++i)
Lars-Peter Clausen74dcd432012-06-05 18:24:12 +0200450 len += scnprintf(buf + len, PAGE_SIZE - len, "%s ", e->items[i]);
Lars-Peter Clausen5212cc82012-06-04 11:36:11 +0200451
452 /* replace last space with a newline */
453 buf[len - 1] = '\n';
454
455 return len;
456}
457EXPORT_SYMBOL_GPL(iio_enum_available_read);
458
459ssize_t iio_enum_read(struct iio_dev *indio_dev,
460 uintptr_t priv, const struct iio_chan_spec *chan, char *buf)
461{
462 const struct iio_enum *e = (const struct iio_enum *)priv;
463 int i;
464
465 if (!e->get)
466 return -EINVAL;
467
468 i = e->get(indio_dev, chan);
469 if (i < 0)
470 return i;
471 else if (i >= e->num_items)
472 return -EINVAL;
473
Kees Cook598db582014-03-13 16:46:00 +0000474 return snprintf(buf, PAGE_SIZE, "%s\n", e->items[i]);
Lars-Peter Clausen5212cc82012-06-04 11:36:11 +0200475}
476EXPORT_SYMBOL_GPL(iio_enum_read);
477
478ssize_t iio_enum_write(struct iio_dev *indio_dev,
479 uintptr_t priv, const struct iio_chan_spec *chan, const char *buf,
480 size_t len)
481{
482 const struct iio_enum *e = (const struct iio_enum *)priv;
Lars-Peter Clausen5212cc82012-06-04 11:36:11 +0200483 int ret;
484
485 if (!e->set)
486 return -EINVAL;
487
Andy Shevchenko02e9a0ff2017-06-09 15:08:16 +0300488 ret = __sysfs_match_string(e->items, e->num_items, buf);
489 if (ret < 0)
490 return ret;
Lars-Peter Clausen5212cc82012-06-04 11:36:11 +0200491
Andy Shevchenko02e9a0ff2017-06-09 15:08:16 +0300492 ret = e->set(indio_dev, chan, ret);
Lars-Peter Clausen5212cc82012-06-04 11:36:11 +0200493 return ret ? ret : len;
494}
495EXPORT_SYMBOL_GPL(iio_enum_write);
496
Gregor Boiriedfc57732016-04-20 19:23:43 +0200497static const struct iio_mount_matrix iio_mount_idmatrix = {
498 .rotation = {
499 "1", "0", "0",
500 "0", "1", "0",
501 "0", "0", "1"
502 }
503};
504
505static int iio_setup_mount_idmatrix(const struct device *dev,
506 struct iio_mount_matrix *matrix)
507{
508 *matrix = iio_mount_idmatrix;
509 dev_info(dev, "mounting matrix not found: using identity...\n");
510 return 0;
511}
512
513ssize_t iio_show_mount_matrix(struct iio_dev *indio_dev, uintptr_t priv,
514 const struct iio_chan_spec *chan, char *buf)
515{
516 const struct iio_mount_matrix *mtx = ((iio_get_mount_matrix_t *)
517 priv)(indio_dev, chan);
518
519 if (IS_ERR(mtx))
520 return PTR_ERR(mtx);
521
522 if (!mtx)
523 mtx = &iio_mount_idmatrix;
524
525 return snprintf(buf, PAGE_SIZE, "%s, %s, %s; %s, %s, %s; %s, %s, %s\n",
526 mtx->rotation[0], mtx->rotation[1], mtx->rotation[2],
527 mtx->rotation[3], mtx->rotation[4], mtx->rotation[5],
528 mtx->rotation[6], mtx->rotation[7], mtx->rotation[8]);
529}
530EXPORT_SYMBOL_GPL(iio_show_mount_matrix);
531
532/**
Andy Shevchenkofb158972019-02-21 18:02:46 +0100533 * iio_read_mount_matrix() - retrieve iio device mounting matrix from
534 * device "mount-matrix" property
Gregor Boiriedfc57732016-04-20 19:23:43 +0200535 * @dev: device the mounting matrix property is assigned to
536 * @propname: device specific mounting matrix property name
537 * @matrix: where to store retrieved matrix
538 *
539 * If device is assigned no mounting matrix property, a default 3x3 identity
540 * matrix will be filled in.
541 *
542 * Return: 0 if success, or a negative error code on failure.
543 */
Andy Shevchenkofb158972019-02-21 18:02:46 +0100544int iio_read_mount_matrix(struct device *dev, const char *propname,
545 struct iio_mount_matrix *matrix)
Gregor Boiriedfc57732016-04-20 19:23:43 +0200546{
Andy Shevchenkofb158972019-02-21 18:02:46 +0100547 size_t len = ARRAY_SIZE(iio_mount_idmatrix.rotation);
548 int err;
Gregor Boiriedfc57732016-04-20 19:23:43 +0200549
Andy Shevchenkofb158972019-02-21 18:02:46 +0100550 err = device_property_read_string_array(dev, propname,
551 matrix->rotation, len);
552 if (err == len)
553 return 0;
Gregor Boiriedfc57732016-04-20 19:23:43 +0200554
Andy Shevchenkofb158972019-02-21 18:02:46 +0100555 if (err >= 0)
556 /* Invalid number of matrix entries. */
557 return -EINVAL;
Gregor Boiriedfc57732016-04-20 19:23:43 +0200558
Andy Shevchenkofb158972019-02-21 18:02:46 +0100559 if (err != -EINVAL)
560 /* Invalid matrix declaration format. */
561 return err;
Gregor Boiriedfc57732016-04-20 19:23:43 +0200562
563 /* Matrix was not declared at all: fallback to identity. */
564 return iio_setup_mount_idmatrix(dev, matrix);
565}
Andy Shevchenkofb158972019-02-21 18:02:46 +0100566EXPORT_SYMBOL(iio_read_mount_matrix);
Gregor Boiriedfc57732016-04-20 19:23:43 +0200567
Jonathan Cameron51239602016-11-08 12:58:51 +0100568static ssize_t __iio_format_value(char *buf, size_t len, unsigned int type,
569 int size, const int *vals)
570{
571 unsigned long long tmp;
572 int tmp0, tmp1;
573 bool scale_db = false;
574
575 switch (type) {
576 case IIO_VAL_INT:
Takashi Iwai35a4eeb2020-03-11 08:43:24 +0100577 return scnprintf(buf, len, "%d", vals[0]);
Jonathan Cameron51239602016-11-08 12:58:51 +0100578 case IIO_VAL_INT_PLUS_MICRO_DB:
579 scale_db = true;
Gustavo A. R. Silva9d793c12017-11-08 12:08:26 -0600580 /* fall through */
Jonathan Cameron51239602016-11-08 12:58:51 +0100581 case IIO_VAL_INT_PLUS_MICRO:
582 if (vals[1] < 0)
Takashi Iwai35a4eeb2020-03-11 08:43:24 +0100583 return scnprintf(buf, len, "-%d.%06u%s", abs(vals[0]),
Jonathan Cameron51239602016-11-08 12:58:51 +0100584 -vals[1], scale_db ? " dB" : "");
585 else
Takashi Iwai35a4eeb2020-03-11 08:43:24 +0100586 return scnprintf(buf, len, "%d.%06u%s", vals[0], vals[1],
Jonathan Cameron51239602016-11-08 12:58:51 +0100587 scale_db ? " dB" : "");
588 case IIO_VAL_INT_PLUS_NANO:
589 if (vals[1] < 0)
Takashi Iwai35a4eeb2020-03-11 08:43:24 +0100590 return scnprintf(buf, len, "-%d.%09u", abs(vals[0]),
Jonathan Cameron51239602016-11-08 12:58:51 +0100591 -vals[1]);
592 else
Takashi Iwai35a4eeb2020-03-11 08:43:24 +0100593 return scnprintf(buf, len, "%d.%09u", vals[0], vals[1]);
Jonathan Cameron51239602016-11-08 12:58:51 +0100594 case IIO_VAL_FRACTIONAL:
595 tmp = div_s64((s64)vals[0] * 1000000000LL, vals[1]);
596 tmp1 = vals[1];
597 tmp0 = (int)div_s64_rem(tmp, 1000000000, &tmp1);
Takashi Iwai35a4eeb2020-03-11 08:43:24 +0100598 return scnprintf(buf, len, "%d.%09u", tmp0, abs(tmp1));
Jonathan Cameron51239602016-11-08 12:58:51 +0100599 case IIO_VAL_FRACTIONAL_LOG2:
Nikolaus Schulz7fd65922017-03-24 13:41:51 +0100600 tmp = shift_right((s64)vals[0] * 1000000000LL, vals[1]);
601 tmp0 = (int)div_s64_rem(tmp, 1000000000LL, &tmp1);
Takashi Iwai35a4eeb2020-03-11 08:43:24 +0100602 return scnprintf(buf, len, "%d.%09u", tmp0, abs(tmp1));
Jonathan Cameron51239602016-11-08 12:58:51 +0100603 case IIO_VAL_INT_MULTIPLE:
604 {
605 int i;
606 int l = 0;
607
608 for (i = 0; i < size; ++i) {
Takashi Iwai35a4eeb2020-03-11 08:43:24 +0100609 l += scnprintf(&buf[l], len - l, "%d ", vals[i]);
Jonathan Cameron51239602016-11-08 12:58:51 +0100610 if (l >= len)
611 break;
612 }
613 return l;
614 }
Andrea Merello8cb34032019-11-20 15:47:51 +0100615 case IIO_VAL_CHAR:
Takashi Iwai35a4eeb2020-03-11 08:43:24 +0100616 return scnprintf(buf, len, "%c", (char)vals[0]);
Jonathan Cameron51239602016-11-08 12:58:51 +0100617 default:
618 return 0;
619 }
620}
621
Lars-Peter Clausen3661f3f2013-10-07 15:11:00 +0100622/**
623 * iio_format_value() - Formats a IIO value into its string representation
Cristina Opriceana2498dcf2015-07-24 16:16:19 +0300624 * @buf: The buffer to which the formatted value gets written
Jonathan Cameron51239602016-11-08 12:58:51 +0100625 * which is assumed to be big enough (i.e. PAGE_SIZE).
Randy Dunlapc175cb72017-10-29 17:06:01 -0700626 * @type: One of the IIO_VAL_* constants. This decides how the val
Cristina Opriceana2498dcf2015-07-24 16:16:19 +0300627 * and val2 parameters are formatted.
628 * @size: Number of IIO value entries contained in vals
629 * @vals: Pointer to the values, exact meaning depends on the
630 * type parameter.
631 *
632 * Return: 0 by default, a negative number on failure or the
633 * total number of characters written for a type that belongs
Randy Dunlapc175cb72017-10-29 17:06:01 -0700634 * to the IIO_VAL_* constant.
Lars-Peter Clausen3661f3f2013-10-07 15:11:00 +0100635 */
Srinivas Pandruvada9fbfb4b2014-04-29 00:51:00 +0100636ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals)
Jonathan Cameron847ec802009-08-18 18:06:19 +0100637{
Jonathan Cameron51239602016-11-08 12:58:51 +0100638 ssize_t len;
Jonathan Cameron847ec802009-08-18 18:06:19 +0100639
Jonathan Cameron51239602016-11-08 12:58:51 +0100640 len = __iio_format_value(buf, PAGE_SIZE, type, size, vals);
641 if (len >= PAGE_SIZE - 1)
642 return -EFBIG;
Srinivas Pandruvada9fbfb4b2014-04-29 00:51:00 +0100643
Jonathan Cameron51239602016-11-08 12:58:51 +0100644 return len + sprintf(buf + len, "\n");
Jonathan Cameron1d892712011-05-18 14:40:51 +0100645}
Andrew F. Davis7d2c2aca2015-12-14 16:35:57 -0600646EXPORT_SYMBOL_GPL(iio_format_value);
Jonathan Cameron1d892712011-05-18 14:40:51 +0100647
Lars-Peter Clausen3661f3f2013-10-07 15:11:00 +0100648static ssize_t iio_read_channel_info(struct device *dev,
649 struct device_attribute *attr,
650 char *buf)
651{
652 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
653 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
Srinivas Pandruvada9fbfb4b2014-04-29 00:51:00 +0100654 int vals[INDIO_MAX_RAW_ELEMENTS];
655 int ret;
656 int val_len = 2;
657
658 if (indio_dev->info->read_raw_multi)
659 ret = indio_dev->info->read_raw_multi(indio_dev, this_attr->c,
660 INDIO_MAX_RAW_ELEMENTS,
661 vals, &val_len,
662 this_attr->address);
663 else
664 ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
665 &vals[0], &vals[1], this_attr->address);
Lars-Peter Clausen3661f3f2013-10-07 15:11:00 +0100666
667 if (ret < 0)
668 return ret;
669
Srinivas Pandruvada9fbfb4b2014-04-29 00:51:00 +0100670 return iio_format_value(buf, ret, val_len, vals);
Lars-Peter Clausen3661f3f2013-10-07 15:11:00 +0100671}
672
Jonathan Cameron51239602016-11-08 12:58:51 +0100673static ssize_t iio_format_avail_list(char *buf, const int *vals,
674 int type, int length)
675{
676 int i;
677 ssize_t len = 0;
678
679 switch (type) {
680 case IIO_VAL_INT:
681 for (i = 0; i < length; i++) {
682 len += __iio_format_value(buf + len, PAGE_SIZE - len,
683 type, 1, &vals[i]);
684 if (len >= PAGE_SIZE)
685 return -EFBIG;
686 if (i < length - 1)
Takashi Iwai35a4eeb2020-03-11 08:43:24 +0100687 len += scnprintf(buf + len, PAGE_SIZE - len,
Jonathan Cameron51239602016-11-08 12:58:51 +0100688 " ");
689 else
Takashi Iwai35a4eeb2020-03-11 08:43:24 +0100690 len += scnprintf(buf + len, PAGE_SIZE - len,
Jonathan Cameron51239602016-11-08 12:58:51 +0100691 "\n");
692 if (len >= PAGE_SIZE)
693 return -EFBIG;
694 }
695 break;
696 default:
697 for (i = 0; i < length / 2; i++) {
698 len += __iio_format_value(buf + len, PAGE_SIZE - len,
699 type, 2, &vals[i * 2]);
700 if (len >= PAGE_SIZE)
701 return -EFBIG;
702 if (i < length / 2 - 1)
Takashi Iwai35a4eeb2020-03-11 08:43:24 +0100703 len += scnprintf(buf + len, PAGE_SIZE - len,
Jonathan Cameron51239602016-11-08 12:58:51 +0100704 " ");
705 else
Takashi Iwai35a4eeb2020-03-11 08:43:24 +0100706 len += scnprintf(buf + len, PAGE_SIZE - len,
Jonathan Cameron51239602016-11-08 12:58:51 +0100707 "\n");
708 if (len >= PAGE_SIZE)
709 return -EFBIG;
710 }
711 }
712
713 return len;
714}
715
716static ssize_t iio_format_avail_range(char *buf, const int *vals, int type)
717{
718 int i;
719 ssize_t len;
720
721 len = snprintf(buf, PAGE_SIZE, "[");
722 switch (type) {
723 case IIO_VAL_INT:
724 for (i = 0; i < 3; i++) {
725 len += __iio_format_value(buf + len, PAGE_SIZE - len,
726 type, 1, &vals[i]);
727 if (len >= PAGE_SIZE)
728 return -EFBIG;
729 if (i < 2)
Takashi Iwai35a4eeb2020-03-11 08:43:24 +0100730 len += scnprintf(buf + len, PAGE_SIZE - len,
Jonathan Cameron51239602016-11-08 12:58:51 +0100731 " ");
732 else
Takashi Iwai35a4eeb2020-03-11 08:43:24 +0100733 len += scnprintf(buf + len, PAGE_SIZE - len,
Jonathan Cameron51239602016-11-08 12:58:51 +0100734 "]\n");
735 if (len >= PAGE_SIZE)
736 return -EFBIG;
737 }
738 break;
739 default:
740 for (i = 0; i < 3; i++) {
741 len += __iio_format_value(buf + len, PAGE_SIZE - len,
742 type, 2, &vals[i * 2]);
743 if (len >= PAGE_SIZE)
744 return -EFBIG;
745 if (i < 2)
Takashi Iwai35a4eeb2020-03-11 08:43:24 +0100746 len += scnprintf(buf + len, PAGE_SIZE - len,
Jonathan Cameron51239602016-11-08 12:58:51 +0100747 " ");
748 else
Takashi Iwai35a4eeb2020-03-11 08:43:24 +0100749 len += scnprintf(buf + len, PAGE_SIZE - len,
Jonathan Cameron51239602016-11-08 12:58:51 +0100750 "]\n");
751 if (len >= PAGE_SIZE)
752 return -EFBIG;
753 }
754 }
755
756 return len;
757}
758
759static ssize_t iio_read_channel_info_avail(struct device *dev,
760 struct device_attribute *attr,
761 char *buf)
762{
763 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
764 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
765 const int *vals;
766 int ret;
767 int length;
768 int type;
769
770 ret = indio_dev->info->read_avail(indio_dev, this_attr->c,
771 &vals, &type, &length,
772 this_attr->address);
773
774 if (ret < 0)
775 return ret;
776 switch (ret) {
777 case IIO_AVAIL_LIST:
778 return iio_format_avail_list(buf, vals, type, length);
779 case IIO_AVAIL_RANGE:
780 return iio_format_avail_range(buf, vals, type);
781 default:
782 return -EINVAL;
783 }
784}
785
Lars-Peter Clausen6807d722012-11-20 13:36:00 +0000786/**
Beniamin Biab8528222020-02-06 17:11:45 +0200787 * __iio_str_to_fixpoint() - Parse a fixed-point number from a string
Lars-Peter Clausen6807d722012-11-20 13:36:00 +0000788 * @str: The string to parse
789 * @fract_mult: Multiplier for the first decimal place, should be a power of 10
790 * @integer: The integer part of the number
791 * @fract: The fractional part of the number
Beniamin Biab8528222020-02-06 17:11:45 +0200792 * @scale_db: True if this should parse as dB
Lars-Peter Clausen6807d722012-11-20 13:36:00 +0000793 *
794 * Returns 0 on success, or a negative error code if the string could not be
795 * parsed.
796 */
Beniamin Biab8528222020-02-06 17:11:45 +0200797static int __iio_str_to_fixpoint(const char *str, int fract_mult,
798 int *integer, int *fract, bool scale_db)
Lars-Peter Clausen6807d722012-11-20 13:36:00 +0000799{
800 int i = 0, f = 0;
801 bool integer_part = true, negative = false;
802
Sean Nyekjaerf47dff32015-11-09 13:55:34 +0100803 if (fract_mult == 0) {
804 *fract = 0;
805
806 return kstrtoint(str, 0, integer);
807 }
808
Lars-Peter Clausen6807d722012-11-20 13:36:00 +0000809 if (str[0] == '-') {
810 negative = true;
811 str++;
812 } else if (str[0] == '+') {
813 str++;
814 }
815
816 while (*str) {
817 if ('0' <= *str && *str <= '9') {
818 if (integer_part) {
819 i = i * 10 + *str - '0';
820 } else {
821 f += fract_mult * (*str - '0');
822 fract_mult /= 10;
823 }
824 } else if (*str == '\n') {
825 if (*(str + 1) == '\0')
826 break;
827 else
828 return -EINVAL;
Beniamin Biab8528222020-02-06 17:11:45 +0200829 } else if (!strncmp(str, " dB", sizeof(" dB") - 1) && scale_db) {
830 /* Ignore the dB suffix */
831 str += sizeof(" dB") - 1;
832 continue;
833 } else if (!strncmp(str, "dB", sizeof("dB") - 1) && scale_db) {
834 /* Ignore the dB suffix */
835 str += sizeof("dB") - 1;
836 continue;
Lars-Peter Clausen6807d722012-11-20 13:36:00 +0000837 } else if (*str == '.' && integer_part) {
838 integer_part = false;
839 } else {
840 return -EINVAL;
841 }
842 str++;
843 }
844
845 if (negative) {
846 if (i)
847 i = -i;
848 else
849 f = -f;
850 }
851
852 *integer = i;
853 *fract = f;
854
855 return 0;
856}
Beniamin Biab8528222020-02-06 17:11:45 +0200857
858/**
859 * iio_str_to_fixpoint() - Parse a fixed-point number from a string
860 * @str: The string to parse
861 * @fract_mult: Multiplier for the first decimal place, should be a power of 10
862 * @integer: The integer part of the number
863 * @fract: The fractional part of the number
864 *
865 * Returns 0 on success, or a negative error code if the string could not be
866 * parsed.
867 */
868int iio_str_to_fixpoint(const char *str, int fract_mult,
869 int *integer, int *fract)
870{
871 return __iio_str_to_fixpoint(str, fract_mult, integer, fract, false);
872}
Lars-Peter Clausen6807d722012-11-20 13:36:00 +0000873EXPORT_SYMBOL_GPL(iio_str_to_fixpoint);
874
Jonathan Cameron1d892712011-05-18 14:40:51 +0100875static ssize_t iio_write_channel_info(struct device *dev,
876 struct device_attribute *attr,
877 const char *buf,
878 size_t len)
879{
Lars-Peter Clausene53f5ac2012-05-12 15:39:33 +0200880 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
Jonathan Cameron1d892712011-05-18 14:40:51 +0100881 struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
Lars-Peter Clausen6807d722012-11-20 13:36:00 +0000882 int ret, fract_mult = 100000;
Andrea Merello8cb34032019-11-20 15:47:51 +0100883 int integer, fract = 0;
884 bool is_char = false;
Beniamin Biab8528222020-02-06 17:11:45 +0200885 bool scale_db = false;
Jonathan Cameron1d892712011-05-18 14:40:51 +0100886
887 /* Assumes decimal - precision based on number of digits */
Jonathan Cameron6fe81352011-05-18 14:42:37 +0100888 if (!indio_dev->info->write_raw)
Jonathan Cameron1d892712011-05-18 14:40:51 +0100889 return -EINVAL;
Michael Hennerich5c04af02011-06-27 13:07:10 +0100890
891 if (indio_dev->info->write_raw_get_fmt)
892 switch (indio_dev->info->write_raw_get_fmt(indio_dev,
893 this_attr->c, this_attr->address)) {
Sean Nyekjaerf47dff32015-11-09 13:55:34 +0100894 case IIO_VAL_INT:
895 fract_mult = 0;
896 break;
Beniamin Biab8528222020-02-06 17:11:45 +0200897 case IIO_VAL_INT_PLUS_MICRO_DB:
898 scale_db = true;
899 /* fall through */
Michael Hennerich5c04af02011-06-27 13:07:10 +0100900 case IIO_VAL_INT_PLUS_MICRO:
901 fract_mult = 100000;
902 break;
903 case IIO_VAL_INT_PLUS_NANO:
904 fract_mult = 100000000;
905 break;
Andrea Merello8cb34032019-11-20 15:47:51 +0100906 case IIO_VAL_CHAR:
907 is_char = true;
908 break;
Michael Hennerich5c04af02011-06-27 13:07:10 +0100909 default:
910 return -EINVAL;
911 }
912
Andrea Merello8cb34032019-11-20 15:47:51 +0100913 if (is_char) {
914 char ch;
915
916 if (sscanf(buf, "%c", &ch) != 1)
917 return -EINVAL;
918 integer = ch;
919 } else {
Mircea Caprioru5403f282020-04-01 14:22:30 +0300920 ret = __iio_str_to_fixpoint(buf, fract_mult, &integer, &fract,
921 scale_db);
Andrea Merello8cb34032019-11-20 15:47:51 +0100922 if (ret)
923 return ret;
924 }
Jonathan Cameron847ec802009-08-18 18:06:19 +0100925
Jonathan Cameron6fe81352011-05-18 14:42:37 +0100926 ret = indio_dev->info->write_raw(indio_dev, this_attr->c,
Michael Hennerich5c04af02011-06-27 13:07:10 +0100927 integer, fract, this_attr->address);
Jonathan Cameron1d892712011-05-18 14:40:51 +0100928 if (ret)
929 return ret;
930
931 return len;
932}
933
Jonathan Camerondf9c1c42011-08-12 17:56:03 +0100934static
Jonathan Cameron1d892712011-05-18 14:40:51 +0100935int __iio_device_attr_init(struct device_attribute *dev_attr,
936 const char *postfix,
937 struct iio_chan_spec const *chan,
938 ssize_t (*readfunc)(struct device *dev,
939 struct device_attribute *attr,
940 char *buf),
941 ssize_t (*writefunc)(struct device *dev,
942 struct device_attribute *attr,
943 const char *buf,
944 size_t len),
Jonathan Cameron37044322013-09-08 14:57:00 +0100945 enum iio_shared_by shared_by)
Jonathan Cameron1d892712011-05-18 14:40:51 +0100946{
Jonathan Cameron37044322013-09-08 14:57:00 +0100947 int ret = 0;
Lars-Peter Clausen7bbcf7e2014-02-14 14:19:00 +0000948 char *name = NULL;
Jonathan Cameron37044322013-09-08 14:57:00 +0100949 char *full_postfix;
Jonathan Cameron1d892712011-05-18 14:40:51 +0100950 sysfs_attr_init(&dev_attr->attr);
Jonathan Cameronade7ef72011-09-02 17:14:45 +0100951
952 /* Build up postfix of <extend_name>_<modifier>_postfix */
Jonathan Cameron37044322013-09-08 14:57:00 +0100953 if (chan->modified && (shared_by == IIO_SEPARATE)) {
Jonathan Cameronade7ef72011-09-02 17:14:45 +0100954 if (chan->extend_name)
955 full_postfix = kasprintf(GFP_KERNEL, "%s_%s_%s",
956 iio_modifier_names[chan
957 ->channel2],
958 chan->extend_name,
959 postfix);
960 else
961 full_postfix = kasprintf(GFP_KERNEL, "%s_%s",
962 iio_modifier_names[chan
963 ->channel2],
964 postfix);
965 } else {
Lars-Peter Clausen77bfa8b2014-02-14 14:19:00 +0000966 if (chan->extend_name == NULL || shared_by != IIO_SEPARATE)
Jonathan Cameronade7ef72011-09-02 17:14:45 +0100967 full_postfix = kstrdup(postfix, GFP_KERNEL);
968 else
969 full_postfix = kasprintf(GFP_KERNEL,
970 "%s_%s",
971 chan->extend_name,
972 postfix);
973 }
Jonathan Cameron37044322013-09-08 14:57:00 +0100974 if (full_postfix == NULL)
975 return -ENOMEM;
Jonathan Cameron1d892712011-05-18 14:40:51 +0100976
Justin P. Mattock4abf6f82012-02-29 22:00:38 -0800977 if (chan->differential) { /* Differential can not have modifier */
Jonathan Cameron37044322013-09-08 14:57:00 +0100978 switch (shared_by) {
Jonathan Cameronc006ec82013-09-08 14:57:00 +0100979 case IIO_SHARED_BY_ALL:
Lars-Peter Clausen7bbcf7e2014-02-14 14:19:00 +0000980 name = kasprintf(GFP_KERNEL, "%s", full_postfix);
Jonathan Cameronc006ec82013-09-08 14:57:00 +0100981 break;
982 case IIO_SHARED_BY_DIR:
Lars-Peter Clausen7bbcf7e2014-02-14 14:19:00 +0000983 name = kasprintf(GFP_KERNEL, "%s_%s",
Jonathan Cameronc006ec82013-09-08 14:57:00 +0100984 iio_direction[chan->output],
985 full_postfix);
986 break;
Jonathan Cameron37044322013-09-08 14:57:00 +0100987 case IIO_SHARED_BY_TYPE:
Lars-Peter Clausen7bbcf7e2014-02-14 14:19:00 +0000988 name = kasprintf(GFP_KERNEL, "%s_%s-%s_%s",
Jonathan Cameronade7ef72011-09-02 17:14:45 +0100989 iio_direction[chan->output],
990 iio_chan_type_name_spec[chan->type],
991 iio_chan_type_name_spec[chan->type],
992 full_postfix);
Jonathan Cameron37044322013-09-08 14:57:00 +0100993 break;
994 case IIO_SEPARATE:
995 if (!chan->indexed) {
Dan Carpenter231bfe52015-11-21 13:33:00 +0300996 WARN(1, "Differential channels must be indexed\n");
Jonathan Cameron37044322013-09-08 14:57:00 +0100997 ret = -EINVAL;
998 goto error_free_full_postfix;
999 }
Lars-Peter Clausen7bbcf7e2014-02-14 14:19:00 +00001000 name = kasprintf(GFP_KERNEL,
Jonathan Cameron37044322013-09-08 14:57:00 +01001001 "%s_%s%d-%s%d_%s",
Jonathan Cameronade7ef72011-09-02 17:14:45 +01001002 iio_direction[chan->output],
1003 iio_chan_type_name_spec[chan->type],
1004 chan->channel,
1005 iio_chan_type_name_spec[chan->type],
1006 chan->channel2,
1007 full_postfix);
Jonathan Cameron37044322013-09-08 14:57:00 +01001008 break;
Jonathan Cameronade7ef72011-09-02 17:14:45 +01001009 }
1010 } else { /* Single ended */
Jonathan Cameron37044322013-09-08 14:57:00 +01001011 switch (shared_by) {
Jonathan Cameronc006ec82013-09-08 14:57:00 +01001012 case IIO_SHARED_BY_ALL:
Lars-Peter Clausen7bbcf7e2014-02-14 14:19:00 +00001013 name = kasprintf(GFP_KERNEL, "%s", full_postfix);
Jonathan Cameronc006ec82013-09-08 14:57:00 +01001014 break;
1015 case IIO_SHARED_BY_DIR:
Lars-Peter Clausen7bbcf7e2014-02-14 14:19:00 +00001016 name = kasprintf(GFP_KERNEL, "%s_%s",
Jonathan Cameronc006ec82013-09-08 14:57:00 +01001017 iio_direction[chan->output],
1018 full_postfix);
1019 break;
Jonathan Cameron37044322013-09-08 14:57:00 +01001020 case IIO_SHARED_BY_TYPE:
Lars-Peter Clausen7bbcf7e2014-02-14 14:19:00 +00001021 name = kasprintf(GFP_KERNEL, "%s_%s_%s",
Jonathan Cameronade7ef72011-09-02 17:14:45 +01001022 iio_direction[chan->output],
1023 iio_chan_type_name_spec[chan->type],
1024 full_postfix);
Jonathan Cameron37044322013-09-08 14:57:00 +01001025 break;
1026
1027 case IIO_SEPARATE:
1028 if (chan->indexed)
Lars-Peter Clausen7bbcf7e2014-02-14 14:19:00 +00001029 name = kasprintf(GFP_KERNEL, "%s_%s%d_%s",
Jonathan Cameron37044322013-09-08 14:57:00 +01001030 iio_direction[chan->output],
1031 iio_chan_type_name_spec[chan->type],
1032 chan->channel,
1033 full_postfix);
1034 else
Lars-Peter Clausen7bbcf7e2014-02-14 14:19:00 +00001035 name = kasprintf(GFP_KERNEL, "%s_%s_%s",
Jonathan Cameron37044322013-09-08 14:57:00 +01001036 iio_direction[chan->output],
1037 iio_chan_type_name_spec[chan->type],
1038 full_postfix);
1039 break;
1040 }
Jonathan Cameronade7ef72011-09-02 17:14:45 +01001041 }
Lars-Peter Clausen7bbcf7e2014-02-14 14:19:00 +00001042 if (name == NULL) {
Jonathan Cameron1d892712011-05-18 14:40:51 +01001043 ret = -ENOMEM;
1044 goto error_free_full_postfix;
1045 }
Lars-Peter Clausen7bbcf7e2014-02-14 14:19:00 +00001046 dev_attr->attr.name = name;
Jonathan Cameron1d892712011-05-18 14:40:51 +01001047
1048 if (readfunc) {
1049 dev_attr->attr.mode |= S_IRUGO;
1050 dev_attr->show = readfunc;
1051 }
1052
1053 if (writefunc) {
1054 dev_attr->attr.mode |= S_IWUSR;
1055 dev_attr->store = writefunc;
1056 }
Lars-Peter Clausen7bbcf7e2014-02-14 14:19:00 +00001057
Jonathan Cameron1d892712011-05-18 14:40:51 +01001058error_free_full_postfix:
1059 kfree(full_postfix);
Jonathan Cameron37044322013-09-08 14:57:00 +01001060
Jonathan Cameron847ec802009-08-18 18:06:19 +01001061 return ret;
1062}
1063
Jonathan Camerondf9c1c42011-08-12 17:56:03 +01001064static void __iio_device_attr_deinit(struct device_attribute *dev_attr)
Jonathan Cameron1d892712011-05-18 14:40:51 +01001065{
1066 kfree(dev_attr->attr.name);
1067}
1068
1069int __iio_add_chan_devattr(const char *postfix,
Jonathan Cameron1d892712011-05-18 14:40:51 +01001070 struct iio_chan_spec const *chan,
1071 ssize_t (*readfunc)(struct device *dev,
1072 struct device_attribute *attr,
1073 char *buf),
1074 ssize_t (*writefunc)(struct device *dev,
1075 struct device_attribute *attr,
1076 const char *buf,
1077 size_t len),
Jonathan Camerone614a542011-09-02 17:14:41 +01001078 u64 mask,
Jonathan Cameron37044322013-09-08 14:57:00 +01001079 enum iio_shared_by shared_by,
Jonathan Cameron1d892712011-05-18 14:40:51 +01001080 struct device *dev,
1081 struct list_head *attr_list)
1082{
1083 int ret;
1084 struct iio_dev_attr *iio_attr, *t;
1085
Sachin Kamat670c1102013-10-24 12:53:00 +01001086 iio_attr = kzalloc(sizeof(*iio_attr), GFP_KERNEL);
Hartmut Knaack92825ff2014-02-16 11:53:00 +00001087 if (iio_attr == NULL)
1088 return -ENOMEM;
Jonathan Cameron1d892712011-05-18 14:40:51 +01001089 ret = __iio_device_attr_init(&iio_attr->dev_attr,
1090 postfix, chan,
Jonathan Cameron37044322013-09-08 14:57:00 +01001091 readfunc, writefunc, shared_by);
Jonathan Cameron1d892712011-05-18 14:40:51 +01001092 if (ret)
1093 goto error_iio_dev_attr_free;
1094 iio_attr->c = chan;
1095 iio_attr->address = mask;
1096 list_for_each_entry(t, attr_list, l)
1097 if (strcmp(t->dev_attr.attr.name,
1098 iio_attr->dev_attr.attr.name) == 0) {
Jonathan Cameron37044322013-09-08 14:57:00 +01001099 if (shared_by == IIO_SEPARATE)
Jonathan Cameron1d892712011-05-18 14:40:51 +01001100 dev_err(dev, "tried to double register : %s\n",
1101 t->dev_attr.attr.name);
1102 ret = -EBUSY;
1103 goto error_device_attr_deinit;
1104 }
Jonathan Cameron1d892712011-05-18 14:40:51 +01001105 list_add(&iio_attr->l, attr_list);
1106
1107 return 0;
1108
1109error_device_attr_deinit:
1110 __iio_device_attr_deinit(&iio_attr->dev_attr);
1111error_iio_dev_attr_free:
1112 kfree(iio_attr);
Jonathan Cameron1d892712011-05-18 14:40:51 +01001113 return ret;
1114}
1115
Jonathan Cameron37044322013-09-08 14:57:00 +01001116static int iio_device_add_info_mask_type(struct iio_dev *indio_dev,
1117 struct iio_chan_spec const *chan,
1118 enum iio_shared_by shared_by,
1119 const long *infomask)
1120{
1121 int i, ret, attrcount = 0;
1122
Orson Zhai1016d562017-04-25 09:16:56 +08001123 for_each_set_bit(i, infomask, sizeof(*infomask)*8) {
Jonathan Cameronef4b4852014-01-03 22:24:00 +00001124 if (i >= ARRAY_SIZE(iio_chan_info_postfix))
1125 return -EINVAL;
Jonathan Cameron37044322013-09-08 14:57:00 +01001126 ret = __iio_add_chan_devattr(iio_chan_info_postfix[i],
1127 chan,
1128 &iio_read_channel_info,
1129 &iio_write_channel_info,
1130 i,
1131 shared_by,
1132 &indio_dev->dev,
1133 &indio_dev->channel_attr_list);
1134 if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE))
1135 continue;
1136 else if (ret < 0)
1137 return ret;
1138 attrcount++;
1139 }
1140
1141 return attrcount;
1142}
1143
Jonathan Cameron51239602016-11-08 12:58:51 +01001144static int iio_device_add_info_mask_type_avail(struct iio_dev *indio_dev,
1145 struct iio_chan_spec const *chan,
1146 enum iio_shared_by shared_by,
1147 const long *infomask)
1148{
1149 int i, ret, attrcount = 0;
1150 char *avail_postfix;
1151
Orson Zhai1016d562017-04-25 09:16:56 +08001152 for_each_set_bit(i, infomask, sizeof(*infomask) * 8) {
Young Xiao936d3e52019-06-04 20:40:00 +08001153 if (i >= ARRAY_SIZE(iio_chan_info_postfix))
1154 return -EINVAL;
Jonathan Cameron51239602016-11-08 12:58:51 +01001155 avail_postfix = kasprintf(GFP_KERNEL,
1156 "%s_available",
1157 iio_chan_info_postfix[i]);
1158 if (!avail_postfix)
1159 return -ENOMEM;
1160
1161 ret = __iio_add_chan_devattr(avail_postfix,
1162 chan,
1163 &iio_read_channel_info_avail,
1164 NULL,
1165 i,
1166 shared_by,
1167 &indio_dev->dev,
1168 &indio_dev->channel_attr_list);
1169 kfree(avail_postfix);
1170 if ((ret == -EBUSY) && (shared_by != IIO_SEPARATE))
1171 continue;
1172 else if (ret < 0)
1173 return ret;
1174 attrcount++;
1175 }
1176
1177 return attrcount;
1178}
1179
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001180static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
Jonathan Cameron1d892712011-05-18 14:40:51 +01001181 struct iio_chan_spec const *chan)
1182{
Jonathan Cameron5ccb3ad2012-04-15 17:41:16 +01001183 int ret, attrcount = 0;
Lars-Peter Clausen5f420b42012-02-21 18:38:12 +01001184 const struct iio_chan_spec_ext_info *ext_info;
Jonathan Cameron1d892712011-05-18 14:40:51 +01001185
Jonathan Cameron1d892712011-05-18 14:40:51 +01001186 if (chan->channel < 0)
1187 return 0;
Jonathan Cameron37044322013-09-08 14:57:00 +01001188 ret = iio_device_add_info_mask_type(indio_dev, chan,
1189 IIO_SEPARATE,
1190 &chan->info_mask_separate);
1191 if (ret < 0)
1192 return ret;
1193 attrcount += ret;
1194
Jonathan Cameron51239602016-11-08 12:58:51 +01001195 ret = iio_device_add_info_mask_type_avail(indio_dev, chan,
1196 IIO_SEPARATE,
1197 &chan->
1198 info_mask_separate_available);
1199 if (ret < 0)
1200 return ret;
1201 attrcount += ret;
1202
Jonathan Cameron37044322013-09-08 14:57:00 +01001203 ret = iio_device_add_info_mask_type(indio_dev, chan,
1204 IIO_SHARED_BY_TYPE,
1205 &chan->info_mask_shared_by_type);
1206 if (ret < 0)
1207 return ret;
1208 attrcount += ret;
Lars-Peter Clausen5f420b42012-02-21 18:38:12 +01001209
Jonathan Cameron51239602016-11-08 12:58:51 +01001210 ret = iio_device_add_info_mask_type_avail(indio_dev, chan,
1211 IIO_SHARED_BY_TYPE,
1212 &chan->
1213 info_mask_shared_by_type_available);
1214 if (ret < 0)
1215 return ret;
1216 attrcount += ret;
1217
Jonathan Cameronc006ec82013-09-08 14:57:00 +01001218 ret = iio_device_add_info_mask_type(indio_dev, chan,
1219 IIO_SHARED_BY_DIR,
1220 &chan->info_mask_shared_by_dir);
1221 if (ret < 0)
1222 return ret;
1223 attrcount += ret;
1224
Jonathan Cameron51239602016-11-08 12:58:51 +01001225 ret = iio_device_add_info_mask_type_avail(indio_dev, chan,
1226 IIO_SHARED_BY_DIR,
1227 &chan->info_mask_shared_by_dir_available);
1228 if (ret < 0)
1229 return ret;
1230 attrcount += ret;
1231
Jonathan Cameronc006ec82013-09-08 14:57:00 +01001232 ret = iio_device_add_info_mask_type(indio_dev, chan,
1233 IIO_SHARED_BY_ALL,
1234 &chan->info_mask_shared_by_all);
1235 if (ret < 0)
1236 return ret;
1237 attrcount += ret;
1238
Jonathan Cameron51239602016-11-08 12:58:51 +01001239 ret = iio_device_add_info_mask_type_avail(indio_dev, chan,
1240 IIO_SHARED_BY_ALL,
1241 &chan->info_mask_shared_by_all_available);
1242 if (ret < 0)
1243 return ret;
1244 attrcount += ret;
1245
Lars-Peter Clausen5f420b42012-02-21 18:38:12 +01001246 if (chan->ext_info) {
1247 unsigned int i = 0;
1248 for (ext_info = chan->ext_info; ext_info->name; ext_info++) {
1249 ret = __iio_add_chan_devattr(ext_info->name,
1250 chan,
1251 ext_info->read ?
1252 &iio_read_channel_ext_info : NULL,
1253 ext_info->write ?
1254 &iio_write_channel_ext_info : NULL,
1255 i,
1256 ext_info->shared,
1257 &indio_dev->dev,
1258 &indio_dev->channel_attr_list);
1259 i++;
1260 if (ret == -EBUSY && ext_info->shared)
1261 continue;
1262
1263 if (ret)
Jonathan Cameron37044322013-09-08 14:57:00 +01001264 return ret;
Lars-Peter Clausen5f420b42012-02-21 18:38:12 +01001265
1266 attrcount++;
1267 }
1268 }
1269
Jonathan Cameron37044322013-09-08 14:57:00 +01001270 return attrcount;
Jonathan Cameron1d892712011-05-18 14:40:51 +01001271}
1272
Lars-Peter Clausen84088eb2013-10-07 12:50:00 +01001273/**
1274 * iio_free_chan_devattr_list() - Free a list of IIO device attributes
1275 * @attr_list: List of IIO device attributes
1276 *
1277 * This function frees the memory allocated for each of the IIO device
Martin Fuzzeyc1b03ab2015-02-19 15:17:44 +01001278 * attributes in the list.
Lars-Peter Clausen84088eb2013-10-07 12:50:00 +01001279 */
1280void iio_free_chan_devattr_list(struct list_head *attr_list)
Jonathan Cameron1d892712011-05-18 14:40:51 +01001281{
Lars-Peter Clausen84088eb2013-10-07 12:50:00 +01001282 struct iio_dev_attr *p, *n;
1283
1284 list_for_each_entry_safe(p, n, attr_list, l) {
1285 kfree(p->dev_attr.attr.name);
Martin Fuzzeyc1b03ab2015-02-19 15:17:44 +01001286 list_del(&p->l);
Lars-Peter Clausen84088eb2013-10-07 12:50:00 +01001287 kfree(p);
1288 }
Jonathan Cameron1d892712011-05-18 14:40:51 +01001289}
1290
Jonathan Cameron1b732882011-05-18 14:41:43 +01001291static ssize_t iio_show_dev_name(struct device *dev,
1292 struct device_attribute *attr,
1293 char *buf)
1294{
Lars-Peter Clausene53f5ac2012-05-12 15:39:33 +02001295 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
Kees Cook598db582014-03-13 16:46:00 +00001296 return snprintf(buf, PAGE_SIZE, "%s\n", indio_dev->name);
Jonathan Cameron1b732882011-05-18 14:41:43 +01001297}
1298
1299static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
1300
Phil Reid2c3d0c92019-09-19 22:36:08 +08001301static ssize_t iio_show_dev_label(struct device *dev,
1302 struct device_attribute *attr,
1303 char *buf)
1304{
1305 struct iio_dev *indio_dev = dev_to_iio_dev(dev);
1306 return snprintf(buf, PAGE_SIZE, "%s\n", indio_dev->label);
1307}
1308
1309static DEVICE_ATTR(label, S_IRUGO, iio_show_dev_label, NULL);
1310
Gregor Boiriebc2b7da2016-03-09 19:05:49 +01001311static ssize_t iio_show_timestamp_clock(struct device *dev,
1312 struct device_attribute *attr,
1313 char *buf)
1314{
1315 const struct iio_dev *indio_dev = dev_to_iio_dev(dev);
1316 const clockid_t clk = iio_device_get_clock(indio_dev);
1317 const char *name;
1318 ssize_t sz;
1319
1320 switch (clk) {
1321 case CLOCK_REALTIME:
1322 name = "realtime\n";
1323 sz = sizeof("realtime\n");
1324 break;
1325 case CLOCK_MONOTONIC:
1326 name = "monotonic\n";
1327 sz = sizeof("monotonic\n");
1328 break;
1329 case CLOCK_MONOTONIC_RAW:
1330 name = "monotonic_raw\n";
1331 sz = sizeof("monotonic_raw\n");
1332 break;
1333 case CLOCK_REALTIME_COARSE:
1334 name = "realtime_coarse\n";
1335 sz = sizeof("realtime_coarse\n");
1336 break;
1337 case CLOCK_MONOTONIC_COARSE:
1338 name = "monotonic_coarse\n";
1339 sz = sizeof("monotonic_coarse\n");
1340 break;
1341 case CLOCK_BOOTTIME:
1342 name = "boottime\n";
1343 sz = sizeof("boottime\n");
1344 break;
1345 case CLOCK_TAI:
1346 name = "tai\n";
1347 sz = sizeof("tai\n");
1348 break;
1349 default:
1350 BUG();
1351 }
1352
1353 memcpy(buf, name, sz);
1354 return sz;
1355}
1356
1357static ssize_t iio_store_timestamp_clock(struct device *dev,
1358 struct device_attribute *attr,
1359 const char *buf, size_t len)
1360{
1361 clockid_t clk;
1362 int ret;
1363
1364 if (sysfs_streq(buf, "realtime"))
1365 clk = CLOCK_REALTIME;
1366 else if (sysfs_streq(buf, "monotonic"))
1367 clk = CLOCK_MONOTONIC;
1368 else if (sysfs_streq(buf, "monotonic_raw"))
1369 clk = CLOCK_MONOTONIC_RAW;
1370 else if (sysfs_streq(buf, "realtime_coarse"))
1371 clk = CLOCK_REALTIME_COARSE;
1372 else if (sysfs_streq(buf, "monotonic_coarse"))
1373 clk = CLOCK_MONOTONIC_COARSE;
1374 else if (sysfs_streq(buf, "boottime"))
1375 clk = CLOCK_BOOTTIME;
1376 else if (sysfs_streq(buf, "tai"))
1377 clk = CLOCK_TAI;
1378 else
1379 return -EINVAL;
1380
1381 ret = iio_device_set_clock(dev_to_iio_dev(dev), clk);
1382 if (ret)
1383 return ret;
1384
1385 return len;
1386}
1387
1388static DEVICE_ATTR(current_timestamp_clock, S_IRUGO | S_IWUSR,
1389 iio_show_timestamp_clock, iio_store_timestamp_clock);
1390
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001391static int iio_device_register_sysfs(struct iio_dev *indio_dev)
Jonathan Cameron1d892712011-05-18 14:40:51 +01001392{
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01001393 int i, ret = 0, attrcount, attrn, attrcount_orig = 0;
Lars-Peter Clausen84088eb2013-10-07 12:50:00 +01001394 struct iio_dev_attr *p;
Gregor Boiriebc2b7da2016-03-09 19:05:49 +01001395 struct attribute **attr, *clk = NULL;
Jonathan Cameron1d892712011-05-18 14:40:51 +01001396
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01001397 /* First count elements in any existing group */
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001398 if (indio_dev->info->attrs) {
1399 attr = indio_dev->info->attrs->attrs;
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01001400 while (*attr++ != NULL)
1401 attrcount_orig++;
Jonathan Cameron1d892712011-05-18 14:40:51 +01001402 }
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01001403 attrcount = attrcount_orig;
Jonathan Cameron1d892712011-05-18 14:40:51 +01001404 /*
1405 * New channel registration method - relies on the fact a group does
Peter Meerwaldd25b3802012-08-26 13:43:00 +01001406 * not need to be initialized if its name is NULL.
Jonathan Cameron1d892712011-05-18 14:40:51 +01001407 */
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001408 if (indio_dev->channels)
1409 for (i = 0; i < indio_dev->num_channels; i++) {
Gregor Boiriebc2b7da2016-03-09 19:05:49 +01001410 const struct iio_chan_spec *chan =
1411 &indio_dev->channels[i];
1412
1413 if (chan->type == IIO_TIMESTAMP)
1414 clk = &dev_attr_current_timestamp_clock.attr;
1415
1416 ret = iio_device_add_channel_sysfs(indio_dev, chan);
Jonathan Cameron1d892712011-05-18 14:40:51 +01001417 if (ret < 0)
1418 goto error_clear_attrs;
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01001419 attrcount += ret;
Jonathan Cameron1d892712011-05-18 14:40:51 +01001420 }
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01001421
Gregor Boiriebc2b7da2016-03-09 19:05:49 +01001422 if (indio_dev->event_interface)
1423 clk = &dev_attr_current_timestamp_clock.attr;
1424
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001425 if (indio_dev->name)
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01001426 attrcount++;
Phil Reid2c3d0c92019-09-19 22:36:08 +08001427 if (indio_dev->label)
1428 attrcount++;
Gregor Boiriebc2b7da2016-03-09 19:05:49 +01001429 if (clk)
1430 attrcount++;
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01001431
Thomas Meyerd83fb182011-11-29 22:08:00 +01001432 indio_dev->chan_attr_group.attrs = kcalloc(attrcount + 1,
1433 sizeof(indio_dev->chan_attr_group.attrs[0]),
1434 GFP_KERNEL);
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001435 if (indio_dev->chan_attr_group.attrs == NULL) {
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01001436 ret = -ENOMEM;
1437 goto error_clear_attrs;
Jonathan Cameron1b732882011-05-18 14:41:43 +01001438 }
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01001439 /* Copy across original attributes */
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001440 if (indio_dev->info->attrs)
1441 memcpy(indio_dev->chan_attr_group.attrs,
1442 indio_dev->info->attrs->attrs,
1443 sizeof(indio_dev->chan_attr_group.attrs[0])
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01001444 *attrcount_orig);
1445 attrn = attrcount_orig;
1446 /* Add all elements from the list. */
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001447 list_for_each_entry(p, &indio_dev->channel_attr_list, l)
1448 indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr;
1449 if (indio_dev->name)
1450 indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr;
Phil Reid2c3d0c92019-09-19 22:36:08 +08001451 if (indio_dev->label)
1452 indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_label.attr;
Gregor Boiriebc2b7da2016-03-09 19:05:49 +01001453 if (clk)
1454 indio_dev->chan_attr_group.attrs[attrn++] = clk;
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01001455
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001456 indio_dev->groups[indio_dev->groupcounter++] =
1457 &indio_dev->chan_attr_group;
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01001458
Jonathan Cameron1d892712011-05-18 14:40:51 +01001459 return 0;
Jonathan Cameron1b732882011-05-18 14:41:43 +01001460
Jonathan Cameron1d892712011-05-18 14:40:51 +01001461error_clear_attrs:
Lars-Peter Clausen84088eb2013-10-07 12:50:00 +01001462 iio_free_chan_devattr_list(&indio_dev->channel_attr_list);
Jonathan Cameron1d892712011-05-18 14:40:51 +01001463
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01001464 return ret;
Jonathan Cameron1d892712011-05-18 14:40:51 +01001465}
1466
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001467static void iio_device_unregister_sysfs(struct iio_dev *indio_dev)
Jonathan Cameron847ec802009-08-18 18:06:19 +01001468{
Jonathan Cameron1d892712011-05-18 14:40:51 +01001469
Lars-Peter Clausen84088eb2013-10-07 12:50:00 +01001470 iio_free_chan_devattr_list(&indio_dev->channel_attr_list);
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001471 kfree(indio_dev->chan_attr_group.attrs);
Martin Fuzzeyc1b03ab2015-02-19 15:17:44 +01001472 indio_dev->chan_attr_group.attrs = NULL;
Jonathan Cameron847ec802009-08-18 18:06:19 +01001473}
1474
Jonathan Cameron847ec802009-08-18 18:06:19 +01001475static void iio_dev_release(struct device *device)
1476{
Lars-Peter Clausene53f5ac2012-05-12 15:39:33 +02001477 struct iio_dev *indio_dev = dev_to_iio_dev(device);
Benjamin Gaignardd89e1192017-04-27 15:29:15 +02001478 if (indio_dev->modes & INDIO_ALL_TRIGGERED_MODES)
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001479 iio_device_unregister_trigger_consumer(indio_dev);
1480 iio_device_unregister_eventset(indio_dev);
1481 iio_device_unregister_sysfs(indio_dev);
Lars-Peter Clausene407fd62012-06-04 10:41:42 +02001482
Lars-Peter Clausen9e69c932013-10-04 12:06:00 +01001483 iio_buffer_put(indio_dev->buffer);
1484
Lars-Peter Clausene407fd62012-06-04 10:41:42 +02001485 ida_simple_remove(&iio_ida, indio_dev->id);
1486 kfree(indio_dev);
Jonathan Cameron847ec802009-08-18 18:06:19 +01001487}
1488
Guenter Roeck17d82b42013-02-07 17:09:00 +00001489struct device_type iio_device_type = {
Jonathan Cameron847ec802009-08-18 18:06:19 +01001490 .name = "iio_device",
1491 .release = iio_dev_release,
1492};
1493
Sachin Kamata7e57dc2013-10-29 11:39:00 +00001494/**
1495 * iio_device_alloc() - allocate an iio_dev from a driver
1496 * @sizeof_priv: Space to allocate for private structure.
1497 **/
Lars-Peter Clausen7cbb7532012-04-26 13:35:01 +02001498struct iio_dev *iio_device_alloc(int sizeof_priv)
Jonathan Cameron847ec802009-08-18 18:06:19 +01001499{
Jonathan Cameron6f7c8ee2011-04-15 18:55:56 +01001500 struct iio_dev *dev;
1501 size_t alloc_size;
1502
1503 alloc_size = sizeof(struct iio_dev);
1504 if (sizeof_priv) {
1505 alloc_size = ALIGN(alloc_size, IIO_ALIGN);
1506 alloc_size += sizeof_priv;
1507 }
1508 /* ensure 32-byte alignment of whole construct ? */
1509 alloc_size += IIO_ALIGN - 1;
1510
1511 dev = kzalloc(alloc_size, GFP_KERNEL);
Jonathan Cameron0d4b2182020-04-19 16:13:37 +01001512 if (!dev)
1513 return NULL;
Jonathan Cameron847ec802009-08-18 18:06:19 +01001514
Jonathan Cameron0d4b2182020-04-19 16:13:37 +01001515 dev->dev.groups = dev->groups;
1516 dev->dev.type = &iio_device_type;
1517 dev->dev.bus = &iio_bus_type;
1518 device_initialize(&dev->dev);
1519 dev_set_drvdata(&dev->dev, (void *)dev);
1520 mutex_init(&dev->mlock);
1521 mutex_init(&dev->info_exist_lock);
1522 INIT_LIST_HEAD(&dev->channel_attr_list);
Jonathan Camerona9e39f92011-09-14 13:01:25 +01001523
Jonathan Cameron0d4b2182020-04-19 16:13:37 +01001524 dev->id = ida_simple_get(&iio_ida, 0, 0, GFP_KERNEL);
1525 if (dev->id < 0) {
1526 /* cannot use a dev_err as the name isn't available */
1527 pr_err("failed to get device id\n");
1528 kfree(dev);
1529 return NULL;
Jonathan Cameron847ec802009-08-18 18:06:19 +01001530 }
Jonathan Cameron0d4b2182020-04-19 16:13:37 +01001531 dev_set_name(&dev->dev, "iio:device%d", dev->id);
1532 INIT_LIST_HEAD(&dev->buffer_list);
Jonathan Cameron847ec802009-08-18 18:06:19 +01001533
1534 return dev;
1535}
Lars-Peter Clausen7cbb7532012-04-26 13:35:01 +02001536EXPORT_SYMBOL(iio_device_alloc);
Jonathan Cameron847ec802009-08-18 18:06:19 +01001537
Sachin Kamata7e57dc2013-10-29 11:39:00 +00001538/**
1539 * iio_device_free() - free an iio_dev from a driver
1540 * @dev: the iio_dev associated with the device
1541 **/
Lars-Peter Clausen7cbb7532012-04-26 13:35:01 +02001542void iio_device_free(struct iio_dev *dev)
Jonathan Cameron847ec802009-08-18 18:06:19 +01001543{
Lars-Peter Clausene407fd62012-06-04 10:41:42 +02001544 if (dev)
1545 put_device(&dev->dev);
Jonathan Cameron847ec802009-08-18 18:06:19 +01001546}
Lars-Peter Clausen7cbb7532012-04-26 13:35:01 +02001547EXPORT_SYMBOL(iio_device_free);
Jonathan Cameron847ec802009-08-18 18:06:19 +01001548
Grygorii Strashko9dabaf52013-07-18 11:19:00 +01001549static void devm_iio_device_release(struct device *dev, void *res)
1550{
1551 iio_device_free(*(struct iio_dev **)res);
1552}
1553
Sachin Kamata7e57dc2013-10-29 11:39:00 +00001554/**
1555 * devm_iio_device_alloc - Resource-managed iio_device_alloc()
1556 * @dev: Device to allocate iio_dev for
1557 * @sizeof_priv: Space to allocate for private structure.
1558 *
1559 * Managed iio_device_alloc. iio_dev allocated with this function is
1560 * automatically freed on driver detach.
1561 *
Sachin Kamata7e57dc2013-10-29 11:39:00 +00001562 * RETURNS:
1563 * Pointer to allocated iio_dev on success, NULL on failure.
1564 */
Grygorii Strashko9dabaf52013-07-18 11:19:00 +01001565struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv)
1566{
1567 struct iio_dev **ptr, *iio_dev;
1568
1569 ptr = devres_alloc(devm_iio_device_release, sizeof(*ptr),
1570 GFP_KERNEL);
1571 if (!ptr)
1572 return NULL;
1573
Grygorii Strashko9dabaf52013-07-18 11:19:00 +01001574 iio_dev = iio_device_alloc(sizeof_priv);
1575 if (iio_dev) {
1576 *ptr = iio_dev;
1577 devres_add(dev, ptr);
1578 } else {
1579 devres_free(ptr);
1580 }
1581
1582 return iio_dev;
1583}
1584EXPORT_SYMBOL_GPL(devm_iio_device_alloc);
1585
Sachin Kamata7e57dc2013-10-29 11:39:00 +00001586/**
Jonathan Cameron14555b12011-09-21 11:15:57 +01001587 * iio_chrdev_open() - chrdev file open for buffer access and ioctls
Cristina Opriceana2498dcf2015-07-24 16:16:19 +03001588 * @inode: Inode structure for identifying the device in the file system
1589 * @filp: File structure for iio device used to keep and later access
1590 * private data
1591 *
1592 * Return: 0 on success or -EBUSY if the device is already opened
Jonathan Cameron1aa04272011-08-30 12:32:47 +01001593 **/
1594static int iio_chrdev_open(struct inode *inode, struct file *filp)
1595{
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001596 struct iio_dev *indio_dev = container_of(inode->i_cdev,
Jonathan Cameron1aa04272011-08-30 12:32:47 +01001597 struct iio_dev, chrdev);
Lars-Peter Clausenbb014432011-12-19 15:23:45 +01001598
1599 if (test_and_set_bit(IIO_BUSY_BIT_POS, &indio_dev->flags))
1600 return -EBUSY;
1601
Lars-Peter Clausencadc2122013-09-18 21:02:00 +01001602 iio_device_get(indio_dev);
1603
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001604 filp->private_data = indio_dev;
Jonathan Cameron30eb82f2011-09-21 11:16:02 +01001605
Lars-Peter Clausen79335142011-12-19 15:23:49 +01001606 return 0;
Jonathan Cameron1aa04272011-08-30 12:32:47 +01001607}
1608
1609/**
Jonathan Cameron14555b12011-09-21 11:15:57 +01001610 * iio_chrdev_release() - chrdev file close buffer access and ioctls
Cristina Opriceana2498dcf2015-07-24 16:16:19 +03001611 * @inode: Inode structure pointer for the char device
1612 * @filp: File structure pointer for the char device
1613 *
1614 * Return: 0 for successful release
1615 */
Jonathan Cameron1aa04272011-08-30 12:32:47 +01001616static int iio_chrdev_release(struct inode *inode, struct file *filp)
1617{
Lars-Peter Clausenbb014432011-12-19 15:23:45 +01001618 struct iio_dev *indio_dev = container_of(inode->i_cdev,
1619 struct iio_dev, chrdev);
Lars-Peter Clausenbb014432011-12-19 15:23:45 +01001620 clear_bit(IIO_BUSY_BIT_POS, &indio_dev->flags);
Lars-Peter Clausencadc2122013-09-18 21:02:00 +01001621 iio_device_put(indio_dev);
1622
Jonathan Cameron1aa04272011-08-30 12:32:47 +01001623 return 0;
1624}
1625
1626/* Somewhat of a cross file organization violation - ioctls here are actually
1627 * event related */
1628static long iio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1629{
1630 struct iio_dev *indio_dev = filp->private_data;
1631 int __user *ip = (int __user *)arg;
1632 int fd;
1633
Lars-Peter Clausenf18e7a02013-10-04 12:06:00 +01001634 if (!indio_dev->info)
1635 return -ENODEV;
1636
Jonathan Cameron1aa04272011-08-30 12:32:47 +01001637 if (cmd == IIO_GET_EVENT_FD_IOCTL) {
1638 fd = iio_event_getfd(indio_dev);
Linus Walleij3f9059b2015-08-11 11:56:40 +02001639 if (fd < 0)
1640 return fd;
Jonathan Cameron1aa04272011-08-30 12:32:47 +01001641 if (copy_to_user(ip, &fd, sizeof(fd)))
1642 return -EFAULT;
1643 return 0;
1644 }
1645 return -EINVAL;
1646}
1647
Jonathan Cameron14555b12011-09-21 11:15:57 +01001648static const struct file_operations iio_buffer_fileops = {
Lars-Peter Clausenf6d40332019-12-11 12:43:00 +02001649 .read = iio_buffer_read_outer_addr,
Jonathan Cameron1aa04272011-08-30 12:32:47 +01001650 .release = iio_chrdev_release,
1651 .open = iio_chrdev_open,
Jonathan Cameron14555b12011-09-21 11:15:57 +01001652 .poll = iio_buffer_poll_addr,
Jonathan Cameron1aa04272011-08-30 12:32:47 +01001653 .owner = THIS_MODULE,
1654 .llseek = noop_llseek,
1655 .unlocked_ioctl = iio_ioctl,
Arnd Bergmann1832f2d2018-09-11 21:59:08 +02001656 .compat_ioctl = compat_ptr_ioctl,
Jonathan Cameron1aa04272011-08-30 12:32:47 +01001657};
1658
Vlad Dogaru8f5d8722014-12-29 11:37:48 +02001659static int iio_check_unique_scan_index(struct iio_dev *indio_dev)
1660{
1661 int i, j;
1662 const struct iio_chan_spec *channels = indio_dev->channels;
1663
1664 if (!(indio_dev->modes & INDIO_ALL_BUFFER_MODES))
1665 return 0;
1666
1667 for (i = 0; i < indio_dev->num_channels - 1; i++) {
1668 if (channels[i].scan_index < 0)
1669 continue;
1670 for (j = i + 1; j < indio_dev->num_channels; j++)
1671 if (channels[i].scan_index == channels[j].scan_index) {
1672 dev_err(&indio_dev->dev,
1673 "Duplicate scan index %d\n",
1674 channels[i].scan_index);
1675 return -EINVAL;
1676 }
1677 }
1678
1679 return 0;
1680}
1681
Michael Hennerich0f1acee2012-03-01 10:51:04 +01001682static const struct iio_buffer_setup_ops noop_ring_setup_ops;
1683
Jonathan Cameron63b19542017-07-23 17:25:43 +01001684int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod)
Jonathan Cameron847ec802009-08-18 18:06:19 +01001685{
1686 int ret;
1687
Alexandru Ardeleana17cb782020-04-07 18:07:43 +03001688 if (!indio_dev->info)
1689 return -EINVAL;
1690
Jonathan Cameron63b19542017-07-23 17:25:43 +01001691 indio_dev->driver_module = this_mod;
Guenter Roeck17d82b42013-02-07 17:09:00 +00001692 /* If the calling driver did not initialize of_node, do it here */
1693 if (!indio_dev->dev.of_node && indio_dev->dev.parent)
1694 indio_dev->dev.of_node = indio_dev->dev.parent->of_node;
1695
Phil Reid2c3d0c92019-09-19 22:36:08 +08001696 indio_dev->label = of_get_property(indio_dev->dev.of_node, "label",
1697 NULL);
1698
Vlad Dogaru8f5d8722014-12-29 11:37:48 +02001699 ret = iio_check_unique_scan_index(indio_dev);
1700 if (ret < 0)
1701 return ret;
1702
Jonathan Cameron1aa04272011-08-30 12:32:47 +01001703 /* configure elements for the chrdev */
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001704 indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id);
Jonathan Cameron847ec802009-08-18 18:06:19 +01001705
Greg Kroah-Hartman8915aac2019-06-18 17:54:40 +02001706 iio_device_register_debugfs(indio_dev);
Lars-Peter Clausen3e1b6c92014-11-26 18:55:12 +01001707
1708 ret = iio_buffer_alloc_sysfs_and_mask(indio_dev);
1709 if (ret) {
1710 dev_err(indio_dev->dev.parent,
1711 "Failed to create buffer sysfs interfaces\n");
1712 goto error_unreg_debugfs;
1713 }
1714
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001715 ret = iio_device_register_sysfs(indio_dev);
Jonathan Cameron847ec802009-08-18 18:06:19 +01001716 if (ret) {
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001717 dev_err(indio_dev->dev.parent,
Jonathan Cameron847ec802009-08-18 18:06:19 +01001718 "Failed to register sysfs interfaces\n");
Lars-Peter Clausen3e1b6c92014-11-26 18:55:12 +01001719 goto error_buffer_free_sysfs;
Jonathan Cameron847ec802009-08-18 18:06:19 +01001720 }
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001721 ret = iio_device_register_eventset(indio_dev);
Jonathan Cameron847ec802009-08-18 18:06:19 +01001722 if (ret) {
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001723 dev_err(indio_dev->dev.parent,
Roel Van Nyenc849d252010-04-29 19:27:31 +02001724 "Failed to register event set\n");
Jonathan Cameron847ec802009-08-18 18:06:19 +01001725 goto error_free_sysfs;
1726 }
Benjamin Gaignardd89e1192017-04-27 15:29:15 +02001727 if (indio_dev->modes & INDIO_ALL_TRIGGERED_MODES)
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001728 iio_device_register_trigger_consumer(indio_dev);
Jonathan Cameron847ec802009-08-18 18:06:19 +01001729
Michael Hennerich0f1acee2012-03-01 10:51:04 +01001730 if ((indio_dev->modes & INDIO_ALL_BUFFER_MODES) &&
1731 indio_dev->setup_ops == NULL)
1732 indio_dev->setup_ops = &noop_ring_setup_ops;
1733
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001734 cdev_init(&indio_dev->chrdev, &iio_buffer_fileops);
Jonathan Cameron63b19542017-07-23 17:25:43 +01001735
1736 indio_dev->chrdev.owner = this_mod;
Logan Gunthorpe389239112017-03-17 12:48:17 -06001737
1738 ret = cdev_device_add(&indio_dev->chrdev, &indio_dev->dev);
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01001739 if (ret < 0)
Lars-Peter Clausen0d5b7da2013-09-18 21:02:00 +01001740 goto error_unreg_eventset;
Jonathan Cameron847ec802009-08-18 18:06:19 +01001741
Lars-Peter Clausen0d5b7da2013-09-18 21:02:00 +01001742 return 0;
Logan Gunthorpe389239112017-03-17 12:48:17 -06001743
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01001744error_unreg_eventset:
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001745 iio_device_unregister_eventset(indio_dev);
Jonathan Cameron26d25ae2011-09-02 17:14:40 +01001746error_free_sysfs:
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001747 iio_device_unregister_sysfs(indio_dev);
Lars-Peter Clausen3e1b6c92014-11-26 18:55:12 +01001748error_buffer_free_sysfs:
1749 iio_buffer_free_sysfs_and_mask(indio_dev);
Michael Henneriche553f182012-03-01 10:51:03 +01001750error_unreg_debugfs:
1751 iio_device_unregister_debugfs(indio_dev);
Jonathan Cameron847ec802009-08-18 18:06:19 +01001752 return ret;
1753}
Jonathan Cameron63b19542017-07-23 17:25:43 +01001754EXPORT_SYMBOL(__iio_device_register);
Jonathan Cameron847ec802009-08-18 18:06:19 +01001755
Sachin Kamata7e57dc2013-10-29 11:39:00 +00001756/**
1757 * iio_device_unregister() - unregister a device from the IIO subsystem
1758 * @indio_dev: Device structure representing the device.
1759 **/
Jonathan Cameronf8c6f4e2011-10-06 17:14:35 +01001760void iio_device_unregister(struct iio_dev *indio_dev)
Jonathan Cameron847ec802009-08-18 18:06:19 +01001761{
Logan Gunthorpe389239112017-03-17 12:48:17 -06001762 cdev_device_del(&indio_dev->chrdev, &indio_dev->dev);
Lars-Peter Clausena87c82e2013-09-18 21:02:00 +01001763
Fabrice Gasnier7f75591fc2019-03-25 14:01:23 +01001764 mutex_lock(&indio_dev->info_exist_lock);
1765
Lars-Peter Clausenbc4c9612013-09-21 16:21:00 +01001766 iio_device_unregister_debugfs(indio_dev);
Lars-Peter Clausen0d5b7da2013-09-18 21:02:00 +01001767
Lars-Peter Clausena87c82e2013-09-18 21:02:00 +01001768 iio_disable_all_buffers(indio_dev);
1769
Jonathan Cameronac917a82012-02-15 19:48:00 +00001770 indio_dev->info = NULL;
Lars-Peter Clausend2f0a482013-10-04 12:07:00 +01001771
1772 iio_device_wakeup_eventset(indio_dev);
1773 iio_buffer_wakeup_poll(indio_dev);
1774
Jonathan Cameronac917a82012-02-15 19:48:00 +00001775 mutex_unlock(&indio_dev->info_exist_lock);
Lars-Peter Clausen3e1b6c92014-11-26 18:55:12 +01001776
1777 iio_buffer_free_sysfs_and_mask(indio_dev);
Jonathan Cameron847ec802009-08-18 18:06:19 +01001778}
1779EXPORT_SYMBOL(iio_device_unregister);
Sachin Kamat8caa07c2013-10-29 11:39:00 +00001780
1781static void devm_iio_device_unreg(struct device *dev, void *res)
1782{
1783 iio_device_unregister(*(struct iio_dev **)res);
1784}
1785
Jonathan Cameron63b19542017-07-23 17:25:43 +01001786int __devm_iio_device_register(struct device *dev, struct iio_dev *indio_dev,
1787 struct module *this_mod)
Sachin Kamat8caa07c2013-10-29 11:39:00 +00001788{
1789 struct iio_dev **ptr;
1790 int ret;
1791
1792 ptr = devres_alloc(devm_iio_device_unreg, sizeof(*ptr), GFP_KERNEL);
1793 if (!ptr)
1794 return -ENOMEM;
1795
1796 *ptr = indio_dev;
Jonathan Cameron63b19542017-07-23 17:25:43 +01001797 ret = __iio_device_register(indio_dev, this_mod);
Sachin Kamat8caa07c2013-10-29 11:39:00 +00001798 if (!ret)
1799 devres_add(dev, ptr);
1800 else
1801 devres_free(ptr);
1802
1803 return ret;
1804}
Jonathan Cameron63b19542017-07-23 17:25:43 +01001805EXPORT_SYMBOL_GPL(__devm_iio_device_register);
Sachin Kamat8caa07c2013-10-29 11:39:00 +00001806
1807/**
Alison Schofield08a33802016-03-09 11:30:12 -08001808 * iio_device_claim_direct_mode - Keep device in direct mode
1809 * @indio_dev: the iio_dev associated with the device
1810 *
1811 * If the device is in direct mode it is guaranteed to stay
1812 * that way until iio_device_release_direct_mode() is called.
1813 *
1814 * Use with iio_device_release_direct_mode()
1815 *
1816 * Returns: 0 on success, -EBUSY on failure
1817 */
1818int iio_device_claim_direct_mode(struct iio_dev *indio_dev)
1819{
1820 mutex_lock(&indio_dev->mlock);
1821
1822 if (iio_buffer_enabled(indio_dev)) {
1823 mutex_unlock(&indio_dev->mlock);
1824 return -EBUSY;
1825 }
1826 return 0;
1827}
1828EXPORT_SYMBOL_GPL(iio_device_claim_direct_mode);
1829
1830/**
1831 * iio_device_release_direct_mode - releases claim on direct mode
1832 * @indio_dev: the iio_dev associated with the device
1833 *
1834 * Release the claim. Device is no longer guaranteed to stay
1835 * in direct mode.
1836 *
1837 * Use with iio_device_claim_direct_mode()
1838 */
1839void iio_device_release_direct_mode(struct iio_dev *indio_dev)
1840{
1841 mutex_unlock(&indio_dev->mlock);
1842}
1843EXPORT_SYMBOL_GPL(iio_device_release_direct_mode);
1844
Jonathan Cameron847ec802009-08-18 18:06:19 +01001845subsys_initcall(iio_init);
1846module_exit(iio_exit);
1847
Jonathan Cameronc8b95952012-09-02 21:27:56 +01001848MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
Jonathan Cameron847ec802009-08-18 18:06:19 +01001849MODULE_DESCRIPTION("Industrial I/O core");
1850MODULE_LICENSE("GPL");